summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar mikebarnett <unknown>2009-07-15 21:03:41 +0000
committerGravatar mikebarnett <unknown>2009-07-15 21:03:41 +0000
commitce1c2de044c91624370411e23acab13b0381949b (patch)
tree592539996fe08050ead5ee210c973801611dde40
Initial set of files.
-rw-r--r--Binaries/..svnbridge/FSharp.Core.dll1
-rw-r--r--Binaries/..svnbridge/FSharp.PowerPack.dll1
-rw-r--r--Binaries/..svnbridge/Microsoft.SpecSharp.pdb1
-rw-r--r--Binaries/..svnbridge/Mscorlib.Contracts.dll1
-rw-r--r--Binaries/..svnbridge/System.Compiler.Contracts.dll1
-rw-r--r--Binaries/..svnbridge/System.Compiler.Framework.Contracts.dll1
-rw-r--r--Binaries/..svnbridge/System.Compiler.Framework.dll1
-rw-r--r--Binaries/..svnbridge/System.Compiler.Framework.pdb1
-rw-r--r--Binaries/..svnbridge/System.Compiler.dll1
-rw-r--r--Binaries/..svnbridge/System.Compiler.pdb1
-rw-r--r--Binaries/..svnbridge/System.Contracts.dll1
-rw-r--r--Binaries/..svnbridge/System.Xml.Contracts.dll1
-rw-r--r--Binaries/..svnbridge/microsoft.specsharp.dll1
-rw-r--r--Binaries/DafnyPrelude.bpl185
-rw-r--r--Binaries/FSharp.Core.dllbin0 -> 1536424 bytes
-rw-r--r--Binaries/FSharp.PowerPack.dllbin0 -> 1030568 bytes
-rw-r--r--Binaries/Microsoft.SpecSharp.pdbbin0 -> 615936 bytes
-rw-r--r--Binaries/Mscorlib.Contracts.dllbin0 -> 884736 bytes
-rw-r--r--Binaries/System.Compiler.Contracts.dllbin0 -> 57344 bytes
-rw-r--r--Binaries/System.Compiler.Framework.Contracts.dllbin0 -> 16384 bytes
-rw-r--r--Binaries/System.Compiler.Framework.dllbin0 -> 1187840 bytes
-rw-r--r--Binaries/System.Compiler.Framework.pdbbin0 -> 2569728 bytes
-rw-r--r--Binaries/System.Compiler.dllbin0 -> 872448 bytes
-rw-r--r--Binaries/System.Compiler.pdbbin0 -> 2270720 bytes
-rw-r--r--Binaries/System.Contracts.dllbin0 -> 237568 bytes
-rw-r--r--Binaries/System.Xml.Contracts.dllbin0 -> 20480 bytes
-rw-r--r--Binaries/TypedUnivBackPred2.sx131
-rw-r--r--Binaries/UnivBackPred2.smt131
-rw-r--r--Binaries/UnivBackPred2.sx85
-rw-r--r--Binaries/microsoft.specsharp.dllbin0 -> 491520 bytes
-rw-r--r--Chalice/Makefile26
-rw-r--r--Chalice/examples/Answer235
-rw-r--r--Chalice/examples/AssociationList.chalice113
-rw-r--r--Chalice/examples/ForkJoin.chalice77
-rw-r--r--Chalice/examples/HandOverHand.chalice130
-rw-r--r--Chalice/examples/OwickiGries.chalice35
-rw-r--r--Chalice/examples/RockBand-automagic.chalice111
-rw-r--r--Chalice/examples/RockBand.chalice111
-rw-r--r--Chalice/examples/cell-defaults.chalice152
-rw-r--r--Chalice/examples/cell.chalice163
-rw-r--r--Chalice/examples/counter.chalice152
-rw-r--r--Chalice/examples/dining-philosophers.chalice93
-rw-r--r--Chalice/examples/iterator.chalice150
-rw-r--r--Chalice/examples/iterator2.chalice134
-rw-r--r--Chalice/examples/linkedlist.chalice61
-rw-r--r--Chalice/examples/producer-consumer.chalice202
-rw-r--r--Chalice/examples/prog0.chalice65
-rw-r--r--Chalice/examples/prog1.chalice86
-rw-r--r--Chalice/examples/prog2.chalice93
-rw-r--r--Chalice/examples/prog3.chalice247
-rw-r--r--Chalice/examples/prog4.chalice49
-rw-r--r--Chalice/examples/swap.chalice20
-rw-r--r--Chalice/make.bat1
-rw-r--r--Chalice/make.py35
-rw-r--r--Chalice/src/Ast.scala384
-rw-r--r--Chalice/src/Boogie.scala270
-rw-r--r--Chalice/src/Chalice.cs76
-rw-r--r--Chalice/src/Chalice.scala115
-rw-r--r--Chalice/src/ChaliceToCSharp.scala211
-rw-r--r--Chalice/src/Parser.scala409
-rw-r--r--Chalice/src/Prelude.scala251
-rw-r--r--Chalice/src/PrettyPrinter.scala292
-rw-r--r--Chalice/src/Resolver.scala940
-rw-r--r--Chalice/src/Translator.scala2260
-rw-r--r--Chalice/test.bat43
-rw-r--r--Source/..svnbridge/Boogie.suo1
-rw-r--r--Source/..svnbridge/Dafny.suo1
-rw-r--r--Source/AIFramework/AIFramework.sscproj157
-rw-r--r--Source/AIFramework/CommonFunctionSymbols.ssc926
-rw-r--r--Source/AIFramework/Expr.ssc447
-rw-r--r--Source/AIFramework/Functional.ssc284
-rw-r--r--Source/AIFramework/Lattice.ssc685
-rw-r--r--Source/AIFramework/Logger.ssc49
-rw-r--r--Source/AIFramework/MultiLattice.ssc563
-rw-r--r--Source/AIFramework/Mutable.ssc117
-rw-r--r--Source/AIFramework/Polyhedra/LinearConstraint.ssc588
-rw-r--r--Source/AIFramework/Polyhedra/LinearConstraintSystem.ssc1856
-rw-r--r--Source/AIFramework/Polyhedra/PolyhedraAbstraction.ssc744
-rw-r--r--Source/AIFramework/Polyhedra/SimplexTableau.ssc717
-rw-r--r--Source/AIFramework/VariableMap/ConstantAbstraction.ssc210
-rw-r--r--Source/AIFramework/VariableMap/ConstantExpressions.ssc538
-rw-r--r--Source/AIFramework/VariableMap/DynamicTypeLattice.ssc475
-rw-r--r--Source/AIFramework/VariableMap/Intervals.ssc790
-rw-r--r--Source/AIFramework/VariableMap/MicroLattice.ssc79
-rw-r--r--Source/AIFramework/VariableMap/Nullness.ssc227
-rw-r--r--Source/AIFramework/VariableMap/VariableMapLattice.ssc749
-rw-r--r--Source/AbsInt/AbsInt.sscproj120
-rw-r--r--Source/AbsInt/AbstractInterpretation.ssc1074
-rw-r--r--Source/AbsInt/ExprFactories.ssc233
-rw-r--r--Source/AbsInt/LoopInvariantsOnDemand.ssc78
-rw-r--r--Source/AbsInt/Traverse.ssc182
-rw-r--r--Source/Basetypes/Basetypes.sscproj103
-rw-r--r--Source/Basetypes/BigNum.ssc341
-rw-r--r--Source/Basetypes/Rational.ssc300
-rw-r--r--Source/Basetypes/Set.ssc282
-rw-r--r--Source/Boogie.sln99
-rw-r--r--Source/Boogie.suobin0 -> 60928 bytes
-rw-r--r--Source/BoogieDriver/BoogieDriver.ssc648
-rw-r--r--Source/BoogieDriver/BoogieDriver.sscproj140
-rw-r--r--Source/Core.sscproj210
-rw-r--r--Source/Core/Absy.ssc3073
-rw-r--r--Source/Core/AbsyCmd.ssc2389
-rw-r--r--Source/Core/AbsyExpr.ssc3256
-rw-r--r--Source/Core/AbsyType.ssc2857
-rw-r--r--Source/Core/BoogiePL.atg1374
-rw-r--r--Source/Core/CommandLineOptions.ssc1935
-rw-r--r--Source/Core/Core.sscproj212
-rw-r--r--Source/Core/Duplicator.ssc348
-rw-r--r--Source/Core/Graph.as352
-rw-r--r--Source/Core/GraphAlgorithms.ssc175
-rw-r--r--Source/Core/Inline.ssc907
-rw-r--r--Source/Core/LoopUnroll.ssc174
-rw-r--r--Source/Core/Makefile18
-rw-r--r--Source/Core/OOLongUtil.ssc174
-rw-r--r--Source/Core/Parser.ssc2021
-rw-r--r--Source/Core/PureCollections.ssc785
-rw-r--r--Source/Core/Readme.txt61
-rw-r--r--Source/Core/ResolutionContext.ssc518
-rw-r--r--Source/Core/Scanner.ssc720
-rw-r--r--Source/Core/StandardVisitor.ssc503
-rw-r--r--Source/Core/TypeAmbiguitySeeker.ssc95
-rw-r--r--Source/Core/Util.ssc466
-rw-r--r--Source/Core/VCExp.ssc190
-rw-r--r--Source/Core/Xml.ssc292
-rw-r--r--Source/Core/parser.frame99
-rw-r--r--Source/Core/scanner.frame377
-rw-r--r--Source/Dafny.sln26
-rw-r--r--Source/Dafny.suobin0 -> 10752 bytes
-rw-r--r--Source/Dafny/Dafny.atg963
-rw-r--r--Source/Dafny/DafnyAst.ssc1049
-rw-r--r--Source/Dafny/DafnyMain.ssc73
-rw-r--r--Source/Dafny/DafnyPipeline.sscproj118
-rw-r--r--Source/Dafny/Makefile15
-rw-r--r--Source/Dafny/Parser.ssc1592
-rw-r--r--Source/Dafny/Printer.ssc663
-rw-r--r--Source/Dafny/Resolver.ssc1419
-rw-r--r--Source/Dafny/Scanner.ssc491
-rw-r--r--Source/Dafny/Translator.ssc2446
-rw-r--r--Source/Dafny/parser.frame103
-rw-r--r--Source/Dafny/scanner.frame170
-rw-r--r--Source/DafnyDriver/DafnyDriver.ssc681
-rw-r--r--Source/DafnyDriver/DafnyDriver.sscproj124
-rw-r--r--Source/Graph/Graph.ssc746
-rw-r--r--Source/Graph/Graph.sscproj89
-rw-r--r--Source/Houdini/Checker.ssc460
-rw-r--r--Source/Houdini/Houdini.ssc1188
-rw-r--r--Source/Houdini/Houdini.sscproj118
-rw-r--r--Source/Provers/SMTLib/ProverInterface.ssc240
-rw-r--r--Source/Provers/SMTLib/SMTLib.sscproj116
-rw-r--r--Source/Provers/SMTLib/SMTLibLineariser.ssc635
-rw-r--r--Source/Provers/SMTLib/TypeDeclCollector.ssc107
-rw-r--r--Source/Provers/Simplify/Let2ImpliesVisitor.ssc183
-rw-r--r--Source/Provers/Simplify/Prover.ssc606
-rw-r--r--Source/Provers/Simplify/ProverInterface.ssc633
-rw-r--r--Source/Provers/Simplify/Simplify.sscproj135
-rw-r--r--Source/Provers/Z3/Inspector.ssc130
-rw-r--r--Source/Provers/Z3/Prover.ssc870
-rw-r--r--Source/Provers/Z3/ProverInterface.ssc320
-rw-r--r--Source/Provers/Z3/TypeDeclCollector.ssc212
-rw-r--r--Source/Provers/Z3/Z3.sscproj140
-rw-r--r--Source/VCExpr/BigLiteralAbstracter.ssc198
-rw-r--r--Source/VCExpr/Boogie2VCExpr.ssc853
-rw-r--r--Source/VCExpr/Clustering.ssc449
-rw-r--r--Source/VCExpr/LetBindingSorter.ssc135
-rw-r--r--Source/VCExpr/NameClashResolver.ssc129
-rw-r--r--Source/VCExpr/SimplifyLikeLineariser.ssc795
-rw-r--r--Source/VCExpr/TermFormulaFlattening.ssc222
-rw-r--r--Source/VCExpr/TypeErasure.ssc1160
-rw-r--r--Source/VCExpr/TypeErasureArguments.ssc618
-rw-r--r--Source/VCExpr/TypeErasurePremisses.ssc1025
-rw-r--r--Source/VCExpr/VCExpr.sscproj141
-rw-r--r--Source/VCExpr/VCExprAST.ssc1285
-rw-r--r--Source/VCExpr/VCExprASTPrinter.ssc240
-rw-r--r--Source/VCExpr/VCExprASTVisitors.ssc999
-rw-r--r--Source/VCGeneration/Check.ssc375
-rw-r--r--Source/VCGeneration/ConditionGeneration.ssc790
-rw-r--r--Source/VCGeneration/Context.ssc199
-rw-r--r--Source/VCGeneration/OrderingAxioms.ssc285
-rw-r--r--Source/VCGeneration/VC.ssc3215
-rw-r--r--Source/VCGeneration/VCDoomed.ssc817
-rw-r--r--Source/VCGeneration/VCGeneration.sscproj142
-rw-r--r--Source/VCGeneration/Wlp.ssc131
-rw-r--r--Source/XAHA/XAHA.ssc601
-rw-r--r--Source/XAHA/XAHA.sscproj93
-rw-r--r--Source/foo.txt93
-rw-r--r--Source/version.ssc8
-rw-r--r--Test/CollectBenchmarks.py295
-rw-r--r--Test/CompareAll22
-rw-r--r--Test/aitest0/Answer111
-rw-r--r--Test/aitest0/Output111
-rw-r--r--Test/aitest0/constants.bpl69
-rw-r--r--Test/aitest0/runtest.bat6
-rw-r--r--Test/aitest1/Answer510
-rw-r--r--Test/aitest1/Bound.bpl28
-rw-r--r--Test/aitest1/Linear0.bpl10
-rw-r--r--Test/aitest1/Linear1.bpl11
-rw-r--r--Test/aitest1/Linear2.bpl11
-rw-r--r--Test/aitest1/Linear3.bpl11
-rw-r--r--Test/aitest1/Linear4.bpl15
-rw-r--r--Test/aitest1/Linear5.bpl21
-rw-r--r--Test/aitest1/Linear6.bpl21
-rw-r--r--Test/aitest1/Linear7.bpl19
-rw-r--r--Test/aitest1/Linear8.bpl42
-rw-r--r--Test/aitest1/Linear9.bpl29
-rw-r--r--Test/aitest1/Output510
-rw-r--r--Test/aitest1/ineq.bpl81
-rw-r--r--Test/aitest1/runtest.bat17
-rw-r--r--Test/aitest9/Output26
-rw-r--r--Test/aitest9/TestIntervals.bpl24
-rw-r--r--Test/aitest9/VarMapFixpoint.bpl58
-rw-r--r--Test/aitest9/answer26
-rw-r--r--Test/aitest9/runtest.bat11
-rw-r--r--Test/alltests.txt22
-rw-r--r--Test/bitvectors/Answer62
-rw-r--r--Test/bitvectors/Output62
-rw-r--r--Test/bitvectors/arrays.bpl41
-rw-r--r--Test/bitvectors/bv0.bpl13
-rw-r--r--Test/bitvectors/bv1.bpl17
-rw-r--r--Test/bitvectors/bv2.bpl11
-rw-r--r--Test/bitvectors/bv3.bpl3
-rw-r--r--Test/bitvectors/bv4.bpl23
-rw-r--r--Test/bitvectors/bv5.bpl11
-rw-r--r--Test/bitvectors/bv6.bpl9
-rw-r--r--Test/bitvectors/bv7.bpl9
-rw-r--r--Test/bitvectors/runtest.bat21
-rw-r--r--Test/bitvectors/vcc0.bpl883
-rw-r--r--Test/ccnet.runtestall.bat2
-rw-r--r--Test/dafny0/Answer100
-rw-r--r--Test/dafny0/BQueue.bpl430
-rw-r--r--Test/dafny0/BinaryTree.dfy245
-rw-r--r--Test/dafny0/DTypes.dfy74
-rw-r--r--Test/dafny0/ListContents.dfy92
-rw-r--r--Test/dafny0/ListCopy.dfy54
-rw-r--r--Test/dafny0/ListReverse.dfy26
-rw-r--r--Test/dafny0/Output100
-rw-r--r--Test/dafny0/Queue.dfy205
-rw-r--r--Test/dafny0/SchorrWaite.dfy229
-rw-r--r--Test/dafny0/Simple.dfy29
-rw-r--r--Test/dafny0/SmallTests.dfy26
-rw-r--r--Test/dafny0/Termination.dfy80
-rw-r--r--Test/dafny0/TypeParameters.dfy22
-rw-r--r--Test/dafny0/Use.dfy70
-rw-r--r--Test/dafny0/runtest.bat27
-rw-r--r--Test/filter.pl38
-rw-r--r--Test/havoc0/Answer12
-rw-r--r--Test/havoc0/KbdCreateClassObject.bpl5155
-rw-r--r--Test/havoc0/KeyboardClassFindMorePorts.bpl3780
-rw-r--r--Test/havoc0/KeyboardClassUnload.bpl3333
-rw-r--r--Test/havoc0/MouCreateClassObject.bpl4918
-rw-r--r--Test/havoc0/MouseClassFindMorePorts.bpl3837
-rw-r--r--Test/havoc0/MouseClassUnload.bpl3369
-rw-r--r--Test/havoc0/Output12
-rw-r--r--Test/havoc0/runtest.bat13
-rw-r--r--Test/houdini/Answer78
-rw-r--r--Test/houdini/houd1.bpl19
-rw-r--r--Test/houdini/houd10.bpl23
-rw-r--r--Test/houdini/houd11.bpl13
-rw-r--r--Test/houdini/houd12.bpl58
-rw-r--r--Test/houdini/houd2.bpl27
-rw-r--r--Test/houdini/houd3.bpl27
-rw-r--r--Test/houdini/houd4.bpl27
-rw-r--r--Test/houdini/houd5.bpl29
-rw-r--r--Test/houdini/houd6.bpl44
-rw-r--r--Test/houdini/houd7.bpl35
-rw-r--r--Test/houdini/houd8.bpl30
-rw-r--r--Test/houdini/houd9.bpl32
-rw-r--r--Test/houdini/runtest.bat11
-rw-r--r--Test/inline/Answer983
-rw-r--r--Test/inline/Elevator.asml56
-rw-r--r--Test/inline/Elevator.bpl153
-rw-r--r--Test/inline/Output983
-rw-r--r--Test/inline/expansion.bpl33
-rw-r--r--Test/inline/expansion2.bpl14
-rw-r--r--Test/inline/expansion2.sx178
-rw-r--r--Test/inline/expansion3.bpl19
-rw-r--r--Test/inline/expansion4.bpl31
-rw-r--r--Test/inline/fundef.bpl6
-rw-r--r--Test/inline/fundef2.bpl7
-rw-r--r--Test/inline/polyInline.bpl40
-rw-r--r--Test/inline/runtest.bat30
-rw-r--r--Test/inline/test1.bpl45
-rw-r--r--Test/inline/test2.bpl31
-rw-r--r--Test/inline/test3.bpl28
-rw-r--r--Test/inline/test4.bpl53
-rw-r--r--Test/inline/test5.bpl20
-rw-r--r--Test/inline/test6.bpl37
-rw-r--r--Test/lock/Answer8
-rw-r--r--Test/lock/Lock.bpl122
-rw-r--r--Test/lock/LockIncorrect.bpl51
-rw-r--r--Test/lock/Output8
-rw-r--r--Test/lock/runtest.bat7
-rw-r--r--Test/rtest25
-rw-r--r--Test/rtestall32
-rw-r--r--Test/runtest.bat36
-rw-r--r--Test/runtestall.bat24
-rw-r--r--Test/smoke/Answer25
-rw-r--r--Test/smoke/Output25
-rw-r--r--Test/smoke/runtest.bat11
-rw-r--r--Test/smoke/smoke0.bpl53
-rw-r--r--Test/test0/Answer252
-rw-r--r--Test/test0/Arrays0.bpl3
-rw-r--r--Test/test0/Arrays1.bpl16
-rw-r--r--Test/test0/AttributeParsing.bpl25
-rw-r--r--Test/test0/AttributeParsingErr.bpl23
-rw-r--r--Test/test0/AttributeResolution.bpl38
-rw-r--r--Test/test0/BadLabels0.bpl13
-rw-r--r--Test/test0/BadLabels1.bpl81
-rw-r--r--Test/test0/BadQuantifier.bpl3
-rw-r--r--Test/test0/EmptyCallArgs.bpl33
-rw-r--r--Test/test0/LargeLiterals0.bpl7
-rw-r--r--Test/test0/LineParse.bpl12
-rw-r--r--Test/test0/LineResolve.bpl38
-rw-r--r--Test/test0/MapsResolutionErrors.bpl28
-rw-r--r--Test/test0/ModifiedBag.bpl371
-rw-r--r--Test/test0/Orderings.bpl20
-rw-r--r--Test/test0/Output252
-rw-r--r--Test/test0/PrettyPrint.bpl40
-rw-r--r--Test/test0/Prog0.bpl51
-rw-r--r--Test/test0/Quoting.bpl16
-rw-r--r--Test/test0/Triggers0.bpl15
-rw-r--r--Test/test0/Triggers1.bpl127
-rw-r--r--Test/test0/Types0.bpl8
-rw-r--r--Test/test0/Types1.bpl7
-rw-r--r--Test/test0/WhereParsing.bpl25
-rw-r--r--Test/test0/WhereParsing0.bpl28
-rw-r--r--Test/test0/WhereParsing1.bpl15
-rw-r--r--Test/test0/WhereParsing2.bpl2
-rw-r--r--Test/test0/WhereResolution.bpl62
-rw-r--r--Test/test0/runtest.bat33
-rw-r--r--Test/test1/Answer137
-rw-r--r--Test/test1/Arrays.bpl224
-rw-r--r--Test/test1/AttributeTyping.bpl36
-rw-r--r--Test/test1/CallForallResolve.bpl23
-rw-r--r--Test/test1/EmptyCallArgs.bpl31
-rw-r--r--Test/test1/Family.bpl47
-rw-r--r--Test/test1/Frame0.bpl15
-rw-r--r--Test/test1/Frame1.bpl97
-rw-r--r--Test/test1/FunBody.bpl13
-rw-r--r--Test/test1/LogicalExprs.bpl6
-rw-r--r--Test/test1/MapsTypeErrors.bpl127
-rw-r--r--Test/test1/Orderings.bpl8
-rw-r--r--Test/test1/Output137
-rw-r--r--Test/test1/UpdateExprTyping.bpl43
-rw-r--r--Test/test1/WhereTyping.bpl45
-rw-r--r--Test/test1/runtest.bat19
-rw-r--r--Test/test13/Answer15
-rw-r--r--Test/test13/ErrorTraceTestLoopInvViolationBPL.bpl30
-rw-r--r--Test/test13/Output15
-rw-r--r--Test/test13/runtest.bat11
-rw-r--r--Test/test15/Answer177
-rw-r--r--Test/test15/IntInModel.bpl3
-rw-r--r--Test/test15/InterpretedFunctionTests.bpl17
-rw-r--r--Test/test15/ModelTest.bpl10
-rw-r--r--Test/test15/NullInModel.bpl5
-rw-r--r--Test/test15/Output177
-rw-r--r--Test/test15/runtest.bat16
-rw-r--r--Test/test16/Answer23
-rw-r--r--Test/test16/LoopUnroll.bpl79
-rw-r--r--Test/test16/Output23
-rw-r--r--Test/test16/runtest.bat13
-rw-r--r--Test/test17/Answer8
-rw-r--r--Test/test17/contractinfer.bpl24
-rw-r--r--Test/test17/flpydisk.bpl2295
-rw-r--r--Test/test17/runtest.bat12
-rw-r--r--Test/test2/Answer359
-rw-r--r--Test/test2/Arrays.bpl180
-rw-r--r--Test/test2/AssumeEnsures.bpl69
-rw-r--r--Test/test2/Axioms.bpl29
-rw-r--r--Test/test2/B.bpl86
-rw-r--r--Test/test2/Call.bpl60
-rw-r--r--Test/test2/CallForall.bpl134
-rw-r--r--Test/test2/CutBackEdge.bpl14
-rw-r--r--Test/test2/Ensures.bpl75
-rw-r--r--Test/test2/False.bpl16
-rw-r--r--Test/test2/FormulaTerm.bpl139
-rw-r--r--Test/test2/FormulaTerm2.bpl49
-rw-r--r--Test/test2/Implies.bpl16
-rw-r--r--Test/test2/LoopInvAssume.bpl20
-rw-r--r--Test/test2/NeverPattern.bpl29
-rw-r--r--Test/test2/NullaryMaps.bpl57
-rw-r--r--Test/test2/Old.bpl132
-rw-r--r--Test/test2/OldIllegal.bpl16
-rw-r--r--Test/test2/Output359
-rw-r--r--Test/test2/Passification.bpl169
-rw-r--r--Test/test2/Quantifiers.bpl154
-rw-r--r--Test/test2/Structured.bpl327
-rw-r--r--Test/test2/UpdateExpr.bpl81
-rw-r--r--Test/test2/Where.bpl163
-rw-r--r--Test/test2/runtest.bat26
-rw-r--r--Test/test2/sk_hack.bpl32
-rw-r--r--Test/test2/strings-no-where.bpl995
-rw-r--r--Test/test2/strings-where.bpl995
-rw-r--r--Test/test20/Answer192
-rw-r--r--Test/test20/Coercions.bpl17
-rw-r--r--Test/test20/EmptySeq.bpl6
-rw-r--r--Test/test20/Output192
-rw-r--r--Test/test20/ParallelAssignment.bpl23
-rw-r--r--Test/test20/ParallelAssignment2.bpl11
-rw-r--r--Test/test20/PolyFuns0.bpl55
-rw-r--r--Test/test20/PolyFuns1.bpl59
-rw-r--r--Test/test20/PolyPolyPoly.bpl22
-rw-r--r--Test/test20/PolyPolyPoly2.bpl34
-rw-r--r--Test/test20/PolyProcs0.bpl44
-rw-r--r--Test/test20/ProcParamReordering.bpl15
-rw-r--r--Test/test20/Prog0.bpl35
-rw-r--r--Test/test20/Prog1.bpl26
-rw-r--r--Test/test20/Prog2.bpl16
-rw-r--r--Test/test20/TypeDecls0.bpl45
-rw-r--r--Test/test20/TypeDecls1.bpl23
-rw-r--r--Test/test20/TypeSynonyms0.bpl29
-rw-r--r--Test/test20/TypeSynonyms1.bpl47
-rw-r--r--Test/test20/TypeSynonyms2.bpl20
-rw-r--r--Test/test20/runtest.bat26
-rw-r--r--Test/test21/Answer1677
-rw-r--r--Test/test21/BooleanQuantification.bpl32
-rw-r--r--Test/test21/BooleanQuantification2.bpl14
-rw-r--r--Test/test21/Boxing.bpl21
-rw-r--r--Test/test21/Casts.bpl11
-rw-r--r--Test/test21/Coercions2.bpl24
-rw-r--r--Test/test21/Colors.bpl21
-rw-r--r--Test/test21/DisjointDomains.bpl30
-rw-r--r--Test/test21/DisjointDomains2.bpl64
-rw-r--r--Test/test21/EmptyList.bpl47
-rw-r--r--Test/test21/EmptySetBug.bpl30
-rw-r--r--Test/test21/Flattening.bpl13
-rw-r--r--Test/test21/FunAxioms.bpl40
-rw-r--r--Test/test21/FunAxioms2.bpl21
-rw-r--r--Test/test21/HeapAbstraction.bpl19
-rw-r--r--Test/test21/HeapAxiom.bpl27
-rw-r--r--Test/test21/InterestingExamples0.bpl8
-rw-r--r--Test/test21/InterestingExamples1.bpl27
-rw-r--r--Test/test21/InterestingExamples2.bpl14
-rw-r--r--Test/test21/InterestingExamples3.bpl27
-rw-r--r--Test/test21/InterestingExamples4.bpl42
-rw-r--r--Test/test21/InterestingExamples5.bpl16
-rw-r--r--Test/test21/Keywords.bpl9
-rw-r--r--Test/test21/LargeLiterals0.bpl20
-rw-r--r--Test/test21/LetSorting.bpl15
-rw-r--r--Test/test21/MapAxiomsConsistency.bpl97
-rw-r--r--Test/test21/MapOutputTypeParams.bpl33
-rw-r--r--Test/test21/Maps0.bpl56
-rw-r--r--Test/test21/Maps1.bpl36
-rw-r--r--Test/test21/Maps2.bpl24
-rw-r--r--Test/test21/NameClash.bpl8
-rw-r--r--Test/test21/Orderings.bpl20
-rw-r--r--Test/test21/Orderings2.bpl18
-rw-r--r--Test/test21/Orderings3.bpl38
-rw-r--r--Test/test21/Orderings4.bpl11
-rw-r--r--Test/test21/Output1677
-rw-r--r--Test/test21/ParallelAssignment.bpl56
-rw-r--r--Test/test21/PolyList.bpl62
-rw-r--r--Test/test21/Triggers0.bpl44
-rw-r--r--Test/test21/Triggers1.bpl17
-rw-r--r--Test/test21/runtest.bat53
-rw-r--r--Test/test21/test3_AddMethod_conv.bpl1820
-rw-r--r--Test/test7/Answer64
-rw-r--r--Test/test7/MultipleErrors.bpl17
-rw-r--r--Test/test7/NestedVC.bpl21
-rw-r--r--Test/test7/Output64
-rw-r--r--Test/test7/UnreachableBlocks.bpl40
-rw-r--r--Test/test7/runtest.bat34
-rw-r--r--Test/textbook/Answer12
-rw-r--r--Test/textbook/Bubble.bpl66
-rw-r--r--Test/textbook/DutchFlag.bpl62
-rw-r--r--Test/textbook/Find.bpl39
-rw-r--r--Test/textbook/Output12
-rw-r--r--Test/textbook/runtest.bat13
-rw-r--r--Test/z3api/Answer187
-rw-r--r--Test/z3api/Boog24.bpl16
-rw-r--r--Test/z3api/boog0.bpl48
-rw-r--r--Test/z3api/boog1.bpl16
-rw-r--r--Test/z3api/boog10.bpl22
-rw-r--r--Test/z3api/boog11.bpl16
-rw-r--r--Test/z3api/boog12.bpl20
-rw-r--r--Test/z3api/boog13.bpl25
-rw-r--r--Test/z3api/boog14.bpl11
-rw-r--r--Test/z3api/boog15.bpl10
-rw-r--r--Test/z3api/boog16.bpl11
-rw-r--r--Test/z3api/boog17.bpl25
-rw-r--r--Test/z3api/boog18.bpl15
-rw-r--r--Test/z3api/boog19.bpl228
-rw-r--r--Test/z3api/boog2.bpl22
-rw-r--r--Test/z3api/boog20.bpl17
-rw-r--r--Test/z3api/boog21.bpl17
-rw-r--r--Test/z3api/boog22.bpl10
-rw-r--r--Test/z3api/boog23.bpl410
-rw-r--r--Test/z3api/boog25.bpl282
-rw-r--r--Test/z3api/boog28.bpl16
-rw-r--r--Test/z3api/boog29.bpl19
-rw-r--r--Test/z3api/boog3.bpl7
-rw-r--r--Test/z3api/boog30.bpl13
-rw-r--r--Test/z3api/boog31.bpl14
-rw-r--r--Test/z3api/boog34.bpl10
-rw-r--r--Test/z3api/boog4.bpl40
-rw-r--r--Test/z3api/boog5.bpl40
-rw-r--r--Test/z3api/boog6.bpl22
-rw-r--r--Test/z3api/boog7.bpl19
-rw-r--r--Test/z3api/boog8.bpl24
-rw-r--r--Test/z3api/boog9.bpl21
-rw-r--r--Test/z3api/runtest.bat10
-rw-r--r--Util/Emacs/boogie-mode.el120
-rw-r--r--Util/Emacs/chalice-mode.el115
-rw-r--r--Util/Emacs/dafny-mode.el112
-rw-r--r--Util/latex/boogie.sty120
-rw-r--r--Util/latex/chalice.sty63
-rw-r--r--Util/latex/dafny.sty101
506 files changed, 131167 insertions, 0 deletions
diff --git a/Binaries/..svnbridge/FSharp.Core.dll b/Binaries/..svnbridge/FSharp.Core.dll
new file mode 100644
index 00000000..08149303
--- /dev/null
+++ b/Binaries/..svnbridge/FSharp.Core.dll
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="utf-8"?><ItemProperties xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><Properties><Property><Name>svn:mime-type</Name><Value>application/octet-stream</Value></Property></Properties></ItemProperties> \ No newline at end of file
diff --git a/Binaries/..svnbridge/FSharp.PowerPack.dll b/Binaries/..svnbridge/FSharp.PowerPack.dll
new file mode 100644
index 00000000..08149303
--- /dev/null
+++ b/Binaries/..svnbridge/FSharp.PowerPack.dll
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="utf-8"?><ItemProperties xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><Properties><Property><Name>svn:mime-type</Name><Value>application/octet-stream</Value></Property></Properties></ItemProperties> \ No newline at end of file
diff --git a/Binaries/..svnbridge/Microsoft.SpecSharp.pdb b/Binaries/..svnbridge/Microsoft.SpecSharp.pdb
new file mode 100644
index 00000000..08149303
--- /dev/null
+++ b/Binaries/..svnbridge/Microsoft.SpecSharp.pdb
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="utf-8"?><ItemProperties xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><Properties><Property><Name>svn:mime-type</Name><Value>application/octet-stream</Value></Property></Properties></ItemProperties> \ No newline at end of file
diff --git a/Binaries/..svnbridge/Mscorlib.Contracts.dll b/Binaries/..svnbridge/Mscorlib.Contracts.dll
new file mode 100644
index 00000000..08149303
--- /dev/null
+++ b/Binaries/..svnbridge/Mscorlib.Contracts.dll
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="utf-8"?><ItemProperties xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><Properties><Property><Name>svn:mime-type</Name><Value>application/octet-stream</Value></Property></Properties></ItemProperties> \ No newline at end of file
diff --git a/Binaries/..svnbridge/System.Compiler.Contracts.dll b/Binaries/..svnbridge/System.Compiler.Contracts.dll
new file mode 100644
index 00000000..08149303
--- /dev/null
+++ b/Binaries/..svnbridge/System.Compiler.Contracts.dll
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="utf-8"?><ItemProperties xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><Properties><Property><Name>svn:mime-type</Name><Value>application/octet-stream</Value></Property></Properties></ItemProperties> \ No newline at end of file
diff --git a/Binaries/..svnbridge/System.Compiler.Framework.Contracts.dll b/Binaries/..svnbridge/System.Compiler.Framework.Contracts.dll
new file mode 100644
index 00000000..08149303
--- /dev/null
+++ b/Binaries/..svnbridge/System.Compiler.Framework.Contracts.dll
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="utf-8"?><ItemProperties xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><Properties><Property><Name>svn:mime-type</Name><Value>application/octet-stream</Value></Property></Properties></ItemProperties> \ No newline at end of file
diff --git a/Binaries/..svnbridge/System.Compiler.Framework.dll b/Binaries/..svnbridge/System.Compiler.Framework.dll
new file mode 100644
index 00000000..08149303
--- /dev/null
+++ b/Binaries/..svnbridge/System.Compiler.Framework.dll
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="utf-8"?><ItemProperties xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><Properties><Property><Name>svn:mime-type</Name><Value>application/octet-stream</Value></Property></Properties></ItemProperties> \ No newline at end of file
diff --git a/Binaries/..svnbridge/System.Compiler.Framework.pdb b/Binaries/..svnbridge/System.Compiler.Framework.pdb
new file mode 100644
index 00000000..08149303
--- /dev/null
+++ b/Binaries/..svnbridge/System.Compiler.Framework.pdb
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="utf-8"?><ItemProperties xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><Properties><Property><Name>svn:mime-type</Name><Value>application/octet-stream</Value></Property></Properties></ItemProperties> \ No newline at end of file
diff --git a/Binaries/..svnbridge/System.Compiler.dll b/Binaries/..svnbridge/System.Compiler.dll
new file mode 100644
index 00000000..08149303
--- /dev/null
+++ b/Binaries/..svnbridge/System.Compiler.dll
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="utf-8"?><ItemProperties xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><Properties><Property><Name>svn:mime-type</Name><Value>application/octet-stream</Value></Property></Properties></ItemProperties> \ No newline at end of file
diff --git a/Binaries/..svnbridge/System.Compiler.pdb b/Binaries/..svnbridge/System.Compiler.pdb
new file mode 100644
index 00000000..08149303
--- /dev/null
+++ b/Binaries/..svnbridge/System.Compiler.pdb
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="utf-8"?><ItemProperties xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><Properties><Property><Name>svn:mime-type</Name><Value>application/octet-stream</Value></Property></Properties></ItemProperties> \ No newline at end of file
diff --git a/Binaries/..svnbridge/System.Contracts.dll b/Binaries/..svnbridge/System.Contracts.dll
new file mode 100644
index 00000000..08149303
--- /dev/null
+++ b/Binaries/..svnbridge/System.Contracts.dll
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="utf-8"?><ItemProperties xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><Properties><Property><Name>svn:mime-type</Name><Value>application/octet-stream</Value></Property></Properties></ItemProperties> \ No newline at end of file
diff --git a/Binaries/..svnbridge/System.Xml.Contracts.dll b/Binaries/..svnbridge/System.Xml.Contracts.dll
new file mode 100644
index 00000000..08149303
--- /dev/null
+++ b/Binaries/..svnbridge/System.Xml.Contracts.dll
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="utf-8"?><ItemProperties xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><Properties><Property><Name>svn:mime-type</Name><Value>application/octet-stream</Value></Property></Properties></ItemProperties> \ No newline at end of file
diff --git a/Binaries/..svnbridge/microsoft.specsharp.dll b/Binaries/..svnbridge/microsoft.specsharp.dll
new file mode 100644
index 00000000..08149303
--- /dev/null
+++ b/Binaries/..svnbridge/microsoft.specsharp.dll
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="utf-8"?><ItemProperties xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><Properties><Property><Name>svn:mime-type</Name><Value>application/octet-stream</Value></Property></Properties></ItemProperties> \ No newline at end of file
diff --git a/Binaries/DafnyPrelude.bpl b/Binaries/DafnyPrelude.bpl
new file mode 100644
index 00000000..7ff940b5
--- /dev/null
+++ b/Binaries/DafnyPrelude.bpl
@@ -0,0 +1,185 @@
+// Dafny prelude
+// Created 9 February 2008 by Rustan Leino.
+// Converted to Boogie 2 on 28 June 2008.
+// Copyright (c) 2008, Microsoft.
+
+type ref;
+const null: ref;
+
+// ---------------------------------------------------------------
+// -- Axiomatization of sets -------------------------------------
+// ---------------------------------------------------------------
+
+type Set T = [T]bool;
+
+function Set#Empty<T>() returns (Set T);
+axiom (forall<T> o: T :: { Set#Empty()[o] } !Set#Empty()[o]);
+
+function Set#Singleton<T>(T) returns (Set T);
+axiom (forall<T> r: T :: { Set#Singleton(r) } Set#Singleton(r)[r]);
+axiom (forall<T> r: T, o: T :: { Set#Singleton(r)[o] } Set#Singleton(r)[o] <==> r == o);
+
+function Set#UnionOne<T>(Set T, T) returns (Set T);
+axiom (forall<T> a: Set T, x: T, o: T :: { Set#UnionOne(a,x)[o] }
+ Set#UnionOne(a,x)[o] <==> o == x || a[o]);
+
+function Set#Union<T>(Set T, Set T) returns (Set T);
+axiom (forall<T> a: Set T, b: Set T, o: T :: { Set#Union(a,b)[o] }
+ Set#Union(a,b)[o] <==> a[o] || b[o]);
+
+function Set#Intersection<T>(Set T, Set T) returns (Set T);
+axiom (forall<T> a: Set T, b: Set T, o: T :: { Set#Intersection(a,b)[o] }
+ Set#Intersection(a,b)[o] <==> a[o] && b[o]);
+
+function Set#Difference<T>(Set T, Set T) returns (Set T);
+axiom (forall<T> a: Set T, b: Set T, o: T :: { Set#Difference(a,b)[o] }
+ Set#Difference(a,b)[o] <==> a[o] && !b[o]);
+
+function Set#Subset<T>(Set T, Set T) returns (bool);
+axiom(forall<T> a: Set T, b: Set T :: { Set#Subset(a,b) }
+ Set#Subset(a,b) <==> (forall o: T :: {a[o]} {b[o]} a[o] ==> b[o]));
+
+function Set#Equal<T>(Set T, Set T) returns (bool);
+axiom(forall<T> a: Set T, b: Set T :: { Set#Equal(a,b) }
+ Set#Equal(a,b) <==> (forall o: T :: {a[o]} {b[o]} a[o] <==> b[o]));
+axiom(forall<T> a: Set T, b: Set T :: { Set#Equal(a,b) } // extensionality axiom for sets
+ Set#Equal(a,b) ==> a == b);
+
+function Set#Disjoint<T>(Set T, Set T) returns (bool);
+axiom (forall<T> a: Set T, b: Set T :: { Set#Disjoint(a,b) }
+ Set#Disjoint(a,b) <==> (forall o: T :: {a[o]} {b[o]} !a[o] || !b[o]));
+
+// ---------------------------------------------------------------
+// -- Axiomatization of sequences --------------------------------
+// ---------------------------------------------------------------
+
+type Seq T;
+
+function Seq#Length<T>(Seq T) returns (int);
+axiom (forall<T> s: Seq T :: { Seq#Length(s) } 0 <= Seq#Length(s));
+
+function Seq#Empty<T>() returns (Seq T);
+axiom (forall<T> :: Seq#Length(Seq#Empty(): Seq T) == 0);
+axiom (forall<T> s: Seq T :: { Seq#Length(s) } Seq#Length(s) == 0 ==> s == Seq#Empty());
+
+function Seq#Singleton<T>(T) returns (Seq T);
+axiom (forall<T> t: T :: { Seq#Length(Seq#Singleton(t)) } Seq#Length(Seq#Singleton(t)) == 1);
+
+function Seq#Build<T>(s: Seq T, index: int, val: T, newLength: int) returns (Seq T);
+axiom (forall<T> s: Seq T, i: int, v: T, len: int :: { Seq#Length(Seq#Build(s,i,v,len)) }
+ Seq#Length(Seq#Build(s,i,v,len)) == len);
+
+function Seq#Append<T>(Seq T, Seq T) returns (Seq T);
+axiom (forall<T> s0: Seq T, s1: Seq T :: { Seq#Length(Seq#Append(s0,s1)) }
+ Seq#Length(Seq#Append(s0,s1)) == Seq#Length(s0) + Seq#Length(s1));
+
+function Seq#Index<T>(Seq T, int) returns (T);
+axiom (forall<T> t: T :: { Seq#Index(Seq#Singleton(t), 0) } Seq#Index(Seq#Singleton(t), 0) == t);
+axiom (forall<T> s0: Seq T, s1: Seq T, n: int :: { Seq#Index(Seq#Append(s0,s1), n) }
+ (n < Seq#Length(s0) ==> Seq#Index(Seq#Append(s0,s1), n) == Seq#Index(s0, n)) &&
+ (Seq#Length(s0) <= n ==> Seq#Index(Seq#Append(s0,s1), n) == Seq#Index(s1, n - Seq#Length(s0))));
+axiom (forall<T> s: Seq T, i: int, v: T, len: int, n: int :: { Seq#Index(Seq#Build(s,i,v,len),n) }
+ (i == n ==> Seq#Index(Seq#Build(s,i,v,len),n) == v) &&
+ (i != n ==> Seq#Index(Seq#Build(s,i,v,len),n) == Seq#Index(s,n)));
+
+function Seq#Contains<T>(Seq T, T) returns (bool);
+axiom (forall<T> s: Seq T, x: T :: { Seq#Contains(s,x) }
+ Seq#Contains(s,x) <==>
+ (exists i: int :: { Seq#Index(s,i) } 0 <= i && i < Seq#Length(s) && Seq#Index(s,i) == x));
+axiom (forall x: ref ::
+ { Seq#Contains(Seq#Empty(), x) }
+ !Seq#Contains(Seq#Empty(), x));
+axiom (forall<T> s0: Seq T, s1: Seq T, x: T ::
+ { Seq#Contains(Seq#Append(s0, s1), x) }
+ Seq#Contains(Seq#Append(s0, s1), x) <==>
+ Seq#Contains(s0, x) || Seq#Contains(s1, x));
+axiom (forall<T> s: Seq T, i: int, v: T, len: int, x: T ::
+ { Seq#Contains(Seq#Build(s, i, v, len), x) }
+ Seq#Contains(Seq#Build(s, i, v, len), x) <==>
+ x == v || Seq#Contains(s, x));
+axiom (forall<T> s: Seq T, n: int, x: T ::
+ { Seq#Contains(Seq#Take(s, n), x) }
+ Seq#Contains(Seq#Take(s, n), x) <==>
+ (exists i: int :: { Seq#Index(s, i) }
+ 0 <= i && i < n && n <= Seq#Length(s) && Seq#Index(s, i) == x));
+axiom (forall<T> s: Seq T, n: int, x: T ::
+ { Seq#Contains(Seq#Drop(s, n), x) }
+ Seq#Contains(Seq#Drop(s, n), x) <==>
+ (exists i: int :: { Seq#Index(s, i) }
+ 0 <= n && n <= i && i < Seq#Length(s) && Seq#Index(s, i) == x));
+
+function Seq#Equal<T>(Seq T, Seq T) returns (bool);
+axiom (forall<T> s0: Seq T, s1: Seq T :: { Seq#Equal(s0,s1) }
+ Seq#Equal(s0,s1) <==>
+ Seq#Length(s0) == Seq#Length(s1) &&
+ (forall j: int :: { Seq#Index(s0,j) } { Seq#Index(s1,j) }
+ 0 <= j && j < Seq#Length(s0) ==> Seq#Index(s0,j) == Seq#Index(s1,j)));
+axiom(forall<T> a: Seq T, b: Seq T :: { Seq#Equal(a,b) } // extensionality axiom for sequences
+ Seq#Equal(a,b) ==> a == b);
+
+function Seq#SameUntil<T>(Seq T, Seq T, int) returns (bool);
+axiom (forall<T> s0: Seq T, s1: Seq T, n: int :: { Seq#SameUntil(s0,s1,n) }
+ Seq#SameUntil(s0,s1,n) <==>
+ (forall j: int :: { Seq#Index(s0,j) } { Seq#Index(s1,j) }
+ 0 <= j && j < n ==> Seq#Index(s0,j) == Seq#Index(s1,j)));
+
+function Seq#Take<T>(Seq T, howMany: int) returns (Seq T);
+axiom (forall<T> s: Seq T, n: int :: { Seq#Length(Seq#Take(s,n)) }
+ 0 <= n ==>
+ (n <= Seq#Length(s) ==> Seq#Length(Seq#Take(s,n)) == n) &&
+ (Seq#Length(s) < n ==> Seq#Length(Seq#Take(s,n)) == Seq#Length(s)));
+axiom (forall<T> s: Seq T, n: int, j: int :: { Seq#Index(Seq#Take(s,n), j) }
+ 0 <= j && j < n && j < Seq#Length(s) ==>
+ Seq#Index(Seq#Take(s,n), j) == Seq#Index(s, j));
+
+function Seq#Drop<T>(Seq T, howMany: int) returns (Seq T);
+axiom (forall<T> s: Seq T, n: int :: { Seq#Length(Seq#Drop(s,n)) }
+ 0 <= n ==>
+ (n <= Seq#Length(s) ==> Seq#Length(Seq#Drop(s,n)) == Seq#Length(s) - n) &&
+ (Seq#Length(s) < n ==> Seq#Length(Seq#Drop(s,n)) == 0));
+axiom (forall<T> s: Seq T, n: int, j: int :: { Seq#Index(Seq#Drop(s,n), j) }
+ 0 <= n && 0 <= j && j < Seq#Length(s)-n ==>
+ Seq#Index(Seq#Drop(s,n), j) == Seq#Index(s, j+n));
+
+// ---------------------------------------------------------------
+// -- Boxing and unboxing ----------------------------------------
+// ---------------------------------------------------------------
+
+function $Box<T>(T) returns (ref);
+function $Unbox<T>(ref) returns (T);
+
+axiom (forall<T> x: T :: { $Box(x) } $Unbox($Box(x)) == x);
+
+// ---------------------------------------------------------------
+
+type ClassName;
+const unique class.int: ClassName;
+const unique class.bool: ClassName;
+const unique class.object: ClassName;
+const unique class.set: ClassName;
+const unique class.seq: ClassName;
+
+function dtype(ref) returns (ClassName);
+function TypeParams(ref, int) returns (ClassName);
+
+function TypeTuple(a: ClassName, b: ClassName) returns (ClassName);
+function TypeTupleCar(ClassName) returns (ClassName);
+function TypeTupleCdr(ClassName) returns (ClassName);
+// TypeTuple is injective in both arguments:
+axiom (forall a: ClassName, b: ClassName :: { TypeTuple(a,b) }
+ TypeTupleCar(TypeTuple(a,b)) == a &&
+ TypeTupleCdr(TypeTuple(a,b)) == b);
+
+// ---------------------------------------------------------------
+
+type Field alpha;
+type HeapType = <alpha>[ref,Field alpha]alpha;
+
+function $IsGoodHeap(HeapType) returns (bool);
+var $Heap: HeapType where $IsGoodHeap($Heap);
+
+const unique alloc: Field bool;
+
+function $HeapSucc(HeapType, HeapType) returns (bool);
+axiom (forall h: HeapType, k: HeapType :: { $HeapSucc(h,k) }
+ $HeapSucc(h,k) ==> (forall o: ref :: { k[o,alloc] } h[o,alloc] ==> k[o,alloc]));
diff --git a/Binaries/FSharp.Core.dll b/Binaries/FSharp.Core.dll
new file mode 100644
index 00000000..56f1b6cd
--- /dev/null
+++ b/Binaries/FSharp.Core.dll
Binary files differ
diff --git a/Binaries/FSharp.PowerPack.dll b/Binaries/FSharp.PowerPack.dll
new file mode 100644
index 00000000..7e0d3482
--- /dev/null
+++ b/Binaries/FSharp.PowerPack.dll
Binary files differ
diff --git a/Binaries/Microsoft.SpecSharp.pdb b/Binaries/Microsoft.SpecSharp.pdb
new file mode 100644
index 00000000..9fa6f932
--- /dev/null
+++ b/Binaries/Microsoft.SpecSharp.pdb
Binary files differ
diff --git a/Binaries/Mscorlib.Contracts.dll b/Binaries/Mscorlib.Contracts.dll
new file mode 100644
index 00000000..b0aeeb5f
--- /dev/null
+++ b/Binaries/Mscorlib.Contracts.dll
Binary files differ
diff --git a/Binaries/System.Compiler.Contracts.dll b/Binaries/System.Compiler.Contracts.dll
new file mode 100644
index 00000000..6a573ef8
--- /dev/null
+++ b/Binaries/System.Compiler.Contracts.dll
Binary files differ
diff --git a/Binaries/System.Compiler.Framework.Contracts.dll b/Binaries/System.Compiler.Framework.Contracts.dll
new file mode 100644
index 00000000..50726f3e
--- /dev/null
+++ b/Binaries/System.Compiler.Framework.Contracts.dll
Binary files differ
diff --git a/Binaries/System.Compiler.Framework.dll b/Binaries/System.Compiler.Framework.dll
new file mode 100644
index 00000000..0c891dd0
--- /dev/null
+++ b/Binaries/System.Compiler.Framework.dll
Binary files differ
diff --git a/Binaries/System.Compiler.Framework.pdb b/Binaries/System.Compiler.Framework.pdb
new file mode 100644
index 00000000..7e580bd1
--- /dev/null
+++ b/Binaries/System.Compiler.Framework.pdb
Binary files differ
diff --git a/Binaries/System.Compiler.dll b/Binaries/System.Compiler.dll
new file mode 100644
index 00000000..645853a1
--- /dev/null
+++ b/Binaries/System.Compiler.dll
Binary files differ
diff --git a/Binaries/System.Compiler.pdb b/Binaries/System.Compiler.pdb
new file mode 100644
index 00000000..328e2aa4
--- /dev/null
+++ b/Binaries/System.Compiler.pdb
Binary files differ
diff --git a/Binaries/System.Contracts.dll b/Binaries/System.Contracts.dll
new file mode 100644
index 00000000..ed1ae103
--- /dev/null
+++ b/Binaries/System.Contracts.dll
Binary files differ
diff --git a/Binaries/System.Xml.Contracts.dll b/Binaries/System.Xml.Contracts.dll
new file mode 100644
index 00000000..1ba5ec57
--- /dev/null
+++ b/Binaries/System.Xml.Contracts.dll
Binary files differ
diff --git a/Binaries/TypedUnivBackPred2.sx b/Binaries/TypedUnivBackPred2.sx
new file mode 100644
index 00000000..5ee200f1
--- /dev/null
+++ b/Binaries/TypedUnivBackPred2.sx
@@ -0,0 +1,131 @@
+; -------------------------------------------------------------------------
+; Boogie 2 universal background predicate for Z3 (Simplify notation with types)
+; Copyright (c) 2004-2009, Microsoft Corp.
+
+(DEFTYPE $int :BUILTIN Int)
+(DEFTYPE $bool :BUILTIN bool)
+(DEFTYPE U)
+(DEFTYPE T)
+
+(DEFOP <: U U $bool) ; used for translation with type premisses
+(DEFOP <:: T U U $bool) ; used for translation with type arguments
+
+(BG_PUSH (AND
+
+ ; false is not true
+
+ (DISTINCT |@false| |@true|)
+
+ ; we assume type correctness of the operations here
+ ; a-l>=0 ==> (v ++ w:l)[a:b] = v[a-l:b-l]
+ (FORALL (v lv w lw lvw a b)
+ (QID bv:e:c1)
+ (PATS ($bv_extract ($bv_concat v lv w lw) lvw a b))
+ (IMPLIES
+ (>= (- a lw) 0)
+ (EQ ($bv_extract ($bv_concat v lv w lw) lvw a b) ($bv_extract v lv (- a lw) (- b lw)))))
+
+ ; b<=l ==> (v ++ w:l)[a:b] = w[a:b]
+ (FORALL (v lv w lw lvw a b)
+ (QID bv:e:c2)
+ (PATS ($bv_extract ($bv_concat v lv w lw) lvw a b))
+ (IMPLIES
+ (<= b lw)
+ (EQ ($bv_extract ($bv_concat v lv w lw) lvw a b) ($bv_extract w lw a b))))
+
+ ; v:l
+ ; a>=x || b<=y ==> (v[x:l] ++ w ++ v[0:y])[a:b] = v[a:b]
+ (FORALL (v lv x lxv w lw lwy y a b)
+ (QID bv:e:c3)
+ (PATS
+ ($bv_extract
+ ($bv_concat
+ ($bv_extract v lv x lv) lxv
+ ($bv_concat
+ w lw
+ ($bv_extract v lv 0 y) y) lwy) lv a b))
+ (IMPLIES
+ (AND
+ (EQ lw (- x y))
+ (EQ lxv (- lv x))
+ (EQ lwy (+ w y))
+ (OR (>= a x) (<= b y)))
+ (EQ
+ ($bv_extract
+ ($bv_concat
+ ($bv_extract v lv x lv) lxv
+ ($bv_concat
+ w lw
+ ($bv_extract v lv 0 y) y) lwy) lv a b)
+ ($bv_extract v lv a b))))
+
+ ; a>=x ==> (v[x:l] ++ w)[a:b] = v[a:b]
+ (FORALL (v lv x lxv w a b)
+ (QID bv:e:c4)
+ (PATS
+ ($bv_extract
+ ($bv_concat
+ ($bv_extract v lv x lv) lxv
+ w x)
+ lv a b))
+ (IMPLIES
+ (AND
+ (EQ lxv (- lv x))
+ (>= a x))
+ (EQ
+ ($bv_extract
+ ($bv_concat
+ ($bv_extract v lv x lv) lxv
+ w x)
+ lv a b)
+ ($bv_extract v lv a b))))
+
+ (FORALL (v l)
+ (QID bv:e:0)
+ (PATS ($bv_extract v l 0 l))
+ (EQ ($bv_extract v l 0 l) v))
+
+ (FORALL (n)
+ (QID bv:pow)
+ (PATS ($pow2 n))
+ (IMPLIES (> n 0) (EQ ($pow2 n) (* 2 ($pow2 (- n 1))))))
+
+ (EQ ($pow2 0) 1)
+
+ ; 0 <= v < 2^Y ==> 0bvX ++ v[0:Y] == v
+ (FORALL (v l a b)
+ (QID bv:e:pow)
+ (PATS ($bv_concat 0 b ($bv_extract v l 0 a) a))
+ (IMPLIES
+ (AND
+ (<= 0 v)
+ (< v ($pow2 a))
+ (EQ l (+ a b)))
+ (EQ ($bv_concat 0 b ($bv_extract v l 0 a) a) v)))
+
+ ; X > 0 ==> 0bvX ++ v >= 0
+ (FORALL (v a b)
+ (QID bv:e:pos)
+ (PATS ($bv_concat 0 b v a))
+ (IMPLIES
+ (> b 0)
+ (>= ($bv_concat 0 b v a) 0)))
+
+ ;; unsound?
+; (FORALL (lv w lw)
+; (QID bv:c:0)
+; (PATS ($bv_concat 0 lv w lw))
+; (EQ ($bv_concat 0 lv w lw) w))
+ ;; matching loop
+; (FORALL (v l1 a b l2 c d)
+; (QID bv:e:e)
+; (PATS ($bv_extract ($bv_extract v l1 a b) l2 c d))
+; (EQ ($bv_extract ($bv_extract v l1 a b) l2 c d) ($bv_extract v l1 (+ c a) (+ d a))))
+
+
+ ; Reflect plus
+ (FORALL (a b) (PATS (Reflect$Add a b)) (EQ (Reflect$Add a b) (+ a b)))
+
+)) ;; AND, BG_PUSH
+; End Boogie universal background predicate
+; -------------------------------------------------------------------------
diff --git a/Binaries/UnivBackPred2.smt b/Binaries/UnivBackPred2.smt
new file mode 100644
index 00000000..76c77d60
--- /dev/null
+++ b/Binaries/UnivBackPred2.smt
@@ -0,0 +1,131 @@
+; -------------------------------------------------------------------------
+; Boogie universal background predicate
+; Copyright (c) 2004-2006, Microsoft Corp.
+ :logic AUFLIA
+ :category { industrial }
+
+:extrasorts ( boogieU )
+:extrasorts ( boogieT )
+:extrasorts ( TermBool )
+
+:extrafuns (( boolTrue TermBool ))
+:extrafuns (( boolFalse TermBool ))
+:extrafuns (( boolIff TermBool TermBool TermBool ))
+:extrafuns (( boolImplies TermBool TermBool TermBool ))
+:extrafuns (( boolAnd TermBool TermBool TermBool ))
+:extrafuns (( boolOr TermBool TermBool TermBool ))
+:extrafuns (( boolNot TermBool TermBool ))
+:extrafuns (( UEqual boogieU boogieU TermBool ))
+:extrafuns (( TEqual boogieT boogieT TermBool ))
+:extrafuns (( IntEqual Int Int TermBool ))
+:extrafuns (( intLess Int Int TermBool ))
+:extrafuns (( intAtMost Int Int TermBool ))
+:extrafuns (( intGreater Int Int TermBool ))
+:extrafuns (( intAtLeast Int Int TermBool ))
+:extrafuns (( boogieIntMod Int Int Int ))
+:extrafuns (( boogieIntDiv Int Int Int ))
+
+; used for translation with type premisses
+:extrapreds (( UOrdering2 boogieU boogieU ))
+; used for translation with type arguments
+:extrapreds (( UOrdering3 boogieT boogieU boogieU ))
+
+; used for translation with type premisses
+:extrafuns (( TermUOrdering2 boogieU boogieU TermBool ))
+; used for translation with type arguments
+:extrafuns (( TermUOrdering3 boogieT boogieU boogieU TermBool ))
+
+ ; formula/term axioms
+ :assumption
+ (forall (?x TermBool) (?y TermBool)
+ (iff
+ (= (boolIff ?x ?y) boolTrue)
+ (iff (= ?x boolTrue) (= ?y boolTrue))))
+
+ :assumption
+ (forall (?x TermBool) (?y TermBool)
+ (iff
+ (= (boolImplies ?x ?y) boolTrue)
+ (implies (= ?x boolTrue) (= ?y boolTrue))))
+
+ :assumption
+ (forall (?x TermBool) (?y TermBool)
+ (iff
+ (= (boolAnd ?x ?y) boolTrue)
+ (and (= ?x boolTrue) (= ?y boolTrue))))
+
+ :assumption
+ (forall (?x TermBool) (?y TermBool)
+ (iff
+ (= (boolOr ?x ?y) boolTrue)
+ (or (= ?x boolTrue) (= ?y boolTrue))))
+
+ :assumption
+ (forall (?x TermBool)
+ (iff
+ (= (boolNot ?x) boolTrue)
+ (not (= ?x boolTrue)))
+ :pat { (boolNot ?x) }
+ )
+
+ :assumption
+ (forall (?x boogieU) (?y boogieU)
+ (iff
+ (= (UEqual ?x ?y) boolTrue)
+ (= ?x ?y)))
+
+ :assumption
+ (forall (?x boogieT) (?y boogieT)
+ (iff
+ (= (TEqual ?x ?y) boolTrue)
+ (= ?x ?y)))
+
+ :assumption
+ (forall (?x Int) (?y Int)
+ (iff
+ (= (IntEqual ?x ?y) boolTrue)
+ (= ?x ?y)))
+
+ :assumption
+ (forall (?x Int) (?y Int)
+ (iff
+ (= (intLess ?x ?y) boolTrue)
+ (< ?x ?y)))
+
+ :assumption
+ (forall (?x Int) (?y Int)
+ (iff
+ (= (intAtMost ?x ?y) boolTrue)
+ (<= ?x ?y)))
+
+ :assumption
+ (forall (?x Int) (?y Int)
+ (iff
+ (= (intAtLeast ?x ?y) boolTrue)
+ (>= ?x ?y)))
+
+ :assumption
+ (forall (?x Int) (?y Int)
+ (iff
+ (= (intGreater ?x ?y) boolTrue)
+ (> ?x ?y)))
+
+ ; false is not true
+ :assumption
+ (distinct boolFalse boolTrue)
+
+ :assumption
+ (forall (?x boogieU) (?y boogieU)
+ (iff
+ (= (TermUOrdering2 ?x ?y) boolTrue)
+ (UOrdering2 ?x ?y)))
+
+ :assumption
+ (forall (?x boogieT) (?y boogieU) (?z boogieU)
+ (iff
+ (= (TermUOrdering3 ?x ?y ?z) boolTrue)
+ (UOrdering3 ?x ?y ?z)))
+
+; End Boogie universal background predicate
+; -------------------------------------------------------------------------
+
diff --git a/Binaries/UnivBackPred2.sx b/Binaries/UnivBackPred2.sx
new file mode 100644
index 00000000..7c3dac8e
--- /dev/null
+++ b/Binaries/UnivBackPred2.sx
@@ -0,0 +1,85 @@
+; -------------------------------------------------------------------------
+; Boogie 2 universal background predicate
+; Copyright (c) 2004-2008, Microsoft Corp.
+(DEFPRED (<: t u)) ; used for translation with type premisses
+(DEFPRED (<:: s t u)) ; used for translation with type arguments
+
+(BG_PUSH (AND
+
+ ; formula/term axioms
+
+ (FORALL (x y)
+ (IFF
+ (EQ (boolIff x y) |@true|)
+ (IFF (EQ x |@true|) (EQ y |@true|))))
+
+ (FORALL (x y)
+ (IFF
+ (EQ (boolImplies x y) |@true|)
+ (IMPLIES (EQ x |@true|) (EQ y |@true|))))
+
+ (FORALL (x y)
+ (IFF
+ (EQ (boolAnd x y) |@true|)
+ (AND (EQ x |@true|) (EQ y |@true|))))
+
+ (FORALL (x y)
+ (IFF
+ (EQ (boolOr x y) |@true|)
+ (OR (EQ x |@true|) (EQ y |@true|))))
+
+ (FORALL (x)
+ (PATS (boolNot x))
+ (IFF
+ (EQ (boolNot x) |@true|)
+ (NEQ x |@true|)))
+
+ (FORALL (x y)
+ (IFF
+ (EQ (anyEqual x y) |@true|)
+ (EQ x y)))
+
+ (FORALL (x y)
+ (PATS (anyNeq x y))
+ (IFF
+ (EQ (anyNeq x y) |@true|)
+ (NEQ x y)))
+
+ (FORALL (x y)
+ (IFF
+ (EQ (intLess x y) |@true|)
+ (< x y)))
+
+ (FORALL (x y)
+ (IFF
+ (EQ (intAtMost x y) |@true|)
+ (<= x y)))
+
+ (FORALL (x y)
+ (IFF
+ (EQ (intAtLeast x y) |@true|)
+ (>= x y)))
+
+ (FORALL (x y)
+ (IFF
+ (EQ (intGreater x y) |@true|)
+ (> x y)))
+
+ ; false is not true
+
+ (DISTINCT |@false| |@true|)
+
+ ;; The following axiom gives a way to typed produce verification conditions,
+ ;; that is, verification conditions where the terms are typable. To use these,
+ ;; the VCExpressionGenerator.{CastTo,CastFrom} methods must be overridden.
+ ;; Look for USE_SORTED_LOGIC in VCGeneration/VCExpr.ssc.
+ ; (FORALL (val T U)
+ ; (PATS (TypeConvert (TypeConvert val T U) U T))
+ ; (EQ (TypeConvert (TypeConvert val T U) U T) val))
+
+ ; Reflect plus
+ (FORALL (a b) (PATS (Reflect$Add a b)) (EQ (Reflect$Add a b) (+ a b)))
+
+)) ;; AND, BG_PUSH
+; End Boogie universal background predicate
+; -------------------------------------------------------------------------
diff --git a/Binaries/microsoft.specsharp.dll b/Binaries/microsoft.specsharp.dll
new file mode 100644
index 00000000..b63cc192
--- /dev/null
+++ b/Binaries/microsoft.specsharp.dll
Binary files differ
diff --git a/Chalice/Makefile b/Chalice/Makefile
new file mode 100644
index 00000000..a0edde9b
--- /dev/null
+++ b/Chalice/Makefile
@@ -0,0 +1,26 @@
+# Makefile for Chalice tool
+
+SCALAC = scalac
+SCALA = scala
+CLASS_DIR = bin
+SRC_DIR = src
+
+
+all: $(CLASS_DIR)/Chalice.class
+
+SOURCES = $(SRC_DIR)/*.scala
+
+$(CLASS_DIR)/Chalice.class: $(SOURCES)
+ IF NOT EXIST $(CLASS_DIR) MKDIR $(CLASS_DIR)
+ $(SCALAC) -d $(CLASS_DIR) -unchecked $(SOURCES)
+
+clean:
+ rm -f $(CLASS_DIR)/*.class
+
+RUN_CHALICE = $(SCALA) -cp $(CLASS_DIR) -unchecked Chalice
+RUN_BOOGIE = ..\Binaries\boogie.exe
+test: $(RUN_CHALICE) examples\cell.chalice > examples\results\cell.chalice.expected
+
+try: $(CLASS_DIR)/Chalice.class
+ $(RUN_CHALICE) prog3.chalice > prog3.bpl
+ $(RUN_BOOGIE) prog3.bpl /smoke
diff --git a/Chalice/examples/Answer b/Chalice/examples/Answer
new file mode 100644
index 00000000..b81e3893
--- /dev/null
+++ b/Chalice/examples/Answer
@@ -0,0 +1,235 @@
+start
+------ Running regression test AssociationList.chalice
+
+Boogie program verifier finished with 12 verified, 0 errors
+------ Running regression test cell.chalice
+ 142.5: Assertion might not hold. Insufficient fraction at 142.12 for Cell.valid.
+
+Boogie program verifier finished with 31 verified, 1 error
+------ Running regression test counter.chalice
+ 69.5: Monitor invariant might hot hold. The expression at 4.27 might not evaluate to true.
+ 80.5: Assertion might not hold. The expression at 80.12 might not evaluate to true.
+ 119.5: The held field of the target of the release statement might not be writable.
+ 128.7: The mu field of the target of the acquire statement might not be above maxlock.
+ 136.7: The mu field of the target of the acquire statement might not be above maxlock.
+ 145.5: The held field of the target of the release statement might not be writable.
+
+Boogie program verifier finished with 24 verified, 6 errors
+------ Running regression test dining-philosophers.chalice
+
+Boogie program verifier finished with 12 verified, 0 errors
+------ Running regression test ForkJoin.chalice
+
+Boogie program verifier finished with 18 verified, 0 errors
+------ Running regression test HandOverHand.chalice
+
+Boogie program verifier finished with 10 verified, 0 errors
+------ Running regression test iterator.chalice
+
+Boogie program verifier finished with 22 verified, 0 errors
+------ Running regression test iterator2.chalice
+
+Boogie program verifier finished with 21 verified, 0 errors
+------ Running regression test producer-consumer.chalice
+
+Boogie program verifier finished with 36 verified, 0 errors
+------ Running regression test prog0.chalice
+The program did not typecheck.
+3.17: undeclared member a in class C
+3.37: undeclared member a in class C
+3.41: undeclared member a in class C
+3.12: assert statement requires a boolean expression (found int)
+4.5: undeclared member a in class C
+4.10: undeclared member a in class C
+5.5: undeclared member b in class C
+5.10: undeclared member a in class C
+5.14: undeclared member b in class C
+5.18: undeclared member c in class C
+5.26: undeclared member d in class C
+6.5: undeclared member b in class C
+6.14: undeclared member a in class C
+6.18: undeclared member b in class C
+6.23: undeclared member c in class C
+6.32: undeclared member d in class C
+7.5: undeclared member c in class C
+7.10: undeclared member a in class C
+7.15: undeclared member b in class C
+7.20: undeclared member c in class C
+7.29: undeclared member d in class C
+8.13: undeclared member X in class C
+8.19: undeclared member Y in class C
+8.13: incorrect type of ==> LHS (expected bool, found int)
+8.19: incorrect type of ==> RHS (expected bool, found int)
+8.26: undeclared member Z in class C
+8.26: incorrect type of ==> RHS (expected bool, found int)
+8.33: undeclared member A in class C
+8.39: undeclared member B in class C
+8.45: undeclared member C in class C
+8.39: incorrect type of ==> LHS (expected bool, found int)
+8.45: incorrect type of ==> RHS (expected bool, found int)
+8.33: incorrect type of ==> LHS (expected bool, found int)
+9.12: undeclared member A in class C
+9.17: undeclared member B in class C
+9.12: incorrect type of && LHS (expected bool, found int)
+9.17: incorrect type of && RHS (expected bool, found int)
+9.23: undeclared member C in class C
+9.28: undeclared member D in class C
+9.23: incorrect type of || LHS (expected bool, found int)
+9.28: incorrect type of || RHS (expected bool, found int)
+9.33: undeclared member E in class C
+9.33: incorrect type of || RHS (expected bool, found int)
+9.39: undeclared member F in class C
+9.39: incorrect type of && RHS (expected bool, found int)
+11.21: undeclared member f in class int
+11.21: undeclared member g in class int
+11.21: undeclared member h in class int
+<undefined position>: not-expression requires boolean operand
+<undefined position>: incorrect type of + RHS (expected int, found bool)
+11.33: not-expression requires boolean operand
+11.33: undeclared member f in class bool
+11.43: undeclared member f in class int
+11.42: not-expression requires boolean operand
+11.42: incorrect type of + RHS (expected int, found bool)
+13.5: type mismatch in assignment, lhs=int rhs=D
+14.5: undeclared member o in class C
+14.5: undeclared member f in class int
+15.6: undeclared member a in class C
+15.10: undeclared member b in class C
+15.5: undeclared member y in class int
+15.18: undefined class T used in new expression
+16.19: undeclared member O in class C
+16.14: == requires operands of the same type, found int and bool
+16.31: undeclared member O in class C
+16.13: != requires operands of the same type, found bool and int
+16.13: object in install statement must be of a reference type (found bool)
+16.41: undeclared member a in class C
+16.41: install bound must be of a reference type or Mu type (found int)
+16.43: undeclared member b in class C
+16.43: install bound must be of a reference type or Mu type (found int)
+16.45: undeclared member c in class C
+16.45: install bound must be of a reference type or Mu type (found int)
+16.51: install bound must be of a reference type or Mu type (found int)
+16.53: install bound must be of a reference type or Mu type (found int)
+17.13: undeclared member X in class C
+17.19: undeclared member Y in class C
+17.13: incorrect type of ==> LHS (expected bool, found int)
+17.19: incorrect type of ==> RHS (expected bool, found int)
+17.13: object in install statement must be of a reference type (found bool)
+17.27: install bound must be of a reference type or Mu type (found int)
+18.13: undeclared member o in class C
+18.13: undeclared member f in class int
+18.13: object in install statement must be of a reference type (found int)
+19.11: undeclared member o in class C
+19.11: object in share statement must be of a reference type (found int)
+20.13: undeclared member o in class C
+20.13: object in unshare statement must be of a reference type (found int)
+21.13: undeclared member o in class C
+21.13: object in acquire statement must be of a reference type (found int)
+22.13: undeclared member o in class C
+22.13: object in release statement must be of a reference type (found int)
+23.16: undeclared member o in class C
+23.16: object in rd acquire statement must be of a reference type (found int)
+24.16: undeclared member o in class C
+24.16: object in rd release statement must be of a reference type (found int)
+25.15: undeclared member o in class C
+25.15: object in downgrade statement must be of a reference type (found int)
+27.17: undeclared member o in class C
+27.5: call of undeclared member m in class int
+27.10: wrong token type
+29.12: rd expression is allowed only in positive predicate contexts
+29.15: undeclared member x in class C
+29.20: acc expression is allowed only in positive predicate contexts
+29.24: undeclared member y in class C
+29.12: incorrect type of + LHS (expected int, found bool)
+29.20: incorrect type of + RHS (expected int, found bool)
+29.29: acc expression is allowed only in positive predicate contexts
+29.33: undeclared member z in class C
+29.29: incorrect type of + RHS (expected int, found bool)
+29.51: undeclared member k in class C
+29.57: undeclared member f in class null
+29.12: assert statement requires a boolean expression (found int)
+30.10: undeclared member f in class C
+31.5: wrong number of actual in-parameters in call to C.m (3 instead of 0)
+32.5: wrong number of actual in-parameters in call to C.m (3 instead of 0)
+33.19: undeclared member o in class C
+33.10: undefined local variable a
+33.12: undefined local variable b
+33.14: undefined local variable c
+33.5: call of undeclared member m in class int
+34.5: wrong number of actual in-parameters in call to C.m (1 instead of 0)
+34.5: wrong number of actual out-parameters in call to C.m (1 instead of 0)
+35.13: undeclared member o in class C
+35.13: object in install statement must be of a reference type (found int)
+58.17: undeclared member sqrt2 in class C
+58.25: undeclared member sqrt2 in class C
+62.17: undeclared member s in class C
+62.10: undefined local variable v
+62.5: call of undeclared member M in class int
+------ Running regression test prog1.chalice
+ 9.10: Location might not be readable.
+ 25.5: Location might not be writable
+ 33.14: Location might not be readable.
+ 42.5: Monitor invariant might hot hold. The expression at 5.23 might not evaluate to true.
+ 60.5: Location might not be writable
+ 76.5: The held field of the target of the unshare statement might not be writable.
+ 84.5: The held field of the target of the unshare statement might not be writable.
+
+Boogie program verifier finished with 16 verified, 7 errors
+------ Running regression test prog2.chalice
+ 24.5: Assertion might not hold. The expression at 24.12 might not evaluate to true.
+ 31.13: Location might not be readable.
+ 73.5: Const variable can be assigned to only once.
+ 78.5: Assertion might not hold. The expression at 78.12 might not evaluate to true.
+
+Boogie program verifier finished with 24 verified, 4 errors
+------ Running regression test prog3.chalice
+ 76.3: The postcondition at 77.13 might not hold. The expression at 77.13 might not evaluate to true.
+ 76.3: Method might lock/unlock more than allowed.
+ 191.5: The precondition at 182.14 might not hold. Insufficient epsilons at 182.14 for ReadSharing.x.
+ 202.3: The postcondition at 204.13 might not hold. Insufficient epsilons at 204.13 for ReadSharing.x.
+
+Boogie program verifier finished with 51 verified, 4 errors
+------ Running regression test prog4.chalice
+ 5.5: Assertion might not hold. The expression at 5.12 might not evaluate to true.
+ 15.7: The held field of the target of the release statement might not be writable.
+ 27.7: The held field of the target of the release statement might not be writable.
+
+Boogie program verifier finished with 6 verified, 3 errors
+------ Running regression test RockBand.chalice
+ 27.3: The postcondition at 29.13 might not hold. Insufficient fraction at 29.13 for RockBand.Valid.
+ 41.10: Location might not be readable.
+ 50.5: Location might not be writable
+ 58.3: The postcondition at 60.13 might not hold. Insufficient fraction at 60.13 for Guitar.Valid.
+ 77.3: The postcondition at 79.13 might not hold. Insufficient fraction at 79.13 for Vocalist.Valid.
+ 96.3: The postcondition at 98.13 might not hold. Insufficient fraction at 98.13 for Organ.Valid.
+
+Boogie program verifier finished with 29 verified, 6 errors
+------ Running regression test swap.chalice
+
+Boogie program verifier finished with 5 verified, 0 errors
+------ Running regression test GhostConst.chalice
+The program did not typecheck.
+7.27: undeclared member c in class C
+13.10: ghost variable not allowed here
+21.10: ghost variable not allowed here
+29.10: ghost fields not allowed here
+------ Running regression test OwickiGries.chalice
+
+Boogie program verifier finished with 5 verified, 0 errors
+------ Running regression test cell-defaults.chalice
+ 96.5: The heap of the callee might not be strictly smaller than the heap of the caller.
+ 102.5: The heap of the callee might not be strictly smaller than the heap of the caller.
+ 131.5: Assertion might not hold. Automatic fold might fail. Insufficient fraction at 42.5 for Cell.x.
+
+Boogie program verifier finished with 29 verified, 3 errors
+------ Running regression test RockBand-automagic.chalice
+
+Boogie program verifier finished with 35 verified, 0 errors
+------ Running regression test Leaks.chalice
+ 6.3: Monitor invariant is not allowed to hold write permission to this.mu
+ 11.3: Monitor invariant can hold permission of other o.mu field only this.mu if this.mu<<o.mu
+ 16.3: Monitor invariant can hold permission of other o.mu field only this.mu if this.mu<<o.mu
+ 29.3: Monitor invariant can hold permission of other o.mu field only this.mu if this.mu<<o.mu
+ 62.3: Monitor invariant is not allowed to hold write permission to this.mu
+
+Boogie program verifier finished with 7 verified, 5 errors
diff --git a/Chalice/examples/AssociationList.chalice b/Chalice/examples/AssociationList.chalice
new file mode 100644
index 00000000..6adcbef5
--- /dev/null
+++ b/Chalice/examples/AssociationList.chalice
@@ -0,0 +1,113 @@
+class Client {
+ method Main(d: Data)
+ requires d != null
+ {
+ var a := new AssociationList
+ call a.Init()
+ call a.Add(5, d)
+ call a.Add(10, d)
+ var t: Data
+ call t := a.Get(10)
+ }
+}
+
+class AssociationList {
+ var head: Node // sentinel
+ invariant rd(head) && head != null
+ invariant rd(mu) && rd(head.mu) && this << head
+
+ method Init()
+ requires acc(head) && acc(mu) && mu == lockbottom
+ ensures acc(mu) && maxlock << this
+ {
+ head := new Node
+ head.next := null
+ share head
+ share this between maxlock and head
+ }
+
+ method Add(key: int, value: Data)
+ requires value != null
+ requires rd(mu) && maxlock << this
+ ensures rd(mu)
+ {
+ acquire this
+ var p: Node := head
+ acquire p
+ release this
+
+ var n := new Node
+ n.key := key
+ n.value := value
+ n.next := p.next
+ p.next := n
+ share n between p and n.next
+ release p
+ }
+
+ method Get(key: int) returns (d: Data)
+ requires rd(mu) && maxlock << this
+ ensures rd(mu)
+ {
+ d := null
+ acquire this
+ var p: Node := head
+ acquire p
+ release this
+
+ if (p.next != null) {
+ acquire p.next
+ if (p.next.key == key) {
+ d := p.next.value
+ } else {
+ var done := false
+ while (!done)
+ // invariant: holds p and p.next
+ invariant p != null && rd(p.key) && rd(p.value) && acc(p.next) && acc(p.mu,50) && p.next != null
+ invariant acc(p.next.mu) && p << p.next
+ invariant rd(p.next.key) && rd(p.next.value) && acc(p.next.next)
+ invariant p.next.next != null ==>
+ acc(p.next.next.mu,50) && p.next << p.next.next
+ invariant holds(p) && holds(p.next) && maxlock == p.next.mu
+ invariant p.next.next != null ==> maxlock << p.next.next
+ lockchange p, p.next.next
+ {
+ if (p.next.next == null) {
+ done := true // key not present
+ } else {
+ acquire p.next.next
+ if (p.next.next.key == key) {
+ done := true // key is present
+ d := p.next.next.value
+ // move p.next.next closer to the head by one step
+
+ var t: Node := p.next
+ p.next := t.next
+ t.next := p.next.next
+ p.next.next := t
+ reorder t between p.next and t.next
+ release t
+ } else {
+ var t: Node := p
+ p := p.next
+ release t
+ }
+ }
+ }
+ }
+ release p.next
+ }
+ release p
+ }
+}
+
+class Data { }
+
+class Node
+{
+ var key: int
+ var value: Data
+ var next: Node
+ invariant rd(key) && rd(value) && acc(next) && acc(mu,50)
+ invariant next != null ==> acc(next.mu,50) && this << next
+}
diff --git a/Chalice/examples/ForkJoin.chalice b/Chalice/examples/ForkJoin.chalice
new file mode 100644
index 00000000..e79cded9
--- /dev/null
+++ b/Chalice/examples/ForkJoin.chalice
@@ -0,0 +1,77 @@
+/* Example taken from ESOP submission */
+
+class T {
+ var k: int;
+ var l: int;
+
+ method run()
+ requires acc(k);
+ ensures acc(k) && k == old(k) + 1;
+ {
+ k := k + 1;
+ }
+}
+
+class Program {
+ method main() {
+ var x := new T;
+ x.k := 17;
+ x.l := 20;
+ fork tok := x.run();
+ x.l := 10;
+ join tok;
+ assert x.k == 18 && x.l == 10;
+ }
+
+ method justJoin(tok: token<T.run>, x: T) returns (rt: int)
+ requires x!=null && tok!=null && acc(tok.joinable) && tok.joinable && eval(tok.fork x.run(), acc(x.k));
+ ensures rt == old(eval(tok.fork x.run(), x.k)) + 1;
+ {
+ join tok;
+ rt := x.k;
+ }
+}
+
+/* example using asynchronous method calls */
+
+class C {
+ var x: int;
+
+ method m(v: int) returns (rt: int)
+ ensures rt == v + 1;
+ {
+ rt := v + 1;
+ }
+}
+
+class Program2 {
+ method main1(){
+ var c := new C;
+ var tok: token<C.m>;
+ fork tok := c.m(5);
+
+ // do some computation
+
+ var x : int;
+ join x := tok;
+ assert x == 6;
+ }
+
+ method main2(){
+ var c := new C;
+ var tok: token<C.m>;
+ fork tok := c.m(5);
+
+ // do some computation
+
+ call foo(tok, c);
+ }
+
+ method foo(tok: token<C.m>, o: C)
+ requires tok!=null && acc(tok.joinable) && tok.joinable && eval(tok.fork o.m(5), true);
+ {
+ var x: int;
+ join x := tok;
+ assert x == 6;
+ }
+} \ No newline at end of file
diff --git a/Chalice/examples/HandOverHand.chalice b/Chalice/examples/HandOverHand.chalice
new file mode 100644
index 00000000..f0f6323a
--- /dev/null
+++ b/Chalice/examples/HandOverHand.chalice
@@ -0,0 +1,130 @@
+class List {
+ ghost var sum: int
+ var head: Node
+ invariant acc(head) && head != null
+ invariant rd(head.val) && head.val == -1
+ invariant rd(mu) && acc(head.mu,50) && this << head
+ invariant acc(sum,20) && acc(head.sum, 50) && sum == head.sum
+
+ method Main()
+ {
+ var list := new List
+ call list.Init()
+ call list.Insert(8)
+ call list.Insert(12)
+ call list.Insert(4)
+ assert list.sum == 24
+ }
+
+ method Init()
+ requires acc(mu) && mu == lockbottom && acc(head) && acc(sum)
+ ensures rd(mu,*) && maxlock << this
+ ensures acc(sum,80) && sum == 0
+ {
+ var t := new Node
+ t.val := -1
+ t.next := null
+ t.sum := 0
+ share t
+ head := t
+ sum := 0
+ share this between maxlock and t
+ }
+
+ method Insert(x: int)
+ requires rd(mu) && maxlock << this
+ requires acc(sum,80) && 0 <= x
+ ensures rd(mu)
+ ensures acc(sum,80) && sum == old(sum) + x
+ {
+ acquire this
+ assert maxlock == this.mu;
+ sum := sum + x
+ var p: Node := head
+ acquire p
+ p.sum := p.sum + x
+ release this
+
+ while (p.next != null && p.next.val < x)
+ invariant p != null && acc(p.next) && rd(p.val) && acc(p.mu,50)
+ invariant holds(p) && maxlock == p.mu
+ invariant p.next != null ==> acc(p.next.mu,50) && p << p.next
+ invariant p.next != null ==> rd(p.next.val) && p.val <= p.next.val
+ invariant acc(p.sum, 50)
+ invariant p.next == null ==> p.sum == x
+ invariant p.next != null ==> acc(p.next.sum, 50) && p.sum == p.next.val + p.next.sum + x
+ invariant p.val <= x
+ lockchange p
+ {
+ var nx: Node := p.next
+ acquire nx
+ nx.sum := nx.sum + x
+ release p
+ p := nx
+ }
+ var t := new Node
+ t.val := x
+ t.next := p.next
+ if (t.next == null) { t.sum := 0 } else { t.sum := p.next.val + p.next.sum }
+ share t between p and p.next
+ p.next := t
+ release p
+ }
+
+ method Delete(x: int) returns (wasPresent: bool)
+ requires rd(mu) && maxlock << this
+ requires acc(sum,80) && 0 <= x
+ ensures acc(sum,80) && (wasPresent ==> sum == old(sum) - x) && (!wasPresent ==> sum == old(sum))
+ {
+ ghost const c
+
+ acquire this
+ sum := sum - c
+ var p: Node := head
+ acquire p
+ p.sum := p.sum - c
+ release this
+
+ while (p.next != null && p.next.val < x)
+ invariant p != null && acc(p.next) && rd(p.val) && acc(p.mu,50)
+ invariant holds(p) && maxlock == p.mu && !assigned(c)
+ invariant p.next != null ==> acc(p.next.mu,50) && p << p.next
+ invariant p.next != null ==> rd(p.next.val) && p.val <= p.next.val
+ invariant acc(p.sum, 50)
+ invariant p.next == null ==> p.sum == 0 - c
+ invariant p.next != null ==> acc(p.next.sum, 50) && p.sum == p.next.val + p.next.sum - c
+ invariant p.val <= x
+ lockchange p
+ {
+ var nx: Node := p.next
+ acquire nx
+ nx.sum := nx.sum - c
+ release p
+ p := nx
+ }
+ if (p.next != null && p.next.val == x) {
+ wasPresent := true
+ c := x
+ var nx: Node := p.next
+ acquire nx
+ p.next := nx.next
+ unshare nx
+ } else {
+ wasPresent := false
+ c := 0
+ }
+ release p
+ }
+}
+
+class Node {
+ ghost var sum: int
+ var val: int
+ var next: Node
+ invariant acc(next) && rd(val)
+ invariant next != null ==> rd(next.val) && val <= next.val
+ invariant acc(sum, 50)
+ invariant next == null ==> sum == 0
+ invariant next != null ==> acc(next.sum, 50) && sum == next.val + next.sum
+ invariant acc(mu,50) && (next != null ==> acc(next.mu,50) && this << next)
+}
diff --git a/Chalice/examples/OwickiGries.chalice b/Chalice/examples/OwickiGries.chalice
new file mode 100644
index 00000000..63f029e8
--- /dev/null
+++ b/Chalice/examples/OwickiGries.chalice
@@ -0,0 +1,35 @@
+class OwickiGries {
+ var counter: int
+ ghost var c0: int
+ ghost var c1: int
+ invariant acc(counter) && acc(c0,50) && acc(c1,50) && counter == c0 + c1
+
+ method Main() {
+ var og := new OwickiGries{ counter := 0, c0 := 0, c1 := 0 }
+ share og
+
+ fork tk0 := og.Worker(false)
+ fork tk1 := og.Worker(true)
+ join tk0; join tk1
+
+ acquire og; unshare og
+ assert og.counter == 2
+ }
+
+ method Worker(b: bool)
+ requires rd(mu) && maxlock << mu
+ requires (!b ==> acc(c0,50)) && (b ==> acc(c1,50))
+ ensures rd(mu)
+ ensures !b ==> acc(c0,50) && c0 == old(c0) + 1
+ ensures b ==> acc(c1,50) && c1 == old(c1) + 1
+ {
+ lock (this) {
+ counter := counter + 1
+ if (!b) {
+ c0 := c0 + 1
+ } else {
+ c1 := c1 + 1
+ }
+ }
+ }
+}
diff --git a/Chalice/examples/RockBand-automagic.chalice b/Chalice/examples/RockBand-automagic.chalice
new file mode 100644
index 00000000..d231ae5a
--- /dev/null
+++ b/Chalice/examples/RockBand-automagic.chalice
@@ -0,0 +1,111 @@
+// verify this program with -checkLeaks -defaults -autoFold -autoMagic
+
+class Client {
+ method Main() {
+ var b := new RockBand
+ call b.Init()
+ call b.Play()
+ call b.Play()
+ call b.Dispose()
+ }
+}
+
+class RockBand module M {
+ var gigs: int
+ var gt: Guitar
+ var doowops: seq<Vocalist>
+ var b3: Organ
+ predicate Valid {
+ /*acc(gigs) &&*/ 0 <= gigs &&
+ /*acc(gt) && gt != null &&*/ gt.Valid &&
+ acc(gt.mu) &&
+ acc(doowops) &&
+ /*acc(b3) && b3 != null &&*/ b3.Valid &&
+ acc(b3.mu)
+ }
+
+ method Init()
+ requires acc(this.*)
+ ensures Valid
+ {
+ gigs := 0
+ gt := new Guitar
+ call gt.Init()
+ b3 := new Organ
+ call b3.Init()
+ }
+
+ method Dispose()
+ requires Valid && acc(mu)
+ {
+ call gt.Dispose()
+ call b3.Dispose()
+ free this
+ }
+
+ method Play()
+ requires Valid
+ ensures Valid
+ {
+ gigs := gigs + 1
+ call gt.Strum()
+ call b3.Grind()
+ }
+}
+
+class Guitar module Musicians {
+ predicate Valid { true }
+ method Init()
+ requires acc(this.*)
+ ensures Valid
+ {
+ }
+ method Dispose()
+ requires Valid && acc(mu)
+ {
+ free this
+ }
+ method Strum()
+ requires Valid
+ ensures Valid
+ {
+ }
+}
+
+class Vocalist module Musicians {
+ predicate Valid { true }
+ method Init()
+ requires acc(this.*)
+ ensures Valid
+ {
+ }
+ method Dispose()
+ requires Valid && acc(mu)
+ {
+ free this
+ }
+ method Strum()
+ requires Valid
+ ensures Valid
+ {
+ }
+}
+
+class Organ module Musicians {
+ predicate Valid { true }
+ method Init()
+ requires acc(this.*)
+ ensures Valid
+ {
+ }
+ method Dispose()
+ requires Valid && acc(mu)
+ {
+ free this
+ }
+ method Grind()
+ requires Valid
+ ensures Valid
+ {
+ }
+}
diff --git a/Chalice/examples/RockBand.chalice b/Chalice/examples/RockBand.chalice
new file mode 100644
index 00000000..c7a2bba0
--- /dev/null
+++ b/Chalice/examples/RockBand.chalice
@@ -0,0 +1,111 @@
+// verify this program with -checkLeaks -defaults -autoFold
+
+class Client {
+ method Main() {
+ var b := new RockBand
+ call b.Init()
+ call b.Play()
+ call b.Play()
+ call b.Dispose()
+ }
+}
+
+class RockBand module M {
+ var gigs: int
+ var gt: Guitar
+ var doowops: seq<Vocalist>
+ var b3: Organ
+ predicate Valid {
+ acc(gigs) && 0 <= gigs &&
+ acc(gt) && gt != null && gt.Valid &&
+ acc(gt.mu) && // to enable an eventual free
+ acc(doowops) && //forall{d: Vocalist in doowops; d != null && d.Valid} &&
+ acc(b3) && b3 != null && b3.Valid &&
+ acc(b3.mu) // to enable an eventual free
+ }
+
+ method Init()
+ requires acc(this.*)
+ ensures Valid
+ {
+ gigs := 0
+ gt := new Guitar
+ call gt.Init()
+ b3 := new Organ
+ call b3.Init()
+ }
+
+ method Dispose()
+ requires Valid && acc(mu)
+ {
+ call gt.Dispose()
+ call b3.Dispose()
+ free this
+ }
+
+ method Play()
+ requires Valid
+ ensures Valid
+ {
+ gigs := gigs + 1
+ call gt.Strum()
+ call b3.Grind()
+ }
+}
+
+class Guitar module Musicians {
+ predicate Valid { true }
+ method Init()
+ requires acc(this.*)
+ ensures Valid
+ {
+ }
+ method Dispose()
+ requires Valid && acc(mu)
+ {
+ free this
+ }
+ method Strum()
+ requires Valid
+ ensures Valid
+ {
+ }
+}
+
+class Vocalist module Musicians {
+ predicate Valid { true }
+ method Init()
+ requires acc(this.*)
+ ensures Valid
+ {
+ }
+ method Dispose()
+ requires Valid && acc(mu)
+ {
+ free this
+ }
+ method Strum()
+ requires Valid
+ ensures Valid
+ {
+ }
+}
+
+class Organ module Musicians {
+ predicate Valid { true }
+ method Init()
+ requires acc(this.*)
+ ensures Valid
+ {
+ }
+ method Dispose()
+ requires Valid && acc(mu)
+ {
+ free this
+ }
+ method Grind()
+ requires Valid
+ ensures Valid
+ {
+ }
+}
diff --git a/Chalice/examples/cell-defaults.chalice b/Chalice/examples/cell-defaults.chalice
new file mode 100644
index 00000000..4781db97
--- /dev/null
+++ b/Chalice/examples/cell-defaults.chalice
@@ -0,0 +1,152 @@
+// verify this program with -defaults -autoFold -autoMagic
+
+class Cell module Library {
+ var x: int;
+
+ method init(v: int)
+ requires acc(this.x) && 0<=v;
+ ensures valid && this.get() == v;
+ {
+ x := v;
+ }
+
+ method set(v: int)
+ requires valid && 0<=v;
+ ensures valid && get()==v;
+ {
+ x := v;
+ }
+
+ method increment()
+ requires valid;
+ ensures valid && get() == old(get()) + 1;
+ {
+ x := x + 1;
+ }
+
+ method dispose()
+ requires valid && acc(mu);
+ ensures true;
+ {
+ free this;
+ }
+
+ function get(): int
+ requires valid;
+ ensures 0<=result;
+ {
+ x
+ }
+
+ predicate valid {
+ acc(this.x) && 0<=x
+ }
+
+ invariant valid;
+}
+
+class Interval module Library2 {
+ var left: Cell;
+ var right: Cell;
+
+ method init(l: int, r: int)
+ requires 0<=l && l <= r;
+ requires acc(left) && acc(right);
+ ensures valid;
+ ensures getLeft()==l
+ ensures getRight()==r;
+ {
+ left := new Cell;
+ call left.init(l);
+ right := new Cell;
+ call right.init(r);
+ }
+
+ method setLeft(l: int)
+ requires valid;
+ requires 0<=l && l<=getRight();
+ ensures valid;
+ ensures getLeft()==l && getRight()==old(getRight());
+ {
+ call left.set(l);
+ }
+
+ method setRight(r: int)
+ requires valid;
+ requires 0<=r && getLeft()<=r;
+ ensures valid;
+ ensures getLeft()==old(getLeft()) && getRight()==r;
+ {
+ call right.set(r);
+ }
+
+ method shift(v: int)
+ requires valid;
+ requires 0<=v;
+ ensures valid;
+ ensures getLeft()==old(getLeft())+v && getRight()==old(getRight())+v;
+ {
+ call left.set(left.get()+v);
+ call right.set(right.get()+v);
+ }
+
+ function getLeft() : int
+ requires valid;
+ {
+ left.get() // for some reason, Boogie can't figure out the callee's heap is smaller when using defaults
+ }
+
+ function getRight() : int
+ requires valid;
+ {
+ right.get() // for some reason, Boogie can't figure out the callee's heap is smaller when using defaults
+ }
+
+ predicate valid
+ {
+ left.valid && right.valid && left.get() <= right.get()
+ }
+}
+
+class Program module Main {
+ method main(){
+ var c1 := new Cell;
+ call c1.init(5);
+ call c1.set(6);
+
+ var c2 := new Cell;
+ call c2.init(10);
+ call c2.set(11);
+
+ assert c1.get() == 6;
+ }
+
+ method main2(){
+ var c: Cell;
+
+ c := new Cell;
+ call c.init(0);
+ call c.dispose();
+
+ assert c.valid; // should fail
+ }
+
+ method main3() returns (rt: Cell)
+ ensures rt!=null && rt.valid && rt.get() == 0
+ {
+ rt := new Cell;
+ call rt.init(0)
+ }
+
+ method main4() {
+ var c: Cell;
+
+ c := new Cell;
+ call c.init(0);
+ share c;
+
+ acquire c;
+ call c.set(1);
+ release c;
+ }
+} \ No newline at end of file
diff --git a/Chalice/examples/cell.chalice b/Chalice/examples/cell.chalice
new file mode 100644
index 00000000..d4003a3c
--- /dev/null
+++ b/Chalice/examples/cell.chalice
@@ -0,0 +1,163 @@
+class Cell module Library {
+ var x: int;
+
+ method init(v: int)
+ requires acc(this.x) && 0<=v;
+ ensures valid && this.get() == v;
+ {
+ x := v;
+ fold valid;
+ }
+
+ method set(v: int)
+ requires valid && 0<=v;
+ ensures valid && get()==v;
+ {
+ unfold valid;
+ x := v;
+ fold valid;
+ }
+
+ method increment()
+ requires valid;
+ ensures valid && get() == old(get()) + 1;
+ {
+ unfold valid;
+ x := x + 1;
+ fold valid;
+ }
+
+ method dispose()
+ requires valid && acc(mu);
+ ensures true;
+ {
+ unfold valid;
+ free this;
+ }
+
+ function get(): int
+ requires valid;
+ ensures 0<=result;
+ {
+ unfolding valid in x
+ }
+
+ predicate valid {
+ acc(this.x) && 0<=x
+ }
+
+ invariant valid;
+}
+
+class Interval module Library2 {
+ var left: Cell;
+ var right: Cell;
+
+ method init(l: int, r: int)
+ requires 0<=l && l <= r;
+ requires acc(left) && acc(right);
+ ensures valid;
+ ensures getLeft()==l
+ ensures getRight()==r;
+ {
+ left := new Cell;
+ call left.init(l);
+ right := new Cell;
+ call right.init(r);
+ fold valid;
+ }
+
+ method setLeft(l: int)
+ requires valid;
+ requires 0<=l && l<=getRight();
+ ensures valid;
+ ensures getLeft()==l && getRight()==old(getRight());
+ {
+ unfold valid;
+ call left.set(l);
+ fold valid;
+ }
+
+ method setRight(r: int)
+ requires valid;
+ requires 0<=r && getLeft()<=r;
+ ensures valid;
+ ensures getLeft()==old(getLeft()) && getRight()==r;
+ {
+ unfold valid;
+ call right.set(r);
+ fold valid;
+ }
+
+ method shift(v: int)
+ requires valid;
+ requires 0<=v;
+ ensures valid;
+ ensures getLeft()==old(getLeft())+v && getRight()==old(getRight())+v;
+ {
+ unfold valid;
+ call left.set(left.get()+v);
+ call right.set(right.get()+v);
+ fold valid;
+ }
+
+ function getLeft() : int
+ requires valid;
+ {
+ unfolding valid in left.get()
+ }
+
+ function getRight() : int
+ requires valid;
+ {
+ unfolding valid in right.get()
+ }
+
+ predicate valid
+ {
+ acc(left) && acc(right) && left!=null && right!=null && left.valid && right.valid && left.get() <= right.get()
+ }
+}
+
+class Program module Main {
+ method main(){
+ var c1 := new Cell;
+ call c1.init(5);
+ call c1.set(6);
+
+ var c2 := new Cell;
+ call c2.init(10);
+ call c2.set(11);
+
+ assert c1.get() == 6;
+ }
+
+ method main2(){
+ var c: Cell;
+
+ c := new Cell;
+ call c.init(0);
+ call c.dispose();
+
+ assert c.valid; // should fail
+ }
+
+ method main3() returns (rt: Cell)
+ ensures rt!=null && rt.valid && rt.get() == 0
+ {
+ rt := new Cell;
+ call rt.init(0)
+ }
+
+ method main4() {
+ var c: Cell;
+
+ c := new Cell;
+ call c.init(0);
+ share c;
+
+ acquire c;
+ call c.set(1);
+ release c;
+ }
+} \ No newline at end of file
diff --git a/Chalice/examples/counter.chalice b/Chalice/examples/counter.chalice
new file mode 100644
index 00000000..0cab7736
--- /dev/null
+++ b/Chalice/examples/counter.chalice
@@ -0,0 +1,152 @@
+class Counter {
+ var value: int;
+
+ invariant acc(value) && old(value)<=value;
+}
+
+class Program {
+
+ method main1(){
+ var counter := new Counter;
+ counter.value := 0;
+ share counter;
+
+ acquire counter;
+ var tmp1 := counter.value;
+ release counter;
+
+ acquire counter;
+ var tmp2 := counter.value;
+ release counter;
+
+ assert tmp1 <= tmp2;
+ }
+
+ method main2(){
+ var counter := new Counter;
+ counter.value := 0;
+ share counter;
+
+ acquire counter;
+ release counter;
+
+ call bar(counter);
+ }
+
+ method bar(c: Counter)
+ requires c!=null && acc(c.mu) && maxlock << c.mu;
+ requires eval(c.release, acc(c.value) && 0<=c.value);
+ {
+ lock (c) {
+ assert 0 <= c.value; // ok, because of the lastSeen conjunct in the precondition
+ }
+ }
+
+ method main3() returns (counter: Counter)
+ lockchange counter;
+ {
+ counter := new Counter;
+ counter.value := 0;
+ share counter;
+ acquire counter;
+ call doRelease(counter, counter.value);
+ }
+
+ method doRelease(c: Counter, i: int)
+ requires c!=null && holds(c) && acc(c.value) && eval(c.acquire, acc(c.value) && i<=c.value);
+ lockchange c;
+ {
+ release c; // ok, because of atAcquire conjunct in the precondition
+ }
+
+ method main4(){
+ var counter := new Counter;
+ counter.value := 0;
+ share counter;
+
+ acquire counter;
+ counter.value := counter.value - 1;
+ release counter; // error: should fail
+ }
+
+ method main5(){
+ var counter := new Counter;
+ counter.value := 10;
+ share counter;
+
+ call foo(counter);
+
+ unshare counter;
+ assert 10<=counter.value; // error: should fail
+ }
+
+ method foo(c: Counter)
+ requires c!=null && acc(c.mu) && maxlock << c.mu && eval(c.release, acc(c.value) && 10<=c.value);
+ ensures c!=null && holds(c) && acc(c.mu) && acc(c.value);
+ lockchange c;
+ {
+ acquire c;
+ unshare c;
+ c.value := 5;
+ share c;
+ acquire c;
+ }
+
+ method nestedGood0(c: Counter)
+ requires c != null && acc(c.mu) && maxlock << c.mu;
+ {
+ lock (c) {
+ release c
+ acquire c
+ }
+ }
+
+ method nestedGood1(c: Counter)
+ requires c != null && acc(c.mu) && maxlock << c.mu;
+ {
+ var t: Counter := c
+ lock (t) {
+ t := new Counter
+ share t
+ acquire t
+ } // this line releases the original value for t
+ release t
+ }
+
+ method nestedBad0(c: Counter)
+ requires c != null && acc(c.mu) && maxlock << c.mu;
+ {
+ lock (c) {
+ release c
+ } // error: no longer holds c
+ }
+
+ method nestedBad1(c: Counter)
+ requires c != null && acc(c.mu) && maxlock << c.mu;
+ {
+ lock (c) {
+ acquire c // error: already holds c
+ }
+ }
+
+ method nestedBad2(c: Counter)
+ requires c != null && acc(c.mu) && maxlock << c.mu;
+ {
+ lock (c) {
+ lock (c) { // error: already holds c
+ }
+ }
+ }
+
+ method nestedBad3(c: Counter)
+ requires c != null && acc(c.mu) && maxlock << c.mu;
+ {
+ var t: Counter := c
+ lock (t) {
+ release t
+ t := new Counter
+ share t
+ acquire t
+ } // error: this line attempts to release the original t
+ }
+} \ No newline at end of file
diff --git a/Chalice/examples/dining-philosophers.chalice b/Chalice/examples/dining-philosophers.chalice
new file mode 100644
index 00000000..6a67174c
--- /dev/null
+++ b/Chalice/examples/dining-philosophers.chalice
@@ -0,0 +1,93 @@
+class Philosopher module Philosophers {
+ var left: Fork;
+ var right: Fork;
+
+ method init(f1: Fork, f2: Fork)
+ requires f1!=null && f2!=null;
+ requires acc(this.*);
+ ensures valid;
+ ensures getLeft()==f1 && getRight()==f2;
+ {
+ left := f1;
+ right := f2;
+ fold valid;
+ }
+
+ method run()
+ requires valid;
+ requires acc(getLeft().mu, 10);
+ requires acc(getRight().mu, 10);
+ requires maxlock << getLeft().mu;
+ requires maxlock << getRight().mu;
+ requires getLeft().mu << getRight().mu;
+ {
+ while(true)
+ invariant valid && acc(getLeft().mu, 10) && acc(getRight().mu, 10) && maxlock << getLeft().mu && maxlock << getRight().mu && getLeft().mu << getRight().mu;
+ {
+ unfold valid;
+ acquire left;
+ acquire right;
+ //eat
+ release left;
+ release right;
+ fold valid;
+ }
+ }
+
+ function getLeft(): Fork
+ requires valid;
+ ensures result!=null;
+ {
+ unfolding valid in left
+ }
+
+ function getRight(): Fork
+ requires valid;
+ ensures result!=null;
+ {
+ unfolding valid in right
+ }
+
+ predicate valid {
+ acc(left) && acc(right) && left!=null && right!=null
+ }
+}
+
+class Fork module Dining {
+ invariant true;
+}
+
+class Program module Main {
+ method main(){
+ // create forks
+ var f1 := new Fork;
+ var f2 := new Fork;
+ var f3 := new Fork;
+
+ share f1;
+ share f2 above f1;
+ share f3 above f1, f2;
+
+ // create philosophers
+ var aristotle := new Philosopher;
+ call aristotle.init(f1, f2);
+
+ var plato := new Philosopher;
+ call plato.init(f2, f3);
+
+ var kant := new Philosopher;
+ call kant.init(f1, f3);
+
+ assert f2.mu << f3.mu;
+
+ // start eating
+ fork tk0 := aristotle.run();
+ fork tk1 := plato.run();
+ fork tk2 := kant.run();
+
+ // everyone's done
+ join tk0;
+ join tk1;
+ join tk2;
+ }
+} \ No newline at end of file
diff --git a/Chalice/examples/iterator.chalice b/Chalice/examples/iterator.chalice
new file mode 100644
index 00000000..356e6d83
--- /dev/null
+++ b/Chalice/examples/iterator.chalice
@@ -0,0 +1,150 @@
+class List module Collections {
+ var contents: seq<int>;
+
+ method init()
+ requires acc(contents);
+ ensures valid && size(100)==0;
+ {
+ contents := nil<int>;
+ fold valid;
+ }
+
+ method add(x: int)
+ requires valid;
+ ensures valid && size(100) == old(size(100)+1) && get(size(100)-1, 100) == x;
+ ensures forall { i in [0:size(100)-1]; get(i, 100) == old(get(i, 100)) };
+ {
+ unfold valid;
+ contents := contents ++ [x];
+ fold valid;
+ }
+
+ function get(index: int, f: int): int
+ requires 0<f && f<=100 && acc(valid, f) && (0<=index && index<size(f));
+ ensures forall { i in [1:f]; get(index, f) == get(index, i)};
+ {
+ unfolding acc(valid, f) in contents[index]
+ }
+
+ function size(f: int): int
+ requires 0<f && f<=100 && acc(valid, f);
+ ensures 0<=result;
+ ensures forall { i in [1:f]; size(f) == size(i)};
+ {
+ unfolding acc(valid, f) in |contents|
+ }
+
+ predicate valid {
+ acc(contents)
+ }
+}
+
+class Iterator module Collections {
+ var list: List;
+ var index: int;
+ var frac: int;
+
+ method init(l: List, f: int)
+ requires 0<f && f<=100;
+ requires acc(list) && acc(index) && acc(frac);
+ requires l!=null;
+ requires acc(l.valid, f);
+ ensures valid;
+ ensures getList()==l;
+ ensures getFraction()==f;
+ {
+ list := l;
+ this.index := 0;
+ frac := f;
+ fold valid;
+ }
+
+ method next() returns (rt: int)
+ requires valid && hasNext();
+ ensures valid;
+ ensures getList()==old(getList());
+ ensures getFraction()==old(getFraction());
+ {
+ unfold valid;
+ rt := list.get(index, frac);
+ index := index + 1;
+ fold valid;
+ }
+
+ method dispose()
+ requires valid;
+ ensures acc(old(getList()).valid, old(getFraction()));
+ {
+ unfold valid;
+ }
+
+ function hasNext(): bool
+ requires valid;
+ {
+ unfolding valid in index<list.size(frac)
+ }
+
+ function getFraction(): int
+ requires valid;
+ ensures 0<result && result<=100;
+ {
+ unfolding valid in frac
+ }
+
+ function getList(): List
+ requires valid;
+ ensures getList()!=null;
+ {
+ unfolding valid in list
+ }
+
+ predicate valid
+ {
+ acc(list) && acc(index) && acc(frac) && 0<frac && frac<=100 && list!=null && acc(list.valid, frac) && 0<=index && index<=list.size(frac)
+ }
+}
+
+class Program module Main {
+ method main(){
+ var tmp: int;
+ //create a new list
+ var list := new List;
+ call list.init();
+ call list.add(5);
+ call list.add(6);
+
+ // create a new iterator
+ var iter1 := new Iterator;
+ assert list!=null; // needed here: triggering problem?
+ assert list.size(100)==2;
+ assert list.size(50)==2;
+ call iter1.init(list, 10);
+
+ // create a second iterator
+ var iter2 := new Iterator;
+ assert list!=null; // needed here: triggering problem?
+ call iter2.init(list, 10);
+
+ // iterate over the list
+ while(iter1.hasNext())
+ invariant iter1.valid && iter1.getList()==list && iter1.getFraction()==10;
+ {
+ call tmp := iter1.next();
+ }
+
+ // iterate over the list
+ while(iter2.hasNext())
+ invariant iter2.valid && iter2.getList()==list && iter2.getFraction()==10;
+ {
+ call tmp := iter2.next();
+ }
+
+ // dispose the iterators
+ call iter1.dispose();
+ call iter2.dispose();
+
+ // full access to the list
+ assert list.valid;
+ assert list.size(50)==2;
+ }
+} \ No newline at end of file
diff --git a/Chalice/examples/iterator2.chalice b/Chalice/examples/iterator2.chalice
new file mode 100644
index 00000000..5b75c1ca
--- /dev/null
+++ b/Chalice/examples/iterator2.chalice
@@ -0,0 +1,134 @@
+/* Iterator pattern in Chalice. */
+
+class List module Collections {
+ var contents: seq<int>;
+
+ method init()
+ requires acc(contents);
+ ensures valid && size()==0;
+ {
+ contents := nil<int>;
+ fold valid;
+ }
+
+ method add(x: int)
+ requires valid;
+ ensures valid && size() == old(size()+1) && get(size()-1) == x; // I don't know why this happens.
+ ensures forall { i in [0:size()-1]; get(i) == old(get(i)) };
+ {
+ unfold valid;
+ contents := contents ++ [x];
+ fold valid;
+ }
+
+ function get(index: int): int
+ requires rd(valid) && 0<=index && index<size();
+ {
+ unfolding rd(valid) in contents[index]
+ }
+
+ function size(): int
+ requires rd(valid);
+ ensures 0<=result;
+ {
+ unfolding rd(valid) in |contents|
+ }
+
+ predicate valid {
+ acc(contents)
+ }
+}
+
+class Iterator module Collections {
+ var list: List;
+ var index: int;
+
+ method init(l: List)
+ requires acc(list) && acc(index);
+ requires l!=null;
+ requires rd(l.valid);
+ ensures valid;
+ ensures getList()==l;
+ {
+ list := l;
+ this.index := 0;
+ fold valid;
+ }
+
+ method next() returns (rt: int)
+ requires valid && hasNext();
+ ensures valid;
+ ensures getList()==old(getList());
+ {
+ unfold valid;
+ rt := list.get(index);
+ index := index + 1;
+ fold valid;
+ }
+
+ method dispose()
+ requires valid;
+ ensures rd(old(getList()).valid);
+ {
+ unfold valid;
+ }
+
+ function hasNext(): bool
+ requires valid;
+ {
+ unfolding valid in index<list.size()
+ }
+
+ function getList(): List
+ requires valid;
+ ensures result!=null;
+ {
+ unfolding valid in list
+ }
+
+ predicate valid
+ {
+ acc(list) && acc(index) && list!=null && rd(list.valid) && 0<=index && index<=list.size()
+ }
+}
+
+class Program module Main {
+ method main(){
+ var tmp: int;
+ //create a new list
+ var list := new List;
+ call list.init();
+ call list.add(5);
+ call list.add(6);
+
+ // create a new iterator
+ var iter1 := new Iterator;
+ call iter1.init(list);
+
+ // create a second iterator
+ var iter2 := new Iterator;
+ call iter2.init(list);
+
+ // iterate over the list
+ while(iter1.hasNext())
+ invariant iter1.valid && iter1.getList()==list;
+ {
+ call tmp := iter1.next();
+ }
+
+ // iterate over the list
+ while(iter2.hasNext())
+ invariant iter2.valid && iter2.getList()==list;
+ {
+ call tmp := iter2.next();
+ }
+
+ // dispose the iterators
+ call iter1.dispose();
+ call iter2.dispose();
+
+ // full access to the list
+ assert list.valid;
+ assert list.size()==2;
+ }
+} \ No newline at end of file
diff --git a/Chalice/examples/linkedlist.chalice b/Chalice/examples/linkedlist.chalice
new file mode 100644
index 00000000..acde86ab
--- /dev/null
+++ b/Chalice/examples/linkedlist.chalice
@@ -0,0 +1,61 @@
+/* Recursive implementation and specification of a linked list. */
+
+class Node {
+ var next: Node;
+ var value: int;
+
+ method init(v: int)
+ requires acc(next) && acc(value);
+ ensures valid && size() == 1;
+ {
+ next := null;
+ value := v;
+ fold this.valid;
+ }
+
+ method add(x: int)
+ requires valid;
+ ensures valid;
+ ensures size() == old(size())+1;
+ {
+ unfold this.valid;
+ if(next==null) {
+ var n : Node;
+ n := new Node;
+ call n.init(x);
+ next := n;
+ } else {
+ call next.add(x);
+ }
+ fold this.valid;
+ }
+
+ method addFirst(x: int) returns (rt: Node)
+ requires valid;
+ ensures rt!=null && rt.valid;
+ ensures rt.size() == old(size()) + 1;
+ {
+ var n: Node;
+ n := new Node;
+ n.value := x;
+ n.next := this;
+ fold n.valid;
+ rt := n;
+ }
+
+ 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!
+ }
+
+ function size(): int
+ requires valid;
+ {
+ unfolding this.valid in (next!=null ? 1+ next.size() : 1)
+ }
+
+ predicate valid {
+ acc(next) && acc(value) && (next!=null ==> next.valid)
+ }
+} \ No newline at end of file
diff --git a/Chalice/examples/producer-consumer.chalice b/Chalice/examples/producer-consumer.chalice
new file mode 100644
index 00000000..f2c751d9
--- /dev/null
+++ b/Chalice/examples/producer-consumer.chalice
@@ -0,0 +1,202 @@
+class Program {
+ method main(){
+ var buffer := new Queue;
+ call buffer.init();
+ share buffer;
+
+ var producer := new Producer;
+ call producer.init(buffer);
+ fork tkP := producer.run();
+
+ var consumer := new Consumer;
+ call consumer.init(buffer);
+ fork tkC := consumer.run();
+
+ join tkP;
+ join tkC;
+
+ acquire buffer;
+ unshare buffer;
+
+ var tmp := buffer.size();
+ }
+}
+
+class Producer module Producer {
+ var buffer: Queue;
+
+ method init(buff: Queue)
+ requires acc(buffer) && buff!=null;
+ ensures valid && getBuffer()==buff;
+ {
+ buffer := buff;
+ fold valid;
+ }
+
+ method run()
+ requires valid && rd(getBuffer().mu) && maxlock << getBuffer().mu;
+ ensures rd(old(getBuffer()).mu);
+ {
+ var tmp: int;
+
+ while(true)
+ invariant valid && rd(getBuffer().mu) && maxlock << getBuffer().mu;
+ {
+ unfold valid;
+ acquire buffer;
+ call buffer.enqueue(5);
+ release buffer;
+ fold valid;
+ }
+ unfold valid;
+ }
+
+ function getBuffer(): Queue
+ requires valid;
+ ensures result!=null;
+ {
+ unfolding valid in buffer
+ }
+
+ predicate valid {
+ acc(buffer) && buffer!=null
+ }
+}
+
+class Consumer module Consumer {
+ var buffer: Queue;
+
+ method init(buff: Queue)
+ requires acc(buffer) && buff!=null;
+ ensures valid && getBuffer()==buff;
+ {
+ buffer := buff;
+ fold valid;
+ }
+
+ method run()
+ requires valid && rd(getBuffer().mu) && maxlock << getBuffer().mu;
+ ensures rd(old(getBuffer()).mu);
+ {
+ while(true)
+ invariant valid && rd(getBuffer().mu) && maxlock << getBuffer().mu;
+ {
+ unfold valid;
+ acquire buffer;
+ if(0<=buffer.size()){
+ call buffer.enqueue(5);
+ }
+ release buffer;
+ fold valid;
+ }
+ unfold valid;
+ }
+
+ function getBuffer(): Queue
+ requires valid;
+ ensures result!=null;
+ {
+ unfolding valid in buffer
+ }
+
+ predicate valid {
+ acc(buffer) && buffer!=null
+ }
+}
+
+class Queue module Queue {
+ var contents: List;
+
+ invariant valid;
+
+ method init()
+ requires acc(contents);
+ ensures valid;
+ ensures size()==0;
+ {
+ contents := new List;
+ call contents.init();
+ fold valid;
+ }
+
+ method enqueue(x: int)
+ requires valid;
+ ensures valid;
+ ensures size() == old(size())+1;
+ {
+ unfold valid;
+ call contents.add(x);
+ fold valid;
+ }
+
+ method dequeue() returns (rt: int)
+ requires valid && 0<size();
+ ensures valid;
+ ensures size() == old(size())-1;
+ {
+ unfold valid;
+ call rt := contents.removeFirst();
+ fold valid;
+ }
+
+ function size(): int
+ requires valid;
+ {
+ unfolding valid in contents.size()
+ }
+
+ predicate valid {
+ acc(contents) && contents!=null && contents.valid
+ }
+}
+
+class List module Collections {
+ var contents: seq<int>;
+
+ method init()
+ requires acc(contents);
+ ensures valid && size()==0;
+ {
+ contents := nil<int>;
+ fold valid;
+ }
+
+ method add(x: int)
+ requires valid;
+ ensures valid && size() == old(size()+1) && get(size()-1) == x;
+ ensures forall { i in [0:size()-1]; get(i) == old(get(i)) };
+ {
+ unfold valid;
+ contents := contents ++ [x];
+ fold valid;
+ }
+
+ method removeFirst() returns (rt: int)
+ requires valid && 0<size();
+ ensures valid && size() == old(size()-1);
+ ensures forall { i in [0:size()]; get(i) == old(get(i+1)) };
+ {
+ unfold valid;
+ rt := contents[0];
+ contents := contents[1..];
+ fold valid;
+ }
+
+
+ function get(index: int): int
+ requires rd(valid) && 0<=index && index<size();
+ {
+ unfolding rd(valid) in contents[index]
+ }
+
+ function size(): int
+ requires rd(valid);
+ ensures 0<=result;
+ {
+ unfolding rd(valid) in |contents|
+ }
+
+ predicate valid {
+ acc(contents)
+ }
+} \ No newline at end of file
diff --git a/Chalice/examples/prog0.chalice b/Chalice/examples/prog0.chalice
new file mode 100644
index 00000000..da351c85
--- /dev/null
+++ b/Chalice/examples/prog0.chalice
@@ -0,0 +1,65 @@
+class C {
+ method m() {
+ assert 4 + (a * 5) + (2 + 3) * (a + a);
+ a := a + 3;
+ b := a - b - c + 4 * d + 20 + --25;
+ b := ((((a - b) - c) + 4 * d) + 20) + --25;
+ c := a - (b - (c + (4 * d + (20 + 25))));
+ assert (X ==> Y) ==> Z <==> A ==> B ==> C;
+ assume A && B && (C || D || E) && F;
+ var x;
+ var y := 12 + !(x.f.g).h - (!x).f + (!x.f);
+ var z := new C;
+ y := new D;
+ o.f := 5;
+ (a + b).y := new T;
+ reorder (2 ==(O != 3)) != O between a,b,c and x,y,z;
+ reorder X ==> Y below x+5;
+ reorder o.f above this, null;
+ share o;
+ unshare o;
+ acquire o;
+ release o;
+ rd acquire o;
+ rd release o;
+ downgrade o;
+ var tok: token<C.m>;
+ fork tok := o.m();
+ join tok;
+ assert rd(x) + acc(y) + acc(z, 1/4) + old(old(k)) + null.f;
+ x := this.f;
+ call m(2,3,4);
+ call this.m(2,3,4);
+ call a,b,c := o.m();
+ call x := m(200);
+ reorder o above maxlock;
+ }
+ method p(a,b,c) returns (x,y,z)
+ requires 8 + 2 == 10;
+ ensures 8 + 5 > 10;
+ requires x == y+1;
+ ensures old(x) < x;
+ {
+ if (x == 7) {
+ y := y + 1; z := z + 2;
+ } else if (x == 8) {
+ y := 2;
+ } else {
+ z := 10;
+ }
+ { // empty block
+ }
+ if (x == 9) { }
+ if (x == 10) { x := 10; } else { }
+ var n := 0;
+ while (n < 100) { n := n - 1; }
+ while (n != 0)
+ invariant n % 2 == 0;
+ invariant sqrt2 * sqrt2 == 2;
+ {
+ n := n - 2;
+ }
+ call v,x := s.M(65);
+ }
+}
+class D { }
diff --git a/Chalice/examples/prog1.chalice b/Chalice/examples/prog1.chalice
new file mode 100644
index 00000000..133de36d
--- /dev/null
+++ b/Chalice/examples/prog1.chalice
@@ -0,0 +1,86 @@
+// 7 errors expected
+
+class C {
+ var x: int;
+ invariant acc(x) && 0 <= x;
+
+ method seq0() returns (r: int)
+ {
+ r := x; // error: cannot access this.x here (90)
+ }
+ method seq1() returns (r: int)
+ requires acc(x);
+ {
+ r := x;
+ }
+ method seq2() returns (r: int)
+ requires rd(x);
+ {
+ r := x;
+ }
+ method seq3() returns (r: int)
+ requires rd(x);
+ {
+ r := x;
+ x := x + 1; // error: cannot write to this.x here (184)
+ }
+
+ method main0()
+ {
+ var c := new C;
+ c.x := 0;
+ share c;
+ var t := c.x; // error: cannot access c.x now (254)
+ }
+ method main1()
+ {
+ var c := new C;
+ c.x := 2;
+ share c;
+ acquire c;
+ c.x := c.x - 1;
+ release c; // error: monitor invariant might not hold (362)
+ }
+ method main2()
+ {
+ var c := new C;
+ c.x := 2;
+ share c;
+ acquire c;
+ c.x := c.x + 1;
+ release c; // good!
+ }
+ method main3()
+ {
+ var c := new C;
+ c.x := 2;
+ share c;
+ rd acquire c;
+ var tmp := c.x + 1; // fine
+ c.x := tmp; // error: cannot write to c.x here (582)
+ rd release c;
+ }
+ method main4()
+ {
+ var c := new C;
+ c.x := 2;
+ share c;
+ acquire c;
+ c.x := c.x + 1;
+ unshare c;
+ c.x := c.x + 1;
+ }
+ method main5()
+ {
+ var c := new C;
+ unshare c; // error: cannot unshare an object that isn't shared (754)
+ }
+ method main6()
+ {
+ var c := new C;
+ c.x := 0;
+ share c; acquire c;
+ unshare c;
+ unshare c; // error: cannot unshare an object that isn't shared (862)
+ }
+} \ No newline at end of file
diff --git a/Chalice/examples/prog2.chalice b/Chalice/examples/prog2.chalice
new file mode 100644
index 00000000..55fe8ff5
--- /dev/null
+++ b/Chalice/examples/prog2.chalice
@@ -0,0 +1,93 @@
+// 4 errors expected
+
+class C {
+ method M(x: int) returns (y: bool)
+ requires 0 <= x;
+ ensures y <==> x == 10;
+ {
+ y := true;
+ if (x != 10) { y := !y; }
+ }
+
+ method Caller0()
+ {
+ var b: bool;
+ call b := M(12);
+ assert !b;
+ call b := M(10);
+ assert b;
+ }
+ method Caller1()
+ {
+ var b: bool;
+ call b := M(11);
+ assert b; // error (258)
+ }
+
+ var F: int;
+
+ method P(n: int)
+ requires acc(F);
+ ensures F == old(F) + n; // error
+ {
+ F := F + n;
+ }
+ method Caller2()
+ requires acc(F);
+ {
+ var prev := F;
+ call P(2);
+ assert false; // succeeds because postcondition of P is not well-defined (i.e. we do not havoc this.F, so the verifier assumes the value is the same in pre and post)
+ }
+
+ method Q(n: int)
+ requires acc(F);
+ ensures acc(F) && F == old(F) + n;
+ {
+ F := F + n;
+ }
+ method Caller3()
+ requires acc(F);
+ ensures acc(F);
+ {
+ var prev := F;
+ call Q(2);
+ assert F == prev + 2;
+ }
+}
+
+class Consts {
+ method M0() returns (z: int)
+ ensures z == 5
+ {
+ const a := 5
+ z := a
+ }
+ method M1() {
+ ghost const a
+ a := 5
+ }
+ method M2() {
+ ghost const a
+ a := 5
+ a := 5 // error (569)
+ }
+ method M3(b: bool) {
+ ghost const a
+ if (b) { a := 5 }
+ assert a < 10 // error (611)
+ }
+ method M4(b: bool) {
+ ghost const a
+ if (b) { a := 5 }
+ ghost var x := a
+ if (!b) { a := 7 }
+ assert a < 10
+ assert b ==> x == 5 // cool, huh?
+ }
+ method M5(b: bool) {
+ ghost const a
+ if (b) { a := 5 }
+ assert assigned(a) ==> a == 5
+ }
+}
diff --git a/Chalice/examples/prog3.chalice b/Chalice/examples/prog3.chalice
new file mode 100644
index 00000000..6c323d0e
--- /dev/null
+++ b/Chalice/examples/prog3.chalice
@@ -0,0 +1,247 @@
+// 4 errors expected
+
+class Main {
+ method A() {
+ var d := new Data;
+ call d.Init();
+ share d;
+
+ var t0: T := new T; t0.d := d;
+ share t0 between maxlock and d
+ var t1: T := new T; t1.d := d;
+ share t1 between maxlock and d
+
+ var t0Token: token<T.run>;
+ fork t0Token := t0.run();
+ var t1Token: token<T.run>;
+ fork t1Token := t1.run();
+
+ join t0Token; acquire t0; unshare t0;
+ join t1Token; acquire t1; unshare t1;
+
+ acquire d; unshare d;
+ assert 0 <= d.x && d.x < 100;
+ }
+
+ method B() returns (r: U)
+ lockchange r;
+ {
+ var u := new U;
+ share u;
+
+ var uToken: token<U.run>;
+ fork uToken := u.run();
+
+ acquire u; // a little unusual to acquire after a fork, but allowed
+ assert maxlock == u.mu;
+
+ var v := new U;
+ share v; acquire v; // this line has the effect of increasing maxlock
+
+ assert maxlock == v.mu;
+ assert maxlock != u.mu;
+ assert u << v;
+ assert u << maxlock;
+
+ join uToken; // material for the smoke check
+ release u;
+ r := v;
+ }
+
+ method C()
+ ensures maxlock == old(maxlock);
+ {
+ var u := new U;
+ share u;
+ acquire u;
+ release u;
+ }
+
+ method Mx0()
+ {
+ }
+ method Mx1()
+ lockchange this
+ {
+ }
+ method MxCaller0()
+ ensures maxlock == old(maxlock);
+ {
+ }
+ method MxCaller1()
+ ensures maxlock == old(maxlock);
+ {
+ call Mx0();
+ }
+ method MxCaller2()
+ ensures maxlock == old(maxlock); // error
+ {
+ call Mx1();
+ } // error: missing lockchange
+
+ method D(u: U)
+ requires u != null && rd(u.mu) && maxlock << u;
+ ensures maxlock == old(maxlock);
+ {
+ acquire u;
+ release u;
+ }
+}
+
+class Data {
+ var x: int;
+ invariant acc(x) && 0 <= x && x < 100;
+ method Init()
+ requires acc(x);
+ ensures acc(x) && x == 0;
+ {
+ x := 0;
+ }
+}
+
+class T {
+ var d: Data;
+ invariant rd(d) && d != null && rd(d.mu) && rd(this.mu) && this << d;
+ method run()
+ requires rd(mu) && maxlock << this;
+ ensures rd(mu);
+ {
+ acquire this;
+ acquire d;
+ d.x := d.x + 1;
+ if (d.x == 100) { d.x := 0; }
+ release d;
+ release this;
+ }
+}
+
+class U {
+ method run()
+ requires rd(mu) && maxlock << this;
+ ensures rd(mu);
+ {
+ }
+}
+
+// Tests that use OLD in postcondition of run:
+
+class X {
+ var k: int
+ var l: int
+
+ method inc()
+ requires acc(k)
+ ensures acc(k) && k == old(k) + 1
+ {
+ k := k + 1
+ }
+ method Client0() returns (y: int)
+ ensures y == 8
+ {
+ var x := new X
+ x.k := 17 x.l := 10
+ call x.inc()
+ assert x.k == 18 && x.l == 10
+ y := x.k - x.l
+ }
+
+ method run()
+ requires acc(k) && 0 <= k
+ ensures acc(k) && k == old(k) + 1
+ {
+ k := k + 1
+ }
+
+ method Client1() returns (y: int)
+ ensures y == 8
+ {
+ var x := new X
+ x.k := 17
+ x.l := 20
+ var xToken: token<X.run>;
+ fork xToken := x.run();
+ x.l := 10
+ join xToken
+ assert x.k == 18 && x.l == 10
+ y := x.k - x.l
+ }
+ method Client2(tk: token<X.run>, x: X) returns (z: int)
+ requires x!=null && tk!=null && acc(tk.joinable) && tk.joinable && eval(tk.fork x.run(), acc(x.k) && 0<=x.k);
+ ensures 1 <= z
+ {
+ join tk
+ z := x.k
+ assert 1<=x.k;
+ }
+}
+
+class ReadSharing {
+ var x: int
+
+ method Consume()
+ requires rd(x)
+ {
+ // skip
+ }
+
+ method Divulge() // bad
+ requires rd(x)
+ {
+ call Consume()
+ call Consume() // error: cannot share twice (1773)
+ }
+
+ method Communicates() // good
+ requires rd(x,3)
+ ensures rd(x,1)
+ {
+ call Consume()
+ call Consume()
+ }
+
+ method Gossips() // bad
+ requires rd(x,3)
+ ensures rd(x,1)
+ {
+ call Consume()
+ call Consume()
+ call Consume()
+ } // error: does not live up to postcondition (2015)
+
+ method Shares() // good
+ requires rd(x,*)
+ ensures rd(x,*)
+ {
+ call Consume()
+ call Consume()
+ call Consume()
+ }
+
+ method TeamPlayer(N: int) // good
+ requires 0<=N && rd(x,N)
+ ensures rd(x,0)
+ {
+ var n := N
+ while (0 < n)
+ invariant 0<=n && rd(x,n)
+ {
+ n := n - 1
+ }
+ }
+
+ method Unselfish(N: int) // good
+ requires rd(x,*)
+ ensures rd(x,*)
+ {
+ var n := N
+ if (N == 173) {
+ call Unselfish(200)
+ }
+ while (0 < n)
+ invariant rd(x,*)
+ {
+ call Consume()
+ n := n - 1
+ }
+ }
+}
diff --git a/Chalice/examples/prog4.chalice b/Chalice/examples/prog4.chalice
new file mode 100644
index 00000000..655c5815
--- /dev/null
+++ b/Chalice/examples/prog4.chalice
@@ -0,0 +1,49 @@
+class LoopTargets {
+ method M() returns (y) {
+ y := 0
+ while (y < 100) { y := y + 1 }
+ assert y == 0 // error (139)
+ }
+ method N() returns (t: LoopTargets)
+ lockchange t
+ {
+ t := new LoopTargets
+ share t
+ acquire t
+ var s := true
+ while (s) {
+ release t // error: loop invariant does not say holds(t) (252)
+ s := false
+ }
+ }
+ method P() {
+ var t := new LoopTargets
+ share t
+ acquire t
+ var s := true
+ while (s)
+ invariant acc(t.mu) && maxlock == t.mu
+ {
+ release t // error: loop invariant does not say holds(t) (414)
+ acquire t
+ s := false
+ }
+ release t
+ }
+ method Q() {
+ var t := new LoopTargets
+ share t
+ acquire t
+ var s := true
+ while (s)
+ invariant rd(t.mu)
+ invariant holds(t) && maxlock == t.mu
+ {
+ release t
+ acquire t
+ s := false
+ }
+ assert holds(t) // there we are
+ release t
+ }
+}
diff --git a/Chalice/examples/swap.chalice b/Chalice/examples/swap.chalice
new file mode 100644
index 00000000..46a6a71a
--- /dev/null
+++ b/Chalice/examples/swap.chalice
@@ -0,0 +1,20 @@
+class C {
+ method m(a, b) returns (x, y)
+ ensures x == a && y == b;
+ {
+ x := a;
+ y := b;
+ }
+
+ var F;
+ var G;
+ method n()
+ requires acc(F) && acc(this.G);
+ ensures acc(F) && acc(G);
+ ensures F == old(G) && G == old(F);
+ {
+ var tmp := F;
+ F := G;
+ G := tmp;
+ }
+}
diff --git a/Chalice/make.bat b/Chalice/make.bat
new file mode 100644
index 00000000..5ad68d43
--- /dev/null
+++ b/Chalice/make.bat
@@ -0,0 +1 @@
+python make.py \ No newline at end of file
diff --git a/Chalice/make.py b/Chalice/make.py
new file mode 100644
index 00000000..e3ba1ab9
--- /dev/null
+++ b/Chalice/make.py
@@ -0,0 +1,35 @@
+import os
+import glob
+import sys
+import datetime
+
+bindir = "bin"
+
+srcspecs = ["src\\*.scala"]
+srcfiles = [file for spec in srcspecs for file in glob.glob(spec)]
+
+buildstamp = "makestamp"
+
+lastbuild = None
+if os.path.exists(buildstamp):
+ lastbuild = os.path.getmtime(buildstamp)
+
+changedfiles = [file for file in srcfiles if not lastbuild or lastbuild <= os.path.getmtime(file)]
+
+if not changedfiles:
+ print "Build is up-to-date."
+ sys.exit(0)
+
+def printtime():
+ print datetime.datetime.now().strftime("%H:%M:%S")
+
+printtime()
+cmd = "scalac -d bin -unchecked -deprecation " + " ".join(changedfiles) + " & if errorlevel 1 exit 1"
+print cmd
+result = os.system(cmd)
+printtime()
+
+if result == 0:
+ open(buildstamp, "w").close()
+else:
+ print "Build failed."
diff --git a/Chalice/src/Ast.scala b/Chalice/src/Ast.scala
new file mode 100644
index 00000000..44d97290
--- /dev/null
+++ b/Chalice/src/Ast.scala
@@ -0,0 +1,384 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+import scala.util.parsing.input.Position
+import scala.util.parsing.input.Positional
+
+trait ASTNode extends Positional
+
+// classes and types
+
+sealed case class Class(id: String, parameters: List[Class], module: String, members: List[Member]) extends ASTNode {
+ var mm = Map[String,Member]()
+ def LookupMember(id: String): Option[Member] = {
+ if (mm.keys exists { i => i.equals(id)})
+ Some(mm(id))
+ else if (IsRef && (RootClass.mm contains id)) {
+ val m = RootClass.mm(id)
+ if (m.Hidden) None else Some(m)
+ } else
+ None
+ }
+ def IsInt: boolean = false
+ def IsBool: boolean = false
+ def IsRef: boolean = true
+ def IsNull: boolean = false
+ def IsMu: boolean = false
+ def IsSeq: boolean = false
+ def IsToken: boolean = false
+ def IsState: boolean = false
+ def IsNormalClass = true;
+ var IsExternal = false; // says whether or not to compile the class (compilation ignores external classes)
+
+ def Fields: List[Field] = {
+ members flatMap (m => m match { case f:Field => List(f) case _ => List() })
+ }
+ def Invariants: List[MonitorInvariant] = {
+ (members :\ List[MonitorInvariant]()) { (m,list) => m match {
+ case m:MonitorInvariant => m :: list
+ case _ => list }}
+ }
+ def FullName: String = if(parameters.isEmpty) id else id + "<" + parameters.tail.foldLeft(parameters.head.FullName){(a, b) => a + ", " + b.FullName} + ">"
+}
+
+case class SeqClass(parameter: Class) extends Class("seq", List(parameter), "default", Nil) {
+ override def IsRef = false;
+ override def IsSeq = true;
+ override def IsNormalClass = false;
+}
+object IntClass extends Class("int", Nil, "default", Nil) {
+ override def IsRef = false
+ override def IsInt = true
+ override def IsNormalClass = false;
+}
+object BoolClass extends Class("bool", Nil, "default", Nil) {
+ override def IsRef = false
+ override def IsBool = true
+ override def IsNormalClass = false;
+}
+object NullClass extends Class("null", Nil, "default", Nil) {
+ override def IsNull = true
+ override def IsNormalClass = false;
+}
+object MuClass extends Class("$Mu", Nil, "default", Nil) {
+ override def IsRef = false
+ override def IsMu = true
+ override def IsNormalClass = false;
+}
+case class TokenClass(c: Type, m: String) extends Class("token", Nil, "default", List(
+ new SpecialField("joinable", new Type(BoolClass))
+))
+{
+ var method = null: Method;
+ override def IsRef = true;
+ override def IsToken = true;
+ override def IsNormalClass = false;
+ override def FullName: String = "token<" + c.FullName + "." + m + ">"
+ mm = mm.+(("joinable", Fields(0)));
+}
+
+object RootClass extends Class("$root", Nil, "default", List(
+ new SpecialField("mu", new Type(MuClass)),
+ new SpecialField("held", new Type(BoolClass)){ override val Hidden = true },
+ new SpecialField("rdheld", new Type(BoolClass)){ override val Hidden = true }
+ )) // joinable and held are bool in Chalice, but translated into an int in Boogie
+{
+ def MentionableFields = Fields filter {fld => fld.id != "held" && fld.id != "rdheld"}
+}
+
+sealed case class Type(id: String, params: List[Type]) extends ASTNode { // denotes the use of a type
+ var typ: Class = null
+ def this(id: String) = { this(id, Nil); }
+ def this(cl: Class) = { this(cl.id); typ = cl }
+ def FullName: String = if(params.isEmpty) id else id + "<" + params.tail.foldLeft(params.head.FullName){(a, b) => a + ", " + b.FullName} + ">"
+}
+
+sealed case class TokenType(C: Type, m: String) extends Type("token", Nil) { // denotes the use of a type
+ typ = TokenClass(C, m);
+ var method = null : Method;
+
+ override def FullName: String = "token<" + C.FullName + "." + m + ">"
+}
+
+// members
+
+sealed abstract class Member extends ASTNode {
+ val Hidden: boolean = false // hidden means not mentionable in source
+}
+case class MonitorInvariant(e: Expression) extends Member
+sealed abstract class NamedMember(id: String) extends Member {
+ val Id = id
+ var Parent: Class = null
+ def FullName = Parent.id + "." + Id
+}
+case class Field(id: String, typ: Type) extends NamedMember(id) {
+ val IsGhost: boolean = false
+}
+case class SpecialField(name: String, tp: Type) extends Field(name, tp) { // direct assignments are not allowed to a SpecialField
+ override def FullName = id
+}
+case class Method(id: String, ins: List[Variable], outs: List[Variable], spec: List[Specification], body: List[Statement]) extends NamedMember(id)
+case class Predicate(id: String, definition: Expression) extends NamedMember(id)
+case class Function(id: String, ins: List[Variable], out: Type, spec: List[Specification], definition: Expression) extends NamedMember(id) {
+ def apply(rec: Expression, args: List[Expression]): FunctionApplication = {
+ val result = FunctionApplication(rec, id, args);
+ result.f = this;
+ result
+ }
+}
+class Variable(name: String, typ: Type) extends ASTNode {
+ val id = name
+ val t = typ
+ val IsGhost: boolean = false
+ val IsImmutable: boolean = false
+ val UniqueName = {
+ val n = S_Variable.VariableCount
+ S_Variable.VariableCount = S_Variable.VariableCount + 1
+ name + "#" + n
+ }
+}
+object S_Variable { var VariableCount = 0 }
+class ImmutableVariable(id: String, t: Type) extends Variable(id, t) {
+ override val IsImmutable: boolean = true
+}
+class SpecialVariable(name: String, typ: Type) extends Variable(name, typ) {
+ override val UniqueName = name
+}
+
+sealed abstract class Specification extends ASTNode
+case class Precondition(e: Expression) extends Specification
+case class Postcondition(e: Expression) extends Specification
+case class LockChange(ee: List[Expression]) extends Specification
+
+// statements
+
+sealed abstract class Statement extends ASTNode
+case class Assert(e: Expression) extends Statement
+case class Assume(e: Expression) extends Statement
+case class BlockStmt(ss: List[Statement]) extends Statement
+case class IfStmt(guard: Expression, thn: BlockStmt, els: Option[Statement]) extends Statement
+case class WhileStmt(guard: Expression,
+ invs: List[Expression], lkch: List[Expression],
+ body: BlockStmt) extends Statement {
+ var LoopTargets: Set[Variable] = null
+ lazy val LoopTargetsList: List[Variable] = { // to be called only after LoopTargets has been completely filled in
+ var vv = List[Variable]()
+ LoopTargets foreach (v => vv = v :: vv)
+ vv
+ }
+}
+case class Assign(lhs: VariableExpr, rhs: RValue) extends Statement
+case class FieldUpdate(lhs: MemberAccess, rhs: RValue) extends Statement
+case class LocalVar(id: String, t: Type, const: boolean, ghost: boolean, rhs: Option[RValue]) extends Statement {
+ val v =
+ if (const)
+ new ImmutableVariable(id, t){override val IsGhost = ghost}
+ else
+ new Variable(id, t){override val IsGhost = ghost}
+}
+case class Call(lhs: List[VariableExpr], obj: Expression, id: String, args: List[Expression]) extends Statement {
+ var m: Method = null
+}
+case class Install(obj: Expression, lowerBounds: List[Expression], upperBounds: List[Expression]) extends Statement
+case class Share(obj: Expression, lowerBounds: List[Expression], upperBounds: List[Expression]) extends Statement
+case class Unshare(obj: Expression) extends Statement
+case class Acquire(obj: Expression) extends Statement
+case class Release(obj: Expression) extends Statement
+case class RdAcquire(obj: Expression) extends Statement
+case class RdRelease(obj: Expression) extends Statement
+case class Downgrade(obj: Expression) extends Statement
+case class Lock(obj: Expression, b: BlockStmt, rdLock: boolean) extends Statement
+case class Free(obj: Expression) extends Statement
+case class CallAsync(declaresLocal: boolean, lhs: VariableExpr, obj: Expression, id: String, args: List[Expression]) extends Statement {
+ var local: Variable = null
+ var m: Method = null
+}
+case class JoinAsync(lhs: List[VariableExpr], token: Expression) extends Statement {
+ var m: Method = null
+}
+
+case class Fold(pred: PermissionExpr) extends Statement
+case class Unfold(pred: PermissionExpr) extends Statement
+
+// expressions
+
+sealed abstract class RValue extends ASTNode {
+ var typ: Class = null
+}
+case class NewRhs(id: String, initialization: List[Init]) extends RValue
+case class Init(id: String, e: Expression) extends ASTNode {
+ var f: Field = null;
+}
+sealed abstract class Expression extends RValue
+sealed abstract class Literal extends Expression
+case class IntLiteral(n: int) extends Literal
+case class BoolLiteral(b: boolean) extends Literal
+case class NullLiteral extends Literal
+case class MaxLockLiteral extends Literal
+case class LockBottomLiteral extends Literal
+case class VariableExpr(id: String) extends Expression {
+ var v: Variable = null
+ def this(vr: Variable) = { this(vr.id); v = vr; typ = vr.t.typ }
+}
+case class Result extends Expression
+sealed abstract class ThisExpr extends Expression {
+ override def equals(other: Any): Boolean = {
+ // needed in autoMagic, which checks for syntactic equality using equals
+ other.isInstanceOf[ThisExpr]
+ }
+}
+case class ExplicitThisExpr extends ThisExpr
+case class ImplicitThisExpr extends ThisExpr
+case class MemberAccess(e: Expression, id: String) extends Expression {
+ var isPredicate: Boolean = false;
+ var f: Field = null
+ var predicate: Predicate = null
+}
+case class IfThenElse(con: Expression, then: Expression, els: Expression) extends Expression
+
+sealed abstract class PermissionExpr extends Expression {
+ def getMemberAccess : MemberAccess
+}
+
+case class Access(e: MemberAccess, perm: Option[Expression]) extends PermissionExpr {
+ def getMemberAccess = e : MemberAccess;
+}
+case class RdAccess(e: MemberAccess, perm: Option[Option[Expression]]) extends PermissionExpr {
+ def getMemberAccess = e : MemberAccess;
+}
+
+case class AccessAll(obj: Expression, perm: Option[Expression]) extends Expression
+case class RdAccessAll(obj: Expression, perm: Option[Option[Expression]]) extends Expression
+
+case class Holds(e: Expression) extends Expression
+case class RdHolds(e: Expression) extends Expression
+case class Assigned(id: String) extends Expression {
+ var v: Variable = null
+}
+case class Old(e: Expression) extends Expression
+case class Not(e: Expression) extends Expression
+case class FunctionApplication(obj: Expression, id: String, args: List[Expression]) extends Expression {
+ var f: Function = null
+}
+case class Unfolding(pred: PermissionExpr, in: Expression) extends Expression
+sealed abstract class BinaryExpr(e0: Expression, e1: Expression) extends Expression {
+ def E0 = e0
+ def E1 = e1
+ def ExpectedLhsType: Class = BoolClass // sometimes undefined
+ def ExpectedRhsType: Class = BoolClass // sometimes undefined
+ val ResultType: Class = BoolClass
+ val OpName: String
+}
+case class Iff(e0: Expression, e1: Expression) extends BinaryExpr(e0,e1) {
+ override val OpName = "<==>"
+}
+case class Implies(e0: Expression, e1: Expression) extends BinaryExpr(e0,e1) {
+ override val OpName = "==>"
+}
+case class And(e0: Expression, e1: Expression) extends BinaryExpr(e0,e1) {
+ override val OpName = "&&"
+}
+case class Or(e0: Expression, e1: Expression) extends BinaryExpr(e0,e1) {
+ override val OpName = "||"
+}
+sealed abstract class ArithmeticExpr(e0: Expression, e1: Expression) extends BinaryExpr(e0,e1) {
+ override def ExpectedLhsType = IntClass
+ override def ExpectedRhsType = IntClass
+ override val ResultType = IntClass
+}
+case class Plus(e0: Expression, e1: Expression) extends ArithmeticExpr(e0,e1) {
+ override val OpName = "+"
+}
+case class Minus(e0: Expression, e1: Expression) extends ArithmeticExpr(e0,e1) {
+ override val OpName = "-"
+}
+case class Times(e0: Expression, e1: Expression) extends ArithmeticExpr(e0,e1) {
+ override val OpName = "*"
+}
+case class Div(e0: Expression, e1: Expression) extends ArithmeticExpr(e0,e1) {
+ override val OpName = "/"
+}
+case class Mod(e0: Expression, e1: Expression) extends ArithmeticExpr(e0,e1) {
+ override val OpName = "%"
+}
+sealed abstract class CompareExpr(e0: Expression, e1: Expression) extends BinaryExpr(e0,e1) {
+ override def ExpectedLhsType = IntClass
+ override def ExpectedRhsType = IntClass
+}
+sealed abstract class EqualityCompareExpr(e0: Expression, e1: Expression) extends CompareExpr(e0,e1) {
+ override def ExpectedLhsType = throw new Exception("EqualityCompareExpr does not have a single ExpectedArgsType")
+ override def ExpectedRhsType = throw new Exception("EqualityCompareExpr does not have a single ExpectedArgsType")
+}
+case class Eq(e0: Expression, e1: Expression) extends EqualityCompareExpr(e0,e1) {
+ override val OpName = "=="
+}
+case class Neq(e0: Expression, e1: Expression) extends EqualityCompareExpr(e0,e1) {
+ override val OpName = "!="
+}
+case class Less(e0: Expression, e1: Expression) extends CompareExpr(e0,e1) {
+ override val OpName = "<"
+}
+case class AtMost(e0: Expression, e1: Expression) extends CompareExpr(e0,e1) {
+ override val OpName = "<="
+}
+case class AtLeast(e0: Expression, e1: Expression) extends CompareExpr(e0,e1) {
+ override val OpName = ">="
+}
+case class Greater(e0: Expression, e1: Expression) extends CompareExpr(e0,e1) {
+ override val OpName = ">"
+}
+case class LockBelow(e0: Expression, e1: Expression) extends CompareExpr(e0,e1) {
+ override def ExpectedLhsType = throw new Exception("LockBelow does not have a single ExpectedArgsType")
+ override def ExpectedRhsType = throw new Exception("LockBelow does not have a single ExpectedArgsType")
+ override val OpName = "<<"
+}
+sealed abstract class Quantification(is: List[String], seq: Expression, e: Expression) extends Expression {
+ def Quantor: String;
+ def Is = is
+ def Seq = seq
+ def E = e
+ var variables = null: List[Variable];
+}
+case class Forall(is: List[String], seq: Expression, e: Expression) extends Quantification(is, seq, e) {
+ override def Quantor = "forall"
+}
+
+// sequences
+
+case class EmptySeq(t: Type) extends Literal
+case class ExplicitSeq(elems: List[Expression]) extends Expression
+case class Range(min: Expression, max: Expression /* non-inclusive*/) extends Expression
+case class Append(s0: Expression, s1: Expression) extends SeqAccess(s0, s1) {
+ override val OpName = "++"
+}
+ sealed abstract case class SeqAccess(e0: Expression, e1: Expression) extends BinaryExpr(e0, e1)
+case class Length(e: Expression) extends Expression
+case class At(s: Expression, n: Expression) extends SeqAccess(s, n) {
+ override val OpName = "@"
+}
+case class Drop(s: Expression, n: Expression) extends SeqAccess(s, n) {
+ override val OpName = ""
+}
+case class Take(s: Expression, n: Expression) extends SeqAccess(s, n) {
+ override val OpName = ""
+}
+
+
+// eval
+
+case class Eval(h: EvalState, e: Expression) extends Expression
+sealed abstract class EvalState {
+ def target(): Expression;
+}
+case class AcquireState(obj: Expression) extends EvalState {
+ def target() = obj
+}
+case class ReleaseState(obj: Expression) extends EvalState {
+ def target() = obj
+}
+case class CallState(token: Expression, obj: Expression, id: String, args: List[Expression]) extends EvalState {
+ var m = null: Method;
+ def target() = token;
+}
diff --git a/Chalice/src/Boogie.scala b/Chalice/src/Boogie.scala
new file mode 100644
index 00000000..492e0669
--- /dev/null
+++ b/Chalice/src/Boogie.scala
@@ -0,0 +1,270 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+import scala.util.parsing.input.Position
+import scala.util.parsing.input.NoPosition
+
+object Boogie {
+
+ sealed abstract class Decl
+ case class Const(id: String, unique: boolean, t: BType) extends Decl
+ case class Proc(id: String, ins: List[BVar], outs: List[BVar],
+ mod: List[String], PrePost: List[String],
+ body: List[Stmt]) extends Decl
+ case class Function(id: String, ins: List[BVar], out: BVar) extends Decl
+ case class Axiom(expr: Expr) extends Decl
+
+ sealed abstract class BType
+ case class NamedType(s: String) extends BType
+ case class ClassType(cl: Class) extends BType
+ case class IndexedType(id: String, t: BType) extends BType
+
+ sealed abstract class Stmt {
+ def Locals = List[BVar]()
+ }
+ case class Comment(comment: String) extends Stmt
+ case class Assert(e: Expr) extends Stmt {
+ def this(e: Expr, p: Position, txt: String) = { this(e); this.pos = p; this.message = txt; this }
+ var pos = NoPosition : Position
+ var message = "" : String
+ }
+ case class Assume(e: Expr) extends Stmt
+ case class Assign(lhs: Expr, rhs: Expr) extends Stmt
+ case class AssignMap(lhs: Expr, index: Expr, rhs: Expr) extends Stmt
+ case class Havoc(x: Expr) extends Stmt
+ case class MapUpdate(map: Expr, arg0: Expr, arg1: String, rhs: Expr) extends Stmt {
+ def this(map: Expr, arg0: Expr, rhs: Expr) = this(map, arg0, null, rhs)
+ }
+ case class If(guard: Expr, thn: List[Stmt], els: List[Stmt]) extends Stmt {
+ override def Locals = (thn flatMap (_.Locals)) ::: (els flatMap (_.Locals))
+ }
+ case class LocalVar(x: BVar) extends Stmt {
+ def this(id: String, tp: BType) = this(BVar(id, tp))
+
+ override def Locals = List(x)
+ }
+
+ sealed abstract class Expr {
+ 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 Equals(that: Expr) = BinaryExpr("==", this, that)
+ def ==>(that: Expr) = BinaryExpr("==>", this, that)
+ def <==>(that: Expr) = BinaryExpr("<==>", this, that)
+ def unary_! = UnaryExpr("!", this)
+ 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("-", this, that)
+ def *(that: Expr) = BinaryExpr("*", this, that)
+ def /(that: Expr) = BinaryExpr("/", this, that)
+ def %(that: Expr) = BinaryExpr("%", this, that)
+ def := (that: Expr) = Assign(this, that)
+ def select(e: Expr, f: Expr) = new MapSelect(this, e, PrintExpr(f))
+ def store(e: Expr, f: Expr, rhs: Expr) = MapUpdate(this, e, PrintExpr(f), rhs)
+ }
+ case class IntLiteral(n: int) extends Expr
+ case class BoolLiteral(b: boolean) extends Expr
+ case class Null extends Expr
+ case class VarExpr(id: String) extends Expr {
+ def this(v: BVar) = this(v.id)
+ }
+ case class MapSelect(map: Expr, arg0: Expr, arg1: String) extends Expr {
+ def this(map: Expr, arg0: Expr) = this(map, arg0, null) // for one-dimensional maps
+ def this(map: Expr, arg0: Expr, arg1: String, arg2: String) = // for 3-dimensional maps
+ this(MapSelect(map, arg0, arg1), VarExpr(arg2), null)
+ }
+ case class MapStore(map: Expr, arg0: String, rhs: Expr) extends Expr
+ case class Old(e: Expr) extends Expr
+ case class UnaryExpr(op: String, e: Expr) extends Expr
+ case class BinaryExpr(op: String, e0: Expr, e1: Expr) extends Expr
+ case class FunctionApp(f: String, args: List[Expr]) extends Expr {
+ def this(f: String, a0: Expr) = this(f, List(a0))
+ def this(f: String, a0: Expr, a1: Expr) = this(f, List(a0, a1))
+ def this(f: String, a0: Expr, a1: Expr, a2: Expr) = this(f, List(a0, a1, a2))
+ }
+ case class Forall(ta: List[TVar], xs: List[BVar], triggers: List[Expr], body: Expr) extends Expr {
+ def this(xs: List[BVar], triggers: List[Expr], body: Expr) = this(List(), xs, triggers, body)
+ def this(x: BVar, body: Expr) = this(List(), List(x), List(), body)
+ def this(t: TVar, x: BVar, body: Expr) = this(List(t), List(x), List(), body)
+ }
+ case class Exists(xs: List[BVar], triggers: List[Expr], body: Expr) extends Expr {
+ def this(x: BVar, body: Expr) = this(List(x), List(), body)
+ }
+ case class Ite(con: Expr, then: Expr, els: Expr) extends Expr
+
+ case class BVar(id: String, t: BType) {
+ def this(id: String, t: BType, uniquifyName: boolean) =
+ this(if (uniquifyName) {
+ val n = S_BVar.VariableCount
+ S_BVar.VariableCount = S_BVar.VariableCount + 1
+ id + "#_" + n
+ } else {
+ id
+ }, t)
+ val where: Expr = null
+ }
+ object S_BVar { var VariableCount = 0 }
+ def NewBVar(id: String, t: BType, uniquifyName: boolean) = {
+ val v = new Boogie.BVar(id, t, uniquifyName)
+ val e = new Boogie.VarExpr(v)
+ (v,e)
+ }
+ case class TVar(id: String) {
+ def this(id: String, uniquifyName: boolean) =
+ this(if (uniquifyName) {
+ val n = S_TVar.VariableCount
+ S_TVar.VariableCount = S_TVar.VariableCount + 1
+ id + "#_" + n
+ } else {
+ id
+ })
+ val where: Expr = null
+ }
+ object S_TVar { var VariableCount = 0 }
+ def NewTVar(id: String) = {
+ val v = new Boogie.TVar(id, true)
+ val e = new Boogie.NamedType(v.id)
+ (v,e)
+ }
+
+ // def out(s: String) = Console.out.print(s)
+ var indentLevel = 1
+ def indent: String = {
+ def doIndent(i: int): String = {
+ if(i==0) { "" } else { " " + doIndent(i-1) }
+ }
+ doIndent(indentLevel);
+ }
+
+ def IndentMore(what: => String) = {
+ val prev = indentLevel
+ indentLevel = indentLevel + 1
+ val result = what
+ indentLevel = prev
+ result
+ }
+ def nl = System.getProperty("line.separator");
+
+ def Print[T](list: List[T], sep: String, p: T => String): String = list match {
+ case Nil => ""
+ case x :: Nil => p(x)
+ case x :: xs => p(x) + sep + Print(xs, sep, p)
+ }
+ def PrintType(t: BType): String = t match {
+ case nt@ NamedType(s) =>
+ s
+ case ClassType(cl) =>
+ if (cl.IsRef) "ref" else cl.id
+ case IndexedType(id,t) =>
+ id + " (" + PrintType(t) + ")"
+ }
+ def Print(d: Decl): String = d match {
+ case Const(id, u, t) =>
+ "const " + (if (u) "unique " else "" ) + id + ": " + PrintType(t) + ";" + nl
+ case p: Proc =>
+ "procedure " + p.id +
+ "(" + Print(p.ins, ", ", PrintVar) + ")" +
+ " returns (" + Print(p.outs, ", ", PrintVar) + ")" + nl +
+ (p.mod match {
+ case Nil => ""
+ case x :: xs =>
+ indent + "modifies " +
+ Print(p.mod, ", ", { s: String => s }) +
+ ";" + nl
+ }) +
+ Print(p.PrePost, nl, { spec: String => indent + spec }) + nl +
+ "{" + nl +
+ Print(p.body flatMap (_.Locals), "", { v:BVar => indent + "var " + PrintVar(v) + ";" + nl}) +
+ Print(p.body, "", PrintStmt) +
+ "}" + nl
+ case Function(id, ins, out) =>
+ "function " + id + "(" + Print(ins, ", ", PrintVar) + ") returns (" + PrintVar(out) + ");" + nl
+ case Axiom(e) =>
+ "axiom " + PrintExpr(e) + ";" + nl
+ }
+ def PrintVar(v: BVar): String = {
+ v.id + ": " + PrintType(v.t) +
+ (if (v.where != null) {" where " + PrintExpr(v.where) } else { "" })
+ }
+ def PrintStmt(s: Stmt): String = s match {
+ case Comment(msg) => indent + "// " + msg + nl
+ case assert@Assert(e) => indent + "assert " + "{:msg \" " + assert.pos + ": " + assert.message + "\"}" + " " + PrintExpr(e) + ";" + nl
+ case Assume(e) => indent + "assume " + PrintExpr(e) + ";" + nl
+ case If(guard, thn, els) =>
+ indent + "if (" +
+ (if (guard == null) "*" else PrintExpr(guard)) +
+ ") {" + nl +
+ IndentMore { Print(thn, "", PrintStmt) } +
+ indent + "} else {" + nl +
+ IndentMore { Print(els, "", PrintStmt) } +
+ indent + "}" + nl
+ case Assign(lhs, rhs) =>
+ indent + PrintExpr(lhs) + " := " + PrintExpr(rhs) + ";" + nl
+ case AssignMap(lhs, index, rhs) =>
+ indent + PrintExpr(lhs) + "[" + PrintExpr(index) + "] := " + PrintExpr(rhs) + ";" + nl
+ case Havoc(lhs) =>
+ indent + "havoc " + PrintExpr(lhs) + ";" + nl
+ case MapUpdate(map, a0, a1, rhs) =>
+ indent + PrintExpr(map) + "[" +
+ PrintExpr(a0) +
+ (if (a1 != null) { ", " + a1 } else { "" }) +
+ "] := " +
+ PrintExpr(rhs) + ";" + nl
+ case _:LocalVar => "" /* print nothing */
+ }
+ def PrintExpr(e: Expr): String = {
+ PrintExpr(e, false)
+ }
+ def PrintExpr(e: Expr, useParens: boolean): String = e match {
+ case IntLiteral(n) => n.toString
+ case BoolLiteral(b) => b.toString
+ case Null() => "null"
+ case VarExpr(id) => id
+ case MapSelect(map, arg0, arg1) =>
+ PrintExpr(map) + "[" + PrintExpr(arg0, false) +
+ (if (arg1 != null) { ", " + arg1 } else { "" }) +
+ "]"
+ case MapStore(map, arg0, rhs) =>
+ PrintExpr(map) + "[" + arg0 + " := " + PrintExpr(rhs, false) + "]"
+ case Old(e) => "old(" + PrintExpr(e, false) + ")"
+ case UnaryExpr(op, e) =>
+ (if (useParens) { "(" } else "") +
+ op + PrintExpr(e, true) +
+ (if (useParens) ")" else "" )
+ case BinaryExpr(op, e0, e1) =>
+ // reduce parentheses in a special common case:
+ val binIsAndImpIff = op=="&&" || op=="==>" || op=="<==>";
+ def IsAnd(e: Expr) = e match { case BinaryExpr(op,_,_) if op=="&&" => true case _ => false }
+ (if (useParens) "(" else "") + PrintExpr(e0, !(binIsAndImpIff && IsAnd(e0))) +
+ " " + op + " " +
+ PrintExpr(e1, !(binIsAndImpIff && IsAnd(e1))) +
+ (if (useParens) ")" else "")
+ case FunctionApp(f, args) =>
+ f + "(" +
+ Print(args, ", ", { e: Expr => PrintExpr(e, false) }) +
+ ")"
+ case Ite(con, then, els) =>
+ "ite(" + PrintExpr(con) + ", " + PrintExpr(then) + ", " + PrintExpr(els) + ")"
+ case Forall(ts, xs, triggers, body) =>
+ "(forall" +
+ (if (ts.length == 0) " " else "<" + Print(ts, ", ", { x: TVar => x.id }) + "> ") +
+ Print(xs, ", ", { x: BVar => x.id + ": " + PrintType(x.t) }) +
+ " :: " +
+ Print(triggers , "", { s: Expr => "{" + PrintExpr(s) + "} " }) +
+ PrintExpr(body) +
+ ")"
+ case Exists(xs, triggers, body) =>
+ "(exists " +
+ Print(xs, ", ", { x: BVar => x.id + ": " + PrintType(x.t) }) +
+ " :: " +
+ Print(triggers , "", { s: Expr => "{" + PrintExpr(s) + "} " }) +
+ PrintExpr(body) +
+ ")"
+ }
+}
diff --git a/Chalice/src/Chalice.cs b/Chalice/src/Chalice.cs
new file mode 100644
index 00000000..f4a804e7
--- /dev/null
+++ b/Chalice/src/Chalice.cs
@@ -0,0 +1,76 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using System.Collections.Generic;
+using System.Linq;
+
+namespace Chalice
+{
+ public class ImmutableList<E>
+ {
+ private List<E> list;
+
+ public ImmutableList() {
+ list = new List<E>();
+ }
+
+ public ImmutableList(IEnumerable<E> elems)
+ {
+ list = new List<E>(elems);
+ }
+
+ public ImmutableList<E> Append(ImmutableList<E> other)
+ {
+ var res = new ImmutableList<E>();
+ res.list.AddRange(list);
+ res.list.AddRange(other.list);
+ return res;
+ }
+
+ public E At(int index)
+ {
+ return list[index];
+ }
+
+ public ImmutableList<E> Take(int howMany)
+ {
+ var res = new ImmutableList<E>(this.list.Take(howMany));
+ return res;
+ }
+
+ public ImmutableList<E> Drop(int howMany)
+ {
+ var res = new ImmutableList<E>(this.list.Skip(howMany));
+ return res;
+ }
+
+ public int Length
+ {
+ get
+ {
+ return list.Count;
+ }
+ }
+
+ public static ImmutableList<int> Range(int min, int max)
+ {
+ ImmutableList<int> l = new ImmutableList<int>();
+ for (int i = min; i < max; i++)
+ {
+ l.list.Add(i);
+ }
+ return l;
+ }
+ }
+
+ public class ChalicePrint {
+ public void Int(int x) {
+ System.Console.WriteLine(x);
+ }
+ public void Bool(bool x) {
+ System.Console.WriteLine(x);
+ }
+ }
+}
diff --git a/Chalice/src/Chalice.scala b/Chalice/src/Chalice.scala
new file mode 100644
index 00000000..439805d4
--- /dev/null
+++ b/Chalice/src/Chalice.scala
@@ -0,0 +1,115 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+import java.io.BufferedReader
+import java.io.InputStreamReader
+import java.io.File
+import java.io.FileWriter
+
+object Chalice {
+ def main(args: Array[String]): unit = {
+ var boogiePath = "C:\\Boogie\\2\\Binaries\\Boogie.exe"
+ // parse command-line arguments
+ var inputName: String = null
+ var printProgram = false
+ var doTypecheck = true
+ var doTranslate = true
+ var checkLeaks = false
+ // level 0 or below: no defaults
+ // level 1: unfold predicates with receiver this in pre and postconditions
+ // level 2: unfold predicates and functions with receiver this in pre and postconditions
+ // level 3 or above: level 2 + autoMagic
+ var defaults = 0
+ var autoFold = false
+ var autoMagic = false
+ var boogieArgs = " ";
+ var gen = false;
+
+ for (a <- args) {
+ if (a == "-print") printProgram = true
+ else if (a == "-noTranslate") doTranslate = false
+ else if (a == "-noTypecheck") doTypecheck = false
+ else if (a == "-checkLeaks") checkLeaks = true
+ else if (a.startsWith("-boogie:")) boogiePath = a.substring(8)
+ else if (a == "-defaults") defaults = 3
+ else if (a.startsWith("-defaults:")) { try { defaults = Integer.parseInt(a.substring(10)); if(3<=defaults) { autoMagic = true; } } catch { case _ => CommandLineError("-defaults takes integer argument"); } }
+ else if (a == "-gen") { gen = true; doTranslate = false }
+ else if (a == "-autoFold") autoFold = true
+ else if (a == "-autoMagic") autoMagic = true
+ else if (a.startsWith("-") || a.startsWith("/")) boogieArgs += (a + " ") // arguments starting with "-" or "/" are sent to Boogie.exe
+ else if (inputName != null) { CommandLineError("multiple input filenames: " + inputName + " and " + a); return }
+ else { inputName = a }
+ }
+ // check the command-line arguments
+ if (inputName == null) { CommandLineError("missing input filename"); return } else {
+ val file = new File(inputName);
+ if(! file.exists()){
+ CommandLineError("input file " + file.getName() + " could not be found"); return
+ }
+ }
+ // parse program
+ val parser = new Parser();
+ parser.parseFile(inputName) match {
+ case e: parser.NoSuccess => Console.err.println("Error: " + e)
+ case parser.Success(prog, _) =>
+ if (printProgram) PrintProgram.P(prog)
+ if (doTypecheck) {
+ // typecheck program
+ Resolver.Resolve(prog) match {
+ case Resolver.Error(pos, msg) =>
+ Console.err.println("The program did not typecheck.\n");
+ Console.err.println(msg)
+ case Resolver.Errors(msgs) =>
+ Console.err.println("The program did not typecheck.");
+ msgs foreach { msg => Console.err.println(msg) }
+ case Resolver.Success() =>
+ if(gen) {
+ val converter = new ChaliceToCSharp();
+ val cs = converter.convertProgram(prog);
+ writeFile("out.cs", cs);
+ }
+ if (doTranslate) {
+ // checking if Boogie.exe exists
+ val boogieFile = new File(boogiePath);
+ if(! boogieFile.exists() || ! boogieFile.isFile()) {
+ CommandLineError("Boogie.exe not found at " + boogiePath); return
+ }
+ // translate program to BoogiePL
+ val translator = new Translator();
+ // set the translation options
+ TranslationOptions.checkLeaks = checkLeaks;
+ TranslationOptions.defaults = defaults;
+ TranslationOptions.autoFold = autoFold;
+ TranslationOptions.autoMagic = autoMagic;
+ val bplProg = translator.translateProgram(prog);
+ // write to out.bpl
+ val bplText = TranslatorPrelude.P + (bplProg map Boogie.Print).foldLeft(""){ (a, b) => a + b };
+ writeFile("out.bpl", bplText);
+ // run Boogie.exe on out.bpl
+ val boogie = Runtime.getRuntime().exec(boogiePath + " /errorTrace:0 " + boogieArgs + "out.bpl");
+ val input = new BufferedReader(new InputStreamReader(boogie.getInputStream()));
+ var line = input.readLine();
+ while(line!=null){
+ println(line);
+ line = input.readLine();
+ }
+ }
+ }
+ }
+ }
+ }
+
+ def writeFile(filename: String, text: String) {
+ val writer = new FileWriter(new File(filename));
+ writer.write(text);
+ writer.flush();
+ writer.close();
+ }
+
+ def CommandLineError(msg: String) = {
+ Console.err.println("Error: " + msg)
+ Console.err.println("syntax: chalice [-print] [-noTypecheck] [-noTranslate] [-boogie:path] [-defaults] [-autoFold] [-checkLeaks] inputFile")
+ }
+}
diff --git a/Chalice/src/ChaliceToCSharp.scala b/Chalice/src/ChaliceToCSharp.scala
new file mode 100644
index 00000000..75135e38
--- /dev/null
+++ b/Chalice/src/ChaliceToCSharp.scala
@@ -0,0 +1,211 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+class ChaliceToCSharp {
+
+ def convertProgram(classes: List[Class]): String = {
+ "using Chalice;" + nl + nl +
+ rep(classes map convertClass)
+ }
+
+ def convertClass(cl: Class): String = if (cl.IsExternal) "" else {
+ "public class " + cl.id + " {" + nl +
+ indentMore { indent + "public " + cl.id + "() " + "{" + nl + indent + "}" } + nl + nl +
+ (if(0 < cl.Fields.length) {
+ indentMore { indent + "public " + cl.id + "(" + repsep(cl.Fields map { f => convertType(f.typ) + " " + f.Id }, ", ") + ") " + "{" + nl +
+ indentMore { rep(cl.Fields map { f => indent + "this." + f.Id + " = " + f.Id + ";" + nl}) } +
+ indent + "}" } + nl + nl
+ } else "") +
+ indentMore { repsep(cl.members map convertMember, nl) } +
+ "}" + nl + nl
+ }
+
+ def convertMember(member: Member): String = {
+ member match {
+ case Field(id, tp) =>
+ indent + "public " + convertType(tp) + " " + id + ";" + nl
+ case meth@Method(id, ins, outs, spec, body) =>
+ var csharpmain = if(id.equals("Start") && ins.length == 0 && outs.length == 0) {
+ indent + "public static void Main() { " + nl +
+ indentMore {
+ indent + meth.Parent.id + " newObject = new " + meth.Parent.id + "();" + nl +
+ indent + "newObject.Start();" + nl
+ } +
+ indent + "}" + nl + nl
+ } else { "" };
+ var params = repsep(ins map { variable => convertType(variable.t) + " " + variable.id }, ", ") + (if(ins.length > 0 && outs.length > 0) ", " else "") +
+ repsep(outs map { variable => "out " + convertType(variable.t) + " " + variable.id }, ", ");
+ csharpmain +
+ indent + "public " + "void " + id + "(" + params + ") " + "{" + nl +
+ indentMore {
+ rep(outs map { x => indent + x.id + " = " + defaultValue(x.t) + ";" + nl } ) +
+ rep(body map convertStatement)
+ } +
+ indent + "}" + nl + nl +
+ indent + "public delegate " + "void " + id + "_delegate" + "(" + params + ");" + nl + nl +
+ indent + "public class " + "Token_" + id + " { " + nl +
+ (indentMore {
+ indent + "public " + id + "_delegate " + "del;" + nl +
+ indent + "public " + "System.IAsyncResult " + "async;" + nl +
+ (rep(outs map { o: Variable => indent + "public " + convertType(o.t) + " " + o.id + ";" + nl }))
+ }) +
+ indent + "}" + nl
+ case Function(id, ins, out, spec, definition) =>
+ indent + "public " + convertType(out) + " " + id + "(" +
+ repsep(ins map { variable => convertType(variable.t) + " " + variable.id }, ", ") +
+ ") " + "{" + nl +
+ indentMore { indent + "return " + convertExpression(definition) + ";" + nl } +
+ indent + "}" + nl
+ case MonitorInvariant(_) => indent + "// monitor invariant" + nl
+ case Predicate(_, _) => indent + "//predicate" + nl
+ }
+ }
+
+ def convertStatement(statement: Statement): String = {
+ statement match {
+ case Assert(e) => indent + "// assert" + nl
+ case Assume(e) => indent + "assert " + convertExpression(e) + ";" // todo: what if e contains old, result, ...
+ case BlockStmt(ss) => indent + "{" + nl + (indentMore { rep(ss map convertStatement) }) + indent + "}" + nl
+ case IfStmt(guard, thn, els) => indent + "if (" + convertExpression(guard) + ")" + nl + convertStatement(thn) +
+ (if(els.isDefined) (indent + "else" + nl + convertStatement(els.get)) else { "" }) + nl
+ case LocalVar(id, tp, const, ghost, rhs) =>
+ indent + convertType(tp) + " " + id + " = " +
+ (if(rhs.isDefined) convertExpression(rhs.get) else defaultValue(tp)) +
+ ";" + nl
+ case FieldUpdate(MemberAccess(target, f), rhs) =>
+ indent + convertExpression(target) + "." + f + " = " + convertExpression(rhs) + ";" + nl
+ case Assign(VariableExpr(x), rhs) =>
+ indent + x + " = " + convertExpression(rhs) + ";" + nl
+ case WhileStmt(guard, _, _, body) =>
+ indent + "while (" + convertExpression(guard) + ")" + nl + convertStatement(body) + nl
+ case Call(lhs, target, id, args) =>
+ indent + convertExpression(target) + "." + id + "(" +
+ repsep(args map convertExpression, ", ") +
+ (if(args.length > 0 && lhs.length > 0) ", " else "") +
+ repsep(lhs map { l => "out " + convertExpression(l) }, ", ") +
+ ")" + ";" + nl
+ case Install(_, _, _) => indent + "// install" + nl
+ case Share(_, _, _) => indent + "// share" + nl
+ case Unshare(_) => indent + "// unshare" + nl
+ case Downgrade(_) => indent + "// downgrade" + nl
+ case Acquire(obj) => indent + "System.Threading.Monitor.Enter(" + convertExpression(obj) + ")" + ";" + nl
+ case Release(obj) => indent + "System.Threading.Monitor.Exit(" + convertExpression(obj) + ")" + ";" + nl
+ case Lock(obj, body, false) => indent + "lock(" + convertExpression(obj) + ") " + nl + convertStatement(body) + nl
+ case Free(_) => indent + "// free" + nl
+ case Fold(_) => indent + "// fold" + nl
+ case Unfold(_) => indent + "// unfold" + nl
+ case RdAcquire(obj) => assert(false); ""
+ case RdRelease(obj) => assert(false); ""
+ case Lock(_, _, true) => assert(false); ""
+ case ca@CallAsync(declaresLocal, lhs, obj, id, args) =>
+ val tokenName = if(declaresLocal) lhs.id else { uniqueInt += 1; "tok_" + uniqueInt };
+ val call = convertExpression(obj) + "." + id;
+ val tokenClass = ca.m.Parent.id + ".Token_" + id;
+ val delegateName = ca.m.Parent.id + "." + id + "_delegate";
+ indent + tokenClass + " " + tokenName + " = new " + tokenClass + "();" + nl +
+ indent + tokenName + "." + "del" + " = new " + delegateName + "(" + call + ");" + nl +
+ indent + tokenName + "." + "async" + " = " + tokenName + "." + "del" + "." + "BeginInvoke(" + repsep(args map convertExpression, ", ") +
+ (if(args.length > 0 && ca.m.outs.length > 0) ", " else "") + repsep(ca.m.outs map { o => "out " + tokenName + "." + o.id }, ", ") +
+ (if(args.length > 0 || ca.m.outs.length > 0) ", " else "") + "null, null" +
+ ");" + nl
+ case ja@JoinAsync(lhs, token) =>
+ indent + convertExpression(token) + "." + "del.EndInvoke(" +
+ repsep(lhs map { x => "out " + x.id}, ", ") +
+ (if(lhs.length > 0) ", " else "") + convertExpression(token) + "." + "async" + ");" + nl
+ }
+ }
+
+ def convertExpression(expression: RValue): String = {
+ expression match {
+ case IntLiteral(n) => "" + n
+ case BoolLiteral(b) => "" + b
+ case NullLiteral() => "null"
+ case th: ThisExpr => "this"
+ case VariableExpr(id) => id
+ case MemberAccess(target, f) => convertExpression(target) + "." + f
+ case newrhs@NewRhs(c, initialization) =>
+ if(initialization.length == 0) { "new " + c + "()" } else {
+ val init = repsep(newrhs.typ.Fields map { f => (initialization.find { i => i.f == f}) match {
+ case None => defaultValue(f.typ)
+ case Some(init) => convertExpression(init.e);
+ }
+ }, ", ");
+ "new " + c + "(" + init + ")";
+ }
+ case At(s, i) => convertExpression(s) + ".At(" + convertExpression(i) + ")"
+ case Append(s1, s2) => convertExpression(s1) + ".Append(" + convertExpression(s2) + ")"
+ case Take(s, i) => convertExpression(s) + ".Take(" + convertExpression(i) + ")"
+ case Drop(s, i) => convertExpression(s) + ".Drop(" + convertExpression(i) + ")"
+ case bin: BinaryExpr => "(" + convertExpression(bin.E0) + " " + bin.OpName + " " + convertExpression(bin.E1) + ")"// todo: <==> and ==>
+ case Unfolding(p, e) => convertExpression(e)
+ case FunctionApplication(target, id, args) => convertExpression(target) + "." + id + "(" + repsep(args map convertExpression, ", ") + ")"
+ case Not(e) => "(! " + convertExpression(e) + ")"
+ case EmptySeq(tp) => "new Chalice.ImmutableList<" + convertType(tp) + ">()"
+ case es@ExplicitSeq(elems) =>
+ val elemType = new Type(es.typ.asInstanceOf[SeqClass].parameter);
+ "new Chalice.ImmutableList<" + convertType(elemType) + ">(" +
+ "new " + convertType(elemType) + "[] {" + repsep(elems map convertExpression, ", ") + "}" +
+ ")"
+ case Range(min, max) => "Chalice.ImmutableList.Range(" + convertExpression(min) + ", " + convertExpression(max) + ")"
+ case Length(s) => convertExpression(s) + ".Length"
+ case IfThenElse(c, thn, els) => "(" + convertExpression(c) + " ? " + convertExpression(thn) + " : " + convertExpression(els) + ")"
+ }
+ }
+
+ def convertType(tp: Type): String = {
+ tp.typ match {
+ case t: TokenClass => t.c.FullName + ".Token_" + t.m
+ case s: SeqClass => "Chalice.ImmutableList<" + convertType(new Type(s.parameter)) + ">"
+ case IntClass => "int"
+ case BoolClass => "bool"
+ case NullClass => "object"
+ case Class(id, _, _, _) => id
+ }
+ }
+
+ def defaultValue(tp: Type) = {
+ tp.typ match {
+ case t: TokenClass => "null"
+ case s: SeqClass => "new Chalice.ImmutableList<" + convertType(new Type(s.parameter)) + ">()"
+ case IntClass => "0"
+ case BoolClass => "false"
+ case NullClass => "null"
+ case Class(id, _, _, _) => "null"
+ }
+ }
+
+ // utility methods below
+
+ var uniqueInt: int = 0;
+ val nl = System.getProperty("line.separator");
+ var indentLevel = 0
+
+ def rep(strings: List[String]): String = {
+ strings.foldLeft("")({ (a, b) => a + b })
+ }
+
+ def repsep(strings: List[String], separator: String): String = {
+ if(strings.length == 0) {
+ ""
+ } else {
+ strings.reduceLeft({ (a, b) => a + separator + b })
+ }
+ }
+
+ def indent: String = {
+ def doIndent(i: int): String = {
+ if(i==0) { "" } else { " " + doIndent(i-1) }
+ }
+ doIndent(indentLevel);
+ }
+
+ def indentMore(what: => String) = {
+ val prev = indentLevel
+ indentLevel = indentLevel + 1
+ val result = what
+ indentLevel = prev
+ result
+ }
+}
diff --git a/Chalice/src/Parser.scala b/Chalice/src/Parser.scala
new file mode 100644
index 00000000..5063cc92
--- /dev/null
+++ b/Chalice/src/Parser.scala
@@ -0,0 +1,409 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+import scala.util.parsing.combinator.syntactical.StandardTokenParsers
+import scala.util.parsing.input.PagedSeqReader
+import scala.collection.immutable.PagedSeq
+import scala.util.parsing.input.Position
+import scala.util.parsing.input.Positional
+import scala.util.parsing.input.NoPosition
+
+class Parser extends StandardTokenParsers {
+
+ def parseFile(path: String): this.ParseResult[List[Class]] = {
+ val tokens = new lexical.Scanner(new PagedSeqReader(PagedSeq fromFile path));
+ phrase(programUnit)(tokens)
+ }
+
+ case class PositionedString(v: String) extends Positional
+
+ lexical.reserved += ("class", "ghost", "var", "const", "method", "assert", "assume", "new", "this", "reorder",
+ "between", "and", "above", "below", "share", "unshare", "acquire", "release", "downgrade",
+ "lock", "fork", "join", "rd", "acc", "holds", "old", "assigned",
+ "call", "if", "else", "while", "invariant", "lockchange",
+ "returns", "requires", "ensures", "int", "bool", "false", "true", "null", "maxlock", "lockbottom",
+ "module", "external",
+ "predicate", "function", "free", "ite", "fold", "unfold", "unfolding", "in", "forall", "exists",
+ "seq", "nil", "result", "eval", "token")
+ // todo: can we remove "nil"?
+ lexical.delimiters += ("(", ")", "{", "}",
+ "<==>", "==>", "&&", "||",
+ "==", "!=", "<", "<=", ">=", ">", "<<",
+ "+", "-", "*", "/", "%", "!", ".", "..",
+ ";", ":", ":=", ",", "?", "|", "@", "[", "]", "++")
+
+ def programUnit = classDecl*
+
+ // class and members
+
+ def classDecl =
+ positioned(("external" ?) ~ ("class" ~> ident) ~ opt("module" ~> ident) ~ "{" ~ (memberDecl*) <~ "}" ^^ {
+ case ext ~ id ~ module ~ _ ~ members =>
+ val cl = Class(id, Nil, module.getOrElse("default"), members)
+ ext match { case None => case Some(t) => cl.IsExternal = true }
+ cl
+ })
+ def memberDecl = positioned(fieldDecl | invariantDecl | methodDecl | predicateDecl | functionDecl)
+
+ def fieldDecl =
+ ( "var" ~> idType <~ Semi ^^ { case (id,t) => Field(id,t) }
+ | "ghost" ~> "var" ~> idType <~ Semi ^^ { case (id,t) => new Field(id,t){override val IsGhost = true} }
+ )
+ def Ident =
+ positioned(ident ^^ PositionedString)
+ def idType =
+ idTypeOpt ^^ {
+ case (id, None) => (id, Type("int", Nil))
+ case (id, Some(t)) => (id, t) }
+ def idTypeOpt =
+ ident ~ (":" ~> typeDecl ?) ^^ { case id ~ optT => (id, optT) }
+ def typeDecl: Parser[Type] =
+ positioned(("int" | "bool" | ident | "seq") ~ opt("<" ~> repsep(typeDecl, ",") <~ ">") ^^ { case t ~ parameters => Type(t, parameters.getOrElse(Nil)) }
+ | ("token" ~ "<") ~> (typeDecl <~ ".") ~ ident <~ ">" ^^ { case c ~ m => TokenType(c, m) }
+ )
+ def Semi = ";" ?
+
+ def invariantDecl = positioned("invariant" ~> expression <~ Semi ^^ MonitorInvariant)
+
+ def methodDecl =
+ "method" ~> ident ~ formalParameters(true) ~ ("returns" ~> formalParameters(false) ?) ~
+ (methodSpec*) ~ blockStatement ^^ {
+ case id ~ ins ~ outs ~ spec ~ body =>
+ currentLocalVariables = Set[String]()
+ outs match {
+ case None => Method(id, ins, Nil, spec, body)
+ case Some(outs) => Method(id, ins, outs, spec, body) }}
+ def predicateDecl: Parser[Predicate] =
+ ("predicate" ~> ident) ~ ("{" ~> expression <~ "}") ^^ { case id ~ definition => Predicate(id, definition) }
+ def functionDecl =
+ ("function" ~> ident) ~ formalParameters(true) ~ (":" ~> typeDecl) ~ (methodSpec*) ~ ("{" ~> expression <~ "}") ^^ { case id ~ ins ~ out ~ specs ~ body => Function(id, ins, out, specs, body) }
+ def formalParameters(immutable: boolean) =
+ "(" ~> (formalList(immutable) ?) <~ ")" ^^ {
+ case None => Nil
+ case Some(ids) => ids }
+ def formalList(immutable: boolean) = {
+ def MVar(id: String, t: Type) = {
+ currentLocalVariables = currentLocalVariables + id
+ if (immutable) new ImmutableVariable(id,t) else new Variable(id,t)
+ }
+ ( idType ^^ { case (id,t) => MVar(id,t)} ) ~
+ (("," ~> idType ^^ { case (id,t) => MVar(id,t)} ) *) ^^ {
+ case e ~ ee => e::ee }
+ }
+ def methodSpec =
+ positioned( "requires" ~> expression <~ Semi ^^ Precondition
+ | "ensures" ~> expression <~ Semi ^^ Postcondition
+ | "lockchange" ~> expressionList <~ Semi ^^ LockChange
+ )
+ def blockStatement: Parser[List[Statement]] = {
+ val prev = currentLocalVariables
+ "{" ~> (statement*) <~ "}" ^^ {
+ case x => currentLocalVariables = prev; x }
+ }
+
+ // statements
+
+ def statement =
+ positioned( "assert" ~> expression <~ Semi ^^ Assert
+ | "assume" ~> expression <~ Semi ^^ Assume
+ | blockStatement ^^ BlockStmt
+ | "var" ~> localVarStmt(false, false)
+ | "const" ~> localVarStmt(true, false)
+ | "ghost" ~> ( "const" ~> localVarStmt(true, true) | "var" ~> localVarStmt(false, true))
+ | "call" ~> callStmt
+ | "if" ~> ifStmtThen
+ | "while" ~> "(" ~> expression ~ ")" ~ loopSpec ~ blockStatement ^^ {
+ case guard ~ _ ~ lSpec ~ body =>
+ lSpec match { case (invs,lkch) => WhileStmt(guard, invs, lkch, BlockStmt(body)) }}
+ | "reorder" ~> expression ~ (installBounds ?) <~ Semi ^^ {
+ case obj ~ None => Install(obj, List(), List())
+ case obj ~ Some(bounds) => Install(obj, bounds._1, bounds._2) }
+ | "share" ~> expression ~ (installBounds ?) <~ Semi ^^ {
+ case obj ~ None => Share(obj, List(), List())
+ case obj ~ Some(bounds) => Share(obj, bounds._1, bounds._2) }
+ | "unshare" ~> expression <~ Semi ^^ Unshare
+ | "acquire" ~> expression <~ Semi ^^ Acquire
+ | "release" ~> expression <~ Semi ^^ Release
+ | "lock" ~> "(" ~> expression ~ ")" ~ blockStatement ^^ {
+ case e ~ _ ~ b => Lock(e, BlockStmt(b), false) }
+ | "rd" ~>
+ ( "lock" ~> "(" ~> expression ~ ")" ~ blockStatement ^^ {
+ case e ~ _ ~ b => Lock(e, BlockStmt(b), true) }
+ | "acquire" ~> expression <~ Semi ^^ RdAcquire
+ | "release" ~> expression <~ Semi ^^ RdRelease
+ )
+ | "downgrade" ~> expression <~ Semi ^^ Downgrade
+ | "free" ~> expression <~ Semi ^^ Free
+ | Ident ~ ":=" ~ Rhs <~ Semi ^^ {
+ case lhs ~ _ ~ rhs =>
+ if (currentLocalVariables contains lhs.v) {
+ val varExpr = VariableExpr(lhs.v); varExpr.pos = lhs.pos;
+ Assign(varExpr, rhs)
+ } else {
+ val implicitThis = ImplicitThisExpr();
+ val select = MemberAccess(implicitThis, lhs.v);
+ implicitThis.pos = lhs.pos;
+ select.pos = lhs.pos;
+ FieldUpdate(select, rhs)
+ }}
+ | selectExprFerSure ~ ":=" ~ Rhs <~ Semi ^^ {
+ case lhs ~ _ ~ rhs => FieldUpdate(lhs, rhs) }
+ | ("fold" ~> expression <~ Semi) ^? {
+ case pred: MemberAccess => Fold(Access(pred, None))
+ case perm: PermissionExpr => Fold(perm)
+ }
+ | ("unfold" ~> expression <~ Semi) ^? {
+ case pred: MemberAccess => Unfold(Access(pred, None))
+ case perm: PermissionExpr => Unfold(perm)
+ }
+ | ("fork") ~> callSignature ^? ({
+ case None ~ target ~ args =>
+ val (receiver, name) = target match {
+ case VariableExpr(id) => (new ImplicitThisExpr, id)
+ case MemberAccess(obj, id) => (obj, id)
+ }
+ CallAsync(false, null, receiver, name, ExtractList(args))
+ case Some(List(tok)) ~ target ~ args =>
+ val (receiver, name) = target match {
+ case VariableExpr(id) => (new ImplicitThisExpr, id)
+ case MemberAccess(obj, id) => (obj, id)
+ }
+ if (currentLocalVariables contains tok.id) {
+ CallAsync(false, tok, receiver, name, ExtractList(args))
+ } else {
+ currentLocalVariables = currentLocalVariables + tok.id;
+ CallAsync(true, tok, receiver, name, ExtractList(args))
+ }
+ }, t => "fork statement cannot take more than 1 left-hand side")
+ | (("join") ~> ( identList <~ ":=" ?)) ~ expression <~ Semi ^^
+ { case results ~ token => JoinAsync(ExtractList(results), token) }
+ )
+ def localVarStmt(const: boolean, ghost: boolean) =
+ idTypeOpt ~ (":=" ~> Rhs ?) <~ Semi ^^ {
+ case (id,optT) ~ rhs =>
+ currentLocalVariables = currentLocalVariables + id
+ LocalVar(id,
+ optT match {
+ case Some(t) => t
+ case None =>
+ // do a cheap (and hokey) type inference of the RHS
+ rhs match {
+ case Some(NewRhs(tid, _)) => Type(tid, Nil)
+ case Some(BoolLiteral(b)) => Type("bool", Nil)
+ case _ => Type("int", Nil)
+ }
+ },
+ const, ghost, rhs)
+ }
+ def ifStmtThen: Parser[IfStmt] =
+ "(" ~> expression ~ ")" ~ blockStatement ~ ("else" ~> ifStmtElse ?) ^^ {
+ case guard ~ _ ~ thenClause ~ elseClause => IfStmt(guard, BlockStmt(thenClause), elseClause) }
+ def ifStmtElse =
+ ( "if" ~> ifStmtThen
+ | statement
+ )
+ def loopSpec: Parser[(List[Expression], List[Expression])] =
+ (loopSpecX *) ^^ {
+ case pp => (pp :\ (List[Expression](), List[Expression]())) ( (p,list) =>
+ (p,list) match {
+ case ((null,ee),(e0,e1)) => (e0, ee ++ e1)
+ case ((e,ee),(e0,e1)) => (e :: e0, ee ++ e1)
+ })
+ }
+ def loopSpecX =
+ ( "invariant" ~> expression <~ Semi ^^ { case e => (e,Nil) }
+ | "lockchange" ~> expressionList <~ Semi ^^ { case ee => (null,ee) }
+ )
+ def callStmt =
+ callSignature ^? ({
+ case outs ~ VariableExpr(id) ~ args => Call(ExtractList(outs), new ImplicitThisExpr, id, ExtractList(args))
+ case outs ~ MemberAccess(obj,id) ~ args => Call(ExtractList(outs), obj, id, ExtractList(args))
+ }, t => "bad call statement")
+ def callSignature =
+ (identList <~ ":=" ?) ~ callTarget ~ (expressionList?) <~ ")" <~ Semi
+ def callTarget = // returns a VariableExpr or a FieldSelect
+ ( ident <~ "(" ^^ VariableExpr
+ | selectExprFerSure <~ "("
+ )
+ def ExtractList[T](a: Option[List[T]]): List[T] = a match {
+ case None => Nil
+ case Some(list) => list }
+ def identList =
+ ( Ident ^^ { case t => val v = VariableExpr(t.v); v.pos = t.pos; v }) ~
+ (("," ~> Ident ^^ { case t => val v = VariableExpr(t.v); v.pos = t.pos; v }) *) ^^ { case e ~ ee => e::ee }
+ def Rhs : Parser[RValue] =
+ positioned( "new" ~> ident ~ opt("{" ~> repsep(FieldInit, ",") <~ "}") ^^ { case id ~ None => NewRhs(id, Nil)
+ case id ~ Some(inits) => NewRhs(id, inits)
+ }
+ | expression
+ )
+ def FieldInit: Parser[Init] =
+ positioned( (ident <~ ":=") ~ expression ^^ { case id ~ e => Init(id, e) } )
+ def installBounds: Parser[(List[Expression], List[Expression])] =
+ ( "between" ~> expressionList ~ "and" ~ expressionList ^^ { case l ~ _ ~ u => (l,u) }
+ | "below" ~> expressionList ^^ { (Nil,_) }
+ | "above" ~> expressionList ^^ { (_,Nil) }
+ )
+
+ // expressions
+
+ def expression = positioned(iteExpr)
+
+ def iteExpr: Parser[Expression] =
+ positioned(iffExpr ~ (("?" ~> iteExpr) ~ (":" ~> iteExpr) ?) ^^ {
+ case e ~ None => e
+ case e0 ~ Some(e1 ~ e2) => IfThenElse(e0,e1,e2) })
+ def iffExpr: Parser[Expression] =
+ positioned(implExpr ~ ("<==>" ~> iffExpr ?) ^^ {
+ case e ~ None => e
+ case e0 ~ Some(e1) => Iff(e0,e1) })
+ def implExpr: Parser[Expression] =
+ positioned(logicalExpr ~ ("==>" ~> implExpr ?) ^^ {
+ case e ~ None => e
+ case e0 ~ Some(e1) => Implies(e0,e1) })
+ def logicalExpr =
+ positioned(cmpExpr ~ (( ("&&" ~ cmpExpr +) | ("||" ~ cmpExpr +) )?) ^^ {
+ case e ~ None => e
+ case e0 ~ Some(rest) => (rest foldLeft e0) {
+ case (a, "&&" ~ b) => And(a,b)
+ case (a, "||" ~ b) => Or(a,b) }})
+ def cmpExpr =
+ positioned(seqExpr ~ ((CompareOp ~ seqExpr)?) ^^ {
+ case e ~ None => e
+ case e0 ~ Some("==" ~ e1) => Eq(e0,e1)
+ case e0 ~ Some("!=" ~ e1) => Neq(e0,e1)
+ case e0 ~ Some("<" ~ e1) => Less(e0,e1)
+ case e0 ~ Some("<=" ~ e1) => AtMost(e0,e1)
+ case e0 ~ Some(">=" ~ e1) => AtLeast(e0,e1)
+ case e0 ~ Some(">" ~ e1) => Greater(e0,e1)
+ case e0 ~ Some("<<" ~ e1) => LockBelow(e0,e1)
+ })
+ def CompareOp = "==" | "!=" | "<" | "<=" | ">=" | ">" | "<<"
+ def seqExpr =
+ positioned(addExpr ~ (seqAccess *) ^^ { case e ~ as => as.foldLeft(e: Expression)({ (t, a) => val result = a(t); result.pos = t.pos; result }) })
+
+ def seqAccess : Parser[(Expression => SeqAccess)] =
+ ( ("[" ~> expression) <~ "]" ^^ { case e1 => { e0: Expression => At(e0, e1) }}
+ | "[" ~> expression <~ (".." ~ "]") ^^ { case e1 => { e0: Expression => Drop(e0, e1)}}
+ | ("[" ~ "..") ~> expression <~ "]" ^^ { case e1 => { e0: Expression => Take(e0, e1)}}
+ | "++" ~> expression ^^ { case e1 => { e0: Expression => Append(e0, e1) }}
+ | ("[" ~> expression <~ "..") ~ (expression <~ "]") ^^ { case e1 ~ e2 => {e0: Expression => val tak = Take(e0, e2); tak.pos = e0.pos; Drop(tak, e1)} })
+
+ def addExpr =
+ positioned(multExpr ~ (AddOp ~ multExpr *) ^^ {
+ case e0 ~ rest => (rest foldLeft e0) {
+ case (a, "+" ~ b) => Plus(a,b)
+ case (a, "-" ~ b) => Minus(a,b) }})
+ def AddOp = "+" | "-"
+ def multExpr: Parser[Expression] =
+ unaryExpr ~ (MulOp ~ unaryExpr *) ^^ {
+ case e0 ~ rest => (rest foldLeft e0) {
+ case (a, "*" ~ b) => Times(a,b)
+ case (a, "/" ~ b) => Div(a,b)
+ case (a, "%" ~ b) => Mod(a,b) }}
+ def MulOp = "*" | "/" | "%"
+ def unaryExpr: Parser[Expression] =
+ ( "!" ~> unaryExpr ^^ Not
+ | "-" ~> unaryExpr ^^ { Minus(IntLiteral(0),_) }
+ | functionApplication
+ | selectExpr
+ )
+ def selectExpr: Parser[Expression] =
+ atom ~ ("." ~> identOrSpecial *) ^^ {
+ case e ~ fields => (fields foldLeft e) { case (e, f) => val result = MemberAccess(e, f); result.pos = e.pos; result }
+ }
+ def selectExprFerSure: Parser[MemberAccess] =
+ positioned(atom ~ "." ~ identOrSpecial ~ ("." ~> ident *) ^^ {
+ case e ~ _ ~ field ~ moreFields => (moreFields foldLeft MemberAccess(e,field)) { (target, f) => val result = MemberAccess(target, f); result.pos = target.pos; result }})
+ def functionApplication: Parser[Expression] =
+ atom ~ rep("." ~> identOrSpecial ~ opt("(" ~> repsep(expression, ",") <~ ")")) ^^ {
+ case target ~ members =>
+ members.foldLeft(target)({ case (e, name ~ args) => val result = if(! args.isDefined) MemberAccess(e, name) else FunctionApplication(e, name, args.get); result.pos = e.pos; result })
+ }
+
+ def identOrSpecial: Parser[String] =
+ ( ident ^^ { case s => s }
+ | "acquire" ^^^ "acquire"
+ | "release" ^^^ "release"
+ | "fork" ^^^ "fork"
+ | "*" ^^^ "*")
+
+ var currentLocalVariables = Set[String]()
+
+ def expressionList =
+ expression ~ ("," ~> expression *) ^^ { case e ~ ee => e::ee }
+
+ def atom : Parser[Expression] =
+ positioned( numericLit ^^ { case n => IntLiteral(n.toInt) }
+ | "false" ^^^ BoolLiteral(false)
+ | "true" ^^^ BoolLiteral(true)
+ | "null" ^^^ NullLiteral()
+ | "maxlock" ^^^ MaxLockLiteral()
+ | "lockbottom" ^^^ LockBottomLiteral()
+ | "this" ^^^ ExplicitThisExpr()
+ | ("[" ~> expression) ~ (":" ~> expression <~ "]") ^^ { case from ~ to => Range(from, to) }
+ | "(" ~> expression <~ ")"
+ | ("eval" ~ "(") ~> (evalstate <~ ",") ~ (expression <~ ")") ^^ { case h ~ e => Eval(h, e) }
+ | ("ite(" ~> expression <~ ",") ~ (expression <~ ",") ~ (expression <~ ")") ^^ { case con ~ then ~ els => IfThenElse (con, then, els) }
+ | "rd" ~>
+ ( "holds" ~> "(" ~> expression <~ ")" ^^ RdHolds
+ | "(" ~>
+ ( (Ident ^^ (e => { val result = MemberAccess(ImplicitThisExpr(),e.v); result.pos = e.pos; result})) ~ rdPermArg <~ ")"
+ | selectExprFerSure ~ rdPermArg <~ ")"
+ ) ^^ { case MemberAccess(obj, "*") ~ p => RdAccessAll(obj, p) case e ~ p => RdAccess(e,p) }
+ )
+ | "acc" ~> "(" ~>
+ ( (Ident ^^ (e => { val result = MemberAccess(ImplicitThisExpr(),e.v); result.pos = e.pos; result} )) ~ ("," ~> expression ?) <~ ")"
+ | selectExprFerSure ~ ("," ~> expression ?) <~ ")"
+ ) ^^ { case MemberAccess(obj, "*") ~ perm => AccessAll(obj, perm) case e ~ perm => Access(e, perm) }
+ | "holds" ~> "(" ~> expression <~ ")" ^^ Holds
+ | "assigned" ~> "(" ~> ident <~ ")" ^^ Assigned
+ | "old" ~> "(" ~> expression <~ ")" ^^ Old
+ | positioned(Ident) ~ opt("(" ~> repsep(expression, ",") <~ ")") ^^
+ { case id ~ args => val result =
+ if(args.isDefined){
+ val implicitThis = ImplicitThisExpr(); implicitThis.pos = id.pos;
+ FunctionApplication(implicitThis, id.v, args.get)
+ } else {
+ if (currentLocalVariables contains id.v)
+ VariableExpr(id.v)
+ else {
+ val implicitThis = ImplicitThisExpr(); implicitThis.pos = id.pos; MemberAccess(implicitThis, id.v)
+ }
+ }; result.pos = id.pos; result }
+ | ("unfolding" ~> expression <~ "in") ~ expression ^? {
+ case (pred: MemberAccess) ~ e => val acc = Access(pred, None); acc.pos = pred.pos; Unfolding(acc, e)
+ case (perm: PermissionExpr) ~ e => Unfolding(perm, e)
+ }
+ | ("nil" ~> "<") ~> (typeDecl <~ ">") ^^ EmptySeq
+ | ("[" ~> repsep(expression, ",") <~ "]") ^^ { case es => ExplicitSeq(es) }
+ | "|" ~> expression <~ "|" ^^ Length
+ | forall
+ | "result" ^^^ Result()
+ )
+ def forall: Parser[Forall] =
+ (("forall" ~ "{") ~> repsep(ident, ",") <~ "in") into { is => (expression <~ ";") ~ (exprWithLocals(is) <~ "}") ^^
+ { case seq ~ e => val result = Forall(is, seq, e); currentLocalVariables = currentLocalVariables -- is; result } }
+ def exprWithLocals(i: List[String]) : Parser[Expression] = {
+ val savedCurrentLocals = currentLocalVariables;
+ currentLocalVariables = currentLocalVariables ++ i;
+ val result = ((expression) ^^ { case e => e});
+ result
+ }
+
+ def evalstate: Parser[EvalState] = {
+ functionApplication ~ opt(callTarget ~ (repsep(expression, ",") <~ ")")) ^?
+ { case MemberAccess(e, "acquire") ~ None => AcquireState(e)
+ case MemberAccess(e, "release") ~ None => ReleaseState(e)
+ case MemberAccess(e, "fork") ~ Some((MemberAccess(obj, id) ~ args)) => CallState(e, obj, id, args)
+ }
+ }
+
+ def rdPermArg : Parser[Option[Option[Expression]]] =
+ (("," ~> ( "*" ^^^ None
+ | expression ^^ { case e => Some(e) }
+ )) ?
+ )
+}
diff --git a/Chalice/src/Prelude.scala b/Chalice/src/Prelude.scala
new file mode 100644
index 00000000..876a5abe
--- /dev/null
+++ b/Chalice/src/Prelude.scala
@@ -0,0 +1,251 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+object TranslatorPrelude {
+
+ val P =
+"""// Copyright (c) 2008, Microsoft
+type Field a;
+type HeapType = <a>[ref,Field a]a;
+type MaskType = <a>[ref,Field a][PermissionComponent]int;
+type ref;
+const null: ref;
+
+var Heap: HeapType;
+
+type PermissionComponent;
+const unique perm$R: PermissionComponent;
+const unique perm$N: PermissionComponent;
+const Permission$MinusInfinity: int;
+axiom Permission$MinusInfinity < -10000;
+const Permission$PlusInfinity: int;
+axiom 10000 < Permission$PlusInfinity;
+var Mask: MaskType where IsGoodMask(Mask);
+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] == 100 && Permission$Full[perm$N] == 0;
+const ZeroMask: MaskType;
+axiom (forall<T> o: ref, f: Field T, pc: PermissionComponent :: ZeroMask[o,f][pc] == 0);
+axiom IsGoodMask(ZeroMask);
+function {:expand false} CanRead<T>(m: MaskType, obj: ref, f: Field T) returns (bool)
+{
+ 0 < m[obj,f][perm$R] || 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] == 100 && m[obj,f][perm$N] == 0
+}
+function {:expand true} IsGoodMask(m: MaskType) returns (bool)
+{
+ (forall<T> o: ref, f: Field T ::
+ 0 <= m[o,f][perm$R] &&
+ (NonPredicateField(f) ==>
+ (m[o,f][perm$R]<=100 &&
+ (0 < m[o,f][perm$N] ==> m[o,f][perm$R] < 100))) &&
+ (m[o,f][perm$N] < 0 ==> 0 < m[o,f][perm$R]))
+}
+
+function IsGoodState<T>(T) returns (bool);
+function combine<T,U>(T, U) returns (T);
+const nostate: HeapType;
+
+axiom (forall<T,U> a: T, b: U :: {IsGoodState(combine(a, b))} IsGoodState(combine(a, b)) <==> IsGoodState(a) && IsGoodState(b));
+axiom IsGoodState(nostate);
+
+type ModuleName;
+const CurrentModule: ModuleName;
+type TypeName;
+function dtype(ref) returns (TypeName);
+const CanAssumeFunctionDefs: bool;
+
+type Mu;
+const unique mu: Field Mu;
+axiom NonPredicateField(mu);
+function MuBelow(Mu, Mu) returns (bool); // strict partial order
+axiom (forall m: Mu, n: Mu ::
+ { MuBelow(m,n), MuBelow(n,m) }
+ !(MuBelow(m,n) && MuBelow(n,m)));
+axiom (forall m: Mu, n: Mu, o: Mu ::
+ { MuBelow(m,n), MuBelow(n,o) }
+ MuBelow(m,n) && MuBelow(n,o) ==> MuBelow(m,o));
+const $LockBottom: Mu;
+axiom (forall m, n: Mu :: MuBelow(m, n) ==> n != $LockBottom);
+
+const unique held: Field int;
+function Acquire$Heap(int) returns (HeapType);
+function Acquire$Mask(int) returns (MaskType);
+axiom NonPredicateField(held);
+
+function LastSeen$Heap(Mu, int) returns (HeapType);
+function LastSeen$Mask(Mu, int) returns (MaskType);
+
+const unique rdheld: Field bool;
+axiom NonPredicateField(rdheld);
+function wf(h: HeapType, m: MaskType) returns (bool);
+
+function IsGoodInhaleState(ih: HeapType, h: HeapType,
+ m: MaskType) returns (bool)
+{
+ (forall<T> o: ref, f: Field T :: { ih[o, f] } CanRead(m, o, f) ==> ih[o, f] == h[o, f]) &&
+ (forall o: ref :: { ih[o, held] } (0<ih[o, held]) == (0<h[o, held])) &&
+ (forall o: ref :: { ih[o, rdheld] } ih[o, rdheld] == h[o, rdheld]) &&
+ (forall o: ref :: { h[o, held] } (0<h[o, held]) ==> ih[o, mu] == h[o, mu])
+}
+
+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);
+
+type Seq T;
+
+function Seq#Length<T>(Seq T) returns (int);
+axiom (forall<T> s: Seq T :: { Seq#Length(s) } 0 <= Seq#Length(s));
+
+function Seq#Empty<T>() returns (Seq T);
+axiom (forall<T> :: Seq#Length(Seq#Empty(): Seq T) == 0);
+axiom (forall<T> s: Seq T :: { Seq#Length(s) } Seq#Length(s) == 0 ==> s == Seq#Empty());
+
+function Seq#Singleton<T>(T) returns (Seq T);
+axiom (forall<T> t: T :: { Seq#Length(Seq#Singleton(t)) } Seq#Length(Seq#Singleton(t)) == 1);
+
+function Seq#Build<T>(s: Seq T, index: int, val: T, newLength: int) returns (Seq T);
+axiom (forall<T> s: Seq T, i: int, v: T, len: int :: { Seq#Length(Seq#Build(s,i,v,len)) }
+ Seq#Length(Seq#Build(s,i,v,len)) == len);
+
+function Seq#Append<T>(Seq T, Seq T) returns (Seq T);
+axiom (forall<T> s0: Seq T, s1: Seq T :: { Seq#Length(Seq#Append(s0,s1)) }
+ Seq#Length(Seq#Append(s0,s1)) == Seq#Length(s0) + Seq#Length(s1));
+
+function Seq#Index<T>(Seq T, int) returns (T);
+axiom (forall<T> t: T :: { Seq#Index(Seq#Singleton(t), 0) } Seq#Index(Seq#Singleton(t), 0) == t);
+axiom (forall<T> s0: Seq T, s1: Seq T, n: int :: { Seq#Index(Seq#Append(s0,s1), n) }
+ (n < Seq#Length(s0) ==> Seq#Index(Seq#Append(s0,s1), n) == Seq#Index(s0, n)) &&
+ (Seq#Length(s0) <= n ==> Seq#Index(Seq#Append(s0,s1), n) == Seq#Index(s1, n - Seq#Length(s0))));
+axiom (forall<T> s: Seq T, i: int, v: T, len: int, n: int :: { Seq#Index(Seq#Build(s,i,v,len),n) }
+ (i == n ==> Seq#Index(Seq#Build(s,i,v,len),n) == v) &&
+ (i != n ==> Seq#Index(Seq#Build(s,i,v,len),n) == Seq#Index(s,n)));
+
+function Seq#Contains<T>(Seq T, T) returns (bool);
+axiom (forall<T> s: Seq T, x: T :: { Seq#Contains(s,x) }
+ Seq#Contains(s,x) <==>
+ (exists i: int :: { Seq#Index(s,i) } 0 <= i && i < Seq#Length(s) && Seq#Index(s,i) == x));
+axiom (forall x: ref ::
+ { Seq#Contains(Seq#Empty(), x) }
+ !Seq#Contains(Seq#Empty(), x));
+axiom (forall<T> s0: Seq T, s1: Seq T, x: T ::
+ { Seq#Contains(Seq#Append(s0, s1), x) }
+ Seq#Contains(Seq#Append(s0, s1), x) <==>
+ Seq#Contains(s0, x) || Seq#Contains(s1, x));
+axiom (forall<T> s: Seq T, i: int, v: T, len: int, x: T ::
+ { Seq#Contains(Seq#Build(s, i, v, len), x) }
+ Seq#Contains(Seq#Build(s, i, v, len), x) <==>
+ x == v || Seq#Contains(s, x));
+axiom (forall<T> s: Seq T, n: int, x: T ::
+ { Seq#Contains(Seq#Take(s, n), x) }
+ Seq#Contains(Seq#Take(s, n), x) <==>
+ (exists i: int :: { Seq#Index(s, i) }
+ 0 <= i && i < n && n <= Seq#Length(s) && Seq#Index(s, i) == x));
+axiom (forall<T> s: Seq T, n: int, x: T ::
+ { Seq#Contains(Seq#Drop(s, n), x) }
+ Seq#Contains(Seq#Drop(s, n), x) <==>
+ (exists i: int :: { Seq#Index(s, i) }
+ 0 <= n && n <= i && i < Seq#Length(s) && Seq#Index(s, i) == x));
+
+function Seq#Equal<T>(Seq T, Seq T) returns (bool);
+axiom (forall<T> s0: Seq T, s1: Seq T :: { Seq#Equal(s0,s1) }
+ Seq#Equal(s0,s1) <==>
+ Seq#Length(s0) == Seq#Length(s1) &&
+ (forall j: int :: { Seq#Index(s0,j) } { Seq#Index(s1,j) }
+ 0 <= j && j < Seq#Length(s0) ==> Seq#Index(s0,j) == Seq#Index(s1,j)));
+axiom(forall<T> a: Seq T, b: Seq T :: { Seq#Equal(a,b) } // extensionality axiom for sequences
+ Seq#Equal(a,b) ==> a == b);
+
+function Seq#SameUntil<T>(Seq T, Seq T, int) returns (bool);
+axiom (forall<T> s0: Seq T, s1: Seq T, n: int :: { Seq#SameUntil(s0,s1,n) }
+ Seq#SameUntil(s0,s1,n) <==>
+ (forall j: int :: { Seq#Index(s0,j) } { Seq#Index(s1,j) }
+ 0 <= j && j < n ==> Seq#Index(s0,j) == Seq#Index(s1,j)));
+
+function Seq#Take<T>(Seq T, howMany: int) returns (Seq T);
+axiom (forall<T> s: Seq T, n: int :: { Seq#Length(Seq#Take(s,n)) }
+ 0 <= n ==>
+ (n <= Seq#Length(s) ==> Seq#Length(Seq#Take(s,n)) == n) &&
+ (Seq#Length(s) < n ==> Seq#Length(Seq#Take(s,n)) == Seq#Length(s)));
+axiom (forall<T> s: Seq T, n: int, j: int :: { Seq#Index(Seq#Take(s,n), j) }
+ 0 <= j && j < n && j < Seq#Length(s) ==>
+ Seq#Index(Seq#Take(s,n), j) == Seq#Index(s, j));
+
+function Seq#Drop<T>(Seq T, howMany: int) returns (Seq T);
+axiom (forall<T> s: Seq T, n: int :: { Seq#Length(Seq#Drop(s,n)) }
+ 0 <= n ==>
+ (n <= Seq#Length(s) ==> Seq#Length(Seq#Drop(s,n)) == Seq#Length(s) - n) &&
+ (Seq#Length(s) < n ==> Seq#Length(Seq#Drop(s,n)) == 0));
+axiom (forall<T> s: Seq T, n: int, j: int :: { Seq#Index(Seq#Drop(s,n), j) }
+ 0 <= n && 0 <= j && j < Seq#Length(s)-n ==>
+ Seq#Index(Seq#Drop(s,n), j) == Seq#Index(s, j+n));
+
+function Seq#Range(min: int, max: int) returns (Seq int);
+
+axiom (forall min: int, max: int :: { Seq#Length(Seq#Range(min, max)) } (min < max ==> Seq#Length(Seq#Range(min, max)) == max-min) && (max <= min ==> Seq#Length(Seq#Range(min, max)) == 0));
+axiom (forall min: int, max: int, j: int :: { Seq#Index(Seq#Range(min, max), j) } 0<=j && j<max-min ==> Seq#Index(Seq#Range(min, max), j) == min + j);
+
+axiom (forall h: HeapType, m: MaskType, o: ref, q: ref :: {wf(h, m), h[o, mu], h[q, mu]} wf(h, m) && o!=q && (0 < h[o, held]) && (0 < h[q, held]) ==> h[o, mu] != h[q, mu]);
+
+function DecPerm<T>(m: MaskType, o: ref, f: Field T, howMuch: int) 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]}
+ 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);
+
+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]}
+ 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);
+
+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]}
+ 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);
+
+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]}
+ 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])
+);
+
+function Havocing<T,U>(h: HeapType, o: ref, f: Field T, newValue: U) returns (HeapType);
+
+axiom (forall<T,U> h: HeapType, o: ref, f: Field T, newValue: U, q: ref, g: Field U :: {Havocing(h, o, f, newValue)[q, g]}
+ Havocing(h, o, f, newValue)[q, g] == ite(o==q && f ==g, newValue, h[q, g])
+);
+
+const unique joinable: Field int;
+axiom NonPredicateField(joinable);
+const unique token#t: TypeName;
+
+function Call$Heap(int) returns (HeapType);
+function Call$Mask(int) returns (MaskType);
+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));
+
+function NonPredicateField<T>(f: Field T) returns (bool);
+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 submask(m1: MaskType, m2: MaskType) returns (bool);
+
+axiom (forall m1: MaskType, m2: MaskType :: {submask(m1, m2)}
+ submask(m1, m2) <==> (forall<T> o: ref, f: Field T :: (m1[o, f][perm$R] < m2[o, f][perm$R]) || (m1[o, f][perm$R] == m2[o, f][perm$R] && m1[o, f][perm$N] <= m2[o, f][perm$N]))
+);
+
+"""
+}
diff --git a/Chalice/src/PrettyPrinter.scala b/Chalice/src/PrettyPrinter.scala
new file mode 100644
index 00000000..b93c23bd
--- /dev/null
+++ b/Chalice/src/PrettyPrinter.scala
@@ -0,0 +1,292 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+object PrintProgram {
+ def P(prog: List[Class]) =
+ for (cl <- prog) {
+ if (cl.IsExternal) print("external ")
+ println("class " + cl.id + " module " + cl.module + " {")
+ cl.members foreach Member
+ println("}")
+ }
+ def Semi = ";"
+ def Member(m: Member) = m match {
+ case MonitorInvariant(e) =>
+ print(" invariant "); Expr(e); println(Semi)
+ case f@ Field(id, t) =>
+ println(" " + (if (f.IsGhost) "ghost " else "") + "var " + id + ": " + t.id + Semi)
+ case m: Method =>
+ print(" method " + m.id)
+ print("("); VarList(m.ins); print(")")
+ if (m.outs != Nil) {
+ print(" returns ("); VarList(m.outs); print(")")
+ }
+ println
+ m.spec foreach {
+ case Precondition(e) => print(" requires "); Expr(e); println(Semi)
+ case Postcondition(e) => print(" ensures "); Expr(e); println(Semi)
+ case LockChange(ee) => print(" lockchange "); ExprList(ee); println(Semi)
+ }
+ println(" {");
+ for (s <- m.body) {
+ print(" "); Stmt(s, 4)
+ }
+ println(" }")
+ case Predicate(id, definition) =>
+ print(" predicate " + id + " { " + Expr(definition) + "}")
+ case Function(id, ins, out, specs, e) =>
+ print(" function " + id + "(" + VarList(ins) + ")" + ": " + out.id);
+ specs foreach {
+ case Precondition(e) => print(" requires "); Expr(e); println(Semi)
+ case Postcondition(e) => print(" ensures "); Expr(e); println(Semi)
+ case LockChange(ee) => print(" lockchange "); ExprList(ee); println(Semi)
+ }
+ print(" { " + Expr(e) + "}");
+ }
+ def Stmt(s: Statement, indent: int): unit = s match {
+ case Assert(e) =>
+ print("assert "); Expr(e); println(Semi)
+ case Assume(e) =>
+ print("assume "); Expr(e); println(Semi)
+ case BlockStmt(ss) =>
+ PrintBlockStmt(ss, indent); println
+ case IfStmt(guard, BlockStmt(thn), els) =>
+ print("if ("); Expr(guard); print(") ")
+ PrintBlockStmt(thn, indent)
+ els match {
+ case None => println
+ case Some(s) => print(" else "); Stmt(s, indent)
+ }
+ case WhileStmt(guard, invs, lkch, body) =>
+ print("while ("); Expr(guard); println(")")
+ for (inv <- invs) {
+ Spaces(indent+2)
+ print("invariant "); Expr(inv); println(Semi)
+ }
+ for (l <- lkch) {
+ Spaces(indent+2)
+ print("lockchange "); Expr(l); println(Semi)
+ }
+ Spaces(indent); Stmt(body, indent)
+ case Assign(lhs,rhs) =>
+ Expr(lhs); print(" := "); Rhs(rhs); println(Semi)
+ case FieldUpdate(lhs,rhs) =>
+ Expr(lhs); print(" := "); Rhs(rhs); println(Semi)
+ case LocalVar(id,t,c,g,rhs) =>
+ if (g) print("ghost ")
+ if (c) print("const ") else print("var ")
+ print(id + ": " + t.id)
+ rhs match { case None => case Some(rhs) => print(" := "); Rhs(rhs) }
+ println(Semi)
+ case Call(outs, obj, id, args) =>
+ print("call ")
+ outs match {
+ case Nil =>
+ case x :: xs => Expr(x); xs foreach { x => print(", "); Expr(x) }; print(" := ")
+ }
+ MemberSelect(obj,id,0,false)
+ print("(")
+ ExprList(args)
+ println(");")
+ case Install(obj,lower,upper) =>
+ print("reorder ")
+ Expr(obj)
+ PrintBounds(lower, upper)
+ println(Semi)
+ case Share(obj,lower,upper) =>
+ print("share ")
+ Expr(obj)
+ PrintBounds(lower, upper)
+ println(Semi)
+ case Unshare(e) =>
+ print("unshare "); Expr(e); println(Semi)
+ case Acquire(e) =>
+ print("acquire "); Expr(e); println(Semi)
+ case Release(e) =>
+ print("release "); Expr(e); println(Semi)
+ case RdAcquire(e) =>
+ print("rd acquire "); Expr(e); println(Semi)
+ case RdRelease(e) =>
+ print("rd release "); Expr(e); println(Semi)
+ case Lock(e, b, rdLock) =>
+ if (rdLock) print("rd lock (") else print("lock (")
+ Expr(e); print(") ")
+ Stmt(b, indent)
+ case Downgrade(e) =>
+ print("downgrade "); Expr(e); println(Semi)
+ case Free(e) =>
+ print("free "); Expr(e); println(Semi)
+ case Fold(e) =>
+ print("fold "); Expr(e); println(Semi)
+ case Unfold(e) =>
+ print("unfold "); Expr(e); println(Semi)
+ case CallAsync(declaresLocal, token, obj, name, args) =>
+ print("call async ");
+ if (token != null) {
+ Expr(token); print(" := ");
+ }
+ Expr(obj); print("."); print(name); print("("); ExprList(args); print(")");
+ case JoinAsync(lhs, token) =>
+ print("join async "); ExprList(lhs); print(" := "); Expr(token);
+ }
+ def PrintBounds(lower: List[Expression], upper: List[Expression]) = {
+ if (lower == Nil && upper == Nil) {
+ } else if (lower == Nil) {
+ print(" below "); ExprList(upper)
+ } else if (upper == Nil) {
+ print(" above "); ExprList(lower)
+ } else {
+ print(" between "); ExprList(lower); print(" and "); ExprList(upper)
+ }
+ }
+ def PrintBlockStmt(ss: List[Statement], indent: int) = {
+ println("{")
+ for (s <- ss) { Spaces(indent+2); Stmt(s, indent+2) }
+ Spaces(indent); print("}")
+ }
+ def VarList(vv: List[Variable]) = vv match {
+ case Nil =>
+ case v :: rest =>
+ print(v.id + ": " + v.t.id)
+ rest foreach { v => print(", " + v.id + ": " + v.t.id) }
+ }
+ def ExprList(ee: List[Expression]) = ee match {
+ case Nil =>
+ case e :: rest =>
+ Expr(e)
+ rest foreach { e => print(", "); Expr(e) }
+ }
+ def Rhs(e: RValue) = e match {
+ case NewRhs(id, initialization) =>
+ print("new " + id);
+ if(0 < initialization.length) {
+ print(" {"); print(initialization(0).id); print(":="); Expr(initialization(0).e); initialization.foreach({ init => print(", "); print(init.id); print(":="); Expr(init.e); }); print("}");
+ }
+ case e: Expression => Expr(e)
+ }
+ def Expr(e: Expression): Unit = Expr(e, 0, false)
+ def Expr(e: Expression, contextBindingPower: int, fragileContext: boolean): Unit = e match {
+ case IntLiteral(n) => print(n)
+ case BoolLiteral(b) => print(b)
+ case NullLiteral() => print("null")
+ case MaxLockLiteral() => print("maxlock")
+ case LockBottomLiteral() => print("lockbottom")
+ case _:ThisExpr => print("this")
+ case _:Result => print("result")
+ case VariableExpr(id) => print(id)
+ case MemberAccess(e,f) => MemberSelect(e,f,contextBindingPower,fragileContext)
+ case Access(e,perm) =>
+ print("acc("); Expr(e)
+ perm match { case None => case Some(perm) => print(", "); Expr(perm) }
+ print(")")
+ case RdAccess(e,p) =>
+ print("rd("); Expr(e)
+ p match {
+ case None => print(")")
+ case Some(None) => print(", *)")
+ case Some(Some(e)) => print(", "); Expr(e); print(")")
+ }
+ case AccessAll(obj, perm) =>
+ print("acc("); Expr(obj); print(".*");
+ perm match { case None => case Some(perm) => print(", "); Expr(perm) }
+ print(")")
+ case RdAccessAll(obj, p) =>
+ print("rd("); Expr(e); print(".*");
+ p match {
+ case None => print(")")
+ case Some(None) => print(", *)")
+ case Some(Some(e)) => print(", "); Expr(e); print(")")
+ }
+ case Holds(e) =>
+ print("holds("); Expr(e); print(")")
+ case RdHolds(e) =>
+ print("rd holds("); Expr(e); print(")")
+ case Assigned(id) => print("assigned(" + id + ")")
+ case Old(e) =>
+ print("old("); Expr(e); print(")")
+ case IfThenElse(con, then, els) =>
+ print("ite("); Expr(con); print(", "); Expr(then); print(", "); Expr(els); print(")");
+ case Not(e) => print("!"); Expr(e, 0x80, false)
+ case FunctionApplication(obj, id, ins) =>
+ Expr(obj); print("."); print(id); print("("); ExprList(ins); print(")");
+ case Unfolding(pred, e) =>
+ print("unfolding "); Expr(pred); print(" in "); Expr(e);
+ case e:Iff => BinExpr(e, e.OpName, 0x10, false, false, contextBindingPower, fragileContext)
+ case e:Implies => BinExpr(e, e.OpName, 0x20, true, false, contextBindingPower, fragileContext)
+ case e:And => BinExpr(e, e.OpName, 0x30, false, false, contextBindingPower, fragileContext)
+ case e:Or => BinExpr(e, e.OpName, 0x31, false, false, contextBindingPower, fragileContext)
+ case e:Eq => BinExpr(e, e.OpName, 0x40, true, true, contextBindingPower, fragileContext)
+ case e:Neq => BinExpr(e, e.OpName, 0x40, true, true, contextBindingPower, fragileContext)
+ case e:Less => BinExpr(e, e.OpName, 0x40, true, true, contextBindingPower, fragileContext)
+ case e:AtMost => BinExpr(e, e.OpName, 0x40, true, true, contextBindingPower, fragileContext)
+ case e:AtLeast => BinExpr(e, e.OpName, 0x40, true, true, contextBindingPower, fragileContext)
+ case e:Greater => BinExpr(e, e.OpName, 0x40, true, true, contextBindingPower, fragileContext)
+ case e:LockBelow => BinExpr(e, e.OpName, 0x40, true, true, contextBindingPower, fragileContext)
+ case e:Plus => BinExpr(e, e.OpName, 0x50, false, false, contextBindingPower, fragileContext)
+ case e:Minus => BinExpr(e, e.OpName, 0x50, false, true, contextBindingPower, fragileContext)
+ case e:Times => BinExpr(e, e.OpName, 0x60, false, false, contextBindingPower, fragileContext)
+ case e:Div => BinExpr(e, e.OpName, 0x60, false, true, contextBindingPower, fragileContext)
+ case e:Mod => BinExpr(e, e.OpName, 0x60, false, true, contextBindingPower, fragileContext)
+ case q:Quantification =>
+ print(q.Quantor + "{");
+ q.Is match {
+ case Nil =>
+ case i :: rest => print(i); rest foreach { v => print(", " + v) }
+ }
+ print(" in "); Expr(q.Seq); print("; "); Expr(q.E); print("}");
+ case EmptySeq(t) =>
+ print("nil<"); print(t.FullName); print(">");
+ case ExplicitSeq(es) =>
+ print("["); ExprList(es); print("]");
+ case Range(min, max) =>
+ print("("); Expr(min); print(":"); Expr(max); print(")");
+ case Length(e)=>
+ print("|"); Expr(e); print("|");
+ case e:At =>
+ BinExpr(e, e.OpName, 0x45, true, true, contextBindingPower, fragileContext)
+ case e:Append =>
+ BinExpr(e, e.OpName, 0x45, true, true, contextBindingPower, fragileContext)
+ case Drop(s, n) =>
+ Expr(s); print("["); Expr(n); print(" ..]");
+ case Take(s, n) =>
+ Expr(s); print("[.. "); Expr(n); print("]");
+ case Eval(h, e) =>
+ print("eval("); (h match
+ {
+ case AcquireState(obj) => Expr(obj); print(".acquire");
+ case ReleaseState(obj) => Expr(obj); print(".release");
+ case CallState(token, obj, id, args) => Expr(token); print(".joinable"); print(", "); Expr(obj); print("." + id + "("); ExprList(args); print(")");
+ }); print(", "); Expr(e); print(")");
+ }
+ def MemberSelect(e: Expression, f: String, contextBindingPower: int, fragileContext: boolean) = e match {
+ case e:ImplicitThisExpr => print(f)
+ case _ =>
+ ParenExpr(0x90, contextBindingPower, fragileContext, { Expr(e,0x90,false); print("." + f) })
+ }
+ def BinExpr(bin: BinaryExpr, op: String, power: int, fragileLeft: boolean, fragileRight: boolean,
+ context: int, fragileContext: boolean) = {
+ ParenExpr(power, context, fragileContext,
+ { Expr(bin.E0, power, fragileLeft); print(" " + op + " "); Expr(bin.E1, power, fragileRight) })
+ }
+ def ParenExpr(power: int, context: int, fragileContext: boolean, pe: =>Unit) {
+ val ap = power & 0xF0;
+ val cp = context & 0xF0;
+ val parensNeeded = ap < cp || (ap == cp && (power != context || fragileContext));
+ if (parensNeeded) { print("(") }
+ pe
+ if (parensNeeded) { print(")") }
+ }
+ def Spaces(N: int) = {
+ val abunchaSpaces = " "
+ var n = N
+ while (abunchaSpaces.length <= n) {
+ print(abunchaSpaces)
+ n = n - abunchaSpaces.length
+ }
+ if (0 < n) {
+ print(abunchaSpaces.substring(0, n))
+ }
+ }
+}
diff --git a/Chalice/src/Resolver.scala b/Chalice/src/Resolver.scala
new file mode 100644
index 00000000..c7bdfd15
--- /dev/null
+++ b/Chalice/src/Resolver.scala
@@ -0,0 +1,940 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+import scala.util.parsing.input.Position
+import scala.util.parsing.input.Positional
+
+object Resolver {
+ sealed abstract class ResolverOutcome
+ case class Success extends ResolverOutcome
+ case class Error(pos: Position, s: String) extends ResolverOutcome
+ case class Errors(ss: List[String]) extends ResolverOutcome
+
+ var seqClasses = Map[String, SeqClass]();
+
+ class ProgramContext(classes: Map[String,Class], currentClass: Class) {
+ val Classes = classes
+ val CurrentClass = currentClass
+ var currentMember = null: Member;
+ def CurrentMember = currentMember: Member;
+ var errors: List[String] = Nil
+ def Error(pos: Position, msg: String) {
+ errors = errors + (pos + ": " + msg)
+ }
+ def AddVariable(v: Variable): ProgramContext = {
+ new LProgramContext(v, this);
+ }
+ def LookupVariable(id: String): Option[Variable] = None
+ def IsVariablePresent(vr: Variable): boolean = false
+
+ private class LProgramContext(v: Variable, parent: ProgramContext) extends ProgramContext(parent.Classes, parent.CurrentClass) {
+ override def Error(pos: Position, msg: String) = parent.Error(pos, msg)
+ 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 CurrentMember() = {
+ parent.CurrentMember
+ }
+ }
+ }
+
+ def Resolve(prog: List[Class]): ResolverOutcome = {
+ // register the classes and their members
+ var classes = Map[String,Class]()
+ for (cl <- BoolClass :: IntClass :: RootClass :: NullClass :: MuClass :: prog) {
+ if (classes contains cl.id) {
+ return Error(cl.pos, "duplicate class name: " + cl.id)
+ } else {
+ for (m <- cl.members) m match {
+ case _:MonitorInvariant =>
+ case m: NamedMember =>
+ m.Parent = cl
+ if (cl.mm contains m.Id) {
+ return Error(m.pos, "duplicate member name " + m.Id + " in class " + cl.id)
+ } else {
+ cl.mm = cl.mm + (m.Id -> m)
+ }
+ }
+ classes = classes + (cl.id -> cl)
+ }
+ }
+ var errors = List[String]()
+
+ // resolve types of fields and methods
+ val contextNoCurrentClass = new ProgramContext(classes, null)
+ for (cl <- prog; m <- cl.members) m match {
+ case _:MonitorInvariant =>
+ case Field(id,t) =>
+ ResolveType(t, contextNoCurrentClass)
+ case Method(id, ins, outs, spec, body) =>
+ for (v <- ins ++ outs) {
+ ResolveType(v.t, contextNoCurrentClass)
+ }
+ case Predicate(id, definition) =>
+ case Function(id, ins, out, specs, definition) =>
+ for (v <- ins) {
+ ResolveType(v.t, contextNoCurrentClass)
+ }
+ ResolveType(out, contextNoCurrentClass)
+ }
+ errors = errors ++ contextNoCurrentClass.errors;
+
+ // now, resolve and typecheck all
+ // * Field types and Method formal-parameter types
+ // * Assign, FieldUpdate, and Call statements
+ // * VariableExpr and FieldSelect expressions
+ for (cl <- prog) {
+ val context = new ProgramContext(classes, cl)
+ for (m <- cl.members) {
+ context.currentMember = m;
+ m match {
+ case MonitorInvariant(e) =>
+ ResolveExpr(e, context, true, true)(true)
+ if (!e.typ.IsBool) context.Error(m.pos, "monitor invariant requires a boolean expression (found " + e.typ.FullName + ")")
+ case _:Field => // nothing more to do
+ case m@Method(id, ins, outs, spec, body) =>
+ var ctx = context
+ for (v <- ins ++ outs) {
+ ctx = ctx.AddVariable(v)
+ }
+ spec foreach {
+ case Precondition(e) => ResolveExpr(e, ctx, false, true)(false)
+ case Postcondition(e) => ResolveExpr(e, ctx, true, true)(false)
+ case lc@LockChange(ee) =>
+ if(m.id.equals("run")) context.Error(lc.pos, "lockchange not allowed on method run")
+ ee foreach (e => ResolveExpr(e, ctx, true, false)(false))
+ }
+ ResolveStmt(BlockStmt(body), ctx)
+ case p@Predicate(id, e) =>
+ var ctx = context;
+ ResolveExpr(e, ctx, false, true)(true);
+ if(!e.typ.IsBool) context.Error(e.pos, "predicate requires a boolean expression (found " + e.typ.FullName + ")")
+ case f@Function(id, ins, out, spec, e) =>
+ var ctx = context
+ for (v <- ins) {
+ ctx = ctx.AddVariable(v)
+ }
+ spec foreach {
+ case Precondition(e) => ResolveExpr(e, ctx, false, true)(false)
+ case pc@Postcondition(e) => assert(ctx.CurrentMember != null); ResolveExpr(e, ctx, false, true)(false)
+ case lc@LockChange(ee) => context.Error(lc.pos, "lockchange not allowed on function")
+ }
+ ResolveExpr(e, ctx, false, false)(false)
+ if(! canAssign(out.typ, e.typ)) context.Error(e.pos, "function body does not match declared type (expected: " + out.FullName + ", found: " + e.typ.FullName + ")")
+ }
+ }
+ errors = errors ++ context.errors
+ }
+
+ if (errors.length == 0) {
+ Success()
+ } else {
+ Errors(errors)
+ }
+ }
+
+ def ResolveType(t: Type, context: ProgramContext): unit = {
+ for(p <- t.params){
+ ResolveType(p, context);
+ }
+ if(t.isInstanceOf[TokenType]){
+ val tt = t.asInstanceOf[TokenType];
+ ResolveType(tt.C, context);
+ if(! tt.C.typ.IsNormalClass) context.Error(t.pos, "Invalid token type. " + tt.C.FullName + " is not a user-defined class.");
+ tt.C.typ.LookupMember(tt.m) match {
+ case Some(m: Method) => val tc = TokenClass(tt.C, tt.m); tc.method = m; tt.typ = tc;
+ case _ => context.Error(t.pos, "Invalid token type. " + tt.C.FullName + " does not declare a method " + tt.m + ".");
+ }
+ return;
+ }
+ if (context.Classes contains t.FullName) {
+ t.typ = context.Classes(t.FullName)
+ } else {
+ if(seqClasses.contains(t.FullName)) {
+ t.typ = seqClasses(t.FullName)
+ } else if(t.id.equals("seq") && t.params.length == 1) {
+ val seqt = new SeqClass(t.params(0).typ);
+ seqClasses = seqClasses + ((seqt.FullName, seqt));
+ t.typ = seqt;
+ } else {
+ context.Error(t.pos, "undeclared type " + t.FullName)
+ t.typ = IntClass
+ }
+ }
+ }
+
+ def getSeqType(param: Class, context: ProgramContext): Class = {
+ if(seqClasses.contains("seq<" + param.FullName + ">")) {
+ seqClasses("seq<" + param.FullName + ">")
+ } else {
+ val seqt = new SeqClass(param);
+ seqClasses = seqClasses + ((seqt.FullName, seqt));
+ seqt
+ }
+ }
+
+ def ResolveStmt(s: Statement, context: ProgramContext): unit = s match {
+ case Assert(e) =>
+ ResolveExpr(e, context, true, true)(false)
+ if (!e.typ.IsBool) context.Error(e.pos, "assert statement requires a boolean expression (found " + e.typ.FullName + ")")
+ case Assume(e) =>
+ ResolveExpr(e, context, false, false)(false) // assume expressions remain at run-time, so OLD is not allowed
+ if (!e.typ.IsBool) context.Error(e.pos, "assume statement requires a boolean expression (found " + e.typ.FullName + ")")
+ CheckNoGhost(e, context)
+ case BlockStmt(ss) =>
+ var ctx = context
+ for (s <- ss) s match {
+ case l @ LocalVar(id, t, c, g, rhs) =>
+ ResolveType(l.v.t, ctx)
+ val oldCtx = ctx
+ ctx = ctx.AddVariable(l.v)
+ rhs match {
+ case None =>
+ case Some(rhs) =>
+ val lhs = VariableExpr(id)
+ lhs.pos = l.pos;
+ ResolveExpr(lhs, ctx, false, false)(false)
+ ResolveAssign(lhs, rhs, oldCtx)
+ }
+ case c@CallAsync(declaresLocal, token, obj, id, args) =>
+ ResolveStmt(c, ctx)
+ if (declaresLocal) {
+ c.local = new Variable(token.id, TokenType(new Type(obj.typ), id))
+ ResolveType(c.local.t, ctx)
+ ctx = ctx.AddVariable(c.local)
+ ResolveExpr(token, ctx, false, false)(false)
+ }
+ case s =>
+ ResolveStmt(s, ctx)
+ }
+ case IfStmt(guard, thn, els) =>
+ ResolveExpr(guard, context, false, false)(false)
+ if (!guard.typ.IsBool) context.Error(guard.pos, "if statement requires a boolean guard (found " + guard.typ.FullName + ")")
+ CheckNoGhost(guard, context)
+ ResolveStmt(thn, context)
+ els match { case None => case Some(s) => ResolveStmt(s, context) }
+ case w@ WhileStmt(guard, invs, lkch, body) =>
+ ResolveExpr(guard, context, false, false)(false)
+ if (!guard.typ.IsBool) context.Error(guard.pos, "while statement requires a boolean guard (found " + guard.typ.FullName + ")")
+ CheckNoGhost(guard, context)
+ for (inv <- invs) {
+ ResolveExpr(inv, context, true, true)(false)
+ if (!inv.typ.IsBool) context.Error(inv.pos, "loop invariant must be boolean (found " + inv.typ.FullName + ")")
+ }
+ for (l <- lkch) {
+ ResolveExpr(l, context, true, false)(false)
+ if (!l.typ.IsRef) context.Error(l.pos, "lockchange expression must be reference (found " + l.typ.FullName + ")")
+ }
+ ResolveStmt(body, context)
+ w.LoopTargets = ComputeLoopTargets(body) filter context.IsVariablePresent
+ case Assign(lhs, rhs) =>
+ ResolveExpr(lhs, context, false, false)(false)
+ ResolveAssign(lhs, rhs, context)
+ if (lhs.v != null && lhs.v.IsImmutable) {
+ if (lhs.v.IsGhost)
+ CheckNoGhost(rhs, context)
+ else
+ context.Error(lhs.pos, "cannot assign to immutable variable " + lhs.v.id)
+ }
+ case fu@FieldUpdate(lhs, rhs) =>
+ ResolveExpr(lhs, context, false, false)(false)
+ if (! lhs.isPredicate && lhs.f != null && !lhs.f.IsGhost) CheckNoGhost(lhs.e, context)
+ if (! lhs.isPredicate && lhs.f.isInstanceOf[SpecialField]) context.Error(lhs.pos, "cannot assign directly to special field: " + lhs.id)
+ ResolveExpr(rhs, context, false, false)(false)
+ if (! lhs.isPredicate && !canAssign(lhs.typ, rhs.typ)) context.Error(fu.pos, "type mismatch in assignment, lhs=" + lhs.typ.FullName + " rhs=" + rhs.typ.FullName)
+ if (! lhs.isPredicate && lhs.f != null && !lhs.f.IsGhost) CheckNoGhost(rhs, context)
+ case lv:LocalVar => throw new Exception("unexpected LocalVar; should have been handled in BlockStmt above")
+ case c @ Call(lhs, obj, id, args) =>
+ ResolveExpr(obj, context, false, false)(false)
+ CheckNoGhost(obj, context)
+ args foreach { a => ResolveExpr(a, context, false, false)(false); CheckNoGhost(a, context) }
+ var vars = Set[Variable]()
+ for (v <- lhs) {
+ ResolveExpr(v, context, false, false)(false)
+ if (v.v != null) {
+ if (v.v.IsImmutable) context.Error(v.pos, "cannot use immutable variable " + v.id + " as actual out-parameter")
+ if (vars contains v.v) {
+ context.Error(v.pos, "duplicate actual out-parameter: " + v.id)
+ } else {
+ vars = vars + v.v
+ }
+ }
+ }
+ // lookup method
+ var typ: Class = IntClass
+ obj.typ.LookupMember(id) match {
+ case None =>
+ context.Error(c.pos, "call of undeclared member " + id + " in class " + obj.typ.FullName)
+ case Some(m: Method) =>
+ c.m = m
+ if (args.length != m.ins.length)
+ context.Error(c.pos, "wrong number of actual in-parameters in call to " + obj.typ.FullName + "." + id +
+ " (" + args.length + " instead of " + m.ins.length + ")")
+ else {
+ for((actual, formal) <- args zip m.ins){
+ if(! canAssign(formal.t.typ, actual.typ))
+ context.Error(actual.pos, "the type of the actual argument is not assignable to the formal parameter (expected: " + formal.t.FullName + ", found: " + actual.typ.FullName + ")")
+ }
+ }
+ if (lhs.length != m.outs.length)
+ context.Error(c.pos, "wrong number of actual out-parameters in call to " + obj.typ.FullName + "." + id +
+ " (" + lhs.length + " instead of " + m.outs.length + ")")
+ else {
+ for((out, l) <- m.outs zip lhs){
+ if(! canAssign(l.typ, out.t.typ))
+ context.Error(l.pos, "the out parameter cannot be assigned to the lhs (expected: " + l.typ.FullName + ", found: " + out.t.FullName + ")")
+ }
+ }
+
+ case _ => context.Error(c.pos, "call expression does not denote a method: " + obj.typ.FullName + "." + id)
+ }
+ case Install(obj, lowerBounds, upperBounds) =>
+ ResolveExpr(obj, context, false, false)(false)
+ if (!obj.typ.IsRef) context.Error(obj.pos, "object in install statement must be of a reference type (found " + obj.typ.FullName + ")")
+ for (b <- lowerBounds ++ upperBounds) {
+ ResolveExpr(b, context, true, false)(false)
+ if (!b.typ.IsRef && !b.typ.IsMu) context.Error(b.pos, "install bound must be of a reference type or Mu type" +
+ " (found " + b.typ.FullName + ")")
+ }
+ case Share(obj, lowerBounds, upperBounds) =>
+ ResolveExpr(obj, context, false, false)(false)
+ CheckNoGhost(obj, context)
+ if (!obj.typ.IsRef) context.Error(obj.pos, "object in share statement must be of a reference type (found " + obj.typ.FullName + ")")
+ for (b <- lowerBounds ++ upperBounds) {
+ ResolveExpr(b, context, true, false)(false)
+ if (!b.typ.IsRef && !b.typ.IsMu) context.Error(b.pos, "share bound must be of a reference type or Mu type" +
+ " (found " + b.typ.FullName + ")")
+ }
+ case Unshare(obj) =>
+ ResolveExpr(obj, context, false, false)(false)
+ CheckNoGhost(obj, context)
+ if (!obj.typ.IsRef) context.Error(obj.pos, "object in unshare statement must be of a reference type (found " + obj.typ.FullName + ")")
+ case Acquire(obj) =>
+ ResolveExpr(obj, context, false, false)(false)
+ CheckNoGhost(obj, context)
+ if (!obj.typ.IsRef) context.Error(obj.pos, "object in acquire statement must be of a reference type (found " + obj.typ.FullName + ")")
+ case Release(obj) =>
+ ResolveExpr(obj, context, false, false)(false)
+ CheckNoGhost(obj, context)
+ if (!obj.typ.IsRef) context.Error(obj.pos, "object in release statement must be of a reference type (found " + obj.typ.FullName + ")")
+ case RdAcquire(obj) =>
+ ResolveExpr(obj, context, false, false)(false)
+ CheckNoGhost(obj, context)
+ if (!obj.typ.IsRef) context.Error(obj.pos, "object in rd acquire statement must be of a reference type (found " + obj.typ.FullName + ")")
+ case RdRelease(obj) =>
+ ResolveExpr(obj, context, false, false)(false)
+ CheckNoGhost(obj, context)
+ if (!obj.typ.IsRef) context.Error(obj.pos, "object in rd release statement must be of a reference type (found " + obj.typ.FullName + ")")
+ case Lock(obj, b, rdLock) =>
+ ResolveExpr(obj, context, false, false)(false)
+ CheckNoGhost(obj, context)
+ if (!obj.typ.IsRef) {
+ val sname = if (rdLock) "rd lock" else "lock";
+ context.Error(obj.pos, "object in " + sname + " statement must be of a reference type (found " + obj.typ.FullName + ")")
+
+ }
+ ResolveStmt(b, context)
+ case Downgrade(obj) =>
+ ResolveExpr(obj, context, false, false)(false)
+ CheckNoGhost(obj, context)
+ if (!obj.typ.IsRef) context.Error(obj.pos, "object in downgrade statement must be of a reference type (found " + obj.typ.FullName + ")")
+ case Free(obj) =>
+ ResolveExpr(obj, context, false, false)(false)
+ CheckNoGhost(obj, context)
+ if (!obj.typ.IsRef) context.Error(obj.pos, "object in free statement must be of a reference type (found " + obj.typ.FullName + ")")
+ case fld@Fold(e) =>
+ ResolveExpr(e, context, false, true)(false);
+ CheckNoGhost(e, context);
+ if(!e.getMemberAccess.isPredicate) context.Error(fld.pos, "Fold can only be applied to predicates.")
+ case ufld@Unfold(e) =>
+ ResolveExpr(e, context, false, true)(false);
+ CheckNoGhost(e, context);
+ if(!e.getMemberAccess.isPredicate) context.Error(ufld.pos, "Unfold can only be applied to predicates.")
+ case c@CallAsync(declaresLocal, token, obj, id, args) =>
+ // resolve receiver
+ ResolveExpr(obj, context, false, false)(false)
+ CheckNoGhost(obj, context)
+ // resolve arguments
+ args foreach { a => ResolveExpr(a, context, false, false)(false); CheckNoGhost(a, context) }
+ // lookup method
+ var typ: Class = IntClass
+ obj.typ.LookupMember(id) match {
+ case None =>
+ context.Error(c.pos, "call of undeclared member " + id + " in class " + obj.typ.FullName)
+ case Some(m: Method) =>
+ c.m = m
+ if (args.length != m.ins.length)
+ context.Error(c.pos, "wrong number of actual in-parameters in call to " + obj.typ.FullName + "." + id +
+ " (" + args.length + " instead of " + m.ins.length + ")")
+ else {
+ for((actual, formal) <- args zip m.ins){
+ if(! canAssign(formal.t.typ, actual.typ))
+ context.Error(actual.pos, "the type of the actual argument is not assignable to the formal parameter (expected: " + formal.t.FullName + ", found: " + actual.typ.FullName + ")")
+ }
+ }
+ case _ => context.Error(c.pos, "call expression does not denote a method: " + obj.typ.FullName + "." + id)
+ }
+ // resolve the token
+ if (declaresLocal) {
+ // this is taken care of in the caller that handles the enclosing block statement
+ } else if (token != null) {
+ ResolveExpr(token, context, false, false)(false)
+ if(! canAssign(token.typ, TokenClass(new Type(obj.typ), id)))
+ context.Error(token.pos, "wrong token type")
+ }
+ case jn@JoinAsync(lhs, token) =>
+ // resolve the assignees
+ var vars = Set[Variable]()
+ for (v <- lhs) {
+ ResolveExpr(v, context, false, false)(false)
+ if (v.v != null) {
+ if (v.v.IsImmutable) context.Error(v.pos, "cannot use immutable variable " + v.id + " as actual out-parameter")
+ if (vars contains v.v) {
+ context.Error(v.pos, "duplicate actual out-parameter: " + v.id)
+ } else {
+ vars = vars + v.v
+ }
+ }
+ }
+ // resolve the token
+ ResolveExpr(token, context, false, false)(false);
+ if(token.typ == null || ! token.typ.IsToken || ! token.typ.isInstanceOf[TokenClass] || token.typ.asInstanceOf[TokenClass].method == null)
+ context.Error(token.pos, "the first argument of a join async must be a token")
+ else {
+ val m = token.typ.asInstanceOf[TokenClass].method;
+ jn.m = m
+ if (lhs.length != m.outs.length)
+ context.Error(jn.pos, "wrong number of actual out-parameters in join async of " + m.FullName +
+ " (" + lhs.length + " instead of " + m.outs.length + ")")
+ else {
+ for((out, l) <- m.outs zip lhs){
+ if(! canAssign(l.typ, out.t.typ))
+ context.Error(l.pos, "the out parameter cannot be assigned to the lhs (expected: " + l.typ.FullName + ", found: " + out.t.FullName + ")")
+ }
+ }
+
+ }
+ }
+
+ def ComputeLoopTargets(s: Statement): Set[Variable] = s match { // local variables
+ case BlockStmt(ss) =>
+ (ss :\ Set[Variable]()) { (s,vars) => vars ++ ComputeLoopTargets(s) }
+ case IfStmt(guard, thn, els) =>
+ val vars = ComputeLoopTargets(thn)
+ els match { case None => vars; case Some(els) => vars ++ ComputeLoopTargets(els) }
+ case w: WhileStmt =>
+ // assume w.LoopTargets is non-null and that it was computed with a larger context
+ w.LoopTargets
+ case Assign(lhs, rhs) =>
+ if (lhs.v != null) Set(lhs.v) else Set() // don't assume resolution was successful
+ case lv: LocalVar =>
+ lv.rhs match { case None => Set() case Some(_) => Set(lv.v) }
+ case Call(lhs, obj, id, args) =>
+ (lhs :\ Set[Variable]()) { (ve,vars) => if (ve.v != null) vars + ve.v else vars }
+ case _ => Set()
+ }
+
+ def ResolveAssign(lhs: VariableExpr, rhs: RValue, context: ProgramContext) = {
+ rhs match {
+ case ExplicitSeq(Nil) => rhs.typ = lhs.typ; // if [] appears on the rhs of an assignment, we "infer" its type by looking at the type of the lhs
+ case _ => ResolveExpr(rhs, context, false, false)(false)
+ }
+ if (! canAssign(lhs.typ, rhs.typ))
+ context.Error(lhs.pos, "type mismatch in assignment, lhs=" + lhs.typ.FullName + " rhs=" + rhs.typ.FullName)
+ if (lhs.v != null && !lhs.v.IsGhost) CheckNoGhost(rhs, context)
+ }
+
+ // ResolveExpr resolves all parts of an RValue, if possible, and (always) sets the RValue's typ field
+ def ResolveExpr(e: RValue, context: ProgramContext,
+ twoStateContext: boolean, specContext: boolean)(implicit inPredicate: Boolean): unit = e match {
+ case e @ NewRhs(id, initialization) =>
+ if (context.Classes contains id) {
+ e.typ = context.Classes(id)
+ var fieldNames = Set[String]()
+ for(ini@Init(f, init) <- initialization) {
+ if (fieldNames contains f) {
+ context.Error(ini.pos, "The field " + f + " occurs more than once in initializer.")
+ } else {
+ fieldNames = fieldNames + f
+ e.typ.LookupMember(f) match {
+ case Some(field@Field(name, tp)) =>
+ if(field.isInstanceOf[SpecialField]) context.Error(init.pos, "Initializer cannot assign to special field " + name + ".");
+ ResolveExpr(init, context, false, false);
+ if(! canAssign(tp.typ, init.typ)) context.Error(init.pos, "The field " + name + " cannot be initialized with an expression of type " + init.typ.id + ".");
+ ini.f = field;
+ case _ =>
+ context.Error(e.pos, "The type " + id + " does not declare a field " + f + ".");
+ }
+ }
+ }
+ } else {
+ context.Error(e.pos, "undefined class " + id + " used in new expression")
+ e.typ = IntClass
+ }
+ case i:IntLiteral =>
+ i.typ = IntClass
+ case b:BoolLiteral =>
+ b.typ = BoolClass
+ case n:NullLiteral =>
+ n.typ = NullClass
+ case mx:MaxLockLiteral =>
+ mx.typ = MuClass
+ case mx:LockBottomLiteral =>
+ mx.typ = MuClass
+ case r:Result =>
+ assert(context.CurrentMember!=null);
+ r.typ = IntClass
+ if(context.CurrentMember==null || ! context.CurrentMember.isInstanceOf[Function]){
+ context.Error(r.pos, "The variable result can only be used in the postcondition of a function.");
+ } else {
+ r.typ = context.CurrentMember.asInstanceOf[Function].out.typ;
+ }
+ case ve @ VariableExpr(id) =>
+ context.LookupVariable(id) match {
+ case None => context.Error(ve.pos, "undefined local variable " + id); ve.typ = IntClass
+ case Some(v) => ve.v = v; ve.typ = v.t.typ }
+ case v:ThisExpr => v.typ = context.CurrentClass
+ case sel @ MemberAccess(e, id) =>
+ ResolveExpr(e, context, twoStateContext, false)
+ var typ: Class = IntClass
+ e.typ.LookupMember(id) match {
+ case None =>
+ context.Error(sel.pos, "undeclared member " + id + " in class " + e.typ.FullName)
+ case Some(f: Field) => sel.f = f; typ = f.typ.typ
+ case Some(pred@Predicate(id, body)) =>
+ if(! specContext)
+ context.Error(sel.pos, "predicate can only be used in positive predicate contexts")
+ sel.predicate = pred;
+ sel.isPredicate = true;
+ typ = BoolClass
+ case _ => context.Error(sel.pos, "field-select expression does not denote a field: " + e.typ.FullName + "." + id);
+ }
+ sel.typ = typ
+ case expr@ Access(e, perm) =>
+ if (!specContext) context.Error(expr.pos, "acc expression is allowed only in positive predicate contexts")
+ ResolveExpr(e, context, twoStateContext, true)
+ perm match {
+ case None =>
+ case Some(perm) => ResolveExpr(perm, context, twoStateContext, false) }
+ expr.typ = BoolClass
+ case expr@ RdAccess(e,perm) =>
+ if (!specContext) context.Error(expr.pos, "rd expression is allowed only in positive predicate contexts")
+ ResolveExpr(e, context, twoStateContext, true)
+ perm match {
+ case Some(Some(p)) => ResolveExpr(p, context, twoStateContext, false)
+ case _ => }
+ expr.typ = BoolClass
+ case expr@AccessAll(obj, perm) =>
+ if (!specContext) context.Error(expr.pos, "acc expression is allowed only in positive predicate contexts")
+ ResolveExpr(obj, context, twoStateContext, false)
+ if(!obj.typ.IsRef) context.Error(expr.pos, "Target of .* must be object reference.")
+ perm match {
+ case None =>
+ case Some(perm) => ResolveExpr(perm, context, twoStateContext, false) }
+ expr.typ = BoolClass
+ case expr@RdAccessAll(obj,perm) =>
+ if (!specContext) context.Error(expr.pos, "rd expression is allowed only in positive predicate contexts")
+ ResolveExpr(obj, context, twoStateContext, false)
+ if(!obj.typ.IsRef) context.Error(expr.pos, "Target of .* must be object reference.")
+ perm match {
+ case Some(Some(p)) => ResolveExpr(p, context, twoStateContext, false)
+ case _ => }
+ expr.typ = BoolClass
+ case expr@ Holds(e) =>
+ if(inPredicate) context.Error(expr.pos, "holds cannot be mentioned in monitor invariants or predicates")
+ if(! specContext)
+ context.Error(expr.pos, "holds is allowed only in positive predicate contexts");
+ //todo: check that we are not in an invariant
+ ResolveExpr(e, context, twoStateContext, false)
+ expr.typ = BoolClass
+ case expr@ RdHolds(e) =>
+ if(inPredicate) context.Error(expr.pos, "rdholds cannot be mentioned in monitor invariants or predicates")
+ ResolveExpr(e, context, twoStateContext, false)
+ expr.typ = BoolClass
+ case expr@ Assigned(id) =>
+ context.LookupVariable(id) match {
+ case None => context.Error(expr.pos, "undefined local variable " + id)
+ case Some(v) =>
+ expr.v = v
+ if (!(v.IsImmutable && v.IsGhost))
+ context.Error(expr.pos, "assigned can only be used with ghost consts")
+ }
+ expr.typ = BoolClass
+ case expr@ Old(e) =>
+ if (! twoStateContext) { context.Error(expr.pos, "old expression is not allowed here") }
+ ResolveExpr(e, context, twoStateContext, false)
+ expr.typ = e.typ
+ 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");
+ 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);
+ args foreach { arg => ResolveExpr(arg, context, twoStateContext, false)};
+ // lookup function
+ appl.typ = IntClass
+ obj.typ.LookupMember(id) match {
+ case None =>
+ context.Error(appl.pos, "function " + id + " not found in class " + obj.typ.FullName)
+ case Some(func@Function(f, ins, out, specs, body)) =>
+ appl.f = func
+ appl.typ = func.out.typ;
+ if (args.length != ins.length)
+ context.Error(appl.pos, "wrong number of actual arguments in function application of " + obj.typ.FullName + "." + id +
+ " (" + args.length + " instead of " + ins.length + ")")
+ else {
+ for((actual, formal) <- args zip func.ins){
+ if(! canAssign(formal.t.typ, actual.typ))
+ context.Error(actual.pos, "the type of the actual argument is not assignable to the formal parameter (expected: " + formal.t.FullName + ", found: " + actual.typ.FullName + ")")
+ }
+ }
+ case _ => context.Error(appl.pos, obj.typ.id + "." + id + " is not a function")
+ }
+ case uf@Unfolding(pred, e) =>
+ ResolveExpr(pred, context, twoStateContext, true);
+ ResolveExpr(e, context, twoStateContext, false);
+ if(! pred.getMemberAccess.isPredicate) context.Error(uf.pos, "Only predicates can be unfolded.")
+ uf.typ = e.typ;
+ case bin: EqualityCompareExpr =>
+ ResolveExpr(bin.E0, context, twoStateContext, false)
+ ResolveExpr(bin.E1, context, twoStateContext, false)
+ if (bin.E0.typ == bin.E1.typ) { /* all is well */ }
+ else if (bin.E0.typ.IsRef && bin.E1.typ.IsNull) { /* all is well */ }
+ else if (bin.E0.typ.IsNull && bin.E1.typ.IsRef) { /* all is well */ }
+ else
+ context.Error(bin.pos, bin.OpName + " requires operands of the same type, found " + bin.E0.typ.FullName + " and " + bin.E1.typ.FullName)
+ bin.typ = BoolClass
+ case bin: LockBelow =>
+ ResolveExpr(bin.E0, context, twoStateContext, false)
+ ResolveExpr(bin.E1, context, twoStateContext, false)
+ if (!(bin.E0.typ.IsRef || bin.E0.typ.IsMu))
+ context.Error(bin.pos, "type of " + bin.OpName + " LHS operand must be a reference or Mu type (found " + bin.E0.typ.FullName + ")")
+ if (!(bin.E1.typ.IsRef || bin.E1.typ.IsMu))
+ context.Error(bin.pos, "type of " + bin.OpName + " RHS operand must be a reference or Mu type (found " + bin.E1.typ.FullName + ")")
+ bin.typ = BoolClass
+ case app@Append(e0, e1) =>
+ ResolveExpr(e0, context, twoStateContext, false);
+ ResolveExpr(e1, context, twoStateContext, false);
+ if(! e0.typ.IsSeq) context.Error(app.pos, "LHS operand of ++ must be sequence (found: " + e0.typ.FullName + ").");
+ if(! e1.typ.IsSeq) context.Error(app.pos, "RHS operand of ++ must be sequence (found: " + e1.typ.FullName + ").");
+ if(e0.typ != e1.typ) context.Error(app.pos, "++ can only be applied to sequences of the same type.");
+ app.typ = e0.typ;
+ case at@At(e0, e1) =>
+ ResolveExpr(e0, context, twoStateContext, false);
+ ResolveExpr(e1, context, twoStateContext, false);
+ if(! e0.typ.IsSeq) context.Error(at.pos, "LHS operand of @ must be sequence. (found: " + e0.typ.FullName + ").");
+ if(! e1.typ.IsInt) context.Error(at.pos, "RHS operand of @ must be an integer (found: " + e1.typ.FullName + ").");
+ if(e0.typ.IsSeq) at.typ = e0.typ.parameters(0) else at.typ = IntClass;
+ case drop@Drop(e0, e1) =>
+ ResolveExpr(e0, context, twoStateContext, false);
+ ResolveExpr(e1, context, twoStateContext, false);
+ if(! e0.typ.IsSeq) context.Error(drop.pos, "LHS operand of drop must be sequence. (found: " + e0.typ.FullName + ").");
+ if(! e1.typ.IsInt) context.Error(drop.pos, "RHS operand of drop must be an integer (found: " + e1.typ.FullName + ").");
+ drop.typ = e0.typ;
+ case take@Take(e0, e1) =>
+ ResolveExpr(e0, context, twoStateContext, false);
+ ResolveExpr(e1, context, twoStateContext, false);
+ if(! e0.typ.IsSeq) context.Error(take.pos, "LHS operand of take must be sequence. (found: " + e0.typ.FullName + ").");
+ if(! e1.typ.IsInt) context.Error(take.pos, "RHS operand of take must be an integer (found: " + e1.typ.FullName + ").");
+ take.typ = e0.typ;
+ case bin: BinaryExpr =>
+ ResolveExpr(bin.E0, context, twoStateContext, specContext && bin.isInstanceOf[And])
+ ResolveExpr(bin.E1, context, twoStateContext, specContext && (bin.isInstanceOf[And] || bin.isInstanceOf[Implies]))
+ if (bin.E0.typ != bin.ExpectedLhsType)
+ context.Error(bin.E0.pos, "incorrect type of " + bin.OpName + " LHS" +
+ " (expected " + bin.ExpectedLhsType.FullName +
+ ", found " + bin.E0.typ.FullName + ")")
+ if (bin.E1.typ != bin.ExpectedRhsType)
+ context.Error(bin.E1.pos, "incorrect type of " + bin.OpName + " RHS" +
+ " (expected " + bin.ExpectedRhsType.FullName + ", found " + bin.E1.typ.FullName + ")")
+ bin.typ = bin.ResultType
+ case q: Quantification =>
+ q.Is foreach { i => if(context.LookupVariable(i).isDefined) context.Error(q.pos, "The variable " + i + " hides another local.") }
+ ResolveExpr(q.Seq, context, twoStateContext, false);
+ if(! q.Seq.typ.IsSeq)
+ context.Error(q.Seq.pos, "A quantification must range over a sequence. (found: " + q.Seq.typ.FullName + ").");
+ else {
+ val elementType = q.Seq.typ.parameters(0);
+ var bodyContext = context;
+ var bvariables = Nil: List[Variable];
+ q.Is foreach { i =>
+ val variable = new Variable(i, new Type(elementType));
+ bodyContext = bodyContext.AddVariable(variable);
+ bvariables = bvariables + variable;
+ }
+ ResolveExpr(q.E, bodyContext, twoStateContext, true);
+ if(! q.E.typ.IsBool) context.Error(q.E.pos, "Body of quantification must be a boolean. (found: " + q.E.typ.FullName + ").");
+ q.variables = bvariables;
+ }
+ q.typ = BoolClass
+ case seq@EmptySeq(t) =>
+ ResolveType(t, context)
+ seq.typ = getSeqType(t.typ, context);
+ case seq@ExplicitSeq(es) =>
+ es foreach { e => ResolveExpr(e, context, twoStateContext, false) }
+ es match {
+ case Nil => seq.typ = getSeqType(IntClass, context);
+ case h :: t =>
+ t foreach { e => if(! (e.typ == h.typ)) context.Error(e.pos, "The elements of the sequence expression have different types.")};
+ seq.typ = getSeqType(h.typ, context);
+ }
+ case ran@Range(min, max) =>
+ ResolveExpr(min, context, twoStateContext, false);
+ if(! min.typ.IsInt) context.Error(min.pos, "The mininum of a range expression must be an integer (found: " + min.typ.FullName + ").");
+ ResolveExpr(max, context, twoStateContext, false);
+ if(! max.typ.IsInt) context.Error(max.pos, "The maximum of a range expression must be an integer (found: " + max.typ.FullName + ").");
+ ran.typ = getSeqType(IntClass, context);
+ case len@Length(e) =>
+ ResolveExpr(e, context, twoStateContext, false);
+ if(! e.typ.IsSeq) context.Error(len.pos, "The operand of a length expression must be sequence. (found: " + e.typ.FullName + ").");
+ len.typ = IntClass;
+ case ev@Eval(h, e) =>
+ if(inPredicate) context.Error(ev.pos, "eval cannot be used in monitor invariants or predicates")
+ h match {
+ case AcquireState(obj) =>
+ ResolveExpr(obj, context, twoStateContext, false)
+ if(! obj.typ.IsRef) context.Error(ev.pos, "The target of acquire must be a reference.");
+ case ReleaseState(obj) => ResolveExpr(obj, context, twoStateContext, false)
+ if(! obj.typ.IsRef) context.Error(ev.pos, "The target of acquire must be a reference.");
+ case c@CallState(token, obj, id, args) =>
+ ResolveExpr(token, context, twoStateContext, false);
+ if( ! token.typ.IsToken) context.Error(token.pos, "joinable is only applicable to tokens");
+ ResolveExpr(obj, context, false, false)
+ CheckNoGhost(obj, context)
+ args foreach { a => ResolveExpr(a, context, false, false); CheckNoGhost(a, context) }
+ // lookup method
+ var typ: Class = IntClass
+ obj.typ.LookupMember(id) match {
+ case None =>
+ context.Error(obj.pos, "call of undeclared member " + id + " in class " + obj.typ.FullName)
+ case Some(m: Method) =>
+ c.m = m
+ if (args.length != m.ins.length)
+ context.Error(obj.pos, "wrong number of actual in-parameters in call to " + obj.typ.FullName + "." + id +
+ " (" + args.length + " instead of " + m.ins.length + ")")
+ else {
+ for((actual, formal) <- args zip m.ins){
+ if(! canAssign(formal.t.typ, actual.typ))
+ context.Error(actual.pos, "the type of the actual argument is not assignable to the formal parameter (expected: " + formal.t.FullName + ", found: " + actual.typ.FullName + ")")
+ }
+ }
+ case _ => context.Error(obj.pos, "call expression does not denote a method: " + obj.typ.FullName + "." + id)
+ }
+
+
+ }
+ ResolveExpr(e, context, false, specContext)
+ ev.typ = e.typ;
+ }
+
+ def LookupRunMethod(cl: Class, context: ProgramContext, op: String, pos: Position): Option[Method] = {
+ cl.LookupMember("run") match {
+ case None =>
+ context.Error(pos, "object given in " + op + " statement must be of a type with a parameter-less run method" +
+ " (found type " + cl.id + ")")
+ None
+ case Some(m: Method) =>
+ m.spec foreach {
+ case Precondition(e) => CheckRunSpecification(e, context, true)
+ case Postcondition(e) => CheckRunSpecification(e, context, false)
+ case lc: LockChange => context.Error(lc.pos, "lockchange is not allowed in specification of run method")
+ }
+ if(0<m.ins.length || 0<m.outs.length) {
+ context.Error(pos, "object given in " + op + " statement must be of a type with a parameter-less run method" +
+ " (found " + m.ins.length + " in-parameters and " + m.outs.length + " out-parameters)"); None
+ } else
+ Some(m)
+ case _ =>
+ context.Error(pos, "object given in " + op + " statement must be of a type with a parameter-less run method" +
+ " (found non-method member)")
+ None
+ }
+ }
+
+ // assumes that lhs and rhs are resolved
+ def canAssign(lhs: Class, rhs: Class): Boolean = {
+ (lhs, rhs) match {
+ case (TokenClass(c1, m1), TokenClass(c2, m2)) => c1.id.equals(c2.id) && m1.equals(m2)
+ case (TokenClass(c1, m1), _) => false
+ case (_, TokenClass(c2, m2)) => false
+ case (lhs, rhs) => lhs == rhs || (lhs.IsRef && rhs.IsNull)
+ }
+ }
+
+ def CheckNoGhost(expr: RValue, context: ProgramContext): Unit = {
+ def specOk(e: RValue): Unit = {
+ e match {
+ case ve: VariableExpr =>
+ if (ve.v != null && ve.v.IsGhost) context.Error(ve.pos, "ghost variable not allowed here")
+ case fs@ MemberAccess(e, id) =>
+ if (!fs.isPredicate && fs.f != null && fs.f.IsGhost) context.Error(fs.pos, "ghost fields not allowed here")
+ CheckNoGhost(e, context)
+ case a: Assigned =>
+ if (a.v != null && a.v.IsGhost) context.Error(a.pos, "ghost variable not allowed here")
+ case _ => visitE(e, specOk)
+ }
+ }
+ specOk(expr)
+ }
+
+ def CheckNoImmutableGhosts(expr: RValue, context: ProgramContext): Unit = {
+ def specOk(e: RValue): Unit = {
+ e match {
+ case ve: VariableExpr =>
+ if (ve.v != null && ve.v.IsGhost && ve.v.IsImmutable) context.Error(ve.pos, "ghost const not allowed here")
+ case a: Assigned =>
+ if (a.v != null && a.v.IsGhost && a.v.IsImmutable) context.Error(a.pos, "ghost const not allowed here")
+ case _ => visitE(e, specOk)
+ }
+ }
+ specOk(expr)
+ }
+
+ def CheckRunSpecification(e: Expression, context: ProgramContext, allowMaxLock: boolean): unit = e match {
+ case _:MaxLockLiteral =>
+ if (!allowMaxLock) context.Error(e.pos, "specification of run method is not allowed to mention maxlock here")
+ case _:Literal =>
+ case _:VariableExpr =>
+ case _:ThisExpr =>
+ case _:Result =>
+ case MemberAccess(e, id) =>
+ CheckRunSpecification(e, context, false)
+ case Access(e, perm) =>
+ CheckRunSpecification(e, context, false)
+ perm match { case None => case Some(perm) => CheckRunSpecification(perm, context, false) }
+ case RdAccess(e, perm) =>
+ CheckRunSpecification(e, context, false)
+ perm match { case Some(Some(p)) => CheckRunSpecification(p, context, false) case _ => }
+ case AccessAll(obj, perm) =>
+ CheckRunSpecification(obj, context, false)
+ perm match { case None => case Some(perm) => CheckRunSpecification(perm, context, false) }
+ case RdAccessAll(obj, perm) =>
+ CheckRunSpecification(obj, context, false)
+ perm match { case Some(Some(p)) => CheckRunSpecification(p, context, false) case _ => }
+ case Holds(e) =>
+ context.Error(e.pos, "holds is not allowed in specification of run method")
+ case RdHolds(e) =>
+ context.Error(e.pos, "rd holds is not allowed in specification of run method")
+ case _:Assigned =>
+ case Old(e) =>
+ CheckRunSpecification(e, context, false) // OLD occurs only in postconditions and monitor invariants, where maxlock is not allowed anyhow
+ case IfThenElse(con, then, els) =>
+ CheckRunSpecification(con, context, false);
+ CheckRunSpecification(con, context, allowMaxLock);
+ CheckRunSpecification(con, context, allowMaxLock);
+ case Not(e) =>
+ CheckRunSpecification(e, context, false)
+ case FunctionApplication(obj, id, args) =>
+ obj :: args foreach { arg => CheckRunSpecification(arg, context, false)}
+ case Unfolding(pred, e) =>
+ CheckRunSpecification(pred, context, true);
+ CheckRunSpecification(e, context, allowMaxLock);
+ case LockBelow(e0,e1) =>
+ CheckRunSpecification(e0, context, allowMaxLock)
+ CheckRunSpecification(e1, context, false)
+ case And(e0,e1) =>
+ CheckRunSpecification(e0, context, allowMaxLock)
+ CheckRunSpecification(e1, context, allowMaxLock)
+ case Implies(e0,e1) =>
+ CheckRunSpecification(e0, context, false)
+ CheckRunSpecification(e1, context, allowMaxLock)
+ case bin: BinaryExpr =>
+ CheckRunSpecification(bin.E0, context, false)
+ CheckRunSpecification(bin.E1, context, false)
+ case q: Quantification =>
+ CheckRunSpecification(q.Seq, context, false)
+ CheckRunSpecification(q.E, context, true)
+ case Length(e) =>
+ CheckRunSpecification(e, context, false);
+ case ExplicitSeq(es) =>
+ es foreach { e => CheckRunSpecification(e, context, false) }
+ case Range(min, max) =>
+ CheckRunSpecification(min, context, false)
+ CheckRunSpecification(max, context, false)
+ case Eval(h, e) =>
+ h match {
+ case AcquireState(obj) => CheckRunSpecification(obj, context, false);
+ case ReleaseState(obj) => CheckRunSpecification(obj, context, false);
+ case CallState(token, obj, id, args) => CheckRunSpecification(token, context, false); CheckRunSpecification(obj, context, false); args foreach { a: Expression => CheckRunSpecification(a, context, false)};
+ }
+ CheckRunSpecification(e, context, allowMaxLock)
+ }
+
+ def visitE(expr: RValue, func: RValue => Unit): Unit = {
+ expr match {
+ case _:NewRhs =>
+ case e: Literal => ;
+ case _:ThisExpr => ;
+ case _:Result => ;
+ case e:VariableExpr => ;
+ case acc@MemberAccess(e,f) =>
+ func(e);
+ case Access(e, perm) =>
+ func(e); perm match { case Some(p) => func(p); case _ => ; }
+ case RdAccess(e, perm) =>
+ func(e); perm match { case Some(Some(p)) => func(p); case _ => ; }
+ case AccessAll(obj, perm) =>
+ func(obj); perm match { case Some(p) => func(p); case _ => ; }
+ case RdAccessAll(obj, perm) =>
+ func(obj); perm match { case Some(Some(p)) => func(p); case _ => ; }
+ case Holds(e) => func(e);
+ case RdHolds(e) => func(e);
+ case e: Assigned => e
+ case Old(e) => func(e);
+ case IfThenElse(con, then, els) => func(con); func(then); func(els);
+ case Not(e) => func(e);
+ case funapp@FunctionApplication(obj, id, args) =>
+ func(obj); args foreach { arg => func(arg) };
+ case Unfolding(pred, e) =>
+ func(pred); func(e);
+ case Iff(e0,e1) => func(e0); func(e1);
+ case Implies(e0,e1) => func(e0); func(e1);
+ case And(e0,e1) =>func(e0); func(e1);
+ case Or(e0,e1) => func(e0); func(e1);
+ case Eq(e0,e1) => func(e0); func(e1);
+ case Neq(e0,e1) => func(e0); func(e1);
+ case Less(e0,e1) => func(e0); func(e1);
+ case AtMost(e0,e1) => func(e0); func(e1);
+ case AtLeast(e0,e1) => func(e0); func(e1);
+ case Greater(e0,e1) => func(e0); func(e1);
+ case LockBelow(e0,e1) => func(e0); func(e1);
+ case Plus(e0,e1) => func(e0); func(e1);
+ case Minus(e0,e1) => func(e0); func(e1);
+ case Times(e0,e1) => func(e0); func(e1);
+ case Div(e0,e1) => func(e0); func(e1);
+ case Mod(e0,e1) => func(e0); func(e1);
+ case Forall(i, seq, e) => func(seq); func(e);
+ case ExplicitSeq(es) =>
+ es foreach { e => func(e) }
+ case Range(min, max) =>
+ func(min); func(max);
+ case Append(e0, e1) =>
+ func(e0); func(e1);
+ case at@At(e0, e1) =>
+ func(e0); func(e1);
+ case Drop(e0, e1) =>
+ func(e0); func(e1);
+ case Take(e0, e1) =>
+ func(e0); func(e1);
+ case Length(e) =>
+ func(e)
+ case Eval(h, e) =>
+ h match {
+ case AcquireState(obj) => func(obj);
+ case ReleaseState(obj) => func(obj);
+ case CallState(token, obj, id, args) => func(token); func(obj); args foreach {a : Expression => func(a)};
+ }
+ func(e);
+ }
+ }
+}
diff --git a/Chalice/src/Translator.scala b/Chalice/src/Translator.scala
new file mode 100644
index 00000000..9ec41448
--- /dev/null
+++ b/Chalice/src/Translator.scala
@@ -0,0 +1,2260 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+import scala.util.parsing.input.Position
+
+import Boogie.Proc, Boogie.NamedType, Boogie.NewBVar, Boogie.Havoc, Boogie.Stmt, Boogie.Const,
+ Boogie.Decl, Boogie.Expr, Boogie.FunctionApp, Boogie.Axiom, Boogie.BVar, Boogie.BType,
+ Boogie.VarExpr, Boogie.IndexedType, Boogie.Comment, Boogie.MapUpdate, Boogie.MapSelect,
+ Boogie.If;
+
+case class ErrorMessage(pos: Position, message: String)
+
+object TranslationOptions {
+ // note: the initial values should match those Chalice.scala
+
+ var defaults = 0: int;
+ var autoFold = false: Boolean;
+ var checkLeaks = false: Boolean;
+ var autoMagic = false: Boolean;
+}
+
+class Translator {
+ import TranslationHelper._;
+ import TranslationOptions._;
+ var currentClass = null: Class;
+ var currentMethod = null: Method;
+ var modules = Nil: List[String]
+ var etran = new ExpressionTranslator(null);
+
+ def translateProgram(classes: List[Class]): List[Decl] = {
+ classes flatMap { translateClass(_) }
+ }
+
+ def translateClass(cl: Class): List[Decl] = {
+ currentClass = cl;
+ etran = new ExpressionTranslator(cl);
+ var declarations = Nil: List[Decl]
+ // add module (if no added yet)
+ if(modules forall {mname => ! mname.equals(cl.module)}) {
+ declarations = declarations + Const(ModuleName(cl), true, ModuleType);
+ modules = modules + cl.module;
+ }
+ // add class name
+ declarations = declarations + Const(cl.id + "#t", true, TypeName);
+ // translate monitor invariant
+ declarations = declarations ::: translateMonitorInvariant(cl.Invariants);
+ // translate each member
+ for(member <- cl.members) {
+ declarations = declarations ::: translateMember(member);
+ }
+ declarations
+ }
+
+ /**********************************************************************
+ ***************** MEMBERS *****************
+ **********************************************************************/
+
+ def translateMember(member: Member): List[Decl] = {
+ member match {
+ case f: Field =>
+ translateField(f)
+ case m: Method =>
+ translateMethod(m)
+ case f: Function =>
+ translateFunction(f)
+ case pred: Predicate =>
+ translatePredicate(pred)
+ case inv: MonitorInvariant =>
+ Nil // already dealt with before
+ }
+ }
+
+ def translateMonitorInvariant(invs: List[MonitorInvariant]): List[Decl] = {
+ val (m1V, m1) = NewBVar("m1", tmask, true); val (h1V, h1) = NewBVar("h1", theap, true);
+ val (m2V, m2) = NewBVar("m2", tmask, true); val (h2V, h2) = NewBVar("h2", theap, true);
+ val (lkV, lk) = NewBVar("lk", tref, true);
+ val oldTranslator = new ExpressionTranslator(List(h2, m2), List(h1, m1), currentClass);
+ Proc(currentClass.id + "$monitorinvariant$checkDefinedness",
+ List(NewBVarWhere("this", new Type(currentClass))),
+ Nil,
+ GlobalNames,
+ DefaultPrecondition(),
+ BLocal(h1V) :: BLocal(m1V) ::BLocal(h2V) :: BLocal(m2V) :: BLocal(lkV) ::
+ bassume(wf(h1, m1)) :: bassume(wf(h2, m2)) ::
+ (oldTranslator.Mask := ZeroMask) ::
+ oldTranslator.Inhale(invs map { mi => mi.e}, "monitor invariant", false) :::
+ (etran.Mask := ZeroMask) ::
+ Havoc(etran.Heap) ::
+ // check that invariant is well-defined
+ etran.WhereOldIs(h2, m2).Inhale(invs map { mi => mi.e}, "monitor invariant", true) :::
+ (if (!checkLeaks || invs.length == 0) Nil else
+ // check that there are no loops among .mu permissions in monitors
+ // !CanWrite[this,mu]
+ bassert(!etran.CanWrite(VarExpr("this"), "mu"), invs(0).pos, "Monitor invariant is not allowed to hold write permission to this.mu") ::
+ // (forall lk :: lk != null && lk != this && CanRead[lk,mu] ==>
+ // CanRead[this,mu] && Heap[this,mu] << Heap[lk,mu])
+ bassert(
+ (lk !=@ NullLiteral() && lk !=@ VarExpr("this") && etran.CanRead(lk, "mu")) ==>
+ (etran.CanRead(VarExpr("this"), "mu") &&
+ new FunctionApp("MuBelow", etran.Heap.select(VarExpr("this"), "mu"), etran.Heap.select(lk, "mu"))),
+ invs(0).pos,
+ "Monitor invariant can hold permission of other o.mu field only this.mu if this.mu<<o.mu")
+ ) :::
+ //check that invariant is reflexive
+ etran.UseCurrentAsOld().Exhale(invs map {mi => (mi.e, ErrorMessage(mi.pos, "Monitor invariant might not be reflexive."))}, "invariant reflexive?", false))
+ }
+
+ def translateField(f: Field): List[Decl] = {
+ Const(f.FullName, true, FieldType(f.typ)) ::
+ Axiom(NonPredicateField(f.FullName))
+ }
+
+ def translateFunction(f: Function): List[Decl] = {
+ val myresult = BVar("result", Boogie.ClassType(f.out.typ));
+ etran.checkTermination = true;
+ val checkBody = isDefined(f.definition);
+ etran.checkTermination = false;
+ // BoogiePL function that represents the dafny function
+ Boogie.Function(functionName(f), BVar("heap", theap) :: Boogie.BVar("mask", tmask) :: Boogie.BVar("this", tref) :: (f.ins map Variable2BVar), new Boogie.BVar("$myresult", Boogie.ClassType(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)}),
+ Nil,
+ GlobalNames,
+ DefaultPrecondition(),
+ DefinePreInitialState :::
+ // check definedness of the precondition
+ InhaleWithChecking(Preconditions(f.spec) map { p => (if(0<defaults) UnfoldPredicatesWithReceiverThis(p) else p)}, "precondition") :::
+ bassume(CurrentModule ==@ VarExpr(ModuleName(currentClass))) :: // verify the body assuming that you are in the module
+ // check definedness of function body
+ checkBody :::
+ BLocal(myresult) ::
+ (Boogie.VarExpr("result") := etran.Tr(f.definition)) ::
+ // check that postcondition holds
+ ExhaleWithChecking(Postconditions(f.spec) map { post => ((if(0<defaults) UnfoldPredicatesWithReceiverThis(post) else post), ErrorMessage(f.pos, "Postcondition at " + post.pos + " might not hold."))}, "function postcondition")) ::
+ // definition axiom
+ definitionAxiom(f) ::
+ // framing axiom (+ frame function)
+ framingAxiom(f) :::
+ // postcondition axiom(s)
+ postconditionAxiom(f)
+ }
+
+ def definitionAxiom(f: Function): Axiom = {
+ val version = Version(Preconditions(f.spec).foldLeft(BoolLiteral(true): Expression)({ (a, b) => And(a, b) }), etran);
+ val inArgs = (f.ins map {i => Boogie.VarExpr(i.UniqueName)});
+ val frameFunctionName = "##" + f.FullName;
+
+ /* axiom (forall h: HeapType, m: MaskType, this: ref, x_1: t_1, ..., x_n: t_n ::
+ wf(h, m) && CurrentModule == module#C ==> #C.f(h, m, this, x_1, ..., x_n) == tr(body))
+ */
+ val args = VarExpr("this") :: inArgs;
+ val applyF = f.apply(List(etran.Heap, etran.Mask) ::: args);
+ Axiom(new Boogie.Forall(
+ BVar(HeapName, theap) :: BVar(MaskName, tmask) :: BVar("this", tref) :: (f.ins map Variable2BVar),
+ List(applyF),
+ (wf(Heap, Mask) && (CurrentModule ==@ ModuleName(currentClass)))
+ ==>
+ (applyF ==@ etran.Tr(f.definition)))
+ )
+ }
+
+ def framingAxiom(f: Function): List[Decl] = {
+ /* function ##C.f(state, ref, t_1, ..., t_n) returns (t);
+ axiom (forall h: HeapType, m: MaskType, this: ref, x_1: t_1, ..., x_n: t_n ::
+ wf(h, m) && IsGoodState(version) ==> #C.f(h, m, this, x_1, ..., x_n) == ##C.f(version, this, x_1, ..., x_n))
+ */
+ val version = Version(Preconditions(f.spec).foldLeft(BoolLiteral(true): Expression)({ (a, b) => And(a, b) }), etran);
+ val inArgs = (f.ins map {i => Boogie.VarExpr(i.UniqueName)});
+ val frameFunctionName = "##" + f.FullName;
+
+ val args = VarExpr("this") :: inArgs;
+ val applyF = f.apply(List(etran.Heap, etran.Mask) ::: args);
+ val applyFrameFunction = FunctionApp(frameFunctionName, version :: args);
+ Boogie.Function("##" + f.FullName, Boogie.BVar("state", theap) :: Boogie.BVar("this", tref) :: (f.ins map Variable2BVar), new BVar("$myresult", f.out)) ::
+ Axiom(new Boogie.Forall(
+ BVar(HeapName, theap) :: BVar(MaskName, tmask) :: BVar("this", tref) :: (f.ins map Variable2BVar),
+ List(applyF),
+ (wf(Heap, Mask) && IsGoodState(version) && CanAssumeFunctionDefs)
+ ==>
+ (applyF ==@ applyFrameFunction))
+ )
+ }
+
+ def postconditionAxiom(f: Function): List[Decl] = {
+ /* function ##C.f(state, ref, t_1, ..., t_n) returns (t);
+ axiom (forall h: HeapType, m: MaskType, this: ref, x_1: t_1, ..., x_n: t_n ::
+ wf(h, m) && CanAssumeFunctionDefs ==> Q[#C.f(h, m, this, x_1, ..., x_n)/result]
+ */
+ val version = Version(Preconditions(f.spec).foldLeft(BoolLiteral(true): Expression)({ (a, b) => And(a, b) }), etran);
+ val inArgs = (f.ins map {i => Boogie.VarExpr(i.UniqueName)});
+ val myresult = Boogie.BVar("result", Boogie.ClassType(f.out.typ));
+ val args = VarExpr("this") :: inArgs;
+ val applyF = f.apply(List(Heap, Mask) ::: args)
+ //postcondition axioms
+ (Postconditions(f.spec) map { post : Expression =>
+ Axiom(new Boogie.Forall(
+ BVar(HeapName, theap) :: BVar(MaskName, tmask) :: BVar("this", tref) :: (f.ins map Variable2BVar),
+ List(applyF),
+ (wf(Heap, Mask) && CanAssumeFunctionDefs)
+ ==>
+ etran.Tr(SubstResult(post, f.apply(ExplicitThisExpr(), f.ins map { arg => new VariableExpr(arg) })))
+ ))
+ })
+ }
+
+ def translatePredicate(pred: Predicate): List[Decl] = {
+ // const unique class.name: HeapType;
+ Const(pred.FullName, true, FieldType(theap)) ::
+ // axiom PredicateField(f);
+ Axiom(PredicateField(pred.FullName)) ::
+ // check definedness of predicate body
+ Proc(pred.FullName + "$checkDefinedness",
+ List(NewBVarWhere("this", new Type(currentClass))),
+ Nil,
+ GlobalNames,
+ DefaultPrecondition(),
+ DefinePreInitialState :::
+ InhaleWithChecking(List(DefinitionOf(pred)), "predicate definition"))
+ }
+
+ def translateMethod(method: Method): List[Decl] = {
+ // check definedness of the method contract
+ Proc(method.FullName + "$checkDefinedness",
+ NewBVarWhere("this", new Type(currentClass)) :: (method.ins map {i => Variable2BVarWhere(i)}),
+ method.outs map {i => Variable2BVarWhere(i)},
+ GlobalNames,
+ DefaultPrecondition(),
+ DefinePreInitialState :::
+ bassume(CanAssumeFunctionDefs) ::
+ // check precondition
+ InhaleWithChecking(Preconditions(method.spec), "precondition") :::
+ DefineInitialState :::
+ (Mask := ZeroMask) ::
+ Havoc(etran.Heap) ::
+ // check postcondition
+ InhaleWithChecking(Postconditions(method.spec), "postcondition") :::
+ // check lockchange
+ (LockChanges(method.spec) flatMap { lc => isDefined(lc)})) ::
+ // check that method body satisfies the method contract
+ Proc(method.FullName,
+ NewBVarWhere("this", new Type(currentClass)) :: (method.ins map {i => Variable2BVarWhere(i)}),
+ method.outs map {i => Variable2BVarWhere(i)},
+ GlobalNames,
+ DefaultPrecondition(),
+ bassume(CurrentModule ==@ Boogie.VarExpr(ModuleName(currentClass))) ::
+ bassume(CanAssumeFunctionDefs) ::
+ DefinePreInitialState :::
+ Inhale(Preconditions(method.spec) map { p => (if(0<defaults) UnfoldPredicatesWithReceiverThis(p) else p)}, "precondition") :::
+ DefineInitialState :::
+ translateStatements(method.body) :::
+ Exhale(Postconditions(method.spec) map { p => ((if(0<defaults) UnfoldPredicatesWithReceiverThis(p) else p), ErrorMessage(method.pos, "The postcondition at " + p.pos + " might not hold."))}, "postcondition") :::
+ (if(checkLeaks) isLeaking(method.pos, "Method " + method.FullName + " might leak refereces.") else Nil) :::
+ bassert(LockFrame(LockChanges(method.spec), etran), method.pos, "Method might lock/unlock more than allowed.")) :: Nil
+ }
+
+ def DefaultPrecondition() : List[String] =
+ {
+ List("requires this!=null;", "free requires wf(Heap, Mask);")
+ }
+ def DefinePreInitialState = {
+ Comment("define pre-initial state") ::
+ (etran.Mask := ZeroMask)
+ }
+ def DefineInitialState = {
+ Comment("define initial state") ::
+ bassume(etran.Heap ==@ Boogie.Old(etran.Heap)) ::
+ bassume(etran.Mask ==@ Boogie.Old(etran.Mask))
+ }
+
+ /**********************************************************************
+ ***************** STATEMENTS *****************
+ **********************************************************************/
+ def translateStatements(statements: List[Statement]): List[Stmt] = {
+ statements flatMap translateStatement
+ }
+
+ def translateStatement(s: Statement): List[Stmt] = {
+ s match {
+ case Assert(e) =>
+ val newGlobals = etran.FreshGlobals("assert");
+ val tmpHeap = Boogie.NewBVar(HeapName, theap, true);
+ val tmpMask = Boogie.NewBVar(MaskName, tmask, true);
+ val tmpTranslator = new ExpressionTranslator(List(tmpHeap._1.id, tmpMask._1.id), currentClass);
+ Comment("assert") ::
+ // exhale e in a copy of the heap/mask
+ BLocal(tmpHeap._1) :: (tmpHeap._2 := Heap) ::
+ BLocal(tmpMask._1) :: (tmpMask._2 := Mask) ::
+ tmpTranslator.Exhale(List((e, ErrorMessage(s.pos, "Assertion might not hold."))), "assert", true)
+ case Assume(e) =>
+ Comment("assume") ::
+ isDefined(e) :::
+ bassume(e)
+ case BlockStmt(ss) =>
+ translateStatements(ss)
+ case IfStmt(guard, then, els) =>
+ val tt = translateStatement(then)
+ val et = els match {
+ case None => Nil
+ case Some(els) => translateStatement(els) }
+ Comment("if") ::
+ isDefined(guard) :::
+ Boogie.If(guard, tt, et)
+ case w: WhileStmt =>
+ translateWhile(w)
+ case Assign(lhs, rhs) =>
+ def assignOrAssumeEqual(r: Boogie.Expr): List[Boogie.Stmt] = {
+ if (lhs.v.isInstanceOf[ImmutableVariable]) {
+ // this must be a "ghost const"
+ val name = lhs.v.UniqueName
+ bassert(! VarExpr("assigned$" + name), lhs.pos, "Const variable can be assigned to only once.") ::
+ bassume(lhs ==@ r) ::
+ (VarExpr("assigned$" + name) := true)
+ } else {
+ lhs := r
+ }
+ }
+ Comment("assigment to " + lhs.id) ::
+ (rhs match {
+ case rhs@NewRhs(c, initialization) => // x := new C;
+ val (nw, ss) = translateAllocation(rhs.typ, initialization);
+ ss ::: assignOrAssumeEqual(new VarExpr(nw))
+ case rhs: Expression => // x := E;
+ isDefined(rhs) ::: assignOrAssumeEqual(rhs)
+ })
+ case FieldUpdate(lhs@MemberAccess(target, f), rhs) =>
+ val (statements, toStore : Expr) =
+ (rhs match {
+ case rhs @ NewRhs(c, initialization) =>
+ // e.f := new C;
+ val (nw,ss) = translateAllocation(rhs.typ, initialization)
+ (ss, new VarExpr(nw))
+ case rhs : Expression =>
+ // e.f := E;
+ (isDefined(rhs), TrExpr(rhs))
+ });
+ Comment("update field " + f) ::
+ isDefined(target) :::
+ bassert(CanWrite(target, lhs.f), s.pos, "Location might not be writable") ::
+ statements ::: etran.Heap.store(target, lhs.f, toStore) :: bassume(wf(Heap, Mask))
+ case lv @ LocalVar(id, t, const, ghost, rhs) =>
+ val bv = Variable2BVarWhere(lv.v)
+ val isAssignedVar = if (const) new Boogie.BVar("assigned$" + bv.id, Boogie.ClassType(BoolClass)) else null
+ Comment("local " + (if (ghost) "ghost " else "") + (if (const) "const " else "var ") + id) ::
+ BLocal(bv) ::
+ { if (const)
+ // havoc x; var assigned$x: bool; assigned$x := false;
+ Havoc(new Boogie.VarExpr(bv)) ::
+ BLocal(isAssignedVar) :: (new Boogie.VarExpr(isAssignedVar) := false)
+ else
+ List() } :::
+ { rhs match {
+ //update the local, provided a rhs was provided
+ case None => List()
+ case Some(rhs) => translateStatement(Assign(new VariableExpr(lv.v), rhs)) }}
+ case c: Call =>
+ translateCall(c)
+ case Install(obj, lowerBounds, upperBounds) =>
+ Comment("install") ::
+ isDefined(obj) :::
+ bassert(nonNull(obj), s.pos, "The target of the install statement might be null.") ::
+ bassert(isHeld(obj), s.pos, "The lock of the target of the install statement might not be held.") ::
+ // assert CanWrite(obj.mu); assume lowerbounds < obj.mu < upperBounds;
+ UpdateMu(obj, false, lowerBounds, upperBounds, ErrorMessage(s.pos, "Install might fail."))
+ case Share(obj, lowerBounds, upperBounds) =>
+ val (preShareMaskV, preShareMask) = Boogie.NewBVar("preShareMask", tmask, true)
+ Comment("share") ::
+ // remember the mask immediately before the share
+ BLocal(preShareMaskV) :: Boogie.Assign(preShareMask, etran.Mask) ::
+ isDefined(obj) :::
+ bassert(nonNull(obj), s.pos, "The target of the share statement might be null.") ::
+ UpdateMu(obj, true, lowerBounds, upperBounds, ErrorMessage(s.pos, "Share might fail.")) :::
+ bassume(!isHeld(obj) && ! isRdHeld(obj)) :: // follows from o.mu==lockbottom
+ // no permission to o.held
+ etran.SetNoPermission(etran.Tr(obj), "held", etran.Mask) ::
+ // exhale the monitor invariant (using the current state as the old state)
+ ExhaleInvariants(obj, false, ErrorMessage(s.pos, "Monitor invariant might not hold."), etran.UseCurrentAsOld()) :::
+ // assume a seen state is the one right before the share
+ bassume(LastSeenHeap(etran.Heap.select(obj, "mu"), etran.Heap.select(obj, "held")) ==@ etran.Heap) ::
+ bassume(LastSeenMask(etran.Heap.select(obj, "mu"), etran.Heap.select(obj, "held")) ==@ preShareMask)
+ case Unshare(obj) =>
+ val (heldV, held) = Boogie.NewBVar("held", Boogie.NamedType("int"), true)
+ val o = TrExpr(obj)
+ Comment("unshare") ::
+ isDefined(obj) :::
+ bassert(nonNull(o), s.pos, "The target of the unshare statement might be null.") ::
+ bassert(CanWrite(o, "mu"), s.pos, "The mu field of the target of the unshare statement might not be writable.") ::
+ bassert(CanWrite(o, "held"), s.pos, "The held field of the target of the unshare statement might not be writable.") ::
+ bassert(isShared(o), s.pos, "The target of the unshare statement might not be shared.") ::
+ bassert(isHeld(o), s.pos, "The target of the unshare statement might not be locked by the current thread.") :: // locked or read-locked
+ etran.Heap.store(o, "mu", bLockBottom) ::
+ // havoc o.held where 0<=o.held
+ BLocal(heldV) :: Boogie.Havoc(held) :: bassume(held <= 0) ::
+ etran.Heap.store(o, "held", held) ::
+ // set the permission of o.held to 0
+ etran.SetNoPermission(o, "held", etran.Mask) ::
+ // set o.rdheld to false
+ etran.Heap.store(o, "rdheld", false)
+ case Acquire(obj) =>
+ Comment("acquire") ::
+ isDefined(obj) :::
+ bassert(nonNull(TrExpr(obj)), s.pos, "The target of the acquire statement might be null.") ::
+ TrAcquire(s, obj)
+ case Release(obj) =>
+ Comment("release") ::
+ isDefined(obj) :::
+ bassert(nonNull(TrExpr(obj)), s.pos, "The target of the release statement might be null.") ::
+ TrRelease(s, obj)
+ case Lock(e, body, readonly) =>
+ val objV = new Variable("lock", new Type(e.typ))
+ val obj = new VariableExpr(objV)
+ val sname = if (readonly) "rd lock" else "lock"
+ val o = TrExpr(obj)
+ Comment(sname) ::
+ isDefined(e) :::
+ BLocal(Variable2BVar(objV)) :: (o := TrExpr(e)) ::
+ bassert(nonNull(o), s.pos, "The target of the " + sname + " statement might be null.") ::
+ { if (readonly) {
+ TrRdAcquire(s, obj) :::
+ translateStatement(body) :::
+ TrRdRelease(s, obj)
+ } else {
+ TrAcquire(s, obj) :::
+ translateStatement(body) :::
+ TrRelease(s, obj)
+ }
+ }
+ case RdAcquire(obj) =>
+ Comment("rd acquire") ::
+ isDefined(obj) :::
+ bassert(nonNull(TrExpr(obj)), s.pos, "The target of the read-acquire statement might be null.") ::
+ TrRdAcquire(s, obj)
+ case rdrelease@RdRelease(obj) =>
+ Comment("rd release") ::
+ isDefined(obj) :::
+ bassert(nonNull(TrExpr(obj)), obj.pos, "The target of the read-release statement might be null.") ::
+ TrRdRelease(s, obj)
+ case downgrade@Downgrade(obj) =>
+ val o = TrExpr(obj);
+ val prevHeapV = new Boogie.BVar("prevHeap", theap, true)
+ Comment("downgrade") ::
+ isDefined(obj) :::
+ bassert(nonNull(o), s.pos, "The target of the downgrade statement might be null.") ::
+ bassert(isHeld(o), s.pos, "The lock of the target of the downgrade statement might not be held by the current thread.") ::
+ bassert(! isRdHeld(o), s.pos, "The current thread might hold the read lock.") ::
+ ExhaleInvariants(obj, false, ErrorMessage(downgrade.pos, "Monitor invariant might not hold.")) :::
+ BLocal(prevHeapV) ::
+ InhaleInvariants(obj, true) :::
+ bassume(etran.Heap ==@ new Boogie.VarExpr(prevHeapV)) ::
+ etran.Heap.store(o, "rdheld", true)
+ case Free(obj) =>
+ val o = TrExpr(obj);
+ isDefined(obj) :::
+ bassert(nonNull(o), s.pos, "The target of the free statement might be null.") ::
+ (for (f <- obj.typ.Fields ++ RootClass.MentionableFields) yield
+ bassert(CanWrite(o, f.FullName), s.pos, "The field " + f.id + " of the target of the free statement might not be writable.")) :::
+ (for (f <- obj.typ.Fields ++ RootClass.MentionableFields) yield
+ etran.SetNoPermission(o, f.FullName, etran.Mask))
+ // probably need to havoc all the fields! Do we check enough?
+ case fold@Fold(acc@Access(pred@MemberAccess(e, f), fraction)) =>
+ val o = TrExpr(e);
+ var definition = if(fraction.isDefined) FractionOf(SubstThis(DefinitionOf(pred.predicate), e), fraction.get) else SubstThis(DefinitionOf(pred.predicate), e);
+ Comment("fold") ::
+ isDefined(e) :::
+ bassert(nonNull(o), s.pos, "The target of the fold statement might be null.") ::
+ (if(fraction.isDefined) isDefined(fraction.get) :::
+ bassert(0 <= etran.Tr(fraction.get), s.pos, "Fraction might be negative.") ::
+ bassert(etran.Tr(fraction.get) <= 100, s.pos, "Fraction might be larger than 100.") :: Nil else Nil) :::
+ // remove the definition from the current state, and replace by predicate itself
+ Exhale(List((definition, ErrorMessage(s.pos, "Fold might fail because the definition of " + pred.predicate.FullName + " does not hold."))), "fold") :::
+ Inhale(List(acc), "fold") :::
+ etran.Heap.store(o, pred.predicate.FullName, etran.Heap) :: // Is this necessary?
+ bassume(wf(etran.Heap, etran.Mask))
+ case fld@Fold(acc@RdAccess(pred@MemberAccess(e, f), nbEpsilons)) =>
+ val o = TrExpr(e);
+ var (definition, checkEpsilons) = nbEpsilons match {
+ case None => (EpsilonsOf(SubstThis(pred.predicate.definition, e), IntLiteral(1)), Nil)
+ case Some(None) => throw new Exception("Not supported yet!");
+ case Some(Some(i)) => (EpsilonsOf(SubstThis(DefinitionOf(pred.predicate), e), i), isDefined(i) ::: bassert(Boogie.IntLiteral(0) <= i, s.pos, "Number of epsilons might be negative.") :: Nil)
+ }
+ Comment("fold") ::
+ isDefined(e) :::
+ bassert(nonNull(o), s.pos, "The target of the fold statement might be null.") ::
+ checkEpsilons :::
+ Exhale(List((definition, ErrorMessage(fld.pos, "Fold might fail because the definition of " + pred.predicate.FullName + " does not hold."))), "fold") :::
+ Inhale(List(acc), "fold") :::
+ etran.Heap.store(e, pred.predicate.FullName, etran.Heap) ::
+ bassume(wf(etran.Heap, etran.Mask))
+ case unfld@Unfold(acc@Access(pred@MemberAccess(e, f), fraction)) =>
+ val o = TrExpr(e);
+ var definition = if(fraction.isDefined) FractionOf(SubstThis(DefinitionOf(pred.predicate), e), fraction.get) else SubstThis(DefinitionOf(pred.predicate), e);
+ Comment("unfold") ::
+ isDefined(e) :::
+ bassert(nonNull(o), s.pos, "The target of the fold statement might be null.") ::
+ (if(fraction.isDefined) isDefined(fraction.get) :::
+ bassert(Boogie.IntLiteral(0) <= fraction.get, s.pos, "Fraction might be negative.") ::
+ bassert(fraction.get <= 100, s.pos, "Fraction might be larger than 100.") :: Nil else Nil) :::
+ Exhale(List((acc, ErrorMessage(s.pos, "unfold might fail because the predicate " + pred.predicate.FullName + " does not hold."))), "unfold") :::
+ etran.InhaleFrom(List(definition), "unfold", false, etran.Heap.select(o, pred.predicate.FullName))
+ case unfld@Unfold(acc@RdAccess(pred@MemberAccess(e, f), nbEpsilons)) =>
+ val o = TrExpr(e);
+ var (definition, checkEpsilons) = nbEpsilons match {
+ case None => (EpsilonsOf(SubstThis(DefinitionOf(pred.predicate), e), IntLiteral(1)), Nil)
+ case Some(None) => throw new Exception("Not supported yet!");
+ case Some(Some(i)) => (EpsilonsOf(SubstThis(DefinitionOf(pred.predicate), e), i), isDefined(i) ::: bassert(Boogie.IntLiteral(0) <= i, s.pos, "Number of epsilons might be negative.") :: Nil)
+ }
+ Comment("unfold") ::
+ isDefined(e) :::
+ bassert(nonNull(o), s.pos, "The target of the fold statement might be null.") ::
+ checkEpsilons :::
+ Exhale(List((acc, ErrorMessage(s.pos, "Unold might fail because the predicate " + pred.predicate.FullName + " does not hold."))), "unfold") :::
+ etran.InhaleFrom(List(definition), "unfold", false, etran.Heap.select(o, pred.predicate.FullName))
+ case c@CallAsync(declaresLocal, token, obj, id, args) =>
+ val formalThisV = new Variable("this", new Type(c.m.Parent))
+ val formalThis = new VariableExpr(formalThisV)
+ val formalInsV = for (p <- c.m.ins) yield new Variable(p.id, p.t)
+ val formalIns = for (v <- formalInsV) yield new VariableExpr(v)
+
+ val (tokenV,tokenId) = NewBVar("token", tref, true)
+ val (asyncStateV,asyncState) = NewBVar("asyncstate", tint, true)
+ val (preCallMaskV, preCallMask) = NewBVar("preCallMask", tmask, true)
+ val (preCallHeapV, preCallHeap) = NewBVar("preCallHeap", theap, true)
+ val (argsSeqV, argsSeq) = NewBVar("argsSeq", tArgSeq, true)
+ val argsSeqLength = 1 + args.length;
+ Comment("call " + id) ::
+ // declare the local variable, if needed
+ { if (c.local == null)
+ List[Stmt]()
+ else
+ List(BLocal(Variable2BVarWhere(c.local))) } :::
+ // remember the value of the heap and mask
+ BLocal(preCallMaskV) :: (preCallMask := etran.Mask) ::
+ BLocal(preCallHeapV) :: (preCallHeap := etran.Heap) ::
+ BLocal(argsSeqV) ::
+ // introduce formal parameters and pre-state globals
+ (for (v <- formalThisV :: formalInsV) yield BLocal(Variable2BVarWhere(v))) :::
+ // check definedness of arguments
+ isDefined(obj) :::
+ bassert(nonNull(obj), c.pos, "The target of the method call might be null.") ::
+ (args flatMap { e: Expression => isDefined(e)}) :::
+ // assign actual ins to formal ins
+ (formalThis := obj) ::
+ (for ((v,e) <- formalIns zip args) yield (v := e)) :::
+ // insert all arguments in the argument sequence
+ Boogie.AssignMap(argsSeq, 0, formalThis) ::
+ { var i = 1
+ for (v <- formalIns) yield { val r = Boogie.AssignMap(argsSeq, i, v); i += 1; r }
+ } :::
+ // exhale preconditions
+ Exhale(Preconditions(c.m.spec) map
+ (p => SubstThisAndVars(p, formalThis, c.m.ins, formalIns)) zip (Preconditions(c.m.spec) map { p => ErrorMessage(c.pos, "The precondition at " + p.pos + " might not hold.")}), "precondition") :::
+ // create a new token
+ BLocal(tokenV) :: Havoc(tokenId) :: bassume(nonNull(tokenId)) ::
+ // the following assumes help in proving that the token is fresh
+ bassume(Heap.select(tokenId, "joinable") ==@ 0) ::
+ bassume(new Boogie.MapSelect(Mask, tokenId, "joinable", "perm$N")==@ 0) ::
+ bassume(new Boogie.MapSelect(Mask, tokenId, "joinable", "perm$R")==@ 0) ::
+ etran.IncPermission(tokenId, "joinable", 100) ::
+ // create a fresh value for the joinable field
+ BLocal(asyncStateV) :: Boogie.Havoc(asyncState) :: bassume(asyncState !=@ 0) ::
+ etran.Heap.store(tokenId, "joinable", asyncState) ::
+ // assume the pre call state for the token is the state before inhaling the precondition
+ bassume(CallHeap(asyncState) ==@ preCallHeap) ::
+ bassume(CallMask(asyncState) ==@ preCallMask) ::
+ bassume(CallArgs(asyncState) ==@ argsSeq) ::
+ // assign the returned token to the variable
+ { if (token != null) List(token := tokenId) else List() }
+ case jn@JoinAsync(lhs, token) =>
+ val formalThisV = new Variable("this", new Type(jn.m.Parent))
+ val formalThis = new VariableExpr(formalThisV)
+ val formalInsV = for (p <- jn.m.ins) yield new Variable(p.id, p.t)
+ val formalIns = for (v <- formalInsV) yield new VariableExpr(v)
+ val formalOutsV = for (p <- jn.m.outs) yield new Variable(p.id, p.t)
+ val formalOuts = for (v <- formalOutsV) yield new VariableExpr(v)
+
+ val (argsSeqV, argsSeq) = NewBVar("argsSeq", tArgSeq, true)
+ val (preCallHeapV, preCallHeap) = NewBVar("preCallHeap", theap, true);
+ val (preCallMaskV, preCallMask) = NewBVar("preCallMask", tmask, true);
+ val preGlobals = List(preCallHeap, preCallMask);
+ val postEtran = new ExpressionTranslator(List(etran.Heap, etran.Mask), preGlobals, currentClass);
+ Comment("join async") ::
+ // check that we did not join yet
+ bassert(CanWrite(token, "joinable"), jn.pos, "The joinable field might not be writable.") ::
+ bassert(etran.Heap.select(token, "joinable") !=@ 0, jn.pos, "The joinable field might not be true.") ::
+ // lookup token.joinable
+ BLocal(argsSeqV) :: (argsSeq := CallArgs(etran.Heap.select(token, "joinable"))) ::
+ // check that token is well-defined
+ isDefined(token) :::
+ // retrieve the call's pre-state from token.joinable
+ BLocal(preCallHeapV) :: (preCallHeap := CallHeap(etran.Heap.select(token, "joinable"))) ::
+ BLocal(preCallMaskV) :: (preCallMask := CallMask(etran.Heap.select(token, "joinable"))) ::
+ // introduce locals for the out parameters
+ (for (v <- formalThisV :: formalInsV ::: formalOutsV) yield BLocal(Variable2BVarWhere(v))) :::
+ // initialize the in parameters
+ (formalThis := new MapSelect(argsSeq, 0)) ::
+ { var i = 1
+ (formalIns map { v => val r = (v := new MapSelect(argsSeq, i)); i += 1; r })
+ } :::
+ // havoc formal outs
+ (for (v <- formalOuts) yield Havoc(v)) :::
+ // set joinable to false
+ etran.Heap.store(token, "joinable", 0) ::
+ etran.SetNoPermission(token, "joinable", etran.Mask) ::
+ // inhale postcondition of the call
+ postEtran.Inhale(Postconditions(jn.m.spec) map
+ { p => SubstThisAndVars(p, formalThis, jn.m.ins ++ jn.m.outs, formalIns ++ formalOuts)}, "postcondition", false) :::
+ // assign formal outs to actual outs
+ (for ((v,e) <- lhs zip formalOuts) yield (v :=e))
+ }
+ }
+
+ def translateAllocation(cl: Class, initialization: List[Init]): (Boogie.BVar, List[Boogie.Stmt]) = {
+ val (nw, nwe) = NewBVar("nw", Boogie.ClassType(cl), true)
+ val (ttV,tt) = Boogie.NewTVar("T")
+ val f = new Boogie.BVar("f", FieldType(tt))
+ (nw,
+ Comment("new") ::
+ BLocal(nw) :: Havoc(nwe) ::
+ bassume(nonNull(nwe) && (dtype(nwe) ==@ TrType(cl))) ::
+ bassume(new Boogie.Forall(ttV, f, etran.HasNoPermission(nwe, f.id))) ::
+ // initial values of fields:
+ bassume(etran.Heap.select(nwe, "mu") ==@ bLockBottom) ::
+ bassume(etran.Heap.select(nwe, "held") <= 0) ::
+ bassume(etran.Heap.select(nwe, "rdheld") ==@ false) ::
+ // give access to user-defined fields and special fields:
+ (for (f <- cl.Fields ++ RootClass.MentionableFields) yield
+ etran.IncPermission(nwe, f.FullName, 100)) :::
+ // initialize fields according to the initialization
+ (initialization flatMap { init => isDefined(init.e) ::: etran.Heap.store(nwe, init.f.FullName, init.e) })
+ )
+ }
+
+ def TrAcquire(s: Statement, nonNullObj: Expression) = {
+ val o = TrExpr(nonNullObj);
+ val (lastAcquireVar, lastAcquire) = Boogie.NewBVar("lastAcquire", Boogie.ClassType(IntClass), true)
+ val (lastSeenHeldV, lastSeenHeld) = Boogie.NewBVar("lastSeenHeld", tint, true)
+ val (lastSeenMuV, lastSeenMu) = Boogie.NewBVar("lastSeenMu", tmu, true)
+ bassert(CanRead(o, "mu"), s.pos, "The mu field of the target of the acquire statement might not be readable.") ::
+ bassert(etran.MaxLockIsBelowX(etran.Heap.select(o,"mu")), s.pos, "The mu field of the target of the acquire statement might not be above maxlock.") ::
+ bassume(etran.Heap.select(o,"mu") !=@ bLockBottom) :: // this isn't strictly necessary, it seems; but we might as well include it
+ // remember the state right before releasing
+ BLocal(lastSeenMuV) :: (lastSeenMu := etran.Heap.select(o, "mu")) ::
+ BLocal(lastSeenHeldV) :: Havoc(lastSeenHeld) :: (lastSeenHeld := etran.Heap.select(o, "held")) ::
+ bassume(! isHeld(o) && ! isRdHeld(o)) :: // this assume follows from the previous assert
+ // update the thread's locking state
+ BLocal(lastAcquireVar) :: Havoc(lastAcquire) :: bassume(0 < lastAcquire) ::
+ etran.SetFullPermission(o, "held") ::
+ etran.Heap.store(o, "held", lastAcquire) ::
+ InhaleInvariants(nonNullObj, false, etran.WhereOldIs(LastSeenHeap(lastSeenMu, lastSeenHeld), LastSeenMask(lastSeenMu, lastSeenHeld))) :::
+ // remember values of Heap/Mask globals (for proving history constraint at release)
+ bassume(AcquireHeap(lastAcquire) ==@ etran.Heap) ::
+ bassume(AcquireMask(lastAcquire) ==@ etran.Mask)
+ }
+ def TrRelease(s: Statement, nonNullObj: Expression) = {
+ val (heldV, held) = Boogie.NewBVar("held", tint, true)
+ val (prevLmV, prevLm) = Boogie.NewBVar("prevLM", tref, true)
+ val (preReleaseMaskV, preReleaseMask) = NewBVar("preReleaseMask", tmask, true)
+ val (preReleaseHeapV, preReleaseHeap) = NewBVar("preReleaseHeap", theap, true)
+ val o = TrExpr(nonNullObj);
+ BLocal(preReleaseMaskV) :: (preReleaseMask := etran.Mask) ::
+ BLocal(preReleaseHeapV) :: (preReleaseHeap := etran.Heap) ::
+ bassert(CanWrite(o, "held"), s.pos, "The held field of the target of the release statement might not be writable.") ::
+ bassert(isHeld(o), s.pos, "The target of the release statement might be not be locked by the current thread.") ::
+ bassert(!isRdHeld(o), s.pos, "Release might fail because the current thread might hold the read lock.") ::
+ ExhaleInvariants(nonNullObj, false, ErrorMessage(s.pos, "Monitor invariant might hot hold."), etran.WhereOldIs(AcquireHeap(etran.Heap.select(o, "held")), AcquireMask(etran.Heap.select(o, "held")))) :::
+ // havoc o.held where 0<=o.held
+ BLocal(heldV) :: Havoc(held) :: bassume(held <= 0) ::
+ etran.Heap.store(o, "held", held) ::
+ etran.SetNoPermission(o, "held", etran.Mask) ::
+ // assume a seen state is the one right before the share
+ bassume(LastSeenHeap(etran.Heap.select(o, "mu"), held) ==@ preReleaseHeap) ::
+ bassume(LastSeenMask(etran.Heap.select(o, "mu"), held) ==@ preReleaseMask)
+ }
+ def TrRdAcquire(s: Statement, nonNullObj: Expression) = {
+ val (heldV, held) = Boogie.NewBVar("held", tint, true)
+ val o = TrExpr(nonNullObj)
+ bassert(CanRead(o, "mu"), s.pos, "The mu field of the target of the read-acquire statement might not be readable.") ::
+ bassert(etran.MaxLockIsBelowX(etran.Heap.select(o, "mu")), s.pos, "The mu field of the target of the read-acquire statement might not be above maxlock.") ::
+ bassume(etran.Heap.select(o,"mu") !=@ bLockBottom) :: // this isn't strictly necessary, it seems; but we might as well include it
+ bassume(! isHeld(o) && ! isRdHeld(o)) ::
+ BLocal(heldV) :: Havoc(held) :: bassume(held <= 0) ::
+ etran.Heap.store(o, "held", held) ::
+ etran.Heap.store(o, "rdheld", true) ::
+ InhaleInvariants(nonNullObj, true)
+ }
+ def TrRdRelease(s: Statement, nonNullObj: Expression) = {
+ val (heldV, held) = Boogie.NewBVar("held", tint, true)
+ val o = TrExpr(nonNullObj);
+ bassert(isRdHeld(o), s.pos, "The current thread might not hold the read-lock of the object being released.") ::
+ ExhaleInvariants(nonNullObj, true, ErrorMessage(s.pos, "Monitor invariant might not hold.")) :::
+ BLocal(heldV) :: Havoc(held) :: bassume(held <= 0) ::
+ etran.Heap.store(o, "held", held) ::
+ etran.Heap.store(o, "rdheld", false)
+ }
+
+ def translateCall(c: Call): List[Stmt] = {
+ val obj = c.obj;
+ val lhs = c.lhs;
+ val id = c.id;
+ val args = c.args;
+ val formalThisV = new Variable("this", new Type(c.m.Parent))
+ val formalThis = new VariableExpr(formalThisV)
+ val formalInsV = for (p <- c.m.ins) yield new Variable(p.id, p.t)
+ val formalIns = for (v <- formalInsV) yield new VariableExpr(v)
+ val formalOutsV = for (p <- c.m.outs) yield new Variable(p.id, p.t)
+ val formalOuts = for (v <- formalOutsV) yield new VariableExpr(v)
+ val preGlobals = etran.FreshGlobals("call")
+ val postEtran = etran.FromPreGlobals(preGlobals)
+ Comment("call " + id) ::
+ // introduce formal parameters and pre-state globals
+ (for (v <- formalThisV :: formalInsV ::: formalOutsV) yield BLocal(Variable2BVarWhere(v))) :::
+ (for (v <- preGlobals) yield BLocal(v)) :::
+ // remember values of globals
+ (for ((o,g) <- preGlobals zip etran.Globals) yield (new Boogie.VarExpr(o) := g)) :::
+ // check definedness of arguments
+ isDefined(obj) :::
+ bassert(nonNull(obj), c.pos, "The target of the method call might be null.") ::
+ (args flatMap { e: Expression => isDefined(e)}) :::
+ // assign actual ins to formal ins
+ (formalThis := obj) ::
+ (for ((v,e) <- formalIns zip args) yield (v := e)) :::
+ // exhale preconditions
+ Exhale(Preconditions(c.m.spec) map
+ (p => SubstThisAndVars(p, formalThis, c.m.ins, formalIns)) zip (Preconditions(c.m.spec) map { p => ErrorMessage(c.pos, "The precondition at " + p.pos + " might not hold.")}), "precondition") :::
+ // havoc formal outs
+ (for (v <- formalOuts) yield Havoc(v)) :::
+ // havoc lockchanges
+ LockHavoc(for (e <- LockChanges(c.m.spec) map (p => SubstThisAndVars(p, formalThis, c.m.ins, formalIns))) yield etran.Tr(e), postEtran) :::
+ // inhale postconditions (using the state before the call as the "old" state)
+ postEtran.Inhale(Postconditions(c.m.spec) map
+ (p => SubstThisAndVars(p, formalThis, c.m.ins ++ c.m.outs, formalIns ++ formalOuts)) , "postcondition", false) :::
+ // assign formal outs to actual outs
+ (for ((v,e) <- lhs zip formalOuts) yield (v :=e))
+ }
+
+ def translateWhile(w: WhileStmt): List[Stmt] = {
+ val guard = w.guard;
+ val invs = w.invs;
+ val lkch = w. lkch;
+ val body = w.body;
+
+ val preLoopGlobals = etran.FreshGlobals("while")
+ val loopEtran = etran.FromPreGlobals(preLoopGlobals)
+ val iterStartGlobals = etran.FreshGlobals("iterStart")
+ val iterStartEtran = etran.FromPreGlobals(iterStartGlobals)
+ val saveLocalsV = for (v <- w.LoopTargetsList) yield new Variable(v.id, v.t)
+ val iterStartLocalsV = for (v <- w.LoopTargetsList) yield new Variable(v.id, v.t)
+ val lkchOld = lkch map (e => SubstVars(e, w.LoopTargetsList,
+ for (v <- saveLocalsV) yield new VariableExpr(v)))
+ val lkchIterStart = lkch map (e => SubstVars(e, w.LoopTargetsList,
+ for (v <- iterStartLocalsV) yield new VariableExpr(v)))
+ 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));
+ Comment("while") ::
+ // save globals
+ (for (v <- preLoopGlobals) yield BLocal(v)) :::
+ (loopEtran.oldEtran.Heap := loopEtran.Heap) ::
+ (loopEtran.oldEtran.Mask := loopEtran.Mask) :: // oldMask is not actually used below
+ // check invariant on entry to the loop
+ Exhale(invs map { inv => (inv, ErrorMessage(inv.pos, "The loop invariant might not hold on entry to the loop."))}, "loop invariant, initially") :::
+ // save values of local-variable loop targets
+ (for (sv <- saveLocalsV) yield BLocal(Variable2BVarWhere(sv))) :::
+ (for ((v,sv) <- w.LoopTargetsList zip saveLocalsV) yield
+ (new VariableExpr(sv) := new VariableExpr(v))) :::
+ // havoc local-variable loop targets
+ (w.LoopTargets :\ List[Boogie.Stmt]()) ( (v,vars) => (v match {
+ case v: ImmutableVariable => Boogie.Havoc(Boogie.VarExpr("assigned$" + v.id))
+ case _ => Boogie.Havoc(Boogie.VarExpr(v.UniqueName)) }) :: vars) :::
+ Boogie.If(null,
+ // 1. CHECK DEFINEDNESS OF INVARIANT
+ Comment("check loop invariant definedness") ::
+ //(w.LoopTargets.toList map { v: Variable => Boogie.Havoc(Boogie.VarExpr(v.id)) }) :::
+ Boogie.Havoc(etran.Heap) :: Boogie.Assign(etran.Mask, ZeroMask) ::
+ InhaleWithChecking(invs, "loop invariant definedness") :::
+ bassume(false)
+ , Boogie.If(null,
+ // 2. CHECK LOOP BODY
+ // Renew Heap and Mask: set Mask to ZeroMask, and havoc Heap everywhere except
+ // at {old(local),local}.{held,rdheld}
+ Havoc(etran.Heap) :: (etran.Mask := ZeroMask) ::
+ Inhale(invs, "loop invariant, body") :::
+ // this is the state at the beginning of the loop iteration; save these values
+ (for (v <- iterStartGlobals) yield BLocal(v)) :::
+ (iterStartEtran.oldEtran.Heap := iterStartEtran.Heap) ::
+ (iterStartEtran.oldEtran.Mask := iterStartEtran.Mask) :: // oldMask is not actually used below
+ (for (isv <- iterStartLocalsV) yield BLocal(Variable2BVarWhere(isv))) :::
+ (for ((v,isv) <- w.LoopTargetsList zip iterStartLocalsV) yield
+ (new VariableExpr(isv) := new VariableExpr(v))) :::
+ // evaluate the guard
+ isDefined(guard) ::: List(bassume(guard)) :::
+ translateStatement(body) :::
+ // check invariant
+ Exhale(invs map { inv => (inv, ErrorMessage(w.pos, "The loop invariant at " + inv.pos + " might not be preserved by the loop."))}, "loop invariant, maintained") :::
+ isLeaking(w.pos, "The loop might leak refereces.") :::
+ // enforce lockchange
+ (NumberOfLocksHeldIsInvariant(iterStartLocks, newLocks, iterStartEtran) map { e: Boogie.Expr => bassert(e, w.pos, "The loop might lock/unlock more than the changelock clause allows.") }) :::
+ bassume(false),
+ // 3. AFTER LOOP
+ LockHavoc(oldLocks ++ newLocks, loopEtran) :::
+ (NumberOfLocksHeldIsInvariant(oldLocks, newLocks, loopEtran) map bassume) :::
+ Inhale(invs, "loop invariant, after loop") :::
+ bassume(!guard)))
+ }
+
+ def UpdateMu(o: Expr, allowOnlyFromBottom: boolean,
+ lowerBounds: List[Expression], upperBounds: List[Expression], error: ErrorMessage): List[Stmt] = {
+ def BoundIsNullObject(b: Expression): Boogie.Expr = {
+ if (b.typ.IsMu) false else b ==@ bnull
+ }
+ def MuValue(b: Expression): Expr = {
+ if (b.typ.IsMu) b else etran.Heap.select(b, "mu")
+ }
+ def Below(a: Expr, b: Expr) = {
+ new FunctionApp("MuBelow", a, b)
+ }
+ val (muV, mu) = Boogie.NewBVar("mu", Boogie.NamedType("Mu"), true)
+ // check that bounds are well-defined
+ ((lowerBounds ++ upperBounds) flatMap { bound => isDefined(bound)}) :::
+ // check that we have full access to mu
+ bassert(CanWrite(o, "mu"), error.pos, error.message + " The mu field of the target might not be writable.") ::
+ // ...and that mu starts off as lockbottom, if desired
+ (if (allowOnlyFromBottom)
+ List(bassert(etran.Heap.select(o,"mu") ==@ bLockBottom,
+ error.pos, error.message + " The object may already be shared (i.e., mu may not be LockBottom)"))
+ else
+ List()) :::
+ // check for each bound that if it is a non-null object, then its mu field is readable
+ (for (bound <- lowerBounds ++ upperBounds if !bound.typ.IsMu) yield
+ bassert((bound ==@ bnull) || CanRead(bound, "mu"), bound.pos, "The mu field of bound at " + bound.pos + " might not be readable." )) :::
+ // check that each lower bound is smaller than each upper bound
+ (for (lb <- lowerBounds; ub <- upperBounds) yield
+ bassert( (etran.ShaveOffOld(lb), etran.ShaveOffOld(ub)) match {
+ case ((MaxLockLiteral(),o0), (MaxLockLiteral(),o1)) =>
+ if (o0 == o1)
+ false
+ else
+ etran.TemporalMaxLockComparison(etran.ChooseEtran(o0), etran.ChooseEtran(o1))
+ case ((MaxLockLiteral(),o), _) => etran.ChooseEtran(o).MaxLockIsBelowX(MuValue(ub))
+ case (_, (MaxLockLiteral(),o)) => etran.ChooseEtran(o).MaxLockIsAboveX(MuValue(lb))
+ case _ => BoundIsNullObject(lb) ||
+ BoundIsNullObject(ub) ||
+ Below(MuValue(lb), MuValue(ub)) }, lb.pos, "The lower bound at " + lb.pos + " might not be smaller than the upper bound at " + ub.pos + ".")) :::
+ // havoc o.mu
+ BLocal(muV) :: Havoc(mu) :: bassume(mu !=@ bLockBottom) ::
+ // assume that o.mu is between the given bounds (or above maxlock if no bounds are given)
+ (if (lowerBounds == Nil && upperBounds == Nil) {
+ // assume maxlock << o.mu
+ List(bassume(etran.MaxLockIsBelowX(mu)))
+ } else {
+ (for (lb <- lowerBounds) yield
+ // assume lb << o.mu
+ bassume(
+ if (etran.IsMaxLockLit(lb)) {
+ val (f,o) = etran.ShaveOffOld(lb)
+ etran.ChooseEtran(o).MaxLockIsBelowX(mu)
+ } else
+ (BoundIsNullObject(lb) || Below(MuValue(lb), mu)))) :::
+ (for (ub <- upperBounds) yield
+ // assume o.mu << ub
+ bassume(
+ if (etran.IsMaxLockLit(ub)) {
+ val (f,o) = etran.ShaveOffOld(ub)
+ etran.ChooseEtran(o).MaxLockIsAboveX(mu)
+ } else
+ (BoundIsNullObject(ub) || Below(mu, MuValue(ub)))))
+ }) :::
+ // store the mu field
+ etran.Heap.store(o, "mu", mu)
+ }
+
+ def isLeaking(pos: Position, msg: String): List[Boogie.Stmt] = {
+ if(checkLeaks) {
+ var o = Boogie.VarExpr("$o");
+ var f = "$f";
+ val (ttV,tt) = Boogie.NewTVar("T")
+ List(
+ bassert(new Boogie.Forall(
+ 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))
+ ), pos, msg)
+ )
+ } else {
+ Nil
+ }
+ }
+
+ def LockFrame(lkch: List[Expression], etran: ExpressionTranslator) =
+ LocksUnchanged(for (l <- lkch) yield etran.Tr(l), etran)
+ def LocksUnchanged(exceptions: List[Boogie.Expr], etran: ExpressionTranslator) = {
+ val (lkV, lk) = Boogie.NewBVar("lk", tref, true)
+ val b: Boogie.Expr = false
+ new Boogie.Forall(List(lkV),
+ List(etran.Heap.select(lk, "held"), etran.Heap.select(lk, "rdheld")),
+ (((0 < Boogie.MapSelect(etran.Heap, lk, "held")) ==@
+ (0 < Boogie.MapSelect(etran.oldEtran.Heap, lk, "held"))) &&
+ (Boogie.MapSelect(etran.Heap, lk, "rdheld") ==@
+ Boogie.MapSelect(etran.oldEtran.Heap, lk, "rdheld"))) ||
+ ((exceptions :\ b) ((e,ll) => ll || (lk ==@ e))))
+ }
+ def LockHavoc(locks: List[Boogie.Expr], etran: ExpressionTranslator) = {
+ val (heldV, held) = NewBVar("isHeld", Boogie.ClassType(IntClass), true)
+ val (rdheldV, rdheld) = NewBVar("isRdHeld", Boogie.ClassType(BoolClass), true)
+ BLocal(heldV) :: BLocal(rdheldV) ::
+ List.flatten (for (o <- locks) yield { // todo: somewhere we should worry about Df(l)
+ Havoc(held) :: Havoc(rdheld) ::
+ bassume(rdheld ==> (0 < held)) ::
+ MapUpdate(etran.Heap, o, "held", held) ::
+ MapUpdate(etran.Heap, o, "rdheld", rdheld) })
+ }
+ def NumberOfLocksHeldIsInvariant(oldLocks: List[Boogie.Expr], newLocks: List[Boogie.Expr],
+ etran: ExpressionTranslator) = {
+ List.flatten (for ((o,n) <- oldLocks zip newLocks) yield {
+ // oo.held == nn.held && oo.rdheld == nn.rdheld
+ (((0 < Boogie.MapSelect(etran.oldEtran.Heap, o, "held")) ==@
+ (0 < Boogie.MapSelect(etran.Heap, n, "held"))) &&
+ (Boogie.MapSelect(etran.oldEtran.Heap, o, "rdheld") ==@
+ Boogie.MapSelect(etran.Heap, n, "rdheld"))) ::
+ // no.held == on.held && no.rdheld == on.rdheld
+ (((0 < Boogie.MapSelect(etran.Heap, o, "held")) ==@
+ (0 < Boogie.MapSelect(etran.oldEtran.Heap, n, "held"))) &&
+ (Boogie.MapSelect(etran.Heap, o, "rdheld") ==@
+ Boogie.MapSelect(etran.oldEtran.Heap, n, "rdheld"))) ::
+ // o == n || (oo.held != no.held && (!oo.rdheld || !no.rdheld))
+ ((o ==@ n) ||
+ (((0 < Boogie.MapSelect(etran.oldEtran.Heap, o, "held")) !=@ (0 < Boogie.MapSelect(etran.Heap, o, "held"))) &&
+ ((! Boogie.MapSelect(etran.oldEtran.Heap, o, "rdheld")) ||
+ (! Boogie.MapSelect(etran.Heap, o, "rdheld"))))) ::
+ Nil
+ })
+ }
+
+ implicit def lift(s: Stmt): List[Stmt] = List(s)
+ def isDefined(e: Expression) = etran.isDefined(e)(true)
+ def TrExpr(e: Expression) = etran.Tr(e)
+
+ def InhaleInvariants(obj: Expression, readonly: boolean, tran: ExpressionTranslator) = {
+ val shV = new Variable("sh", new Type(obj.typ))
+ val sh = new VariableExpr(shV)
+ BLocal(Variable2BVar(shV)) :: Boogie.Assign(TrExpr(sh), TrExpr(obj)) ::
+ tran.Inhale(obj.typ.Invariants map
+ (inv => SubstThis(inv.e, sh)) map
+ (inv => (if (readonly) SubstRd(inv) else inv)), "monitor invariant", false)
+ }
+ def ExhaleInvariants(obj: Expression, readonly: boolean, msg: ErrorMessage, tran: ExpressionTranslator) = {
+ val shV = new Variable("sh", new Type(obj.typ))
+ val sh = new VariableExpr(shV)
+ BLocal(Variable2BVar(shV)) :: Boogie.Assign(TrExpr(sh), TrExpr(obj)) ::
+ tran.Exhale(obj.typ.Invariants map
+ (inv => SubstThis(inv.e, sh)) map
+ (inv => (if (readonly) SubstRd(inv) else inv, msg)), "monitor invariant", false)
+ }
+ def InhaleInvariants(obj: Expression, readonly: boolean) = {
+ val shV = new Variable("sh", new Type(obj.typ))
+ val sh = new VariableExpr(shV)
+ BLocal(Variable2BVar(shV)) :: Boogie.Assign(TrExpr(sh), TrExpr(obj)) ::
+ Inhale(obj.typ.Invariants map
+ (inv => SubstThis(inv.e, sh)) map
+ (inv => (if (readonly) SubstRd(inv) else inv)), "monitor invariant")
+ }
+ def ExhaleInvariants(obj: Expression, readonly: boolean, msg: ErrorMessage) = {
+ val shV = new Variable("sh", new Type(obj.typ))
+ val sh = new VariableExpr(shV)
+ BLocal(Variable2BVar(shV)) :: Boogie.Assign(TrExpr(sh), TrExpr(obj)) ::
+ Exhale(obj.typ.Invariants map
+ (inv => SubstThis(inv.e, sh)) map
+ (inv => (if (readonly) SubstRd(inv) else inv, msg)), "monitor invariant")
+ }
+
+ def Inhale(predicates: List[Expression], occasion: String): List[Boogie.Stmt] = etran.Inhale(predicates, occasion, false)
+ def Exhale(predicates: List[(Expression, ErrorMessage)], occasion: String): List[Boogie.Stmt] = etran.Exhale(predicates, occasion, false)
+ def InhaleWithChecking(predicates: List[Expression], occasion: String): List[Boogie.Stmt] = etran.Inhale(predicates, occasion, true)
+ def ExhaleWithChecking(predicates: List[(Expression, ErrorMessage)], occasion: String): List[Boogie.Stmt] = etran.Exhale(predicates, occasion, true)
+
+ def CanRead(obj: Boogie.Expr, field: Boogie.Expr): Boogie.Expr = etran.CanRead(obj, field)
+ def CanWrite(obj: Boogie.Expr, field: Boogie.Expr): Boogie.Expr = etran.CanWrite(obj, field)
+
+
+ /**********************************************************************
+ ***************** EXPRESSIONS *****************
+ **********************************************************************/
+
+class ExpressionTranslator(globals: List[Boogie.Expr], preGlobals: List[Boogie.Expr], currentClass: Class) {
+ import TranslationHelper._
+ import TranslationOptions._
+
+ val Heap = globals(0);
+ val Mask = globals(1);
+ lazy val oldEtran = new ExpressionTranslator(preGlobals, preGlobals, currentClass)
+ var checkTermination = false; // check that heap required by callee is strictly smaller than heap required by caller
+
+ def this(globals: List[Boogie.Expr], cl: Class) = this(globals, globals map (g => Boogie.Old(g)), cl)
+ def this(cl: Class) = this(for ((id,t) <- S_ExpressionTranslator.Globals) yield Boogie.VarExpr(id), cl)
+
+ def Globals = List(Heap, Mask)
+ def ChooseEtran(chooseOld: boolean) = if (chooseOld) oldEtran else this
+ // Create a list of fresh global variables
+ def FreshGlobals(prefix: String) = {
+ new Boogie.BVar(prefix + "Heap", theap, true) ::
+ new Boogie.BVar(prefix + "Mask", tmask, true) ::
+ Nil
+ }
+
+ // Create a new ExpressionTranslator that is a copy of the receiver, but with
+ // preGlobals as the old global variables
+ def FromPreGlobals(preGlobals: List[Boogie.BVar]) = {
+ val g = for ((id,t) <- S_ExpressionTranslator.Globals) yield VarExpr(id)
+ val pg = preGlobals map (g => new VarExpr(g))
+ new ExpressionTranslator(g, pg, currentClass)
+ }
+
+ def UseCurrentAsOld() = {
+ new ExpressionTranslator(globals, globals, currentClass);
+ }
+
+ def WhereOldIs(h: Boogie.Expr, m: Boogie.Expr) = {
+ new ExpressionTranslator(globals, List(h, m), currentClass);
+ }
+
+ /**********************************************************************
+ ***************** TR/DF *****************
+ **********************************************************************/
+
+ def isDefined(e: Expression)(implicit assumption: Expr): List[Boogie.Stmt] = {
+ def prove(goal: Expr, pos: Position, msg: String)(implicit assumption: Expr): Boogie.Assert = {
+ bassert(assumption ==> goal, pos, msg)
+ }
+ e match {
+ case IntLiteral(n) => Nil
+ case BoolLiteral(b) => Nil
+ case NullLiteral() => Nil
+ case MaxLockLiteral() => Nil
+ case LockBottomLiteral() => Nil
+ case _:ThisExpr => Nil
+ case _:Result => Nil
+ case _:VariableExpr => Nil
+ case fs @ MemberAccess(e, f) =>
+ assert(!fs.isPredicate);
+ isDefined(e) :::
+ prove(nonNull(Tr(e)), e.pos, "Receiver might be null.") ::
+ prove(CanRead(Tr(e), fs.f.FullName), fs.pos, "Location might not be readable.")
+ case _:Access => throw new Exception("acc expression unexpected here")
+ case _:RdAccess => throw new Exception("rd expression unexpected here")
+ case _:AccessAll => throw new Exception("acc expression unexpected here")
+ case _:RdAccessAll => throw new Exception("rd expression unexpected here")
+ case Holds(e) =>
+ isDefined(e)
+ case RdHolds(e) =>
+ isDefined(e)
+ case _: Assigned => Nil
+ case Old(e) =>
+ oldEtran.isDefined(e)
+ case IfThenElse(con, then, els) =>
+ isDefined(con) ::: Boogie.If(Tr(con), isDefined(then), isDefined(els))
+ case Not(e) =>
+ isDefined(e)
+ case func@FunctionApplication(obj, id, args) =>
+ val newGlobals = FreshGlobals("checkPre");
+ val (tmpHeapV, tmpHeap) = Boogie.NewBVar("Heap", theap, true);
+ val (tmpMaskV, tmpMask) = Boogie.NewBVar("Mask", tmask, true);
+ val tmpTranslator = new ExpressionTranslator(List(tmpHeap,tmpMask), currentClass);
+ // check definedness of receiver + arguments
+ (obj :: args flatMap { arg => isDefined(arg) }) :::
+ // check that receiver is not null
+ List(prove(nonNull(Tr(obj)), obj.pos, "Receiver might be null.")) :::
+ // check precondition of the function by exhaling the precondition in tmpHeap/tmpMask
+ Comment("check precondition of call") ::
+ bassume(assumption) ::
+ BLocal(tmpHeapV) :: (tmpHeap := Heap) ::
+ BLocal(tmpMaskV) :: (tmpMask := Mask) :::
+ tmpTranslator.Exhale(Preconditions(func.f.spec) map { pre=> (SubstThisAndVars(pre, obj, func.f.ins, args), ErrorMessage(func.pos, "Precondition at " + pre.pos + " might not hold."))},
+ "function call",
+ false) :::
+ // size of the heap of callee must be strictly smaller than size of the heap of the caller
+ (if(checkTermination) { List(prove(NonEmptyMask(tmpMask), func.pos, "The heap of the callee might not be strictly smaller than the heap of the caller.")) } else Nil)
+ case unfolding@Unfolding(access, e) =>
+ val (checks, predicate, definition, from) = access match {
+ case acc@Access(pred@MemberAccess(obj, f), perm) =>
+ val receiverOk = isDefined(obj) ::: prove(nonNull(Tr(obj)), obj.pos, "Receiver might be null.");
+ val body = SubstThis(DefinitionOf(pred.predicate), obj);
+ perm match {
+ case None => (receiverOk, acc, body, Heap.select(Tr(obj), pred.predicate.FullName))
+ case Some(fraction) => (receiverOk ::: isDefined(fraction) ::: prove(0 <= Tr(fraction), fraction.pos, "Fraction might be negative") :: prove(Tr(fraction) <= 100, fraction.pos, "Fraction might exceed 100."), acc, FractionOf(body, fraction), Heap.select(Tr(obj), pred.predicate.FullName))
+ }
+ case acc@RdAccess(pred@MemberAccess(obj, f), perm) =>
+ val receiverOk = isDefined(obj) ::: prove(nonNull(Tr(obj)), obj.pos, "Receiver might be null.");
+ val body = SubstThis(DefinitionOf(pred.predicate), obj);
+ perm match {
+ case None => (receiverOk, acc, EpsilonsOf(body, IntLiteral(1)), Heap.select(Tr(obj), pred.predicate.FullName))
+ case Some(None) => assert(false); (null, null, null, Heap.select(Tr(obj), pred.predicate.FullName))
+ case Some(Some(epsilons)) => (receiverOk ::: isDefined(epsilons) ::: prove(0 <= Tr(epsilons), epsilons.pos, "Number of epsilons might be negative"), acc, EpsilonsOf(body, epsilons), Heap.select(Tr(obj), pred.predicate.FullName))
+ }
+ }
+ val newGlobals = FreshGlobals("checkPre");
+ val (tmpHeapV, tmpHeap) = Boogie.NewBVar("Heap", theap, true);
+ val (tmpMaskV, tmpMask) = Boogie.NewBVar("Mask", tmask, true);
+ val tmpTranslator = new ExpressionTranslator(List(tmpHeap, tmpMask), currentClass);
+ Comment("unfolding") ::
+ // check definedness
+ checks :::
+ // copy state into temporary variables
+ BLocal(tmpHeapV) :: Boogie.Assign(tmpHeap, Heap) ::
+ BLocal(tmpMaskV) :: Boogie.Assign(tmpMask, Mask) ::
+ // exhale the predicate
+ tmpTranslator.Exhale(List((predicate, ErrorMessage(unfolding.pos, "Unfolding might fail."))), "unfolding", false) :::
+ // inhale the definition of the predicate
+ tmpTranslator.InhaleFrom(List(definition), "unfolding", false, from) :::
+ // check definedness of e in state where the predicate is unfolded
+ tmpTranslator.isDefined(e)
+ case Iff(e0,e1) =>
+ isDefined(e0) ::: isDefined(e1)
+ case Implies(e0,e1) =>
+ isDefined(e0) ::: isDefined(e1)(assumption && Tr(e0))
+ case And(e0,e1) =>
+ isDefined(e0) ::: isDefined(e1)(assumption && Tr(e0))
+ case Or(e0,e1) =>
+ isDefined(e0) ::: isDefined(e1)(assumption && Boogie.UnaryExpr("!", Tr(e0)))
+ case LockBelow(e0,e1) =>
+ var df = isDefined(e0) ::: isDefined(e1);
+ if (e0.typ.IsRef) {
+ df = df ::: List(prove(nonNull(Tr(e0)), e0.pos, "Receiver might be null."), prove(CanRead(Tr(e0),"mu"), e0.pos, "The mu field might not be readable."));
+ }
+ if (e1.typ.IsRef) {
+ df = df ::: List(prove(nonNull(Tr(e1)), e1.pos, "Receiver might be null."), prove(CanRead(Tr(e1),"mu"), e1.pos, "The mu field might not be readable."));
+ }
+ df
+ case e: CompareExpr =>
+ isDefined(e.E0) ::: isDefined(e.E1)
+ case Div(e0,e1) =>
+ isDefined(e0) ::: isDefined(e1) :::
+ List(prove(Tr(e1) !=@ 0, e1.pos, "Denominator might be zero."))
+ case Mod(e0,e1) =>
+ isDefined(e0) ::: isDefined(e1) ::: List(prove(Tr(e1) !=@ 0, e1.pos, "Denominator might be zero."))
+ case e: ArithmeticExpr =>
+ isDefined(e.E0) ::: isDefined(e.E1)
+ case q@Forall(i, Range(min, max), e) =>
+ // optimize for range
+ isDefinedForall(q.variables, min, max, e)
+ case q@Forall(i, seq, e) =>
+ var newVars = Nil : List[Variable];
+ for(i <- q.variables) {
+ newVars = newVars + new Variable(i.UniqueName, new Type(IntClass))
+ }
+ isDefinedForall(newVars, IntLiteral(0), Length(seq), SubstVars(e, q.variables, newVars map {newVar => At(seq, new VariableExpr(newVar)) }))
+ case EmptySeq(t) => Nil
+ case ExplicitSeq(es) =>
+ es flatMap { e => isDefined(e) }
+ case Range(min, max) =>
+ isDefined(min) ::: isDefined(max)
+ case Append(e0, e1) =>
+ isDefined(e0) ::: isDefined(e1)
+ case at@At(e0, e1) =>
+ isDefined(e0) ::: isDefined(e1) ::: List(prove(0 <= Tr(e1), at.pos, "Sequence index might be negative."), prove(Tr(e1) < Boogie.FunctionApp("Seq#Length", List(Tr(e0))), at.pos, "Sequence index might be larger than or equal to the length of the sequence."))
+ case Drop(e0, e1) =>
+ isDefined(e0) ::: isDefined(e1) ::: List(prove(0 <= Tr(e1), e.pos, "Cannot drop less than zero elements."), prove(Tr(e1) <= Boogie.FunctionApp("Seq#Length", List(Tr(e0))), e.pos, "Cannot drop more than elements than the length of the sequence."))
+ case Take(e0, e1) =>
+ isDefined(e0) ::: isDefined(e1) ::: List(prove(0 <= Tr(e1), e.pos, "Cannot take less than zero elements."), prove(Tr(e1) <= Boogie.FunctionApp("Seq#Length", List(Tr(e0))), e.pos, "Cannot take more than elements than the length of the sequence."))
+ case Length(e) =>
+ isDefined(e)
+ case Eval(h, e) =>
+ val (evalHeap, evalMask, checks, assumptions) = fromEvalState(h);
+ val evalEtran = new ExpressionTranslator(List(evalHeap, evalMask), currentClass);
+ evalEtran.isDefined(e)
+ }
+ }
+
+ def isDefinedForall(is: List[Variable], min: Expression, max: Expression, e: Expression)(implicit assumption: Expr): List[Stmt] = {
+ var iTmps = Nil: List[Variable];
+ var assumption2 = assumption;
+ for(i <- is) {
+ val iTmp = new Variable(i.UniqueName, new Type(IntClass));
+ iTmps = iTmps + iTmp;
+ assumption2 = assumption2 && (Tr(min)<=VarExpr(iTmp.UniqueName)) && (VarExpr(iTmp.UniqueName) < Tr(max))
+ }
+ // check definedness of the bounds
+ isDefined(min) ::: isDefined(max) :::
+ // introduce a new local iTmp with an arbitrary value
+ (iTmps map { iTmp =>
+ BLocal(Boogie.BVar(iTmp.UniqueName, Boogie.NamedType("int")))
+ }) :::
+ // prove that the body is well-defined for iTmp, provided iTmp lies betweeen min and max
+ isDefined(SubstVars(e, is, iTmps map { iTmp => new VariableExpr(iTmp)}))(assumption2)
+ }
+
+ def Tr(e: Expression): Boogie.Expr = e match {
+ case IntLiteral(n) => n
+ case BoolLiteral(b) => b
+ case NullLiteral() => bnull
+ case MaxLockLiteral() => throw new Exception("maxlock 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 fs @ MemberAccess(e,_) =>
+ assert(! fs.isPredicate);
+ var r = Heap.select(Tr(e), fs.f.FullName);
+ if (fs.f.isInstanceOf[SpecialField] && fs.f.id == "joinable")
+ r !=@ 0 // joinable is encoded as an integer
+ else
+ r
+ case _:Access => throw new Exception("acc expression unexpected here")
+ case _:RdAccess => throw new Exception("rd expression unexpected here")
+ case _:AccessAll => throw new Exception("acc expression unexpected here")
+ case _:RdAccessAll => throw new Exception("rd expression unexpected here")
+ case Holds(e) =>
+ (0 < Heap.select(Tr(e), "held")) &&
+ !Heap.select(Tr(e), "rdheld")
+ case RdHolds(e) =>
+ Heap.select(Tr(e), "rdheld")
+ case a: Assigned =>
+ VarExpr("assigned$" + a.v.UniqueName)
+ case Old(e) =>
+ oldEtran.Tr(e)
+ case IfThenElse(con, then, els) =>
+ Boogie.Ite(Tr(con), Tr(then), Tr(els)) // of type: VarExpr(TrClass(then.typ))
+ case Not(e) =>
+ ! Tr(e)
+ case func@FunctionApplication(obj, id, args) =>
+ FunctionApp("#" + func.f.Parent.id + "." + id, Heap :: Mask :: (obj :: args map { arg => Tr(arg)}))
+ case uf@Unfolding(_, e) =>
+ Tr(e)
+ case Iff(e0,e1) =>
+ Tr(e0) <==> Tr(e1)
+ case Implies(e0,e1) =>
+ Tr(e0) ==> Tr(e1)
+ case And(e0,e1) =>
+ Tr(e0) && Tr(e1)
+ case Or(e0,e1) =>
+ Tr(e0) || Tr(e1)
+ case Eq(e0,e1) =>
+ (ShaveOffOld(e0), ShaveOffOld(e1)) match {
+ case ((MaxLockLiteral(),o0), (MaxLockLiteral(),o1)) =>
+ if (o0 == o1)
+ true
+ else
+ MaxLockPreserved
+ case ((MaxLockLiteral(),o), (fs@MemberAccess(q, "mu"), useOld)) => isHeldInHeap(Tr(q), ChooseEtran(useOld).Heap) && ChooseEtran(o).MaxLockEqualsX(Tr(fs))
+ case ((MaxLockLiteral(),o), _) => ChooseEtran(o).MaxLockEqualsX(Tr(e1))
+ case (_, (MaxLockLiteral(),o)) => ChooseEtran(o).MaxLockEqualsX(Tr(e0))
+ case _ => if(e0.typ.IsSeq) FunctionApp("Seq#Equal", List(Tr(e0), Tr(e1))) else (Tr(e0) ==@ Tr(e1))
+ }
+ case Neq(e0,e1) =>
+ if (IsMaxLockLit(e0) || IsMaxLockLit(e1))
+ Tr(Not(Eq(e0,e1)))
+ else
+ (Tr(e0) !=@ Tr(e1))
+ case Less(e0,e1) =>
+ Tr(e0) < Tr(e1)
+ case AtMost(e0,e1) =>
+ Tr(e0) <= Tr(e1)
+ case AtLeast(e0,e1) =>
+ Tr(e0) >= Tr(e1)
+ case Greater(e0,e1) =>
+ Tr(e0) > Tr(e1)
+ case LockBelow(e0,e1) => {
+ def MuValue(b: Expression): Boogie.Expr =
+ if (b.typ.IsRef) Boogie.MapSelect(Heap, Tr(b), "mu") else Tr(b)
+ (ShaveOffOld(e0), ShaveOffOld(e1)) match {
+ case ((MaxLockLiteral(),o0), (MaxLockLiteral(),o1)) =>
+ if (o0 == o1)
+ false
+ 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)) }
+ }
+ case Plus(e0,e1) =>
+ Tr(e0) + Tr(e1)
+ case Minus(e0,e1) =>
+ Tr(e0) - Tr(e1)
+ case Times(e0,e1) =>
+ Tr(e0) * Tr(e1)
+ case Div(e0,e1) =>
+ Tr(e0) / Tr(e1)
+ case Mod(e0,e1) =>
+ Tr(e0) % Tr(e1)
+ case q@Forall(is, Range(min, max), e) =>
+ // optimize translation for range expressions
+ translateForall(q.variables, min, max, e)
+ case q@Forall(is, seq, e) =>
+ var newVars = Nil : List[Variable];
+ for(i <- q.variables) {
+ newVars = newVars + new Variable(i.UniqueName, new Type(IntClass))
+ }
+ translateForall(newVars, IntLiteral(0), Length(seq), SubstVars(e, q.variables, newVars map {newVar => At(seq, new VariableExpr(newVar)) }))
+ case EmptySeq(t) =>
+ createEmptySeq
+ case ExplicitSeq(es) =>
+ es match {
+ case Nil => createEmptySeq
+ case h :: Nil => createSingletonSeq(Tr(h))
+ case h :: t => createAppendSeq(createSingletonSeq(Tr(h)), Tr(ExplicitSeq(t)))
+ }
+ case Range(min, max) =>
+ createRange(Tr(min), Tr(max))
+ case Append(e0, e1) =>
+ createAppendSeq(Tr(e0), Tr(e1))
+ case at@At(e0, e1) =>
+ FunctionApp("Seq#Index", List(Tr(e0), Tr(e1))) // of type: VarExpr(TrClass(e0.typ.parameters(0)))
+ case Drop(e0, e1) =>
+ Boogie.FunctionApp("Seq#Drop", List(Tr(e0), Tr(e1)))
+ case Take(e0, e1) =>
+ Boogie.FunctionApp("Seq#Take", List(Tr(e0), Tr(e1)))
+ case Length(e) =>
+ Boogie.FunctionApp("Seq#Length", List(Tr(e)))
+ case Eval(h, e) =>
+ val (evalHeap, evalMask, checks, assumptions) = fromEvalState(h);
+ val evalEtran = new ExpressionTranslator(List(evalHeap, evalMask), currentClass);
+ evalEtran.Tr(e)
+ }
+
+ def translateForall(is: List[Variable], min: Expression, max: Expression, e: Expression): Expr = {
+ var assumption = true: Expr;
+ for(i <- is) {
+ assumption = assumption && (Tr(min) <= VarExpr(i.UniqueName) && VarExpr(i.UniqueName) < Tr(max));
+ }
+ new Boogie.Forall(is map { i=> Variable2BVar(i)}, Nil, assumption ==> Tr(e))
+ }
+
+ def ShaveOffOld(e: Expression): (Expression, boolean) = e match {
+ case Old(e) =>
+ val (f,o) = ShaveOffOld(e)
+ (f,true)
+ case _ => (e,false)
+ }
+ def IsMaxLockLit(e: Expression) = {
+ val (f,o) = ShaveOffOld(e)
+ f.isInstanceOf[MaxLockLiteral]
+ }
+
+ /**********************************************************************
+ ***************** INHALE/EXHALE *****************
+ **********************************************************************/
+
+ def Inhale(predicates: List[Expression], occasion: String, check: Boolean): List[Boogie.Stmt] = {
+ val (ihV, ih) = Boogie.NewBVar("inhaleHeap", theap, true)
+ Comment("inhale (" + occasion + ")") ::
+ BLocal(ihV) :: Boogie.Havoc(ih) ::
+ bassume(IsGoodInhaleState(ih, Heap, Mask)) ::
+ List.flatten (for (p <- predicates) yield Inhale(p,ih, check)) :::
+ bassume(IsGoodMask(Mask)) ::
+ bassume(wf(Heap, Mask)) ::
+ Comment("end inhale")
+ }
+
+ def InhaleFrom(predicates: List[Expression], occasion: String, check: Boolean, useHeap: Boogie.Expr): List[Boogie.Stmt] = {
+ val (ihV, ih) = Boogie.NewBVar("inhaleHeap", theap, true)
+ Comment("inhale (" + occasion + ")") ::
+ BLocal(ihV) :: Boogie.Assign(ih, useHeap) ::
+ bassume(IsGoodInhaleState(ih, Heap, Mask)) ::
+ List.flatten (for (p <- predicates) yield Inhale(p,ih, check)) :::
+ bassume(IsGoodMask(Mask)) ::
+ bassume(wf(Heap, Mask)) ::
+ Comment("end inhale")
+ }
+
+ def Inhale(p: Expression, ih: Boogie.Expr, check: Boolean): List[Boogie.Stmt] = p match {
+ case pred@MemberAccess(e, p) if pred.isPredicate =>
+ val tmp = Access(pred, None);
+ tmp.pos = pred.pos;
+ Inhale(tmp, ih, check)
+ case acc@AccessAll(obj, perm) =>
+ obj.typ.Fields flatMap { f =>
+ val ma = MemberAccess(obj, f.id);
+ ma.f = f;
+ ma.pos = acc.pos;
+ val inhalee = Access(ma, perm);
+ inhalee.pos = acc.pos;
+ Inhale(inhalee, ih, check) }
+ case acc@RdAccessAll(obj, perm) =>
+ obj.typ.Fields flatMap { f =>
+ val ma = MemberAccess(obj, f.id);
+ ma.f = f;
+ ma.pos = acc.pos;
+ val inhalee = RdAccess(ma, perm);
+ inhalee.pos = acc.pos;
+ Inhale(inhalee, ih, check) }
+ case acc@Access(e,perm) =>
+ val trE = Tr(e.e)
+ val module = currentClass.module;
+ val memberName = if(e.isPredicate) e.predicate.FullName else e.f.FullName;
+ (if(check) isDefined(e.e)(true)
+ // List(bassert(nonNull(trE), acc.pos, "The target of the acc predicate might be null."))
+ else Nil) :::
+ (perm match {
+ case None => List()
+ case Some(perm) =>
+ (if(check) isDefined(perm)(true) ::: bassert(Boogie.IntLiteral(0)<=Tr(perm), perm.pos, "Fraction might be negative.") ::
+ (if(! e.isPredicate) bassert(Tr(perm) <= Boogie.IntLiteral(100), perm.pos, "Fraction might exceed 100.") :: Nil else Nil) else Nil)
+ }) :::
+ bassume(nonNull(trE)) ::
+ MapUpdate(Heap, trE, memberName, Boogie.MapSelect(ih, trE, memberName)) ::
+ bassume(wf(Heap, Mask)) ::
+ (if(e.isPredicate && e.predicate.Parent.module.equals(currentClass.module)) List(bassume(Boogie.MapSelect(ih, trE, memberName) ==@ Heap)) else Nil) :::
+ (if(e.isPredicate) Nil else List(bassume(TypeInformation(Boogie.MapSelect(Heap, trE, memberName), e.f.typ)))) :::
+ (perm match {
+ case None => IncPermission(trE, memberName, 100)
+ case Some(perm) => IncPermission(trE, memberName, Tr(perm))
+ }) ::
+ bassume(IsGoodMask(Mask)) ::
+ bassume(IsGoodState(Boogie.MapSelect(ih, trE, memberName))) ::
+ bassume(wf(Heap, Mask)) ::
+ bassume(wf(ih, Mask))
+ case rdacc@RdAccess(e,perm) =>
+ val memberName = if(e.isPredicate) e.predicate.FullName else e.f.FullName;
+ val trE = Tr(e.e)
+ val (dfP,p) = perm match {
+ case None => (List(), Boogie.IntLiteral(1))
+ case Some(None) => (List(), null)
+ case Some(Some(p)) => (isDefined(p)(true) ::: bassert(Boogie.IntLiteral(0)<=Tr(p), p.pos, "Number of epsilons might be negative."), Tr(p))
+ }
+ (if(check) { isDefined(e.e)(true) :::
+ // bassert(nonNull(trE), rdacc.pos, "The target of the rd predicate might be null.")
+ dfP } else Nil) :::
+ bassume(nonNull(trE)) ::
+ Boogie.MapUpdate(Heap, trE, memberName,
+ Boogie.MapSelect(ih, trE, memberName)) ::
+ bassume(Boogie.FunctionApp("wf", List(Heap, Mask))) ::
+ (if(e.isPredicate && e.predicate.Parent.module.equals(currentClass.module)) List(bassume(Boogie.MapSelect(ih, trE, memberName) ==@ Heap)) else Nil) :::
+ (if(e.isPredicate) Nil else List(bassume(TypeInformation(Boogie.MapSelect(Heap, trE, memberName), e.f.typ)))) :::
+ IncPermissionEpsilon(trE, memberName, p) ::
+ bassume(IsGoodMask(Mask)) ::
+ bassume(IsGoodState(Boogie.MapSelect(ih, trE, memberName))) ::
+ bassume(wf(Heap, Mask)) ::
+ bassume(wf(ih, Mask))
+ case Implies(e0,e1) =>
+ (if(check) isDefined(e0)(true) else Nil) :::
+ Boogie.If(Tr(e0), Inhale(e1, ih, check), Nil)
+ case IfThenElse(con, then, els) =>
+ (if(check) isDefined(con)(true) else Nil) :::
+ Boogie.If(Tr(con), Inhale(then, ih, check), Inhale(els, ih, check))
+ case And(e0,e1) =>
+ Inhale(e0, ih, check) ::: Inhale(e1, ih, check)
+ case holds@Holds(e) =>
+ val trE = Tr(e);
+ (if(check) isDefined(e)(true) :::
+ List(bassert(nonNull(trE), holds.pos, "The target of the holds predicate might be null.")) else Nil) :::
+ IncPermission(trE, "held", 100) :::
+ bassume(IsGoodMask(Mask)) ::
+ bassume(IsGoodState(Boogie.MapSelect(ih, trE, "held"))) ::
+ bassume(wf(Heap, Mask)) ::
+ bassume(wf(ih, Mask)) ::
+ Boogie.MapUpdate(Heap, trE, "held",
+ Boogie.MapSelect(ih, trE, "held")) ::
+ bassume(0 < Boogie.MapSelect(ih, trE, "held")) ::
+ bassume(! Boogie.MapSelect(ih, trE, "rdheld")) ::
+ bassume(wf(Heap, Mask)) ::
+ bassume(IsGoodMask(Mask)) ::
+ bassume(IsGoodState(Boogie.MapSelect(ih, trE, "held"))) ::
+ bassume(wf(Heap, Mask)) ::
+ bassume(wf(ih, Mask))
+ case Eval(h, e) =>
+ val (evalHeap, evalMask, checks, proofOrAssume) = fromEvalState(h);
+ val preGlobals = etran.FreshGlobals("eval")
+ val preEtran = new ExpressionTranslator(preGlobals map (v => new Boogie.VarExpr(v)), currentClass)
+ BLocal(preGlobals(0)) :: BLocal(preGlobals(1)) ::
+ (new VarExpr(preGlobals(1)) := ZeroMask) ::
+ // Should we start from ZeroMask instead of an arbitrary mask? In that case, assume submask(preEtran.Mask, evalMask); at the end!
+ (if(check) checks else Nil) :::
+ // havoc the held field when inhaling eval(o.release, ...)
+ (if(h.isInstanceOf[ReleaseState]) {
+ val (freshHeldV, freshHeld) = NewBVar("freshHeld", tint, true);
+ val obj = Tr(h.target());
+ List(BLocal(freshHeldV), bassume((0<Heap.select(obj, "held")) <==> (0<freshHeld)), (Heap.select(obj, "held") := freshHeld))
+ } else Nil) :::
+ bassume(IsGoodMask(preEtran.Mask)) ::
+ bassume(wf(preEtran.Heap, preEtran.Mask)) ::
+ bassume(proofOrAssume) ::
+ preEtran.Inhale(e, ih, check) :::
+ bassume(preEtran.Heap ==@ evalHeap) ::
+ bassume(submask(preEtran.Mask, evalMask))
+ case e => (if(check) isDefined(e)(true) else Nil) ::: bassume(Tr(e))
+ }
+
+ def Exhale(predicates: List[(Expression, ErrorMessage)], occasion: String, check: Boolean): List[Boogie.Stmt] = {
+ val (emV, em) = NewBVar("exhaleMask", tmask, true)
+ Comment("begin exhale (" + occasion + ")") ::
+ BLocal(emV) :: (em := Mask) ::
+ (List.flatten (for (p <- predicates) yield Exhale(p._1, em, null, p._2, check))) :::
+ (Mask := em) ::
+ bassume(wf(Heap, Mask)) ::
+ Comment("end exhale")
+ }
+
+ def Exhale(p: Expression, em: Boogie.Expr, eh: Boogie.Expr, error: ErrorMessage, check: Boolean): List[Boogie.Stmt] = p match {
+ case pred@MemberAccess(e, p) if pred.isPredicate =>
+ val tmp = Access(pred, None);
+ tmp.pos = pred.pos;
+ Exhale(tmp, em , eh, error, check)
+ case acc@AccessAll(obj, perm) =>
+ obj.typ.Fields flatMap { f =>
+ val ma = MemberAccess(obj, f.id);
+ ma.f = f;
+ ma.pos = acc.pos;
+ val exhalee = Access(ma, perm);
+ exhalee.pos = acc.pos;
+ Exhale(exhalee, em, eh, error, check) }
+ case acc@RdAccessAll(obj, perm) =>
+ obj.typ.Fields flatMap { f =>
+ val ma = MemberAccess(obj, f.id);
+ ma.f = f;
+ ma.pos = acc.pos;
+ val exhalee = RdAccess(ma, perm);
+ exhalee.pos = acc.pos;
+ Exhale(exhalee, em, eh, error, check) }
+ case acc@Access(e,perm) =>
+ val memberName = if(e.isPredicate) e.predicate.FullName else e.f.FullName;
+ // look up the fraction
+ val (fraction, checkFraction) = perm match {
+ case None => (IntLiteral(100), Nil)
+ case Some(fr) => (fr, bassert(0<=Tr(fr), fr.pos, "Fraction might be negative.") :: (if(! e.isPredicate) bassert(Tr(fr)<=100, fr.pos, "Fraction might exceed 100.") :: Nil else Nil) ::: Nil)
+ }
+ val (fractionV, frac) = NewBVar("fraction", tint, true);
+ // check definedness
+ (if(check) isDefined(e.e)(true) :::
+ checkFraction :::
+ bassert(nonNull(Tr(e.e)), error.pos, error.message + " The target of the acc predicate at " + acc.pos + " might be null.") else Nil) :::
+ BLocal(fractionV) :: (frac := Tr(fraction)) ::
+ // if the mask does not contain sufficient permissions, try folding acc(e, fraction)
+ (if(e.isPredicate && autoFold && (!perm.isDefined || canTakeFractionOf(DefinitionOf(e.predicate)))) {
+ val inhaleTran = new ExpressionTranslator(List(Heap, em), currentClass);
+ val sourceVar = new Variable("fraction", new Type(IntClass));
+ val bplVar = Variable2BVar(sourceVar);
+ BLocal(bplVar) :: (VarExpr(sourceVar.UniqueName) := frac) ::
+ If(new MapSelect(em, Tr(e.e), memberName, "perm$R") < frac,
+ Exhale(if(perm.isDefined) FractionOf(SubstThis(DefinitionOf(e.predicate), e.e), new VariableExpr(sourceVar)) else SubstThis(DefinitionOf(e.predicate), e.e), em, eh, ErrorMessage(error.pos, error.message + " Automatic fold might fail."), false) :::
+ inhaleTran.Inhale(List(if(! perm.isDefined) Access(e, None) else Access(e, Some(new VariableExpr(sourceVar)))), "automatic fold", false)
+ , Nil) :: Nil}
+ else Nil) :::
+ // check that the necessary permissions are there and remove them from the mask
+ DecPermission(Tr(e.e), memberName, frac, em, error, acc.pos) :::
+ bassume(IsGoodMask(Mask)) ::
+ bassume(wf(Heap, Mask)) ::
+ bassume(wf(Heap, em))
+ case rd@RdAccess(e,perm) =>
+ val memberName = if(e.isPredicate) e.predicate.FullName else e.f.FullName;
+ val (epsilonsV, eps) = NewBVar("epsilons", tint, true);
+ val (dfP, epsilons) = perm match {
+ case None => (List(), IntLiteral(1))
+ case Some(None) => (List(), null)
+ case Some(Some(p)) => (isDefined(p)(true) ::: List(bassert(0 <= Tr(p), error.pos, error.message + " The number of epsilons at " + rd.pos + " might be negative.")) , p)
+ }
+ // check definedness
+ (if(check) isDefined(e.e)(true) :::
+ bassert(nonNull(Tr(e.e)), error.pos, error.message + " The target of the rd predicate at " + rd.pos + " might be null.") ::
+ dfP else Nil) :::
+ BLocal(epsilonsV) :: (if(epsilons!=null) (eps := Tr(epsilons)) :: Nil else Nil) :::
+ // if the mask does not contain sufficient permissions, try folding rdacc(e, epsilons)
+ (if(e.isPredicate && autoFold && canTakeEpsilonsOf(DefinitionOf(e.predicate)) && epsilons!=null) {
+ val inhaleTran = new ExpressionTranslator(List(Heap, em), currentClass);
+ val sourceVar = new Variable("epsilons", new Type(IntClass));
+ val bplVar = Variable2BVar(sourceVar);
+ BLocal(bplVar) :: (VarExpr(sourceVar.UniqueName) := eps) ::
+ If(new MapSelect(em, Tr(e.e), memberName, "perm$N") < eps,
+ Exhale(EpsilonsOf(SubstThis(DefinitionOf(e.predicate), e.e), new VariableExpr(sourceVar)), em, eh, ErrorMessage(error.pos, error.message + " Automatic fold might fail."), false) :::
+ inhaleTran.Inhale(List(RdAccess(e, Some(Some(new VariableExpr(sourceVar))))), "automatic fold", false)
+ , Nil) :: Nil}
+ else Nil) :::
+ // check that the necessary permissions are there and remove them from the mask
+ DecPermissionEpsilon(Tr(e.e), memberName, if(epsilons != null) eps else null, em, error, rd.pos) :::
+ bassume(IsGoodMask(Mask)) ::
+ bassume(wf(Heap, Mask)) ::
+ bassume(wf(Heap, em))
+ case Implies(e0,e1) =>
+ (if(check) isDefined(e0)(true) else Nil) :::
+ Boogie.If(Tr(e0), Exhale(e1, em, eh, error, check), Nil)
+ case IfThenElse(con, then, els) =>
+ (if(check) isDefined(con)(true) else Nil) :::
+ Boogie.If(Tr(con), Exhale(then, em, eh, error, check), Exhale(els, em, eh, error, check))
+ case And(e0,e1) =>
+ Exhale(e0, em, eh, error, check) ::: Exhale(e1, em, eh, error, check)
+ case holds@Holds(e) =>
+ (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) :::
+ bassert(HasFullPermission(Tr(e), "held", em), error.pos, error.message + " The current thread might not have full permission to the held field at " + holds.pos + ".") ::
+ bassert(0 < Boogie.MapSelect(Heap, Tr(e), "held"), error.pos, error.message + " The current thread might not hold lock at " + holds.pos + ".") ::
+ bassert(! Boogie.MapSelect(Heap, Tr(e), "rdheld"), error.pos, error.message + " The current thread might hold the read lock at " + holds.pos + ".") ::
+ SetNoPermission(Tr(e), "held", em) ::
+ bassume(IsGoodMask(Mask)) ::
+ bassume(wf(Heap, Mask)) ::
+ bassume(wf(Heap, em))
+ case Eval(h, e) =>
+ val (evalHeap, evalMask, checks, proofOrAssume) = fromEvalState(h);
+ val preGlobals = etran.FreshGlobals("eval")
+ val preEtran = new ExpressionTranslator(List(Boogie.VarExpr(preGlobals(0).id), Boogie.VarExpr(preGlobals(1).id)), currentClass);
+ BLocal(preGlobals(0)) :: (VarExpr(preGlobals(0).id) := evalHeap) ::
+ BLocal(preGlobals(1)) :: (VarExpr(preGlobals(1).id) := evalMask) ::
+ (if(check) checks else Nil) :::
+ bassume(IsGoodMask(preEtran.Mask)) ::
+ bassume(wf(preEtran.Heap, preEtran.Mask)) ::
+ bassert(proofOrAssume, p.pos, "Arguments for joinable might not match up.") ::
+ preEtran.Exhale(List((e, error)), "eval", check)
+ case e => (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."))
+ }
+
+ def fromEvalState(h: EvalState): (Expr, Expr, List[Stmt], Expr) = {
+ h match {
+ case AcquireState(obj) =>
+ (AcquireHeap(Heap.select(Tr(obj), "held")), AcquireMask(Heap.select(Tr(obj), "held")), isDefined(obj)(true), true)
+ case ReleaseState(obj) =>
+ (LastSeenHeap(Heap.select(Tr(obj), "mu"), Heap.select(Tr(obj), "held")), LastSeenMask(Heap.select(Tr(obj), "mu"), Heap.select(Tr(obj), "held")), isDefined(obj)(true), true)
+ case CallState(token, obj, id, args) =>
+ val argsSeq = CallArgs(Heap.select(Tr(token), "joinable"));
+
+ var i : int = 0;
+ (CallHeap(Heap.select(Tr(token), "joinable")),
+ CallMask(Heap.select(Tr(token), "joinable")),
+ isDefined(token)(true) :::
+ isDefined(obj)(true) :::
+ (args flatMap { a => isDefined(a)(true)}) :::
+ bassert(CanRead(Tr(token), "joinable"), obj.pos, "Joinable field of the token might not be readable.") ::
+ bassert(Heap.select(Tr(token), "joinable") !=@ 0, obj.pos, "Token might not be active."),
+ (new MapSelect(argsSeq, 0) ==@ Tr(obj) ) &&
+ (((args zip (1 until args.length+1).toList) map { a => new MapSelect(argsSeq, a._2) ==@ Tr(a._1)}).foldLeft(true: Expr){ (a: Expr, b: Expr) => a && b})
+ )
+ }
+ }
+
+ // permissions
+
+ def CanRead(obj: Boogie.Expr, field: Boogie.Expr): Boogie.Expr = new Boogie.FunctionApp("CanRead", Mask, obj, field)
+ def CanRead(obj: Boogie.Expr, field: String): Boogie.Expr = CanRead(obj, new Boogie.VarExpr(field))
+ 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))
+ def SetNoPermission(obj: Boogie.Expr, field: String, mask: Boogie.Expr) =
+ Boogie.Assign(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") ==@ Boogie.IntLiteral(100)) &&
+ (new Boogie.MapSelect(mask, obj, field, "perm$N") ==@ Boogie.IntLiteral(0))
+ def SetFullPermission(obj: Boogie.Expr, field: String) =
+ Boogie.Assign(Boogie.MapSelect(Mask, obj, field), Boogie.VarExpr("Permission$Full"))
+
+ def IncPermission(obj: Boogie.Expr, field: String, howMuch: Boogie.Expr) =
+ MapUpdate3(Mask, obj, field, "perm$R", new Boogie.MapSelect(Mask, obj, field, "perm$R") + howMuch)
+ def IncPermissionEpsilon(obj: Boogie.Expr, field: String, epsilons: Boogie.Expr) =
+ if (epsilons != null) {
+ val g = (new Boogie.MapSelect(Mask, obj, field, "perm$N") !=@ Boogie.VarExpr("Permission$MinusInfinity")) &&
+ (new Boogie.MapSelect(Mask, obj, field, "perm$N") !=@ Boogie.VarExpr("Permission$PlusInfinity"))
+ Boogie.If(g,
+ MapUpdate3(Mask, obj, field, "perm$N", new Boogie.MapSelect(Mask, obj, field, "perm$N") + epsilons) ::
+ bassume(Boogie.FunctionApp("wf", List(Heap, Mask))) :: Nil
+ , Nil)
+ } else {
+ val g = (new Boogie.MapSelect(Mask, obj, field, "perm$N") !=@ Boogie.VarExpr("Permission$MinusInfinity"))
+ Boogie.If(g, MapUpdate3(Mask, obj, field, "perm$N", Boogie.VarExpr("Permission$PlusInfinity")), Nil)
+ }
+
+ def DecPermission(obj: Boogie.Expr, field: String, howMuch: Boogie.Expr, mask: Boogie.Expr, error: ErrorMessage, pos: Position) = {
+ val xyz: Boogie.Expr = new Boogie.MapSelect(mask, obj, field, "perm$R")
+ bassert(howMuch <= xyz, error.pos, error.message + " Insufficient fraction at " + pos + " for " + field + ".") ::
+ 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) =
+ if (epsilons != null) {
+ val g = (new Boogie.MapSelect(mask, obj, field, "perm$N") !=@ Boogie.VarExpr("Permission$MinusInfinity")) &&
+ (new Boogie.MapSelect(mask, obj, field, "perm$N") !=@ Boogie.VarExpr("Permission$PlusInfinity"))
+ 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 + ".") ::
+ Boogie.If(g,
+ MapUpdate3(mask, obj, field, "perm$N", new Boogie.MapSelect(mask, obj, field, "perm$N") - epsilons) ::
+ bassume(Boogie.FunctionApp("wf", List(Heap, Mask))) :: Nil
+ , Nil)
+ } else {
+ val g = (new Boogie.MapSelect(mask, obj, field, "perm$N") !=@ Boogie.VarExpr("Permission$PlusInfinity"))
+ bassert((new Boogie.MapSelect(mask, obj, field, "perm$R") ==@ Boogie.IntLiteral(0)) ==>
+ (new Boogie.MapSelect(mask, obj, field, "perm$N") ==@ Boogie.VarExpr("Permission$PlusInfinity")), error.pos, error.message + " Insufficient epsilons at " + pos + " for " + field + ".") ::
+ Boogie.If(g, MapUpdate3(mask, obj, field, "perm$N", Boogie.VarExpr("Permission$MinusInfinity")), Nil)
+ }
+ var uniqueInt = 0;
+
+ def MapUpdate3(m: Boogie.Expr, arg0: Boogie.Expr, arg1: String, arg2: String, rhs: Boogie.Expr) = {
+ // m[a,b,c] := rhs
+ // m[a,b][c] := rhs
+ // m[a,b] := map[a,b][c := rhs]
+ val m01 = Boogie.MapSelect(m, arg0, arg1)
+ Boogie.Assign(m01, Boogie.MapStore(m01, arg2, rhs))
+ }
+
+ def DecPerm(m: Expr, e: Expr, f: Expr, i: Expr) = FunctionApp("DecPerm", List(m, e, f, i))
+ def DecEpsilons(m: Expr, e: Expr, f: Expr, i: Expr) = FunctionApp("DecEpsilons", List(m, e, f, i))
+ def IncPerm(m: Expr, e: Expr, f: Expr, i: Expr) = FunctionApp("IncPerm", List(m, e, f, i))
+ def IncEpsilons(m: Expr, e: Expr, f: Expr, i: Expr) = FunctionApp("IncEpsilons", List(m, e, f, i))
+
+
+ def MaxLockIsBelowX(x: Boogie.Expr) = { // maxlock << x
+ val (oV, o) = Boogie.NewBVar("o", tref, false)
+ new Boogie.Forall(oV,
+ (isHeldInHeap(o, Heap)) ==>
+ new Boogie.FunctionApp("MuBelow", Boogie.MapSelect(Heap, o, "mu"), x))
+ }
+ def MaxLockIsAboveX(x: Boogie.Expr) = { // x << maxlock
+ val (oV, o) = Boogie.NewBVar("o", tref, false)
+ new Boogie.Exists(oV,
+ (isHeldInHeap(o, Heap)) &&
+ new Boogie.FunctionApp("MuBelow", x, Boogie.MapSelect(Heap, o, "mu")))
+ }
+ def MaxLockEqualsX(x: Boogie.Expr) = { // maxlock == o.mu
+ // Note: Instead of the existential below, we could generate a nicer expression if we knew that
+ // x has the form y.mu--then, we'd replace the existential with y.held. Another possibility
+ // would be if we had an inverse of .mu (such an inverse exists, but we're not encoding it).
+// val (oV, o) = Boogie.NewBVar("o", tref, false)
+ //new Boogie.Exists(oV,
+ // (isHeldInHeap(o, Heap)) && (Boogie.MapSelect(Heap, o, "mu") ==@ x)) &&
+ /*isHeldInHeap(x, Heap) &&*/ IsHighestLock(x)
+ }
+ def IsHighestLock(x: Boogie.Expr) = {
+ // (forall r :: r.held ==> r.mu << x || r.mu == x)
+ val (rV, r) = Boogie.NewBVar("r", tref, false)
+ new Boogie.Forall(rV,
+ (isHeldInHeap(r, Heap)) ==>
+ (new Boogie.FunctionApp("MuBelow", MapSelect(Heap, r, "mu"), x) ||
+ (Boogie.MapSelect(Heap, r, "mu") ==@ x)))
+ }
+ def MaxLockPreserved = { // old(maxlock) == maxlock
+ // I don't know what the best encoding of this conding is, so I'll try a disjunction.
+ // Disjunct b0 is easier to prove, but it is stronger than b1.
+
+ // (forall r: ref ::
+ // old(Heap)[r,held] == Heap[r,held] &&
+ // (Heap[r,held] ==> old(Heap)[r,mu] == Heap[r,mu]))
+ val (rV, r) = Boogie.NewBVar("r", tref, false)
+ val b0 = new Boogie.Forall(rV,
+ ((0 < Boogie.MapSelect(oldEtran.Heap, r, "held")) ==@
+ (0 < Boogie.MapSelect(Heap, r, "held"))) &&
+ ((0 < Boogie.MapSelect(Heap, r, "held")) ==>
+ (Boogie.MapSelect(oldEtran.Heap, r, "mu") ==@
+ Boogie.MapSelect(Heap, r, "mu"))))
+
+ // (forall o, p ::
+ // old(o.held) && (forall r :: old(r.held) ==> old(r.mu) << old(o.mu) || old(r.mu)==old(o.mu)) &&
+ // p.held && (forall r :: r.held ==> r.mu << p.mu || r.mu == p.mu )
+ // ==>
+ // old(o.mu) == p.mu)
+ val (oV, o) = Boogie.NewBVar("o", tref, false)
+ val (pV, p) = Boogie.NewBVar("p", tref, false)
+ val b1 = new Boogie.Forall(List(oV,pV), List(),
+ ((0 < Boogie.MapSelect(oldEtran.Heap, o, "held")) &&
+ oldEtran.IsHighestLock(Boogie.MapSelect(oldEtran.Heap, o, "mu")) &&
+ (0 < Boogie.MapSelect(Heap, p, "held")) &&
+ IsHighestLock(Boogie.MapSelect(Heap, p, "mu")))
+ ==>
+ (Boogie.MapSelect(oldEtran.Heap, o, "mu") ==@ Boogie.MapSelect(Heap, p, "mu")))
+ b0 || b1
+ }
+ def TemporalMaxLockComparison(e0: ExpressionTranslator, e1: ExpressionTranslator) = { // e0(maxlock) << e1(maxlock)
+ // (exists o ::
+ // e1(o.held) &&
+ // (forall r :: e0(r.held) ==> e0(r.mu) << e1(o.mu)))
+ val (oV, o) = Boogie.NewBVar("o", tref, false)
+ new Boogie.Exists(oV,
+ (0 < Boogie.MapSelect(e0.Heap, o, "held")) &&
+ e0.MaxLockIsBelowX(Boogie.MapSelect(e1.Heap, o, "mu")))
+ }
+
+ def fractionOk(expr: Expression) = {
+ bassert(0<=Tr(expr), expr.pos, "Fraction might be negative.") ::
+ bassert(Tr(expr) <= 100, expr.pos, "Fraction might exceed 100.")
+ }
+}
+object S_ExpressionTranslator {
+ val Globals = {
+ ("Heap", theap) ::
+ ("Mask", tmask) ::
+ Nil
+ }
+}
+
+
+ // implicit
+ implicit def string2VarExpr(s: String) = VarExpr(s)
+ implicit def expression2Expr(e: Expression) = etran.Tr(e)
+ implicit def field2Expr(f: Field) = VarExpr(f.FullName)
+
+ // prelude
+
+ def ModuleType = NamedType("ModuleName");
+ def ModuleName(cl: Class) = "module#" + cl.module.id;
+ def TypeName = NamedType("TypeName");
+ def FieldType(tp: BType) = IndexedType("Field", tp);
+ def bassert(e: Expr, pos: Position, msg: String) = {
+ val result = Boogie.Assert(e); result.pos = pos; result.message = msg; result
+ }
+ def bassume(e: Expr) = Boogie.Assume(e)
+ def BLocal(id: String, tp: BType) = new Boogie.LocalVar(id, tp)
+ def BLocal(x: Boogie.BVar) = Boogie.LocalVar(x)
+ def tArgSeq = NamedType("ArgSeq");
+ def tref = NamedType("ref");
+ def tbool = NamedType("bool");
+ def tmu = NamedType("Mu");
+ def tint = NamedType("int");
+ def tseq(arg: BType) = IndexedType("Seq", arg)
+ def theap = NamedType("HeapType");
+ def tmask = NamedType("MaskType");
+ def ZeroMask = VarExpr("ZeroMask");
+ def HeapName = "Heap";
+ def MaskName = "Mask";
+ def Heap = VarExpr(HeapName);
+ def Mask = VarExpr(MaskName);
+ def GlobalNames = List(HeapName, MaskName);
+ def CanAssumeFunctionDefs = VarExpr("CanAssumeFunctionDefs");
+ def CurrentModule = VarExpr("CurrentModule");
+ def IsGoodState(e: Expr) = FunctionApp("IsGoodState", List(e));
+ def dtype(e: Expr) = FunctionApp("dtype", List(e))
+ def functionName(f: Function) = "#" + f.FullName;
+ def bnull = Boogie.Null();
+ def bLockBottom = VarExpr("$LockBottom")
+ def nonNull(e: Expr): Expr = e !=@ bnull
+ def isHeld(e: Expr): Expr = (0 < etran.Heap.select(e, "held"))
+ def isRdHeld(e: Expr): Expr = etran.Heap.select(e, "rdheld")
+ def isShared(e: Expr): Expr = etran.Heap.select(e, "mu") !=@ bLockBottom
+ def LastSeenHeap(sharedBit: Expr, heldBit: Expr) = FunctionApp("LastSeen$Heap", List(sharedBit, heldBit))
+ def LastSeenMask(sharedBit: Expr, heldBit: Expr) = FunctionApp("LastSeen$Mask", List(sharedBit, heldBit))
+ def AcquireHeap(heldBit: Expr) = FunctionApp("Acquire$Heap", List(heldBit))
+ def AcquireMask(heldBit: Expr) = FunctionApp("Acquire$Mask", List(heldBit))
+ def CallHeap(joinableBit: Expr) = FunctionApp("Call$Heap", List(joinableBit))
+ def CallMask(joinableBit: Expr) = FunctionApp("Call$Mask", List(joinableBit))
+ def CallArgs(joinableBit: Expr) = FunctionApp("Call$Args", List(joinableBit))
+ def submask(m1: Expr, m2: Expr) = FunctionApp("submask", List(m1, m2))
+
+object TranslationHelper {
+ def wf(h: Expr, m: Expr) = FunctionApp("wf", List(h, m));
+ def IsGoodMask(m: Expr) = FunctionApp("IsGoodMask", List(m))
+ def IsGoodInhaleState(a: Expr, b: Expr, c: Expr) = FunctionApp("IsGoodInhaleState", List(a, b, c))
+ def isHeldInHeap(e: Expr, h: Expr) = 0 < h.select(e, "held")
+ def NonEmptyMask(m: Expr) = ! FunctionApp("EmptyMask", List(m))
+ def NonPredicateField(f: String) = FunctionApp("NonPredicateField", List(VarExpr(f)))
+ def PredicateField(f: String) = FunctionApp("PredicateField", List(VarExpr(f)))
+ def createEmptySeq = FunctionApp("Seq#Empty", List())
+ def createSingletonSeq(e: Expr) = FunctionApp("Seq#Singleton", List(e))
+ def createAppendSeq(a: Expr, b: Expr) = FunctionApp("Seq#Append", List(a, b))
+ def createRange(min: Expr, max: Expr) = FunctionApp("Seq#Range", List(min, max))
+ def cast(a: Expr, b: Expr) = FunctionApp("cast", List(a, b))
+
+ // implicit conversions
+ implicit def bool2Bool(b: Boolean): Boogie.BoolLiteral = Boogie.BoolLiteral(b)
+ implicit def int2Int(n: int): Boogie.IntLiteral = Boogie.IntLiteral(n)
+ implicit def lift(s: Boogie.Stmt): List[Boogie.Stmt] = List(s)
+ implicit def type2BType(tp: Type): BType = {
+ val cl = tp.typ;
+ if(cl.IsRef) {
+ tref
+ } else if(cl.IsBool) {
+ tbool
+ } else if(cl.IsMu) {
+ tmu
+ } else if(cl.IsInt) {
+ tint
+ } else if(cl.IsSeq) {
+ tseq(type2BType(new Type(cl.asInstanceOf[SeqClass].parameter)))
+ } else {
+ assert(false); null
+ }
+ }
+ implicit def decl2DeclList(decl: Decl): List[Decl] = List(decl)
+ implicit def function2RichFunction(f: Function) = RichFunction(f);
+
+ case class RichFunction(f: Function) {
+ def apply(args: List[Expr]) = {
+ FunctionApp(functionName(f), args)
+ }
+ }
+
+ def Variable2BVar(v: Variable) = new Boogie.BVar(v.UniqueName, Boogie.ClassType(v.t.typ))
+ def Variable2BVarWhere(v: Variable) = NewBVarWhere(v.UniqueName, v.t)
+ def NewBVarWhere(id: String, tp: Type) = {
+ new Boogie.BVar(id, Boogie.ClassType(tp.typ)){
+ override val where = TypeInformation(new Boogie.VarExpr(id), tp) }
+ }
+
+ // scale an expression by a fraction
+ def FractionOf(expr: Expression, fraction: Expression) : Expression = {
+ val result = expr match {
+ case Access(e, None) => Access(e, Some(fraction))
+ case And(lhs, rhs) => And(FractionOf(lhs, fraction), FractionOf(rhs, fraction))
+ case _ if ! expr.isInstanceOf[PermissionExpr] => expr
+ case _ => throw new Exception(" " + expr.pos + ": Scaling non-full permissions is not supported yet." + expr);
+ }
+ result.pos = expr.pos;
+ result
+ }
+
+ def canTakeFractionOf(expr: Expression): Boolean = {
+ expr match {
+ case Access(e, None) => true
+ case And(lhs, rhs) => canTakeFractionOf(lhs) && canTakeFractionOf(rhs)
+ case _ if ! expr.isInstanceOf[PermissionExpr] => true
+ case _ => false
+ }
+ }
+
+ // scale an expression by a number of epsilons
+ def EpsilonsOf(expr: Expression, nbEpsilons: Expression) : Expression = {
+ val result = expr match {
+ case Access(e, _) => RdAccess(e, Some(Some(nbEpsilons)))
+ case And(lhs, rhs) => And(FractionOf(lhs, nbEpsilons), FractionOf(rhs, nbEpsilons))
+ case _ if ! expr.isInstanceOf[PermissionExpr] => expr
+ case _ => throw new Exception(" " + expr.pos + ": Scaling non-full permissions is not supported yet." + expr);
+ }
+ result.pos = expr.pos;
+ result
+ }
+
+ def canTakeEpsilonsOf(expr: Expression): Boolean = {
+ expr match {
+ case Access(e, _) => true
+ case And(lhs, rhs) => canTakeEpsilonsOf(lhs) && canTakeEpsilonsOf(rhs)
+ case _ if ! expr.isInstanceOf[PermissionExpr] => true
+ case _ => false
+ }
+ }
+
+ def TrType(cl: Class) = Boogie.VarExpr(cl.id + "#t")
+
+ def TypeInformation(e: Boogie.Expr, t: Type): Boogie.Expr = {
+ if (t.typ.IsRef) {
+ (e ==@ Boogie.Null()) || (new Boogie.FunctionApp("dtype", e) ==@ TrType(t.typ))
+ } else {
+ true
+ }
+ }
+
+ def Version(expr: Expression, etran: ExpressionTranslator): Boogie.Expr =
+ {
+ expr match{
+ case pred@MemberAccess(e, p) if pred.isPredicate =>
+ Version(Access(pred, None), etran)
+ case acc@Access(e,perm) =>
+ val memberName = if(e.isPredicate) e.predicate.FullName else e.f.FullName;
+ Boogie.MapSelect(etran.Heap, etran.Tr(e.e), memberName)
+ case rd@RdAccess(e,perm) =>
+ val memberName = if(e.isPredicate) e.predicate.FullName else e.f.FullName;
+ Boogie.MapSelect(etran.Heap, etran.Tr(e.e), memberName)
+ case Implies(e0,e1) =>
+ Boogie.Ite(etran.Tr(e0), Version(e1, etran), 0)
+ case And(e0,e1) =>
+ Boogie.FunctionApp("combine", List(Version(e0, etran), Version(e1, etran)))
+ case IfThenElse(con, then, els) =>
+ Boogie.Ite(etran.Tr(con), Version(then, etran), Version(els, etran))
+ case e => Boogie.VarExpr("nostate")
+ }
+ }
+ def FieldTp(f: Field): String = {
+ f match {
+ case SpecialField("mu", _) => "Mu"
+ case SpecialField("held", _) => "int"
+ case SpecialField("rdheld", _) => "bool"
+ case SpecialField("joinable", _) => "int"
+ case f: Field => TrClass(f.typ.typ)
+ }
+ }
+
+ def TrClass(tp: Class): String = {
+ tp.id match {
+ case "int" => "int"
+ case "bool" => "bool"
+ case "$Mu" => "Mu"
+ case _ => if(tp.IsSeq) "seq" else "ref"
+ }
+ }
+ def Preconditions(spec: List[Specification]): List[Expression] = {
+ val result = spec flatMap ( s => s match {
+ case Precondition(e) => List(e)
+ case _ => Nil });
+ if(autoMagic) {
+ automagic(result.foldLeft(BoolLiteral(true): Expression)({ (a, b) => And(a, b)}), Nil)._1 ::: result
+ } else {
+ result
+ }
+ }
+ def Postconditions(spec: List[Specification]): List[Expression] = {
+ val result = spec flatMap ( s => s match {
+ case Postcondition(e) => List(e)
+ case _ => Nil })
+ if(autoMagic) {
+ automagic(result.foldLeft(BoolLiteral(true): Expression)({ (a, b) => And(a, b)}), Nil)._1 ::: result
+ } else {
+ result
+ }
+ }
+
+ def automagic(expr: Expression, handled: List[Expression]): (/*assumptions*/ List[Expression], /*newHandled*/List[Expression]) = {
+ def isHandled(e: Expression) = handled exists { ex => ex.equals(e) }
+ expr match {
+ case ma@MemberAccess(obj, f) =>
+ val (assumptions, handled1) = automagic(obj, handled);
+ if(isHandled(ma)) {
+ (assumptions, handled1)
+ } else {
+ if(ma.isPredicate){
+ // assumption: obj!=null
+ (assumptions ::: Neq(obj, NullLiteral()) :: Nil, handled1 + ma)
+ } else {
+ // assumption: obj!=null && acc(obj, f)
+ (assumptions ::: Neq(obj, NullLiteral()) :: Access(ma, None) :: Nil, handled1 + ma)
+ }
+ }
+ case Access(ma@MemberAccess(obj, f), perm) =>
+ val (assumptions, handled1) = automagic(obj, handled + ma);
+ perm match {
+ case None => (assumptions, handled1);
+ case Some(fraction) => val result = automagic(fraction, handled1); (assumptions ::: result._1, result._2)
+ }
+ case RdAccess(ma@MemberAccess(obj, f), perm) =>
+ val (assumptions, handled1) = automagic(obj, handled + ma);
+ perm match {
+ case None => (assumptions, handled1);
+ case Some(None) => (assumptions, handled1);
+ case Some(Some(epsilon)) => val result = automagic(epsilon, handled1); (assumptions ::: result._1, result._2)
+ }
+ case AccessAll(obj, perm) =>
+ automagic(obj, handled)
+ case RdAccessAll(obj, perm) =>
+ automagic(obj, handled)
+ case Holds(e) =>
+ automagic(e, handled)
+ case RdHolds(e) =>
+ automagic(e, handled)
+ case a: Assigned =>
+ (Nil, handled)
+ case Old(e) =>
+ (Nil, handled) // ??
+ case IfThenElse(con, then, els) =>
+ val (assumptions, handled1) = automagic(con, handled);
+ val (assumptions2, handled2) = automagic(then, handled1);
+ val result = automagic(els, handled2);
+ (assumptions ::: assumptions2 ::: result._1, result._2)
+ case Not(e) =>
+ automagic(e, handled)
+ case func@FunctionApplication(obj, id, args) =>
+ var assumption = Nil: List[Expression];
+ var newHandled = handled;
+ for(a <- obj :: args) {
+ val (ass, hd) = automagic(a, handled);
+ assumption = assumption ::: ass;
+ newHandled = hd;
+ }
+ (assumption, newHandled)
+ case uf@Unfolding(_, e) =>
+ (Nil, handled)
+ case bin: BinaryExpr =>
+ val (assumptions, handled1) = automagic(bin.E0, handled);
+ val result = automagic(bin.E1, handled1);
+ (assumptions ::: result._1, result._2)
+ case q@Forall(is, Range(min, max), e) =>
+ (Nil, handled)
+ case q@Forall(is, seq, e) =>
+ (Nil, handled)
+ case EmptySeq(t) =>
+ (Nil, handled)
+ case ExplicitSeq(es) =>
+ var assumption = Nil: List[Expression];
+ var newHandled = handled;
+ for(a <- es) {
+ val (ass, hd) = automagic(a, handled);
+ assumption = assumption ::: ass;
+ newHandled = hd;
+ }
+ (assumption, newHandled)
+ case Range(min, max) =>
+ val (assumptions, handled1) = automagic(min, handled);
+ val result = automagic(max, handled1);
+ (assumptions ::: result._1, result._2)
+ case Length(e) =>
+ automagic(e, handled)
+ case Eval(h, e) =>
+ (Nil, handled)
+ case _ => (Nil, handled)
+ }
+ }
+
+ def DefinitionOf(predicate: Predicate): Expression = {
+ if(autoMagic) {
+ And(automagic(predicate.definition, Nil)._1.foldLeft(BoolLiteral(true): Expression)({ (a, b) => And(a, b)}), predicate.definition)
+ } else {
+ predicate.definition
+ }
+ }
+
+ def LockChanges(spec: List[Specification]): List[Expression] = {
+ spec flatMap ( s => s match {
+ case LockChange(ee) => ee
+ case _ => Nil })
+ }
+
+ def SubstRd(e: Expression): Expression = e match {
+ case Access(e,_) =>
+ val r = RdAccess(e,None); r.typ = BoolClass; r
+ case e: RdAccess => e
+ case Implies(e0,e1) =>
+ val r = Implies(e0, SubstRd(e1)); r.typ = BoolClass; r
+ case And(e0,e1) =>
+ val r = And(SubstRd(e0), SubstRd(e1)); r.typ = BoolClass; r
+ case e => e
+ }
+ }
+
+ def UnfoldPredicatesWithReceiverThis(expr: Expression): Expression = {
+ def unfoldPred(e: Expression): Expression = {
+ e match {
+ case pred@MemberAccess(o, f) if pred.isPredicate && o.isInstanceOf[ThisExpr] =>
+ SubstThis(DefinitionOf(pred.predicate), o)
+ case Access(pred@MemberAccess(o, f), p) if pred.isPredicate && o.isInstanceOf[ThisExpr] =>
+ p match {
+ case None => SubstThis(DefinitionOf(pred.predicate), o)
+ case Some(p) => FractionOf(SubstThis(DefinitionOf(pred.predicate), o), p)
+ }
+ case RdAccess(pred@MemberAccess(o, f), p) if pred.isPredicate && o.isInstanceOf[ThisExpr] =>
+ p match {
+ case None => EpsilonsOf(SubstThis(DefinitionOf(pred.predicate), o), IntLiteral(1))
+ case Some(None) => throw new Exception("not supported yet")
+ case Some(Some(p)) => EpsilonsOf(SubstThis(DefinitionOf(pred.predicate), o), p)
+ }
+ case func@FunctionApplication(obj: ThisExpr, name, args) if 2<=TranslationOptions.defaults =>
+ SubstThisAndVars(func.f.definition, obj, func.f.ins, args)
+ case _ => manipulate(e, {ex => unfoldPred(ex)})
+ }
+ }
+ unfoldPred(expr)
+ }
+
+ // needed to do a _simultaneous_ substitution!
+ def SubstThisAndVars(expr: Expression, thisReplacement: Expression, vs: List[Variable], xs: List[Expression]): Expression = {
+ def replace(e: Expression): Expression = {
+ e match {
+ case _: ThisExpr => thisReplacement
+ case e: VariableExpr =>
+ for ((v,x) <- vs zip xs if v == e.v) { return x }
+ e
+ case q@Forall(is, seq, e) =>
+ val sub = vs zip xs filter { xv => is forall { variable => ! variable.id.equals(xv._1)}};
+ val result = Forall(is, SubstThisAndVars(seq, thisReplacement, vs, xs), SubstThisAndVars(e, thisReplacement, sub map { x => x._1}, sub map { x => x._2}));
+ result.variables = q.variables;
+ result
+ case _ => manipulate(e, {ex => replace(ex)})
+ }
+ }
+ replace(expr)
+ }
+
+ def SubstThis(expr: Expression, x: Expression): Expression = {
+ def replaceThis(e: Expression): Expression = {
+ e match {
+ case _: ThisExpr => x
+ case _ => manipulate(e, {ex => replaceThis(ex)})
+ }
+ }
+ replaceThis(expr)
+ }
+
+ def SubstResult(expr: Expression, x: Expression): Expression = {
+ def replaceThis(e: Expression): Expression = {
+ e match {
+ case _: Result => x
+ case _ => manipulate(e, {ex => replaceThis(ex)})
+ }
+ }
+ replaceThis(expr)
+ }
+
+ def SubstVars(expr: Expression, vs: List[Variable], xs: List[Expression]): Expression = {
+ def replaceThis(e: Expression): Expression = {
+ e match {
+ case e: VariableExpr =>
+ for ((v,x) <- vs zip xs if v == e.v) { return x }
+ e
+ case q@Forall(is, seq, e) =>
+ val sub = vs zip xs filter { xv => is forall { variable => ! variable.id.equals(xv._1)}};
+ val result = Forall(is, SubstVars(seq, vs, xs), SubstVars(e, sub map { x => x._1}, sub map { x => x._2}));
+ result.variables = q.variables;
+ result
+ case _ => manipulate(e, {ex => replaceThis(ex)})
+ }
+ }
+ replaceThis(expr)
+ }
+
+ def manipulate(expr: Expression, func: Expression => Expression): Expression = {
+ val result = expr match {
+ case e: Literal => expr
+ case _:ThisExpr => expr
+ case _:Result => expr
+ case e:VariableExpr => expr
+ case acc@MemberAccess(e,f) =>
+ val g = MemberAccess(func(e), f); g.f = acc.f; g.predicate = acc.predicate; g.isPredicate = acc.isPredicate; g
+ case Access(e, perm) =>
+ Access(func(e).asInstanceOf[MemberAccess],
+ perm match { case None => perm case Some(perm) => Some(func(perm)) })
+ case RdAccess(e, perm) =>
+ RdAccess(func(e).asInstanceOf[MemberAccess],
+ perm match { case Some(Some(p)) => Some(Some(func(p))) case _ => perm })
+ case AccessAll(obj, perm) =>
+ AccessAll(func(obj),
+ perm match { case None => perm case Some(perm) => Some(func(perm)) })
+ case RdAccessAll(obj, perm) =>
+ RdAccessAll(func(obj),
+ perm match { case Some(Some(p)) => Some(Some(func(p))) case _ => perm })
+ case Holds(e) => Holds(func(e))
+ case RdHolds(e) => RdHolds(func(e))
+ case e: Assigned => e
+ case Old(e) => Old(func(e))
+ case IfThenElse(con, then, els) => IfThenElse(func(con), func(then), func(els))
+ case Not(e) => Not(func(e))
+ case funapp@FunctionApplication(obj, id, args) =>
+ val appl = FunctionApplication(func(obj), id, args map { arg => func(arg)}); appl.f = funapp.f; appl
+ case Unfolding(pred, e) =>
+ Unfolding(func(pred).asInstanceOf[PermissionExpr], func(e))
+ case Iff(e0,e1) => Iff(func(e0), func(e1))
+ case Implies(e0,e1) => Implies(func(e0), func(e1))
+ case And(e0,e1) => And(func(e0), func(e1))
+ case Or(e0,e1) => Or(func(e0), func(e1))
+ case Eq(e0,e1) => Eq(func(e0), func(e1))
+ case Neq(e0,e1) => Neq(func(e0), func(e1))
+ case Less(e0,e1) => Less(func(e0), func(e1))
+ case AtMost(e0,e1) => AtMost(func(e0), func(e1))
+ case AtLeast(e0,e1) => AtLeast(func(e0), func(e1))
+ case Greater(e0,e1) => Greater(func(e0), func(e1))
+ case LockBelow(e0,e1) => LockBelow(func(e0), func(e1))
+ case Plus(e0,e1) => Plus(func(e0), func(e1))
+ case Minus(e0,e1) => Minus(func(e0), func(e1))
+ case Times(e0,e1) => Times(func(e0), func(e1))
+ case Div(e0,e1) => Div(func(e0), func(e1))
+ case Mod(e0,e1) => Mod(func(e0), func(e1))
+ case forall@Forall(i, seq, e) => val result = Forall(i, func(seq), func(e)); result.variables = forall.variables; result
+ case ExplicitSeq(es) =>
+ ExplicitSeq(es map { e => func(e) })
+ case Range(min, max)=>
+ Range(func(min), func(max))
+ case Append(e0, e1) =>
+ Append(func(e0), func(e1))
+ case At(e0, e1) =>
+ At(func(e0), func(e1))
+ case Drop(e0, e1) =>
+ Drop(func(e0), func(e1))
+ case Take(e0, e1) =>
+ Take(func(e0), func(e1))
+ case Length(e) =>
+ Length(func(e))
+ case Eval(h, e) =>
+ Eval(h match {
+ case AcquireState(obj) => AcquireState(func(obj))
+ case ReleaseState(obj) => ReleaseState(func(obj))
+ case CallState(token, obj, i, args) => CallState(func(token), func(obj), i, args map { a => func(a)})
+ }, func(e))
+ }
+ if(result.typ == null) {
+ result.typ = expr.typ;
+ }
+ result.pos = expr.pos
+ result
+ }
+
+}
diff --git a/Chalice/test.bat b/Chalice/test.bat
new file mode 100644
index 00000000..480a7bf7
--- /dev/null
+++ b/Chalice/test.bat
@@ -0,0 +1,43 @@
+@echo off
+echo start > Output
+
+set CHALICE=call scala -cp bin Chalice -nologo
+
+for %%f in (AssociationList cell counter dining-philosophers ForkJoin HandOverHand
+ iterator iterator2 producer-consumer
+ prog0 prog1 prog2 prog3 prog4 RockBand swap GhostConst OwickiGries) do (
+ echo Testing %%f.chalice ...
+ echo ------ Running regression test %%f.chalice >> Output
+ %CHALICE% %* examples\%%f.chalice >> Output 2>&1
+)
+
+echo Testing cell-defaults.chalice ...
+echo ------ Running regression test cell-defaults.chalice >> Output
+%CHALICE% %* -defaults -autoFold -autoMagic examples\cell-defaults.chalice >> Output 2>&1
+
+echo Testing RockBand-automagic.chalice ...
+echo ------ Running regression test RockBand-automagic.chalice >> Output
+%CHALICE% %* -defaults -autoMagic -checkLeaks -autoFold examples\RockBand-automagic.chalice >> Output 2>&1
+
+echo Testing Leaks.chalice ...
+echo ------ Running regression test Leaks.chalice >> Output
+%CHALICE% %* -checkLeaks examples\Leaks.chalice >> Output 2>&1
+
+
+fc examples\Answer Output > nul
+if not errorlevel 1 goto passTest
+goto failTest
+
+:passTest
+echo Succeeded
+goto end
+
+:failTest
+echo Failed
+goto end
+
+:errorEnd
+exit /b 1
+
+:end
+exit /b 0
diff --git a/Source/..svnbridge/Boogie.suo b/Source/..svnbridge/Boogie.suo
new file mode 100644
index 00000000..08149303
--- /dev/null
+++ b/Source/..svnbridge/Boogie.suo
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="utf-8"?><ItemProperties xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><Properties><Property><Name>svn:mime-type</Name><Value>application/octet-stream</Value></Property></Properties></ItemProperties> \ No newline at end of file
diff --git a/Source/..svnbridge/Dafny.suo b/Source/..svnbridge/Dafny.suo
new file mode 100644
index 00000000..08149303
--- /dev/null
+++ b/Source/..svnbridge/Dafny.suo
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="utf-8"?><ItemProperties xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><Properties><Property><Name>svn:mime-type</Name><Value>application/octet-stream</Value></Property></Properties></ItemProperties> \ No newline at end of file
diff --git a/Source/AIFramework/AIFramework.sscproj b/Source/AIFramework/AIFramework.sscproj
new file mode 100644
index 00000000..dd79b9b8
--- /dev/null
+++ b/Source/AIFramework/AIFramework.sscproj
@@ -0,0 +1,157 @@
+<?xml version="1.0" encoding="utf-8"?>
+<VisualStudioProject>
+ <XEN ProjectType="Local"
+ SchemaVersion="1.0"
+ Name="AIFramework"
+ ProjectGuid="24b55172-ad8b-47d1-8952-5a95cfdb9b31"
+ >
+ <Build>
+ <Settings ApplicationIcon=""
+ AssemblyName="AIFramework"
+ OutputType="Library"
+ RootNamespace="AIFramework"
+ StartupObject=""
+ StandardLibraryLocation=""
+ TargetPlatform="v2"
+ TargetPlatformLocation=""
+ ShadowedAssembly=""
+ >
+ <Config Name="Debug"
+ AllowUnsafeBlocks="False"
+ BaseAddress="285212672"
+ CheckForOverflowUnderflow="False"
+ ConfigurationOverrideFile=""
+ DefineConstants="DEBUG;TRACE"
+ DocumentationFile=""
+ DebugSymbols="True"
+ FileAlignment="4096"
+ IncrementalBuild="True"
+ Optimize="False"
+ OutputPath="bin\debug"
+ RegisterForComInterop="False"
+ RemoveIntegerChecks="false"
+ TreatWarningsAsErrors="False"
+ WarningLevel="4"
+ RunProgramVerifier="False"
+ ProgramVerifierCommandLineOptions=""
+ ReferenceTypesAreNonNullByDefault="False"
+ RunProgramVerifierWhileEditing="False"
+ AllowPointersToManagedStructures="False"
+ CheckContractAdmissibility="True"
+ CheckPurity="False"
+ />
+ <Config Name="Release"
+ AllowUnsafeBlocks="false"
+ BaseAddress="285212672"
+ CheckForOverflowUnderflow="false"
+ ConfigurationOverrideFile=""
+ DefineConstants="TRACE"
+ DocumentationFile=""
+ DebugSymbols="false"
+ FileAlignment="4096"
+ IncrementalBuild="false"
+ Optimize="true"
+ OutputPath="bin\release"
+ RegisterForComInterop="false"
+ RemoveIntegerChecks="false"
+ TreatWarningsAsErrors="True"
+ WarningLevel="4"
+ />
+ </Settings>
+ <References>
+ <Reference Name="System"
+ AssemblyName="System"
+ Private="false"
+ />
+ <Reference Name="Basetypes"
+ Project="{0C692837-77EC-415F-BF04-395E3ED06E9A}"
+ Private="true"
+ />
+ </References>
+ </Build>
+ <Files>
+ <Include>
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="Expr.ssc"
+ />
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="CommonFunctionSymbols.ssc"
+ />
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="Lattice.ssc"
+ />
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="Functional.ssc"
+ />
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="Mutable.ssc"
+ />
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="Logger.ssc"
+ />
+ <Folder RelPath="VariableMap\"
+ />
+ <Folder RelPath="Polyhedra\"
+ />
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="VariableMap\MicroLattice.ssc"
+ />
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="VariableMap\VariableMapLattice.ssc"
+ />
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="MultiLattice.ssc"
+ />
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="VariableMap\Nullness.ssc"
+ />
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="VariableMap\ConstantAbstraction.ssc"
+ />
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="VariableMap\DynamicTypeLattice.ssc"
+ />
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="Polyhedra\SimplexTableau.ssc"
+ />
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="Polyhedra\LinearConstraint.ssc"
+ />
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="Polyhedra\LinearConstraintSystem.ssc"
+ />
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="Polyhedra\PolyhedraAbstraction.ssc"
+ />
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="..\version.ssc"
+ />
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="VariableMap\Intervals.ssc"
+ />
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="VariableMap\ConstantExpressions.ssc"
+ />
+ </Include>
+ </Files>
+ </XEN>
+</VisualStudioProject> \ No newline at end of file
diff --git a/Source/AIFramework/CommonFunctionSymbols.ssc b/Source/AIFramework/CommonFunctionSymbols.ssc
new file mode 100644
index 00000000..4e38fbcb
--- /dev/null
+++ b/Source/AIFramework/CommonFunctionSymbols.ssc
@@ -0,0 +1,926 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+namespace Microsoft.AbstractInterpretationFramework
+{
+ using Microsoft.Contracts;
+ using System.Collections;
+ using Microsoft.SpecSharp.Collections;
+ using Microsoft.Basetypes;
+
+ /// <summary>
+ /// A basic class for function symbols.
+ /// </summary>
+ public class FunctionSymbol : IFunctionSymbol
+ {
+ private readonly string! display;
+ private readonly AIType! typ;
+
+ public FunctionSymbol(AIType! typ)
+ : this("FunctionSymbol", typ)
+ {
+ }
+
+ internal FunctionSymbol(string! display, AIType! typ)
+ {
+ this.display = display;
+ this.typ = typ;
+ // base();
+ }
+
+// public AIType! AIType { [Pure][Reads(ReadsAttribute.Reads.Owned)] get { return typ; } }
+ public AIType! AIType { [Pure][Reads(ReadsAttribute.Reads.Owned)] get { return typ; } }
+
+ [NoDefaultContract]
+ [Pure][Reads(ReadsAttribute.Reads.Owned)]
+ public override string! ToString()
+ {
+ return display;
+ }
+
+ }
+
+ /// <summary>
+ /// A class for integer constants.
+ /// </summary>
+ public class IntSymbol : FunctionSymbol
+ {
+ public readonly BigNum Value;
+
+ /// <summary>
+ /// The intention is that this constructor be called only from the Int.Const method.
+ /// </summary>
+ internal IntSymbol(BigNum x)
+ : base((!)x.ToString(), Int.Type)
+ {
+ this.Value = x;
+ }
+
+ [Pure][Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals(object other)
+ {
+ IntSymbol isym = other as IntSymbol;
+ return isym != null && isym.Value.Equals(this.Value);
+ }
+
+ [Pure][Reads(ReadsAttribute.Reads.Owned)]
+ public override int GetHashCode()
+ {
+ return Value.GetHashCode();
+ }
+ }
+
+ /// <summary>
+ /// A class for bitvector constants.
+ /// </summary>
+ public class BvSymbol : FunctionSymbol
+ {
+ public readonly BigNum Value;
+ public readonly int Bits;
+
+ /// <summary>
+ /// The intention is that this constructor be called only from the Int.Const method.
+ /// </summary>
+ internal BvSymbol(BigNum x, int y)
+ : base(x + "bv" + y, Bv.Type)
+ {
+ this.Value = x;
+ this.Bits = y;
+ }
+
+ [Pure][Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals(object other)
+ {
+ BvSymbol isym = other as BvSymbol;
+ return isym != null && isym.Value == this.Value && isym.Bits == this.Bits;
+ }
+
+ [Pure][Reads(ReadsAttribute.Reads.Owned)]
+ public override int GetHashCode()
+ {
+ unchecked {
+ return Value.GetHashCode() ^ Bits;
+ }
+ }
+ }
+
+ public class DoubleSymbol : FunctionSymbol
+ {
+ public readonly double Value;
+
+ /// <summary>
+ /// The intention is that this constructor be called only from the Double.Const method.
+ /// </summary>
+ internal DoubleSymbol(double x)
+ : base((!)x.ToString(), Double.Type)
+ {
+ this.Value = x;
+ }
+
+ [Pure][Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals(object other)
+ {
+ DoubleSymbol dsym = other as DoubleSymbol;
+ return dsym != null && dsym.Value == this.Value;
+ }
+
+ [Pure][Reads(ReadsAttribute.Reads.Owned)]
+ public override int GetHashCode()
+ {
+ return Value.GetHashCode();
+ }
+ }
+
+ /// <summary>
+ /// Function symbol based on a string. Uses the string equality for determining equality
+ /// of symbol.
+ /// </summary>
+ public class NamedSymbol : FunctionSymbol
+ {
+ public string! Value { [NoDefaultContract] get { return (!) this.ToString(); } }
+
+ public NamedSymbol(string! symbol, AIType! typ)
+ : base(symbol, typ)
+ {
+ }
+
+ [NoDefaultContract]
+ [Pure][Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals(object other)
+ {
+ NamedSymbol nsym = other as NamedSymbol;
+ return nsym != null && this.Value.Equals(nsym.Value);
+ }
+
+ [NoDefaultContract]
+ [Pure][Reads(ReadsAttribute.Reads.Owned)]
+ public override int GetHashCode()
+ {
+ return Value.GetHashCode();
+ }
+ }
+
+ //
+ // In the following, the classes like Value and Prop serve two
+ // roles. The primary role is to be the base types for AIType.
+ // The only objects of these classes are the representative
+ // objects that denote an AIType, which are given by the
+ // "Type" property. Subtypes in the AIType language are
+ // encoded by subclassing. This yields some "higher-orderness"
+ // for checking subtyping in the AIType language, by using
+ // the Spec#/C# subclassing checks.
+ //
+ // The other role is simply as a module for collecting like function
+ // symbols.
+ //
+
+ //-------------------------- Terms ----------------------------------
+
+ /// <summary>
+ /// A class with the equality symbol and the ValueType.Type.
+ /// </summary>
+ public class Value : AIType
+ {
+ private static readonly AIType! valtype = new Value();
+ public static AIType! Type { get { return valtype; } }
+
+ private static readonly FunctionType[]! funtypeCache = new FunctionType[5];
+ public static FunctionType! FunctionType(int inParameterCount)
+ requires 0 <= inParameterCount;
+ // ensures result.Arity == inParameterCount;
+ {
+ FunctionType result;
+ if (inParameterCount < funtypeCache.Length) {
+ result = funtypeCache[inParameterCount];
+ if (result != null) {
+ return result;
+ }
+ }
+ AIType[] signature = new AIType[1 + inParameterCount];
+ for (int i = 0; i < signature.Length; i++) {
+ signature[i] = valtype;
+ }
+ result = new FunctionType(signature);
+ if (inParameterCount < funtypeCache.Length) {
+ funtypeCache[inParameterCount] = result;
+ }
+ return result;
+ }
+
+ [Once] private static AIType! binreltype;
+ private static AIType! BinrelType {
+ get {
+ if (binreltype == null) {
+ binreltype = new FunctionType(Type, Type, Prop.Type);
+ }
+ return binreltype;
+ }
+ }
+
+ [Once] private static FunctionSymbol! _eq;
+ public static FunctionSymbol! Eq {
+ get {
+ if (_eq == null) {
+ _eq = new FunctionSymbol("=", BinrelType);
+ }
+ return _eq;
+ }
+ }
+ [Once] private static FunctionSymbol! _neq;
+ public static FunctionSymbol! Neq {
+ get {
+ if (_neq == null) {
+ _neq = new FunctionSymbol("!=", BinrelType);
+ }
+ return _neq;
+ }
+ }
+ [Once] private static FunctionSymbol! _subtype;
+ public static FunctionSymbol! Subtype {
+ get {
+ if (_subtype == null) {
+ _subtype = new FunctionSymbol("<:", BinrelType);
+ }
+ return _subtype;
+ }
+ }
+
+ [Once] private static AIType! typeof_type;
+ private static AIType! TypeofType {
+ get {
+ if (typeof_type == null) {
+ typeof_type = new FunctionType(Ref.Type, Type);
+ }
+ return typeof_type;
+ }
+ }
+ [Once] private static FunctionSymbol! _typeof;
+ public static FunctionSymbol! Typeof {
+ get {
+ if (_typeof == null) {
+ _typeof = new FunctionSymbol("typeof", TypeofType);
+ }
+ return _typeof;
+ }
+ }
+
+ /// <summary>
+ /// Value should not be instantiated from the outside, except perhaps in
+ /// subclasses.
+ /// </summary>
+ protected Value() { }
+
+ }
+
+ public class Int : Value
+ {
+ private static readonly AIType! inttype = new Int();
+ public static AIType! Type { get { return inttype; } }
+
+ private static readonly AIType! unaryinttype = new FunctionType(Type, Type);
+ private static readonly AIType! bininttype = new FunctionType(Type, Type, Type);
+ private static readonly AIType! relationtype = new FunctionType(Type, Type, Prop.Type);
+
+ private static readonly FunctionSymbol! _negate = new FunctionSymbol("~", unaryinttype);
+ private static readonly FunctionSymbol! _add = new FunctionSymbol("+", bininttype);
+ private static readonly FunctionSymbol! _sub = new FunctionSymbol("-", bininttype);
+ private static readonly FunctionSymbol! _mul = new FunctionSymbol("*", bininttype);
+ private static readonly FunctionSymbol! _div = new FunctionSymbol("/", bininttype);
+ private static readonly FunctionSymbol! _mod = new FunctionSymbol("%", bininttype);
+ private static readonly FunctionSymbol! _atmost = new FunctionSymbol("<=", relationtype);
+ private static readonly FunctionSymbol! _less = new FunctionSymbol("<", relationtype);
+ private static readonly FunctionSymbol! _greater = new FunctionSymbol(">", relationtype);
+ private static readonly FunctionSymbol! _atleast = new FunctionSymbol(">=", relationtype);
+
+ [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol! Negate { get { return _negate; } }
+ [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol! Add { get { return _add; } }
+ [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol! Sub { get { return _sub; } }
+ [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol! Mul { get { return _mul; } }
+ [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol! Div { get { return _div; } }
+ [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol! Mod { get { return _mod; } }
+ [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol! AtMost { get { return _atmost; } }
+ [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol! Less { get { return _less; } }
+ [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol! Greater { get { return _greater; } }
+ [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol! AtLeast { get { return _atleast; } }
+
+ public static IntSymbol! Const(BigNum x)
+ {
+ // We could cache things here, but for now we don't.
+ return new IntSymbol(x);
+ }
+
+ /// <summary>
+ /// Int should not be instantiated from the outside, except perhaps in
+ /// subclasses.
+ /// </summary>
+ private Int() { }
+ }
+
+ public class Double : Value
+ {
+ private static readonly AIType! doubletype = new Double();
+ public static AIType! Type { get { return doubletype; } }
+
+ public static DoubleSymbol! Const(double x)
+ {
+ // We could cache things here, but for now we don't.
+ return new DoubleSymbol(x);
+ }
+
+ /// <summary>
+ /// Double should not be instantiated from the outside, except perhaps in
+ /// subclasses.
+ /// </summary>
+ private Double() { }
+ }
+
+ public class Bv : Value
+ {
+ private static readonly AIType! bvtype = new Bv();
+ public static AIType! Type { get { return bvtype; } }
+
+ private static readonly AIType! unaryinttype = new FunctionType(Type, Type);
+ private static readonly AIType! bininttype = new FunctionType(Type, Type, Type);
+ private static readonly AIType! relationtype = new FunctionType(Type, Type, Prop.Type);
+
+ private static readonly FunctionSymbol! _negate = new FunctionSymbol("~", unaryinttype);
+ private static readonly FunctionSymbol! _add = new FunctionSymbol("+", bininttype);
+ private static readonly FunctionSymbol! _sub = new FunctionSymbol("-", bininttype);
+ private static readonly FunctionSymbol! _mul = new FunctionSymbol("*", bininttype);
+ private static readonly FunctionSymbol! _div = new FunctionSymbol("/", bininttype);
+ private static readonly FunctionSymbol! _mod = new FunctionSymbol("%", bininttype);
+ private static readonly FunctionSymbol! _concat = new FunctionSymbol("$concat", bininttype);
+ private static readonly FunctionSymbol! _extract = new FunctionSymbol("$extract", unaryinttype);
+ private static readonly FunctionSymbol! _atmost = new FunctionSymbol("<=", relationtype);
+ private static readonly FunctionSymbol! _less = new FunctionSymbol("<", relationtype);
+ private static readonly FunctionSymbol! _greater = new FunctionSymbol(">", relationtype);
+ private static readonly FunctionSymbol! _atleast = new FunctionSymbol(">=", relationtype);
+
+ [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol! Negate { get { return _negate; } }
+ [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol! Add { get { return _add; } }
+ [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol! Sub { get { return _sub; } }
+ [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol! Mul { get { return _mul; } }
+ [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol! Div { get { return _div; } }
+ [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol! Mod { get { return _mod; } }
+ [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol! AtMost { get { return _atmost; } }
+ [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol! Less { get { return _less; } }
+ [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol! Greater { get { return _greater; } }
+ [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol! AtLeast { get { return _atleast; } }
+ [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol! Extract { get { return _extract; } }
+ [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol! Concat { get { return _concat; } }
+
+ public static BvSymbol! Const(BigNum x, int y)
+ {
+ // We could cache things here, but for now we don't.
+ return new BvSymbol(x, y);
+ }
+
+ /// <summary>
+ /// Int should not be instantiated from the outside, except perhaps in
+ /// subclasses.
+ /// </summary>
+ private Bv() { }
+ }
+
+ public class Ref : Value
+ {
+ private static readonly AIType! reftype = new Ref();
+ public static AIType! Type { get { return reftype; } }
+
+ private static readonly FunctionSymbol! _null = new FunctionSymbol("null", Type);
+
+ public static FunctionSymbol! Null { get { return _null; } }
+
+ /// <summary>
+ /// Ref should not be instantiated from the outside, except perhaps in
+ /// subclasses.
+ /// </summary>
+ private Ref() { }
+ }
+
+ public class HeapStructure : Value
+ {
+ private static readonly AIType! reftype = new HeapStructure();
+ public static AIType! Type { get { return reftype; } }
+
+
+
+ /// <summary>
+ /// HeapStructure should not be instantiated from the outside, except perhaps in
+ /// subclasses.
+ /// </summary>
+ private HeapStructure() { }
+ }
+
+ public class FieldName : Value
+ {
+ private static readonly AIType! fieldnametype = new FieldName();
+ public static AIType! Type { get { return fieldnametype; } }
+
+ private static readonly FunctionSymbol! _allocated = new FunctionSymbol("$allocated", FieldName.Type);
+ public static FunctionSymbol! Allocated { get { return _allocated; } }
+
+ /// <summary>
+ /// Is this a boolean field that monotonically goes from false to true?
+ /// </summary>
+ public static bool IsBooleanMonotonicallyWeakening(IFunctionSymbol! f)
+ {
+ return f.Equals(Allocated);
+ }
+
+ /// <summary>
+ /// FieldName should not be instantiated from the outside, except perhaps in
+ /// subclasses.
+ /// </summary>
+ private FieldName() { }
+ }
+
+ public class Heap : Value
+ {
+ private static readonly AIType! heaptype = new Heap();
+ public static AIType! Type { get { return heaptype; } }
+
+ // the types in the following, select1, select2, are hard-coded;
+ // these types may not always be appropriate
+ private static readonly FunctionSymbol! _select1 = new FunctionSymbol("sel1",
+ // Heap x FieldName -> Prop
+ new FunctionType(Type, FieldName.Type, Prop.Type)
+ );
+ public static FunctionSymbol! Select1 { get { return _select1; } }
+
+ private static readonly FunctionSymbol! _select2 = new FunctionSymbol("sel2",
+ // Heap x Ref x FieldName -> Value
+ new FunctionType(Type, Ref.Type, FieldName.Type, Value.Type)
+ );
+ public static FunctionSymbol! Select2 { get { return _select2; } }
+
+ // the types in the following, store1, store2, are hard-coded;
+ // these types may not always be appropriate
+ private static readonly FunctionSymbol! _update1 = new FunctionSymbol("upd1",
+ // Heap x FieldName x Value -> Heap
+ new FunctionType(Type, FieldName.Type, Value.Type, Type)
+ );
+ public static FunctionSymbol! Update1 { get { return _update1; } }
+
+ private static readonly FunctionSymbol! _update2 = new FunctionSymbol("upd2",
+ // Heap x Ref x FieldName x Value -> Heap
+ new FunctionType(Type, Ref.Type, FieldName.Type, Value.Type, Type)
+ );
+ public static FunctionSymbol! Update2 { get { return _update2; } }
+
+ private static readonly FunctionSymbol! _unsupportedHeapOp =
+ new FunctionSymbol("UnsupportedHeapOp",
+ // Heap x FieldName -> Prop
+ new FunctionType(Type, FieldName.Type, Prop.Type)
+ );
+ public static FunctionSymbol! UnsupportedHeapOp { get { return _unsupportedHeapOp; } }
+
+ /// <summary>
+ /// Heap should not be instantiated from the outside, except perhaps in
+ /// subclasses.
+ /// </summary>
+ private Heap() { }
+ }
+
+// public class List : Value
+// {
+// private static IDictionary/*<AIType!,AIType!>*/! lists = new Hashtable();
+// public static AIType! Type(AIType! typeParameter)
+// {
+// if (lists.Contains(typeParameter))
+// return lists[typeParameter];
+// else
+// {
+// AIType! result = new List(typeParameter);
+// lists[typeParameter] = result;
+// return result;
+// }
+// }
+//
+// private static IDictionary/*<AIType!,AIType!>*/! nils = new Hashtable();
+// public static FunctionSymbol! Nil(AIType! typeParameter)
+// {
+// if (nils.Contains(typeParameter))
+// return nils[typeParameter];
+// else
+// {
+// FunctionSymbol! result = new FunctionSymbol(Type(typeParameter));
+// nils[typeParameter] = result;
+// return result;
+// }
+// }
+//
+// private static IDictionary/*<AIType!,AIType!>*/! cons = new Hashtable();
+// public static FunctionSymbol! Cons(AIType! typeParameter)
+// {
+// if (cons.Contains(typeParameter))
+// return cons[typeParameter];
+// else
+// {
+// FunctionSymbol! result = new FunctionSymbol(
+// new FunctionType(typeParameter, Type(typeParameter), Type(typeParameter))
+// );
+// cons[typeParameter] = result;
+// return result;
+// }
+// }
+//
+// private AIType! typeParameter;
+// public AIType! TypeParameter { get { return typeParameter; } }
+//
+// /// <summary>
+// /// List should not be instantiated from the outside.
+// /// </summary>
+// private List(AIType! typeParameter)
+// {
+// this.typeParameter = typeParameter;
+// }
+// }
+//
+// public class Pair : Value
+// {
+// private static IDictionary! pairs = new Hashtable();
+// public static AIType! Type(AIType! type1, AIType! type2)
+// {
+// Microsoft.AbstractInterpretationFramework.Collections.Pair typpair
+// = new Microsoft.AbstractInterpretationFramework.Collections.Pair(type1, type2);
+//
+// if (pairs.Contains(typpair))
+// return pairs[typpair];
+// else
+// {
+// AIType! result = new Pair(type1, type2);
+// pairs[typpair] = result;
+// return result;
+// }
+// }
+//
+// private static IDictionary! constructs = new Hashtable();
+// public static FunctionSymbol! Pair(AIType! type1, AIType! type2)
+// {
+// Microsoft.AbstractInterpretationFramework.Collections.Pair typpair
+// = new Microsoft.AbstractInterpretationFramework.Collections.Pair(type1, type2);
+//
+// if (constructs.Contains(typpair))
+// return constructs[typpair];
+// else
+// {
+// FunctionSymbol! result = new FunctionSymbol(
+// new FunctionType(type1, type2, Type(type1, type2))
+// );
+// constructs[typpair] = result;
+// return result;
+// }
+// }
+//
+// protected AIType! type1;
+// protected AIType! type2;
+//
+// public AIType! Type1 { get { return type1; } }
+// public AIType! Type2 { get { return type2; } }
+//
+// /// <summary>
+// /// Pair should not be instantiated from the outside, except by subclasses.
+// /// </summary>
+// protected Pair(AIType! type1, AIType! type2)
+// {
+// this.type1 = type1;
+// this.type2 = type2;
+// }
+// }
+
+ //-------------------------- Propositions ---------------------------
+
+
+ /// <summary>
+ /// A class with global propositional symbols and the Prop.Type.
+ /// </summary>
+ public sealed class Prop : AIType
+ {
+ private static readonly AIType! proptype = new Prop();
+ public static AIType! Type { get { return proptype; } }
+
+ private static readonly AIType! unaryproptype = new FunctionType(Type, Type);
+ private static readonly AIType! binproptype = new FunctionType(Type, Type, Type);
+ private static readonly AIType! quantifiertype =
+ new FunctionType(new FunctionType(Value.Type, Type), Type);
+
+ private static readonly FunctionSymbol! _false = new FunctionSymbol("false", Type);
+ private static readonly FunctionSymbol! _true = new FunctionSymbol("true", Type);
+ private static readonly FunctionSymbol! _not = new FunctionSymbol("!", unaryproptype);
+ private static readonly FunctionSymbol! _and = new FunctionSymbol("/\\", binproptype);
+ private static readonly FunctionSymbol! _or = new FunctionSymbol("\\/", binproptype);
+ private static readonly FunctionSymbol! _implies = new FunctionSymbol("==>", binproptype);
+ private static readonly FunctionSymbol! _exists = new FunctionSymbol("Exists", quantifiertype);
+ private static readonly FunctionSymbol! _forall = new FunctionSymbol("Forall", quantifiertype);
+
+
+ [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol! False { get { return _false; } }
+ [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol! True { get { return _true; } }
+ [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol! Not { get { return _not; } }
+ [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol! And { [Pure] get { return _and; } }
+ [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol! Or { get { return _or; } }
+ [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol! Implies { get { return _implies; } }
+ [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol! Exists { get { return _exists; } }
+ [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol! Forall { get { return _forall; } }
+
+
+ /// <summary>
+ /// Prop should not be instantiated from the outside.
+ /// </summary>
+ private Prop() { }
+
+
+
+ //
+ // Utility Methods
+ //
+
+ public static IExpr! SimplifiedAnd(IPropExprFactory! factory, IExpr! e0, IExpr! e1)
+ {
+ IFunApp fun0 = e0 as IFunApp;
+ if (fun0 != null)
+ {
+ if (fun0.FunctionSymbol.Equals(Prop.True))
+ {
+ return e1;
+ }
+ else if (fun0.FunctionSymbol.Equals(Prop.False))
+ {
+ return e0;
+ }
+ }
+
+ IFunApp fun1 = e1 as IFunApp;
+ if (fun1 != null)
+ {
+ if (fun1.FunctionSymbol.Equals(Prop.True))
+ {
+ return e0;
+ }
+ else if (fun1.FunctionSymbol.Equals(Prop.False))
+ {
+ return e1;
+ }
+ }
+
+ return factory.And(e0, e1);
+ }
+
+ public static IExpr! SimplifiedAnd(IPropExprFactory! factory, IEnumerable/*<IExpr!>*/! exprs)
+ {
+ IExpr! result = factory.True;
+ foreach (IExpr! conjunct in exprs)
+ {
+ result = SimplifiedAnd(factory, result, conjunct);
+ }
+ return result;
+ }
+
+ public static IExpr! SimplifiedOr(IPropExprFactory! factory, IExpr! e0, IExpr! e1)
+ {
+ IFunApp fun0 = e0 as IFunApp;
+ if (fun0 != null)
+ {
+ if (fun0.FunctionSymbol.Equals(Prop.False))
+ {
+ return e1;
+ }
+ else if (fun0.FunctionSymbol.Equals(Prop.True))
+ {
+ return e0;
+ }
+ }
+
+ IFunApp fun1 = e1 as IFunApp;
+ if (fun1 != null)
+ {
+ if (fun1.FunctionSymbol.Equals(Prop.False))
+ {
+ return e0;
+ }
+ else if (fun1.FunctionSymbol.Equals(Prop.True))
+ {
+ return e1;
+ }
+ }
+
+ return factory.Or(e0, e1);
+ }
+
+ public static IExpr! SimplifiedOr(IPropExprFactory! factory, IEnumerable/*<IExpr!>*/! exprs)
+ {
+ IExpr! result = factory.False;
+ foreach (IExpr! disj in exprs)
+ {
+ result = SimplifiedOr(factory, result, disj);
+ }
+ return result;
+ }
+
+
+
+ /// <summary>
+ /// Break top-level conjuncts into a list of sub-expressions.
+ /// </summary>
+ /// <param name="e">The expression to examine.</param>
+ /// <returns>A list of conjuncts.</returns>
+ internal static IList/*<IExpr!>*/! BreakConjuncts(IExpr! e)
+ ensures forall{ IExpr sub in result; sub is IFunApp ==> !((IFunApp) sub).FunctionSymbol.Equals(Prop.And) };
+ {
+ return BreakJuncts(e, Prop.And);
+ }
+
+ /// <summary>
+ /// Break top-level disjuncts into a list of sub-expressions.
+ /// </summary>
+ /// <param name="e">The expression to examine.</param>
+ /// <returns>A list of conjuncts.</returns>
+ internal static IList/*<IExpr!>*/! BreakDisjuncts(IExpr! e)
+ ensures forall{ IExpr sub in result; sub is IFunApp ==> !((IFunApp) sub).FunctionSymbol.Equals(Prop.Or) };
+ {
+ return BreakJuncts(e, Prop.Or);
+ }
+
+ private static IList/*<IExpr!>*/! BreakJuncts(IExpr! e, IFunctionSymbol! sym)
+ ensures forall{ IExpr sub in result; sub is IFunApp ==> !((IFunApp) sub).FunctionSymbol.Equals(sym) };
+ {
+ ArrayList/*<IExpr!>*/! result = new ArrayList();
+
+ IFunApp f = e as IFunApp;
+ if (f != null)
+ {
+ // If it is a sym, go down into sub-expressions.
+ if (f.FunctionSymbol.Equals(sym))
+ {
+ foreach (IExpr! arg in f.Arguments)
+ {
+ result.AddRange(BreakJuncts(arg,sym));
+ }
+ }
+ // Otherwise, stop.
+ else
+ {
+ result.Add(e);
+ }
+ }
+ else
+ {
+ result.Add(e);
+ }
+
+ return result;
+ }
+ }
+
+ /// <summary>
+ /// A callback to produce a function body given the bound variable.
+ /// </summary>
+ /// <param name="var">The bound variable to use.</param>
+ /// <returns>The function body.</returns>
+ public delegate IExpr! FunctionBody(IVariable! var);
+
+ /// <summary>
+ /// An interface for constructing propositional expressions.
+ ///
+ /// This interface should be implemented by the client. An implementation of
+ /// of this class should generally be used as a singleton object.
+ /// </summary>
+ public interface IPropExprFactory
+ {
+ IFunApp! False { get /*ensures result.FunctionSymbol.Equals(Prop.False);*/; }
+ IFunApp! True { get /*ensures result.FunctionSymbol.Equals(Prop.True);*/; }
+
+ IFunApp! Not(IExpr! p) /*ensures result.FunctionSymbol.Equals(Prop.Not);*/;
+
+ IFunApp! And(IExpr! p, IExpr! q) /*ensures result.FunctionSymbol.Equals(Prop.And);*/;
+ IFunApp! Or(IExpr! p, IExpr! q) /*ensures result.FunctionSymbol.Equals(Prop.Or);*/;
+
+ IFunApp! Implies(IExpr! p, IExpr! q) /*ensures result.FunctionSymbol.Equals(Prop.Implies);*/;
+ }
+
+ /// <summary>
+ /// Like IPropExprFactory, but also with quantifiers.
+ /// </summary>
+ public interface IQuantPropExprFactory : IPropExprFactory {
+ /// <summary>
+ /// Produce an existential given the lambda-expression.
+ /// </summary>
+ /// <param name="p">The lambda-expression.</param>
+ /// <returns>The existential.</returns>
+ IFunApp! Exists(IFunction! p) /*ensures result.FunctionSymbol.Equals(Prop.Exists);*/;
+ IFunApp! Forall(IFunction! p) /*ensures result.FunctionSymbol.Equals(Prop.Forall);*/;
+
+ /// <summary>
+ /// Produce an existential given a callback that can produce a function body given the
+ /// bound variable to use. The implementer of this method is responsible for generating
+ /// a fresh new variable to pass to the FunctionBody callback to use as the bound variable.
+ /// </summary>
+ /// <param name="body">The function body callback.</param>
+ /// <returns>The existential.</returns>
+ IFunApp! Exists(AIType paramType, FunctionBody! body) /*ensures result.FunctionSymbol.Equals(Prop.Exists);*/;
+ IFunApp! Forall(AIType paramType, FunctionBody! body) /*ensures result.FunctionSymbol.Equals(Prop.Forall);*/;
+ }
+
+ /// <summary>
+ /// An interface for constructing value expressions.
+ ///
+ /// This interface should be implemented by the client. An implementation of
+ /// of this class should generally be used as a singleton object.
+ /// </summary>
+ public interface IValueExprFactory
+ {
+ IFunApp! Eq(IExpr! e0, IExpr! e1) /*ensures result.FunctionSymbol.Equals(Value.Eq);*/;
+ IFunApp! Neq(IExpr! e0, IExpr! e1) /*ensures result.FunctionSymbol.Equals(Value.Neq);*/;
+ }
+
+ /// <summary>
+ /// An interface for constructing value expressions having to with null.
+ ///
+ /// This interface should be implemented by the client. An implementation of
+ /// of this class should generally be used as a singleton object.
+ /// </summary>
+ public interface INullnessFactory
+ {
+ IFunApp! Eq(IExpr! e0, IExpr! e1) /*ensures result.FunctionSymbol.Equals(Value.Eq);*/;
+ IFunApp! Neq(IExpr! e0, IExpr! e1) /*ensures result.FunctionSymbol.Equals(Value.Neq);*/;
+ IFunApp! Null { get; /*ensures result.FunctionSymbol.Equals(Ref.Null);*/ }
+ }
+
+ /// <summary>
+ /// An interface for constructing integer expressions.
+ ///
+ /// This interface should be implemented by the client. An implementation of
+ /// of this class should generally be used as a singleton object.
+ /// </summary>
+ public interface IIntExprFactory : IValueExprFactory
+ {
+ IFunApp! Const(BigNum i) /*ensures result.FunctionSymbol.Equals(new IntSymbol(i));*/;
+ }
+
+ /// <summary>
+ /// An interface for constructing linear integer expressions.
+ ///
+ /// This interface should be implemented by the client. An implementation of
+ /// of this class should generally be used as a singleton object.
+ /// </summary>
+ public interface ILinearExprFactory : IIntExprFactory
+ {
+ IFunApp! AtMost(IExpr! e0, IExpr! e1) /*ensures result.FunctionSymbol.Equals(Value.AtMost);*/;
+ IFunApp! Add(IExpr! e0, IExpr! e1) /*ensures result.FunctionSymbol.Equals(Value.Add);*/;
+ /// <summary>
+ /// If "var" is null, returns an expression representing r.
+ /// Otherwise, returns an expression representing r*var.
+ /// </summary>
+ IExpr! Term(Microsoft.Basetypes.Rational r, IVariable var);
+
+ IFunApp! False { get /*ensures result.FunctionSymbol.Equals(Prop.False);*/; }
+ IFunApp! True { get /*ensures result.FunctionSymbol.Equals(Prop.True);*/; }
+ IFunApp! And(IExpr! p, IExpr! q) /*ensures result.FunctionSymbol.Equals(Prop.And);*/;
+ }
+
+ /// <summary>
+ /// An interface for constructing type expressions and performing some type operations.
+ /// The types are assumed to be arranged in a rooted tree.
+ ///
+ /// This interface should be implemented by the client. An implementation of
+ /// of this class should generally be used as a singleton object.
+ /// </summary>
+ public interface ITypeExprFactory
+ {
+ /// <summary>
+ /// Returns an expression denoting the top of the type hierarchy.
+ /// </summary>
+ IExpr! RootType { get; }
+
+ /// <summary>
+ /// Returns true iff "t" denotes a type constant.
+ /// </summary>
+ [Pure][Reads(ReadsAttribute.Reads.Owned)]
+ bool IsTypeConstant(IExpr! t);
+
+ /// <summary>
+ /// Returns true iff t0 and t1 are types such that t0 and t1 are equal.
+ /// </summary>
+ [Pure][Reads(ReadsAttribute.Reads.Owned)]
+ bool IsTypeEqual(IExpr! t0, IExpr! t1);
+
+ /// <summary>
+ /// Returns true iff t0 and t1 are types such that t0 is a subtype of t1.
+ /// </summary>
+ [Pure][Reads(ReadsAttribute.Reads.Owned)]
+ bool IsSubType(IExpr! t0, IExpr! t1);
+
+ /// <summary>
+ /// Returns the most derived supertype of both "t0" and "t1". A precondition is
+ /// that "t0" and "t1" both represent types.
+ /// </summary>
+ IExpr! JoinTypes(IExpr! t0, IExpr! t1);
+
+ IFunApp! IsExactlyA(IExpr! e, IExpr! type) /*requires IsTypeConstant(type); ensures result.FunctionSymbol.Equals(Value.Eq);*/;
+ IFunApp! IsA(IExpr! e, IExpr! type) /*requires IsTypeConstant(type); ensures result.FunctionSymbol.Equals(Value.Subtype);*/;
+ }
+
+}
diff --git a/Source/AIFramework/Expr.ssc b/Source/AIFramework/Expr.ssc
new file mode 100644
index 00000000..94dc4dc7
--- /dev/null
+++ b/Source/AIFramework/Expr.ssc
@@ -0,0 +1,447 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+// This file specifies the expression language used by the Abstract
+// Interpretation Framework.
+//
+// expressions e ::= x variables
+// | f(e1,...,en) uninterpreted functions
+// | \x:t.e lambda expressions
+//
+// types t ::= b user-defined/built-in base types
+// | t1 * ... * tn -> t' function type
+
+namespace Microsoft.AbstractInterpretationFramework
+{
+ using System.Collections;
+ using Microsoft.Contracts;
+
+ //----------------------------- Expressions -----------------------------
+
+ /// <summary>
+ /// An interface for expressions. This expression language is specified
+ /// by interfaces to allow the client to be able to use their existing
+ /// AST nodes as AIF expressions.
+ ///
+ /// This only serves as a place for operations on expressions. Clients
+ /// should implement directly either IVariable or IFunApp.
+ /// </summary>
+ public interface IExpr
+ {
+ /// <summary>
+ /// Execute a visit over the expression.
+ /// </summary>
+ /// <param name="visitor">The expression visitor.</param>
+ /// <returns>The result of the visit.</returns>
+ [Pure][Reads(ReadsAttribute.Reads.Owned)] object DoVisit(ExprVisitor! visitor);
+
+ // TODO: Type checking of the expressions.
+ }
+
+ /// <summary>
+ /// An interface for variables.
+ ///
+ /// This interface should be implemented by the client.
+ /// </summary>
+ public interface IVariable : IExpr
+ {
+ string! Name { get; } // Each client must define the name for variables
+ }
+
+ /// <summary>
+ /// An interface for function applications.
+ ///
+ /// This interface should be implemented by the client.
+ /// </summary>
+ public interface IFunApp : IExpr
+ {
+ IFunctionSymbol! FunctionSymbol { [Pure][Reads(ReadsAttribute.Reads.Owned)] get; }
+ IList/*<IExpr!>*/! Arguments
+ {
+ [Pure][Reads(ReadsAttribute.Reads.Owned)][Rep] get
+ ensures result.IsReadOnly;
+ ;
+ }
+
+ /// <summary>
+ /// Provides a method to create a new uninterpreted function
+ /// with the same function symbol but with the arguments with
+ /// args.
+ /// </summary>
+ /// <param name="args">The new arguments.</param>
+ /// <returns>A copy of the function with the new arguments.</returns>
+ IFunApp! CloneWithArguments(IList/*<IExpr!>*/! args)
+ //TODO requires this.Arguments.Count == args.Count;
+ ;
+ }
+
+ /// <summary>
+ /// An interface for anonymous functions (i.e., lambda expressions)
+ /// </summary>
+ public interface IFunction : IExpr
+ {
+ IVariable! Param { [Pure][Reads(ReadsAttribute.Reads.Owned)] get; }
+ AIType! ParamType { [Pure][Reads(ReadsAttribute.Reads.Owned)] get; }
+ IExpr! Body { [Pure][Reads(ReadsAttribute.Reads.Owned)] get; }
+
+ IFunction! CloneWithBody(IExpr! body);
+ }
+
+ /// <summary>
+ /// An abstract class that provides an interface for expression visitors.
+ /// </summary>
+ public abstract class ExprVisitor
+ {
+ public abstract object Default(IExpr! expr);
+
+ public virtual object VisitVariable(IVariable! var)
+ {
+ return Default(var);
+ }
+
+ public virtual object VisitFunApp(IFunApp! funapp)
+ {
+ return Default(funapp);
+ }
+
+ public virtual object VisitFunction(IFunction! fun)
+ {
+ return Default(fun);
+ }
+ }
+
+ /// <summary>
+ /// A utility class for dealing with expressions.
+ /// </summary>
+ public sealed class ExprUtil
+ {
+ /// <summary>
+ /// Yield an expression that is 'inexpr' with 'var' replaced by 'subst'.
+ /// </summary>
+ /// <param name="subst">The expression to substitute.</param>
+ /// <param name="var">The variable to substitute for.</param>
+ /// <param name="inexpr">The expression to substitute into.</param>
+ public static IExpr! Substitute(IExpr! subst, IVariable! var, IExpr! inexpr)
+ {
+ IExpr result = null;
+
+ if (inexpr is IVariable)
+ {
+ result = inexpr.Equals(var) ? subst : inexpr;
+ }
+ else if (inexpr is IFunApp)
+ {
+ IFunApp! funapp = (IFunApp!)inexpr;
+ IList newargs = null;
+ newargs = new ArrayList{ IExpr! arg in funapp.Arguments; Substitute(subst, var, arg) };
+ result = funapp.CloneWithArguments(newargs);
+ }
+ else if (inexpr is IFunction)
+ {
+ IFunction! fun = (IFunction!)inexpr;
+
+ if (fun.Param.Equals(var))
+ result = fun;
+ else
+ result = fun.CloneWithBody(Substitute(subst, var, fun.Body));
+ }
+ else
+ {
+ assert false;
+ }
+
+ return result;
+ }
+
+
+ //
+ // Poor man's pattern matching.
+ //
+ // The methods below implement pattern matching for AI expressions.
+ //
+ // Example Usage:
+ // Match(e, Prop.Imp,
+ // (Matcher)delegate (IExpr e) { return Match(e, Prop.And, out x, out y); }
+ // out z)
+ // which sees if 'e' matches Prop.Imp(Prop.And(x,y),z) binding x,y,z to the subtrees.
+ //
+ public delegate bool Matcher(IExpr! expr);
+
+ private static IFunApp/*?*/ MatchFunctionSymbol(IExpr! expr, IFunctionSymbol! f)
+ {
+ IFunApp app = expr as IFunApp;
+ if (app != null)
+ {
+ if (app.FunctionSymbol.Equals(f))
+ return app;
+ else
+ return null;
+ }
+ else
+ return null;
+ }
+
+ public static bool Match(IExpr! expr, IFunctionSymbol! f, params Matcher[]! subs)
+ {
+ IFunApp app = MatchFunctionSymbol(expr,f);
+ if (app != null)
+ {
+ int i = 0; // Note ***0***
+ foreach (Matcher! s in subs)
+ {
+ if (!s((IExpr!)app.Arguments[i])) { return false; }
+ i++;
+ }
+ return true;
+ }
+ else { return false; }
+ }
+
+ // Unary Binding
+ public static bool Match(IExpr! expr, IFunctionSymbol! f, out IExpr arg0, params Matcher[]! subs)
+ {
+ arg0 = null;
+
+ IFunApp app = MatchFunctionSymbol(expr,f);
+ if (app != null)
+ {
+ arg0 = (IExpr!)app.Arguments[0];
+
+ int i = 1; // Note ***1***
+ foreach (Matcher! s in subs)
+ {
+ if (!s((IExpr!)app.Arguments[i])) { return false; }
+ i++;
+ }
+ return true;
+ }
+ else { return false; }
+ }
+
+ // Binary Binding
+ public static bool Match(IExpr! expr, IFunctionSymbol! f, Matcher! sub0, out IExpr arg1, params Matcher[]! subs)
+ {
+ arg1 = null;
+
+ IFunApp app = MatchFunctionSymbol(expr,f);
+ if (app != null)
+ {
+ if (!sub0((IExpr!)app.Arguments[0])) { return false; }
+
+ arg1 = (IExpr!)app.Arguments[1];
+
+ int i = 2; // Note ***2***
+ foreach (Matcher! s in subs)
+ {
+ if (!s((IExpr!)app.Arguments[i])) { return false; }
+ i++;
+ }
+ return true;
+ }
+ else { return false; }
+ }
+
+ public static bool Match(IExpr! expr, IFunctionSymbol! f, out IExpr arg0, out IExpr arg1, params Matcher[]! subs)
+ {
+ arg0 = null;
+ arg1 = null;
+
+ IFunApp app = MatchFunctionSymbol(expr,f);
+ if (app != null)
+ {
+ arg0 = (IExpr!)app.Arguments[0];
+ arg1 = (IExpr!)app.Arguments[1];
+
+ int i = 2; // Note ***2***
+ foreach (Matcher! s in subs)
+ {
+ if (!s((IExpr!)app.Arguments[i])) { return false; }
+ i++;
+ }
+ return true;
+ }
+ else { return false; }
+ }
+
+ // Ternary Binding
+ public static bool Match(IExpr! expr, IFunctionSymbol! f, out IExpr arg0, out IExpr arg1, out IExpr arg2, params Matcher[]! subs)
+ {
+ arg0 = null;
+ arg1 = null;
+ arg2 = null;
+
+ IFunApp app = MatchFunctionSymbol(expr,f);
+ if (app != null)
+ {
+ arg0 = (IExpr!)app.Arguments[0];
+ arg1 = (IExpr!)app.Arguments[1];
+ arg2 = (IExpr!)app.Arguments[2];
+
+ int i = 3; // Note ***3***
+ foreach (Matcher! s in subs)
+ {
+ if (!s((IExpr!)app.Arguments[i])) { return false; }
+ i++;
+ }
+ return true;
+ }
+ else { return false; }
+ }
+
+ /// <summary>
+ /// Not intended to be instantiated.
+ /// </summary>
+ private ExprUtil() { }
+ }
+
+ //------------------------------ Symbols --------------------------------
+
+ /// <summary>
+ /// An interface for function symbols. Constants are represented by
+ /// 0-ary function symbols.
+ ///
+ /// This interface should be implemented by abstract domains, but client
+ /// expressions need keep track of function symbols.
+ /// </summary>
+ public interface IFunctionSymbol
+ {
+ AIType! AIType { [Pure][Reads(ReadsAttribute.Reads.Owned)][Rep][ResultNotNewlyAllocated]
+ get; }
+ }
+
+ /// <summary>
+ /// The type of the arguments to ExprUtil.Match, a poor man's pattern
+ /// matching.
+ /// </summary>
+ public interface IMatchable
+ {
+ }
+
+ //-------------------------------- Types --------------------------------
+
+ /// <summary>
+ /// Types.
+ /// </summary>
+ public interface AIType
+ {
+ }
+
+ /// <summary>
+ /// Function type constructor.
+ /// </summary>
+ public sealed class FunctionType : AIType
+ {
+ /*[Own]*/ private readonly IList/*<Type!>*/! argTypes;
+ /*[Own]*/ private readonly AIType! retType;
+
+ public FunctionType(params AIType[]! types)
+ requires types.Length >= 2;
+ {
+ AIType type = types[types.Length-1];
+ assume type != null;
+ this.retType = type;
+ ArrayList argTypes = new ArrayList();
+ for (int i = 0; i < types.Length-1; i++)
+ {
+ type = types[i];
+ assume type != null;
+ argTypes.Add(types);
+ }
+ this.argTypes = ArrayList.ReadOnly(argTypes);
+ }
+
+ public IList/*<AIType!>*/! Arguments
+ {
+ [Pure][Reads(ReadsAttribute.Reads.Owned)][Rep]
+ get
+ ensures result.IsReadOnly;
+ {
+ return argTypes;
+ }
+ }
+
+ public int Arity
+ {
+ [Pure][Reads(ReadsAttribute.Reads.Owned)] get { return argTypes.Count; }
+ }
+
+ public AIType! ReturnType
+ {
+ [Pure][Reads(ReadsAttribute.Reads.Owned)] get { return retType; }
+ }
+
+ /* TODO Do we have the invariant that two functions are equal iff they're the same object.
+ public override bool Equals(object o)
+ {
+ if (o != null && o is FunctionType)
+ {
+ FunctionType other = (FunctionType) o;
+
+ if (Arity == other.Arity
+ && ReturnType.Equals(other.ReturnType))
+ {
+ for (int i = 0; i < Arity; i++)
+ {
+ if (!argTypes[i].Equals(other.argTypes[i]))
+ return false;
+ }
+ return true;
+ }
+ else
+ return false;
+ }
+ else
+ return false;
+ }
+ */
+ }
+
+ //------------------------------ Queries -------------------------------
+
+ public enum Answer { Yes, No, Maybe };
+
+ /// <summary>
+ /// An interface that specifies a queryable object that can answer
+ /// whether a predicate holds.
+ /// </summary>
+ public interface IQueryable
+ {
+ /// <summary>
+ /// Answers the query whether the given predicate holds.
+ /// </summary>
+ /// <param name="pred">The given predicate.</param>
+ /// <returns>Yes, No, or Maybe.</returns>
+ Answer CheckPredicate(IExpr! pred);
+
+ /// <summary>
+ /// A simplified interface for disequalities. One can always
+ /// implement this by calling CheckPredicate, but it may be
+ /// more efficient with this method.
+ /// </summary>
+ Answer CheckVariableDisequality(IVariable! var1, IVariable! var2);
+ }
+
+ public static class QueryUtil
+ {
+ public static Answer Negate(Answer ans)
+ {
+ switch (ans)
+ {
+ case Answer.Yes:
+ return Answer.No;
+ case Answer.No:
+ return Answer.Yes;
+ default:
+ return Answer.Maybe;
+ }
+ }
+ }
+
+ //----------------------------- Exceptions -----------------------------
+
+ public class TypeError : CheckedException
+ {
+ }
+}
diff --git a/Source/AIFramework/Functional.ssc b/Source/AIFramework/Functional.ssc
new file mode 100644
index 00000000..4c4a5791
--- /dev/null
+++ b/Source/AIFramework/Functional.ssc
@@ -0,0 +1,284 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using Microsoft.Contracts;
+
+namespace Microsoft.AbstractInterpretationFramework.Collections
+{
+ using System.Collections;
+
+ /// <summary>Represents a functional collection of key/value pairs.</summary>
+ /// <filterpriority>2</filterpriority>
+ public interface IFunctionalMap : System.Collections.ICollection, System.Collections.IEnumerable
+ {
+ /// <summary>Adds an element with the provided key and value to the <see cref="T:Microsoft.AbstractInterpretationFramework.Collections.IFunctionalMap" />.</summary>
+ /// <param name="value">The <see cref="T:System.Object" /> to use as the value of the element to add. </param>
+ /// <param name="key">The <see cref="T:System.Object" /> to use as the key of the element to add. </param>
+ /// <filterpriority>2</filterpriority>
+ IFunctionalMap! Add(object! key, object value);
+
+ /// <summary>
+ /// Set the value of the key (that is already in the map)
+ /// </summary>
+ IFunctionalMap! Set(object! key, object value);
+
+ /// <summary>Determines whether the <see cref="T:Microsoft.AbstractInterpretationFramework.Collections.IFunctionalMap" /> contains an element with the specified key.</summary>
+ /// <returns>true if the <see cref="T:Microsoft.AbstractInterpretationFramework.Collections.IFunctionalMap" /> contains an element with the key; otherwise, false.</returns>
+ /// <param name="key">The key to locate in the <see cref="T:Microsoft.AbstractInterpretationFramework.Collections.IFunctionalMap" />. </param>
+ /// <filterpriority>2</filterpriority>
+ [Pure][Reads(ReadsAttribute.Reads.Owned)]
+ bool Contains(object! key);
+
+ /// <summary>Returns an <see cref="T:System.Collections.IDictionaryEnumerator" /> for the <see cref="T:Microsoft.AbstractInterpretationFramework.Collections.IFunctionalMap" />.</summary>
+ /// <returns>An <see cref="T:System.Collections.IDictionaryEnumerator" /> for the <see cref="T:Microsoft.AbstractInterpretationFramework.Collections.IFunctionalMap" />.</returns>
+ /// <filterpriority>2</filterpriority>
+ [Pure] [GlobalAccess(false)] [Escapes(true,false)]
+ new System.Collections.IDictionaryEnumerator GetEnumerator();
+
+ /// <summary>Gets an <see cref="T:System.Collections.ICollection" /> containing the keys of the <see cref="T:Microsoft.AbstractInterpretationFramework.Collections.IFunctionalMap" />.</summary>
+ /// <returns>An <see cref="T:System.Collections.ICollection" /> containing the keys of the <see cref="T:Microsoft.AbstractInterpretationFramework.Collections.IFunctionalMap" />.</returns>
+ /// <filterpriority>2</filterpriority>
+ System.Collections.ICollection Keys { get; }
+
+ /// <summary>Removes the element with the specified key from the <see cref="T:Microsoft.AbstractInterpretationFramework.Collections.IFunctionalMap" />.</summary>
+ /// <param name="key">The key of the element to remove. </param>
+ /// <filterpriority>2</filterpriority>
+ IFunctionalMap! Remove(object! key);
+
+ /// <summary>Gets an <see cref="T:System.Collections.ICollection" /> containing the values in the <see cref="T:Microsoft.AbstractInterpretationFramework.Collections.IFunctionalMap" />.</summary>
+ /// <returns>An <see cref="T:System.Collections.ICollection" /> containing the values in the <see cref="T:Microsoft.AbstractInterpretationFramework.Collections.IFunctionalMap" />.</returns>
+ /// <filterpriority>2</filterpriority>
+ System.Collections.ICollection Values { get; }
+
+ object this [object! key] { get; /*set;*/ }
+ }
+
+
+
+ /// <summary>
+ /// An implementation of the
+ /// <see cref="T:Microsoft.AbstractInterpretationFramework.Collections.IFunctionalMap" />
+ /// interface with a <see cref="T:System.Collections.Hashtable" /> as the backing store.
+ /// </summary>
+ class FunctionalHashtable : IFunctionalMap
+ {
+ private readonly Hashtable! h;
+
+ /// <summary>
+ /// Cannot directly construct an instance of a FunctionalHashtbl.
+ /// </summary>
+ private FunctionalHashtable()
+ {
+ this.h = new Hashtable();
+ // base();
+ }
+
+ /// <summary>
+ /// Cannot directly construct an instance of a FunctionalHashtbl.
+ /// </summary>
+ private FunctionalHashtable(Hashtable! h)
+ {
+ this.h = h;
+ // base();
+ }
+
+ private static readonly IFunctionalMap! empty = new FunctionalHashtable();
+ public static IFunctionalMap! Empty { get { return empty; } }
+
+ public IFunctionalMap! Add(object! key, object value)
+ {
+ Hashtable r = h.Clone() as Hashtable;
+ assume r != null;
+ r.Add(key, value);
+ return new FunctionalHashtable(r);
+ }
+
+ public IFunctionalMap! Set(object! key, object value)
+ {
+ Hashtable r = h.Clone() as Hashtable;
+
+ assume r != null;
+ assert this.Contains(key); // The entry must be defined
+
+ r[key] = value;
+ return new FunctionalHashtable(r);
+ }
+
+ [Pure][Reads(ReadsAttribute.Reads.Owned)]
+ public bool Contains(object! key)
+ {
+ return h.Contains(key);
+ }
+
+ [Pure] [GlobalAccess(false)] [Escapes(true,false)]
+ IEnumerator! IEnumerable.GetEnumerator()
+ {
+ return h.GetEnumerator();
+ }
+
+ [Pure] [GlobalAccess(false)] [Escapes(true,false)]
+ IDictionaryEnumerator IFunctionalMap.GetEnumerator()
+ {
+ return h.GetEnumerator();
+ }
+
+ public ICollection Keys
+ {
+ get { return h.Keys; }
+ }
+
+ public IFunctionalMap! Remove(object! key)
+ {
+ Hashtable r = h.Clone() as Hashtable;
+ assume r != null;
+ r.Remove(key);
+ return new FunctionalHashtable(r);
+ }
+
+ public ICollection Values
+ {
+ get { return h.Values; }
+ }
+
+
+ public object this[object! key]
+ {
+ get { return h[key]; }
+ }
+
+ public int Count
+ {
+ [Pure] get { return h.Count; }
+ }
+
+ public bool IsSynchronized
+ {
+ [Pure] get { return h.IsSynchronized; }
+ }
+
+ public object! SyncRoot
+ {
+ [Pure] get { return h.SyncRoot; }
+ }
+
+ public void CopyTo(System.Array! a, int index)
+ {
+ h.CopyTo(a, index);
+ }
+ }
+
+ public struct Pair/*<T1,T2>*/
+ {
+ private object first;
+ private object second;
+
+ public object First { get { return first; } }
+ public object Second { get { return second; } }
+
+ public Pair(object first, object second)
+ {
+ this.first = first;
+ this.second = second;
+ }
+
+ public override bool Equals(object obj)
+ {
+ if (obj == null) return false;
+ if (!(obj is Pair)) return false;
+
+ Pair other = (Pair)obj;
+ return object.Equals(this.first, other.first) && object.Equals(this.second, other.second);
+ }
+
+ public override int GetHashCode()
+ {
+ int h = this.first == null ? 0 : this.first.GetHashCode();
+ h ^= this.second == null ? 0 : this.second.GetHashCode();
+ return h;
+ }
+ }
+}
+
+
+namespace Microsoft.AbstractInterpretationFramework.Collections.Generic
+{
+ using System.Collections.Generic;
+
+ public struct Pair<T1,T2>
+ {
+ private T1 first;
+ private T2 second;
+
+ public T1 First { get { return first; } }
+ public T2 Second { get { return second; } }
+
+ public Pair(T1 first, T2 second)
+ {
+ this.first = first;
+ this.second = second;
+ }
+
+ public override bool Equals(object obj)
+ {
+ if (obj == null) return false;
+ if (!(obj is Pair<T1,T2>)) return false;
+
+ Pair<T1,T2> other = (Pair<T1,T2>)obj;
+ return object.Equals(this.first, other.first) && object.Equals(this.second, other.second);
+ }
+
+ public override int GetHashCode()
+ {
+ int h = this.first == null ? 0 : this.first.GetHashCode();
+ h ^= this.second == null ? 0 : this.second.GetHashCode();
+ return h;
+ }
+
+ public override string! ToString()
+ {
+ return string.Format("({0},{1})", first, second);
+ }
+ }
+
+ public struct Triple<T1,T2,T3>
+ {
+ private T1 first;
+ private T2 second;
+ private T3 third;
+
+ public T1 First { get { return first; } }
+ public T2 Second { get { return second; } }
+ public T3 Third { get { return third; } }
+
+ public Triple(T1 first, T2 second, T3 third)
+ {
+ this.first = first;
+ this.second = second;
+ this.third = third;
+ }
+
+ public override bool Equals(object obj)
+ {
+ if (obj == null) return false;
+ if (!(obj is Triple<T1,T2,T3>)) return false;
+
+ Triple<T1,T2,T3> other = (Triple<T1,T2,T3>)obj;
+ return object.Equals(this.first, other.first) && object.Equals(this.second, other.second) && object.Equals(this.third, other.third);
+ }
+
+ public override int GetHashCode()
+ {
+ int h = this.first == null ? 0 : this.first.GetHashCode();
+ h ^= this.second == null ? 0 : this.second.GetHashCode();
+ h ^= this.third == null ? 0 : this.third.GetHashCode();
+ return h;
+ }
+
+ public override string! ToString()
+ {
+ return string.Format("({0},{1},{2})", first, second, third);
+ }
+ }
+}
diff --git a/Source/AIFramework/Lattice.ssc b/Source/AIFramework/Lattice.ssc
new file mode 100644
index 00000000..2b606492
--- /dev/null
+++ b/Source/AIFramework/Lattice.ssc
@@ -0,0 +1,685 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+namespace Microsoft.AbstractInterpretationFramework
+{
+ using Microsoft.Contracts;
+ using System.Collections;
+ using G = System.Collections.Generic;
+ using System.Diagnostics;
+ using Microsoft.AbstractInterpretationFramework.Collections;
+ using Microsoft.Boogie;
+ using IMutableSet = Microsoft.Boogie.Set;
+ using ISet = Microsoft.Boogie.Set;
+ using HashSet = Microsoft.Boogie.Set;
+ using ArraySet = Microsoft.Boogie.Set;
+
+
+
+ /// <summary>
+ /// Specifies the operations (e.g., join) on a mathematical lattice that depend
+ /// only on the elements of the lattice.
+ /// </summary>
+ public abstract class MathematicalLattice
+ {
+ /// <summary>
+ /// An element of the lattice. This class should be derived from in any
+ /// implementation of MathematicalLattice.
+ /// </summary>
+ public abstract class Element : System.ICloneable {
+ /// <summary>
+ /// Print out a debug-useful representation of the internal data structure of the lattice element.
+ /// </summary>
+ public virtual void Dump(string! msg) {
+ System.Console.WriteLine("Dump({0}) = {1}", msg, this);
+ }
+
+ public abstract Element! Clone();
+ object! System.ICloneable.Clone() { return this.Clone(); }
+
+ public abstract G.ICollection<IVariable!>! FreeVariables()
+ ensures result.IsReadOnly;
+ }
+
+ public abstract Element! Top { get; }
+ public abstract Element! Bottom { get; }
+
+ public abstract bool IsTop(Element! e);
+ public abstract bool IsBottom(Element! e);
+
+ /// <summary>
+ /// Returns true if a &lt;= this.
+ /// </summary>
+ protected abstract bool AtMost(Element! a, Element! b)
+ /* The following cases are handled elsewhere and need not be considered in subclass. */
+ // requires a.GetType() == b.GetType();
+ // requires ! a.IsTop;
+ // requires ! a.IsBottom;
+ // requires ! b.IsTop;
+ // requires ! b.IsBottom;
+ ;
+
+ protected Answer TrivialLowerThan(Element! a, Element! b)
+ {
+ if (a.GetType() != b.GetType())
+ {
+ throw new System.InvalidOperationException(
+ "operands to <= must be of same Element type"
+ );
+ }
+ if (IsBottom(a)) { return Answer.Yes; }
+ if (IsTop(b)) { return Answer.Yes; }
+ if (IsTop(a)) { return Answer.No; }
+ if (IsBottom(b)) { return Answer.No; }
+
+ return Answer.Maybe;
+ }
+
+ // Is 'a' better information than 'b'?
+ //
+ public bool LowerThan(Element! a, Element! b)
+ {
+ Answer ans = TrivialLowerThan(a,b);
+ return ans != Answer.Maybe ? ans == Answer.Yes : AtMost(a, b);
+ }
+
+ // Is 'a' worse information than 'b'?
+ //
+ public bool HigherThan(Element! a, Element! b)
+ {
+ return LowerThan(b, a);
+ }
+
+ // Are 'a' and 'b' equivalent?
+ //
+ public bool Equivalent(Element! a, Element! b)
+ {
+ return LowerThan(a, b) && LowerThan(b, a);
+ }
+
+ public abstract Element! NontrivialJoin(Element! a, Element! b)
+ /* The following cases are handled elsewhere and need not be considered in subclass. */
+ // requires a.GetType() == b.GetType();
+ // requires ! a.IsTop;
+ // requires ! a.IsBottom;
+ // requires ! b.IsTop;
+ // requires ! b.IsBottom;
+ ;
+
+ protected Element/*?*/ TrivialJoin(Element! a, Element! b)
+ {
+ if (a.GetType() != b.GetType())
+ {
+ throw new System.InvalidOperationException(
+ "operands to Join must be of same Lattice.Element type"
+ );
+ }
+ if (IsTop(a)) { return a; }
+ if (IsTop(b)) { return b; }
+ if (IsBottom(a)) { return b; }
+ if (IsBottom(b)) { return a; }
+
+ return null;
+ }
+
+ public Element! Join(Element! a, Element! b)
+ {
+ Element/*?*/ r = TrivialJoin(a,b);
+ return r != null ? r : NontrivialJoin(a, b);
+ }
+
+ public abstract Element! NontrivialMeet(Element! a, Element! b)
+ /* The following cases are handled elsewhere and need not be considered in subclass. */
+ // requires a.GetType() == b.GetType();
+ // requires ! a.IsTop;
+ // requires ! a.IsBottom;
+ // requires ! b.IsTop;
+ // requires ! b.IsBottom;
+ ;
+
+ protected Element/*?*/ TrivialMeet(Element! a, Element! b)
+ {
+ if (a.GetType() != b.GetType())
+ {
+ throw new System.InvalidOperationException(
+ "operands to Meet must be of same Lattice.Element type"
+ );
+ }
+ if (IsTop(a)) { return b; }
+ if (IsTop(b)) { return a; }
+ if (IsBottom(a)) { return a; }
+ if (IsBottom(b)) { return b; }
+
+ return null;
+ }
+
+ public Element! Meet(Element! a, Element! b)
+ {
+ Element/*?*/ r = TrivialMeet(a,b);
+ return r != null ? r : NontrivialMeet(a, b);
+ }
+
+ public abstract Element! Widen(Element! a, Element! b);
+
+ public virtual void Validate()
+ {
+ Debug.Assert(IsTop(Top));
+ Debug.Assert(IsBottom(Bottom));
+ Debug.Assert(!IsBottom(Top));
+ Debug.Assert(!IsTop(Bottom));
+
+ Debug.Assert(LowerThan(Top, Top));
+ Debug.Assert(LowerThan(Bottom, Top));
+ Debug.Assert(LowerThan(Bottom, Bottom));
+
+ Debug.Assert(IsTop(Join(Top, Top)));
+ Debug.Assert(IsBottom(Join(Bottom, Bottom)));
+ }
+ }
+
+
+ /// <summary>
+ /// Provides an abstract interface for the operations of a lattice specific
+ /// to abstract interpretation (i.e., that deals with the expression language).
+ /// </summary>
+ public abstract class Lattice : MathematicalLattice
+ {
+ internal readonly IValueExprFactory! valueExprFactory;
+
+ public Lattice(IValueExprFactory! valueExprFactory)
+ {
+ this.valueExprFactory = valueExprFactory;
+ // base();
+ }
+
+ #region Primitives that commands translate into
+
+ public abstract Element! Eliminate(Element! e, IVariable! variable);
+
+ public abstract Element! Rename(Element! e, IVariable! oldName, IVariable! newName);
+
+ public abstract Element! Constrain(Element! e, IExpr! expr);
+
+ #endregion
+
+
+// TODO keep this?
+// public Element! Eliminate(Element! e, VariableSeq! variables)
+// {
+// Lattice.Element result = e;
+// foreach (IVariable var in variables)
+// {
+// result = this.Eliminate(result, var);
+// }
+// return result;
+// }
+
+
+ //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ // Note!
+ //
+ // Concrete classes that implement Lattice must implement one of the AtMost
+ // overloads. We provide here a default implementation for one given a "real"
+ // implementation of the other. Otherwise, there will be an infinite loop!
+ //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+ protected override bool AtMost(Element! a, Element! b)
+ {
+ return AtMost(a, IdentityCombineNameMap.Map, b, IdentityCombineNameMap.Map);
+ }
+
+ protected virtual bool AtMost(Element! a, ICombineNameMap! aToResult, Element! b, ICombineNameMap! bToResult)
+ {
+ return AtMost(ApplyCombineNameMap(a,aToResult), ApplyCombineNameMap(b,bToResult));
+ }
+
+ public bool LowerThan(Element! a, ICombineNameMap! aToResult, Element! b, ICombineNameMap! bToResult)
+ {
+ Answer ans = TrivialLowerThan(a,b);
+ return ans != Answer.Maybe ? ans == Answer.Yes : AtMost(a, aToResult, b, bToResult);
+ }
+
+ public bool HigherThan(Element! a, ICombineNameMap! aToResult, Element! b, ICombineNameMap! bToResult)
+ {
+ return LowerThan(b, bToResult, a, aToResult);
+ }
+
+
+ //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ // Note!
+ //
+ // Concrete classes that implement Lattice must implement one of the NontrivialJoin
+ // overloads. We provide here a default implementation for one given a "real"
+ // implementation of the other. Otherwise, there will be an infinite loop!
+ //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+ public override Element! NontrivialJoin(Element! a, Element! b)
+ {
+ return NontrivialJoin(a, IdentityCombineNameMap.Map, b, IdentityCombineNameMap.Map);
+ }
+
+ public virtual Element! NontrivialJoin(Element! a, ICombineNameMap! aToResult, Element! b, ICombineNameMap! bToResult)
+ {
+ return NontrivialJoin(ApplyCombineNameMap(a,aToResult), ApplyCombineNameMap(b,bToResult));
+ }
+
+ public Element! Join(Element! a, ICombineNameMap! aToResult, Element! b, ICombineNameMap! bToResult)
+ {
+ Element/*?*/ r = TrivialJoin(a,b);
+ return r != null ? r : NontrivialJoin(a, aToResult, b, bToResult);
+ }
+
+
+ //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ // Note!
+ //
+ // Concrete classes that implement Lattice must implement one of the Widen
+ // overloads. We provide here a default implementation for one given a "real"
+ // implementation of the other. Otherwise, there will be an infinite loop!
+ //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+ public override Element! Widen(Element! a, Element! b)
+ {
+ return Widen(a, IdentityCombineNameMap.Map, b, IdentityCombineNameMap.Map);
+ }
+
+ public virtual Element! Widen(Element! a, ICombineNameMap! aToResult, Element! b, ICombineNameMap! bToResult)
+ {
+ return Widen(ApplyCombineNameMap(a,aToResult), ApplyCombineNameMap(b,bToResult));
+ }
+
+
+ /// <summary>
+ /// Returns the predicate that corresponds to the given lattice element.
+ /// </summary>
+ public abstract IExpr! ToPredicate(Element! e);
+
+ /// <summary>
+ /// Allows the lattice to specify whether it understands a particular function symbol.
+ ///
+ /// The lattice is always allowed to return "true" even when it really can't do anything
+ /// with such functions; however, it is advantageous to say "false" when possible to
+ /// avoid being called to do certain things.
+ ///
+ /// The arguments to a function are provided for context so that the lattice can say
+ /// true or false for the same function symbol in different situations. For example,
+ /// a lattice may understand the multiplication of a variable and a constant but not
+ /// of two variables. The implementation of a lattice should not hold on to the
+ /// arguments.
+ /// </summary>
+ /// <param name="f">The function symbol.</param>
+ /// <param name="args">The argument context.</param>
+ /// <returns>True if it may understand f, false if it does not understand f.</returns>
+ public abstract bool Understands(IFunctionSymbol! f, IList/*<IExpr!>*/! args);
+
+ /// <summary>
+ /// Return an expression that is equivalent to the given expression that does not
+ /// contain the given variable according to the lattice element and queryable.
+ /// </summary>
+ /// <param name="e">The lattice element.</param>
+ /// <param name="q">A queryable for asking addtional information.</param>
+ /// <param name="expr">The expression to find an equivalent expression.</param>
+ /// <param name="var">The variable to eliminate.</param>
+ /// <param name="prohibitedVars">The set of variables that can't be used in the resulting expression.</param>
+ /// <returns>
+ /// An equivalent expression to <paramref name="expr"/> without <paramref name="var"/>
+ /// or null if not possible.
+ /// </returns>
+ public abstract IExpr/*?*/ EquivalentExpr(Element! e, IQueryable! q, IExpr! expr, IVariable! var, Set/*<IVariable!>*/! prohibitedVars);
+
+ /// <summary>
+ /// Answers a query about whether the given predicate holds given the lattice element.
+ /// </summary>
+ /// <param name="e">The lattice element.</param>
+ /// <param name="pred">The predicate.</param>
+ /// <returns>Yes, No, or Maybe.</returns>
+ public abstract Answer CheckPredicate(Element! e, IExpr! pred);
+
+ /// <summary>
+ /// Answers a disequality about two variables. The same information could be obtained
+ /// by asking CheckPredicate, but a different implementation may be simpler and more
+ /// efficient.
+ /// </summary>
+ /// <param name="e">The lattice element.</param>
+ /// <param name="var1">The first variable.</param>
+ /// <param name="var2">The second variable.</param>
+ /// <returns>Yes, No, or Maybe.</returns>
+ public abstract Answer CheckVariableDisequality(Element! e, IVariable! var1, IVariable! var2);
+
+ /// <summary>
+ /// A default implementation of the <see cref="CheckVariableDisequality"/> given
+ /// the appropriate expression factories by calling CheckPredicate.
+ /// </summary>
+ protected Answer DefaultCheckVariableDisequality(
+ IPropExprFactory! propExprFactory, IValueExprFactory! valExprFactory,
+ Element! e, IVariable! var1, IVariable! var2)
+ {
+ return this.CheckPredicate(e, propExprFactory.Not(valExprFactory.Eq(var1, var2)));
+ }
+
+ private Element! ApplyCombineNameMap(Element! e, ICombineNameMap! eToResult)
+ {
+ Element! result = e;
+
+ foreach (G.KeyValuePair<IVariable!,ISet/*<IVariable!>*/!> entry in eToResult.GetSourceToResult())
+ {
+ IVariable! sourceName = entry.Key;
+ ISet/*<IVariable!*/! resultNames = entry.Value;
+
+ // Renaming s to r is okay if
+ // (1) s is not used in the result
+ // and (2) s has not been renamed already
+ bool renameOkay = !resultNames.Contains(sourceName);
+ IVariable! representative = sourceName;
+
+ foreach (IVariable! rname in resultNames)
+ {
+ // skip if sourceName and rname are the same
+ if (object.Equals(sourceName, rname)) { continue; }
+
+ if (renameOkay)
+ {
+ result = this.Rename(result, sourceName, rname);
+ representative = rname; // representative now rname
+ renameOkay = false; // no longer okay to rename
+ }
+ else
+ {
+ result = this.Constrain(result, valueExprFactory.Eq(representative, rname));
+ }
+ }
+ }
+
+ return result;
+ }
+
+ private sealed class IdentityCombineNameMap : ICombineNameMap
+ {
+ public static readonly IdentityCombineNameMap! Map = new IdentityCombineNameMap();
+
+ private static readonly G.Dictionary<IVariable!,ISet/*<IVariable!>*/!>! emptyDictionary1 = new G.Dictionary<IVariable!,ISet/*<IVariable!>*/!>();
+ private static readonly G.Dictionary<IVariable!,IVariable!>! emptyDictionary2 = new G.Dictionary<IVariable!,IVariable!>();
+
+ public ISet/*<IVariable!>*//*?*/ GetResultNames(IVariable! srcname)
+ {
+ ArraySet a = new ArraySet();
+ a.Add(srcname);
+ return a;
+ }
+
+ public IVariable/*?*/ GetSourceName(IVariable! resname)
+ {
+ return resname;
+ }
+
+ //TODO: uncomment when works in compiler
+ //public G.IEnumerable<G.KeyValuePair<IVariable!,ISet/*<IVariable!>*/!>> GetSourceToResult()
+ public IEnumerable! GetSourceToResult()
+ {
+ return emptyDictionary1;
+ }
+
+ //public G.IEnumerable<G.KeyValuePair<IVariable!,IVariable!>> GetResultToSource()
+ public IEnumerable! GetResultToSource()
+ {
+ return emptyDictionary2;
+ }
+
+ private IdentityCombineNameMap() { }
+ }
+
+ public abstract string! ToString(Element! e); // for debugging
+
+ #region Support for MultiLattice to uniquely number every subclass of Lattice
+
+ private static Hashtable/*<System.Type,int>*/! indexMap = new Hashtable();
+ private static Hashtable/*<int,Lattice>*/! reverseIndexMap = new Hashtable();
+ private static int globalCount = 0;
+
+ protected virtual object! UniqueId { get { return (!)this.GetType(); } }
+
+ public int Index
+ {
+ get
+ {
+ object unique = this.UniqueId;
+ if (indexMap.ContainsKey(unique))
+ {
+ object index = indexMap[unique];
+ assert index != null; // this does nothing for nonnull analysis
+ if (index != null) { return (int)index; }
+ return 0;
+ }
+ else
+ {
+ int myIndex = globalCount++;
+ indexMap[unique] = myIndex;
+ reverseIndexMap[myIndex] = this;
+ return myIndex;
+ }
+ }
+ }
+
+ public static Lattice GetGlobalLattice(int i) { return reverseIndexMap[i] as Lattice; }
+ #endregion
+
+ public static bool LogSwitch = false;
+ }
+
+
+ /// <summary>
+ /// Defines the relation between names used in the respective input lattice elements to the
+ /// various combination operators (Join,Widen,Meet,AtMost) and the names that should be used
+ /// in the resulting lattice element.
+ /// </summary>
+ public interface ICombineNameMap
+ {
+ ISet/*<IVariable!>*//*?*/ GetResultNames(IVariable! srcname);
+ IVariable/*?*/ GetSourceName(IVariable! resname);
+
+ //TODO: uncommet when works in compiler
+ //G.IEnumerable<G.KeyValuePair<IVariable!,ISet/*<IVariable!>*/!>> GetSourceToResult();
+ IEnumerable! GetSourceToResult();
+ //G.IEnumerable<G.KeyValuePair<IVariable!,IVariable!>> GetResultToSource();
+ IEnumerable! GetResultToSource();
+ }
+
+ /// <summary>
+ /// Provides statistics on the number of times an operation is performed
+ /// and forwards the real operations to the given lattice in the constructor.
+ /// </summary>
+ public class StatisticsLattice : Lattice
+ {
+ readonly Lattice! lattice;
+ int eliminateCount;
+ int renameCount;
+ int constrainCount;
+ int toPredicateCount;
+ int atMostCount;
+ int topCount;
+ int bottomCount;
+ int isTopCount;
+ int isBottomCount;
+ int joinCount;
+ int meetCount;
+ int widenCount;
+ int understandsCount;
+ int equivalentExprCount;
+ int checkPredicateCount;
+ int checkVariableDisequalityCount;
+
+ public StatisticsLattice(Lattice! lattice)
+ : base(lattice.valueExprFactory)
+ {
+ this.lattice = lattice;
+ // base(lattice.valueExprFactory);
+ }
+
+ public override Element! Eliminate(Element! e, IVariable! variable)
+ {
+ eliminateCount++;
+ return lattice.Eliminate(e, variable);
+ }
+
+ public override Element! Rename(Element! e, IVariable! oldName, IVariable! newName)
+ {
+ renameCount++;
+ return lattice.Rename(e, oldName, newName);
+ }
+
+ public override Element! Constrain(Element! e, IExpr! expr)
+ {
+ constrainCount++;
+ return lattice.Constrain(e, expr);
+ }
+
+
+ public override bool Understands(IFunctionSymbol! f, IList! args)
+ {
+ understandsCount++;
+ return lattice.Understands(f, args);
+ }
+
+
+ public override IExpr/*?*/ EquivalentExpr(Element! e, IQueryable! q, IExpr! expr, IVariable! var, ISet/*<IVariable!>*/! prohibitedVars)
+ {
+ equivalentExprCount++;
+ return lattice.EquivalentExpr(e, q, expr, var, prohibitedVars);
+ }
+
+
+ public override Answer CheckPredicate(Element! e, IExpr! pred)
+ {
+ checkPredicateCount++;
+ return lattice.CheckPredicate(e, pred);
+ }
+
+
+ public override Answer CheckVariableDisequality(Element! e, IVariable! var1, IVariable! var2)
+ {
+ checkVariableDisequalityCount++;
+ return lattice.CheckVariableDisequality(e, var1, var2);
+ }
+
+
+
+ public override IExpr! ToPredicate(Element! e)
+ {
+ toPredicateCount++;
+ return lattice.ToPredicate(e);
+ }
+
+ public override string! ToString(Element! e)
+ {
+ return lattice.ToString(e);
+ }
+
+ [Pure][Reads(ReadsAttribute.Reads.Owned)]
+ public override string! ToString()
+ {
+ return string.Format(
+ "StatisticsLattice: #Eliminate={0} #Rename={1} #Constrain={2} #ToPredicate={3} " +
+ "#Understands={4} #EquivalentExpr={5} #CheckPredicate={6} #CheckVariableDisequality={7} " +
+ "#AtMost={8} #Top={9} #Bottom={9} #IsTop={10} #IsBottom={11} " +
+ "#NonTrivialJoin={12} #NonTrivialMeet={13} #Widen={14}",
+ eliminateCount, renameCount, constrainCount, toPredicateCount,
+ understandsCount, equivalentExprCount, checkPredicateCount, checkVariableDisequalityCount,
+ atMostCount, topCount, bottomCount, isTopCount, isBottomCount,
+ joinCount, meetCount, widenCount);
+ }
+
+ protected override bool AtMost(Element! a, Element! b)
+ {
+ atMostCount++;
+ return lattice.LowerThan(a, b);
+ }
+
+ public override Element! Top
+ {
+ get
+ {
+ topCount++;
+ return lattice.Top;
+ }
+ }
+ public override Element! Bottom
+ {
+ get
+ {
+ bottomCount++;
+ return lattice.Bottom;
+ }
+ }
+
+ public override bool IsTop(Element! e)
+ {
+ isTopCount++;
+ return lattice.IsTop(e);
+ }
+
+ public override bool IsBottom(Element! e)
+ {
+ isBottomCount++;
+ return lattice.IsBottom(e);
+ }
+
+ public override Element! NontrivialJoin(Element! a, Element! b)
+ {
+ joinCount++;
+ return lattice.NontrivialJoin(a, b);
+ }
+
+ public override Element! NontrivialMeet(Element! a, Element! b)
+ {
+ meetCount++;
+ return lattice.NontrivialMeet(a, b);
+ }
+
+ public override Element! Widen(Element! a, Element! b)
+ {
+ widenCount++;
+ return lattice.Widen(a, b);
+ }
+
+ public override void Validate()
+ {
+ base.Validate();
+ lattice.Validate();
+ }
+
+ protected override object! UniqueId
+ {
+ get
+ {
+ // use the base id, not the underlying-lattice id (is that the right thing to do?)
+ return base.UniqueId;
+ }
+ }
+ }
+
+
+ public sealed class LatticeQueryable : IQueryable
+ {
+ private Lattice! lattice;
+ private Lattice.Element! element;
+
+ public LatticeQueryable(Lattice! lattice, Lattice.Element! element)
+ {
+ this.lattice = lattice;
+ this.element = element;
+ // base();
+ }
+
+ public Answer CheckPredicate(IExpr! pred)
+ {
+ return lattice.CheckPredicate(element, pred);
+ }
+
+ public Answer CheckVariableDisequality(IVariable! var1, IVariable! var2)
+ {
+ return lattice.CheckVariableDisequality(element, var1, var2);
+ }
+ }
+}
diff --git a/Source/AIFramework/Logger.ssc b/Source/AIFramework/Logger.ssc
new file mode 100644
index 00000000..12c3ba08
--- /dev/null
+++ b/Source/AIFramework/Logger.ssc
@@ -0,0 +1,49 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+namespace Microsoft.AbstractInterpretationFramework
+{
+ using System;
+ using System.Diagnostics;
+
+ public class Logger
+ {
+ private string! dbgmsgContext;
+ private static int contextWidth = 0;
+
+ public bool Enabled = false;
+
+ public Logger(string! contextMsg)
+ {
+ this.dbgmsgContext = "[" + contextMsg + "] ";
+ contextWidth = Math.Max(contextWidth, contextMsg.Length + 3);
+ // base();
+ }
+
+ private static System.Text.StringBuilder! dbgmsgIndent = new System.Text.StringBuilder();
+ public void DbgMsgIndent() { dbgmsgIndent.Append(' ', 2); }
+ public void DbgMsgUnindent()
+ { if (dbgmsgIndent.Length >= 2) dbgmsgIndent.Remove(0,2); }
+
+ [ConditionalAttribute("DEBUG")]
+ public void DbgMsg(string msg)
+ {
+ if (Enabled)
+ Debug.WriteLine(dbgmsgContext.PadRight(contextWidth) + dbgmsgIndent + msg);
+ }
+ [ConditionalAttribute("DEBUG")]
+ public void DbgMsgNoLine(string msg)
+ {
+ if (Enabled)
+ Debug.Write(dbgmsgContext.PadRight(contextWidth) + dbgmsgIndent + msg);
+ }
+ [ConditionalAttribute("DEBUG")]
+ public void DbgMsgPlain(string msg)
+ {
+ if (Enabled)
+ Debug.Write(msg);
+ }
+ }
+}
diff --git a/Source/AIFramework/MultiLattice.ssc b/Source/AIFramework/MultiLattice.ssc
new file mode 100644
index 00000000..b6b6ba5e
--- /dev/null
+++ b/Source/AIFramework/MultiLattice.ssc
@@ -0,0 +1,563 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+namespace Microsoft.AbstractInterpretationFramework
+{
+ using Microsoft.Contracts;
+ using System.Collections;
+ using System.Collections.Generic;
+ using System.Diagnostics;
+ using Microsoft.AbstractInterpretationFramework.Collections;
+
+ using Microsoft.Boogie;
+ using ISet = Microsoft.Boogie.Set;
+
+
+ /// <summary>
+ /// The cartesian product lattice.
+ /// </summary>
+ public class MultiLattice : Lattice, IEnumerable
+ {
+ internal class Elt : Element
+ {
+ public /*MaybeNull*/Element[] elementPerLattice;
+
+ public Elt(int domainCount, bool isBottom)
+ {
+ this.elementPerLattice = (domainCount == 0 && isBottom) ? null : new Element[domainCount];
+ }
+
+ private Elt(Elt! other)
+ {
+ Element[] otherEPL = other.elementPerLattice;
+ if (otherEPL != null)
+ {
+ Element[] newEPL = new Element[otherEPL.Length];
+ for (int i = 0; i < newEPL.Length; i++)
+ {
+ newEPL[i] = (Element) ((!)otherEPL[i]).Clone();
+ }
+ this.elementPerLattice = newEPL;
+ }
+ }
+
+ public override Element! Clone()
+ {
+ return new Elt(this);
+ }
+
+ [Pure][Reads(ReadsAttribute.Reads.Owned)]
+ public override string! ToString()
+ {
+// string s = "MultiLattice+Elt{";
+// string sep = "";
+// Element[] epl = this.elementPerLattice;
+// if (epl != null)
+// {
+// foreach (Element! e in epl)
+// {
+// s += sep + e.ToString();
+// sep = ", ";
+// }
+// }
+// return s + "}";
+ if (elementPerLattice == null) return "";
+ System.Text.StringBuilder buffer = new System.Text.StringBuilder();
+ for (int i = 0; i < this.Count; i++)
+ {
+ if (i > 0) buffer.Append("; ");
+ buffer.AppendFormat("{0}", elementPerLattice[i]);
+ }
+ return buffer.ToString();
+ }
+
+ public override void Dump(string! msg) {
+ System.Console.WriteLine("MultiLattice.Elt.Dump({0})", msg);
+ Element[] epl = this.elementPerLattice;
+ if (epl != null) {
+ foreach (Element! e in epl) {
+ e.Dump(msg);
+ }
+ }
+ }
+
+ [Pure][Reads(ReadsAttribute.Reads.Owned)]
+ public override ICollection<IVariable!>! FreeVariables()
+ {
+ List<IVariable!>! list = new List<IVariable!>();
+ for (int i = 0; i < this.Count; i++)
+ {
+ list.AddRange(((!)this[i]).FreeVariables());
+ }
+ return (!)list.AsReadOnly();
+ }
+
+ public static Elt! Top(ArrayList/*<Lattice>*/! lattices)
+ {
+ Elt multiValue = new Elt(lattices.Count, false);
+ for (int i = 0; i < lattices.Count; i++)
+ {
+ Lattice d = (Lattice!)lattices[i];
+ multiValue[d.Index] = d.Top;
+ }
+ Debug.Assert(multiValue.IsValid);
+ return multiValue;
+ }
+
+
+ public static Elt! Bottom(ArrayList/*<Lattice>*/! lattices)
+ {
+ Elt multiValue = new Elt(lattices.Count, true);
+ for (int i = 0; i < lattices.Count; i++)
+ {
+ Lattice d = (Lattice!)lattices[i];
+ multiValue[d.Index] = d.Bottom;
+ }
+ Debug.Assert(multiValue.IsValid);
+ return multiValue;
+ }
+
+ public bool IsValid
+ {
+ get
+ {
+ if (this.elementPerLattice == null) { return true; /*bottom*/ }
+
+ Element[] epl = this.elementPerLattice;
+ for (int i = 0; i < epl.Length; i++)
+ {
+ if (epl[i] == null) { return false; }
+ }
+ return true;
+ }
+ }
+
+ public int Count { get { return this.elementPerLattice == null ? 0 : this.elementPerLattice.Length; } }
+
+ public bool Contains(int i) { return 0 <= i && i < this.Count; }
+
+ public Element this[int i] // just syntactic sugar
+ {
+ get { Element[] epl = this.elementPerLattice; return epl == null ? null : epl[i]; }
+ set { Element[] epl = this.elementPerLattice; if (epl == null) return; epl[i] = value; }
+ }
+
+ } // class
+
+
+
+ ArrayList/*<Lattice>*/! lattices = new ArrayList();
+
+ private readonly IPropExprFactory! propExprFactory;
+
+
+ public MultiLattice(IPropExprFactory! propExprFactory, IValueExprFactory! valueExprFactory)
+ : base(valueExprFactory)
+ {
+ this.propExprFactory = propExprFactory;
+ // base(valueExprFactory);
+ }
+
+
+
+ public void AddLattice(Lattice lattice) { this.lattices.Add(lattice); }
+
+ private Lattice! SubLattice(int i) { return (Lattice!)this.lattices[i]; }
+
+
+ public override Element! Top { get { return Elt.Top(this.lattices); } }
+
+ public override Element! Bottom { get { return Elt.Bottom(this.lattices); } }
+
+
+
+
+ public override bool IsBottom(Element! element)
+ {
+ Elt e = (Elt)element;
+ // The program is errorneous/nonterminating if any subdomain knows it is.
+ //
+ if (e.elementPerLattice == null) { return true; }
+ for (int i = 0; i < e.Count; i++) { if (SubLattice(i).IsBottom((!)e[i])) { return true; } }
+ return false;
+ }
+
+ public override bool IsTop(Element! element)
+ {
+ Elt e = (Elt)element;
+ if (e.elementPerLattice == null) { return false; }
+ // The multidomain knows nothing about the program only if no subdomain
+ // knows anything about it.
+ //
+ for (int i = 0; i < e.Count; i++) { if (!SubLattice(i).IsTop((!)e[i])) { return false; } }
+ return true;
+ }
+
+ protected override bool AtMost(Element! first, Element! second)
+ {
+ Elt a = (Elt)first;
+ Elt b = (Elt)second;
+
+ for (int i = 0; i < a.Count; i++)
+ {
+ Element thisElement = (!) a[i];
+ Element thatElement = (!) b[i];
+ if (thisElement.GetType() != thatElement.GetType())
+ {
+ throw new System.InvalidOperationException(
+ "AtMost called on MultiDomain objects with different lattices"
+ );
+ }
+ if (!SubLattice(i).LowerThan(thisElement, thatElement)) { return false; }
+ }
+ return true;
+ }
+
+ protected override bool AtMost(Element! first, ICombineNameMap! firstToResult, Element! second, ICombineNameMap! secondToResult)
+ {
+ Elt a = (Elt)first;
+ Elt b = (Elt)second;
+
+ for (int i = 0; i < a.Count; i++)
+ {
+ Element thisElement = (!) a[i];
+ Element thatElement = (!) b[i];
+ if (thisElement.GetType() != thatElement.GetType())
+ {
+ throw new System.InvalidOperationException(
+ "AtMost called on MultiDomain objects with different lattices"
+ );
+ }
+ if (!SubLattice(i).LowerThan(thisElement, firstToResult, thatElement, secondToResult)) { return false; }
+ }
+ return true;
+ }
+
+
+ private enum CombineOp { Meet, Join, Widen }
+
+ private Element! Combine(Element! first, ICombineNameMap/*?*/ firstToResult, Element! second, ICombineNameMap/*?*/ secondToResult, CombineOp c)
+ {
+ Elt a = (Elt)first;
+ Elt b = (Elt)second;
+
+ int unionCount = System.Math.Max(a.Count, b.Count);
+ Elt combined = new Elt(unionCount, IsBottom(a) && IsBottom(b));
+ for (int i = 0; i < unionCount; i++)
+ {
+ bool thisExists = a.Contains(i);
+ bool thatExists = b.Contains(i);
+
+ if (thisExists && thatExists)
+ {
+ Lattice.Element suba = a[i];
+ Lattice.Element subb = b[i];
+ assert suba != null && subb != null;
+
+ switch (c)
+ {
+ case CombineOp.Meet:
+ combined[i] = SubLattice(i).Meet(suba, subb);
+ break;
+ case CombineOp.Join:
+ if (firstToResult != null && secondToResult != null)
+ combined[i] = SubLattice(i).Join(suba, firstToResult, subb, secondToResult);
+ else
+ combined[i] = SubLattice(i).Join(suba, subb);
+ break;
+ case CombineOp.Widen:
+ if (firstToResult != null && secondToResult != null)
+ combined[i] = SubLattice(i).Widen(suba, firstToResult, subb, secondToResult);
+ else
+ combined[i] = SubLattice(i).Widen(suba, subb);
+ break;
+ }
+ }
+ else if (thisExists)
+ {
+ combined[i] = a[i];
+ }
+ else
+ {
+ combined[i] = b[i];
+ }
+ }
+ Debug.Assert(combined.IsValid);
+ return combined;
+ }
+
+ public override Element! NontrivialJoin(Element! a, Element! b) { return this.Combine(a, null, b, null, CombineOp.Join); }
+
+ public override Element! NontrivialJoin(Element! a, ICombineNameMap! aToResult, Element! b, ICombineNameMap! bToResult) { return this.Combine(a, aToResult, b, bToResult, CombineOp.Join); }
+
+ public override Element! NontrivialMeet(Element! a, Element! b) { return this.Combine(a, null, b, null, CombineOp.Meet); }
+
+ public override Element! Widen(Element! a, Element! b) { return this.Combine(a, null, b, null, CombineOp.Widen); }
+
+ public override Element! Widen(Element! a, ICombineNameMap! aToResult, Element! b, ICombineNameMap! bToResult) { return this.Combine(a, aToResult, b, bToResult, CombineOp.Widen); }
+
+ public override Element! Eliminate(Element! element, IVariable! variable)
+ {
+ Elt e = (Elt)element;
+ if (IsBottom(e))
+ {
+ return e;
+ }
+ Elt newValue = new Elt(e.Count, false);
+ for (int i = 0; i < this.lattices.Count; i++)
+ {
+ newValue[i] = SubLattice(i).Eliminate((!) e[i], variable);
+ }
+ return newValue;
+ }
+
+
+ public override Element! Constrain(Element! element, IExpr! expr)
+ {
+ Elt e = (Elt)element;
+ if (IsBottom(e))
+ {
+ return e;
+ }
+ Elt newValue = new Elt(e.Count, false);
+ for (int i = 0; i < this.lattices.Count; i++)
+ {
+ newValue[i] = SubLattice(i).Constrain((!)e[i], expr);
+ }
+ return newValue;
+ }
+
+
+ public override Element! Rename(Element! element, IVariable! oldName, IVariable! newName)
+ {
+ Elt e = (Elt)element;
+ if (IsBottom(e))
+ {
+ return e;
+ }
+ Elt newValue = new Elt(e.Count, false);
+ for (int i = 0; i < this.lattices.Count; i++)
+ {
+ newValue[i] = SubLattice(i).Rename((!)e[i], oldName, newName);
+ }
+ return newValue;
+ }
+
+
+ public override bool Understands(IFunctionSymbol! f, IList! args)
+ {
+ bool result = false;
+
+ for (int i = 0; i < this.lattices.Count; i++)
+ {
+ result = (result || SubLattice(i).Understands(f, args));
+ }
+
+ return result;
+ }
+
+
+ public override string! ToString(Element! element)
+ {
+ Elt e = (Elt)element;
+ return e.ToString();
+ }
+
+
+ public override IExpr! ToPredicate(Element! element)
+ {
+ Elt e = (Elt)element;
+
+ IExpr result = propExprFactory.True;
+ for (int i = 0; i < e.Count; i++)
+ {
+ IExpr conjunct = SubLattice(i).ToPredicate((!)e[i]);
+ assert conjunct != null;
+
+ result = Prop.SimplifiedAnd(propExprFactory, conjunct, result);
+ }
+ return result;
+ }
+
+ /// <summary>
+ /// Return an expression that is equivalent to the given expression that does not
+ /// contain the given variable according to the lattice element and queryable.
+ ///
+ /// Simply asks each sublattice to try to generate an equivalent expression. We
+ /// do not try to combine information to infer new equivalences here.
+ /// </summary>
+ /// <param name="e">The lattice element.</param>
+ /// <param name="q">A queryable for asking addtional information.</param>
+ /// <param name="expr">The expression to find an equivalent expression.</param>
+ /// <param name="var">The variable to eliminate.</param>
+ /// <returns>
+ /// An equivalent expression to <paramref name="expr"/> without <paramref name="var"/>
+ /// or null if not possible.
+ /// </returns>
+ public override IExpr/*?*/ EquivalentExpr(Element! element, IQueryable! q, IExpr! expr, IVariable! var, Set/*<IVariable!>*/! prohibitedVars)
+ {
+ Elt! e = (Elt!)element;
+
+ for (int i = 0; i < e.Count; i++)
+ {
+ IExpr equivexpr = SubLattice(i).EquivalentExpr((!)e[i], q, expr, var, prohibitedVars);
+
+ if (equivexpr != null)
+ return equivexpr;
+ }
+
+ return null;
+ }
+
+
+ public override Answer CheckPredicate(Element! element, IExpr! pred)
+ {
+ Elt! e = (Elt!)element;
+
+ for (int i = 0; i < e.Count; i++)
+ {
+ Answer ans = SubLattice(i).CheckPredicate((!)e[i], pred);
+
+ if (ans == Answer.Yes || ans == Answer.No)
+ return ans;
+ }
+
+ return Answer.Maybe;
+ }
+
+
+ public override Answer CheckVariableDisequality(Element! element, IVariable! var1, IVariable! var2)
+ {
+ Elt! e = (Elt!)element;
+
+ for (int i = 0; i < e.Count; i++)
+ {
+ Answer ans = SubLattice(i).CheckVariableDisequality((!)e[i], var1, var2);
+
+ if (ans == Answer.Yes || ans == Answer.No)
+ return ans;
+ }
+
+ return Answer.Maybe;
+ }
+
+
+
+ public override void Validate()
+ {
+ base.Validate();
+ foreach (Lattice! l in lattices)
+ {
+ l.Validate();
+ }
+ }
+
+ /// <summary>
+ /// The enumeration over a MultiLattice is its sublattices.
+ /// </summary>
+ /// <returns>An enumerator over the sublattices.</returns>
+ [Pure] [GlobalAccess(false)] [Escapes(true,false)]
+ public IEnumerator/*<Lattice!>*/! GetEnumerator()
+ {
+ return lattices.GetEnumerator();
+ }
+
+ /// <summary>
+ /// Return an enumerable over a mapping of sublattices to the their corresponding
+ /// lattice elements given a MultiLattice element.
+ /// </summary>
+ /// <param name="element">The MultiLattice element.</param>
+ /// <returns>
+ /// An enumerable that yields an IDictionaryEnumerator over the
+ /// (Lattice, Lattice.Element) pairs.
+ /// </returns>
+ public IEnumerable! Subelements(Element! element)
+ {
+ return new SubelementsEnumerable(this, (Elt!) element);
+ }
+
+ /// <summary>
+ /// An enumerator over the sublattices and elements.
+ /// </summary>
+ private sealed class SubelementsEnumerable : IEnumerable
+ {
+ private sealed class SubelementsEnumerator : IDictionaryEnumerator
+ {
+ private readonly IEnumerator/*<Lattice!>*/! multiLatticeIter;
+ private readonly IEnumerator/*<Lattice.Element!>*/! multiElementIter;
+
+ public SubelementsEnumerator(MultiLattice! multiLattice, Elt! multiElement)
+ requires multiElement.elementPerLattice != null;
+ {
+ this.multiLatticeIter = multiLattice.lattices.GetEnumerator();
+ this.multiElementIter = multiElement.elementPerLattice.GetEnumerator();
+ // base();
+ }
+
+ public DictionaryEntry Entry
+ {
+ get
+ {
+ return new DictionaryEntry((!)multiLatticeIter.Current, multiElementIter.Current);
+ }
+ }
+
+ public object Key
+ {
+ get
+ {
+ return multiLatticeIter.Current;
+ }
+ }
+
+ public object Value
+ {
+ get
+ {
+ return multiElementIter.Current;
+ }
+ }
+
+ public object Current
+ {
+ [Pure][Reads(ReadsAttribute.Reads.Owned)]
+ get
+ {
+ return this.Entry;
+ }
+ }
+
+ public bool MoveNext()
+ {
+ return multiLatticeIter.MoveNext() && multiElementIter.MoveNext();
+ }
+
+ public void Reset()
+ {
+ multiLatticeIter.Reset();
+ multiElementIter.Reset();
+ }
+ }
+
+ private MultiLattice! multiLattice;
+ private Elt! multiElement;
+
+ public SubelementsEnumerable(MultiLattice! multiLattice, Elt! multiElement)
+ {
+ this.multiLattice = multiLattice;
+ this.multiElement = multiElement;
+ // base();
+ }
+
+ [Pure] [GlobalAccess(false)] [Escapes(true,false)]
+ public IEnumerator! GetEnumerator()
+ {
+ return new SubelementsEnumerator(multiLattice, multiElement);
+ }
+ }
+
+
+ }
+}
diff --git a/Source/AIFramework/Mutable.ssc b/Source/AIFramework/Mutable.ssc
new file mode 100644
index 00000000..894359ef
--- /dev/null
+++ b/Source/AIFramework/Mutable.ssc
@@ -0,0 +1,117 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+namespace Microsoft.AbstractInterpretationFramework.Collections
+{
+ using System.Collections;
+ using Microsoft.Contracts;
+
+ /// <summary>
+ /// Extend sets for using as a IWorkList.
+ /// </summary>
+ public class WorkSet : Microsoft.Boogie.Set, Microsoft.Boogie.IWorkList
+ {
+
+ // See Bug #148 for an explanation of why this is here.
+ // Without it, the contract inheritance rules will complain since it
+ // has nowhere to attach the out-of-band contract it gets from
+ // ICollection.Count that it gets from IWorkList.
+ [Pure][Reads(ReadsAttribute.Reads.Owned)]
+ public override int Count { get { return base.Count; } }
+
+ [Pure][Reads(ReadsAttribute.Reads.Owned)] public bool IsEmpty()
+ {
+ return Count == 0;
+ }
+
+ /// <summary>
+ /// Pull an element out of the workset.
+ /// </summary>
+ public object Pull()
+ {
+ IEnumerator iter = GetEnumerator();
+ iter.MoveNext();
+
+ object result = (!)iter.Current;
+ Remove(result);
+
+ return result;
+ }
+
+ bool Microsoft.Boogie.IWorkList.Add(object o){
+ if (o == null) throw new System.ArgumentNullException();
+ this.Add(o);
+ return true;
+ }
+ bool Microsoft.Boogie.IWorkList.AddAll(IEnumerable objs){
+ if (objs == null) throw new System.ArgumentNullException();
+ return this.AddAll(objs);
+ }
+
+ // ICollection members
+ public void CopyTo (System.Array! a, int i) {
+ if (this.Count > a.Length - i) throw new System.ArgumentException();
+ int j = i;
+ foreach(object o in this){
+ a.SetValue(o, j++);
+ }
+ return;
+ }
+ object! ICollection.SyncRoot { [Pure] get { return this; } }
+ public bool IsSynchronized { get { return false; } }
+
+ }
+}
+
+namespace Microsoft.AbstractInterpretationFramework.Collections.Generic
+{
+ using System.Collections.Generic;
+
+ public class HashMultiset<T>
+ {
+ private readonly IDictionary<T,int>! dict;
+
+ //invariant forall{KeyValuePair<T,int> entry in dict; entry.Value >= 1};
+
+ public HashMultiset()
+ {
+ this.dict = new Dictionary<T,int>();
+ // base();
+ }
+
+ public HashMultiset(int size)
+ {
+ this.dict = new Dictionary<T,int>(size);
+ // base();
+ }
+
+ public void Add(T t)
+ { expose (this) {
+ if (dict.ContainsKey(t))
+ {
+ dict[t] = dict[t] + 1;
+ }
+ else
+ {
+ dict.Add(t,1);
+ }
+ }}
+
+ public void Remove(T t)
+ {
+ if (dict.ContainsKey(t))
+ { expose (this) {
+ int count = dict[t];
+ if (count == 1) { dict.Remove(t); }
+ else { dict[t] = count - 1; }
+ }}
+ }
+
+ public bool Contains(T t)
+ {
+ return dict.ContainsKey(t);
+ }
+ }
+}
diff --git a/Source/AIFramework/Polyhedra/LinearConstraint.ssc b/Source/AIFramework/Polyhedra/LinearConstraint.ssc
new file mode 100644
index 00000000..9ce1552b
--- /dev/null
+++ b/Source/AIFramework/Polyhedra/LinearConstraint.ssc
@@ -0,0 +1,588 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using Microsoft.Contracts;
+namespace Microsoft.AbstractInterpretationFramework
+{
+ using System;
+ using System.Compiler;
+ using System.Collections;
+ using Microsoft.Basetypes;
+ using IMutableSet = Microsoft.Boogie.Set;
+ using HashSet = Microsoft.Boogie.Set;
+ using ISet = Microsoft.Boogie.Set;
+
+
+ /// <summary>
+ /// Represents a single linear constraint, coefficients are stored as Rationals.
+ /// </summary>
+ public class LinearConstraint
+ {
+
+ public enum ConstraintRelation
+ {
+ EQ, // equal
+ LE, // less-than or equal
+ }
+
+ public readonly ConstraintRelation Relation;
+ internal Hashtable /*IVariable->Rational*/! coefficients = new Hashtable /*IVariable->Rational*/ ();
+ internal Rational rhs;
+
+ public LinearConstraint (ConstraintRelation rel)
+ {
+ Relation = rel;
+ }
+
+ [Pure][Reads(ReadsAttribute.Reads.Owned)]
+ public override string! ToString()
+ {
+ string s = null;
+ foreach (DictionaryEntry /*IVariable->Rational*/ entry in coefficients)
+ {
+ if (s == null)
+ {
+ s = "";
+ }
+ else
+ {
+ s += " + ";
+ }
+ s += String.Format("{0}*{1}", entry.Value, entry.Key);
+ }
+ System.Diagnostics.Debug.Assert(s != null, "malformed LinearConstraint: no variables");
+ s += String.Format(" {0} {1}", Relation == ConstraintRelation.EQ ? "==" : "<=", rhs);
+ return s;
+ }
+
+
+#if DONT_KNOW_HOW_TO_TAKE_THE_TYPE_OF_AN_IVARIABLE_YET
+ public bool IsOverIntegers
+ {
+ get
+ {
+ foreach (DictionaryEntry /*IVariable->Rational*/ entry in coefficients)
+ {
+ IVariable var = (IVariable)entry.Key;
+ if ( ! var.TypedIdent.Type.IsInt) { return false; }
+ }
+ return true;
+ }
+ }
+#endif
+
+
+ /// <summary>
+ /// Note: This method requires that all dimensions are of type Variable, something that's
+ /// not required elsewhere in this class.
+ /// </summary>
+ /// <returns></returns>
+ public IExpr! ConvertToExpression(ILinearExprFactory! factory)
+ {
+ IExpr leftSum = null;
+ IExpr rightSum = null;
+ foreach (DictionaryEntry /*object->Rational*/ entry in coefficients)
+ {
+ IVariable var = (IVariable)entry.Key;
+ Rational coeff = (Rational) ((!)entry.Value);
+ if (coeff.IsPositive)
+ {
+ leftSum = AddTerm(factory, leftSum, coeff, var);
+ }
+ else if (coeff.IsNegative)
+ {
+ rightSum = AddTerm(factory, rightSum, -coeff, var);
+ }
+ else
+ {
+ // ignore the term is coeff==0
+ }
+ }
+
+ if (leftSum == null && rightSum == null)
+ {
+ // there are no variables in this constraint
+ if (Relation == ConstraintRelation.EQ ? rhs.IsZero : rhs.IsNonNegative) {
+ return factory.True;
+ } else {
+ return factory.False;
+ }
+ }
+
+ if (leftSum == null || (rightSum != null && rhs.IsNegative))
+ {
+ // show the constant on the left side
+ leftSum = AddTerm(factory, leftSum, -rhs, null);
+ }
+ else if (rightSum == null || rhs.IsPositive)
+ {
+ // show the constant on the right side
+ rightSum = AddTerm(factory, rightSum, rhs, null);
+ }
+
+ assert leftSum != null;
+ assert rightSum != null;
+ return Relation == ConstraintRelation.EQ ? factory.Eq(leftSum, rightSum) : factory.AtMost(leftSum, rightSum);
+ }
+
+ /// <summary>
+ /// Returns an expression that denotes sum + r*x.
+ /// If sum==null, drops the "sum +".
+ /// If x==null, drops the "*x".
+ /// if x!=null and r==1, drops the "r*".
+ /// </summary>
+ /// <param name="factory"></param>
+ /// <param name="sum"></param>
+ /// <param name="r"></param>
+ /// <param name="x"></param>
+ static IExpr! AddTerm(ILinearExprFactory! factory, /*MayBeNull*/ IExpr sum, Rational r, /*MayBeNull*/ IVariable x)
+ {
+ IExpr! product = factory.Term(r, x);
+ if (sum == null) {
+ return product;
+ } else {
+ return factory.Add(sum, product);
+ }
+ }
+
+ public ISet /*IVariable!*/! GetDefinedDimensions()
+ {
+ HashSet /*IVariable!*/ dims = new HashSet /*IVariable!*/ (coefficients.Count);
+ int j = 0;
+ foreach (IVariable! dim in coefficients.Keys)
+ {
+ dims.Add(dim);
+ j++;
+ }
+ System.Diagnostics.Debug.Assert(j == coefficients.Count);
+ return dims;
+ }
+
+ /// <summary>
+ /// Returns true iff all of the coefficients in the constraint are 0. In that
+ /// case, the constraint has the form 0 &lt;= C for some constant C; hence, the
+ /// constraint is either unsatisfiable or trivially satisfiable.
+ /// </summary>
+ /// <returns></returns>
+ public bool IsConstant()
+ {
+ foreach (Rational coeff in coefficients.Values)
+ {
+ if (coeff.IsNonZero)
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /// <summary>
+ /// For an equality constraint, returns 0 == rhs.
+ /// For an inequality constraint, returns 0 &lt;= rhs.
+ /// </summary>
+ public bool IsConstantSatisfiable()
+ {
+ if (Relation == ConstraintRelation.EQ)
+ {
+ return rhs.IsZero;
+ }
+ else
+ {
+ return rhs.IsNonNegative;
+ }
+ }
+
+ /// <summary>
+ /// Returns 0 if "this" and "c" are not equivalent constraints. If "this" and "c"
+ /// are equivalent constraints, the non-0 return value "m" satisfies "this == m*c".
+ /// </summary>
+ /// <param name="c"></param>
+ /// <returns></returns>
+ public Rational IsEquivalent(LinearConstraint! c)
+ {
+ // "m" is the scale factor. If it is 0, it hasn't been used yet. If it
+ // is non-0, it will remain that value throughout, and it then says that
+ // for every dimension "d", "this[d] == m * c[d]".
+ Rational m = Rational.ZERO;
+
+ ArrayList /*IVariable*/ dd = new ArrayList /*IVariable*/ ();
+ foreach (IVariable! d in this.GetDefinedDimensions())
+ {
+ if (!dd.Contains(d)) { dd.Add(d); }
+ }
+ foreach (IVariable! d in c.GetDefinedDimensions())
+ {
+ if (!dd.Contains(d)) { dd.Add(d); }
+ }
+
+ foreach (IVariable! d in dd)
+ {
+ Rational a = this[d];
+ Rational b = c[d];
+
+ if (a.IsZero || b.IsZero)
+ {
+ if (a.IsNonZero || b.IsNonZero)
+ {
+ return Rational.ZERO; // not equivalent
+ }
+ }
+ else if (m.IsZero)
+ {
+ m = a / b;
+ }
+ else if (a != m * b)
+ {
+ return Rational.ZERO; // not equivalent
+ }
+ }
+
+ // we expect there to have been some non-zero coefficient, so "m" should have been used by now
+ System.Diagnostics.Debug.Assert(m.IsNonZero);
+
+ // finally, check the rhs
+ if (this.rhs == m * c.rhs)
+ {
+ return m; // equivalent
+ }
+ else
+ {
+ return Rational.ZERO; // not equivalent
+ }
+ }
+
+ /// <summary>
+ /// Splits an equality constraint into two inequality constraints, the conjunction of
+ /// which equals the equality constraint. Assumes "this" is a equality constraint.
+ /// </summary>
+ /// <param name="a"></param>
+ /// <param name="b"></param>
+ public void GenerateInequalityConstraints(out LinearConstraint a, out LinearConstraint b)
+ {
+ System.Diagnostics.Debug.Assert(this.Relation == ConstraintRelation.EQ);
+
+ a = new LinearConstraint(ConstraintRelation.LE);
+ a.coefficients = (Hashtable)this.coefficients.Clone();
+ a.rhs = this.rhs;
+
+ b = new LinearConstraint(ConstraintRelation.LE);
+ b.coefficients = new Hashtable /*IVariable->Rational*/ ();
+ foreach (DictionaryEntry entry in this.coefficients)
+ {
+ b.coefficients[entry.Key] = -(Rational) ((!)entry.Value);
+ }
+ b.rhs = -this.rhs;
+ }
+
+ public void SetCoefficient(IVariable! dimension, Rational coefficient)
+ {
+ coefficients[dimension] = coefficient;
+ }
+
+ /// <summary>
+ /// Removes dimension "dim" from the constraint. Only dimensions with coefficient 0 can
+ /// be removed.
+ /// </summary>
+ /// <param name="dim"></param>
+ public void RemoveDimension(IVariable! dim)
+ {
+ object val = coefficients[dim];
+ if (val != null)
+ {
+#if FIXED_SERIALIZER
+ assert ((Rational)val).IsZero;
+#endif
+ coefficients.Remove(dim);
+ }
+ }
+
+ /// <summary>
+ /// The getter returns 0 if the dimension is not present.
+ /// </summary>
+ public Rational this [IVariable! dimension]
+ {
+ get
+ {
+ object z = coefficients[dimension];
+ if (z == null)
+ {
+ return Rational.ZERO;
+ }
+ else
+ {
+ return (Rational)z;
+ }
+ }
+ set { SetCoefficient(dimension, value); }
+ }
+
+ public LinearConstraint Rename(IVariable! oldName, IVariable! newName)
+ {
+ object /*Rational*/ z = coefficients[oldName];
+ if (z == null)
+ {
+ return this;
+ }
+ else
+ {
+ System.Diagnostics.Debug.Assert(z is Rational);
+ Hashtable /*IVariable->Rational*/ newCoeffs = (Hashtable! /*IVariable->Rational*/)coefficients.Clone();
+ newCoeffs.Remove(oldName);
+ newCoeffs.Add(newName, z);
+
+ LinearConstraint lc = new LinearConstraint(this.Relation);
+ lc.coefficients = newCoeffs;
+ lc.rhs = this.rhs;
+ return lc;
+ }
+ }
+
+ public LinearConstraint Clone()
+ {
+ LinearConstraint z = new LinearConstraint(Relation);
+ z.coefficients = (Hashtable /*IVariable->Rational*/)this.coefficients.Clone();
+ z.rhs = this.rhs;
+ return z;
+ }
+
+ /// <summary>
+ /// Returns a constraint like "this", but with the given relation "r".
+ /// </summary>
+ /// <returns></returns>
+ public LinearConstraint! ChangeRelation(ConstraintRelation rel)
+ {
+ if (Relation == rel)
+ {
+ return this;
+ }
+ else
+ {
+ LinearConstraint z = new LinearConstraint(rel);
+ z.coefficients = (Hashtable)this.coefficients.Clone();
+ z.rhs = this.rhs;
+ return z;
+ }
+ }
+
+ /// <summary>
+ /// Returns a constraint like "this", but, conceptually, with the inequality relation >=.
+ /// </summary>
+ /// <returns></returns>
+ public LinearConstraint! ChangeRelationToAtLeast()
+ {
+ LinearConstraint z = new LinearConstraint(ConstraintRelation.LE);
+ foreach (DictionaryEntry /*IVariable->Rational*/ entry in this.coefficients)
+ {
+ z.coefficients.Add(entry.Key, -(Rational) ((!)entry.Value));
+ }
+ z.rhs = -this.rhs;
+ return z;
+ }
+
+ /// <summary>
+ /// Returns the left-hand side of the constraint evaluated at the point "v".
+ /// Any coordinate not present in "v" is treated as if it were 0.
+ /// Stated differently, this routine treats the left-hand side of the constraint
+ /// as a row vector and "v" as a column vector, and then returns the dot-product
+ /// of the two.
+ /// </summary>
+ /// <param name="v"></param>
+ /// <returns></returns>
+ public Rational EvaluateLhs(FrameElement! v)
+ {
+ Rational q = Rational.ZERO;
+ foreach (DictionaryEntry /*IVariable,Rational*/ term in coefficients)
+ {
+ IVariable dim = (IVariable!)term.Key;
+ Rational a = (Rational) ((!)term.Value);
+ Rational x = v[dim];
+ q += a * x;
+ }
+ return q;
+ }
+
+ /// <summary>
+ /// Determines whether or not a given vertex or ray saturates the constraint.
+ /// </summary>
+ /// <param name="fe"></param>
+ /// <param name="vertex">true if "fe" is a vertex; false if "fe" is a ray</param>
+ /// <returns></returns>
+ public bool IsSaturatedBy(FrameElement! fe, bool vertex)
+ {
+ Rational lhs = EvaluateLhs(fe);
+ Rational rhs = vertex ? this.rhs : Rational.ZERO;
+ return lhs == rhs;
+ }
+
+ /// <summary>
+ /// Changes the current constraint A*X &lt;= B into (A + m*aa)*X &lt;= B + m*bb,
+ /// where "cc" is the constraint aa*X &lt;= bb.
+ /// </summary>
+ /// <param name="m"></param>
+ /// <param name="cc"></param>
+ /// <returns></returns>
+ public void AddMultiple(Rational m, LinearConstraint! cc)
+ {
+ foreach (DictionaryEntry /*IVariable->Rational*/ entry in cc.coefficients)
+ {
+ IVariable dim = (IVariable)entry.Key;
+ Rational d = m * (Rational) ((!)entry.Value);
+ if (d.IsNonZero)
+ {
+ object prev = coefficients[dim];
+ if (prev == null)
+ {
+ coefficients[dim] = d;
+ }
+ else
+ {
+ coefficients[dim] = (Rational)prev + d;
+ }
+ }
+ }
+ rhs += m * cc.rhs;
+ }
+
+ /// <summary>
+ /// Try to reduce the magnitude of the coefficients used.
+ /// Has a side effect on the coefficients, but leaves the meaning of the linear constraint
+ /// unchanged.
+ /// </summary>
+ public void Normalize() {
+ // compute the gcd of the numerators and the gcd of the denominators
+ Rational gcd = rhs;
+ foreach (Rational r in coefficients.Values) {
+ gcd = Rational.Gcd(gcd, r);
+ }
+ // Change all coefficients, to divide their numerators with gcdNum and to
+ // divide their denominators with gcdDen.
+ Hashtable /*IVariable->Rational*/ newCoefficients = new Hashtable /*IVariable->Rational*/ (coefficients.Count);
+ foreach (DictionaryEntry /*IVarianble->Rational*/ e in coefficients) {
+ Rational r = (Rational) ((!)e.Value);
+ if (r.IsNonZero) {
+ newCoefficients.Add(e.Key, new Rational(r.Numerator / gcd.Numerator, r.Denominator / gcd.Denominator));
+ } else {
+ newCoefficients.Add(e.Key, r);
+ }
+ }
+
+ coefficients = newCoefficients;
+ rhs = rhs.IsNonZero ? (Rational)new Rational(rhs.Numerator / gcd.Numerator, rhs.Denominator / gcd.Denominator) : rhs;
+ }
+ }
+
+ /// <summary>
+ /// Represents a frame element (vector of dimension/value tuples). Used only
+ /// internally in class LinearConstraintSystem and its communication with class
+ /// LinearConstraint.
+ /// </summary>
+ public class FrameElement
+ {
+
+ Hashtable /*IVariable->Rational*/! terms = new Hashtable /*IVariable->Rational*/ ();
+
+ /// <summary>
+ /// Constructs an empty FrameElement. To add dimensions, call AddCoordinate after construction.
+ /// </summary>
+ public FrameElement()
+ {
+ }
+
+ /// <summary>
+ /// This method is to be thought of as being part of the FrameElement object's construction process.
+ /// Assumes "dimension" is not already in FrameElement.
+ /// </summary>
+ /// <param name="dimension"></param>
+ /// <param name="value"></param>
+ public void AddCoordinate(IVariable! dimension, Rational value)
+ {
+ terms.Add(dimension, value);
+ }
+
+ [Pure][Reads(ReadsAttribute.Reads.Owned)]
+ public override string! ToString()
+ {
+ string s = null;
+ foreach (DictionaryEntry item in terms)
+ {
+ if (s == null)
+ {
+ s = "(";
+ }
+ else
+ {
+ s += ", ";
+ }
+ s += String.Format("<{0},{1}>", item.Key, (Rational) ((!)item.Value));
+ }
+ if (s == null)
+ {
+ s = "(";
+ }
+ return s + ")";
+ }
+
+ public IMutableSet /*IVariable!*/! GetDefinedDimensions()
+ {
+ HashSet /*IVariable!*/! dims = new HashSet /*IVariable!*/ (terms.Count);
+ foreach (IVariable! dim in terms.Keys)
+ {
+ dims.Add(dim);
+ }
+ System.Diagnostics.Debug.Assert(dims.Count == terms.Count);
+ return dims;
+ }
+
+ /// <summary>
+ /// The getter returns the value at the given dimension, or 0 if that dimension is not defined.
+ /// </summary>
+ public Rational this [IVariable! dimension]
+ {
+ get
+ {
+ object z = terms[dimension];
+ if (z == null)
+ {
+ return Rational.ZERO;
+ }
+ else
+ {
+ return (Rational)z;
+ }
+ }
+ set
+ {
+ terms[dimension] = value;
+ }
+ }
+
+ public FrameElement Rename(IVariable! oldName, IVariable! newName)
+ {
+ object /*Rational*/ z = terms[oldName];
+ if (z == null)
+ {
+ return this;
+ }
+ else
+ {
+ System.Diagnostics.Debug.Assert(z is Rational);
+ Hashtable /*IVariable->Rational*/ newTerms = (Hashtable! /*IVariable->Rational*/)terms.Clone();
+ newTerms.Remove(oldName);
+ newTerms.Add(newName, z);
+
+ FrameElement fe = new FrameElement();
+ fe.terms = newTerms;
+ return fe;
+ }
+ }
+
+ public FrameElement Clone()
+ {
+ FrameElement z = new FrameElement();
+ z.terms = (Hashtable /*IVariable->Rational*/)this.terms.Clone();
+ return z;
+ }
+ }
+}
diff --git a/Source/AIFramework/Polyhedra/LinearConstraintSystem.ssc b/Source/AIFramework/Polyhedra/LinearConstraintSystem.ssc
new file mode 100644
index 00000000..b4e33a28
--- /dev/null
+++ b/Source/AIFramework/Polyhedra/LinearConstraintSystem.ssc
@@ -0,0 +1,1856 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+namespace Microsoft.AbstractInterpretationFramework
+{
+ using System.Collections;
+ using System.Collections.Generic;
+ using System.Diagnostics;
+ using System;
+ using Microsoft.SpecSharp.Collections;
+ using Microsoft.Contracts;
+ using Microsoft.Basetypes;
+ using IMutableSet = Microsoft.Boogie.Set;
+ using HashSet = Microsoft.Boogie.Set;
+ using ISet = Microsoft.Boogie.Set;
+
+ /// <summary>
+ /// Represents a system of linear constraints (constraint/frame representations).
+ /// </summary>
+ public class LinearConstraintSystem
+ {
+ // --------------------------------------------------------------------------------------------------------
+ // ------------------ Data structure ----------------------------------------------------------------------
+ // --------------------------------------------------------------------------------------------------------
+
+ public /*maybe null*/ ArrayList /*LinearConstraint!*/ Constraints;
+ /*maybe null*/ ArrayList /*FrameElement!*/ FrameVertices;
+ /*maybe null*/ ArrayList /*FrameElement!*/ FrameRays;
+ IMutableSet/*IVariable!*/! FrameDimensions;
+ /*maybe null*/ ArrayList /*FrameElement!*/ FrameLines;
+ // Invariant: Either all of Constraints, FrameVertices, FrameRays, and FrameLines are
+ // null, or all are non-null.
+ // Invariant: Any dimension mentioned in Constraints, FrameVertices, FrameRays, or
+ // FrameLines is mentioned in FrameDimensions.
+ // The meaning of FrameDimensions is that for any dimension x not in FrameDimensions,
+ // there is an implicit line along dimension x (that is, (<x,1>)).
+
+ void CheckInvariant()
+ {
+ if (Constraints == null)
+ {
+ System.Diagnostics.Debug.Assert(FrameVertices == null);
+ System.Diagnostics.Debug.Assert(FrameRays == null);
+ System.Diagnostics.Debug.Assert(FrameLines == null);
+ System.Diagnostics.Debug.Assert(FrameDimensions.Count == 0);
+ }
+ else
+ {
+ System.Diagnostics.Debug.Assert(FrameVertices != null);
+ System.Diagnostics.Debug.Assert(FrameRays != null);
+ System.Diagnostics.Debug.Assert(FrameLines != null);
+
+ foreach (LinearConstraint! cc in Constraints)
+ {
+#if FIXED_DESERIALIZER
+ assert Forall{IVariable! var in cc.GetDefinedDimensions(); FrameDimensions.Contains(var)};
+#endif
+ assert cc.coefficients.Count != 0;
+ }
+ foreach (ArrayList /*FrameElement*/! FrameComponent in new ArrayList /*FrameElement*/ [] {FrameVertices, FrameRays, FrameLines})
+ {
+ foreach (FrameElement fe in FrameComponent)
+ {
+ if (fe == null) continue;
+#if FIXED_DESERIALIZER
+ assert Forall{IVariable! var in fe.GetDefinedDimensions(); FrameDimensions.Contains(var)};
+#endif
+ }
+ }
+ }
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ // ------------------ Constructors ------------------------------------------------------------------------
+ // --------------------------------------------------------------------------------------------------------
+
+ /// <summary>
+ /// Creates a LinearConstraintSystem representing the bottom element, that is, representing
+ /// an unsatisfiable system of constraints.
+ /// </summary>
+ [NotDelayed]
+ public LinearConstraintSystem()
+ {
+ FrameDimensions = new HashSet /*IVariable!*/ ();
+ base();
+ CheckInvariant();
+ }
+
+ /// <summary>
+ /// Constructs a linear constraint system with constraints "cs".
+ /// The constructor captures all constraints in "cs".
+ /// </summary>
+ /// <param name="cs"></param>
+ [NotDelayed]
+ public LinearConstraintSystem(ArrayList /*LinearConstraint!*/! cs)
+#if BUG_159_HAS_BEEN_FIXED
+ requires Forall{LinearConstraint! cc in cs; cc.coefficients.Count != 0};
+#endif
+ {
+ ArrayList constraints = new ArrayList /*LinearConstraint!*/ (cs.Count);
+ foreach (LinearConstraint! cc in cs)
+ {
+ constraints.Add(cc);
+ }
+ Constraints = constraints;
+ FrameDimensions = new HashSet /*IVariable!*/ (); // to please compiler; this value will be overridden in the call to GenerateFrameConstraints below
+ base();
+
+ GenerateFrameFromConstraints();
+ SimplifyConstraints();
+ CheckInvariant();
+#if DEBUG_PRINT
+ Console.WriteLine("LinearConstraintSystem: constructor produced:");
+ Dump();
+#endif
+ }
+
+ /// <summary>
+ /// Constructs a linear constraint system corresponding to given vertex. This constructor
+ /// is only used in the test harness--it is not needed for abstract interpretation.
+ /// </summary>
+ /// <param name="v"></param>
+ [NotDelayed]
+ LinearConstraintSystem(FrameElement! v)
+ {
+ IMutableSet! frameDims = v.GetDefinedDimensions();
+ ArrayList /*LinearConstraint!*/ constraints = new ArrayList /*LinearConstraint!*/ ();
+ foreach (IVariable! dim in frameDims)
+ {
+ LinearConstraint lc = new LinearConstraint(LinearConstraint.ConstraintRelation.EQ);
+ lc.SetCoefficient(dim, Rational.ONE);
+ lc.rhs = v[dim];
+ constraints.Add(lc);
+ }
+ FrameDimensions = frameDims;
+ Constraints = constraints;
+
+ ArrayList /*FrameElement*/ frameVertices = new ArrayList /*FrameElement*/ ();
+ frameVertices.Add(v);
+ FrameVertices = frameVertices;
+
+ FrameRays = new ArrayList /*FrameElement*/ ();
+ FrameLines = new ArrayList /*FrameElement*/ ();
+
+ base();
+ CheckInvariant();
+ }
+
+ void ChangeIntoBottom()
+ {
+ Constraints = null;
+ FrameVertices = null;
+ FrameRays = null;
+ FrameLines = null;
+ IMutableSet ss;
+ FrameDimensions.Clear(); // no implicit lines
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ // ------------------ Public operations and their support routines ----------------------------------------
+ // --------------------------------------------------------------------------------------------------------
+
+ public bool IsBottom()
+ {
+ return Constraints == null;
+ }
+
+ public bool IsTop()
+ {
+ return Constraints != null && Constraints.Count == 0;
+ }
+
+ [Pure][Reads(ReadsAttribute.Reads.Owned)]
+ public override string! ToString()
+ {
+ if (Constraints == null)
+ {
+ return "<bottom>";
+ }
+ else if (Constraints.Count == 0)
+ {
+ return "<top>";
+ }
+ else
+ {
+ string z = null;
+ foreach (LinearConstraint! lc in Constraints)
+ {
+ string s = lc.ToString();
+ if (z == null)
+ {
+ z = s;
+ }
+ else
+ {
+ z += " AND " + s;
+ }
+ }
+ assert z != null;
+ return z;
+ }
+ }
+
+
+ public ICollection<IVariable!>! FreeVariables()
+ ensures result.IsReadOnly;
+ {
+ List<IVariable!> list = new List<IVariable!>();
+ foreach (IVariable! v in FrameDimensions) { list.Add(v); }
+ return (!)list.AsReadOnly();
+ }
+
+ /// <summary>
+ /// Note: This method requires that all dimensions are of type Variable, something that's
+ /// not required elsewhere in this class.
+ /// </summary>
+ /// <returns></returns>
+ public IExpr! ConvertToExpression(ILinearExprFactory! factory)
+ {
+ if (this.Constraints == null) {
+ return factory.False;
+ }
+ if (this.Constraints.Count == 0) {
+ return factory.True;
+ }
+
+ IExpr result = null;
+ foreach (LinearConstraint! lc in Constraints)
+ {
+ IExpr conjunct = lc.ConvertToExpression(factory);
+ result = (result == null) ? conjunct : (IExpr)factory.And(conjunct, result);
+ }
+ assert result != null;
+ return result;
+ }
+
+
+ /* IsSubset(): determines if 'lcs' is a subset of 'this'
+ * -- See Cousot/Halbwachs 1978, section
+ */
+ public bool IsSubset(LinearConstraintSystem! lcs)
+ {
+ if (lcs.IsBottom())
+ {
+ return true;
+ }
+ else if (this.IsBottom())
+ {
+ return false;
+#if DEBUG
+#else
+ } else if (this.IsTop()) { // optimization -- this case not needed for correctness
+ return true;
+ } else if (lcs.IsTop()) { // optimization -- this case not needed for correctness
+ return false;
+#endif
+ }
+ else
+ {
+ // phase 0: check if frame dimensions are a superset of the constraint dimensions
+ ISet /*IVariable!*/! frameDims = lcs.GetDefinedDimensions();
+#if DEBUG_PRINT
+ Console.WriteLine("DEBUG: IsSubset:");
+ Console.WriteLine(" --- this:");
+ this.Dump();
+ Console.WriteLine(" --- lcs:");
+ lcs.Dump();
+ Console.WriteLine(" ---");
+#endif
+ foreach (LinearConstraint! cc in (!)this.Constraints)
+ {
+#if DEBUG_PRINT
+ Console.WriteLine(" cc: {0}", cc);
+ Console.WriteLine(" cc.GetDefinedDimensions(): {0}", cc.GetDefinedDimensions());
+#endif
+ if (!forall{IVariable! var in cc.GetDefinedDimensions(); frameDims.Contains(var)})
+ {
+#if DEBUG_PRINT
+ Console.WriteLine(" ---> phase 0 subset violated, return false from IsSubset");
+#endif
+ return false;
+ }
+ }
+ }
+
+ // phase 1: check frame vertices against each constraint...
+ foreach (FrameElement! v in (!)lcs.FrameVertices)
+ {
+ foreach (LinearConstraint! cc in this.Constraints)
+ {
+ Rational q = cc.EvaluateLhs(v);
+ if (cc.Relation == LinearConstraint.ConstraintRelation.LE)
+ {
+ if (!(q <= cc.rhs))
+ {
+#if DEBUG_PRINT
+ Console.WriteLine(" ---> phase 1a subset violated, return false from IsSubset");
+#endif
+ return false;
+ }
+ }
+ else
+ {
+ if (!(q == cc.rhs))
+ {
+#if DEBUG_PRINT
+ Console.WriteLine(" ---> phase 1b subset violated, return false from IsSubset");
+#endif
+ return false;
+ }
+ }
+ }
+ }
+
+ // phase 2: check frame rays against each constraint...
+ // To check if a ray "r" falls within a constraint "cc", we add the vector "r" to
+ // any point "p" on the side of the half-space or plane described by constraint, and
+ // then check if the resulting point satisfies the constraint. That is, we check (for
+ // an inequality constraint with coefficients a1,a2,...,an and right-hand side
+ // constant C):
+ // a1*(r1+p1) + a2*(r2+p2) + ... + an*(rn+pn) <= C
+ // Equivalently:
+ // a1*r1 + a2*r2 + ... + an*rn + a1*p1 + a2*p2 + ... + an*pn <= C
+ // To find a point "p", we can pick out a coordinate, call it 1, with a non-zero
+ // coefficient in the constraint, and then choose "p" as the point that has the
+ // value C/a1 in coordinate 1 and has 0 in all other coordinates. We then check:
+ // a1*r1 + a2*r2 + ... + an*rn + a1*(C/a1) + a2*0 + ... + an*0 <= C
+ // which simplifies to:
+ // a1*r1 + a2*r2 + ... + an*rn + C <= C
+ // which in turn simplifies to:
+ // a1*r1 + a2*r2 + ... + an*rn <= 0
+ // If the constraint is an equality constraint, we simply replace "<=" with "=="
+ // above.
+ foreach (FrameElement! r in (!)lcs.FrameRays)
+ {
+ System.Diagnostics.Debug.Assert(r != null, "encountered a null ray...");
+ foreach (LinearConstraint! cc in this.Constraints)
+ {
+ System.Diagnostics.Debug.Assert(cc != null, "encountered an null constraint...");
+ Rational q = cc.EvaluateLhs(r);
+ if (cc.Relation == LinearConstraint.ConstraintRelation.LE)
+ {
+ if (q.IsPositive)
+ {
+#if DEBUG_PRINT
+ Console.WriteLine(" ---> phase 2a subset violated, return false from IsSubset");
+#endif
+ return false;
+ }
+ }
+ else
+ {
+ if (q.IsNonZero)
+ {
+#if DEBUG_PRINT
+ Console.WriteLine(" ---> phase 2b subset violated, return false from IsSubset");
+#endif
+ return false;
+ }
+ }
+ }
+ }
+
+ // phase 3: check frame lines against each constraint...
+ // To check if a line "L" falls within a constraint "cc", we check if both the
+ // vector "L" and "-L", interpreted as rays, fall within the constraint. From
+ // the discussion above, this means we check the following two properties:
+ // a1*L1 + a2*L2 + ... + an*Ln <= 0 (*)
+ // a1*(-L1) + a2*(-L2) + ... + an*(-Ln) <= 0
+ // The second of these lines can be rewritten as:
+ // - a1*L1 - a2*L2 - ... - an*Ln <= 0
+ // which is equivalent to:
+ // -1 * (a1*L1 + a2*L2 + ... + an*Ln) <= 0
+ // Multiplying both sides by -1 and flipping the direction of the inequality,
+ // we have:
+ // a1*L1 + a2*L2 + ... + an*Ln >= 0 (**)
+ // Putting (*) and (**) together, we conclude that we need to check:
+ // a1*L1 + a2*L2 + ... + an*Ln == 0
+ // If the constraint is an equality constraint, we end up with the same equation.
+ foreach (FrameElement! line in (!)lcs.FrameLines)
+ {
+ System.Diagnostics.Debug.Assert(line != null, "encountered a null line...");
+ foreach (LinearConstraint! cc in this.Constraints)
+ {
+ System.Diagnostics.Debug.Assert(cc != null, "encountered an null constraint...");
+ Rational q = cc.EvaluateLhs(line);
+ if (q.IsNonZero)
+ {
+#if DEBUG_PRINT
+ Console.WriteLine(" ---> phase 3 subset violated, return false from IsSubset");
+#endif
+ return false;
+ }
+ }
+ }
+
+#if DEBUG_PRINT
+ Console.WriteLine(" ---> IsSubset returns true");
+#endif
+ return true;
+ }
+
+ public LinearConstraintSystem! Meet(LinearConstraintSystem! lcs)
+ requires this.Constraints != null;
+ requires lcs.Constraints != null;
+ {
+ ArrayList /*LinearConstraint*/ clist = new ArrayList(this.Constraints.Count + lcs.Constraints.Count);
+ clist.AddRange(this.Constraints);
+ clist.AddRange(lcs.Constraints);
+ return new LinearConstraintSystem(clist);
+ }
+
+#if DEBUG_PRINT
+ public LinearConstraintSystem Join(LinearConstraintSystem lcs)
+ {
+ Console.WriteLine("===================================================================================");
+ Console.WriteLine("DEBUG: Join");
+ Console.WriteLine("Join: this=");
+ Dump();
+ Console.WriteLine("Join: lcs=");
+ lcs.Dump();
+ LinearConstraintSystem z = JoinX(lcs);
+ Console.WriteLine("----------Join------------------------------>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
+ Console.WriteLine("Join: result=");
+ z.Dump();
+ Console.WriteLine("===================================================================================");
+ return z;
+ }
+#endif
+
+ /// <summary>
+ /// The join is computed as described in section 4.4 in Cousot and Halbwachs.
+ /// </summary>
+ /// <param name="lcs"></param>
+ /// <returns></returns>
+#if DEBUG_PRINT
+ public LinearConstraintSystem JoinX(LinearConstraintSystem lcs)
+#else
+ public LinearConstraintSystem! Join(LinearConstraintSystem! lcs)
+#endif
+ {
+ if (this.IsBottom())
+ {
+ return (!) lcs.Clone();
+ }
+ else if (lcs.IsBottom())
+ {
+ return (!) this.Clone();
+ }
+ else if (this.IsTop() || lcs.IsTop())
+ {
+ return new LinearConstraintSystem(new ArrayList /*LinearConstraint*/ ());
+ }
+ else
+ {
+ LinearConstraintSystem! z;
+ // Start from the "larger" of the two frames (this is just a heuristic measure intended
+ // to save work).
+ assume this.FrameVertices != null;
+ assume this.FrameRays != null;
+ assume this.FrameLines != null;
+ assume lcs.FrameVertices != null;
+ assume lcs.FrameRays != null;
+ assume lcs.FrameLines != null;
+ if (this.FrameVertices.Count + this.FrameRays.Count + this.FrameLines.Count - this.FrameDimensions.Count <
+ lcs.FrameVertices.Count + lcs.FrameRays.Count + lcs.FrameLines.Count - lcs.FrameDimensions.Count)
+ {
+ z = (!) lcs.Clone();
+ lcs = this;
+ }
+ else
+ {
+ z = (!) this.Clone();
+ }
+#if DEBUG_PRINT
+ Console.WriteLine("DEBUG: LinearConstraintSystem.Join ---------------");
+ Console.WriteLine("z:");
+ z.Dump();
+ Console.WriteLine("lcs:");
+ lcs.Dump();
+#endif
+
+ // Start by explicating the implicit lines of z for the dimensions dims(lcs)-dims(z).
+ foreach (IVariable! dim in lcs.FrameDimensions)
+ {
+ if (!z.FrameDimensions.Contains(dim))
+ {
+ z.FrameDimensions.Add(dim);
+ FrameElement line = new FrameElement();
+ line.AddCoordinate(dim, Rational.ONE);
+ // Note: AddLine is not called (because the line already exists in z--it's just that
+ // it was represented implicitly). Instead, just tack the explicit representation onto
+ // FrameLines.
+ assume z.FrameLines != null;
+ z.FrameLines.Add(line);
+#if DEBUG_PRINT
+ Console.WriteLine("Join: After explicating line: {0}", line);
+ z.Dump();
+#endif
+ }
+ }
+
+ // Now, the vertices, rays, and lines can be added.
+ foreach (FrameElement! v in lcs.FrameVertices)
+ {
+ z.AddVertex(v);
+#if DEBUG_PRINT
+ Console.WriteLine("Join: After adding vertex: {0}", v);
+ z.Dump();
+#endif
+ }
+ foreach (FrameElement! r in lcs.FrameRays)
+ {
+ z.AddRay(r);
+#if DEBUG_PRINT
+ Console.WriteLine("Join: After adding ray: {0}", r);
+ z.Dump();
+#endif
+ }
+ foreach (FrameElement! l in lcs.FrameLines)
+ {
+ z.AddLine(l);
+#if DEBUG_PRINT
+ Console.WriteLine("Join: After adding line: {0}", l);
+ z.Dump();
+#endif
+ }
+ // also add to z the implicit lines of lcs
+ foreach (IVariable! dim in z.FrameDimensions)
+ {
+ if (!lcs.FrameDimensions.Contains(dim))
+ {
+ // "dim" is a dimension that's explicit in "z" but implicit in "lcs"
+ FrameElement line = new FrameElement();
+ line.AddCoordinate(dim, Rational.ONE);
+ z.AddLine(line);
+#if DEBUG_PRINT
+ Console.WriteLine("Join: After adding lcs's implicit line: {0}", line);
+ z.Dump();
+#endif
+ }
+ }
+
+ z.SimplifyFrame();
+ z.SimplifyConstraints();
+ z.CheckInvariant();
+#if DEBUG_PRINT
+ Console.WriteLine("Join: Returning z:");
+ z.Dump();
+ Console.WriteLine("----------------------------------------");
+#endif
+ return z;
+ }
+ }
+
+#if DEBUG_PRINT
+ public LinearConstraintSystem Widen(LinearConstraintSystem lcs)
+ {
+ Console.WriteLine("===================================================================================");
+ Console.WriteLine("DEBUG: Widen");
+ Console.WriteLine("Widen: this=");
+ Dump();
+ Console.WriteLine("Widen: lcs=");
+ lcs.Dump();
+ LinearConstraintSystem z = WidenX(lcs);
+ Console.WriteLine("----------Widen------------------------------>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
+ Console.WriteLine("Widen: result=");
+ z.Dump();
+ Console.WriteLine("===================================================================================");
+ return z;
+ }
+#endif
+
+#if DEBUG_PRINT
+ public LinearConstraintSystem WidenX(LinearConstraintSystem lcs)
+#else
+ public LinearConstraintSystem! Widen(LinearConstraintSystem! lcs)
+#endif
+ {
+ if (this.IsBottom())
+ {
+ return (!) lcs.Clone();
+ }
+ else if (lcs.IsBottom())
+ {
+ return (!) this.Clone();
+ }
+ else if (this.IsTop() || lcs.IsTop())
+ {
+ return new LinearConstraintSystem(new ArrayList /*LinearConstraint*/ ());
+ }
+
+ // create new LCS, we will add only verified constraints to this...
+ ArrayList /*LinearConstraint*/ newConstraints = new ArrayList /*LinearConstraint*/ ();
+ assume this.Constraints != null;
+ foreach (LinearConstraint! ccX in this.Constraints)
+ {
+ LinearConstraint cc = ccX;
+#if DEBUG_PRINT
+ Console.WriteLine("Widen checking: Starting to check constraint: {0}", cc);
+#endif
+ if (cc.IsConstant())
+ {
+ // (Can this ever occur in the stable state of a LinearConstraintSystem? --KRML)
+ // constraint is unaffected by the frame components
+#if DEBUG_PRINT
+ Console.WriteLine("Widen checking: --Adding it!");
+#endif
+ newConstraints.Add(cc);
+ continue;
+ }
+
+ // PHASE I: verify constraints against all frame vertices...
+
+ foreach (FrameElement! vertex in (!)lcs.FrameVertices)
+ {
+ Rational lhs = cc.EvaluateLhs(vertex);
+ if (lhs > cc.rhs)
+ {
+ // the vertex does not satisfy the inequality <=
+ if (cc.Relation == LinearConstraint.ConstraintRelation.LE)
+ {
+#if DEBUG_PRINT
+ Console.WriteLine("Widen checking: throwing out because of vertex: {0}", vertex);
+#endif
+ goto CHECK_NEXT_CONSTRAINT;
+ }
+ else
+ {
+ // ... but it does satisfy the inequality >=
+#if DEBUG_PRINT
+ Console.WriteLine("Widen checking: throwing out <= because of vertex: {0}", vertex);
+#endif
+ cc = cc.ChangeRelationToAtLeast();
+#if DEBUG_PRINT
+ Console.WriteLine("Widen checking: left with constraint: {0}", cc);
+#endif
+ }
+ }
+ else if (cc.Relation == LinearConstraint.ConstraintRelation.EQ && lhs < cc.rhs)
+ {
+ // the vertex does not satisfy the inequality >=, and the constraint is an equality constraint
+#if DEBUG_PRINT
+ Console.WriteLine("Widen checking: throwing out >= because of vertex: {0}", vertex);
+#endif
+ cc = cc.ChangeRelation(LinearConstraint.ConstraintRelation.LE);
+#if DEBUG_PRINT
+ Console.WriteLine("Widen checking: left with contraint: {0}", cc);
+#endif
+ }
+ }
+
+ // PHASE II: verify constraints against all frame rays...
+
+ foreach (FrameElement! ray in (!)lcs.FrameRays)
+ {
+ // The following assumes the constraint to have some dimension with a non-zero coefficient
+ Rational lhs = cc.EvaluateLhs(ray);
+ if (lhs.IsPositive)
+ {
+ // the ray does not satisfy the inequality <=
+ if (cc.Relation == LinearConstraint.ConstraintRelation.LE)
+ {
+#if DEBUG_PRINT
+ Console.WriteLine("Widen checking: throwing out because of ray: {0}", ray);
+#endif
+ goto CHECK_NEXT_CONSTRAINT;
+ }
+ else
+ {
+ // ... but it does satisfy the inequality >=
+#if DEBUG_PRINT
+ Console.WriteLine("Widen checking: throwing out <= because of ray: {0}", ray);
+#endif
+ cc = cc.ChangeRelationToAtLeast();
+#if DEBUG_PRINT
+ Console.WriteLine("Widen checking: left with contraint: {0}", cc);
+#endif
+ }
+ }
+ else if (cc.Relation == LinearConstraint.ConstraintRelation.EQ && lhs.IsNegative)
+ {
+ // the ray does not satisfy the inequality >=, and the constraint is an equality constraint
+#if DEBUG_PRINT
+ Console.WriteLine("Widen checking: throwing out >= because of ray: {0}", ray);
+#endif
+ cc = cc.ChangeRelation(LinearConstraint.ConstraintRelation.LE);
+#if DEBUG_PRINT
+ Console.WriteLine("Widen checking: left with constraint: {0}", cc);
+#endif
+ }
+ }
+
+ // PHASE III: verify constraints against all frame lines...
+
+ foreach (FrameElement! line in (!)lcs.FrameLines)
+ {
+ // The following assumes the constraint to have some dimension with a non-zero coefficient
+ Rational lhs = cc.EvaluateLhs(line);
+ if (!lhs.IsZero)
+ {
+ // The line satisfies neither the inequality <= nor the equality ==
+#if DEBUG_PRINT
+ Console.WriteLine("Widen checking: throwing out because of line: {0}", line);
+#endif
+ goto CHECK_NEXT_CONSTRAINT;
+ }
+ }
+
+ // constraint has been verified, so add to new constraint system
+#if DEBUG_PRINT
+ Console.WriteLine("Widen checking: --Adding it!");
+#endif
+ newConstraints.Add(cc);
+
+ CHECK_NEXT_CONSTRAINT: {}
+#if DEBUG_PRINT
+ Console.WriteLine("Widen checking: done with that constraint");
+#endif
+ }
+
+ return new LinearConstraintSystem(newConstraints);
+ }
+
+#if DEBUG_PRINT
+ public LinearConstraintSystem Project(IVariable! dim)
+ {
+ Console.WriteLine("===================================================================================");
+ Console.WriteLine("DEBUG: Project(dim={0})", dim);
+ Console.WriteLine("Project: this=");
+ Dump();
+ LinearConstraintSystem z = ProjectX(dim);
+ Console.WriteLine("----------Project------------------------------>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
+ Console.WriteLine("Project: result=");
+ z.Dump();
+ Console.WriteLine("===================================================================================");
+ return z;
+ }
+#endif
+
+#if DEBUG_PRINT
+ public LinearConstraintSystem ProjectX(IVariable! dim)
+#else
+ public LinearConstraintSystem! Project(IVariable! dim)
+#endif
+ requires this.Constraints != null;
+ {
+ ArrayList /*LinearConstraint!*/! cc = Project(dim, Constraints);
+ return new LinearConstraintSystem(cc);
+ }
+
+#if DEBUG_PRINT
+ public LinearConstraintSystem Rename(IVariable! oldName, IVariable! newName)
+ {
+ Console.WriteLine("===================================================================================");
+ Console.WriteLine("DEBUG: Rename(oldName={0}, newName={1})", oldName, newName);
+ Console.WriteLine("Rename: this=");
+ Dump();
+ LinearConstraintSystem z = RenameX(oldName, newName);
+ Console.WriteLine("----------Rename------------------------------>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
+ Console.WriteLine("Rename: result=");
+ z.Dump();
+ Console.WriteLine("===================================================================================");
+ return z;
+ }
+#endif
+
+#if DEBUG_PRINT
+ public LinearConstraintSystem RenameX(IVariable! oldName, IVariable! newName)
+#else
+ public LinearConstraintSystem! Rename(IVariable! oldName, IVariable! newName)
+#endif
+ {
+ if (this.Constraints == null)
+ {
+ System.Diagnostics.Debug.Assert(this.FrameVertices == null);
+ System.Diagnostics.Debug.Assert(this.FrameRays == null);
+ System.Diagnostics.Debug.Assert(this.FrameLines == null);
+ return this;
+ }
+ IMutableSet /*IVariable!*/! dims = this.FrameDimensions;
+ if (!dims.Contains(oldName))
+ {
+ return this;
+ }
+
+ LinearConstraintSystem z = new LinearConstraintSystem();
+ z.FrameDimensions = (HashSet! /*IVariable!*/)dims.Clone();
+ z.FrameDimensions.Remove(oldName);
+ z.FrameDimensions.Add(newName);
+
+ z.Constraints = new ArrayList /*LinearConstraint!*/ (this.Constraints.Count);
+ foreach (LinearConstraint! lc in (!)this.Constraints)
+ {
+ z.Constraints.Add(lc.Rename(oldName, newName));
+ }
+ z.FrameVertices = RenameInFE((!)this.FrameVertices, oldName, newName);
+ z.FrameRays = RenameInFE((!)this.FrameRays, oldName, newName);
+ z.FrameLines = RenameInFE((!)this.FrameLines, oldName, newName);
+ return z;
+ }
+
+ static ArrayList /*FrameElement*/ RenameInFE(ArrayList! /*FrameElement*/ list, IVariable! oldName, IVariable! newName)
+ {
+ ArrayList/*FrameElement!*/! z = new ArrayList/*FrameElement!*/ (list.Count);
+ foreach (FrameElement! fe in list)
+ {
+ z.Add(fe.Rename(oldName, newName));
+ }
+ System.Diagnostics.Debug.Assert(z.Count == list.Count);
+ return z;
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ // ------------------ support routines --------------------------------------------------------------------
+ // --------------------------------------------------------------------------------------------------------
+
+ /// <summary>
+ /// Returns a set of constraints that is the given set of constraints with dimension "dim"
+ /// projected out. See Cousot and Halbwachs, section 3.3.1.1.
+ /// </summary>
+ /// <param name="dim"></param>
+ /// <param name="constraints"></param>
+ /// <returns></returns>
+ static ArrayList /*LinearConstraint!*/! Project(IVariable! dim, ArrayList /*LinearConstraint!*/! constraints)
+ {
+ // Sort the inequality constaints into ones where dimension "dim" is 0, negative, and
+ // positive, respectively. Put equality constraints with a non-0 "dim" into "eq".
+ ArrayList /*LinearConstraint!*/! final = new ArrayList /*LinearConstraint!*/ ();
+ ArrayList /*LinearConstraint!*/! negative = new ArrayList /*LinearConstraint!*/ ();
+ ArrayList /*LinearConstraint!*/! positive = new ArrayList /*LinearConstraint!*/ ();
+ ArrayList /*LinearConstraint!*/! eq = new ArrayList /*LinearConstraint!*/ ();
+ foreach (LinearConstraint! cc in constraints)
+ {
+ Rational coeff = cc[dim];
+ if (coeff.IsZero)
+ {
+ LinearConstraint lc = (!) cc.Clone();
+ if (!lc.IsConstant())
+ {
+ lc.RemoveDimension(dim);
+ final.Add(lc);
+ }
+ }
+ else if (cc.Relation == LinearConstraint.ConstraintRelation.EQ)
+ {
+ eq.Add(cc);
+ }
+ else if (coeff.IsNegative)
+ {
+ negative.Add(cc);
+ }
+ else
+ {
+ System.Diagnostics.Debug.Assert(coeff.IsPositive);
+ positive.Add(cc);
+ }
+ }
+
+ if (eq.Count != 0)
+ {
+ LinearConstraint eqConstraint = (LinearConstraint!)eq[eq.Count-1];
+ eq.RemoveAt(eq.Count-1);
+ Rational eqC = -eqConstraint[dim];
+
+ foreach (ArrayList /*LinearConstraint!*/! list in new ArrayList[]{eq, negative, positive})
+ {
+ foreach (LinearConstraint! lcX in list)
+ {
+ LinearConstraint lc = (!) lcX.Clone();
+ lc.AddMultiple(lc[dim]/eqC, eqConstraint);
+ System.Diagnostics.Debug.Assert(lc[dim].IsZero);
+ if (!lc.IsConstant())
+ {
+ lc.RemoveDimension(dim);
+ final.Add(lc);
+ }
+ else
+ {
+ System.Diagnostics.Debug.Assert(lc.IsConstantSatisfiable());
+ }
+ }
+ }
+ }
+ else
+ {
+ // Consider all pairs of constraints with (negative,positive) coefficients of "dim".
+ foreach (LinearConstraint! cn in negative)
+ {
+ Rational dn = -cn[dim];
+ System.Diagnostics.Debug.Assert(dn.IsNonNegative);
+ foreach (LinearConstraint! cp in positive)
+ {
+ Rational dp = cp[dim];
+
+ LinearConstraint lc = new LinearConstraint(LinearConstraint.ConstraintRelation.LE);
+ lc.AddMultiple(dn, cp);
+ lc.AddMultiple(dp, cn);
+ System.Diagnostics.Debug.Assert(lc[dim].IsZero);
+ if (!lc.IsConstant())
+ {
+ lc.RemoveDimension(dim);
+ final.Add(lc);
+ }
+ else
+ {
+ System.Diagnostics.Debug.Assert(lc.IsConstantSatisfiable());
+ }
+ }
+ }
+ }
+
+ return final;
+ }
+
+ /// <summary>
+ /// Initializes FrameVertices, FrameRays, FrameLines, and FrameDimensions, see
+ /// Cousot and Halbwachs, section 3.4. Any previous values of these fields are
+ /// ignored and overwritten.
+ ///
+ /// If the set of Constraints is unsatisfiable, then "this" is changed into Bottom.
+ /// </summary>
+ void GenerateFrameFromConstraints()
+ {
+ if (Constraints == null)
+ {
+ FrameVertices = null;
+ FrameRays = null;
+ FrameLines = null;
+ FrameDimensions = new HashSet /*IVariable!*/ ();
+ return;
+ }
+
+ // Step 1 (see Cousot and Halbwachs, section 3.4.3): create a Simplex Tableau.
+#if DEBUG_PRINT
+ Console.WriteLine("DEBUG: --- GenerateFrameFromConstraint ---");
+ Console.WriteLine("Constraints:");
+ foreach (LinearConstraint cc in Constraints)
+ {
+ Console.WriteLine(" {0}", cc);
+ }
+#endif
+ SimplexTableau tableau = new SimplexTableau(Constraints);
+#if DEBUG_PRINT
+ Console.WriteLine("Initial tableau:");
+ tableau.Dump();
+#endif
+ FrameDimensions = tableau.GetDimensions();
+#if DEBUG_PRINT
+ Console.WriteLine("Dimensions:");
+ foreach (object dim in FrameDimensions)
+ {
+ Console.Write(" {0}", dim);
+ }
+ Console.WriteLine();
+#endif
+
+ // Step 3 and 2: Put as many initial variables as possible into basis, then check if
+ // we reached a feasible basis
+ tableau.AddInitialVarsToBasis();
+#if DEBUG_PRINT
+ Console.WriteLine("Tableau after Step 3:");
+ tableau.Dump();
+#endif
+ if (!tableau.IsFeasibleBasis)
+ {
+ // The polyhedron is empty (according to Cousot and Halbwachs)
+ ChangeIntoBottom();
+ return;
+ }
+
+ FrameVertices = new ArrayList /*FrameElement*/ ();
+ FrameRays = new ArrayList /*FrameElement*/ ();
+ FrameLines = new ArrayList /*FrameElement*/ ();
+ if (FrameDimensions.Count == 0)
+ {
+ // top element
+ return;
+ }
+
+ if (tableau.AllInitialVarsInBasis)
+ {
+ // All initial variables are in basis; there are no lines.
+#if DEBUG_PRINT
+ Console.WriteLine("Tableau after Steps 2 and 3 (all initial variables in basis):");
+ tableau.Dump();
+#endif
+ }
+ else
+ {
+ // There are lines
+#if DEBUG_PRINT
+ Console.WriteLine("Tableau after Steps 2 and 3 (NOT all initial variables in basis--there are lines):");
+ tableau.Dump();
+#endif
+ // Step 4.2: Pick out the lines, then produce the tableau for a new polyhedron without those lines.
+ ArrayList /*LinearConstraint*/ moreConstraints = (ArrayList! /*LinearConstraint*/) Constraints.Clone();
+ tableau.ProduceLines(FrameLines, moreConstraints);
+ tableau = new SimplexTableau(moreConstraints);
+#if DEBUG_PRINT
+ Console.WriteLine("Lines produced:");
+ foreach (FrameElement line in FrameLines)
+ {
+ Console.WriteLine(" {0}", line);
+ }
+ Console.WriteLine("The new list of constraints is:");
+ foreach (LinearConstraint c in moreConstraints)
+ {
+ Console.WriteLine(" {0}", c);
+ }
+ Console.WriteLine("Tableau after producing lines in Step 4.2:");
+ tableau.Dump();
+#endif
+
+ // Repeat step 3 for the new tableau.
+ // Since the new tableau contains no lines, the following call should cause all initial
+ // variables to be in basis (see step 4.2 in section 3.4.3 of Cousot and Halbwachs).
+ tableau.AddInitialVarsToBasis();
+ System.Diagnostics.Debug.Assert(tableau.AllInitialVarsInBasis);
+ System.Diagnostics.Debug.Assert(tableau.IsFeasibleBasis); // the new tableau represents a set of feasible constraints, so this basis should be found to be feasible
+#if DEBUG_PRINT
+ Console.WriteLine("Tableau after all initial variables have been moved into basis:");
+ tableau.Dump();
+#endif
+ }
+
+ // Step 4.1: One vertex has been found. Find all others, too.
+ tableau.TraverseVertices(FrameVertices, FrameRays);
+#if DEBUG_PRINT
+ Console.WriteLine("Tableau after vertex traversal:");
+ tableau.Dump();
+#endif
+ }
+
+ class LambdaDimension : IVariable
+ {
+ readonly int id;
+ static int count = 0;
+
+ /// <summary>
+ /// Return the name of the variable
+ /// </summary>
+ public string! Name
+ {
+ get
+ {
+ return this.ToString();
+ }
+ }
+
+ public LambdaDimension()
+ {
+ id = count;
+ count++;
+ }
+ [Pure][Reads(ReadsAttribute.Reads.Owned)]
+ public override string! ToString()
+ {
+ return "lambda" + id;
+ }
+ [Pure][Reads(ReadsAttribute.Reads.Owned)]
+ public object DoVisit(ExprVisitor! visitor)
+ {
+ return visitor.VisitVariable(this);
+ }
+ }
+
+ /// <summary>
+ /// Adds a vertex to the frame of "this" and updates Constraints accordingly, see
+ /// Cousot and Halbwachs, section 3.3.1.1. However, this method does not simplify
+ /// Constraints after the operation; that remains the caller's responsibility (which
+ /// gives the caller the opportunity to make multiple calls to AddVertex, AddRay,
+ /// and AddLine before calling SimplifyConstraints).
+ /// Assumes Constraints (and the frame fields) to be non-null.
+ /// </summary>
+ /// <param name="vertex"></param>
+ void AddVertex(FrameElement! vertex)
+ requires this.FrameVertices != null;
+ {
+#if DEBUG_PRINT
+ Console.WriteLine("DEBUG: AddVertex called on {0}", vertex);
+ Console.WriteLine(" Initial constraints:");
+ foreach (LinearConstraint cc in Constraints) {
+ Console.WriteLine(" {0}", cc);
+ }
+#endif
+
+ FrameVertices.Add(vertex.Clone());
+#if FIXED_DESERIALIZER
+ assert Forall{IVariable! var in vertex.GetDefinedDimensions(); FrameDimensions.Contains(var)};
+#endif
+
+ // We use a new temporary dimension.
+ IVariable! lambda = new LambdaDimension();
+
+ // We change the constraints A*X <= B into
+ // A*X + (A*vector - B)*lambda <= A*vector.
+ // That means that each row k in A (which corresponds to one LinearConstraint
+ // in Constraints) is changed by adding
+ // (A*vector - B)[k] * lambda
+ // to row k and changing the right-hand side of row k to
+ // (A*vector)[k]
+ // Note:
+ // (A*vector - B)[k]
+ // = { vector subtraction is pointwise }
+ // (A*vector)[k] - B[k]
+ // = { A*vector is a row vector whose every row i is the dot-product of
+ // row i of A with the column vector "vector" }
+ // A[k]*vector - B[k]
+ foreach (LinearConstraint! cc in (!)Constraints)
+ {
+ Rational d = cc.EvaluateLhs(vertex);
+ cc.SetCoefficient(lambda, d - cc.rhs);
+ cc.rhs = d;
+ }
+
+ // We also add the constraints that lambda lies between 0 ...
+ LinearConstraint la = new LinearConstraint(LinearConstraint.ConstraintRelation.LE);
+ la.SetCoefficient(lambda, Rational.MINUS_ONE);
+ la.rhs = Rational.ZERO;
+ Constraints.Add(la);
+ // ... and 1.
+ la = new LinearConstraint(LinearConstraint.ConstraintRelation.LE);
+ la.SetCoefficient(lambda, Rational.ONE);
+ la.rhs = Rational.ONE;
+ Constraints.Add(la);
+#if DEBUG_PRINT
+ Console.WriteLine(" Constraints after addition:");
+ foreach (LinearConstraint cc in Constraints) {
+ Console.WriteLine(" {0}", cc);
+ }
+#endif
+
+ // Finally, project out the dummy dimension.
+ Constraints = Project(lambda, Constraints);
+
+#if DEBUG_PRINT
+ Console.WriteLine(" Resulting constraints:");
+ foreach (LinearConstraint cc in Constraints) {
+ Console.WriteLine(" {0}", cc);
+ }
+#endif
+ }
+
+ /// <summary>
+ /// Adds a ray to the frame of "this" and updates Constraints accordingly, see
+ /// Cousot and Halbwachs, section 3.3.1.1. However, this method does not simplify
+ /// Constraints after the operation; that remains the caller's responsibility (which
+ /// gives the caller the opportunity to make multiple calls to AddVertex, AddRay,
+ /// and AddLine before calling SimplifyConstraints).
+ /// Assumes Constraints (and the frame fields) to be non-null.
+ /// </summary>
+ /// <param name="ray"></param>
+ void AddRay(FrameElement! ray)
+ requires this.FrameRays != null;
+ {
+#if DEBUG_PRINT
+ Console.WriteLine("DEBUG: AddRay called on {0}", ray);
+ Console.WriteLine(" Initial constraints:");
+ foreach (LinearConstraint cc in Constraints) {
+ Console.WriteLine(" {0}", cc);
+ }
+#endif
+
+ FrameRays.Add(ray.Clone());
+#if FIXED_DESERIALIZER
+ assert Forall{IVariable! var in ray.GetDefinedDimensions(); FrameDimensions.Contains(var)};
+#endif
+
+ // We use a new temporary dimension.
+ IVariable! lambda = new LambdaDimension();
+
+ // We change the constraints A*X <= B into
+ // A*X - (A*ray)*lambda <= B.
+ // That means that each row k in A (which corresponds to one LinearConstraint
+ // in Constraints) is changed by subtracting
+ // (A*ray)[k] * lambda
+ // from row k.
+ // Note:
+ // (A*ray)[k]
+ // = { A*ray is a row vector whose every row i is the dot-product of
+ // row i of A with the column vector "ray" }
+ // A[k]*ray
+ foreach (LinearConstraint! cc in (!)Constraints)
+ {
+ Rational d = cc.EvaluateLhs(ray);
+ cc.SetCoefficient(lambda, -d);
+ }
+
+ // We also add the constraints that lambda is at least 0.
+ LinearConstraint la = new LinearConstraint(LinearConstraint.ConstraintRelation.LE);
+ la.SetCoefficient(lambda, Rational.MINUS_ONE);
+ la.rhs = Rational.ZERO;
+ Constraints.Add(la);
+#if DEBUG_PRINT
+ Console.WriteLine(" Constraints after addition:");
+ foreach (LinearConstraint cc in Constraints) {
+ Console.WriteLine(" {0}", cc);
+ }
+#endif
+
+ // Finally, project out the dummy dimension.
+ Constraints = Project(lambda, Constraints);
+
+#if DEBUG_PRINT
+ Console.WriteLine(" Resulting constraints:");
+ foreach (LinearConstraint cc in Constraints) {
+ Console.WriteLine(" {0}", cc);
+ }
+#endif
+ }
+
+ /// <summary>
+ /// Adds a line to the frame of "this" and updates Constraints accordingly, see
+ /// Cousot and Halbwachs, section 3.3.1.1. However, this method does not simplify
+ /// Constraints after the operation; that remains the caller's responsibility (which
+ /// gives the caller the opportunity to make multiple calls to AddVertex, AddRay,
+ /// and AddLine before calling SimplifyConstraints).
+ /// Assumes Constraints (and the frame fields) to be non-null.
+ /// </summary>
+ /// <param name="line"></param>
+ void AddLine(FrameElement! line)
+ requires this.FrameLines != null;
+ {
+ // Note: The code for AddLine is identical to that of AddRay, except the AddLine
+ // does not introduce the constraint 0 <= lambda. (One could imagine sharing the
+ // code between AddRay and AddLine.)
+#if DEBUG_PRINT
+ Console.WriteLine("DEBUG: AddLine called on {0}", line);
+ Console.WriteLine(" Initial constraints:");
+ foreach (LinearConstraint cc in Constraints) {
+ Console.WriteLine(" {0}", cc);
+ }
+#endif
+
+ FrameLines.Add(line.Clone());
+#if FIXED_DESERIALIZER
+ assert Forall{IVariable! var in line.GetDefinedDimensions(); FrameDimensions.Contains(var)};
+#endif
+
+ // We use a new temporary dimension.
+ IVariable! lambda = new LambdaDimension();
+
+ // We change the constraints A*X <= B into
+ // A*X - (A*line)*lambda <= B.
+ // That means that each row k in A (which corresponds to one LinearConstraint
+ // in Constraints) is changed by subtracting
+ // (A*line)[k] * lambda
+ // from row k.
+ // Note:
+ // (A*line)[k]
+ // = { A*line is a row vector whose every row i is the dot-product of
+ // row i of A with the column vector "line" }
+ // A[k]*line
+ foreach (LinearConstraint! cc in (!)Constraints)
+ {
+ Rational d = cc.EvaluateLhs(line);
+ cc.SetCoefficient(lambda, -d);
+ }
+
+#if DEBUG_PRINT
+ Console.WriteLine(" Constraints after addition:");
+ foreach (LinearConstraint cc in Constraints) {
+ Console.WriteLine(" {0}", cc);
+ }
+#endif
+
+ // Finally, project out the dummy dimension.
+ Constraints = Project(lambda, Constraints);
+
+#if DEBUG_PRINT
+ Console.WriteLine(" Resulting constraints:");
+ foreach (LinearConstraint cc in Constraints) {
+ Console.WriteLine(" {0}", cc);
+ }
+#endif
+ }
+
+ ISet /*IVariable!*/! GetDefinedDimensions()
+ {
+ HashSet /*IVariable!*/! dims = new HashSet /*IVariable!*/ ();
+ foreach (ArrayList p in new ArrayList[]{FrameVertices, FrameRays, FrameLines})
+ {
+ if (p != null)
+ {
+ foreach (FrameElement! element in p)
+ {
+ foreach (IVariable! dim in element.GetDefinedDimensions())
+ {
+ dims.Add(dim);
+ }
+ }
+ }
+ }
+ return dims;
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ // ------------------ Simplification routines -------------------------------------------------------------
+ // --------------------------------------------------------------------------------------------------------
+
+ /// <summary>
+ /// Uses the Constraints to simplify the frame. See section 3.4.4 of Cousot and Halbwachs.
+ /// </summary>
+ void SimplifyFrame()
+ requires this.Constraints != null;
+ {
+ SimplificationStatus[]! status;
+
+ SimplifyFrameElements((!)FrameVertices, true, Constraints, out status);
+ RemoveIrrelevantFrameElements(FrameVertices, status, null);
+
+ SimplifyFrameElements((!)FrameRays, false, Constraints, out status);
+ RemoveIrrelevantFrameElements(FrameRays, status, FrameLines);
+ }
+
+ enum SimplificationStatus { Irrelevant, Relevant, More };
+
+ /// <summary>
+ /// For each i, sets status[i] to:
+ /// <ul>
+ /// <li>Irrelevant if ff[i] is irrelevant</li>
+ /// <li>Relevant if ff[i] is irrelevant</li>
+ /// <li>More if vertices is true and ray ff[i] can be replaced by a line ff[i]</li>
+ /// </ul>
+ /// </summary>
+ /// <param name="ff"></param>
+ /// <param name="vertices">true if "ff" contains vertices; false if "ff" contains rays</param>
+ /// <param name="constraints"></param>
+ /// <param name="status"></param>
+ static void SimplifyFrameElements(ArrayList! /*FrameElement*/ ff, bool vertices,
+ ArrayList! /*LinearConstraint*/ constraints,
+ out SimplificationStatus[]! status)
+ {
+ status = new SimplificationStatus[ff.Count];
+ bool[,] sat = new bool[ff.Count, constraints.Count];
+ for (int i = 0; i < ff.Count; i++)
+ {
+ FrameElement f = (FrameElement!)ff[i];
+ int cnt = 0;
+ for (int c = 0; c < constraints.Count; c++)
+ {
+ LinearConstraint lc = (LinearConstraint!)constraints[c];
+ bool s = lc.IsSaturatedBy(f, vertices);
+ if (s)
+ {
+ sat[i,c] = true;
+ cnt++;
+ }
+ }
+ if (!vertices && cnt == constraints.Count)
+ {
+ status[i] = SimplificationStatus.More;
+ }
+ else
+ {
+ status[i] = SimplificationStatus.Relevant;
+ }
+ }
+
+ CheckPairSimplifications(sat, status);
+ }
+
+ /// <summary>
+ /// Requires sat.GetLength(0) == status.Length.
+ /// </summary>
+ /// <param name="sat"></param>
+ /// <param name="status"></param>
+ static void CheckPairSimplifications(bool[,]! sat, SimplificationStatus[]! status)
+ requires sat.GetLength(0) == status.Length;
+ {
+ int M = sat.GetLength(0);
+ int N = sat.GetLength(1);
+
+ for (int i = 0; i < M-1; i++)
+ {
+ if (status[i] != SimplificationStatus.Relevant)
+ {
+ continue;
+ }
+ for (int j = i+1; j < M; j++)
+ {
+ if (status[j] != SimplificationStatus.Relevant)
+ {
+ continue;
+ }
+ // check (sat[i,*] <= sat[j,*]) and (sat[i,*] >= sat[j,*])
+ int cmp = 0; // -1: (sat[i,*] <= sat[j,*]), 0: equal, 1: (sat[i,*] >= sat[j,*])
+ for (int c = 0; c < N; c++)
+ {
+ if (cmp < 0)
+ {
+ if (sat[i,c] && !sat[j,c])
+ {
+ // incomparable
+ goto NEXT_PAIR;
+ }
+ }
+ else if (0 < cmp)
+ {
+ if (!sat[i,c] && sat[j,c])
+ {
+ // incomparable
+ goto NEXT_PAIR;
+ }
+ }
+ else if (sat[i,c] != sat[j,c])
+ {
+ if (!sat[i,c])
+ {
+ cmp = -1;
+ }
+ else
+ {
+ cmp = 1;
+ }
+ }
+ }
+ if (cmp <= 0)
+ {
+ // sat[i,*] <= sat[j,*] holds, so mark i as irrelevant
+ status[i] = SimplificationStatus.Irrelevant;
+ goto NEXT_OUTER;
+ }
+ else
+ {
+ // sat[i,*] >= sat[j,*] holds, so mark j as irrelevant
+ status[j] = SimplificationStatus.Irrelevant;
+ }
+ NEXT_PAIR: {}
+ }
+ NEXT_OUTER: {}
+ }
+ }
+
+ static void RemoveIrrelevantFrameElements(ArrayList! /*FrameElement*/ ff, SimplificationStatus[]! status,
+ /*maybe null*/ ArrayList /*FrameElement*/ lines)
+ requires ff.Count == status.Length;
+ {
+ for (int j = ff.Count - 1; 0 <= j; j--)
+ {
+ switch (status[j])
+ {
+ case SimplificationStatus.Relevant:
+ break;
+ case SimplificationStatus.Irrelevant:
+#if DEBUG_PRINT
+ Console.WriteLine("Removing irrelevant {0}: {1}", lines == null ? "vertex" : "ray", ff[j]);
+#endif
+ ff.RemoveAt(j);
+ break;
+ case SimplificationStatus.More:
+ System.Diagnostics.Debug.Assert(lines != null);
+ FrameElement f = (FrameElement)ff[j];
+#if DEBUG_PRINT
+ Console.WriteLine("Changing ray into line: {0}", f);
+#endif
+ ff.RemoveAt(j);
+ assert lines != null;
+ lines.Add(f);
+ break;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Uses the frame to simplify Constraints. See section 3.3.1.2 of Cousot and Halbwachs.
+ ///
+ /// Note: This code does not necessarily eliminate all irrelevant equalities; Cousot and
+ /// Halbwachs only claim that the technique eliminates all irrelevant inequalities.
+ /// </summary>
+ void SimplifyConstraints()
+ {
+ if (Constraints == null)
+ {
+ return;
+ }
+ assume this.FrameVertices != null;
+ assume this.FrameRays != null;
+
+ SimplificationStatus[] status = new SimplificationStatus[Constraints.Count];
+ /*readonly*/ int feCount = FrameVertices.Count + FrameRays.Count;
+
+ // Create a table that keeps track of which constraints are satisfied by which vertices and rays
+ bool[,] sat = new bool[Constraints.Count, FrameVertices.Count + FrameRays.Count];
+ for (int i = 0; i < Constraints.Count; i++)
+ {
+ status[i] = SimplificationStatus.Relevant;
+ LinearConstraint lc = (LinearConstraint!)Constraints[i];
+ int cnt = 0; // number of vertices and rays that saturate lc
+ for (int j = 0; j < FrameVertices.Count; j++)
+ {
+ FrameElement vertex = (FrameElement!)FrameVertices[j];
+ if (lc.IsSaturatedBy(vertex, true))
+ {
+ sat[i,j] = true;
+ cnt++;
+ }
+ }
+ if (cnt == 0)
+ {
+ // no vertex saturates the constraint, so the constraint is irrelevant
+ status[i] = SimplificationStatus.Irrelevant;
+ continue;
+ }
+ for (int j = 0; j < FrameRays.Count; j++)
+ {
+ FrameElement ray = (FrameElement!)FrameRays[j];
+ if (lc.IsSaturatedBy(ray, false))
+ {
+ sat[i, FrameVertices.Count + j] = true;
+ cnt++;
+ }
+ }
+ if (cnt == feCount)
+ {
+ status[i] = SimplificationStatus.More;
+ }
+ else
+ {
+ // Cousot and Halbwachs says that all equalities are found in the way we just tested.
+ // If I understand that right, then we should not get here if the constraint is an
+ // equality constraint. The following assertion tests my understanding. --KRML
+ System.Diagnostics.Debug.Assert(lc.Relation == LinearConstraint.ConstraintRelation.LE);
+ }
+ }
+
+ CheckPairSimplifications(sat, status);
+
+ // Finally, make the changes to the list of constraints
+ for (int i = Constraints.Count - 1; 0 <= i; i--)
+ {
+ switch (status[i])
+ {
+ case SimplificationStatus.Relevant:
+ break;
+ case SimplificationStatus.Irrelevant:
+#if DEBUG_PRINT
+ Console.WriteLine("Removing irrelevant constraint: {0}", Constraints[i]);
+#endif
+ Constraints.RemoveAt(i);
+ break;
+ case SimplificationStatus.More:
+ LinearConstraint lc = (LinearConstraint!)Constraints[i];
+ if (lc.Relation == LinearConstraint.ConstraintRelation.LE)
+ {
+#if DEBUG_PRINT
+ Console.WriteLine("Converting the following constraint into an equality: {0}", lc);
+#endif
+ LinearConstraint lcEq = lc.ChangeRelation(LinearConstraint.ConstraintRelation.EQ);
+ Constraints[i] = lcEq;
+ }
+ break;
+ }
+ }
+
+ foreach (LinearConstraint! lc in Constraints) {
+ lc.Normalize();
+ }
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ // ------------------ Cloning routines --------------------------------------------------------------------
+ // --------------------------------------------------------------------------------------------------------
+
+ public LinearConstraintSystem! Clone()
+ {
+ LinearConstraintSystem z = new LinearConstraintSystem();
+ z.FrameDimensions = (IMutableSet /*IVariable!*/!)this.FrameDimensions.Clone();
+ if (this.Constraints != null)
+ {
+ z.Constraints = DeeperListCopy_LC(this.Constraints);
+ z.FrameVertices = DeeperListCopy_FE((!)this.FrameVertices);
+ z.FrameRays = DeeperListCopy_FE((!)this.FrameRays);
+ z.FrameLines = DeeperListCopy_FE((!)this.FrameLines);
+ }
+ else
+ {
+ System.Diagnostics.Debug.Assert(this.FrameVertices == null);
+ System.Diagnostics.Debug.Assert(this.FrameRays == null);
+ System.Diagnostics.Debug.Assert(this.FrameLines == null);
+ // the constructor should already have set these fields of z to null
+ System.Diagnostics.Debug.Assert(z.Constraints == null);
+ System.Diagnostics.Debug.Assert(z.FrameVertices == null);
+ System.Diagnostics.Debug.Assert(z.FrameRays == null);
+ System.Diagnostics.Debug.Assert(z.FrameLines == null);
+ }
+ return z;
+ }
+
+ /// <summary>
+ /// Clones "list" and the elements of "list".
+ /// </summary>
+ /// <param name="list"></param>
+ /// <returns></returns>
+ ArrayList /*LinearConstraint*/ DeeperListCopy_LC(ArrayList! /*LinearConstraint*/ list)
+ {
+ ArrayList /*LinearConstraint*/ z = new ArrayList /*LinearConstraint*/ (list.Count);
+ foreach (LinearConstraint! lc in list)
+ {
+ z.Add(lc.Clone());
+ }
+ System.Diagnostics.Debug.Assert(z.Count == list.Count);
+ return z;
+ }
+
+ /// <summary>
+ /// Clones "list" and the elements of "list".
+ /// </summary>
+ /// <param name="list"></param>
+ /// <returns></returns>
+ ArrayList /*FrameElement*/ DeeperListCopy_FE(ArrayList! /*FrameElement*/ list)
+ {
+ ArrayList /*FrameElement*/ z = new ArrayList /*FrameElement*/ (list.Count);
+ foreach (FrameElement! fe in list)
+ {
+ z.Add(fe.Clone());
+ }
+ System.Diagnostics.Debug.Assert(z.Count == list.Count);
+ return z;
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ // ------------------ Debugging and unit test routines ----------------------------------------------------
+ // --------------------------------------------------------------------------------------------------------
+
+ public void Dump()
+ {
+ Console.WriteLine(" Constraints:");
+ if (Constraints == null)
+ {
+ Console.WriteLine(" <bottom>");
+ }
+ else
+ {
+ foreach (LinearConstraint cc in Constraints)
+ {
+ Console.WriteLine(" {0}", cc);
+ }
+ }
+
+ Console.WriteLine(" FrameDimensions: {0}", FrameDimensions);
+
+ Console.WriteLine(" FrameVerticies:");
+ if (FrameVertices == null)
+ {
+ Console.WriteLine(" <null>");
+ }
+ else
+ {
+ foreach (FrameElement fe in FrameVertices)
+ {
+ Console.WriteLine(" {0}", fe);
+ }
+ }
+
+ Console.WriteLine(" FrameRays:");
+ if (FrameRays == null)
+ {
+ Console.WriteLine(" <null>");
+ }
+ else
+ {
+ foreach (FrameElement fe in FrameRays)
+ {
+ Console.WriteLine(" {0}", fe);
+ }
+ }
+
+ Console.WriteLine(" FrameLines:");
+ if (FrameLines == null)
+ {
+ Console.WriteLine(" <null>");
+ }
+ else
+ {
+ foreach (FrameElement fe in FrameLines)
+ {
+ Console.WriteLine(" {0}", fe);
+ }
+ }
+ }
+
+ class TestVariable : IVariable {
+ readonly string! name;
+
+ public string! Name
+ {
+ get
+ {
+ return name;
+ }
+ }
+
+ public TestVariable(string! name) {
+ this.name = name;
+ }
+ [Pure][Reads(ReadsAttribute.Reads.Owned)]
+ public object DoVisit(ExprVisitor! visitor) {
+ return visitor.VisitVariable(this);
+ }
+ }
+
+ public static void RunValidationA()
+ {
+ IVariable! dim1 = new TestVariable("X");
+ IVariable! dim2 = new TestVariable("Y");
+ IVariable! dim3 = new TestVariable("Z");
+
+ FrameElement s1 = new FrameElement();
+ s1.AddCoordinate(dim1, Rational.ONE);
+ s1.AddCoordinate(dim2, Rational.MINUS_ONE);
+ s1.AddCoordinate(dim3, Rational.ZERO);
+ FrameElement s2 = new FrameElement();
+ s2.AddCoordinate(dim1, Rational.MINUS_ONE);
+ s2.AddCoordinate(dim2, Rational.ONE);
+ s2.AddCoordinate(dim3, Rational.ZERO);
+ FrameElement r1 = new FrameElement();
+ r1.AddCoordinate(dim1, Rational.ZERO);
+ r1.AddCoordinate(dim2, Rational.ZERO);
+ r1.AddCoordinate(dim3, Rational.ONE);
+ FrameElement d1 = new FrameElement();
+ d1.AddCoordinate(dim1, Rational.ONE);
+ d1.AddCoordinate(dim2, Rational.ONE);
+ d1.AddCoordinate(dim3, Rational.ZERO);
+
+ // create lcs from frame -- cf. Cousot/Halbwachs 1978, section 3.3.1.1
+ LinearConstraintSystem lcs = new LinearConstraintSystem(s1);
+ lcs.Dump();
+
+ lcs.AddVertex(s2);
+ lcs.Dump();
+
+ lcs.AddRay(r1);
+ lcs.Dump();
+
+ lcs.AddLine(d1);
+ lcs.Dump();
+
+ lcs.SimplifyConstraints();
+ lcs.Dump();
+
+#if LATER
+ lcs.GenerateFrameFromConstraints(); // should give us back the original frame...
+#endif
+ Console.WriteLine("IsSubset? {0}", lcs.IsSubset(lcs.Clone()));
+ lcs.Dump();
+ }
+
+ /// <summary>
+ /// Tests the example in section 3.4.3 of Cousot and Halbwachs.
+ /// </summary>
+ public static void RunValidationB()
+ {
+ IVariable! X = new TestVariable("X");
+ IVariable! Y = new TestVariable("Y");
+ IVariable! Z = new TestVariable("Z");
+ ArrayList /*LinearConstraint*/ cs = new ArrayList /*LinearConstraint*/ ();
+
+ LinearConstraint c = new LinearConstraint(LinearConstraint.ConstraintRelation.LE);
+ c.SetCoefficient(X, Rational.MINUS_ONE);
+ c.SetCoefficient(Y, Rational.ONE);
+ c.SetCoefficient(Z, Rational.MINUS_ONE);
+ c.rhs = Rational.ZERO;
+ cs.Add(c);
+
+ c = new LinearConstraint(LinearConstraint.ConstraintRelation.LE);
+ c.SetCoefficient(X, Rational.MINUS_ONE);
+ c.rhs = Rational.MINUS_ONE;
+ cs.Add(c);
+
+ c = new LinearConstraint(LinearConstraint.ConstraintRelation.LE);
+ c.SetCoefficient(X, Rational.MINUS_ONE);
+ c.SetCoefficient(Y, Rational.MINUS_ONE);
+ c.SetCoefficient(Z, Rational.ONE);
+ c.rhs = Rational.ZERO;
+ cs.Add(c);
+
+ c = new LinearConstraint(LinearConstraint.ConstraintRelation.LE);
+ c.SetCoefficient(Y, Rational.MINUS_ONE);
+ c.SetCoefficient(Z, Rational.ONE);
+ c.rhs = Rational.FromInt(3);
+ cs.Add(c);
+
+ LinearConstraintSystem lcs = new LinearConstraintSystem(cs);
+ Console.WriteLine("==================== The final linear constraint system ====================");
+ lcs.Dump();
+ }
+
+ public static void RunValidationC()
+ {
+ // Run the example in section 3.4.3 of Cousot and Halbwachs backwards, that is, from
+ // from to constraints.
+ IVariable! dim1 = new TestVariable("X");
+ IVariable! dim2 = new TestVariable("Y");
+ IVariable! dim3 = new TestVariable("Z");
+
+ FrameElement s0 = new FrameElement();
+ s0.AddCoordinate(dim1, Rational.ONE);
+ s0.AddCoordinate(dim2, Rational.FromInts(1, 2));
+ s0.AddCoordinate(dim3, Rational.FromInts(-1, 2));
+
+ FrameElement s1 = new FrameElement();
+ s1.AddCoordinate(dim1, Rational.ONE);
+ s1.AddCoordinate(dim2, Rational.FromInts(-1, 2));
+ s1.AddCoordinate(dim3, Rational.FromInts(1, 2));
+
+ FrameElement s2 = new FrameElement();
+ s2.AddCoordinate(dim1, Rational.FromInt(3));
+ s2.AddCoordinate(dim2, Rational.FromInts(-3, 2));
+ s2.AddCoordinate(dim3, Rational.FromInts(3, 2));
+
+ FrameElement r0 = new FrameElement();
+ r0.AddCoordinate(dim1, Rational.ONE);
+ r0.AddCoordinate(dim2, Rational.FromInts(1, 2));
+ r0.AddCoordinate(dim3, Rational.FromInts(-1, 2));
+
+ FrameElement r1 = new FrameElement();
+ r1.AddCoordinate(dim1, Rational.ONE);
+ r1.AddCoordinate(dim2, Rational.ZERO);
+ r1.AddCoordinate(dim3, Rational.ZERO);
+
+ FrameElement d0 = new FrameElement();
+ d0.AddCoordinate(dim1, Rational.ZERO);
+ d0.AddCoordinate(dim2, Rational.ONE);
+ d0.AddCoordinate(dim3, Rational.ONE);
+
+ LinearConstraintSystem lcs = new LinearConstraintSystem(s0);
+ lcs.Dump();
+
+ lcs.AddVertex(s1);
+ lcs.Dump();
+
+ lcs.AddVertex(s2);
+ lcs.Dump();
+
+ lcs.AddRay(r0);
+ lcs.Dump();
+
+ lcs.AddRay(r1);
+ lcs.Dump();
+
+ lcs.AddLine(d0);
+ lcs.Dump();
+
+ lcs.SimplifyConstraints();
+ lcs.Dump();
+
+#if LATER
+ lcs.GenerateFrameFromConstraints(); // should give us back the original frame...
+#endif
+ }
+ }
+} \ No newline at end of file
diff --git a/Source/AIFramework/Polyhedra/PolyhedraAbstraction.ssc b/Source/AIFramework/Polyhedra/PolyhedraAbstraction.ssc
new file mode 100644
index 00000000..bcf9c64d
--- /dev/null
+++ b/Source/AIFramework/Polyhedra/PolyhedraAbstraction.ssc
@@ -0,0 +1,744 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+namespace Microsoft.AbstractInterpretationFramework
+{
+ using System;
+ using System.Collections;
+ using System.Collections.Generic;
+ using System.Diagnostics;
+ using Microsoft.Contracts;
+ using Microsoft.Basetypes;
+
+ using ISet = Microsoft.Boogie.Set;
+ using HashSet = Microsoft.Boogie.Set;
+
+
+ /// <summary>
+ /// Represents an invariant over linear variable constraints, represented by a polyhedron.
+ /// </summary>
+ public class PolyhedraLattice : Lattice
+ {
+ private static readonly Logger! log = new Logger("Polyhedra");
+
+ private class PolyhedraLatticeElement : Element
+ {
+
+ public LinearConstraintSystem! lcs;
+
+ /// <summary>
+ /// Creates a top or bottom elements, according to parameter "top".
+ /// </summary>
+ public PolyhedraLatticeElement (bool top)
+ {
+ if (top)
+ {
+ lcs = new LinearConstraintSystem(new ArrayList /*LinearConstraint*/ ());
+ }
+ else
+ {
+ lcs = new LinearConstraintSystem();
+ }
+ }
+
+ [Pure][Reads(ReadsAttribute.Reads.Owned)]
+ public override string! ToString()
+ {
+ return lcs.ToString();
+ }
+
+ public override void Dump(string! msg) {
+ System.Console.WriteLine("PolyhedraLatticeElement.Dump({0}):", msg);
+ lcs.Dump();
+ }
+
+ [Pure][Reads(ReadsAttribute.Reads.Owned)]
+ public override ICollection<IVariable!>! FreeVariables()
+ {
+ return lcs.FreeVariables();
+ }
+
+ public PolyhedraLatticeElement (LinearConstraintSystem! lcs)
+ {
+ this.lcs = lcs;
+ }
+
+ public override Element! Clone ()
+ {
+ return new PolyhedraLatticeElement( (!) lcs.Clone());
+ }
+
+ } // class
+
+ readonly ILinearExprFactory! factory;
+ readonly IPropExprFactory! propFactory;
+
+ public PolyhedraLattice(ILinearExprFactory! linearFactory, IPropExprFactory! propFactory)
+ : base(linearFactory)
+ {
+ log.Enabled = Lattice.LogSwitch;
+ this.factory = linearFactory;
+ this.propFactory = propFactory;
+ // base(linearFactory);
+ }
+
+ public override Element! Top
+ {
+ get
+ {
+ return new PolyhedraLatticeElement(true);
+ }
+ }
+
+ public override Element! Bottom
+ {
+ get
+ {
+ return new PolyhedraLatticeElement(false);
+ }
+ }
+
+ public override bool IsBottom (Element! element)
+ {
+ PolyhedraLatticeElement e = (PolyhedraLatticeElement)element;
+ return e.lcs.IsBottom();
+ }
+
+ public override bool IsTop (Element! element)
+ {
+ PolyhedraLatticeElement e = (PolyhedraLatticeElement)element;
+ return e.lcs.IsTop();
+ }
+
+
+ /// <summary>
+ /// Returns true iff a is a subset of this.
+ /// </summary>
+ /// <param name="a"></param>
+ /// <returns></returns>
+ protected override bool AtMost (Element! first, Element! second) // this <= that
+ {
+ PolyhedraLatticeElement a = (PolyhedraLatticeElement) first;
+ PolyhedraLatticeElement b = (PolyhedraLatticeElement) second;
+ return b.lcs.IsSubset(a.lcs);
+ }
+
+
+ public override string! ToString (Element! e)
+ {
+ return ((PolyhedraLatticeElement)e).lcs.ToString();
+ }
+
+ public override IExpr! ToPredicate(Element! element)
+ {
+ PolyhedraLatticeElement e = (PolyhedraLatticeElement)element;
+ return e.lcs.ConvertToExpression(factory);
+ }
+
+
+
+ public override Lattice.Element! NontrivialJoin (Element! first, Element! second)
+ {
+ log.DbgMsg("Joining ..."); log.DbgMsgIndent();
+ PolyhedraLatticeElement aa = (PolyhedraLatticeElement) first;
+ PolyhedraLatticeElement bb = (PolyhedraLatticeElement) second;
+ PolyhedraLatticeElement result = new PolyhedraLatticeElement(aa.lcs.Join(bb.lcs));
+ log.DbgMsg(string.Format("{0} |_| {1} --> {2}", this.ToString(first), this.ToString(second), this.ToString(result)));
+ log.DbgMsgUnindent();
+ return result;
+ }
+
+
+ public override Lattice.Element! NontrivialMeet (Element! first, Element! second)
+ {
+ PolyhedraLatticeElement aa = (PolyhedraLatticeElement) first;
+ PolyhedraLatticeElement bb = (PolyhedraLatticeElement) second;
+ return new PolyhedraLatticeElement(aa.lcs.Meet(bb.lcs));
+ }
+
+
+ public override Lattice.Element! Widen (Element! first, Element! second)
+ {
+ log.DbgMsg("Widening ..."); log.DbgMsgIndent();
+ PolyhedraLatticeElement aa = (PolyhedraLatticeElement)first;
+ PolyhedraLatticeElement bb = (PolyhedraLatticeElement)second;
+
+ LinearConstraintSystem lcs = aa.lcs.Widen(bb.lcs);
+ PolyhedraLatticeElement result = new PolyhedraLatticeElement(lcs);
+ log.DbgMsg(string.Format("{0} |_| {1} --> {2}", this.ToString(first), this.ToString(second), this.ToString(result)));
+ log.DbgMsgUnindent();
+ return result;
+ }
+
+
+ public override Element! Eliminate (Element! e, IVariable! variable)
+ {
+ log.DbgMsg(string.Format("Eliminating {0} ...", variable));
+
+ PolyhedraLatticeElement ple = (PolyhedraLatticeElement)e;
+ if (ple.lcs.IsBottom())
+ {
+ return ple;
+ }
+ return new PolyhedraLatticeElement(ple.lcs.Project(variable));
+ }
+
+
+ public override Element! Rename (Element! e, IVariable! oldName, IVariable! newName)
+ {
+ log.DbgMsg(string.Format("Renaming {0} to {1} in {2} ...", oldName, newName, this.ToString(e)));
+
+ PolyhedraLatticeElement ple = (PolyhedraLatticeElement)e;
+ if (ple.lcs.IsBottom())
+ {
+ return ple;
+ }
+ return new PolyhedraLatticeElement(ple.lcs.Rename(oldName, newName));
+ }
+
+ public override bool Understands(IFunctionSymbol! f, IList/*<IExpr!>*/! args) {
+ return f is IntSymbol ||
+ f.Equals(Int.Add) ||
+ f.Equals(Int.Sub) ||
+ f.Equals(Int.Negate) ||
+ f.Equals(Int.Mul) ||
+ f.Equals(Int.Eq) ||
+ f.Equals(Int.Neq) ||
+ f.Equals(Prop.Not) ||
+ f.Equals(Int.AtMost) ||
+ f.Equals(Int.Less) ||
+ f.Equals(Int.Greater) ||
+ f.Equals(Int.AtLeast);
+ }
+
+ public override Answer CheckVariableDisequality(Element! e, IVariable! var1, IVariable! var2) {
+ PolyhedraLatticeElement! ple = (PolyhedraLatticeElement)e;
+ assume ple.lcs.Constraints != null;
+ ArrayList /*LinearConstraint!*/! clist = (ArrayList /*LinearConstraint!*/!)ple.lcs.Constraints.Clone();
+ LinearConstraint! lc = new LinearConstraint(LinearConstraint.ConstraintRelation.EQ);
+ lc.SetCoefficient(var1, Rational.ONE);
+ lc.SetCoefficient(var2, Rational.MINUS_ONE);
+ clist.Add(lc);
+ LinearConstraintSystem newLcs = new LinearConstraintSystem(clist);
+ if (newLcs.IsBottom()) {
+ return Answer.Yes;
+ } else {
+ return Answer.Maybe;
+ }
+ }
+
+ public override Answer CheckPredicate(Element! e, IExpr! pred) {
+ PolyhedraLatticeElement! ple = (PolyhedraLatticeElement)Constrain(e, pred);
+ if (ple.lcs.IsBottom()) {
+ return Answer.No;
+ }
+
+ // Note, "pred" may contain expressions that are not understood by the propFactory (in
+ // particular, this may happen because--currently, and perhaps is a design we'll want
+ // to change in the future--propFactory deals with BoogiePL expressions whereas "pred"
+ // may also refer to Equivalences.UninterpFun expressions). Thus, we cannot just
+ // call propFactory.Not(pred) to get the negation of "pred".
+ pred = new PolyhedraLatticeNegation(pred);
+ ple = (PolyhedraLatticeElement)Constrain(e, pred);
+ if (ple.lcs.IsBottom()) {
+ return Answer.Yes;
+ } else {
+ return Answer.Maybe;
+ }
+ }
+
+ class PolyhedraLatticeNegation : IFunApp
+ {
+ IExpr! arg;
+
+ public PolyhedraLatticeNegation(IExpr! arg) {
+ this.arg = arg;
+ // base();
+ }
+
+ [Pure][Reads(ReadsAttribute.Reads.Owned)] public object DoVisit(ExprVisitor! visitor) {
+ return visitor.VisitFunApp(this);
+ }
+
+ public IFunctionSymbol! FunctionSymbol { [Pure][Reads(ReadsAttribute.Reads.Owned)] get { return Prop.Not; } }
+
+ public IList/*<IExpr!>*/! Arguments {
+ [Pure][Reads(ReadsAttribute.Reads.Owned)] get {
+ IExpr[] args = new IExpr[] { arg };
+ return ArrayList.ReadOnly(args);
+ }
+ }
+
+ public IFunApp! CloneWithArguments(IList/*<IExpr!>*/! args) {
+ assert args.Count == 1;
+ return new PolyhedraLatticeNegation((IExpr!)args[0]);
+ }
+ }
+
+ public override IExpr/*?*/ EquivalentExpr(Element! e, IQueryable! q, IExpr! expr, IVariable! var, ISet/*<IVariable!>*/! prohibitedVars) {
+ // BUGBUG: TODO: this method can be implemented in a more precise way
+ return null;
+ }
+
+
+ public override Element! Constrain (Element! e, IExpr! expr)
+ {
+ log.DbgMsg(string.Format("Constraining with {0} into {1} ...", expr, this.ToString(e)));
+
+ PolyhedraLatticeElement ple = (PolyhedraLatticeElement)e;
+ if (ple.lcs.IsBottom())
+ {
+ return ple;
+ }
+ LinearCondition le = LinearExpressionBuilder.AsCondition(expr);
+ if (le != null) {
+ // update the polyhedron according to the linear expression
+ assume ple.lcs.Constraints != null;
+ ArrayList /*LinearConstraint*/ clist = (ArrayList! /*LinearConstraint*/)ple.lcs.Constraints.Clone();
+ le.AddToConstraintSystem(clist);
+ LinearConstraintSystem newLcs = new LinearConstraintSystem(clist);
+
+ return new PolyhedraLatticeElement(newLcs);
+ }
+ return ple;
+ }
+
+ } // class
+
+
+ /// <summary>
+ /// A LinearCondition follows this grammar:
+ /// LinearCondition ::= unsatisfiable
+ /// | LinearConstraint
+ /// | ! LinearConstraint
+ /// Note that negations are distributed to the leaves.
+ /// </summary>
+ abstract class LinearCondition
+ {
+ /// <summary>
+ /// Adds constraints to the list "clist". If "this"
+ /// entails some disjunctive constraints, they may not be added.
+ /// </summary>
+ /// <param name="clist"></param>
+ public abstract void AddToConstraintSystem(ArrayList! /*LinearConstraint*/ clist);
+ }
+
+ class LCBottom : LinearCondition
+ {
+ public override void AddToConstraintSystem(ArrayList! /*LinearConstraint*/ clist)
+ {
+ // make an unsatisfiable constraint
+ LinearConstraint lc = new LinearConstraint(LinearConstraint.ConstraintRelation.EQ);
+ lc.rhs = Rational.FromInt(1);
+ clist.Add(lc);
+ }
+ }
+
+ class LinearConditionLiteral : LinearCondition
+ {
+ public readonly bool positive;
+ public readonly LinearConstraint! constraint;
+ /// <summary>
+ /// Precondition: positive || constraint.Relation == LinearConstraint.ConstraintRelation.EQ
+ /// </summary>
+ /// <param name="positive"></param>
+ /// <param name="constraint"></param>
+ public LinearConditionLiteral(bool positive, LinearConstraint! constraint)
+ requires positive || constraint.Relation == LinearConstraint.ConstraintRelation.EQ;
+ {
+ this.positive = positive;
+ this.constraint = constraint;
+ }
+ public override void AddToConstraintSystem(ArrayList! /*LinearConstraint*/ clist)
+ {
+ if (positive)
+ {
+ clist.Add(constraint);
+ }
+ else
+ {
+ assert constraint.Relation == LinearConstraint.ConstraintRelation.EQ;
+ // the constraint is disjunctive, so just ignore it
+ }
+ }
+ }
+
+ class LinearExpressionBuilder
+ {
+ /// <summary>
+ /// Builds a linear condition from "e", if possible; returns null if not possible.
+ /// </summary>
+ /// <param name="e"></param>
+ /// <returns></returns>
+ public static /*maybe null*/ LinearCondition AsCondition(IExpr e) /* throws ArithmeticException */
+ {
+ return GetCond(e, true);
+ }
+
+ static /*maybe null*/ LinearCondition GetCond(IExpr e, bool positive) /* throws ArithmeticException */
+ {
+ IFunApp funapp = e as IFunApp;
+ if (funapp == null) {
+ return null;
+ }
+ IFunctionSymbol! s = funapp.FunctionSymbol;
+ if ((positive && s.Equals(Prop.False)) ||
+ (!positive && s.Equals(Prop.True))) {
+ return new LCBottom();
+ } else if (s.Equals(Prop.Not)) {
+ assert funapp.Arguments.Count == 1;
+ return GetCond((IExpr!)funapp.Arguments[0], !positive);
+ } else if (funapp.Arguments.Count == 2) {
+ IExpr! arg0 = (IExpr!)funapp.Arguments[0];
+ IExpr! arg1 = (IExpr!)funapp.Arguments[1];
+ LinearExpr le0 = AsExpr(arg0);
+ if (le0 == null) {
+ return null;
+ }
+ LinearExpr le1 = AsExpr(arg1);
+ if (le1 == null) {
+ return null;
+ }
+
+ LinearConstraint constraint = null;
+ bool sense = true;
+ if ((positive && s.Equals(Int.Less)) || (!positive && s.Equals(Int.AtLeast)))
+ {
+ constraint = MakeConstraint(le0, le1, LinearConstraint.ConstraintRelation.LE, BigNum.ONE);
+ }
+ else if ((positive && s.Equals(Int.AtMost)) || (!positive && s.Equals(Int.Greater)))
+ {
+ constraint = MakeConstraint(le0, le1, LinearConstraint.ConstraintRelation.LE, BigNum.ZERO);
+ }
+ else if ((positive && s.Equals(Int.AtLeast)) || (!positive && s.Equals(Int.Less)))
+ {
+ constraint = MakeConstraint(le1, le0, LinearConstraint.ConstraintRelation.LE, BigNum.ZERO);
+ }
+ else if ((positive && s.Equals(Int.Greater)) || (!positive && s.Equals(Int.AtMost)))
+ {
+ constraint = MakeConstraint(le1, le0, LinearConstraint.ConstraintRelation.LE, BigNum.ONE);
+ }
+ else if (s.Equals(Int.Eq))
+ {
+ constraint = MakeConstraint(le0, le1, LinearConstraint.ConstraintRelation.EQ, BigNum.ZERO);
+ sense = positive;
+ }
+ else if (s.Equals(Int.Neq))
+ {
+ constraint = MakeConstraint(le0, le1, LinearConstraint.ConstraintRelation.EQ, BigNum.ZERO);
+ sense = !positive;
+ }
+ if (constraint != null) {
+ if (constraint.coefficients.Count != 0) {
+ return new LinearConditionLiteral(sense, constraint);
+ } else if (constraint.IsConstantSatisfiable()) {
+ return null;
+ } else {
+ return new LCBottom();
+ }
+ }
+ }
+ return null;
+ }
+
+ public static LinearConstraint MakeConstraint(LinearExpr! le0, LinearExpr! le1,
+ LinearConstraint.ConstraintRelation rel, BigNum constantOffset) /* throws ArithmeticException */
+ {
+ le1.Negate();
+ le0.Add(le1);
+ le0.AddConstant(constantOffset);
+ return le0.ToConstraint(rel);
+ }
+
+ /// <summary>
+ /// Builds a linear expression from "e", if possible; returns null if not possible.
+ /// </summary>
+ /// <param name="e"></param>
+ /// <returns></returns>
+ public static /*maybe null*/ LinearExpr AsExpr(IExpr! e) /* throws ArithmeticException */
+ {
+ if (e is IVariable) {
+ // Note, without a type for the variable, we don't know if the identifier is intended to hold an integer value.
+ // However, it seems that no harm can be caused by here treating the identifier as if it held an
+ // integer value, because other parts of this method will reject the expression as a linear expression
+ // if non-numeric operations other than equality are applied to the identifier.
+ return new LinearExpr((IVariable)e);
+ } else if (e is IFunApp) {
+ IFunApp! funapp = (IFunApp)e;
+ IFunctionSymbol! s = funapp.FunctionSymbol;
+
+ if (s is IntSymbol) {
+ return new LinearExpr(((IntSymbol)s).Value);
+ } else if (s.Equals(Int.Negate)) {
+ assert funapp.Arguments.Count == 1;
+ LinearExpr le = AsExpr((IExpr!)funapp.Arguments[0]);
+ if (le != null) {
+ le.Negate();
+ return le;
+ }
+ } else if (s.Equals(Int.Add) || s.Equals(Int.Sub) || s.Equals(Int.Mul)) {
+ assert funapp.Arguments.Count == 2;
+ IExpr! arg0 = (IExpr!)funapp.Arguments[0];
+ IExpr! arg1 = (IExpr!)funapp.Arguments[1];
+ LinearExpr le0 = AsExpr(arg0);
+ if (le0 == null) {
+ return null;
+ }
+ LinearExpr le1 = AsExpr(arg1);
+ if (le1 == null) {
+ return null;
+ }
+
+ if (s.Equals(Int.Add)) {
+ le0.Add(le1);
+ return le0;
+ } else if (s.Equals(Int.Sub)) {
+ le1.Negate();
+ le0.Add(le1);
+ return le0;
+ } else if (s.Equals(Int.Mul)) {
+ BigNum x;
+ if (le0.AsConstant(out x))
+ {
+ le1.Multiply(x);
+ return le1;
+ }
+ else if (le1.AsConstant(out x))
+ {
+ le0.Multiply(x);
+ return le0;
+ }
+ }
+ }
+ }
+ return null;
+ }
+ }
+
+ class LinearExpr
+ {
+ BigNum constant;
+ Term terms;
+
+ class Term
+ {
+ public BigNum coeff; // non-0, if the node is used
+ public IVariable! var;
+ public Term next;
+
+ public Term(BigNum coeff, IVariable! var)
+ {
+ this.coeff = coeff;
+ this.var = var;
+ // base();
+ }
+ }
+
+ public LinearExpr(BigNum x)
+ {
+ constant = x;
+ }
+
+ public LinearExpr(IVariable! var)
+ {
+ constant = BigNum.ZERO;
+ terms = new Term(BigNum.ONE, var);
+ }
+
+ public ISet /*IVariable!*/ GetDefinedDimensions()
+ {
+ HashSet /*IVariable!*/! dims = new HashSet /*IVariable!*/ ();
+ for (Term current = terms; current != null; current = current.next)
+ {
+ dims.Add(current.var);
+ }
+ return dims;
+ }
+
+ public BigNum TermCoefficient(/*MayBeNull*/ IVariable! var)
+ {
+ BigNum z = BigNum.ZERO;
+ if (var == null)
+ {
+ z = this.constant;
+ }
+ else if (terms != null)
+ {
+ Term current = terms;
+ while (current != null)
+ {
+ if (current.var == var)
+ {
+ break;
+ }
+ current = current.next;
+ }
+ if (current != null)
+ {
+ z = current.coeff;
+ }
+ }
+ return z;
+ }
+
+ public bool AsConstant(out BigNum x)
+ {
+ if (terms == null)
+ {
+ x = constant;
+ return true;
+ }
+ else
+ {
+ x = BigNum.FromInt(-70022); // to please complier
+ return false;
+ }
+ }
+
+ public void Negate() /* throws ArithmeticException */
+ {
+ checked
+ {
+ constant = -constant;
+ }
+
+ for (Term t = terms; t != null; t = t.next)
+ {
+ checked
+ {
+ t.coeff = -t.coeff;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Adds "x" to "this".
+ /// </summary>
+ /// <param name="x"></param>
+ public void AddConstant(BigNum x) /* throws ArithmeticException */
+ {
+ checked
+ {
+ constant += x;
+ }
+ }
+
+ /// <summary>
+ /// Adds "le" to "this". Afterwards, "le" should not be used, because it will have been destroyed.
+ /// </summary>
+ /// <param name="le"></param>
+ public void Add(LinearExpr! le) /* throws ArithmeticException */
+ requires le != this;
+ {
+ checked
+ {
+ constant += le.constant;
+ }
+ le.constant = BigNum.FromInt(-70029); // "le" should no longer be used; assign it a strange value so that misuse is perhaps more easily detected
+
+ // optimization:
+ if (le.terms == null)
+ {
+ return;
+ }
+ else if (terms == null)
+ {
+ terms = le.terms;
+ le.terms = null;
+ return;
+ }
+
+ // merge the two term lists
+ // Use a nested loop, which is quadratic in time complexity, but we hope the lists will be small
+ Term newTerms = null;
+ while (le.terms != null)
+ {
+ // take off next term from "le"
+ Term t = le.terms;
+ le.terms = t.next;
+ t.next = null;
+
+ for (Term u = terms; u != null; u = u.next)
+ {
+ if (u.var == t.var)
+ {
+ checked
+ {
+ u.coeff += t.coeff;
+ }
+ goto NextOuter;
+ }
+ }
+ t.next = newTerms;
+ newTerms = t;
+
+ NextOuter: ;
+ }
+
+ // finally, include all non-0 terms
+ while (terms != null)
+ {
+ // take off next term from "this"
+ Term t = terms;
+ terms = t.next;
+
+ if (!t.coeff.IsZero)
+ {
+ t.next = newTerms;
+ newTerms = t;
+ }
+ }
+ terms = newTerms;
+ }
+
+ public void Multiply(BigNum x) /* throws ArithmeticException */
+ {
+ if (x.IsZero)
+ {
+ constant = BigNum.ZERO;
+ terms = null;
+ }
+ else
+ {
+ for (Term t = terms; t != null; t = t.next)
+ {
+ checked
+ {
+ t.coeff *= x;
+ }
+ }
+ checked
+ {
+ constant *= x;
+ }
+ }
+ }
+
+ public bool IsInvertible(IVariable! var)
+ {
+ for (Term t = terms; t != null; t = t.next)
+ {
+ if (t.var == var)
+ {
+ System.Diagnostics.Debug.Assert(!t.coeff.IsZero);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public LinearConstraint ToConstraint(LinearConstraint.ConstraintRelation rel) /* throws ArithmeticException */
+ {
+ LinearConstraint constraint = new LinearConstraint(rel);
+ for (Term t = terms; t != null; t = t.next)
+ {
+ constraint.SetCoefficient(t.var, t.coeff.ToRational);
+ }
+ BigNum rhs = -constant;
+ constraint.rhs = rhs.ToRational;
+ return constraint;
+ }
+ }
+}
diff --git a/Source/AIFramework/Polyhedra/SimplexTableau.ssc b/Source/AIFramework/Polyhedra/SimplexTableau.ssc
new file mode 100644
index 00000000..b6f4095c
--- /dev/null
+++ b/Source/AIFramework/Polyhedra/SimplexTableau.ssc
@@ -0,0 +1,717 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+namespace Microsoft.AbstractInterpretationFramework
+{
+ using System.Collections;
+ using System;
+ using Microsoft.Contracts;
+ using Microsoft.Basetypes;
+ using IMutableSet = Microsoft.Boogie.Set;
+ using HashSet = Microsoft.Boogie.Set;
+
+
+ /// <summary>
+ /// Used by LinearConstraintSystem.GenerateFrameFromConstraints.
+ /// </summary>
+ public class SimplexTableau
+ {
+ readonly int rows;
+ readonly int columns;
+ readonly Rational[,]! m;
+
+ readonly int numInitialVars;
+ readonly int numSlackVars;
+ readonly int rhsColumn;
+
+ readonly ArrayList /*IVariable!*/! dims;
+ readonly int[]! basisColumns;
+ readonly int[]! inBasis;
+ bool constructionDone = false;
+
+ void CheckInvariant()
+ {
+ assert(rows == m.GetLength(0));
+ assert(1 <= columns && columns == m.GetLength(1));
+ assert(0 <= numInitialVars);
+ assert(0 <= numSlackVars && numSlackVars <= rows);
+ assert(numInitialVars + numSlackVars + 1 == columns);
+ assert(rhsColumn == columns - 1);
+ assert(dims.Count == numInitialVars);
+ assert(basisColumns.Length == rows);
+ assert(inBasis.Length == numInitialVars + numSlackVars);
+
+ bool[] b = new bool[numInitialVars + numSlackVars];
+ int numColumnsInBasis = 0;
+ int numUninitializedRowInfo = 0;
+ for (int i = 0; i < rows; i++)
+ {
+ int c = basisColumns[i];
+ if (c == rhsColumn)
+ {
+ // all coefficients in this row are 0 (but the right-hand side may be non-0)
+ for (int j = 0; j < rhsColumn; j++)
+ {
+ assert m[i,j].IsZero;
+ }
+ numColumnsInBasis++;
+ }
+ else if (c == -1)
+ {
+ assert(!constructionDone);
+ numUninitializedRowInfo++;
+ }
+ else
+ {
+ // basis column is a column
+ assert(0 <= c && c < numInitialVars + numSlackVars);
+ // basis column is unique
+ assert(!b[c]);
+ b[c] = true;
+ // column is marked as being in basis
+ assert(inBasis[c] == i);
+ // basis column really is a basis column
+ for (int j = 0; j < rows; j++)
+ {
+ if (j == i)
+ {
+ assert m[j,c].HasValue(1);// == (Rational)new Rational(1));
+ }
+ else
+ {
+ assert m[j,c].IsZero;
+ }
+ }
+ }
+ }
+ // no other columns are marked as being in basis
+ foreach (int i in inBasis)
+ {
+ if (0 <= i)
+ {
+ assert(i < rows);
+ numColumnsInBasis++;
+ }
+ else
+ {
+ assert(i == -1);
+ }
+ }
+ assert(rows - numUninitializedRowInfo <= numColumnsInBasis && numColumnsInBasis <= rows);
+ assert(!constructionDone || numUninitializedRowInfo == 0);
+ }
+
+ /// <summary>
+ /// Constructs a matrix that represents the constraints "constraints", adding slack
+ /// variables for the inequalities among "constraints". Puts the matrix in canonical
+ /// form.
+ /// </summary>
+ /// <param name="constraints"></param>
+ [NotDelayed]
+ public SimplexTableau(ArrayList /*LinearConstraint*/! constraints)
+ {
+#if DEBUG_PRINT
+ Console.WriteLine("DEBUG: SimplexTableau constructor called with:");
+ foreach (LinearConstraint lc in constraints)
+ {
+ Console.WriteLine(" {0}", lc);
+ }
+#endif
+ // Note: This implementation is not particularly efficient, but it'll do for now.
+
+ ArrayList dims = this.dims = new ArrayList /*IVariable!*/ ();
+ int slacks = 0;
+ foreach (LinearConstraint! cc in constraints)
+ {
+ foreach (IVariable! dim in cc.coefficients.Keys)
+ {
+ if (!dims.Contains(dim))
+ {
+ dims.Add(dim);
+ }
+ }
+ if (cc.Relation == LinearConstraint.ConstraintRelation.LE)
+ {
+ slacks++;
+ }
+ }
+
+ int numInitialVars = this.numInitialVars = dims.Count;
+ int numSlackVars = this.numSlackVars = slacks;
+ int rows = this.rows = constraints.Count;
+ int columns = this.columns = numInitialVars + numSlackVars + 1;
+ this.m = new Rational[rows, columns];
+ this.rhsColumn = columns-1;
+ this.basisColumns = new int[rows];
+ this.inBasis = new int[columns-1];
+
+ base();
+
+ for (int i = 0; i < inBasis.Length; i++)
+ {
+ inBasis[i] = -1;
+ }
+
+ // Fill in the matrix
+ int r = 0;
+ int iSlack = 0;
+ foreach (LinearConstraint! cc in constraints)
+ {
+ for (int i = 0; i < dims.Count; i++)
+ {
+ m[r,i] = cc[(IVariable!)dims[i]];
+ }
+ if (cc.Relation == LinearConstraint.ConstraintRelation.LE)
+ {
+ m[r, numInitialVars + iSlack] = Rational.ONE;
+ basisColumns[r] = numInitialVars + iSlack;
+ inBasis[numInitialVars + iSlack] = r;
+ iSlack++;
+ }
+ else
+ {
+ basisColumns[r] = -1; // special value to communicate to Pivot that basis column i hasn't been set up yet
+ }
+ m[r,rhsColumn] = cc.rhs;
+ r++;
+ }
+ assert(r == constraints.Count);
+ assert(iSlack == numSlackVars);
+#if DEBUG_PRINT
+ Console.WriteLine("DEBUG: Intermediate tableau state in SimplexTableau constructor:");
+ Dump();
+#endif
+
+ // Go through the rows with uninitialized basis columns. These correspond to equality constraints.
+ // For each one, find an initial variable (non-slack variable) whose column we can make the basis
+ // column of the row.
+ for (int i = 0; i < rows; i++)
+ {
+ if (basisColumns[i] != -1)
+ {
+ continue;
+ }
+ // Find a non-0 column in row i that we can make a basis column. Since rows corresponding
+ // to equality constraints don't have slack variables and since the pivot operations performed
+ // by iterations of this loop don't introduce any non-0 coefficients in the slack-variable
+ // columns of these rows, we only need to look through the columns corresponding to initial
+ // variables.
+ for (int j = 0; j < numInitialVars; j++)
+ {
+ if (m[i,j].IsNonZero)
+ {
+#if DEBUG_PRINT
+ Console.WriteLine("-- About to Pivot({0},{1})", i, j);
+#endif
+ assert(inBasis[j] == -1);
+ Pivot(i,j);
+#if DEBUG_PRINT
+ Console.WriteLine("Tableau after Pivot:");
+ Dump();
+ #endif
+ goto SET_UP_NEXT_INBASIS_COLUMN;
+ }
+ }
+ // Check the assertion in the comment above, that is, that columns corresponding to slack variables
+ // are 0 in this row.
+ for (int j = numInitialVars; j < rhsColumn; j++)
+ {
+ assert m[i,j].IsZero;
+ }
+ // There is no column in this row that we can put into basis.
+ basisColumns[i] = rhsColumn;
+ SET_UP_NEXT_INBASIS_COLUMN: {}
+ }
+
+ constructionDone = true;
+ CheckInvariant();
+ }
+
+ public IMutableSet! /*IVariable!*/ GetDimensions()
+ {
+ HashSet /*IVariable!*/ z = new HashSet /*IVariable!*/ ();
+ foreach (IVariable! dim in dims)
+ {
+ z.Add(dim);
+ }
+ return z;
+ }
+
+ public Rational this [int r, int c]
+ {
+ get
+ {
+ return m[r,c];
+ }
+ set
+ {
+ m[r,c] = value;
+ }
+ }
+
+ /// <summary>
+ /// Applies the Pivot Operation on row "r" and column "c".
+ ///
+ /// This method can be called when !constructionDone, that is, at a time when not all basis
+ /// columns have been set up (indicated by -1 in basisColumns). This method helps set up
+ /// those basis columns.
+ ///
+ /// The return value is an undo record that can be used with UnPivot.
+ /// </summary>
+ /// <param name="r"></param>
+ /// <param name="c"></param>
+ public Rational[]! Pivot(int r, int c)
+ {
+ assert(0 <= r && r < rows);
+ assert(0 <= c && c < columns-1);
+ assert(m[r,c].IsNonZero);
+ assert(inBasis[c] == -1); // follows from invariant and m[r,c] != 0
+ assert(basisColumns[r] != rhsColumn); // follows from invariant and m[r,c] != 0
+
+ Rational[] undo = new Rational[rows+1];
+ for (int i = 0; i < rows; i++)
+ {
+ undo[i] = m[i,c];
+ }
+
+ // scale the pivot row
+ Rational q = m[r,c];
+ if (q != Rational.ONE)
+ {
+ for (int j = 0; j < columns; j++)
+ {
+ m[r,j] /= q;
+ }
+ }
+
+ // subtract a multiple of the pivot row from all other rows
+ for (int i = 0; i < rows; i++)
+ {
+ if (i != r)
+ {
+ q = m[i,c];
+ if (q.IsNonZero)
+ {
+ for (int j = 0; j < columns; j++)
+ {
+ m[i,j] -= q * m[r,j];
+ }
+ }
+ }
+ }
+
+ // update basis information
+ int prevCol = basisColumns[r];
+ undo[rows] = Rational.FromInt(prevCol);
+ basisColumns[r] = c;
+ if (prevCol != -1)
+ {
+ inBasis[prevCol] = -1;
+ }
+ inBasis[c] = r;
+
+ return undo;
+ }
+
+ /// <summary>
+ /// If the last operation applied to the tableau was:
+ /// undo = Pivot(i,j);
+ /// then UnPivot(i, j, undo) undoes the pivot operation.
+ /// Note: This operation is not supported for any call to Pivot before constructionDone
+ /// is set to true.
+ /// </summary>
+ /// <param name="r"></param>
+ /// <param name="c"></param>
+ /// <param name="undo"></param>
+ void UnPivot(int r, int c, Rational[]! undo)
+ {
+ assert(0 <= r && r < rows);
+ assert(0 <= c && c < columns-1);
+ assert(m[r,c].HasValue(1));
+ assert(undo.Length == rows+1);
+
+ // add a multiple of the pivot row to all other rows
+ for (int i = 0; i < rows; i++)
+ {
+ if (i != r)
+ {
+ Rational q = undo[i];
+ if (q.IsNonZero)
+ {
+ for (int j = 0; j < columns; j++)
+ {
+ m[i,j] += q * m[r,j];
+ }
+ }
+ }
+ }
+
+ // scale the pivot row
+ Rational p = undo[r];
+ for (int j = 0; j < columns; j++)
+ {
+ m[r,j] *= p;
+ }
+
+ // update basis information
+ int prevCol = undo[rows].AsInteger;
+ assert(prevCol != -1);
+ basisColumns[r] = prevCol;
+ inBasis[c] = -1;
+ inBasis[prevCol] = r;
+ }
+
+ /// <summary>
+ /// Returns true iff the current basis of the system of constraints modeled by the simplex tableau
+ /// is feasible. May have a side effect of performing a number of pivot operations on the tableau,
+ /// but any such pivot operation will be in the columns of slack variables (that is, this routine
+ /// does not change the set of initial-variable columns in basis).
+ ///
+ /// CAVEAT: I have no particular reason to believe that the algorithm used here will terminate. --KRML
+ /// </summary>
+ /// <returns></returns>
+ public bool IsFeasibleBasis
+ {
+ get
+ {
+ // while there is a slack variable in basis whose row has a negative right-hand side
+ while (true)
+ {
+ bool feasibleBasis = true;
+ for (int c = numInitialVars; c < rhsColumn; c++)
+ {
+ int k = inBasis[c];
+ if (0 <= k && k < rhsColumn && m[k,rhsColumn].IsNegative)
+ {
+ assert(m[k,c].HasValue(1)); // c is in basis
+ // Try to pivot on a different slack variable in this row
+ for (int i = numInitialVars; i < rhsColumn; i++)
+ {
+ if (m[k,i].IsNegative)
+ {
+ assert(c != i); // c is in basis, so m[k,c]==1, which is not negative
+ Pivot(k, i);
+#if DEBUG_PRINT
+ Console.WriteLine("Tableau after Pivot operation on ({0},{1}) in IsFeasibleBasis:", k, i);
+ Dump();
+#endif
+ assert(inBasis[c] == -1);
+ assert(inBasis[i] == k);
+ assert(m[k,rhsColumn].IsNonNegative);
+ goto START_ANEW;
+ }
+ }
+ feasibleBasis = false;
+ }
+ }
+ return feasibleBasis;
+ START_ANEW: ;
+ }
+ return false; // make compiler shut up
+ }
+ }
+
+ /// <summary>
+ /// Whether or not all initial variables (the non-slack variables) are in basis)
+ /// </summary>
+ public bool AllInitialVarsInBasis
+ {
+ get
+ {
+ for (int i = 0; i < numInitialVars; i++)
+ {
+ if (inBasis[i] == -1)
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+
+ /// <summary>
+ /// Adds as many initial variables as possible to the basis.
+ /// </summary>
+ /// <returns></returns>
+ public void AddInitialVarsToBasis()
+ {
+ // while there exists an initial variable not in the basis and not satisfying
+ // condition 3.4.2.2 in Cousot and Halbwachs, perform a pivot operation
+ while (true)
+ {
+ for (int i = 0; i < numInitialVars; i++)
+ {
+ if (inBasis[i] == -1)
+ {
+ // initial variable i is not in the basis
+ for (int j = 0; j < rows; j++)
+ {
+ if (m[j,i].IsNonZero)
+ {
+ int k = basisColumns[j];
+ if (numInitialVars <= k && k < rhsColumn)
+ {
+ // slack variable k is in basis for row j
+ Pivot(j, i);
+ assert(inBasis[k] == -1);
+ assert(inBasis[i] == j && basisColumns[j] == i);
+ goto START_ANEW;
+ }
+ }
+ }
+ }
+ }
+ // No more initial variables can be moved into basis.
+ return;
+ START_ANEW: {}
+ }
+ }
+
+ /// <summary>
+ /// Adds to "lines" the lines implied by initial-variable columns not in basis
+ /// (see section 3.4.2 of Cousot and Halbwachs), and adds to "constraints" the
+ /// constraints to exclude those lines (see step 4.2 of section 3.4.3 of
+ /// Cousot and Halbwachs).
+ /// </summary>
+ /// <param name="lines"></param>
+ /// <param name="constraints"></param>
+ public void ProduceLines(ArrayList /*FrameElement*/! lines, ArrayList /*LinearConstraint*/! constraints)
+ {
+ // for every initial variable not in basis
+ for (int i0 = 0; i0 < numInitialVars; i0++)
+ {
+ if (inBasis[i0] == -1)
+ {
+ FrameElement fe = new FrameElement();
+ LinearConstraint lc = new LinearConstraint(LinearConstraint.ConstraintRelation.EQ);
+ for (int i = 0; i < numInitialVars; i++)
+ {
+ if (i == i0)
+ {
+ fe.AddCoordinate((IVariable!)dims[i], Rational.ONE);
+ lc.SetCoefficient((IVariable!)dims[i], Rational.ONE);
+ }
+ else if (inBasis[i] != -1)
+ {
+ // i is a basis column
+ assert(m[inBasis[i],i].HasValue(1));
+ Rational val = -m[inBasis[i],i0];
+ fe.AddCoordinate((IVariable!)dims[i], val);
+ lc.SetCoefficient((IVariable!)dims[i], val);
+ }
+ }
+ lines.Add(fe);
+ constraints.Add(lc);
+ }
+ }
+ }
+
+ /// <summary>
+ /// From a feasible point where all initial variables are in the basis, traverses
+ /// all feasible bases containing all initial variables. For each such basis, adds
+ /// the vertices to "vertices" and adds to "rays" the extreme rays. See step 4.2
+ /// in section 3.4.3 of Cousot and Halbwachs.
+ /// A more efficient algorithm is found in the paper "An algorithm for
+ /// determining all extreme points of a convex polytope" by N. E. Dyer and L. G. Proll,
+ /// Mathematical Programming, 12, 1977.
+ /// Assumes that the tableau is in a state where all initial variables are in the basis.
+ /// This method has no net effect on the tableau.
+ /// Note: Duplicate vertices and rays may be added.
+ /// </summary>
+ /// <param name="vertices"></param>
+ /// <param name="rays"></param>
+ public void TraverseVertices(ArrayList! /*FrameElement*/ vertices, ArrayList! /*FrameElement*/ rays)
+ {
+ ArrayList /*bool[]*/ basesSeenSoFar = new ArrayList /*bool[]*/ ();
+ TraverseBases(basesSeenSoFar, vertices, rays);
+ }
+
+ /// <summary>
+ /// Worker method of TraverseVertices.
+ /// This method has no net effect on the tableau.
+ /// </summary>
+ /// <param name="basesSeenSoFar"></param>
+ /// <param name="vertices"></param>
+ /// <param name="rays"></param>
+ void TraverseBases(ArrayList /*bool[]*/! basesSeenSoFar, ArrayList /*FrameElement*/! vertices, ArrayList /*FrameElement*/! rays)
+ {
+ CheckInvariant();
+
+ bool[] thisBasis = new bool[numSlackVars];
+ for (int i = numInitialVars; i < rhsColumn; i++)
+ {
+ if (inBasis[i] != -1)
+ {
+ thisBasis[i-numInitialVars] = true;
+ }
+ }
+ foreach (bool[]! basis in basesSeenSoFar)
+ {
+ assert(basis.Length == numSlackVars);
+ for (int i = 0; i < numSlackVars; i++)
+ {
+ if (basis[i] != thisBasis[i])
+ {
+ goto COMPARE_WITH_NEXT_BASIS;
+ }
+ }
+ // thisBasis and basis are the same--that is, basisColumns has been visited before--so
+ // we don't traverse anything from here
+ return;
+ COMPARE_WITH_NEXT_BASIS: {}
+ }
+ // basisColumns has not been seen before; record thisBasis and continue with the traversal here
+ basesSeenSoFar.Add(thisBasis);
+
+#if DEBUG_PRINT
+ Console.Write("TraverseBases, new basis: ");
+ foreach (bool t in thisBasis) {
+ Console.Write("{0}", t ? "*" : ".");
+ }
+ Console.WriteLine();
+ Dump();
+#endif
+ // Add vertex
+ FrameElement v = new FrameElement();
+ for (int i = 0; i < rows; i++)
+ {
+ int j = basisColumns[i];
+ if (j < numInitialVars)
+ {
+ v.AddCoordinate((IVariable!)dims[j], m[i,rhsColumn]);
+ }
+ }
+#if DEBUG_PRINT
+ Console.WriteLine(" Adding vertex: {0}", v);
+#endif
+ vertices.Add(v);
+
+ // Add rays. Traverse all columns corresponding to slack variables that
+ // are not in basis (see second bullet of section 3.4.2 of Cousot and Halbwachs).
+ for (int i0 = numInitialVars; i0 < rhsColumn; i0++)
+ {
+ if (inBasis[i0] != -1)
+ {
+ // skip those slack-variable columns that are in basis
+ continue;
+ }
+ // check if slack-variable, non-basis column i corresponds to an extreme ray
+ for (int row = 0; row < rows; row++)
+ {
+ if (m[row,i0].IsPositive)
+ {
+ for (int k = numInitialVars; k < rhsColumn; k++)
+ {
+ if (inBasis[k] != -1 && m[row,k].IsNonZero)
+ {
+ // does not correspond to an extreme ray
+ goto CHECK_NEXT_SLACK_VAR;
+ }
+ }
+ }
+ }
+ // corresponds to an extreme ray
+ FrameElement ray = new FrameElement();
+ for (int i = 0; i < numInitialVars; i++)
+ {
+ int j0 = inBasis[i];
+ Rational val = -m[j0,i0];
+ ray.AddCoordinate((IVariable!)dims[i], val);
+ }
+#if DEBUG_PRINT
+ Console.WriteLine(" Adding ray: {0}", ray);
+#endif
+ rays.Add(ray);
+ CHECK_NEXT_SLACK_VAR: {}
+ }
+
+ // Continue traversal
+ for (int i = numInitialVars; i < rhsColumn; i++)
+ {
+ int j = inBasis[i];
+ if (j != -1)
+ {
+ // try moving i out of basis and some other slack-variable column into basis
+ for (int k = numInitialVars; k < rhsColumn; k++)
+ {
+ if (inBasis[k] == -1 && m[j,k].IsPositive)
+ {
+ Rational[] undo = Pivot(j, k);
+ // check if the new basis is feasible
+ for (int p = 0; p < rows; p++)
+ {
+ int c = basisColumns[p];
+ if (numInitialVars <= c && c < rhsColumn && m[p,rhsColumn].IsNegative)
+ {
+ // not feasible
+ goto AFTER_TRAVERSE;
+ }
+ }
+ TraverseBases(basesSeenSoFar, vertices, rays);
+ AFTER_TRAVERSE:
+ UnPivot(j, k, undo);
+ }
+ }
+ }
+ }
+ }
+
+ public void Dump()
+ {
+ // names
+ Console.Write(" ");
+ for (int i = 0; i < numInitialVars; i++)
+ {
+ Console.Write(" {0,4} ", dims[i]);
+ }
+ Console.WriteLine();
+ // numbers
+ Console.Write(" ");
+ for (int i = 0; i < columns; i++)
+ {
+ if (i == numInitialVars || i == rhsColumn)
+ {
+ Console.Write("|");
+ }
+ Console.Write(" {0,4}", i);
+ if (i < rhsColumn && inBasis[i] != -1)
+ {
+ Console.Write("* ");
+ assert(basisColumns[inBasis[i]] == i);
+ }
+ else
+ {
+ Console.Write(" ");
+ }
+ }
+ Console.WriteLine();
+ // line
+ Console.Write(" ");
+ for (int i = 0; i < columns; i++)
+ {
+ if (i == numInitialVars || i == rhsColumn)
+ {
+ Console.Write("+");
+ }
+ Console.Write("---------");
+ }
+ Console.WriteLine();
+
+ for (int j = 0; j < rows; j++)
+ {
+ Console.Write("{0,4}: ", basisColumns[j]);
+ for (int i = 0; i < columns; i++)
+ {
+ if (i == numInitialVars || i == rhsColumn)
+ {
+ Console.Write("|");
+ }
+ Console.Write(" {0,4:n1} ", m[j,i]);
+ }
+ Console.WriteLine();
+ }
+ }
+ }
+}
diff --git a/Source/AIFramework/VariableMap/ConstantAbstraction.ssc b/Source/AIFramework/VariableMap/ConstantAbstraction.ssc
new file mode 100644
index 00000000..7b7fd87e
--- /dev/null
+++ b/Source/AIFramework/VariableMap/ConstantAbstraction.ssc
@@ -0,0 +1,210 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using Microsoft.Contracts;
+namespace Microsoft.AbstractInterpretationFramework
+{
+ using System.Collections;
+ using System.Diagnostics;
+ using System.Compiler.Analysis;
+ using Microsoft.Basetypes;
+
+ /// <summary>
+ /// Represents an invariant over constant variable assignments.
+ /// </summary>
+ public class ConstantLattice : MicroLattice
+ {
+ enum Value { Top, Bottom, Constant }
+
+ private class Elt : Element
+ {
+ public Value domainValue;
+ public BigNum constantValue; // valid iff domainValue == Value.Constant
+
+ public Elt (Value v) { this.domainValue = v; }
+
+ public Elt (BigNum i) { this.domainValue = Value.Constant; this.constantValue = i; }
+
+ public bool IsConstant { get { return this.domainValue == Value.Constant; } }
+
+ public BigNum Constant { get { return this.constantValue; } } // only when IsConstant
+
+ [Pure][Reads(ReadsAttribute.Reads.Owned)]
+ public override System.Collections.Generic.ICollection<IVariable!>! FreeVariables()
+ {
+ return (!) (new System.Collections.Generic.List<IVariable!>()).AsReadOnly();
+ }
+
+ public override Element! Clone()
+ {
+ if (this.IsConstant)
+ return new Elt(constantValue);
+ else
+ return new Elt(domainValue);
+ }
+ }
+
+ readonly IIntExprFactory! factory;
+
+ public ConstantLattice(IIntExprFactory! factory)
+ {
+ this.factory = factory;
+ // base();
+ }
+
+ public override Element! Top
+ {
+ get { return new Elt(Value.Top); }
+ }
+
+ public override Element! Bottom
+ {
+ get { return new Elt(Value.Bottom); }
+ }
+
+ public override bool IsTop (Element! element)
+ {
+ Elt e = (Elt)element;
+ return e.domainValue == Value.Top;
+ }
+
+ public override bool IsBottom (Element! element)
+ {
+ Elt e = (Elt)element;
+ return e.domainValue == Value.Bottom;
+ }
+
+ public override Element! NontrivialJoin (Element! first, Element! second)
+ {
+ Elt a = (Elt)first;
+ Elt b = (Elt)second;
+ Debug.Assert(a.domainValue == Value.Constant && b.domainValue == Value.Constant);
+ return (a.constantValue.Equals(b.constantValue)) ? a : (Elt)Top;
+ }
+
+ public override Element! NontrivialMeet (Element! first, Element! second)
+ {
+ Elt a = (Elt)first;
+ Elt b = (Elt)second;
+ Debug.Assert(a.domainValue == Value.Constant && b.domainValue == Value.Constant);
+ return (a.constantValue.Equals(b.constantValue)) ? a : (Elt)Bottom;
+ }
+
+ public override Element! Widen (Element! first, Element! second)
+ {
+ return Join(first,second);
+ }
+
+ protected override bool AtMost (Element! first, Element! second) // this <= that
+ {
+ Elt a = (Elt)first;
+ Elt b = (Elt)second;
+ return a.Constant.Equals(b.Constant);
+ }
+
+ public override IExpr! ToPredicate(IVariable! var, Element! element) {
+ return factory.Eq(var, (!)GetFoldExpr(element));
+ }
+
+ public override IExpr GetFoldExpr(Element! element) {
+ Elt e = (Elt)element;
+ assert e.domainValue == Value.Constant;
+ return factory.Const(e.constantValue);
+ }
+
+ public override bool Understands(IFunctionSymbol! f, IList/*<IExpr!>*/! args) {
+ return f.Equals(Microsoft.AbstractInterpretationFramework.Value.Eq);
+ }
+
+ public override Element! EvaluatePredicate(IExpr! e) {
+
+ IFunApp nary = e as IFunApp;
+ if (nary != null) {
+ if (nary.FunctionSymbol.Equals(Microsoft.AbstractInterpretationFramework.Value.Eq)) {
+ IList/*<IExpr!>*/! args = nary.Arguments;
+ assert args.Count == 2;
+ IExpr! arg0 = (IExpr!)args[0];
+ IExpr! arg1 = (IExpr!)args[1];
+
+ // Look for "x == const" or "const == x".
+ try {
+ if (arg0 is IVariable) {
+ BigNum z;
+ if (Fold(arg1, out z)) {
+ return new Elt(z);
+ }
+ } else if (arg1 is IVariable) {
+ BigNum z;
+ if (Fold(arg0, out z)) {
+ return new Elt(z);
+ }
+ }
+ } catch (System.ArithmeticException) {
+ // fall through and return Top. (Note, an alternative design may
+ // consider returning Bottom.)
+ }
+ }
+ }
+ return Top;
+ }
+
+ /// <summary>
+ /// Returns true if "expr" represents a constant integer expressions, in which case
+ /// "z" returns as that integer. Otherwise, returns false, in which case "z" should
+ /// not be used by the caller.
+ ///
+ /// This method throws an System.ArithmeticException in the event that folding the
+ /// constant expression results in an arithmetic overflow or division by zero.
+ /// </summary>
+ private bool Fold(IExpr! expr, out BigNum z)
+ {
+ IFunApp e = expr as IFunApp;
+ if (e == null) {
+ z = BigNum.ZERO;
+ return false;
+ }
+
+ if (e.FunctionSymbol is IntSymbol) {
+ z = ((IntSymbol)e.FunctionSymbol).Value;
+ return true;
+
+ } else if (e.FunctionSymbol.Equals(Int.Negate)) {
+ IList/*<IExpr!>*/! args = e.Arguments;
+ assert args.Count == 1;
+ IExpr! arg0 = (IExpr!)args[0];
+
+ if (Fold(arg0, out z)) {
+ z = z.Neg;
+ return true;
+ }
+
+ } else if (e.Arguments.Count == 2) {
+ IExpr! arg0 = (IExpr!)e.Arguments[0];
+ IExpr! arg1 = (IExpr!)e.Arguments[1];
+ BigNum z0, z1;
+ if (Fold(arg0, out z0) && Fold(arg1, out z1)) {
+ if (e.FunctionSymbol.Equals(Int.Add)) {
+ z = z0 + z1;
+ } else if (e.FunctionSymbol.Equals(Int.Sub)) {
+ z = z0 - z1;
+ } else if (e.FunctionSymbol.Equals(Int.Mul)) {
+ z = z0 * z1;
+ } else if (e.FunctionSymbol.Equals(Int.Div)) {
+ z = z0 / z1;
+ } else if (e.FunctionSymbol.Equals(Int.Mod)) {
+ z = z0 % z1;
+ } else {
+ z = BigNum.ZERO;
+ return false;
+ }
+ return true;
+ }
+ }
+
+ z = BigNum.ZERO;
+ return false;
+ }
+ }
+}
diff --git a/Source/AIFramework/VariableMap/ConstantExpressions.ssc b/Source/AIFramework/VariableMap/ConstantExpressions.ssc
new file mode 100644
index 00000000..306c4e8f
--- /dev/null
+++ b/Source/AIFramework/VariableMap/ConstantExpressions.ssc
@@ -0,0 +1,538 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+
+ /////////////////////////////////////////////////////////////////////////////////
+ // The Abstract domain for determining "constant" expressions
+ // i.e. It determines which expression are statically binded
+ /////////////////////////////////////////////////////////////////////////////////
+/*
+using System;
+
+namespace Microsoft.AbstractInterpretationFramework
+{
+ using Microsoft.Contracts;
+ using System.Collections.Generic;
+ using Microsoft.AbstractInterpretationFramework;
+
+ /// <summary>
+ /// This is an abstract domain for inferring constant expressions
+ /// </summary>
+
+ public class ConstantExpressions : Lattice
+ {
+ /// <summary>
+ /// An abstract element is made of two maps:
+ /// + A map from variables to expressions \cup top ( i.e. for each variable, the expression it is binded )
+ /// + A map from variables to set of variabes ( i.e. for each variable, the set of variables that depends on its value )
+ /// </summary>
+ private class AbstractElement: Element
+ {
+ private Dictionary<IVariable!, BindExpr> variableBindings;
+ private Dictionary<IVariable!, List<IVariable>> variableDependences;
+
+ static private AbstractElement! bottom;
+ static public Element! Bottom
+ {
+ get
+ {
+ if(bottom == null)
+ {
+ bottom = new AbstractElement();
+ bottom.variableBindings = null;
+ bottom.variableDependences = null;
+ }
+ assert bottom.variableBindings == null && bottom.variableDependences == null;
+ return bottom;
+ }
+ }
+
+ static public Element! Top
+ {
+ get
+ {
+ return new AbstractElement();
+ }
+ }
+
+ AbstractElement()
+ {
+ this.variableBindings = new Dictionary<IVariable!, BindExpr>();
+ this.variableDependences = new Dictionary<IVariable!, List<IVariable>>();
+ }
+
+ /// <summary>
+ /// Our abstract element is top if and only if it has any constraint on variables
+ /// </summary>
+ public bool IsTop
+ {
+ get
+ {
+ return this.variableBindings.Keys.Count == 0 && this.variableDependences.Keys.Count == 0;
+ }
+ }
+
+ /// <summary>
+ /// Our abstract element is bottom if and only if the maps are null
+ /// </summary>
+ public bool IsBottom
+ {
+ get
+ {
+ assert (this.variableBindings == null) <==> (this.variableDependences == null);
+ return this.variableBindings == null && this.variableDependences == null;
+ }
+ }
+
+ /// <summary>
+ /// The pointwise join...
+ /// </summary>
+ public static AbstractElement! Join(AbstractElement! left, AbstractElement! right)
+ {
+ AbstractElement! result = new AbstractElement();
+
+ // Put all the variables in the left
+ foreach(IVariable! var in left.variableBindings.Keys)
+ {
+ BindExpr leftVal = left.variableBindings[var];
+ assert leftVal != null;
+
+ BindExpr rightVal = right.variableBindings[var];
+
+ if(rightVal== null) // the expression is not there
+ {
+ result.variableBindings.Add(var, leftVal);
+ }
+ else // both abstract elements have a definition for the variable....
+ {
+ result.variableBindings.Add(var, BindExpr.Join(leftVal, rightVal));
+ }
+ }
+
+ // Put all the variables in the right
+ foreach(IVariable! var in right.variableBindings.Keys)
+ {
+ BindExpr rightVal = right.variableBindings[var];
+ assert rightVal != null;
+
+ BindExpr leftVal = left.variableBindings[var];
+
+ if(rightVal== null) // the expression is not there
+ {
+ result.variableBindings.Add(var, rightVal);
+ }
+ else // both abstract elements have a definition for the variable....
+ {
+ result.variableBindings.Add(var, BindExpr.Join(rightVal, leftVal));
+ }
+ }
+
+ // Join the dependencies...
+ foreach(IVariable! var in left.variableDependences.Keys)
+ {
+ List<IVariable> dependencies = left.variableDependences[var];
+ List<IVariable> dup = new List<IVariable>(dependencies);
+
+ result.variableDependences.Add(var, dup);
+ }
+
+ foreach(IVariable! var in right.variableDependences.Keys)
+ {
+ if(result.variableDependences.ContainsKey(var))
+ {
+ List<IVariable> dependencies = result.variableDependences[var];
+ dependencies.AddRange(right.variableDependences[var]);
+ }
+ else
+ {
+ List<IVariable> dependencies = right.variableDependences[var];
+ List<IVariable> dup = new List<IVariable>(dependencies);
+
+ result.variableDependences.Add(var, dup);
+ }
+ }
+
+ // Normalize... i.e. for the variables such thas they point to an unknown expression (top) we have to update also their values
+ result.Normalize();
+
+ return result;
+ }
+
+
+ ///<summary>
+ /// Normalize the current abstract element, in that it propagetes the "dynamic" information throughtout the abstract element
+ ///</summary>
+ public void Normalize()
+ {
+ if(this.IsBottom)
+ return;
+ if(this.IsTop)
+ return;
+ assert this.variableBindings != null;
+
+ bool atFixpoint = false;
+
+ while(!atFixpoint)
+ {
+ atFixpoint = true; // guess that we've got the fixpoint...
+
+ foreach(IVariable x in this.variableBindings.Keys)
+ {
+ if(this.variableBindings[x].IsTop) // It means that the variable is tied to a dynamic expression
+ {
+ foreach(IVariable y in this.variableDependences[x]) // The all the variables that depend on x are also dynamic...
+ {
+ assert x != y; // A variable cannot depend on itself...
+ if(!this.variableBindings[y].IsTop)
+ {
+ this.variableBindings[y] = BindExpr.Top;
+ atFixpoint = false; // the assumption that we were at the fixpoint was false, we have still to propagate some information...
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /// <summary>
+ /// The pointwise meet...
+ /// </summary>
+ public static AbstractElement! Meet(AbstractElement! left, AbstractElement! right)
+ {
+ AbstractElement! result = new AbstractElement();
+
+ // Put the variables that are both in left and right
+ foreach(IVariable var in left.variableBindings.Keys)
+ {
+ if(right.variableBindings.ContainsKey(var))
+ {
+ result.variableBindings.Add(var, BindExpr.Meet(left.variableBindings[var], right.variableBindings[var]));
+ }
+ }
+
+ // Intersect the dependencies
+ foreach(IVariable var in result.variableBindings.Keys)
+ {
+ List<IVariable> depLeft = left.variableDependences[var];
+ List<IVariable> depRight = right.variableDependences[var];
+
+ // Intersect the two sets
+ result.variableDependences.Add(var, depLeft);
+ foreach(IVariable v in depRight)
+ {
+ if(!result.variableDependences.ContainsKey(v))
+ {
+ result.variableDependences.Remove(v);
+ }
+ }
+ }
+
+ // Now we remove the dependencies with variables not in variableBindings
+ List<IVariable>! varsToRemove = new List<IVariable>();
+
+ foreach(IVariable var in result.
+
+
+ }
+
+ /// <summary>
+ /// Clone the current abstract element
+ /// </summary>
+ public override Element! Clone()
+ {
+ AbstractElement cloned = new AbstractElement();
+ foreach(IVariable var in this.variableBindings.Keys)
+ {
+ cloned.variableBindings.Add(var, this.variableBindings[var]);
+ }
+
+ foreach(IVariable var in this.variableDependences.Keys)
+ {
+ List<IVariable> dependingVars = this.variableDependences[var];
+ List<IVariable> clonedDependingVars = new List<IVariable>(dependingVars);
+ cloned.variableDependences.Add(var, clonedDependingVars);
+ }
+ }
+
+ /// <summary>
+ /// Return the variables that have a binding
+ /// </summary>
+ public override ICollection<IVariable!>! FreeVariables()
+ {
+ List<IVariable!> vars = new List<IVariable!>(this.variableBindings.Keys);
+
+ return vars;
+ }
+
+ public override string! ToString()
+ {
+ string! retString = "";
+ retString += "Bindings";
+
+ foreach(IVariable var in this.variableBindings.Keys)
+ {
+ string! toAdd = var.ToString() + " -> " + this.variableBindings[var];
+ retString += toAdd + ",";
+ }
+
+ retString += "\nDependencies";
+ foreach(IVariable var in this.variableDependences.Keys)
+ {
+ string! toAdd = var.ToString() + " -> " + this.variableDependences[var];
+ retString += toAdd + ",";
+ }
+
+ return retString;
+ }
+ }
+
+ public override Element! Top
+ {
+ get
+ {
+ return AbstractElement.Top;
+ }
+ }
+
+ public override Element! Bottom
+ {
+ get
+ {
+ return AbstractElement.Bottom;
+ }
+ }
+
+ public override bool IsTop(Element! e)
+ {
+ assert e is AbstractElement;
+ AbstractElement! absElement = (AbstractElement) e;
+
+ return absElement.IsTop;
+ }
+
+ public override bool IsBottom(Element! e)
+ {
+ assert e is AbstractElement;
+ AbstractElement absElement = (AbstractElement) e;
+ return absElement.IsBottom;
+ }
+
+ /// <summary>
+ /// Perform the pointwise join of the two abstract elements
+ /// </summary>
+ public override Element! NontrivialJoin(Element! a, Element! b)
+ {
+ assert a is AbstractElement;
+ assert b is AbstractElement;
+
+ AbstractElement! left = (AbstractElement!) a;
+ AbstractElement! right = (AbstractElement!) b;
+
+ return AbstractElement.Join(left, right);
+ }
+
+ /// <summary>
+ /// Perform the pointwise meet of two abstract elements
+ /// </summary>
+ public override Element! NontrivialMeet(Element! a, Element!b)
+ {
+ assert a is AbstractElement;
+ assert b is AbstractElement;
+
+ AbstractElement! left = (AbstractElement!) a;
+ AbstractElement! right = (AbstractElement!) b;
+
+ return AbstractElement.Meet(left, right);
+ }
+
+
+ }
+
+ /// <summary>
+ /// A wrapper in order to have the algebraic datatype BindExpr := IExpr | Top
+ /// </summary>
+ abstract class BindExpr
+ {
+ /// <summary>
+ /// True iff this expression is instance of BindExprTop
+ /// </summary>
+ public bool IsTop
+ {
+ get
+ {
+ return this is BindExprTop;
+ }
+ }
+
+ static public BindExpr Top
+ {
+ get
+ {
+ return BindExprTop.UniqueTop;
+ }
+ }
+
+ /// <summary>
+ /// True iff this expression is instance of BindExprBottom
+ /// </summary>
+ public bool IsBottom
+ {
+ get
+ {
+ return this is BindExprBottom;
+ }
+ }
+
+ static public BindExpr Bottom
+ {
+ get
+ {
+ return BindExprBottom.UniqueBottom;
+ }
+ }
+
+ public static BindExpr! Join(BindExpr! left, BindExpr! right)
+ {
+ if(left.IsTop || right.IsTop)
+ {
+ return BindExpr.Top;
+ }
+ else if(left.IsBottom)
+ {
+ return right;
+ }
+ else if(right.IsBottom)
+ {
+ return left;
+ }
+ else if(left.EmbeddedExpr != right.EmbeddedExpr)
+ {
+ return BindExpr.Top;
+ }
+ else // left.EmbeddedExpr == right.EmbeddedExpr
+ {
+ return left;
+ }
+ }
+
+ public static BindExpr! Meet(BindExpr! left, BindExpr! right)
+ {
+ if(left.IsTop)
+ {
+ return right;
+ }
+ else if(right.IsTop)
+ {
+ return right;
+ }
+ else if(left.IsBottom || right.IsBottom)
+ {
+ return BindExpr.Bottom;
+ }
+ else if(left.EmbeddedExpr != right.EmbeddedExpr)
+ {
+ return BindExpr.Bottom;
+ }
+ else // left.EmbeddedExpr == right.EmbeddedExpr
+ {
+ return left;
+ }
+ }
+
+ abstract public IExpr! EmbeddedExpr
+ {
+ get;
+ }
+
+ }
+
+ /// <summary>
+ /// A wrapper for an integer
+ /// </summary>
+ class Expr : BindExpr
+ {
+ private IExpr! exp;
+
+ public Expr(IExpr! exp)
+ {
+ this.exp = exp;
+ }
+
+ override public IExpr! EmbeddedExpr
+ {
+ get
+ {
+ return this.exp;
+ }
+ }
+
+ public override string! ToString()
+ {
+ return this.exp.ToString();
+ }
+ }
+
+ /// <summary>
+ /// The dynamic expression
+ /// </summary>
+ class BindExprTop : BindExpr
+ {
+ private BindExprTop top = new BindExprTop();
+ static public BindExprTop! UniqueTop
+ {
+ get
+ {
+ return this.top;
+ }
+ }
+
+ private BindExprTop() {}
+
+ override public IExpr! EmbeddedExpr
+ {
+ get
+ {
+ assert false; // If we get there, we have an error
+ }
+ }
+
+ public override string! ToString()
+ {
+ return "<dynamic expression>";
+ }
+ }
+
+ /// <summary>
+ /// The unreachable expression
+ /// </summary>
+ class BindExprBottom : BindExpr
+ {
+ private BindExprBottom! bottom = new BindExprBottom();
+ static public BindExprBottom! UniqueBottom
+ {
+ get
+ {
+ return this.bottom;
+ }
+ }
+
+ private BindExprBottom() {}
+
+ override public IExpr! EmbeddedExpr
+ {
+ get
+ {
+ assert false;
+ }
+ }
+
+ public override string! ToString()
+ {
+ return "<unreachable expression>";
+ }
+ }
+
+} // end namespace Microsoft.AbstractInterpretationFramework
+*/ \ No newline at end of file
diff --git a/Source/AIFramework/VariableMap/DynamicTypeLattice.ssc b/Source/AIFramework/VariableMap/DynamicTypeLattice.ssc
new file mode 100644
index 00000000..b9d1a7a4
--- /dev/null
+++ b/Source/AIFramework/VariableMap/DynamicTypeLattice.ssc
@@ -0,0 +1,475 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+namespace Microsoft.AbstractInterpretationFramework
+{
+ using System.Collections;
+ using System.Diagnostics;
+ using System.Compiler.Analysis;
+ using Microsoft.SpecSharp.Collections;
+ using Microsoft.Contracts;
+
+ /// <summary>
+ /// Represents information about the dynamic type of a variable. In particular, for a
+ /// variable "v", represents either Bottom, "typeof(v)==T" for some type T, or a set
+ /// of constraints "typeof(v) subtype of T_i for some number of T_i's.
+ /// </summary>
+ public class DynamicTypeLattice : MicroLattice
+ {
+ enum What { Bottom, Exact, Bounds }
+
+ private class Elt : Element {
+ // Representation:
+ // - Bottom is represented by: what==What.Bottom
+ // - An exact type T is represented by: what==What.Exact && ty==T
+ // - A set of type constraints T0, T1, T2, ..., T{n-1} is represented by:
+ // -- if n==0: what==What.Bounds && ty==null && manyBounds==null
+ // -- if n==1: what==What.Bounds && ty==T0 && manyBounds==null
+ // -- if n>=2: what==What.Bounds && ty==null &&
+ // manyBounds!=null && manyBounds.Length==n &&
+ // manyBounds[0]==T0 && manyBounds[1]==T1 && ... && manyBounds[n-1]==T{n-1}
+ // The reason for keeping the one-and-only bound in "ty" in case n==1 is to try
+ // to prevent the need for allocating a whole array of bounds, since 1 bound is
+ // bound to be common.
+ // In the representation, there are no redundant bounds in manyBounds.
+ // It is assumed that the types can can occur as exact bounds form a single-inheritance
+ // hierarchy. That is, if T0 and T1 are types that can occur as exact types, then
+ // there is no v such that typeof(v) is a subtype of both T0 and T1, unless T0 and T1 are
+ // the same type.
+ public readonly What what;
+ public readonly IExpr ty;
+ [Rep]
+ public readonly IExpr[] manyBounds;
+ invariant what == What.Bottom ==> ty == null && manyBounds == null;
+ invariant manyBounds != null ==> what == What.Bounds;
+ invariant manyBounds != null ==> forall{int i in (0:manyBounds.Length); manyBounds[i] != null};
+
+ public Elt(What what, IExpr ty)
+ requires what == What.Bottom ==> ty == null;
+ requires what == What.Exact ==> ty != null;
+ {
+ this.what = what;
+ this.ty = ty;
+ this.manyBounds = null;
+ }
+
+ public Elt(IExpr[]! bounds)
+ requires forall{int i in (0:bounds.Length); bounds[i] != null};
+ {
+ this.what = What.Bounds;
+ if (bounds.Length == 0) {
+ this.ty = null;
+ this.manyBounds = null;
+ } else if (bounds.Length == 1) {
+ this.ty = bounds[0];
+ this.manyBounds = null;
+ } else {
+ this.ty = null;
+ this.manyBounds = bounds;
+ }
+ }
+
+ /// <summary>
+ /// Constructs an Elt with "n" bounds, namely the n non-null values of the "bounds" list.
+ /// </summary>
+ [NotDelayed]
+ public Elt(ArrayList /*IExpr*/! bounds, int n)
+ requires 0 <= n && n <= bounds.Count;
+ {
+ this.what = What.Bounds;
+ if (n > 1) {
+ this.manyBounds = new IExpr[n];
+ }
+ int k = 0;
+ foreach (IExpr bound in bounds) {
+ if (bound != null) {
+ assert k != n;
+ if (n == 1) {
+ assert this.ty == null;
+ this.ty = bound;
+ } else {
+ assume manyBounds != null;
+ manyBounds[k] = bound;
+ }
+ k++;
+ }
+ }
+ assert k == n;
+ }
+
+ public int BoundsCount
+ {
+ get
+ ensures 0 <= result;
+ {
+ if (manyBounds != null) {
+ return manyBounds.Length;
+ } else if (ty != null) {
+ return 1;
+ } else {
+ return 0;
+ }
+ }
+ }
+
+ [Pure][Reads(ReadsAttribute.Reads.Owned)]
+ public override System.Collections.Generic.ICollection<IVariable!>! FreeVariables()
+ {
+ return (!) (new System.Collections.Generic.List<IVariable!>()).AsReadOnly();
+ }
+
+ public override Element! Clone()
+ {
+ if (this.manyBounds != null)
+ return new Elt(this.manyBounds);
+ else
+ return new Elt(this.what, this.ty);
+ }
+ }
+
+ readonly ITypeExprFactory! factory;
+ readonly IPropExprFactory! propFactory;
+
+ public DynamicTypeLattice(ITypeExprFactory! factory, IPropExprFactory! propFactory)
+ {
+ this.factory = factory;
+ this.propFactory = propFactory;
+ // base();
+ }
+
+ public override Element! Top
+ {
+ get { return new Elt(What.Bounds, null); }
+ }
+
+ public override Element! Bottom
+ {
+ get { return new Elt(What.Bottom, null); }
+ }
+
+ public override bool IsTop (Element! element)
+ {
+ Elt e = (Elt)element;
+ return e.what == What.Bounds && e.ty == null && e.manyBounds == null;
+ }
+
+ public override bool IsBottom(Element! element)
+ {
+ Elt e = (Elt)element;
+ return e.what == What.Bottom;
+ }
+
+ public override Element! NontrivialJoin(Element! first, Element! second)
+ {
+ Elt a = (Elt)first;
+ Elt b = (Elt)second;
+ assert a.what != What.Bottom && b.what != What.Bottom;
+ if (a.what == What.Exact && b.what == What.Exact) {
+ assert a.ty != null && b.ty != null;
+ if (factory.IsTypeEqual(a.ty, b.ty)) {
+ return a;
+ } else {
+ return new Elt(What.Bounds, factory.JoinTypes(a.ty, b.ty));
+ }
+ }
+
+ // The result is going to be a Bounds, since at least one of the operands is a Bounds.
+ assert 1 <= a.BoundsCount && 1 <= b.BoundsCount; // a preconditions is that neither operand is Top
+ int n = a.BoundsCount + b.BoundsCount;
+
+ // Special case: a and b each has exactly one bound
+ if (n == 2) {
+ assert a.ty != null && b.ty != null;
+ IExpr! join = factory.JoinTypes(a.ty, b.ty);
+ if (join == a.ty && a.what == What.Bounds) {
+ return a;
+ } else if (join == b.ty && b.what == What.Bounds) {
+ return b;
+ } else {
+ return new Elt(What.Bounds, join);
+ }
+ }
+
+ // General case
+ ArrayList /*IExpr*/ allBounds = new ArrayList /*IExpr*/ (n); // final size
+ ArrayList /*IExpr!*/ result = new ArrayList /*IExpr!*/ (n); // a guess at the size, but could be as big as size(a)*size(b)
+ if (a.ty != null) {
+ allBounds.Add(a.ty);
+ } else {
+ allBounds.AddRange((!)a.manyBounds);
+ }
+ int bStart = allBounds.Count;
+ if (b.ty != null) {
+ allBounds.Add(b.ty);
+ } else {
+ allBounds.AddRange((!)b.manyBounds);
+ }
+ // compute the join of each pair, putting non-redundant joins into "result"
+ for (int i = 0; i < bStart; i++) {
+ IExpr! aBound = (IExpr!)allBounds[i];
+ for (int j = bStart; j < allBounds.Count; j++) {
+ IExpr! bBound = (IExpr!)allBounds[j];
+
+ IExpr! join = factory.JoinTypes(aBound, bBound);
+
+ int k = 0;
+ while (k < result.Count) {
+ IExpr! r = (IExpr!)result[k];
+ if (factory.IsSubType(join, r)) {
+ // "join" is more restrictive than a bound already placed in "result",
+ // so toss out "join" and compute the join of the next pair
+ goto NEXT_PAIR;
+ } else if (factory.IsSubType(r, join)) {
+ // "join" is less restrictive than a bound already placed in "result",
+ // so toss out that old bound
+ result.RemoveAt(k);
+ } else {
+ k++;
+ }
+ }
+ result.Add(join);
+ NEXT_PAIR: {}
+ }
+ }
+ return new Elt(result, result.Count);
+ }
+
+
+ public override Element! NontrivialMeet(Element! first, Element! second)
+ {
+ Elt a = (Elt)first;
+ Elt b = (Elt)second;
+ assert a.what != What.Bottom && b.what != What.Bottom;
+
+ if (a.what == What.Exact && b.what == What.Exact) {
+ assert a.ty != null && b.ty != null;
+ if (factory.IsTypeEqual(a.ty, b.ty)) {
+ return a;
+ } else {
+ return Bottom;
+ }
+
+ } else if (a.what == What.Exact || b.what == What.Exact) {
+ // One is Bounds, the other Exact. Make b be the Bounds one.
+ if (a.what == What.Bounds) {
+ Elt tmp = a;
+ a = b;
+ b = tmp;
+ }
+ assert a.what == What.Exact && b.what == What.Bounds;
+ // Check the exact type against all bounds. If the exact type is more restrictive
+ // than all bounds, then return it. If some bound is not met by the exact type, return
+ // bottom.
+ assert a.ty != null;
+ if (b.ty != null && !factory.IsSubType(a.ty, b.ty)) {
+ return Bottom;
+ }
+ if (b.manyBounds != null) {
+ foreach (IExpr! bound in b.manyBounds) {
+ if (!factory.IsSubType(a.ty, bound)) {
+ return Bottom;
+ }
+ }
+ }
+ return a;
+ }
+
+ else {
+ // Both operands are Bounds.
+ assert a.what == What.Bounds && b.what == What.Bounds;
+
+ // Take all the bounds, but prune those bounds that follow from others.
+ assert 1 <= a.BoundsCount && 1 <= b.BoundsCount; // a preconditions is that neither operand is Top
+ int n = a.BoundsCount + b.BoundsCount;
+ // Special case: a and b each has exactly one bound
+ if (n == 2) {
+ assert a.ty != null && b.ty != null;
+ if (factory.IsSubType(a.ty, b.ty)) {
+ // a is more restrictive
+ return a;
+ } else if (factory.IsSubType(b.ty, a.ty)) {
+ // b is more restrictive
+ return b;
+ } else {
+ IExpr[]! bounds = new IExpr[2];
+ bounds[0] = a.ty;
+ bounds[1] = b.ty;
+ return new Elt(bounds);
+ }
+ }
+
+ // General case
+ ArrayList /*IExpr*/ allBounds = new ArrayList /*IExpr*/ (n);
+ if (a.ty != null) {
+ allBounds.Add(a.ty);
+ } else {
+ allBounds.AddRange((!)a.manyBounds);
+ }
+ int bStart = allBounds.Count;
+ if (b.ty != null) {
+ allBounds.Add(b.ty);
+ } else {
+ allBounds.AddRange((!)b.manyBounds);
+ }
+ for (int i = 0; i < bStart; i++) {
+ IExpr! aBound = (IExpr!)allBounds[i];
+ for (int j = bStart; j < allBounds.Count; j++) {
+ IExpr bBound = (IExpr!)allBounds[j];
+ if (bBound == null) {
+ continue;
+ } else if (factory.IsSubType(aBound, bBound)) {
+ // a is more restrictive, so blot out the b bound
+ allBounds[j] = null;
+ n--;
+ } else if (factory.IsSubType(bBound, aBound)) {
+ // b is more restrictive, so blot out the a bound
+ allBounds[i] = null;
+ n--;
+ goto CONTINUE_OUTER_LOOP;
+ }
+ }
+ CONTINUE_OUTER_LOOP: {}
+ }
+ assert 1 <= n;
+ return new Elt(allBounds, n);
+ }
+ }
+
+ public override Element! Widen (Element! first, Element! second)
+ {
+ return Join(first,second);
+ }
+
+ protected override bool AtMost (Element! first, Element! second) // this <= that
+ {
+ Elt! a = (Elt!)first;
+ Elt! b = (Elt!)second;
+ assert a.what != What.Bottom && b.what != What.Bottom;
+
+ if (a.what == What.Exact && b.what == What.Exact) {
+ assert a.ty != null && b.ty != null;
+ return factory.IsTypeEqual(a.ty, b.ty);
+ } else if (b.what == What.Exact) {
+ return false;
+ } else if (a.what == What.Exact) {
+ assert a.ty != null;
+ if (b.ty != null) {
+ return factory.IsSubType(a.ty, b.ty);
+ } else {
+ return forall{IExpr! bound in b.manyBounds; factory.IsSubType(a.ty, bound)};
+ }
+ } else {
+ assert a.what == What.Bounds && b.what == What.Bounds;
+ assert a.ty != null || a.manyBounds != null; // a precondition is that a is not Top
+ assert b.ty != null || b.manyBounds != null; // a precondition is that b is not Top
+ // Return true iff: for each constraint in b, there is a stricter constraint in a.
+ if (a.ty != null && b.ty != null) {
+ return factory.IsSubType(a.ty, b.ty);
+ } else if (a.ty != null) {
+ return forall{IExpr! bound in b.manyBounds; factory.IsSubType(a.ty, bound)};
+ } else if (b.ty != null) {
+ return exists{IExpr! bound in a.manyBounds; factory.IsSubType(bound, b.ty)};
+ } else {
+ return forall{IExpr! bBound in b.manyBounds;
+ exists{IExpr! aBound in a.manyBounds; factory.IsSubType(aBound, bBound)}};
+ }
+ }
+ }
+
+ public override IExpr! ToPredicate(IVariable! var, Element! element) {
+ Elt e = (Elt)element;
+ switch (e.what) {
+ case What.Bottom:
+ return propFactory.False;
+ case What.Exact:
+ return factory.IsExactlyA(var, (!)e.ty);
+ case What.Bounds:
+ if (e.ty == null && e.manyBounds == null) {
+ return propFactory.True;
+ } else if (e.ty != null) {
+ return factory.IsA(var, e.ty);
+ } else {
+ IExpr! p = factory.IsA(var, (IExpr!)((!)e.manyBounds)[0]);
+ for (int i = 1; i < e.manyBounds.Length; i++) {
+ p = propFactory.And(p, factory.IsA(var, (IExpr!)e.manyBounds[i]));
+ }
+ return p;
+ }
+ default:
+ assert false;
+ throw new System.Exception();
+ }
+ }
+
+ public override IExpr GetFoldExpr(Element! e) {
+ // cannot fold into an expression that can be substituted for the variable
+ return null;
+ }
+
+ public override bool Understands(IFunctionSymbol! f, IList/*<IExpr!>*/! args) {
+ bool isEq = f.Equals(Microsoft.AbstractInterpretationFramework.Value.Eq);
+ if (isEq || f.Equals(Microsoft.AbstractInterpretationFramework.Value.Subtype)) {
+ assert args.Count == 2;
+ IExpr! arg0 = (IExpr!)args[0];
+ IExpr! arg1 = (IExpr!)args[1];
+
+ // Look for $typeof(var) == t or t == $typeof(var) or $typeof(var) <: t
+ if (isEq && factory.IsTypeConstant(arg0)) {
+ // swap the arguments
+ IExpr! tmp = arg0;
+ arg0 = arg1;
+ arg1 = tmp;
+ } else if (!factory.IsTypeConstant(arg1)) {
+ return false;
+ }
+ IFunApp typeofExpr = arg0 as IFunApp;
+ if (typeofExpr != null &&
+ typeofExpr.FunctionSymbol.Equals(Microsoft.AbstractInterpretationFramework.Value.Typeof)) {
+ assert typeofExpr.Arguments.Count == 1;
+ if (typeofExpr.Arguments[0] is IVariable) {
+ // we have a match
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ public override Element! EvaluatePredicate(IExpr! e) {
+ IFunApp nary = e as IFunApp;
+ if (nary != null) {
+
+ bool isEq = nary.FunctionSymbol.Equals(Microsoft.AbstractInterpretationFramework.Value.Eq);
+ if (isEq || nary.FunctionSymbol.Equals(Microsoft.AbstractInterpretationFramework.Value.Subtype)) {
+ IList/*<IExpr!>*/! args = nary.Arguments;
+ assert args.Count == 2;
+ IExpr! arg0 = (IExpr!)args[0];
+ IExpr! arg1 = (IExpr!)args[1];
+
+ // Look for $typeof(var) == t or t == $typeof(var) or $typeof(var) <: t
+ if (isEq && factory.IsTypeConstant(arg0)) {
+ // swap the arguments
+ IExpr! tmp = arg0;
+ arg0 = arg1;
+ arg1 = tmp;
+ } else if (!factory.IsTypeConstant(arg1)) {
+ return Top;
+ }
+ IFunApp typeofExpr = arg0 as IFunApp;
+ if (typeofExpr != null &&
+ typeofExpr.FunctionSymbol.Equals(Microsoft.AbstractInterpretationFramework.Value.Typeof)) {
+ assert typeofExpr.Arguments.Count == 1;
+ if (typeofExpr.Arguments[0] is IVariable) {
+ // we have a match
+ return new Elt(isEq ? What.Exact : What.Bounds, arg1);
+ }
+ }
+ }
+ }
+ return Top;
+ }
+
+ }
+}
diff --git a/Source/AIFramework/VariableMap/Intervals.ssc b/Source/AIFramework/VariableMap/Intervals.ssc
new file mode 100644
index 00000000..721b175d
--- /dev/null
+++ b/Source/AIFramework/VariableMap/Intervals.ssc
@@ -0,0 +1,790 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using System;
+using System.Collections;
+using System.Compiler.Analysis;
+using Microsoft.AbstractInterpretationFramework.Collections;
+using Microsoft.Contracts;
+using Microsoft.Basetypes;
+
+/////////////////////////////////////////////////////////////////////////////////
+// An implementation of the interval abstract domain
+/////////////////////////////////////////////////////////////////////////////////
+
+namespace Microsoft.AbstractInterpretationFramework
+{
+ public class IntervalLattice : MicroLattice
+ {
+ readonly ILinearExprFactory! factory;
+
+ public IntervalLattice(ILinearExprFactory! factory)
+ {
+ this.factory = factory;
+ // base();
+ }
+
+ public override bool UnderstandsBasicArithmetics
+ {
+ get
+ {
+ return true;
+ }
+ }
+
+ public override Element! Top
+ {
+ get
+ {
+ return IntervalElement.Top;
+ }
+ }
+
+ public override Element! Bottom
+ {
+ get
+ {
+ return IntervalElement.Bottom;
+ }
+ }
+
+ /// <summary>
+ /// The paramter is the top?
+ /// </summary>
+ public override bool IsTop(Element! element)
+ {
+ IntervalElement interval = (IntervalElement) element;
+
+ return interval.IsTop();
+ }
+
+ /// <summary>
+ /// The parameter is the bottom?
+ /// </summary>
+ public override bool IsBottom(Element! element)
+ {
+ IntervalElement interval = (IntervalElement) element;
+
+ return interval.IsBottom();
+ }
+
+ /// <summary>
+ /// The classic, pointwise, join of intervals
+ /// </summary>
+ public override Element! NontrivialJoin(Element! left, Element! right)
+ {
+ IntervalElement! leftInterval = (IntervalElement!) left;
+ IntervalElement! rightInterval = (IntervalElement) right;
+
+ ExtendedInt inf = ExtendedInt.Inf(leftInterval.Inf, rightInterval.Inf);
+ ExtendedInt sup = ExtendedInt.Sup(leftInterval.Sup, rightInterval.Sup);
+
+ IntervalElement! join = IntervalElement.Factory(inf, sup);
+
+ return join;
+ }
+
+ /// <summary>
+ /// The classic, pointwise, meet of intervals
+ /// </summary>
+ public override Element! NontrivialMeet(Element! left, Element! right)
+ {
+ IntervalElement! leftInterval = (IntervalElement!) left;
+ IntervalElement! rightInterval = (IntervalElement) right;
+
+ ExtendedInt inf = ExtendedInt.Sup(leftInterval.Inf, rightInterval.Inf);
+ ExtendedInt sup = ExtendedInt.Inf(leftInterval.Sup, rightInterval.Sup);
+
+ return IntervalElement.Factory(inf, sup);
+ }
+
+
+ /// <summary>
+ /// The very simple widening of intervals, to be improved with thresholds
+ /// left is the PREVIOUS value in the iterations and right is the NEW one
+ /// </summary>
+ public override Element! Widen(Element! left, Element! right)
+ {
+ IntervalElement! prevInterval = (IntervalElement!) left;
+ IntervalElement! nextInterval = (IntervalElement!) right;
+
+ ExtendedInt inf = nextInterval.Inf < prevInterval.Inf ? ExtendedInt.MinusInfinity : prevInterval.Inf;
+ ExtendedInt sup = nextInterval.Sup > prevInterval.Sup ? ExtendedInt.PlusInfinity : prevInterval.Sup;
+
+ IntervalElement widening = IntervalElement.Factory(inf, sup);
+
+ return widening;
+ }
+
+
+ /// <summary>
+ /// Return true iff the interval left is containted in right
+ /// </summary>
+ protected override bool AtMost(Element! left, Element! right)
+ {
+ IntervalElement! leftInterval = (IntervalElement!) left;
+ IntervalElement! rightInterval = (IntervalElement!) right;
+
+ if(leftInterval.IsBottom() || rightInterval.IsTop())
+ return true;
+
+ return rightInterval.Inf <= leftInterval.Inf && leftInterval.Sup <= rightInterval.Sup;
+ }
+
+ /// <summary>
+ /// Return just null
+ /// </summary>
+ public override IExpr GetFoldExpr(Element! element)
+ {
+ return null;
+ }
+
+ /// <summary>
+ /// return a predicate inf "\leq x and x "\leq" sup (if inf [or sup] is not oo)
+ /// </summary>
+ public override IExpr! ToPredicate(IVariable! var, Element! element)
+ {
+ IntervalElement! interval = (IntervalElement!) element;
+ IExpr lowerBound = null;
+ IExpr upperBound = null;
+
+ if(! (interval.Inf is InfinitaryInt))
+ {
+ IExpr constant = this.factory.Const(interval.Inf.Value);
+ lowerBound = this.factory.AtMost(constant, var); // inf <= var
+ }
+ if(! (interval.Sup is InfinitaryInt))
+ {
+ IExpr constant = this.factory.Const(interval.Sup.Value);
+ upperBound = this.factory.AtMost(var, constant); // var <= inf
+ }
+
+ if(lowerBound != null && upperBound != null)
+ return this.factory.And(lowerBound, upperBound); // inf <= var && var <= sup
+ else
+ if(lowerBound != null)
+ return lowerBound;
+ else
+ if(upperBound != null)
+ return upperBound;
+ else // If we reach this point, both lowerBound and upperBound are null, i.e. we have no bounds on var, so we return simply true...
+ return this.factory.True;
+ }
+
+ /// <summary>
+ /// For the moment consider just equalities. Other case must be considered
+ /// </summary>
+ public override bool Understands(IFunctionSymbol! f, IList /*<IExpr*/ ! args)
+ {
+ return f.Equals(Microsoft.AbstractInterpretationFramework.Value.Eq);
+ }
+
+
+ /// <summary>
+ /// Evaluate the predicate passed as input according the semantics of intervals
+ /// </summary>
+ public override Element! EvaluatePredicate(IExpr! pred)
+ {
+ return this.EvaluatePredicateWithState(pred, null);
+ }
+
+ /// <summary>
+ /// Evaluate the predicate passed as input according the semantics of intervals and the given state.
+ /// Right now just basic arithmetic operations are supported. A future extension may consider an implementation of boolean predicates
+ /// </summary>
+ public override Element! EvaluatePredicateWithState(IExpr! pred, IFunctionalMap/* Var -> Element */ state)
+ {
+ if(pred is IFunApp)
+ {
+ IFunApp fun = (IFunApp) pred;
+ if(fun.FunctionSymbol.Equals(Microsoft.AbstractInterpretationFramework.Value.Eq)) // if it is a symbol of equality
+ {
+ IExpr! leftArg = (IExpr!) fun.Arguments[0];
+ IExpr! rightArg = (IExpr!) fun.Arguments[1];
+ if (leftArg is IVariable) {
+ return Eval(rightArg, state);
+ } else if (rightArg is IVariable) {
+ return Eval(leftArg, state);
+ }
+ }
+ }
+ // otherwise we simply return Top
+ return IntervalElement.Top;
+ }
+
+ /// <summary>
+ /// Evaluate the expression (that is assured to be an arithmetic expression, in the state passed as a parameter
+ /// </summary>
+ private IntervalElement! Eval(IExpr! exp, IFunctionalMap/* Var -> Element */ state)
+ {
+
+ IntervalElement! retVal = (IntervalElement!) Top;
+
+ // Eval the expression by structural induction
+
+
+ if(exp is IVariable && state != null) // A variable
+ {
+ object lookup = state[exp];
+ if(lookup is IntervalElement)
+ retVal = (IntervalElement) lookup;
+ else
+ {
+ retVal = (IntervalElement) Top;
+ }
+ }
+ else if(exp is IFunApp)
+ {
+ IFunApp fun = (IFunApp) exp;
+
+ if(fun.FunctionSymbol is IntSymbol) // An integer
+ {
+ IntSymbol intSymb = (IntSymbol) fun.FunctionSymbol;
+ BigNum val = intSymb.Value;
+
+ retVal = IntervalElement.Factory(val);
+ }
+ else if(fun.FunctionSymbol.Equals(Int.Negate)) // An unary minus
+ {
+ IExpr! arg = (IExpr!) fun.Arguments[0];
+ IntervalElement! argEval = Eval(arg, state);
+ IntervalElement! zero = IntervalElement.Factory(BigNum.ZERO);
+
+ retVal = zero - argEval;
+ }
+ else if(fun.Arguments.Count == 2)
+ {
+ IExpr! left = (IExpr!) fun.Arguments[0];
+ IExpr! right = (IExpr!) fun.Arguments[1];
+
+ IntervalElement! leftVal = Eval(left, state);
+ IntervalElement! rightVal = Eval(right, state);
+
+ if(fun.FunctionSymbol.Equals(Int.Add))
+ retVal = leftVal + rightVal;
+ else if(fun.FunctionSymbol.Equals(Int.Sub))
+ retVal = leftVal - rightVal;
+ else if(fun.FunctionSymbol.Equals(Int.Mul))
+ retVal = leftVal * rightVal;
+ else if(fun.FunctionSymbol.Equals(Int.Div))
+ retVal = leftVal / rightVal;
+ else if(fun.FunctionSymbol.Equals(Int.Mod))
+ retVal = leftVal % rightVal;
+ }
+ }
+
+ return retVal;
+ }
+
+ /// <summary>
+ /// Inner class standing for an interval on integers, possibly unbounded
+ /// </summary>
+ private class IntervalElement : Element
+ {
+ protected static readonly IntervalElement! TopInterval = new IntervalElement(new MinusInfinity(), new PlusInfinity()); // Top = [-oo , +oo]
+ protected static readonly IntervalElement! BottomInterval = new IntervalElement(new PlusInfinity(), new MinusInfinity()); // Bottom = [+oo, -oo]
+
+ private readonly ExtendedInt! inf;
+ private readonly ExtendedInt! sup;
+
+ public ExtendedInt! Inf
+ {
+ get
+ {
+ return inf;
+ }
+ }
+
+ public ExtendedInt! Sup
+ {
+ get
+ {
+ return sup;
+ }
+ }
+
+ // Construct the inteval [val, val]
+ protected IntervalElement(BigNum val)
+ {
+ this.inf = this.sup = ExtendedInt.Factory(val);
+ // base();
+ }
+
+ // Construct the interval [inf, sup]
+ protected IntervalElement(BigNum infInt, BigNum supInt)
+ {
+ this.inf = ExtendedInt.Factory(infInt);
+ this.sup = ExtendedInt.Factory(supInt);
+ // base(); // to please the compiler...
+ }
+
+ protected IntervalElement(ExtendedInt! inf, ExtendedInt! sup)
+ {
+ this.inf = inf;
+ this.sup = sup;
+ // base();
+ }
+
+ // Construct an Interval
+ public static IntervalElement! Factory(ExtendedInt! inf, ExtendedInt! sup)
+ {
+ if(inf is MinusInfinity && sup is PlusInfinity)
+ return Top;
+ if(inf > sup)
+ return Bottom;
+ // otherwise...
+ return new IntervalElement(inf, sup);
+ }
+
+ public static IntervalElement! Factory(BigNum i)
+ {
+ return new IntervalElement(i);
+ }
+
+ public static IntervalElement! Factory(BigNum inf, BigNum sup)
+ {
+ ExtendedInt! i = ExtendedInt.Factory(inf);
+ ExtendedInt! s = ExtendedInt.Factory(sup);
+
+ return Factory(i, s);
+ }
+
+ static public IntervalElement! Top
+ {
+ get
+ {
+ return TopInterval;
+ }
+ }
+
+ static public IntervalElement! Bottom
+ {
+ get
+ {
+ return BottomInterval;
+ }
+ }
+
+ public bool IsTop()
+ {
+ return this.inf is MinusInfinity && this.sup is PlusInfinity;
+ }
+
+ public bool IsBottom()
+ {
+ return this.inf > this.sup;
+ }
+
+ #region Below are the arithmetic operations lifted to intervals
+
+ // Addition
+ public static IntervalElement! operator+(IntervalElement! a, IntervalElement! b)
+ {
+ ExtendedInt! inf = a.inf + b.inf;
+ ExtendedInt! sup = a.sup + b.sup;
+
+ return Factory(inf, sup);
+ }
+
+ // Subtraction
+ public static IntervalElement! operator-(IntervalElement! a, IntervalElement! b)
+ {
+ ExtendedInt! inf = a.inf - b.sup;
+ ExtendedInt! sup = a.sup - b.inf;
+
+ IntervalElement! sub = Factory(inf, sup);
+
+ return sub;
+ }
+
+ // Multiplication
+ public static IntervalElement! operator*(IntervalElement! a, IntervalElement! b)
+ {
+ ExtendedInt! infinf = a.inf * b.inf;
+ ExtendedInt! infsup = a.inf * b.sup;
+ ExtendedInt! supinf = a.sup * b.inf;
+ ExtendedInt! supsup = a.sup * b.sup;
+
+ ExtendedInt! inf = ExtendedInt.Inf(infinf, infsup, supinf, supsup);
+ ExtendedInt! sup = ExtendedInt.Sup(infinf, infsup, supinf, supsup);
+
+ return Factory(inf, sup);
+ }
+
+ // Division
+ public static IntervalElement! operator/(IntervalElement! a, IntervalElement! b)
+ {
+ if(b.inf.IsZero && b.sup.IsZero) // Check division by zero
+ return IntervalElement.Top;
+
+ ExtendedInt! infinf = a.inf / b.inf;
+ ExtendedInt! infsup = a.inf / b.sup;
+ ExtendedInt! supinf = a.sup / b.inf;
+ ExtendedInt! supsup = a.sup / b.sup;
+
+ ExtendedInt! inf = ExtendedInt.Inf(infinf, infsup, supinf, supsup);
+ ExtendedInt! sup = ExtendedInt.Sup(infinf, infsup, supinf, supsup);
+
+ return Factory(inf, sup);
+ }
+
+ // Division
+ public static IntervalElement! operator%(IntervalElement! a, IntervalElement! b)
+ {
+ if(b.inf.IsZero && b.sup.IsZero) // Check division by zero
+ return IntervalElement.Top;
+
+ ExtendedInt! infinf = a.inf % b.inf;
+ ExtendedInt! infsup = a.inf % b.sup;
+ ExtendedInt! supinf = a.sup % b.inf;
+ ExtendedInt! supsup = a.sup % b.sup;
+
+ ExtendedInt inf = ExtendedInt.Inf(infinf, infsup, supinf, supsup);
+ ExtendedInt sup = ExtendedInt.Sup(infinf, infsup, supinf, supsup);
+
+ return Factory(inf, sup);
+ }
+
+ #endregion
+
+ #region Overriden methods
+
+ public override Element! Clone()
+ {
+ // Real copying should not be needed because intervals are immutable?
+ return this;
+ /*
+ int valInf = this.inf.Value;
+ int valSup = this.sup.Value;
+
+ ExtendedInt clonedInf = ExtendedInt.Factory(valInf);
+ ExtendedInt clonedSup = ExtendedInt.Factory(valSup);
+
+ return Factory(clonedInf, clonedSup);
+ */
+ }
+
+ [Pure][Reads(ReadsAttribute.Reads.Owned)]
+ public override System.Collections.Generic.ICollection<IVariable!>! FreeVariables()
+ {
+ return (!) (new System.Collections.Generic.List<IVariable!>()).AsReadOnly();
+ }
+
+ [Pure][Reads(ReadsAttribute.Reads.Owned)]
+ public override string! ToString()
+ {
+ return "[" + this.inf + ", " + this.sup + "]";
+ }
+
+ #endregion
+ }
+}
+
+
+ /// The interface for an extended integer
+ abstract class ExtendedInt
+ {
+ private static readonly PlusInfinity! cachedPlusInf = new PlusInfinity();
+ private static readonly MinusInfinity! cachedMinusInf = new MinusInfinity();
+
+ static public ExtendedInt! PlusInfinity
+ {
+ get
+ {
+ return cachedPlusInf;
+ }
+ }
+
+ static public ExtendedInt! MinusInfinity
+ {
+ get
+ {
+ return cachedMinusInf;
+ }
+ }
+
+ public abstract BigNum Value { get; }
+
+ public abstract int Signum { get; }
+
+ public bool IsZero {
+ get {
+ return Signum == 0;
+ }
+ }
+
+ public bool IsPositive {
+ get {
+ return Signum > 0;
+ }
+ }
+
+ public bool IsNegative {
+ get {
+ return Signum < 0;
+ }
+ }
+
+
+ #region Below are the extensions of arithmetic operations on extended integers
+
+ // Addition
+ public static ExtendedInt! operator+(ExtendedInt! a, ExtendedInt! b)
+ {
+ if (a is InfinitaryInt) {
+ return a;
+ } else if (b is InfinitaryInt) {
+ return b;
+ } else {
+ return ExtendedInt.Factory(a.Value + b.Value);
+ }
+ }
+
+ // Subtraction
+ public static ExtendedInt! operator-(ExtendedInt! a, ExtendedInt! b)
+ {
+ if (a is InfinitaryInt) {
+ return a;
+ } else if (b is InfinitaryInt) {
+ return UnaryMinus(b);
+ } else {
+ return ExtendedInt.Factory(a.Value - b.Value);
+ }
+ }
+
+ // Unary minus
+ public static ExtendedInt! operator-(ExtendedInt! a)
+ {
+ // BUGBUG: Some compiler error prevents the unary minus operator from being used
+ return UnaryMinus(a);
+ }
+
+ // Unary minus
+ public static ExtendedInt! UnaryMinus(ExtendedInt! a)
+ {
+ if(a is PlusInfinity)
+ return cachedMinusInf;
+ if(a is MinusInfinity)
+ return cachedPlusInf;
+ else // a is a PureInteger
+ return new PureInteger(-a.Value);
+ }
+
+ // Multiplication
+ public static ExtendedInt! operator*(ExtendedInt! a, ExtendedInt! b)
+ {
+ if (a.IsZero) {
+ return a;
+ } else if (b.IsZero) {
+ return b;
+ } else if (a is InfinitaryInt) {
+ if (b.IsPositive) {
+ return a;
+ } else {
+ return UnaryMinus(a);
+ }
+ } else if (b is InfinitaryInt) {
+ if (a.IsPositive) {
+ return b;
+ } else {
+ return UnaryMinus(b);
+ }
+ } else {
+ return ExtendedInt.Factory(a.Value * b.Value);
+ }
+ }
+
+ // Division
+ public static ExtendedInt! operator/(ExtendedInt! a, ExtendedInt! b)
+ {
+ if(b.IsZero)
+ {
+ return a.IsPositive? (ExtendedInt) cachedPlusInf : cachedMinusInf;
+ }
+ if (a is InfinitaryInt) {
+ return a;
+ } else if (b is InfinitaryInt) {
+ return b;
+ } else {
+ return ExtendedInt.Factory(a.Value / b.Value);
+ }
+ }
+
+ // Modulo
+ public static ExtendedInt! operator%(ExtendedInt! a, ExtendedInt! b)
+ {
+ if(b.IsZero)
+ {
+ return a.IsPositive? (ExtendedInt) cachedPlusInf : cachedMinusInf;
+ }
+ if (a is InfinitaryInt) {
+ return a;
+ } else if (b is InfinitaryInt) {
+ return b;
+ } else {
+ return ExtendedInt.Factory(a.Value % b.Value);
+ }
+ }
+
+ #endregion
+
+ #region Inf and Sup operations
+
+ public abstract int CompareTo(ExtendedInt! that);
+
+ public static bool operator<(ExtendedInt! inf, ExtendedInt! sup)
+ {
+ return inf.CompareTo(sup) < 0;
+ }
+
+ public static bool operator>(ExtendedInt! inf, ExtendedInt! sup)
+ {
+ return inf.CompareTo(sup) > 0;
+ }
+
+ public static bool operator<=(ExtendedInt! inf, ExtendedInt! sup)
+ {
+ return inf.CompareTo(sup) <= 0;
+ }
+
+ public static bool operator>=(ExtendedInt! inf, ExtendedInt! sup)
+ requires inf != null && sup != null;
+ {
+ return inf.CompareTo(sup) >= 0;
+ }
+
+ public static ExtendedInt! Inf(ExtendedInt! inf, ExtendedInt! sup)
+ {
+ if(inf < sup)
+ return inf;
+ else
+ return sup;
+ }
+
+ public static ExtendedInt! Inf(ExtendedInt! a, ExtendedInt! b, ExtendedInt! c, ExtendedInt! d)
+ {
+ ExtendedInt! infab = Inf(a,b);
+ ExtendedInt! infcd = Inf(c,d);
+
+ return Inf(infab, infcd);
+ }
+
+ public static ExtendedInt! Sup(ExtendedInt! inf, ExtendedInt! sup)
+ {
+ if(inf > sup)
+ return inf;
+ else
+ return sup;
+ }
+
+ public static ExtendedInt! Sup(ExtendedInt! a, ExtendedInt! b, ExtendedInt! c, ExtendedInt! d)
+ {
+ ExtendedInt! supab = Sup(a,b);
+ ExtendedInt! supcd = Sup(c,d);
+
+ return Sup(supab, supcd);
+ }
+
+ #endregion
+
+ // Return the ExtendedInt corresponding to the value
+ public static ExtendedInt! Factory(BigNum val)
+ {
+ return new PureInteger(val);
+ }
+ }
+
+ // Stands for a normal (finite) integer x
+ class PureInteger : ExtendedInt
+ {
+ public PureInteger(BigNum i)
+ {
+ this.val = i;
+ }
+
+ [Pure][Reads(ReadsAttribute.Reads.Owned)]
+ public override string! ToString()
+ {
+ return this.Value.ToString();
+ }
+
+ private BigNum val;
+ public override BigNum Value {
+ get
+ {
+ return this.val;
+ }
+ }
+
+ public override int Signum {
+ get {
+ return val.Signum;
+ }
+ }
+
+ public override int CompareTo(ExtendedInt! that) {
+ if (that is PlusInfinity)
+ return -1;
+ else if (that is PureInteger)
+ return this.Value.CompareTo(that.Value);
+ else // then that is a MinusInfinity
+ return 1;
+ }
+ }
+
+ abstract class InfinitaryInt : ExtendedInt
+ {
+ public override BigNum Value
+ {
+ get {
+ throw new InvalidOperationException();
+ }
+ }
+ }
+
+ class PlusInfinity : InfinitaryInt
+ {
+ [Pure][Reads(ReadsAttribute.Reads.Owned)]
+ public override string! ToString()
+ {
+ return "+oo";
+ }
+
+ public override int Signum {
+ get {
+ return 1;
+ }
+ }
+
+ public override int CompareTo(ExtendedInt! that) {
+ if (that is PlusInfinity)
+ return 0;
+ else
+ return 1;
+ }
+ }
+
+ class MinusInfinity : InfinitaryInt
+ {
+ [Pure][Reads(ReadsAttribute.Reads.Owned)]
+ public override string! ToString()
+ {
+ return "-oo";
+ }
+
+ public override int Signum {
+ get {
+ return -1;
+ }
+ }
+
+ public override int CompareTo(ExtendedInt! that) {
+ if (that is MinusInfinity)
+ return 0;
+ else
+ return -1;
+ }
+ }
+}
diff --git a/Source/AIFramework/VariableMap/MicroLattice.ssc b/Source/AIFramework/VariableMap/MicroLattice.ssc
new file mode 100644
index 00000000..d38a37c0
--- /dev/null
+++ b/Source/AIFramework/VariableMap/MicroLattice.ssc
@@ -0,0 +1,79 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+namespace Microsoft.AbstractInterpretationFramework
+{
+ using Microsoft.Contracts;
+ using System.Collections;
+ using System.Diagnostics;
+ using System.Compiler;
+ using Microsoft.AbstractInterpretationFramework.Collections;
+
+ /// <summary>
+ /// Interface for a lattice that works on a per-variable basis.
+ /// </summary>
+ public abstract class MicroLattice : MathematicalLattice
+ {
+ /// <summary>
+ /// Returns the predicate on the given variable for the given
+ /// lattice element.
+ /// </summary>
+ public abstract IExpr! ToPredicate(IVariable! v, Element! e);
+ /* requires !e.IsBottom && !e.IsTop; */
+
+ /// <summary>
+ /// Allows the lattice to specify whether it understands a particular function symbol.
+ ///
+ /// The lattice is always allowed to "true" even when it really can't do anything with
+ /// such functions; however, it is advantageous to say "false" when possible to avoid
+ /// being called to do certain things.
+ ///
+ /// The arguments to a function are provided for context so that the lattice can say
+ /// true or false for the same function symbol in different situations. For example,
+ /// a lattice may understand the multiplication of a variable and a constant but not
+ /// of two variables. The implementation of a lattice should not hold on to the
+ /// arguments.
+ /// </summary>
+ /// <param name="f">The function symbol.</param>
+ /// <param name="args">The argument context.</param>
+ /// <returns>True if it may understand f, false if it does not understand f.</returns>
+ public abstract bool Understands(IFunctionSymbol! f, IList/*<IExpr!>*/! args);
+
+ /// <summary>
+ /// Set this property to true if the implemented MicroLattice can handle basic arithmetic.
+ /// Stated otherwise this property is set to true if the MicroLattice provides a transfer function for a predicate in a given state
+ /// </summary>
+ public virtual bool UnderstandsBasicArithmetics
+ {
+ get { return false; }
+ }
+
+ /// <summary>
+ /// Evaluate the predicate e and a yield the lattice element
+ /// that is implied by it.
+ /// </summary>
+ /// <param name="e">The predicate that is assumed to contain 1 variable.</param>
+ /// <returns>The most precise lattice element that is implied by the predicate.</returns>
+ public abstract Element! EvaluatePredicate(IExpr! e);
+
+ /// <summary>
+ /// Evaluate the predicate e and yield an overapproximation of the predicate under the state that is passed as a parameter
+ /// Note that unless the subclass implement it, the default behavior is to evaluate the predicate stateless, that implies that it
+ /// is evaluated in any possible context, i.e. it is an upper approximation
+ /// </summary>
+ public virtual Element! EvaluatePredicateWithState(IExpr! e, IFunctionalMap state)
+ {
+ return EvaluatePredicate(e);
+ }
+
+ /// <summary>
+ /// Give an expression (often a value) that can be used to substitute for
+ /// the variable.
+ /// </summary>
+ /// <param name="e">A lattice element.</param>
+ /// <returns>The null value if no such expression can be given.</returns>
+ public abstract IExpr GetFoldExpr(Element! e);
+ }
+} \ No newline at end of file
diff --git a/Source/AIFramework/VariableMap/Nullness.ssc b/Source/AIFramework/VariableMap/Nullness.ssc
new file mode 100644
index 00000000..63d637ce
--- /dev/null
+++ b/Source/AIFramework/VariableMap/Nullness.ssc
@@ -0,0 +1,227 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using Microsoft.Contracts;
+namespace Microsoft.AbstractInterpretationFramework
+{
+ using System.Collections;
+ using System.Diagnostics;
+ using System.Compiler.Analysis;
+
+ public class NullnessLattice : MicroLattice
+ {
+ readonly INullnessFactory! factory;
+
+ public NullnessLattice(INullnessFactory! factory) {
+ this.factory = factory;
+ // base();
+ }
+
+ enum Value { Bottom, NotNull, Null, MayBeNull }
+
+ private class Elt : Element
+ {
+ public Value value;
+
+ public Elt (Value v) { this.value = v; }
+
+ [Pure][Reads(ReadsAttribute.Reads.Owned)]
+ public override System.Collections.Generic.ICollection<IVariable!>! FreeVariables()
+ {
+ return (!) (new System.Collections.Generic.List<IVariable!>()).AsReadOnly();
+ }
+
+ public override Element! Clone()
+ {
+ return new Elt(this.value);
+ }
+ }
+
+
+ public override Element! Top
+ {
+ get { return new Elt(Value.MayBeNull); }
+ }
+
+ public override Element! Bottom
+ {
+ get { return new Elt(Value.Bottom); }
+ }
+
+ public static Element! Null
+ {
+ get { return new Elt(Value.Null); }
+ }
+
+ public static Element! NotNull
+ {
+ get { return new Elt(Value.NotNull); }
+ }
+
+ public override bool IsTop (Element! element)
+ {
+ Elt e = (Elt) element;
+ return e.value == Value.MayBeNull;
+ }
+
+ public override bool IsBottom (Element! element)
+ {
+ Elt e = (Elt) element;
+ return e.value == Value.Bottom;
+ }
+
+ public override Lattice.Element! NontrivialJoin (Element! first, Element! second)
+ {
+ Elt a = (Elt) first;
+ Elt b = (Elt) second;
+ return (a.value == b.value) ? a : (Elt)Top;
+ }
+
+ public override Lattice.Element! NontrivialMeet (Element! first, Element! second)
+ {
+ Elt a = (Elt) first;
+ Elt b = (Elt) second;
+ return (a.value == b.value) ? a : (Elt)Bottom;
+ }
+
+ public override Element! Widen (Element! first, Element! second)
+ {
+ return Join(first,second);
+ }
+
+ protected override bool AtMost (Element! first, Element! second) // this <= that
+ {
+ Elt a = (Elt) first;
+ Elt b = (Elt) second;
+ return a.value == b.value;
+ }
+
+ public override IExpr! ToPredicate(IVariable! var, Element! element) {
+ Elt e = (Elt)element;
+
+ if (e.value == Value.NotNull)
+ {
+ return factory.Neq(var, factory.Null);
+ }
+ if (e.value == Value.Null)
+ {
+ return factory.Eq(var, factory.Null);
+ }
+ assert false;
+ throw new System.Exception();
+ }
+
+ public override IExpr GetFoldExpr(Element! e) {
+ Elt elt = (Elt)e;
+ if (elt.value == Value.Null) {
+ return factory.Null;
+ } else {
+ // can't fold into an expression
+ return null;
+ }
+ }
+
+ public override bool Understands(IFunctionSymbol! f, IList/*<IExpr!>*/! args) {
+ if (f.Equals(Microsoft.AbstractInterpretationFramework.Value.Eq) ||
+ f.Equals(Microsoft.AbstractInterpretationFramework.Value.Neq)) {
+
+ assert args.Count == 2;
+ IExpr! arg0 = (IExpr!)args[0];
+ IExpr! arg1 = (IExpr!)args[1];
+
+ // Look for "x OP null" or "null OP x" where OP is "==" or "!=".
+ if (arg0 is IVariable && arg1 is IFunApp && ((IFunApp)arg1).FunctionSymbol == Ref.Null) {
+ return true;
+ } else if (arg1 is IVariable && arg0 is IFunApp && ((IFunApp)arg0).FunctionSymbol == Ref.Null) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public override Element! EvaluatePredicate(IExpr! e) {
+ IFunApp nary = e as IFunApp;
+ if (nary != null) {
+ bool isEq = nary.FunctionSymbol.Equals(Microsoft.AbstractInterpretationFramework.Value.Eq);
+ if (isEq || nary.FunctionSymbol.Equals(Microsoft.AbstractInterpretationFramework.Value.Neq)) {
+ IList/*<IExpr!>*/! args = nary.Arguments;
+ assert args.Count == 2;
+ IExpr! arg0 = (IExpr!)args[0];
+ IExpr! arg1 = (IExpr!)args[1];
+
+ // Look for "x OP null" or "null OP x" where OP is "==" or "!=".
+ IVariable var = null;
+ if (arg0 is IVariable && arg1 is IFunApp && ((IFunApp)arg1).FunctionSymbol == Ref.Null)
+ {
+ var = (IVariable)arg0;
+ }
+ else if (arg1 is IVariable && arg0 is IFunApp && ((IFunApp)arg0).FunctionSymbol == Ref.Null)
+ {
+ var = (IVariable)arg1;
+ }
+
+ if (var != null) // found the pattern
+ {
+ return isEq ? Null:NotNull;
+ }
+ }
+ }
+ return Top;
+ }
+ }
+
+#if false
+
+ public class NullnessMicroLattice : MicroLattice
+ {
+ public override MicroLatticeElement Top { get { return NullnessLatticeElement.Top; } }
+ public override MicroLatticeElement Bottom { get { return NullnessLatticeElement.Bottom; } }
+
+
+ public override MicroLatticeElement EvaluateExpression (Expr e, LookupValue lookup)
+ {
+ if (e is LiteralExpr && ((LiteralExpr)e).Val == null)
+ {
+ return NullnessLatticeElement.Null;
+ }
+ return Top;
+ }
+
+
+ public override MicroLatticeElement EvaluatePredicate (Expr e, LookupValue lookup)
+ {
+ NAryExpr nary = e as NAryExpr;
+ if (nary != null &&
+ (nary.Fun.FunctionName.Equals("==") || nary.Fun.FunctionName.Equals("!=")))
+ {
+ Debug.Assert(nary.Args.Length == 2);
+
+ Expr arg0 = nary.Args[0], arg1 = nary.Args[1];
+ Variable var = null;
+
+ // Look for "x OP null" or "null OP x" where OP is "==" or "!=".
+ if (arg0 is IdentifierExpr && arg1 is LiteralExpr && ((LiteralExpr)arg1).Val == null)
+ {
+ var = ((IdentifierExpr)arg0).Decl;
+ }
+ else if (arg1 is IdentifierExpr && arg0 is LiteralExpr && ((LiteralExpr)arg0).Val == null)
+ {
+ var = ((IdentifierExpr)arg1).Decl;
+ }
+
+ if (var != null) // found the pattern
+ {
+ return nary.Fun.FunctionName.Equals("==") ?
+ NullnessLatticeElement.Null :
+ NullnessLatticeElement.NotNull;
+ }
+ }
+ return Top;
+ }
+ }
+
+#endif
+
+}
diff --git a/Source/AIFramework/VariableMap/VariableMapLattice.ssc b/Source/AIFramework/VariableMap/VariableMapLattice.ssc
new file mode 100644
index 00000000..aa15f1e6
--- /dev/null
+++ b/Source/AIFramework/VariableMap/VariableMapLattice.ssc
@@ -0,0 +1,749 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+namespace Microsoft.AbstractInterpretationFramework
+{
+ using Microsoft.Contracts;
+ using System.Collections;
+ using System.Collections.Generic;
+ using System.Diagnostics;
+
+ using Microsoft.AbstractInterpretationFramework;
+ using Microsoft.AbstractInterpretationFramework.Collections;
+
+ using Microsoft.Boogie;
+ using IMutableSet = Microsoft.Boogie.Set;
+ using HashSet = Microsoft.Boogie.Set;
+ using ISet = Microsoft.Boogie.Set;
+
+ /// <summary>
+ /// Creates a lattice that works for several variables given a MicroLattice. Assumes
+ /// if one variable is bottom, then all variables are bottom.
+ /// </summary>
+ public class VariableMapLattice : Lattice
+ {
+ private class Elt : Element
+ {
+ /// <summary>
+ /// IsBottom(e) iff e.constraints == null
+ /// </summary>
+ /*MayBeNull*/
+ private IFunctionalMap constraints; // of type IVariable -> LATTICE_ELEMENT
+ public IFunctionalMap Constraints
+ {
+ get
+ {
+ return this.constraints;
+ }
+ }
+
+ private Elt(bool top) {
+ if (top) {
+ this.constraints = FunctionalHashtable.Empty;
+ } else {
+ this.constraints = null;
+ }
+ }
+
+ public override Element! Clone()
+ {
+ return new Elt(this.constraints);
+ }
+
+ public static Elt! Top = new Elt(true);
+ public static Elt! Bottom = new Elt(false);
+
+ public Elt(IFunctionalMap constraints)
+ {
+ this.constraints = constraints;
+ }
+
+ public bool IsBottom {
+ [Pure][Reads(ReadsAttribute.Reads.Owned)]
+ get {
+ return this.constraints == null;
+ }
+ }
+
+ public int Count { get { return this.constraints == null ? 0 : this.constraints.Count; } }
+
+ public IEnumerable/*<IVariable>*/! Variables {
+ get
+ requires !this.IsBottom;
+ {
+ assume this.constraints != null;
+ return (!) this.constraints.Keys;
+ }
+ }
+
+ public IEnumerable/*<IVariable>*/! SortedVariables(/*maybe null*/ IComparer variableComparer) {
+ if (variableComparer == null) {
+ return Variables;
+ } else {
+ ArrayList /*IVariable*/ vars = new ArrayList /*IVariable*/ (Count);
+ foreach (IVariable variable in Variables) {
+ vars.Add(variable);
+ }
+ vars.Sort(variableComparer);
+ return vars;
+ }
+ }
+
+ public Element Lookup(IVariable v)
+ {
+ if ((v == null) || (this.constraints == null)) { return null; }
+ return (Element)this.constraints[v];
+ }
+
+ public Element this [IVariable! key] {
+ get
+ requires !this.IsBottom;
+ {
+ assume this.constraints != null;
+ return (Element)constraints[key];
+ }
+ }
+
+ /// <summary>
+ /// Add a new entry in the functional map: var --> value.
+ /// If the variable is already there, throws an exception
+ /// </summary>
+ public Elt! Add(IVariable! var, Element! value, MicroLattice! microLattice)
+ requires !this.IsBottom;
+ {
+ assume this.constraints != null;
+ assert !this.constraints.Contains(var);
+
+ if (microLattice.IsBottom(value)) { return Bottom; }
+ if (microLattice.IsTop(value)) { return this.Remove(var, microLattice); }
+
+ return new Elt(this.constraints.Add(var, value));
+ }
+
+ /// <summary>
+ /// Set the value of the variable in the functional map
+ /// If the variable is not already there, throws an exception
+ /// </summary>
+ public Elt! Set(IVariable! var, Element! value, MicroLattice! microLattice)
+ {
+ if(microLattice.IsBottom(value)) { return Bottom; }
+ if(microLattice.IsTop(value)) { return this.Remove(var, microLattice); }
+
+ assume this.constraints != null;
+ assert this.constraints.Contains(var);
+
+ // this.constraints[var] = value;
+ IFunctionalMap newMap = this.constraints.Set(var, value);
+
+ return new Elt(newMap);
+ }
+
+ public Elt! Remove(IVariable! var, MicroLattice microLattice)
+ {
+ if (this.IsBottom) { return this; }
+ assume this.constraints != null;
+ return new Elt(this.constraints.Remove(var));
+ }
+
+ public Elt! Rename(IVariable! oldName, IVariable! newName, MicroLattice! microLattice)
+ requires !this.IsBottom;
+ {
+ Element value = this[oldName];
+ if (value == null) { return this; } // 'oldName' isn't in the map, so neither will be 'newName'
+ assume this.constraints != null;
+ IFunctionalMap newMap = this.constraints.Remove(oldName);
+ newMap = newMap.Add(newName, value);
+ return new Elt(newMap);
+ }
+
+ [Pure][Reads(ReadsAttribute.Reads.Owned)]
+ public override ICollection<IVariable!>! FreeVariables()
+ {
+ throw new System.NotImplementedException();
+ }
+
+ } // class
+
+ private readonly MicroLattice! microLattice;
+
+ private readonly IPropExprFactory! propExprFactory;
+
+ private readonly /*maybe null*/IComparer variableComparer;
+
+ public VariableMapLattice(IPropExprFactory! propExprFactory, IValueExprFactory! valueExprFactory, MicroLattice! microLattice, /*maybe null*/IComparer variableComparer)
+ : base(valueExprFactory)
+ {
+ this.propExprFactory = propExprFactory;
+ this.microLattice = microLattice;
+ this.variableComparer = variableComparer;
+ // base(valueExprFactory);
+ }
+
+ protected override object! UniqueId { get { return this.microLattice.GetType(); } }
+
+ public override Element! Top { get { return Elt.Top; } }
+
+ public override Element! Bottom { get { return Elt.Bottom; } }
+
+ public override bool IsTop(Element! element)
+ {
+ Elt e = (Elt)element;
+ return !e.IsBottom && e.Count == 0;
+ }
+
+ public override bool IsBottom(Element! element)
+ {
+ return ((Elt)element).IsBottom;
+ }
+
+ protected override bool AtMost(Element! first, Element! second)
+ {
+ Elt a = (Elt)first;
+ Elt b = (Elt)second;
+
+ // return true iff every constraint in "this" is no weaker than the corresponding
+ // constraint in "that" and there are no additional constraints in "that"
+ foreach (IVariable! var in a.Variables)
+ {
+ Element thisValue = (!)a[var];
+
+ Element thatValue = b[var];
+ if (thatValue == null) { continue; } // it's okay for "a" to know something "b" doesn't
+
+ if (this.microLattice.LowerThan(thisValue, thatValue)) { continue; } // constraint for "var" satisfies AtMost relation
+
+ return false;
+ }
+ foreach (IVariable! var in b.Variables)
+ {
+ if (a.Lookup(var) != null) { continue; } // we checked this case in the loop above
+
+ Element thatValue = (!)b[var];
+ if (this.microLattice.IsTop(thatValue)) { continue; } // this is a trivial constraint
+
+ return false;
+ }
+ return true;
+ }
+
+ private Elt! AddConstraint(Element! element, IVariable! var, /*MicroLattice*/Element! newValue)
+ {
+ Elt e = (Elt)element;
+
+ if (!e.IsBottom && !this.microLattice.IsBottom(newValue)) // if we're not at bottom
+ {
+ /*MicroLattice*/Element currentValue = e[var];
+
+ if (currentValue == null)
+ {
+ // No information currently, so we just add the new info.
+ return e.Add(var, newValue, this.microLattice);
+ }
+ else
+ {
+ // Otherwise, take the meet of the new and current info.
+ //return e.Add(var, this.microLattice.Meet(currentValue, newValue), this.microLattice);
+ return e.Set(var, this.microLattice.Meet(currentValue, newValue), this.microLattice);
+ }
+ }
+ return e;
+ }
+
+ public override string! ToString(Element! element)
+ {
+ Elt e = (Elt)element;
+
+ if (IsTop(e)) { return "<top>"; }
+ if (IsBottom(e)) { return "<bottom>"; }
+
+ int k = 0;
+ System.Text.StringBuilder buffer = new System.Text.StringBuilder();
+ foreach (IVariable! key in e.SortedVariables(variableComparer))
+ {
+ if (k++ > 0) { buffer.Append("; "); }
+ buffer.AppendFormat("{0} = {1}", key, e[key]);
+ }
+ return buffer.ToString();
+ }
+
+ public override Element! NontrivialJoin(Element! first, Element! second)
+ {
+ Elt a = (Elt)first;
+ Elt b = (Elt)second;
+
+ IFunctionalMap newMap = FunctionalHashtable.Empty;
+ foreach (IVariable! key in a.Variables)
+ {
+ Element aValue = a[key];
+ Element bValue = b[key];
+
+ if (aValue != null && bValue != null)
+ {
+ // Keep only the variables known to both elements.
+ Element newValue = this.microLattice.Join(aValue, bValue);
+ newMap = newMap.Add(key, newValue);
+ }
+ }
+ Elt! join = new Elt(newMap);
+
+ // System.Console.WriteLine("{0} join {1} = {2} ", this.ToString(a), ToString(b), ToString(join));
+
+ return join;
+ }
+
+ public override Element! NontrivialMeet(Element! first, Element! second)
+ {
+ Elt a = (Elt)first;
+ Elt b = (Elt)second;
+
+ IFunctionalMap newMap = FunctionalHashtable.Empty;
+ foreach (IVariable! key in a.Variables)
+ {
+ Element! aValue = (!) a[key];
+ Element bValue = b[key];
+
+ Element newValue =
+ bValue == null ? aValue :
+ this.microLattice.Meet(aValue, bValue);
+
+ newMap = newMap.Add(key, newValue);
+ }
+ foreach (IVariable! key in b.Variables)
+ {
+ Element aValue = a[key];
+ Element bValue = b[key]; Debug.Assert(bValue != null);
+
+ if (aValue == null)
+ {
+ // It's a variable we didn't cover in the last loop.
+ newMap = newMap.Add(key, bValue);
+ }
+ }
+ return new Elt(newMap);
+ }
+
+ /// <summary>
+ /// Perform the pointwise widening of the elements in the map
+ /// </summary>
+ public override Element! Widen (Element! first, Element! second)
+ {
+ Elt a = (Elt)first;
+ Elt b = (Elt)second;
+
+ // Note we have to add those cases as we do not have a "NonTrivialWiden" method
+ if(a.IsBottom)
+ return new Elt(b.Constraints);
+ if(b.IsBottom)
+ return new Elt(a.Constraints);
+
+ IFunctionalMap newMap = FunctionalHashtable.Empty;
+ foreach (IVariable! key in a.Variables)
+ {
+ Element aValue = a[key];
+ Element bValue = b[key];
+
+ if (aValue != null && bValue != null)
+ {
+ // Keep only the variables known to both elements.
+ Element newValue = this.microLattice.Widen(aValue, bValue);
+ newMap = newMap.Add(key, newValue);
+ }
+ }
+ Element! widen= new Elt(newMap);
+
+ // System.Console.WriteLine("{0} widen {1} = {2} ", this.ToString(a), ToString(b), ToString(widen));
+
+ return widen;
+ }
+
+ internal static ISet/*<IVariable!>*/! VariablesInExpression(IExpr! e, ISet/*<IVariable!>*/! ignoreVars)
+ {
+ HashSet s = new HashSet();
+
+ IFunApp f = e as IFunApp;
+ IFunction lambda = e as IFunction;
+
+ if (e is IVariable)
+ {
+ if (!ignoreVars.Contains(e))
+ s.Add(e);
+ }
+ else if (f != null) // e is IFunApp
+ {
+ foreach (IExpr! arg in f.Arguments)
+ {
+ s.AddAll(VariablesInExpression(arg, ignoreVars));
+ }
+ }
+ else if (lambda != null)
+ {
+ IMutableSet x = new HashSet(1);
+ x.Add(lambda.Param);
+
+ // Ignore the bound variable
+ s.AddAll(VariablesInExpression(lambda.Body, (!) Set.Union(ignoreVars, x)));
+ }
+ else
+ {
+ Debug.Assert(false, "case not handled: " + e);
+ }
+ return s;
+ }
+
+
+ private static ArrayList/*<IExpr>*/! FindConjuncts(IExpr e)
+ {
+ ArrayList result = new ArrayList();
+
+ IFunApp f = e as IFunApp;
+ if (f != null)
+ {
+ if (f.FunctionSymbol.Equals(Prop.And))
+ {
+ foreach (IExpr arg in f.Arguments)
+ {
+ result.AddRange(FindConjuncts(arg));
+ }
+ }
+ else if (f.FunctionSymbol.Equals(Prop.Or)
+ || f.FunctionSymbol.Equals(Prop.Implies))
+ {
+ // Do nothing.
+ }
+ else
+ {
+ result.Add(e);
+ }
+ }
+ else
+ {
+ result.Add(e);
+ }
+
+ return result;
+ }
+
+ private static bool IsSimpleEquality(IExpr expr, out IVariable left, out IVariable right)
+ ensures result ==> left != null && right != null;
+ {
+ left = null;
+ right = null;
+
+ // See if we have an equality
+ IFunApp nary = expr as IFunApp;
+ if (nary == null || !nary.FunctionSymbol.Equals(Value.Eq)) { return false; }
+
+ // See if it is an equality of two variables
+ IVariable idLeft = nary.Arguments[0] as IVariable;
+ IVariable idRight = nary.Arguments[1] as IVariable;
+ if (idLeft == null || idRight == null) { return false; }
+
+ left = idLeft;
+ right = idRight;
+ return true;
+ }
+
+ /// <summary>
+ /// Returns true iff the expression is in the form var == arithmeticExpr
+ /// </summary>
+ private static bool IsArithmeticExpr(IExpr! expr)
+ {
+ // System.Console.WriteLine("\t\tIsArithmetic called with {0} of type {1}", expr, expr.GetType().ToString());
+
+ if(expr is IVariable) // expr is a variable
+ return true;
+ else if(expr is IFunApp) // may be ==, +, -, /, % or an integer
+ {
+ IFunApp fun = (IFunApp) expr;
+
+ if(fun.FunctionSymbol is IntSymbol) // it is an integer
+ return true;
+ else if(fun.FunctionSymbol.Equals(Int.Negate)) // it is an unary minus
+ return IsArithmeticExpr((IExpr!) fun.Arguments[0]);
+ else if(fun.Arguments.Count != 2) // A function of two or more operands is not arithmetic
+ return false;
+ else
+ {
+ IExpr! left = (IExpr!) fun.Arguments[0];
+ IExpr! right = (IExpr!) fun.Arguments[1];
+
+ if(!(left is IVariable || right is IVariable)) // At least one of the two operands must be a variable
+ return false;
+
+ if(fun.FunctionSymbol.Equals(Value.Eq)
+ || fun.FunctionSymbol.Equals(Int.Add)
+ || fun.FunctionSymbol.Equals(Int.Sub)
+ || fun.FunctionSymbol.Equals(Int.Mul)
+ || fun.FunctionSymbol.Equals(Int.Div)
+ || fun.FunctionSymbol.Equals(Int.Mod))
+ return IsArithmeticExpr(left) && IsArithmeticExpr(right);
+ else
+ return false;
+ }
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ public override IExpr! ToPredicate(Element! element)
+ {
+ if (IsTop(element)) { return propExprFactory.True; }
+ if (IsBottom(element)) { return propExprFactory.False; }
+
+ Elt e = (Elt)element;
+ IExpr truth = propExprFactory.True;
+ IExpr result = truth;
+
+ foreach (IVariable! variable in e.SortedVariables(variableComparer))
+ {
+ Element value = (Element)e[variable];
+
+ if (value == null || this.microLattice.IsTop(value)) { continue; } // Skip variables about which we know nothing.
+ if (this.microLattice.IsBottom(value)) { return propExprFactory.False; }
+
+ IExpr conjunct = this.microLattice.ToPredicate(variable, value);
+
+ result = (result == truth) ? (IExpr)conjunct : (IExpr)propExprFactory.And(result, conjunct);
+ }
+ return result;
+ }
+
+
+ public override Element! Eliminate(Element! element, IVariable! variable)
+ {
+ return ((Elt!)element).Remove(variable, this.microLattice);
+ }
+
+ private delegate IExpr! OnUnableToInline(IVariable! var);
+ private IExpr! IdentityVarToExpr(IVariable! var)
+ {
+ return var;
+ }
+
+ /// <summary>
+ /// Return a new expression in which each variable has been
+ /// replaced by an expression representing what is known about
+ /// that variable.
+ /// </summary>
+ private IExpr! InlineVariables(Elt! element, IExpr! expr, ISet/*<IVariable!>*/! notInlineable,
+ OnUnableToInline! unableToInline)
+ {
+ IVariable var = expr as IVariable;
+ if (var != null)
+ {
+ /*MicroLattice*/Element value = element[var];
+ if (notInlineable.Contains(var) || value == null || this.microLattice.IsTop(value))
+ {
+ return unableToInline(var); // We don't know anything about this variable.
+ }
+ else
+ {
+ // GetFoldExpr returns null when it can yield an expression that
+ // can be substituted for the variable.
+ IExpr valueExpr = this.microLattice.GetFoldExpr(value);
+ return (valueExpr == null) ? var : valueExpr;
+ }
+ }
+
+ // else
+
+ IFunApp fun = expr as IFunApp;
+ if (fun != null)
+ {
+ IList newargs = new ArrayList();
+ foreach (IExpr! arg in fun.Arguments)
+ {
+ newargs.Add(InlineVariables(element, arg, notInlineable, unableToInline));
+ }
+ return fun.CloneWithArguments(newargs);
+ }
+
+ // else
+
+ IFunction lambda = expr as IFunction;
+ if (lambda != null)
+ {
+ IMutableSet x = new HashSet(1);
+ x.Add(lambda.Param);
+
+ // Don't inline the bound variable
+ return lambda.CloneWithBody(
+ InlineVariables(element, lambda.Body,
+ (!) Set.Union(notInlineable, x), unableToInline)
+ );
+ }
+
+ else
+ {
+ throw
+ new System.NotImplementedException("cannot inline identifies in expression " + expr);
+ }
+ }
+
+
+ public override Element! Constrain(Element! element, IExpr! expr)
+ {
+ Elt! result = (Elt)element;
+
+ if(IsBottom(element))
+ {
+ return result; // == element
+ }
+
+ expr = InlineVariables(result, expr, (!)Set.Empty, new OnUnableToInline(IdentityVarToExpr));
+
+ foreach (IExpr! conjunct in FindConjuncts(expr))
+ {
+ IVariable left, right;
+
+ if (IsSimpleEquality(conjunct, out left, out right))
+ {
+ #region The conjunct is a simple equality
+
+
+ assert left != null && right != null;
+
+ Element leftValue = result[left], rightValue = result[right];
+ if (leftValue == null) { leftValue = this.microLattice.Top; }
+ if (rightValue == null) { rightValue = this.microLattice.Top; }
+ Element newValue = this.microLattice.Meet(leftValue, rightValue);
+ result = AddConstraint(result, left, newValue);
+ result = AddConstraint(result, right, newValue);
+
+ #endregion
+ }
+ else
+ {
+ ISet/*<IVariable>*/ variablesInvolved = VariablesInExpression(conjunct, Set.Empty);
+
+ if (variablesInvolved.Count == 1)
+ {
+ #region We have just one variable
+
+ IVariable var = null;
+ foreach (IVariable! v in variablesInvolved) { var = v; } // why is there no better way to get the elements?
+ assert var != null;
+ Element! value = this.microLattice.EvaluatePredicate(conjunct);
+ result = AddConstraint(result, var, value);
+
+ #endregion
+ }
+ else if(IsArithmeticExpr(conjunct) && this.microLattice.UnderstandsBasicArithmetics)
+ {
+ #region We evalaute an arithmetic expression
+
+ IFunApp fun = (IFunApp) conjunct;
+ if(fun.FunctionSymbol.Equals(Microsoft.AbstractInterpretationFramework.Value.Eq)) // if it is a symbol of equality
+ {
+ // get the variable to be assigned
+ IExpr! leftArg = (IExpr!) fun.Arguments[0];
+ IExpr! rightArg = (IExpr!) fun.Arguments[1];
+ IExpr! var = (leftArg is IVariable) ? leftArg : rightArg;
+
+ Element! value = this.microLattice.EvaluatePredicateWithState(conjunct, result.Constraints);
+ result = AddConstraint(result, (IVariable!) var, value);
+ }
+ #endregion
+ }
+ }
+ }
+ return result;
+ }
+
+
+ public override Element! Rename(Element! element, IVariable! oldName, IVariable! newName)
+ {
+ if(IsBottom(element))
+ {
+ return element;
+ }
+ else
+ {
+ return ((Elt)element).Rename(oldName, newName, this.microLattice);
+ }
+ }
+
+
+ public override bool Understands(IFunctionSymbol! f, IList! args)
+ {
+ return f.Equals(Prop.And) ||
+ f.Equals(Value.Eq) ||
+ microLattice.Understands(f, args);
+ }
+
+ private sealed class EquivalentExprException : CheckedException { }
+ private sealed class EquivalentExprInlineCallback
+ {
+ private readonly IVariable! var;
+ public EquivalentExprInlineCallback(IVariable! var)
+ {
+ this.var = var;
+ // base();
+ }
+
+ public IExpr! ThrowOnUnableToInline(IVariable! othervar)
+ throws EquivalentExprException;
+ {
+ if (othervar.Equals(var))
+ throw new EquivalentExprException();
+ else
+ return othervar;
+ }
+ }
+
+ public override IExpr/*?*/ EquivalentExpr(Element! e, IQueryable! q, IExpr! expr, IVariable! var, ISet/*<IVariable!>*/! prohibitedVars)
+ {
+ try
+ {
+ EquivalentExprInlineCallback closure = new EquivalentExprInlineCallback(var);
+ return InlineVariables((Elt)e, expr, (!)Set.Empty,
+ new OnUnableToInline(closure.ThrowOnUnableToInline));
+ }
+ catch (EquivalentExprException)
+ {
+ return null;
+ }
+ }
+
+
+ /// <summary>
+ /// Check to see if the given predicate holds in the given lattice element.
+ ///
+ /// TODO: We leave this unimplemented for now and just return maybe.
+ /// </summary>
+ /// <param name="e">The lattice element.</param>
+ /// <param name="pred">The predicate.</param>
+ /// <returns>Yes, No, or Maybe</returns>
+ public override Answer CheckPredicate(Element! e, IExpr! pred)
+ {
+ return Answer.Maybe;
+ }
+
+ /// <summary>
+ /// Answers a disequality about two variables. The same information could be obtained
+ /// by asking CheckPredicate, but a different implementation may be simpler and more
+ /// efficient.
+ ///
+ /// TODO: We leave this unimplemented for now and just return maybe.
+ /// </summary>
+ /// <param name="e">The lattice element.</param>
+ /// <param name="var1">The first variable.</param>
+ /// <param name="var2">The second variable.</param>
+ /// <returns>Yes, No, or Maybe.</returns>
+ public override Answer CheckVariableDisequality(Element! e, IVariable! var1, IVariable! var2)
+ {
+ return Answer.Maybe;
+ }
+
+ public override void Validate()
+ {
+ base.Validate();
+ microLattice.Validate();
+ }
+
+ }
+}
diff --git a/Source/AbsInt/AbsInt.sscproj b/Source/AbsInt/AbsInt.sscproj
new file mode 100644
index 00000000..95d6f1d2
--- /dev/null
+++ b/Source/AbsInt/AbsInt.sscproj
@@ -0,0 +1,120 @@
+<?xml version="1.0" encoding="utf-8"?>
+<VisualStudioProject>
+ <XEN ProjectType="Local"
+ SchemaVersion="1.0"
+ Name="AbsInt"
+ ProjectGuid="11d06232-2039-4bca-853b-c596e2a4edb0"
+ >
+ <Build>
+ <Settings ApplicationIcon=""
+ AssemblyName="AbsInt"
+ OutputType="Library"
+ RootNamespace="AbsInt"
+ StartupObject=""
+ TargetPlatform="v2"
+ TargetPlatformLocation=""
+ ShadowedAssembly=""
+ StandardLibraryLocation=""
+ >
+ <Config Name="Debug"
+ AllowUnsafeBlocks="False"
+ BaseAddress="285212672"
+ CheckForOverflowUnderflow="False"
+ ConfigurationOverrideFile=""
+ DefineConstants="DEBUG;TRACE"
+ DocumentationFile=""
+ DebugSymbols="True"
+ FileAlignment="4096"
+ IncrementalBuild="True"
+ Optimize="False"
+ OutputPath="bin\Debug"
+ RegisterForComInterop="False"
+ RemoveIntegerChecks="false"
+ TreatWarningsAsErrors="False"
+ WarningLevel="4"
+ RunProgramVerifier="False"
+ ProgramVerifierCommandLineOptions=""
+ ReferenceTypesAreNonNullByDefault="False"
+ RunProgramVerifierWhileEditing="False"
+ AllowPointersToManagedStructures="False"
+ CheckContractAdmissibility="True"
+ CheckPurity="False"
+ />
+ <Config Name="Release"
+ AllowUnsafeBlocks="false"
+ BaseAddress="285212672"
+ CheckForOverflowUnderflow="false"
+ ConfigurationOverrideFile=""
+ DefineConstants="TRACE"
+ DocumentationFile=""
+ DebugSymbols="false"
+ FileAlignment="4096"
+ IncrementalBuild="false"
+ Optimize="true"
+ OutputPath="bin\release"
+ RegisterForComInterop="false"
+ RemoveIntegerChecks="false"
+ TreatWarningsAsErrors="True"
+ WarningLevel="4"
+ />
+ </Settings>
+ <References>
+ <Reference Name="Mscorlib.Contracts"
+ AssemblyName="Mscorlib.Contracts"
+ Private="false"
+ HintPath="../../Binaries/Mscorlib.Contracts.dll"
+ />
+ <Reference Name="System"
+ AssemblyName="System"
+ Private="false"
+ />
+ <Reference Name="System.Compiler"
+ AssemblyName="System.Compiler"
+ Private="false"
+ HintPath="../../Binaries/System.Compiler.dll"
+ />
+ <Reference Name="System.Compiler.Framework"
+ AssemblyName="System.Compiler.Framework"
+ Private="false"
+ HintPath="../../Binaries/System.Compiler.Framework.dll"
+ />
+ <Reference Name="AIFramework"
+ Project="{24B55172-AD8B-47D1-8952-5A95CFDB9B31}"
+ Private="true"
+ />
+ <Reference Name="Core"
+ Project="{47BC34F1-A173-40BE-84C2-9332B4418387}"
+ Private="true"
+ />
+ <Reference Name="Basetypes"
+ Project="{0C692837-77EC-415F-BF04-395E3ED06E9A}"
+ Private="true"
+ />
+ </References>
+ </Build>
+ <Files>
+ <Include>
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="Traverse.ssc"
+ />
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="AbstractInterpretation.ssc"
+ />
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="ExprFactories.ssc"
+ />
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="..\version.ssc"
+ />
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="LoopInvariantsOnDemand.ssc"
+ />
+ </Include>
+ </Files>
+ </XEN>
+</VisualStudioProject> \ No newline at end of file
diff --git a/Source/AbsInt/AbstractInterpretation.ssc b/Source/AbsInt/AbstractInterpretation.ssc
new file mode 100644
index 00000000..eee25a09
--- /dev/null
+++ b/Source/AbsInt/AbstractInterpretation.ssc
@@ -0,0 +1,1074 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using Microsoft.Contracts;
+
+namespace Microsoft.Boogie.AbstractInterpretation
+{
+ using System;
+ using System.Collections;
+ using System.Collections.Generic;
+ using System.Diagnostics;
+ using Microsoft.Boogie;
+ using Cci = System.Compiler;
+ using AI = Microsoft.AbstractInterpretationFramework;
+ using Microsoft.Contracts;
+
+ /// <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;
+ private Cci.IRelation/*<Procedure,Implementation>*/ procedureImplementations;
+
+ 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]
+
+ invariant 0 <= Index && Index < Proc.Summary.Count;
+
+ public ProcedureWorkItem ([Captured] Procedure! p, AI.Lattice.Element! v, AI.Lattice! lattice)
+ 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)
+ {
+ assume log.IsExposable; //PM: One would need static class invariants to prove this property
+ expose(log) {
+ log.Enabled = AI.Lattice.LogSwitch;
+ }
+ this.lattice = lattice;
+ this.procWorkItems = new Queue<ProcedureWorkItem!>();
+ this.callReturnWorkItems = new Queue();
+ // base();
+ }
+
+ private Cci.IGraphNavigator ComputeCallGraph (Program! program)
+ ensures this.procedureImplementations != 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.
+
+ Cci.IMutableRelation/*<Implementation,Procedure>*/ callsProcedure = new Cci.Relation();
+ Cci.IMutableRelation/*<Procedure,Implementation>*/ implementsProcedure = new Cci.Relation();
+ this.procedureImplementations = implementsProcedure;
+
+// ArrayList publics = new ArrayList();
+// publicImpls = publics;
+
+ foreach (Declaration member in program.TopLevelDeclarations)
+ {
+ Implementation impl = member as Implementation;
+ if (impl != null)
+ {
+ implementsProcedure.Add(impl.Proc, impl);
+ // if (impl.IsPublic) { publics.Add(impl); } // PR: what does "IsPublic" stand for?
+
+ foreach (Block block in impl.Blocks)
+ {
+ foreach (Cmd cmd in block.Cmds)
+ {
+ CallCmd call = cmd as CallCmd;
+ if (call != null)
+ {
+ callsProcedure.Add(impl, call.Proc);
+ }
+ }
+ }
+ }
+ }
+
+ // Now compute a graph from implementations to implementations.
+
+ Cci.GraphBuilder callGraph = new Cci.GraphBuilder();
+
+ IEnumerable callerImpls = callsProcedure.GetKeys();
+ assume callerImpls != null; // because of non-generic collection
+ foreach (Implementation caller in callerImpls)
+ {
+ IEnumerable callerProcs = callsProcedure.GetValues(caller);
+ assume callerProcs != null; // because of non-generic collection
+ foreach (Procedure callee in callerProcs)
+ {
+ IEnumerable calleeImpls = implementsProcedure.GetValues(callee);
+ assume calleeImpls != null; // because of non-generic collection
+ foreach (Implementation calleeImpl in calleeImpls)
+ {
+ callGraph.AddEdge(caller, calleeImpl);
+ }
+ }
+ }
+
+ return callGraph;
+ }
+
+#if OLDCODE
+ public void ComputeImplementationInvariants (Implementation impl)
+ {
+ // process each procedure implementation by recursively processing the first (entry) block...
+ ComputeBlockInvariants(impl.Blocks[0], lattice.Top);
+
+ // 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)
+ {
+ AI.Lattice.Element postValue = block.PostInvariantBuckets[invariantIndex];
+ Debug.Assert(postValue != null);
+ post = post.Join(postValue);
+ }
+ }
+ impl.PostInvariant = post;
+
+ // Now update the procedure to reflect the new properties
+ // of this implementation.
+
+ if (impl.Proc.PreInvariant <= impl.PreInvariant)
+ {
+ // Strengthen the precondition
+ impl.Proc.PreInvariant = impl.PreInvariant;
+ foreach (Implementation otherImpl in this.procedureImplementations.GetValues(impl.Proc))
+ {
+ if (otherImpl == impl) { continue; }
+ if (otherImpl.PreInvariant <= impl.Proc.PreInvariant)
+ {
+ // If another implementation of the same procedure has
+ // a weaker precondition, re-do it with the stronger
+ // precondition.
+ otherImpl.PreInvariant = impl.Proc.PreInvariant;
+ this.implWorkItems.Enqueue(otherImpl);
+ }
+ }
+ }
+ }
+#endif
+
+
+#if NOTYET
+ public void ComputeSccInvariants (IEnumerable/*<Implementation>*/ implementations)
+ {
+ Debug.Assert(this.implWorkItems.Count == 0); // no work left over from last SCC
+
+ foreach (Implementation impl in implementations)
+ {
+ impl.AbstractFunction = AbstractFunction.Empty.WithPair(this.lattice.Bottom, this.lattice.Bottom);
+ this.implWorkItems.Enqueue(impl);
+ }
+
+ while (this.implWorkItems.Count > 0) // until fixed point reached
+ {
+ Implementation impl = (Implementation)this.implWorkItems.Dequeue();
+ }
+ }
+#endif
+
+ public AI.Lattice.Element! ApplyProcedureSummary (CallCmd! call, Implementation! caller, AI.Lattice.Element! knownAtCallSite, CallSite! callSite)
+ requires call.Proc != null;
+ {
+ Procedure! proc = call.Proc;
+
+ // 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! releventToCall = knownAtCallSite;
+ for (int i=0; i<proc.InParams.Length; i++)
+ {
+ // "Assign" the actual expressions to the corresponding formal variables.
+ assume proc.InParams[i] != null; //PM: this can be fixed once VariableSeq is replaced by List<Variable!>;
+ assume call.Ins[i] != null; //PM: this can be fixed once VariableSeq is replaced by List<Variable!>;
+ Expr equality = Expr.Eq(Expr.Ident( (!) proc.InParams[i]), (!) call.Ins[i]);
+ releventToCall = lattice.Constrain(releventToCall, equality.IExpr);
+ }
+ foreach (Variable! var in caller.LocVars) {
+ releventToCall = this.lattice.Eliminate(releventToCall, var);
+ }
+
+ ProcedureSummary! summary = proc.Summary;
+ ProcedureSummaryEntry applicableEntry = null;
+
+ for (int i=0; i<summary.Count; i++)
+ {
+ ProcedureSummaryEntry! current = (!) summary[i];
+
+ if (lattice.Equivalent(current.OnEntry, releventToCall))
+ {
+ applicableEntry = current;
+ break;
+ }
+ }
+
+ // Not found in current map, so add new entry.
+ if (applicableEntry == null)
+ {
+ ProcedureWorkItem! newWorkItem = new ProcedureWorkItem(proc, releventToCall, lattice);
+ this.procWorkItems.Enqueue(newWorkItem);
+ applicableEntry = (!) 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, (!) call.Proc.OutParams[i], (!)((!) call.Outs[i]).Decl);
+ knownAtCallSite = this.lattice.Eliminate(knownAtCallSite, (!)((!) call.Outs[i]).Decl);
+ }
+
+ return this.lattice.Meet(atReturn, knownAtCallSite);
+ }
+
+ private Cci.IGraphNavigator callGraph;
+ public Cci.IGraphNavigator CallGraph {
+ get { return this.callGraph; }
+ }
+
+ /// <summary>
+ /// Compute the invariants for the program using the underlying abstract domain
+ /// </summary>
+ public void ComputeProgramInvariants (Program! program)
+ {
+
+#if NOT_YET
+ Cci.IGraphNavigator callGraph =
+#endif
+
+ callGraph = this.ComputeCallGraph(program);
+ assert this.procedureImplementations != null;
+ Cci.IRelation! procedureImplementations = this.procedureImplementations;
+
+#if NOT_YET
+ IEnumerable/*<IStronglyConnectedComponent>*/ sccs =
+ StronglyConnectedComponent.ConstructSCCs(publicImpls, callGraph);
+
+ IList/*<IStronglyConnectedComponent>*/ sortedSccs =
+ GraphUtil.TopologicallySortComponentGraph(sccs);
+
+ // Go bottom-up through the SCCs of the call graph
+ foreach (IStronglyConnectedComponent scc in sortedSccs)
+ {
+ this.ComputeSccInvariants(scc.Nodes);
+ }
+#endif
+ AI.Lattice.Element! initialElement = this.lattice.Top;
+ // 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 = (!) workItem.Proc.Summary[workItem.Index];
+
+ if (((!) procedureImplementations.GetValues(workItem.Proc)).Count == 0)
+ {
+ // 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 (!) procedureImplementations.GetValues(workItem.Proc))
+ {
+ // process each procedure implementation by recursively processing the first (entry) block...
+ ((!)impl.Blocks[0]).Lattice = lattice;
+ ComputeBlockInvariants(impl, (!) impl.Blocks[0], summaryEntry.OnEntry);
+
+ if (!CommandLineOptions.Clo.IntraproceduralInfer)
+ {
+ // 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)
+ {
+ atReturn = this.lattice.Eliminate(atReturn, var);
+ }
+ foreach (Variable! var in impl.InParams)
+ {
+ 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)
+ {
+ this.callReturnWorkItems.Enqueue(callSite);
+ }
+ }
+ }
+ }
+ }
+ }
+
+
+ while (this.callReturnWorkItems.Count > 0)
+ {
+ CallSite callSite = (CallSite!) this.callReturnWorkItems.Dequeue();
+
+ PropagateStartingAtStatement( callSite.Impl, callSite.Block, callSite.Statement, callSite.KnownBeforeCall);
+ }
+
+
+ } // both queues
+
+ }
+
+ private static int freshVarId = 0;
+ private static Variable! FreshVar(Boogie.Type! ty)
+ {
+ 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)
+ {
+ assume log.IsPeerConsistent;
+ 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 = (!) block.Cmds[cmdIndex]; // Fetch the command
+ currentValue = Step(cmd, currentValue, impl, // Apply the transition function
+ delegate (AI.Lattice.Element! currentValue)
+ {
+ return new CallSite(impl, block, cmdIndex, currentValue);
+ }
+ );
+ }
+
+ block.PostInvariant = currentValue; // The invariant at the exit point of the block is that of the last statement
+
+ log.DbgMsg(string.Format("pre {0}", ((!)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.
+ assume @goto.labelTargets != null;
+
+ // For all the successors of this block, propagate the abstract state
+ foreach (Block! succ in @goto.labelTargets)
+ {
+ 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);
+ }
+ }
+ }
+ #endregion
+ }
+
+ /// <summary>
+ /// The abstract transition relation.
+ /// </summary>
+ private AI.Lattice.Element! Step(Cmd! cmd, AI.Lattice.Element! pre, Implementation! impl, MarkCallSite/*?*/ callSiteMarker)
+ {
+ assume log.IsPeerConsistent;
+ log.DbgMsg(string.Format("{0}", cmd)); log.DbgMsgIndent();
+
+ AI.Lattice.Element! currentValue = pre;
+
+ // Case split...
+ #region AssignCmd
+ if (cmd is AssignCmd) { // parallel assignment
+ // we first eliminate map assignments
+ AssignCmd! assmt = ((AssignCmd)cmd).AsSimpleAssignCmd;
+ //PM: Assume variables have been resolved
+ assume forall {AssignLhs! lhs in assmt.Lhss;
+ lhs.DeepAssignedVariable != null};
+
+ List<IdentifierExpr!>! freshLhs = new List<IdentifierExpr!> ();
+ foreach (AssignLhs! lhs in assmt.Lhss)
+ freshLhs.Add(Expr.Ident(FreshVar(((!)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)
+ currentValue =
+ this.lattice.Eliminate(currentValue, (!)lhs.DeepAssignedVariable);
+ for (int i = 0; i < freshLhs.Count; ++i)
+ currentValue =
+ this.lattice.Rename(currentValue, (!)freshLhs[i].Decl,
+ (!)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)
+ {
+ currentValue = this.lattice.Eliminate(currentValue, (!)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 = (!)((PredicateCmd)cmd).Expr;
+ List<Expr!>! conjuncts = flatConjunction(embeddedExpr); // Handle "assume P && Q" as if it was "assume P; assume Q"
+ foreach(Expr! c in conjuncts) {
+ 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) { currentValue = Step(callDesug, currentValue, impl, null); }
+
+ // Now, project out the local variables
+ foreach (Variable! local in statecmd.Locals) { 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) { currentValue = Step(callDesug, currentValue, impl, null); }
+ // Now, project out the local variables
+ foreach (Variable! local in statecmd.Locals) { currentValue = this.lattice.Eliminate(currentValue, local); }
+ } else {
+ currentValue = Step(desugaring, currentValue, impl, null);
+ }
+ }
+ else
+ {
+ assert false; // unknown command
+ }
+
+ log.DbgMsgUnindent();
+
+ return currentValue;
+ }
+
+ /// <summary>
+ /// Flat an expresion in the form P AND Q ... AND R into a list [P, Q, ..., R]
+ /// </summary>
+ private List<Expr!>! flatConjunction(Expr! embeddedExpr)
+ {
+ List<Expr!>! 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)
+ {
+ List<Expr!>! 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)
+ {
+ if (block.PreInvariant == null) // block has not yet been processed
+ {
+ assert block.PostInvariant == null;
+
+ // To a first approximation the block is unreachable
+ block.PreInvariant = this.lattice.Bottom;
+ block.PostInvariant = this.lattice.Bottom;
+ }
+
+ assert block.PreInvariant != null;
+ 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, (!) block.PreInvariant.Clone());
+ #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
+
+
+ /// <summary>
+ /// Analyze the given set of blocks.
+ /// <param name="blocks"> The set of blocks to analyze </param>
+ /// <param name="entryPoint"> The initial block (from where we start the analysis </param>
+ /// <param name="initialState"> The initial abstract state </param>
+ /// </summary>
+ public void AnalyzeBlocks(ICollection<Block!>! blocks, Block! entryPoint, AI.MathematicalLattice.Element! initialState)
+ requires blocks.Contains(entryPoint);
+ {
+ TypeVariableSeq! dummyVarSeq = new TypeVariableSeq();
+ VariableSeq! dummySeq = new VariableSeq();
+ List<Block!> blockSequence = new List<Block!>();
+
+ foreach(Block! block in blocks) {
+ blockSequence.Add(block);
+ }
+
+ Implementation dummyImplementation =
+ new Implementation(Token.NoToken, "dummyImplementation", dummyVarSeq, dummySeq, dummySeq, dummySeq, blockSequence);
+
+ ComputeBlockInvariants(dummyImplementation, entryPoint, initialState);
+ }
+
+ } // 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()
+ {
+ AI.IQuantPropExprFactory 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);
+
+ 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()
+ {
+ AbstractAlgebra! retAlgebra;
+
+ AI.Lattice! returnLattice;
+
+ AI.IQuantPropExprFactory 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.IQuantPropExprFactory 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;
+
+ public AI.Lattice! Lattice
+ {
+ get
+ {
+ return lattice;
+ }
+ }
+
+ public AI.IQuantPropExprFactory 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.IQuantPropExprFactory propFactory,
+ AI.ILinearExprFactory linearFactory,
+ AI.IIntExprFactory intFactory,
+ AI.IValueExprFactory valueFactory,
+ AI.INullnessFactory nullFactory,
+ IComparer variableComparer)
+ requires propFactory != null ==> Owner.Same(lattice, propFactory);
+ requires linearFactory != null ==> Owner.Same(lattice, linearFactory);
+ requires intFactory != null ==> Owner.Same(lattice, intFactory);
+ requires valueFactory != null ==> Owner.Same(lattice, valueFactory);
+ requires nullFactory != null ==> Owner.Same(lattice, nullFactory);
+ requires variableComparer != null ==> Owner.Same(lattice, variableComparer);
+ // ensures Owner.Same(this, lattice); // KRML:
+ {
+ 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)
+ {
+ 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.Now;
+ }
+
+ WidenPoints.Compute(program);
+
+ if (CommandLineOptions.Clo.Ai.AnySet) // if there is some user defined domain we override the default (= intervals)
+ {
+ AI.Lattice! lattice;
+
+ lattice = AbstractDomainBuilder.BuildAbstractDomain().Lattice;
+
+ ApplyAbstractInterpretation(program, lattice);
+
+ if (CommandLineOptions.Clo.Ai.DebugStatistics)
+ {
+ Console.Error.WriteLine(lattice);
+ }
+
+ if (!CommandLineOptions.Clo.IntraproceduralInfer)
+ {
+ Procedure.ShowSummaries = true;
+ }
+ }
+ else // Otherwise the default is the use of the abstract domain of intervals (useful for simple for loops)
+ {
+ AI.Lattice! lattice = AbstractDomainBuilder.BuildIntervalsAbstractDomain().Lattice;
+ ApplyAbstractInterpretation(program, lattice);
+ }
+
+ program.InstrumentWithInvariants();
+
+ if (CommandLineOptions.Clo.Trace) {
+ DateTime end = DateTime.Now;
+ TimeSpan elapsed = end - start;
+ Console.WriteLine(" [{0} s]", elapsed.TotalSeconds);
+ Console.Out.Flush();
+ }
+ }
+ }
+
+ static void ApplyAbstractInterpretation (Program! program, AI.Lattice! lattice)
+ {
+ AbstractionEngine engine = new AbstractionEngine(lattice);
+ engine.ComputeProgramInvariants(program);
+ callGraph = engine.CallGraph;
+ }
+ private static Cci.IGraphNavigator callGraph;
+ public static Cci.IGraphNavigator CallGraph {
+ get { return callGraph; }
+ }
+
+
+}
+
+} // namespace
diff --git a/Source/AbsInt/ExprFactories.ssc b/Source/AbsInt/ExprFactories.ssc
new file mode 100644
index 00000000..1569c36c
--- /dev/null
+++ b/Source/AbsInt/ExprFactories.ssc
@@ -0,0 +1,233 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using Microsoft.Boogie;
+using AI = Microsoft.AbstractInterpretationFramework;
+using Microsoft.Contracts;
+using Microsoft.Basetypes;
+
+namespace Microsoft.Boogie.AbstractInterpretation {
+
+ public class BoogiePropFactory : BoogieFactory, AI.IQuantPropExprFactory
+ {
+ public AI.IFunApp! False {
+ get {
+
+ return Expr.False;
+ }
+ }
+ public AI.IFunApp! True {
+ get {
+ return Expr.True;
+ }
+ }
+
+ public AI.IFunApp! Not(AI.IExpr! p) {
+ return Expr.Unary(Token.NoToken, UnaryOperator.Opcode.Not, IExpr2Expr(p));
+ }
+
+ public AI.IFunApp! And(AI.IExpr! p, AI.IExpr! q) {
+ return Expr.Binary(BinaryOperator.Opcode.And, IExpr2Expr(p), IExpr2Expr(q));
+ }
+
+ public AI.IFunApp! Or(AI.IExpr! p, AI.IExpr! q) {
+ return Expr.Binary(BinaryOperator.Opcode.Or, IExpr2Expr(p), IExpr2Expr(q));
+ }
+
+ public AI.IFunApp! Implies(AI.IExpr! p, AI.IExpr! q) {
+ return Expr.Binary(BinaryOperator.Opcode.Imp, IExpr2Expr(p), IExpr2Expr(q));
+ }
+
+ public AI.IFunApp! Exists(AI.IFunction! p) {
+ return (AI.IFunApp)(new ExistsExpr(Token.NoToken, new VariableSeq((Variable)p.Param), IExpr2Expr(p.Body))).IExpr;
+ }
+ public AI.IFunApp! Exists(AI.AIType paramType, AI.FunctionBody! bodygen) {
+ // generate a fresh new variable
+ Variable! var = FreshBoundVariable(paramType);
+ Expr! expr = IExpr2Expr(bodygen(var));
+ return (AI.IFunApp)(new ExistsExpr(Token.NoToken, new VariableSeq(var), expr)).IExpr;
+ }
+
+ public AI.IFunApp! Forall(AI.IFunction! p) {
+ return (AI.IFunApp)(new ForallExpr(Token.NoToken, new VariableSeq((Variable)p.Param), IExpr2Expr(p.Body))).IExpr;
+ }
+ public AI.IFunApp! Forall(AI.AIType paramType, AI.FunctionBody! bodygen) {
+ // generate a fresh new variable
+ Variable! var = FreshBoundVariable(paramType);
+ Expr! expr = IExpr2Expr(bodygen(var));
+ return (AI.IFunApp)(new ForallExpr(Token.NoToken, new VariableSeq(var), expr)).IExpr;
+ }
+
+ private static int freshVarNum = 0;
+ private static Variable! FreshBoundVariable(AI.AIType paramType)
+ {
+ // TODO: Should use the AI.AIType given in Exists and Forall to determine what Boogie type
+ // to make this new variable? For now, we use Type.Any.
+ Type! t = Type.Int;
+ /*
+ if (paramType is AI.Ref)
+ t = Type.Ref;
+ else if (paramType is AI.FieldName)
+ t = Type.Name;
+ else
+ System.Console.WriteLine("*** unsupported type in AI {0}", paramType); */
+ assert false;
+ TypedIdent id = new TypedIdent(Token.NoToken, "propfactory_freshvar" + freshVarNum, t);
+ freshVarNum++;
+ return new BoundVariable(Token.NoToken, id);
+ }
+ }
+
+ public class BoogieValueFactory : BoogieFactory, AI.IValueExprFactory
+ {
+ public AI.IFunApp! Eq(AI.IExpr! e0, AI.IExpr! e1) {
+ return Expr.Eq(IExpr2Expr(e0), IExpr2Expr(e1));
+ }
+ public AI.IFunApp! Neq(AI.IExpr! e0, AI.IExpr! e1) {
+ return Expr.Neq(IExpr2Expr(e0), IExpr2Expr(e1));
+ }
+ }
+
+ public class BoogieNullnessFactory : BoogieFactory, AI.INullnessFactory
+ {
+ public AI.IFunApp! Eq(AI.IExpr! e0, AI.IExpr! e1) {
+ return Expr.Eq(IExpr2Expr(e0), IExpr2Expr(e1));
+ }
+
+ public AI.IFunApp! Neq(AI.IExpr! e0, AI.IExpr! e1) {
+ return Expr.Neq(IExpr2Expr(e0), IExpr2Expr(e1));
+ }
+
+ public AI.IFunApp! Null {
+ get {
+ assert false; // don't know where to get null from
+ }
+ }
+ }
+
+ public class BoogieIntFactory : BoogieValueFactory, AI.IIntExprFactory {
+ public AI.IFunApp! Const(BigNum i) {
+ return new LiteralExpr(Token.NoToken, i);
+ }
+ }
+
+ public class BoogieLinearFactory : BoogieIntFactory, AI.ILinearExprFactory {
+ public AI.IFunApp! AtMost(AI.IExpr! e0, AI.IExpr! e1) {
+ return Expr.Le(IExpr2Expr(e0), IExpr2Expr(e1));
+ }
+ public AI.IFunApp! Add(AI.IExpr! e0, AI.IExpr! e1) {
+ return Expr.Add(IExpr2Expr(e0), IExpr2Expr(e1));
+ }
+ public AI.IExpr! Term(Rational r, AI.IVariable var) {
+ 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 {
+ return Expr.False;
+ }
+ }
+ public AI.IFunApp! True {
+ get {
+ return Expr.True;
+ }
+ }
+ public AI.IFunApp! And(AI.IExpr! p, AI.IExpr! q) {
+ 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 {
+ assert false; // BUGBUG: TODO
+ throw new System.NotImplementedException();
+ }
+ }
+
+ /// <summary>
+ /// Returns true iff "t" denotes a type constant.
+ /// </summary>
+ [Pure][Reads(ReadsAttribute.Reads.Owned)]
+ public bool IsTypeConstant(AI.IExpr! t)
+ ensures result == (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][Reads(ReadsAttribute.Reads.Owned)]
+ public bool IsTypeEqual(AI.IExpr! t0, AI.IExpr! t1) {
+ 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][Reads(ReadsAttribute.Reads.Owned)]
+ public bool IsSubType(AI.IExpr! t0, AI.IExpr! t1) {
+ assert false; // BUGBUG: TODO
+ return false;
+ }
+
+ /// <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) {
+ assert false; // BUGBUG: TODO
+ throw new System.NotImplementedException();
+ }
+
+ 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.
+ assume type is Constant;
+ Constant theType = (Constant)type;
+ assert false;
+ 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) {
+ //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.
+ assume type is Constant;
+ assert false;
+ 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/LoopInvariantsOnDemand.ssc b/Source/AbsInt/LoopInvariantsOnDemand.ssc
new file mode 100644
index 00000000..1ebd11b2
--- /dev/null
+++ b/Source/AbsInt/LoopInvariantsOnDemand.ssc
@@ -0,0 +1,78 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+namespace Microsoft.Boogie.AbstractInterpretation
+{
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using Microsoft.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;
+ public List<AI.IVariable!>! FreeVariables
+ {
+ get
+ {
+ 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);
+
+ 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
+ {
+ assert false;
+ }
+ }
+
+ public override object VisitFunApp(AI.IFunApp! funapp)
+ {
+ foreach (AI.IExpr! arg in funapp.Arguments)
+ {
+ arg.DoVisit(this);
+ }
+ return true;
+ }
+
+ public override object VisitFunction(AI.IFunction! fun)
+ {
+ fun.Body.DoVisit(this);
+ this.variables.Remove(fun.Param);
+ return true;
+ }
+
+ }
+
+} \ No newline at end of file
diff --git a/Source/AbsInt/Traverse.ssc b/Source/AbsInt/Traverse.ssc
new file mode 100644
index 00000000..694811da
--- /dev/null
+++ b/Source/AbsInt/Traverse.ssc
@@ -0,0 +1,182 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+namespace Microsoft.Boogie
+{
+ using System;
+ using System.Collections.Generic;
+ using Microsoft.Contracts;
+
+ /// <summary>
+ /// This class provides the functionality of traversing a program to determine which
+ /// blocks are blocks where the widening operator may need to be applied. Assumes
+ /// all 'currentlyTraversed' bits to be initially false, and leaves them that way in
+ /// the end. Assumes the 'widenBlock' bits are initially false, and sets them
+ /// appropriately.
+ /// </summary>
+ public class WidenPoints
+ {
+ /// <summary>
+ /// Compute the widen points of a program
+ /// </summary>
+ public static void Compute(Program! program)
+ {
+ expose (program)
+ {
+ foreach (Declaration m in program.TopLevelDeclarations)
+ {
+ Implementation impl = m as Implementation;
+ if (impl != null)
+ {
+ if (impl.Blocks != null && impl.Blocks.Count > 0)
+ {
+ assume impl.IsConsistent;
+ expose (impl) {
+ Block start = impl.Blocks[0];
+ assume start != null;
+ assume start.IsConsistent;
+ Visit(start);
+
+ // We reset the state...
+ foreach(Block b in impl.Blocks) {
+ expose (b) {
+ b.TraversingStatus = Block.VisitState.ToVisit;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ static void Visit(Block! b)
+ {
+ assume b.IsExposable;
+ if (b.TraversingStatus == Block.VisitState.BeingVisited)
+ {
+ expose (b)
+ {
+ // we got here through a back-edge
+ b.widenBlock = true;
+ }
+ }
+ else if(b.TraversingStatus == Block.VisitState.AlreadyVisited)
+ {
+ // do nothing... we already saw this node
+ }
+ else if (b.TransferCmd is GotoCmd)
+ {
+ assert b.TraversingStatus == Block.VisitState.ToVisit;
+
+ GotoCmd g = (GotoCmd)b.TransferCmd;
+ expose (b)
+ {
+ expose (g) { //PM: required for the subsequent expose (g.labelTargets)
+ b.TraversingStatus = Block.VisitState.BeingVisited;
+
+ // labelTargets is made non-null by Resolve, which we assume
+ // has already called in a prior pass.
+ assume g.labelTargets != null;
+ expose (g.labelTargets) {
+ foreach (Block succ in g.labelTargets)
+// invariant b.currentlyTraversed;
+ //PM: The following loop invariant will work once properties are axiomatized
+ //&& (g.labelNames != null && g.labelTargets != null ==> g.labelNames.Length == g.labelTargets.Length);
+ {
+ assert succ != null;
+ Visit(succ);
+ }
+ }
+
+ assert b.TraversingStatus == Block.VisitState.BeingVisited;
+// System.Diagnostics.Debug.Assert(b.currentlyTraversed);
+
+ b.TraversingStatus = Block.VisitState.AlreadyVisited;
+
+ //PM: The folowing assumption is needed because we cannot prove that a simple field update
+ //PM: leaves the value of a property unchanged.
+ assume (g.labelNames != null ==> g.labelNames.Length == g.labelTargets.Length);
+ }
+ }
+ }
+ else
+ {
+ assert b.TransferCmd == null || b.TransferCmd is ReturnCmd; // It must be a returnCmd;
+ }
+ }
+
+ static private Block rootBlock = null; // The root point we have to consider
+
+ /// <summary>
+ /// Compute the blocks in the body loop.
+ /// <param name ="block"> Tt is the head of the loop. It must be a widen block </param>
+ /// <return> The blocks that are in the loop from block </return>
+ /// </summary>
+ public static List<Block!> ComputeLoopBodyFrom(Block! block)
+ requires block.widenBlock;
+ {
+ assert rootBlock == null;
+ rootBlock = block;
+
+ List<Block!> blocksInLoop = new List<Block!>(); // We use a list just because .net does not define a set
+ List<Block!> visitingPath = new List<Block!>(); // The order is important, as we want paths
+
+ blocksInLoop.Add(block);
+
+ DoDFSVisit(block, visitingPath, blocksInLoop);
+
+ visitingPath.Add(block);
+
+
+ rootBlock = null; // We reset the invariant
+
+ return blocksInLoop;
+ }
+
+ /// <summary>
+ /// Perform the Depth-first search of the so to find the loop
+ /// <param name = "block"> The block to visit </param>
+ /// <param name = "path"> The path we are visiting so far </param>
+ /// </summary>
+ private static void DoDFSVisit(Block! block, List<Block!>! path, List<Block!>! blocksInPath)
+ {
+ #region case 1. We visit the root => We are done, "path" is a path inside the loop
+ if(block == rootBlock && path.Count > 1)
+ {
+ blocksInPath.AddRange(path); // Add all the blocks in this path
+ }
+
+ #endregion
+ #region case 2. We visit a node that ends with a return => "path" is not inside the loop
+ if(block.TransferCmd is ReturnCmd)
+ {
+ return;
+ }
+ #endregion
+ #region case 3. We visit a node with successors => continue the exploration of its successors
+ {
+ assert block.TransferCmd is GotoCmd;
+ GotoCmd! successors = (GotoCmd) block.TransferCmd;
+
+ if (successors.labelTargets != null)
+ foreach (Block! nextBlock in successors.labelTargets)
+ {
+ if(path.Contains(nextBlock)) // If the current path has already seen the block, just skip it
+ continue;
+ // Otherwise we perform the DFS visit
+ path.Add(nextBlock);
+ DoDFSVisit(nextBlock, path, blocksInPath);
+
+ assert nextBlock == path[path.Count-1];
+ path.RemoveAt(path.Count-1);
+ }
+
+ }
+
+ #endregion
+ }
+ }
+}
diff --git a/Source/Basetypes/Basetypes.sscproj b/Source/Basetypes/Basetypes.sscproj
new file mode 100644
index 00000000..4c3e3cb6
--- /dev/null
+++ b/Source/Basetypes/Basetypes.sscproj
@@ -0,0 +1,103 @@
+<?xml version="1.0" encoding="utf-8"?>
+<VisualStudioProject>
+ <XEN ProjectType="Local"
+ SchemaVersion="1.0"
+ Name="Basetypes"
+ ProjectGuid="0c692837-77ec-415f-bf04-395e3ed06e9a"
+ >
+ <Build>
+ <Settings ApplicationIcon=""
+ AssemblyName="Basetypes"
+ OutputType="Library"
+ RootNamespace="Basetypes"
+ StartupObject=""
+ StandardLibraryLocation=""
+ TargetPlatform="v2"
+ TargetPlatformLocation=""
+ >
+ <Config Name="Debug"
+ AllowUnsafeBlocks="False"
+ BaseAddress="285212672"
+ CheckForOverflowUnderflow="False"
+ ConfigurationOverrideFile=""
+ DefineConstants="DEBUG;TRACE"
+ DocumentationFile=""
+ DebugSymbols="True"
+ FileAlignment="4096"
+ IncrementalBuild="True"
+ Optimize="False"
+ OutputPath="bin\debug"
+ RegisterForComInterop="False"
+ RemoveIntegerChecks="false"
+ TreatWarningsAsErrors="False"
+ WarningLevel="4"
+ CheckContractAdmissibility="True"
+ CheckPurity="False"
+ />
+ <Config Name="Release"
+ AllowUnsafeBlocks="false"
+ BaseAddress="285212672"
+ CheckForOverflowUnderflow="false"
+ ConfigurationOverrideFile=""
+ DefineConstants="TRACE"
+ DocumentationFile=""
+ DebugSymbols="false"
+ FileAlignment="4096"
+ IncrementalBuild="false"
+ Optimize="true"
+ OutputPath="bin\release"
+ RegisterForComInterop="false"
+ RemoveIntegerChecks="false"
+ TreatWarningsAsErrors="false"
+ WarningLevel="4"
+ CheckContractAdmissibility="True"
+ CheckPurity="False"
+ />
+ </Settings>
+ <References>
+ <Reference Name="System"
+ AssemblyName="System"
+ Private="false"
+ />
+ <Reference Name="System.Data"
+ AssemblyName="System.Data"
+ Private="false"
+ />
+ <Reference Name="System.Xml"
+ AssemblyName="System.Xml"
+ Private="false"
+ />
+ <Reference Name="FSharp.Core"
+ AssemblyName="FSharp.Core"
+ Private="false"
+ HintPath="../../Binaries/FSharp.Core.dll"
+ />
+ <Reference Name="FSharp.PowerPack"
+ AssemblyName="FSharp.PowerPack"
+ Private="false"
+ HintPath="../../Binaries/FSharp.PowerPack.dll"
+ />
+ </References>
+ </Build>
+ <Files>
+ <Include>
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="BigNum.ssc"
+ />
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="Rational.ssc"
+ />
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="..\version.ssc"
+ />
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="Set.ssc"
+ />
+ </Include>
+ </Files>
+ </XEN>
+</VisualStudioProject> \ No newline at end of file
diff --git a/Source/Basetypes/BigNum.ssc b/Source/Basetypes/BigNum.ssc
new file mode 100644
index 00000000..0bf52290
--- /dev/null
+++ b/Source/Basetypes/BigNum.ssc
@@ -0,0 +1,341 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using System;
+using System.Text;
+
+
+namespace Microsoft.Basetypes {
+ using Microsoft.Contracts;
+ using BIM = Microsoft.FSharp.Math.BigInt;
+
+ /// <summary>
+ /// A thin wrapper around Microsoft.FSharp.Math.BigInt
+ /// (to be able to define equality, etc. properly)
+ /// </summary>
+ public struct BigNum {
+
+ // the internal representation
+ [Rep] internal readonly Microsoft.FSharp.Math.BigInt val;
+
+ public static readonly BigNum ZERO = new BigNum (BIM.Zero);
+ public static readonly BigNum ONE = new BigNum (BIM.One);
+ public static readonly BigNum MINUS_ONE = new BigNum (-BIM.One);
+
+ [Pure]
+ public static BigNum FromInt(int v) {
+ return new BigNum(new BIM(v));
+ }
+
+ [Pure]
+ public static BigNum FromUInt(uint v) {
+ return new BigNum(new BIM((long)v));
+ }
+
+ [Pure]
+ public static BigNum FromLong(long v) {
+ return new BigNum(new BIM(v));
+ }
+
+ [Pure]
+ public static BigNum FromBigInt(Microsoft.FSharp.Math.BigInt v) {
+ return new BigNum(v);
+ }
+
+ [Pure]
+ public static BigNum FromULong(ulong v) {
+ return FromString("" + v);
+ }
+
+ [Pure]
+ public static BigNum FromString(string v) {
+ try {
+ return new BigNum(BIM.Parse(v));
+ } catch (System.ArgumentException) {
+ throw new FormatException();
+ }
+ }
+
+ public static bool TryParse(string v, out BigNum res) {
+ try {
+ res = BigNum.FromString(v);
+ return true;
+ } catch (FormatException) {
+ res = ZERO;
+ return false;
+ }
+ }
+
+ // Convert to int, without checking whether overflows occur
+ public int ToInt {
+ get {
+ return BIM.ToInt32(val);
+ }
+ }
+
+ // Convert to int; assert that no overflows occur
+ public int ToIntSafe {
+ get {
+ assert this.InInt32;
+ return this.ToInt;
+ }
+ }
+
+ public Rational ToRational {
+ get {
+ return new Rational (this, BigNum.ONE);
+ }
+ }
+
+ internal BigNum(Microsoft.FSharp.Math.BigInt val) {
+ this.val = val;
+ }
+
+ public static bool operator==(BigNum x, BigNum y) {
+ return (x.val == y.val);
+ }
+
+ public static bool operator!=(BigNum x, BigNum y) {
+ return !(x.val == y.val);
+ }
+
+ [Pure][Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals(object obj) {
+ if (obj == null) return false;
+ if (!(obj is BigNum)) return false;
+
+ BigNum other = (BigNum)obj;
+ return (this.val == other.val);
+ }
+
+ [Pure]
+ public override int GetHashCode() {
+ return this.val.GetHashCode();
+ }
+
+ [Pure]
+ public override string! ToString() {
+ return (!)val.ToString();
+ }
+
+ //////////////////////////////////////////////////////////////////////////////
+ // Very limited support for format strings
+ // Note: Negative integers are linearised with a minus "-" in hexadecimal,
+ // not in 2-complement notation (in contrast to what the method
+ // int32.ToString(format) does)
+
+ [Pure]
+ public string! ToString(string! format) {
+ if (format.StartsWith("d") || format.StartsWith("D")) {
+ string! res = this.Abs.ToString();
+ return addMinus(this.Signum,
+ prefixWithZeros(extractPrecision(format), res));
+ } else if (format.StartsWith("x") || format.StartsWith("X")) {
+ string! res = this.toHex(format.Substring(0, 1));
+ return addMinus(this.Signum,
+ prefixWithZeros(extractPrecision(format), res));
+ } else {
+ throw new FormatException("Format " + format + " is not supported");
+ }
+ }
+
+ private static readonly Microsoft.FSharp.Math.BigInt BI_2_TO_24 = new BIM(0x1000000);
+
+ [Pure]
+ private string! toHex(string! format) {
+ string! res = "";
+ Microsoft.FSharp.Math.BigInt rem = this.Abs.val;
+
+ while (rem > BIM.Zero) {
+ res = BIM.ToInt32(rem %BI_2_TO_24).ToString(format) + res;
+ rem = rem / BI_2_TO_24;
+ }
+
+ return res;
+ }
+
+ [Pure]
+ private int extractPrecision(string! format) {
+ if (format.Length > 1)
+ // will throw a FormatException if the precision is invalid;
+ // that is ok
+ return Int32.Parse(format.Substring(1));
+ // always output at least one digit
+ return 1;
+ }
+
+ [Pure]
+ private string! addMinus(int signum, string! suffix) {
+ if (signum < 0)
+ return "-" + suffix;
+ return suffix;
+ }
+
+ [Pure]
+ private string! prefixWithZeros(int minLength, string! suffix) {
+ StringBuilder res = new StringBuilder();
+ while (res.Length + suffix.Length < minLength)
+ res.Append("0");
+ res.Append(suffix);
+ return res.ToString();
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Basic arithmetic operations
+
+ public BigNum Abs {
+ get {
+ return new BigNum(BIM.Abs(this.val));
+ }
+ }
+
+ public BigNum Neg {
+ get {
+ return new BigNum(-this.val);
+ }
+ }
+
+ [Pure]
+ public static BigNum operator-(BigNum x) {
+ return x.Neg;
+ }
+
+ [Pure]
+ public static BigNum operator+(BigNum x, BigNum y) {
+ return new BigNum(x.val + y.val);
+ }
+
+ [Pure]
+ public static BigNum operator-(BigNum x, BigNum y) {
+ return new BigNum(x.val - y.val);
+ }
+
+ [Pure]
+ public static BigNum operator*(BigNum x, BigNum y) {
+ return new BigNum(x.val * y.val);
+ }
+
+ // TODO: check that this has a proper semantics (which? :-))
+ [Pure]
+ public static BigNum operator/(BigNum x, BigNum y) {
+ return new BigNum(x.val / y.val);
+ }
+
+ // TODO: check that this has a proper semantics (which? :-))
+ [Pure]
+ public static BigNum operator%(BigNum x, BigNum y) {
+ return new BigNum(x.val - ((x.val / y.val) * y.val));
+ }
+
+ [Pure]
+ public BigNum Min(BigNum that) {
+ return new BigNum(this.val <= that.val ? this.val : that.val);
+ }
+
+ [Pure]
+ public BigNum Max(BigNum that) {
+ return new BigNum(this.val >= that.val ? this.val : that.val);
+ }
+
+ /// <summary>
+ /// Returns the greatest common divisor of this and _y.
+ /// </summary>
+ /// <param name="_y"></param>
+ /// <returns></returns>
+ public BigNum Gcd(BigNum _y)
+ ensures !result.IsNegative;
+ {
+ BigNum x = this.Abs;
+ BigNum y = _y.Abs;
+
+ while (true)
+ {
+ if (x < y)
+ {
+ y = y % x;
+ if (y.IsZero)
+ {
+ return x;
+ }
+ }
+ else
+ {
+ x = x % y;
+ if (x.IsZero)
+ {
+ return y;
+ }
+ }
+ }
+ return ZERO; // make compiler shut up
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Some basic comparison operations
+
+ public int Signum {
+ get {
+ return this.val.Sign;
+ }
+ }
+
+ public bool IsPositive {
+ get {
+ return (this.val > BIM.Zero);
+ }
+ }
+
+ public bool IsNegative {
+ get {
+ return (this.val < BIM.Zero);
+ }
+ }
+
+ public bool IsZero {
+ get {
+ return this.val.IsZero;
+ }
+ }
+
+ [Pure]
+ public int CompareTo(BigNum that) {
+ if (this.val == that.val) return 0;
+ if (this.val < that.val) return -1;
+ return 1;
+ }
+
+ [Pure]
+ public static bool operator<(BigNum x, BigNum y) {
+ return (x.val < y.val);
+ }
+
+ [Pure]
+ public static bool operator>(BigNum x, BigNum y) {
+ return (x.val > y.val);
+ }
+
+ [Pure]
+ public static bool operator<=(BigNum x, BigNum y) {
+ return (x.val <= y.val);
+ }
+
+ [Pure]
+ public static bool operator>=(BigNum x, BigNum y) {
+ return (x.val >= y.val);
+ }
+
+
+ private static readonly Microsoft.FSharp.Math.BigInt MaxInt32 =
+ new BIM(Int32.MaxValue);
+ private static readonly Microsoft.FSharp.Math.BigInt MinInt32 =
+ new BIM(Int32.MinValue);
+
+ public bool InInt32 {
+ get {
+ return (val >= MinInt32) && (val <= MaxInt32);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Source/Basetypes/Rational.ssc b/Source/Basetypes/Rational.ssc
new file mode 100644
index 00000000..08485cdc
--- /dev/null
+++ b/Source/Basetypes/Rational.ssc
@@ -0,0 +1,300 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using System;
+using Microsoft.Contracts;
+
+namespace Microsoft.Basetypes
+{
+ using BNM = Microsoft.FSharp.Math.BigNum;
+
+ /// <summary>
+ /// The representation of a rational number.
+ /// </summary>
+ public struct Rational
+ {
+ public static readonly Rational ZERO = new Rational ((!)BNM.Zero);
+ public static readonly Rational ONE = new Rational ((!)BNM.One);
+ public static readonly Rational MINUS_ONE = new Rational ((!)(-BNM.One));
+
+ private readonly Microsoft.FSharp.Math.BigNum _val;
+
+ private Microsoft.FSharp.Math.BigNum! val {
+ get {
+ if (_val == null)
+ return (!)BNM.Zero;
+ else
+ return _val;
+ }
+ }
+
+
+ // int numerator;
+ // int denominator;
+
+
+ // invariant: 0 < denominator || (numerator == 0 && denominator == 0);
+ // invariant: numerator != 0 ==> gcd(abs(numerator),denominator) == 1;
+ // invariant: numerator == 0 ==> denominator == 1 || denominator == 0;
+
+ private Rational(int x)
+ {
+ this._val = BNM.FromInt(x);
+ }
+
+ public static Rational FromInt(int x) {
+ return new Rational(x);
+ }
+
+ private Rational(Microsoft.FSharp.Math.BigNum! val) {
+ this._val = val;
+ }
+
+ public Rational(BigNum num, BigNum den) {
+ System.Diagnostics.Debug.Assert(!den.IsZero);
+
+ this._val = BNM.FromBigInt(num.val) / BNM.FromBigInt(den.val);
+ }
+
+ public static Rational FromInts(int num, int den) {
+ return new Rational(BigNum.FromInt(num), BigNum.FromInt(den));
+ }
+
+ /// <summary>
+ /// Returns the absolute value of the rational.
+ /// </summary>
+ public Rational Abs()
+ ensures result.IsNonNegative;
+ {
+ if (IsNonNegative) {
+ return this;
+ } else {
+ return -this;
+ }
+ }
+
+ /// <summary>
+ /// Returns a rational whose numerator and denominator, resepctively, are the Gcd
+ /// of the numerators and denominators of r and s. If one of r and s is 0, the absolute
+ /// value of the other is returned. If both are 0, 1 is returned.
+ /// </summary>
+ public static Rational Gcd(Rational r, Rational s)
+ ensures result.IsPositive;
+ {
+ if (r.IsZero) {
+ if (s.IsZero) {
+ return ONE;
+ } else {
+ return s.Abs();
+ }
+ } else if (s.IsZero) {
+ return r.Abs();
+ } else {
+ return new Rational (r.Numerator.Gcd(s.Numerator),
+ r.Denominator.Gcd(s.Denominator));
+ }
+ }
+
+ public BigNum Numerator
+ {
+ get
+ {
+ // Better way to obtain the numerator?
+ // The FSharp library does not seem to offer any methods for this
+ string! lin = (!)val.ToString();
+ int i = lin.IndexOf('/');
+ if (i == -1)
+ return new BigNum(BNM.ToBigInt(this.val));
+ else
+ return BigNum.FromString(lin.Substring(0, i));
+ }
+ }
+
+ public BigNum Denominator
+ {
+ get
+ {
+ // Better way to obtain the numerator?
+ // The FSharp library does not seem to offer any methods for this
+ string! lin = (!)val.ToString();
+ int i = lin.IndexOf('/');
+ if (i == -1)
+ return BigNum.ONE;
+ else
+ return BigNum.FromString(lin.Substring(i+1));
+ }
+ }
+
+ public override string! ToString()
+ {
+ return String.Format("{0}/{1}", Numerator, Denominator);
+ }
+
+
+ public static bool operator==(Rational r, Rational s)
+ {
+ return (r.val == s.val);
+ }
+
+ public static bool operator!=(Rational r, Rational s)
+ {
+ return !(r.val == s.val);
+ }
+
+ public override bool Equals(object obj)
+ {
+ if (obj == null) return false;
+ return obj is Rational && (Rational)obj == this;
+ }
+
+ public override int GetHashCode()
+ {
+ return this.val.GetHashCode();
+ }
+
+ public int Signum {
+ get { return this.val.Sign; }
+ }
+
+ public bool IsZero
+ {
+ get
+ {
+ return Signum == 0;
+ }
+ }
+
+ public bool IsNonZero
+ {
+ get
+ {
+ return Signum != 0;
+ }
+ }
+
+ public bool IsIntegral
+ {
+ get
+ {
+ // better way?
+ return !((!)this.val.ToString()).Contains("/");
+ }
+ }
+
+
+ [Pure][Reads(ReadsAttribute.Reads.Nothing)]
+ public bool HasValue (int n) { return this == new Rational(n); }
+
+ /// <summary>
+ /// Returns the rational as an integer. Requires the rational to be integral.
+ /// </summary>
+ public int AsInteger
+ {
+ get
+ {
+ System.Diagnostics.Debug.Assert(this.IsIntegral);
+ return Numerator.ToIntSafe;
+ }
+ }
+
+ public BigNum AsBigNum {
+ get
+ {
+ System.Diagnostics.Debug.Assert(this.IsIntegral);
+ return new BigNum (BNM.ToBigInt(this.val));
+ }
+ }
+
+ public double AsDouble
+ {
+ [Pure]
+ get
+ {
+ if (this.IsZero)
+ {
+ return 0.0;
+ }
+ else
+ {
+ return (double)Numerator.ToIntSafe / (double)Denominator.ToIntSafe;
+ }
+ }
+ }
+
+ public bool IsNegative
+ {
+ [Pure]
+ get
+ {
+ return Signum < 0;
+ }
+ }
+
+ public bool IsPositive
+ {
+ [Pure]
+ get
+ {
+ return 0 < Signum;
+ }
+ }
+
+ public bool IsNonNegative
+ {
+ [Pure]
+ get
+ {
+ return 0 <= Signum;
+ }
+ }
+
+
+ public static Rational operator-(Rational r)
+ {
+ return new Rational ((!)(BNM.Zero -r.val)); // for whatever reason, the Spec# compiler refuses to accept -r.val (unary negation)
+ }
+
+
+ public static Rational operator+(Rational r, Rational s)
+ {
+ return new Rational ((!)(r.val + s.val));
+ }
+
+ public static Rational operator-(Rational r, Rational s)
+ {
+ return new Rational ((!)(r.val - s.val));
+ }
+
+ public static Rational operator*(Rational r, Rational s)
+ {
+ return new Rational ((!)(r.val * s.val));
+ }
+
+ public static Rational operator/(Rational r, Rational s)
+ {
+ return new Rational ((!)(r.val / s.val));
+ }
+
+ public static bool operator<=(Rational r, Rational s)
+ {
+ return (r.val <= s.val);
+ }
+
+ public static bool operator>=(Rational r, Rational s)
+ {
+ return (r.val >= s.val);
+ }
+
+ public static bool operator<(Rational r, Rational s)
+ {
+ return (r.val < s.val);
+ }
+
+ public static bool operator>(Rational r, Rational s)
+ {
+ return (r.val > s.val);
+ }
+ }
+}
diff --git a/Source/Basetypes/Set.ssc b/Source/Basetypes/Set.ssc
new file mode 100644
index 00000000..221a9ad4
--- /dev/null
+++ b/Source/Basetypes/Set.ssc
@@ -0,0 +1,282 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+namespace Microsoft.Boogie
+{
+ using System;
+ using System.IO;
+ using System.Collections;
+ using Microsoft.Contracts;
+
+ /// <summary>
+ /// A class representing a mathematical set.
+ /// </summary>
+ public class Set : ICloneable, IEnumerable
+ {
+ /*[Own]*/ Hashtable! ht;
+
+ public Set()
+ {
+ ht = new Hashtable();
+ base();
+ }
+
+ private Set(Hashtable! ht)
+ {
+ this.ht = ht;
+ base();
+ }
+
+ public Set(int capacity)
+ {
+ ht = new Hashtable(capacity);
+ base();
+ }
+
+
+ public readonly static Set! Empty = new Set();
+
+ public void Clear()
+ {
+ ht.Clear();
+ }
+
+ /// <summary>
+ /// This method idempotently adds "o" to the set.
+ /// In notation:
+ /// this.SetElements = this.SetElements_old \union {o};
+ /// </summary>
+ public void Add(object! o)
+ {
+ ht[o] = o;
+ }
+
+ /// <summary>
+ /// this.SetElements = this.SetElements_old \union s.SetElements;
+ /// </summary>
+ public void AddRange(Set! s)
+ {
+ foreach (object! o in s)
+ {
+ Add(o);
+ }
+ }
+
+ /// <summary>
+ /// this.SetElements = this.SetElements_old \setminus {o};
+ /// </summary>
+ public void Remove(object! o)
+ {
+ ht.Remove(o);
+ }
+
+ /// <summary>
+ /// this.SetElements = this.SetElements_old \setminus s.SetElements;
+ /// </summary>
+ public void RemoveRange(Set! s)
+ {
+ if (s == this)
+ {
+ ht.Clear();
+ }
+ else
+ {
+ foreach (object! o in s)
+ {
+ ht.Remove(o);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Returns an arbitrary element from the set.
+ /// </summary>
+ public object! Choose()
+ requires Count > 0;
+ {
+ IEnumerator iter = GetEnumerator();
+ iter.MoveNext();
+ return (!)iter.Current;
+ }
+
+ /// <summary>
+ /// Picks an arbitrary element from the set, removes it, and returns it.
+ /// </summary>
+ public object! Take()
+ requires Count > 0;
+ ensures Count == old(Count) - 1;
+ {
+ object r = Choose();
+ Remove(r);
+ return r;
+ }
+
+ public void Intersect(Set! s)
+ {
+ Hashtable h = new Hashtable(ht.Count);
+ foreach (object! key in ht.Keys)
+ {
+ if (s.ht.ContainsKey(key))
+ {
+ h.Add(key, key);
+ }
+ }
+ ht = h;
+ }
+
+ /// <summary>
+ /// The getter returns true iff "o" is in the set.
+ /// The setter adds the value "o" (for "true") or removes "o" (for "false")
+ /// </summary>
+ public bool this[object! o]
+ {
+ get
+ {
+ return ht.ContainsKey(o);
+ }
+ set
+ {
+ if (value) {
+ Add(o);
+ } else {
+ Remove(o);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Returns true iff "o" is an element of "this".
+ /// </summary>
+ /// <param name="o"></param>
+ /// <returns></returns>
+ [Pure]
+ public bool Contains(object! o)
+ {
+ if (!this.ht.ContainsKey(o))
+ {
+ return false;
+ }
+ return true;
+ }
+
+ /// <summary>
+ /// Returns true iff every element of "s" is an element of "this", that is, if
+ /// "s" is a subset of "this".
+ /// </summary>
+ /// <param name="s"></param>
+ /// <returns></returns>
+ public bool ContainsRange(Set! s)
+ {
+ if (s != this)
+ {
+ foreach (object! key in s.ht.Keys)
+ {
+ if (!this.ht.ContainsKey(key))
+ {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ public object! Clone()
+ {
+ return new Set((Hashtable!)ht.Clone());
+ }
+
+ public virtual int Count
+ {
+ [Pure][Reads(ReadsAttribute.Reads.Owned)] get
+ {
+ return ht.Count;
+ }
+ }
+
+ [Pure]
+ public IEnumerator! GetEnumerator()
+ {
+ return ht.Keys.GetEnumerator();
+ }
+
+ [Pure][Reads(ReadsAttribute.Reads.Owned)]
+ public override string! ToString()
+ {
+ string s = null;
+ foreach (object! key in ht.Keys)
+ {
+ if (s == null)
+ {
+ s = "{";
+ }
+ else
+ {
+ s += ", ";
+ }
+ s += key.ToString();
+ }
+ if (s == null)
+ {
+ return "{}";
+ }
+ else
+ {
+ return s + "}";
+ }
+ }
+
+ public bool AddAll(IEnumerable! objs){
+ foreach (object! o in objs){
+ this.Add(o);
+ }
+ return true;
+ }
+ //----------------------------- Static Methods ---------------------------------
+
+ // Functional Intersect
+ public static Set! Intersect(Set! a, Set! b)
+ // ensures Forall{ object x in result; a[x] && b[x] };
+ {
+ Set! res = (Set!) a.Clone();
+ res.Intersect(b);
+ return res;
+ }
+ // Functional Union
+ public static Set! Union(Set! a, Set! b)
+ // ensures Forall{ object x in result; a[x] || b[x] };
+ {
+ Set! res = (Set!) a.Clone();
+ res.AddRange(b);
+ return res;
+ }
+
+ public delegate bool SetFilter(object! obj);
+
+ public static Set! Filter(Set! a, SetFilter! filter)
+ {
+ Set inter = new Set();
+
+ foreach(object! elem in a)
+ {
+ if (filter(elem))
+ {
+ inter.Add(elem);
+ }
+ }
+ return inter;
+ }
+
+ }
+
+ public interface IWorkList: ICollection
+ {
+ bool Add(object o);
+ bool AddAll(IEnumerable objs);
+ bool IsEmpty();
+ object Pull();
+ }
+
+
+} \ No newline at end of file
diff --git a/Source/Boogie.sln b/Source/Boogie.sln
new file mode 100644
index 00000000..40c39af5
--- /dev/null
+++ b/Source/Boogie.sln
@@ -0,0 +1,99 @@
+
+Microsoft Visual Studio Solution File, Format Version 10.00
+# Visual Studio 2008
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Provers", "Provers", "{B758C1E3-824A-439F-AA2F-0BA1143E8C8D}"
+EndProject
+Project("{07C4E3D1-6B67-4060-8A92-940DB82041ED}") = "Simplify", "Provers\Simplify\Simplify.sscproj", "{F75666DE-FB56-457C-8782-09BE243450FC}"
+EndProject
+Project("{07C4E3D1-6B67-4060-8A92-940DB82041ED}") = "Z3", "Provers\Z3\Z3.sscproj", "{F75666DE-CD56-457C-8782-09BE243450FC}"
+EndProject
+Project("{07C4E3D1-6B67-4060-8A92-940DB82041ED}") = "SMTLib", "Provers\SMTLib\SMTLib.sscproj", "{13C3A68C-462A-4CDA-A480-738046E37C5A}"
+EndProject
+Project("{07C4E3D1-6B67-4060-8A92-940DB82041ED}") = "AbsInt", "AbsInt\AbsInt.sscproj", "{11D06232-2039-4BCA-853B-C596E2A4EDB0}"
+EndProject
+Project("{07C4E3D1-6B67-4060-8A92-940DB82041ED}") = "AIFramework", "AIFramework\AIFramework.sscproj", "{24B55172-AD8B-47D1-8952-5A95CFDB9B31}"
+EndProject
+Project("{07C4E3D1-6B67-4060-8A92-940DB82041ED}") = "Basetypes", "Basetypes\Basetypes.sscproj", "{0C692837-77EC-415F-BF04-395E3ED06E9A}"
+EndProject
+Project("{07C4E3D1-6B67-4060-8A92-940DB82041ED}") = "Core", "Core\Core.sscproj", "{47BC34F1-A173-40BE-84C2-9332B4418387}"
+EndProject
+Project("{07C4E3D1-6B67-4060-8A92-940DB82041ED}") = "Graph", "Graph\Graph.sscproj", "{4C28FB90-630E-4B55-A937-11A011B79765}"
+EndProject
+Project("{07C4E3D1-6B67-4060-8A92-940DB82041ED}") = "VCExpr", "VCExpr\VCExpr.sscproj", "{CF42B700-10AA-4DA9-8992-48A800251C11}"
+EndProject
+Project("{07C4E3D1-6B67-4060-8A92-940DB82041ED}") = "VCGeneration", "VCGeneration\VCGeneration.sscproj", "{F65666DE-FB56-457C-8782-09BE243450FC}"
+EndProject
+Project("{07C4E3D1-6B67-4060-8A92-940DB82041ED}") = "BoogieDriver", "BoogieDriver\BoogieDriver.sscproj", "{D2B98E4A-2EAB-4065-ABFA-709AC5CA7D4C}"
+ ProjectSection(ProjectDependencies) = postProject
+ {CF42B700-10AA-4DA9-8992-48A800251C11} = {CF42B700-10AA-4DA9-8992-48A800251C11}
+ {11D06232-2039-4BCA-853B-C596E2A4EDB0} = {11D06232-2039-4BCA-853B-C596E2A4EDB0}
+ {0C692837-77EC-415F-BF04-395E3ED06E9A} = {0C692837-77EC-415F-BF04-395E3ED06E9A}
+ {24B55172-AD8B-47D1-8952-5A95CFDB9B31} = {24B55172-AD8B-47D1-8952-5A95CFDB9B31}
+ {13C3A68C-462A-4CDA-A480-738046E37C5A} = {13C3A68C-462A-4CDA-A480-738046E37C5A}
+ {4C28FB90-630E-4B55-A937-11A011B79765} = {4C28FB90-630E-4B55-A937-11A011B79765}
+ {F65666DE-FB56-457C-8782-09BE243450FC} = {F65666DE-FB56-457C-8782-09BE243450FC}
+ {F75666DE-CD56-457C-8782-09BE243450FC} = {F75666DE-CD56-457C-8782-09BE243450FC}
+ {F75666DE-FB56-457C-8782-09BE243450FC} = {F75666DE-FB56-457C-8782-09BE243450FC}
+ {47BC34F1-A173-40BE-84C2-9332B4418387} = {47BC34F1-A173-40BE-84C2-9332B4418387}
+ EndProjectSection
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|.NET = Debug|.NET
+ Release|.NET = Release|.NET
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {F75666DE-FB56-457C-8782-09BE243450FC}.Debug|.NET.ActiveCfg = Debug|.NET
+ {F75666DE-FB56-457C-8782-09BE243450FC}.Debug|.NET.Build.0 = Debug|.NET
+ {F75666DE-FB56-457C-8782-09BE243450FC}.Release|.NET.ActiveCfg = Release|.NET
+ {F75666DE-FB56-457C-8782-09BE243450FC}.Release|.NET.Build.0 = Release|.NET
+ {F75666DE-CD56-457C-8782-09BE243450FC}.Debug|.NET.ActiveCfg = Debug|.NET
+ {F75666DE-CD56-457C-8782-09BE243450FC}.Debug|.NET.Build.0 = Debug|.NET
+ {F75666DE-CD56-457C-8782-09BE243450FC}.Release|.NET.ActiveCfg = Release|.NET
+ {F75666DE-CD56-457C-8782-09BE243450FC}.Release|.NET.Build.0 = Release|.NET
+ {13C3A68C-462A-4CDA-A480-738046E37C5A}.Debug|.NET.ActiveCfg = Debug|.NET
+ {13C3A68C-462A-4CDA-A480-738046E37C5A}.Debug|.NET.Build.0 = Debug|.NET
+ {13C3A68C-462A-4CDA-A480-738046E37C5A}.Release|.NET.ActiveCfg = Release|.NET
+ {13C3A68C-462A-4CDA-A480-738046E37C5A}.Release|.NET.Build.0 = Release|.NET
+ {11D06232-2039-4BCA-853B-C596E2A4EDB0}.Debug|.NET.ActiveCfg = Debug|.NET
+ {11D06232-2039-4BCA-853B-C596E2A4EDB0}.Debug|.NET.Build.0 = Debug|.NET
+ {11D06232-2039-4BCA-853B-C596E2A4EDB0}.Release|.NET.ActiveCfg = Release|.NET
+ {11D06232-2039-4BCA-853B-C596E2A4EDB0}.Release|.NET.Build.0 = Release|.NET
+ {24B55172-AD8B-47D1-8952-5A95CFDB9B31}.Debug|.NET.ActiveCfg = Debug|.NET
+ {24B55172-AD8B-47D1-8952-5A95CFDB9B31}.Debug|.NET.Build.0 = Debug|.NET
+ {24B55172-AD8B-47D1-8952-5A95CFDB9B31}.Release|.NET.ActiveCfg = Release|.NET
+ {24B55172-AD8B-47D1-8952-5A95CFDB9B31}.Release|.NET.Build.0 = Release|.NET
+ {0C692837-77EC-415F-BF04-395E3ED06E9A}.Debug|.NET.ActiveCfg = Debug|.NET
+ {0C692837-77EC-415F-BF04-395E3ED06E9A}.Debug|.NET.Build.0 = Debug|.NET
+ {0C692837-77EC-415F-BF04-395E3ED06E9A}.Release|.NET.ActiveCfg = Release|.NET
+ {0C692837-77EC-415F-BF04-395E3ED06E9A}.Release|.NET.Build.0 = Release|.NET
+ {47BC34F1-A173-40BE-84C2-9332B4418387}.Debug|.NET.ActiveCfg = Debug|.NET
+ {47BC34F1-A173-40BE-84C2-9332B4418387}.Debug|.NET.Build.0 = Debug|.NET
+ {47BC34F1-A173-40BE-84C2-9332B4418387}.Release|.NET.ActiveCfg = Release|.NET
+ {47BC34F1-A173-40BE-84C2-9332B4418387}.Release|.NET.Build.0 = Release|.NET
+ {4C28FB90-630E-4B55-A937-11A011B79765}.Debug|.NET.ActiveCfg = Debug|.NET
+ {4C28FB90-630E-4B55-A937-11A011B79765}.Debug|.NET.Build.0 = Debug|.NET
+ {4C28FB90-630E-4B55-A937-11A011B79765}.Release|.NET.ActiveCfg = Release|.NET
+ {4C28FB90-630E-4B55-A937-11A011B79765}.Release|.NET.Build.0 = Release|.NET
+ {CF42B700-10AA-4DA9-8992-48A800251C11}.Debug|.NET.ActiveCfg = Debug|.NET
+ {CF42B700-10AA-4DA9-8992-48A800251C11}.Debug|.NET.Build.0 = Debug|.NET
+ {CF42B700-10AA-4DA9-8992-48A800251C11}.Release|.NET.ActiveCfg = Release|.NET
+ {CF42B700-10AA-4DA9-8992-48A800251C11}.Release|.NET.Build.0 = Release|.NET
+ {F65666DE-FB56-457C-8782-09BE243450FC}.Debug|.NET.ActiveCfg = Debug|.NET
+ {F65666DE-FB56-457C-8782-09BE243450FC}.Debug|.NET.Build.0 = Debug|.NET
+ {F65666DE-FB56-457C-8782-09BE243450FC}.Release|.NET.ActiveCfg = Release|.NET
+ {F65666DE-FB56-457C-8782-09BE243450FC}.Release|.NET.Build.0 = Release|.NET
+ {D2B98E4A-2EAB-4065-ABFA-709AC5CA7D4C}.Debug|.NET.ActiveCfg = Debug|.NET
+ {D2B98E4A-2EAB-4065-ABFA-709AC5CA7D4C}.Debug|.NET.Build.0 = Debug|.NET
+ {D2B98E4A-2EAB-4065-ABFA-709AC5CA7D4C}.Release|.NET.ActiveCfg = Release|.NET
+ {D2B98E4A-2EAB-4065-ABFA-709AC5CA7D4C}.Release|.NET.Build.0 = Release|.NET
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(NestedProjects) = preSolution
+ {F75666DE-FB56-457C-8782-09BE243450FC} = {B758C1E3-824A-439F-AA2F-0BA1143E8C8D}
+ {F75666DE-CD56-457C-8782-09BE243450FC} = {B758C1E3-824A-439F-AA2F-0BA1143E8C8D}
+ {13C3A68C-462A-4CDA-A480-738046E37C5A} = {B758C1E3-824A-439F-AA2F-0BA1143E8C8D}
+ EndGlobalSection
+EndGlobal
diff --git a/Source/Boogie.suo b/Source/Boogie.suo
new file mode 100644
index 00000000..cf2332be
--- /dev/null
+++ b/Source/Boogie.suo
Binary files differ
diff --git a/Source/BoogieDriver/BoogieDriver.ssc b/Source/BoogieDriver/BoogieDriver.ssc
new file mode 100644
index 00000000..0254c3ef
--- /dev/null
+++ b/Source/BoogieDriver/BoogieDriver.ssc
@@ -0,0 +1,648 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------------
+// OnlyBoogie OnlyBoogie.ssc
+// - main program for taking a BPL program and verifying it
+//---------------------------------------------------------------------------------------------
+
+namespace Microsoft.Boogie
+{
+ using System;
+ using System.IO;
+ using System.Collections;
+ using System.Collections.Generic;
+ using PureCollections;
+ using Microsoft.Boogie;
+ using Microsoft.Boogie.AbstractInterpretation;
+ using System.Diagnostics;
+ using VC;
+ using Cci = System.Compiler;
+ using AI = Microsoft.AbstractInterpretationFramework;
+
+/*
+ The following assemblies are referenced because they are needed at runtime, not at compile time:
+ BaseTypes
+ Provers.Z3
+ System.Compiler.Framework
+*/
+
+ public class OnlyBoogie
+ {
+ // ------------------------------------------------------------------------
+ // Main
+
+ public static void Main (string[]! args)
+ {
+ assert forall{int i in (0:args.Length); args[i] != null};
+ CommandLineOptions.Clo.RunningBoogieFromCommandLine = true;
+ if (CommandLineOptions.Clo.Parse(args) != 1)
+ {
+ goto END;
+ }
+ if (CommandLineOptions.Clo.Files.Count == 0)
+ {
+ ErrorWriteLine("*** Error: No input files were specified.");
+ goto END;
+ }
+ if (CommandLineOptions.Clo.XmlSink != null) {
+ string errMsg = CommandLineOptions.Clo.XmlSink.Open();
+ if (errMsg != null) {
+ ErrorWriteLine("*** Error: " + errMsg);
+ goto END;
+ }
+ }
+ if (!CommandLineOptions.Clo.DontShowLogo)
+ {
+ Console.WriteLine(CommandLineOptions.Clo.Version);
+ }
+ if (CommandLineOptions.Clo.ShowEnv == CommandLineOptions.ShowEnvironment.Always)
+ {
+ Console.WriteLine("---Command arguments");
+ foreach (string! arg in args)
+ {
+ Console.WriteLine(arg);
+ }
+ Console.WriteLine("--------------------");
+ }
+
+ SelectPlatform(CommandLineOptions.Clo);
+
+ Helpers.ExtraTraceInformation("Becoming sentinent");
+
+ // Make sure the Spec# runtime is initialized.
+ // This happens when the static constructor for the Runtime type is executed.
+ // Otherwise, if a reference happens to get chased to it, it is loaded twice
+ // and then the types in it do not get unique representations.
+ if (System.Type.GetType("Mono.Runtime") == null) { // MONO
+ Cci.AssemblyNode a = Microsoft.SpecSharp.Runtime.RuntimeAssembly;
+ assert a != null;
+ }
+
+ foreach (string! file in CommandLineOptions.Clo.Files)
+ {
+ string extension = Path.GetExtension(file);
+ if (extension != null) { extension = extension.ToLower(); }
+ 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;
+ }
+ }
+ CommandLineOptions.Clo.RunningBoogieOnSsc = false;
+ ProcessFiles(CommandLineOptions.Clo.Files);
+
+ END:
+ if (CommandLineOptions.Clo.XmlSink != null) {
+ CommandLineOptions.Clo.XmlSink.Close();
+ }
+ if (CommandLineOptions.Clo.Wait)
+ {
+ Console.WriteLine("Press Enter to exit.");
+ Console.ReadLine();
+ }
+ }
+
+ public static void ErrorWriteLine(string! s) {
+ if (!s.Contains("Error: ") && !s.Contains("Error BP")) {
+ Console.WriteLine(s);
+ return;
+ }
+
+ // split the string up into its first line and the remaining lines
+ string remaining = null;
+ int i = s.IndexOf('\r');
+ if (0 <= i) {
+ remaining = s.Substring(i+1);
+ if (remaining.StartsWith("\n")) {
+ remaining = remaining.Substring(1);
+ }
+ s = s.Substring(0, i);
+ }
+
+ ConsoleColor col = Console.ForegroundColor;
+ Console.ForegroundColor = ConsoleColor.Red;
+ Console.WriteLine(s);
+ Console.ForegroundColor = col;
+
+ if (remaining != null) {
+ Console.WriteLine(remaining);
+ }
+ }
+
+ public static void ErrorWriteLine(string! format, params object[] args) {
+ string s = string.Format(format, args);
+ ErrorWriteLine(s);
+ }
+
+ public static void AdvisoryWriteLine(string! format, params object[] args) {
+ ConsoleColor col = Console.ForegroundColor;
+ Console.ForegroundColor = ConsoleColor.Yellow;
+ Console.WriteLine(format, args);
+ Console.ForegroundColor = col;
+ }
+
+ public static void SelectPlatform(CommandLineOptions! options)
+ {
+ if (options.TargetPlatformLocation != null) {
+ // Make sure static constructor runs before we start setting locations, etc.
+ System.Compiler.SystemTypes.Clear();
+
+ switch (options.TargetPlatform){
+ case CommandLineOptions.PlatformType.v1: Microsoft.SpecSharp.TargetPlatform.SetToV1(options.TargetPlatformLocation); break;
+ case CommandLineOptions.PlatformType.v11: Microsoft.SpecSharp.TargetPlatform.SetToV1_1(options.TargetPlatformLocation); break;
+ case CommandLineOptions.PlatformType.v2: Microsoft.SpecSharp.TargetPlatform.SetToV2(options.TargetPlatformLocation); break;
+ case CommandLineOptions.PlatformType.cli1: Microsoft.SpecSharp.TargetPlatform.SetToPostV1_1(options.TargetPlatformLocation); break;
+ }
+
+ if (options.StandardLibraryLocation != null && options.StandardLibraryLocation.Length > 0){
+ System.Compiler.SystemAssemblyLocation.Location = options.StandardLibraryLocation;
+ }
+ System.Compiler.SystemCompilerRuntimeAssemblyLocation.Location = options.TargetPlatformLocation + @"\System.Compiler.Runtime.dll";
+
+ System.Compiler.SystemTypes.Initialize(true, true);
+ }
+ }
+
+ static string! GetErrorLine(Cci.ErrorNode! node)
+ requires node.SourceContext.Document != null ==> node.SourceContext.Document.Name != null;
+ {
+ string message = node.GetMessage(System.Threading.Thread.CurrentThread.CurrentUICulture);
+ string kind;
+ if (message.Contains("(trace position)")) {
+ kind = "Related information";
+ } else {
+ kind = "Error";
+ }
+ if (node.SourceContext.Document != null) {
+ return string.Format("{0}({1},{2}): {3}: {4}", Path.GetFileName((!)node.SourceContext.Document.Name), node.SourceContext.StartLine, node.SourceContext.StartColumn, kind, message);
+ } else {
+ return string.Format("{0}: {1}", kind, message);
+ }
+ }
+
+ enum FileType { Unknown, Cil, Bpl, Dafny };
+
+ class ErrorReporter
+ {
+ public Cci.ErrorNodeList! errors = new Cci.ErrorNodeList();
+ public int errorsReported;
+
+ public void ReportErrors()
+ {
+ //sort the portion of the array that will be reported to make output more deterministic
+ errors.Sort(errorsReported,errors.Count-errorsReported);
+ for(;errorsReported < errors.Count; errorsReported++) {
+ Cci.ErrorNode error = errors[errorsReported];
+ if (error != null)
+ ErrorWriteLine(GetErrorLine(error));
+ }
+ }
+ }
+
+ static void ProcessFiles (List<string!>! fileNames)
+ {
+ 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) {
+ PrintBplFile(CommandLineOptions.Clo.PrintFile, program, false);
+ }
+
+ PipelineOutcome oc = ResolveAndTypecheck(program, fileNames[fileNames.Count-1]);
+ if (oc != PipelineOutcome.ResolvedAndTypeChecked) return;
+ BoogiePL.Errors.count = 0;
+ int errorCount, verified, inconclusives, timeOuts, outOfMemories;
+ oc = InferAndVerify(program, null, out errorCount, out verified, out inconclusives, out timeOuts, out outOfMemories);
+ switch (oc) {
+ case PipelineOutcome.Done:
+ case PipelineOutcome.VerificationCompleted:
+ WriteTrailer(verified, errorCount, inconclusives, timeOuts, outOfMemories);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+
+ static void PrintBplFile (string! filename, Program! program, bool allowPrintDesugaring)
+ {
+ bool oldPrintDesugaring = CommandLineOptions.Clo.PrintDesugarings;
+ 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) {
+ writer.WriteLine("// " + CommandLineOptions.Clo.Version);
+ writer.WriteLine("// " + CommandLineOptions.Clo.Environment);
+ }
+ writer.WriteLine();
+ program.Emit(writer);
+ }
+ CommandLineOptions.Clo.PrintDesugarings = oldPrintDesugaring;
+ }
+
+
+ static bool ProgramHasDebugInfo (Program! program)
+ {
+ // We inspect the last declaration because the first comes from the prelude and therefore always has source context.
+ return program.TopLevelDeclarations.Count > 0 &&
+ ((!)program.TopLevelDeclarations[program.TopLevelDeclarations.Count - 1]).tok.IsValid;
+ }
+
+
+ /// <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; }
+ Console.WriteLine(s);
+ }
+
+ static void WriteTrailer(int verified, int errors, int inconclusives, int timeOuts, int outOfMemories)
+ requires 0 <= errors && 0 <= inconclusives && 0 <= timeOuts && 0 <= outOfMemories;
+ {
+ Console.WriteLine();
+ Console.Write("{0} finished with {1} verified, {2} error{3}", CommandLineOptions.Clo.ToolName, verified, errors, errors == 1 ? "" : "s");
+ if (inconclusives != 0) {
+ Console.Write(", {0} inconclusive{1}", inconclusives, inconclusives == 1 ? "" : "s");
+ }
+ if (timeOuts != 0) {
+ Console.Write(", {0} time out{1}", timeOuts, timeOuts == 1 ? "" : "s");
+ }
+ if (outOfMemories != 0) {
+ Console.Write(", {0} out of memory", outOfMemories);
+ }
+ Console.WriteLine();
+ Console.Out.Flush();
+ }
+
+
+
+ static void ReportBplError(Absy! node, string! message, bool error, bool showBplLocation)
+ {
+ IToken tok = node.tok;
+ string s;
+ if (tok != null && showBplLocation) {
+ s = string.Format("{0}({1},{2}): {3}", tok.filename, tok.line, tok.col, message);
+ } else {
+ s = message;
+ }
+ if (error) {
+ ErrorWriteLine(s);
+ } else {
+ Console.WriteLine(s);
+ }
+ }
+
+ /// <summary>
+ /// 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)
+ {
+ BoogiePL.Errors.count = 0;
+ Program program = null;
+ bool okay = true;
+ foreach (string bplFileName in fileNames) {
+ if (!suppressTraceOutput) {
+ if (CommandLineOptions.Clo.XmlSink != null) {
+ CommandLineOptions.Clo.XmlSink.WriteFileFragment(bplFileName);
+ }
+ if (CommandLineOptions.Clo.Trace) {
+ Console.WriteLine("Parsing " + bplFileName);
+ }
+ }
+
+ Program programSnippet;
+ int errorCount;
+ try {
+ errorCount = BoogiePL.Parser.Parse(bplFileName, out programSnippet);
+ if (programSnippet == null || errorCount != 0) {
+ Console.WriteLine("{0} parse errors detected in {1}", BoogiePL.Errors.count, bplFileName);
+ okay = false;
+ continue;
+ }
+ } catch (IOException e) {
+ ErrorWriteLine("Error opening file \"{0}\": {1}", bplFileName, e.Message);
+ okay = false;
+ continue;
+ }
+ if (program == null) {
+ program = programSnippet;
+ } else if (programSnippet != null) {
+ program.TopLevelDeclarations.AddRange(programSnippet.TopLevelDeclarations);
+ }
+ }
+ if (!okay) {
+ return null;
+ } else if (program == null) {
+ return new Program();
+ } else {
+ return program;
+ }
+ }
+
+
+ enum PipelineOutcome { Done, ResolutionError, TypeCheckingError, ResolvedAndTypeChecked, FatalError, VerificationCompleted }
+
+ /// <summary>
+ /// Resolves and type checks the given Boogie program. Any errors are reported to the
+ /// console. Returns:
+ /// - Done if no errors occurred, and command line specified no resolution or no type checking.
+ /// - ResolutionError if a resolution error occurred
+ /// - TypeCheckingError if a type checking error occurred
+ /// - ResolvedAndTypeChecked if both resolution and type checking succeeded
+ /// </summary>
+ static PipelineOutcome ResolveAndTypecheck (Program! program, string! bplFileName)
+ {
+ // ---------- Resolve ------------------------------------------------------------
+
+ if (CommandLineOptions.Clo.NoResolve) { return PipelineOutcome.Done; }
+
+ int errorCount = program.Resolve();
+ if (errorCount != 0) {
+ Console.WriteLine("{0} name resolution errors detected in {1}", errorCount, bplFileName);
+ return PipelineOutcome.ResolutionError;
+ }
+
+ // ---------- Type check ------------------------------------------------------------
+
+ if (CommandLineOptions.Clo.NoTypecheck) { return PipelineOutcome.Done; }
+
+ errorCount = program.Typecheck();
+ 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 PrintDesugaring option is engaged, print the file here, after resolution and type checking
+ PrintBplFile(CommandLineOptions.Clo.PrintFile, program, true);
+ }
+
+ return PipelineOutcome.ResolvedAndTypeChecked;
+ }
+
+ /// <summary>
+ /// Given a resolved and type checked Boogie program, infers invariants for the program
+ /// and then attempts to verify it. Returns:
+ /// - Done if command line specified no verification
+ /// - FatalError if a fatal error occurred, in which case an error has been printed to console
+ /// - VerificationCompleted if inference and verification completed, in which the out
+ /// parameters contain meaningful values
+ /// </summary>
+ static PipelineOutcome InferAndVerify (Program! program,
+ ErrorReporter errorReporter,
+ out int errorCount, out int verified, out int inconclusives, out int timeOuts, out int outOfMemories)
+ ensures 0 <= inconclusives && 0 <= timeOuts;
+ {
+ errorCount = verified = inconclusives = timeOuts = outOfMemories = 0;
+
+ // ---------- Infer invariants --------------------------------------------------------
+
+ // Abstract interpretation -> Always use (at least) intervals, if not specified otherwise (e.g. with the "/noinfer" switch)
+ Microsoft.Boogie.AbstractInterpretation.AbstractInterpretation.RunAbstractInterpretation(program);
+
+ if (CommandLineOptions.Clo.LoopUnrollCount != -1) {
+ program.UnrollLoops(CommandLineOptions.Clo.LoopUnrollCount);
+ }
+
+ if (CommandLineOptions.Clo.PrintInstrumented) {
+ program.Emit(new TokenTextWriter(Console.Out));
+ }
+
+ // ---------- Verify ------------------------------------------------------------
+
+ if (!CommandLineOptions.Clo.Verify) { return PipelineOutcome.Done; }
+
+ #region Verify each implementation
+
+#if ROB_DEBUG
+ string now = DateTime.Now.ToString().Replace(' ','-').Replace('/','-').Replace(':','-');
+ System.IO.StreamWriter w = new System.IO.StreamWriter(@"\temp\batch_"+now+".bpl");
+ program.Emit(new TokenTextWriter(w));
+ w.Close();
+#endif
+
+ 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);
+ }
+ }
+ catch (ProverException e)
+ {
+ ErrorWriteLine("Fatal Error: ProverException: {0}", e);
+ return PipelineOutcome.FatalError;
+ }
+
+ foreach ( Declaration! decl in program.TopLevelDeclarations )
+ {
+ Implementation impl = decl as Implementation;
+ if (impl != null && CommandLineOptions.Clo.UserWantsToCheckRoutine((!)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) {
+ start = DateTime.Now;
+ if (CommandLineOptions.Clo.Trace) {
+ Console.WriteLine();
+ Console.WriteLine("Verifying {0} ...", impl.Name);
+ }
+ if (CommandLineOptions.Clo.XmlSink != null) {
+ CommandLineOptions.Clo.XmlSink.WriteStartMethod(impl.Name, start);
+ }
+ }
+
+ VCGen.Outcome outcome;
+ try
+ {
+ outcome = vcgen.VerifyImplementation(impl, program, out errors);
+ }
+ 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)
+ {
+ AdvisoryWriteLine("Advisory: {0} SKIPPED because of internal error: unexpected prover output: {1}", impl.Name, upo.Message);
+ errors = null;
+ outcome = VCGen.Outcome.Inconclusive;
+ }
+
+ string! timeIndication = "";
+ DateTime end = DateTime.Now;
+ TimeSpan elapsed = end - start;
+ if (CommandLineOptions.Clo.Trace || CommandLineOptions.Clo.XmlSink != null) {
+ if (CommandLineOptions.Clo.Trace) {
+ timeIndication = string.Format(" [{0} s] ", elapsed.TotalSeconds);
+ }
+ }
+
+
+ switch (outcome) {
+ default:
+ assert false; // unexpected outcome
+ case VCGen.Outcome.Correct:
+ if (CommandLineOptions.Clo.vcVariety == CommandLineOptions.VCVariety.Doomed) {
+ Inform(String.Format("{0}doomed", timeIndication));
+ errorCount++;
+ } else {
+ Inform(String.Format("{0}verified", timeIndication));
+ verified++;
+ }
+ break;
+ case VCGen.Outcome.TimedOut:
+ timeOuts++;
+ Inform(String.Format("{0}timed out", timeIndication));
+ break;
+ case VCGen.Outcome.OutOfMemory:
+ outOfMemories++;
+ Inform(String.Format("{0}out of memory", timeIndication));
+ break;
+ case VCGen.Outcome.Inconclusive:
+ inconclusives++;
+ Inform(String.Format("{0}inconclusive", timeIndication));
+ break;
+ case VCGen.Outcome.Errors:
+ if (CommandLineOptions.Clo.vcVariety == CommandLineOptions.VCVariety.Doomed) {
+ Inform(String.Format("{0}credible", timeIndication));
+ verified++;
+ } else {
+ assert errors != null; // guaranteed by postcondition of VerifyImplementation
+ if (errorReporter != null)
+ {
+ // assert translatedProgram != null;
+ // ErrorReporting h = new ErrorReporting();
+ // h.errorReportingWithTrace(translatedProgram, errors, impl);
+
+ errorReporter.ReportErrors();
+ }
+ else
+ {
+ // BP1xxx: Parsing errors
+ // BP2xxx: Name resolution errors
+ // BP3xxx: Typechecking errors
+ // BP4xxx: Abstract interpretation errors (Is there such a thing?)
+ // BP5xxx: Verification errors
+
+ errors.Sort(new CounterexampleComparer());
+ 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 {
+ ReportBplError(err.FailingCall, "Error BP5002: 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);
+ }
+ if (CommandLineOptions.Clo.XmlSink != null) {
+ CommandLineOptions.Clo.XmlSink.WriteError("precondition violation", err.FailingCall.tok, err.FailingRequires.tok, error.Trace);
+ }
+ }
+ 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 {
+ ReportBplError(err.FailingReturn, "Error BP5003: A postcondition might not hold at this return statement.", true, true);
+ ReportBplError(err.FailingEnsures, "Related location: This is the postcondition that might not hold.", false, true);
+ }
+ if (CommandLineOptions.Clo.XmlSink != null) {
+ CommandLineOptions.Clo.XmlSink.WriteError("postcondition violation", err.FailingReturn.tok, err.FailingEnsures.tok, error.Trace);
+ }
+ }
+ else // error is AssertCounterexample
+ {
+ AssertCounterexample! err = (AssertCounterexample) error;
+ if (err.FailingAssert is LoopInitAssertCmd) {
+ ReportBplError(err.FailingAssert, "Error BP5004: 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);
+ }
+ }
+ else if (err.FailingAssert is LoopInvMaintainedAssertCmd) {
+ // this assertion is a loop invariant which is not maintained
+ ReportBplError(err.FailingAssert, "Error BP5005: 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);
+ }
+ } 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 {
+ ReportBplError(err.FailingAssert, "Error BP5001: This assertion might not hold.", true, true);
+ }
+ if (CommandLineOptions.Clo.XmlSink != null) {
+ CommandLineOptions.Clo.XmlSink.WriteError("assertion violation", err.FailingAssert.tok, null, error.Trace);
+ }
+ }
+ }
+ if (CommandLineOptions.Clo.EnhancedErrorMessages == 1) {
+ foreach (string! info in error.relatedInformation) {
+ Console.WriteLine(" " + info);
+ }
+ }
+ if (CommandLineOptions.Clo.ErrorTrace > 0) {
+ Console.WriteLine("Execution trace:");
+ foreach (Block! b in error.Trace) {
+ if (b.tok == null) {
+ Console.WriteLine(" <intermediate block>");
+ } else {
+ // for ErrorTrace == 1 restrict the output;
+ // do not print tokens with -17:-4 as their location because they have been
+ // introduced in the translation and do not give any useful feedback to the user
+ if (!(CommandLineOptions.Clo.ErrorTrace == 1 && b.tok.line == -17 && b.tok.col == -4)) {
+ Console.WriteLine(" {0}({1},{2}): {3}", b.tok.filename, b.tok.line, b.tok.col, b.Label);
+ }
+ }
+ }
+ }
+ errorCount++;
+ }
+ }
+ Inform(String.Format("{0}error{1}", timeIndication, errors.Count == 1 ? "" : "s"));
+ }
+ break;
+ }
+ if (CommandLineOptions.Clo.XmlSink != null) {
+ CommandLineOptions.Clo.XmlSink.WriteEndMethod(outcome.ToString().ToLowerInvariant(), end, elapsed);
+ }
+ if (outcome == VCGen.Outcome.Errors || CommandLineOptions.Clo.Trace) {
+ Console.Out.Flush();
+ }
+ }
+ }
+ vcgen.Close();
+ ((!)CommandLineOptions.Clo.TheProverFactory).Close();
+
+ #endregion
+
+ return PipelineOutcome.VerificationCompleted;
+ }
+
+ }
+}
diff --git a/Source/BoogieDriver/BoogieDriver.sscproj b/Source/BoogieDriver/BoogieDriver.sscproj
new file mode 100644
index 00000000..37a31003
--- /dev/null
+++ b/Source/BoogieDriver/BoogieDriver.sscproj
@@ -0,0 +1,140 @@
+<?xml version="1.0" encoding="utf-8"?>
+<VisualStudioProject>
+ <XEN ProjectType="Local"
+ SchemaVersion="1.0"
+ Name="BoogieDriver"
+ ProjectGuid="d2b98e4a-2eab-4065-abfa-709ac5ca7d4c"
+ >
+ <Build>
+ <Settings ApplicationIcon=""
+ AssemblyName="Boogie"
+ OutputType="Exe"
+ RootNamespace="Boogie"
+ StartupObject=""
+ StandardLibraryLocation=""
+ TargetPlatform="v2"
+ TargetPlatformLocation=""
+ >
+ <Config Name="Debug"
+ AllowUnsafeBlocks="False"
+ BaseAddress="285212672"
+ CheckForOverflowUnderflow="False"
+ ConfigurationOverrideFile=""
+ DefineConstants="DEBUG;TRACE"
+ DocumentationFile=""
+ DebugSymbols="True"
+ FileAlignment="4096"
+ IncrementalBuild="True"
+ Optimize="False"
+ OutputPath="..\..\Binaries"
+ RegisterForComInterop="False"
+ RemoveIntegerChecks="false"
+ TreatWarningsAsErrors="False"
+ WarningLevel="4"
+ CheckContractAdmissibility="True"
+ CheckPurity="False"
+ />
+ <Config Name="Release"
+ AllowUnsafeBlocks="false"
+ BaseAddress="285212672"
+ CheckForOverflowUnderflow="false"
+ ConfigurationOverrideFile=""
+ DefineConstants="TRACE"
+ DocumentationFile=""
+ DebugSymbols="false"
+ FileAlignment="4096"
+ IncrementalBuild="false"
+ Optimize="true"
+ OutputPath="bin\release"
+ RegisterForComInterop="false"
+ RemoveIntegerChecks="false"
+ TreatWarningsAsErrors="false"
+ WarningLevel="4"
+ CheckContractAdmissibility="True"
+ CheckPurity="False"
+ />
+ </Settings>
+ <References>
+ <Reference Name="System"
+ AssemblyName="System"
+ Private="false"
+ />
+ <Reference Name="System.Data"
+ AssemblyName="System.Data"
+ Private="false"
+ />
+ <Reference Name="System.Xml"
+ AssemblyName="System.Xml"
+ Private="false"
+ />
+ <Reference Name="System.Compiler"
+ AssemblyName="System.Compiler"
+ Private="false"
+ HintPath="../../Binaries/System.Compiler.dll"
+ />
+ <Reference Name="Microsoft.SpecSharp"
+ AssemblyName="Microsoft.SpecSharp"
+ Private="false"
+ HintPath="../../Binaries/Microsoft.SpecSharp.dll"
+ />
+ <Reference Name="System.Compiler.Framework"
+ AssemblyName="System.Compiler.Framework"
+ Private="false"
+ HintPath="../../Binaries/System.Compiler.Framework.dll"
+ />
+ <Reference Name="AbsInt"
+ Project="{11D06232-2039-4BCA-853B-C596E2A4EDB0}"
+ Private="true"
+ />
+ <Reference Name="AIFramework"
+ Project="{24B55172-AD8B-47D1-8952-5A95CFDB9B31}"
+ Private="true"
+ />
+ <Reference Name="Basetypes"
+ Project="{0C692837-77EC-415F-BF04-395E3ED06E9A}"
+ Private="true"
+ />
+ <Reference Name="Core"
+ Project="{47BC34F1-A173-40BE-84C2-9332B4418387}"
+ Private="true"
+ />
+ <Reference Name="Graph"
+ Project="{4C28FB90-630E-4B55-A937-11A011B79765}"
+ Private="true"
+ />
+ <Reference Name="Simplify"
+ Project="{F75666DE-FB56-457C-8782-09BE243450FC}"
+ Private="true"
+ />
+ <Reference Name="SMTLib"
+ Project="{13C3A68C-462A-4CDA-A480-738046E37C5A}"
+ Private="true"
+ />
+ <Reference Name="Z3"
+ Project="{F75666DE-CD56-457C-8782-09BE243450FC}"
+ Private="true"
+ />
+ <Reference Name="VCExpr"
+ Project="{CF42B700-10AA-4DA9-8992-48A800251C11}"
+ Private="true"
+ />
+ <Reference Name="VCGeneration"
+ Project="{F65666DE-FB56-457C-8782-09BE243450FC}"
+ Private="true"
+ />
+ </References>
+ </Build>
+ <Files>
+ <Include>
+ <File RelPath="BoogieDriver.ssc"
+ SubType="Code"
+ BuildAction="Compile"
+ />
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="..\version.ssc"
+ />
+ </Include>
+ </Files>
+ </XEN>
+</VisualStudioProject> \ No newline at end of file
diff --git a/Source/Core.sscproj b/Source/Core.sscproj
new file mode 100644
index 00000000..f1b7aea7
--- /dev/null
+++ b/Source/Core.sscproj
@@ -0,0 +1,210 @@
+<?xml version="1.0" encoding="utf-8"?>
+<VisualStudioProject>
+ <XEN ProjectType="Local"
+ SchemaVersion="1.0"
+ Name="Core"
+ ProjectGuid="47bc34f1-a173-40be-84c2-9332b4418387"
+ >
+ <Build>
+ <Settings ApplicationIcon=""
+ AssemblyName="Core"
+ OutputType="Library"
+ RootNamespace="Core"
+ StartupObject=""
+ TargetPlatform="v2"
+ TargetPlatformLocation=""
+ ShadowedAssembly=""
+ StandardLibraryLocation=""
+ >
+ <Config Name="Debug"
+ AllowUnsafeBlocks="False"
+ BaseAddress="285212672"
+ CheckForOverflowUnderflow="False"
+ ConfigurationOverrideFile=""
+ DefineConstants="DEBUG;TRACE;WHIDBEY"
+ DocumentationFile=""
+ DebugSymbols="True"
+ FileAlignment="4096"
+ IncrementalBuild="True"
+ Optimize="False"
+ OutputPath="bin\Debug"
+ RegisterForComInterop="False"
+ RemoveIntegerChecks="false"
+ TreatWarningsAsErrors="False"
+ WarningLevel="4"
+ RunProgramVerifier="False"
+ ProgramVerifierCommandLineOptions=""
+ ReferenceTypesAreNonNullByDefault="False"
+ RunProgramVerifierWhileEditing="False"
+ AllowPointersToManagedStructures="False"
+ CheckContractAdmissibility="True"
+ CheckPurity="False"
+ DisableAssumeChecks="False"
+ DisableDefensiveChecks="False"
+ DisableGuardedClassesChecks="False"
+ DisableInternalChecks="False"
+ DisableInternalContractsMetadata="False"
+ DisablePublicContractsMetadata="False"
+ DebugMode="Project"
+ StartProgram=""
+ StartURL=""
+ StartPage=""
+ CmdArgs="houd1.bpl /Houdini /prover:z3api"
+ WorkingDirectory="c:\boogie\test\houdini"
+ UseIE="False"
+ EnableRemoteDebugging="False"
+ RemoteDebugMachine=""
+ />
+ <Config Name="Release"
+ AllowUnsafeBlocks="false"
+ BaseAddress="285212672"
+ CheckForOverflowUnderflow="false"
+ ConfigurationOverrideFile=""
+ DefineConstants="TRACE;WHIDBEY"
+ DocumentationFile=""
+ DebugSymbols="false"
+ FileAlignment="4096"
+ IncrementalBuild="false"
+ Optimize="true"
+ OutputPath="bin\release"
+ RegisterForComInterop="false"
+ RemoveIntegerChecks="false"
+ TreatWarningsAsErrors="True"
+ WarningLevel="4"
+ />
+ </Settings>
+ <References>
+ <Reference Name="Mscorlib.Contracts"
+ AssemblyName="Mscorlib.Contracts"
+ Private="false"
+ HintPath="C:/Program Files/Microsoft/Spec#/bin/Mscorlib.Contracts.dll"
+ />
+ <Reference Name="System"
+ AssemblyName="System"
+ Private="false"
+ />
+ <Reference Name="System.Compiler.Framework"
+ AssemblyName="System.Compiler.Framework"
+ Private="true"
+ HintPath="C:/Program Files/Microsoft/Spec#/bin/System.Compiler.Framework.dll"
+ />
+ <Reference Name="AIFramework"
+ Project="{24B55172-AD8B-47D1-8952-5A95CFDB9B31}"
+ Private="true"
+ />
+ <Reference Name="System.Compiler"
+ AssemblyName="System.Compiler"
+ Private="true"
+ HintPath="C:/Program Files/Microsoft/Spec#/bin/System.Compiler.dll"
+ />
+ <Reference Name="Graph"
+ Project="{4C28FB90-630E-4B55-A937-11A011B79765}"
+ Private="true"
+ />
+ <Reference Name="System.XML"
+ AssemblyName="System.XML"
+ Private="false"
+ HintPath="C:/WINDOWS/Microsoft.NET/Framework/v2.0.50727/System.XML.dll"
+ />
+ <Reference Name="System.Xml.Contracts"
+ AssemblyName="System.Xml.Contracts"
+ Private="true"
+ HintPath="C:/Program Files/Microsoft/Spec#/bin/System.Xml.Contracts.dll"
+ />
+ <Reference Name="FSharp.Core"
+ AssemblyName="FSharp.Core"
+ Private="true"
+ HintPath="C:/Program Files/FSharp-1.9.6.16/bin/FSharp.Core.dll"
+ />
+ <Reference Name="Basetypes"
+ Project="{0C692837-77EC-415F-BF04-395E3ED06E9A}"
+ Private="true"
+ />
+ </References>
+ </Build>
+ <Files>
+ <Include>
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="Absy.ssc"
+ />
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="..\version.ssc"
+ />
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="Duplicator.ssc"
+ />
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="OOLongUtil.ssc"
+ />
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="PureCollections.ssc"
+ />
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="ResolutionContext.ssc"
+ />
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="StandardVisitor.ssc"
+ />
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="Util.ssc"
+ />
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="CommandLineOptions.ssc"
+ />
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="scanner.ssc"
+ />
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="parser.ssc"
+ />
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="GraphAlgorithms.ssc"
+ />
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="AbsyType.ssc"
+ />
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="AbsyCmd.ssc"
+ />
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="AbsyExpr.ssc"
+ />
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="Xml.ssc"
+ />
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="Inline.ssc"
+ />
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="LoopUnroll.ssc"
+ />
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="VCExp.ssc"
+ />
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="TypeAmbiguitySeeker.ssc"
+ />
+ </Include>
+ </Files>
+ </XEN>
+</VisualStudioProject> \ No newline at end of file
diff --git a/Source/Core/Absy.ssc b/Source/Core/Absy.ssc
new file mode 100644
index 00000000..fd54412c
--- /dev/null
+++ b/Source/Core/Absy.ssc
@@ -0,0 +1,3073 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------------
+// BoogiePL - Absy.cs
+//---------------------------------------------------------------------------------------------
+namespace Microsoft.Boogie.AbstractInterpretation
+{
+ using System.Diagnostics;
+ using CCI = System.Compiler;
+ using System.Collections;
+ using AI = Microsoft.AbstractInterpretationFramework;
+
+ public class CallSite
+ {
+ public Implementation! Impl;
+ public Block! Block;
+ public int Statement; // invariant: Block[Statement] is CallCmd
+ public AI.Lattice.Element! KnownBeforeCall;
+
+ public CallSite (Implementation! impl, Block! b, int stmt, AI.Lattice.Element! e)
+ {
+ this.Impl = impl;
+ this.Block = b;
+ this.Statement = stmt;
+ this.KnownBeforeCall = e;
+ }
+ }
+
+ public class ProcedureSummaryEntry
+ {
+ public AI.Lattice! Lattice;
+ public AI.Lattice.Element! OnEntry;
+ public AI.Lattice.Element! OnExit;
+ public CCI.IMutableSet/*<CallSite>*/! ReturnPoints; // whenever OnExit changes, we start analysis again at all the ReturnPoints
+
+ public ProcedureSummaryEntry (AI.Lattice! lattice, AI.Lattice.Element! onEntry)
+ {
+ this.Lattice = lattice;
+ this.OnEntry = onEntry;
+ this.OnExit = lattice.Bottom;
+ this.ReturnPoints = new CCI.HashSet();
+ // base();
+ }
+
+ } // class
+
+ public class ProcedureSummary : ArrayList/*<ProcedureSummaryEntry>*/
+ {
+ invariant !IsReadOnly && !IsFixedSize;
+
+ public new ProcedureSummaryEntry! this [int i]
+ {
+ get
+ requires 0 <= i && i < Count;
+ { return (ProcedureSummaryEntry!) base[i]; }
+ }
+
+ } // class
+} // namespace
+
+
+namespace Microsoft.Boogie
+{
+ using System;
+ using System.Collections;
+ using System.Diagnostics;
+ using System.Collections.Generic;
+ using Microsoft.Boogie.AbstractInterpretation;
+ using AI = Microsoft.AbstractInterpretationFramework;
+ using Microsoft.Contracts;
+
+
+ public abstract class Absy
+ {
+ public IToken! tok;
+ private int uniqueId;
+
+ public int Line { get { return tok != null ? tok.line : -1; } }
+ public int Col { get { return tok != null ? tok.col : -1; } }
+
+ public Absy (IToken! tok)
+ {
+ this.tok = tok;
+ this.uniqueId = AbsyNodeCount++;
+ // base();
+ }
+
+ private static int AbsyNodeCount = 0;
+
+ // We uniquely number every AST node to make them
+ // suitable for our implementation of functional maps.
+ //
+ public int UniqueId { get { return this.uniqueId; } }
+
+ private const int indent_size = 2;
+ protected static string Indent (int level)
+ {
+ return new string(' ', (indent_size * level));
+ }
+
+ public abstract void Resolve (ResolutionContext! rc);
+
+ /// <summary>
+ /// Requires the object to have been successfully resolved.
+ /// </summary>
+ /// <param name="tc"></param>
+ public abstract void Typecheck (TypecheckingContext! tc);
+ /// <summary>
+ /// Intorduced this so the uniqueId is not the same on a cloned object.
+ /// </summary>
+ /// <param name="tc"></param>
+ public virtual Absy! Clone()
+ {
+ Absy! result = (Absy!) this.MemberwiseClone();
+ result.uniqueId = AbsyNodeCount++; // BUGBUG??
+ return result;
+ }
+
+ public virtual Absy! StdDispatch(StandardVisitor! visitor)
+ {
+ System.Diagnostics.Debug.Fail("Unknown Absy node type: " + this.GetType());
+ throw new System.NotImplementedException();
+ }
+ }
+
+ // TODO: Ideally, this would use generics.
+ public interface IPotentialErrorNode
+ {
+ object ErrorData { get; set; }
+ }
+
+ public class Program : Absy
+ {
+ [Rep]
+ public List<Declaration!>! TopLevelDeclarations;
+
+ public Program()
+ : base(Token.NoToken)
+ {
+ this.TopLevelDeclarations = new List<Declaration!>();
+ // base(Token.NoToken);
+ }
+
+ public void Emit (TokenTextWriter! stream)
+ {
+ stream.SetToken(this);
+ Emitter.Declarations(this.TopLevelDeclarations, stream);
+ }
+ /// <summary>
+ /// Returns the number of name resolution errors.
+ /// </summary>
+ /// <returns></returns>
+ public int Resolve ()
+ {
+ return Resolve((IErrorSink) null);
+ }
+
+ public int Resolve (IErrorSink errorSink)
+ {
+ ResolutionContext rc = new ResolutionContext(errorSink);
+ Resolve(rc);
+ return rc.ErrorCount;
+ }
+
+ public override void Resolve (ResolutionContext! rc)
+ {
+ Helpers.ExtraTraceInformation("Starting resolution");
+
+ foreach (Declaration d in TopLevelDeclarations) {
+ d.Register(rc);
+ }
+
+ ResolveTypes(rc);
+
+ List<Declaration!> prunedTopLevelDecls = CommandLineOptions.Clo.OverlookBoogieTypeErrors ? new List<Declaration!>() : null;
+
+ foreach (Declaration d in TopLevelDeclarations) {
+ // resolve all the non-type-declarations
+ if (d is TypeCtorDecl || d is TypeSynonymDecl) {
+ if (prunedTopLevelDecls != null)
+ prunedTopLevelDecls.Add(d);
+ } else {
+ int e = rc.ErrorCount;
+ d.Resolve(rc);
+ if (prunedTopLevelDecls != null) {
+ if (rc.ErrorCount != e && d is Implementation) {
+ // ignore this implementation
+ System.Console.WriteLine("Warning: Ignoring implementation {0} because of translation resolution errors", ((Implementation)d).Name);
+ rc.ErrorCount = e;
+ } else {
+ prunedTopLevelDecls.Add(d);
+ }
+ }
+ }
+ }
+ if (prunedTopLevelDecls != null) {
+ TopLevelDeclarations = prunedTopLevelDecls;
+ }
+
+ foreach (Declaration d in TopLevelDeclarations) {
+ Variable v = d as Variable;
+ if (v != null) {
+ v.ResolveWhere(rc);
+ }
+ }
+ }
+
+
+ private void ResolveTypes (ResolutionContext! rc) {
+ // first resolve type constructors
+ foreach (Declaration d in TopLevelDeclarations) {
+ if (d is TypeCtorDecl)
+ d.Resolve(rc);
+ }
+
+ // collect type synonym declarations
+ List<TypeSynonymDecl!>! synonymDecls = new List<TypeSynonymDecl!> ();
+ foreach (Declaration d in TopLevelDeclarations) {
+ if (d is TypeSynonymDecl)
+ synonymDecls.Add((TypeSynonymDecl)d);
+ }
+
+ // then resolve the type synonyms by a simple
+ // fixed-point iteration
+ TypeSynonymDecl.ResolveTypeSynonyms(synonymDecls, rc);
+ }
+
+
+ public int Typecheck ()
+ {
+ return this.Typecheck((IErrorSink) null);
+ }
+
+ public int Typecheck (IErrorSink errorSink)
+ {
+ TypecheckingContext tc = new TypecheckingContext(errorSink);
+ Typecheck(tc);
+ return tc.ErrorCount;
+ }
+
+ public override void Typecheck (TypecheckingContext! tc)
+ {
+ Helpers.ExtraTraceInformation("Starting typechecking");
+
+ int oldErrorCount = tc.ErrorCount;
+ foreach (Declaration d in TopLevelDeclarations) {
+ d.Typecheck(tc);
+ }
+
+ if (oldErrorCount == tc.ErrorCount) {
+ // check whether any type proxies have remained uninstantiated
+ TypeAmbiguitySeeker! seeker = new TypeAmbiguitySeeker (tc);
+ foreach (Declaration d in TopLevelDeclarations) {
+ seeker.Visit(d);
+ }
+ }
+
+ AxiomExpander expander = new AxiomExpander(this, tc);
+ expander.CollectExpansions();
+
+ if (CommandLineOptions.Clo.ProcedureInlining != CommandLineOptions.Inlining.None) {
+ bool inline = false;
+ foreach (Declaration d in TopLevelDeclarations) {
+ if (d.FindExprAttribute("inline") != null) inline = true;
+ }
+ if (inline) {
+ foreach (Declaration d in TopLevelDeclarations) {
+ Implementation impl = d as Implementation;
+ if (impl != null) {
+ impl.OriginalBlocks = impl.Blocks;
+ impl.OriginalLocVars = impl.LocVars;
+ }
+ }
+ foreach (Declaration d in TopLevelDeclarations) {
+ Implementation impl = d as Implementation;
+ if (impl != null) {
+ Inliner.ProcessImplementation(tc, this, impl);
+ }
+ }
+ }
+ }
+ }
+
+ public void ComputeStronglyConnectedComponents()
+ {
+ foreach(Declaration d in this.TopLevelDeclarations) {
+ d.ComputeStronglyConnectedComponents();
+ }
+ }
+
+ public void InstrumentWithInvariants ()
+ {
+ foreach (Declaration d in this.TopLevelDeclarations) {
+ d.InstrumentWithInvariants();
+ }
+ }
+
+ /// <summary>
+ /// Instrument the "widen" blocks with a statement in the form of "assume J", where J is a loop predicate "variable"
+ /// </summary>
+ public void InstrumentWithLoopInvariantPredicates()
+ {
+ foreach (Declaration d in this.TopLevelDeclarations) {
+ d.InstrumentWithLoopInvariantPredicates();
+ }
+ }
+
+ /// <summary>
+ /// Reset the abstract stated computed before
+ /// </summary>
+ public void ResetAbstractInterpretationState()
+ {
+ foreach(Declaration d in this.TopLevelDeclarations) {
+ d.ResetAbstractInterpretationState();
+ }
+ }
+
+ public void UnrollLoops(int n)
+ requires 0 <= n;
+ {
+ foreach (Declaration d in this.TopLevelDeclarations) {
+ Implementation impl = d as Implementation;
+ if (impl != null && impl.Blocks != null && impl.Blocks.Count > 0) {
+ expose (impl) {
+ Block start = impl.Blocks[0];
+ assume start != null;
+ assume start.IsConsistent;
+ impl.Blocks = LoopUnroll.UnrollLoops(start, n);
+ }
+ }
+ }
+ }
+
+
+ public override Absy! StdDispatch(StandardVisitor! visitor)
+ {
+ return visitor.VisitProgram(this);
+ }
+ }
+
+ //---------------------------------------------------------------------
+ // Declarations
+
+ public abstract class Declaration : Absy
+ {
+ public QKeyValue Attributes;
+
+ public Declaration(IToken! tok)
+ : base(tok)
+ {
+ }
+
+ protected void EmitAttributes(TokenTextWriter! stream)
+ {
+ for (QKeyValue kv = this.Attributes; kv != null; kv = kv.Next) {
+ kv.Emit(stream);
+ stream.Write(" ");
+ }
+ }
+
+ protected void ResolveAttributes(ResolutionContext! rc)
+ {
+ for (QKeyValue kv = this.Attributes; kv != null; kv = kv.Next) {
+ kv.Resolve(rc);
+ }
+ }
+
+ protected void TypecheckAttributes(TypecheckingContext! rc)
+ {
+ for (QKeyValue kv = this.Attributes; kv != null; kv = kv.Next) {
+ kv.Typecheck(rc);
+ }
+ }
+
+ // Look for {:name true} or {:name false} in list of attributes. Return result in 'result'
+ // (which is not touched if there is no attribute specified).
+ //
+ // Returns false is there was an error processing the flag, true otherwise.
+ public bool CheckBooleanAttribute(string! name, ref bool result)
+ {
+ Expr? expr = FindExprAttribute(name);
+ if (expr != null) {
+ if (expr is LiteralExpr && ((LiteralExpr)expr).isBool) {
+ result = ((LiteralExpr)expr).asBool;
+ } else {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ // Look for {:name expr} in list of attributes.
+ public Expr? FindExprAttribute(string! name)
+ {
+ Expr? res = null;
+ for (QKeyValue kv = this.Attributes; kv != null; kv = kv.Next) {
+ if (kv.Key == name) {
+ if (kv.Params.Count == 1 && kv.Params[0] is Expr) {
+ res = (Expr)kv.Params[0];
+ }
+ }
+ }
+ return res;
+ }
+
+ // Look for {:name string} in list of attributes.
+ public string? FindStringAttribute(string! name)
+ {
+ return QKeyValue.FindStringAttribute(this.Attributes, name);
+ }
+
+ // Look for {:name N} or {:name N} in list of attributes. Return result in 'result'
+ // (which is not touched if there is no attribute specified).
+ //
+ // Returns false is there was an error processing the flag, true otherwise.
+ public bool CheckIntAttribute(string! name, ref int result)
+ {
+ Expr? expr = FindExprAttribute(name);
+ if (expr != null) {
+ if (expr is LiteralExpr && ((LiteralExpr)expr).isBigNum) {
+ result = ((LiteralExpr)expr).asBigNum.ToInt;
+ } else {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public abstract void Emit(TokenTextWriter! stream, int level);
+ public abstract void Register(ResolutionContext! rc);
+
+ /// <summary>
+ /// Compute the strongly connected components of the declaration.
+ /// By default, it does nothing
+ /// </summary>
+ public virtual void ComputeStronglyConnectedComponents() { /* Does nothing */}
+
+ /// <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>
+ /// Insert a statement "assume J", for an opportune J - loop invariant predicate - in the "widen" blocks
+ /// </summary>
+ public virtual void InstrumentWithLoopInvariantPredicates() { /* by default it does nothing */ }
+
+ /// <summary>
+ /// Reset the abstract stated computed before
+ /// </summary>
+ public virtual void ResetAbstractInterpretationState() { /* does nothing */ }
+ }
+
+ public class Axiom : Declaration
+ {
+ public Expr! Expr;
+ public string? Comment;
+
+ public Axiom(IToken! tok, Expr! expr)
+ {
+ this(tok, expr, null);
+ }
+
+ public Axiom(IToken! tok, Expr! expr, string? comment)
+ : base(tok)
+ {
+ Expr = expr;
+ Comment = comment;
+ // base(tok);
+ }
+
+ public Axiom(IToken! tok, Expr! expr, string? comment, QKeyValue kv)
+ {
+ this(tok, expr, comment);
+ this.Attributes = kv;
+ }
+
+ public override void Emit(TokenTextWriter! stream, int level)
+ {
+ if (Comment != null) {
+ stream.WriteLine(this, level, "// " + Comment);
+ }
+ stream.Write(this, level, "axiom ");
+ EmitAttributes(stream);
+ this.Expr.Emit(stream);
+ stream.WriteLine(";");
+ }
+ public override void Register(ResolutionContext! rc)
+ {
+ // nothing to register
+ }
+ public override void Resolve(ResolutionContext! rc)
+ {
+ ResolveAttributes(rc);
+ rc.StateMode = ResolutionContext.State.StateLess;
+ Expr.Resolve(rc);
+ rc.StateMode = ResolutionContext.State.Single;
+ }
+ public override void Typecheck(TypecheckingContext! tc)
+ {
+ TypecheckAttributes(tc);
+ Expr.Typecheck(tc);
+ assert Expr.Type != null; // follows from postcondition of Expr.Typecheck
+ if (! Expr.Type.Unify(Type.Bool))
+ {
+ tc.Error(this, "axioms must be of type bool");
+ }
+ }
+
+ public override Absy! StdDispatch(StandardVisitor! visitor)
+ {
+ return visitor.VisitAxiom(this);
+ }
+ }
+
+ public abstract class NamedDeclaration : Declaration
+ {
+ private string! name;
+ public string! Name
+ {
+ get
+ {
+ return this.name;
+ }
+ set
+ {
+ this.name = value;
+ }
+ }
+
+
+ public NamedDeclaration(IToken! tok, string! name)
+ : base(tok)
+ {
+ this.name = name;
+ // base(tok);
+ }
+ [Pure][Reads(ReadsAttribute.Reads.Owned)]
+ public override string! ToString()
+ {
+ return (!) Name;
+ }
+ }
+
+ public class TypeCtorDecl : NamedDeclaration
+ {
+ public readonly int Arity;
+
+ public TypeCtorDecl(IToken! tok, string! name, int Arity)
+ : base(tok, name)
+ {
+ this.Arity = Arity;
+ }
+ public TypeCtorDecl(IToken! tok, string! name, int Arity, QKeyValue kv)
+ : base(tok, name)
+ {
+ this.Arity = Arity;
+ this.Attributes = kv;
+ }
+ public override void Emit(TokenTextWriter! stream, int level)
+ {
+ stream.Write(this, level, "type ");
+ EmitAttributes(stream);
+ stream.Write("{0}", TokenTextWriter.SanitizeIdentifier(Name));
+ for (int i = 0; i < Arity; ++i)
+ stream.Write(" _");
+ stream.WriteLine(";");
+ }
+ public override void Register(ResolutionContext! rc)
+ {
+ rc.AddType(this);
+ }
+ public override void Resolve(ResolutionContext! rc)
+ {
+ ResolveAttributes(rc);
+ }
+ public override void Typecheck(TypecheckingContext! tc)
+ {
+ TypecheckAttributes(tc);
+ }
+
+ public override Absy! StdDispatch(StandardVisitor! visitor)
+ {
+ return visitor.VisitTypeCtorDecl(this);
+ }
+ }
+
+
+ public class TypeSynonymDecl : NamedDeclaration
+ {
+ public TypeVariableSeq! TypeParameters;
+ public Type! Body;
+
+ public TypeSynonymDecl(IToken! tok, string! name,
+ TypeVariableSeq! typeParams, Type! body)
+ : base(tok, name)
+ {
+ this.TypeParameters = typeParams;
+ this.Body = body;
+ }
+ public TypeSynonymDecl(IToken! tok, string! name,
+ TypeVariableSeq! typeParams, Type! body, QKeyValue kv)
+ : base(tok, name)
+ {
+ this.TypeParameters = typeParams;
+ this.Body = body;
+ this.Attributes = kv;
+ }
+ public override void Emit(TokenTextWriter! stream, int level)
+ {
+ stream.Write(this, level, "type ");
+ EmitAttributes(stream);
+ stream.Write("{0}", TokenTextWriter.SanitizeIdentifier(Name));
+ if (TypeParameters.Length > 0)
+ stream.Write(" ");
+ TypeParameters.Emit(stream, " ");
+ stream.Write(" = ");
+ Body.Emit(stream);
+ stream.WriteLine(";");
+ }
+ public override void Register(ResolutionContext! rc)
+ {
+ rc.AddType(this);
+ }
+ public override void Resolve(ResolutionContext! rc)
+ {
+ ResolveAttributes(rc);
+
+ int previousState = rc.TypeBinderState;
+ try {
+ foreach (TypeVariable! v in TypeParameters)
+ rc.AddTypeBinder(v);
+ Body = Body.ResolveType(rc);
+ } finally {
+ rc.TypeBinderState = previousState;
+ }
+ }
+ public override void Typecheck(TypecheckingContext! tc)
+ {
+ TypecheckAttributes(tc);
+ }
+
+ public static void ResolveTypeSynonyms(List<TypeSynonymDecl!>! synonymDecls,
+ ResolutionContext! rc) {
+ // then discover all dependencies between type synonyms
+ IDictionary<TypeSynonymDecl!, List<TypeSynonymDecl!>!>! deps =
+ new Dictionary<TypeSynonymDecl!, List<TypeSynonymDecl!>!> ();
+ foreach (TypeSynonymDecl! decl in synonymDecls) {
+ List<TypeSynonymDecl!>! declDeps = new List<TypeSynonymDecl!> ();
+ FindDependencies(decl.Body, declDeps, rc);
+ deps.Add(decl, declDeps);
+ }
+
+ List<TypeSynonymDecl!>! resolved = new List<TypeSynonymDecl!> ();
+
+ int unresolved = synonymDecls.Count - resolved.Count;
+ while (unresolved > 0) {
+ foreach (TypeSynonymDecl! decl in synonymDecls) {
+ if (!resolved.Contains(decl) &&
+ forall{TypeSynonymDecl! d in deps[decl]; resolved.Contains(d)}) {
+ decl.Resolve(rc);
+ resolved.Add(decl);
+ }
+ }
+
+ int newUnresolved = synonymDecls.Count - resolved.Count;
+ if (newUnresolved < unresolved) {
+ // we are making progress
+ unresolved = newUnresolved;
+ } else {
+ // there have to be cycles in the definitions
+ foreach (TypeSynonymDecl! decl in synonymDecls) {
+ if (!resolved.Contains(decl)) {
+ rc.Error(decl,
+ "type synonym could not be resolved because of cycles: {0}" +
+ " (replacing body with \"bool\" to continue resolving)",
+ decl.Name);
+
+ // we simply replace the bodies of all remaining type
+ // synonyms with "bool" so that resolution can continue
+ decl.Body = Type.Bool;
+ decl.Resolve(rc);
+ }
+ }
+
+ unresolved = 0;
+ }
+ }
+ }
+
+ // determine a list of all type synonyms that occur in "type"
+ private static void FindDependencies(Type! type, List<TypeSynonymDecl!>! deps,
+ ResolutionContext! rc) {
+ if (type.IsVariable || type.IsBasic) {
+ // nothing
+ } else if (type.IsUnresolved) {
+ UnresolvedTypeIdentifier! unresType = type.AsUnresolved;
+ TypeSynonymDecl dep = rc.LookUpTypeSynonym(unresType.Name);
+ if (dep != null)
+ deps.Add(dep);
+ foreach (Type! subtype in unresType.Arguments)
+ FindDependencies(subtype, deps, rc);
+ } else if (type.IsMap) {
+ MapType! mapType = type.AsMap;
+ foreach (Type! subtype in mapType.Arguments)
+ FindDependencies(subtype, deps, rc);
+ FindDependencies(mapType.Result, deps, rc);
+ } else if (type.IsCtor) {
+ // this can happen because we allow types to be resolved multiple times
+ CtorType! ctorType = type.AsCtor;
+ foreach (Type! subtype in ctorType.Arguments)
+ FindDependencies(subtype, deps, rc);
+ } else {
+ System.Diagnostics.Debug.Fail("Did not expect this type during resolution: "
+ + type);
+ }
+ }
+
+
+ public override Absy! StdDispatch(StandardVisitor! visitor)
+ {
+ return visitor.VisitTypeSynonymDecl(this);
+ }
+ }
+
+
+ public abstract class Variable : NamedDeclaration, AI.IVariable
+ {
+ public TypedIdent! TypedIdent;
+ public Variable(IToken! tok, TypedIdent! typedIdent)
+ : base(tok, typedIdent.Name)
+ {
+ this.TypedIdent = typedIdent;
+ // base(tok, typedIdent.Name);
+ }
+
+ public Variable(IToken! tok, TypedIdent! typedIdent, QKeyValue kv)
+ : base(tok, typedIdent.Name)
+ {
+ this.TypedIdent = typedIdent;
+ // base(tok, typedIdent.Name);
+ this.Attributes = kv;
+ }
+
+ public abstract bool IsMutable
+ {
+ get;
+ }
+
+ public override void Emit(TokenTextWriter! stream, int level)
+ {
+ stream.Write(this, level, "var ");
+ EmitAttributes(stream);
+ EmitVitals(stream, level);
+ stream.WriteLine(";");
+ }
+ public void EmitVitals(TokenTextWriter! stream, int level)
+ {
+ if (CommandLineOptions.Clo.PrintWithUniqueASTIds && this.TypedIdent.HasName)
+ {
+ stream.Write("h{0}^^", this.GetHashCode()); // the idea is that this will prepend the name printed by TypedIdent.Emit
+ }
+ this.TypedIdent.Emit(stream);
+ }
+ public override void Resolve(ResolutionContext! rc)
+ {
+ this.TypedIdent.Resolve(rc);
+ }
+ public void ResolveWhere(ResolutionContext! rc)
+ {
+ if (this.TypedIdent.WhereExpr != null) {
+ this.TypedIdent.WhereExpr.Resolve(rc);
+ }
+ ResolveAttributes(rc);
+ }
+ public override void Typecheck(TypecheckingContext! tc)
+ {
+ TypecheckAttributes(tc);
+ this.TypedIdent.Typecheck(tc);
+ }
+ [Pure][Reads(ReadsAttribute.Reads.Owned)]
+ public object DoVisit(AI.ExprVisitor! visitor)
+ {
+ return visitor.VisitVariable(this);
+ }
+ }
+
+ public class VariableComparer : IComparer
+ {
+ public int Compare(object a, object b) {
+ Variable A = a as Variable;
+ Variable B = b as Variable;
+ if (A == null || B == null) {
+ throw new ArgumentException("VariableComparer works only on objects of type Variable");
+ }
+ return ((!)A.Name).CompareTo(B.Name);
+ }
+ }
+
+ // class to specify the <:-parents of the values of constants
+ public class ConstantParent {
+ public readonly IdentifierExpr! Parent;
+ // if true, the sub-dag underneath this constant-parent edge is
+ // disjoint from all other unique sub-dags
+ public readonly bool Unique;
+
+ public ConstantParent(IdentifierExpr! parent, bool unique) {
+ Parent = parent;
+ Unique = unique;
+ }
+ }
+
+ public class Constant : Variable
+ {
+ // when true, the value of this constant is meant to be distinct
+ // from all other constants.
+ public readonly bool Unique;
+
+ // the <:-parents of the value of this constant. If the field is
+ // null, no information about the parents is provided, which means
+ // that the parental situation is unconstrained.
+ public readonly List<ConstantParent!> Parents;
+
+ // if true, it is assumed that the immediate <:-children of the
+ // value of this constant are completely specified
+ public readonly bool ChildrenComplete;
+
+ public Constant(IToken! tok, TypedIdent! typedIdent)
+ : base(tok, typedIdent)
+ requires typedIdent.Name != null && typedIdent.Name.Length > 0;
+ requires typedIdent.WhereExpr == null;
+ {
+ // base(tok, typedIdent);
+ this.Unique = true;
+ this.Parents = null;
+ this.ChildrenComplete = false;
+ }
+ public Constant(IToken! tok, TypedIdent! typedIdent, bool unique)
+ : base(tok, typedIdent)
+ requires typedIdent.Name != null && typedIdent.Name.Length > 0;
+ requires typedIdent.WhereExpr == null;
+ {
+ // base(tok, typedIdent);
+ this.Unique = unique;
+ this.Parents = null;
+ this.ChildrenComplete = false;
+ }
+ public Constant(IToken! tok, TypedIdent! typedIdent,
+ bool unique,
+ List<ConstantParent!> parents, bool childrenComplete,
+ QKeyValue kv)
+ : base(tok, typedIdent, kv)
+ requires typedIdent.Name != null && typedIdent.Name.Length > 0;
+ requires typedIdent.WhereExpr == null;
+ {
+ // base(tok, typedIdent);
+ this.Unique = unique;
+ this.Parents = parents;
+ this.ChildrenComplete = childrenComplete;
+ }
+ public override bool IsMutable
+ {
+ get
+ {
+ return false;
+ }
+ }
+ public override void Emit(TokenTextWriter! stream, int level)
+ {
+ stream.Write(this, level, "const ");
+ EmitAttributes(stream);
+ if (this.Unique){
+ stream.Write(this, level, "unique ");
+ }
+ EmitVitals(stream, level);
+
+ if (Parents != null || ChildrenComplete) {
+ stream.Write(this, level, " extends");
+ string! sep = " ";
+ foreach (ConstantParent! p in (!)Parents) {
+ stream.Write(this, level, sep);
+ sep = ", ";
+ if (p.Unique)
+ stream.Write(this, level, "unique ");
+ p.Parent.Emit(stream);
+ }
+ if (ChildrenComplete)
+ stream.Write(this, level, " complete");
+ }
+
+ stream.WriteLine(";");
+ }
+ public override void Register(ResolutionContext! rc)
+ {
+ rc.AddVariable(this, true);
+ }
+ public override void Resolve(ResolutionContext! rc)
+ {
+ base.Resolve(rc);
+ if (Parents != null) {
+ foreach (ConstantParent! p in Parents) {
+ p.Parent.Resolve(rc);
+ if (p.Parent.Decl != null && !(p.Parent.Decl is Constant))
+ rc.Error(p.Parent, "the parent of a constant has to be a constant");
+ if (this.Equals(p.Parent.Decl))
+ rc.Error(p.Parent, "constant cannot be its own parent");
+ }
+ }
+
+ // check that no parent occurs twice
+ // (could be optimised)
+ if (Parents != null) {
+ for (int i = 0; i < Parents.Count; ++i) {
+ if (Parents[i].Parent.Decl != null) {
+ for (int j = i + 1; j < Parents.Count; ++j) {
+ if (Parents[j].Parent.Decl != null &&
+ ((!)Parents[i].Parent.Decl).Equals(Parents[j].Parent.Decl))
+ rc.Error(Parents[j].Parent,
+ "{0} occurs more than once as parent",
+ Parents[j].Parent.Decl);
+ }
+ }
+ }
+ }
+ }
+ public override void Typecheck(TypecheckingContext! tc)
+ {
+ base.Typecheck(tc);
+
+ if (Parents != null) {
+ foreach (ConstantParent! p in Parents) {
+ p.Parent.Typecheck(tc);
+ if (!((!)p.Parent.Decl).TypedIdent.Type.Unify(this.TypedIdent.Type))
+ tc.Error(p.Parent,
+ "parent of constant has incompatible type ({0} instead of {1})",
+ p.Parent.Decl.TypedIdent.Type, this.TypedIdent.Type);
+ }
+ }
+ }
+
+ public override Absy! StdDispatch(StandardVisitor! visitor)
+ {
+ return visitor.VisitConstant(this);
+ }
+ }
+ public class GlobalVariable : Variable
+ {
+ public GlobalVariable(IToken! tok, TypedIdent! typedIdent)
+ : base(tok, typedIdent)
+ {
+ }
+ public GlobalVariable(IToken! tok, TypedIdent! typedIdent, QKeyValue kv)
+ : base(tok, typedIdent, kv)
+ {
+ }
+ public override bool IsMutable
+ {
+ get
+ {
+ return true;
+ }
+ }
+ public override void Register(ResolutionContext! rc)
+ {
+ rc.AddVariable(this, true);
+ }
+
+ public override Absy! StdDispatch(StandardVisitor! visitor)
+ {
+ return visitor.VisitGlobalVariable(this);
+ }
+ }
+ public class Formal : Variable
+ {
+ public bool InComing;
+ public Formal(IToken! tok, TypedIdent! typedIdent, bool incoming)
+ : base(tok, typedIdent)
+ {
+ InComing = incoming;
+ }
+ public override bool IsMutable
+ {
+ get
+ {
+ return !InComing;
+ }
+ }
+ public override void Register(ResolutionContext! rc)
+ {
+ rc.AddVariable(this, false);
+ }
+
+ /// <summary>
+ /// Given a sequence of Formal declarations, returns sequence of Formals like the given one but without where clauses.
+ /// The Type of each Formal is cloned.
+ /// </summary>
+ public static VariableSeq! StripWhereClauses(VariableSeq! w)
+ {
+ VariableSeq s = new VariableSeq();
+ foreach (Variable! v in w) {
+ Formal f = (Formal)v;
+ TypedIdent ti = f.TypedIdent;
+ s.Add(new Formal(f.tok, new TypedIdent(ti.tok, ti.Name, ti.Type.CloneUnresolved()), f.InComing));
+ }
+ return s;
+ }
+
+ public override Absy! StdDispatch(StandardVisitor! visitor)
+ {
+ return visitor.VisitFormal(this);
+ }
+ }
+ public class LocalVariable : Variable
+ {
+ public LocalVariable(IToken! tok, TypedIdent! typedIdent, QKeyValue kv)
+ {
+ base(tok, typedIdent, kv);
+ }
+ public LocalVariable(IToken! tok, TypedIdent! typedIdent)
+ {
+ base(tok, typedIdent, null);
+ }
+ public override bool IsMutable
+ {
+ get
+ {
+ return true;
+ }
+ }
+ public override void Register(ResolutionContext! rc)
+ {
+ rc.AddVariable(this, false);
+ }
+
+ public override Absy! StdDispatch(StandardVisitor! visitor)
+ {
+ return visitor.VisitLocalVariable(this);
+ }
+ }
+ public class Incarnation : LocalVariable
+ {
+ public int incarnationNumber;
+ public Incarnation(Variable! var, int i) :
+ base(
+ var.tok,
+ new TypedIdent(var.TypedIdent.tok,var.TypedIdent.Name + "@" + i,var.TypedIdent.Type)
+ )
+ {
+ incarnationNumber = i;
+ }
+
+ }
+ public class BoundVariable : Variable
+ {
+ public BoundVariable(IToken! tok, TypedIdent! typedIdent)
+ requires typedIdent.WhereExpr == null;
+ {
+ base(tok, typedIdent); // here for aesthetic reasons
+ }
+ public override bool IsMutable
+ {
+ get
+ {
+ return false;
+ }
+ }
+ public override void Register(ResolutionContext! rc)
+ {
+ rc.AddVariable(this, false);
+ }
+
+ public override Absy! StdDispatch(StandardVisitor! visitor)
+ {
+ return visitor.VisitBoundVariable(this);
+ }
+ }
+
+ // A generic variable. It is used for the LoopInvariantsOnDemand
+ public class SimpleVariable : Variable
+ {
+ public SimpleVariable(IToken! tok, TypedIdent! typedIdent)
+ {
+ base(tok, typedIdent); // here for aesthetic reasons
+ }
+
+ public override bool IsMutable
+ {
+ get
+ {
+ return false;
+ }
+ }
+
+ public override void Register(ResolutionContext! rc)
+ {
+ rc.AddVariable(this, false);
+ }
+ }
+
+ public abstract class DeclWithFormals : NamedDeclaration
+ {
+ public TypeVariableSeq! TypeParameters;
+ public /*readonly--except in StandardVisitor*/ VariableSeq! InParams, OutParams;
+
+ public DeclWithFormals (IToken! tok, string! name, TypeVariableSeq! typeParams,
+ VariableSeq! inParams, VariableSeq! outParams)
+ : base(tok, name)
+ {
+ this.TypeParameters = typeParams;
+ this.InParams = inParams;
+ this.OutParams = outParams;
+ // base(tok, name);
+ }
+
+ protected DeclWithFormals (DeclWithFormals! that)
+ : base(that.tok, (!) that.Name)
+ {
+ this.TypeParameters = that.TypeParameters;
+ this.InParams = that.InParams;
+ this.OutParams = that.OutParams;
+ // base(that.tok, (!) that.Name);
+ }
+
+ protected void EmitSignature (TokenTextWriter! stream)
+ {
+ Type.EmitOptionalTypeParams(stream, TypeParameters);
+ stream.Write("(");
+ InParams.Emit(stream);
+ stream.Write(")");
+
+ if (OutParams.Length > 0)
+ {
+ stream.Write(" returns (");
+ OutParams.Emit(stream);
+ stream.Write(")");
+ }
+ }
+
+ // Register all type parameters at the resolution context
+ protected void RegisterTypeParameters(ResolutionContext! rc) {
+ foreach (TypeVariable! v in TypeParameters)
+ rc.AddTypeBinder(v);
+ }
+
+ protected void SortTypeParams() {
+ TypeSeq! allTypes = InParams.ToTypeSeq;
+ allTypes.AddRange(OutParams.ToTypeSeq);
+ TypeParameters = Type.SortTypeParams(TypeParameters, allTypes, null);
+ }
+
+ /// <summary>
+ /// Adds the given formals to the current variable context, and then resolves
+ /// the types of those formals. Does NOT resolve the where clauses of the
+ /// formals.
+ /// Relies on the caller to first create, and later tear down, that variable
+ /// context.
+ /// </summary>
+ /// <param name="rc"></param>
+ protected void RegisterFormals(VariableSeq! formals, ResolutionContext! rc)
+ {
+ foreach (Formal! f in formals)
+ {
+ if (f.Name != TypedIdent.NoName)
+ {
+ rc.AddVariable(f, false);
+ }
+ f.Resolve(rc);
+ }
+ }
+
+ /// <summary>
+ /// Resolves the where clauses (and attributes) of the formals.
+ /// </summary>
+ /// <param name="rc"></param>
+ protected void ResolveFormals(VariableSeq! formals, ResolutionContext! rc)
+ {
+ foreach (Formal! f in formals)
+ {
+ f.ResolveWhere(rc);
+ }
+ }
+
+ public override void Typecheck(TypecheckingContext! tc) {
+ TypecheckAttributes(tc);
+ foreach (Formal! p in InParams) {
+ p.Typecheck(tc);
+ }
+ foreach (Formal! p in OutParams) {
+ p.Typecheck(tc);
+ }
+ }
+ }
+
+ public class Expansion {
+ public string? ignore; // when to ignore
+ public Expr! body;
+ public TypeVariableSeq! TypeParameters;
+ public Variable[]! formals;
+
+ public Expansion(string? ignore, Expr! body,
+ TypeVariableSeq! typeParams, Variable[]! formals)
+ {
+ this.ignore = ignore;
+ this.body = body;
+ this.TypeParameters = typeParams;
+ this.formals = formals;
+ }
+ }
+
+ public class Function : DeclWithFormals
+ {
+ public string? Comment;
+
+ // the body is only set if the function is declared with {:expand true}
+ public Expr Body;
+ public List<Expansion!>? expansions;
+ public bool doingExpansion;
+
+ private bool neverTrigger;
+ private bool neverTriggerComputed;
+
+ public Function(IToken! tok, string! name, VariableSeq! args, Variable! result)
+ {
+ this(tok, name, new TypeVariableSeq(), args, result, null);
+ }
+ public Function(IToken! tok, string! name, TypeVariableSeq! typeParams, VariableSeq! args, Variable! result)
+ {
+ this(tok, name, typeParams, args, result, null);
+ }
+ public Function(IToken! tok, string! name, VariableSeq! args, Variable! result,
+ string? comment)
+ {
+ this(tok, name, new TypeVariableSeq(), args, result, comment);
+ }
+ public Function(IToken! tok, string! name, TypeVariableSeq! typeParams, VariableSeq! args, Variable! result,
+ string? comment)
+ : base(tok, name, typeParams, args, new VariableSeq(result))
+ {
+ Comment = comment;
+ // base(tok, name, args, new VariableSeq(result));
+ }
+ public Function(IToken! tok, string! name, TypeVariableSeq! typeParams, VariableSeq! args, Variable! result,
+ string? comment, QKeyValue kv)
+ {
+ this(tok, name, typeParams, args, result, comment);
+ this.Attributes = kv;
+ }
+ public override void Emit(TokenTextWriter! stream, int level)
+ {
+ if (Comment != null) {
+ stream.WriteLine(this, level, "// " + Comment);
+ }
+ stream.Write(this, level, "function ");
+ EmitAttributes(stream);
+ if (CommandLineOptions.Clo.PrintWithUniqueASTIds) {
+ stream.Write("h{0}^^{1}", this.GetHashCode(), TokenTextWriter.SanitizeIdentifier(this.Name));
+ } else {
+ stream.Write("{0}", TokenTextWriter.SanitizeIdentifier(this.Name));
+ }
+ EmitSignature(stream);
+ if (Body != null) {
+ stream.WriteLine();
+ stream.WriteLine("{");
+ stream.Write(level+1, "");
+ Body.Emit(stream);
+ stream.WriteLine();
+ stream.WriteLine("}");
+ } else {
+ stream.WriteLine(";");
+ }
+ }
+ public override void Register(ResolutionContext! rc)
+ {
+ rc.AddProcedure(this);
+ }
+ public override void Resolve(ResolutionContext! rc)
+ {
+ int previousTypeBinderState = rc.TypeBinderState;
+ try {
+ RegisterTypeParameters(rc);
+ rc.PushVarContext();
+ RegisterFormals(InParams, rc);
+ RegisterFormals(OutParams, rc);
+ ResolveAttributes(rc);
+ if (Body != null)
+ Body.Resolve(rc);
+ rc.PopVarContext();
+ Type.CheckBoundVariableOccurrences(TypeParameters,
+ InParams.ToTypeSeq, OutParams.ToTypeSeq,
+ this.tok, "function arguments",
+ rc);
+ } finally {
+ rc.TypeBinderState = previousTypeBinderState;
+ }
+ SortTypeParams();
+ }
+ public override void Typecheck(TypecheckingContext! tc)
+ {
+ // PR: why was the base call left out previously?
+ base.Typecheck(tc);
+ // TypecheckAttributes(tc);
+ if (Body != null) {
+ Body.Typecheck(tc);
+ if (!((!)Body.Type).Unify(((!)OutParams[0]).TypedIdent.Type))
+ tc.Error(Body,
+ "function body with invalid type: {0} (expected: {1})",
+ Body.Type, ((!)OutParams[0]).TypedIdent.Type);
+ }
+ }
+
+ public bool NeverTrigger
+ {
+ get {
+ if (!neverTriggerComputed) {
+ this.CheckBooleanAttribute("never_pattern", ref neverTrigger);
+ neverTriggerComputed = true;
+ }
+ return neverTrigger;
+ }
+ }
+
+ public override Absy! StdDispatch(StandardVisitor! visitor)
+ {
+ return visitor.VisitFunction(this);
+ }
+ }
+
+ public class Requires : Absy, IPotentialErrorNode
+ {
+ public readonly bool Free;
+ public Expr! Condition;
+ public string? Comment;
+
+ // TODO: convert to use generics
+ private object errorData;
+ public object ErrorData {
+ get { return errorData; }
+ set { errorData = value; }
+ }
+ invariant errorData != null ==> errorData is string;
+
+ private MiningStrategy errorDataEnhanced;
+ public MiningStrategy ErrorDataEnhanced {
+ get { return errorDataEnhanced; }
+ set { errorDataEnhanced = value; }
+ }
+
+ public QKeyValue Attributes;
+
+ public String ErrorMessage {
+ get {
+ return QKeyValue.FindStringAttribute(Attributes, "msg");
+ }
+ }
+
+ public Requires(IToken! token, bool free, Expr! condition, string? comment, QKeyValue kv)
+ : base(token)
+ {
+ this.Free = free;
+ this.Condition = condition;
+ this.Comment = comment;
+ this.Attributes = kv;
+ // base(token);
+ }
+
+ public Requires(IToken! token, bool free, Expr! condition, string? comment)
+ {
+ this(token, free, condition, comment, null);
+ }
+
+ public Requires(bool free, Expr! condition)
+ {
+ this(Token.NoToken, free, condition, null);
+ }
+
+ public Requires(bool free, Expr! condition, string? comment)
+ {
+ this(Token.NoToken, free, condition, comment);
+ }
+
+ public void Emit(TokenTextWriter! stream, int level)
+ {
+ if (Comment != null) {
+ stream.WriteLine(this, level, "// " + Comment);
+ }
+ stream.Write(this, level, "{0}requires ", Free ? "free " : "");
+ this.Condition.Emit(stream);
+ stream.WriteLine(";");
+ }
+
+ public override void Resolve(ResolutionContext! rc)
+ {
+ this.Condition.Resolve(rc);
+ }
+
+ public override void Typecheck(TypecheckingContext! tc)
+ {
+ this.Condition.Typecheck(tc);
+ assert this.Condition.Type != null; // follows from postcondition of Expr.Typecheck
+ if (!this.Condition.Type.Unify(Type.Bool))
+ {
+ tc.Error(this, "preconditions must be of type bool");
+ }
+ }
+ }
+
+ public class Ensures : Absy, IPotentialErrorNode
+ {
+ public readonly bool Free;
+ public Expr! Condition;
+ public string? Comment;
+
+ // TODO: convert to use generics
+ private object errorData;
+ public object ErrorData {
+ get { return errorData; }
+ set { errorData = value; }
+ }
+ invariant errorData != null ==> errorData is string;
+
+ private MiningStrategy errorDataEnhanced;
+ public MiningStrategy ErrorDataEnhanced {
+ get { return errorDataEnhanced; }
+ set { errorDataEnhanced = value; }
+ }
+
+ public String ErrorMessage {
+ get {
+ return QKeyValue.FindStringAttribute(Attributes, "msg");
+ }
+ }
+
+ public QKeyValue Attributes;
+
+ public Ensures(IToken! token, bool free, Expr! condition, string? comment, QKeyValue kv)
+ : base(token)
+ {
+ this.Free = free;
+ this.Condition = condition;
+ this.Comment = comment;
+ this.Attributes = kv;
+ // base(token);
+ }
+
+ public Ensures(IToken! token, bool free, Expr! condition, string? comment)
+ {
+ this(token, free, condition, comment, null);
+ }
+
+ public Ensures(bool free, Expr! condition)
+ {
+ this(Token.NoToken, free, condition, null);
+ }
+
+ public Ensures(bool free, Expr! condition, string? comment)
+ {
+ this(Token.NoToken, free, condition, comment);
+ }
+
+ public void Emit(TokenTextWriter! stream, int level)
+ {
+ if (Comment != null) {
+ stream.WriteLine(this, level, "// " + Comment);
+ }
+ stream.Write(this, level, "{0}ensures ", Free ? "free " : "");
+ this.Condition.Emit(stream);
+ stream.WriteLine(";");
+ }
+
+ public override void Resolve(ResolutionContext! rc)
+ {
+ this.Condition.Resolve(rc);
+ }
+
+ public override void Typecheck(TypecheckingContext! tc)
+ {
+ this.Condition.Typecheck(tc);
+ assert this.Condition.Type != null; // follows from postcondition of Expr.Typecheck
+ if (!this.Condition.Type.Unify(Type.Bool))
+ {
+ tc.Error(this, "postconditions must be of type bool");
+ }
+ }
+ }
+
+ public class Procedure : DeclWithFormals
+ {
+ public RequiresSeq! Requires;
+ public IdentifierExprSeq! Modifies;
+ public EnsuresSeq! Ensures;
+
+ // Abstract interpretation: Procedure-specific invariants...
+ [Rep]
+ public readonly ProcedureSummary! Summary;
+
+ public static bool ShowSummaries = false;
+
+ public Procedure (
+ IToken! tok,
+ string! name,
+ TypeVariableSeq! typeParams,
+ VariableSeq! inParams,
+ VariableSeq! outParams,
+ RequiresSeq! @requires,
+ IdentifierExprSeq! @modifies,
+ EnsuresSeq! @ensures
+ )
+ {
+ this(tok, name, typeParams, inParams, outParams, @requires, @modifies, @ensures, null);
+ }
+
+ public Procedure (
+ IToken! tok,
+ string! name,
+ TypeVariableSeq! typeParams,
+ VariableSeq! inParams,
+ VariableSeq! outParams,
+ RequiresSeq! @requires,
+ IdentifierExprSeq! @modifies,
+ EnsuresSeq! @ensures,
+ QKeyValue kv
+ )
+ : base(tok, name, typeParams, inParams, outParams)
+ {
+ this.Requires = @requires;
+ this.Modifies = @modifies;
+ this.Ensures = @ensures;
+ this.Summary = new ProcedureSummary();
+ this.Attributes = kv;
+ }
+
+ public override void Emit(TokenTextWriter! stream, int level)
+ {
+ stream.Write(this, level, "procedure ");
+ EmitAttributes(stream);
+ stream.Write(this, level, "{0}", TokenTextWriter.SanitizeIdentifier(this.Name));
+ EmitSignature(stream);
+ stream.WriteLine(";");
+
+ level++;
+
+ foreach (Requires! e in this.Requires)
+ {
+ e.Emit(stream, level);
+ }
+
+ if (this.Modifies.Length > 0)
+ {
+ stream.Write(level, "modifies ");
+ this.Modifies.Emit(stream, false);
+ stream.WriteLine(";");
+ }
+
+ foreach (Ensures! e in this.Ensures)
+ {
+ e.Emit(stream, level);
+ }
+
+ if (ShowSummaries)
+ {
+ for (int s=0; s<this.Summary.Count; s++)
+ {
+ ProcedureSummaryEntry! entry = (!) 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();
+ }
+ }
+
+ stream.WriteLine();
+ stream.WriteLine();
+ }
+
+ public override void Register(ResolutionContext! rc)
+ {
+ rc.AddProcedure(this);
+ }
+ public override void Resolve(ResolutionContext! rc)
+ {
+ rc.PushVarContext();
+
+ foreach (IdentifierExpr! ide in Modifies)
+ {
+ ide.Resolve(rc);
+ }
+
+ int previousTypeBinderState = rc.TypeBinderState;
+ try {
+ RegisterTypeParameters(rc);
+
+ RegisterFormals(InParams, rc);
+ ResolveFormals(InParams, rc); // "where" clauses of in-parameters are resolved without the out-parameters in scope
+ foreach (Requires! e in Requires)
+ {
+ e.Resolve(rc);
+ }
+ RegisterFormals(OutParams, rc);
+ ResolveFormals(OutParams, rc); // "where" clauses of out-parameters are resolved with both in- and out-parametes in scope
+
+ rc.StateMode = ResolutionContext.State.Two;
+ foreach (Ensures! e in Ensures)
+ {
+ e.Resolve(rc);
+ }
+ rc.StateMode = ResolutionContext.State.Single;
+ ResolveAttributes(rc);
+
+ Type.CheckBoundVariableOccurrences(TypeParameters,
+ InParams.ToTypeSeq, OutParams.ToTypeSeq,
+ this.tok, "procedure arguments",
+ rc);
+
+ } finally {
+ rc.TypeBinderState = previousTypeBinderState;
+ }
+
+ rc.PopVarContext();
+
+ SortTypeParams();
+ }
+ public override void Typecheck(TypecheckingContext! tc)
+ {
+ base.Typecheck(tc);
+ foreach (IdentifierExpr! ide in Modifies)
+ {
+ assume ide.Decl != null;
+ if (!ide.Decl.IsMutable)
+ {
+ tc.Error(this, "modifies list contains constant: {0}", ide.Name);
+ }
+ ide.Typecheck(tc);
+ }
+ foreach (Requires! e in Requires)
+ {
+ e.Typecheck(tc);
+ }
+ foreach (Ensures! e in Ensures)
+ {
+ e.Typecheck(tc);
+ }
+ }
+
+ public override Absy! StdDispatch(StandardVisitor! visitor)
+ {
+ return visitor.VisitProcedure(this);
+ }
+ }
+
+ public class Implementation : DeclWithFormals
+ {
+ public VariableSeq! LocVars;
+ [Rep] public StmtList StructuredStmts;
+ [Rep] public List<Block!>! Blocks;
+ public Procedure Proc;
+
+ // Blocks before applying passification etc.
+ // Both are used only when /inline is set.
+ public List<Block!>? OriginalBlocks;
+ public VariableSeq? OriginalLocVars;
+
+ // Strongly connected components
+ private StronglyConnectedComponents<Block!> scc;
+ private bool BlockPredecessorsComputed;
+ public bool StronglyConnectedComponentsComputed
+ {
+ get
+ {
+ return this.scc != null;
+ }
+ }
+
+ public bool SkipVerification
+ {
+ get
+ {
+ bool verify = true;
+ ((!)this.Proc).CheckBooleanAttribute("verify", ref verify);
+ this.CheckBooleanAttribute("verify", ref verify);
+ if (!verify) {
+ return true;
+ }
+
+ if (CommandLineOptions.Clo.ProcedureInlining == CommandLineOptions.Inlining.MacroLike) {
+ Expr? inl = this.FindExprAttribute("inline");
+ if (inl == null) inl = this.Proc.FindExprAttribute("inline");
+ if (inl != null && inl is LiteralExpr && ((LiteralExpr)inl).isBigNum && ((LiteralExpr)inl).asBigNum.Signum > 0) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+ }
+
+ public Implementation(IToken! tok, string! name, TypeVariableSeq! typeParams,
+ VariableSeq! inParams, VariableSeq! outParams,
+ VariableSeq! localVariables, [Captured] StmtList! structuredStmts)
+ {
+ this(tok, name, typeParams, inParams, outParams, localVariables, structuredStmts, null);
+ }
+
+ public Implementation(IToken! tok, string! name, TypeVariableSeq! typeParams,
+ VariableSeq! inParams, VariableSeq! outParams,
+ VariableSeq! localVariables, [Captured] StmtList! structuredStmts, QKeyValue kv)
+ : base(tok, name, typeParams, inParams, outParams)
+ {
+ LocVars = localVariables;
+ StructuredStmts = structuredStmts;
+ BigBlocksResolutionContext ctx = new BigBlocksResolutionContext(structuredStmts);
+ Blocks = ctx.Blocks;
+ BlockPredecessorsComputed = false;
+ scc = null;
+ Attributes = kv;
+
+ // base(tok, name, inParams, outParams);
+ }
+
+ public Implementation(IToken! tok, string! name, TypeVariableSeq! typeParams,
+ VariableSeq! inParams, VariableSeq! outParams,
+ VariableSeq! localVariables, [Captured] List<Block!>! block)
+ {
+ this(tok, name, typeParams, inParams, outParams, localVariables, block, null);
+ }
+
+ public Implementation(IToken! tok, string! name, TypeVariableSeq! typeParams,
+ VariableSeq! inParams, VariableSeq! outParams,
+ VariableSeq! localVariables, [Captured] List<Block!>! blocks, QKeyValue kv)
+ : base(tok, name, typeParams, inParams, outParams)
+ {
+ LocVars = localVariables;
+ Blocks = blocks;
+ BlockPredecessorsComputed = false;
+ scc = null;
+ Attributes = kv;
+
+ //base(tok, name, inParams, outParams);
+ }
+
+ public override void Emit(TokenTextWriter! stream, int level)
+ {
+ stream.Write(this, level, "implementation ");
+ EmitAttributes(stream);
+ stream.Write(this, level, "{0}", TokenTextWriter.SanitizeIdentifier(this.Name));
+ EmitSignature(stream);
+ stream.WriteLine();
+
+ stream.WriteLine(level, "{0}", '{');
+
+ foreach (Variable! v in this.LocVars) {
+ v.Emit(stream, level + 1);
+ }
+
+ if (this.StructuredStmts != null && !CommandLineOptions.Clo.PrintInstrumented && !CommandLineOptions.Clo.PrintInlined) {
+ if (this.LocVars.Length > 0) {
+ stream.WriteLine();
+ }
+ if (CommandLineOptions.Clo.PrintUnstructured < 2) {
+ if (CommandLineOptions.Clo.PrintUnstructured == 1) {
+ stream.WriteLine(this, level+1, "/*** structured program:");
+ }
+ this.StructuredStmts.Emit(stream, level+1);
+ if (CommandLineOptions.Clo.PrintUnstructured == 1) {
+ stream.WriteLine(level+1, "**** end structured program */");
+ }
+ }
+ }
+
+ if (this.StructuredStmts == null || 1 <= CommandLineOptions.Clo.PrintUnstructured ||
+ CommandLineOptions.Clo.PrintInstrumented || CommandLineOptions.Clo.PrintInlined)
+ {
+ foreach (Block b in this.Blocks)
+ {
+ b.Emit(stream, level+1);
+ }
+ }
+
+ stream.WriteLine(level, "{0}", '}');
+
+ stream.WriteLine();
+ stream.WriteLine();
+ }
+ public override void Register(ResolutionContext! rc)
+ {
+ // nothing to register
+ }
+ public override void Resolve(ResolutionContext! rc)
+ {
+ if (Proc != null)
+ {
+ // already resolved
+ return;
+ }
+ DeclWithFormals dwf = rc.LookUpProcedure((!) this.Name);
+ Proc = dwf as Procedure;
+ if (dwf == null)
+ {
+ rc.Error(this, "implementation given for undeclared procedure: {0}", this.Name);
+ }
+ else if (Proc == null)
+ {
+ rc.Error(this, "implementations given for function, not procedure: {0}", this.Name);
+ }
+
+ int previousTypeBinderState = rc.TypeBinderState;
+ try {
+ RegisterTypeParameters(rc);
+
+ rc.PushVarContext();
+ RegisterFormals(InParams, rc);
+ RegisterFormals(OutParams, rc);
+
+ foreach (Variable! v in LocVars)
+ {
+ v.Register(rc);
+ v.Resolve(rc);
+ }
+ foreach (Variable! v in LocVars)
+ {
+ v.ResolveWhere(rc);
+ }
+
+ rc.StartProcedureContext();
+ foreach (Block b in Blocks)
+ {
+ b.Register(rc);
+ }
+
+ ResolveAttributes(rc);
+
+ rc.StateMode = ResolutionContext.State.Two;
+ foreach (Block b in Blocks)
+ {
+ b.Resolve(rc);
+ }
+ rc.StateMode = ResolutionContext.State.Single;
+
+ rc.EndProcedureContext();
+ rc.PopVarContext();
+
+ Type.CheckBoundVariableOccurrences(TypeParameters,
+ InParams.ToTypeSeq, OutParams.ToTypeSeq,
+ this.tok, "implementation arguments",
+ rc);
+ } finally {
+ rc.TypeBinderState = previousTypeBinderState;
+ }
+ SortTypeParams();
+ }
+ public override void Typecheck(TypecheckingContext! tc)
+ {
+ base.Typecheck(tc);
+
+ assume this.Proc != null;
+
+ if (this.TypeParameters.Length != Proc.TypeParameters.Length) {
+ tc.Error(this, "mismatched number of type parameters in procedure implementation: {0}",
+ this.Name);
+ } else {
+ // if the numbers of type parameters are different, it is
+ // difficult to compare the argument types
+ MatchFormals(this.InParams, Proc.InParams, "in", tc);
+ MatchFormals(this.OutParams, Proc.OutParams, "out", tc);
+ }
+
+ foreach (Variable! v in LocVars)
+ {
+ v.Typecheck(tc);
+ }
+ IdentifierExprSeq oldFrame = tc.Frame;
+ tc.Frame = Proc.Modifies;
+ foreach (Block b in Blocks)
+ {
+ b.Typecheck(tc);
+ }
+ assert tc.Frame == Proc.Modifies;
+ tc.Frame = oldFrame;
+ }
+ void MatchFormals(VariableSeq! implFormals, VariableSeq! procFormals,
+ string! inout, TypecheckingContext! tc)
+ {
+ if (implFormals.Length != procFormals.Length)
+ {
+ tc.Error(this, "mismatched number of {0}-parameters in procedure implementation: {1}",
+ inout, this.Name);
+ }
+ else
+ {
+ // unify the type parameters so that types can be compared
+ assert Proc != null;
+ assert this.TypeParameters.Length == Proc.TypeParameters.Length;
+
+ IDictionary<TypeVariable!, Type!>! subst1 =
+ new Dictionary<TypeVariable!, Type!> ();
+ IDictionary<TypeVariable!, Type!>! subst2 =
+ new Dictionary<TypeVariable!, Type!> ();
+
+ for (int i = 0; i < this.TypeParameters.Length; ++i) {
+ TypeVariable! newVar =
+ new TypeVariable (Token.NoToken, Proc.TypeParameters[i].Name);
+ subst1.Add(Proc.TypeParameters[i], newVar);
+ subst2.Add(this.TypeParameters[i], newVar);
+ }
+
+ for (int i = 0; i < implFormals.Length; i++)
+ {
+ // the names of the formals are allowed to change from the proc to the impl
+
+ // but types must be identical
+ Type t = ((Variable!)implFormals[i]).TypedIdent.Type.Substitute(subst2);
+ Type u = ((Variable!)procFormals[i]).TypedIdent.Type.Substitute(subst1);
+ if (!t.Equals(u))
+ {
+ string! a = (!) ((Variable!)implFormals[i]).Name;
+ string! b = (!) ((Variable!)procFormals[i]).Name;
+ string! c;
+ if (a == b) {
+ c = a;
+ } else {
+ c = String.Format("{0} (named {1} in implementation)", b, a);
+ }
+ tc.Error(this, "mismatched type of {0}-parameter in implementation {1}: {2}", inout, this.Name, c);
+ }
+ }
+ }
+ }
+
+ private Hashtable/*Variable->Expr*//*?*/ formalMap = null;
+ public void ResetImplFormalMap() {
+ this.formalMap = null;
+ }
+ public Hashtable /*Variable->Expr*/! GetImplFormalMap()
+ {
+ if (this.formalMap != null)
+ return this.formalMap;
+ else
+ {
+ Hashtable /*Variable->Expr*/! map = new Hashtable /*Variable->Expr*/ (InParams.Length + OutParams.Length);
+
+ assume this.Proc != null;
+ assume InParams.Length == Proc.InParams.Length;
+ for (int i = 0; i < InParams.Length; i++)
+ {
+ Variable! v = (!) InParams[i];
+ IdentifierExpr ie = new IdentifierExpr(v.tok, v);
+ Variable! pv = (!) Proc.InParams[i];
+ map.Add(pv, ie);
+ }
+ System.Diagnostics.Debug.Assert(OutParams.Length == Proc.OutParams.Length);
+ for (int i = 0; i < OutParams.Length; i++)
+ {
+ Variable! v = (!) OutParams[i];
+ IdentifierExpr ie = new IdentifierExpr(v.tok, v);
+ Variable! pv = (!) Proc.OutParams[i];
+ map.Add(pv, ie);
+ }
+ this.formalMap = map;
+
+ if (CommandLineOptions.Clo.PrintWithUniqueASTIds)
+ {
+ Console.WriteLine("Implementation.GetImplFormalMap on {0}:", this.Name);
+ using (TokenTextWriter stream = new TokenTextWriter("<console>", Console.Out, false))
+ {
+ foreach (DictionaryEntry e in map)
+ {
+ Console.Write(" ");
+ ((Variable!)e.Key).Emit(stream, 0);
+ Console.Write(" --> ");
+ ((Expr!)e.Value).Emit(stream);
+ Console.WriteLine();
+ }
+ }
+ }
+
+ return map;
+ }
+ }
+
+ /// <summary>
+ /// Instrument the blocks with the inferred invariants
+ /// </summary>
+ public override void InstrumentWithInvariants()
+ {
+ foreach (Block b in this.Blocks)
+ {
+ if (b.Lattice != null)
+ {
+ CmdSeq newCommands = new CmdSeq();
+
+ assert b.PreInvariant != null; /* If the pre-abstract state is null, then something is wrong */
+
+ Expr inv = (Expr) b.Lattice.ToPredicate(b.PreInvariant); /*b.PreInvariantBuckets.GetDisjunction(b.Lattice);*/
+ PredicateCmd cmd = CommandLineOptions.Clo.InstrumentWithAsserts ? (PredicateCmd)new AssertCmd(Token.NoToken,inv) : (PredicateCmd)new AssumeCmd(Token.NoToken, inv);
+ newCommands.Add(cmd);
+ newCommands.AddRange(b.Cmds);
+
+ assert b.PostInvariant != null; /* If the post-state is null, then something is wrong */
+
+ // if(b.Cmds.Length > 0) // If it is not an empty block
+ // {
+ inv = (Expr) b.Lattice.ToPredicate(b.PostInvariant);
+ cmd = CommandLineOptions.Clo.InstrumentWithAsserts ? (PredicateCmd)new AssertCmd(Token.NoToken,inv) : (PredicateCmd)new AssumeCmd(Token.NoToken, inv);
+ newCommands.Add(cmd);
+ // }
+
+ b.Cmds = newCommands;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Insert a statement "assume J", for an opportune J - loop invariant predicate - in the "widen" blocks
+ /// </summary>
+ override public void InstrumentWithLoopInvariantPredicates()
+ {
+ foreach(Block b in this.Blocks)
+ {
+ if(b.widenBlock) { // if it is the head of a loop
+ CmdSeq newCommands = new CmdSeq();
+
+ Block! entryBlock = b;
+
+ ICollection<Block!> connectedComponents = this.GetConnectedComponents(b); // Get the connected components from this block
+
+ // Duplicate the connected components.
+ // Note that as we duplicate all the nodes, in particular we have also to keep track of the *copy* of the entry node.
+ // This is the reason why we pass entryBlockByReference
+ ICollection<Block!> dupConnectedComponents = duplicate((!) connectedComponents, ref entryBlock);
+
+ Expr loopInvariantPredicate = new LoopPredicate(entryBlock, dupConnectedComponents); // Create a new predicate J_{b.Label}
+
+ PredicateCmd cmd = new AssumeCmd(Token.NoToken, loopInvariantPredicate);
+
+ newCommands.Add(cmd);
+ newCommands.AddRange(b.Cmds);
+
+ 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>
+ public ICollection<Block!> GetConnectedComponents(Block! startingBlock)
+ {
+ assert this.Blocks.Contains(startingBlock);
+
+ if(!this.BlockPredecessorsComputed)
+ ComputeStronglyConnectedComponents();
+
+#if DEBUG_PRINT
+ System.Console.WriteLine("* Strongly connected components * \n{0} \n ** ", scc);
+#endif
+
+ foreach(ICollection<Block!> component in (!) this.scc)
+ {
+ foreach(Block! b in component)
+ {
+ if(b == startingBlock) // We found the compontent that owns the startingblock
+ {
+ return component;
+ }
+ }
+ }
+
+ assert false; // if we are here, it means that the block is not in one of the components. This is an error.
+
+ return null; // unreachable code, just to please the compiler
+ }
+
+ /// <summary>
+ /// Compute the strongly connected compontents of the blocks in the implementation.
+ /// As a side effect, it also computes the "predecessor" relation for the block in the implementation
+ /// </summary>
+ override public void ComputeStronglyConnectedComponents()
+ {
+ if(!this.BlockPredecessorsComputed)
+ ComputedPredecessorsForBlocks();
+
+ Adjacency<Block!> next = new Adjacency<Block!>(Successors);
+ Adjacency<Block!> prev = new Adjacency<Block!>(Predecessors);
+
+ this.scc = new StronglyConnectedComponents<Block><Block!>(this.Blocks, next, prev);
+ scc.Compute();
+
+ foreach(Block! block in this.Blocks)
+ {
+ block.Predecessors = new BlockSeq();
+ }
+
+ }
+
+ /// <summary>
+ /// Reset the abstract stated computed before
+ /// </summary>
+ override public void ResetAbstractInterpretationState()
+ {
+ foreach(Block! b in this.Blocks)
+ {
+ b.ResetAbstractInterpretationState();
+ }
+ }
+
+ /// <summary>
+ /// A private method used as delegate for the strongly connected components.
+ /// It return, given a node, the set of its successors
+ /// </summary>
+ private IEnumerable/*<Block!>*/! Successors(Block! node)
+ {
+ GotoCmd gotoCmd = node.TransferCmd as GotoCmd;
+
+ if(gotoCmd != null)
+ { // If it is a gotoCmd
+ assert gotoCmd.labelTargets != null;
+
+ return gotoCmd.labelTargets;
+ }
+ else
+ { // otherwise must be a ReturnCmd
+ assert node.TransferCmd is ReturnCmd;
+
+ return new List<Block!>();
+ }
+ }
+
+ /// <summary>
+ /// A private method used as delegate for the strongly connected components.
+ /// It return, given a node, the set of its predecessors
+ /// </summary>
+ private IEnumerable/*<Block!>*/! Predecessors(Block! node)
+ {
+ assert this.BlockPredecessorsComputed;
+
+ return node.Predecessors;
+ }
+
+ /// <summary>
+ /// Compute the predecessor informations for the blocks
+ /// </summary>
+ private void ComputedPredecessorsForBlocks()
+ {
+ foreach (Block b in this.Blocks)
+ {
+ GotoCmd gtc = b.TransferCmd as GotoCmd;
+ if (gtc != null)
+ {
+ assert gtc.labelTargets != null;
+ foreach (Block! dest in gtc.labelTargets)
+ {
+ dest.Predecessors.Add(b);
+ }
+ }
+ }
+ this.BlockPredecessorsComputed = true;
+ }
+
+ /// <summary>
+ /// Make a deep copy of the set of blocks in the input.
+ /// The input must NOT contain two copies of the same block
+ /// </summary>
+ private ICollection<Block!>! duplicate(ICollection<Block!>! blocks, ref Block! head)
+ {
+ Dictionary<Block!, Block!> transMap = new Dictionary<Block!, Block!>(); // A map from the old block to a fresh one
+
+ foreach(Block! block in blocks) // Create fresh copies for the blocks
+ {
+ Block! freshBlock = new Block(block.tok, block.Label, block.Cmds, block.TransferCmd); // Construct a copy of the block
+ freshBlock.widenBlock = block.widenBlock;
+ freshBlock.Predecessors = new BlockSeq();
+ transMap.Add(block, freshBlock); // Add a link block -> freshblock
+ }
+
+ foreach(Block! block in blocks) // Update the references
+ {
+ Block! freshBlock = transMap[block];
+
+ GotoCmd gotoCmd = freshBlock.TransferCmd as GotoCmd;
+ if(gotoCmd != null)
+ {
+ StringSeq! targetNames = new StringSeq();
+ BlockSeq! targetBlocks = new BlockSeq();
+
+ foreach(Block! next in (!) gotoCmd.labelTargets)
+ {
+ if(blocks.Contains(next))
+ {
+ assert transMap[next] != null;
+ targetNames.Add(next.Label);
+ targetBlocks.Add(transMap[next]);
+ }
+ }
+
+ GotoCmd freshGotoCmd = new GotoCmd(gotoCmd.tok, targetNames, targetBlocks);
+ freshBlock.TransferCmd = freshGotoCmd;
+ }
+ else
+ {
+ assert freshBlock.TransferCmd is ReturnCmd; // Do nothing as we do not need to update a returnCmd.
+ // However, as we want to make the code robust, we check that it is a ReturnCmd
+ }
+ }
+
+ head = transMap[head];
+
+ return transMap.Values;
+ }
+
+ public void PruneUnreachableBlocks() {
+ ArrayList /*Block!*/ visitNext = new ArrayList /*Block!*/ ();
+ List<Block!> reachableBlocks = new List<Block!>();
+ System.Compiler.IMutableSet /*Block!*/ reachable = new System.Compiler.HashSet /*Block!*/ (); // the set of elements in "reachableBlocks"
+
+ visitNext.Add(this.Blocks[0]);
+ while (visitNext.Count != 0) {
+ Block! b = (Block!)visitNext[visitNext.Count-1];
+ visitNext.RemoveAt(visitNext.Count-1);
+ if (!reachable.Contains(b)) {
+ reachableBlocks.Add(b);
+ reachable.Add(b);
+ if (b.TransferCmd is GotoCmd) {
+ foreach (Cmd! s in b.Cmds) {
+ if (s is PredicateCmd) {
+ LiteralExpr e = ((PredicateCmd)s).Expr as LiteralExpr;
+ if (e != null && e.IsFalse) {
+ // This statement sequence will never reach the end, because of this "assume false" or "assert false".
+ // Hence, it does not reach its successors.
+ b.TransferCmd = new ReturnCmd(b.TransferCmd.tok);
+ goto NEXT_BLOCK;
+ }
+ }
+ }
+ // it seems that the goto statement at the end may be reached
+ foreach (Block! succ in (!)((GotoCmd)b.TransferCmd).labelTargets) {
+ visitNext.Add(succ);
+ }
+ }
+ }
+ NEXT_BLOCK: {}
+ }
+
+ this.Blocks = reachableBlocks;
+ }
+
+ public override Absy! StdDispatch(StandardVisitor! visitor)
+ {
+ return visitor.VisitImplementation(this);
+ }
+ }
+
+
+ public class TypedIdent : Absy
+ {
+ public const string NoName = "";
+ public string! Name;
+ public Type! Type;
+ public Expr WhereExpr;
+ // [NotDelayed]
+ public TypedIdent (IToken! tok, string! name, Type! type)
+ ensures this.WhereExpr == null; //PM: needed to verify BoogiePropFactory.FreshBoundVariable
+ {
+ this(tok, name, type, null); // here for aesthetic reasons
+ }
+ // [NotDelayed]
+ public TypedIdent (IToken! tok, string! name, Type! type, Expr whereExpr)
+ : base(tok)
+ ensures this.WhereExpr == whereExpr;
+ {
+ this.Name = name;
+ this.Type = type;
+ this.WhereExpr = whereExpr;
+ // base(tok);
+ }
+ public bool HasName {
+ get {
+ return this.Name != NoName;
+ }
+ }
+ public void Emit(TokenTextWriter! stream)
+ {
+ stream.SetToken(this);
+ if (this.Name != NoName)
+ {
+ stream.Write("{0}: ", TokenTextWriter.SanitizeIdentifier(this.Name));
+ }
+ this.Type.Emit(stream);
+ if (this.WhereExpr != null)
+ {
+ stream.Write(" where ");
+ this.WhereExpr.Emit(stream);
+ }
+ }
+ public override void Resolve(ResolutionContext! rc)
+ {
+// this.Type.Resolve(rc);
+ // NOTE: WhereExpr needs to be resolved by the caller, because the caller must provide a modified ResolutionContext
+ this.Type = this.Type.ResolveType(rc);
+ }
+ public override void Typecheck(TypecheckingContext! tc)
+ {
+// type variables can occur when working with polymorphic functions/procedures
+// if (!this.Type.IsClosed)
+// tc.Error(this, "free variables in type of an identifier: {0}",
+// this.Type.FreeVariables);
+ if (this.WhereExpr != null) {
+ this.WhereExpr.Typecheck(tc);
+ assert this.WhereExpr.Type != null; // follows from postcondition of Expr.Typecheck
+ if (!this.WhereExpr.Type.Unify(Type.Bool))
+ {
+ tc.Error(this, "where clauses must be of type bool");
+ }
+ }
+ }
+
+ public override Absy! StdDispatch(StandardVisitor! visitor)
+ {
+ return visitor.VisitTypedIdent(this);
+ }
+ }
+
+ /// <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)
+ {
+ 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) {
+ 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) {
+ Expr[] e = new Expr[a.Count];
+ int i = 0;
+ foreach (AI.IExpr! aei in a) {
+ 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)
+ {
+// 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
+ //---------------------------------------------------------------------
+
+ public sealed class TypedIdentSeq : PureCollections.Sequence
+ {
+ public TypedIdentSeq(params Type[]! args) : base(args) { }
+ public new TypedIdent this[int index]
+ {
+ get
+ {
+ return (TypedIdent)base[index];
+ }
+ set
+ {
+ base[index] = value;
+ }
+ }
+ }
+
+ public sealed class RequiresSeq : PureCollections.Sequence
+ {
+ public RequiresSeq(params Requires[]! args) : base(args) { }
+ public new Requires! this[int index]
+ {
+ get
+ {
+ return (Requires!) base[index];
+ }
+ set
+ {
+ base[index] = value;
+ }
+ }
+ }
+
+ public sealed class EnsuresSeq : PureCollections.Sequence
+ {
+ public EnsuresSeq(params Ensures[]! args) : base(args) { }
+ public new Ensures! this[int index]
+ {
+ get
+ {
+ return (Ensures!) base[index];
+ }
+ set
+ {
+ base[index] = value;
+ }
+ }
+ }
+
+ public sealed class VariableSeq : PureCollections.Sequence
+ {
+ public VariableSeq(params Variable[]! args)
+ : base(args)
+ {
+ }
+ public VariableSeq(VariableSeq! varSeq)
+ : base(varSeq)
+ {
+ }
+ public new Variable this[int index]
+ {
+ get
+ {
+ return (Variable)base[index];
+ }
+ set
+ {
+ base[index] = value;
+ }
+ }
+ public void Emit(TokenTextWriter! stream)
+ {
+ string sep = "";
+ foreach (Variable! v in this)
+ {
+ stream.Write(sep);
+ sep = ", ";
+ v.EmitVitals(stream, 0);
+ }
+ }
+ public TypeSeq! ToTypeSeq { get {
+ TypeSeq! res = new TypeSeq ();
+ foreach(Variable! v in this)
+ res.Add(v.TypedIdent.Type);
+ return res;
+ } }
+ }
+
+ public sealed class TypeSeq : PureCollections.Sequence
+ {
+ public TypeSeq(params Type[]! args)
+ : base(args)
+ {
+ }
+ public TypeSeq(TypeSeq! varSeq)
+ : base(varSeq)
+ {
+ }
+ public new Type! this[int index]
+ {
+ get
+ {
+ return (Type!)base[index];
+ }
+ set
+ {
+ base[index] = value;
+ }
+ }
+ public List<Type!>! ToList() {
+ List<Type!>! res = new List<Type!> (Length);
+ foreach (Type! t in this)
+ res.Add(t);
+ return res;
+ }
+ public void Emit(TokenTextWriter! stream, string! separator)
+ {
+ string sep = "";
+ foreach (Type! v in this)
+ {
+ stream.Write(sep);
+ sep = separator;
+ v.Emit(stream);
+ }
+ }
+ }
+
+ public sealed class TypeVariableSeq : PureCollections.Sequence
+ {
+ public TypeVariableSeq(params TypeVariable[]! args)
+ : base(args)
+ {
+ }
+ public TypeVariableSeq(TypeVariableSeq! varSeq)
+ : base(varSeq)
+ {
+ }
+/* PR: the following two constructors cause Spec# crashes
+ public TypeVariableSeq(TypeVariable! var)
+ : base(new TypeVariable! [] { var })
+ {
+ }
+ public TypeVariableSeq()
+ : base(new TypeVariable![0])
+ {
+ } */
+ public new TypeVariable! this[int index]
+ {
+ get
+ {
+ return (TypeVariable!)base[index];
+ }
+ set
+ {
+ base[index] = value;
+ }
+ }
+ public void AppendWithoutDups(TypeVariableSeq! s1) {
+ for (int i = 0; i < s1.card; i++) {
+ TypeVariable! next = s1[i];
+ if (!this.Has(next)) this.Add(next);
+ }
+ }
+ public void Emit(TokenTextWriter! stream, string! separator)
+ {
+ string sep = "";
+ foreach (TypeVariable! v in this)
+ {
+ stream.Write(sep);
+ sep = separator;
+ v.Emit(stream);
+ }
+ }
+ public new TypeVariable[]! ToArray() {
+ TypeVariable[]! n = new TypeVariable[Length];
+ int ct = 0;
+ foreach (TypeVariable! var in this)
+ n[ct++] = var;
+ return n;
+ }
+ public List<TypeVariable!>! ToList() {
+ List<TypeVariable!>! res = new List<TypeVariable!> (Length);
+ foreach (TypeVariable! var in this)
+ res.Add(var);
+ return res;
+ }
+ }
+
+ public sealed class IdentifierExprSeq : PureCollections.Sequence
+ {
+ public IdentifierExprSeq(params IdentifierExpr[]! args)
+ : base(args)
+ {
+ }
+ public IdentifierExprSeq(IdentifierExprSeq! ideSeq)
+ : base(ideSeq)
+ {
+ }
+ public new IdentifierExpr! this[int index]
+ {
+ get
+ {
+ return (IdentifierExpr!)base[index];
+ }
+ set
+ {
+ base[index] = value;
+ }
+ }
+
+ public void Emit(TokenTextWriter! stream, bool printWhereComments)
+ {
+ string sep = "";
+ foreach (IdentifierExpr! e in this)
+ {
+ stream.Write(sep);
+ sep = ", ";
+ e.Emit(stream);
+
+ if (printWhereComments && e.Decl != null && e.Decl.TypedIdent.WhereExpr != null) {
+ stream.Write(" /* where ");
+ e.Decl.TypedIdent.WhereExpr.Emit(stream);
+ stream.Write(" */");
+ }
+ }
+ }
+ }
+
+
+ public sealed class CmdSeq : PureCollections.Sequence
+ {
+ public CmdSeq(params Cmd[]! args) : base(args){}
+ public CmdSeq(CmdSeq! cmdSeq)
+ : base(cmdSeq)
+ {
+ }
+ public new Cmd! this[int index]
+ {
+ get
+ {
+ return (Cmd!)base[index];
+ }
+ set
+ {
+ base[index] = value;
+ }
+ }
+ }
+
+ public sealed class ExprSeq : PureCollections.Sequence
+ {
+ public ExprSeq(params Expr[]! args)
+ : base(args)
+ {
+ }
+ public ExprSeq(ExprSeq! exprSeq)
+ : base(exprSeq)
+ {
+ }
+ public new Expr this[int index]
+ {
+ get
+ {
+ return (Expr)base[index];
+ }
+ set
+ {
+ base[index] = value;
+ }
+ }
+
+ public new Expr Last() { return (Expr)base.Last(); }
+
+ public static ExprSeq operator +(ExprSeq a, ExprSeq b)
+ {
+ if (a==null) throw new ArgumentNullException("a");
+ if (b==null) throw new ArgumentNullException("b");
+ return Append(a,b);
+ }
+
+ public static ExprSeq Append(ExprSeq! s, ExprSeq! t)
+ {
+ Expr[] n = new Expr[s.card+t.card];
+ for (int i = 0; i< s.card; i++) n[i] = s[i];
+ for (int i = 0; i< t.card; i++) n[s.card+i] = t[i];
+ return new ExprSeq(n);
+ }
+ public void Emit(TokenTextWriter! stream)
+ {
+ string sep = "";
+ foreach (Expr! e in this)
+ {
+ stream.Write(sep);
+ sep = ", ";
+ e.Emit(stream);
+ }
+ }
+ public TypeSeq! ToTypeSeq { get {
+ TypeSeq! res = new TypeSeq ();
+ foreach(Expr e in this)
+ res.Add(((!)e).Type);
+ return res;
+ } }
+ }
+
+ public sealed class TokenSeq : PureCollections.Sequence
+ {
+ public TokenSeq(params Token[]! args)
+ : base(args)
+ {
+ }
+ public new Token this[int index]
+ {
+ get
+ {
+ return (Token)base[index];
+ }
+ set
+ {
+ base[index] = value;
+ }
+ }
+ }
+
+ public sealed class StringSeq : PureCollections.Sequence
+ {
+ public StringSeq(params string[]! args)
+ : base(args)
+ {
+ }
+ public new String this[int index]
+ {
+ get
+ {
+ return (String)base[index];
+ }
+ set
+ {
+ base[index] = value;
+ }
+ }
+ public void Emit(TokenTextWriter! stream)
+ {
+ string sep = "";
+ foreach (string! s in this)
+ {
+ stream.Write(sep);
+ sep = ", ";
+ stream.Write(s);
+ }
+ }
+ }
+
+ public sealed class BlockSeq : PureCollections.Sequence
+ {
+ public BlockSeq(params Block[]! args)
+ : base(args)
+ {
+ }
+ public BlockSeq(BlockSeq! blockSeq)
+ : base(blockSeq)
+ {
+ }
+
+ public new Block this[int index]
+ {
+ get
+ {
+ return (Block)base[index];
+ }
+ set
+ {
+ base[index] = value;
+ }
+ }
+ }
+
+ public static class Emitter {
+ public static void Declarations(List<Declaration!>! decls, TokenTextWriter! stream)
+ {
+ bool first = true;
+ foreach (Declaration d in decls)
+ {
+ if (d == null) continue;
+ if (first)
+ {
+ first = false;
+ }
+ else
+ {
+ stream.WriteLine();
+ }
+ d.Emit(stream, 0);
+ }
+ }
+ }
+ public sealed class DeclarationSeq : PureCollections.Sequence
+ {
+ public DeclarationSeq(params string[]! args)
+ : base(args)
+ {
+ }
+ public new Declaration this[int index]
+ {
+ get
+ {
+ return (Declaration)base[index];
+ }
+ set
+ {
+ base[index] = value;
+ }
+ }
+ public void Emit(TokenTextWriter! stream)
+ {
+ bool first = true;
+ foreach (Declaration d in this)
+ {
+ if (d == null) continue;
+ if (first)
+ {
+ first = false;
+ }
+ else
+ {
+ stream.WriteLine();
+ }
+ d.Emit(stream, 0);
+ }
+ }
+ public void InstrumentWithInvariants ()
+ {
+ foreach (Declaration! d in this)
+ {
+ d.InstrumentWithInvariants();
+ }
+ }
+ }
+ #endregion
+
+
+ #region Regular Expressions
+ // a data structure to recover the "program structure" from the flow graph
+ public sealed class RESeq : PureCollections.Sequence
+ {
+ public RESeq(params RE[]! args)
+ : base (args)
+ {
+ }
+ public RESeq(RESeq! reSeq)
+ : base(reSeq)
+ {
+ }
+ public new RE this[int index]
+ {
+ get
+ {
+ return (RE)base[index];
+ }
+ set
+ {
+ base[index] = value;
+ }
+ }
+ // public void Emit(TokenTextWriter stream)
+ // {
+ // string sep = "";
+ // foreach (RE e in this)
+ // {
+ // stream.Write(sep);
+ // sep = ", ";
+ // e.Emit(stream);
+ // }
+ // }
+ }
+ public abstract class RE : Cmd
+ {
+ public RE() : base(Token.NoToken) {}
+ public override void AddAssignedVariables(VariableSeq! vars) { throw new NotImplementedException(); }
+ }
+ public class AtomicRE : RE
+ {
+ public Block! b;
+ public AtomicRE(Block! block) { b = block; }
+ public override void Resolve(ResolutionContext! rc)
+ {
+ b.Resolve(rc);
+ }
+ public override void Typecheck(TypecheckingContext! tc)
+ {
+ b.Typecheck(tc);
+ }
+ public override void Emit(TokenTextWriter! stream, int level)
+ {
+ b.Emit(stream,level);
+ }
+
+ public override Absy! StdDispatch(StandardVisitor! visitor)
+ {
+ return visitor.VisitAtomicRE(this);
+ }
+ }
+ public abstract class CompoundRE : RE
+ {
+ public override void Resolve(ResolutionContext! rc)
+ {
+ return;
+ }
+ public override void Typecheck(TypecheckingContext! tc)
+ {
+ return;
+ }
+ }
+ public class Sequential : CompoundRE
+ {
+ public RE! first;
+ public RE! second;
+ public Sequential(RE! a, RE! b)
+ {
+ first = a;
+ second = b;
+ }
+ public override void Emit(TokenTextWriter! stream, int level)
+ {
+ stream.WriteLine();
+ stream.WriteLine("{0};", Indent(level));
+ first.Emit(stream,level+1);
+ second.Emit(stream,level+1);
+ }
+
+ public override Absy! StdDispatch(StandardVisitor! visitor)
+ {
+ return visitor.VisitSequential(this);
+ }
+ }
+ public class Choice : CompoundRE
+ {
+ public RESeq! rs;
+ public Choice(RESeq! operands)
+ {
+ rs = operands;
+ // base();
+ }
+ public override void Emit(TokenTextWriter! stream, int level)
+ {
+ stream.WriteLine();
+ stream.WriteLine("{0}[]", Indent(level));
+ foreach (RE! r in rs )
+ r.Emit(stream,level+1);
+ }
+
+ public override Absy! StdDispatch(StandardVisitor! visitor)
+ {
+ return visitor.VisitChoice(this);
+ }
+ }
+ public class DAG2RE
+ {
+ public static RE! Transform(Block! b)
+ {
+ TransferCmd tc = b.TransferCmd;
+ if ( tc is ReturnCmd )
+ {
+ return new AtomicRE(b);
+ }
+ else if ( tc is GotoCmd )
+ {
+ GotoCmd! g = (GotoCmd) tc ;
+ assume g.labelTargets != null;
+ if ( g.labelTargets.Length == 1 )
+ {
+ return new Sequential(new AtomicRE(b),Transform( (!) g.labelTargets[0]));
+ }
+ else
+ {
+ RESeq rs = new RESeq();
+ foreach (Block! target in g.labelTargets )
+ {
+ RE r = Transform(target);
+ rs.Add(r);
+ }
+ RE second = new Choice(rs);
+ return new Sequential(new AtomicRE(b),second);
+ }
+ }
+ else
+ {
+ assume false;
+ return new AtomicRE(b);
+ }
+ }
+ }
+
+ #endregion
+
+ // NOTE: This class is here for convenience, since this file's
+ // classes are used pretty much everywhere.
+
+ public class BoogieDebug
+ {
+ public static bool DoPrinting = false;
+
+ public static void Write (string! format, params object[]! args)
+ {
+ if (DoPrinting) { Console.Error.Write(format, args); }
+ }
+
+ public static void WriteLine (string! format, params object[]! args)
+ {
+ if (DoPrinting) { Console.Error.WriteLine(format, args); }
+ }
+
+ public static void WriteLine () { if (DoPrinting) { Console.Error.WriteLine(); } }
+ }
+
+}
diff --git a/Source/Core/AbsyCmd.ssc b/Source/Core/AbsyCmd.ssc
new file mode 100644
index 00000000..5fb97548
--- /dev/null
+++ b/Source/Core/AbsyCmd.ssc
@@ -0,0 +1,2389 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------------
+// BoogiePL - Absy.cs
+//---------------------------------------------------------------------------------------------
+
+namespace Microsoft.Boogie
+{
+ using System;
+ using System.Collections;
+ using System.Diagnostics;
+ using System.Collections.Generic;
+ using Microsoft.Boogie.AbstractInterpretation;
+ using AI = Microsoft.AbstractInterpretationFramework;
+ using Microsoft.Contracts;
+
+
+ //---------------------------------------------------------------------
+ // BigBlock
+ public class BigBlock
+ {
+ public readonly IToken! tok;
+ public string LabelName;
+ public readonly bool Anonymous;
+ invariant !Anonymous ==> LabelName != null;
+ [Rep] public CmdSeq! simpleCmds;
+ public StructuredCmd ec;
+ public TransferCmd tc;
+ invariant ec == null || tc == null;
+ public BigBlock successorBigBlock; // null if successor is end of proceduure body (or if field has not yet been initialized)
+
+ public BigBlock(IToken! tok, string? labelName, [Captured] CmdSeq! simpleCmds, StructuredCmd? ec, TransferCmd? tc)
+ requires ec == null || tc == null;
+ {
+ this.tok = tok;
+ this.LabelName = labelName;
+ this.Anonymous = labelName == null;
+ this.simpleCmds = simpleCmds;
+ this.ec = ec;
+ this.tc = tc;
+ }
+
+ public void Emit(TokenTextWriter! stream, int level) {
+ if (!Anonymous) {
+ stream.WriteLine(level, "{0}:",
+ CommandLineOptions.Clo.PrintWithUniqueASTIds ? String.Format("h{0}^^{1}", this.GetHashCode(), this.LabelName) : this.LabelName);
+ }
+
+ foreach (Cmd! c in this.simpleCmds) {
+ c.Emit(stream, level+1);
+ }
+
+ if (this.ec != null) {
+ this.ec.Emit(stream, level+1);
+ } else if (this.tc != null) {
+ this.tc.Emit(stream, level+1);
+ }
+ }
+ }
+
+ public class StmtList
+ {
+ [Rep] public readonly List<BigBlock!>! BigBlocks;
+ public CmdSeq PrefixCommands;
+ public readonly IToken! EndCurly;
+ public StmtList ParentContext;
+ public BigBlock ParentBigBlock;
+ public Set<string!>! Labels = new Set<string!>();
+
+ public StmtList([Captured] List<BigBlock!>! bigblocks, IToken! endCurly)
+ requires bigblocks.Count > 0;
+ {
+ this.BigBlocks = bigblocks;
+ this.EndCurly = endCurly;
+ }
+
+ // prints the list of statements, not the surrounding curly braces
+ public void Emit(TokenTextWriter! stream, int level) {
+ bool needSeperator = false;
+ foreach (BigBlock b in BigBlocks) {
+ assume b.IsPeerConsistent;
+ if (needSeperator) {
+ stream.WriteLine();
+ }
+ b.Emit(stream, level);
+ needSeperator = true;
+ }
+ }
+
+ /// <summary>
+ /// Tries to insert the commands "prefixCmds" at the beginning of the first block
+ /// of the StmtList, and returns "true" iff it succeeded.
+ /// In the event of success, the "suggestedLabel" returns as the name of the
+ /// block inside StmtList where "prefixCmds" were inserted. This name may be the
+ /// same as the one passed in, in case this StmtList has no preference as to what
+ /// to call its first block. In the event of failure, "suggestedLabel" is returned
+ /// as its input value.
+ /// Note, to be conservative (that is, ignoring the possible optimization that this
+ /// method enables), this method can do nothing and return false.
+ /// </summary>
+ public bool PrefixFirstBlock([Captured] CmdSeq! prefixCmds, ref string! suggestedLabel)
+ ensures !result ==> Owner.None(prefixCmds); // "prefixCmds" is captured only on success
+ {
+ assume PrefixCommands == null; // prefix has not been used
+
+ BigBlock bb0 = BigBlocks[0];
+ if (prefixCmds.Length == 0) {
+ // This is always a success, since there is nothing to insert. Now, decide
+ // which name to use for the first block.
+ if (bb0.Anonymous) {
+ bb0.LabelName = suggestedLabel;
+ } else {
+ assert bb0.LabelName != null;
+ suggestedLabel = bb0.LabelName;
+ }
+ return true;
+
+ } else {
+ // There really is something to insert. We can do this inline only if the first
+ // block is anonymous (which implies there is no branch to it from within the block).
+ if (bb0.Anonymous) {
+ PrefixCommands = prefixCmds;
+ bb0.LabelName = suggestedLabel;
+ return true;
+ } else {
+ return false;
+ }
+ }
+ }
+ }
+
+ /// <summary>
+ /// The AST for Boogie structured commands was designed to support backward compatibility with
+ /// the Boogie unstructured commands. This has made the structured commands hard to construct.
+ /// The StmtListBuilder class makes it easier to build structured commands.
+ /// </summary>
+ public class StmtListBuilder {
+ List<BigBlock!>! bigBlocks = new List<BigBlock!>();
+ string label;
+ CmdSeq simpleCmds;
+
+ void Dump(StructuredCmd scmd, TransferCmd tcmd)
+ requires scmd == null || tcmd == null;
+ ensures label == null && simpleCmds == null;
+ {
+ if (label == null && simpleCmds == null && scmd == null && tcmd == null) {
+ // nothing to do
+ } else {
+ if (simpleCmds == null) {
+ simpleCmds = new CmdSeq();
+ }
+ bigBlocks.Add(new BigBlock(Token.NoToken, label, simpleCmds, scmd, tcmd));
+ label = null;
+ simpleCmds = null;
+ }
+ }
+
+ /// <summary>
+ /// Collects the StmtList built so far and returns it. The StmtListBuilder should no longer
+ /// be used once this method has been invoked.
+ /// </summary>
+ public StmtList! Collect(IToken! endCurlyBrace) {
+ Dump(null, null);
+ if (bigBlocks.Count == 0) {
+ simpleCmds = new CmdSeq(); // the StmtList constructor doesn't like an empty list of BigBlock's
+ Dump(null, null);
+ }
+ return new StmtList(bigBlocks, endCurlyBrace);
+ }
+
+ public void Add(Cmd! cmd) {
+ if (simpleCmds == null) {
+ simpleCmds = new CmdSeq();
+ }
+ simpleCmds.Add(cmd);
+ }
+
+ public void Add(StructuredCmd! scmd) {
+ Dump(scmd, null);
+ }
+
+ public void Add(TransferCmd! tcmd) {
+ Dump(null, tcmd);
+ }
+
+ public void AddLabelCmd(string! label) {
+ Dump(null, null);
+ this.label = label;
+ }
+
+ public void AddLocalVariable(string! name) {
+ // TODO
+ }
+ }
+
+ class BigBlocksResolutionContext {
+ StmtList! stmtList;
+ [Peer] List<Block!> blocks;
+ string! prefix = "anon";
+ int anon = 0;
+ Set<string!> allLabels = new Set<string!>();
+
+ public BigBlocksResolutionContext(StmtList! stmtList) {
+ this.stmtList = stmtList;
+ }
+
+ public List<Block!>! Blocks {
+ get {
+ if (blocks == null) {
+ blocks = new List<Block!>();
+
+ int startErrorCount = BoogiePL.Errors.count;
+ // Check that there are no goto's into the middle of a block, and no break statement to a non-enclosing loop.
+ // Also, determine a good value for "prefix".
+ CheckLegalLabels(stmtList, null, null);
+
+ // fill in names of anonymous blocks
+ NameAnonymousBlocks(stmtList);
+
+ // determine successor blocks
+ RecordSuccessors(stmtList, null);
+
+ if (BoogiePL.Errors.count == startErrorCount) {
+ // generate blocks from the big blocks
+ CreateBlocks(stmtList, null);
+ }
+ }
+ return blocks;
+ }
+ }
+
+ void CheckLegalLabels(StmtList! stmtList, StmtList parentContext, BigBlock parentBigBlock)
+ requires parentContext == null <==> parentBigBlock == null;
+ requires stmtList.ParentContext == null; // it hasn't been set yet
+ modifies stmtList.*;
+ ensures stmtList.ParentContext == parentContext;
+ {
+ stmtList.ParentContext = parentContext;
+ stmtList.ParentBigBlock = parentBigBlock;
+
+ // record the labels declared in this StmtList
+ foreach (BigBlock b in stmtList.BigBlocks) {
+ if (b.LabelName != null) {
+ string n = b.LabelName;
+ if (n.StartsWith(prefix)) {
+ if (prefix.Length < n.Length && n[prefix.Length] == '0') {
+ prefix += "1";
+ } else {
+ prefix += "0";
+ }
+ }
+ stmtList.Labels.Add(b.LabelName);
+ }
+ }
+
+ // check that labels in this and nested StmtList's are legal
+ foreach (BigBlock b in stmtList.BigBlocks) {
+ // goto's must reference blocks in enclosing blocks
+ if (b.tc is GotoCmd) {
+ GotoCmd g = (GotoCmd)b.tc;
+ foreach (string! lbl in (!)g.labelNames) {
+ bool found = false;
+ for (StmtList sl = stmtList; sl != null; sl = sl.ParentContext) {
+ if (sl.Labels.Contains(lbl)) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ BoogiePL.Errors.SemErr(g.tok, "Error: goto label '" + lbl + "' is undefined or out of reach");
+ }
+ }
+ }
+
+ // break labels must refer to an enclosing while statement
+ else if (b.ec is BreakCmd) {
+ BreakCmd bcmd = (BreakCmd)b.ec;
+ assert bcmd.BreakEnclosure == null; // it hasn't been initialized yet
+ bool found = false;
+ for (StmtList sl = stmtList; sl.ParentBigBlock != null; sl = sl.ParentContext)
+ invariant sl != null;
+ {
+ BigBlock bb = sl.ParentBigBlock;
+
+ if (bcmd.Label == null) {
+ // a label-less break statement breaks out of the innermost enclosing while statement
+ if (bb.ec is WhileCmd) {
+ bcmd.BreakEnclosure = bb;
+ found = true;
+ break;
+ }
+ } else if (bcmd.Label == bb.LabelName) {
+ // a break statement with a label can break out of both if statements and while statements
+ if (bb.simpleCmds.Length == 0) {
+ // this is a good target: the label refers to the if/while statement
+ bcmd.BreakEnclosure = bb;
+ } else {
+ // the label of bb refers to the first statement of bb, which in which case is a simple statement, not an if/while statement
+ BoogiePL.Errors.SemErr(bcmd.tok, "Error: break label '" + bcmd.Label + "' must designate an enclosing statement");
+ }
+ found = true; // don't look any further, since we've found a matching label
+ break;
+ }
+ }
+ if (!found) {
+ if (bcmd.Label == null) {
+ BoogiePL.Errors.SemErr(bcmd.tok, "Error: break statement is not inside a loop");
+ } else {
+ BoogiePL.Errors.SemErr(bcmd.tok, "Error: break label '" + bcmd.Label + "' must designate an enclosing statement");
+ }
+ }
+ }
+
+ // recurse
+ else if (b.ec is WhileCmd) {
+ WhileCmd wcmd = (WhileCmd)b.ec;
+ CheckLegalLabels(wcmd.Body, stmtList, b);
+ } else {
+ for (IfCmd ifcmd = b.ec as IfCmd; ifcmd != null; ifcmd = ifcmd.elseIf) {
+ CheckLegalLabels(ifcmd.thn, stmtList, b);
+ if (ifcmd.elseBlock != null) {
+ CheckLegalLabels(ifcmd.elseBlock, stmtList, b);
+ }
+ }
+ }
+ }
+ }
+
+ void NameAnonymousBlocks(StmtList! stmtList) {
+ foreach (BigBlock b in stmtList.BigBlocks) {
+ if (b.LabelName == null) {
+ b.LabelName = prefix + anon;
+ anon++;
+ }
+ if (b.ec is WhileCmd) {
+ WhileCmd wcmd = (WhileCmd)b.ec;
+ NameAnonymousBlocks(wcmd.Body);
+ } else {
+ for (IfCmd ifcmd = b.ec as IfCmd; ifcmd != null; ifcmd = ifcmd.elseIf) {
+ NameAnonymousBlocks(ifcmd.thn);
+ if (ifcmd.elseBlock != null) {
+ NameAnonymousBlocks(ifcmd.elseBlock);
+ }
+ }
+ }
+ }
+ }
+
+ void RecordSuccessors(StmtList! stmtList, BigBlock successor) {
+ for (int i = stmtList.BigBlocks.Count; 0 <= --i; ) {
+ BigBlock big = stmtList.BigBlocks[i];
+ big.successorBigBlock = successor;
+
+ if (big.ec is WhileCmd) {
+ WhileCmd wcmd = (WhileCmd)big.ec;
+ RecordSuccessors(wcmd.Body, successor);
+ } else {
+ for (IfCmd ifcmd = big.ec as IfCmd; ifcmd != null; ifcmd = ifcmd.elseIf) {
+ RecordSuccessors(ifcmd.thn, successor);
+ if (ifcmd.elseBlock != null) {
+ RecordSuccessors(ifcmd.elseBlock, successor);
+ }
+ }
+ }
+
+ successor = big;
+ }
+ }
+
+ // If the enclosing context is a loop, then "runOffTheEndLabel" is the loop head label;
+ // otherwise, it is null.
+ void CreateBlocks(StmtList! stmtList, string runOffTheEndLabel)
+ requires blocks != null;
+ {
+ CmdSeq cmdPrefixToApply = stmtList.PrefixCommands;
+
+ int n = stmtList.BigBlocks.Count;
+ foreach (BigBlock b in stmtList.BigBlocks) {
+ n--;
+ assert b.LabelName != null;
+ CmdSeq theSimpleCmds;
+ if (cmdPrefixToApply == null) {
+ theSimpleCmds = b.simpleCmds;
+ } else {
+ theSimpleCmds = new CmdSeq();
+ theSimpleCmds.AddRange(cmdPrefixToApply);
+ theSimpleCmds.AddRange(b.simpleCmds);
+ cmdPrefixToApply = null; // now, we've used 'em up
+ }
+
+ if (b.tc != null) {
+ // this BigBlock has the very same components as a Block
+ assert b.ec == null;
+ Block block = new Block(b.tok, b.LabelName, theSimpleCmds, b.tc);
+ blocks.Add(block);
+
+ } else if (b.ec == null) {
+ TransferCmd trCmd;
+ if (n == 0 && runOffTheEndLabel != null) {
+ // goto the given label instead of the textual successor block
+ trCmd = new GotoCmd(stmtList.EndCurly, new StringSeq(runOffTheEndLabel));
+ } else {
+ trCmd = GotoSuccessor(stmtList.EndCurly, b);
+ }
+ Block block = new Block(b.tok, b.LabelName, theSimpleCmds, trCmd);
+ blocks.Add(block);
+
+ } else if (b.ec is BreakCmd) {
+ BreakCmd bcmd = (BreakCmd)b.ec;
+ assert bcmd.BreakEnclosure != null;
+ Block block = new Block(b.tok, b.LabelName, theSimpleCmds, GotoSuccessor(b.ec.tok, bcmd.BreakEnclosure));
+ blocks.Add(block);
+
+ } else if (b.ec is WhileCmd) {
+ WhileCmd wcmd = (WhileCmd)b.ec;
+ string loopHeadLabel = prefix + anon + "_LoopHead";
+ string! loopBodyLabel = prefix + anon + "_LoopBody";
+ string loopDoneLabel = prefix + anon + "_LoopDone";
+ anon++;
+
+ CmdSeq ssBody = new CmdSeq();
+ CmdSeq ssDone = new CmdSeq();
+ if (wcmd.Guard != null) {
+ ssBody.Add(new AssumeCmd(wcmd.tok, wcmd.Guard));
+ ssDone.Add(new AssumeCmd(wcmd.tok, Expr.Not(wcmd.Guard)));
+ }
+
+ // Try to squeeze in ssBody into the first block of wcmd.Body
+ bool bodyGuardTakenCareOf = wcmd.Body.PrefixFirstBlock(ssBody, ref loopBodyLabel);
+
+ // ... goto LoopHead;
+ Block block = new Block(b.tok, b.LabelName, theSimpleCmds, new GotoCmd(wcmd.tok, new StringSeq(loopHeadLabel)));
+ blocks.Add(block);
+
+ // LoopHead: assert/assume loop_invariant; goto LoopDone, LoopBody;
+ CmdSeq ssHead = new CmdSeq();
+ foreach (PredicateCmd inv in wcmd.Invariants) {
+ ssHead.Add(inv);
+ }
+ block = new Block(wcmd.tok, loopHeadLabel, ssHead, new GotoCmd(wcmd.tok, new StringSeq(loopDoneLabel, loopBodyLabel)));
+ blocks.Add(block);
+
+ if (!bodyGuardTakenCareOf) {
+ // LoopBody: assume guard; goto firstLoopBlock;
+ block = new Block(wcmd.tok, loopBodyLabel, ssBody, new GotoCmd(wcmd.tok, new StringSeq(wcmd.Body.BigBlocks[0].LabelName)));
+ blocks.Add(block);
+ }
+
+ // recurse to create the blocks for the loop body
+ CreateBlocks(wcmd.Body, loopHeadLabel);
+
+ // LoopDone: assume !guard; goto loopSuccessor;
+ TransferCmd trCmd;
+ if (n == 0 && runOffTheEndLabel != null) {
+ // goto the given label instead of the textual successor block
+ trCmd = new GotoCmd(wcmd.tok, new StringSeq(runOffTheEndLabel));
+ } else {
+ trCmd = GotoSuccessor(wcmd.tok, b);
+ }
+ block = new Block(wcmd.tok, loopDoneLabel, ssDone, trCmd);
+ blocks.Add(block);
+
+ } else {
+ IfCmd ifcmd = (IfCmd)b.ec;
+ string predLabel = b.LabelName;
+ CmdSeq predCmds = theSimpleCmds;
+
+ for (; ifcmd != null; ifcmd = ifcmd.elseIf) {
+ string! thenLabel = prefix + anon + "_Then";
+ string! elseLabel = prefix + anon + "_Else";
+ anon++;
+
+ CmdSeq ssThen = new CmdSeq();
+ CmdSeq ssElse = new CmdSeq();
+ if (ifcmd.Guard != null) {
+ ssThen.Add(new AssumeCmd(ifcmd.tok, ifcmd.Guard));
+ ssElse.Add(new AssumeCmd(ifcmd.tok, Expr.Not(ifcmd.Guard)));
+ }
+
+ // Try to squeeze in ssThen/ssElse into the first block of ifcmd.thn/ifcmd.elseBlock
+ bool thenGuardTakenCareOf = ifcmd.thn.PrefixFirstBlock(ssThen, ref thenLabel);
+ bool elseGuardTakenCareOf = false;
+ if (ifcmd.elseBlock != null) {
+ elseGuardTakenCareOf = ifcmd.elseBlock.PrefixFirstBlock(ssElse, ref elseLabel);
+ }
+
+ // ... goto Then, Else;
+ Block block = new Block(b.tok, predLabel, predCmds,
+ new GotoCmd(ifcmd.tok, new StringSeq(thenLabel, elseLabel)));
+ blocks.Add(block);
+
+ if (!thenGuardTakenCareOf) {
+ // Then: assume guard; goto firstThenBlock;
+ block = new Block(ifcmd.tok, thenLabel, ssThen, new GotoCmd(ifcmd.tok, new StringSeq(ifcmd.thn.BigBlocks[0].LabelName)));
+ blocks.Add(block);
+ }
+
+ // recurse to create the blocks for the then branch
+ CreateBlocks(ifcmd.thn, n == 0 ? runOffTheEndLabel : null);
+
+ if (ifcmd.elseBlock != null) {
+ assert ifcmd.elseIf == null;
+ if (!elseGuardTakenCareOf) {
+ // Else: assume !guard; goto firstElseBlock;
+ block = new Block(ifcmd.tok, elseLabel, ssElse, new GotoCmd(ifcmd.tok, new StringSeq(ifcmd.elseBlock.BigBlocks[0].LabelName)));
+ blocks.Add(block);
+ }
+
+ // recurse to create the blocks for the else branch
+ CreateBlocks(ifcmd.elseBlock, n == 0 ? runOffTheEndLabel : null);
+
+ } else if (ifcmd.elseIf != null) {
+ // this is an "else if"
+ predLabel = elseLabel;
+ predCmds = new CmdSeq();
+ if (ifcmd.Guard != null) {
+ predCmds.Add(new AssumeCmd(ifcmd.tok, Expr.Not(ifcmd.Guard)));
+ }
+
+ } else {
+ // no else alternative is specified, so else branch is just "skip"
+ // Else: assume !guard; goto ifSuccessor;
+ TransferCmd trCmd;
+ if (n == 0 && runOffTheEndLabel != null) {
+ // goto the given label instead of the textual successor block
+ trCmd = new GotoCmd(ifcmd.tok, new StringSeq(runOffTheEndLabel));
+ } else {
+ trCmd = GotoSuccessor(ifcmd.tok, b);
+ }
+ block = new Block(ifcmd.tok, elseLabel, ssElse, trCmd);
+ blocks.Add(block);
+ }
+ }
+ }
+ }
+ }
+
+ TransferCmd! GotoSuccessor(IToken! tok, BigBlock! b) {
+ if (b.successorBigBlock != null) {
+ return new GotoCmd(tok, new StringSeq(b.successorBigBlock.LabelName));
+ } else {
+ return new ReturnCmd(tok);
+ }
+ }
+ }
+
+ public abstract class StructuredCmd
+ {
+ public IToken! tok;
+ public StructuredCmd(IToken! tok)
+ {
+ this.tok = tok;
+ }
+
+ public abstract void Emit(TokenTextWriter! stream, int level);
+ }
+
+ public class IfCmd : StructuredCmd
+ {
+ public Expr? Guard;
+ public StmtList! thn;
+ public IfCmd? elseIf;
+ public StmtList elseBlock;
+ invariant elseIf == null || elseBlock == null;
+
+ public IfCmd(IToken! tok, Expr? guard, StmtList! thn, IfCmd? elseIf, StmtList elseBlock)
+ : base(tok)
+ requires elseIf == null || elseBlock == null;
+ {
+ this.Guard = guard;
+ this.thn = thn;
+ this.elseIf = elseIf;
+ this.elseBlock = elseBlock;
+ // base(tok);
+ }
+
+ public override void Emit(TokenTextWriter! stream, int level) {
+ stream.Write(level, "if (");
+ IfCmd! ifcmd = this;
+ while (true) {
+ if (ifcmd.Guard == null) {
+ stream.Write("*");
+ } else {
+ ifcmd.Guard.Emit(stream);
+ }
+ stream.WriteLine(")");
+
+ stream.WriteLine(level, "{");
+ ifcmd.thn.Emit(stream, level + 1);
+ stream.WriteLine(level, "}");
+
+ if (ifcmd.elseIf != null) {
+ stream.Write(level, "else if (");
+ ifcmd = ifcmd.elseIf;
+ continue;
+ } else if (ifcmd.elseBlock != null) {
+ stream.WriteLine(level, "else");
+ stream.WriteLine(level, "{");
+ ifcmd.elseBlock.Emit(stream, level + 1);
+ stream.WriteLine(level, "}");
+ }
+ break;
+ }
+ }
+ }
+
+ public class WhileCmd : StructuredCmd
+ {
+ [Peer] public Expr? Guard;
+ public List<PredicateCmd!>! Invariants;
+ public StmtList! Body;
+
+ public WhileCmd(IToken! tok, [Captured] Expr? guard, List<PredicateCmd!>! invariants, StmtList! body)
+ : base(tok)
+ {
+ this.Guard = guard;
+ this.Invariants = invariants;
+ this.Body = body;
+ /// base(tok);
+ }
+
+ public override void Emit(TokenTextWriter! stream, int level) {
+ stream.Write(level, "while (");
+ if (Guard == null) {
+ stream.Write("*");
+ } else {
+ Guard.Emit(stream);
+ }
+ stream.WriteLine(")");
+
+ foreach (PredicateCmd inv in Invariants) {
+ if (inv is AssumeCmd) {
+ stream.Write(level + 1, "free invariant ");
+ } else {
+ stream.Write(level + 1, "invariant ");
+ }
+ inv.Expr.Emit(stream);
+ stream.WriteLine(";");
+ }
+
+ stream.WriteLine(level, "{");
+ Body.Emit(stream, level + 1);
+ stream.WriteLine(level, "}");
+ }
+ }
+
+ public class BreakCmd : StructuredCmd
+ {
+ public string Label;
+ public BigBlock BreakEnclosure;
+
+ public BreakCmd(IToken! tok, string? label)
+ : base(tok)
+ {
+ this.Label = label;
+ // base(tok);
+ }
+
+ public override void Emit(TokenTextWriter! stream, int level) {
+ if (Label == null) {
+ stream.WriteLine(level, "break;");
+ } else {
+ stream.WriteLine(level, "break {0};", Label);
+ }
+ }
+ }
+
+ //---------------------------------------------------------------------
+ // Block
+ public sealed class Block : Absy
+ {
+ public readonly string! Label;
+ [Rep] [ElementsPeer] public CmdSeq! Cmds;
+ [Rep] //PM: needed to verify Traverse.Visit
+ public TransferCmd TransferCmd; // maybe null only because we allow deferred initialization (necessary for cyclic structures)
+
+ // Abstract interpretation
+
+ // public bool currentlyTraversed;
+
+ public enum VisitState {ToVisit, BeingVisited, AlreadyVisited}; // used by WidenPoints.Compute
+ public VisitState TraversingStatus;
+
+ 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 PreInvariant != null <==> PostInvariant != null;
+
+ // VC generation and SCC computation
+ public BlockSeq! Predecessors;
+
+ public Block() { this(Token.NoToken, "", new CmdSeq(), new ReturnCmd(Token.NoToken));}
+
+ public Block (IToken! tok, string! label, CmdSeq! cmds, TransferCmd transferCmd)
+ : base(tok)
+ {
+ this.Label = label;
+ this.Cmds = cmds;
+ this.TransferCmd = transferCmd;
+ this.PreInvariant = null;
+ this.PostInvariant = null;
+ this.Predecessors = new BlockSeq();
+ this.TraversingStatus = VisitState.ToVisit;
+ this.iterations = 0;
+ // base(tok);
+ }
+
+ public void Emit (TokenTextWriter! stream, int level)
+ {
+ stream.WriteLine();
+ stream.WriteLine(
+ this,
+ level,
+ "{0}:{1}",
+ CommandLineOptions.Clo.PrintWithUniqueASTIds ? String.Format("h{0}^^{1}", this.GetHashCode(), this.Label) : this.Label,
+ this.widenBlock ? " // cut point" : "");
+
+ foreach (Cmd! c in this.Cmds)
+ {
+ c.Emit(stream, level + 1);
+ }
+ assume this.TransferCmd != null;
+ this.TransferCmd.Emit(stream, level + 1);
+ }
+
+ public void Register (ResolutionContext! rc)
+ {
+ rc.AddBlock(this);
+ }
+
+ public override void Resolve (ResolutionContext! rc)
+ {
+ foreach (Cmd! c in Cmds)
+ {
+ c.Resolve(rc);
+ }
+ assume this.TransferCmd != null;
+ TransferCmd.Resolve(rc);
+ }
+
+ public override void Typecheck (TypecheckingContext! tc)
+ {
+ foreach (Cmd! c in Cmds)
+ {
+ c.Typecheck(tc);
+ }
+ assume this.TransferCmd != null;
+ TransferCmd.Typecheck(tc);
+ }
+
+ /// <summary>
+ /// Reset the abstract intepretation state of this block. It does this by putting the iterations to 0 and the pre and post states to null
+ /// </summary>
+ public void ResetAbstractInterpretationState()
+ {
+// this.currentlyTraversed = false;
+ this.TraversingStatus = VisitState.ToVisit;
+ this.iterations = 0;
+ this.Lattice = null;
+ this.PreInvariant = null;
+ this.PostInvariant = null;
+ }
+
+ [Pure][Reads(ReadsAttribute.Reads.Owned)]
+ public override string! ToString()
+ {
+ return this.Label + (this.widenBlock? "[w]" : "");
+ }
+
+ public override Absy! StdDispatch(StandardVisitor! visitor)
+ {
+ return visitor.VisitBlock(this);
+ }
+ }
+
+ //---------------------------------------------------------------------
+ // Commands
+
+ public abstract class Cmd : Absy
+ {
+ public Cmd(IToken! tok) : base(tok) { }
+ public abstract void Emit(TokenTextWriter! stream, int level);
+ public abstract void AddAssignedVariables(VariableSeq! vars);
+ public void CheckAssignments(TypecheckingContext! tc)
+ {
+ VariableSeq! vars = new VariableSeq();
+ this.AddAssignedVariables(vars);
+ foreach (Variable! v in vars)
+ {
+ if (!v.IsMutable)
+ {
+ tc.Error(this, "command assigns to an immutable variable: {0}", v.Name);
+ }
+ else if (v is GlobalVariable && !tc.InFrame(v))
+ {
+ tc.Error(this, "command assigns to a global variable that is not in the enclosing method's modifies clause: {0}", v.Name);
+ }
+ }
+ }
+
+ // Methods to simulate the old SimpleAssignCmd and MapAssignCmd
+ public static AssignCmd! SimpleAssign(IToken! tok, IdentifierExpr! lhs, Expr! rhs) {
+ List<AssignLhs!>! lhss = new List<AssignLhs!> ();
+ List<Expr!>! rhss = new List<Expr!> ();
+
+ lhss.Add(new SimpleAssignLhs (lhs.tok, lhs));
+ rhss.Add(rhs);
+
+ return new AssignCmd(tok, lhss, rhss);
+ }
+
+ public static AssignCmd! MapAssign(IToken! tok,
+ IdentifierExpr! map,
+ ExprSeq! indexes, Expr! rhs) {
+ List<AssignLhs!>! lhss = new List<AssignLhs!> ();
+ List<Expr!>! rhss = new List<Expr!> ();
+ List<Expr!>! indexesList = new List<Expr!> ();
+
+ foreach (Expr e in indexes)
+ indexesList.Add((!)e);
+
+ lhss.Add(new MapAssignLhs (map.tok,
+ new SimpleAssignLhs (map.tok, map),
+ indexesList));
+ rhss.Add(rhs);
+
+ return new AssignCmd(tok, lhss, rhss);
+ }
+
+ public static AssignCmd! MapAssign(IToken! tok,
+ IdentifierExpr! map,
+ params Expr[]! args)
+ requires args.Length > 0; // at least the rhs
+ requires forall{int i in (0:args.Length); args[i] != null};
+ {
+ List<AssignLhs!>! lhss = new List<AssignLhs!> ();
+ List<Expr!>! rhss = new List<Expr!> ();
+ List<Expr!>! indexesList = new List<Expr!> ();
+
+ for (int i = 0; i < args.Length - 1; ++i)
+ indexesList.Add((!)args[i]);
+
+ lhss.Add(new MapAssignLhs (map.tok,
+ new SimpleAssignLhs (map.tok, map),
+ indexesList));
+ rhss.Add((!)args[args.Length - 1]);
+
+ return new AssignCmd(tok, lhss, rhss);
+ }
+
+ }
+
+ public class CommentCmd : Cmd // just a convenience for debugging
+ {
+ public readonly string! Comment;
+ public CommentCmd (string! c)
+ : base(Token.NoToken)
+ {
+ Comment = c;
+ // base(Token.NoToken);
+ }
+ public override void Emit(TokenTextWriter! stream, int level)
+ {
+ if (this.Comment.Contains("\n")) {
+ stream.WriteLine(this, level, "/* {0} */", this.Comment);
+ } else {
+ stream.WriteLine(this, level, "// {0}", this.Comment);
+ }
+ }
+ public override void Resolve(ResolutionContext! rc) { }
+ public override void AddAssignedVariables(VariableSeq! vars) { }
+ public override void Typecheck(TypecheckingContext! tc) { }
+
+ public override Absy! StdDispatch(StandardVisitor! visitor)
+ {
+ return visitor.VisitCommentCmd(this);
+ }
+ }
+
+ // class for parallel assignments, which subsumes both the old
+ // SimpleAssignCmd and the old MapAssignCmd
+ public class AssignCmd : Cmd {
+ public List<AssignLhs!>! Lhss;
+ public List<Expr!>! Rhss;
+
+ public AssignCmd(IToken! tok, List<AssignLhs!>! lhss, List<Expr!>! rhss) {
+ base(tok);
+ Lhss = lhss;
+ Rhss = rhss;
+ }
+
+ public override void Emit(TokenTextWriter! stream, int level)
+ {
+ stream.Write(this, level, "");
+
+ string! sep = "";
+ foreach (AssignLhs! l in Lhss) {
+ stream.Write(sep);
+ sep = ", ";
+ l.Emit(stream);
+ }
+
+ stream.Write(" := ");
+
+ sep = "";
+ foreach (Expr! e in Rhss) {
+ stream.Write(sep);
+ sep = ", ";
+ e.Emit(stream);
+ }
+
+ stream.WriteLine(";");
+ }
+
+ public override void Resolve(ResolutionContext! rc)
+ {
+ if (Lhss.Count != Rhss.Count)
+ rc.Error(this,
+ "number of left-hand sides does not match number of right-hand sides");
+
+ foreach (AssignLhs! e in Lhss)
+ e.Resolve(rc);
+ foreach (Expr! e in Rhss)
+ e.Resolve(rc);
+
+ // check for double occurrences of assigned variables
+ // (could be optimised)
+ for (int i = 0; i < Lhss.Count; ++i) {
+ for (int j = i + 1; j < Lhss.Count; ++j) {
+ if (((!)Lhss[i].DeepAssignedVariable).Equals(
+ Lhss[j].DeepAssignedVariable))
+ rc.Error(Lhss[j],
+ "variable {0} is assigned more than once in parallel assignment",
+ Lhss[j].DeepAssignedVariable);
+ }
+ }
+ }
+
+ public override void Typecheck(TypecheckingContext! tc) {
+ foreach (AssignLhs! e in Lhss)
+ e.Typecheck(tc);
+ foreach (Expr! e in Rhss)
+ e.Typecheck(tc);
+
+ this.CheckAssignments(tc);
+
+ for (int i = 0; i < Lhss.Count; ++i) {
+ Type ltype = Lhss[i].Type;
+ Type rtype = Rhss[i].Type;
+ if (ltype != null && rtype != null) {
+ // otherwise, there has already been an error when
+ // typechecking the lhs or rhs
+ if (!ltype.Unify(rtype))
+ tc.Error(Lhss[i],
+ "mismatched types in assignment command (cannot assign {0} to {1})",
+ rtype, ltype);
+ }
+ }
+ }
+
+ public override void AddAssignedVariables(VariableSeq! vars)
+ {
+ foreach (AssignLhs! l in Lhss)
+ vars.Add(l.DeepAssignedVariable);
+ }
+
+ // transform away the syntactic sugar of map assignments and
+ // determine an equivalent assignment in which all rhs are simple
+ // variables
+ public AssignCmd! AsSimpleAssignCmd { get {
+ List<AssignLhs!>! newLhss = new List<AssignLhs!> ();
+ List<Expr!>! newRhss = new List<Expr!> ();
+
+ for (int i = 0; i < Lhss.Count; ++i) {
+ IdentifierExpr! newLhs;
+ Expr! newRhs;
+ Lhss[i].AsSimpleAssignment(Rhss[i], out newLhs, out newRhs);
+ newLhss.Add(new SimpleAssignLhs(Token.NoToken, newLhs));
+ newRhss.Add(newRhs);
+ }
+
+ return new AssignCmd(Token.NoToken, newLhss, newRhss);
+ } }
+
+ public override Absy! StdDispatch(StandardVisitor! visitor)
+ {
+ return visitor.VisitAssignCmd(this);
+ }
+ }
+
+ // There are two different kinds of left-hand sides in assignments:
+ // simple variables (identifiers), or locations of a map
+ public abstract class AssignLhs : Absy {
+ // The type of the lhs is determined during typechecking
+ public abstract Type Type { get; }
+ // Determine the variable that is actually assigned in this lhs
+ public abstract IdentifierExpr! DeepAssignedIdentifier { get; }
+ public abstract Variable DeepAssignedVariable { get; }
+
+ public AssignLhs(IToken! tok) : base(tok) {}
+ public abstract void Emit(TokenTextWriter! stream);
+
+ public abstract Expr! AsExpr { get; }
+
+ // transform away the syntactic sugar of map assignments and
+ // determine an equivalent simple assignment
+ internal abstract void AsSimpleAssignment(Expr! rhs,
+ out IdentifierExpr! simpleLhs,
+ out Expr! simpleRhs);
+ }
+
+ public class SimpleAssignLhs : AssignLhs {
+ public IdentifierExpr! AssignedVariable;
+
+ public override Type Type { get {
+ return AssignedVariable.Type;
+ } }
+
+ public override IdentifierExpr! DeepAssignedIdentifier { get {
+ return AssignedVariable;
+ } }
+
+ public override Variable DeepAssignedVariable { get {
+ return AssignedVariable.Decl;
+ } }
+
+ public SimpleAssignLhs(IToken! tok, IdentifierExpr! assignedVariable) {
+ base(tok);
+ AssignedVariable = assignedVariable;
+ }
+ public override void Resolve(ResolutionContext! rc) {
+ AssignedVariable.Resolve(rc);
+ }
+ public override void Typecheck(TypecheckingContext! tc) {
+ AssignedVariable.Typecheck(tc);
+ }
+ public override void Emit(TokenTextWriter! stream) {
+ AssignedVariable.Emit(stream);
+ }
+ public override Expr! AsExpr { get {
+ return AssignedVariable;
+ } }
+ internal override void AsSimpleAssignment(Expr! rhs,
+ out IdentifierExpr! simpleLhs,
+ out Expr! simpleRhs) {
+ simpleLhs = AssignedVariable;
+ simpleRhs = rhs;
+ }
+
+ public override Absy! StdDispatch(StandardVisitor! visitor)
+ {
+ return visitor.VisitSimpleAssignLhs(this);
+ }
+ }
+
+ // A map-assignment-lhs (m[t1, t2, ...] := ...) is quite similar to
+ // a map select expression, but it is cleaner to keep those two
+ // things separate
+ public class MapAssignLhs : AssignLhs {
+ public AssignLhs! Map;
+
+ public List<Expr!>! Indexes;
+
+ // The instantiation of type parameters of the map that is
+ // determined during type checking.
+ public TypeParamInstantiation TypeParameters = null;
+
+ private Type TypeAttr = null;
+
+ public override Type Type { get {
+ return TypeAttr;
+ } }
+
+ public override IdentifierExpr! DeepAssignedIdentifier { get {
+ return Map.DeepAssignedIdentifier;
+ } }
+
+ public override Variable DeepAssignedVariable { get {
+ return Map.DeepAssignedVariable;
+ } }
+
+ public MapAssignLhs(IToken! tok, AssignLhs! map, List<Expr!>! indexes) {
+ base(tok);
+ Map = map;
+ Indexes = indexes;
+ }
+ public override void Resolve(ResolutionContext! rc) {
+ Map.Resolve(rc);
+ foreach (Expr! e in Indexes)
+ e.Resolve(rc);
+ }
+ public override void Typecheck(TypecheckingContext! tc) {
+ Map.Typecheck(tc);
+ foreach (Expr! e in Indexes)
+ e.Typecheck(tc);
+
+ // we use the same typechecking code as in MapSelect
+ ExprSeq! selectArgs = new ExprSeq ();
+ foreach (Expr! e in Indexes)
+ selectArgs.Add(e);
+ TypeParamInstantiation! tpInsts;
+ TypeAttr =
+ MapSelect.Typecheck((!)Map.Type, Map,
+ selectArgs, out tpInsts, tc, tok, "map assignment");
+ TypeParameters = tpInsts;
+ }
+ public override void Emit(TokenTextWriter! stream) {
+ Map.Emit(stream);
+ stream.Write("[");
+ string! sep = "";
+ foreach (Expr! e in Indexes) {
+ stream.Write(sep);
+ sep = ", ";
+ e.Emit(stream);
+ }
+ stream.Write("]");
+ }
+ public override Expr! AsExpr { get {
+ NAryExpr! res = Expr.Select(Map.AsExpr, Indexes);
+ res.TypeParameters = this.TypeParameters;
+ return res;
+ } }
+ internal override void AsSimpleAssignment(Expr! rhs,
+ out IdentifierExpr! simpleLhs,
+ out Expr! simpleRhs) {
+ NAryExpr! newRhs = Expr.Store(Map.AsExpr, Indexes, rhs);
+ newRhs.TypeParameters = this.TypeParameters;
+ Map.AsSimpleAssignment(newRhs, out simpleLhs, out simpleRhs);
+ }
+
+ public override Absy! StdDispatch(StandardVisitor! visitor)
+ {
+ return visitor.VisitMapAssignLhs(this);
+ }
+ }
+
+ /// <summary>
+ /// A StateCmd is like an imperative-let binding around a sequence of commands.
+ /// There is no user syntax for a StateCmd. Instead, a StateCmd is only used
+ /// temporarily during the desugaring phase inside the VC generator.
+ /// </summary>
+ public class StateCmd : Cmd
+ {
+ public /*readonly, except for the StandardVisitor*/ VariableSeq! Locals;
+ public /*readonly, except for the StandardVisitor*/ CmdSeq! Cmds;
+
+ public StateCmd(IToken! tok, VariableSeq! locals, CmdSeq! cmds)
+ : base(tok)
+ {
+ this.Locals = locals;
+ this.Cmds = cmds;
+ // base(tok);
+ }
+
+ public override void Resolve(ResolutionContext! rc) {
+ rc.PushVarContext();
+ foreach (Variable! v in Locals) {
+ rc.AddVariable(v, false);
+ }
+ foreach (Cmd! cmd in Cmds) {
+ cmd.Resolve(rc);
+ }
+ rc.PopVarContext();
+ }
+
+ public override void AddAssignedVariables(VariableSeq! vars) {
+ VariableSeq! vs = new VariableSeq();
+ foreach (Cmd! cmd in this.Cmds)
+ {
+ cmd.AddAssignedVariables(vs);
+ }
+ System.Collections.Hashtable! localsSet = new System.Collections.Hashtable();
+ foreach (Variable! local in this.Locals)
+ {
+ localsSet[local] = bool.TrueString;
+ }
+ foreach (Variable! v in vs)
+ {
+ if (!localsSet.ContainsKey(v))
+ {
+ vars.Add(v);
+ }
+ }
+ }
+
+ public override void Typecheck(TypecheckingContext! tc) {
+ foreach (Cmd! cmd in Cmds) {
+ cmd.Typecheck(tc);
+ }
+ }
+
+ public override void Emit(TokenTextWriter! stream, int level) {
+ stream.WriteLine(this, level, "{");
+ foreach (Variable! v in Locals) {
+ v.Emit(stream, level+1);
+ }
+ foreach (Cmd! c in Cmds) {
+ c.Emit(stream, level+1);
+ }
+ stream.WriteLine(level, "}");
+ }
+
+ public override Absy! StdDispatch(StandardVisitor! visitor)
+ {
+ return visitor.VisitStateCmd(this);
+ }
+ }
+
+ abstract public class SugaredCmd : Cmd
+ {
+ private Cmd desugaring; // null until desugared
+
+ public SugaredCmd(IToken! tok) : base(tok) {}
+
+ public Cmd! Desugaring {
+ get {
+ if (desugaring == null) {
+ desugaring = ComputeDesugaring();
+ }
+ return desugaring;
+ }
+ }
+ protected abstract Cmd! ComputeDesugaring();
+
+ public override void Emit(TokenTextWriter! stream, int level) {
+ if (CommandLineOptions.Clo.PrintDesugarings) {
+ stream.WriteLine(this, level, "/*** desugaring:");
+ Desugaring.Emit(stream, level);
+ stream.WriteLine(level, "**** end desugaring */");
+ }
+ }
+ }
+
+ public abstract class CallCommonality : SugaredCmd
+ {
+ protected CallCommonality(IToken! tok) {
+ base(tok);
+ }
+
+ protected enum TempVarKind { Formal, Old, Bound }
+
+ // We have to give the type explicitly, because the type of the formal "likeThisOne" can contain type variables
+ protected Variable! CreateTemporaryVariable(VariableSeq! tempVars, Variable! likeThisOne, Type! ty, TempVarKind kind) {
+ string! tempNamePrefix;
+ switch (kind) {
+ case TempVarKind.Formal:
+ tempNamePrefix = "formal@";
+ break;
+ case TempVarKind.Old:
+ tempNamePrefix = "old@";
+ break;
+ case TempVarKind.Bound:
+ tempNamePrefix = "forall@";
+ break;
+ default:
+ assert false; // unexpected kind
+ }
+ TypedIdent ti = likeThisOne.TypedIdent;
+ TypedIdent newTi = new TypedIdent(ti.tok, "call" + UniqueId + tempNamePrefix + ti.Name, ty);
+ Variable! v;
+ if (kind == TempVarKind.Bound) {
+ v = new BoundVariable(likeThisOne.tok, newTi);
+ } else {
+ v = new LocalVariable(likeThisOne.tok, newTi);
+ tempVars.Add(v);
+ }
+ return v;
+ }
+ }
+
+ public class CallCmd : CallCommonality, IPotentialErrorNode
+ {
+ string! callee;
+ public Procedure Proc;
+
+ // Element of the following lists can be null, which means that
+ // the call happens with * as these parameters
+ public List<Expr>! Ins;
+ public List<IdentifierExpr>! Outs;
+ //public Lattice.Element StateAfterCall;
+
+ // The instantiation of type parameters that is determined during
+ // type checking
+ public TypeParamInstantiation TypeParameters = null;
+
+ // TODO: convert to use generics
+ private object errorData;
+ public object ErrorData {
+ get { return errorData; }
+ set { errorData = value; }
+ }
+
+ public CallCmd(IToken! tok, string! callee, ExprSeq! ins, IdentifierExprSeq! outs)
+ {
+ List<Expr>! insList = new List<Expr> ();
+ List<IdentifierExpr>! outsList = new List<IdentifierExpr> ();
+ foreach (Expr e in ins)
+ insList.Add(e);
+ foreach (IdentifierExpr e in outs)
+ outsList.Add(e);
+
+ this(tok, callee, insList, outsList);
+ }
+ public CallCmd(IToken! tok, string! callee, List<Expr>! ins, List<IdentifierExpr>! outs)
+ : base(tok)
+ {
+ this.callee = callee;
+ this.Ins = ins;
+ this.Outs = outs;
+ // base(tok);
+ }
+ public override void Emit(TokenTextWriter! stream, int level)
+ {
+ stream.Write(this, level, "call ");
+ string sep = "";
+ if (Outs.Count > 0) {
+ foreach (Expr arg in Outs) {
+ stream.Write(sep);
+ sep = ", ";
+ if (arg == null) {
+ stream.Write("*");
+ } else {
+ arg.Emit(stream);
+ }
+ }
+ stream.Write(" := ");
+ }
+ stream.Write(TokenTextWriter.SanitizeIdentifier(callee));
+ stream.Write("(");
+ sep = "";
+ foreach (Expr arg in Ins) {
+ stream.Write(sep);
+ sep = ", ";
+ if (arg == null) {
+ stream.Write("*");
+ } else {
+ arg.Emit(stream);
+ }
+ }
+ stream.WriteLine(");");
+ base.Emit(stream, level);
+ }
+ public override void Resolve(ResolutionContext! rc)
+ {
+ if (Proc != null)
+ {
+ // already resolved
+ return;
+ }
+ Proc = rc.LookUpProcedure(callee) as Procedure;
+ if (Proc == null) {
+ rc.Error(this, "call to undeclared procedure: {0}", callee);
+ }
+ foreach (Expr e in Ins)
+ {
+ if (e!=null) {
+ e.Resolve(rc);
+ }
+ }
+ Set/*<Variable>*/ actualOuts = new Set/*<Variable>*/ (Outs.Count);
+ foreach (IdentifierExpr ide in Outs)
+ {
+ if (ide != null) {
+ ide.Resolve(rc);
+ if (ide.Decl != null) {
+ if (actualOuts[ide.Decl]) {
+ rc.Error(this, "left-hand side of call command contains variable twice: {0}", ide.Name);
+ } else {
+ actualOuts.Add(ide.Decl);
+ }
+ }
+ }
+ }
+
+ if (Proc == null)
+ return;
+
+ // first make sure that the right number of parameters is given
+ // (a similar check is in CheckArgumentTypes, but we are not
+ // able to call this method because it cannot cope with Ins/Outs
+ // that are null)
+ if (Ins.Count != Proc.InParams.Length) {
+ rc.Error(this.tok,
+ "wrong number of arguments in call to {0}: {1}",
+ callee, Ins.Count);
+ return;
+ }
+ if (Outs.Count != Proc.OutParams.Length) {
+ rc.Error(this.tok,
+ "wrong number of result variables in call to {0}: {1}",
+ callee, Outs.Count);
+ return;
+ }
+
+ // Check that type parameters can be determined using the given
+ // actual i/o arguments. This is done already during resolution
+ // because CheckBoundVariableOccurrences needs a resolution
+ // context
+ TypeSeq! formalInTypes = new TypeSeq();
+ TypeSeq! formalOutTypes = new TypeSeq();
+ for (int i = 0; i < Ins.Count; ++i)
+ if (Ins[i] != null)
+ formalInTypes.Add(((!)Proc.InParams[i]).TypedIdent.Type);
+ for (int i = 0; i < Outs.Count; ++i)
+ if (Outs[i] != null)
+ formalOutTypes.Add(((!)Proc.OutParams[i]).TypedIdent.Type);
+
+ // we need to bind the type parameters for this
+ // (this is expected by CheckBoundVariableOccurrences)
+ int previousTypeBinderState = rc.TypeBinderState;
+ try {
+ foreach (TypeVariable! v in Proc.TypeParameters)
+ rc.AddTypeBinder(v);
+ Type.CheckBoundVariableOccurrences(Proc.TypeParameters,
+ formalInTypes, formalOutTypes,
+ this.tok, "types of given arguments",
+ rc);
+ } finally {
+ rc.TypeBinderState = previousTypeBinderState;
+ }
+ }
+
+ public override void AddAssignedVariables(VariableSeq! vars)
+ {
+ foreach (IdentifierExpr e in Outs)
+ {
+ if (e!=null) {
+ vars.Add(e.Decl);
+ }
+ }
+ assume this.Proc != null;
+ foreach (IdentifierExpr! e in this.Proc.Modifies)
+ {
+ vars.Add(e.Decl);
+ }
+ }
+
+ public override void Typecheck(TypecheckingContext! tc)
+ {
+ assume this.Proc != null; // we assume the CallCmd has been successfully resolved before calling this Typecheck method
+
+ // typecheck in-parameters
+ foreach (Expr e in Ins)
+ if (e!=null)
+ e.Typecheck(tc);
+ foreach (Expr e in Outs)
+ if (e!=null)
+ e.Typecheck(tc);
+ this.CheckAssignments(tc);
+
+ TypeSeq! formalInTypes = new TypeSeq();
+ TypeSeq! formalOutTypes = new TypeSeq();
+ ExprSeq! actualIns = new ExprSeq();
+ IdentifierExprSeq! actualOuts = new IdentifierExprSeq();
+ for (int i = 0; i < Ins.Count; ++i)
+ if (Ins[i] != null) {
+ formalInTypes.Add(((!)Proc.InParams[i]).TypedIdent.Type);
+ actualIns.Add(Ins[i]);
+ }
+ for (int i = 0; i < Outs.Count; ++i)
+ if (Outs[i] != null) {
+ formalOutTypes.Add(((!)Proc.OutParams[i]).TypedIdent.Type);
+ actualOuts.Add(Outs[i]);
+ }
+
+ // match actuals with formals
+ List<Type!>! actualTypeParams;
+ Type.CheckArgumentTypes(Proc.TypeParameters,
+ out actualTypeParams,
+ formalInTypes, actualIns,
+ formalOutTypes, actualOuts,
+ this.tok,
+ "call to " + callee,
+ tc);
+ TypeParameters = SimpleTypeParamInstantiation.From(Proc.TypeParameters,
+ actualTypeParams);
+ }
+
+ private IDictionary<TypeVariable!, Type!>! TypeParamSubstitution() {
+ assume TypeParameters != null;
+ IDictionary<TypeVariable!, Type!>! res = new Dictionary<TypeVariable!, Type!> ();
+ foreach (TypeVariable! v in TypeParameters.FormalTypeParams)
+ res.Add(v, TypeParameters[v]);
+ return res;
+ }
+
+ protected override Cmd! ComputeDesugaring() {
+ CmdSeq newBlockBody = new CmdSeq();
+ Hashtable /*Variable -> Expr*/ substMap = new Hashtable/*Variable -> Expr*/();
+ Hashtable /*Variable -> Expr*/ substMapOld = new Hashtable/*Variable -> Expr*/();
+ Hashtable /*Variable -> Expr*/ substMapBound = new Hashtable/*Variable -> Expr*/();
+ VariableSeq! tempVars = new VariableSeq();
+
+ // proc P(ins) returns (outs)
+ // requires Pre
+ // modifies frame
+ // ensures Post
+ //
+ // call aouts := P(ains)
+
+ // ins : formal in parameters of procedure
+ // frame : a list of global variables from the modifies clause
+ // outs : formal out parameters of procedure
+ // ains : actual in arguments passed to call
+ // aouts : actual variables assigned to from call
+ // cins : new variables created just for this call, one per ains
+ // cframe : new variables created just for this call, to keep track of OLD values
+ // couts : new variables created just for this call, one per aouts
+ // WildcarVars : new variables created just for this call, one per null in ains
+
+ #region Create cins; each one is an incarnation of the corresponding in parameter
+ VariableSeq! cins = new VariableSeq();
+ VariableSeq wildcardVars = new VariableSeq();
+ assume this.Proc != null;
+ for (int i = 0; i < this.Proc.InParams.Length; ++i)
+ {
+ Variable! param = (!)this.Proc.InParams[i];
+ bool isWildcard = this.Ins[i] == null;
+
+ Type! actualType;
+ if (isWildcard)
+ actualType = param.TypedIdent.Type.Substitute(TypeParamSubstitution());
+ else
+ // during type checking, we have ensured that the type of the actual
+ // parameter Ins[i] is correct, so we can use it here
+ actualType = (!)((!)Ins[i]).Type;
+
+ Variable cin = CreateTemporaryVariable(tempVars, param, actualType,
+ TempVarKind.Formal);
+ cins.Add(cin);
+ IdentifierExpr ie = new IdentifierExpr(cin.tok, cin);
+ substMap.Add(param, ie);
+ if (isWildcard) {
+ cin = CreateTemporaryVariable(tempVars, param,
+ actualType, TempVarKind.Bound);
+ wildcardVars.Add(cin);
+ ie = new IdentifierExpr(cin.tok, cin);
+ }
+ substMapBound.Add(param, ie);
+ }
+ #endregion
+ #region call aouts := P(ains) becomes: (open outlining one level to see)
+ #region cins := ains (or havoc cin when ain is null)
+ for (int i = 0, n = this.Ins.Count; i < n; i++)
+ {
+ IdentifierExpr! cin_exp = new IdentifierExpr(((!)cins[i]).tok, (!) cins[i]);
+ if (this.Ins[i] != null) {
+ AssignCmd assign = Cmd.SimpleAssign(Token.NoToken, cin_exp, (!) this.Ins[i]);
+ newBlockBody.Add(assign);
+ } else {
+ IdentifierExprSeq! ies = new IdentifierExprSeq();
+ ies.Add(cin_exp);
+ HavocCmd havoc = new HavocCmd(Token.NoToken, ies);
+ newBlockBody.Add(havoc);
+ }
+ }
+ #endregion
+
+ #region assert (exists wildcardVars :: Pre[ins := cins])
+ Substitution s = Substituter.SubstitutionFromHashtable(substMapBound);
+ bool hasWildcard = (wildcardVars.Length != 0);
+ Expr preConjunction = null;
+ for (int i = 0; i < this.Proc.Requires.Length; i++)
+ {
+ Requires! req = (!) this.Proc.Requires[i];
+ if (!req.Free) {
+ if (hasWildcard) {
+ Expr pre = Substituter.Apply(s, req.Condition);
+ if (preConjunction == null) {
+ preConjunction = pre;
+ } else {
+ preConjunction = Expr.And(preConjunction, pre);
+ }
+ } else {
+ Requires! reqCopy = (Requires!) req.Clone();
+ reqCopy.Condition = Substituter.Apply(s, req.Condition);
+ AssertCmd! a = new AssertRequiresCmd(this, reqCopy);
+ a.ErrorDataEnhanced = reqCopy.ErrorDataEnhanced;
+ newBlockBody.Add(a);
+ }
+ }
+ }
+ if (hasWildcard) {
+ if (preConjunction == null) {
+ preConjunction = Expr.True;
+ }
+ Expr! expr = new ExistsExpr(tok, wildcardVars, preConjunction);
+ AssertCmd! a = new AssertCmd(tok, expr);
+ a.ErrorDataEnhanced = AssertCmd.GenerateBoundVarMiningStrategy(expr);
+ newBlockBody.Add(a);
+ }
+ #endregion
+
+ #region assume Pre[ins := cins] with formal paramters
+ if (hasWildcard) {
+ s = Substituter.SubstitutionFromHashtable(substMap);
+ for (int i = 0; i < this.Proc.Requires.Length; i++)
+ {
+ Requires! req = (!) this.Proc.Requires[i];
+ if (!req.Free) {
+ Requires! reqCopy = (Requires!) req.Clone();
+ reqCopy.Condition = Substituter.Apply(s, req.Condition);
+ AssumeCmd! a = new AssumeCmd(tok, reqCopy.Condition);
+ newBlockBody.Add(a);
+ }
+ }
+ }
+ #endregion
+
+ #region cframe := frame (to hold onto frame values in case they are referred to in the postcondition)
+ IdentifierExprSeq havocVarExprs = new IdentifierExprSeq();
+
+ foreach (IdentifierExpr! f in this.Proc.Modifies)
+ {
+ assume f.Decl != null;
+ assert f.Type != null;
+ Variable v = CreateTemporaryVariable(tempVars, f.Decl, f.Type, TempVarKind.Old);
+ IdentifierExpr v_exp = new IdentifierExpr(v.tok, v);
+ substMapOld.Add(f.Decl, v_exp); // this assumes no duplicates in this.Proc.Modifies
+ AssignCmd assign = Cmd.SimpleAssign(f.tok, v_exp, f);
+ newBlockBody.Add(assign);
+
+ // fra
+ if(!havocVarExprs.Has(f))
+ havocVarExprs.Add(f);
+ }
+ #endregion
+ #region Create couts
+ VariableSeq! couts = new VariableSeq();
+ for (int i = 0; i < this.Proc.OutParams.Length; ++i)
+ {
+ Variable! param = (!)this.Proc.OutParams[i];
+ bool isWildcard = this.Outs[i] == null;
+
+ Type! actualType;
+ if (isWildcard)
+ actualType = param.TypedIdent.Type.Substitute(TypeParamSubstitution());
+ else
+ // during type checking, we have ensured that the type of the actual
+ // out parameter Outs[i] is correct, so we can use it here
+ actualType = (!)((!)Outs[i]).Type;
+
+ Variable cout = CreateTemporaryVariable(tempVars, param, actualType,
+ TempVarKind.Formal);
+ couts.Add(cout);
+ IdentifierExpr ie = new IdentifierExpr(cout.tok, cout);
+ substMap.Add(param, ie);
+
+ if(!havocVarExprs.Has(ie))
+ havocVarExprs.Add(ie);
+ }
+ // add the where clauses, now that we have the entire substitution map
+ foreach (Variable! param in this.Proc.OutParams) {
+ Expr w = param.TypedIdent.WhereExpr;
+ if (w != null) {
+ IdentifierExpr ie = (IdentifierExpr!)substMap[param];
+ assert ie.Decl != null;
+ ie.Decl.TypedIdent.WhereExpr = Substituter.Apply(Substituter.SubstitutionFromHashtable(substMap), w);
+ }
+ }
+ #endregion
+
+ #region havoc frame, couts
+ // pass on this's token
+ HavocCmd hc = new HavocCmd(this.tok, havocVarExprs);
+ newBlockBody.Add(hc);
+ #endregion
+
+ #region assume Post[ins, outs, old(frame) := cins, couts, cframe]
+ Substitution s2 = Substituter.SubstitutionFromHashtable(substMap);
+ Substitution s2old = Substituter.SubstitutionFromHashtable(substMapOld);
+ foreach (Ensures! e in this.Proc.Ensures)
+ {
+ Expr copy = Substituter.ApplyReplacingOldExprs(s2, s2old, e.Condition);
+ AssumeCmd assume = new AssumeCmd(this.tok, copy);
+ newBlockBody.Add(assume);
+ }
+ #endregion
+
+ #region aouts := couts
+ for (int i = 0, n = this.Outs.Count; i < n; i++)
+ {
+ if (this.Outs[i]!=null) {
+ Variable! param_i = (!) this.Proc.OutParams[i];
+ Expr! cout_exp = new IdentifierExpr(((!)couts[i]).tok, (!) couts[i]);
+ AssignCmd assign = Cmd.SimpleAssign(param_i.tok, (!) this.Outs[i], cout_exp);
+ newBlockBody.Add(assign);
+ }
+ }
+ #endregion
+ #endregion
+
+ return new StateCmd(this.tok, tempVars, newBlockBody);
+ }
+
+ public override Absy! StdDispatch(StandardVisitor! visitor)
+ {
+ return visitor.VisitCallCmd(this);
+ }
+ }
+
+ public class CallForallCmd : CallCommonality
+ {
+ string! callee;
+ public Procedure Proc;
+ public List<Expr>! Ins;
+
+ // the types of the formal in-parameters after instantiating all
+ // type variables whose value could be inferred using the given
+ // actual non-wildcard arguments
+ public TypeSeq InstantiatedTypes;
+
+ public CallForallCmd(IToken! tok, string! callee, List<Expr>! ins)
+ : base(tok)
+ {
+ this.callee = callee;
+ this.Ins = ins;
+ }
+ public override void Emit(TokenTextWriter! stream, int level)
+ {
+ stream.Write(this, level, "call forall ");
+ stream.Write(TokenTextWriter.SanitizeIdentifier(callee));
+ stream.Write("(");
+ string sep = "";
+ foreach (Expr arg in Ins) {
+ stream.Write(sep);
+ sep = ", ";
+ if (arg == null) {
+ stream.Write("*");
+ } else {
+ arg.Emit(stream);
+ }
+ }
+ stream.WriteLine(");");
+ base.Emit(stream, level);
+ }
+ public override void Resolve(ResolutionContext! rc)
+ {
+ if (Proc != null) {
+ // already resolved
+ return;
+ }
+ Proc = rc.LookUpProcedure(callee) as Procedure;
+ if (Proc == null) {
+ rc.Error(this, "call to undeclared procedure: {0}", callee);
+ }
+ foreach (Expr e in Ins) {
+ if (e != null) {
+ e.Resolve(rc);
+ }
+ }
+ }
+ public override void AddAssignedVariables(VariableSeq! vars) { }
+ public override void Typecheck(TypecheckingContext! tc)
+ {
+ // typecheck in-parameters
+ foreach (Expr e in Ins) {
+ if (e != null) {
+ e.Typecheck(tc);
+ }
+ }
+
+ if (this.Proc == null)
+ {
+ // called procedure didn't resolve, so bug out
+ return;
+ }
+
+ // match actuals with formals
+ if (Ins.Count != Proc.InParams.Length)
+ {
+ tc.Error(this, "wrong number of in-parameters in call: {0}", callee);
+ }
+ else
+ {
+ // determine the lists of formal and actual arguments that need
+ // to be matched (stars are left out)
+ TypeSeq! formalTypes = new TypeSeq ();
+ ExprSeq! actualArgs = new ExprSeq ();
+ for (int i = 0; i < Ins.Count; i++)
+ if (Ins[i] != null) {
+ formalTypes.Add(((!)Proc.InParams[i]).TypedIdent.Type);
+ actualArgs.Add(Ins[i]);
+ }
+ IDictionary<TypeVariable!, Type!>! subst =
+ Type.MatchArgumentTypes(Proc.TypeParameters,
+ formalTypes, actualArgs, null, null,
+ "call forall to " + callee, tc);
+
+ InstantiatedTypes = new TypeSeq ();
+ foreach (Variable! var in Proc.InParams) {
+ InstantiatedTypes.Add(var.TypedIdent.Type.Substitute(subst));
+ }
+ }
+
+// if (Proc.OutParams.Length != 0)
+// {
+// tc.Error(this, "call forall is allowed only on procedures with no out-parameters: {0}", callee);
+// }
+
+ if (Proc.Modifies.Length != 0)
+ {
+ tc.Error(this, "call forall is allowed only on procedures with no modifies clause: {0}", callee);
+ }
+ }
+
+ protected override Cmd! ComputeDesugaring() {
+ CmdSeq newBlockBody = new CmdSeq();
+ Hashtable /*Variable -> Expr*/ substMap = new Hashtable/*Variable -> Expr*/();
+ VariableSeq! tempVars = new VariableSeq();
+
+ // proc P(ins) returns ()
+ // requires Pre;
+ // modifies ;
+ // ensures Post;
+ //
+ // call forall P(ains);
+
+ // ins : formal in-parameters of procedure
+ // ains : actual in-arguments passed to call
+ // cins : new variables created just for this call, one per ains
+ // wildcardVars : the bound variables to be wrapped up in a quantification
+
+ #region Create cins; each one is an incarnation of the corresponding in parameter
+ VariableSeq! cins = new VariableSeq();
+ VariableSeq wildcardVars = new VariableSeq();
+ assume this.Proc != null;
+ for (int i = 0, n = this.Proc.InParams.Length; i < n; i++) {
+ Variable param = (!)this.Proc.InParams[i];
+ Type! paramType = ((!)this.InstantiatedTypes)[i]; // might contain type variables
+ bool isWildcard = this.Ins[i] == null;
+ Variable cin = CreateTemporaryVariable(tempVars, param, paramType,
+ isWildcard ? TempVarKind.Bound : TempVarKind.Formal);
+ if (isWildcard) {
+ cins.Add(null);
+ wildcardVars.Add(cin);
+ } else {
+ cins.Add(cin);
+ }
+ IdentifierExpr ie = new IdentifierExpr(cin.tok, cin);
+ substMap.Add(param, ie);
+ }
+ #endregion
+
+ #region call forall P(ains) becomes: (open outlining one level to see)
+ #region cins := ains
+ for (int i = 0, n = this.Ins.Count; i < n; i++)
+ {
+ if (this.Ins[i] != null) {
+ IdentifierExpr! cin_exp = new IdentifierExpr(((!)cins[i]).tok, (!) cins[i]);
+ AssignCmd assign = Cmd.SimpleAssign(Token.NoToken, cin_exp, (!) this.Ins[i]);
+ newBlockBody.Add(assign);
+ }
+ }
+ #endregion
+
+ #region assert Pre[ins := cins]
+ Substitution s = Substituter.SubstitutionFromHashtable(substMap);
+ Expr preConjunction = null;
+ for (int i = 0; i < this.Proc.Requires.Length; i++)
+ {
+ Requires! req = (!) this.Proc.Requires[i];
+ if (!req.Free) {
+ Expr pre = Substituter.Apply(s, req.Condition);
+ if (preConjunction == null) {
+ preConjunction = pre;
+ } else {
+ preConjunction = Expr.And(preConjunction, pre);
+ }
+ }
+ }
+ if (preConjunction == null) {
+ preConjunction = Expr.True;
+ }
+ #endregion
+
+ #region Create couts
+ VariableSeq! couts = new VariableSeq();
+ foreach ( Variable! param in this.Proc.OutParams )
+ {
+ Variable cout = CreateTemporaryVariable(tempVars, param,
+ param.TypedIdent.Type, TempVarKind.Bound);
+ couts.Add(cout);
+ IdentifierExpr ie = new IdentifierExpr(cout.tok, cout);
+ substMap.Add(param, ie);
+ }
+ // add the where clauses, now that we have the entire substitution map
+ foreach (Variable! param in this.Proc.OutParams) {
+ Expr w = param.TypedIdent.WhereExpr;
+ if (w != null) {
+ IdentifierExpr ie = (IdentifierExpr!)substMap[param];
+ assert ie.Decl != null;
+ ie.Decl.TypedIdent.WhereExpr = Substituter.Apply(Substituter.SubstitutionFromHashtable(substMap), w);
+ }
+ }
+ #endregion
+
+ #region assume Post[ins := cins]
+ s = Substituter.SubstitutionFromHashtable(substMap);
+ Expr postConjunction = null;
+ foreach (Ensures! e in this.Proc.Ensures)
+ {
+ Expr post = Substituter.Apply(s, e.Condition);
+ if (postConjunction == null) {
+ postConjunction = post;
+ } else {
+ postConjunction = Expr.And(postConjunction, post);
+ }
+ }
+ if (postConjunction == null) {
+ postConjunction = Expr.True;
+ }
+ #endregion
+
+ #region assume (forall wildcardVars :: Pre ==> Post);
+ Expr body = postConjunction;
+ if (couts.Length > 0) {
+ body = new ExistsExpr(tok, couts, body);
+ }
+ body = Expr.Imp(preConjunction, body);
+ if (wildcardVars.Length != 0) {
+ TypeVariableSeq! typeParams = Type.FreeVariablesIn((!)InstantiatedTypes);
+ body = new ForallExpr(tok, typeParams, wildcardVars, body);
+ }
+ newBlockBody.Add(new AssumeCmd(tok, body));
+ #endregion
+ #endregion
+
+ return new StateCmd(this.tok, tempVars, newBlockBody);
+ }
+
+ public override Absy! StdDispatch(StandardVisitor! visitor)
+ {
+ return visitor.VisitCallForallCmd(this);
+ }
+ }
+
+ public abstract class PredicateCmd : Cmd
+ {
+ public /*readonly--except in StandardVisitor*/ Expr! Expr;
+ public PredicateCmd(IToken! tok, Expr! expr)
+ : base(tok)
+ {
+ Expr = expr;
+ }
+ public override void Resolve(ResolutionContext! rc)
+ {
+ Expr.Resolve(rc);
+ }
+ public override void AddAssignedVariables(VariableSeq! vars) { }
+ }
+
+ public abstract class MiningStrategy {
+ // abstract class to bind all MiningStrategys, i.e., all types of enhanced error data
+ // types together
+ }
+
+ public class ListOfMiningStrategies : MiningStrategy {
+ public List<MiningStrategy>! msList;
+
+ public ListOfMiningStrategies (List<MiningStrategy>! l) {
+ this.msList = l;
+ }
+ }
+
+ public class EEDTemplate : MiningStrategy {
+ public string! reason;
+ public List<Expr!>! exprList;
+
+ public EEDTemplate (string! reason, List<Expr!>! exprList) {
+ this.reason = reason;
+ this.exprList = exprList;
+ }
+ }
+
+ public class AssertCmd : PredicateCmd, IPotentialErrorNode
+ {
+ public Expr OrigExpr;
+ public Hashtable /*Variable -> Expr*/ IncarnationMap;
+
+ // TODO: convert to use generics
+ private object errorData;
+ public object ErrorData {
+ get { return errorData; }
+ set { errorData = value; }
+ }
+
+ public string ErrorMessage {
+ get {
+ return QKeyValue.FindStringAttribute(Attributes, "msg");
+ }
+ }
+
+ public QKeyValue Attributes;
+
+ private MiningStrategy errorDataEnhanced;
+ public MiningStrategy ErrorDataEnhanced {
+ get { return errorDataEnhanced; }
+ set { errorDataEnhanced = value; }
+ }
+
+ public AssertCmd(IToken! tok, Expr! expr)
+ : base(tok, expr)
+ {
+ errorDataEnhanced = GenerateBoundVarMiningStrategy(expr);
+ }
+
+ public AssertCmd(IToken! tok, Expr! expr, QKeyValue kv)
+ : base(tok, expr)
+ {
+ errorDataEnhanced = GenerateBoundVarMiningStrategy(expr);
+ Attributes = kv;
+ }
+
+ public override void Emit(TokenTextWriter! stream, int level)
+ {
+ stream.Write(this, level, "assert ");
+ this.Expr.Emit(stream);
+ stream.WriteLine(";");
+ }
+ public override void Typecheck(TypecheckingContext! tc)
+ {
+ Expr.Typecheck(tc);
+ assert Expr.Type != null; // follows from Expr.Typecheck postcondition
+ if (!Expr.Type.Unify(Type.Bool))
+ {
+ tc.Error(this, "an asserted expression must be of type bool (got: {0})", Expr.Type);
+ }
+ }
+
+ public static MiningStrategy GenerateBoundVarMiningStrategy (Expr! expr) {
+ List<MiningStrategy> l = new List<MiningStrategy>();
+ if (expr != null) {
+ l = GenerateBoundVarListForMining(expr, l);
+ }
+ return new ListOfMiningStrategies(l);
+ }
+
+ public static List<MiningStrategy>! GenerateBoundVarListForMining (Expr! expr, List<MiningStrategy>! l) {
+ // go through the origExpr and identify all bound variables in the AST.
+ if (expr is LiteralExpr || expr is IdentifierExpr) {
+ //end recursion
+ }
+ else if (expr is NAryExpr) {
+ NAryExpr e = (NAryExpr)expr;
+ foreach (Expr! arg in e.Args) {
+ l = GenerateBoundVarListForMining(arg, l);
+ }
+ }
+ else if (expr is OldExpr) {
+ OldExpr e = (OldExpr)expr;
+ l = GenerateBoundVarListForMining(e.Expr, l);
+ }
+ else if (expr is QuantifierExpr) {
+ QuantifierExpr qe = (QuantifierExpr) expr;
+ VariableSeq vs = qe.Dummies;
+ foreach (Variable! x in vs) {
+ string name = x.Name;
+ if (name.StartsWith("^")) {
+ name = name.Substring(1);
+ List<Expr!> exprList = new List<Expr!>();
+ exprList.Add(new IdentifierExpr(Token.NoToken, x.ToString(), x.TypedIdent.Type));
+ MiningStrategy eed = new EEDTemplate("The bound variable " + name + " has the value {0}.", exprList);
+ l.Add(eed);
+ }
+ }
+ l = GenerateBoundVarListForMining(qe.Body, l);
+ }
+ return l;
+ }
+
+
+ public override Absy! StdDispatch(StandardVisitor! visitor)
+ {
+ return visitor.VisitAssertCmd(this);
+ }
+ }
+
+ // An AssertCmd that is a loop invariant check before the loop iteration starts
+ public class LoopInitAssertCmd : AssertCmd
+ {
+ public LoopInitAssertCmd(IToken! tok, Expr! expr)
+ : base(tok, expr)
+ {
+ }
+ }
+
+ // An AssertCmd that is a loop invariant check to maintain the invariant after iteration
+ public class LoopInvMaintainedAssertCmd : AssertCmd
+ {
+ public LoopInvMaintainedAssertCmd(IToken! tok, Expr! expr)
+ : base(tok, expr)
+ {
+ }
+ }
+
+ /// <summary>
+ /// An AssertCmd that is introduced in translation from the requires on a call.
+ /// </summary>
+ public class AssertRequiresCmd : AssertCmd
+ {
+ public CallCmd! Call;
+ public Requires! Requires;
+
+ public AssertRequiresCmd(CallCmd! call, Requires! @requires)
+ : base(call.tok, @requires.Condition)
+ {
+ this.Call = call;
+ this.Requires = @requires;
+ // base(call.tok, @requires.Condition);
+ }
+
+ public override Absy! StdDispatch(StandardVisitor! visitor)
+ {
+ return visitor.VisitAssertRequiresCmd(this);
+ }
+ }
+
+ /// <summary>
+ /// An AssertCmd that is introduced in translation from an ensures
+ /// declaration.
+ /// </summary>
+ public class AssertEnsuresCmd : AssertCmd
+ {
+ public Ensures! Ensures;
+ public AssertEnsuresCmd(Ensures! ens)
+ : base(ens.tok, ens.Condition)
+ {
+ this.Ensures = ens;
+ // base(ens.tok, ens.Condition);
+ }
+
+ public override Absy! StdDispatch(StandardVisitor! visitor)
+ {
+ return visitor.VisitAssertEnsuresCmd(this);
+ }
+ }
+
+ public class AssumeCmd : PredicateCmd
+ {
+ public AssumeCmd(IToken! tok, Expr! expr)
+ : base(tok, expr)
+ {
+ //Debug.Assert(expr != null);
+ }
+ public override void Emit(TokenTextWriter! stream, int level)
+ {
+ stream.Write(this, level, "assume ");
+ this.Expr.Emit(stream);
+ stream.WriteLine(";");
+ }
+ public override void Typecheck(TypecheckingContext! tc)
+ {
+ Expr.Typecheck(tc);
+ assert Expr.Type != null; // follows from Expr.Typecheck postcondition
+ if (!Expr.Type.Unify(Type.Bool))
+ {
+ tc.Error(this, "an assumed expression must be of type bool (got: {0})", Expr.Type);
+ }
+ }
+
+ public override Absy! StdDispatch(StandardVisitor! visitor)
+ {
+ return visitor.VisitAssumeCmd(this);
+ }
+ }
+
+ public class ReturnExprCmd : ReturnCmd
+ {
+ public Expr! Expr;
+ public ReturnExprCmd(IToken! tok, Expr! expr)
+ : base(tok)
+ {
+ Expr = expr;
+ }
+ public override void Emit(TokenTextWriter! stream, int level)
+ {
+ stream.Write(this, level, "return ");
+ this.Expr.Emit(stream);
+ stream.WriteLine(";");
+ }
+ public override void Typecheck(TypecheckingContext! tc)
+ {
+ Expr.Typecheck(tc);
+ assert Expr.Type != null; // follows from Expr.Typecheck postcondition
+ if (!Expr.Type.Unify(Type.Bool))
+ {
+ tc.Error(this, "a return expression must be of type bool (got: {0})", Expr.Type);
+ }
+ }
+ public override void Resolve(ResolutionContext! rc)
+ {
+ Expr.Resolve(rc);
+ }
+
+ public override Absy! StdDispatch(StandardVisitor! visitor)
+ {
+ return visitor.VisitReturnExprCmd(this);
+ }
+ }
+
+ public class HavocCmd : Cmd
+ {
+ public IdentifierExprSeq! Vars;
+ public HavocCmd(IToken! tok, IdentifierExprSeq! vars)
+ : base(tok)
+ {
+ Vars = vars;
+ }
+ public override void Emit(TokenTextWriter! stream, int level)
+ {
+ stream.Write(this, level, "havoc ");
+ Vars.Emit(stream, true);
+ stream.WriteLine(";");
+ }
+ public override void Resolve(ResolutionContext! rc)
+ {
+ foreach (IdentifierExpr! ide in Vars)
+ {
+ ide.Resolve(rc);
+ }
+ }
+ public override void AddAssignedVariables(VariableSeq! vars)
+ {
+ foreach (IdentifierExpr! e in this.Vars)
+ {
+ vars.Add(e.Decl);
+ }
+ }
+ public override void Typecheck(TypecheckingContext! tc)
+ {
+ this.CheckAssignments(tc);
+ }
+
+
+ public override Absy! StdDispatch(StandardVisitor! visitor)
+ {
+ return visitor.VisitHavocCmd(this);
+ }
+ }
+
+ //---------------------------------------------------------------------
+ // Transfer commands
+
+ public abstract class TransferCmd : Absy
+ {
+ internal TransferCmd(IToken! tok)
+ : base(tok)
+ {
+ }
+ public abstract void Emit(TokenTextWriter! stream, int level);
+ public override void Typecheck(TypecheckingContext! tc)
+ {
+ // nothing to typecheck
+ }
+ }
+
+ public class ReturnCmd : TransferCmd
+ {
+ public ReturnCmd(IToken! tok)
+ : base(tok)
+ {
+ }
+ public override void Emit(TokenTextWriter! stream, int level)
+ {
+ stream.WriteLine(this, level, "return;");
+ }
+ public override void Resolve(ResolutionContext! rc)
+ {
+ // nothing to resolve
+ }
+
+ public override Absy! StdDispatch(StandardVisitor! visitor)
+ {
+ return visitor.VisitReturnCmd(this);
+ }
+ }
+
+ public class GotoCmd : TransferCmd
+ {
+ [Rep]
+ public StringSeq labelNames;
+ [Rep]
+ public BlockSeq labelTargets;
+
+ invariant labelNames != null && labelTargets != null ==> labelNames.Length == labelTargets.Length;
+
+ [NotDelayed]
+ public GotoCmd(IToken! tok, StringSeq! labelSeq)
+ : base (tok)
+ {
+ this.labelNames = labelSeq;
+ }
+ public GotoCmd(IToken! tok, StringSeq! labelSeq, BlockSeq! blockSeq)
+ : base (tok)
+ {
+ Debug.Assert(labelSeq.Length == blockSeq.Length);
+ for (int i=0; i<labelSeq.Length; i++) { Debug.Assert(Equals(labelSeq[i], ((!)blockSeq[i]).Label)); }
+
+ this.labelNames = labelSeq;
+ this.labelTargets = blockSeq;
+ }
+ public GotoCmd(IToken! tok, BlockSeq! blockSeq)
+ : base (tok)
+ { //requires blockSeq[i] != null ==> blockSeq[i].Label != null;
+ StringSeq labelSeq = new StringSeq();
+ for (int i=0; i<blockSeq.Length; i++)
+ labelSeq.Add(((!)blockSeq[i]).Label);
+ this.labelNames = labelSeq;
+ this.labelTargets = blockSeq;
+ }
+ public void AddTarget(Block! b)
+ requires b.Label != null;
+ requires this.labelTargets != null;
+ requires this.labelNames != null;
+ {
+ this.labelTargets.Add(b);
+ this.labelNames.Add(b.Label);
+ }
+ public override void Emit(TokenTextWriter! stream, int level)
+ {
+ assume this.labelNames != null;
+ stream.Write(this, level, "goto ");
+ if (CommandLineOptions.Clo.PrintWithUniqueASTIds)
+ {
+ if (labelTargets == null)
+ {
+ string sep = "";
+ foreach (string name in labelNames)
+ {
+ stream.Write("{0}{1}^^{2}", sep, "NoDecl", name);
+ sep = ", ";
+ }
+ }
+ else
+ {
+ string sep = "";
+ foreach (Block! b in labelTargets)
+ {
+ stream.Write("{0}h{1}^^{2}", sep, b.GetHashCode(), b.Label);
+ sep = ", ";
+ }
+ }
+ }
+ else
+ {
+ labelNames.Emit(stream);
+ }
+ stream.WriteLine(";");
+ }
+ public override void Resolve(ResolutionContext! rc)
+ ensures labelTargets != null;
+ {
+ if (labelTargets != null)
+ {
+ // already resolved
+ return;
+ }
+ assume this.labelNames != null;
+ labelTargets = new BlockSeq();
+ foreach (string! lbl in labelNames)
+ {
+ Block b = rc.LookUpBlock(lbl);
+ if (b == null)
+ {
+ rc.Error(this, "goto to unknown block: {0}", lbl);
+ }
+ else
+ {
+ labelTargets.Add(b);
+ }
+ }
+ Debug.Assert(rc.ErrorCount > 0 || labelTargets.Length == labelNames.Length);
+ }
+
+ public override Absy! StdDispatch(StandardVisitor! visitor)
+ {
+ return visitor.VisitGotoCmd(this);
+ }
+ }
+
+}
diff --git a/Source/Core/AbsyExpr.ssc b/Source/Core/AbsyExpr.ssc
new file mode 100644
index 00000000..82854412
--- /dev/null
+++ b/Source/Core/AbsyExpr.ssc
@@ -0,0 +1,3256 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------------
+// BoogiePL - Absy.cs
+//---------------------------------------------------------------------------------------------
+
+namespace Microsoft.Boogie
+{
+ using System;
+ using System.Collections;
+ using System.Diagnostics;
+ using System.Collections.Generic;
+ using Microsoft.Boogie.AbstractInterpretation;
+ using AI = Microsoft.AbstractInterpretationFramework;
+ using Microsoft.Contracts;
+ using Microsoft.Basetypes;
+
+
+ //---------------------------------------------------------------------
+ // Expressions
+ //
+ // For expressions, we override the Equals and GetHashCode method to
+ // implement structural equality. Note this is not logical equivalence
+ // and is not modulo alpha-renaming.
+ //---------------------------------------------------------------------
+
+
+ public abstract class Expr : Absy
+ {
+ public Expr(IToken! tok)
+ : base(tok)
+ {
+ }
+
+ public void Emit (TokenTextWriter! stream)
+ {
+ Emit(stream, 0, false);
+ }
+
+ public abstract void Emit (TokenTextWriter! wr, int contextBindingStrength, bool fragileContext);
+
+ [Pure]
+ public override string! ToString ()
+ {
+ System.IO.StringWriter buffer = new System.IO.StringWriter();
+ using (TokenTextWriter stream = new TokenTextWriter("<buffer>", buffer, false))
+ {
+ this.Emit(stream, 0, false);
+ }
+ return buffer.ToString();
+ }
+
+ /// <summary>
+ /// Add to "freeVars" the free variables in the expression.
+ /// </summary>
+ public abstract void ComputeFreeVariables(Set /*Variable*/! freeVars);
+
+ /// <summary>
+ /// Filled in by the Typecheck method. A value of "null" means a succeeding
+ /// call to Typecheck has not taken place (that is, either Typecheck hasn't
+ /// been called or Typecheck encountered an error in the expression to be
+ /// typechecked).
+ /// </summary>
+ public Type Type;
+
+ public override void Typecheck (TypecheckingContext! tc)
+ ensures Type != null;
+ {
+ // This body is added only because C# insists on it. It should really be left out, as if TypeCheck still were abstract.
+ // The reason for mentioning the method here at all is to give TypeCheck a postcondition for all expressions.
+ assert false;
+ }
+
+ /// <summary>
+ /// Returns the type of the expression, supposing that all its subexpressions are well typed.
+ /// </summary>
+ public abstract Type! ShallowType { get; }
+
+ // Handy syntactic sugar follows:
+
+ public static NAryExpr! Binary (IToken! x, BinaryOperator.Opcode op, Expr! e1, Expr! e2)
+ {
+ return new NAryExpr(x, new BinaryOperator(x, op), new ExprSeq(e1, e2));
+ }
+
+ public static NAryExpr! Unary (IToken! x, UnaryOperator.Opcode op, Expr! e1)
+ {
+ return new NAryExpr(x, new UnaryOperator(x, op), new ExprSeq(e1));
+ }
+
+ public static NAryExpr! Binary (BinaryOperator.Opcode op, Expr! e1, Expr! e2)
+ {
+ return new NAryExpr(Token.NoToken, new BinaryOperator(Token.NoToken, op), new ExprSeq(e1, e2));
+ }
+
+ public static NAryExpr! Eq (Expr! e1, Expr! e2) { return Binary(BinaryOperator.Opcode.Eq, e1, e2); }
+ public static NAryExpr! Neq (Expr! e1, Expr! e2) { return Binary(BinaryOperator.Opcode.Neq, e1, e2); }
+ public static NAryExpr! Le (Expr! e1, Expr! e2) { return Binary(BinaryOperator.Opcode.Le, e1, e2); }
+ public static NAryExpr! Ge (Expr! e1, Expr! e2) { return Binary(BinaryOperator.Opcode.Ge, e1, e2); }
+ public static NAryExpr! Lt (Expr! e1, Expr! e2) { return Binary(BinaryOperator.Opcode.Lt, e1, e2); }
+ public static NAryExpr! Gt (Expr! e1, Expr! e2) { return Binary(BinaryOperator.Opcode.Gt, e1, e2); }
+ public static Expr! And (Expr! e1, Expr! e2) {
+ if (e1 == true_) { return e2; }
+ else if (e2 == true_) { return e1; }
+ else if (e1 == false_ || e2 == false_) { return false_; }
+ else { return Binary(BinaryOperator.Opcode.And, e1, e2); }
+ }
+ public static Expr! Or (Expr! e1, Expr! e2) {
+ if (e1 == false_) { return e2; }
+ else if (e2 == false_) { return e1; }
+ else if (e1 == true_ || e2 == true_) { return true_; }
+ else { return Binary(BinaryOperator.Opcode.Or, e1, e2); }
+ }
+ public static Expr! Not (Expr! e1) {
+ NAryExpr nary = e1 as NAryExpr;
+
+ if (e1 == true_) { return false_; }
+ else if (e1 == false_) { return true_; }
+ else if (nary != null)
+ {
+ if (nary.Fun is UnaryOperator)
+ {
+ UnaryOperator op = (UnaryOperator)nary.Fun;
+ if (op.Op == UnaryOperator.Opcode.Not) { return (!) nary.Args[0]; }
+ }
+ else if (nary.Fun is BinaryOperator)
+ {
+ BinaryOperator op = (BinaryOperator)nary.Fun;
+ Expr arg0 = (!)nary.Args[0];
+ Expr arg1 = (!)nary.Args[1];
+ if (op.Op == BinaryOperator.Opcode.Eq) { return Neq(arg0, arg1); }
+ else if (op.Op == BinaryOperator.Opcode.Neq) { return Eq(arg0, arg1); }
+ else if (op.Op == BinaryOperator.Opcode.Lt) { return Ge(arg0, arg1); }
+ else if (op.Op == BinaryOperator.Opcode.Le) { return Gt(arg0, arg1); }
+ else if (op.Op == BinaryOperator.Opcode.Ge) { return Lt(arg0, arg1); }
+ else if (op.Op == BinaryOperator.Opcode.Gt) { return Le(arg0, arg1); }
+ }
+ }
+
+ return Unary(Token.NoToken, UnaryOperator.Opcode.Not, e1);
+ }
+ public static NAryExpr! Imp (Expr! e1, Expr! e2) { return Binary(BinaryOperator.Opcode.Imp, e1, e2); }
+ public static NAryExpr! Iff (Expr! e1, Expr! e2) { return Binary(BinaryOperator.Opcode.Iff, e1, e2); }
+ public static NAryExpr! Add (Expr! e1, Expr! e2) { return Binary(BinaryOperator.Opcode.Add, e1, e2); }
+ public static NAryExpr! Sub (Expr! e1, Expr! e2) { return Binary(BinaryOperator.Opcode.Sub, e1, e2); }
+ public static NAryExpr! Mul (Expr! e1, Expr! e2) { return Binary(BinaryOperator.Opcode.Mul, e1, e2); }
+ public static NAryExpr! Div (Expr! e1, Expr! e2) { return Binary(BinaryOperator.Opcode.Div, e1, e2); }
+ public static NAryExpr! Mod (Expr! e1, Expr! e2) { return Binary(BinaryOperator.Opcode.Mod, e1, e2); }
+ public static NAryExpr! Subtype (Expr! e1, Expr! e2) { return Binary(BinaryOperator.Opcode.Subtype, e1, e2); }
+
+ public static IdentifierExpr! Ident (string! name, Type! type)
+ {
+ return new IdentifierExpr(Token.NoToken, name, type);
+ }
+
+ public static IdentifierExpr! Ident (Variable! decl)
+ {
+ IdentifierExpr result = new IdentifierExpr(Token.NoToken, decl);
+ return result;
+ }
+
+ public static LiteralExpr! Literal (bool value) { return new LiteralExpr(Token.NoToken, value); }
+ public static LiteralExpr! Literal (int value) { return new LiteralExpr(Token.NoToken, BigNum.FromInt(value)); }
+ public static LiteralExpr! Literal (BigNum value) { return new LiteralExpr(Token.NoToken, value); }
+
+ private static LiteralExpr! true_ = Literal(true);
+ public static LiteralExpr! True { get { return true_; } }
+
+ private static LiteralExpr! false_ = Literal(false);
+ public static LiteralExpr! False { get { return false_; } }
+
+
+ public static NAryExpr! Select(Expr! map, params Expr[]! args) {
+ return SelectTok(Token.NoToken, map, args);
+ }
+
+ public static NAryExpr! Select(Expr! map, List<Expr!>! args) {
+ return Select(map, args.ToArray());
+ }
+
+ // use a different name for this variant of the method
+ // (-> some bug prevents overloading in this case)
+ public static NAryExpr! SelectTok(IToken! x, Expr! map, params Expr[]! args)
+ {
+ ExprSeq! allArgs = new ExprSeq ();
+ allArgs.Add(map);
+ foreach (Expr! a in args)
+ allArgs.Add(a);
+ return new NAryExpr(x, new MapSelect(Token.NoToken, args.Length), allArgs);
+ }
+
+ public static NAryExpr! Store(Expr! map, params Expr[]! args) {
+ return StoreTok(Token.NoToken, map, args);
+ }
+
+ public static NAryExpr! Store(Expr! map, List<Expr!>! indexes, Expr! rhs) {
+ Expr[]! allArgs = new Expr [indexes.Count + 1];
+ for (int i = 0; i < indexes.Count; ++i)
+ allArgs[i] = indexes[i];
+ allArgs[indexes.Count] = rhs;
+ return Store(map, allArgs);
+ }
+
+ // use a different name for this variant of the method
+ // (-> some bug prevents overloading in this case)
+ public static NAryExpr! StoreTok(IToken! x, Expr! map, params Expr[]! args)
+ requires args.Length > 0; // zero or more indices, plus the value
+ {
+ ExprSeq! allArgs = new ExprSeq ();
+ allArgs.Add(map);
+ foreach (Expr! a in args)
+ allArgs.Add(a);
+ return new NAryExpr(x, new MapStore(Token.NoToken, args.Length - 1), allArgs);
+ }
+
+ public static NAryExpr! CoerceType(IToken! x, Expr! subexpr, Type! type) {
+ ExprSeq! args = new ExprSeq ();
+ 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;
+ }
+
+ }
+
+ public class LiteralExpr : Expr, AI.IFunApp
+ {
+ public readonly object! Val; // false, true, a BigNum, or a BvConst
+ /// <summary>
+ /// Creates a literal expression for the boolean value "b".
+ /// </summary>
+ /// <param name="tok"></param>
+ /// <param name="b"></param>
+ public LiteralExpr(IToken! tok, bool b)
+ : base(tok)
+ {
+ Val = b;
+ }
+ /// <summary>
+ /// Creates a literal expression for the integer value "v".
+ /// </summary>
+ /// <param name="tok"></param>
+ /// <param name="v"></param>
+ public LiteralExpr(IToken! tok, BigNum v)
+ : base(tok)
+ {
+ Val = v;
+ }
+
+ /// <summary>
+ /// Creates a literal expression for the bitvector value "v".
+ /// </summary>
+ public LiteralExpr(IToken! tok, BigNum v, int b)
+ : base(tok)
+ {
+ Val = new BvConst(v, b);
+ }
+
+ [Pure][Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals(object obj)
+ {
+ if (obj == null) return false;
+ if (!(obj is LiteralExpr)) return false;
+
+ LiteralExpr other = (LiteralExpr)obj;
+ return object.Equals(this.Val, other.Val);
+ }
+ [Pure]
+ public override int GetHashCode()
+ {
+ return this.Val.GetHashCode();
+ }
+ public override void Emit(TokenTextWriter! stream, int contextBindingStrength, bool fragileContext)
+ {
+ stream.SetToken(this);
+ if (this.Val is bool)
+ {
+ stream.Write((bool)this.Val ? "true" : "false"); // correct capitalization
+ }
+ else
+ {
+ stream.Write((!) this.Val.ToString());
+ }
+ }
+ public override void Resolve(ResolutionContext! rc)
+ {
+ // nothing to resolve
+ }
+ public override void ComputeFreeVariables(Set /*Variable*/! freeVars) {
+ // no free variables to add
+ }
+
+ public override void Typecheck(TypecheckingContext! tc)
+ {
+ if (Val is BvConst && CommandLineOptions.Clo.Verify && CommandLineOptions.Clo.Bitvectors == CommandLineOptions.BvHandling.None)
+ tc.Error(this, "no bitvector handling specified, please use /bv:i or /bv:z flag");
+ this.Type = ShallowType;
+ }
+
+ public override Type! ShallowType {
+ get {
+ if (Val is bool)
+ {
+ return Type.Bool;
+ }
+ else if (Val is BigNum)
+ {
+ return Type.Int;
+ }
+ else if (Val is BvConst)
+ {
+ return Type.GetBvType(((BvConst)Val).Bits);
+ }
+ else
+ {
+ assert false; // like, where did this value come from?!
+ }
+ }
+ }
+
+ public bool IsFalse {
+ get {
+ return Val is bool && ((bool)Val) == false;
+ }
+ }
+ public bool IsTrue {
+ get {
+ return Val is bool && ((bool)Val) == true;
+ }
+ }
+ public override AI.IExpr! IExpr {
+ get {
+ return this;
+ }
+ }
+
+ // should be eliminated after converting everything to BigNums
+ private int asInt {
+ get {
+ return asBigNum.ToIntSafe;
+ }
+ }
+
+ public bool isBigNum {
+ get {
+ return Val is BigNum;
+ }
+ }
+
+ public BigNum asBigNum {
+ get {
+ assert isBigNum;
+ return (BigNum)(!)Val;
+ }
+ }
+
+ public bool isBool {
+ get {
+ return Val is bool;
+ }
+ }
+
+ public bool asBool {
+ get {
+ assert isBool;
+ return (bool)(!)Val;
+ }
+ }
+
+ public AI.IFunctionSymbol! FunctionSymbol {
+ get {
+ 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
+ {
+ assert false; // like, where did this value come from?!
+ }
+ }
+ }
+ public IList/*<AI.IExpr!>*/! Arguments {
+ get {
+ return ArrayList.ReadOnly(new AI.IExpr[0]);
+ }
+ }
+ public Microsoft.AbstractInterpretationFramework.IFunApp! CloneWithArguments(IList/*<AI.IExpr!>*/! args) {
+ assert args.Count == 0;
+ return this;
+ }
+ public AI.AIType! AIType {
+ get {
+ 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 {
+ assert false; // like, where did this value come from?!
+ }
+ }
+ }
+ [Pure]
+ public object DoVisit(AI.ExprVisitor! visitor)
+ {
+ return visitor.VisitFunApp(this);
+ }
+
+ public override Absy! StdDispatch(StandardVisitor! visitor)
+ {
+ return visitor.VisitLiteralExpr(this);
+ }
+ }
+
+ public class BvConst
+ {
+ public BigNum Value;
+ public int Bits;
+
+ public BvConst(BigNum v, int b)
+ {
+ assert v.Signum >= 0;
+ Value = v;
+ Bits = b;
+ }
+
+ [Pure]
+ public override string! ToString()
+ {
+ return Value + "bv" + Bits;
+ }
+
+ [Pure]
+ public string! ToReadableString()
+ {
+ if (Value > BigNum.FromInt(10000)) {
+ string! val = (!)Value.ToString("x");
+ int pos = val.Length % 4;
+ string! res = "0x" + val.Substring(0, pos);
+ while (pos < val.Length) {
+ res += "." + val.Substring(pos, 4);
+ pos += 4;
+ }
+ return res + ".bv" + Bits;
+ } else
+ return ToString();
+ }
+
+ [Pure][Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals(object obj)
+ {
+ BvConst other = obj as BvConst;
+ if (other == null) return false;
+
+ return Bits == other.Bits && Value == other.Value;
+ }
+
+ [Pure]
+ public override int GetHashCode()
+ {
+ unchecked {
+ return Value.GetHashCode() ^ Bits;
+ }
+ }
+ }
+
+ public class AIVariableExpr : Expr
+ {
+
+ public string Name; // identifier symbol
+ public AI.IVariable! Decl; // identifier declaration
+
+ /// <summary>
+ /// Creates an unresolved identifier expression.
+ /// </summary>
+ /// <param name="tok"></param>
+ /// <param name="name"></param>
+ public AIVariableExpr(IToken! tok, AI.IVariable! var)
+ : base(tok)
+ {
+ 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)
+ {
+ 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)
+ {
+ }
+ public override void ComputeFreeVariables(Set /*Variable*/! freeVars) {
+ if (Decl is Variable) {
+ freeVars.Add((Variable)Decl);
+ }
+ }
+ public override void Typecheck(TypecheckingContext! tc)
+ {
+ throw new System.NotImplementedException();
+ }
+ public override Type! ShallowType
+ {
+ get { throw new System.NotImplementedException(); }
+ }
+ public override AI.IExpr! IExpr {
+ get {
+ return Decl;
+ }
+ }
+
+ public override Absy! StdDispatch(StandardVisitor! visitor)
+ {
+ return visitor.VisitAIVariableExpr(this);
+ }
+ }
+
+ public class IdentifierExpr : Expr
+ {
+ public string! Name; // identifier symbol
+ public Variable Decl; // identifier declaration
+
+ /// <summary>
+ /// Creates an unresolved identifier expression. This constructor is intended to be called
+ /// only from within the parser; for use inside the translation, use another constructor, which
+ /// specifies the type of the expression.
+ /// </summary>
+ /// <param name="tok"></param>
+ /// <param name="name"></param>
+ internal IdentifierExpr(IToken! tok, string! name)
+ : base(tok)
+ {
+ Name = name;
+ // base(tok);
+ }
+ /// <summary>
+ /// Creates an unresolved identifier expression.
+ /// </summary>
+ /// <param name="tok"></param>
+ /// <param name="name"></param>
+ /// <param name="type"></param>
+ public IdentifierExpr(IToken! tok, string! name, Type! type)
+ : base(tok)
+ {
+ Name = name;
+ Type = type;
+ // base(tok);
+ }
+
+ /// <summary>
+ /// Creates a resolved identifier expression.
+ /// </summary>
+ /// <param name="tok"></param>
+ /// <param name="d"></param>
+ public IdentifierExpr(IToken! tok, Variable! d)
+ : base(tok)
+ {
+ Name = (!) d.Name;
+ Decl = d;
+ Type = d.TypedIdent.Type;
+ // base(tok);
+ }
+ [Pure][Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals(object obj)
+ {
+ if (obj == null) return false;
+ if (!(obj is IdentifierExpr)) return false;
+
+ IdentifierExpr other = (IdentifierExpr)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)
+ {
+ if (CommandLineOptions.Clo.PrintWithUniqueASTIds)
+ {
+ stream.Write("{0}^^", this.Decl == null ? "NoDecl" : "h"+this.Decl.GetHashCode());
+ }
+ stream.Write(this, "{0}", TokenTextWriter.SanitizeIdentifier(this.Name));
+ }
+ public override void Resolve(ResolutionContext! rc)
+ {
+ if (Decl != null)
+ {
+ // already resolved, but re-resolve type just in case it came from an unresolved type
+ if (Type != null) {
+ Type = Type.ResolveType(rc);
+ }
+ return;
+ }
+ Decl = rc.LookUpVariable(Name);
+ if (rc.StateMode == ResolutionContext.State.StateLess && Decl is GlobalVariable) {
+ rc.Error(this, "cannot refer to a global variable in this context: {0}", Name);
+ } else if (Decl == null) {
+ rc.Error(this, "undeclared identifier: {0}", Name);
+ }
+ if (Type != null) {
+ Type = Type.ResolveType(rc);
+ }
+ }
+ public override void ComputeFreeVariables(Set /*Variable*/! freeVars) {
+ assume this.Decl != null;
+ freeVars.Add(Decl);
+ }
+ public override void Typecheck(TypecheckingContext! tc)
+ {
+ if (this.Decl != null)
+ {
+ // sanity check
+ if (Type != null && !Type.Equals(Decl.TypedIdent.Type)) {
+ tc.Error(this, "internal error, shallow-type assignment was done incorrectly, {0}:{1} != {2}",
+ Name, Type, Decl.TypedIdent.Type);
+ assert false;
+ }
+ Type = Decl.TypedIdent.Type;
+ }
+ }
+
+ public override Type! ShallowType {
+ get {
+ assert Type != null;
+ return Type;
+ }
+ }
+
+ public sealed class ConstantFunApp : AI.IFunApp
+ {
+ private IdentifierExpr! identifierExpr;
+ public IdentifierExpr! IdentifierExpr { get { return identifierExpr; } }
+
+ private AI.IFunctionSymbol! symbol;
+ public AI.IFunctionSymbol! FunctionSymbol { get { return symbol; } }
+
+ private static IList! emptyArgs = ArrayList.ReadOnly((IList!)new ArrayList());
+ public IList! Arguments { get { return emptyArgs; } }
+
+ public AI.IFunApp! CloneWithArguments(IList! newargs) { return this; }
+
+ [Pure]
+ public object DoVisit(AI.ExprVisitor! visitor) { return visitor.VisitFunApp(this); }
+
+ public ConstantFunApp(IdentifierExpr! ie, Constant! c)
+ {
+ 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
+ {
+ if (iexprCache == null)
+ {
+ if (Decl is Constant)
+ iexprCache = new ConstantFunApp(this, (Constant)Decl);
+ else{
+ assume this.Decl != null;
+ iexprCache = Decl;
+ }
+ }
+ return iexprCache;
+ }
+ }
+
+ public override Absy! StdDispatch(StandardVisitor! visitor)
+ {
+ return visitor.VisitIdentifierExpr(this);
+ }
+ }
+
+ public class OldExpr : Expr
+ , AI.IFunApp // HACK
+ {
+ public Expr! Expr;
+ public OldExpr(IToken! tok, Expr! expr)
+ : base(tok)
+ {
+ Expr = expr;
+ }
+ [Pure][Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals(object obj)
+ {
+ if (obj == null) return false;
+ if (!(obj is OldExpr)) return false;
+
+ OldExpr other = (OldExpr)obj;
+ return object.Equals(this.Expr, other.Expr);
+ }
+ [Pure]
+ public override int GetHashCode()
+ {
+ return this.Expr == null ? 0 : this.Expr.GetHashCode();
+ }
+ public override void Emit(TokenTextWriter! stream, int contextBindingStrength, bool fragileContext)
+ {
+ stream.Write(this, "old(");
+ this.Expr.Emit(stream);
+ stream.Write(")");
+ }
+ public override void Resolve(ResolutionContext! rc)
+ {
+ if (rc.StateMode != ResolutionContext.State.Two)
+ {
+ rc.Error(this, "old expressions allowed only in two-state contexts");
+ }
+ Expr.Resolve(rc);
+ }
+ public override void ComputeFreeVariables(Set /*Variable*/! freeVars) {
+ Expr.ComputeFreeVariables(freeVars);
+ }
+ public override void Typecheck(TypecheckingContext! tc)
+ {
+ Expr.Typecheck(tc);
+ Type = Expr.Type;
+ }
+ public override Type! ShallowType {
+ get {
+ return Expr.ShallowType;
+ }
+ }
+ public override AI.IExpr! IExpr {
+ get {
+// Put back these lines when "HACK" removed
+// // An Old expression has no AI.IExpr representation
+// assert false;
+// throw new System.Exception(); // make compiler shut up
+ return this; // HACK
+ }
+ }
+ [Pure]
+ public object DoVisit(AI.ExprVisitor! visitor)
+ {
+ return visitor.VisitFunApp(this);
+ }
+ public AI.IFunApp! CloneWithArguments(IList/*<IExpr!>*/! args)
+ {
+ assume args.Count == 1;
+ AI.IExpr! iexpr = (AI.IExpr!)args[0];
+ return new OldExpr(Token.NoToken, BoogieFactory.IExpr2Expr(iexpr));
+ }
+ private IList/*?*/ argCache = null;
+ public IList/*<IExpr!*/! Arguments
+ {
+ get {
+ 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 AI.AIType! aitype = new AI.FunctionType(AI.Value.Type, AI.Value.Type);
+ public AI.AIType! AIType { get { return aitype; } }
+ private OldFunctionSymbol() { }
+ internal static OldFunctionSymbol! Sym = new OldFunctionSymbol();
+ [Pure]
+ public override string! ToString() { return "old"; }
+ }
+ public AI.IFunctionSymbol! FunctionSymbol
+ {
+ get { return OldFunctionSymbol.Sym; }
+ }
+
+ public override Absy! StdDispatch(StandardVisitor! visitor)
+ {
+ return visitor.VisitOldExpr(this);
+ }
+ }
+
+ public interface IAppliableVisitor<T> {
+
+ T Visit(UnaryOperator! unaryOperator);
+
+ T Visit(BinaryOperator! binaryOperator);
+
+ T Visit(FunctionCall! functionCall);
+
+ T Visit(LoopPredicateName! loopPredicateName);
+
+ T Visit(MapSelect! mapSelect);
+
+ T Visit(MapStore! mapStore);
+
+ T Visit(TypeCoercion! typeCoercion);
+ }
+
+ public interface IAppliable
+ {
+ string! FunctionName { get; }
+
+ /// <summary>
+ /// Emits to "stream" the operator applied to the given arguments.
+ /// The length of "args" can be anything that the parser allows for this appliable operator
+ /// (but can be nothing else).
+ /// </summary>
+ /// <param name="args"></param>
+ /// <param name="stream"></param>
+ /// <param name="contextBindingStrength"></param>
+ /// <param name="fragileContext"></param>
+ void Emit(ExprSeq! args, TokenTextWriter! stream, int contextBindingStrength, bool fragileContext);
+
+ void Resolve(ResolutionContext! rc, Expr! subjectForErrorReporting);
+
+ /// <summary>
+ /// Requires the object to have been properly resolved.
+ /// </summary>
+ int ArgumentCount { get; }
+
+ /// <summary>
+ /// Typechecks the arguments "args" for the Appliable. If the arguments are
+ /// appropriate, returns the result type; otherwise returns null.
+ /// As result of the type checking, the values of type parameters of the
+ /// appliable can be returned (which are then stored in the NAryExpr and later
+ /// also used in the VCExprAST).
+ /// Requires the object to have been successfully resolved.
+ /// Requires args.Length == ArgumentCount.
+ /// Requires all elements of "args" to have a non-null Type field.
+ /// </summary>
+ /// <param name="args"></param>
+ /// <param name="tc"></param>
+ Type Typecheck(ref ExprSeq! args, out TypeParamInstantiation! tpInstantiation, TypecheckingContext! tc);
+ ensures args.Length == old(args.Length);
+ // requires Microsoft.SpecSharp.Collections.Reductions.Forall{Expr! arg in args; arg.Type != null};
+
+ /// <summary>
+ /// Returns the result type of the IAppliable, supposing the argument are of the correct types.
+ /// </summary>
+ Type! ShallowType(ExprSeq! args);
+
+ AI.IFunctionSymbol! AIFunctionSymbol { get; }
+
+ T Dispatch<T>(IAppliableVisitor<T>! visitor);
+ }
+
+ public interface IOverloadedAppliable
+ {
+ void ResolveOverloading(NAryExpr! expr);
+ }
+
+ public class UnaryOperator : IAppliable
+ {
+ private IToken! tok;
+ public enum Opcode { Not };
+ private Opcode op;
+ public Opcode Op { get { return op; } }
+ public UnaryOperator (IToken! tok, Opcode op) { this.tok = tok; this.op = op; }
+
+ [Pure][Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals(object obj)
+ {
+ if (obj == null) return false;
+ if (!(obj is UnaryOperator)) return false;
+
+ UnaryOperator other = (UnaryOperator)obj;
+ return object.Equals(this.op, other.op);
+ }
+ [Pure]
+ public override int GetHashCode()
+ {
+ return (int) this.op;
+ }
+
+ public string! FunctionName
+ {
+ get
+ {
+ switch (this.op)
+ {
+ case Opcode.Not: return "!";
+ }
+ System.Diagnostics.Debug.Fail("unknown unary operator: " + op.ToString());
+ throw new Exception();
+ }
+ }
+
+ public AI.IFunctionSymbol! AIFunctionSymbol {
+ get {
+ 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)
+ {
+ stream.SetToken(ref this.tok);
+ assert args.Length == 1;
+ // determine if parens are needed
+ int opBindingStrength = 0x60;
+ bool parensNeeded = opBindingStrength < contextBindingStrength ||
+ (fragileContext && opBindingStrength == contextBindingStrength);
+
+ if (parensNeeded)
+ {
+ stream.Write("(");
+ }
+ stream.Write(FunctionName);
+ ((!)args[0]).Emit(stream, opBindingStrength, false);
+ if (parensNeeded)
+ {
+ stream.Write(")");
+ }
+ }
+
+ public void Resolve(ResolutionContext! rc, Expr! subjectForErrorReporting)
+ {
+ if (rc.TriggerMode && this.op == Opcode.Not) {
+ rc.Error(subjectForErrorReporting, "boolean operators are not allowed in triggers");
+ }
+ }
+
+ public int ArgumentCount
+ {
+ get
+ {
+ return 1;
+ }
+ }
+
+ public Type Typecheck(ref ExprSeq! args, out TypeParamInstantiation! tpInstantiation, TypecheckingContext! tc)
+ {
+ assume args.Length == 1;
+ tpInstantiation = SimpleTypeParamInstantiation.EMPTY;
+ Type arg0type = (!)((!)args[0]).Type;
+ switch (this.op)
+ {
+ case Opcode.Not:
+ if (arg0type.Unify(Type.Bool))
+ {
+ return Type.Bool;
+ }
+ goto BAD_TYPE;
+ }
+ System.Diagnostics.Debug.Fail("unknown unary operator: " + op.ToString());
+ assert false;
+ BAD_TYPE:
+ tc.Error(this.tok, "invalid argument type ({1}) to unary operator {0}",
+ this.FunctionName, arg0type);
+ return null;
+ }
+ public Type! ShallowType(ExprSeq! args) {
+ switch (this.op) {
+ case Opcode.Not:
+ return Type.Bool;
+ default:
+ assert false; // unexpected unary operator
+ }
+ }
+
+ public object Evaluate (object argument)
+ {
+ if (argument == null) { return null; }
+ switch (this.op)
+ {
+ case Opcode.Not:
+ if (argument is bool) { return ! ((bool)argument); }
+ throw new System.InvalidOperationException("unary Not only applies to bool");
+ }
+ return null; // unreachable
+ }
+
+ public T Dispatch<T>(IAppliableVisitor<T>! visitor) {
+ return visitor.Visit(this);
+ }
+ }
+
+ public class BinaryOperator : IAppliable, IOverloadedAppliable
+ {
+ private IToken! tok;
+ public enum Opcode { Add, Sub, Mul, Div, Mod, Eq, Neq, Gt, Ge, Lt, Le, And, Or, Imp, Iff, Subtype };
+ private Opcode op;
+ public Opcode Op { get { return op; } }
+ public BinaryOperator (IToken! tok, Opcode op) { this.tok = tok; this.op = op; }
+
+ [Pure][Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals(object obj)
+ {
+ if (obj == null) return false;
+ if (!(obj is BinaryOperator)) return false;
+
+ BinaryOperator other = (BinaryOperator)obj;
+ return object.Equals(this.op, other.op);
+ }
+
+ [Pure]
+ public override int GetHashCode()
+ {
+ return (int) this.op << 1;
+ }
+
+ public string! FunctionName
+ {
+ get
+ {
+ switch (this.op)
+ {
+ case Opcode.Add: return "+";
+ case Opcode.Sub: return "-";
+ case Opcode.Mul: return "*";
+ case Opcode.Div: return "/";
+ case Opcode.Mod: return "%";
+ case Opcode.Eq: return "==";
+ case Opcode.Neq: return "!=";
+ case Opcode.Gt: return ">";
+ case Opcode.Ge: return ">=";
+ case Opcode.Lt: return "<";
+ case Opcode.Le: return "<=";
+ case Opcode.And: return "&&";
+ case Opcode.Or: return "||";
+ case Opcode.Imp: return "==>";
+ case Opcode.Iff: return "<==>";
+ case Opcode.Subtype: return "<:";
+ }
+ System.Diagnostics.Debug.Fail("unknown binary operator: " + op.ToString());
+ throw new Exception();
+ }
+ }
+
+ public AI.IFunctionSymbol! AIFunctionSymbol {
+ get {
+ 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)
+ {
+ stream.SetToken(ref this.tok);
+ assert args.Length == 2;
+ // determine if parens are needed
+ int opBindingStrength;
+ bool fragileLeftContext = false; // false means "allow same binding power on left without parens"
+ bool fragileRightContext = false; // false means "allow same binding power on right without parens"
+ switch (this.op)
+ {
+ case Opcode.Add:
+ opBindingStrength = 0x40; break;
+ case Opcode.Sub:
+ opBindingStrength = 0x40; fragileRightContext = true; break;
+ case Opcode.Mul:
+ opBindingStrength = 0x50; break;
+ case Opcode.Div:
+ opBindingStrength = 0x50; fragileRightContext = true; break;
+ case Opcode.Mod:
+ opBindingStrength = 0x50; fragileRightContext = true; break;
+ case Opcode.Eq:
+ case Opcode.Neq:
+ case Opcode.Gt:
+ case Opcode.Ge:
+ case Opcode.Lt:
+ case Opcode.Le:
+ case Opcode.Subtype:
+ opBindingStrength = 0x30;
+ fragileLeftContext = fragileRightContext = true;
+ break;
+ case Opcode.And:
+ opBindingStrength = 0x20; break;
+ case Opcode.Or:
+ opBindingStrength = 0x21; break;
+ case Opcode.Imp:
+ opBindingStrength = 0x10; fragileLeftContext = true; break;
+ case Opcode.Iff:
+ opBindingStrength = 0x00; break;
+ default:
+ System.Diagnostics.Debug.Fail("unknown binary operator: " + op.ToString());
+ opBindingStrength = -1; // to please compiler, which refuses to consider whether or not all enumeration cases have been considered!
+ break;
+ }
+ int opBS = opBindingStrength & 0xF0;
+ int ctxtBS = contextBindingStrength & 0xF0;
+ bool parensNeeded = opBS < ctxtBS ||
+ (opBS == ctxtBS && (opBindingStrength != contextBindingStrength || fragileContext));
+
+ if (parensNeeded)
+ {
+ stream.Write("(");
+ }
+ ((!)args[0]).Emit(stream, opBindingStrength, fragileLeftContext);
+ stream.Write(" {0} ", FunctionName);
+ ((!)args[1]).Emit(stream, opBindingStrength, fragileRightContext);
+ if (parensNeeded)
+ {
+ stream.Write(")");
+ }
+ }
+ public void Resolve(ResolutionContext! rc, Expr! subjectForErrorReporting)
+ {
+ if (rc.TriggerMode) {
+ switch (this.op)
+ {
+ case Opcode.Add:
+ case Opcode.Sub:
+ case Opcode.Mul:
+ case Opcode.Div:
+ case Opcode.Mod:
+ case Opcode.Neq: // Neq is allowed, but not Eq
+ case Opcode.Subtype:
+ // These are fine
+ break;
+
+ case Opcode.Eq:
+ rc.Error(subjectForErrorReporting, "equality is not allowed in triggers");
+ break;
+
+ case Opcode.Gt:
+ case Opcode.Ge:
+ case Opcode.Lt:
+ case Opcode.Le:
+ rc.Error(subjectForErrorReporting, "arithmetic comparisons are not allowed in triggers");
+ break;
+
+ case Opcode.And:
+ case Opcode.Or:
+ case Opcode.Imp:
+ case Opcode.Iff:
+ rc.Error(subjectForErrorReporting, "boolean operators are not allowed in triggers");
+ break;
+
+ default:
+ System.Diagnostics.Debug.Fail("unknown binary operator: " + this.op.ToString());
+ break;
+ }
+ }
+ }
+ public int ArgumentCount
+ {
+ get
+ {
+ return 2;
+ }
+ }
+ public Type Typecheck(ref ExprSeq! args, out TypeParamInstantiation! tpInstantiation, TypecheckingContext! tc)
+ {
+ assert args.Length == 2;
+ // the default; the only binary operator with a type parameter is equality, but right
+ // we don't store this parameter because it does not appear necessary
+ tpInstantiation = SimpleTypeParamInstantiation.EMPTY;
+ Expr arg0 = (!)args[0];
+ Expr arg1 = (!)args[1];
+ Type arg0type = (!)arg0.Type;
+ Type arg1type = (!)arg1.Type;
+ switch (this.op)
+ {
+ case Opcode.Add:
+ case Opcode.Sub:
+ case Opcode.Mul:
+ case Opcode.Div:
+ case Opcode.Mod:
+ if (arg0type.Unify(Type.Int) && arg1type.Unify(Type.Int)) {
+ return Type.Int;
+ }
+ goto BAD_TYPE;
+ case Opcode.Eq:
+ case Opcode.Neq:
+ // Comparison is allowed if the argument types are unifiable
+ // (i.e., if there is any chance that the values of the arguments are
+ // in the same domain)
+ if (arg0type.Equals(arg1type)) {
+ // quick path
+ return Type.Bool;
+ }
+ TypeVariableSeq! unifiable = new TypeVariableSeq ();
+ unifiable.AddRange(arg0type.FreeVariables);
+ unifiable.AddRange(arg1type.FreeVariables);
+
+ if (arg0type.Unify(arg1type, unifiable, new Dictionary<TypeVariable!, Type!> ()))
+ return Type.Bool;
+ goto BAD_TYPE;
+ case Opcode.Gt:
+ case Opcode.Ge:
+ case Opcode.Lt:
+ case Opcode.Le:
+ if (arg0type.Unify(Type.Int) && arg1type.Unify(Type.Int)) {
+ return Type.Bool;
+ }
+ goto BAD_TYPE;
+ case Opcode.And:
+ case Opcode.Or:
+ case Opcode.Imp:
+ case Opcode.Iff:
+ if (arg0type.Unify(Type.Bool) && arg1type.Unify(Type.Bool)) {
+ return Type.Bool;
+ }
+ goto BAD_TYPE;
+ case Opcode.Subtype:
+ // Subtype is polymorphically typed and can compare things of
+ // arbitrary types (but both arguments must have the same type)
+ if (arg0type.Unify(arg1type))
+ {
+ return Type.Bool;
+ }
+ goto BAD_TYPE;
+ }
+ System.Diagnostics.Debug.Fail("unknown binary operator: " + op.ToString());
+ assert false;
+ BAD_TYPE:
+ tc.Error(this.tok, "invalid argument types ({1} and {2}) to binary operator {0}", this.FunctionName, arg0type, arg1type);
+ return null;
+ }
+
+ public Type! ShallowType(ExprSeq! args) {
+ switch (this.op)
+ {
+ case Opcode.Add:
+ case Opcode.Sub:
+ case Opcode.Mul:
+ case Opcode.Div:
+ case Opcode.Mod:
+ return Type.Int;
+
+ case Opcode.Eq:
+ case Opcode.Neq:
+ case Opcode.Gt:
+ case Opcode.Ge:
+ case Opcode.Lt:
+ case Opcode.Le:
+ case Opcode.And:
+ case Opcode.Or:
+ case Opcode.Imp:
+ case Opcode.Iff:
+ case Opcode.Subtype:
+ return Type.Bool;
+
+ default:
+ assert false; // unexpected binary operator
+ }
+ }
+
+ public void ResolveOverloading(NAryExpr! expr)
+ {
+ Expr arg0 = (!) expr.Args[0];
+ Expr arg1 = (!) expr.Args[1];
+ switch (op)
+ {
+ case Opcode.Eq:
+ if (arg0.Type != null && arg0.Type.IsBool && arg1.Type != null && arg1.Type.IsBool)
+ {
+ expr.Fun = new BinaryOperator(tok, Opcode.Iff);
+ }
+ break;
+ case Opcode.Neq:
+ if (arg0.Type != null && arg0.Type.IsBool && arg1.Type != null && arg1.Type.IsBool)
+ {
+ expr.Fun = new BinaryOperator(tok, Opcode.Iff);
+ arg1 = new NAryExpr(expr.tok, new UnaryOperator(tok, UnaryOperator.Opcode.Not), new ExprSeq(arg1));
+
+ // ugly ... there should be some more general approach,
+ // e.g., to typecheck the whole expression again
+ arg1.Type = Type.Bool;
+ ((NAryExpr)arg1).TypeParameters = SimpleTypeParamInstantiation.EMPTY;
+
+ expr.Args[1] = arg1;
+ }
+ break;
+ }
+ }
+
+ public object Evaluate (object e1, object e2)
+ {
+ if (e1 == null || e2 == null) { return null; }
+
+ switch (this.op)
+ {
+ case Opcode.Add:
+ if (e1 is BigNum && e2 is BigNum) { return ((BigNum)e1)+((BigNum)e2); }
+ break;
+ case Opcode.Sub:
+ if (e1 is BigNum && e2 is BigNum) { return ((BigNum)e1)-((BigNum)e2); }
+ break;
+ case Opcode.Mul:
+ if (e1 is BigNum && e2 is BigNum) { return ((BigNum)e1)*((BigNum)e2); }
+ break;
+ case Opcode.Div:
+ if (e1 is BigNum && e2 is BigNum) { return /* TODO: right semantics? */ ((BigNum)e1)/((BigNum)e2); }
+ break;
+ case Opcode.Mod:
+ if (e1 is BigNum && e2 is BigNum) { return /* TODO: right semantics? */ ((BigNum)e1)%((BigNum)e2); }
+ break;
+ case Opcode.Lt:
+ if (e1 is BigNum && e2 is BigNum) { return ((BigNum)e1)<((BigNum)e2); }
+ break;
+ case Opcode.Le:
+ if (e1 is BigNum && e2 is BigNum) { return ((BigNum)e1)<=((BigNum)e2); }
+ break;
+ case Opcode.Gt:
+ if (e1 is BigNum && e2 is BigNum) { return ((BigNum)e1)>((BigNum)e2); }
+ break;
+ case Opcode.Ge:
+ if (e1 is BigNum && e2 is BigNum) { return ((BigNum)e1)>=((BigNum)e2); }
+ break;
+
+ case Opcode.And: if (e1 is bool && e2 is bool) { return (bool)e1 && (bool)e2; } break;
+ case Opcode.Or: if (e1 is bool && e2 is bool) { return (bool)e1 || (bool)e2; } break;
+ case Opcode.Imp: if (e1 is bool && e2 is bool) { return ! (bool)e1 || (bool)e2; } break;
+ case Opcode.Iff: if (e1 is bool && e2 is bool) { return e1 == e2; } break;
+
+ case Opcode.Eq: return Equals(e1,e2);
+ case Opcode.Neq: return ! Equals(e1,e2);
+
+ case Opcode.Subtype: throw new System.NotImplementedException();
+ }
+ throw new System.InvalidOperationException("bad types to binary operator " + this.op);
+ }
+
+ public T Dispatch<T>(IAppliableVisitor<T>! visitor) {
+ return visitor.Visit(this);
+ }
+
+ }
+
+ public class FunctionCall : IAppliable, AI.IFunctionSymbol
+ {
+ private IdentifierExpr! name;
+ public Function Func;
+ public FunctionCall(IdentifierExpr! name) { this.name = name; }
+ public string! FunctionName { get { return this.name.Name; } }
+
+ public AI.IFunctionSymbol! AIFunctionSymbol {
+ get {
+ 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() {
+ return name.Name;
+ }
+
+ [Pure][Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals(object other) {
+ FunctionCall fc = other as FunctionCall;
+ return fc != null && this.Func == fc.Func;
+ }
+ [Pure]
+ public override int GetHashCode()
+ {
+ assume this.Func != null;
+ return Func.GetHashCode();
+ }
+
+ public AI.AIType! AIType {
+ get
+ {
+ assume this.Func != null;
+ return AI.Value.FunctionType(this.Func.InParams.Length);
+ }
+ }
+
+ virtual public void Emit(ExprSeq! args, TokenTextWriter! stream, int contextBindingStrength, bool fragileContext)
+ {
+ this.name.Emit(stream, 0xF0, false);
+ stream.Write("(");
+ args.Emit(stream);
+ stream.Write(")");
+ }
+ public void Resolve(ResolutionContext! rc, Expr! subjectForErrorReporting)
+ {
+ if (Func != null)
+ {
+ // already resolved
+ return;
+ }
+ Func = rc.LookUpProcedure(name.Name) as Function;
+ if (Func == null)
+ {
+ rc.Error(this.name, "use of undeclared function: {0}", name.Name);
+ }
+ }
+ public virtual int ArgumentCount
+ {
+ get
+ {
+ assume Func != null; // ArgumentCount requires object to be properly resolved.
+ return Func.InParams.Length;
+ }
+ }
+ public virtual Type Typecheck(ref ExprSeq! actuals, out TypeParamInstantiation! tpInstantiation, TypecheckingContext! tc)
+ {
+ assume this.Func != null;
+ assume actuals.Length == Func.InParams.Length;
+ assume Func.OutParams.Length == 1;
+
+ List<Type!>! resultingTypeArgs;
+ TypeSeq actualResultType =
+ Type.CheckArgumentTypes(Func.TypeParameters,
+ out resultingTypeArgs,
+ Func.InParams.ToTypeSeq,
+ actuals,
+ Func.OutParams.ToTypeSeq,
+ null,
+ // we need some token to report a possibly wrong number of
+ // arguments
+ actuals.Length > 0 ? ((!)actuals[0]).tok : Token.NoToken,
+ "application of " + name.Name,
+ tc);
+
+ if (actualResultType == null) {
+ tpInstantiation = SimpleTypeParamInstantiation.EMPTY;
+ return null;
+ } else {
+ assert actualResultType.Length == 1;
+ tpInstantiation =
+ SimpleTypeParamInstantiation.From(Func.TypeParameters, resultingTypeArgs);
+ return actualResultType[0];
+ }
+ }
+ public Type! ShallowType(ExprSeq! args) {
+ assume name.Type != null;
+ return name.Type;
+ }
+
+ public virtual T Dispatch<T>(IAppliableVisitor<T>! visitor) {
+ return visitor.Visit(this);
+ }
+ }
+
+ public class TypeCoercion : IAppliable {
+ private IToken! tok;
+ public Type! Type;
+
+ public TypeCoercion(IToken! tok, Type! type) {
+ this.tok = tok;
+ this.Type = type;
+ }
+
+ public string! FunctionName { get {
+ return ":";
+ } }
+
+ public void Emit(ExprSeq! args, TokenTextWriter! stream,
+ int contextBindingStrength, bool fragileContext) {
+ stream.SetToken(ref this.tok);
+ assert args.Length == 1;
+ // determine if parens are needed
+ int opBindingStrength = 0x90;
+ bool parensNeeded = opBindingStrength < contextBindingStrength ||
+ (fragileContext && opBindingStrength == contextBindingStrength);
+
+ if (parensNeeded)
+ stream.Write("(");
+
+ ((!)args[0]).Emit(stream, opBindingStrength, false);
+ stream.Write(FunctionName);
+ Type.Emit(stream, 0);
+
+ if (parensNeeded)
+ stream.Write(")");
+ }
+
+ public void Resolve(ResolutionContext! rc, Expr! subjectForErrorReporting) {
+ this.Type = this.Type.ResolveType(rc);
+ }
+
+ public int ArgumentCount { get {
+ return 1;
+ } }
+
+ public Type Typecheck(ref ExprSeq! args,
+ out TypeParamInstantiation! tpInstantiation,
+ TypecheckingContext! tc) {
+ assume args.Length == 1;
+ tpInstantiation = SimpleTypeParamInstantiation.EMPTY;
+
+ if (!this.Type.Unify((!)((!)args[0]).Type))
+ tc.Error(this.tok, "{0} cannot be coerced to {1}",
+ ((!)args[0]).Type, this.Type);
+ return this.Type;
+ }
+
+ public Type! ShallowType(ExprSeq! args) {
+ return this.Type;
+ }
+
+ public AI.IFunctionSymbol! AIFunctionSymbol { get {
+ // not really clear what should be returned here ...
+ // should the operation be completely invisible for the abstract interpretation?
+ return AI.Heap.UnsupportedHeapOp;
+ } }
+
+ public T Dispatch<T>(IAppliableVisitor<T>! visitor) {
+ return visitor.Visit(this);
+ }
+
+ }
+
+ /// <summary>
+ /// A subclass of FunctionCall that stands for a zero-argument function call, used as a loop invariant placeholder
+ /// </summary>
+ public class LoopPredicateName : FunctionCall
+ {
+ private Block! block; // The block the predicate refers to
+ public Block! Block
+ {
+ get
+ {
+ return block;
+ }
+ }
+
+ private string! blockName; // The name of the block
+ private ICollection<Block!>! component;
+ public ICollection<Block!>! Component
+ {
+ get
+ {
+ return this.component;
+ }
+ }
+
+ public string! Name
+ {
+ get
+ {
+ return "J_" + this.blockName;
+ }
+ }
+
+ invariant block.Label == blockName; // Note that we ask for object equality of strings...
+
+ private Hashtable /* Var -> Incarnations */ preHavocIncarnationMap;
+ public Hashtable PreHavocIncarnationMap
+ {
+ get
+ {
+ return this.preHavocIncarnationMap;
+ }
+ }
+
+ private Hashtable /* Var -> Incarnations */ postHavocIncarnationMap;
+ public Hashtable PostHavocIncarnationMap
+ {
+ get
+ {
+ return this.postHavocIncarnationMap;
+ }
+ }
+
+
+ // Those below are the inverse maps of the maps between variables and incarnations
+ private Hashtable /* String -> Var */ preHavocIncarnationInverseMap;
+ private Hashtable /* String -> Var */ postHavocIncarnationInverseMap;
+
+ public Hashtable PreHavocInverseMap
+ {
+ get
+ {
+ if(this.preHavocIncarnationInverseMap == null)
+ {
+ this.preHavocIncarnationInverseMap = new Hashtable();
+ assert this.preHavocIncarnationMap != null; // If we get at this point, then something is wrong with the program
+ foreach(object! key in (!) (this.preHavocIncarnationMap).Keys)
+ {
+ object! val = (!) this.preHavocIncarnationMap[key];
+ if(!this.preHavocIncarnationInverseMap.ContainsKey(val.ToString()))
+ this.preHavocIncarnationInverseMap.Add(val.ToString(), key);
+ }
+ }
+ return this.preHavocIncarnationInverseMap;
+ }
+ }
+
+ public Hashtable PostHavocInverseMap
+ {
+ get
+ {
+ if(this.postHavocIncarnationInverseMap == null)
+ {
+ this.postHavocIncarnationInverseMap = new Hashtable();
+ assert this.postHavocIncarnationMap != null; // If it is null, something is wrong before...
+ foreach(object! key in (!) (this.postHavocIncarnationMap).Keys)
+ {
+ object! val = (!) this.postHavocIncarnationMap[key];
+ if(!this.postHavocIncarnationInverseMap.ContainsKey(val.ToString()))
+ this.postHavocIncarnationInverseMap.Add(val.ToString(), key);
+ }
+ }
+ return this.postHavocIncarnationInverseMap;
+ }
+ }
+
+ /// <summary>
+ /// Create a new LoopPredicate
+ /// </summary>
+ public LoopPredicateName(Block! block, ICollection<Block!>! component)
+ : base(new IdentifierExpr(Token.NoToken, "J_"+ block.Label, Type.Bool))
+ {
+ this.block = block;
+ this.blockName = block.Label;
+ this.component = component;
+ // base(new IdentifierExpr(Token.NoToken, "J_"+ block.Label, Type.Bool));
+ }
+
+ public void SetPreAndPostHavocIncarnationMaps(Hashtable pre, Hashtable post)
+ {
+ assert this.preHavocIncarnationMap == null && this.postHavocIncarnationMap == null;
+
+ this.preHavocIncarnationMap = pre;
+ this.postHavocIncarnationMap = post;
+ }
+
+ /// <summary>
+ /// Writes down the loop predicate and the incarnations map before and after the havoc statements
+ /// </summary>
+ public override void Emit(ExprSeq! args, TokenTextWriter! stream, int contextBindingStrength, bool fragileContext)
+ {
+ string! pre, post;
+
+ if(this.postHavocIncarnationMap != null && this.preHavocIncarnationMap != null)
+ {
+ pre = "pre: [ " + hashtableToString(this.preHavocIncarnationMap) +" ]";
+ post = "post: [ " + hashtableToString(this.postHavocIncarnationMap) +" ]";
+ }
+ else
+ {
+ pre = post = "[]";
+ }
+
+ stream.Write("J_" + this.blockName);
+ stream.Write("(");
+ stream.Write(pre + ", " + post);
+ stream.Write(")");
+ }
+
+ public override Type Typecheck(ref ExprSeq! actuals, out TypeParamInstantiation! tpInstantiation, TypecheckingContext! tc)
+ {
+ tpInstantiation = SimpleTypeParamInstantiation.EMPTY;
+ return Type.Bool;
+ }
+
+ public override int ArgumentCount { get { return 0; } }
+
+ private string! hashtableToString(Hashtable! map)
+ {
+ string! outVal = "";
+
+ foreach (object! key in map.Keys)
+ {
+ object val = map[key];
+ outVal += key + " -> " + val + ",";
+ }
+
+ return outVal;
+ }
+
+ public override T Dispatch<T>(IAppliableVisitor<T>! visitor) {
+ return visitor.Visit(this);
+ }
+
+ }
+
+ public class NAryExpr : Expr, AI.IFunApp
+ {
+ [Additive] [Peer]
+ public IAppliable! Fun;
+ public ExprSeq! Args;
+
+ // The instantiation of type parameters that is determined during type checking.
+ // Which type parameters are available depends on the IAppliable
+ public TypeParamInstantiation TypeParameters = null;
+
+ [Captured]
+ public NAryExpr(IToken! tok, IAppliable! fun, ExprSeq! args)
+ : base(tok)
+ {
+ Fun = fun;
+ Args = args;
+ assert forall{Expr arg in args; arg != null};
+ }
+ [Pure][Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals(object obj)
+ {
+ if (obj == null) return false;
+ if (!(obj is NAryExpr)) return false;
+
+ NAryExpr other = (NAryExpr)obj;
+ return object.Equals(this.Fun, other.Fun) && object.Equals(this.Args, other.Args);
+ }
+ [Pure]
+ public override int GetHashCode()
+ {
+ int h = this.Fun.GetHashCode();
+ h ^= this.Args.GetHashCode();
+ return h;
+ }
+ public override void Emit(TokenTextWriter! stream, int contextBindingStrength, bool fragileContext)
+ {
+ stream.SetToken(this);
+ Fun.Emit(Args, stream, contextBindingStrength, fragileContext);
+ }
+ public override void Resolve(ResolutionContext! rc)
+ {
+ Fun.Resolve(rc, this);
+ foreach (Expr! e in Args)
+ {
+ e.Resolve(rc);
+ }
+ }
+ public override void ComputeFreeVariables(Set /*Variable*/! freeVars) {
+ foreach (Expr! e in Args) {
+ e.ComputeFreeVariables(freeVars);
+ }
+ // also add the free type variables
+ if (TypeParameters != null) {
+ foreach (TypeVariable! var in TypeParameters.FormalTypeParams)
+ foreach (TypeVariable! w in TypeParameters[var].FreeVariables)
+ freeVars.Add(w);
+ }
+ }
+ public override void Typecheck(TypecheckingContext! tc)
+ {
+ int prevErrorCount = tc.ErrorCount;
+ foreach (Expr! e in Args)
+ {
+ e.Typecheck(tc);
+ }
+ if (Fun.ArgumentCount != Args.Length)
+ {
+ tc.Error(this, "wrong number of arguments to function: {0} ({1} instead of {2})",
+ Fun.FunctionName, Args.Length, Fun.ArgumentCount);
+ }
+ else if (tc.ErrorCount == prevErrorCount &&
+ // if the type parameters are set, this node has already been
+ // typechecked and does not need to be checked again
+ TypeParameters == null)
+ {
+ TypeParamInstantiation! tpInsts;
+ Type = Fun.Typecheck(ref Args, out tpInsts, tc);
+ if (Type != null && Type.IsBv && CommandLineOptions.Clo.Verify && CommandLineOptions.Clo.Bitvectors == CommandLineOptions.BvHandling.None) {
+ tc.Error(this, "no bitvector handling specified, please use /bv:i or /bv:z flag");
+ }
+ TypeParameters = tpInsts;
+ }
+ IOverloadedAppliable oa = Fun as IOverloadedAppliable;
+ if (oa != null)
+ {
+ oa.ResolveOverloading(this);
+ }
+ if (Type == null) {
+ // set Type to some non-null value
+ Type = new TypeProxy(this.tok, "type_checking_error");
+ }
+ }
+ public override Type! ShallowType {
+ get {
+ return Fun.ShallowType(Args);
+ }
+ }
+
+ public override AI.IExpr! IExpr {
+ get {
+ return this;
+ }
+ }
+ public AI.IFunctionSymbol! FunctionSymbol {
+ get {
+ return Fun.AIFunctionSymbol;
+ }
+ }
+ public IList/*<AI.IExpr!>*/! Arguments {
+ get {
+ AI.IExpr[] a = new AI.IExpr[Args.Length];
+ for (int i = 0; i < Args.Length; i++) {
+ a[i] = ((!)Args[i]).IExpr;
+ }
+ return ArrayList.ReadOnly(a);
+ }
+ }
+ public AI.IFunApp! CloneWithArguments(IList/*<AI.IExpr!>*/! args) {
+ return new NAryExpr(this.tok, this.Fun, BoogieFactory.IExprArray2ExprSeq(args));
+ }
+
+ [Pure]
+ public object DoVisit(AI.ExprVisitor! visitor)
+ {
+ return visitor.VisitFunApp(this);
+ }
+
+ public override Absy! StdDispatch(StandardVisitor! visitor)
+ {
+ return visitor.VisitNAryExpr(this);
+ }
+ }
+
+ /// <summary>
+ /// An instance of LoopPredicate stands for a loop invariant predicate
+ /// </summary>
+ public class LoopPredicate : NAryExpr
+ {
+ private static ExprSeq! emptyArgs = new ExprSeq(new Expr[0]); // Share the emptylist of arguments among several instances
+
+ invariant loopPredicateName == Fun; // loopPredicateName is just a way of subtyping Fun...
+ LoopPredicateName! loopPredicateName;
+
+ Hashtable /* Var -> Expr */ preHavocIncarnationMap;
+ Hashtable /* Var -> Expr */ postHavocIncarnationMap;
+
+ private Block! block; // The block the predicate refers to
+ private string! BlockName; // Name of the widen block the predicate refers to
+ private ICollection<Block!> component; // The component the block belongs to
+
+ /// <summary>
+ /// Create a predicate (standing for a loop invariant). The parameter are the name of the block and the (strong) connect components the block belongs to
+ /// </summary>
+ public LoopPredicate(Block! block, ICollection<Block!>! component)
+ {
+ this.block = block;
+ this.BlockName = block.Label;
+ this.component = component;
+
+ LoopPredicateName! tmp; // to please the compiler we introde a temp variable
+ this.loopPredicateName = tmp = new LoopPredicateName(block, component);
+ base(Token.NoToken, tmp, emptyArgs); // due to locally computed data
+ }
+
+ public void SetPreAndPostHavocIncarnationMaps(Hashtable pre, Hashtable post)
+ {
+ assert this.preHavocIncarnationMap == null && this.postHavocIncarnationMap == null; // The method must be called just once
+
+ this.preHavocIncarnationMap = pre;
+ this.postHavocIncarnationMap = post;
+ this.loopPredicateName.SetPreAndPostHavocIncarnationMaps(pre, post);
+ }
+
+ [Pure][Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals(object obj)
+ {
+ if (obj == null) return false;
+ if (!(obj is LoopPredicate)) return false;
+
+ LoopPredicate pred = (LoopPredicate) obj;
+ return this.BlockName.Equals(pred.BlockName);
+ }
+
+ [Pure]
+ public override int GetHashCode()
+ {
+ return this.BlockName.GetHashCode();
+ }
+
+ public override Absy! StdDispatch(StandardVisitor! visitor)
+ {
+ return visitor.VisitLoopPredicate(this);
+ }
+ }
+
+ public class MapSelect : IAppliable, AI.IFunctionSymbol {
+
+ public readonly int Arity;
+ private readonly IToken! tok;
+
+ public MapSelect(IToken! tok, int arity) {
+ this.tok = tok;
+ this.Arity = arity;
+ }
+
+ public string! FunctionName { get {
+ return "MapSelect";
+ } }
+
+ [Pure][Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals(object obj)
+ {
+ if (!(obj is MapSelect)) return false;
+
+ MapSelect other = (MapSelect)obj;
+ return this.Arity == other.Arity;
+ }
+
+ [Pure]
+ public override int GetHashCode()
+ {
+ return Arity.GetHashCode() * 2823;
+ }
+
+ public void Emit(ExprSeq! args, TokenTextWriter! stream,
+ int contextBindingStrength, bool fragileContext) {
+ assume args.Length == Arity + 1;
+ Emit(args, stream, contextBindingStrength, fragileContext, false);
+ }
+
+ public static void Emit(ExprSeq! args, TokenTextWriter! stream,
+ int contextBindingStrength, bool fragileContext,
+ bool withRhs) {
+ const int opBindingStrength = 0x70;
+ bool parensNeeded = opBindingStrength < contextBindingStrength ||
+ (fragileContext && opBindingStrength == contextBindingStrength);
+
+ if (parensNeeded)
+ {
+ stream.Write("(");
+ }
+ ((!)args[0]).Emit(stream, opBindingStrength, false);
+ stream.Write("[");
+
+ string sep = "";
+ int lastIndex = withRhs ? args.Length - 1 : args.Length;
+ for (int i = 1; i < lastIndex; ++i) {
+ stream.Write(sep);
+ sep = ", ";
+ ((!)args[i]).Emit(stream);
+ }
+
+ if (withRhs) {
+ stream.Write(" := ");
+ ((!)args.Last()).Emit(stream);
+ }
+
+ stream.Write("]");
+ if (parensNeeded)
+ {
+ stream.Write(")");
+ }
+ }
+
+ public void Resolve(ResolutionContext! rc, Expr! subjectForErrorReporting) {
+ // PR: nothing?
+ }
+
+ public int ArgumentCount { get {
+ return Arity + 1;
+ } }
+
+ // it is assumed that each of the arguments has already been typechecked
+ public static Type Typecheck(Type! mapType,
+ // we just pass an Absy, because in
+ // the AssignCmd maps can also be
+ // represented by non-expressions
+ Absy! map,
+ ExprSeq! indexes,
+ // the type parameters, in this context, are the parameters of the
+ // potentially polymorphic map type. Because it might happen that
+ // the whole map type is unknown and represented using a MapTypeProxy,
+ // the instantiations given in the following out-parameter are subject
+ // to change if further unifications are done.
+ out TypeParamInstantiation! tpInstantiation,
+ TypecheckingContext! tc,
+ IToken! typeCheckingSubject,
+ string! opName) {
+ mapType = mapType.Expanded;
+ if (mapType.IsMap && mapType.MapArity != indexes.Length) {
+ tc.Error(typeCheckingSubject, "wrong number of arguments in {0}: {1} instead of {2}",
+ opName, indexes.Length, mapType.MapArity);
+ tpInstantiation = SimpleTypeParamInstantiation.EMPTY;
+ return null;
+ } else if (!mapType.Unify(new MapTypeProxy(map.tok, "select", indexes.Length))) {
+ tc.Error(map.tok, "{0} applied to a non-map: {1}", opName, map);
+ tpInstantiation = SimpleTypeParamInstantiation.EMPTY;
+ return null;
+ }
+ mapType = TypeProxy.FollowProxy(mapType);
+
+ if (mapType is MapType) {
+ MapType mt = (MapType)mapType;
+ return mt.CheckArgumentTypes(indexes, out tpInstantiation,
+ typeCheckingSubject, opName, tc);
+ } else {
+ MapTypeProxy mt = (MapTypeProxy)mapType;
+ return mt.CheckArgumentTypes(indexes, out tpInstantiation,
+ typeCheckingSubject, opName, tc);
+ }
+ }
+
+ public Type Typecheck(ref ExprSeq! args, out TypeParamInstantiation! tpInstantiation, TypecheckingContext! tc)
+ {
+ assume args.Length == Arity + 1;
+
+ ExprSeq actualArgs = new ExprSeq ();
+ for (int i = 1; i < args.Length; ++i)
+ actualArgs.Add(args[i]);
+
+ return Typecheck((!)((!)args[0]).Type, (!)args[0],
+ actualArgs, out tpInstantiation, tc, this.tok, "map select");
+ }
+
+ /// <summary>
+ /// Returns the result type of the IAppliable, supposing the argument are of the correct types.
+ /// </summary>
+ public Type! ShallowType(ExprSeq! args) {
+ Expr a0 = (!)args[0];
+ Type a0Type = a0.ShallowType;
+ if (a0Type == null || !a0Type.IsMap) {
+ // we are unable to determine the type of the select, so just return an arbitrary type
+ return Type.Int;
+ }
+ MapType mapType = a0Type.AsMap;
+ TypeSeq actualArgTypes = new TypeSeq ();
+ for (int i = 1; i < args.Length; ++i) {
+ actualArgTypes.Add(((!)args[i]).ShallowType);
+ }
+ return Type.InferValueType(mapType.TypeParameters, mapType.Arguments, mapType.Result, actualArgTypes);
+ }
+
+ public AI.IFunctionSymbol! AIFunctionSymbol { get {
+ 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 {
+ 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) {
+ return visitor.Visit(this);
+ }
+ }
+
+ public class MapStore : IAppliable, AI.IFunctionSymbol {
+
+ public readonly int Arity;
+ public readonly IToken! tok;
+
+ public MapStore(IToken! tok, int arity) {
+ this.tok = tok;
+ this.Arity = arity;
+ }
+
+ public string! FunctionName { get {
+ return "MapStore";
+ } }
+
+ [Pure][Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals(object obj)
+ {
+ if (!(obj is MapStore)) return false;
+
+ MapStore other = (MapStore)obj;
+ return this.Arity == other.Arity;
+ }
+
+ [Pure]
+ public override int GetHashCode()
+ {
+ return Arity.GetHashCode() * 28231;
+ }
+
+ public void Emit(ExprSeq! args, TokenTextWriter! stream,
+ int contextBindingStrength, bool fragileContext) {
+ assert args.Length == Arity + 2;
+ MapSelect.Emit(args, stream, contextBindingStrength, fragileContext, true);
+ }
+
+ public void Resolve(ResolutionContext! rc, Expr! subjectForErrorReporting) {
+ // PR: nothing?
+ }
+
+ public int ArgumentCount { get {
+ return Arity + 2;
+ } }
+
+ // it is assumed that each of the arguments has already been typechecked
+ public static Type Typecheck(ExprSeq! args, out TypeParamInstantiation! tpInstantiation,
+ TypecheckingContext! tc,
+ IToken! typeCheckingSubject,
+ string! opName) {
+ // part of the type checking works exactly as for MapSelect
+ ExprSeq! selectArgs = new ExprSeq ();
+ for (int i = 1; i < args.Length - 1; ++i)
+ selectArgs.Add(args[i]);
+ Type resultType =
+ MapSelect.Typecheck((!)((!)args[0]).Type, (!)args[0],
+ selectArgs, out tpInstantiation, tc, typeCheckingSubject, opName);
+
+ // check the the rhs has the right type
+ if (resultType == null) {
+ // error messages have already been created by MapSelect.Typecheck
+ return null;
+ }
+ Type rhsType = (!)((!)args.Last()).Type;
+ if (!resultType.Unify(rhsType)) {
+ tc.Error(((!)args.Last()).tok,
+ "right-hand side in {0} with wrong type: {1} (expected: {2})",
+ opName, rhsType, resultType);
+ return null;
+ }
+
+ return ((!)args[0]).Type;
+ }
+
+ public Type Typecheck(ref ExprSeq! args,
+ out TypeParamInstantiation! tpInstantiation,
+ TypecheckingContext! tc)
+ {
+ assert args.Length == Arity + 2;
+ return Typecheck(args, out tpInstantiation, tc, this.tok, "map store");
+ }
+
+ /// <summary>
+ /// Returns the result type of the IAppliable, supposing the argument are of the correct types.
+ /// </summary>
+ public Type! ShallowType(ExprSeq! args) {
+ return ((!)args[0]).ShallowType;
+ }
+
+ public AI.IFunctionSymbol! AIFunctionSymbol { get {
+ 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 {
+ return AI.Heap.Type;
+ } }
+
+ public T Dispatch<T>(IAppliableVisitor<T>! visitor) {
+ return visitor.Visit(this);
+ }
+ }
+
+ public abstract class QuantifierExpr : Expr
+ {
+ public TypeVariableSeq! TypeParameters;
+ public VariableSeq! Dummies;
+ public QKeyValue Attributes;
+ public Trigger Triggers;
+ public Expr! Body;
+
+ static int SkolemIds = 0;
+ public readonly int SkolemId;
+
+ public QuantifierExpr(IToken! tok, TypeVariableSeq! typeParameters,
+ VariableSeq! dummies, QKeyValue kv, Trigger triggers, Expr! body)
+ requires dummies.Length + typeParameters.Length > 0;
+ {
+ base(tok);
+
+ assert (this is ForallExpr) || (this is ExistsExpr);
+
+ TypeParameters = typeParameters;
+ Dummies = dummies;
+ Attributes = kv;
+ Triggers = triggers;
+ Body = body;
+
+ SkolemId = SkolemIds++;
+ }
+
+ [Pure][Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals(object obj)
+ {
+ if (obj == null) return false;
+ if (!(obj is QuantifierExpr) ||
+ (obj is ForallExpr) != (this is ForallExpr)) return false;
+
+ QuantifierExpr other = (QuantifierExpr)obj;
+ // Note, we consider quantifiers equal modulo the Triggers.
+ return object.Equals(this.TypeParameters, other.TypeParameters)
+ && object.Equals(this.Dummies, other.Dummies)
+ && object.Equals(this.Body, other.Body);
+ }
+
+ [Pure]
+ public override int GetHashCode()
+ {
+ int h = this.Dummies.GetHashCode();
+ // Note, we consider quantifiers equal modulo the Triggers.
+ h ^= this.Body.GetHashCode();
+ h = h*5 + this.TypeParameters.GetHashCode();
+ if (this is ForallExpr) h = h * 3;
+ return h;
+ }
+
+ public override void Emit(TokenTextWriter! stream, int contextBindingStrength, bool fragileContext)
+ {
+ stream.Write(this, "({0}", this is ForallExpr ? "forall" : "exists");
+ Type.EmitOptionalTypeParams(stream, TypeParameters);
+ stream.Write(this, " ");
+ this.Dummies.Emit(stream);
+ stream.Write(" :: ");
+ for (QKeyValue kv = this.Attributes; kv != null; kv = kv.Next) {
+ kv.Emit(stream);
+ stream.Write(" ");
+ }
+ for (Trigger tr = this.Triggers; tr != null; tr = tr.Next) {
+ tr.Emit(stream);
+ stream.Write(" ");
+ }
+
+ this.Body.Emit(stream);
+ stream.Write(")");
+ }
+ // if the user says ( forall x :: forall y :: { f(x,y) } ... ) we transform it to
+ // (forall x, y :: { f(x,y) } ... ) otherwise the prover ignores the trigger
+ private void MergeAdjecentQuantifier()
+ {
+ QuantifierExpr qbody = Body as QuantifierExpr;
+ if (!(qbody != null && (qbody is ForallExpr) == (this is ForallExpr) && Triggers == null)) {
+ return;
+ }
+ qbody.MergeAdjecentQuantifier();
+ if (qbody.Triggers == null) {
+ return;
+ }
+ Body = qbody.Body;
+ TypeParameters.AddRange(qbody.TypeParameters);
+ Dummies.AddRange(qbody.Dummies);
+ Triggers = qbody.Triggers;
+ if (qbody.Attributes != null) {
+ if (Attributes == null) {
+ Attributes = qbody.Attributes;
+ } else {
+ QKeyValue p = Attributes;
+ while (p.Next != null) {
+ p = p.Next;
+ }
+ p.Next = qbody.Attributes;
+ }
+ }
+ }
+ public override void Resolve(ResolutionContext! rc)
+ {
+ int oldErrorCount = rc.ErrorCount;
+
+ this.MergeAdjecentQuantifier();
+ if (rc.TriggerMode) {
+ rc.Error(this, "quantifiers are not allowed in triggers");
+ }
+
+ int previousTypeBinderState = rc.TypeBinderState;
+ try {
+ foreach (TypeVariable! v in TypeParameters)
+ rc.AddTypeBinder(v);
+
+ rc.PushVarContext();
+ foreach (Variable! v in Dummies)
+ {
+ v.Register(rc);
+ v.Resolve(rc);
+ }
+ for (QKeyValue kv = this.Attributes; kv != null; kv = kv.Next) {
+ kv.Resolve(rc);
+ }
+ for (Trigger tr = this.Triggers; tr != null; tr = tr.Next) {
+ int prevErrorCount = rc.ErrorCount;
+ tr.Resolve(rc);
+ if (prevErrorCount == rc.ErrorCount) {
+ // for positive triggers, make sure all bound variables are mentioned
+ if (tr.Pos) {
+ Set /*Variable*/ freeVars = new Set /*Variable*/ ();
+ tr.ComputeFreeVariables(freeVars);
+ foreach (Variable! v in Dummies) {
+ if (!freeVars[v]) {
+ rc.Error(tr, "trigger must mention all quantified variables, but does not mention: {0}", v);
+ }
+ }
+ }
+ }
+ }
+ Body.Resolve(rc);
+ rc.PopVarContext();
+
+ // establish a canonical order of the type parameters
+ this.TypeParameters = Type.SortTypeParams(TypeParameters, Dummies.ToTypeSeq, null);
+
+ } finally {
+ rc.TypeBinderState = previousTypeBinderState;
+ }
+
+ if (oldErrorCount == rc.ErrorCount) {
+ this.ApplyNeverTriggers();
+ }
+ }
+
+ #region never triggers
+ private class NeverTriggerCollector : StandardVisitor
+ {
+ QuantifierExpr! parent;
+ public NeverTriggerCollector(QuantifierExpr! p)
+ {
+ parent = p;
+ }
+
+ public override Expr! VisitNAryExpr(NAryExpr! node)
+ {
+ FunctionCall fn = node.Fun as FunctionCall;
+ if (fn != null && ((!)fn.Func).NeverTrigger) {
+ parent.Triggers = new Trigger(fn.Func.tok, false, new ExprSeq(node), parent.Triggers);
+ }
+ return base.VisitNAryExpr(node);
+ }
+ }
+
+ private bool neverTriggerApplied;
+ private void ApplyNeverTriggers()
+ {
+ if (neverTriggerApplied) {
+ return;
+ }
+ neverTriggerApplied = true;
+
+ for (Trigger t = Triggers; t != null; t = t.Next) {
+ if (t.Pos) { return; }
+ }
+
+ NeverTriggerCollector visitor = new NeverTriggerCollector(this);
+ visitor.VisitExpr(Body);
+ }
+ #endregion
+
+ public override void ComputeFreeVariables(Set /*Variable*/! freeVars) {
+ foreach (Variable! v in Dummies) {
+ assert !freeVars[v];
+ }
+ Body.ComputeFreeVariables(freeVars);
+ foreach (Variable! v in Dummies) {
+ foreach (TypeVariable! w in v.TypedIdent.Type.FreeVariables)
+ freeVars.Add(w);
+ }
+ foreach (Variable! v in Dummies) {
+ freeVars.Remove(v);
+ }
+ foreach (TypeVariable! v in TypeParameters) {
+ freeVars.Remove(v);
+ }
+ }
+ public override void Typecheck(TypecheckingContext! tc)
+ {
+ for (QKeyValue kv = this.Attributes; kv != null; kv = kv.Next) {
+ kv.Typecheck(tc);
+ }
+ for (Trigger tr = this.Triggers; tr != null; tr = tr.Next) {
+ tr.Typecheck(tc);
+ }
+ Body.Typecheck(tc);
+ assert Body.Type != null; // follows from postcondition of Expr.Typecheck
+ if (!Body.Type.Unify(Type.Bool))
+ {
+ tc.Error(this, "quantifier body must be of type bool");
+ }
+ this.Type = Type.Bool;
+
+ // Check that type parameters occur in the types of the
+ // dummies, or otherwise in the triggers. This can only be
+ // done after typechecking
+ TypeVariableSeq! dummyParameters = Type.FreeVariablesIn(Dummies.ToTypeSeq);
+ TypeVariableSeq! unmentionedParameters = new TypeVariableSeq ();
+ foreach (TypeVariable! var in TypeParameters)
+ if (!dummyParameters.Has(var))
+ unmentionedParameters.Add(var);
+
+ if (unmentionedParameters.Length > 0) {
+ // all the type parameters that do not occur in dummy types
+ // have to occur in triggers
+
+ for (Trigger tr = this.Triggers; tr != null; tr = tr.Next) {
+ // for positive triggers, make sure all bound variables are mentioned
+ if (tr.Pos) {
+ Set /*Variable*/ freeVars = new Set /*Variable*/ ();
+ tr.ComputeFreeVariables(freeVars);
+ foreach (TypeVariable! v in unmentionedParameters) {
+ if (!freeVars[v])
+ tc.Error(tr,
+ "trigger does not mention {0}, which does not " +
+ "occur in variables types either",
+ v);
+ }
+ }
+ }
+ }
+ }
+ public override Type! ShallowType {
+ get {
+ return Type.Bool;
+ }
+ }
+
+ public abstract AI.IFunctionSymbol! FunctionSymbol { get; }
+
+ internal sealed class AIQuantifier : AI.IFunApp
+ {
+ internal readonly AIFunctionRep! arg;
+ internal AIQuantifier(QuantifierExpr! realQuantifier, int dummyIndex)
+ : this(new AIFunctionRep(realQuantifier, dummyIndex))
+ {
+ }
+ [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)
+ {
+ this.arg = arg;
+ // base();
+ }
+
+ [Pure]
+ public object DoVisit(AI.ExprVisitor! visitor)
+ {
+ return visitor.VisitFunApp(this);
+ }
+
+ public AI.IFunctionSymbol! FunctionSymbol { get { return arg.RealQuantifier.FunctionSymbol; } }
+
+ private IList/*?*/ argCache = null;
+ public IList/*<IExpr!>*/! Arguments
+ {
+ get
+ {
+ if (argCache == null)
+ {
+ IList a = new ArrayList(1);
+ a.Add(arg);
+ argCache = ArrayList.ReadOnly(a);
+ }
+ return argCache;
+ }
+ }
+
+ public AI.IFunApp! CloneWithArguments(IList/*<IExpr!>*/! args)
+ {
+ 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()
+ {
+ return string.Format("{0}({1})", FunctionSymbol, arg);
+ }
+ }
+
+ internal sealed class AIFunctionRep : AI.IFunction
+ {
+ internal readonly QuantifierExpr! RealQuantifier;
+ private readonly int dummyIndex;
+
+ internal AIFunctionRep(QuantifierExpr! realQuantifier, int dummyIndex)
+ {
+ this.RealQuantifier = realQuantifier;
+ this.dummyIndex = dummyIndex;
+ 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)
+ {
+ return visitor.VisitFunction(this);
+ }
+
+ public AI.IVariable! Param
+ {
+ get { return (!)RealQuantifier.Dummies[dummyIndex]; }
+ }
+ public AI.AIType! ParamType { get { 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
+ {
+ if (bodyCache == null)
+ {
+ int dummyi = dummyIndex;
+ int dummylen = RealQuantifier.Dummies.Length;
+ 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)
+ {
+ QuantifierExpr realquant;
+
+ AIQuantifier innerquant = body as AIQuantifier;
+ if (innerquant == null)
+ {
+ // new quantifier body, clone the real quantifier
+ realquant = (QuantifierExpr)RealQuantifier.Clone();
+ realquant.Body = BoogieFactory.IExpr2Expr(body);
+ }
+ else
+ {
+ if (innerquant.arg.dummyIndex > 0)
+ {
+ realquant = innerquant.arg.RealQuantifier;
+ }
+ else
+ {
+ realquant = (QuantifierExpr)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()
+ {
+ return string.Format("\\{0} :: {1}", Param, Body);
+ }
+ }
+
+ private AI.IExpr aiexprCache = null;
+ public override AI.IExpr! IExpr {
+ get {
+ 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 {
+ public readonly string! Key;
+ public readonly List<object!>! Params; // each element is either a string or an Expr
+ public QKeyValue Next;
+
+ public QKeyValue(IToken! tok, string! key, [Captured] List<object!>! parameters, QKeyValue next)
+ {
+ base(tok);
+ Key = key;
+ Params = parameters;
+ Next = next;
+ }
+
+ public void Emit(TokenTextWriter! stream) {
+ stream.Write("{:");
+ stream.Write(Key);
+ string sep = " ";
+ foreach (object p in Params) {
+ stream.Write(sep); sep = ", ";
+ if (p is string) {
+ stream.Write("\"");
+ stream.Write((string)p);
+ stream.Write("\"");
+ } else {
+ ((Expr)p).Emit(stream);
+ }
+ }
+ stream.Write("}");
+ }
+
+ public override void Resolve(ResolutionContext! rc) {
+ foreach (object p in Params) {
+ if (p is Expr) {
+ ((Expr)p).Resolve(rc);
+ }
+ }
+ }
+
+ public override void Typecheck(TypecheckingContext! tc) {
+ foreach (object p in Params) {
+ if (p is Expr) {
+ ((Expr)p).Typecheck(tc);
+ }
+ }
+ }
+ public void AddLast(QKeyValue! other){
+ QKeyValue current = this;
+ while(current.Next!=null){
+ current = current.Next;
+ }
+ current.Next = other;
+ }
+ // Look for {:name string} in list of attributes.
+ public static string? FindStringAttribute(QKeyValue? kv, string! name)
+ {
+ for (; kv != null; kv = kv.Next) {
+ if (kv.Key == name) {
+ if (kv.Params.Count == 1 && kv.Params[0] is string) {
+ return (string)kv.Params[0];
+ }
+ }
+ }
+ return null;
+ }
+ // Look for {:name expr} in list of attributes.
+ public static Expr? FindExprAttribute(QKeyValue? kv, string! name)
+ {
+ for (; kv != null; kv = kv.Next) {
+ if (kv.Key == name) {
+ if (kv.Params.Count == 1 && kv.Params[0] is Expr) {
+ return (Expr)kv.Params[0];
+ }
+ }
+ }
+ return null;
+ }
+ // Return 'true' if {:name true} or {:name} is an attribute in 'kv'
+ public static bool FindBoolAttribute(QKeyValue? kv, string! name)
+ {
+ for (; kv != null; kv = kv.Next) {
+ if (kv.Key == name) {
+ return kv.Params.Count == 0 ||
+ (kv.Params.Count == 1 && kv.Params[0] is LiteralExpr && ((LiteralExpr)kv.Params[0]).IsTrue);
+ }
+ }
+ return false;
+ }
+
+ public static int FindIntAttribute(QKeyValue? kv, string! name, int defl)
+ {
+ Expr? e = FindExprAttribute(kv, name);
+ LiteralExpr? l = e as LiteralExpr;
+ if (l != null && l.isBigNum)
+ return l.asBigNum.ToIntSafe;
+ return defl;
+ }
+ }
+
+ public class Trigger : Absy {
+ public readonly bool Pos;
+ [Rep]
+ public ExprSeq! Tr;
+ invariant 1 <= Tr.Length;
+ invariant !Pos ==> Tr.Length == 1;
+ public Trigger Next;
+
+ public Trigger(IToken! tok, bool pos, ExprSeq! tr)
+ requires 1 <= tr.Length;
+ requires !pos ==> tr.Length == 1;
+ {
+ this(tok, pos, tr, null);
+ }
+
+ public Trigger(IToken! tok, bool pos, ExprSeq! tr, Trigger next)
+ : base(tok)
+ requires 1 <= tr.Length;
+ requires !pos ==> tr.Length == 1;
+ {
+ this.Pos = pos;
+ this.Tr = tr;
+ this.Next = next;
+ // base(tok);
+ }
+
+ public void Emit(TokenTextWriter! stream) {
+ stream.SetToken(this);
+ assert this.Tr.Length >= 1;
+ string! sep = Pos ? "{ " : "{:nopats ";
+ foreach (Expr! e in this.Tr) {
+ stream.Write(sep);
+ sep = ", ";
+ e.Emit(stream);
+ }
+ stream.Write(" }");
+ }
+ public override void Resolve(ResolutionContext! rc) {
+ rc.TriggerMode = true;
+ foreach (Expr! e in this.Tr) {
+ e.Resolve(rc);
+
+ // just a variable by itself is not allowed
+ if (e is IdentifierExpr) {
+ rc.Error(e, "a matching pattern must be more than just a variable by itself: {0}", e);
+ }
+
+ // the free-variable check is performed in the surrounding quantifier expression (because that's
+ // where the bound variables are known)
+ }
+ rc.TriggerMode = false;
+ }
+
+ /// <summary>
+ /// Add to "freeVars" the free variables in the triggering expressions.
+ /// </summary>
+ public void ComputeFreeVariables(Set /*Variable*/! freeVars) {
+ foreach (Expr! e in this.Tr) {
+ e.ComputeFreeVariables(freeVars);
+ }
+ }
+
+ public override void Typecheck(TypecheckingContext! tc) {
+ foreach (Expr! e in this.Tr) {
+ e.Typecheck(tc);
+ }
+ }
+
+ public void AddLast(Trigger other){
+ Trigger current = this;
+ while(current.Next!=null){
+ current = current.Next;
+ }
+ current.Next = other;
+ }
+
+ public override Absy! StdDispatch(StandardVisitor! visitor)
+ {
+ return visitor.VisitTrigger(this);
+ }
+ }
+
+ public class ForallExpr : QuantifierExpr
+ {
+ public ForallExpr(IToken! tok, TypeVariableSeq! typeParams,
+ VariableSeq! dummies, QKeyValue kv, Trigger triggers, Expr! body)
+ requires dummies.Length + typeParams.Length > 0;
+ {
+ base(tok, typeParams, dummies, kv, triggers, body); // here for aesthetic reasons
+ }
+ public ForallExpr(IToken! tok, VariableSeq! dummies, Trigger triggers, Expr! body)
+ requires dummies.Length > 0;
+ {
+ base(tok, new TypeVariableSeq(), dummies, null, triggers, body); // here for aesthetic reasons
+ }
+ public ForallExpr(IToken! tok, VariableSeq! dummies, Expr! body)
+ requires dummies.Length > 0;
+ {
+ base(tok, new TypeVariableSeq(), dummies, null, null, body); // here for aesthetic reasons
+ }
+ public ForallExpr(IToken! tok, TypeVariableSeq! typeParams, VariableSeq! dummies, Expr! body)
+ requires dummies.Length + typeParams.Length > 0;
+ {
+ base(tok, typeParams, dummies, null, null, body); // here for aesthetic reasons
+ }
+ public override AI.IFunctionSymbol! FunctionSymbol
+ {
+ get {
+ return AI.Prop.Forall;
+ }
+ }
+
+ public override Absy! StdDispatch(StandardVisitor! visitor)
+ {
+ return visitor.VisitForallExpr(this);
+ }
+ }
+ public class ExistsExpr : QuantifierExpr
+ {
+ public ExistsExpr(IToken! tok, TypeVariableSeq! typeParams, VariableSeq! dummies,
+ QKeyValue kv, Trigger triggers, Expr! body)
+ requires dummies.Length + typeParams.Length > 0;
+ {
+ base(tok, typeParams, dummies, kv, triggers, body); // here for aesthetic reasons
+ }
+ public ExistsExpr(IToken! tok, VariableSeq! dummies, Trigger triggers, Expr! body)
+ requires dummies.Length > 0;
+ {
+ base(tok, new TypeVariableSeq (), dummies, null, triggers, body); // here for aesthetic reasons
+ }
+ public ExistsExpr(IToken! tok, VariableSeq! dummies, Expr! body)
+ requires dummies.Length > 0;
+ {
+ base(tok, new TypeVariableSeq(), dummies, null, null, body); // here for aesthetic reasons
+ }
+ public override AI.IFunctionSymbol! FunctionSymbol
+ {
+ get {
+ return AI.Prop.Exists;
+ }
+ }
+
+ public override Absy! StdDispatch(StandardVisitor! visitor)
+ {
+ return visitor.VisitExistsExpr(this);
+ }
+ }
+
+ public class BlockExpr : Expr
+ {
+ public VariableSeq! LocVars;
+ [Rep]
+ public BlockSeq! Blocks;
+ public BlockExpr(VariableSeq! localVariables, BlockSeq! blocks)
+ : base(Token.NoToken)
+ {
+ LocVars = localVariables;
+ Blocks = blocks;
+ }
+ public override AI.IExpr! IExpr {
+ get {
+ // An BlockExpr has no AI.IExpr representation
+ assert false;
+ throw new System.Exception(); // make compiler shut up
+ return Expr.False;
+ }
+ }
+ public override void ComputeFreeVariables(Set /*Variable*/! freeVars) {
+ // Treat a BlockEexpr as if it has no free variables at all
+ }
+ public override void Emit (TokenTextWriter! stream, int contextBindingStrength, bool fragileContext)
+ {
+ //level++;
+ int level = 0;
+ stream.WriteLine(level, "{0}", '{');
+
+ if (this.LocVars.Length > 0)
+ {
+ stream.Write(level + 1, "var ");
+ this.LocVars.Emit(stream);
+ stream.WriteLine(";");
+ }
+
+ foreach (Block! b in this.Blocks)
+ {
+ b.Emit(stream, level+1);
+ }
+
+ stream.WriteLine();
+ stream.WriteLine(level, "{0}", '}');
+
+ stream.WriteLine();
+ stream.WriteLine();
+ }
+
+ public override void Resolve(ResolutionContext! rc)
+ {
+
+ rc.PushVarContext();
+ foreach (Variable! v in LocVars)
+ {
+ v.Register(rc);
+ v.Resolve(rc);
+ }
+
+ rc.StartProcedureContext();
+ foreach (Block! b in Blocks)
+ {
+ b.Register(rc);
+ }
+
+ foreach (Block! b in Blocks)
+ {
+ b.Resolve(rc);
+ }
+
+ rc.EndProcedureContext();
+ rc.PopVarContext();
+ }
+
+ public override void Typecheck(TypecheckingContext! tc){
+ foreach (Variable! v in LocVars){
+ v.Typecheck(tc);
+ }
+ foreach (Block! b in Blocks){
+ b.Typecheck(tc);
+ }
+ this.Type = Type.Bool;
+ }
+ public override Type! ShallowType {
+ get {
+ return Type.Bool;
+ }
+ }
+
+ public override Absy! StdDispatch(StandardVisitor! visitor)
+ {
+ return visitor.VisitBlockExpr(this);
+ }
+ }
+
+
+
+ public class ExtractExpr : Expr, AI.IFunApp
+ {
+ public /*readonly--except in StandardVisitor*/ Expr! Bitvector;
+ public readonly int Start, End;
+
+ public ExtractExpr(IToken! tok, Expr! bv, int end, int start)
+ : base(tok)
+ {
+ Bitvector = bv;
+ Start = start;
+ End = end;
+ // base(tok);
+ }
+
+ [Pure][Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals(object obj)
+ {
+ if (obj == null) return false;
+ if (!(obj is ExtractExpr)) return false;
+
+ ExtractExpr other = (ExtractExpr)obj;
+ return object.Equals(this.Bitvector, other.Bitvector) &&
+ this.Start.Equals(other.Start) && this.End.Equals(other.End);
+ }
+ [Pure]
+ public override int GetHashCode()
+ {
+ int h = this.Bitvector.GetHashCode();
+ h ^= Start * 17 ^ End * 13;
+ return h;
+ }
+ public override void Emit(TokenTextWriter! stream, int contextBindingStrength, bool fragileContext)
+ {
+ stream.SetToken(this);
+ int opBindingStrength = 0x70;
+ bool parensNeeded = opBindingStrength < contextBindingStrength ||
+ (fragileContext && opBindingStrength == contextBindingStrength);
+
+ if (parensNeeded)
+ {
+ stream.Write("(");
+ }
+ Bitvector.Emit(stream, opBindingStrength, false);
+ stream.Write("[" + End + ":" + Start + "]");
+ if (parensNeeded)
+ {
+ stream.Write(")");
+ }
+ }
+ public override void Resolve(ResolutionContext! rc)
+ {
+ Bitvector.Resolve(rc);
+ }
+ public override void ComputeFreeVariables(Set /*Variable*/! freeVars) {
+ Bitvector.ComputeFreeVariables(freeVars);
+ }
+ public override void Typecheck(TypecheckingContext! tc)
+ {
+ Bitvector.Typecheck(tc);
+ assert Bitvector.Type != null; // follows from postcondition of Expr.Typecheck
+
+ if (Start < 0) {
+ tc.Error(this, "start index in extract must not be negative");
+ } else if (End < 0) {
+ tc.Error(this, "end index in extract must not be negative");
+ } else if (End < Start) {
+ tc.Error(this, "start index in extract must be no bigger than the end index");
+ } else {
+ Type typeConstraint = new BvTypeProxy(this.tok, "extract", End - Start);
+ if (typeConstraint.Unify(Bitvector.Type)) {
+ Type = Type.GetBvType(End - Start);
+ } else {
+ tc.Error(this, "extract operand must be a bitvector of at least {0} bits (got {1})", End - Start, Bitvector.Type);
+ }
+ }
+ if (Type == null) {
+ Type = new TypeProxy(this.tok, "type_checking_error");
+ }
+ }
+
+ public override Type! ShallowType {
+ get {
+ return Type.GetBvType(End - Start);
+ }
+ }
+
+ public override AI.IExpr! IExpr {
+ get {
+ return this;
+ }
+ }
+ public AI.IFunctionSymbol! FunctionSymbol {
+ get { return AI.Bv.Extract;
+ }
+ }
+ public IList/*<AI.IExpr!>*/! Arguments {
+ get {
+ 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)
+ {
+ AI.IFunApp! retFun;
+
+ if(args.Count == 3)
+ {
+ retFun = new ExtractExpr(this.tok,
+ BoogieFactory.IExpr2Expr((AI.IExpr!)args[0]),
+ ((LiteralExpr!)args[1]).asBigNum.ToIntSafe,
+ ((LiteralExpr!)args[2]).asBigNum.ToIntSafe);
+ }
+ else
+ {
+ assert false; // If we are something wrong is happended
+ }
+ return retFun;
+ }
+
+ [Pure]
+ public object DoVisit(AI.ExprVisitor! visitor)
+ {
+ return visitor.VisitFunApp(this);
+ }
+
+ public override Absy! StdDispatch(StandardVisitor! visitor)
+ {
+ return visitor.VisitExtractExpr(this);
+ }
+ }
+
+ public class BvConcatExpr : Expr, AI.IFunApp
+ {
+ public /*readonly--except in StandardVisitor*/ Expr! E0, E1;
+
+ public BvConcatExpr(IToken! tok, Expr! e0, Expr! e1)
+ : base(tok)
+ {
+ E0 = e0;
+ E1 = e1;
+ // base(tok);
+ }
+
+ [Pure][Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals(object obj)
+ {
+ if (obj == null) return false;
+ if (!(obj is BvConcatExpr)) return false;
+
+ BvConcatExpr other = (BvConcatExpr)obj;
+ return object.Equals(this.E0, other.E0) && object.Equals(this.E1, other.E1);
+ }
+ [Pure]
+ public override int GetHashCode()
+ {
+ int h = this.E0.GetHashCode() ^ this.E1.GetHashCode() * 17;
+ return h;
+ }
+ public override void Emit(TokenTextWriter! stream, int contextBindingStrength, bool fragileContext)
+ {
+ stream.SetToken(this);
+ int opBindingStrength = 0x32;
+ bool parensNeeded = opBindingStrength < contextBindingStrength ||
+ (fragileContext && opBindingStrength == contextBindingStrength);
+
+ if (parensNeeded)
+ {
+ stream.Write("(");
+ }
+ E0.Emit(stream, opBindingStrength, false);
+ stream.Write(" ++ ");
+ // while this operator is associative, our incomplete axioms in int translation don't
+ // make much use of it, so better stick to the actual tree shape
+ E1.Emit(stream, opBindingStrength, true);
+ if (parensNeeded)
+ {
+ stream.Write(")");
+ }
+ }
+ public override void Resolve(ResolutionContext! rc)
+ {
+ E0.Resolve(rc);
+ E1.Resolve(rc);
+ }
+ public override void ComputeFreeVariables(Set /*Variable*/! freeVars) {
+ E0.ComputeFreeVariables(freeVars);
+ E1.ComputeFreeVariables(freeVars);
+ }
+ public override void Typecheck(TypecheckingContext! tc)
+ {
+ E0.Typecheck(tc);
+ assert E0.Type != null; // follows from postcondition of Expr.Typecheck
+ E1.Typecheck(tc);
+ assert E1.Type != null; // follows from postcondition of Expr.Typecheck
+
+ if (E0.Type.Unify(new BvTypeProxy(this.tok, "concat0", 0)) && E1.Type.Unify(new BvTypeProxy(this.tok, "concat1", 0))) {
+ Type = new BvTypeProxy(this.tok, "concat", E0.Type, E1.Type);
+ } else {
+ tc.Error(this, "++ operands need to be bitvectors (got {0}, {1})", E0.Type, E1.Type);
+ }
+ if (Type == null) {
+ Type = new TypeProxy(this.tok, "type_checking_error");
+ }
+ }
+
+ public override Type! ShallowType {
+ get {
+ Type t0 = E0.ShallowType;
+ Type t1 = E1.ShallowType;
+ int len0 = t0.IsBv ? t0.BvBits : /*expression is not type correct, so just pick an arbitrary number of bits*/0;
+ int len1 = t1.IsBv ? t1.BvBits : /*expression is not type correct, so just pick an arbitrary number of bits*/0;
+ return Type.GetBvType(len0 + len1);
+ }
+ }
+
+ public override AI.IExpr! IExpr {
+ get {
+ return this;
+ }
+ }
+ public AI.IFunctionSymbol! FunctionSymbol {
+ get { return AI.Bv.Concat;
+ }
+ }
+ public IList/*<AI.IExpr!>*/! Arguments {
+ get {
+ 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)
+ {
+ AI.IFunApp! retFun;
+
+ if(args.Count == 2)
+ {
+ retFun = new BvConcatExpr(this.tok,
+ BoogieFactory.IExpr2Expr((AI.IExpr!)args[0]),
+ BoogieFactory.IExpr2Expr((AI.IExpr!)args[1]));
+ }
+ else
+ {
+ assert false; // If we are something wrong is happended
+ }
+ return retFun;
+ }
+
+ [Pure]
+ public object DoVisit(AI.ExprVisitor! visitor)
+ {
+ return visitor.VisitFunApp(this);
+ }
+
+ public override Absy! StdDispatch(StandardVisitor! visitor)
+ {
+ return visitor.VisitBvConcatExpr(this);
+ }
+ }
+}
diff --git a/Source/Core/AbsyType.ssc b/Source/Core/AbsyType.ssc
new file mode 100644
index 00000000..c5f1309d
--- /dev/null
+++ b/Source/Core/AbsyType.ssc
@@ -0,0 +1,2857 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------------
+// BoogiePL - Absy.cs
+//---------------------------------------------------------------------------------------------
+
+namespace Microsoft.Boogie
+{
+ using System;
+ using System.Collections;
+ using System.Diagnostics;
+ using System.Collections.Generic;
+ using Microsoft.Boogie.AbstractInterpretation;
+ using AI = Microsoft.AbstractInterpretationFramework;
+ using Microsoft.Contracts;
+
+ //=====================================================================
+ //---------------------------------------------------------------------
+ // Types
+
+ public abstract class Type : Absy {
+ public Type(IToken! token)
+ : base(token)
+ {
+ }
+
+ //----------- Cloning ----------------------------------
+ // We implement our own clone-method, because bound type variables
+ // have to be created in the right way. It is /not/ ok to just clone
+ // everything recursively. Applying Clone to a type will return
+ // a type in which all bound variables have been replaced with new
+ // variables, whereas free variables have not changed
+
+ public override Absy! Clone() {
+ return this.Clone(new Dictionary<TypeVariable!, TypeVariable!> ());
+ }
+
+ public abstract Type! Clone(IDictionary<TypeVariable!, TypeVariable!>! varMap);
+
+ /// <summary>
+ /// Clones the type, but only syntactically. Anything resolved in the source
+ /// type is left unresolved (that is, with just the name) in the destination type.
+ /// </summary>
+ public abstract Type! CloneUnresolved();
+
+ //----------- Linearisation ----------------------------------
+
+ public void Emit(TokenTextWriter! stream) {
+ this.Emit(stream, 0);
+ }
+
+ public abstract void Emit(TokenTextWriter! stream, int contextBindingStrength);
+
+ [Pure]
+ public override string! ToString() {
+ System.IO.StringWriter buffer = new System.IO.StringWriter();
+ using (TokenTextWriter stream = new TokenTextWriter("<buffer>", buffer, false))
+ {
+ this.Emit(stream);
+ }
+ return buffer.ToString();
+ }
+
+ //----------- Equality ----------------------------------
+
+ [Pure][Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals(object that)
+ {
+ if (ReferenceEquals(this, that))
+ return true;
+ Type thatType = that as Type;
+ return thatType != null && this.Equals(thatType,
+ new TypeVariableSeq (),
+ new TypeVariableSeq ());
+ }
+
+ [Pure]
+ public abstract bool Equals(Type! that,
+ TypeVariableSeq! thisBoundVariables,
+ TypeVariableSeq! thatBoundVariables);
+
+ // used to skip leading type annotations (subexpressions of the
+ // resulting type might still contain annotations)
+ internal virtual Type! Expanded { get {
+ return this;
+ } }
+
+ //----------- Unification of types -----------
+
+ /// <summary>
+ /// Add a constraint that this==that, if possible, and return true.
+ /// If not possible, return false (which may have added some partial constraints).
+ /// No error is printed.
+ /// </summary>
+ public bool Unify(Type! that) {
+ return Unify(that, new TypeVariableSeq(), new Dictionary<TypeVariable!, Type!> ());
+ }
+
+ public abstract bool Unify(Type! that,
+ TypeVariableSeq! unifiableVariables,
+ // an idempotent substitution that describes the
+ // unification result up to a certain point
+ IDictionary<TypeVariable!, Type!>! unifier);
+ requires forall{TypeVariable key in unifier.Keys; unifiableVariables.Has(key)};
+ requires IsIdempotent(unifier);
+
+ [Pure]
+ public static bool IsIdempotent(IDictionary<TypeVariable!, Type!>! unifier) {
+ return forall{Type! t in unifier.Values;
+ forall{TypeVariable! var in t.FreeVariables;
+ !unifier.ContainsKey(var)}};
+ }
+
+
+#if OLD_UNIFICATION
+ // Compute a most general unification of two types. null is returned if
+ // no such unifier exists. The unifier is not allowed to subtitute any
+ // type variables other than the ones in "unifiableVariables"
+ public IDictionary<TypeVariable!, Type!> Unify(Type! that,
+ TypeVariableSeq! unifiableVariables) {
+ Dictionary<TypeVariable!, Type!>! result = new Dictionary<TypeVariable!, Type!> ();
+ try {
+ this.Unify(that, unifiableVariables,
+ new TypeVariableSeq (), new TypeVariableSeq (), result);
+ } catch (UnificationFailedException) {
+ return null;
+ }
+ return result;
+ }
+
+ // Compute an idempotent most general unifier and add the result to the argument
+ // unifier. The result is true iff the unification succeeded
+ public bool Unify(Type! that,
+ TypeVariableSeq! unifiableVariables,
+ // given mappings that need to be taken into account
+ // the old unifier has to be idempotent as well
+ IDictionary<TypeVariable!, Type!>! unifier)
+ requires forall{TypeVariable key in unifier.Keys; unifiableVariables.Has(key)};
+ requires IsIdempotent(unifier);
+ {
+ try {
+ this.Unify(that, unifiableVariables,
+ new TypeVariableSeq (), new TypeVariableSeq (), unifier);
+ } catch (UnificationFailedException) {
+ return false;
+ }
+ return true;
+ }
+
+ public abstract void Unify(Type! that,
+ TypeVariableSeq! unifiableVariables,
+ TypeVariableSeq! thisBoundVariables,
+ TypeVariableSeq! thatBoundVariables,
+ // an idempotent substitution that describes the
+ // unification result up to a certain point
+ IDictionary<TypeVariable!, Type!>! result);
+#endif
+
+ //----------- Substitution of free variables with types not containing bound variables -----------------
+
+ public abstract Type! Substitute(IDictionary<TypeVariable!, Type!>! subst);
+
+ //----------- Hashcodes ----------------------------------
+
+ // Hack to be able to access the hashcode of superclasses further up
+ // (from the subclasses of this class)
+ [Pure]
+ protected int GetBaseHashCode() {
+ return base.GetHashCode();
+ }
+
+ [Pure]
+ public override int GetHashCode()
+ {
+ return this.GetHashCode(new TypeVariableSeq ());
+ }
+
+ [Pure]
+ public abstract int GetHashCode(TypeVariableSeq! boundVariables);
+
+ //----------- Resolution ----------------------------------
+
+ public override void Resolve(ResolutionContext! rc)
+ {
+ System.Diagnostics.Debug.Fail("Type.Resolve should never be called." +
+ " Use Type.ResolveType instead");
+ }
+
+ public abstract Type! ResolveType(ResolutionContext! rc);
+
+ public override void Typecheck(TypecheckingContext! tc)
+ {
+ System.Diagnostics.Debug.Fail("Type.Typecheck should never be called");
+ }
+
+ // determine the free variables in a type, in the order in which the variables occur
+ public abstract TypeVariableSeq! FreeVariables { get; }
+
+ // determine the free type proxies in a type, in the order in which they occur
+ public abstract List<TypeProxy!>! FreeProxies { get; }
+
+ protected static void AppendWithoutDups<A>(List<A>! a, List<A>! b) {
+ foreach (A x in b)
+ if (!a.Contains(x))
+ a.Add(x);
+ }
+
+ public bool IsClosed { get {
+ return FreeVariables.Length == 0;
+ } }
+
+ //----------- Getters/Issers ----------------------------------
+
+ // the following methods should be used instead of simple casts or the
+ // C# "is" operator, because they handle type synonym annotations and
+ // type proxies correctly
+
+ public virtual bool IsBasic { get { return false; } }
+ public virtual bool IsInt { get { return false; } }
+ public virtual bool IsBool { get { return false; } }
+
+ public virtual bool IsVariable { get { return false; } }
+ public virtual TypeVariable! AsVariable { get {
+ assert false; // Type.AsVariable should never be called
+ } }
+ public virtual bool IsCtor { get { return false; } }
+ public virtual CtorType! AsCtor { get {
+ assert false; // Type.AsCtor should never be called
+ } }
+ public virtual bool IsMap { get { return false; } }
+ public virtual MapType! AsMap { get {
+ assert false; // Type.AsMap should never be called
+ } }
+ public virtual int MapArity { get {
+ assert false; // Type.MapArity should never be called
+ } }
+ public virtual bool IsUnresolved { get { return false; } }
+ public virtual UnresolvedTypeIdentifier! AsUnresolved { get {
+ assert false; // Type.AsUnresolved should never be called
+ } }
+
+ public virtual bool IsBv { get { return false; } }
+ public virtual int BvBits { get {
+ assert false; // Type.BvBits should never be called
+ } }
+
+ public static readonly Type! Int = new BasicType(SimpleType.Int);
+ public static readonly Type! Bool = new BasicType(SimpleType.Bool);
+ private static BvType[] bvtypeCache;
+
+ static public BvType! GetBvType(int sz)
+ requires 0 <= sz;
+ {
+ if (bvtypeCache == null) {
+ bvtypeCache = new BvType[128];
+ }
+ if (sz < bvtypeCache.Length) {
+ BvType t = bvtypeCache[sz];
+ if (t == null) {
+ t = new BvType(sz);
+ bvtypeCache[sz] = t;
+ }
+ return t;
+ } else {
+ return new BvType(sz);
+ }
+ }
+
+ //------------ Match formal argument types on actual argument types
+ //------------ and return the resulting substitution of type variables
+
+#if OLD_UNIFICATION
+ public static IDictionary<TypeVariable!, Type!>!
+ MatchArgumentTypes(TypeVariableSeq! typeParams,
+ TypeSeq! formalArgs,
+ ExprSeq! actualArgs,
+ TypeSeq formalOuts,
+ IdentifierExprSeq actualOuts,
+ string! opName,
+ TypecheckingContext! tc)
+ requires formalArgs.Length == actualArgs.Length;
+ requires formalOuts == null <==> actualOuts == null;
+ requires formalOuts != null ==> formalOuts.Length == actualOuts.Length;
+ {
+ TypeVariableSeq! boundVarSeq0 = new TypeVariableSeq ();
+ TypeVariableSeq! boundVarSeq1 = new TypeVariableSeq ();
+ Dictionary<TypeVariable!, Type!>! subst = new Dictionary<TypeVariable!, Type!>();
+
+ for (int i = 0; i < formalArgs.Length; ++i) {
+ try {
+ Type! actualType = (!)((!)actualArgs[i]).Type;
+ // if the type variables to be matched occur in the actual
+ // argument types, something has gone very wrong
+ assert forall{TypeVariable! var in typeParams;
+ !actualType.FreeVariables.Has(var)};
+ formalArgs[i].Unify(actualType,
+ typeParams,
+ boundVarSeq0, boundVarSeq1,
+ subst);
+ } catch (UnificationFailedException) {
+ tc.Error(actualArgs[i],
+ "invalid type for argument {0} in {1}: {2} (expected: {3})",
+ i, opName, actualArgs[i].Type,
+ // we insert the type parameters that have already been
+ // chosen to get a more precise error message
+ formalArgs[i].Substitute(subst));
+ // the bound variable sequences should be empty ...
+ // so that we can continue with the unification
+ assert boundVarSeq0.Length == 0 && boundVarSeq1.Length == 0;
+ }
+ }
+
+ if (formalOuts != null) {
+ for (int i = 0; i < formalOuts.Length; ++i) {
+ try {
+ Type! actualType = (!)((!)actualOuts[i]).Type;
+ // if the type variables to be matched occur in the actual
+ // argument types, something has gone very wrong
+ assert forall{TypeVariable! var in typeParams;
+ !actualType.FreeVariables.Has(var)};
+ formalOuts[i].Unify(actualType,
+ typeParams,
+ boundVarSeq0, boundVarSeq1,
+ subst);
+ } catch (UnificationFailedException) {
+ tc.Error(actualOuts[i],
+ "invalid type for result {0} in {1}: {2} (expected: {3})",
+ i, opName, actualOuts[i].Type,
+ // we insert the type parameters that have already been
+ // chosen to get a more precise error message
+ formalOuts[i].Substitute(subst));
+ // the bound variable sequences should be empty ...
+ // so that we can continue with the unification
+ assert boundVarSeq0.Length == 0 && boundVarSeq1.Length == 0;
+ }
+ }
+ }
+
+ // we only allow type parameters to be substituted
+ assert forall{TypeVariable! var in subst.Keys; typeParams.Has(var)};
+
+ return subst;
+ }
+#else
+ public static IDictionary<TypeVariable!, Type!>!
+ MatchArgumentTypes(TypeVariableSeq! typeParams,
+ TypeSeq! formalArgs,
+ ExprSeq! actualArgs,
+ TypeSeq formalOuts,
+ IdentifierExprSeq actualOuts,
+ string! opName,
+ TypecheckingContext! tc)
+ requires formalArgs.Length == actualArgs.Length;
+ requires formalOuts == null <==> actualOuts == null;
+ requires formalOuts != null ==> formalOuts.Length == ((!)actualOuts).Length;
+ requires tc != null ==> opName != null;
+ // requires "actualArgs" and "actualOuts" to have been type checked
+ {
+ Dictionary<TypeVariable!, Type!> subst = new Dictionary<TypeVariable!, Type!>();
+ foreach (TypeVariable! tv in typeParams) {
+ TypeProxy proxy = new TypeProxy(Token.NoToken, tv.Name);
+ subst.Add(tv, proxy);
+ }
+
+ for (int i = 0; i < formalArgs.Length; i++) {
+ Type formal = formalArgs[i].Substitute(subst);
+ Type actual = (!)((!)actualArgs[i]).Type;
+ // if the type variables to be matched occur in the actual
+ // argument types, something has gone very wrong
+ assert forall{TypeVariable! var in typeParams; !actual.FreeVariables.Has(var)};
+
+ if (!formal.Unify(actual)) {
+ assume tc != null; // caller expected no errors
+ assert opName != null; // follows from precondition
+ tc.Error((!)actualArgs[i],
+ "invalid type for argument {0} in {1}: {2} (expected: {3})",
+ i, opName, actual, formalArgs[i]);
+ }
+ }
+
+ if (formalOuts != null) {
+ for (int i = 0; i < formalOuts.Length; ++i) {
+ Type formal = formalOuts[i].Substitute(subst);
+ Type actual = (!)((!)actualOuts)[i].Type;
+ // if the type variables to be matched occur in the actual
+ // argument types, something has gone very wrong
+ assert forall{TypeVariable! var in typeParams; !actual.FreeVariables.Has(var)};
+
+ if (!formal.Unify(actual)) {
+ assume tc != null; // caller expected no errors
+ assert opName != null; // follows from precondition
+ tc.Error(actualOuts[i],
+ "invalid type for out-parameter {0} in {1}: {2} (expected: {3})",
+ i, opName, actual, formal);
+ }
+ }
+ }
+
+ return subst;
+ }
+#endif
+
+ //------------ Match formal argument types of a function or map
+ //------------ on concrete types, substitute the result into the
+ //------------ result type. Null is returned for type errors
+
+ public static TypeSeq CheckArgumentTypes(TypeVariableSeq! typeParams,
+ out List<Type!>! actualTypeParams,
+ TypeSeq! formalIns,
+ ExprSeq! actualIns,
+ TypeSeq! formalOuts,
+ IdentifierExprSeq actualOuts,
+ IToken! typeCheckingSubject,
+ string! opName,
+ TypecheckingContext! tc)
+ // requires "actualIns" and "actualOuts" to have been type checked
+ {
+ actualTypeParams = new List<Type!> ();
+
+ if (formalIns.Length != actualIns.Length) {
+ tc.Error(typeCheckingSubject, "wrong number of arguments in {0}: {1}",
+ opName, actualIns.Length);
+ // if there are no type parameters, we can still return the result
+ // type and hope that the type checking proceeds
+ return typeParams.Length == 0 ? formalOuts : null;
+ } else if (actualOuts != null && formalOuts.Length != actualOuts.Length) {
+ tc.Error(typeCheckingSubject, "wrong number of result variables in {0}: {1}",
+ opName, actualOuts.Length);
+ // if there are no type parameters, we can still return the result
+ // type and hope that the type checking proceeds
+ actualTypeParams = new List<Type!> ();
+ return typeParams.Length == 0 ? formalOuts : null;
+ }
+
+ int previousErrorCount = tc.ErrorCount;
+ IDictionary<TypeVariable!, Type!> subst =
+ MatchArgumentTypes(typeParams, formalIns, actualIns,
+ actualOuts != null ? formalOuts : null, actualOuts, opName, tc);
+
+ foreach (TypeVariable! var in typeParams)
+ actualTypeParams.Add(subst[var]);
+
+ TypeSeq! actualResults = new TypeSeq ();
+ foreach (Type! t in formalOuts) {
+ actualResults.Add(t.Substitute(subst));
+ }
+ TypeVariableSeq resultFreeVars = FreeVariablesIn(actualResults);
+ if (previousErrorCount != tc.ErrorCount) {
+ // errors occured when matching the formal arguments
+ // in case we have been able to substitute all type parameters,
+ // we can still return the result type and hope that the
+ // type checking proceeds in a meaningful manner
+ if (forall{TypeVariable! var in typeParams; !resultFreeVars.Has(var)})
+ return actualResults;
+ else
+ // otherwise there is no point in returning the result type,
+ // type checking would only get confused even further
+ return null;
+ }
+
+ assert forall{TypeVariable! var in typeParams; !resultFreeVars.Has(var)};
+ return actualResults;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+
+ // about the same as Type.CheckArgumentTypes, but without
+ // detailed error reports
+ public static Type! InferValueType(TypeVariableSeq! typeParams,
+ TypeSeq! formalArgs,
+ Type! formalResult,
+ TypeSeq! actualArgs) {
+ IDictionary<TypeVariable!, Type!>! subst =
+ InferTypeParameters(typeParams, formalArgs, actualArgs);
+
+ Type! res = formalResult.Substitute(subst);
+ // all type parameters have to be substituted with concrete types
+ TypeVariableSeq! resFreeVars = res.FreeVariables;
+ assert forall{TypeVariable! var in typeParams; !resFreeVars.Has(var)};
+ return res;
+ }
+
+#if OLD_UNIFICATION
+ public static IDictionary<TypeVariable!, Type!>!
+ InferTypeParameters(TypeVariableSeq! typeParams,
+ TypeSeq! formalArgs,
+ TypeSeq! actualArgs)
+ requires formalArgs.Length == actualArgs.Length; {
+
+ TypeVariableSeq! boundVarSeq0 = new TypeVariableSeq ();
+ TypeVariableSeq! boundVarSeq1 = new TypeVariableSeq ();
+ Dictionary<TypeVariable!, Type!>! subst = new Dictionary<TypeVariable!, Type!>();
+
+ for (int i = 0; i < formalArgs.Length; ++i) {
+ try {
+ assert forall{TypeVariable! var in typeParams;
+ !actualArgs[i].FreeVariables.Has(var)};
+ formalArgs[i].Unify(actualArgs[i], typeParams,
+ boundVarSeq0, boundVarSeq1, subst);
+ } catch (UnificationFailedException) {
+ System.Diagnostics.Debug.Fail("Type unification failed: " +
+ formalArgs[i] + " vs " + actualArgs[i]);
+ }
+ }
+
+ // we only allow type parameters to be substituted
+ assert forall{TypeVariable! var in subst.Keys; typeParams.Has(var)};
+ return subst;
+ }
+#else
+ /// <summary>
+ /// like Type.CheckArgumentTypes, but assumes no errors
+ /// (and only does arguments, not results; and takes actuals as TypeSeq, not ExprSeq)
+ /// </summary>
+ public static IDictionary<TypeVariable!, Type!>!
+ InferTypeParameters(TypeVariableSeq! typeParams,
+ TypeSeq! formalArgs,
+ TypeSeq! actualArgs)
+ requires formalArgs.Length == actualArgs.Length;
+ {
+ TypeSeq proxies = new TypeSeq();
+ Dictionary<TypeVariable!, Type!>! subst = new Dictionary<TypeVariable!, Type!>();
+ foreach (TypeVariable! tv in typeParams) {
+ TypeProxy proxy = new TypeProxy(Token.NoToken, tv.Name);
+ proxies.Add(proxy);
+ subst.Add(tv, proxy);
+ }
+
+ for (int i = 0; i < formalArgs.Length; i++) {
+ Type formal = formalArgs[i].Substitute(subst);
+ Type actual = actualArgs[i];
+ // if the type variables to be matched occur in the actual
+ // argument types, something has gone very wrong
+ assert forall{TypeVariable! var in typeParams; !actual.FreeVariables.Has(var)};
+
+ if (!formal.Unify(actual)) {
+ assume false; // caller expected no errors
+ }
+ }
+
+ return subst;
+ }
+#endif
+
+ //----------- Helper methods to deal with bound type variables ---------------
+
+ public static void EmitOptionalTypeParams(TokenTextWriter! stream, TypeVariableSeq! typeParams) {
+ if (typeParams.Length > 0) {
+ stream.Write("<");
+ typeParams.Emit(stream, ","); // default binding strength of 0 is ok
+ stream.Write(">");
+ }
+ }
+
+ // Sort the type parameters according to the order of occurrence in the argument types
+ public static TypeVariableSeq! SortTypeParams(TypeVariableSeq! typeParams,
+ TypeSeq! argumentTypes, Type resultType)
+ ensures result.Length == typeParams.Length; {
+ if (typeParams.Length == 0) {
+ return typeParams;
+ }
+
+ TypeVariableSeq freeVarsInUse = FreeVariablesIn(argumentTypes);
+ if (resultType != null) {
+ freeVarsInUse.AppendWithoutDups(resultType.FreeVariables);
+ }
+ // "freeVarsInUse" is already sorted, but it may contain type variables not in "typeParams".
+ // So, project "freeVarsInUse" onto "typeParams":
+ TypeVariableSeq! sortedTypeParams = new TypeVariableSeq ();
+ foreach (TypeVariable! var in freeVarsInUse) {
+ if (typeParams.Has(var)) {
+ sortedTypeParams.Add(var);
+ }
+ }
+
+ if (sortedTypeParams.Length < typeParams.Length)
+ // add the type parameters not mentioned in "argumentTypes" in
+ // the end of the list (this can happen for quantifiers)
+ sortedTypeParams.AppendWithoutDups(typeParams);
+
+ return sortedTypeParams;
+ }
+
+ // Check that each of the type parameters occurs in at least one argument type.
+ // Return true if some type parameters appear only among "moreArgumentTypes" and
+ // not in "argumentTypes".
+ [Pure]
+ public static bool CheckBoundVariableOccurrences(TypeVariableSeq! typeParams,
+ TypeSeq! argumentTypes,
+ TypeSeq moreArgumentTypes,
+ IToken! resolutionSubject,
+ string! subjectName,
+ ResolutionContext! rc) {
+ TypeVariableSeq freeVarsInArgs = FreeVariablesIn(argumentTypes);
+ TypeVariableSeq moFreeVarsInArgs = moreArgumentTypes == null ? null : FreeVariablesIn(moreArgumentTypes);
+ bool someTypeParamsAppearOnlyAmongMo = false;
+ foreach (TypeVariable! var in typeParams) {
+ if (rc.LookUpTypeBinder(var.Name) == var) // avoid to complain twice about variables that are bound multiple times
+ {
+ if (freeVarsInArgs.Has(var)) {
+ // cool
+ } else if (moFreeVarsInArgs != null && moFreeVarsInArgs.Has(var)) {
+ someTypeParamsAppearOnlyAmongMo = true;
+ } else {
+ rc.Error(resolutionSubject,
+ "type variable must occur in {0}: {1}",
+ subjectName, var);
+ }
+ }
+ }
+ return someTypeParamsAppearOnlyAmongMo;
+ }
+
+ [Pure]
+ public static TypeVariableSeq! FreeVariablesIn(TypeSeq! arguments) {
+ TypeVariableSeq! res = new TypeVariableSeq ();
+ foreach (Type! t in arguments)
+ res.AppendWithoutDups(t.FreeVariables);
+ return res;
+ }
+ }
+
+ //=====================================================================
+
+ public class BasicType : Type
+ {
+ public readonly SimpleType T;
+ public BasicType(IToken! token, SimpleType t)
+ : base(token)
+ {
+ T = t;
+ // base(token);
+ }
+ public BasicType(SimpleType t)
+ : base(Token.NoToken)
+ {
+ T = t;
+ // base(Token.NoToken);
+ }
+
+ //----------- Cloning ----------------------------------
+ // We implement our own clone-method, because bound type variables
+ // have to be created in the right way. It is /not/ ok to just clone
+ // everything recursively.
+
+ public override Type! Clone(IDictionary<TypeVariable!, TypeVariable!>! varMap) {
+ // BasicTypes are immutable anyway, we do not clone
+ return this;
+ }
+
+ public override Type! CloneUnresolved() {
+ return this;
+ }
+
+ //----------- Linearisation ----------------------------------
+
+ public override void Emit(TokenTextWriter! stream, int contextBindingStrength)
+ {
+ // no parentheses are necessary for basic types
+ stream.SetToken(this);
+ stream.Write("{0}", this);
+ }
+
+ [Pure]
+ public override string! ToString()
+ {
+ switch (T)
+ {
+ case SimpleType.Int: return "int";
+ case SimpleType.Bool: return "bool";
+ }
+ Debug.Assert(false, "bad type " + T);
+ assert false; // make compiler happy
+ }
+
+ //----------- Equality ----------------------------------
+
+ [Pure][Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals(object that) {
+ // shortcut
+ Type thatType = that as Type;
+ if (thatType == null)
+ return false;
+ BasicType thatBasicType = TypeProxy.FollowProxy(thatType.Expanded) as BasicType;
+ return thatBasicType != null && this.T == thatBasicType.T;
+ }
+
+ [Pure]
+ public override bool Equals(Type! that,
+ TypeVariableSeq! thisBoundVariables,
+ TypeVariableSeq! thatBoundVariables) {
+ return this.Equals(that);
+ }
+
+ //----------- Unification of types -----------
+
+ public override bool Unify(Type! that,
+ TypeVariableSeq! unifiableVariables,
+ // an idempotent substitution that describes the
+ // unification result up to a certain point
+ IDictionary<TypeVariable!, Type!>! unifier) {
+ that = that.Expanded;
+ if (that is TypeProxy || that is TypeVariable) {
+ return that.Unify(this, unifiableVariables, unifier);
+ } else {
+ return this.Equals(that);
+ }
+ }
+
+#if OLD_UNIFICATION
+ public override void Unify(Type! that,
+ TypeVariableSeq! unifiableVariables,
+ TypeVariableSeq! thisBoundVariables,
+ TypeVariableSeq! thatBoundVariables,
+ IDictionary<TypeVariable!, Type!>! result) {
+ that = that.Expanded;
+ if (that is TypeVariable) {
+ that.Unify(this, unifiableVariables, thatBoundVariables, thisBoundVariables, result);
+ } else {
+ if (!this.Equals(that))
+ throw UNIFICATION_FAILED;
+ }
+ }
+#endif
+
+ //----------- Substitution of free variables with types not containing bound variables -----------------
+
+ public override Type! Substitute(IDictionary<TypeVariable!, Type!>! subst) {
+ return this;
+ }
+
+ //----------- Hashcodes ----------------------------------
+
+ [Pure]
+ public override int GetHashCode(TypeVariableSeq! boundVariables)
+ {
+ return this.T.GetHashCode();
+ }
+
+ //----------- Resolution ----------------------------------
+
+ public override Type! ResolveType(ResolutionContext! rc) {
+ // nothing to resolve
+ return this;
+ }
+
+ // determine the free variables in a type, in the order in which the variables occur
+ public override TypeVariableSeq! FreeVariables {
+ get {
+ return new TypeVariableSeq (); // basic type are closed
+ }
+ }
+
+ public override List<TypeProxy!>! FreeProxies { get {
+ return new List<TypeProxy!> ();
+ } }
+
+ //----------- Getters/Issers ----------------------------------
+
+ public override bool IsBasic { get { return true; } }
+ public override bool IsInt { get { return this.T == SimpleType.Int; } }
+ public override bool IsBool { get { return this.T == SimpleType.Bool; } }
+
+ public override Absy! StdDispatch(StandardVisitor! visitor)
+ {
+ return visitor.VisitBasicType(this);
+ }
+ }
+
+ //=====================================================================
+
+ public class BvType : Type
+ {
+ public readonly int Bits;
+
+ public BvType(IToken! token, int bits)
+ : base(token)
+ {
+ Bits = bits;
+ }
+
+ public BvType(int bits)
+ : base(Token.NoToken)
+ {
+ Bits = bits;
+ }
+
+ //----------- Cloning ----------------------------------
+ // We implement our own clone-method, because bound type variables
+ // have to be created in the right way. It is /not/ ok to just clone
+ // everything recursively.
+
+ public override Type! Clone(IDictionary<TypeVariable!, TypeVariable!>! varMap) {
+ // BvTypes are immutable anyway, we do not clone
+ return this;
+ }
+
+ public override Type! CloneUnresolved() {
+ return this;
+ }
+
+ //----------- Linearisation ----------------------------------
+
+ public override void Emit(TokenTextWriter! stream, int contextBindingStrength)
+ {
+ // no parentheses are necessary for bitvector-types
+ stream.SetToken(this);
+ stream.Write("{0}", this);
+ }
+
+ [Pure]
+ public override string! ToString()
+ {
+ return "bv" + Bits;
+ }
+
+ //----------- Equality ----------------------------------
+
+ [Pure]
+ public override bool Equals(Type! that,
+ TypeVariableSeq! thisBoundVariables,
+ TypeVariableSeq! thatBoundVariables) {
+ BvType thatBvType = TypeProxy.FollowProxy(that.Expanded) as BvType;
+ return thatBvType != null && this.Bits == thatBvType.Bits;
+ }
+
+ //----------- Unification of types -----------
+
+ public override bool Unify(Type! that,
+ TypeVariableSeq! unifiableVariables,
+ // an idempotent substitution that describes the
+ // unification result up to a certain point
+ IDictionary<TypeVariable!, Type!>! unifier) {
+ that = that.Expanded;
+ if (that is TypeProxy || that is TypeVariable) {
+ return that.Unify(this, unifiableVariables, unifier);
+ } else {
+ return this.Equals(that);
+ }
+ }
+
+#if OLD_UNIFICATION
+ public override void Unify(Type! that,
+ TypeVariableSeq! unifiableVariables,
+ TypeVariableSeq! thisBoundVariables,
+ TypeVariableSeq! thatBoundVariables,
+ IDictionary<TypeVariable!, Type!>! result) {
+ that = that.Expanded;
+ if (that is TypeVariable) {
+ that.Unify(this, unifiableVariables, thatBoundVariables, thisBoundVariables, result);
+ } else {
+ if (!this.Equals(that))
+ throw UNIFICATION_FAILED;
+ }
+ }
+#endif
+
+ //----------- Substitution of free variables with types not containing bound variables -----------------
+
+ public override Type! Substitute(IDictionary<TypeVariable!, Type!>! subst) {
+ return this;
+ }
+
+ //----------- Hashcodes ----------------------------------
+
+ [Pure]
+ public override int GetHashCode(TypeVariableSeq! boundVariables)
+ {
+ return this.Bits.GetHashCode();
+ }
+
+ //----------- Resolution ----------------------------------
+
+ public override Type! ResolveType(ResolutionContext! rc) {
+ // nothing to resolve
+ return this;
+ }
+
+ // determine the free variables in a type, in the order in which the variables occur
+ public override TypeVariableSeq! FreeVariables {
+ get {
+ return new TypeVariableSeq (); // bitvector-type are closed
+ }
+ }
+
+ public override List<TypeProxy!>! FreeProxies { get {
+ return new List<TypeProxy!> ();
+ } }
+
+ //----------- Getters/Issers ----------------------------------
+
+ public override bool IsBv { get { return true; } }
+ public override int BvBits { get {
+ return Bits;
+ } }
+
+ public override Absy! StdDispatch(StandardVisitor! visitor)
+ {
+ return visitor.VisitBvType(this);
+ }
+ }
+
+ //=====================================================================
+
+ // An AST node containing an identifier and a sequence of type arguments, which
+ // will be turned either into a TypeVariable, into a CtorType or into a BvType
+ // during the resolution phase
+ public class UnresolvedTypeIdentifier : Type {
+ public readonly string! Name;
+ public readonly TypeSeq! Arguments;
+
+ public UnresolvedTypeIdentifier(IToken! token, string! name) {
+ this(token, name, new TypeSeq ());
+ }
+
+ public UnresolvedTypeIdentifier(IToken! token, string! name, TypeSeq! arguments)
+ : base(token)
+ {
+ this.Name = name;
+ this.Arguments = arguments;
+ }
+
+ //----------- Cloning ----------------------------------
+ // We implement our own clone-method, because bound type variables
+ // have to be created in the right way. It is /not/ ok to just clone
+ // everything recursively
+
+ public override Type! Clone(IDictionary<TypeVariable!, TypeVariable!>! varMap) {
+ TypeSeq! newArgs = new TypeSeq ();
+ foreach(Type! t in Arguments)
+ newArgs.Add(t.Clone(varMap));
+ return new UnresolvedTypeIdentifier(tok, Name, newArgs);
+ }
+
+ public override Type! CloneUnresolved() {
+ TypeSeq! newArgs = new TypeSeq ();
+ foreach(Type! t in Arguments)
+ newArgs.Add(t.CloneUnresolved());
+ return new UnresolvedTypeIdentifier(tok, Name, newArgs);
+ }
+
+ //----------- Equality ----------------------------------
+
+ [Pure]
+ public override bool Equals(Type! that,
+ TypeVariableSeq! thisBoundVariables,
+ TypeVariableSeq! thatBoundVariables) {
+ System.Diagnostics.Debug.Fail("UnresolvedTypeIdentifier.Equals should never be called");
+ return false; // to make the compiler happy
+ }
+
+ //----------- Unification of types -----------
+
+ public override bool Unify(Type! that,
+ TypeVariableSeq! unifiableVariables,
+ IDictionary<TypeVariable!, Type!>! result) {
+ assert false; // UnresolvedTypeIdentifier.Unify should never be called
+ }
+
+#if OLD_UNIFICATION
+ public override void Unify(Type! that,
+ TypeVariableSeq! unifiableVariables,
+ TypeVariableSeq! thisBoundVariables,
+ TypeVariableSeq! thatBoundVariables,
+ IDictionary<TypeVariable!, Type!>! result) {
+ System.Diagnostics.Debug.Fail("UnresolvedTypeIdentifier.Unify should never be called");
+ }
+#endif
+
+ //----------- Substitution of free variables with types not containing bound variables -----------------
+
+ public override Type! Substitute(IDictionary<TypeVariable!, Type!>! subst) {
+ assert false; // UnresolvedTypeIdentifier.Substitute should never be called
+ }
+
+ //----------- Hashcodes ----------------------------------
+
+ [Pure]
+ public override int GetHashCode(TypeVariableSeq! boundVariables) {
+ assert false; // UnresolvedTypeIdentifier.GetHashCode should never be called
+ }
+
+ //----------- Resolution ----------------------------------
+
+ public override Type! ResolveType(ResolutionContext! rc) {
+ // first case: the type name denotes a bitvector-type
+ if (Name.StartsWith("bv") && Name.Length > 2) {
+ bool is_bv = true;
+ for (int i = 2; i < Name.Length; ++i) {
+ if (!char.IsDigit(Name[i])) {
+ is_bv = false;
+ break;
+ }
+ }
+ if (is_bv) {
+ if (Arguments.Length > 0) {
+ rc.Error(this,
+ "bitvector types must not be applied to arguments: {0}",
+ Name);
+ }
+ return new BvType(tok, int.Parse(Name.Substring(2)));
+ }
+ }
+
+ // second case: the identifier is resolved to a type variable
+ TypeVariable var = rc.LookUpTypeBinder(Name);
+ if (var != null) {
+ if (Arguments.Length > 0) {
+ rc.Error(this,
+ "type variables must not be applied to arguments: {0}",
+ var);
+ }
+ return var;
+ }
+
+ // third case: the identifier denotes a type constructor and we
+ // recursively resolve the arguments
+ TypeCtorDecl ctorDecl = rc.LookUpType(Name);
+ if (ctorDecl != null) {
+ if (Arguments.Length != ctorDecl.Arity) {
+ rc.Error(this,
+ "type constructor received wrong number of arguments: {0}",
+ ctorDecl);
+ return this;
+ }
+ return new CtorType (tok, ctorDecl, ResolveArguments(rc));
+ }
+
+ // fourth case: the identifier denotes a type synonym
+ TypeSynonymDecl synDecl = rc.LookUpTypeSynonym(Name);
+ if (synDecl != null) {
+ if (Arguments.Length != synDecl.TypeParameters.Length) {
+ rc.Error(this,
+ "type synonym received wrong number of arguments: {0}",
+ synDecl);
+ return this;
+ }
+ TypeSeq! resolvedArgs = ResolveArguments(rc);
+
+
+ return new TypeSynonymAnnotation(this.tok, synDecl, resolvedArgs);
+
+ }
+
+ // otherwise: this name is not declared anywhere
+ rc.Error(this, "undeclared type: {0}", Name);
+ return this;
+ }
+
+ private TypeSeq! ResolveArguments(ResolutionContext! rc) {
+ TypeSeq! resolvedArgs = new TypeSeq ();
+ foreach (Type! t in Arguments)
+ resolvedArgs.Add(t.ResolveType(rc));
+ return resolvedArgs;
+ }
+
+ public override TypeVariableSeq! FreeVariables {
+ get {
+ return new TypeVariableSeq ();
+ }
+ }
+
+ public override List<TypeProxy!>! FreeProxies { get {
+ return new List<TypeProxy!> ();
+ } }
+
+ //----------- Linearisation ----------------------------------
+
+ public override void Emit(TokenTextWriter! stream, int contextBindingStrength)
+ {
+ stream.SetToken(this);
+ // PR: should unresolved types be syntactically distinguished from resolved types?
+ CtorType.EmitCtorType(this.Name, Arguments, stream, contextBindingStrength);
+ }
+
+ //----------- Getters/Issers ----------------------------------
+
+ public override bool IsUnresolved { get { return true; } }
+ public override UnresolvedTypeIdentifier! AsUnresolved { get { return this; } }
+
+ public override Absy! StdDispatch(StandardVisitor! visitor)
+ {
+ return visitor.VisitUnresolvedTypeIdentifier(this);
+ }
+ }
+
+ //=====================================================================
+
+ public class TypeVariable : Type {
+ public readonly string! Name;
+
+ public TypeVariable(IToken! token, string! name)
+ : base(token)
+ {
+ this.Name = name;
+ }
+
+ //----------- Cloning ----------------------------------
+ // We implement our own clone-method, because bound type variables
+ // have to be created in the right way. It is /not/ ok to just clone
+ // everything recursively
+
+ public override Type! Clone(IDictionary<TypeVariable!, TypeVariable!>! varMap) {
+ // if this variable is mapped to some new variable, we take the new one
+ // otherwise, return this
+ TypeVariable res;
+ varMap.TryGetValue(this, out res);
+ if (res == null)
+ return this;
+ else
+ return res;
+ }
+
+ public override Type! CloneUnresolved() {
+ return this;
+ }
+
+ //----------- Equality ----------------------------------
+
+ [Pure]
+ public override bool Equals(Type! that,
+ TypeVariableSeq! thisBoundVariables,
+ TypeVariableSeq! thatBoundVariables) {
+ TypeVariable thatAsTypeVar = TypeProxy.FollowProxy(that.Expanded) as TypeVariable;
+
+ if (thatAsTypeVar == null)
+ return false;
+
+ int thisIndex = thisBoundVariables.LastIndexOf(this);
+ int thatIndex = thatBoundVariables.LastIndexOf(thatAsTypeVar);
+ return (thisIndex >= 0 && thisIndex == thatIndex) ||
+ (thisIndex == -1 && thatIndex == -1 &&
+ Object.ReferenceEquals(this, thatAsTypeVar));
+ }
+
+ //----------- Unification of types -----------
+
+ public override bool Unify(Type! that,
+ TypeVariableSeq! unifiableVariables,
+ // an idempotent substitution that describes the
+ // unification result up to a certain point
+ IDictionary<TypeVariable!, Type!>! unifier) {
+ that = that.Expanded;
+ if (that is TypeProxy && !(that is ConstrainedProxy))
+ return that.Unify(this, unifiableVariables, unifier);
+
+ if (this.Equals(that))
+ return true;
+
+ if (unifiableVariables.Has(this)) {
+ Type previousSubst;
+ unifier.TryGetValue(this, out previousSubst);
+ if (previousSubst == null) {
+ return addSubstitution(unifier, that);
+ } else {
+ // we have to unify the old instantiation with the new one
+ return previousSubst.Unify(that, unifiableVariables, unifier);
+ }
+ }
+
+ // this cannot be instantiated with anything
+ // but that possibly can ...
+
+ TypeVariable tv = that as TypeVariable;
+
+ return tv != null &&
+ unifiableVariables.Has(tv) &&
+ that.Unify(this, unifiableVariables, unifier);
+ }
+
+ // TODO: the following might cause problems, because when applying substitutions
+ // to type proxies the substitutions are not propagated to the proxy
+ // constraints (right now at least)
+ private bool addSubstitution(IDictionary<TypeVariable!, Type!>! oldSolution,
+ // the type that "this" is instantiated with
+ Type! newSubst)
+ requires !oldSolution.ContainsKey(this); {
+
+ Dictionary<TypeVariable!, Type!>! newMapping = new Dictionary<TypeVariable!, Type!> ();
+ // apply the old (idempotent) substitution to the new instantiation
+ Type! substSubst = newSubst.Substitute(oldSolution);
+ // occurs check
+ if (substSubst.FreeVariables.Has(this))
+ return false;
+ newMapping.Add(this, substSubst);
+
+ // apply the new substitution to the old ones to ensure idempotence
+ List<TypeVariable!>! keys = new List<TypeVariable!> ();
+ keys.AddRange(oldSolution.Keys);
+ foreach (TypeVariable! var in keys)
+ oldSolution[var] = oldSolution[var].Substitute(newMapping);
+ oldSolution.Add(this, substSubst);
+
+ assert IsIdempotent(oldSolution);
+ return true;
+ }
+
+#if OLD_UNIFICATION
+ public override void Unify(Type! that,
+ TypeVariableSeq! unifiableVariables,
+ TypeVariableSeq! thisBoundVariables,
+ TypeVariableSeq! thatBoundVariables,
+ IDictionary<TypeVariable!, Type!>! result) {
+ that = that.Expanded;
+ int thisIndex = thisBoundVariables.LastIndexOf(this);
+ if (thisIndex == -1) {
+ // this is not a bound variable and can possibly be matched on that
+ // that must not contain any bound variables
+ TypeVariableSeq! thatFreeVars = that.FreeVariables;
+ if (exists{TypeVariable! var in thatBoundVariables; thatFreeVars.Has(var)})
+ throw UNIFICATION_FAILED;
+
+ // otherwise, in case that is a typevariable it cannot be bound and
+ // we can just check for equality
+ if (this.Equals(that))
+ return;
+
+ if (!unifiableVariables.Has(this)) {
+ // this cannot be instantiated with anything
+ // but that possibly can ...
+ if ((that is TypeVariable) &&
+ unifiableVariables.Has(that as TypeVariable)) {
+ that.Unify(this, unifiableVariables, thatBoundVariables, thisBoundVariables, result);
+ return;
+ } else {
+ throw UNIFICATION_FAILED;
+ }
+ }
+
+ Type previousSubst;
+ result.TryGetValue(this, out previousSubst);
+ if (previousSubst == null) {
+ addSubstitution(result, that);
+ } else {
+ // we have to unify the old instantiation with the new one
+ previousSubst.Unify(that, unifiableVariables, thisBoundVariables, thatBoundVariables, result);
+ }
+ } else {
+ // this is a bound variable, that also has to be one (with the same index)
+ if (!(that is TypeVariable) ||
+ thatBoundVariables.LastIndexOf(that) != thisIndex)
+ throw UNIFICATION_FAILED;
+ }
+ }
+
+#endif
+
+ //----------- Substitution of free variables with types not containing bound variables -----------------
+
+ public override Type! Substitute(IDictionary<TypeVariable!, Type!>! subst) {
+ Type res;
+ if (subst.TryGetValue(this, out res)) {
+ assert res != null;
+ return res;
+ } else {
+ return this;
+ }
+ }
+
+ //----------- Hashcodes ----------------------------------
+
+ [Pure]
+ public override int GetHashCode(TypeVariableSeq! boundVariables) {
+ int thisIndex = boundVariables.LastIndexOf(this);
+ if (thisIndex == -1)
+ return GetBaseHashCode();
+ return thisIndex * 27473671;
+ }
+
+ //----------- Linearisation ----------------------------------
+
+ public override void Emit(TokenTextWriter! stream, int contextBindingStrength)
+ {
+ // never put parentheses around variables
+ stream.SetToken(this);
+ stream.Write("{0}", TokenTextWriter.SanitizeIdentifier(this.Name));
+ }
+
+ //----------- Resolution ----------------------------------
+
+ public override Type! ResolveType(ResolutionContext! rc) {
+ // nothing to resolve
+ return this;
+ }
+
+ public override TypeVariableSeq! FreeVariables {
+ get { return new TypeVariableSeq(this); }
+ }
+
+ public override List<TypeProxy!>! FreeProxies { get {
+ return new List<TypeProxy!> ();
+ } }
+
+ //----------- Getters/Issers ----------------------------------
+
+ public override bool IsVariable { get { return true; } }
+ public override TypeVariable! AsVariable { get { return this; } }
+
+ public override Absy! StdDispatch(StandardVisitor! visitor)
+ {
+ return visitor.VisitTypeVariable(this);
+ }
+ }
+
+ //=====================================================================
+
+ public class TypeProxy : Type {
+ static int proxies = 0;
+ protected readonly string! Name;
+
+ public TypeProxy(IToken! token, string! givenName)
+ {
+ this(token, givenName, "proxy");
+ }
+
+ protected TypeProxy(IToken! token, string! givenName, string! kind)
+ {
+ Name = givenName + "$" + kind + "#" + proxies;
+ proxies++;
+ base(token);
+ }
+
+ private Type proxyFor;
+ public Type ProxyFor {
+ // apply path shortening, and then return the value of proxyFor
+ get {
+ TypeProxy anotherProxy = proxyFor as TypeProxy;
+ if (anotherProxy != null && anotherProxy.proxyFor != null) {
+ // apply path shortening by bypassing "anotherProxy" (and possibly others)
+ proxyFor = anotherProxy.ProxyFor;
+ assert proxyFor != null;
+ }
+ return proxyFor;
+ }
+ }
+
+ [Pure][Reads(ReadsAttribute.Reads.Everything)]
+ public static Type! FollowProxy(Type! t)
+ ensures result is TypeProxy ==> ((TypeProxy)result).proxyFor == null;
+ {
+ if (t is TypeProxy) {
+ Type p = ((TypeProxy)t).ProxyFor;
+ if (p != null) {
+ return p;
+ }
+ }
+ return t;
+ }
+
+ protected void DefineProxy(Type! ty)
+ requires ProxyFor == null;
+ {
+ // follow ty down to the leaf level, so that we can avoid creating a cycle
+ ty = FollowProxy(ty);
+ if (!object.ReferenceEquals(this, ty)) {
+ proxyFor = ty;
+ }
+ }
+
+ //----------- Cloning ----------------------------------
+
+ public override Type! Clone(IDictionary<TypeVariable!, TypeVariable!>! varMap) {
+ Type p = ProxyFor;
+ if (p != null) {
+ return p.Clone(varMap);
+ } else {
+ return new TypeProxy(this.tok, this.Name); // the clone will have a name that ends with $proxy<n>$proxy<m>
+ }
+ }
+
+ public override Type! CloneUnresolved() {
+ return new TypeProxy(this.tok, this.Name); // the clone will have a name that ends with $proxy<n>$proxy<m>
+ }
+
+ //----------- Equality ----------------------------------
+
+ [Pure]
+ public override bool Equals(Type! that,
+ TypeVariableSeq! thisBoundVariables,
+ TypeVariableSeq! thatBoundVariables) {
+ if (object.ReferenceEquals(this, that)) {
+ return true;
+ }
+ Type p = ProxyFor;
+ if (p != null) {
+ return p.Equals(that, thisBoundVariables, thatBoundVariables);
+ } else {
+ // This proxy could be made to be equal to anything, so what to return?
+ return false;
+ }
+ }
+
+ //----------- Unification of types -----------
+
+ // determine whether the occurs check fails: this is a strict subtype of that
+ protected bool ReallyOccursIn(Type! that) {
+ that = FollowProxy(that.Expanded);
+ return that.FreeProxies.Contains(this) &&
+ (that.IsCtor || that.IsMap && this != that && this.ProxyFor != that);
+ }
+
+ public override bool Unify(Type! that,
+ TypeVariableSeq! unifiableVariables,
+ IDictionary<TypeVariable!, Type!>! result) {
+ Type p = ProxyFor;
+ if (p != null) {
+ return p.Unify(that, unifiableVariables, result);
+ } else {
+ // unify this with that
+ if (this.ReallyOccursIn(that))
+ return false;
+ DefineProxy(that.Expanded);
+ return true;
+ }
+ }
+
+ //----------- Substitution of free variables with types not containing bound variables -----------------
+
+ public override Type! Substitute(IDictionary<TypeVariable!, Type!>! subst) {
+ Type p = ProxyFor;
+ if (p != null) {
+ return p.Substitute(subst);
+ } else {
+ return this;
+ }
+ }
+
+ //----------- Hashcodes ----------------------------------
+
+ [Pure]
+ public override int GetHashCode(TypeVariableSeq! boundVariables) {
+ Type p = ProxyFor;
+ if (p != null) {
+ return p.GetHashCode(boundVariables);
+ } else {
+ return GetBaseHashCode();
+ }
+ }
+
+ //----------- Linearisation ----------------------------------
+
+ public override void Emit(TokenTextWriter! stream, int contextBindingStrength)
+ {
+ Type p = ProxyFor;
+ if (p != null) {
+ p.Emit(stream, contextBindingStrength);
+ } else {
+ // no need for parentheses
+ stream.SetToken(this);
+ stream.Write("{0}", TokenTextWriter.SanitizeIdentifier(this.Name));
+ }
+ }
+
+ //----------- Resolution ----------------------------------
+
+ public override Type! ResolveType(ResolutionContext! rc) {
+ Type p = ProxyFor;
+ if (p != null) {
+ return p.ResolveType(rc);
+ } else {
+ return this;
+ }
+ }
+
+ public override TypeVariableSeq! FreeVariables {
+ get {
+ Type p = ProxyFor;
+ if (p != null) {
+ return p.FreeVariables;
+ } else {
+ return new TypeVariableSeq();
+ }
+ }
+ }
+
+ public override List<TypeProxy!>! FreeProxies { get {
+ Type p = ProxyFor;
+ if (p != null) {
+ return p.FreeProxies;
+ } else {
+ List<TypeProxy!>! res = new List<TypeProxy!> ();
+ res.Add(this);
+ return res;
+ }
+ } }
+
+ //----------- Getters/Issers ----------------------------------
+
+ public override bool IsBasic { get {
+ Type p = ProxyFor;
+ return p != null && p.IsBasic;
+ } }
+ public override bool IsInt { get {
+ Type p = ProxyFor;
+ return p != null && p.IsInt;
+ } }
+ public override bool IsBool { get {
+ Type p = ProxyFor;
+ return p != null && p.IsBool;
+ } }
+
+ public override bool IsVariable { get {
+ Type p = ProxyFor;
+ return p != null && p.IsVariable;
+ } }
+ public override TypeVariable! AsVariable { get {
+ Type p = ProxyFor;
+ assume p != null;
+ return p.AsVariable;
+ } }
+
+ public override bool IsCtor { get {
+ Type p = ProxyFor;
+ return p != null && p.IsCtor;
+ } }
+ public override CtorType! AsCtor { get {
+ Type p = ProxyFor;
+ assume p != null;
+ return p.AsCtor;
+ } }
+ public override bool IsMap { get {
+ Type p = ProxyFor;
+ return p != null && p.IsMap;
+ } }
+ public override MapType! AsMap { get {
+ Type p = ProxyFor;
+ assume p != null;
+ return p.AsMap;
+ } }
+ public override int MapArity { get {
+ Type p = ProxyFor;
+ assume p != null;
+ return p.MapArity;
+ } }
+ public override bool IsUnresolved { get {
+ Type p = ProxyFor;
+ return p != null && p.IsUnresolved;
+ } }
+ public override UnresolvedTypeIdentifier! AsUnresolved { get {
+ Type p = ProxyFor;
+ assume p != null;
+ return p.AsUnresolved;
+ } }
+
+ public override bool IsBv { get {
+ Type p = ProxyFor;
+ return p != null && p.IsBv;
+ } }
+ public override int BvBits { get {
+ Type p = ProxyFor;
+ assume p != null;
+ return p.BvBits;
+ } }
+
+ public override Absy! StdDispatch(StandardVisitor! visitor)
+ {
+ return visitor.VisitTypeProxy(this);
+ }
+ }
+
+ public abstract class ConstrainedProxy : TypeProxy {
+ protected ConstrainedProxy(IToken! token, string! givenName, string! kind) {
+ base(token, givenName, kind);
+ }
+ }
+
+ /// <summary>
+ /// Each instance of this class represents a set of bitvector types. In particular, it represents
+ /// a bitvector type bvN iff
+ /// minBits ATMOST N and
+ /// foreach constraint (t0,t1), the types represented by t0 and t1 are bitvector types whose
+ /// number of bits add up to N.
+ /// This means that the size of a BvTypeProxy p is constrained not only by p.minBits, but also
+ /// by the size of various t0 and t1 types that are transitively part of BvTypeProxy constraints.
+ /// If such a t0 or t1 were to get its ProxyFor field defined, then p would have to be further
+ /// constrained too. This doesn't seem like it would ever occur in a Boogie 2 program, because:
+ /// the only place where a BvTypeProxy with constraints can occur is as the type of a
+ /// BvConcatExpr, and
+ /// the types of all local variables are explicitly declared, which means that the types of
+ /// subexpressions of a BvConcatExpr are not going to change other than via the type of the
+ /// BvConcatExpr.
+ /// So, this implementation of BvTypeProxy does not keep track of where a BvTypeProxy may occur
+ /// transitively in some other BvTypeProxy's constraints.
+ /// </summary>
+ public class BvTypeProxy : ConstrainedProxy {
+ public int MinBits;
+ List<BvTypeConstraint!> constraints;
+ class BvTypeConstraint {
+ public Type! T0;
+ public Type! T1;
+ public BvTypeConstraint(Type! t0, Type! t1)
+ requires t0.IsBv && t1.IsBv;
+ {
+ T0 = t0;
+ T1 = t1;
+ }
+ }
+
+ public BvTypeProxy(IToken! token, string! name, int minBits)
+ {
+ base(token, name, "bv" + minBits + "proxy");
+ this.MinBits = minBits;
+ }
+
+ /// <summary>
+ /// Requires that any further constraints to be placed on t0 and t1 go via the object to
+ /// be constructed.
+ /// </summary>
+ public BvTypeProxy(IToken! token, string! name, Type! t0, Type! t1)
+ requires t0.IsBv && t1.IsBv;
+ {
+ base(token, name, "bvproxy");
+ t0 = FollowProxy(t0);
+ t1 = FollowProxy(t1);
+ this.MinBits = MinBitsFor(t0) + MinBitsFor(t1);
+ List<BvTypeConstraint!> list = new List<BvTypeConstraint!>();
+ list.Add(new BvTypeConstraint(t0, t1));
+ this.constraints = list;
+ }
+
+ /// <summary>
+ /// Construct a BvTypeProxy like p, but with minBits.
+ /// </summary>
+ private BvTypeProxy(BvTypeProxy! p, int minBits)
+ {
+ base(p.tok, p.Name, "");
+ this.MinBits = minBits;
+ this.constraints = p.constraints;
+ }
+
+ private BvTypeProxy(IToken! token, string! name, int minBits, List<BvTypeConstraint!> constraints) {
+ base(token, name, "");
+ this.MinBits = minBits;
+ this.constraints = constraints;
+ }
+
+ [Pure][Reads(ReadsAttribute.Reads.Everything)]
+ private static int MinBitsFor(Type! t)
+ requires t.IsBv;
+ ensures 0 <= result;
+ {
+ if (t is BvType) {
+ return t.BvBits;
+ } else {
+ return ((BvTypeProxy)t).MinBits;
+ }
+ }
+
+ //----------- Cloning ----------------------------------
+
+ public override Type! Clone(IDictionary<TypeVariable!, TypeVariable!>! varMap) {
+ Type p = ProxyFor;
+ if (p != null) {
+ return p.Clone(varMap);
+ } else {
+ return new BvTypeProxy(this.tok, this.Name, this.MinBits, this.constraints); // the clone will have a name that ends with $bvproxy<n>$bvproxy<m>
+ }
+ }
+
+ public override Type! CloneUnresolved() {
+ return new BvTypeProxy(this.tok, this.Name, this.MinBits, this.constraints); // the clone will have a name that ends with $bvproxy<n>$bvproxy<m>
+ }
+
+ //----------- Unification of types -----------
+
+ public override bool Unify(Type! that,
+ TypeVariableSeq! unifiableVariables,
+ IDictionary<TypeVariable!, Type!>! result) {
+ Type p = ProxyFor;
+ if (p != null) {
+ return p.Unify(that, unifiableVariables, result);
+ }
+
+ // unify this with that, if possible
+ that = that.Expanded;
+ that = FollowProxy(that);
+
+ if (this.ReallyOccursIn(that))
+ return false;
+
+ TypeVariable tv = that as TypeVariable;
+
+ if (tv != null && unifiableVariables.Has(tv))
+ return that.Unify(this, unifiableVariables, result);
+
+ if (object.ReferenceEquals(this, that)) {
+ return true;
+ } else if (that is BvType) {
+ if (MinBits <= that.BvBits) {
+ if (constraints != null) {
+ foreach (BvTypeConstraint btc in constraints) {
+ int minT1 = MinBitsFor(btc.T1);
+ int left = IncreaseBits(btc.T0, that.BvBits - minT1);
+ left = IncreaseBits(btc.T1, minT1 + left);
+ assert left == 0; // because it should always be possible to increase the total size of a BvTypeConstraint pair (t0,t1) arbitrarily
+ }
+ }
+ DefineProxy(that);
+ return true;
+ }
+ } else if (that is BvTypeProxy) {
+ BvTypeProxy bt = (BvTypeProxy)that;
+ // keep the proxy with the stronger constraint (that is, the higher minBits), but if either
+ // has a constraints list, then concatenate both constraints lists and define the previous
+ // proxies to the new one
+ if (this.constraints != null || bt.constraints != null) {
+ List<BvTypeConstraint!> list = new List<BvTypeConstraint!>();
+ if (this.constraints != null) { list.AddRange(this.constraints); }
+ if (bt.constraints != null) { list.AddRange(bt.constraints); }
+ BvTypeProxy np = new BvTypeProxy(this.tok, this.Name, max{this.MinBits, bt.MinBits}, list);
+ this.DefineProxy(np);
+ bt.DefineProxy(np);
+ } else if (this.MinBits <= bt.MinBits) {
+ this.DefineProxy(bt);
+ } else {
+ bt.DefineProxy(this);
+ }
+ return true;
+ } else if (that is ConstrainedProxy) {
+ // only bitvector proxies can be unified with this BvTypeProxy
+ return false;
+ } else if (that is TypeProxy) {
+ // define: that.ProxyFor := this;
+ return that.Unify(this, unifiableVariables, result);
+ }
+ return false;
+ }
+
+ private static int IncreaseBits(Type! t, int to)
+ requires t.IsBv && 0 <= to && MinBitsFor(t) <= to;
+ ensures 0 <= result && result <= to;
+ {
+ t = FollowProxy(t);
+ if (t is BvType) {
+ return to - t.BvBits;
+ } else {
+ BvTypeProxy p = (BvTypeProxy)t;
+ assert p.MinBits <= to;
+ if (p.MinBits < to) {
+ BvTypeProxy q = new BvTypeProxy(p, to);
+ p.DefineProxy(q);
+ }
+ return 0; // we were able to satisfy the request completely
+ }
+ }
+
+ //----------- Substitution of free variables with types not containing bound variables -----------------
+
+ public override Type! Substitute(IDictionary<TypeVariable!, Type!>! subst) {
+ if (this.ProxyFor == null) {
+ // check that the constraints are clean and do not contain any
+ // of the substituted variables (otherwise, we are in big trouble)
+ assert forall{BvTypeConstraint! c in constraints;
+ forall{TypeVariable! var in subst.Keys;
+ !c.T0.FreeVariables.Has(var) && !c.T1.FreeVariables.Has(var)}};
+ }
+ return base.Substitute(subst);
+ }
+
+ //----------- Getters/Issers ----------------------------------
+
+ public override bool IsBv { get {
+ return true;
+ } }
+ public override int BvBits { get {
+ // This method is supposed to return the number of bits supplied, but unless the proxy has been resolved,
+ // we only have a lower bound on the number of bits supplied. But this method is not supposed to be
+ // called until type checking has finished, at which time the minBits is stable.
+ Type p = ProxyFor;
+ if (p != null) {
+ return p.BvBits;
+ } else {
+ return MinBits;
+ }
+ } }
+
+ public override Absy! StdDispatch(StandardVisitor! visitor)
+ {
+ return visitor.VisitBvTypeProxy(this);
+ }
+ }
+
+ // Proxy representing map types with a certain arity. Apart from the arity,
+ // a number of constraints on the index and value type of the map type may
+ // be known (such constraints result from applied select and store operations).
+ // Because map type can be polymorphic (in the most general case, each index or
+ // value type is described by a separate type parameter) any combination of
+ // constraints can be satisfied.
+ public class MapTypeProxy : ConstrainedProxy {
+ public readonly int Arity;
+ private readonly List<Constraint>! constraints = new List<Constraint> ();
+
+ // each constraint specifies that the given combination of argument/result
+ // types must be a possible instance of the formal map argument/result types
+ private struct Constraint {
+ public readonly TypeSeq! Arguments;
+ public readonly Type! Result;
+
+ public Constraint(TypeSeq! arguments, Type! result) {
+ Arguments = arguments;
+ Result = result;
+ }
+
+ public Constraint Clone(IDictionary<TypeVariable!, TypeVariable!>! varMap) {
+ TypeSeq! args = new TypeSeq ();
+ foreach (Type! t in Arguments)
+ args.Add(t.Clone(varMap));
+ Type! res = Result.Clone(varMap);
+ return new Constraint(args, res);
+ }
+
+ public bool Unify(MapType! that,
+ TypeVariableSeq! unifiableVariables,
+ IDictionary<TypeVariable!, Type!>! result)
+ requires Arguments.Length == that.Arguments.Length; {
+ Dictionary<TypeVariable!, Type!>! subst = new Dictionary<TypeVariable!, Type!>();
+ foreach (TypeVariable! tv in that.TypeParameters) {
+ TypeProxy proxy = new TypeProxy(Token.NoToken, tv.Name);
+ subst.Add(tv, proxy);
+ }
+
+ bool good = true;
+ for (int i = 0; i < that.Arguments.Length; i++) {
+ Type t0 = that.Arguments[i].Substitute(subst);
+ Type t1 = this.Arguments[i];
+ good &= t0.Unify(t1, unifiableVariables, result);
+ }
+ good &= that.Result.Substitute(subst).Unify(this.Result, unifiableVariables, result);
+ return good;
+ }
+ }
+
+ public MapTypeProxy(IToken! token, string! name, int arity)
+ requires 0 <= arity; {
+ base(token, name, "mapproxy");
+ this.Arity = arity;
+ }
+
+ private void AddConstraint(Constraint c)
+ requires c.Arguments.Length == Arity; {
+
+ Type f = ProxyFor;
+ MapType mf = f as MapType;
+ if (mf != null) {
+ bool success = c.Unify(mf, new TypeVariableSeq(), new Dictionary<TypeVariable!, Type!> ());
+ assert success;
+ return;
+ }
+
+ MapTypeProxy mpf = f as MapTypeProxy;
+ if (mpf != null) {
+ mpf.AddConstraint(c);
+ return;
+ }
+
+ assert f == null; // no other types should occur as specialisations of this proxy
+
+ constraints.Add(c);
+ }
+
+ public Type CheckArgumentTypes(ExprSeq! actualArgs,
+ out TypeParamInstantiation! tpInstantiation,
+ IToken! typeCheckingSubject,
+ string! opName,
+ TypecheckingContext! tc)
+ {
+ Type f = ProxyFor;
+ MapType mf = f as MapType;
+ if (mf != null)
+ return mf.CheckArgumentTypes(actualArgs, out tpInstantiation, typeCheckingSubject, opName, tc);
+
+ MapTypeProxy mpf = f as MapTypeProxy;
+ if (mpf != null)
+ return mpf.CheckArgumentTypes(actualArgs, out tpInstantiation, typeCheckingSubject, opName, tc);
+
+ assert f == null; // no other types should occur as specialisations of this proxy
+
+ // otherwise, we just record the constraints given by this usage of the map type
+ TypeSeq! arguments = new TypeSeq ();
+ foreach (Expr! e in actualArgs)
+ arguments.Add(e.Type);
+ Type! result = new TypeProxy (tok, "result");
+ AddConstraint(new Constraint (arguments, result));
+
+ TypeSeq! argumentsResult = new TypeSeq ();
+ foreach (Expr! e in actualArgs)
+ argumentsResult.Add(e.Type);
+ argumentsResult.Add(result);
+
+ tpInstantiation = new MapTypeProxyParamInstantiation(this, argumentsResult);
+ return result;
+ }
+
+ //----------- Cloning ----------------------------------
+
+ public override Type! Clone(IDictionary<TypeVariable!, TypeVariable!>! varMap) {
+ Type p = ProxyFor;
+ if (p != null) {
+ return p.Clone(varMap);
+ } else {
+ MapTypeProxy p2 = new MapTypeProxy(tok, Name, Arity);
+ foreach (Constraint c in constraints)
+ p2.AddConstraint(c.Clone(varMap));
+ return p2; // the clone will have a name that ends with $mapproxy<n>$mapproxy<m> (hopefully)
+ }
+ }
+
+ //----------- Linearisation ----------------------------------
+
+ public override void Emit(TokenTextWriter! stream, int contextBindingStrength)
+ {
+ Type p = ProxyFor;
+ if (p != null) {
+ p.Emit(stream, contextBindingStrength);
+ } else {
+ stream.Write("[");
+ string! sep = "";
+ for (int i = 0; i < Arity; ++i) {
+ stream.Write(sep);
+ sep = ", ";
+ stream.Write("?");
+ }
+ stream.Write("]?");
+ }
+ }
+
+ //----------- Unification of types -----------
+
+ public override bool Unify(Type! that,
+ TypeVariableSeq! unifiableVariables,
+ IDictionary<TypeVariable!, Type!>! result) {
+ Type p = ProxyFor;
+ if (p != null) {
+ return p.Unify(that, unifiableVariables, result);
+ }
+
+ // unify this with that, if possible
+ that = that.Expanded;
+ that = FollowProxy(that);
+
+ if (this.ReallyOccursIn(that))
+ return false;
+
+ TypeVariable tv = that as TypeVariable;
+
+ if (tv != null && unifiableVariables.Has(tv))
+ return that.Unify(this, unifiableVariables, result);
+
+ if (object.ReferenceEquals(this, that)) {
+ return true;
+ } else if (that is MapType) {
+ MapType mapType = (MapType)that;
+ if (mapType.Arguments.Length == Arity) {
+ bool good = true;
+ foreach (Constraint c in constraints)
+ good &= c.Unify(mapType, unifiableVariables, result);
+ if (good) {
+ DefineProxy(mapType);
+ return true;
+ }
+ }
+ } else if (that is MapTypeProxy) {
+ MapTypeProxy mt = (MapTypeProxy)that;
+ if (mt.Arity == this.Arity) {
+ // we propagate the constraints of this proxy to the more specific one
+ foreach (Constraint c in constraints)
+ mt.AddConstraint(c);
+ DefineProxy(mt);
+ return true;
+ }
+ } else if (that is ConstrainedProxy) {
+ // only map-type proxies can be unified with this MapTypeProxy
+ return false;
+ } else if (that is TypeProxy) {
+ // define: that.ProxyFor := this;
+ return that.Unify(this, unifiableVariables, result);
+ }
+ return false;
+ }
+
+ //----------- Substitution of free variables with types not containing bound variables -----------------
+
+ public override Type! Substitute(IDictionary<TypeVariable!, Type!>! subst) {
+ if (this.ProxyFor == null) {
+ // check that the constraints are clean and do not contain any
+ // of the substituted variables (otherwise, we are in big trouble)
+ assert forall{Constraint c in constraints;
+ forall{TypeVariable! var in subst.Keys;
+ forall{Type! t in c.Arguments; !t.FreeVariables.Has(var)} &&
+ !c.Result.FreeVariables.Has(var)}};
+ }
+ return base.Substitute(subst);
+ }
+
+ //----------- Getters/Issers ----------------------------------
+
+ public override bool IsMap { get { return true; } }
+ public override MapType! AsMap { get {
+ Type p = ProxyFor;
+ if (p != null) {
+ return p.AsMap;
+ } else {
+ assert false; // what to do now?
+ }
+ } }
+ public override int MapArity { get {
+ return Arity;
+ } }
+
+ public override Absy! StdDispatch(StandardVisitor! visitor)
+ {
+ return visitor.VisitMapTypeProxy(this);
+ }
+ }
+
+ //=====================================================================
+
+ // Used to annotate types with type synoyms that were used in the
+ // original unresolved types. Such types should be considered as
+ // equivalent to ExpandedType, the annotations are only used to enable
+ // better pretty-printing
+ public class TypeSynonymAnnotation : Type {
+ public Type! ExpandedType;
+
+ public readonly TypeSeq! Arguments;
+ // is set during resolution and determines whether the right number of arguments is given
+ public readonly TypeSynonymDecl! Decl;
+
+ public TypeSynonymAnnotation(IToken! token, TypeSynonymDecl! decl, TypeSeq! arguments)
+ : base(token)
+ requires arguments.Length == decl.TypeParameters.Length;
+ {
+ this.Decl = decl;
+ this.Arguments = arguments;
+
+ // build a substitution that can be applied to the definition of
+ // the type synonym
+ IDictionary<TypeVariable!, Type!>! subst =
+ new Dictionary<TypeVariable!, Type!> ();
+ for (int i = 0; i < arguments.Length; ++i)
+ subst.Add(decl.TypeParameters[i], arguments[i]);
+
+ ExpandedType = decl.Body.Substitute(subst);
+ }
+
+ private TypeSynonymAnnotation(IToken! token, TypeSynonymDecl! decl, TypeSeq! arguments,
+ Type! expandedType)
+ : base(token) {
+ this.Decl = decl;
+ this.Arguments = arguments;
+ this.ExpandedType = expandedType;
+ }
+
+ //----------- Cloning ----------------------------------
+ // We implement our own clone-method, because bound type variables
+ // have to be created in the right way. It is /not/ ok to just clone
+ // everything recursively
+
+ public override Type! Clone(IDictionary<TypeVariable!, TypeVariable!>! varMap) {
+ TypeSeq! newArgs = new TypeSeq ();
+ foreach(Type! t in Arguments)
+ newArgs.Add(t.Clone(varMap));
+ Type! newExpandedType = ExpandedType.Clone(varMap);
+ return new TypeSynonymAnnotation(tok, Decl, newArgs, newExpandedType);
+ }
+
+ public override Type! CloneUnresolved() {
+ TypeSeq! newArgs = new TypeSeq ();
+ foreach(Type! t in Arguments)
+ newArgs.Add(t.CloneUnresolved());
+ return new TypeSynonymAnnotation(tok, Decl, newArgs);
+ }
+
+ //----------- Equality ----------------------------------
+
+ [Pure]
+ public override bool Equals(Type! that,
+ TypeVariableSeq! thisBoundVariables,
+ TypeVariableSeq! thatBoundVariables) {
+ return ExpandedType.Equals(that, thisBoundVariables, thatBoundVariables);
+ }
+
+ // used to skip leading type annotations
+ internal override Type! Expanded { get {
+ return ExpandedType.Expanded;
+ } }
+
+ //----------- Unification of types -----------
+
+ public override bool Unify(Type! that,
+ TypeVariableSeq! unifiableVariables,
+ IDictionary<TypeVariable!, Type!>! result) {
+ return ExpandedType.Unify(that, unifiableVariables, result);
+ }
+
+#if OLD_UNIFICATION
+ public override void Unify(Type! that,
+ TypeVariableSeq! unifiableVariables,
+ TypeVariableSeq! thisBoundVariables,
+ TypeVariableSeq! thatBoundVariables,
+ IDictionary<TypeVariable!, Type!>! result) {
+ ExpandedType.Unify(that, unifiableVariables,
+ thisBoundVariables, thatBoundVariables, result);
+ }
+#endif
+
+ //----------- Substitution of free variables with types not containing bound variables -----------------
+
+ public override Type! Substitute(IDictionary<TypeVariable!, Type!>! subst) {
+ if (subst.Count == 0)
+ return this;
+ TypeSeq newArgs = new TypeSeq ();
+ foreach (Type! t in Arguments)
+ newArgs.Add(t.Substitute(subst));
+ Type! newExpandedType = ExpandedType.Substitute(subst);
+ return new TypeSynonymAnnotation(tok, Decl, newArgs, newExpandedType);
+ }
+
+ //----------- Hashcodes ----------------------------------
+
+ [Pure]
+ public override int GetHashCode(TypeVariableSeq! boundVariables) {
+ return ExpandedType.GetHashCode(boundVariables);
+ }
+
+ //----------- Linearisation ----------------------------------
+
+ public override void Emit(TokenTextWriter! stream, int contextBindingStrength)
+ {
+ stream.SetToken(this);
+ CtorType.EmitCtorType(this.Decl.Name, Arguments, stream, contextBindingStrength);
+ }
+
+ //----------- Resolution ----------------------------------
+
+ public override Type! ResolveType(ResolutionContext! rc) {
+ TypeSeq resolvedArgs = new TypeSeq ();
+ foreach (Type! t in Arguments)
+ resolvedArgs.Add(t.ResolveType(rc));
+ return new TypeSynonymAnnotation(tok, Decl, resolvedArgs);
+ }
+
+ public override TypeVariableSeq! FreeVariables { get {
+ return ExpandedType.FreeVariables;
+ } }
+
+ public override List<TypeProxy!>! FreeProxies { get {
+ return ExpandedType.FreeProxies;
+ } }
+
+ //----------- Getters/Issers ----------------------------------
+
+ public override bool IsBasic { get { return ExpandedType.IsBasic; } }
+ public override bool IsInt { get { return ExpandedType.IsInt; } }
+ public override bool IsBool { get { return ExpandedType.IsBool; } }
+
+ public override bool IsVariable { get { return ExpandedType.IsVariable; } }
+ public override TypeVariable! AsVariable { get { return ExpandedType.AsVariable; } }
+ public override bool IsCtor { get { return ExpandedType.IsCtor; } }
+ public override CtorType! AsCtor { get { return ExpandedType.AsCtor; } }
+ public override bool IsMap { get { return ExpandedType.IsMap; } }
+ public override MapType! AsMap { get { return ExpandedType.AsMap; } }
+ public override bool IsUnresolved { get { return ExpandedType.IsUnresolved; } }
+ public override UnresolvedTypeIdentifier! AsUnresolved { get {
+ return ExpandedType.AsUnresolved; } }
+
+ public override bool IsBv { get { return ExpandedType.IsBv; } }
+ public override int BvBits { get { return ExpandedType.BvBits; } }
+
+ public override Absy! StdDispatch(StandardVisitor! visitor)
+ {
+ return visitor.VisitTypeSynonymAnnotation(this);
+ }
+ }
+
+ //=====================================================================
+
+ public class CtorType : Type {
+ public readonly TypeSeq! Arguments;
+ // is set during resolution and determines whether the right number of arguments is given
+ public readonly TypeCtorDecl! Decl;
+
+ public CtorType(IToken! token, TypeCtorDecl! decl, TypeSeq! arguments)
+ : base(token)
+ requires arguments.Length == decl.Arity;
+ {
+ this.Decl = decl;
+ this.Arguments = arguments;
+ }
+
+ //----------- Cloning ----------------------------------
+ // We implement our own clone-method, because bound type variables
+ // have to be created in the right way. It is /not/ ok to just clone
+ // everything recursively
+
+ public override Type! Clone(IDictionary<TypeVariable!, TypeVariable!>! varMap) {
+ TypeSeq! newArgs = new TypeSeq ();
+ foreach(Type! t in Arguments)
+ newArgs.Add(t.Clone(varMap));
+ return new CtorType(tok, Decl, newArgs);
+ }
+
+ public override Type! CloneUnresolved() {
+ TypeSeq! newArgs = new TypeSeq ();
+ foreach(Type! t in Arguments)
+ newArgs.Add(t.CloneUnresolved());
+ return new CtorType(tok, Decl, newArgs);
+ }
+
+ //----------- Equality ----------------------------------
+
+ [Pure][Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals(object that) {
+ Type thatType = that as Type;
+ if (thatType == null)
+ return false;
+ thatType = TypeProxy.FollowProxy(thatType.Expanded);
+ // shortcut
+ CtorType thatCtorType = thatType as CtorType;
+ if (thatCtorType == null || !this.Decl.Equals(thatCtorType.Decl))
+ return false;
+ if (Arguments.Length == 0)
+ return true;
+ return base.Equals(thatType);
+ }
+
+ [Pure]
+ public override bool Equals(Type! that,
+ TypeVariableSeq! thisBoundVariables,
+ TypeVariableSeq! thatBoundVariables) {
+ that = TypeProxy.FollowProxy(that.Expanded);
+ CtorType thatCtorType = that as CtorType;
+ if (thatCtorType == null || !this.Decl.Equals(thatCtorType.Decl))
+ return false;
+ for (int i = 0; i < Arguments.Length; ++i) {
+ if (!Arguments[i].Equals(thatCtorType.Arguments[i],
+ thisBoundVariables, thatBoundVariables))
+ return false;
+ }
+ return true;
+ }
+
+ //----------- Unification of types -----------
+
+ public override bool Unify(Type! that,
+ TypeVariableSeq! unifiableVariables,
+ IDictionary<TypeVariable!, Type!>! result) {
+ that = that.Expanded;
+ if (that is TypeProxy || that is TypeVariable)
+ return that.Unify(this, unifiableVariables, result);
+
+ CtorType thatCtorType = that as CtorType;
+ if (thatCtorType == null || !thatCtorType.Decl.Equals(Decl)) {
+ return false;
+ } else {
+ bool good = true;
+ for (int i = 0; i < Arguments.Length; ++i)
+ good &= Arguments[i].Unify(thatCtorType.Arguments[i], unifiableVariables, result);
+ return good;
+ }
+ }
+
+#if OLD_UNIFICATION
+ public override void Unify(Type! that,
+ TypeVariableSeq! unifiableVariables,
+ TypeVariableSeq! thisBoundVariables,
+ TypeVariableSeq! thatBoundVariables,
+ IDictionary<TypeVariable!, Type!>! result) {
+ that = that.Expanded;
+ if (that is TypeVariable) {
+ that.Unify(this, unifiableVariables, thatBoundVariables, thisBoundVariables, result);
+ return;
+ }
+
+ CtorType thatCtorType = that as CtorType;
+ if (thatCtorType == null || !thatCtorType.Decl.Equals(Decl))
+ throw UNIFICATION_FAILED;
+ for (int i = 0; i < Arguments.Length; ++i)
+ Arguments[i].Unify(thatCtorType.Arguments[i],
+ unifiableVariables,
+ thisBoundVariables, thatBoundVariables,
+ result);
+ }
+#endif
+
+ //----------- Substitution of free variables with types not containing bound variables -----------------
+
+ public override Type! Substitute(IDictionary<TypeVariable!, Type!>! subst) {
+ if (subst.Count == 0)
+ return this;
+ TypeSeq newArgs = new TypeSeq ();
+ foreach (Type! t in Arguments)
+ newArgs.Add(t.Substitute(subst));
+ return new CtorType(tok, Decl, newArgs);
+ }
+
+ //----------- Hashcodes ----------------------------------
+
+ [Pure]
+ public override int GetHashCode(TypeVariableSeq! boundVariables) {
+ int res = 1637643879 * Decl.GetHashCode();
+ foreach (Type! t in Arguments)
+ res = res * 3 + t.GetHashCode(boundVariables);
+ return res;
+ }
+
+ //----------- Linearisation ----------------------------------
+
+ public override void Emit(TokenTextWriter! stream, int contextBindingStrength)
+ {
+ stream.SetToken(this);
+ EmitCtorType(this.Decl.Name, Arguments, stream, contextBindingStrength);
+ }
+
+ internal static void EmitCtorType(string! name, TypeSeq! args, TokenTextWriter! stream, int contextBindingStrength) {
+ int opBindingStrength = args.Length > 0 ? 0 : 2;
+ if (opBindingStrength < contextBindingStrength)
+ stream.Write("(");
+
+ stream.Write("{0}", TokenTextWriter.SanitizeIdentifier(name));
+ int i = args.Length;
+ foreach (Type! t in args) {
+ stream.Write(" ");
+ // use a lower binding strength for the last argument
+ // to allow map-types without parentheses
+ t.Emit(stream, i == 1 ? 1 : 2);
+ i = i - 1;
+ }
+
+ if (opBindingStrength < contextBindingStrength)
+ stream.Write(")");
+ }
+
+ //----------- Resolution ----------------------------------
+
+ public override Type! ResolveType(ResolutionContext! rc) {
+ TypeSeq resolvedArgs = new TypeSeq ();
+ foreach (Type! t in Arguments)
+ resolvedArgs.Add(t.ResolveType(rc));
+ return new CtorType(tok, Decl, resolvedArgs);
+ }
+
+ public override TypeVariableSeq! FreeVariables {
+ get {
+ TypeVariableSeq! res = new TypeVariableSeq ();
+ foreach (Type! t in Arguments)
+ res.AppendWithoutDups(t.FreeVariables);
+ return res;
+ }
+ }
+
+ public override List<TypeProxy!>! FreeProxies { get {
+ List<TypeProxy!>! res = new List<TypeProxy!> ();
+ foreach (Type! t in Arguments)
+ AppendWithoutDups(res, t.FreeProxies);
+ return res;
+ } }
+
+ //----------- Getters/Issers ----------------------------------
+
+ public override bool IsCtor { get { return true; } }
+ public override CtorType! AsCtor { get { return this; } }
+
+ public override Absy! StdDispatch(StandardVisitor! visitor)
+ {
+ return visitor.VisitCtorType(this);
+ }
+ }
+
+ //=====================================================================
+
+ public class MapType : Type {
+ // an invariant is that each of the type parameters has to occur as
+ // free variable in at least one of the arguments
+ public readonly TypeVariableSeq! TypeParameters;
+ public readonly TypeSeq! Arguments;
+ public Type! Result;
+
+ public MapType(IToken! token, TypeVariableSeq! typeParameters, TypeSeq! arguments, Type! result)
+ : base(token)
+ {
+ this.TypeParameters = typeParameters;
+ this.Result = result;
+ this.Arguments = arguments;
+ }
+
+ //----------- Cloning ----------------------------------
+ // We implement our own clone-method, because bound type variables
+ // have to be created in the right way. It is /not/ ok to just clone
+ // everything recursively
+
+ public override Type! Clone(IDictionary<TypeVariable!, TypeVariable!>! varMap) {
+ IDictionary<TypeVariable!, TypeVariable!>! newVarMap =
+ new Dictionary<TypeVariable!, TypeVariable!>();
+ foreach (KeyValuePair<TypeVariable!, TypeVariable!> p in varMap) {
+ if (!TypeParameters.Has(p.Key))
+ newVarMap.Add(p);
+ }
+
+ TypeVariableSeq! newTypeParams = new TypeVariableSeq ();
+ foreach (TypeVariable! var in TypeParameters) {
+ TypeVariable! newVar = new TypeVariable (var.tok, var.Name);
+ newVarMap.Add(var, newVar);
+ newTypeParams.Add(newVar);
+ }
+
+ TypeSeq! newArgs = new TypeSeq ();
+ foreach(Type! t in Arguments)
+ newArgs.Add(t.Clone(newVarMap));
+ Type! newResult = Result.Clone(newVarMap);
+
+ return new MapType (this.tok, newTypeParams, newArgs, newResult);
+ }
+
+ public override Type! CloneUnresolved() {
+ TypeVariableSeq! newTypeParams = new TypeVariableSeq ();
+ foreach (TypeVariable! var in TypeParameters) {
+ TypeVariable! newVar = new TypeVariable (var.tok, var.Name);
+ newTypeParams.Add(newVar);
+ }
+
+ TypeSeq! newArgs = new TypeSeq ();
+ foreach(Type! t in Arguments)
+ newArgs.Add(t.CloneUnresolved());
+ Type! newResult = Result.CloneUnresolved();
+
+ return new MapType (this.tok, newTypeParams, newArgs, newResult);
+ }
+
+ //----------- Equality ----------------------------------
+
+ [Pure]
+ public override bool Equals(Type! that,
+ TypeVariableSeq! thisBoundVariables,
+ TypeVariableSeq! thatBoundVariables) {
+ that = TypeProxy.FollowProxy(that.Expanded);
+ MapType thatMapType = that as MapType;
+ if (thatMapType == null ||
+ this.TypeParameters.Length != thatMapType.TypeParameters.Length ||
+ this.Arguments.Length != thatMapType.Arguments.Length)
+ return false;
+
+ foreach (TypeVariable! var in this.TypeParameters)
+ thisBoundVariables.Add(var);
+ foreach (TypeVariable! var in thatMapType.TypeParameters)
+ thatBoundVariables.Add(var);
+
+ try {
+
+ for (int i = 0; i < Arguments.Length; ++i) {
+ if (!Arguments[i].Equals(thatMapType.Arguments[i],
+ thisBoundVariables, thatBoundVariables))
+ return false;
+ }
+ if (!this.Result.Equals(thatMapType.Result,
+ thisBoundVariables, thatBoundVariables))
+ return false;
+
+ } finally {
+ // make sure that the bound variables are removed again
+ for (int i = 0; i < this.TypeParameters.Length; ++i) {
+ thisBoundVariables.Remove();
+ thatBoundVariables.Remove();
+ }
+ }
+
+ return true;
+ }
+
+ //----------- Unification of types -----------
+
+ public override bool Unify(Type! that,
+ TypeVariableSeq! unifiableVariables,
+ IDictionary<TypeVariable!, Type!>! result) {
+ that = that.Expanded;
+ if (that is TypeProxy || that is TypeVariable)
+ return that.Unify(this, unifiableVariables, result);
+
+ MapType thatMapType = that as MapType;
+ if (thatMapType == null ||
+ this.TypeParameters.Length != thatMapType.TypeParameters.Length ||
+ this.Arguments.Length != thatMapType.Arguments.Length)
+ return false;
+
+ // treat the bound variables of the two map types as equal...
+ Dictionary<TypeVariable!, Type!>! subst0 = new Dictionary<TypeVariable!, Type!>();
+ Dictionary<TypeVariable!, Type!>! subst1 = new Dictionary<TypeVariable!, Type!>();
+ TypeVariableSeq freshies = new TypeVariableSeq();
+ for (int i = 0; i < this.TypeParameters.Length; i++) {
+ TypeVariable tp0 = this.TypeParameters[i];
+ TypeVariable tp1 = thatMapType.TypeParameters[i];
+ TypeVariable freshVar = new TypeVariable(tp0.tok, tp0.Name);
+ freshies.Add(freshVar);
+ subst0.Add(tp0, freshVar);
+ subst1.Add(tp1, freshVar);
+ }
+ // ... and then unify the domain and range types
+ bool good = true;
+ for (int i = 0; i < this.Arguments.Length; i++) {
+ Type t0 = this.Arguments[i].Substitute(subst0);
+ Type t1 = thatMapType.Arguments[i].Substitute(subst1);
+ good &= t0.Unify(t1, unifiableVariables, result);
+ }
+ Type r0 = this.Result.Substitute(subst0);
+ Type r1 = thatMapType.Result.Substitute(subst1);
+ good &= r0.Unify(r1, unifiableVariables, result);
+
+ // Finally, check that none of the bound variables has escaped
+ if (good && freshies.Length != 0) {
+ // This is done by looking for occurrences of the fresh variables in the
+ // non-substituted types ...
+ TypeVariableSeq freeVars = this.FreeVariables;
+ foreach (TypeVariable fr in freshies)
+ if (freeVars.Has(fr)) { return false; } // fresh variable escaped
+ freeVars = thatMapType.FreeVariables;
+ foreach (TypeVariable fr in freshies)
+ if (freeVars.Has(fr)) { return false; } // fresh variable escaped
+
+ // ... and in the resulting unifier of type variables
+ foreach (KeyValuePair<TypeVariable!, Type!> pair in result) {
+ freeVars = pair.Value.FreeVariables;
+ foreach (TypeVariable fr in freshies)
+ if (freeVars.Has(fr)) { return false; } // fresh variable escaped
+ }
+ }
+
+ return good;
+ }
+
+#if OLD_UNIFICATION
+ public override void Unify(Type! that,
+ TypeVariableSeq! unifiableVariables,
+ TypeVariableSeq! thisBoundVariables,
+ TypeVariableSeq! thatBoundVariables,
+ IDictionary<TypeVariable!, Type!>! result) {
+ that = that.Expanded;
+ if (that is TypeVariable) {
+ that.Unify(this, unifiableVariables, thatBoundVariables, thisBoundVariables, result);
+ return;
+ }
+
+ MapType thatMapType = that as MapType;
+ if (thatMapType == null ||
+ this.TypeParameters.Length != thatMapType.TypeParameters.Length ||
+ this.Arguments.Length != thatMapType.Arguments.Length)
+ throw UNIFICATION_FAILED;
+
+ // ensure that no collisions occur
+ if (this.collisionsPossible(result)) {
+ ((MapType)this.Clone())
+ .Unify(that, unifiableVariables,
+ thisBoundVariables, thatBoundVariables, result);
+ return;
+ }
+ if (thatMapType.collisionsPossible(result))
+ thatMapType = (MapType)that.Clone();
+
+ foreach (TypeVariable! var in this.TypeParameters)
+ thisBoundVariables.Add(var);
+ foreach (TypeVariable! var in thatMapType.TypeParameters)
+ thatBoundVariables.Add(var);
+
+ try {
+
+ for (int i = 0; i < Arguments.Length; ++i)
+ Arguments[i].Unify(thatMapType.Arguments[i],
+ unifiableVariables,
+ thisBoundVariables, thatBoundVariables,
+ result);
+ Result.Unify(thatMapType.Result,
+ unifiableVariables,
+ thisBoundVariables, thatBoundVariables,
+ result);
+
+ } finally {
+ // make sure that the bound variables are removed again
+ for (int i = 0; i < this.TypeParameters.Length; ++i) {
+ thisBoundVariables.Remove();
+ thatBoundVariables.Remove();
+ }
+ }
+ }
+#endif
+
+ //----------- Substitution of free variables with types not containing bound variables -----------------
+
+ [Pure]
+ private bool collisionsPossible(IDictionary<TypeVariable!, Type!>! subst) {
+ // PR: could be written more efficiently
+ return exists{TypeVariable! var in TypeParameters;
+ subst.ContainsKey(var) ||
+ exists{Type! t in subst.Values; t.FreeVariables.Has(var)}};
+ }
+
+ public override Type! Substitute(IDictionary<TypeVariable!, Type!>! subst) {
+ if (subst.Count == 0)
+ return this;
+
+ // there are two cases in which we have to be careful:
+ // * a variable to be substituted is shadowed by a variable binder
+ // * a substituted term contains variables that are bound in the
+ // type (variable capture)
+ //
+ // in both cases, we first clone the type to ensure that bound
+ // variables are fresh
+
+ if (collisionsPossible(subst)) {
+ MapType! newType = (MapType)this.Clone();
+ assert newType.Equals(this) && !newType.collisionsPossible(subst);
+ return newType.Substitute(subst);
+ }
+
+ TypeSeq newArgs = new TypeSeq ();
+ foreach (Type! t in Arguments)
+ newArgs.Add(t.Substitute(subst));
+ Type! newResult = Result.Substitute(subst);
+
+ return new MapType(tok, TypeParameters, newArgs, newResult);
+ }
+
+ //----------- Hashcodes ----------------------------------
+
+ [Pure]
+ public override int GetHashCode(TypeVariableSeq! boundVariables) {
+ int res = 7643761 * TypeParameters.Length + 65121 * Arguments.Length;
+
+ foreach (TypeVariable! var in this.TypeParameters)
+ boundVariables.Add(var);
+
+ foreach (Type! t in Arguments)
+ res = res * 5 + t.GetHashCode(boundVariables);
+ res = res * 7 + Result.GetHashCode(boundVariables);
+
+ for (int i = 0; i < this.TypeParameters.Length; ++i)
+ boundVariables.Remove();
+
+ return res;
+ }
+
+ //----------- Linearisation ----------------------------------
+
+ public override void Emit(TokenTextWriter! stream, int contextBindingStrength)
+ {
+ stream.SetToken(this);
+
+ const int opBindingStrength = 1;
+ if (opBindingStrength < contextBindingStrength)
+ stream.Write("(");
+
+ EmitOptionalTypeParams(stream, TypeParameters);
+
+ stream.Write("[");
+ Arguments.Emit(stream, ","); // default binding strength of 0 is ok
+ stream.Write("]");
+ Result.Emit(stream); // default binding strength of 0 is ok
+
+ if (opBindingStrength < contextBindingStrength)
+ stream.Write(")");
+ }
+
+ //----------- Resolution ----------------------------------
+
+ public override Type! ResolveType(ResolutionContext! rc) {
+ int previousState = rc.TypeBinderState;
+ try {
+ foreach (TypeVariable! v in TypeParameters) {
+ rc.AddTypeBinder(v);
+ }
+
+ TypeSeq resolvedArgs = new TypeSeq ();
+ foreach (Type! ty in Arguments) {
+ resolvedArgs.Add(ty.ResolveType(rc));
+ }
+
+ Type resolvedResult = Result.ResolveType(rc);
+
+ CheckBoundVariableOccurrences(TypeParameters,
+ resolvedArgs, new TypeSeq(resolvedResult),
+ this.tok, "map arguments",
+ rc);
+
+ // sort the type parameters so that they are bound in the order of occurrence
+ TypeVariableSeq! sortedTypeParams = SortTypeParams(TypeParameters, resolvedArgs, resolvedResult);
+ return new MapType(tok, sortedTypeParams, resolvedArgs, resolvedResult);
+ } finally {
+ rc.TypeBinderState = previousState;
+ }
+ }
+
+ public override TypeVariableSeq! FreeVariables {
+ get {
+ TypeVariableSeq! res = FreeVariablesIn(Arguments);
+ res.AppendWithoutDups(Result.FreeVariables);
+ foreach (TypeVariable! v in TypeParameters)
+ res.Remove(v);
+ return res;
+ }
+ }
+
+ public override List<TypeProxy!>! FreeProxies { get {
+ List<TypeProxy!>! res = new List<TypeProxy!> ();
+ foreach (Type! t in Arguments)
+ AppendWithoutDups(res, t.FreeProxies);
+ AppendWithoutDups(res, Result.FreeProxies);
+ return res;
+ } }
+
+ //----------- Getters/Issers ----------------------------------
+
+ public override bool IsMap { get { return true; } }
+ public override MapType! AsMap { get { return this; } }
+ public override int MapArity { get {
+ return Arguments.Length;
+ } }
+
+ //------------ Match formal argument types of the map
+ //------------ on concrete types, substitute the result into the
+ //------------ result type. Null is returned if so many type checking
+ //------------ errors occur that the situation is hopeless
+
+ public Type CheckArgumentTypes(ExprSeq! actualArgs,
+ out TypeParamInstantiation! tpInstantiation,
+ IToken! typeCheckingSubject,
+ string! opName,
+ TypecheckingContext! tc) {
+ List<Type!>! actualTypeParams;
+ TypeSeq actualResult =
+ Type.CheckArgumentTypes(TypeParameters, out actualTypeParams, Arguments, actualArgs,
+ new TypeSeq (Result), null, typeCheckingSubject, opName, tc);
+ if (actualResult == null) {
+ tpInstantiation = SimpleTypeParamInstantiation.EMPTY;
+ return null;
+ } else {
+ assert actualResult.Length == 1;
+ tpInstantiation = SimpleTypeParamInstantiation.From(TypeParameters, actualTypeParams);
+ return actualResult[0];
+ }
+ }
+
+ public override Absy! StdDispatch(StandardVisitor! visitor)
+ {
+ return visitor.VisitMapType(this);
+ }
+ }
+
+ //---------------------------------------------------------------------
+
+ public enum SimpleType { Int, Bool };
+
+
+ //=====================================================================
+
+ // Interface for representing the instantiations of type parameters of
+ // polymorphic functions or maps. We introduce an own interface for this
+ // instead of using a simple list or dictionary, because in some cases
+ // (due to the type proxies for map types) the actual number and instantiation
+ // of type parameters can only be determined very late.
+ public interface TypeParamInstantiation {
+ // return what formal type parameters there are
+ List<TypeVariable!>! FormalTypeParams { get; }
+ // given a formal type parameter, return the actual instantiation
+ Type! this[TypeVariable! var] { get; }
+ }
+
+ public class SimpleTypeParamInstantiation : TypeParamInstantiation {
+ private readonly List<TypeVariable!>! TypeParams;
+ private readonly IDictionary<TypeVariable!, Type!>! Instantiations;
+
+ public SimpleTypeParamInstantiation(List<TypeVariable!>! typeParams,
+ IDictionary<TypeVariable!, Type!>! instantiations) {
+ this.TypeParams = typeParams;
+ this.Instantiations = instantiations;
+ }
+
+ public static TypeParamInstantiation!
+ From(TypeVariableSeq! typeParams, List<Type!>! actualTypeParams)
+ requires typeParams.Length == actualTypeParams.Count; {
+ if (typeParams.Length == 0)
+ return EMPTY;
+
+ List<TypeVariable!>! typeParamList = new List<TypeVariable!> ();
+ IDictionary<TypeVariable!, Type!>! dict = new Dictionary<TypeVariable!, Type!> ();
+ for (int i = 0; i < typeParams.Length; ++i) {
+ typeParamList.Add(typeParams[i]);
+ dict.Add(typeParams[i], actualTypeParams[i]);
+ }
+ return new SimpleTypeParamInstantiation(typeParamList, dict);
+ }
+
+ public static readonly TypeParamInstantiation! EMPTY =
+ new SimpleTypeParamInstantiation (new List<TypeVariable!> (),
+ new Dictionary<TypeVariable!, Type!> ());
+
+ // return what formal type parameters there are
+ public List<TypeVariable!>! FormalTypeParams { get {
+ return TypeParams;
+ } }
+ // given a formal type parameter, return the actual instantiation
+ public Type! this[TypeVariable! var] { get {
+ return Instantiations[var];
+ } }
+ }
+
+ // Implementation of TypeParamInstantiation that refers to the current
+ // value of a MapTypeProxy. This means that the values return by the
+ // methods of this implementation can change in case the MapTypeProxy
+ // receives further unifications.
+ class MapTypeProxyParamInstantiation : TypeParamInstantiation {
+ private readonly MapTypeProxy! Proxy;
+
+ // the argument and result type of this particular usage of the map
+ // type. these are necessary to derive the values of the type parameters
+ private readonly TypeSeq! ArgumentsResult;
+
+ // field that is initialised once all necessary information is available
+ // (the MapTypeProxy is instantiated to an actual type) and the instantiation
+ // of a type parameter is queried
+ private IDictionary<TypeVariable!, Type!> Instantiations = null;
+
+ public MapTypeProxyParamInstantiation(MapTypeProxy! proxy,
+ TypeSeq! argumentsResult) {
+ this.Proxy = proxy;
+ this.ArgumentsResult = argumentsResult;
+ }
+
+ // return what formal type parameters there are
+ public List<TypeVariable!>! FormalTypeParams { get {
+ MapType realType = Proxy.ProxyFor as MapType;
+ if (realType == null)
+ // no instantiation of the map type is known, which means
+ // that the map type is assumed to be monomorphic
+ return new List<TypeVariable!> ();
+ else
+ return realType.TypeParameters.ToList();
+ } }
+
+ // given a formal type parameter, return the actual instantiation
+ public Type! this[TypeVariable! var] { get {
+ // then there has to be an instantiation that is a polymorphic map type
+ if (Instantiations == null) {
+ MapType realType = Proxy.ProxyFor as MapType;
+ assert realType != null;
+ TypeSeq! formalArgs = new TypeSeq ();
+ foreach (Type! t in realType.Arguments)
+ formalArgs.Add(t);
+ formalArgs.Add(realType.Result);
+ Instantiations =
+ Type.InferTypeParameters(realType.TypeParameters, formalArgs, ArgumentsResult);
+ }
+ return Instantiations[var];
+ } }
+ }
+
+}
diff --git a/Source/Core/BoogiePL.atg b/Source/Core/BoogiePL.atg
new file mode 100644
index 00000000..a690c1e2
--- /dev/null
+++ b/Source/Core/BoogiePL.atg
@@ -0,0 +1,1374 @@
+
+/*---------------------------------------------------------------------------
+// BoogiePL -
+//--------------------------------------------------------------------------*/
+
+/*using System;*/
+using PureCollections;
+using System.Collections;
+using System.Collections.Generic;
+using Microsoft.Boogie;
+using Microsoft.Basetypes;
+using Bpl = Microsoft.Boogie;
+using AI = Microsoft.AbstractInterpretationFramework;
+
+
+COMPILER BoogiePL
+
+/*--------------------------------------------------------------------------*/
+
+static Program! Pgm = new Program();
+
+static Expr! dummyExpr = new LiteralExpr(Token.NoToken, false);
+static Cmd! dummyCmd = new AssumeCmd(Token.NoToken, dummyExpr);
+static Block! dummyBlock = new Block(Token.NoToken, "dummyBlock", new CmdSeq(),
+ new ReturnCmd(Token.NoToken));
+static Bpl.Type! dummyType = new BasicType(Token.NoToken, SimpleType.Bool);
+static Bpl.ExprSeq! dummyExprSeq = new ExprSeq ();
+static TransferCmd! dummyTransferCmd = new ReturnCmd(Token.NoToken);
+static StructuredCmd! dummyStructuredCmd = new BreakCmd(Token.NoToken, null);
+
+///<summary>
+///Returns the number of parsing errors encountered. If 0, "program" returns as
+///the parsed program.
+///</summary>
+public static int Parse (string! filename, out /*maybe null*/ Program program) /* throws System.IO.IOException */ {
+ using (System.IO.StreamReader reader = new System.IO.StreamReader(filename)) {
+ Buffer.Fill(reader);
+ Scanner.Init(filename);
+ return Parse(out program);
+ }
+}
+
+///<summary>
+///Returns the number of parsing errors encountered. If 0, "program" returns as
+///the parsed program.
+///Note: first initialize the Scanner.
+///</summary>
+public static int Parse (out /*maybe null*/ Program program) {
+ Pgm = new Program(); // reset the global variable
+ Parse();
+ if (Errors.count == 0)
+ {
+ program = Pgm;
+ return 0;
+ }
+ else
+ {
+ program = null;
+ return Errors.count;
+ }
+}
+
+
+public static int ParseProposition (string! text, out Expr! expression)
+{
+ Buffer.Fill(text);
+ Scanner.Init(string.Format("\"{0}\"", text));
+
+ Errors.SynErr = new ErrorProc(SynErr);
+ t = new Token();
+ Get();
+ Proposition(out expression);
+ return Errors.count;
+}
+
+// Class to represent the bounds of a bitvector expression t[a:b].
+// Objects of this class only exist during parsing and are directly
+// turned into BvExtract before they get anywhere else
+private class BvBounds : Expr {
+ public BigNum Lower;
+ public BigNum Upper;
+ public BvBounds(IToken! tok, BigNum lower, BigNum upper) {
+ base(tok);
+ this.Lower = lower;
+ this.Upper = upper;
+ }
+ public override Type! ShallowType { get { return Bpl.Type.Int; } }
+ public override void Resolve(ResolutionContext! rc) {
+ rc.Error(this, "bitvector bounds in illegal position");
+ }
+ public override void Emit(TokenTextWriter! stream,
+ int contextBindingStrength, bool fragileContext) {
+ assert false;
+ }
+ public override void ComputeFreeVariables(Set! freeVars) { assert false; }
+ public override AI.IExpr! IExpr { get { assert false; } }
+}
+
+/*--------------------------------------------------------------------------*/
+CHARACTERS
+ letter = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".
+ digit = "0123456789".
+ special = "'~#$^_.?`".
+ glyph = "`~!@#$%^&*()-_=+[{]}|;:',<.>/?\\".
+
+ cr = '\r'.
+ lf = '\n'.
+ tab = '\t'.
+
+ space = ' '.
+ quote = '"'.
+
+ nondigit = letter + special.
+ nonquote = letter + digit + space + glyph.
+
+
+/*------------------------------------------------------------------------*/
+TOKENS
+ ident = [ '\\' ] nondigit {nondigit | digit}.
+ bvlit = digit {digit} 'b' 'v' digit {digit}.
+ digits = digit {digit}.
+ string = quote {nonquote} quote.
+ float = digit {digit} '.' {digit}.
+
+COMMENTS FROM "/*" TO "*/" NESTED
+COMMENTS FROM "//" TO lf
+
+IGNORE cr + lf + tab
+
+
+/*------------------------------------------------------------------------*/
+PRODUCTIONS
+
+
+/*------------------------------------------------------------------------*/
+BoogiePL
+= (. VariableSeq! vs;
+ DeclarationSeq! ds;
+ Axiom! ax;
+ List<Declaration!>! ts;
+ Procedure! pr;
+ Implementation im;
+ Implementation! nnim;
+ .)
+ { Consts<out vs> (. foreach (Bpl.Variable! v in vs) { Pgm.TopLevelDeclarations.Add(v); } .)
+ | Function<out ds> (. foreach (Bpl.Declaration! d in ds) { Pgm.TopLevelDeclarations.Add(d); } .)
+ | Axiom<out ax> (. Pgm.TopLevelDeclarations.Add(ax); .)
+ | UserDefinedTypes<out ts> (. foreach (Declaration! td in ts) {
+ Pgm.TopLevelDeclarations.Add(td);
+ } .)
+ | GlobalVars<out vs> (. foreach (Bpl.Variable! v in vs) { Pgm.TopLevelDeclarations.Add(v); } .)
+ | Procedure<out pr, out im> (. Pgm.TopLevelDeclarations.Add(pr);
+ if (im != null) {
+ Pgm.TopLevelDeclarations.Add(im);
+ }
+ .)
+ | Implementation<out nnim> (. Pgm.TopLevelDeclarations.Add(nnim); .)
+ }
+ EOF
+ .
+
+/*------------------------------------------------------------------------*/
+GlobalVars<out VariableSeq! ds>
+= (. TypedIdentSeq! tyds = new TypedIdentSeq(); ds = new VariableSeq(); QKeyValue kv = null; .)
+ "var"
+ { Attribute<ref kv> }
+ IdsTypeWheres<true, tyds> ";"
+ (. foreach(TypedIdent! tyd in tyds) {
+ ds.Add(new GlobalVariable(tyd.tok, tyd, kv));
+ }
+ .)
+ .
+
+LocalVars<VariableSeq! ds>
+= (. TypedIdentSeq! tyds = new TypedIdentSeq(); QKeyValue kv = null; .)
+ "var"
+ { Attribute<ref kv> }
+ IdsTypeWheres<true, tyds> ";"
+ (. foreach(TypedIdent! tyd in tyds) {
+ ds.Add(new LocalVariable(tyd.tok, tyd, kv));
+ }
+ .)
+ .
+
+ProcFormals<bool incoming, bool allowWhereClauses, out VariableSeq! ds>
+= (. TypedIdentSeq! tyds = new TypedIdentSeq(); ds = new VariableSeq(); .)
+ "("
+ [ IdsTypeWheres<allowWhereClauses, tyds> ]
+ ")"
+ (. foreach (TypedIdent! tyd in tyds) {
+ ds.Add(new Formal(tyd.tok, tyd, incoming));
+ }
+ .)
+ .
+
+BoundVars<IToken! x, out VariableSeq! ds>
+= (. TypedIdentSeq! tyds = new TypedIdentSeq(); ds = new VariableSeq(); .)
+ IdsTypeWheres<false, tyds>
+ (. foreach (TypedIdent! tyd in tyds) {
+ ds.Add(new BoundVariable(tyd.tok, tyd));
+ }
+ .)
+ .
+
+/*------------------------------------------------------------------------*/
+/* IdsType is used with const declarations */
+IdsType<out TypedIdentSeq! tyds>
+= (. TokenSeq! ids; Bpl.Type! ty; .)
+ Idents<out ids> ":" Type<out ty>
+ (. tyds = new TypedIdentSeq();
+ foreach (Token! id in ids) {
+ tyds.Add(new TypedIdent(id, id.val, ty, null));
+ }
+ .)
+ .
+
+/* IdsTypeWheres is used with the declarations of global and local variables,
+ procedure parameters, and quantifier bound variables. */
+IdsTypeWheres<bool allowWhereClauses, TypedIdentSeq! tyds>
+=
+ IdsTypeWhere<allowWhereClauses, tyds>
+ { "," IdsTypeWhere<allowWhereClauses, tyds> }
+ .
+
+IdsTypeWhere<bool allowWhereClauses, TypedIdentSeq! tyds>
+= (. TokenSeq! ids; Bpl.Type! ty; Expr wh = null; Expr! nne; .)
+ Idents<out ids> ":" Type<out ty>
+ [ "where" Expression<out nne> (. if (allowWhereClauses) {
+ wh = nne;
+ } else {
+ SemErr("where clause not allowed here");
+ }
+ .)
+ ]
+ (. foreach (Token! id in ids) {
+ tyds.Add(new TypedIdent(id, id.val, ty, wh));
+ }
+ .)
+ .
+
+/*------------------------------------------------------------------------*/
+Type<out Bpl.Type! ty>
+= (. IToken! tok; ty = dummyType; .)
+ (
+ TypeAtom<out ty>
+ |
+ Ident<out tok> (. TypeSeq! args = new TypeSeq (); .)
+ [ TypeArgs<args> ] (. ty = new UnresolvedTypeIdentifier (tok, tok.val, args); .)
+ |
+ MapType<out ty>
+ )
+ .
+
+TypeArgs<TypeSeq! ts>
+= (. IToken! tok; Type! ty; .)
+ (
+ TypeAtom<out ty> (. ts.Add(ty); .)
+ [ TypeArgs<ts> ]
+ |
+ Ident<out tok> (. TypeSeq! args = new TypeSeq ();
+ ts.Add(new UnresolvedTypeIdentifier (tok, tok.val, args)); .)
+ [ TypeArgs<ts> ]
+ |
+ MapType<out ty> (. ts.Add(ty); .)
+ )
+ .
+
+TypeAtom<out Bpl.Type! ty>
+= (. ty = dummyType; .)
+ ( "int" (. ty = new BasicType(token, SimpleType.Int); .)
+ | "bool" (. ty = new BasicType(token, SimpleType.Bool); .)
+ /* note: bitvectors are handled in UnresolvedTypeIdentifier */
+ |
+ "("
+ Type<out ty>
+ ")"
+ )
+ .
+
+MapType<out Bpl.Type! ty>
+= (. IToken tok = null;
+ IToken! nnTok;
+ TypeSeq! arguments = new TypeSeq();
+ Type! result;
+ TypeVariableSeq! typeParameters = new TypeVariableSeq();
+ .)
+ [ TypeParams<out nnTok, out typeParameters> (. tok = nnTok; .) ]
+ "[" (. if (tok == null) tok = token; .)
+ [ Types<arguments> ]
+ "]"
+ Type<out result>
+ (.
+ ty = new MapType(tok, typeParameters, arguments, result);
+ .)
+ .
+
+TypeParams<out IToken! tok, out Bpl.TypeVariableSeq! typeParams>
+= (. TokenSeq! typeParamToks; .)
+ "<" (. tok = token; .)
+ Idents<out typeParamToks>
+ ">"
+ (.
+ typeParams = new TypeVariableSeq ();
+ foreach (Token! id in typeParamToks)
+ typeParams.Add(new TypeVariable(id, id.val));
+ .)
+ .
+
+Types<TypeSeq! ts>
+= (. Bpl.Type! ty; .)
+ Type<out ty> (. ts.Add(ty); .)
+ { "," Type<out ty> (. ts.Add(ty); .)
+ }
+ .
+
+
+/*------------------------------------------------------------------------*/
+Consts<out VariableSeq! ds>
+= (. IToken! y; TypedIdentSeq! xs;
+ ds = new VariableSeq();
+ bool u = false; QKeyValue kv = null;
+ bool ChildrenComplete = false;
+ List<ConstantParent!> Parents = null; .)
+ "const" (. y = token; .)
+ { Attribute<ref kv> }
+ [ "unique" (. u = true; .)
+ ]
+ IdsType<out xs>
+ [ OrderSpec<out ChildrenComplete, out Parents> ]
+ (. bool makeClone = false;
+ foreach(TypedIdent! x in xs) {
+
+ // ensure that no sharing is introduced
+ List<ConstantParent!> ParentsClone;
+ if (makeClone && Parents != null) {
+ ParentsClone = new List<ConstantParent!> ();
+ foreach (ConstantParent! p in Parents)
+ ParentsClone.Add(new ConstantParent (
+ new IdentifierExpr (p.Parent.tok, p.Parent.Name),
+ p.Unique));
+ } else {
+ ParentsClone = Parents;
+ }
+ makeClone = true;
+
+ ds.Add(new Constant(y, x, u, ParentsClone, ChildrenComplete, kv));
+ }
+ .)
+ ";"
+ .
+
+OrderSpec<out bool ChildrenComplete, out List<ConstantParent!\> Parents>
+= (. ChildrenComplete = false;
+ Parents = null;
+ bool u;
+ IToken! parent; .)
+ "extends" (. Parents = new List<ConstantParent!> ();
+ u = false; .)
+ [
+ [ "unique" (. u = true; .)
+ ]
+ Ident<out parent> (. Parents.Add(new ConstantParent (
+ new IdentifierExpr(parent, parent.val), u)); .)
+ {
+ "," (. u = false; .)
+ [ "unique" (. u = true; .)
+ ]
+ Ident<out parent> (. Parents.Add(new ConstantParent (
+ new IdentifierExpr(parent, parent.val), u)); .)
+ }
+ ]
+ [ "complete" (. ChildrenComplete = true; .)
+ ]
+ .
+
+/*------------------------------------------------------------------------*/
+Function<out DeclarationSeq! ds>
+= (. ds = new DeclarationSeq(); IToken! z;
+ IToken! typeParamTok;
+ TypeVariableSeq! typeParams = new TypeVariableSeq();
+ VariableSeq arguments = new VariableSeq();
+ TypedIdent! tyd;
+ QKeyValue kv = null;
+ Expr definition = null;
+ Expr! tmp;
+ .)
+ "function" { Attribute<ref kv> } Ident<out z>
+ [ TypeParams<out typeParamTok, out typeParams> ]
+ "("
+ [ VarOrType<out tyd> (. arguments.Add(new Formal(tyd.tok, tyd, true)); .)
+ { "," VarOrType<out tyd> (. arguments.Add(new Formal(tyd.tok, tyd, true)); .)
+ } ] ")"
+ "returns" "(" VarOrType<out tyd> ")"
+ ( "{" Expression<out tmp> (. definition = tmp; .) "}" | ";" )
+ (.
+ Function! func = new Function(z, z.val, typeParams, arguments,
+ new Formal(tyd.tok, tyd, false), null, kv);
+ ds.Add(func);
+ if (definition != null) {
+ // generate either an axiom or a function body
+ if (QKeyValue.FindBoolAttribute(kv, "inline")) {
+ func.Body = definition;
+ } else {
+ VariableSeq dummies = new VariableSeq();
+ ExprSeq callArgs = new ExprSeq();
+ int i = 0;
+ foreach (Formal! f in arguments) {
+ string nm = f.TypedIdent.HasName ? f.TypedIdent.Name : "_" + i;
+ dummies.Add(new BoundVariable(f.tok, new TypedIdent(f.tok, nm, f.TypedIdent.Type)));
+ callArgs.Add(new IdentifierExpr(f.tok, nm));
+ i++;
+ }
+ TypeVariableSeq! quantifiedTypeVars = new TypeVariableSeq ();
+ foreach (TypeVariable! t in typeParams)
+ quantifiedTypeVars.Add(new TypeVariable (Token.NoToken, t.Name));
+
+ Expr call = new NAryExpr(z, new FunctionCall(new IdentifierExpr(z, z.val)), callArgs);
+ // specify the type of the function, because it might be that
+ // type parameters only occur in the output type
+ call = Expr.CoerceType(z, call, (Type)tyd.Type.Clone());
+ Expr def = new ForallExpr(z, quantifiedTypeVars, dummies,
+ kv,
+ new Trigger(z, true, new ExprSeq(call), null),
+ Expr.Eq(call, definition));
+ ds.Add(new Axiom(z, def, "autogenerated definition axiom", null));
+ }
+ }
+ .)
+ .
+
+VarOrType<out TypedIdent! tyd>
+= (. string! varName = ""; Bpl.Type! ty; IToken! tok; .)
+ Type<out ty> (. tok = ty.tok; .)
+ [ ":" (. if (ty is UnresolvedTypeIdentifier &&
+ ((!)(ty as UnresolvedTypeIdentifier)).Arguments.Length == 0) {
+ varName = ((!)(ty as UnresolvedTypeIdentifier)).Name;
+ } else {
+ SemErr("expected identifier before ':'");
+ }
+ .)
+ Type<out ty>
+ ]
+ (. tyd = new TypedIdent(tok, varName, ty); .)
+ .
+
+/*------------------------------------------------------------------------*/
+Axiom<out Axiom! m>
+= (. Expr! e; QKeyValue kv = null; .)
+ "axiom"
+ { Attribute<ref kv> }
+ (. IToken! x = token; .)
+ Proposition<out e> ";" (. m = new Axiom(x,e, null, kv); .)
+ .
+
+/*------------------------------------------------------------------------*/
+UserDefinedTypes<out List<Declaration!\>! ts>
+= (. Declaration! decl; QKeyValue kv = null; ts = new List<Declaration!> (); .)
+ "type"
+ { Attribute<ref kv> }
+ UserDefinedType<out decl, kv> (. ts.Add(decl); .)
+ { "," UserDefinedType<out decl, kv> (. ts.Add(decl); .) }
+ ";"
+ .
+
+UserDefinedType<out Declaration! decl, QKeyValue kv>
+= (. IToken! id; IToken! id2; TokenSeq! paramTokens = new TokenSeq ();
+ Type! body = dummyType; bool synonym = false; .)
+ Ident<out id>
+ [ WhiteSpaceIdents<out paramTokens> ]
+ [
+ "=" Type<out body>
+ (. synonym = true; .)
+ ]
+ (.
+ if (synonym) {
+ TypeVariableSeq! typeParams = new TypeVariableSeq();
+ foreach (Token! t in paramTokens)
+ typeParams.Add(new TypeVariable(t, t.val));
+ decl = new TypeSynonymDecl(id, id.val, typeParams, body, kv);
+ } else {
+ decl = new TypeCtorDecl(id, id.val, paramTokens.Length, kv);
+ }
+ .)
+ .
+
+
+/*------------------------------------------------------------------------*/
+Procedure<out Procedure! proc, out /*maybe null*/ Implementation impl>
+= (. IToken! x;
+ TypeVariableSeq! typeParams;
+ VariableSeq! ins, outs;
+ RequiresSeq! pre = new RequiresSeq();
+ IdentifierExprSeq! mods = new IdentifierExprSeq();
+ EnsuresSeq! post = new EnsuresSeq();
+
+ VariableSeq! locals = new VariableSeq();
+ StmtList! stmtList;
+ QKeyValue kv = null;
+ impl = null;
+ .)
+
+ "procedure"
+ ProcSignature<true, out x, out typeParams, out ins, out outs, out kv>
+ ( ";"
+ { Spec<pre, mods, post> }
+ | { Spec<pre, mods, post> }
+ ImplBody<out locals, out stmtList>
+ (.
+ // here we attach kv only to the Procedure, not its implementation
+ impl = new Implementation(x, x.val, typeParams,
+ Formal.StripWhereClauses(ins), Formal.StripWhereClauses(outs), locals, stmtList, null);
+ .)
+ )
+ (. proc = new Procedure(x, x.val, typeParams, ins, outs, pre, mods, post, kv); .)
+ .
+
+
+Implementation<out Implementation! impl>
+= (. IToken! x;
+ TypeVariableSeq! typeParams;
+ VariableSeq! ins, outs;
+ VariableSeq! locals;
+ StmtList! stmtList;
+ QKeyValue kv;
+ .)
+
+ "implementation"
+ 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); .)
+ .
+
+
+ProcSignature<bool allowWhereClausesOnFormals, out IToken! name, out TypeVariableSeq! typeParams,
+ out VariableSeq! ins, out VariableSeq! outs, out QKeyValue kv>
+= (. IToken! typeParamTok; typeParams = new TypeVariableSeq();
+ outs = new VariableSeq(); kv = null; .)
+ { Attribute<ref kv> }
+ Ident<out name>
+ [ TypeParams<out typeParamTok, out typeParams> ]
+ ProcFormals<true, allowWhereClausesOnFormals, out ins>
+ [ "returns" ProcFormals<false, allowWhereClausesOnFormals, out outs> ]
+ .
+
+
+Spec<RequiresSeq! pre, IdentifierExprSeq! mods, EnsuresSeq! post>
+= (. TokenSeq! ms; .)
+ ( "modifies"
+ [ Idents<out ms> (. foreach (IToken! m in ms) {
+ mods.Add(new IdentifierExpr(m, m.val));
+ }
+ .)
+ ] ";"
+ | "free" SpecPrePost<true, pre, post>
+ | SpecPrePost<false, pre, post>
+ )
+ .
+
+SpecPrePost<bool free, RequiresSeq! pre, EnsuresSeq! post>
+= (. Expr! e; VariableSeq! locals; BlockSeq! blocks; Token tok = null; QKeyValue kv = null; .)
+ ( "requires" (. tok = token; .)
+ { Attribute<ref kv> }
+ (Proposition<out e> ";" (. pre.Add(new Requires(tok, free, e, null, kv)); .)
+ |
+ SpecBody<out locals, out blocks> ";"
+ (. pre.Add(new Requires(tok, free, new BlockExpr(locals, blocks), null, kv)); .)
+ )
+ | "ensures" (. tok = token; .)
+ { Attribute<ref kv> }
+ (Proposition<out e> ";" (. post.Add(new Ensures(tok, free, e, null, kv)); .)
+ |
+ SpecBody<out locals, out blocks> ";"
+ (. post.Add(new Ensures(tok, free, new BlockExpr(locals, blocks), null, kv)); .)
+ )
+ )
+ .
+
+SpecBody<out VariableSeq! locals, out BlockSeq! blocks>
+= (. locals = new VariableSeq(); Block! b; .)
+ "{{"
+ { LocalVars<locals> }
+ SpecBlock<out b> (. blocks = new BlockSeq(b); .)
+ { SpecBlock<out b> (. blocks.Add(b); .)
+ }
+ "}}"
+ .
+
+SpecBlock<out Block! b>
+= (. IToken! x; IToken! y;
+ Cmd c; IToken label;
+ CmdSeq cs = new CmdSeq();
+ TokenSeq! xs;
+ StringSeq ss = new StringSeq();
+ b = dummyBlock;
+ Expr! e;
+ .)
+ Ident<out x> ":"
+ { LabelOrCmd<out c, out label>
+ (. if (c != null) {
+ assert label == null;
+ cs.Add(c);
+ } else {
+ assert label != null;
+ SemErr("SpecBlock's can only have one label");
+ }
+ .)
+ }
+ ( "goto" (. y = token; .)
+ Idents<out xs> (. foreach (IToken! s in xs) { ss.Add(s.val); }
+ b = new Block(x,x.val,cs,new GotoCmd(y,ss));
+ .)
+ | "return" Expression<out e>
+ (. b = new Block(x,x.val,cs,new ReturnExprCmd(token,e)); .)
+ ) ";"
+ .
+
+/*------------------------------------------------------------------------*/
+
+ImplBody<out VariableSeq! locals, out StmtList! stmtList>
+= (. locals = new VariableSeq(); .)
+ "{"
+ { LocalVars<locals> }
+ StmtList<out stmtList>
+ .
+
+/* the StmtList also reads the final curly brace */
+StmtList<out StmtList! stmtList>
+= (. List<BigBlock!> bigblocks = new List<BigBlock!>();
+ /* built-up state for the current BigBlock: */
+ IToken startToken = null; string currentLabel = null;
+ CmdSeq cs = null; /* invariant: startToken != null ==> cs != null */
+ /* temporary variables: */
+ IToken label; Cmd c; BigBlock b;
+ StructuredCmd ec = null; StructuredCmd! ecn;
+ TransferCmd tc = null; TransferCmd! tcn;
+ .)
+
+ {
+ ( LabelOrCmd<out c, out label>
+ (. if (c != null) {
+ // LabelOrCmd read a Cmd
+ assert label == null;
+ if (startToken == null) { startToken = c.tok; cs = new CmdSeq(); }
+ assert cs != null;
+ cs.Add(c);
+ } else {
+ // LabelOrCmd read a label
+ assert label != null;
+ if (startToken != null) {
+ assert cs != null;
+ // dump the built-up state into a BigBlock
+ b = new BigBlock(startToken, currentLabel, cs, null, null);
+ bigblocks.Add(b);
+ cs = null;
+ }
+ startToken = label;
+ currentLabel = label.val;
+ cs = new CmdSeq();
+ }
+ .)
+
+ | StructuredCmd<out ecn>
+ (. ec = ecn;
+ if (startToken == null) { startToken = ec.tok; cs = new CmdSeq(); }
+ assert cs != null;
+ b = new BigBlock(startToken, currentLabel, cs, ec, null);
+ bigblocks.Add(b);
+ startToken = null; currentLabel = null; cs = null;
+ .)
+
+ | TransferCmd<out tcn>
+ (. tc = tcn;
+ if (startToken == null) { startToken = tc.tok; cs = new CmdSeq(); }
+ assert cs != null;
+ b = new BigBlock(startToken, currentLabel, cs, null, tc);
+ bigblocks.Add(b);
+ startToken = null; currentLabel = null; cs = null;
+ .)
+
+ )
+ }
+ "}"
+ (. IToken! endCurly = token;
+ if (startToken == null && bigblocks.Count == 0) {
+ startToken = token; cs = new CmdSeq();
+ }
+ if (startToken != null) {
+ assert cs != null;
+ b = new BigBlock(startToken, currentLabel, cs, null, null);
+ bigblocks.Add(b);
+ }
+
+ stmtList = new StmtList(bigblocks, endCurly);
+ .)
+ .
+
+TransferCmd<out TransferCmd! tc>
+= (. tc = dummyTransferCmd;
+ Token y; TokenSeq! xs;
+ StringSeq ss = new StringSeq();
+ .)
+ ( "goto" (. y = token; .)
+ Idents<out xs> (. foreach (IToken! s in xs) { ss.Add(s.val); }
+ tc = new GotoCmd(y, ss);
+ .)
+ | "return" (. tc = new ReturnCmd(token); .)
+ ) ";"
+ .
+
+StructuredCmd<out StructuredCmd! ec>
+= (. ec = dummyStructuredCmd; assume ec.IsPeerConsistent;
+ IfCmd! ifcmd; WhileCmd! wcmd; BreakCmd! bcmd;
+ .)
+ ( IfCmd<out ifcmd> (. ec = ifcmd; .)
+ | WhileCmd<out wcmd> (. ec = wcmd; .)
+ | BreakCmd<out bcmd> (. ec = bcmd; .)
+ )
+ .
+
+IfCmd<out IfCmd! ifcmd>
+= (. IToken! x;
+ Expr guard;
+ StmtList! thn;
+ IfCmd! elseIf; IfCmd elseIfOption = null;
+ StmtList! els; StmtList elseOption = null;
+ .)
+ "if" (. x = token; .)
+ Guard<out guard>
+ "{" StmtList<out thn>
+ [ "else"
+ ( IfCmd<out elseIf> (. elseIfOption = elseIf; .)
+ | "{"
+ StmtList<out els> (. elseOption = els; .)
+ )
+ ]
+ (. ifcmd = new IfCmd(x, guard, thn, elseIfOption, elseOption); .)
+ .
+
+WhileCmd<out WhileCmd! wcmd>
+= (. IToken! x; Token z;
+ Expr guard; Expr! e; bool isFree;
+ List<PredicateCmd!> invariants = new List<PredicateCmd!>();
+ StmtList! body;
+ .)
+ "while" (. x = token; .)
+ Guard<out guard> (. assume guard == null || Owner.None(guard); .)
+ { (. isFree = false; z = t/*lookahead token*/; .)
+ [ "free" (. isFree = true; .)
+ ]
+ "invariant"
+ Expression<out e> (. if (isFree) {
+ invariants.Add(new AssumeCmd(z, e));
+ } else {
+ invariants.Add(new AssertCmd(z, e));
+ }
+ .)
+ ";"
+ }
+ "{"
+ StmtList<out body> (. wcmd = new WhileCmd(x, guard, invariants, body); .)
+ .
+
+Guard<out Expr e>
+= (. Expr! ee; e = null; .)
+ "("
+ ( "*" (. e = null; .)
+ | Expression<out ee> (. e = ee; .)
+ )
+ ")"
+ .
+
+BreakCmd<out BreakCmd! bcmd>
+= (. IToken! x; IToken! y;
+ string breakLabel = null;
+ .)
+ "break" (. x = token; .)
+ [ Ident<out y> (. breakLabel = y.val; .)
+ ] ";" (. bcmd = new BreakCmd(x, breakLabel); .)
+ .
+
+/*------------------------------------------------------------------------*/
+
+LabelOrCmd<out Cmd c, out IToken label>
+/* ensures (c == null) != (label != null) */
+= (. IToken! x; Expr! e;
+ TokenSeq! xs;
+ IdentifierExprSeq ids;
+ c = dummyCmd; label = null;
+ Cmd! cn;
+ QKeyValue kv = null;
+ .)
+ ( LabelOrAssign<out c, out label>
+ | "assert" (. x = token; .)
+ { Attribute<ref kv> }
+ Proposition<out e> (. c = new AssertCmd(x,e, kv); .)
+ ";"
+ | "assume" (. x = token; .)
+ Proposition<out e> (. c = new AssumeCmd(x,e); .)
+ ";"
+ | "havoc" (. x = token; .)
+ Idents<out xs> ";" (. ids = new IdentifierExprSeq();
+ foreach (IToken! y in xs) {
+ ids.Add(new IdentifierExpr(y, y.val));
+ }
+ c = new HavocCmd(x,ids);
+ .)
+ | CallCmd<out cn> ";" (. c = cn; .)
+ )
+ .
+
+/*------------------------------------------------------------------------*/
+
+LabelOrAssign<out Cmd c, out IToken label>
+/* ensures (c == null) != (label != null) */
+= (. IToken! id; IToken! x; Expr! e, e0;
+ c = dummyCmd; label = null;
+ AssignLhs! lhs;
+ List<AssignLhs!>! lhss;
+ List<Expr!>! rhss;
+ .)
+ Ident<out id> (. x = token; .)
+ ( ":" (. c = null; label = x; .)
+ |
+ MapAssignIndexes<id, out lhs> (. lhss = new List<AssignLhs!> ();
+ lhss.Add(lhs); .)
+ { ","
+ Ident<out id>
+ MapAssignIndexes<id, out lhs> (. lhss.Add(lhs); .)
+ }
+ ":=" (. x = token; /* use location of := */ .)
+ Expression<out e0> (. rhss = new List<Expr!> ();
+ rhss.Add(e0); .)
+ { ","
+ Expression<out e0> (. rhss.Add(e0); .)
+ }
+ ";" (. c = new AssignCmd(x, lhss, rhss); .)
+ )
+ .
+
+MapAssignIndexes<IToken! assignedVariable, out AssignLhs! lhs>
+= (. IToken! x;
+ AssignLhs! runningLhs =
+ new SimpleAssignLhs(assignedVariable,
+ new IdentifierExpr(assignedVariable, assignedVariable.val));
+ List<Expr!>! indexes;
+ Expr! e0;
+ .)
+ {
+ "[" (. x = token;
+ indexes = new List<Expr!> (); .)
+ [
+ Expression<out e0> (. indexes.Add(e0); .)
+ { ","
+ Expression<out e0> (. indexes.Add(e0); .)
+ }
+ ]
+ "]" (. runningLhs =
+ new MapAssignLhs (x, runningLhs, indexes); .)
+ }
+ (. lhs = runningLhs; .)
+ .
+
+/*------------------------------------------------------------------------*/
+CallCmd<out Cmd! c>
+= (. IToken! x; IToken! first; IToken p;
+ List<IdentifierExpr>! ids = new List<IdentifierExpr>();
+ List<Expr>! es = new List<Expr>();
+ Expr en; List<Expr> args;
+ c = dummyCmd;
+ .)
+ "call" (. x = token; .)
+ ( Ident<out first>
+ ( "("
+ [ CallForallArg<out en> (. es.Add(en); .)
+ { "," CallForallArg<out en> (. es.Add(en); .)
+ }
+ ]
+ ")" (. c = new CallCmd(x, first.val, es, ids); .)
+ |
+ (. ids.Add(new IdentifierExpr(first, first.val)); .)
+ [ "," CallOutIdent<out p> (.
+ if (p==null) {
+ ids.Add(null);
+ } else {
+ ids.Add(new IdentifierExpr(p, p.val));
+ }
+ .)
+ { "," CallOutIdent<out p> (.
+ if (p==null) {
+ ids.Add(null);
+ } else {
+ ids.Add(new IdentifierExpr(p, p.val));
+ }
+ .)
+ }
+ ] ":="
+ Ident<out first> "("
+ [ CallForallArg<out en> (. es.Add(en); .)
+ { "," CallForallArg<out en> (. es.Add(en); .)
+ }
+ ]
+ ")" (. c = new CallCmd(x, first.val, es, ids); .)
+ )
+ | "forall"
+ Ident<out first> "(" (. args = new List<Expr>(); .)
+ [ CallForallArg<out en> (. args.Add(en); .)
+ { "," CallForallArg<out en> (. args.Add(en); .)
+ }
+ ]
+ ")" (. c = new CallForallCmd(x, first.val, args); .)
+ | "*"
+ (. ids.Add(null); .)
+ [ "," CallOutIdent<out p> (.
+ if (p==null) {
+ ids.Add(null);
+ } else {
+ ids.Add(new IdentifierExpr(p, p.val));
+ }
+ .)
+ { "," CallOutIdent<out p> (.
+ if (p==null) {
+ ids.Add(null);
+ } else {
+ ids.Add(new IdentifierExpr(p, p.val));
+ }
+ .)
+ }
+ ] ":="
+ Ident<out first> "("
+ [ CallForallArg<out en> (. es.Add(en); .)
+ { "," CallForallArg<out en> (. es.Add(en); .)
+ }
+ ]
+ ")" (. c = new CallCmd(x, first.val, es, ids); .)
+ )
+ .
+
+CallOutIdent<out IToken id>
+= (. id = null;
+ IToken! p;
+ .)
+ ( "*"
+ | Ident<out p> (. id = p; .)
+ )
+ .
+
+CallForallArg<out Expr exprOptional>
+= (. exprOptional = null;
+ Expr! e;
+ .)
+ ( "*"
+ | Expression<out e> (. exprOptional = e; .)
+ )
+ .
+
+/*------------------------------------------------------------------------*/
+Proposition<out Expr! e>
+=
+ Expression<out e>
+ .
+
+/*------------------------------------------------------------------------*/
+Idents<out TokenSeq! xs>
+= (. IToken! id; xs = new TokenSeq(); .)
+ Ident<out id> (. xs.Add(id); .)
+ { "," Ident<out id> (. xs.Add(id); .)
+ }
+ .
+
+/*------------------------------------------------------------------------*/
+WhiteSpaceIdents<out TokenSeq! xs>
+= (. IToken! id; xs = new TokenSeq(); .)
+ Ident<out id> (. xs.Add(id); .)
+ { Ident<out id> (. xs.Add(id); .)
+ }
+ .
+
+/*------------------------------------------------------------------------*/
+Expressions<out ExprSeq! es>
+= (. Expr! e; es = new ExprSeq(); .)
+ Expression<out e> (. es.Add(e); .)
+ { "," Expression<out e> (. es.Add(e); .)
+ }
+ .
+
+/*------------------------------------------------------------------------*/
+Expression<out Expr! e0>
+= (. IToken! x; Expr! e1; .)
+ ImpliesExpression<false, out e0>
+ { EquivOp (. x = token; .)
+ ImpliesExpression<false, out e1>
+ (. e0 = Expr.Binary(x, BinaryOperator.Opcode.Iff, e0, e1); .)
+ }
+ .
+
+EquivOp = "<==>" | '\u21d4'.
+
+/*------------------------------------------------------------------------*/
+ImpliesExpression<bool noExplies, out Expr! e0>
+= (. IToken! x; Expr! e1; .)
+ LogicalExpression<out e0>
+ [
+ ImpliesOp (. x = token; .)
+ /* recurse because implication is right-associative */
+ ImpliesExpression<true, out e1>
+ (. e0 = Expr.Binary(x, BinaryOperator.Opcode.Imp, e0, e1); .)
+ |
+ ExpliesOp (. if (noExplies)
+ SemErr("illegal mixture of ==> and <==, use parentheses to disambiguate");
+ x = token; .)
+ LogicalExpression<out e1>
+ (. e0 = Expr.Binary(x, BinaryOperator.Opcode.Imp, e1, e0); .)
+ /* loop because explies is left-associative */
+ {
+ ExpliesOp (. x = token; .)
+ LogicalExpression<out e1>
+ (. e0 = Expr.Binary(x, BinaryOperator.Opcode.Imp, e1, e0); .)
+ }
+ ]
+ .
+
+ImpliesOp = "==>" | '\u21d2'.
+ExpliesOp = "<==" | '\u21d0'.
+
+/*------------------------------------------------------------------------*/
+LogicalExpression<out Expr! e0>
+= (. IToken! x; Expr! e1; BinaryOperator.Opcode op; .)
+ RelationalExpression<out e0>
+ [ AndOp (. x = token; .)
+ RelationalExpression<out e1>
+ (. e0 = Expr.Binary(x, BinaryOperator.Opcode.And, e0, e1); .)
+ { AndOp (. x = token; .)
+ RelationalExpression<out e1>
+ (. e0 = Expr.Binary(x, BinaryOperator.Opcode.And, e0, e1); .)
+ }
+ | OrOp (. x = token; .)
+ RelationalExpression<out e1>
+ (. e0 = Expr.Binary(x, BinaryOperator.Opcode.Or, e0, e1); .)
+ { OrOp (. x = token; .)
+ RelationalExpression<out e1>
+ (. e0 = Expr.Binary(x, BinaryOperator.Opcode.Or, e0, e1); .)
+ }
+ ]
+ .
+
+AndOp = "&&" | '\u2227'.
+OrOp = "||" | '\u2228'.
+
+/*------------------------------------------------------------------------*/
+RelationalExpression<out Expr! e0>
+= (. IToken! x; Expr! e1; BinaryOperator.Opcode op; .)
+ BvTerm<out e0>
+ [ RelOp<out x, out op>
+ BvTerm<out e1> (. e0 = Expr.Binary(x, op, e0, e1); .)
+ ]
+ .
+
+RelOp<out IToken! x, out BinaryOperator.Opcode op>
+= (. x = Token.NoToken; op=BinaryOperator.Opcode.Add/*(dummy)*/; .)
+ ( "==" (. x = token; op=BinaryOperator.Opcode.Eq; .)
+ | "<" (. x = token; op=BinaryOperator.Opcode.Lt; .)
+ | ">" (. x = token; op=BinaryOperator.Opcode.Gt; .)
+ | "<=" (. x = token; op=BinaryOperator.Opcode.Le; .)
+ | ">=" (. x = token; op=BinaryOperator.Opcode.Ge; .)
+ | "!=" (. x = token; op=BinaryOperator.Opcode.Neq; .)
+ | "<:" (. x = token; op=BinaryOperator.Opcode.Subtype; .)
+ | '\u2260' (. x = token; op=BinaryOperator.Opcode.Neq; .)
+ | '\u2264' (. x = token; op=BinaryOperator.Opcode.Le; .)
+ | '\u2265' (. x = token; op=BinaryOperator.Opcode.Ge; .)
+ )
+ .
+
+/*------------------------------------------------------------------------*/
+BvTerm<out Expr! e0>
+= (. IToken! x; Expr! e1; .)
+ Term<out e0>
+ { "++" (. x = token; .)
+ Term<out e1> (. e0 = new BvConcatExpr(x, e0, e1); .)
+ }
+ .
+
+
+/*------------------------------------------------------------------------*/
+Term<out Expr! e0>
+= (. IToken! x; Expr! e1; BinaryOperator.Opcode op; .)
+ Factor<out e0>
+ { AddOp<out x, out op>
+ Factor<out e1> (. e0 = Expr.Binary(x, op, e0, e1); .)
+ }
+ .
+
+AddOp<out IToken! x, out BinaryOperator.Opcode op>
+= (. x = Token.NoToken; op=BinaryOperator.Opcode.Add/*(dummy)*/; .)
+ ( "+" (. x = token; op=BinaryOperator.Opcode.Add; .)
+ | "-" (. x = token; op=BinaryOperator.Opcode.Sub; .)
+ )
+ .
+
+/*------------------------------------------------------------------------*/
+Factor<out Expr! e0>
+= (. IToken! x; Expr! e1; BinaryOperator.Opcode op; .)
+ UnaryExpression<out e0>
+ { MulOp<out x, out op>
+ UnaryExpression<out e1> (. e0 = Expr.Binary(x, op, e0, e1); .)
+ }
+ .
+
+MulOp<out IToken! x, out BinaryOperator.Opcode op>
+= (. x = Token.NoToken; op=BinaryOperator.Opcode.Add/*(dummy)*/; .)
+ ( "*" (. x = token; op=BinaryOperator.Opcode.Mul; .)
+ | "/" (. x = token; op=BinaryOperator.Opcode.Div; .)
+ | "%" (. x = token; op=BinaryOperator.Opcode.Mod; .)
+ )
+ .
+
+/*------------------------------------------------------------------------*/
+UnaryExpression<out Expr! e>
+= (. IToken! x;
+ e = dummyExpr;
+ .)
+ ( "-" (. x = token; .)
+ UnaryExpression<out e> (. e = Expr.Binary(x, BinaryOperator.Opcode.Sub, new LiteralExpr(x, BigNum.ZERO), e); .)
+ | NegOp (. x = token; .)
+ UnaryExpression<out e> (. e = Expr.Unary(x, UnaryOperator.Opcode.Not, e); .)
+ | CoercionExpression<out e>
+ )
+ .
+
+NegOp = "!" | '\u00ac'.
+
+/*------------------------------------------------------------------------*/
+
+/* This production creates ambiguities, because types can start with "<"
+ (polymorphic map types), but can also be followed by "<" (inequalities).
+ Coco deals with these ambiguities in a reasonable way by preferring to read
+ further types (type arguments) over relational symbols. E.g., "5 : C < 0"
+ will cause a parse error because "<" is treated as the beginning of a
+ map type. */
+
+CoercionExpression<out Expr! e>
+= (. IToken! x;
+ Type! coercedTo;
+ BigNum bn;
+ .)
+ ArrayExpression<out e>
+ { ":" (. x = token; .)
+ (
+ Type<out coercedTo> (. e = Expr.CoerceType(x, e, coercedTo); .)
+ |
+ Nat<out bn> /* This means that we really look at a bitvector
+ expression t[a:b] */
+ (. if (!(e is LiteralExpr) || !((LiteralExpr)e).isBigNum) {
+ SemErr("arguments of extract need to be integer literals");
+ e = new BvBounds(x, bn, BigNum.ZERO);
+ } else {
+ e = new BvBounds(x, bn, ((LiteralExpr)e).asBigNum);
+ }
+ .)
+ )
+ }
+ .
+
+/*------------------------------------------------------------------------*/
+ArrayExpression<out Expr! e>
+= (. IToken! x;
+ Expr! index0 = dummyExpr; Expr! e1;
+ bool store; bool bvExtract;
+ ExprSeq! allArgs = dummyExprSeq;
+ .)
+ AtomExpression<out e>
+ { "[" (. x = token; allArgs = new ExprSeq ();
+ allArgs.Add(e);
+ store = false; bvExtract = false; .)
+ [
+ Expression<out index0>
+ (. if (index0 is BvBounds)
+ bvExtract = true;
+ else
+ allArgs.Add(index0);
+ .)
+ { "," Expression<out e1>
+ (. if (bvExtract || e1 is BvBounds)
+ SemErr("bitvectors only have one dimension");
+ allArgs.Add(e1);
+ .)
+ }
+ [ ":=" Expression<out e1>
+ (. if (bvExtract || e1 is BvBounds)
+ SemErr("assignment to bitvectors is not possible");
+ allArgs.Add(e1); store = true;
+ .)
+ ]
+ | ":=" Expression<out e1> (. allArgs.Add(e1); store = true; .)
+ ]
+ "]"
+ (. if (store)
+ e = new NAryExpr(x, new MapStore(x, allArgs.Length - 2), allArgs);
+ else if (bvExtract)
+ e = new ExtractExpr(x, e,
+ ((BvBounds)index0).Upper.ToIntSafe,
+ ((BvBounds)index0).Lower.ToIntSafe);
+ else
+ e = new NAryExpr(x, new MapSelect(x, allArgs.Length - 1), allArgs);
+ .)
+ }
+ .
+
+
+/*------------------------------------------------------------------------*/
+AtomExpression<out Expr! e>
+= (. IToken! x; int n; BigNum bn;
+ ExprSeq! es; VariableSeq! ds; Trigger trig;
+ TypeVariableSeq! typeParams;
+ IdentifierExpr! id;
+ Bpl.Type! ty;
+ QKeyValue kv;
+ e = dummyExpr;
+ .)
+ ( "false" (. e = new LiteralExpr(token, false); .)
+ | "true" (. e = new LiteralExpr(token, true); .)
+ | Nat<out bn> (. e = new LiteralExpr(token, bn); .)
+ | BvLit<out bn, out n> (. e = new LiteralExpr(token, bn, n); .)
+
+ | Ident<out x> (. id = new IdentifierExpr(x, x.val); e = id; .)
+ [ "("
+ ( Expressions<out es> (. e = new NAryExpr(x, new FunctionCall(id), es); .)
+ | /* empty */ (. e = new NAryExpr(x, new FunctionCall(id), new ExprSeq()); .)
+ )
+ ")"
+ ]
+
+ | "old" (. x = token; .)
+ "("
+ Expression<out e>
+ ")" (. e = new OldExpr(x, e); .)
+
+ | "(" ( Expression<out e> (. if (e is BvBounds)
+ SemErr("parentheses around bitvector bounds " +
+ "are not allowed"); .)
+ | Forall (. x = token; .)
+ 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); .)
+ | Exists (. x = token; .)
+ 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); .)
+ )
+ ")"
+ )
+ .
+
+Attribute<ref QKeyValue kv>
+= (. Trigger trig = null; .)
+ AttributeOrTrigger<ref kv, ref trig> (. if (trig != null) SemErr("only attributes, not triggers, allowed here"); .)
+.
+
+AttributeOrTrigger<ref QKeyValue kv, ref Trigger trig>
+= (. IToken! tok; Expr! e; ExprSeq! es;
+ string key; string value;
+ List<object!> parameters; object! param;
+ .)
+ "{" (. tok = token; .)
+ (
+ ":" ident (. key = token.val; parameters = new List<object!>(); .)
+ [ AttributeParameter<out param> (. parameters.Add(param); .)
+ { "," AttributeParameter<out param> (. parameters.Add(param); .)
+ }
+ ]
+ (. if (key == "nopats") {
+ if (parameters.Count == 1 && parameters[0] is Expr) {
+ e = (Expr)parameters[0];
+ if(trig==null){
+ trig = new Trigger(tok, false, new ExprSeq(e), null);
+ } else {
+ trig.AddLast(new Trigger(tok, false, new ExprSeq(e), null));
+ }
+ } else {
+ SemErr("the 'nopats' quantifier attribute expects a string-literal parameter");
+ }
+ } else {
+ if (kv==null) {
+ kv = new QKeyValue(tok, key, parameters, null);
+ } else {
+ kv.AddLast(new QKeyValue(tok, key, parameters, null));
+ }
+ }
+ .)
+ |
+ Expression<out e> (. es = new ExprSeq(e); .)
+ { "," Expression<out e> (. es.Add(e); .)
+ } (. if (trig==null) {
+ trig = new Trigger(tok, true, es, null);
+ } else {
+ trig.AddLast(new Trigger(tok, true, es, null));
+ }
+ .)
+ )
+ "}"
+ .
+
+AttributeParameter<out object! o>
+= (. o = "error";
+ Expr! e;
+ .)
+ ( string (. o = token.val.Substring(1, token.val.Length-2); .)
+ | Expression<out e> (. o = e; .)
+ )
+ .
+
+QuantifierBody<IToken! q, out TypeVariableSeq! typeParams, out VariableSeq! ds,
+ out QKeyValue kv, out Trigger trig, out Expr! body>
+= (. trig = null; typeParams = new TypeVariableSeq ();
+ IToken! tok; Expr! e; ExprSeq! es;
+ kv = null; string key; string value;
+ ds = new VariableSeq ();
+ .)
+ (
+ TypeParams<out tok, out typeParams>
+ [ BoundVars<q, out ds> ]
+ |
+ BoundVars<q, out ds>
+ )
+ QSep
+ { AttributeOrTrigger<ref kv, ref trig> }
+ Expression<out body>
+ .
+
+Forall = "forall" | '\u2200'.
+Exists = "exists" | '\u2203'.
+QSep = "::" | '\u2022'.
+
+/*------------------------------------------------------------------------*/
+Ident<out IToken! x>
+=
+ ident (. x = token;
+ if (x.val.StartsWith("\\"))
+ x.val = x.val.Substring(1);
+ .)
+ .
+
+/*------------------------------------------------------------------------*/
+Nat<out BigNum n>
+=
+ digits
+ (. try {
+ n = BigNum.FromString(token.val);
+ } catch (FormatException) {
+ SemErr("incorrectly formatted number");
+ n = BigNum.ZERO;
+ }
+ .)
+ .
+
+/*------------------------------------------------------------------------*/
+BvLit<out BigNum n, out int m>
+=
+ bvlit
+ (.
+ int pos = token.val.IndexOf("bv");
+ string a = token.val.Substring(0, pos);
+ string b = token.val.Substring(pos + 2);
+ try {
+ n = BigNum.FromString(a);
+ m = Convert.ToInt32(b);
+ } catch (FormatException) {
+ SemErr("incorrectly formatted bitvector");
+ n = BigNum.ZERO;
+ m = 0;
+ }
+ .)
+ .
+
+END BoogiePL.
diff --git a/Source/Core/CommandLineOptions.ssc b/Source/Core/CommandLineOptions.ssc
new file mode 100644
index 00000000..1a25e283
--- /dev/null
+++ b/Source/Core/CommandLineOptions.ssc
@@ -0,0 +1,1935 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.Specialized;
+using System.IO;
+using System.Diagnostics;
+using Microsoft.Contracts;
+using Cci = System.Compiler;
+
+namespace Microsoft.Boogie
+{
+ public class CommandLineOptions
+ {
+ public const string VersionNumber = "2.00";
+ public const string ToolNameBoogie = "Boogie program verifier";
+ public const string ToolNameSpecSharp = "Spec# program verifier";
+ public const string ToolNameDafny = "Dafny program verifier";
+ public const string VersionSuffix = " version " + VersionNumber + ", Copyright (c) 2003-2009, Microsoft.";
+ public string! InputFileExtension {
+ set
+ modifies _toolname, _version;
+ {
+ switch (value) {
+ case ".bpl": _toolname = ToolNameBoogie; break;
+ case ".dfy": _toolname = ToolNameDafny; break;
+ default: _toolname = ToolNameSpecSharp; break;
+ }
+ _version = _toolname + VersionSuffix;
+ }
+ }
+ string! _toolname = ToolNameBoogie;
+ string! _version = ToolNameBoogie + VersionSuffix;
+ public string! ToolName { get { return _toolname; } }
+ public string! Version { get { return _version; } }
+
+ public static CommandLineOptions! Clo = new CommandLineOptions(); // singleton to access all global data
+
+ public string! Environment = "";
+ public string! FileName = "unknown";
+
+ public const long Megabyte = 1048576;
+
+ // Flags and arguments
+
+ public bool RunningBoogieFromCommandLine = false; // "false" means running Boogie from the plug-in
+ public bool RunningBoogieOnSsc = true; // "true" means running Boogie on ssc input while false means running it on bpl input
+
+ public bool AttrHelpRequested = false;
+
+ [Peer] public List<string!>! Files = new List<string!>();
+ public List<string!>! ContractAssemblies = new List<string!>();
+
+ public string! FileTimestamp = ((!)DateTime.Now.ToString("o")).Replace(':', '.');
+ public void ExpandFilename(ref string pattern)
+ {
+ if (pattern != null) {
+ pattern = pattern.Replace("@PREFIX@", LogPrefix).Replace("@TIME@", FileTimestamp);
+ string fn = Files.Count == 0 ? "" : Files[Files.Count-1];
+ fn = fn.Replace('/', '-').Replace('\\', '-');
+ pattern = pattern.Replace("@FILE@", fn);
+ }
+ }
+
+ public string PrintFile = null;
+ public int PrintUnstructured = 0;
+ invariant 0 <= PrintUnstructured && PrintUnstructured < 3; // 0 = print only structured, 1 = both structured and unstructured, 2 = only unstructured
+ public bool PrintDesugarings = false;
+ public string SimplifyLogFilePath = null;
+ public string SMTLibOutputPath = "boogie-vc-@PROC@.smt";
+ public string! LogPrefix = "";
+ public bool PrintInstrumented = false;
+ public bool InstrumentWithAsserts = false;
+ public bool PrintWithUniqueASTIds = false;
+ private string XmlSinkFilename = null;
+ [Peer] public XmlSink XmlSink = null;
+ public bool Wait = false;
+ public bool Trace = false;
+ public bool TraceTimes = false;
+ public bool NoResolve = false;
+ public bool NoTypecheck = false;
+ public bool OverlookBoogieTypeErrors = false;
+ public bool Verify = true;
+ public bool TraceVerify = false;
+ public int /*(0:3)*/ ErrorTrace = 1;
+ public bool IntraproceduralInfer = true;
+ public bool ContractInfer = false;
+ public bool UseUncheckedContracts = false;
+ public bool SimplifyLogFileAppend = false;
+ public bool SoundnessSmokeTest = false;
+
+ public List<string!>! Z3DebugTraces = new List<string!>();
+
+ private bool noConsistencyChecks = false;
+ public bool NoConsistencyChecks {
+ get {return !Verify ? true : noConsistencyChecks;}
+ set
+ modifies noConsistencyChecks;
+ {noConsistencyChecks = value;}
+ }
+
+ public string DafnyPrintFile = null;
+
+ public enum ProverWarnings { None, Stdout, Stderr }
+ public ProverWarnings PrintProverWarnings = ProverWarnings.None;
+ public int ProverShutdownLimit = 0;
+
+ public enum SubsumptionOption { Never, NotForQuantifiers, Always }
+ public SubsumptionOption UseSubsumption = SubsumptionOption.Always;
+
+ public bool ShowTrace = false;
+ public enum ShowEnvironment { Never, DuringPrint, Always }
+ public ShowEnvironment ShowEnv = ShowEnvironment.DuringPrint;
+ public bool DontShowLogo = false;
+
+ public int CheckingLevel = 2;
+ invariant 0 <= CheckingLevel && CheckingLevel < 3;
+ public enum Methodology { Boogie, VisibleState }
+ public Methodology MethodologySelection = Methodology.Boogie;
+ public int OrderStrength = 0;
+ invariant 0 <= OrderStrength && OrderStrength < 2;
+ public bool UseArithDistributionAxioms = false;
+ public int SummationAxiomStrength = 1;
+ invariant 0 <= SummationAxiomStrength && SummationAxiomStrength < 2;
+ public int InductiveMinMax = 0;
+ invariant 0 <= InductiveMinMax && InductiveMinMax < 6;
+ public int FCOStrength = 5;
+ invariant 0 <= FCOStrength && FCOStrength < 6;
+ public int LoopUnrollCount = -1; // -1 means don't unroll loops
+ public int LoopFrameConditions = -1; // -1 means not specified -- this will be replaced by the "implications" section below
+ invariant -1 <= LoopFrameConditions && LoopFrameConditions < 3;
+ public int ModifiesDefault = 5;
+ invariant 0 <= ModifiesDefault && ModifiesDefault < 7;
+ public bool LocalModifiesChecks = true;
+ public bool NoVerifyByDefault = false;
+ public enum OwnershipModelOption { Standard, Experimental, Trivial }
+ public OwnershipModelOption OwnershipModelEncoding = OwnershipModelOption.Standard;
+ public int PrintErrorModel = 0;
+ public string PrintErrorModelFile = null;
+ invariant (0 <= PrintErrorModel && PrintErrorModel <= 2) || PrintErrorModel == 4;
+ public int EnhancedErrorMessages = 0;
+ invariant 0 <= EnhancedErrorMessages && EnhancedErrorMessages < 2;
+ public bool ForceBplErrors = false; // if true, boogie error is shown even if "msg" attribute is present
+
+ public enum BvHandling { None, Z3Native, ToInt }
+ public BvHandling Bitvectors = BvHandling.Z3Native;
+
+ public bool UseAbstractInterpretation = true; // true iff the user want to use abstract interpretation
+ public int /*0..9*/StepsBeforeWidening = 0; // The number of steps that must be done before applying a widen operator
+ invariant 0 <= StepsBeforeWidening && StepsBeforeWidening <= 9;
+
+ public enum VCVariety { Structured, Block, Local, BlockNested, BlockReach, BlockNestedReach, Dag, Doomed, Unspecified }
+ public VCVariety vcVariety = VCVariety.Unspecified; // will not be Unspecified after command line has been parsed
+
+ public bool RemoveEmptyBlocks = true;
+
+ [Rep] public ProverFactory TheProverFactory;
+ public string ProverName;
+ [Peer] public List<string!>! ProverOptions = new List<string!>();
+
+ public int BracketIdsInVC = -1; // -1 - not specified, 0 - no, 1 - yes
+ public bool CausalImplies = false;
+ invariant -1 <= BracketIdsInVC && BracketIdsInVC <= 1;
+ public int SimplifyProverMatchDepth = -1; // -1 means not specified
+ public int ProverKillTime = -1; // -1 means not specified
+ public int SmokeTimeout = 10; // default to 10s
+ public int ProverCCLimit = 5;
+ public bool RestartProverPerVC = false;
+
+ public double VcsMaxCost = 1.0;
+ public double VcsPathJoinMult = 0.8;
+ public double VcsPathCostMult = 1.0;
+ public double VcsAssumeMult = 0.01;
+ public double VcsPathSplitMult = 0.5; // 0.5-always, 2-rarely do path splitting
+ public int VcsMaxSplits = 1;
+ public int VcsMaxKeepGoingSplits = 1;
+ public int VcsFinalAssertTimeout = 30;
+ public int VcsKeepGoingTimeout = 1;
+ public int VcsCores = 1;
+ public bool VcsDumpSplits = false;
+
+ public bool houdiniEnabled = false;
+ public bool DebugRefuted = false;
+
+ public XmlSink XmlRefuted
+ {
+ get { if (DebugRefuted) return XmlSink; else return null; }
+ }
+
+ public int Z3mam = 0;
+ [Peer] public List<string!>! Z3Options = new List<string!>();
+ public bool Z3types = false;
+
+ // Maximum amount of virtual memory (in bytes) for the prover to use
+ //
+ // Non-positive number indicates unbounded.
+ public long MaxProverMemory = 100 * Megabyte;
+
+ // Minimum number of prover calls before restart
+ public int MinNumOfProverCalls = 5;
+
+ public enum PlatformType{notSpecified, v1, v11, v2, cli1}
+ public PlatformType TargetPlatform;
+ public string TargetPlatformLocation;
+ public string StandardLibraryLocation;
+
+ // whether procedure inlining is enabled at call sites.
+ public enum Inlining { None, MacroLike, Bounded };
+ public Inlining ProcedureInlining = Inlining.MacroLike;
+ public bool PrintInlined = false;
+
+ public enum TypeEncoding { None, Predicates, Arguments, Monomorphic };
+ public TypeEncoding TypeEncodingMethod = TypeEncoding.Predicates;
+
+ public bool Monomorphize = false;
+
+ public bool ReflectAdd = false;
+
+ // Static constructor
+ static CommandLineOptions()
+ {
+ if (System.Type.GetType("Mono.Runtime") == null) { // MONO
+ TraceListenerCollection! dbl = Debug.Listeners;
+ assume dbl.IsPeerConsistent; // hangs off static field
+#if WHIDBEY
+ dbl.Add(new ConsoleTraceListener());
+#else
+ dpl.Add(new DefaultTraceListener());
+#endif
+ }
+ }
+
+ private string methodToLog = null;
+ private string methodToBreakOn = null;
+
+ [Rep] private List<string!> procsToCheck = null; // null means "no restriction"
+ [Rep] private List<string!> methodsToTranslateSubstring = null; // null means "no restriction"
+ [Rep] private List<string!> methodsToTranslateMethod = null; // null means "no restriction"
+ [Rep] private List<string!> methodsToTranslateMethodQualified = null; // null means "no restriction"
+ [Rep] private List<string!> methodsToTranslateClass = null; // null means "no restriction"
+ [Rep] private List<string!> methodsToTranslateClassQualified = null; // null means "no restriction"
+ [Rep] private List<string!> methodsToTranslateFile = null; // null means "no restriction"
+ [Rep] private List<string!>! methodsToTranslateExclude = new List<string!>();
+
+ 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 DebugStatistics = false;
+
+ public bool AnySet
+ {
+ get
+ {
+ return Intervals
+ || Constant
+ || DynamicType
+ || Nullness
+ || Polyhedra;
+ }
+ }
+ }
+ public AiFlags! Ai = new AiFlags();
+
+ public class HoudiniFlags {
+ public bool continueAtError = false;
+ public bool incremental = false;
+ }
+
+ public HoudiniFlags! houdiniFlags = new HoudiniFlags();
+
+ [Verify(false)]
+ public CommandLineOptions() {
+ // this is just to suppress verification.
+ }
+
+
+ /// <summary>
+ /// Parses the command-line arguments "args" into the global flag variables. The possible result
+ /// values are:
+ /// -2: an error occurred and help was requested
+ /// -1: no error occurred and help was requested
+ /// 1: no error occurred and help was not requested
+ /// 2: an error occurred and help was not requested
+ /// </summary>
+ /// <param name="args">Consumed ("captured" and possibly modified) by the method.</param>
+ [Verify(false)]
+ public int Parse([Captured] string[]! args)
+ requires forall{int i in (0:args.Length); args[i] != null};
+ ensures TheProverFactory != null;
+ ensures vcVariety != VCVariety.Unspecified;
+ ensures -2 <= result && result <= 2 && result != 0;
+ {
+ // save the command line options for the log files
+ Environment += "Command Line Options:";
+ foreach (string s in args)
+ Environment += " " + s;
+ args = (string[]!)args.Clone(); // the operations performed may mutate the array, so make a copy
+ CommandLineParseState! ps = new CommandLineParseState(args);
+ int res = 1; // the result value
+
+ while (ps.i < args.Length)
+ invariant ps.IsPeerConsistent;
+ invariant ps.args == args;
+ {
+ ps.s = args[ps.i];
+ assert ps.s != null;
+ ps.s = ps.s.Trim();
+
+ int colonIndex = ps.s.IndexOf(':');
+ if (colonIndex >= 0 && (ps.s.StartsWith("-") || ps.s.StartsWith("/")))
+ {
+ ps.hasColonArgument = true;
+ args[ps.i] = ps.s.Substring(colonIndex+1);
+ ps.s = ps.s.Substring(0, colonIndex);
+ }
+ else
+ {
+ expose(ps) {
+ ps.i++;
+ }
+ ps.hasColonArgument = false;
+ }
+ ps.nextIndex = ps.i;
+
+
+ switch (ps.s)
+ {
+ case "-help":
+ case "/help":
+ case "-?":
+ case "/?":
+ if (ps.ConfirmArgumentCount(0)) {
+ res = -1; // help requested
+ }
+ break;
+
+ case "-attrHelp":
+ case "/attrHelp":
+ if (ps.ConfirmArgumentCount(0)) {
+ AttrHelpRequested = true;
+ }
+ break;
+
+ case "-infer":
+ case "/infer":
+ if (ps.ConfirmArgumentCount(1)) {
+ foreach (char c in (!)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 's': Ai.DebugStatistics = true; UseAbstractInterpretation = true; break;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ StepsBeforeWidening = (int) char.GetNumericValue(c); break;
+ default:
+ ps.Error("Invalid argument '{0}' to option {1}", c.ToString(), ps.s);
+ break;
+ }
+ }
+ }
+ break;
+
+ case "-noinfer":
+ case "/noinfer":
+ if (ps.ConfirmArgumentCount(0)) {
+ UseAbstractInterpretation = false;
+ }
+ break;
+
+ case "-log":
+ case "/log":
+ if (ps.hasColonArgument) {
+ methodToLog = args[ps.i];
+ ps.nextIndex = ps.i + 1;
+ } else {
+ methodToLog = "*";
+ }
+ break;
+
+ case "-logInfer":
+ case "/logInfer":
+ Microsoft.AbstractInterpretationFramework.Lattice.LogSwitch = true;
+ break;
+
+ case "-break":
+ case "/break":
+ if (ps.hasColonArgument)
+ {
+ methodToBreakOn = args[ps.i];
+ ps.nextIndex = ps.i + 1;
+ }
+ else
+ {
+ System.Diagnostics.Debugger.Break();
+ }
+ break;
+
+ case "-launch":
+ case "/launch":
+ System.Diagnostics.Debugger.Launch();
+ break;
+
+ case "-proc":
+ case "/proc":
+ if (procsToCheck == null) {
+ procsToCheck = new List<string!>();
+ }
+ if (ps.ConfirmArgumentCount(1)) {
+ procsToCheck.Add((!)args[ps.i]);
+ }
+ break;
+
+ case "-translate":
+ case "/translate":
+ if (methodsToTranslateSubstring == null) {
+ methodsToTranslateSubstring = new List<string!>();
+ }
+ if (ps.ConfirmArgumentCount(1)) {
+ methodsToTranslateSubstring.Add((!)args[ps.i]);
+ }
+ break;
+
+ case "-trMethod":
+ case "/trMethod":
+ if (ps.ConfirmArgumentCount(1)) {
+ string m = (!)args[ps.i];
+ if (0 <= m.IndexOf('.')) {
+ if (methodsToTranslateMethodQualified == null) {
+ methodsToTranslateMethodQualified = new List<string!>();
+ }
+ methodsToTranslateMethodQualified.Add(m);
+ } else {
+ if (methodsToTranslateMethod == null) {
+ methodsToTranslateMethod = new List<string!>();
+ }
+ methodsToTranslateMethod.Add(m);
+ }
+ }
+ break;
+
+ case "-trClass":
+ case "/trClass":
+ if (ps.ConfirmArgumentCount(1)) {
+ string m = (!)args[ps.i];
+ if (0 <= m.IndexOf('.')) {
+ if (methodsToTranslateClassQualified == null) {
+ methodsToTranslateClassQualified = new List<string!>();
+ }
+ methodsToTranslateClassQualified.Add(m);
+ } else {
+ if (methodsToTranslateClass == null) {
+ methodsToTranslateClass = new List<string!>();
+ }
+ methodsToTranslateClass.Add(m);
+ }
+ }
+ break;
+
+ case "-trFile":
+ case "/trFile":
+ if (methodsToTranslateFile == null) {
+ methodsToTranslateFile = new List<string!>();
+ }
+ if (ps.ConfirmArgumentCount(1)) {
+ methodsToTranslateFile.Add((!)args[ps.i]);
+ }
+ break;
+
+ case "-trExclude":
+ case "/trExclude":
+ if (ps.ConfirmArgumentCount(1)) {
+ methodsToTranslateExclude.Add((!)args[ps.i]);
+ }
+ break;
+
+ case "-xml":
+ case "/xml":
+ if (ps.ConfirmArgumentCount(1))
+ {
+ XmlSinkFilename = args[ps.i];
+ }
+ break;
+
+ case "-print":
+ case "/print":
+ if (ps.ConfirmArgumentCount(1))
+ {
+ PrintFile = args[ps.i];
+ }
+ break;
+
+ case "-dprint":
+ case "/dprint":
+ if (ps.ConfirmArgumentCount(1))
+ {
+ DafnyPrintFile = args[ps.i];
+ }
+ break;
+
+ case "-contracts":
+ case "/contracts":
+ case "-c":
+ case "/c":
+ if (ps.ConfirmArgumentCount(1))
+ {
+ ContractAssemblies.Add((!)args[ps.i]);
+ }
+ break;
+
+ case "-proverLog":
+ case "/proverLog":
+ if (ps.ConfirmArgumentCount(1))
+ {
+ SimplifyLogFilePath = args[ps.i];
+ }
+ break;
+
+ case "-logPrefix":
+ case "/logPrefix":
+ if (ps.ConfirmArgumentCount(1))
+ {
+ string s = (!)args[ps.i];
+ LogPrefix += s.Replace('/', '-').Replace('\\', '-');
+ }
+ break;
+
+ case "-proverShutdownLimit":
+ case "/proverShutdownLimit":
+ ps.GetNumericArgument(ref ProverShutdownLimit);
+ break;
+
+ case "-smtOutput":
+ case "/smtOutput":
+ if (ps.ConfirmArgumentCount(1))
+ {
+ SMTLibOutputPath = args[ps.i];
+ }
+ break;
+
+ case "-errorTrace":
+ case "/errorTrace":
+ ps.GetNumericArgument(ref ErrorTrace, 3);
+ break;
+
+ case "-level":
+ case "/level":
+ ps.GetNumericArgument(ref CheckingLevel, 3);
+ break;
+
+ case "-methodology":
+ case "/methodology":
+ if (ps.ConfirmArgumentCount(1))
+ {
+ switch (args[ps.i])
+ {
+ case "b":
+ case "Boogie":
+ case "boogie":
+ MethodologySelection = Methodology.Boogie;
+ break;
+ case "vs":
+ case "visible-state":
+ MethodologySelection = Methodology.VisibleState;
+ break;
+ default:
+ ps.Error("Invalid argument \"{0}\" to option {1}", args[ps.i], ps.s);
+ break;
+ }
+ }
+ break;
+
+ case "-proverWarnings":
+ case "/proverWarnings":
+ if (ps.ConfirmArgumentCount(1))
+ {
+ switch (args[ps.i])
+ {
+ case "0":
+ PrintProverWarnings = ProverWarnings.None;
+ break;
+ case "1":
+ PrintProverWarnings = ProverWarnings.Stdout;
+ break;
+ case "2":
+ PrintProverWarnings = ProverWarnings.Stderr;
+ break;
+ default:
+ ps.Error("Invalid argument \"{0}\" to option {1}", args[ps.i], ps.s);
+ break;
+ }
+ }
+ break;
+
+ case "-env":
+ case "/env":
+ if (ps.ConfirmArgumentCount(1))
+ {
+ switch (args[ps.i])
+ {
+ case "0":
+ ShowEnv = ShowEnvironment.Never;
+ break;
+ case "1":
+ ShowEnv = ShowEnvironment.DuringPrint;
+ break;
+ case "2":
+ ShowEnv = ShowEnvironment.Always;
+ break;
+ default:
+ ps.Error("Invalid argument \"{0}\" to option {1}", args[ps.i], ps.s);
+ break;
+ }
+ }
+ break;
+
+ case "-loopUnroll":
+ case "/loopUnroll":
+ ps.GetNumericArgument(ref LoopUnrollCount);
+ break;
+
+ case "-modifiesOnLoop":
+ case "/modifiesOnLoop":
+ ps.GetNumericArgument(ref LoopFrameConditions, 3);
+ break;
+
+ case "-modifiesDefault":
+ case "/modifiesDefault":
+ ps.GetNumericArgument(ref ModifiesDefault, 7);
+ break;
+
+ case "-localModifiesChecks":
+ case "/localModifiesChecks":
+ {
+ int localChecks = 0;
+ ps.GetNumericArgument(ref localChecks, 7);
+ LocalModifiesChecks = (localChecks != 0);
+ }
+ break;
+
+ case "-orderStrength":
+ case "/orderStrength":
+ ps.GetNumericArgument(ref OrderStrength, 2);
+ break;
+
+ case "-summationStrength":
+ case "/summationStrength":
+ ps.GetNumericArgument(ref SummationAxiomStrength, 2);
+ break;
+
+ case "-inductiveMinMax":
+ case "/inductiveMinMax":
+ ps.GetNumericArgument(ref InductiveMinMax, 6);
+ break;
+
+ case "-fcoStrength":
+ case "/fcoStrength":
+ ps.GetNumericArgument(ref FCOStrength, 6);
+ break;
+
+ case "-ownerModelEncoding":
+ case "/ownerModelEncoding":
+ if (ps.ConfirmArgumentCount(1))
+ {
+ switch (args[ps.i])
+ {
+ case "s":
+ case "standard":
+ OwnershipModelEncoding = OwnershipModelOption.Standard;
+ break;
+ case "e":
+ case "experimental":
+ OwnershipModelEncoding = OwnershipModelOption.Experimental;
+ break;
+ case "t":
+ case "trivial":
+ OwnershipModelEncoding = OwnershipModelOption.Trivial;
+ break;
+ default:
+ ps.Error("Invalid argument \"{0}\" to option {1}", args[ps.i], ps.s);
+ break;
+ }
+ }
+ break;
+
+ case "-printModel":
+ case "/printModel":
+ if (ps.ConfirmArgumentCount(1))
+ {
+ switch (args[ps.i])
+ {
+ case "0":
+ PrintErrorModel = 0;
+ break;
+ case "1":
+ PrintErrorModel = 1;
+ break;
+ case "2":
+ PrintErrorModel = 2;
+ break;
+ case "4":
+ PrintErrorModel = 4;
+ break;
+ default:
+ ps.Error("Invalid argument \"{0}\" to option {1}", args[ps.i], ps.s);
+ break;
+ }
+ }
+ break;
+
+
+ case "-printModelToFile":
+ case "/printModelToFile":
+ if (ps.ConfirmArgumentCount(1))
+ {
+ PrintErrorModelFile = args[ps.i];
+ }
+ break;
+
+
+ case "-enhancedErrorMessages":
+ case "/enhancedErrorMessages":
+ ps.GetNumericArgument(ref EnhancedErrorMessages, 2);
+ break;
+
+ case "-forceBplErrors":
+ case "/forceBplErrors":
+ ForceBplErrors = true;
+ break;
+
+ case "-bv":
+ case "/bv":
+ if (ps.ConfirmArgumentCount(1))
+ {
+ if (TheProverFactory == null) {
+ TheProverFactory = ProverFactory.Load("Z3");
+ ProverName = "Z3".ToUpper();
+ }
+
+ switch (args[ps.i])
+ {
+ case "n":
+ Bitvectors = BvHandling.None;
+ break;
+ case "z":
+ Bitvectors = BvHandling.Z3Native;
+ break;
+ case "i":
+ Bitvectors = BvHandling.ToInt;
+ break;
+ default:
+ ps.Error("Invalid argument \"{0}\" to option {1}", args[ps.i], ps.s);
+ break;
+ }
+ }
+ break;
+
+ case "-contractInfer":
+ case "/contractInfer":
+ ContractInfer = true;
+ TheProverFactory = ProverFactory.Load("ContractInference");
+ ProverName = "ContractInference".ToUpper();
+ break;
+
+ case "-subsumption":
+ case "/subsumption":
+ if (ps.ConfirmArgumentCount(1))
+ {
+ switch (args[ps.i])
+ {
+ case "0":
+ UseSubsumption = SubsumptionOption.Never;
+ break;
+ case "1":
+ UseSubsumption = SubsumptionOption.NotForQuantifiers;
+ break;
+ case "2":
+ UseSubsumption = SubsumptionOption.Always;
+ break;
+ default:
+ ps.Error("Invalid argument \"{0}\" to option {1}", args[ps.i], ps.s);
+ break;
+ }
+ }
+ break;
+
+ case "-vc":
+ case "/vc":
+ if (ps.ConfirmArgumentCount(1)) {
+ switch (args[ps.i])
+ {
+ case "s":
+ case "structured":
+ vcVariety = VCVariety.Structured;
+ break;
+ case "b":
+ case "block":
+ vcVariety = VCVariety.Block;
+ break;
+ case "l":
+ case "local":
+ vcVariety = VCVariety.Local;
+ break;
+ case "n":
+ case "nested":
+ vcVariety = VCVariety.BlockNested;
+ break;
+ case "m":
+ vcVariety = VCVariety.BlockNestedReach;
+ break;
+ case "r":
+ vcVariety = VCVariety.BlockReach;
+ break;
+ case "d":
+ case "dag":
+ vcVariety = VCVariety.Dag;
+ break;
+ case "doomed":
+ vcVariety = VCVariety.Doomed;
+ break;
+ default:
+ ps.Error("Invalid argument \"{0}\" to option {1}", args[ps.i], ps.s);
+ break;
+ }
+ }
+ break;
+
+ case "-prover":
+ case "/prover":
+ if (ps.ConfirmArgumentCount(1)) {
+ TheProverFactory = ProverFactory.Load((!)args[ps.i]);
+ ProverName = ((!)args[ps.i]).ToUpper();
+ }
+ break;
+
+ case "-proverOpt":
+ case "/proverOpt":
+ if (ps.ConfirmArgumentCount(1)) {
+ ProverOptions.Add((!)args[ps.i]);
+ }
+ break;
+
+ case "-z3DebugTrace":
+ case "/z3DebugTrace":
+ if (ps.ConfirmArgumentCount(1)) {
+ CommandLineOptions.Clo.Z3DebugTraces.Add((!)args[ps.i]);
+ }
+ break;
+
+ case "-inline":
+ case "/inline":
+ if (ps.ConfirmArgumentCount(1)) {
+ switch (args[ps.i])
+ {
+ case "m":
+ case "macrolike":
+ ProcedureInlining = Inlining.MacroLike;
+ break;
+ case "n":
+ case "none":
+ ProcedureInlining = Inlining.None;
+ break;
+ case "b":
+ case "bounded":
+ ProcedureInlining = Inlining.Bounded;
+ break;
+ default:
+ ps.Error("Invalid argument \"{0}\" to option {1}", args[ps.i], ps.s);
+ break;
+ }
+ }
+ break;
+
+ case "-typeEncoding":
+ case "/typeEncoding":
+ if (ps.ConfirmArgumentCount(1)) {
+ switch (args[ps.i])
+ {
+ case "n":
+ case "none":
+ TypeEncodingMethod = TypeEncoding.None;
+ break;
+ case "p":
+ case "predicates":
+ TypeEncodingMethod = TypeEncoding.Predicates;
+ break;
+ case "a":
+ case "arguments":
+ TypeEncodingMethod = TypeEncoding.Arguments;
+ break;
+ case "m":
+ case "monomorphic":
+ TypeEncodingMethod = TypeEncoding.Monomorphic;
+ break;
+ default:
+ ps.Error("Invalid argument \"{0}\" to option {1}", args[ps.i], ps.s);
+ break;
+ }
+ }
+ break;
+
+ case "-monomorphize":
+ case "/monomorphize":
+ Monomorphize = true;
+ break;
+
+ case "-vcBrackets":
+ case "/vcBrackets":
+ ps.GetNumericArgument(ref BracketIdsInVC, 2);
+ break;
+
+ case "-proverMemoryLimit":
+ case "/proverMemoryLimit":
+ {
+ int d = 0;
+ if (ps.GetNumericArgument(ref d)) {
+ MaxProverMemory = d * Megabyte;
+ }
+ break;
+ }
+
+ case "-vcsMaxCost":
+ case "/vcsMaxCost":
+ ps.GetNumericArgument(ref VcsMaxCost);
+ break;
+
+ case "-vcsPathJoinMult":
+ case "/vcsPathJoinMult":
+ ps.GetNumericArgument(ref VcsPathJoinMult);
+ break;
+
+ case "-vcsPathCostMult":
+ case "/vcsPathCostMult":
+ ps.GetNumericArgument(ref VcsPathCostMult);
+ break;
+
+ case "-vcsAssumeMult":
+ case "/vcsAssumeMult":
+ ps.GetNumericArgument(ref VcsAssumeMult);
+ break;
+
+ case "-vcsPathSplitMult":
+ case "/vcsPathSplitMult":
+ ps.GetNumericArgument(ref VcsPathSplitMult);
+ break;
+
+ case "-vcsMaxSplits":
+ case "/vcsMaxSplits":
+ ps.GetNumericArgument(ref VcsMaxSplits);
+ break;
+
+ case "-vcsMaxKeepGoingSplits":
+ case "/vcsMaxKeepGoingSplits":
+ ps.GetNumericArgument(ref VcsMaxKeepGoingSplits);
+ break;
+
+ case "-vcsFinalAssertTimeout":
+ case "/vcsFinalAssertTimeout":
+ ps.GetNumericArgument(ref VcsFinalAssertTimeout);
+ break;
+
+ case "-vcsKeepGoingTimeout":
+ case "/vcsKeepGoingTimeout":
+ ps.GetNumericArgument(ref VcsKeepGoingTimeout);
+ break;
+
+ case "-vcsCores":
+ case "/vcsCores":
+ ps.GetNumericArgument(ref VcsCores);
+ break;
+
+ case "-simplifyMatchDepth":
+ case "/simplifyMatchDepth":
+ ps.GetNumericArgument(ref SimplifyProverMatchDepth);
+ break;
+
+ case "-timeLimit":
+ case "/timeLimit":
+ ps.GetNumericArgument(ref ProverKillTime);
+ break;
+
+ case "-smokeTimeout":
+ case "/smokeTimeout":
+ ps.GetNumericArgument(ref SmokeTimeout);
+ break;
+
+ case "-errorLimit":
+ case "/errorLimit":
+ ps.GetNumericArgument(ref ProverCCLimit);
+ break;
+
+ case "-z3mam":
+ case "/z3mam":
+ {
+ int mam = 0;
+ if (ps.GetNumericArgument(ref mam)) {
+ if (mam == 0 || mam == 3 || mam == 4) {
+ Z3mam = mam;
+ } else
+ ps.Error("Invalid argument \"{0}\" to option {1}", args[ps.i], ps.s);
+ }
+ }
+ break;
+
+ case "-z3opt":
+ case "/z3opt":
+ if (ps.ConfirmArgumentCount(1))
+ {
+ Z3Options.Add((!)args[ps.i]);
+ }
+ break;
+
+ case "-z3types":
+ case "/z3types":
+ Z3types = true;
+ break;
+
+ case "-platform":
+ case "/platform":
+ if (ps.ConfirmArgumentCount(1))
+ {
+ StringCollection platformOptions = this.ParseNamedArgumentList(args[ps.i]);
+ if (platformOptions != null && platformOptions.Count > 0){
+ try{
+ this.TargetPlatform = (PlatformType)(!)Enum.Parse(typeof(PlatformType), (!)platformOptions[0]);
+ }
+ catch {
+ ps.Error("Bad /platform type '{0}'", platformOptions[0]);
+ break;
+ }
+ if (platformOptions.Count > 1){
+ this.TargetPlatformLocation = platformOptions[1];
+ if (!Directory.Exists(platformOptions[1])) {
+ ps.Error("/platform directory '{0}' does not exist", platformOptions[1]);
+ break;
+ }
+ }
+ }
+ }
+ break;
+
+ case "-stdlib":
+ case "/stdlib":
+ if (ps.ConfirmArgumentCount(1))
+ {
+ this.StandardLibraryLocation = args[ps.i];
+ }
+ break;
+
+ case "-Houdini":
+ case "/Houdini":
+ this.houdiniEnabled=true;
+ if (ps.hasColonArgument) {
+ if (ps.ConfirmArgumentCount(1)) {
+ foreach (char c in (!)args[ps.i])
+ {
+ switch (c)
+ {
+ case 'c': houdiniFlags.continueAtError = true; break;
+ case 'i': houdiniFlags.incremental = true; break;
+ default : ps.Error("Unknown houdini flag: " + c + "\n"); break;
+ }
+ }
+ }
+ }
+ break;
+
+ default:
+ assume true;
+ bool option = false;
+ if (ps.CheckBooleanFlag("printUnstructured", ref option)) {
+ expose(this) {
+ PrintUnstructured = option ? 1 : 0;
+ }
+ } else if (
+ ps.CheckBooleanFlag("printDesugared", ref PrintDesugarings) ||
+ ps.CheckBooleanFlag("printInstrumented", ref PrintInstrumented) ||
+ ps.CheckBooleanFlag("printWithUniqueIds", ref PrintWithUniqueASTIds) ||
+ ps.CheckBooleanFlag("wait", ref Wait) ||
+ ps.CheckBooleanFlag("trace", ref Trace) ||
+ ps.CheckBooleanFlag("traceTimes", ref TraceTimes) ||
+ ps.CheckBooleanFlag("noResolve", ref NoResolve) ||
+ ps.CheckBooleanFlag("noTypecheck", ref NoTypecheck) ||
+ ps.CheckBooleanFlag("overlookTypeErrors", ref OverlookBoogieTypeErrors) ||
+ ps.CheckBooleanFlag("noVerify", ref Verify, false) ||
+ ps.CheckBooleanFlag("noRemoveEmptyBlocks", ref RemoveEmptyBlocks, false) ||
+ ps.CheckBooleanFlag("traceverify", ref TraceVerify) ||
+ ps.CheckBooleanFlag("noConsistencyChecks", ref NoConsistencyChecks, true) ||
+ ps.CheckBooleanFlag("nologo", ref DontShowLogo) ||
+ ps.CheckBooleanFlag("noVerifyByDefault", ref NoVerifyByDefault) ||
+ ps.CheckBooleanFlag("useUncheckedContracts", ref UseUncheckedContracts) ||
+ ps.CheckBooleanFlag("proverLogAppend", ref SimplifyLogFileAppend) ||
+ ps.CheckBooleanFlag("checkInfer", ref InstrumentWithAsserts) ||
+ ps.CheckBooleanFlag("interprocInfer", ref IntraproceduralInfer, false) ||
+ ps.CheckBooleanFlag("restartProver", ref RestartProverPerVC) ||
+ ps.CheckBooleanFlag("printInlined", ref PrintInlined) ||
+ ps.CheckBooleanFlag("arithDistributionAxioms", ref UseArithDistributionAxioms) ||
+ ps.CheckBooleanFlag("smoke", ref SoundnessSmokeTest) ||
+ ps.CheckBooleanFlag("vcsDumpSplits", ref VcsDumpSplits) ||
+ ps.CheckBooleanFlag("dbgRefuted", ref DebugRefuted) ||
+ ps.CheckBooleanFlag("causalImplies", ref CausalImplies) ||
+ ps.CheckBooleanFlag("reflectAdd", ref ReflectAdd)
+ )
+ {
+ // one of the boolean flags matched
+ }
+ else if (ps.s.StartsWith("-") || ps.s.StartsWith("/"))
+ {
+ ps.Error("unknown switch: {0}", ps.s);
+ }
+ else if (ps.ConfirmArgumentCount(0))
+ {
+ string filename = ps.s;
+ string extension = Path.GetExtension(filename);
+ if (extension != null) {
+ InputFileExtension = extension.ToLower();
+ }
+ Files.Add(filename);
+ FileName = filename;
+ }
+ break;
+ }
+ expose(ps) ps.i = ps.nextIndex;
+ }
+
+ assume true;
+ if (ps.encounteredErrors) res *= 2;
+ if (res < 0) { // help requested
+ Usage();
+ } else if (AttrHelpRequested) {
+ AttributeUsage();
+ } else if (ps.encounteredErrors) {
+ Console.WriteLine("Use /help for available options");
+ }
+
+ SetProverOptions();
+
+ if (Trace) { BoogieDebug.DoPrinting = true; } // reuse the -trace option for debug printing
+ return res;
+ }
+
+ private void SetProverOptions()
+ modifies this.*;
+ ensures TheProverFactory != null;
+ ensures vcVariety != VCVariety.Unspecified;
+ {
+ // expand macros in filenames, now that LogPrefix is fully determined
+ ExpandFilename(ref XmlSinkFilename);
+ ExpandFilename(ref PrintFile);
+ ExpandFilename(ref DafnyPrintFile);
+ ExpandFilename(ref SimplifyLogFilePath);
+ ExpandFilename(ref SMTLibOutputPath);
+ ExpandFilename(ref PrintErrorModelFile);
+
+ assume XmlSink == null; // XmlSink is to be set here
+ if (XmlSinkFilename != null) {
+ XmlSink = new XmlSink(XmlSinkFilename);
+ }
+
+ if (TheProverFactory == null) {
+ expose(this) {
+ TheProverFactory = ProverFactory.Load("Z3");
+ ProverName = "Z3".ToUpper();
+ }
+ }
+
+ if (vcVariety == VCVariety.Unspecified) {
+ vcVariety = TheProverFactory.DefaultVCVariety;
+ }
+
+ if (LoopFrameConditions == -1) {
+ // /modifiesOnLoop not specified. Set its default depending on /level
+ if (CheckingLevel == 2) {
+ LoopFrameConditions = 2;
+ } else {
+ LoopFrameConditions = 1;
+ }
+ }
+
+ switch (InductiveMinMax) {
+ case 1: case 2: case 4: case 5:
+ ReflectAdd = true; // these InductiveMinMax modes imply ReflectAdd
+ break;
+ default:
+ break;
+ }
+
+ if (MethodologySelection == Methodology.VisibleState) {
+ OwnershipModelEncoding = OwnershipModelOption.Trivial;
+ }
+ }
+
+
+
+ public bool UserWantsMethodLogging (string! methodFullName)
+ {
+ if (methodToLog == null) { return false; }
+ return methodToLog == "*" || methodFullName.IndexOf(methodToLog) >= 0;
+ }
+
+ public bool UserWantsToBreak (string! methodFullName)
+ {
+ if (methodToBreakOn == null) { return false; }
+ return methodFullName.IndexOf(methodToBreakOn) >= 0;
+ }
+
+ public bool UserWantsToCheckRoutine(string! methodFullname)
+ {
+ if (procsToCheck == null) {
+ // no preference
+ return true;
+ }
+ return exists{string s in procsToCheck; 0 <= methodFullname.IndexOf(s)};
+ }
+
+ public bool UserWantsToTranslateRoutine(Cci.Method! method, string! methodFullname) {
+ return UserWantsToTranslateRoutineInclude(method, methodFullname) &&
+ !exists{string s in methodsToTranslateExclude; 0 <= methodFullname.IndexOf(s)};
+ }
+
+ public bool UserWantsToTranslateRoutineInclude(Cci.Method! method, string! methodFullname)
+ {
+ if (methodsToTranslateSubstring == null &&
+ methodsToTranslateClass == null &&
+ methodsToTranslateClassQualified == null &&
+ methodsToTranslateFile == null &&
+ methodsToTranslateMethod == null &&
+ methodsToTranslateMethodQualified == null) {
+ // no preference
+ return true;
+ }
+ if (methodsToTranslateSubstring != null) {
+ if (exists{string s in methodsToTranslateSubstring; 0 <= methodFullname.IndexOf(s)}) {
+ return true;
+ }
+ }
+ if (methodsToTranslateMethod != null) {
+ string methodName = method.Name.Name;
+ assert methodsToTranslateMethod != null;
+ if (methodsToTranslateMethod.Contains(methodName)) {
+ return true;
+ }
+ }
+ if (methodsToTranslateMethodQualified != null && method.DeclaringType != null) {
+ string methodName = method.DeclaringType.Name.Name + "." + method.Name.Name;
+ assert methodsToTranslateMethodQualified != null;
+ if (methodsToTranslateMethodQualified.Contains(methodName)) {
+ return true;
+ }
+ }
+ if (method.DeclaringType != null) {
+ if (methodsToTranslateClass != null) {
+ string className = method.DeclaringType.Name.Name;
+ if (methodsToTranslateClass.Contains(className)) {
+ return true;
+ }
+ }
+ if (methodsToTranslateClassQualified != null) {
+ string className = method.DeclaringType.FullName;
+ if (className != null) {
+ className = className.Replace('+', '.');
+ if (methodsToTranslateClassQualified.Contains(className)) {
+ return true;
+ }
+ }
+ }
+ }
+ if (methodsToTranslateFile != null) {
+ string methodFilename = GetSourceDocument(method);
+ if (methodFilename != null) {
+ string path = methodFilename;
+ if (path != null) {
+ string filename = Path.GetFileName(path);
+ if (methodsToTranslateFile.Contains(filename)) {
+ return true;
+ }
+ }
+ }
+ }
+ // the method is not among the desired routines
+ return false;
+ }
+
+ /// <summary>
+ /// Returns the file containing "method". Returns null f that information is not available.
+ /// </summary>
+ static string GetSourceDocument(Cci.Method! method) {
+ // Start by looking for a source context in the method itself. However, if the program
+ // was read from a binary, then there is no source location for the method. If so, there
+ // some other ways we might find a source location.
+ if (method.SourceContext.Document != null) {
+ return method.SourceContext.Document.Name;
+ }
+ // Try to find a source location in the method's contract
+ if (method.Contract != null) {
+ if (method.Contract.Requires != null) {
+ foreach (Cci.Requires c in method.Contract.Requires) {
+ if (c != null && c.SourceContext.Document != null) {
+ return c.SourceContext.Document.Name;
+ }
+ }
+ }
+ if (method.Contract.Modifies != null) {
+ foreach (Cci.Expression c in method.Contract.Modifies) {
+ if (c != null && c.SourceContext.Document != null) {
+ return c.SourceContext.Document.Name;
+ }
+ }
+ }
+ if (method.Contract.Ensures != null) {
+ foreach (Cci.Ensures c in method.Contract.Ensures) {
+ if (c != null && c.SourceContext.Document != null) {
+ return c.SourceContext.Document.Name;
+ }
+ }
+ }
+ }
+ // As a last attempt, look for a source location among the statements
+ if (method.Body != null) {
+ return GetSourceDocumentFromStatements(method.Body.Statements);
+ }
+ return null; // no source location found
+ }
+
+ [Pure] static string GetSourceDocumentFromStatements(Cci.StatementList list) {
+ if (list != null) {
+ foreach (Cci.Statement c in list) {
+ if (c != null && c.SourceContext.Document != null) {
+ return c.SourceContext.Document.Name;
+ }
+ if (c is Cci.Block) {
+ Cci.Block b = (Cci.Block)c;
+ string n = GetSourceDocumentFromStatements(b.Statements);
+ if (n != null) {
+ return n;
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ class CommandLineParseState
+ {
+ public string s;
+ public bool hasColonArgument;
+ public readonly string[]! args;
+ public int i;
+ public int nextIndex;
+ public bool encounteredErrors;
+
+ invariant 0 <= i && i <= args.Length;
+ invariant 0 <= nextIndex && nextIndex <= args.Length;
+
+ public CommandLineParseState(string[]! args)
+ requires forall{int i in (0:args.Length); args[i] != null};
+ ensures this.args == args;
+ {
+ this.s = null; // set later by client
+ this.hasColonArgument = false; // set later by client
+ this.args = args;
+ this.i = 0;
+ this.nextIndex = 0; // set later by client
+ this.encounteredErrors = false;
+ }
+
+ public bool CheckBooleanFlag(string! flagName, ref bool flag, bool valueWhenPresent)
+ modifies nextIndex, encounteredErrors, Console.Error.*;
+ {
+ bool flagPresent = false;
+
+ if ((s == "/"+flagName || s == "-"+flagName) && ConfirmArgumentCount(0))
+ {
+ flag = valueWhenPresent;
+ flagPresent = true;
+ }
+ return flagPresent;
+ }
+
+ public bool CheckBooleanFlag(string! flagName, ref bool flag)
+ modifies nextIndex, encounteredErrors, Console.Error.*;
+ {
+ return CheckBooleanFlag(flagName, ref flag, true);
+ }
+
+ /// <summary>
+ /// If there is one argument and it is a non-negative integer, then set "arg" to that number and return "true".
+ /// Otherwise, emit error message, leave "arg" unchanged, and return "false".
+ /// </summary>
+ public bool GetNumericArgument(ref int arg)
+ modifies nextIndex, encounteredErrors, Console.Error.*;
+ {
+ if (this.ConfirmArgumentCount(1))
+ {
+ try {
+ assume args[i] != null;
+ assert args[i] is string; // needed to prove args[i].IsPeerConsistent
+ int d = Convert.ToInt32(this.args[this.i]);
+ if (0 <= d) {
+ arg = d;
+ return true;
+ }
+ } catch (System.FormatException) {
+ } catch (System.OverflowException) {
+ }
+ } else {
+ return false;
+ }
+ Error("Invalid argument \"{0}\" to option {1}", args[this.i], this.s);
+ return false;
+ }
+
+ /// <summary>
+ /// If there is one argument and it is a non-negative integer less than "limit",
+ /// then set "arg" to that number and return "true".
+ /// Otherwise, emit error message, leave "arg" unchanged, and return "false".
+ /// </summary>
+ public bool GetNumericArgument(ref int arg, int limit)
+ requires this.i < args.Length;
+ modifies nextIndex, encounteredErrors, Console.Error.*;
+ {
+ int a = arg;
+ if (!GetNumericArgument(ref a)) {
+ return false;
+ } else if (a < limit) {
+ arg = a;
+ return true;
+ } else {
+ Error("Invalid argument \"{0}\" to option {1}", args[this.i], this.s);
+ return false;
+ }
+ }
+
+ /// <summary>
+ /// If there is one argument and it is a non-negative real, then set "arg" to that number and return "true".
+ /// Otherwise, emit an error message, leave "arg" unchanged, and return "false".
+ /// </summary>
+ public bool GetNumericArgument(ref double arg)
+ modifies nextIndex, encounteredErrors, Console.Error.*;
+ {
+ if (this.ConfirmArgumentCount(1))
+ {
+ try {
+ assume args[i] != null;
+ assert args[i] is string; // needed to prove args[i].IsPeerConsistent
+ double d = Convert.ToDouble(this.args[this.i]);
+ if (0 <= d) {
+ arg = d;
+ return true;
+ }
+ } catch (System.FormatException) {
+ } catch (System.OverflowException) {
+ }
+ } else {
+ return false;
+ }
+ Error("Invalid argument \"{0}\" to option {1}", args[this.i], this.s);
+ return false;
+ }
+
+ public bool ConfirmArgumentCount(int argCount)
+ requires 0 <= argCount;
+ modifies nextIndex, encounteredErrors, Console.Error.*;
+ ensures result == ( !(hasColonArgument && argCount != 1) && !(args.Length < i + argCount) );
+ {
+ if (hasColonArgument && argCount != 1)
+ {
+ Error("\"{0}\" cannot take a colon argument", s);
+ nextIndex = args.Length;
+ return false;
+ }
+ else if (args.Length < i + argCount)
+ {
+ Error("\"{0}\" expects {1} argument{2}", s, argCount.ToString(), (string)(argCount == 1 ? "" : "s"));
+ nextIndex = args.Length;
+ return false;
+ }
+ else
+ {
+ nextIndex = i + argCount;
+ return true;
+ }
+ }
+
+ public void Error(string! message, params string[]! args)
+ modifies encounteredErrors, Console.Error.*;
+ {
+ Console.Error.WriteLine("Boogie: Error: " + String.Format(message, args));
+ encounteredErrors = true;
+ }
+ }
+
+ public virtual StringCollection ParseNamedArgumentList(string argList){
+ if (argList == null || argList.Length == 0) return null;
+ StringCollection result = new StringCollection();
+ int i = 0;
+ for (int n = argList.Length; i < n;)
+ invariant 0 <= i;
+ {
+ int separatorIndex = this.GetArgumentSeparatorIndex(argList, i);
+ if (separatorIndex > i){
+ result.Add(argList.Substring(i, separatorIndex-i));
+ i = separatorIndex+1;
+ continue;
+ }
+ result.Add(argList.Substring(i));
+ break;
+ }
+ return result;
+ }
+ public int GetArgumentSeparatorIndex(string! argList, int startIndex)
+ requires 0 <= startIndex && startIndex <= argList.Length;
+ ensures result < argList.Length;
+ {
+ int commaIndex = argList.IndexOf(",", startIndex);
+ int semicolonIndex = argList.IndexOf(";", startIndex);
+ if (commaIndex == -1) return semicolonIndex;
+ if (semicolonIndex == -1) return commaIndex;
+ if (commaIndex < semicolonIndex) return commaIndex;
+ return semicolonIndex;
+ }
+
+ public static void AttributeUsage()
+ {
+ Console.WriteLine(
+@"Boogie: The following attributes are supported by this implementation.
+
+ ---- On axioms -------------------------------------------------------------
+
+ {:inline true}
+ Works on axiom of the form:
+ (forall VARS :: f(VARS) = expr(VARS))
+ Makes Boogie replace f(VARS) with expr(VARS) everywhere just before
+ doing VC generation.
+
+ {:ignore ""p,q..""}
+ Exclude the axiom when generating VC for a prover supporting any
+ of the features 'p', 'q', ...
+ All the provers support the feature 'all'.
+ Simplify supports 'simplify' and 'simplifyLike'.
+ Z3 supports 'z3', 'simplifyLike' and either 'bvInt' (if the /bv:i
+ option is passed) or 'bvDefSem' (for /bv:z).
+
+ ---- On implementations and procedures -------------------------------------
+
+ {:inline N}
+ Inline given procedure (can be also used on implementation).
+ With /inline:b, N is the maximal number of inlinings per calling
+ procedure (not depth).
+ With /inline:m (default), N is ignored, and recursive calls to
+ inlined procedure will result in an error.
+ With /inline:n the entire attribute is ignored.
+ With /inline:m methods with /inline are not verified at all.
+
+ {:verify false}
+ Skip verification of an implementation.
+
+ {:forceBvZ3Native true}
+ Verify the given implementation with the native Z3 bitvector
+ handling. Only works if /bv:i (or /bv:z, but then it does not do
+ anything) is given on the command line.
+
+ {:forceBvInt true}
+ Use int translation for the given implementation. Only work with
+ /bv:z (or /bv:i).
+
+ {:vcs_max_cost N}
+ {:vcs_max_splits N}
+ {:vcs_max_keep_going_splits N}
+ Per-implementation versions of
+ /vcsMaxCost, /vcsMaxSplits and /vcsMaxKeepGoingSplits.
+
+ ---- On functions ----------------------------------------------------------
+
+ {:bvbuiltin ""spec""}
+ Z3 specific, used only with /bv:z.
+
+ {:bvint ""fn""}
+ With /bv:i rewrite the function to function symbol 'fn', except if
+ the 'fn' is 'id', in which case just strip the function altogether.
+
+ {:never_pattern true}
+ Terms starting with this function symbol will never be
+ automatically selected as patterns. It does not prevent them
+ from being used inside the triggers, and does not affect explicit
+ trigger annotations. Internally it works by adding {:nopats ...}
+ annotations to quantifiers.
+
+ ---- On variables ----------------------------------------------------------
+
+ {:existential true}
+ Marks a global Boolean variable as existentially quantified. If
+ used in combination with option /contractInfer Boogie will check
+ whether there exists a Boolean assignment to the existentials
+ that makes all verification conditions valid. Without option
+ /contractInfer the attribute is ignored.
+
+ ---- The end ---------------------------------------------------------------
+");
+ }
+
+ private static bool printedHelp = false;
+
+ public static void Usage()
+ {
+ // Ensure that we only print the help message once,
+ // no matter how many enabling conditions for printing
+ // help were triggered.
+ if (printedHelp) { return; }
+ printedHelp = true;
+
+ Console.WriteLine(@"Boogie: usage: Boogie [ option ... ] [ filename ... ]
+ where <option> is one of
+
+ ---- General options -------------------------------------------------------
+
+ /help : this message
+ /attrHelp : print a message about declaration attributes supported by
+ this implementation
+ /nologo : suppress printing of version number, copyright message
+ /env:<n> : print command line arguments
+ 0 - never, 1 (default) - during BPL print and prover log,
+ 2 - like 1 and also to standard output
+ /wait : await Enter from keyboard before terminating program
+ /xml:<file> : also produce output in XML format to <file>
+
+ ---- Spec# options ---------------------------------------------------------
+
+ If any of the following switches is included, only those methods specified
+ by some switch are translated into BoogiePL. Furthermore, a method is
+ not translated if a [Verify(false)] attribute applies to it or if the
+ flag /trExclude applies (see below).
+ /translate:<str> : include method if its full name contains substring <str>
+ /trMethod:<method> : include method if its name is <method>
+ Format: Name or Class.Name
+ /trClass:<class> : include method if the enclosing class is <class>
+ Format: Name or Qualification.Name
+ /trFile:<filename> : include method if it is contained in file <filename>
+ Format: Filename.ssc
+
+ /trExclude:<str> : exclude method it its full name contains substring <str>
+
+ /c[ontracts]:<file>
+ : apply the contracts from <file> to
+ the referenced assemblies of the input assembly.
+ Note: the contracts for Xyz must be in Xyz.Contracts
+ /methodology:<m> : selects the specification and verification methodology
+ b = boogie (default)
+ vs = visible-state
+ /level:<n> : 0 - reduced checks,
+ 1 - no modifies checking, 2 - full (default)
+ /useUncheckedContracts : generate purity axioms even when the postconditions
+ could not be checked to be sound (this option only for
+ experts and dare devils)
+ /modifiesDefault:<n> :
+ 0 - just what is declared
+ 1 - what is declared plus E.snapshot for every top-level
+ E.f, E.*, E.**, E[i], or E[*] in the modifies clause
+ 2 - (1) but also for nested E's
+ 3 - (1) plus this.snapshot
+ 4 - (2) plus this.snapshot
+ 5 - (default) (1) plus p.* for receiver parameter p not
+ occurring at the top-level of modifies clause as
+ p.f, p.*, p.**, p[i], p[*], or p.0
+ 6 - (5) but for every parameter p
+ /modifiesOnLoop:<n> : 0 - never, 1 - assume only (usual default),
+ 2 - assume and check (default with /level:2)
+ /localModifiesChecks: 0 - check modifies-clause as post-condition of a
+ procedure
+ 1 - check violations of modifies-clause at each
+ assignment and procedure call (default)
+ /loopUnroll:<n> : unroll loops, following up to n back edges (and then some)
+ /noVerifyByDefault : change the default to [Verify(false)]
+ /orderStrength:<n> : 0 (default) - only few properties of subtyping
+ axiomatized,
+ 1 - full strength
+ /summationStrength:<n> : 0 - less applicable triggers in the axioms
+ 1 - (default) default set of axioms for summation-
+ like quantifiers;
+ /arithDistributionAxioms : emit +/* distribution axioms
+ /inductiveMinMax:<n> : 0 (default) - extreme axioms for min/max;
+ 1 - inductive axioms for min/max;
+ 2 - both extreme and inductive axioms for min/max
+ 3,4,5 - like 0,1,2 but adding the plus-over-min/max
+ distribution axiom
+ Modes 1,2,4,5 imply /reflectAdd.
+ /fcoStrength:<n> : adjusts the amount of information encoded about 'first
+ consistent owners'
+ 0 - no FCO axiom, 1 - cheaper but weaker FCO axiom,
+ 2 - pure-method FCO axiom,
+ 3, 4, 5 (default) - like 0,1,2 plus more specific
+ FCO information on pure-method return
+ /ownerModelEncoding:<enc> : s = standard (default)
+ e = experimental
+ t = trivial (implied by /methodology:vs)
+ /printModel:<n> : 0 (default) - do not print Z3's error model
+ 1 - print Z3's error model
+ 2 - print Z3's error model plus reverse mappings
+ 4 - print Z3's error model in a more human readable way
+ /printModelToFile:<file> : print model to <file> instead of console
+ /enhancedErrorMessages:<n> : 0 (default) - no enhanced error messages
+ 1 - Z3 error model enhanced error messages
+
+ ---- Dafny options ---------------------------------------------------------
+
+ Multiple .dfy files supplied on the command line are concatenated into one
+ Dafny program.
+
+ /dprint:<file> : print Dafny program after parsing it
+ (use - as <file> to print to console)
+
+ ---- Boogie options --------------------------------------------------------
+
+ Multiple .bpl files supplied on the command line are concatenated into one
+ Boogie program.
+
+ /proc:<p> : limits which procedures to check
+ /noResolve : parse only
+ /noTypecheck : parse and resolve only
+
+ /print:<file> : print BoogiePL program after parsing it
+ (use - as <file> to print to console)
+ /printWithUniqueIds : print augmented information that uniquely
+ identifies variables
+ /printUnstructured : with /print option, desugars all structured statements
+ /printDesugared : with /print option, desugars calls
+
+ /overlookTypeErrors : skip any implementation with resolution or type
+ checking errors
+
+ ---- Inference options -----------------------------------------------------
+
+ /infer:<flags> : use abstract interpretation to infer invariants
+ The default is /infer:i" // This is not 100% true, as the /infer ALWAYS creates
+ // a multilattice, whereas if nothing is specified then
+ // intervals are isntantiated WITHOUT being embedded in
+ // a multilattice
+ + @"
+ <flags> are as follows (missing <flags> means all)
+ i = intervals
+ c = constant propagation
+ d = dynamic type
+ n = nullness
+ p = polyhedra for linear inequalities
+ s = debug statistics
+ 0..9 = number of iterations before applying a widen (default=0)
+ /loopInvOnDemand : Infer loop invariants on demand
+ /noinfer : turn off the default inference, and overrides the /infer
+ switch on its left
+ /checkInfer : instrument inferred invariants as asserts to be checked by
+ theorem prover
+ /interprocInfer : perform interprocedural inference
+ /contractInfer : perform procedure contract inference
+ /logInfer : print debug output during inference
+ /printInstrumented : print BoogiePL program after it has been
+ instrumented with invariants
+ /Houdini[:<flags>] : perform procedure Houdini
+ c = continue when an error found
+ i = use incremental queries
+ /dbgRefuted : log refuted Houdini candidates to XmlSink
+
+ ---- Debugging and general tracing options ---------------------------------
+
+ /trace : blurt out various debug trace information
+ /traceTimes : output timing information at certain points in the pipeline
+ /log[:method] : Print debug output during translation
+
+ /break[:method] : break into debugger
+
+ ---- Verification-condition generation options -----------------------------
+
+ /noVerify : skip VC generation and invocation of the theorem prover
+ /noRemoveEmptyBlocks : do not remove empty blocks during VC generation
+ /vc:<variety> : n = nested block (default for non-/prover:z3),
+ m = nested block reach,
+ b = flat block, r = flat block reach,
+ s = structured, l = local, d = dag (default with /prover:z3)
+ doomed = doomed
+ /traceverify : print debug output during verification condition generation
+ /subsumption:<c> : apply subsumption to asserted conditions:
+ 0 - never, 1 - not for quantifiers, 2 (default) - always
+ /bv:<bv> : bitvector handling
+ n = none
+ z = native Z3 bitvectors (default)
+ i = unsoundly translate bitvectors to integers
+ /inline:<i> : use inlining strategy <i> for procedures with the :inline
+ attribute, see /attrHelp for details:
+ n = none
+ m = macrolike (default)
+ b = bounded
+ /printInlined : print the implementation after inlining calls to
+ procedures with the :inline attribute (works with /inline)
+ /smoke : Soundness Smoke Test: try to stick assert false; in some
+ places in the BPL and see if we can still prove it
+ /smokeTimeout:<n> : Timeout, in seconds, for a single theorem prover
+ invocation during smoke test, defaults to 10.
+ /causalImplies : Translate Boogie's A ==> B into prover's A ==> A && B.
+ /typeEncoding:<m> : how to encode types when sending VC to theorem prover
+ n = none (unsound)
+ p = predicates (default)
+ a = arguments
+ /reflectAdd In the VC, generate an auxiliary symbol, elsewhere defined
+ to be +, instead of +.
+
+ ---- Verification-condition splitting --------------------------------------
+
+ /vcsMaxCost:<f> : VC will not be split unless the cost of a VC exceeds this
+ number, defaults to 2000.0. This does NOT apply in the
+ keep-going mode after first round of splitting.
+ /vcsMaxSplits:<n> : Maximal number of VC generated per method. In keep
+ going mode only applies to the first round.
+ Defaults to 1.
+ /vcsMaxKeepGoingSplits:<n> : If set to more than 1, activates the keep
+ going mode, where after the first round of splitting,
+ VCs that timed out are split into <n> pieces and retried
+ until we succeed proving them, or there is only one
+ assertion on a single path and it timeouts (in which
+ case error is reported for that assertion).
+ Defaults to 1.
+ /vcsKeepGoingTimeout:<n> : Timeout in seconds for a single theorem prover
+ invocation in keep going mode, except for the final
+ single-assertion case. Defaults to 1s.
+ /vcsFinalAssertTimeout:<n> : Timeout in seconds for the single last
+ assertion in the keep going mode. Defaults to 30s.
+ /vcsPathJoinMult:<f> : If more than one path join at a block, by how much
+ multiply the number of paths in that block, to accomodate
+ for the fact that the prover will learn something on one
+ paths, before proceeding to another. Defaults to 0.8.
+ /vcsPathCostMult:<f1>
+ /vcsAssumeMult:<f2> : The cost of a block is
+ (<assert-cost> + <f2>*<assume-cost>)*(1.0 + <f1>*<entering-paths>)
+ <f1> defaults to 1.0, <f2> defaults to 0.01.
+ The cost of a single assertion or assumption is
+ currently always 1.0.
+ /vcsPathSplitMult:<f> : If the best path split of a VC of cost A is into
+ VCs of cost B and C, then the split is applied if
+ A >= <f>*(B+C), otherwise assertion splitting will be
+ applied. Defaults to 0.5 (always do path splitting if
+ possible), set to more to do less path splitting
+ and more assertion splitting.
+ /vcsDumpSplits For split #n dump split.n.dot and split.n.bpl.
+ Warning: Affects error reporting.
+ /vcsCores:<n> : Try to verify <n> VCs at once. Defaults to 1.
+
+ ---- Prover options --------------------------------------------------------
+
+ /errorLimit:<num> : Limit the number of errors produced for each procedure
+ (default is 5, some provers may support only 1)
+ /timeLimit:<num> : Limit the number of seconds spent trying to verify
+ each procedure
+ /errorTrace:<n> : 0 - no Trace labels in the error output,
+ 1 (default) - include useful Trace labels in error output,
+ 2 - include all Trace labels in the error output
+ /vcBrackets:<b> : bracket odd-charactered identifier names with |'s. <b> is:
+ 0 - no (default with /prover:Z3),
+ 1 - yes (default with /prover:Simplify)
+ /prover:<tp> : use theorem prover <tp>, where <tp> is either the name of
+ a DLL containing the prover interface located in the
+ Boogie directory, or a full path to a DLL containing such
+ an interface. The standard interfaces shipped include:
+ Z3 (default)
+ Simplify
+ SMTLib (only writes to a file)
+ ContractInference (uses Z3)
+ Z3api (Z3 using Managed .NET API)
+ /proverOpt:KEY[=VALUE] : Provide a prover-specific option.
+ V1 - enables Z3 version 1.3 (with /prover:z3).
+ /proverLog:<file> : Log input for the theorem prover. Like filenames
+ supplied as arguments to other options, <file> can use the
+ following macros:
+ @TIME@' expands to the current time
+ @PREFIX@ expands to the concatenation of strings given
+ by /logPrefix options
+ @FILE@ expands to the last filename specified on the
+ command line
+ In addition, /proverLog can also use the macro '@PROC@',
+ which causes there to be one prover log file per
+ verification condition, and the macro then expands to the
+ name of the procedure that the verification condition is
+ for.
+ /logPrefix:<str> : Defines the expansion of the macro '@PREFIX@', which can
+ be used in various filenames specified by other options.
+ /proverLogAppend : Append (not overwrite) the specified prover log file
+ /proverWarnings : 0 (default) - don't print, 1 - print to stdout,
+ 2 - print to stderr
+ /proverMemoryLimit:<num> : Limit on the virtual memory for prover before
+ restart in MB (default:100MB)
+ /restartProver : Restart the prover after each query
+ /proverShutdownLimit<num> : Time between closing the stream to the prover and
+ killing the prover process (default: 0s)
+ /platform:<ptype>,<location>
+ : ptype = v11,v2,cli1
+ : location = platform libraries directory
+
+ Simplify specific options:
+ /simplifyMatchDepth:<num> : Set Simplify prover's matching depth limit
+
+ Z3 specific options:
+ /z3mam:<num> : Z3 matching engine: 0 (default) - eager instantiation,
+ 3 - lazy instantiation,
+ 4 - eager instantiation w/ matching-loop breaking heuristic
+ /z3opt:<arg> : specify additional Z3 options
+ /z3DebugTrace:<arg> : z3 command line options so that Z3 generates debug
+ tracing
+
+ SMT-Lib specific options:
+ /smtOutput:<file> : Path and basename to which the prover output is
+ written (default: boogie-vc-@PROC@.smt). The same
+ macros as in /proverLog can be used.
+
+ /z3types : generate multi-sorted VC that make use of Z3 types
+");
+ }
+ }
+}
diff --git a/Source/Core/Core.sscproj b/Source/Core/Core.sscproj
new file mode 100644
index 00000000..a1f8e9ca
--- /dev/null
+++ b/Source/Core/Core.sscproj
@@ -0,0 +1,212 @@
+<?xml version="1.0" encoding="utf-8"?>
+<VisualStudioProject>
+ <XEN ProjectType="Local"
+ SchemaVersion="1.0"
+ Name="Core"
+ ProjectGuid="47bc34f1-a173-40be-84c2-9332b4418387"
+ >
+ <Build>
+ <Settings ApplicationIcon=""
+ AssemblyName="Core"
+ OutputType="Library"
+ RootNamespace="Core"
+ StartupObject=""
+ TargetPlatform="v2"
+ TargetPlatformLocation=""
+ ShadowedAssembly=""
+ StandardLibraryLocation=""
+ >
+ <Config Name="Debug"
+ AllowUnsafeBlocks="False"
+ BaseAddress="285212672"
+ CheckForOverflowUnderflow="False"
+ ConfigurationOverrideFile=""
+ DefineConstants="DEBUG;TRACE;WHIDBEY"
+ DocumentationFile=""
+ DebugSymbols="True"
+ FileAlignment="4096"
+ IncrementalBuild="True"
+ Optimize="False"
+ OutputPath="bin\Debug"
+ RegisterForComInterop="False"
+ RemoveIntegerChecks="false"
+ TreatWarningsAsErrors="False"
+ WarningLevel="4"
+ RunProgramVerifier="False"
+ ProgramVerifierCommandLineOptions=""
+ ReferenceTypesAreNonNullByDefault="False"
+ RunProgramVerifierWhileEditing="False"
+ AllowPointersToManagedStructures="False"
+ CheckContractAdmissibility="True"
+ CheckPurity="False"
+ DisableAssumeChecks="False"
+ DisableDefensiveChecks="False"
+ DisableGuardedClassesChecks="False"
+ DisableInternalChecks="False"
+ DisableInternalContractsMetadata="False"
+ DisablePublicContractsMetadata="False"
+ DebugMode="Project"
+ StartProgram=""
+ StartURL=""
+ StartPage=""
+ UseIE="False"
+ EnableRemoteDebugging="False"
+ RemoteDebugMachine=""
+ />
+ <Config Name="Release"
+ AllowUnsafeBlocks="false"
+ BaseAddress="285212672"
+ CheckForOverflowUnderflow="false"
+ ConfigurationOverrideFile=""
+ DefineConstants="TRACE;WHIDBEY"
+ DocumentationFile=""
+ DebugSymbols="false"
+ FileAlignment="4096"
+ IncrementalBuild="false"
+ Optimize="true"
+ OutputPath="bin\release"
+ RegisterForComInterop="false"
+ RemoveIntegerChecks="false"
+ TreatWarningsAsErrors="True"
+ WarningLevel="4"
+ />
+ </Settings>
+ <References>
+ <Reference Name="Mscorlib.Contracts"
+ AssemblyName="Mscorlib.Contracts"
+ Private="false"
+ HintPath="../../Binaries/Mscorlib.Contracts.dll"
+ />
+ <Reference Name="System"
+ AssemblyName="System"
+ Private="false"
+ />
+ <Reference Name="System.Compiler.Framework"
+ AssemblyName="System.Compiler.Framework"
+ Private="true"
+ HintPath="../../Binaries/System.Compiler.Framework.dll"
+ />
+ <Reference Name="AIFramework"
+ Project="{24B55172-AD8B-47D1-8952-5A95CFDB9B31}"
+ Private="true"
+ />
+ <Reference Name="System.Compiler"
+ AssemblyName="System.Compiler"
+ Private="true"
+ HintPath="../../Binaries/System.Compiler.dll"
+ />
+ <Reference Name="System.Compiler.Contracts"
+ AssemblyName="System.Compiler.Contracts"
+ Private="false"
+ HintPath="../../Binaries/System.Compiler.Contracts.dll"
+ />
+ <Reference Name="Graph"
+ Project="{4C28FB90-630E-4B55-A937-11A011B79765}"
+ Private="true"
+ />
+ <Reference Name="System.XML"
+ AssemblyName="System.XML"
+ Private="false"
+ />
+ <Reference Name="System.Xml.Contracts"
+ AssemblyName="System.Xml.Contracts"
+ Private="false"
+ HintPath="../../Binaries/System.Xml.Contracts.dll"
+ />
+ <Reference Name="FSharp.Core"
+ AssemblyName="FSharp.Core"
+ Private="false"
+ HintPath="../../Binaries/FSharp.Core.dll"
+ />
+ <Reference Name="Basetypes"
+ Project="{0C692837-77EC-415F-BF04-395E3ED06E9A}"
+ Private="true"
+ />
+ </References>
+ </Build>
+ <Files>
+ <Include>
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="Absy.ssc"
+ />
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="..\version.ssc"
+ />
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="Duplicator.ssc"
+ />
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="OOLongUtil.ssc"
+ />
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="PureCollections.ssc"
+ />
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="ResolutionContext.ssc"
+ />
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="StandardVisitor.ssc"
+ />
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="Util.ssc"
+ />
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="CommandLineOptions.ssc"
+ />
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="scanner.ssc"
+ />
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="parser.ssc"
+ />
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="GraphAlgorithms.ssc"
+ />
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="AbsyType.ssc"
+ />
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="AbsyCmd.ssc"
+ />
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="AbsyExpr.ssc"
+ />
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="Xml.ssc"
+ />
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="Inline.ssc"
+ />
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="LoopUnroll.ssc"
+ />
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="VCExp.ssc"
+ />
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="TypeAmbiguitySeeker.ssc"
+ />
+ </Include>
+ </Files>
+ </XEN>
+</VisualStudioProject> \ No newline at end of file
diff --git a/Source/Core/Duplicator.ssc b/Source/Core/Duplicator.ssc
new file mode 100644
index 00000000..f3330739
--- /dev/null
+++ b/Source/Core/Duplicator.ssc
@@ -0,0 +1,348 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------------
+// BoogiePL - Duplicator.cs
+//---------------------------------------------------------------------------------------------
+
+using System.Collections;
+using System.Collections.Generic;
+
+namespace Microsoft.Boogie
+{
+ public class Duplicator : StandardVisitor
+ {
+ public override Absy! Visit(Absy! node)
+ {
+ node = base.Visit(node);
+ return node;
+ }
+
+ public override Cmd! VisitAssertCmd(AssertCmd! node)
+ {
+ return base.VisitAssertCmd ((AssertCmd)node.Clone());
+ }
+ public override Cmd! VisitAssignCmd(AssignCmd! node)
+ {
+ AssignCmd clone = (AssignCmd)node.Clone();
+ clone.Lhss = new List<AssignLhs!>(clone.Lhss);
+ clone.Rhss = new List<Expr!>(clone.Rhss);
+ return base.VisitAssignCmd (clone);
+ }
+ public override Cmd! VisitAssumeCmd(AssumeCmd! node)
+ {
+ return base.VisitAssumeCmd ((AssumeCmd)node.Clone());
+ }
+ public override AtomicRE! VisitAtomicRE(AtomicRE! node)
+ {
+ return base.VisitAtomicRE ((AtomicRE)node.Clone());
+ }
+ public override Axiom! VisitAxiom(Axiom! node)
+ {
+ return base.VisitAxiom ((Axiom)node.Clone());
+ }
+ public override Type! VisitBasicType(BasicType! node)
+ {
+ // do /not/ clone the type recursively
+ return (BasicType)node.Clone();
+ }
+ public override Block! VisitBlock(Block! node)
+ {
+ return base.VisitBlock ((Block)node.Clone());
+ }
+ public override BlockSeq! VisitBlockSeq(BlockSeq! blockSeq)
+ {
+ return base.VisitBlockSeq (blockSeq);
+ }
+ public override BoundVariable! VisitBoundVariable(BoundVariable! node)
+ {
+ return base.VisitBoundVariable ((BoundVariable)node.Clone());
+ }
+ public override Type! VisitBvType(BvType! node)
+ {
+ // do /not/ clone the type recursively
+ return (BvType)node.Clone();
+ }
+ public override Cmd! VisitCallCmd(CallCmd! node)
+ {
+ CallCmd! newNode = (CallCmd)node.Clone();
+ newNode.Ins = new List<Expr> (node.Ins);
+ newNode.Outs = new List<IdentifierExpr> (node.Outs);
+ return base.VisitCallCmd (node);
+ }
+ public override Choice! VisitChoice(Choice! node)
+ {
+ return base.VisitChoice ((Choice)node.Clone());
+ }
+ public override CmdSeq! VisitCmdSeq(CmdSeq! cmdSeq)
+ {
+ return base.VisitCmdSeq (cmdSeq);
+ }
+ public override Constant! VisitConstant(Constant! node)
+ {
+ return base.VisitConstant ((Constant)node.Clone());
+ }
+ public override CtorType! VisitCtorType(CtorType! node)
+ {
+ // do /not/ clone the type recursively
+ return (CtorType)node.Clone();
+ }
+ public override Declaration! VisitDeclaration(Declaration! node)
+ {
+ return base.VisitDeclaration ((Declaration)node.Clone());
+ }
+ public override List<Declaration!>! VisitDeclarationList(List<Declaration!>! declarationList)
+ {
+ return base.VisitDeclarationList(declarationList);
+ }
+ public override DeclWithFormals! VisitDeclWithFormals(DeclWithFormals! node)
+ {
+ return base.VisitDeclWithFormals ((DeclWithFormals)node.Clone());
+ }
+ public override ExistsExpr! VisitExistsExpr(ExistsExpr! node)
+ {
+ return base.VisitExistsExpr ((ExistsExpr)node.Clone());
+ }
+ public override Expr! VisitExpr(Expr! node)
+ {
+ return base.VisitExpr ((Expr)node.Clone());
+ }
+ public override ExprSeq! VisitExprSeq(ExprSeq! list)
+ {
+ return base.VisitExprSeq (new ExprSeq(list));
+ }
+ public override ForallExpr! VisitForallExpr(ForallExpr! node)
+ {
+ return base.VisitForallExpr ((ForallExpr)node.Clone());
+ }
+ public override Formal! VisitFormal(Formal! node)
+ {
+ return base.VisitFormal ((Formal)node.Clone());
+ }
+ public override Function! VisitFunction(Function! node)
+ {
+ return base.VisitFunction ((Function)node.Clone());
+ }
+ public override GlobalVariable! VisitGlobalVariable(GlobalVariable! node)
+ {
+ return base.VisitGlobalVariable ((GlobalVariable)node.Clone());
+ }
+ public override GotoCmd! VisitGotoCmd(GotoCmd! node)
+ {
+ return base.VisitGotoCmd ((GotoCmd)node.Clone());
+ }
+ public override Cmd! VisitHavocCmd(HavocCmd! node)
+ {
+ return base.VisitHavocCmd ((HavocCmd)node.Clone());
+ }
+ public override Expr! VisitIdentifierExpr(IdentifierExpr! node)
+ {
+ return base.VisitIdentifierExpr ((IdentifierExpr) node.Clone());
+ }
+ public override IdentifierExprSeq! VisitIdentifierExprSeq(IdentifierExprSeq! identifierExprSeq)
+ {
+ return base.VisitIdentifierExprSeq (new IdentifierExprSeq(identifierExprSeq));
+ }
+ public override Implementation! VisitImplementation(Implementation! node)
+ {
+ return base.VisitImplementation ((Implementation)node.Clone());
+ }
+ public override LiteralExpr! VisitLiteralExpr(LiteralExpr! node)
+ {
+ return base.VisitLiteralExpr ((LiteralExpr)node.Clone());
+ }
+ public override LocalVariable! VisitLocalVariable(LocalVariable! node)
+ {
+ return base.VisitLocalVariable ((LocalVariable)node.Clone());
+ }
+ public override AssignLhs! VisitMapAssignLhs(MapAssignLhs! node)
+ {
+ return base.VisitMapAssignLhs ((MapAssignLhs)node.Clone());
+ }
+ public override MapType! VisitMapType(MapType! node)
+ {
+ // do /not/ clone the type recursively
+ return (MapType)node.Clone();
+ }
+ public override Expr! VisitNAryExpr(NAryExpr! node)
+ {
+ return base.VisitNAryExpr ((NAryExpr)node.Clone());
+ }
+ public override Expr! VisitOldExpr(OldExpr! node)
+ {
+ return base.VisitOldExpr ((OldExpr) node.Clone());
+ }
+ public override Procedure! VisitProcedure(Procedure! node)
+ {
+ return base.VisitProcedure ((Procedure)node.Clone());
+ }
+ public override Program! VisitProgram(Program! node)
+ {
+ return base.VisitProgram ((Program) node.Clone());
+ }
+ public override QuantifierExpr! VisitQuantifierExpr(QuantifierExpr! node)
+ {
+ return base.VisitQuantifierExpr ((QuantifierExpr) node.Clone());
+ }
+ public override Cmd! VisitRE(RE! node)
+ {
+ return base.VisitRE ((RE) node.Clone());
+ }
+ public override RESeq! VisitRESeq(RESeq! reSeq)
+ {
+ return base.VisitRESeq (new RESeq(reSeq));
+ }
+ public override ReturnCmd! VisitReturnCmd(ReturnCmd! node)
+ {
+ return base.VisitReturnCmd ((ReturnCmd) node.Clone());
+ }
+ public override Sequential! VisitSequential(Sequential! node)
+ {
+ return base.VisitSequential ((Sequential) node.Clone());
+ }
+ public override AssignLhs! VisitSimpleAssignLhs(SimpleAssignLhs! node)
+ {
+ return base.VisitSimpleAssignLhs ((SimpleAssignLhs)node.Clone());
+ }
+ public override Cmd! VisitStateCmd(StateCmd! node)
+ {
+ return base.VisitStateCmd ((StateCmd)node.Clone());
+ }
+ public override TransferCmd! VisitTransferCmd(TransferCmd! node)
+ {
+ return base.VisitTransferCmd ((TransferCmd) node.Clone());
+ }
+ public override Trigger! VisitTrigger(Trigger! node)
+ {
+ return base.VisitTrigger ((Trigger) node.Clone());
+ }
+ public override Type! VisitType(Type! node)
+ {
+ // do /not/ clone the type recursively
+ return (Type)node.Clone();
+ }
+ public override TypedIdent! VisitTypedIdent(TypedIdent! node)
+ {
+ return base.VisitTypedIdent ((TypedIdent) node.Clone());
+ }
+ public override Variable! VisitVariable(Variable! node)
+ {
+ return node;
+ }
+ public override VariableSeq! VisitVariableSeq(VariableSeq! variableSeq)
+ {
+ return base.VisitVariableSeq (new VariableSeq(variableSeq));
+ }
+ public override Cmd! VisitAssertRequiresCmd(AssertRequiresCmd! node)
+ {
+ return base.VisitAssertRequiresCmd((AssertRequiresCmd)node.Clone());
+ }
+ public override Cmd! VisitAssertEnsuresCmd(AssertEnsuresCmd! node)
+ {
+ return base.VisitAssertEnsuresCmd((AssertEnsuresCmd)node.Clone());
+ }
+ public override Ensures! VisitEnsures(Ensures! node)
+ {
+ return base.VisitEnsures((Ensures)node.Clone());
+ }
+ public override Requires! VisitRequires(Requires! node)
+ {
+ return base.VisitRequires((Requires)node.Clone());
+ }
+ }
+
+
+ #region A duplicator that also does substitutions for a set of variables
+ /// <summary>
+ /// A substitution is a partial mapping from Variables to Exprs.
+ /// </summary>
+ public delegate Expr/*?*/ Substitution(Variable! v);
+
+ public static class Substituter
+ {
+ public static Substitution! SubstitutionFromHashtable(Hashtable/*Variable!->Expr!*/! map)
+ {
+ // TODO: With Whidbey, could use anonymous functions.
+ return new Substitution(new CreateSubstitutionClosure(map).Method);
+ }
+ private sealed class CreateSubstitutionClosure
+ {
+ Hashtable/*Variable!->Expr!*/! map;
+ public CreateSubstitutionClosure(Hashtable/*Variable!->Expr!*/! map) { this.map = map; base(); }
+ public Expr/*?*/ Method(Variable! v) { return (Expr) map[v]; }
+ }
+
+ /// <summary>
+ /// Apply a substitution to an expression. Any variables not in domain(subst)
+ /// is not changed. The substitutions applies within the "old", but the "old"
+ /// expression remains.
+ /// </summary>
+ public static Expr! Apply(Substitution! subst, Expr! expr)
+ {
+ return (Expr) new NormalSubstituter(subst).Visit(expr);
+ }
+
+ /// <summary>
+ /// Apply a substitution to an expression replacing "old" expressions.
+ /// Outside "old" expressions, the substitution "always" is applied; any variable not in
+ /// domain(always) is not changed. Inside "old" expressions, apply map "oldExpr" to
+ /// variables in domain(oldExpr), apply map "always" to variables in
+ /// domain(always)-domain(oldExpr), and leave variable unchanged otherwise.
+ /// </summary>
+ public static Expr! ApplyReplacingOldExprs(Substitution! always, Substitution! forold, Expr! expr)
+ {
+ return (Expr) new ReplacingOldSubstituter(always, forold).Visit(expr);
+ }
+
+ private sealed class NormalSubstituter : Duplicator
+ {
+ private readonly Substitution! subst;
+ public NormalSubstituter(Substitution! subst) { this.subst = subst; base(); }
+
+ public override Expr! VisitIdentifierExpr(IdentifierExpr! node)
+ {
+ Expr/*?*/ e = subst((!)node.Decl);
+ return e == null ? base.VisitIdentifierExpr(node) : e;
+ }
+ }
+
+ private sealed class ReplacingOldSubstituter : Duplicator
+ {
+ private readonly Substitution! always;
+ private readonly Substitution! forold;
+ public ReplacingOldSubstituter(Substitution! always, Substitution! forold)
+ { this.always = always; this.forold = forold; base(); }
+
+ private bool insideOldExpr = false;
+
+ public override Expr! VisitIdentifierExpr(IdentifierExpr! node)
+ {
+ Expr/*?*/ e = null;
+
+ if (insideOldExpr)
+ {
+ e = forold((!)node.Decl);
+ }
+
+ if (e == null)
+ {
+ e = always((!)node.Decl);
+ }
+
+ return e == null ? base.VisitIdentifierExpr(node) : e;
+ }
+
+ public override Expr! VisitOldExpr(OldExpr! node)
+ {
+ bool previouslyInOld = insideOldExpr;
+ insideOldExpr = true;
+ Expr! e = (Expr!)this.Visit(node.Expr);
+ insideOldExpr = previouslyInOld;
+ return e;
+ }
+ }
+ }
+ #endregion
+} \ No newline at end of file
diff --git a/Source/Core/Graph.as b/Source/Core/Graph.as
new file mode 100644
index 00000000..1466c341
--- /dev/null
+++ b/Source/Core/Graph.as
@@ -0,0 +1,352 @@
+using System.Collections;
+namespace Graphing;
+
+type Node = object;
+type Edge = <Node,Node>;
+
+class PreHeader {
+ Node myHeader;
+ PreHeader(Node h) { myHeader = h; }
+
+ public override string ToString() { return "#" + myHeader.ToString(); }
+}
+
+public class Graph {
+ private Set<Edge> es;
+ private Set<Node> ns;
+ private Node source;
+ private bool reducible;
+ private Set<Node> headers;
+ private Map<Node,Set<Node>> backEdgeNodes;
+ private Map<Edge,Set<Node>> naturalLoops;
+ private Map<Node,Set<Node>> dominatorMap;
+ private Map<Node,Set<Node>> immediateDominatorMap;
+
+ public Graph(Set<Edge> edges)
+ {
+ es = edges;
+ ns = Set<Node>{ x : <x,y> in es } + Set<Node>{ y : <x,y> in es };
+ }
+ public Graph()
+ { es = Set<Edge>{}; ns = Set<Node>{}; }
+
+ public void AddSource(Node x)
+ {
+ ns += Set<Node>{x};
+ source = x;
+ }
+ public void AddEdge(Node source, Node dest)
+ {
+ es += Set<Edge>{<source,dest>};
+ ns += Set<Node>{source, dest};
+ }
+
+ public Set<Node> Nodes { get { return ns; } }
+ public Set<Edge> Edges { get { return es; } }
+
+ public bool Edge(Node x, Node y) { return <x,y> in es; }
+ Set<Node> predecessors(Node n)
+ {
+ Set<Node> result = Set{ x : x in Nodes, Edge(x,n) };
+ return result;
+ }
+ public override string ToString() { return es.ToString(); }
+
+ public IEnumerable TopologicalSort()
+ {
+ <bool,Seq<Node>> <res,ns> = TopSort(this);
+ return res ? ns : null;
+ }
+ public void ComputeLoops()
+ {
+ <bool, Set<Node>, Map<Node,Set<Node>>, Map<Edge,Set<Node>>>
+ <reducible,headers,backEdgeNodes,naturalLoops> = Reducible(this,this.source);
+ this.reducible = reducible;
+ this.headers = headers;
+ this.backEdgeNodes = backEdgeNodes;
+ this.naturalLoops = naturalLoops;
+ return;
+ }
+ public bool Reducible { get { return reducible; } }
+ public IEnumerable Headers { get { return headers; } }
+ public IEnumerable BackEdgeNodes(Node h) { return h in backEdgeNodes ? backEdgeNodes[h] : null; }
+ public IEnumerable NaturalLoops(Node header, Node backEdgeNode)
+ { Edge e = <backEdgeNode,header>; return e in naturalLoops ? naturalLoops[e] : null; }
+ public bool Acyclic { get { return Acyclic(this,this.source); } }
+ public Map<Node,Set<Node>> DominatorMap
+ {
+ get {
+ if (dominatorMap == null) dominatorMap = ComputeDominators(this, source);
+ return dominatorMap;
+ }
+ }
+ public Map<Node,Set<Node>> ImmediateDominatorMap
+ {
+ get {
+ if (immediateDominatorMap == null)
+ {
+ immediateDominatorMap = Map{};
+ foreach(Node y in Nodes)
+ {
+ Set<Node> nodesThatYDominates = Set{ x : x in Nodes, x != y && (y in DominatorMap[x]) };
+ Set<Node> immediateDominatees = Set{ x : x in nodesThatYDominates,
+ !(Exists{ v != y && v != x && (v in DominatorMap[x]) : v in nodesThatYDominates })
+ };
+ immediateDominatorMap[y] = immediateDominatees;
+ }
+ }
+ return immediateDominatorMap;
+ }
+ }
+ public Set<Node> ImmediatelyDominatedBy(Node n) { return ImmediateDominatorMap[n]; }
+
+}
+
+// From AsmL distribution example: TopologicalSort
+<bool,Seq<Node>> TopSort(Graph g)
+{
+ Seq<Node> S = Seq{};
+ Set<Node> V = g.Nodes;
+ bool change = true;
+ while ( change )
+ {
+ change = false;
+ Set<Node> X = V - ((Set<Node>) S);
+ if ( X != Set{} )
+ {
+ Node temp = Choose{ v : v in X, !(Exists{ g.Edge(u,v) : u in X }) ifnone null };
+ if ( temp == null )
+ {
+ return <false,Seq<Node>{}>;
+ }
+ else if ( temp != Seq<Node>{} )
+ {
+ S += Seq{temp};
+ change = true;
+ }
+ }
+ }
+ return <true,S>;
+}
+
+bool Acyclic(Graph g, Node source)
+{
+ <bool,Seq<Node>> <acyc,xs> = TopSort(g);
+ return acyc;
+}
+
+//
+// [Dragon, pp. 670--671]
+// returns map D s.t. d in D(n) iff d dom n
+//
+Map<Node,Set<Node>> ComputeDominators(Graph g, Node source) {
+ Set<Node> N = g.Nodes;
+ Set<Node> nonSourceNodes = N - Set{source};
+ Map<Node,Set<Node>> D = Map{};
+ D[source] = Set<Node>{ source };
+ foreach (Node n in nonSourceNodes)
+ {
+ D[n] = N;
+ }
+ bool change = true;
+ while ( change )
+ {
+ change = false;
+ foreach (Node n in nonSourceNodes)
+ {
+ Set<Set<Node>> allPreds = Set{ D[p] : p in g.predecessors(n) };
+ Set<Node> temp = Set<Node>{ n } + BigIntersect(allPreds);
+ if ( temp != D[n] )
+ {
+ change = true;
+ D[n] = temp;
+ }
+ }
+ }
+ return D;
+}
+
+// [Dragon, Fig. 10.15, p. 604. Algorithm for constructing the natural loop.]
+Set<Node> NaturalLoop(Graph g, Edge backEdge)
+{
+ <Node,Node> <n,d> = backEdge;
+ Seq<Node> stack = Seq{};
+ Set<Node> loop = Set{ d };
+ if ( n != d ) // then n is not in loop
+ {
+ loop += Set{ n };
+ stack = Seq{ n } + stack; // push n onto stack
+ }
+ while ( stack != Seq{} ) // not empty
+ {
+ Node m = Head(stack);
+ stack = Tail(stack); // pop stack
+ foreach (Node p in g.predecessors(m))
+ {
+ if ( !(p in loop) )
+ {
+ loop += Set{ p };
+ stack = Seq{ p } + stack; // push p onto stack
+ }
+ }
+ }
+ return loop;
+}
+
+// [Dragon, p. 606]
+<bool, Set<Node>, Map<Node,Set<Node>>, Map<Edge,Set<Node>>>
+ Reducible(Graph g, Node source) {
+ // first, compute the dom relation
+ Map<Node,Set<Node>> D = g.DominatorMap;
+ return Reducible(g,source,D);
+}
+
+// [Dragon, p. 606]
+<bool, Set<Node>, Map<Node,Set<Node>>, Map<Edge,Set<Node>>>
+ Reducible(Graph g, Node source, Map<Node,Set<Node>> DomRelation) {
+
+ Set<Edge> edges = g.Edges;
+ Set<Edge> backEdges = Set{};
+ Set<Edge> nonBackEdges = Set{};
+ foreach (Edge e in edges)
+ {
+ <Node,Node> <x,y> = e; // so there is an edge from x to y
+ if ( y in DomRelation[x] ) // y dom x: which means y dominates x
+ {
+ backEdges += Set{ e };
+ }
+ else
+ {
+ nonBackEdges += Set{ e };
+ }
+ }
+ if ( !Acyclic(new Graph(nonBackEdges), source) )
+ {
+ return <false,Set<Node>{},Map<Node,Set<Node>>{},Map<Edge,Set<Node>>{}>;
+ }
+ else
+ {
+ Set<Node> headers = Set{ d : <n,d> in backEdges };
+ Map<Node,Set<Node>> backEdgeNodes = Map{ h -> bs : h in headers, bs = Set<Node>{ b : <b,x> in backEdges, x == h } };
+ Map<Edge,Set<Node>> naturalLoops = Map{ e -> NaturalLoop(g,e) : e in backEdges };
+
+ return <true, headers, backEdgeNodes, naturalLoops>;
+ }
+}
+
+// [Dragon, p. 606]
+bool OldReducible(Graph g, Node source) {
+ // first, compute the dom relation
+ Map<Node,Set<Node>> D = ComputeDominators(g, source);
+ return OldReducible(g,source,D);
+}
+
+// [Dragon, p. 606]
+bool OldReducible(Graph g, Node source, Map<Node,Set<Node>> DomRelation) {
+
+ Set<Edge> edges = g.Edges;
+ Set<Edge> backEdges = Set{};
+ Set<Edge> nonBackEdges = Set{};
+ foreach (Edge e in edges)
+ {
+ <Node,Node> <x,y> = e;
+ if ( y in DomRelation[x] ) // y dom x
+ {
+ backEdges += Set{ e };
+ }
+ else
+ {
+ nonBackEdges += Set{ e };
+ }
+ }
+ WriteLine("backEdges: " + backEdges);
+ WriteLine("nonBackEdges: " + nonBackEdges);
+ if ( Acyclic(new Graph(nonBackEdges), source) )
+ {
+ foreach(Edge e in backEdges)
+ {
+ Set<Node> naturalLoop = NaturalLoop(g,e);
+ WriteLine("Natural loop for back edge '" + e + "' is: " + naturalLoop);
+ }
+ Set<Node> headers = Set{ d : <n,d> in backEdges };
+ WriteLine("Loop headers = " + headers);
+
+ edges -= backEdges; // this cuts all of the back edges
+ foreach (Node h in headers)
+ {
+ Set<Edge> bs = Set{ <n,d> : <n,d> in backEdges, d == h };
+ Set<Node> preds = Set<Node>{ p : <p,y> in edges, y == h };
+ Node preheader = new PreHeader(h);
+ edges += Set{ <preheader,h> };
+ foreach (Node p in preds)
+ {
+ edges -= Set{ <p,h> };
+ edges += Set{ <p,preheader> };
+ }
+ }
+ Graph newGraph = new Graph(edges);
+ WriteLine("transformed graph = " + newGraph);
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+void Main()
+{
+ Graph g;
+ Map<Node,Set<Node>> D;
+/*
+ g = new Graph(Set<Edge>{ <1,2>, <1,3>, <2,3> });
+ g.AddSource(1);
+ Map<Node,Set<Node>> doms = ComputeDominators(g,1);
+ WriteLine(doms);
+*/
+ g = new Graph(Set<Edge>{
+ <1,2>, <1,3>,
+ <2,3>,
+ <3,4>,
+ <4,3>, <4,5>, <4,6>,
+ <5,7>,
+ <6,7>,
+ <7,4>, <7,8>,
+ <8,3>, <8,9>, <8,10>,
+ <9,1>,
+ <10,7>
+ });
+ g.AddSource(1);
+ WriteLine("G = " + g);
+ D = ComputeDominators(g,1);
+ WriteLine("Dom relation: " + D);
+ WriteLine("G's Dominator Map = " + g.DominatorMap);
+ WriteLine("G's Immediate Dominator Map = " + g.ImmediateDominatorMap);
+ WriteLine("G is reducible: " + OldReducible(g,1,D));
+ g.ComputeLoops();
+
+ WriteLine("");
+
+ g = new Graph(Set<Edge>{ <1,2>, <1,3>, <2,3>, <3,2> });
+ g.AddSource(1);
+ WriteLine("G = " + g);
+ D = ComputeDominators(g,1);
+ WriteLine("Dom relation: " + D);
+ WriteLine("G's Dominator Map = " + g.DominatorMap);
+ WriteLine("G's Immediate Dominator Map = " + g.ImmediateDominatorMap);
+ WriteLine("G is reducible: " + OldReducible(g,1,D));
+ g.ComputeLoops();
+
+ WriteLine("");
+
+ g = new Graph(Set<Edge>{ <1,2>, <2,3>, <2,4>, <3,2> });
+ g.AddSource(1);
+ WriteLine("G = " + g);
+ WriteLine("G's Dominator Map = " + g.DominatorMap);
+ WriteLine("G's Immediate Dominator Map = " + g.ImmediateDominatorMap);
+// D = ComputeDominators(g,1);
+// WriteLine("Dom relation: " + D);
+// WriteLine("G is reducible: " + OldReducible(g,1,D));
+ g.ComputeLoops();
+
+} \ No newline at end of file
diff --git a/Source/Core/GraphAlgorithms.ssc b/Source/Core/GraphAlgorithms.ssc
new file mode 100644
index 00000000..7ce07d6e
--- /dev/null
+++ b/Source/Core/GraphAlgorithms.ssc
@@ -0,0 +1,175 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using System.Collections.Generic;
+using Microsoft.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>
+ {
+ private IDictionary<Node,object>! nodesMap = new Dictionary<Node,object>();
+ private ICollection<Node>! nodes { get { return (!) nodesMap.Keys; } }
+
+ [Pure] [GlobalAccess(false)] [Escapes(true,false)]
+ System.Collections.IEnumerator! System.Collections.IEnumerable.GetEnumerator()
+ {
+ return ((System.Collections.IEnumerable)nodes).GetEnumerator();
+ }
+
+ [Pure] [GlobalAccess(false)] [Escapes(true,false)]
+ IEnumerator<Node>! IEnumerable<Node>.GetEnumerator()
+ {
+ 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][Reads(ReadsAttribute.Reads.Owned)]
+ public bool Contains(Node item) { return nodesMap.ContainsKey(item); }
+ public void CopyTo(Node[]! array, int arrayIndex) { nodes.CopyTo(array, arrayIndex); }
+ public bool Remove(Node item) { return nodesMap.Remove(item); }
+ }
+
+ public sealed class StronglyConnectedComponents<Node> : IEnumerable<SCC<Node>!>
+ {
+ private readonly IDictionary<Node!,object>! graph;
+ 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)
+ ensures !Computed;
+ {
+ IDictionary<Node!,object>! dict = new Dictionary<Node!,object>();
+ foreach (Node! n in graph) { 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()
+ {
+ return ((System.Collections.IEnumerable)sccs).GetEnumerator();
+ }
+
+ [Pure] [GlobalAccess(false)] [Escapes(true,false)]
+ IEnumerator<SCC<Node>!>! IEnumerable<SCC<Node>!>.GetEnumerator()
+ {
+ assume Computed;
+ return ((IEnumerable<SCC<Node>!>)sccs).GetEnumerator();
+ }
+
+ private readonly IList<SCC<Node>!>! sccs = new List<SCC<Node>!>();
+
+ public void Compute()
+ requires !Computed;
+ ensures Computed;
+ {
+ // Compute post times on graph with edges reversed
+ this.dfsNext = this.preds;
+ foreach (Node! n in (!)graph.Keys)
+ {
+ if (!seen.ContainsKey(n))
+ {
+ OrderNodes(n);
+ }
+ }
+
+ // Clear seen
+ seen.Clear();
+
+ // Compute SCCs
+ this.dfsNext = this.succs;
+ while (postOrder.Count > 0)
+ {
+ Node! n = postOrder.Pop();
+
+ 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!>();
+
+ // DFS to order nodes by post times
+ private void OrderNodes(Node! node)
+ {
+ seen.Add(node,null);
+
+ assert dfsNext != null;
+ System.Collections.IEnumerable! nexts = dfsNext(node);
+ foreach (Node! n in nexts)
+ {
+ if (graph.ContainsKey(n) && !seen.ContainsKey(n)) { OrderNodes(n); }
+ }
+
+ postOrder.Push(node);
+ }
+
+ // DFS to compute SCCs
+ private void FindSCCs(Node! node, SCC<Node>! currSCC)
+ //modifies currSCC.*;
+ {
+ seen.Add(node,null);
+ currSCC.Add(node);
+
+ assert dfsNext != null;
+ System.Collections.IEnumerable! nexts = dfsNext(node);
+ foreach (Node! n in nexts)
+ {
+ if (graph.ContainsKey(n) && !seen.ContainsKey(n)) { FindSCCs(n,currSCC); }
+ }
+ }
+
+ [Pure][Reads(ReadsAttribute.Reads.Owned)]
+ public override string! ToString()
+ {
+ string outStr = "";
+ int i = 0;
+
+ foreach(ICollection<Node> component in this)
+ {
+ string! tmp = System.String.Format("\nComponent #{0} = ", i++);
+ outStr += tmp;
+
+ bool firstInRow = true;
+
+ foreach(Node b in component)
+ {
+ string! tmpComponent = System.String.Format("{0}{1}", firstInRow? "" : ", ", b);
+ outStr += tmpComponent;
+ firstInRow = false;
+ }
+ }
+ return outStr;
+ }
+
+ }
+}
diff --git a/Source/Core/Inline.ssc b/Source/Core/Inline.ssc
new file mode 100644
index 00000000..931c35eb
--- /dev/null
+++ b/Source/Core/Inline.ssc
@@ -0,0 +1,907 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+namespace Microsoft.Boogie {
+
+ using System;
+ using System.IO;
+ using System.Collections;
+ using System.Collections.Generic;
+ using BoogiePL;
+ using System.Diagnostics;
+ using System.Text.RegularExpressions; // for procedure inlining
+
+ // this callback is called before inlining a procedure
+ public delegate void InlineCallback(Implementation! impl);
+
+ public class Inliner
+ {
+ private InlineCallback inlineCallback;
+ private TypecheckingContext! checkingCtx;
+
+ // Maximum number of unrolling per procedure.
+ // This is now given as a commnd line option.
+ // While typically this number will be given with the :inline attribute in the source code
+ // we set this bound in case the programmer does not provide the number along with the :inline attribute.
+ public static int MaxUnrollPerProcedure = 3;
+
+ protected CodeCopier! codeCopier;
+
+ protected Dictionary<string!,int>! /* Procedure.Name -> int */ recursiveProcUnrollMap;
+
+ protected Dictionary<string!,int>! /* Procedure.Name -> int */ inlinedProcLblMap;
+
+ protected void NextInlinedProcLabel(string! procName) {
+ int currentId;
+ if (inlinedProcLblMap.TryGetValue(procName, out currentId)) {
+ inlinedProcLblMap[procName] = currentId + 1;
+ } else {
+ inlinedProcLblMap.Add(procName, 0);
+ }
+ }
+
+ protected string! GetInlinedProcLabel(string! procName) {
+ int currentId;
+ if (!inlinedProcLblMap.TryGetValue(procName, out currentId)) {
+ currentId = 0;
+ inlinedProcLblMap.Add(procName, currentId);
+ }
+ return "inline$" + procName + "$" + currentId;
+ }
+
+ protected string! GetProcVarName(string! procName, string! formalName) {
+ string! prefix = GetInlinedProcLabel(procName);
+ return prefix + "$" + formalName;
+ }
+
+ protected Inliner(TypecheckingContext! ctx, InlineCallback cb) {
+ inlinedProcLblMap = new Dictionary<string!,int>();
+ recursiveProcUnrollMap = new Dictionary<string!,int>();
+ codeCopier = new CodeCopier();
+ inlineCallback = cb;
+ checkingCtx = ctx;
+ }
+
+ public static void ProcessImplementation(TypecheckingContext! ctx, Program! program, Implementation! impl, InlineCallback cb)
+ requires impl.Proc != null;
+ {
+ Inliner inliner = new Inliner(ctx, cb);
+
+ VariableSeq! newInParams = new VariableSeq(impl.InParams);
+ VariableSeq! newOutParams = new VariableSeq(impl.OutParams);
+ VariableSeq! newLocalVars = new VariableSeq(impl.LocVars);
+
+ IdentifierExprSeq! newModifies = new IdentifierExprSeq(impl.Proc.Modifies);
+
+ bool inlined = false;
+ List<Block!>! newBlocks = inliner.DoInline(impl.Blocks, program, newLocalVars, newModifies, out inlined);
+
+ if (!inlined) return;
+
+ impl.InParams = newInParams;
+ impl.OutParams = newOutParams;
+ impl.LocVars = newLocalVars;
+ impl.Blocks = newBlocks;
+ impl.Proc.Modifies = newModifies;
+
+ impl.ResetImplFormalMap();
+
+ // we need to resolve the new code
+ inliner.ResolveImpl(program, impl);
+
+ if(CommandLineOptions.Clo.PrintInlined) {
+ inliner.EmitImpl(impl);
+ }
+ }
+
+
+ public static void ProcessImplementation(TypecheckingContext! ctx, Program! program, Implementation! impl)
+ requires impl.Proc != null;
+ {
+
+ ProcessImplementation(ctx, program, impl, null);
+ }
+
+ protected void EmitImpl(Implementation! impl)
+ requires impl.Proc != null;
+ {
+ Console.WriteLine("after inlining procedure calls");
+ impl.Proc.Emit(new TokenTextWriter("<console>", Console.Out), 0);
+ impl.Emit(new TokenTextWriter("<console>", Console.Out), 0);
+ }
+
+ private sealed class DummyErrorSink : IErrorSink
+ {
+ public void Error(IToken! tok, string! msg) {
+ // FIXME
+ // noop.
+ // This is required because during the resolution, some resolution errors happen
+ // (such as the ones caused addion of loop invariants J_(block.Label) by the AI package
+ }
+ }
+
+ protected void ResolveImpl(Program! program, Implementation! impl)
+ ensures impl.Proc != null;
+ {
+ ResolutionContext rc = new ResolutionContext(new DummyErrorSink());
+
+ foreach(Declaration decl in program.TopLevelDeclarations) {
+ decl.Register(rc);
+ }
+
+ impl.Proc = null; // to force Resolve() redo the operation
+ impl.Resolve(rc);
+
+ TypecheckingContext tc = new TypecheckingContext(new DummyErrorSink());
+
+ impl.Typecheck(tc);
+ }
+
+
+ // returns true if it is ok to further unroll the procedure
+ // otherwise, the procedure is not inlined at the call site
+ protected bool CheckInline(Implementation! impl) {
+ string! procName = impl.Name;
+ int c;
+ if (recursiveProcUnrollMap.TryGetValue(procName, out c)) {
+ if(c > 0) {
+ if (CommandLineOptions.Clo.ProcedureInlining == CommandLineOptions.Inlining.Bounded) {
+ recursiveProcUnrollMap[procName] = c - 1;
+ }
+ return true;
+ }
+ recursiveProcUnrollMap[procName] = 0;
+ return false;
+ }
+
+ bool doinline = false;
+
+ QKeyValue kv = null;
+ // try proc attributes
+ if(impl.Proc != null) {
+ kv = impl.Proc.Attributes;
+ while(kv != null) {
+ if(kv.Key.Equals("inline")) {
+ doinline = true;
+ break;
+ }
+ kv = kv.Next;
+ }
+ }
+ // try impl attributes
+ if(!doinline) {
+ kv = impl.Attributes;
+ while(kv != null) {
+ if(kv.Key.Equals("inline")) {
+ doinline = true;
+ break;
+ }
+ kv = kv.Next;
+ }
+ }
+
+ // try impl attributes
+ if(doinline) {
+ assert(kv != null && kv.Key.Equals("inline"));
+ // check the recursion
+ if (!recursiveProcUnrollMap.TryGetValue(procName, out c)) {
+ c = MaxUnrollPerProcedure;
+ if (kv.Params.Count == 1) {
+ LiteralExpr lit = kv.Params[0] as LiteralExpr;
+ if (lit != null && lit.isBigNum) {
+ c = lit.asBigNum.ToIntSafe;
+ }
+ }
+ recursiveProcUnrollMap.Add(procName, c);
+ }
+
+ if(c > 0) {
+ if (CommandLineOptions.Clo.ProcedureInlining == CommandLineOptions.Inlining.Bounded) {
+ recursiveProcUnrollMap[procName] = c - 1;
+ }
+ return true;
+ }
+ recursiveProcUnrollMap[procName] = 0;
+ return false;
+ }
+
+ // if not inlined, then record its inline count as 0
+ recursiveProcUnrollMap[procName] = 0;
+ return false;
+ }
+
+
+ private List<Block!>! DoInlineBlocks(Stack<Procedure!>! callStack, List<Block!>! blocks, Program! program,
+ VariableSeq! newLocalVars, IdentifierExprSeq! newModifies, ref bool inlinedSomething)
+ {
+ List<Block!>! newBlocks = new List<Block!>();
+
+ foreach(Block block in blocks) {
+
+ TransferCmd! transferCmd = (!) block.TransferCmd;
+
+ CmdSeq cmds = block.Cmds;
+ CmdSeq newCmds = new CmdSeq();
+ Block newBlock;
+ string label = block.Label;
+ int lblCount = 0;
+
+ for(int i = 0; i < cmds.Length; ++i) {
+ Cmd cmd = cmds[i];
+
+ CallCmd callCmd = cmd as CallCmd;
+
+ if(callCmd == null) {
+ // if not call command, leave it as is
+ newCmds.Add(codeCopier.CopyCmd(cmd));
+
+ } else {
+ assert(callCmd.Proc != null);
+ Procedure proc = null;
+ Implementation impl = null;
+ string calleeName = callCmd.Proc.Name;
+
+ bool inline = false;
+
+ // *** now we do not allow constructors to be inlined
+ if(! calleeName.Contains("..ctor")) {
+ // FIXME why on earth are we searching by name?!
+ bool implExists = FindProcImpl(program, calleeName, out proc, out impl);
+ assume(!implExists || (proc != null && impl != null));
+ if(implExists) {
+ if(CheckInline((!)impl)) {
+ inline = true;
+ inlinedSomething = true;
+ }
+ }
+ }
+
+ if (impl != null && CommandLineOptions.Clo.ProcedureInlining == CommandLineOptions.Inlining.MacroLike) {
+ foreach (Procedure! p in callStack) {
+ if (p == impl.Proc) {
+ inline = false;
+ string msg = "";
+ foreach (Procedure! p in callStack) {
+ msg = p.Name + " -> " + msg;
+ }
+ msg += p.Name;
+ checkingCtx.Error(impl, "the inlined procedure is recursive, call stack: {0}", msg);
+ }
+ }
+ }
+
+ assert(!inline || (impl != null));
+
+ if(inline) { // at least one block should exist
+ assume(impl != null && proc != null);
+ assert(((!)impl.OriginalBlocks).Count > 0);
+
+ // do inline now
+ int nextlblCount = lblCount + 1;
+ string nextBlockLabel = label + "$" + nextlblCount;
+
+ // run the callback before each inline
+ if(inlineCallback != null) {
+ inlineCallback(impl);
+ }
+
+ // increment the counter for the procedure to be used in constructing the locals and formals
+ NextInlinedProcLabel(proc.Name);
+
+ BeginInline(newLocalVars, newModifies, proc, impl);
+
+ List<Block!>! inlinedBlocks = CreateInlinedBlocks(callCmd, proc, impl, nextBlockLabel);
+
+ EndInline();
+
+ callStack.Push((!)impl.Proc);
+ inlinedBlocks = DoInlineBlocks(callStack, inlinedBlocks, program, newLocalVars, newModifies, ref inlinedSomething);
+ callStack.Pop();
+
+ Block! startBlock = inlinedBlocks[0];
+
+ GotoCmd gotoCmd = new GotoCmd(Token.NoToken, new StringSeq(startBlock.Label));
+ newBlock = new Block(block.tok, ((lblCount == 0) ? (label) : (label + "$" + lblCount)), newCmds, gotoCmd);
+
+ newBlocks.Add(newBlock);
+ newBlocks.AddRange(inlinedBlocks);
+
+ lblCount = nextlblCount;
+ newCmds = new CmdSeq();
+
+ } else {
+ // if this call will not be inlined, so leave it as is
+ newCmds.Add(codeCopier.CopyCmd(callCmd));
+ }
+ }
+ }
+
+ newBlock = new Block(block.tok, ((lblCount == 0) ? (label) : (label + "$" + lblCount)), newCmds, codeCopier.CopyTransferCmd(transferCmd));
+ newBlocks.Add(newBlock);
+ }
+
+ return newBlocks;
+ }
+
+ protected List<Block!>! DoInline(List<Block!>! blocks, Program! program, VariableSeq! newLocalVars, IdentifierExprSeq! newModifies, out bool inlined)
+ {
+ inlinedProcLblMap.Clear();
+ recursiveProcUnrollMap.Clear();
+
+ inlined = false;
+ return DoInlineBlocks(new Stack<Procedure!>(), blocks, program, newLocalVars, newModifies, ref inlined);
+ }
+
+ protected void BeginInline(VariableSeq! newLocalVars, IdentifierExprSeq! newModifies, Procedure! proc, Implementation! impl) {
+ Hashtable substMap = new Hashtable();
+
+ foreach(Variable! locVar in (!)impl.OriginalLocVars) {
+ LocalVariable localVar = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, GetProcVarName(proc.Name, locVar.Name), locVar.TypedIdent.Type, locVar.TypedIdent.WhereExpr));
+ newLocalVars.Add(localVar);
+ IdentifierExpr ie = new IdentifierExpr(Token.NoToken, localVar);
+ substMap.Add(locVar, ie);
+ }
+
+ for (int i = 0; i < impl.InParams.Length; i++) {
+ Variable inVar = (!) impl.InParams[i];
+ LocalVariable localVar = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, GetProcVarName(proc.Name, inVar.Name), inVar.TypedIdent.Type, inVar.TypedIdent.WhereExpr));
+ newLocalVars.Add(localVar);
+ IdentifierExpr ie = new IdentifierExpr(Token.NoToken, localVar);
+ substMap.Add(inVar, ie);
+ // also add a substitution from the corresponding formal occurring in the PROCEDURE declaration
+ Variable procInVar = (!)proc.InParams[i];
+ if (procInVar != inVar) {
+ substMap.Add(procInVar, ie);
+ }
+ }
+
+ for (int i = 0; i < impl.OutParams.Length; i++) {
+ Variable outVar = (!) impl.OutParams[i];
+ LocalVariable localVar = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, GetProcVarName(proc.Name, outVar.Name), outVar.TypedIdent.Type, outVar.TypedIdent.WhereExpr));
+ newLocalVars.Add(localVar);
+ IdentifierExpr ie = new IdentifierExpr(Token.NoToken, localVar);
+ substMap.Add(outVar, ie);
+ // also add a substitution from the corresponding formal occurring in the PROCEDURE declaration
+ Variable procOutVar = (!)proc.OutParams[i];
+ if (procOutVar != outVar) {
+ substMap.Add(procOutVar, ie);
+ }
+ }
+
+ Hashtable /*Variable -> Expr*/ substMapOld = new Hashtable/*Variable -> Expr*/();
+
+ foreach (IdentifierExpr! mie in proc.Modifies) {
+ Variable! mVar = (!) mie.Decl;
+ LocalVariable localVar = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, GetProcVarName(proc.Name, mVar.Name), mVar.TypedIdent.Type));
+ newLocalVars.Add(localVar);
+ IdentifierExpr ie = new IdentifierExpr(Token.NoToken, localVar);
+ substMapOld.Add(mVar, ie);
+ // FIXME why are we doing this? the modifies list should already include them.
+ // add the modified variable to the modifies list of the procedure
+ if(!newModifies.Has(mie)) {
+ newModifies.Add(mie);
+ }
+ }
+
+ codeCopier.Subst = Substituter.SubstitutionFromHashtable(substMap);
+ codeCopier.SubstForOld = Substituter.SubstitutionFromHashtable(substMapOld);
+ }
+
+ protected void EndInline() {
+ codeCopier.Subst = null;
+ codeCopier.SubstForOld = null;
+ }
+
+
+ // result[0] is the entry block
+ protected List<Block!>! CreateInlinedBlocks(CallCmd! callCmd, Procedure! proc, Implementation! impl, string! nextBlockLabel)
+ requires (codeCopier.Subst != null);
+ requires (codeCopier.SubstForOld != null);
+ {
+
+ List<Block!>! implBlocks = (!)impl.OriginalBlocks;
+ assert (implBlocks.Count > 0);
+
+ string startLabel = implBlocks[0].Label;
+
+ List<Block!>! inlinedBlocks = new List<Block!>();
+
+ // create in block
+ CmdSeq inCmds = new CmdSeq();
+
+ // assign in parameters
+ for(int i = 0; i < impl.InParams.Length; ++i) {
+ Cmd cmd = Cmd.SimpleAssign(impl.tok,
+ (IdentifierExpr) (!) codeCopier.Subst( (!)impl.InParams[i]),
+ (!)callCmd.Ins[i]);
+ inCmds.Add(cmd);
+ }
+
+ // inject non-free requires
+ for (int i = 0; i < proc.Requires.Length; i++) {
+ Requires! req = (!) proc.Requires[i];
+ if (!req.Free) {
+ Requires! reqCopy = (Requires!) req.Clone();
+ reqCopy.Condition = codeCopier.CopyExpr(req.Condition);
+ AssertCmd! a = new AssertRequiresCmd(callCmd, reqCopy);
+ a.ErrorDataEnhanced = reqCopy.ErrorDataEnhanced;
+ inCmds.Add(a);
+ }
+ }
+
+ VariableSeq locVars = (!)impl.OriginalLocVars;
+
+ // add where clauses of local vars as assume
+ for(int i = 0; i < locVars.Length; ++i) {
+ Expr whereExpr = ((!)locVars[i]).TypedIdent.WhereExpr;
+ if(whereExpr != null) {
+ whereExpr = Substituter.Apply(codeCopier.Subst, whereExpr);
+ // FIXME we cannot overwrite it, can we?!
+ ((!)locVars[i]).TypedIdent.WhereExpr = whereExpr;
+ AssumeCmd! a = new AssumeCmd(Token.NoToken, whereExpr);
+ inCmds.Add(a);
+ }
+ }
+
+ // add where clauses of output params as assume
+ for(int i = 0; i < impl.OutParams.Length; ++i) {
+ Expr whereExpr = ((!)impl.OutParams[i]).TypedIdent.WhereExpr;
+ if(whereExpr != null) {
+ whereExpr = Substituter.Apply(codeCopier.Subst, whereExpr);
+ // FIXME likewise
+ ((!)impl.OutParams[i]).TypedIdent.WhereExpr = whereExpr;
+ AssumeCmd! a = new AssumeCmd(Token.NoToken, whereExpr);
+ inCmds.Add(a);
+ }
+ }
+
+ // assign modifies old values
+ foreach (IdentifierExpr! mie in proc.Modifies)
+ {
+ Variable! mvar = (!) mie.Decl;
+ AssignCmd assign = Cmd.SimpleAssign(impl.tok, (IdentifierExpr) (!) codeCopier.SubstForOld(mvar), mie);
+ inCmds.Add(assign);
+ }
+
+ GotoCmd inGotoCmd = new GotoCmd(callCmd.tok, new StringSeq(GetInlinedProcLabel(proc.Name) + "$" + startLabel));
+ Block inBlock = new Block(impl.tok, GetInlinedProcLabel(proc.Name) + "$Entry", inCmds, inGotoCmd);
+ inlinedBlocks.Add(inBlock);
+
+ // inject the blocks of the implementation
+ Block intBlock;
+ foreach (Block block in implBlocks) {
+ CmdSeq copyCmds = codeCopier.CopyCmdSeq(block.Cmds);
+ TransferCmd transferCmd = CreateInlinedTransferCmd((!) block.TransferCmd, GetInlinedProcLabel(proc.Name));
+ intBlock = new Block(block.tok, GetInlinedProcLabel(proc.Name) + "$" + block.Label, copyCmds, transferCmd);
+ inlinedBlocks.Add(intBlock);
+ }
+
+ // create out block
+ CmdSeq outCmds = new CmdSeq();
+
+ // inject non-free ensures
+ for (int i = 0; i < proc.Ensures.Length; i++) {
+ Ensures! ens = (!) proc.Ensures[i];
+ if (!ens.Free) {
+ Ensures! ensCopy = (Ensures!) ens.Clone();
+ ensCopy.Condition = codeCopier.CopyExpr(ens.Condition);
+ AssertCmd! a = new AssertEnsuresCmd(ensCopy);
+ outCmds.Add(a);
+ }
+ }
+
+ // assign out params
+ for(int i = 0; i < impl.OutParams.Length; ++i) {
+ Expr! cout_exp = (IdentifierExpr) (!) codeCopier.Subst((!)impl.OutParams[i]);
+ Cmd cmd = Cmd.SimpleAssign(impl.tok, (!)callCmd.Outs[i], cout_exp);
+ outCmds.Add(cmd);
+ }
+
+ // create out block
+ GotoCmd outGotoCmd = new GotoCmd(Token.NoToken, new StringSeq(nextBlockLabel));
+ Block outBlock = new Block(impl.tok, GetInlinedProcLabel(proc.Name) + "$Return", outCmds, outGotoCmd);
+ inlinedBlocks.Add(outBlock);
+
+ return inlinedBlocks;
+ }
+
+ protected TransferCmd CreateInlinedTransferCmd(TransferCmd! transferCmd, string! procLabel) {
+ TransferCmd newTransferCmd;
+
+ GotoCmd gotoCmd = transferCmd as GotoCmd;
+ if(gotoCmd != null) {
+ StringSeq gotoSeq = gotoCmd.labelNames;
+ StringSeq newGotoSeq = new StringSeq();
+ foreach(string! blockLabel in (!) gotoSeq) {
+ newGotoSeq.Add(procLabel + "$" + blockLabel);
+ }
+ newTransferCmd = new GotoCmd(transferCmd.tok, newGotoSeq);
+ } else {
+ newTransferCmd = new GotoCmd(transferCmd.tok, new StringSeq(procLabel + "$Return"));
+ }
+
+ return newTransferCmd;
+ }
+
+ protected static bool FindProcImpl(Program! program, string! procName, out Procedure outProc, out Implementation outImpl)
+ {
+ // this assumes that there is at most one procedure and only one associated implementation in the current context
+
+ foreach(Declaration decl in program.TopLevelDeclarations) {
+ Implementation impl = decl as Implementation;
+ if(impl != null) {
+ if(impl.Name.Equals(procName)) {
+ assert(impl.Proc != null);
+ outProc = impl.Proc;
+ outImpl = impl;
+ return true;
+ }
+ }
+ }
+
+ foreach(Declaration decl in program.TopLevelDeclarations) {
+ Procedure proc = decl as Procedure;
+ if(proc != null) {
+ if(proc.Name.Equals(procName)) {
+ outProc = proc;
+ outImpl = null;
+ return false;
+ }
+ }
+ }
+
+ outProc = null;
+ outImpl = null;
+ return false;
+ }
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ public class CodeCopier
+ {
+
+ private DefaultDuplicator! dupl;
+
+ private sealed class DefaultDuplicator : Duplicator
+ {
+ public Substitution subst;
+ public Substitution oldSubst;
+ private bool insideOldExpr = false;
+ public DefaultDuplicator(Substitution subst, Substitution oldSubst) {
+ this.subst = subst;
+ this.oldSubst = oldSubst;
+ base();
+ }
+ public override Cmd! VisitAssumeCmd(AssumeCmd! node)
+ {
+ return new AssumeCmd(node.tok, VisitExpr(node.Expr));
+ }
+ public override Cmd! VisitAssertCmd(AssertCmd! node)
+ {
+ return new AssertCmd(node.tok, VisitExpr(node.Expr));
+ }
+ public override Cmd! VisitAssertRequiresCmd(AssertRequiresCmd! node)
+ {
+ return new AssertRequiresCmd((CallCmd)VisitCallCmd(node.Call), VisitRequires(node.Requires));
+ }
+ public override Cmd! VisitAssertEnsuresCmd(AssertEnsuresCmd! node)
+ {
+ return new AssertEnsuresCmd(VisitEnsures(node.Ensures));
+ }
+
+ public override Cmd! VisitCallCmd(CallCmd! node)
+ {
+ List<Expr>! newIns = new List<Expr> ();
+ List<IdentifierExpr>! newOuts = new List<IdentifierExpr> ();
+ foreach (Expr e in node.Ins)
+ newIns.Add(e == null ? null : this.VisitExpr(e));
+ foreach (IdentifierExpr e in node.Outs)
+ newOuts.Add(e == null ? null : (IdentifierExpr)this.VisitIdentifierExpr(e));
+
+ CallCmd! newCmd = new CallCmd(node.tok, ((!)node.Proc).Name, newIns, newOuts);
+ newCmd.Proc = node.Proc;
+ return newCmd;
+ }
+ public override Expr! VisitIdentifierExpr(IdentifierExpr! node)
+ {
+ Expr e = null;
+ if(insideOldExpr && oldSubst != null) {
+ e = oldSubst((!)node.Decl);
+ }
+ if(e == null) {
+ if(subst != null) {
+ e = subst((!)node.Decl);
+ return e == null ? base.VisitIdentifierExpr(node) : e;
+ } else {
+ return base.VisitIdentifierExpr(node);
+ }
+ }
+ return e;
+ }
+ public override Expr! VisitOldExpr(OldExpr! node)
+ {
+ if(this.oldSubst != null) {
+ bool previouslyInOld = insideOldExpr;
+ insideOldExpr = true;
+ Expr! e = (Expr!)this.Visit(node.Expr);
+ insideOldExpr = previouslyInOld;
+ return e;
+ } else {
+ return base.VisitOldExpr(node);
+ }
+ }
+ }
+
+ public CodeCopier(Hashtable! substMap) {
+ this.dupl = new DefaultDuplicator(Substituter.SubstitutionFromHashtable(substMap), null);
+ }
+
+ public CodeCopier(Hashtable! substMap, Hashtable! oldSubstMap) {
+ this.dupl = new DefaultDuplicator(Substituter.SubstitutionFromHashtable(substMap), Substituter.SubstitutionFromHashtable(oldSubstMap));
+ }
+
+ public CodeCopier() {
+ this.dupl = new DefaultDuplicator(null, null);
+ }
+
+ public Substitution Subst {
+ set {
+ this.dupl.subst = value;
+ }
+ get {
+ return this.dupl.subst;
+ }
+ }
+
+ public Substitution SubstForOld {
+ set {
+ this.dupl.oldSubst = value;
+ }
+ get {
+ return this.dupl.oldSubst;
+ }
+ }
+
+ public Duplicator! Dupl {
+ get {
+ return this.dupl;
+ }
+ }
+
+ public List<Block!>! CopyBlocks(List<Block!>! blocks) {
+
+ List<Block!>! newBlocks = new List<Block!>();
+
+ foreach(Block block in blocks) {
+ Block newBlock = CopyBlock(block);
+ newBlocks.Add(newBlock);
+ }
+
+ return newBlocks;
+ }
+
+ public List<Block!>! CopyBlocks(List<Block!>! blocks, string! prefix) {
+
+ List<Block!>! newBlocks = new List<Block!>();
+
+ foreach(Block block in blocks) {
+ Block newBlock = CopyBlock(block, prefix);
+ newBlocks.Add(newBlock);
+ }
+
+ return newBlocks;
+ }
+
+
+ #region CopyBlock
+ public Block! CopyBlock(Block! block) {
+
+ assert(block.TransferCmd != null);
+ Block newBlock = new Block(block.tok, block.Label, CopyCmdSeq(block.Cmds), CopyTransferCmd(block.TransferCmd));
+
+ return newBlock;
+
+ }
+
+ public Block! CopyBlock(Block! block, string! prefix) {
+
+ assert(block.TransferCmd != null);
+ Block newBlock = new Block(block.tok, prefix + "$" + block.Label, CopyCmdSeq(block.Cmds), CopyTransferCmd(block.TransferCmd));
+
+ return newBlock;
+
+ }
+ #endregion
+
+ #region CopyCmdSeq
+ public CmdSeq! CopyCmdSeq(CmdSeq! cmds) {
+
+ CmdSeq newCmds = new CmdSeq();
+
+ for (int i = 0; i < cmds.Length; ++i) {
+ newCmds.Add(CopyCmd(cmds[i]));
+ }
+
+ return newCmds;
+
+ }
+ #endregion
+
+
+ #region CopyTransferCmd
+ public TransferCmd! CopyTransferCmd(TransferCmd! cmd) {
+ TransferCmd transferCmd;
+ GotoCmd gotocmd = cmd as GotoCmd;
+ if(gotocmd != null) {
+ assert(gotocmd.labelNames != null);
+ StringSeq labels = new StringSeq();
+ labels.AddRange(gotocmd.labelNames);
+ transferCmd = new GotoCmd(cmd.tok, labels);
+ } else {
+ transferCmd = new ReturnCmd(cmd.tok);
+ }
+ return transferCmd;
+ }
+
+ public TransferCmd! CopyTransferCmd(TransferCmd! cmd, string! prefix) {
+ TransferCmd transferCmd;
+ GotoCmd gotocmd = cmd as GotoCmd;
+ if(gotocmd != null) {
+ assert(gotocmd.labelNames != null);
+ StringSeq labels = new StringSeq();
+ foreach(string label in gotocmd.labelNames) {
+ labels.Add(prefix + "$" + label);
+ }
+ transferCmd = new GotoCmd(cmd.tok, labels);
+ } else {
+ transferCmd = new ReturnCmd(cmd.tok);
+ }
+ return transferCmd;
+ }
+ #endregion
+
+
+
+ #region CopyCmd
+ public Cmd! CopyCmd(Cmd! cmd) {
+ Cmd newCmd = (Cmd) Dupl.Visit(cmd);
+ return newCmd;
+ }
+ #endregion
+
+ #region CopyExpr
+ public Expr! CopyExpr(Expr! expr) {
+ Expr newExpr = (Expr) Dupl.Visit(expr);
+ return newExpr;
+ }
+ #endregion
+
+ } // end class CodeCopier
+
+
+ public class AxiomExpander : Duplicator
+ {
+ readonly Program! program;
+ readonly TypecheckingContext! tc;
+
+ public AxiomExpander(Program! prog, TypecheckingContext! t)
+ {
+ program = prog;
+ tc = t;
+ }
+
+ public void CollectExpansions()
+ {
+ foreach (Declaration! decl in program.TopLevelDeclarations) {
+ Axiom ax = decl as Axiom;
+ if (ax != null) {
+ bool expand = false;
+ if (!ax.CheckBooleanAttribute("inline", ref expand)) {
+ Error(decl.tok, "{:inline ...} expects either true or false as the argument");
+ }
+ if (expand) {
+ AddExpansion(ax.Expr, ax.FindStringAttribute("ignore"));
+ }
+ }
+ Function f = decl as Function;
+ if (f != null && f.Body != null) {
+ Variable[]! formals = new Variable [f.InParams.Length];
+ for (int i = 0; i < formals.Length; ++i)
+ formals[i] = f.InParams[i];
+ AddExpansion(f, new Expansion(null, f.Body,
+ new TypeVariableSeq (f.TypeParameters),
+ formals));
+ }
+ }
+ }
+
+ void Error(IToken! tok, string msg)
+ {
+ tc.Error(tok, "expansion: " + msg);
+ }
+
+ void AddExpansion(Expr! axiomBody, string? ignore)
+ {
+ // it would be sooooooooo much easier with pattern matching
+ ForallExpr all = axiomBody as ForallExpr;
+ if (all != null) {
+ NAryExpr nary = all.Body as NAryExpr;
+ BinaryOperator bin = nary == null ? null : nary.Fun as BinaryOperator;
+ //System.Console.WriteLine("{0} {1} {2}", nary==null, bin==null, bin==null?0 : bin.Op);
+ if (nary != null && bin != null && (bin.Op == BinaryOperator.Opcode.Eq || bin.Op == BinaryOperator.Opcode.Iff)) {
+ NAryExpr? func = nary.Args[0] as NAryExpr;
+ //System.Console.WriteLine("{0} {1}", func == null, func == null ? null : func.Fun.GetType());
+ while (func != null && func.Fun is TypeCoercion)
+ func = func.Args[0] as NAryExpr;
+ if (func != null && func.Fun is FunctionCall) {
+ Function fn = (!)((FunctionCall)func.Fun).Func;
+ Expansion exp = new Expansion(ignore, (!)nary.Args[1],
+ new TypeVariableSeq (),
+ new Variable[func.Args.Length]);
+ int pos = 0;
+ Dictionary<Declaration, bool> parms = new Dictionary<Declaration, bool>();
+ foreach (Expr! e in func.Args) {
+ IdentifierExpr id = e as IdentifierExpr;
+ if (id == null) {
+ Error(e.tok, "only identifiers supported as function arguments");
+ return;
+ }
+ exp.formals[pos++] = id.Decl;
+ if (parms.ContainsKey(id.Decl)) {
+ Error(all.tok, "an identifier was used more than once");
+ return;
+ }
+ parms[id.Decl] = true;
+ if (!all.Dummies.Has(id.Decl)) {
+ Error(all.tok, "identifier was not quantified over");
+ return;
+ }
+ }
+ if (func.Args.Length != all.Dummies.Length) {
+ Error(all.tok, "more variables quantified over, than used in function");
+ return;
+ }
+
+ Dictionary<TypeVariable!, bool> typeVars = new Dictionary<TypeVariable!, bool>();
+ foreach (TypeVariable! v in ((!)func.TypeParameters).FormalTypeParams) {
+ if (!func.TypeParameters[v].IsVariable) {
+ Error(all.tok, "only identifiers supported as type parameters");
+ return;
+ }
+ TypeVariable! formal = func.TypeParameters[v].AsVariable;
+ exp.TypeParameters.Add(formal);
+ if (typeVars.ContainsKey(formal)) {
+ Error(all.tok, "an identifier was used more than once");
+ return;
+ }
+ typeVars[formal] = true;
+ if (!all.TypeParameters.Has(formal)) {
+ Error(all.tok, "identifier was not quantified over");
+ return;
+ }
+ }
+ if (((FunctionCall)func.Fun).Func.TypeParameters.Length != all.TypeParameters.Length) {
+ Error(all.tok, "more variables quantified over, than used in function");
+ return;
+ }
+ AddExpansion(fn, exp);
+ return;
+ }
+ }
+ }
+
+ Error(axiomBody.tok, "axiom to be expanded must have form (forall VARS :: f(VARS) == expr(VARS))");
+ }
+
+ void AddExpansion(Function! fn, Expansion! x) {
+ if (fn.expansions == null) {
+ fn.expansions = new List<Expansion!>();
+ }
+ fn.expansions.Add(x);
+ }
+ }
+} // end namespace
+
diff --git a/Source/Core/LoopUnroll.ssc b/Source/Core/LoopUnroll.ssc
new file mode 100644
index 00000000..4335a834
--- /dev/null
+++ b/Source/Core/LoopUnroll.ssc
@@ -0,0 +1,174 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using Microsoft.Contracts;
+using System.Collections.Generic;
+using Cci = System.Compiler;
+using Bpl = Microsoft.Boogie;
+
+namespace Microsoft.Boogie
+{
+ public class LoopUnroll {
+ public static List<Block!>! UnrollLoops(Block! start, int unrollMaxDepth)
+ requires 0 <= unrollMaxDepth;
+ {
+ Dictionary<Block,GraphNode!> gd = new Dictionary<Block,GraphNode!>();
+ Cci.HashSet/*Block*/! beingVisited = new Cci.HashSet/*Block*/();
+ GraphNode gStart = GraphNode.ComputeGraphInfo(null, start, gd, beingVisited);
+
+ LoopUnroll lu = new LoopUnroll(gd, unrollMaxDepth, null);
+ lu.Visit(gStart);
+ lu.newBlockSeqGlobal.Reverse();
+ return lu.newBlockSeqGlobal;
+ }
+
+ class GraphNode {
+ public readonly Block! Block;
+ public readonly CmdSeq! Body;
+ bool isCutPoint; // is set during ComputeGraphInfo
+ public bool IsCutPoint { get { return isCutPoint; } }
+ [Rep] public readonly List<GraphNode!>! ForwardEdges = new List<GraphNode!>();
+ [Rep] public readonly List<GraphNode!>! BackEdges = new List<GraphNode!>();
+ invariant isCutPoint <==> BackEdges.Count != 0;
+
+ GraphNode(Block! b, CmdSeq! body) {
+ this.Block = b;
+ this.Body = body;
+ }
+
+ static CmdSeq! GetOptimizedBody(CmdSeq! cmds) {
+ int n = 0;
+ foreach (Cmd c in cmds) {
+ n++;
+ PredicateCmd pc = c as PredicateCmd;
+ if (pc != null && pc.Expr is LiteralExpr && ((LiteralExpr)pc.Expr).IsFalse) {
+ // return a sequence consisting of the commands seen so far
+ Cmd[] s = new Cmd[n];
+ for (int i = 0; i < n; i++) {
+ s[i] = cmds[i];
+ }
+ return new CmdSeq(s);
+ }
+ }
+ return cmds;
+ }
+
+ public static GraphNode! ComputeGraphInfo(GraphNode from, Block! b, Dictionary<Block,GraphNode!>! gd, Cci.HashSet/*Block*/! beingVisited) {
+ GraphNode g;
+ if (gd.TryGetValue(b, out g)) {
+ assume from != null;
+ assert g != null;
+ if (beingVisited.Contains(b)) {
+ // it's a cut point
+ g.isCutPoint = true;
+ from.BackEdges.Add(g);
+ } else {
+ from.ForwardEdges.Add(g);
+ }
+
+ } else {
+ CmdSeq body = GetOptimizedBody(b.Cmds);
+ g = new GraphNode(b, body);
+ gd.Add(b, g);
+ if (from != null) {
+ from.ForwardEdges.Add(g);
+ }
+
+ if (body != b.Cmds) {
+ // the body was optimized -- there is no way through this block
+ } else {
+ beingVisited.Add(b);
+
+ GotoCmd gcmd = b.TransferCmd as GotoCmd;
+ if (gcmd != null) {
+ assume gcmd.labelTargets != null;
+ foreach (Block! succ in gcmd.labelTargets) {
+ ComputeGraphInfo(g, succ, gd, beingVisited);
+ }
+ }
+
+ beingVisited.Remove(b);
+ }
+ }
+ return g;
+ }
+ }
+
+ List<Block!>! newBlockSeqGlobal;
+ readonly int c;
+ readonly LoopUnroll next;
+ Dictionary<Block,int>! visitsRemaining = new Dictionary</*cut-point-*/Block,int>();
+ Dictionary<Block,Block!>! newBlocks = new Dictionary<Block,Block!>();
+
+ private LoopUnroll(Dictionary<Block,GraphNode!>! gd, int unrollMaxDepth, List<Block!> newBlockSeqGlobal)
+ requires 0 <= unrollMaxDepth;
+ {
+ if (newBlockSeqGlobal == null) {
+ newBlockSeqGlobal = new List<Block!>();
+ }
+ this.newBlockSeqGlobal = newBlockSeqGlobal;
+ this.c = unrollMaxDepth;
+ if (unrollMaxDepth != 0) {
+ next = new LoopUnroll(gd, unrollMaxDepth - 1, newBlockSeqGlobal);
+ }
+ }
+
+ Block! Visit(GraphNode! node) {
+ Block orig = node.Block;
+ Block nw;
+ if (newBlocks.TryGetValue(orig, out nw)) {
+ assert nw != null;
+
+ } else {
+ CmdSeq body;
+ TransferCmd tcmd;
+ assert orig.TransferCmd != null;
+
+ if (next == null && node.IsCutPoint) {
+ // as the body, use the assert/assume commands that make up the loop invariant
+ body = new CmdSeq();
+ foreach (Cmd! c in node.Body) {
+ if (c is PredicateCmd || c is CommentCmd) {
+ body.Add(c);
+ } else {
+ break;
+ }
+ }
+ body.Add(new AssumeCmd(orig.tok, Bpl.Expr.False));
+
+ tcmd = new ReturnCmd(orig.TransferCmd.tok);
+
+ } else {
+ body = node.Body;
+ BlockSeq newSuccs = new BlockSeq();
+
+ foreach (GraphNode succ in node.ForwardEdges) {
+ Block s = Visit(succ);
+ newSuccs.Add(s);
+ }
+
+ assert next == null ==> node.BackEdges.Count == 0; // follows from if-else test above and the GraphNode invariant
+ foreach (GraphNode succ in node.BackEdges) {
+ assert next != null; // since if we get here, node.BackEdges.Count != 0
+ Block s = next.Visit(succ);
+ newSuccs.Add(s);
+ }
+
+ if (newSuccs.Length == 0) {
+ tcmd = new ReturnCmd(orig.TransferCmd.tok);
+ } else {
+ tcmd = new GotoCmd(orig.TransferCmd.tok, newSuccs);
+ }
+ }
+
+ nw = new Block(orig.tok, orig.Label + "#" + this.c, body, tcmd);
+ newBlocks.Add(orig, nw);
+ newBlockSeqGlobal.Add(nw);
+ }
+
+ return nw;
+ }
+ }
+}
diff --git a/Source/Core/Makefile b/Source/Core/Makefile
new file mode 100644
index 00000000..ee73b25d
--- /dev/null
+++ b/Source/Core/Makefile
@@ -0,0 +1,18 @@
+COCO = ..\..\Binaries\Coco.exe
+ASML = ..\..\Binaries\asmlc.boot.exe
+
+# "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
+
+#Graph.dll: Graph.as
+# $(ASML) /target:library Graph.as
+
+Parser.ssc: Scanner.frame Parser.frame BoogiePL.atg
+ $(COCO) BoogiePL.atg
+ copy Parser.cs Parser.ssc
+ copy Scanner.cs Scanner.ssc
+
+clean:
+ rm -f Scanner.ssc Parser.ssc
diff --git a/Source/Core/OOLongUtil.ssc b/Source/Core/OOLongUtil.ssc
new file mode 100644
index 00000000..81dadf1b
--- /dev/null
+++ b/Source/Core/OOLongUtil.ssc
@@ -0,0 +1,174 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using System;
+using System.Collections.Generic;
+using System.IO;
+using Microsoft.Contracts;
+
+namespace Boogie.Util {
+ public class TeeWriter : TextWriter {
+ readonly TextWriter! a;
+ readonly TextWriter! b;
+
+ public TeeWriter(TextWriter! a, TextWriter! b) {
+ this.a = a;
+ this.b = b;
+ }
+
+ public override System.Text.Encoding Encoding {
+ get {
+ return a.Encoding;
+ }
+ }
+
+ public override void Close() {
+ a.Close();
+ b.Close();
+ }
+
+ public override void Flush() {
+ a.Flush();
+ b.Flush();
+ }
+
+ [Pure][Reads(ReadsAttribute.Reads.Owned)]
+ public override string! ToString() {
+ return "<TeeWriter: " + a.ToString() + ", " + b.ToString() + ">";
+ }
+
+ public override void Write(char ch) {
+ a.Write(ch);
+ b.Write(ch);
+ }
+
+ public override void Write(string s) {
+ a.Write(s);
+ b.Write(s);
+ }
+ }
+
+ /// <summary>
+ /// A LineReader is a class that allows further subclasses to just override the ReadLine() method.
+ /// It simply reads from the given "reader".
+ /// </summary>
+ public class LineReader : TextReader {
+ [Rep] readonly TextReader! reader;
+ string readAhead;
+ int readAheadConsumed;
+ invariant readAhead == null || (0 <= readAheadConsumed && readAheadConsumed < readAhead.Length);
+
+ public LineReader([Captured] TextReader! reader) {
+ this.reader = reader;
+ }
+ public override void Close() {
+ expose (this) {
+ reader.Close();
+ }
+ }
+ public override int Read() {
+ expose (this) {
+ while (readAhead == null) {
+ readAhead = reader.ReadLine();
+ if (readAhead == null) {
+ // we're at EOF
+ return -1;
+ } else if (readAhead.Length > 0) {
+ readAheadConsumed = 0;
+ break;
+ }
+ }
+ int res = readAhead[readAheadConsumed++];
+ if (readAheadConsumed == readAhead.Length) {
+ readAhead = null;
+ }
+ return res;
+ }
+ }
+ public override int Read(char[]! buffer, int index, int count) {
+ int n = 0;
+ for (; n < count; n++) {
+ int ch = Read();
+ if (ch == -1) {
+ break;
+ }
+ buffer[index + n] = (char)ch;
+ }
+ return n;
+ }
+ public override string ReadLine() {
+ string res;
+ if (readAhead != null) {
+ expose (this) {
+ res = readAhead.Substring(readAheadConsumed);
+ readAhead = null;
+ }
+ } else {
+ res = reader.ReadLine();
+ }
+ return res;
+ }
+ }
+
+ public class IfdefReader : LineReader {
+ [Rep] readonly List<string!>! defines;
+ [Rep] readonly List<bool>! readState = new List<bool>();
+ int ignoreCutoff = 0; // 0 means we're not ignoring
+ invariant 0 <= ignoreCutoff && ignoreCutoff <= readState.Count;
+
+ public IfdefReader([Captured] TextReader! reader, [Captured] List<string!>! defines) {
+ base(reader);
+ this.defines = defines;
+ }
+
+ public override string ReadLine() {
+ while (true) {
+ string s = base.ReadLine();
+ if (s == null) {
+ return s;
+ }
+ string t = s.Trim();
+ if (t.StartsWith("#if")) {
+ string arg = t.Substring(3).TrimStart();
+ bool sense = true;
+ while (t.StartsWith("!")) {
+ sense = !sense;
+ t = t.Substring(1).TrimStart();
+ }
+ // push "true", since we're in a "then" branch
+ readState.Add(true);
+ if (ignoreCutoff == 0 && defines.Contains(arg) != sense) {
+ ignoreCutoff = readState.Count; // start ignoring
+ }
+ } else if (t == "#else") {
+ if (readState.Count == 0 || !readState[readState.Count-1]) {
+ return s; // malformed input; return the read line as if it were not special
+ }
+ // change the "true" to a "false" on top of the state, since we're now going into the "else" branch
+ readState[readState.Count-1] = false;
+ if (ignoreCutoff == 0) {
+ // the "then" branch had been included, so we'll ignore the "else" branch
+ ignoreCutoff = readState.Count;
+ } else if (ignoreCutoff == readState.Count) {
+ // we had ignored the "then" branch, so we'll include the "else" branch
+ ignoreCutoff = 0;
+ }
+ } else if (t == "#endif") {
+ if (readState.Count == 0) {
+ return s; // malformed input; return the read line as if it were not special
+ }
+ if (ignoreCutoff == readState.Count) {
+ // we had ignored the branch that ends here; so, now we start including again
+ ignoreCutoff = 0;
+ }
+ // pop
+ readState.RemoveAt(readState.Count-1);
+ } else if (ignoreCutoff == 0) {
+ return s;
+ }
+ }
+ }
+ }
+}
diff --git a/Source/Core/Parser.ssc b/Source/Core/Parser.ssc
new file mode 100644
index 00000000..3d0f4449
--- /dev/null
+++ b/Source/Core/Parser.ssc
@@ -0,0 +1,2021 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using PureCollections;
+using System.Collections;
+using System.Collections.Generic;
+using Microsoft.Boogie;
+using Microsoft.Basetypes;
+using Bpl = Microsoft.Boogie;
+using AI = Microsoft.AbstractInterpretationFramework;
+using System;
+using Microsoft.Contracts;
+
+namespace BoogiePL {
+
+public class Parser {
+ const int maxT = 85;
+
+ const bool T = true;
+ const bool x = false;
+ const int minErrDist = 2;
+
+ static Token/*!*/ token; // last recognized token
+ static Token/*!*/ t; // lookahead token
+ static int errDist = minErrDist;
+
+ static Program! Pgm = new Program();
+
+static Expr! dummyExpr = new LiteralExpr(Token.NoToken, false);
+static Cmd! dummyCmd = new AssumeCmd(Token.NoToken, dummyExpr);
+static Block! dummyBlock = new Block(Token.NoToken, "dummyBlock", new CmdSeq(),
+ new ReturnCmd(Token.NoToken));
+static Bpl.Type! dummyType = new BasicType(Token.NoToken, SimpleType.Bool);
+static Bpl.ExprSeq! dummyExprSeq = new ExprSeq ();
+static TransferCmd! dummyTransferCmd = new ReturnCmd(Token.NoToken);
+static StructuredCmd! dummyStructuredCmd = new BreakCmd(Token.NoToken, null);
+
+///<summary>
+///Returns the number of parsing errors encountered. If 0, "program" returns as
+///the parsed program.
+///</summary>
+public static int Parse (string! filename, out /*maybe null*/ Program program) /* throws System.IO.IOException */ {
+ using (System.IO.StreamReader reader = new System.IO.StreamReader(filename)) {
+ Buffer.Fill(reader);
+ Scanner.Init(filename);
+ return Parse(out program);
+ }
+}
+
+///<summary>
+///Returns the number of parsing errors encountered. If 0, "program" returns as
+///the parsed program.
+///Note: first initialize the Scanner.
+///</summary>
+public static int Parse (out /*maybe null*/ Program program) {
+ Pgm = new Program(); // reset the global variable
+ Parse();
+ if (Errors.count == 0)
+ {
+ program = Pgm;
+ return 0;
+ }
+ else
+ {
+ program = null;
+ return Errors.count;
+ }
+}
+
+
+public static int ParseProposition (string! text, out Expr! expression)
+{
+ Buffer.Fill(text);
+ Scanner.Init(string.Format("\"{0}\"", text));
+
+ Errors.SynErr = new ErrorProc(SynErr);
+ t = new Token();
+ Get();
+ Proposition(out expression);
+ return Errors.count;
+}
+
+// Class to represent the bounds of a bitvector expression t[a:b].
+// Objects of this class only exist during parsing and are directly
+// turned into BvExtract before they get anywhere else
+private class BvBounds : Expr {
+ public BigNum Lower;
+ public BigNum Upper;
+ public BvBounds(IToken! tok, BigNum lower, BigNum upper) {
+ base(tok);
+ this.Lower = lower;
+ this.Upper = upper;
+ }
+ public override Type! ShallowType { get { return Bpl.Type.Int; } }
+ public override void Resolve(ResolutionContext! rc) {
+ rc.Error(this, "bitvector bounds in illegal position");
+ }
+ public override void Emit(TokenTextWriter! stream,
+ int contextBindingStrength, bool fragileContext) {
+ assert false;
+ }
+ public override void ComputeFreeVariables(Set! freeVars) { assert false; }
+ public override AI.IExpr! IExpr { get { assert false; } }
+}
+
+/*--------------------------------------------------------------------------*/
+
+
+ static void Error(int n) {
+ if (errDist >= minErrDist) Errors.SynErr(n, t.filename, t.line, t.col);
+ errDist = 0;
+ }
+
+ public static void SemErr(string! msg) {
+ if (errDist >= minErrDist) Errors.SemErr(token.filename, token.line, token.col, msg);
+ errDist = 0;
+ }
+
+ static void Get() {
+ for (;;) {
+ token = t;
+ t = Scanner.Scan();
+ if (t.kind<=maxT) {errDist++; return;}
+
+ t = token;
+ }
+ }
+
+ static void Expect(int n) {
+ if (t.kind==n) Get(); else Error(n);
+ }
+
+ static bool StartOf(int s) {
+ return set[s, t.kind];
+ }
+
+ static void ExpectWeak(int n, int follow) {
+ if (t.kind == n) Get();
+ else {
+ Error(n);
+ while (!StartOf(follow)) Get();
+ }
+ }
+
+ static bool WeakSeparator(int n, int syFol, int repFol) {
+ bool[] s = new bool[maxT+1];
+ if (t.kind == n) {Get(); return true;}
+ else if (StartOf(repFol)) return false;
+ else {
+ for (int i=0; i <= maxT; i++) {
+ s[i] = set[syFol, i] || set[repFol, i] || set[0, i];
+ }
+ Error(n);
+ while (!s[t.kind]) Get();
+ return StartOf(syFol);
+ }
+ }
+
+ static void BoogiePL() {
+ VariableSeq! vs;
+ DeclarationSeq! ds;
+ Axiom! ax;
+ List<Declaration!>! ts;
+ Procedure! pr;
+ Implementation im;
+ Implementation! nnim;
+
+ while (StartOf(1)) {
+ switch (t.kind) {
+ case 19: {
+ Consts(out vs);
+ foreach (Bpl.Variable! v in vs) { Pgm.TopLevelDeclarations.Add(v); }
+ break;
+ }
+ case 23: {
+ Function(out ds);
+ foreach (Bpl.Declaration! d in ds) { Pgm.TopLevelDeclarations.Add(d); }
+ break;
+ }
+ case 27: {
+ Axiom(out ax);
+ Pgm.TopLevelDeclarations.Add(ax);
+ break;
+ }
+ case 28: {
+ UserDefinedTypes(out ts);
+ foreach (Declaration! td in ts) {
+ Pgm.TopLevelDeclarations.Add(td);
+ }
+ break;
+ }
+ case 6: {
+ GlobalVars(out vs);
+ foreach (Bpl.Variable! v in vs) { Pgm.TopLevelDeclarations.Add(v); }
+ break;
+ }
+ case 30: {
+ Procedure(out pr, out im);
+ Pgm.TopLevelDeclarations.Add(pr);
+ if (im != null) {
+ Pgm.TopLevelDeclarations.Add(im);
+ }
+
+ break;
+ }
+ case 31: {
+ Implementation(out nnim);
+ Pgm.TopLevelDeclarations.Add(nnim);
+ break;
+ }
+ }
+ }
+ Expect(0);
+ }
+
+ static void Consts(out VariableSeq! ds) {
+ IToken! y; TypedIdentSeq! xs;
+ ds = new VariableSeq();
+ bool u = false; QKeyValue kv = null;
+ bool ChildrenComplete = false;
+ List<ConstantParent!> Parents = null;
+ Expect(19);
+ y = token;
+ while (t.kind == 25) {
+ Attribute(ref kv);
+ }
+ if (t.kind == 20) {
+ Get();
+ u = true;
+ }
+ IdsType(out xs);
+ if (t.kind == 21) {
+ OrderSpec(out ChildrenComplete, out Parents);
+ }
+ bool makeClone = false;
+ foreach(TypedIdent! x in xs) {
+ // ensure that no sharing is introduced
+ List<ConstantParent!> ParentsClone;
+ if (makeClone && Parents != null) {
+ ParentsClone = new List<ConstantParent!> ();
+ foreach (ConstantParent! p in Parents)
+ ParentsClone.Add(new ConstantParent (
+ new IdentifierExpr (p.Parent.tok, p.Parent.Name),
+ p.Unique));
+ } else {
+ ParentsClone = Parents;
+ }
+ makeClone = true;
+ ds.Add(new Constant(y, x, u, ParentsClone, ChildrenComplete, kv));
+ }
+
+ Expect(7);
+ }
+
+ static void Function(out DeclarationSeq! ds) {
+ ds = new DeclarationSeq(); IToken! z;
+ IToken! typeParamTok;
+ TypeVariableSeq! typeParams = new TypeVariableSeq();
+ VariableSeq arguments = new VariableSeq();
+ TypedIdent! tyd;
+ QKeyValue kv = null;
+ Expr definition = null;
+ Expr! tmp;
+
+ Expect(23);
+ while (t.kind == 25) {
+ Attribute(ref kv);
+ }
+ Ident(out z);
+ if (t.kind == 17) {
+ TypeParams(out typeParamTok, out typeParams);
+ }
+ Expect(8);
+ if (StartOf(2)) {
+ VarOrType(out tyd);
+ arguments.Add(new Formal(tyd.tok, tyd, true));
+ while (t.kind == 11) {
+ Get();
+ VarOrType(out tyd);
+ arguments.Add(new Formal(tyd.tok, tyd, true));
+ }
+ }
+ Expect(9);
+ Expect(24);
+ Expect(8);
+ VarOrType(out tyd);
+ Expect(9);
+ if (t.kind == 25) {
+ Get();
+ Expression(out tmp);
+ definition = tmp;
+ Expect(26);
+ } else if (t.kind == 7) {
+ Get();
+ } else Error(86);
+ Function! func = new Function(z, z.val, typeParams, arguments,
+ new Formal(tyd.tok, tyd, false), null, kv);
+ ds.Add(func);
+ if (definition != null) {
+ // generate either an axiom or a function body
+ if (QKeyValue.FindBoolAttribute(kv, "inline")) {
+ func.Body = definition;
+ } else {
+ VariableSeq dummies = new VariableSeq();
+ ExprSeq callArgs = new ExprSeq();
+ int i = 0;
+ foreach (Formal! f in arguments) {
+ string nm = f.TypedIdent.HasName ? f.TypedIdent.Name : "_" + i;
+ dummies.Add(new BoundVariable(f.tok, new TypedIdent(f.tok, nm, f.TypedIdent.Type)));
+ callArgs.Add(new IdentifierExpr(f.tok, nm));
+ i++;
+ }
+ TypeVariableSeq! quantifiedTypeVars = new TypeVariableSeq ();
+ foreach (TypeVariable! t in typeParams)
+ quantifiedTypeVars.Add(new TypeVariable (Token.NoToken, t.Name));
+ Expr call = new NAryExpr(z, new FunctionCall(new IdentifierExpr(z, z.val)), callArgs);
+ // specify the type of the function, because it might be that
+ // type parameters only occur in the output type
+ call = Expr.CoerceType(z, call, (Type)tyd.Type.Clone());
+ Expr def = new ForallExpr(z, quantifiedTypeVars, dummies,
+ kv,
+ new Trigger(z, true, new ExprSeq(call), null),
+ Expr.Eq(call, definition));
+ ds.Add(new Axiom(z, def, "autogenerated definition axiom", null));
+ }
+ }
+
+ }
+
+ static void Axiom(out Axiom! m) {
+ Expr! e; QKeyValue kv = null;
+ Expect(27);
+ while (t.kind == 25) {
+ Attribute(ref kv);
+ }
+ IToken! x = token;
+ Proposition(out e);
+ Expect(7);
+ m = new Axiom(x,e, null, kv);
+ }
+
+ static void UserDefinedTypes(out List<Declaration!>! ts) {
+ Declaration! decl; QKeyValue kv = null; ts = new List<Declaration!> ();
+ Expect(28);
+ while (t.kind == 25) {
+ Attribute(ref kv);
+ }
+ UserDefinedType(out decl, kv);
+ ts.Add(decl);
+ while (t.kind == 11) {
+ Get();
+ UserDefinedType(out decl, kv);
+ ts.Add(decl);
+ }
+ Expect(7);
+ }
+
+ static void GlobalVars(out VariableSeq! ds) {
+ TypedIdentSeq! tyds = new TypedIdentSeq(); ds = new VariableSeq(); QKeyValue kv = null;
+ Expect(6);
+ while (t.kind == 25) {
+ Attribute(ref kv);
+ }
+ IdsTypeWheres(true, tyds);
+ Expect(7);
+ foreach(TypedIdent! tyd in tyds) {
+ ds.Add(new GlobalVariable(tyd.tok, tyd, kv));
+ }
+
+ }
+
+ static void Procedure(out Procedure! proc, out /*maybe null*/ Implementation impl) {
+ IToken! x;
+ TypeVariableSeq! typeParams;
+ VariableSeq! ins, outs;
+ RequiresSeq! pre = new RequiresSeq();
+ IdentifierExprSeq! mods = new IdentifierExprSeq();
+ EnsuresSeq! post = new EnsuresSeq();
+ VariableSeq! locals = new VariableSeq();
+ StmtList! stmtList;
+ QKeyValue kv = null;
+ impl = null;
+
+ Expect(30);
+ ProcSignature(true, out x, out typeParams, out ins, out outs, out kv);
+ if (t.kind == 7) {
+ Get();
+ while (StartOf(3)) {
+ Spec(pre, mods, post);
+ }
+ } else if (StartOf(4)) {
+ while (StartOf(3)) {
+ Spec(pre, mods, post);
+ }
+ ImplBody(out locals, out stmtList);
+ // here we attach kv only to the Procedure, not its implementation
+ impl = new Implementation(x, x.val, typeParams,
+ Formal.StripWhereClauses(ins), Formal.StripWhereClauses(outs), locals, stmtList, null);
+
+ } else Error(87);
+ proc = new Procedure(x, x.val, typeParams, ins, outs, pre, mods, post, kv);
+ }
+
+ static void Implementation(out Implementation! impl) {
+ IToken! x;
+ TypeVariableSeq! typeParams;
+ VariableSeq! ins, outs;
+ VariableSeq! locals;
+ StmtList! stmtList;
+ QKeyValue kv;
+
+ Expect(31);
+ 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);
+ }
+
+ static void Attribute(ref QKeyValue kv) {
+ Trigger trig = null;
+ AttributeOrTrigger(ref kv, ref trig);
+ if (trig != null) SemErr("only attributes, not triggers, allowed here");
+ }
+
+ static void IdsTypeWheres(bool allowWhereClauses, TypedIdentSeq! tyds) {
+ IdsTypeWhere(allowWhereClauses, tyds);
+ while (t.kind == 11) {
+ Get();
+ IdsTypeWhere(allowWhereClauses, tyds);
+ }
+ }
+
+ static void LocalVars(VariableSeq! ds) {
+ TypedIdentSeq! tyds = new TypedIdentSeq(); QKeyValue kv = null;
+ Expect(6);
+ while (t.kind == 25) {
+ Attribute(ref kv);
+ }
+ IdsTypeWheres(true, tyds);
+ Expect(7);
+ foreach(TypedIdent! tyd in tyds) {
+ ds.Add(new LocalVariable(tyd.tok, tyd, kv));
+ }
+
+ }
+
+ static void ProcFormals(bool incoming, bool allowWhereClauses, out VariableSeq! ds) {
+ TypedIdentSeq! tyds = new TypedIdentSeq(); ds = new VariableSeq();
+ Expect(8);
+ if (t.kind == 1) {
+ IdsTypeWheres(allowWhereClauses, tyds);
+ }
+ Expect(9);
+ foreach (TypedIdent! tyd in tyds) {
+ ds.Add(new Formal(tyd.tok, tyd, incoming));
+ }
+
+ }
+
+ static void BoundVars(IToken! x, out VariableSeq! ds) {
+ TypedIdentSeq! tyds = new TypedIdentSeq(); ds = new VariableSeq();
+ IdsTypeWheres(false, tyds);
+ foreach (TypedIdent! tyd in tyds) {
+ ds.Add(new BoundVariable(tyd.tok, tyd));
+ }
+
+ }
+
+ static void IdsType(out TypedIdentSeq! tyds) {
+ TokenSeq! ids; Bpl.Type! ty;
+ Idents(out ids);
+ Expect(10);
+ Type(out ty);
+ tyds = new TypedIdentSeq();
+ foreach (Token! id in ids) {
+ tyds.Add(new TypedIdent(id, id.val, ty, null));
+ }
+
+ }
+
+ static void Idents(out TokenSeq! xs) {
+ IToken! id; xs = new TokenSeq();
+ Ident(out id);
+ xs.Add(id);
+ while (t.kind == 11) {
+ Get();
+ Ident(out id);
+ xs.Add(id);
+ }
+ }
+
+ static void Type(out Bpl.Type! ty) {
+ IToken! tok; ty = dummyType;
+ if (t.kind == 8 || t.kind == 13 || t.kind == 14) {
+ TypeAtom(out ty);
+ } else if (t.kind == 1) {
+ Ident(out tok);
+ TypeSeq! args = new TypeSeq ();
+ if (StartOf(2)) {
+ TypeArgs(args);
+ }
+ ty = new UnresolvedTypeIdentifier (tok, tok.val, args);
+ } else if (t.kind == 15 || t.kind == 17) {
+ MapType(out ty);
+ } else Error(88);
+ }
+
+ static void IdsTypeWhere(bool allowWhereClauses, TypedIdentSeq! tyds) {
+ TokenSeq! ids; Bpl.Type! ty; Expr wh = null; Expr! nne;
+ Idents(out ids);
+ Expect(10);
+ Type(out ty);
+ if (t.kind == 12) {
+ Get();
+ Expression(out nne);
+ if (allowWhereClauses) {
+ wh = nne;
+ } else {
+ SemErr("where clause not allowed here");
+ }
+
+ }
+ foreach (Token! id in ids) {
+ tyds.Add(new TypedIdent(id, id.val, ty, wh));
+ }
+
+ }
+
+ static void Expression(out Expr! e0) {
+ IToken! x; Expr! e1;
+ ImpliesExpression(false, out e0);
+ while (t.kind == 52 || t.kind == 53) {
+ EquivOp();
+ x = token;
+ ImpliesExpression(false, out e1);
+ e0 = Expr.Binary(x, BinaryOperator.Opcode.Iff, e0, e1);
+ }
+ }
+
+ static void TypeAtom(out Bpl.Type! ty) {
+ ty = dummyType;
+ if (t.kind == 13) {
+ Get();
+ ty = new BasicType(token, SimpleType.Int);
+ } else if (t.kind == 14) {
+ Get();
+ ty = new BasicType(token, SimpleType.Bool);
+ } else if (t.kind == 8) {
+ Get();
+ Type(out ty);
+ Expect(9);
+ } else Error(89);
+ }
+
+ static void Ident(out IToken! x) {
+ Expect(1);
+ x = token;
+ if (x.val.StartsWith("\\"))
+ x.val = x.val.Substring(1);
+
+ }
+
+ static void TypeArgs(TypeSeq! ts) {
+ IToken! tok; Type! ty;
+ if (t.kind == 8 || t.kind == 13 || t.kind == 14) {
+ TypeAtom(out ty);
+ ts.Add(ty);
+ if (StartOf(2)) {
+ TypeArgs(ts);
+ }
+ } else if (t.kind == 1) {
+ Ident(out tok);
+ TypeSeq! args = new TypeSeq ();
+ ts.Add(new UnresolvedTypeIdentifier (tok, tok.val, args));
+ if (StartOf(2)) {
+ TypeArgs(ts);
+ }
+ } else if (t.kind == 15 || t.kind == 17) {
+ MapType(out ty);
+ ts.Add(ty);
+ } else Error(90);
+ }
+
+ static void MapType(out Bpl.Type! ty) {
+ IToken tok = null;
+ IToken! nnTok;
+ TypeSeq! arguments = new TypeSeq();
+ Type! result;
+ TypeVariableSeq! typeParameters = new TypeVariableSeq();
+
+ if (t.kind == 17) {
+ TypeParams(out nnTok, out typeParameters);
+ tok = nnTok;
+ }
+ Expect(15);
+ if (tok == null) tok = token;
+ if (StartOf(2)) {
+ Types(arguments);
+ }
+ Expect(16);
+ Type(out result);
+ ty = new MapType(tok, typeParameters, arguments, result);
+
+ }
+
+ static void TypeParams(out IToken! tok, out Bpl.TypeVariableSeq! typeParams) {
+ TokenSeq! typeParamToks;
+ Expect(17);
+ tok = token;
+ Idents(out typeParamToks);
+ Expect(18);
+ typeParams = new TypeVariableSeq ();
+ foreach (Token! id in typeParamToks)
+ typeParams.Add(new TypeVariable(id, id.val));
+
+ }
+
+ static void Types(TypeSeq! ts) {
+ Bpl.Type! ty;
+ Type(out ty);
+ ts.Add(ty);
+ while (t.kind == 11) {
+ Get();
+ Type(out ty);
+ ts.Add(ty);
+ }
+ }
+
+ static void OrderSpec(out bool ChildrenComplete, out List<ConstantParent!> Parents) {
+ ChildrenComplete = false;
+ Parents = null;
+ bool u;
+ IToken! parent;
+ Expect(21);
+ Parents = new List<ConstantParent!> ();
+ u = false;
+ if (t.kind == 1 || t.kind == 20) {
+ if (t.kind == 20) {
+ Get();
+ u = true;
+ }
+ Ident(out parent);
+ Parents.Add(new ConstantParent (
+ new IdentifierExpr(parent, parent.val), u));
+ while (t.kind == 11) {
+ Get();
+ u = false;
+ if (t.kind == 20) {
+ Get();
+ u = true;
+ }
+ Ident(out parent);
+ Parents.Add(new ConstantParent (
+ new IdentifierExpr(parent, parent.val), u));
+ }
+ }
+ if (t.kind == 22) {
+ Get();
+ ChildrenComplete = true;
+ }
+ }
+
+ static void VarOrType(out TypedIdent! tyd) {
+ string! varName = ""; Bpl.Type! ty; IToken! tok;
+ Type(out ty);
+ tok = ty.tok;
+ if (t.kind == 10) {
+ Get();
+ if (ty is UnresolvedTypeIdentifier &&
+ ((!)(ty as UnresolvedTypeIdentifier)).Arguments.Length == 0) {
+ varName = ((!)(ty as UnresolvedTypeIdentifier)).Name;
+ } else {
+ SemErr("expected identifier before ':'");
+ }
+
+ Type(out ty);
+ }
+ tyd = new TypedIdent(tok, varName, ty);
+ }
+
+ static void Proposition(out Expr! e) {
+ Expression(out e);
+ }
+
+ static void UserDefinedType(out Declaration! decl, QKeyValue kv) {
+ IToken! id; IToken! id2; TokenSeq! paramTokens = new TokenSeq ();
+ Type! body = dummyType; bool synonym = false;
+ Ident(out id);
+ if (t.kind == 1) {
+ WhiteSpaceIdents(out paramTokens);
+ }
+ if (t.kind == 29) {
+ Get();
+ Type(out body);
+ synonym = true;
+ }
+ if (synonym) {
+ TypeVariableSeq! typeParams = new TypeVariableSeq();
+ foreach (Token! t in paramTokens)
+ typeParams.Add(new TypeVariable(t, t.val));
+ decl = new TypeSynonymDecl(id, id.val, typeParams, body, kv);
+ } else {
+ decl = new TypeCtorDecl(id, id.val, paramTokens.Length, kv);
+ }
+
+ }
+
+ static void WhiteSpaceIdents(out TokenSeq! xs) {
+ IToken! id; xs = new TokenSeq();
+ Ident(out id);
+ xs.Add(id);
+ while (t.kind == 1) {
+ Ident(out id);
+ xs.Add(id);
+ }
+ }
+
+ static void ProcSignature(bool allowWhereClausesOnFormals, out IToken! name, out TypeVariableSeq! typeParams,
+out VariableSeq! ins, out VariableSeq! outs, out QKeyValue kv) {
+ IToken! typeParamTok; typeParams = new TypeVariableSeq();
+ outs = new VariableSeq(); kv = null;
+ while (t.kind == 25) {
+ Attribute(ref kv);
+ }
+ Ident(out name);
+ if (t.kind == 17) {
+ TypeParams(out typeParamTok, out typeParams);
+ }
+ ProcFormals(true, allowWhereClausesOnFormals, out ins);
+ if (t.kind == 24) {
+ Get();
+ ProcFormals(false, allowWhereClausesOnFormals, out outs);
+ }
+ }
+
+ static void Spec(RequiresSeq! pre, IdentifierExprSeq! mods, EnsuresSeq! post) {
+ TokenSeq! ms;
+ if (t.kind == 32) {
+ Get();
+ if (t.kind == 1) {
+ Idents(out ms);
+ foreach (IToken! m in ms) {
+ mods.Add(new IdentifierExpr(m, m.val));
+ }
+
+ }
+ Expect(7);
+ } else if (t.kind == 33) {
+ Get();
+ SpecPrePost(true, pre, post);
+ } else if (t.kind == 34 || t.kind == 35) {
+ SpecPrePost(false, pre, post);
+ } else Error(91);
+ }
+
+ static void ImplBody(out VariableSeq! locals, out StmtList! stmtList) {
+ locals = new VariableSeq();
+ Expect(25);
+ while (t.kind == 6) {
+ LocalVars(locals);
+ }
+ StmtList(out stmtList);
+ }
+
+ static void SpecPrePost(bool free, RequiresSeq! pre, EnsuresSeq! post) {
+ Expr! e; VariableSeq! locals; BlockSeq! blocks; Token tok = null; QKeyValue kv = null;
+ if (t.kind == 34) {
+ Get();
+ tok = token;
+ while (t.kind == 25) {
+ Attribute(ref kv);
+ }
+ if (StartOf(5)) {
+ Proposition(out e);
+ Expect(7);
+ pre.Add(new Requires(tok, free, e, null, kv));
+ } else if (t.kind == 36) {
+ SpecBody(out locals, out blocks);
+ Expect(7);
+ pre.Add(new Requires(tok, free, new BlockExpr(locals, blocks), null, kv));
+ } else Error(92);
+ } else if (t.kind == 35) {
+ Get();
+ tok = token;
+ while (t.kind == 25) {
+ Attribute(ref kv);
+ }
+ if (StartOf(5)) {
+ Proposition(out e);
+ Expect(7);
+ post.Add(new Ensures(tok, free, e, null, kv));
+ } else if (t.kind == 36) {
+ SpecBody(out locals, out blocks);
+ Expect(7);
+ post.Add(new Ensures(tok, free, new BlockExpr(locals, blocks), null, kv));
+ } else Error(93);
+ } else Error(94);
+ }
+
+ static void SpecBody(out VariableSeq! locals, out BlockSeq! blocks) {
+ locals = new VariableSeq(); Block! b;
+ Expect(36);
+ while (t.kind == 6) {
+ LocalVars(locals);
+ }
+ SpecBlock(out b);
+ blocks = new BlockSeq(b);
+ while (t.kind == 1) {
+ SpecBlock(out b);
+ blocks.Add(b);
+ }
+ Expect(37);
+ }
+
+ static void SpecBlock(out Block! b) {
+ IToken! x; IToken! y;
+ Cmd c; IToken label;
+ CmdSeq cs = new CmdSeq();
+ TokenSeq! xs;
+ StringSeq ss = new StringSeq();
+ b = dummyBlock;
+ Expr! e;
+
+ Ident(out x);
+ Expect(10);
+ while (StartOf(6)) {
+ LabelOrCmd(out c, out label);
+ if (c != null) {
+ assert label == null;
+ cs.Add(c);
+ } else {
+ assert label != null;
+ SemErr("SpecBlock's can only have one label");
+ }
+
+ }
+ if (t.kind == 38) {
+ Get();
+ y = token;
+ Idents(out xs);
+ foreach (IToken! s in xs) { ss.Add(s.val); }
+ b = new Block(x,x.val,cs,new GotoCmd(y,ss));
+
+ } else if (t.kind == 39) {
+ Get();
+ Expression(out e);
+ b = new Block(x,x.val,cs,new ReturnExprCmd(token,e));
+ } else Error(95);
+ Expect(7);
+ }
+
+ static void LabelOrCmd(out Cmd c, out IToken label) {
+ IToken! x; Expr! e;
+ TokenSeq! xs;
+ IdentifierExprSeq ids;
+ c = dummyCmd; label = null;
+ Cmd! cn;
+ QKeyValue kv = null;
+
+ if (t.kind == 1) {
+ LabelOrAssign(out c, out label);
+ } else if (t.kind == 46) {
+ Get();
+ x = token;
+ while (t.kind == 25) {
+ Attribute(ref kv);
+ }
+ Proposition(out e);
+ c = new AssertCmd(x,e, kv);
+ Expect(7);
+ } else if (t.kind == 47) {
+ Get();
+ x = token;
+ Proposition(out e);
+ c = new AssumeCmd(x,e);
+ Expect(7);
+ } else if (t.kind == 48) {
+ Get();
+ x = token;
+ Idents(out xs);
+ Expect(7);
+ ids = new IdentifierExprSeq();
+ foreach (IToken! y in xs) {
+ ids.Add(new IdentifierExpr(y, y.val));
+ }
+ c = new HavocCmd(x,ids);
+
+ } else if (t.kind == 50) {
+ CallCmd(out cn);
+ Expect(7);
+ c = cn;
+ } else Error(96);
+ }
+
+ static void StmtList(out StmtList! stmtList) {
+ List<BigBlock!> bigblocks = new List<BigBlock!>();
+ /* built-up state for the current BigBlock: */
+ IToken startToken = null; string currentLabel = null;
+ CmdSeq cs = null; /* invariant: startToken != null ==> cs != null */
+ /* temporary variables: */
+ IToken label; Cmd c; BigBlock b;
+ StructuredCmd ec = null; StructuredCmd! ecn;
+ TransferCmd tc = null; TransferCmd! tcn;
+
+ while (StartOf(7)) {
+ if (StartOf(6)) {
+ LabelOrCmd(out c, out label);
+ if (c != null) {
+ // LabelOrCmd read a Cmd
+ assert label == null;
+ if (startToken == null) { startToken = c.tok; cs = new CmdSeq(); }
+ assert cs != null;
+ cs.Add(c);
+ } else {
+ // LabelOrCmd read a label
+ assert label != null;
+ if (startToken != null) {
+ assert cs != null;
+ // dump the built-up state into a BigBlock
+ b = new BigBlock(startToken, currentLabel, cs, null, null);
+ bigblocks.Add(b);
+ cs = null;
+ }
+ startToken = label;
+ currentLabel = label.val;
+ cs = new CmdSeq();
+ }
+
+ } else if (t.kind == 40 || t.kind == 42 || t.kind == 45) {
+ StructuredCmd(out ecn);
+ ec = ecn;
+ if (startToken == null) { startToken = ec.tok; cs = new CmdSeq(); }
+ assert cs != null;
+ b = new BigBlock(startToken, currentLabel, cs, ec, null);
+ bigblocks.Add(b);
+ startToken = null; currentLabel = null; cs = null;
+
+ } else {
+ TransferCmd(out tcn);
+ tc = tcn;
+ if (startToken == null) { startToken = tc.tok; cs = new CmdSeq(); }
+ assert cs != null;
+ b = new BigBlock(startToken, currentLabel, cs, null, tc);
+ bigblocks.Add(b);
+ startToken = null; currentLabel = null; cs = null;
+
+ }
+ }
+ Expect(26);
+ IToken! endCurly = token;
+ if (startToken == null && bigblocks.Count == 0) {
+ startToken = token; cs = new CmdSeq();
+ }
+ if (startToken != null) {
+ assert cs != null;
+ b = new BigBlock(startToken, currentLabel, cs, null, null);
+ bigblocks.Add(b);
+ }
+ stmtList = new StmtList(bigblocks, endCurly);
+
+ }
+
+ static void StructuredCmd(out StructuredCmd! ec) {
+ ec = dummyStructuredCmd; assume ec.IsPeerConsistent;
+ IfCmd! ifcmd; WhileCmd! wcmd; BreakCmd! bcmd;
+
+ if (t.kind == 40) {
+ IfCmd(out ifcmd);
+ ec = ifcmd;
+ } else if (t.kind == 42) {
+ WhileCmd(out wcmd);
+ ec = wcmd;
+ } else if (t.kind == 45) {
+ BreakCmd(out bcmd);
+ ec = bcmd;
+ } else Error(97);
+ }
+
+ static void TransferCmd(out TransferCmd! tc) {
+ tc = dummyTransferCmd;
+ Token y; TokenSeq! xs;
+ StringSeq ss = new StringSeq();
+
+ if (t.kind == 38) {
+ Get();
+ y = token;
+ Idents(out xs);
+ foreach (IToken! s in xs) { ss.Add(s.val); }
+ tc = new GotoCmd(y, ss);
+
+ } else if (t.kind == 39) {
+ Get();
+ tc = new ReturnCmd(token);
+ } else Error(98);
+ Expect(7);
+ }
+
+ static void IfCmd(out IfCmd! ifcmd) {
+ IToken! x;
+ Expr guard;
+ StmtList! thn;
+ IfCmd! elseIf; IfCmd elseIfOption = null;
+ StmtList! els; StmtList elseOption = null;
+
+ Expect(40);
+ x = token;
+ Guard(out guard);
+ Expect(25);
+ StmtList(out thn);
+ if (t.kind == 41) {
+ Get();
+ if (t.kind == 40) {
+ IfCmd(out elseIf);
+ elseIfOption = elseIf;
+ } else if (t.kind == 25) {
+ Get();
+ StmtList(out els);
+ elseOption = els;
+ } else Error(99);
+ }
+ ifcmd = new IfCmd(x, guard, thn, elseIfOption, elseOption);
+ }
+
+ static void WhileCmd(out WhileCmd! wcmd) {
+ IToken! x; Token z;
+ Expr guard; Expr! e; bool isFree;
+ List<PredicateCmd!> invariants = new List<PredicateCmd!>();
+ StmtList! body;
+
+ Expect(42);
+ x = token;
+ Guard(out guard);
+ assume guard == null || Owner.None(guard);
+ while (t.kind == 33 || t.kind == 43) {
+ isFree = false; z = t/*lookahead token*/;
+ if (t.kind == 33) {
+ Get();
+ isFree = true;
+ }
+ Expect(43);
+ Expression(out e);
+ if (isFree) {
+ invariants.Add(new AssumeCmd(z, e));
+ } else {
+ invariants.Add(new AssertCmd(z, e));
+ }
+
+ Expect(7);
+ }
+ Expect(25);
+ StmtList(out body);
+ wcmd = new WhileCmd(x, guard, invariants, body);
+ }
+
+ static void BreakCmd(out BreakCmd! bcmd) {
+ IToken! x; IToken! y;
+ string breakLabel = null;
+
+ Expect(45);
+ x = token;
+ if (t.kind == 1) {
+ Ident(out y);
+ breakLabel = y.val;
+ }
+ Expect(7);
+ bcmd = new BreakCmd(x, breakLabel);
+ }
+
+ static void Guard(out Expr e) {
+ Expr! ee; e = null;
+ Expect(8);
+ if (t.kind == 44) {
+ Get();
+ e = null;
+ } else if (StartOf(5)) {
+ Expression(out ee);
+ e = ee;
+ } else Error(100);
+ Expect(9);
+ }
+
+ static void LabelOrAssign(out Cmd c, out IToken label) {
+ IToken! id; IToken! x; Expr! e, e0;
+ c = dummyCmd; label = null;
+ AssignLhs! lhs;
+ List<AssignLhs!>! lhss;
+ List<Expr!>! rhss;
+
+ Ident(out id);
+ x = token;
+ if (t.kind == 10) {
+ Get();
+ c = null; label = x;
+ } else if (t.kind == 11 || t.kind == 15 || t.kind == 49) {
+ MapAssignIndexes(id, out lhs);
+ lhss = new List<AssignLhs!> ();
+ lhss.Add(lhs);
+ while (t.kind == 11) {
+ Get();
+ Ident(out id);
+ MapAssignIndexes(id, out lhs);
+ lhss.Add(lhs);
+ }
+ Expect(49);
+ x = token; /* use location of := */
+ Expression(out e0);
+ rhss = new List<Expr!> ();
+ rhss.Add(e0);
+ while (t.kind == 11) {
+ Get();
+ Expression(out e0);
+ rhss.Add(e0);
+ }
+ Expect(7);
+ c = new AssignCmd(x, lhss, rhss);
+ } else Error(101);
+ }
+
+ static void CallCmd(out Cmd! c) {
+ IToken! x; IToken! first; IToken p;
+ List<IdentifierExpr>! ids = new List<IdentifierExpr>();
+ List<Expr>! es = new List<Expr>();
+ Expr en; List<Expr> args;
+ c = dummyCmd;
+
+ Expect(50);
+ x = token;
+ if (t.kind == 1) {
+ Ident(out first);
+ if (t.kind == 8) {
+ Get();
+ if (StartOf(8)) {
+ CallForallArg(out en);
+ es.Add(en);
+ while (t.kind == 11) {
+ Get();
+ CallForallArg(out en);
+ es.Add(en);
+ }
+ }
+ Expect(9);
+ c = new CallCmd(x, first.val, es, ids);
+ } else if (t.kind == 11 || t.kind == 49) {
+ ids.Add(new IdentifierExpr(first, first.val));
+ if (t.kind == 11) {
+ Get();
+ CallOutIdent(out p);
+ if (p==null) {
+ ids.Add(null);
+ } else {
+ ids.Add(new IdentifierExpr(p, p.val));
+ }
+
+ while (t.kind == 11) {
+ Get();
+ CallOutIdent(out p);
+ if (p==null) {
+ ids.Add(null);
+ } else {
+ ids.Add(new IdentifierExpr(p, p.val));
+ }
+
+ }
+ }
+ Expect(49);
+ Ident(out first);
+ Expect(8);
+ if (StartOf(8)) {
+ CallForallArg(out en);
+ es.Add(en);
+ while (t.kind == 11) {
+ Get();
+ CallForallArg(out en);
+ es.Add(en);
+ }
+ }
+ Expect(9);
+ c = new CallCmd(x, first.val, es, ids);
+ } else Error(102);
+ } else if (t.kind == 51) {
+ Get();
+ Ident(out first);
+ Expect(8);
+ args = new List<Expr>();
+ if (StartOf(8)) {
+ CallForallArg(out en);
+ args.Add(en);
+ while (t.kind == 11) {
+ Get();
+ CallForallArg(out en);
+ args.Add(en);
+ }
+ }
+ Expect(9);
+ c = new CallForallCmd(x, first.val, args);
+ } else if (t.kind == 44) {
+ Get();
+ ids.Add(null);
+ if (t.kind == 11) {
+ Get();
+ CallOutIdent(out p);
+ if (p==null) {
+ ids.Add(null);
+ } else {
+ ids.Add(new IdentifierExpr(p, p.val));
+ }
+
+ while (t.kind == 11) {
+ Get();
+ CallOutIdent(out p);
+ if (p==null) {
+ ids.Add(null);
+ } else {
+ ids.Add(new IdentifierExpr(p, p.val));
+ }
+
+ }
+ }
+ Expect(49);
+ Ident(out first);
+ Expect(8);
+ if (StartOf(8)) {
+ CallForallArg(out en);
+ es.Add(en);
+ while (t.kind == 11) {
+ Get();
+ CallForallArg(out en);
+ es.Add(en);
+ }
+ }
+ Expect(9);
+ c = new CallCmd(x, first.val, es, ids);
+ } else Error(103);
+ }
+
+ static void MapAssignIndexes(IToken! assignedVariable, out AssignLhs! lhs) {
+ IToken! x;
+ AssignLhs! runningLhs =
+ new SimpleAssignLhs(assignedVariable,
+ new IdentifierExpr(assignedVariable, assignedVariable.val));
+ List<Expr!>! indexes;
+ Expr! e0;
+
+ while (t.kind == 15) {
+ Get();
+ x = token;
+ indexes = new List<Expr!> ();
+ if (StartOf(5)) {
+ Expression(out e0);
+ indexes.Add(e0);
+ while (t.kind == 11) {
+ Get();
+ Expression(out e0);
+ indexes.Add(e0);
+ }
+ }
+ Expect(16);
+ runningLhs =
+ new MapAssignLhs (x, runningLhs, indexes);
+ }
+ lhs = runningLhs;
+ }
+
+ static void CallForallArg(out Expr exprOptional) {
+ exprOptional = null;
+ Expr! e;
+
+ if (t.kind == 44) {
+ Get();
+ } else if (StartOf(5)) {
+ Expression(out e);
+ exprOptional = e;
+ } else Error(104);
+ }
+
+ static void CallOutIdent(out IToken id) {
+ id = null;
+ IToken! p;
+
+ if (t.kind == 44) {
+ Get();
+ } else if (t.kind == 1) {
+ Ident(out p);
+ id = p;
+ } else Error(105);
+ }
+
+ static void Expressions(out ExprSeq! es) {
+ Expr! e; es = new ExprSeq();
+ Expression(out e);
+ es.Add(e);
+ while (t.kind == 11) {
+ Get();
+ Expression(out e);
+ es.Add(e);
+ }
+ }
+
+ static void ImpliesExpression(bool noExplies, out Expr! e0) {
+ IToken! x; Expr! e1;
+ LogicalExpression(out e0);
+ if (StartOf(9)) {
+ if (t.kind == 54 || t.kind == 55) {
+ ImpliesOp();
+ x = token;
+ ImpliesExpression(true, out e1);
+ e0 = Expr.Binary(x, BinaryOperator.Opcode.Imp, e0, e1);
+ } else {
+ ExpliesOp();
+ if (noExplies)
+ SemErr("illegal mixture of ==> and <==, use parentheses to disambiguate");
+ x = token;
+ LogicalExpression(out e1);
+ e0 = Expr.Binary(x, BinaryOperator.Opcode.Imp, e1, e0);
+ while (t.kind == 56 || t.kind == 57) {
+ ExpliesOp();
+ x = token;
+ LogicalExpression(out e1);
+ e0 = Expr.Binary(x, BinaryOperator.Opcode.Imp, e1, e0);
+ }
+ }
+ }
+ }
+
+ static void EquivOp() {
+ if (t.kind == 52) {
+ Get();
+ } else if (t.kind == 53) {
+ Get();
+ } else Error(106);
+ }
+
+ static void LogicalExpression(out Expr! e0) {
+ IToken! x; Expr! e1; BinaryOperator.Opcode op;
+ RelationalExpression(out e0);
+ if (StartOf(10)) {
+ if (t.kind == 58 || t.kind == 59) {
+ AndOp();
+ x = token;
+ RelationalExpression(out e1);
+ e0 = Expr.Binary(x, BinaryOperator.Opcode.And, e0, e1);
+ while (t.kind == 58 || t.kind == 59) {
+ AndOp();
+ x = token;
+ RelationalExpression(out e1);
+ e0 = Expr.Binary(x, BinaryOperator.Opcode.And, e0, e1);
+ }
+ } else {
+ OrOp();
+ x = token;
+ RelationalExpression(out e1);
+ e0 = Expr.Binary(x, BinaryOperator.Opcode.Or, e0, e1);
+ while (t.kind == 60 || t.kind == 61) {
+ OrOp();
+ x = token;
+ RelationalExpression(out e1);
+ e0 = Expr.Binary(x, BinaryOperator.Opcode.Or, e0, e1);
+ }
+ }
+ }
+ }
+
+ static void ImpliesOp() {
+ if (t.kind == 54) {
+ Get();
+ } else if (t.kind == 55) {
+ Get();
+ } else Error(107);
+ }
+
+ static void ExpliesOp() {
+ if (t.kind == 56) {
+ Get();
+ } else if (t.kind == 57) {
+ Get();
+ } else Error(108);
+ }
+
+ static void RelationalExpression(out Expr! e0) {
+ IToken! x; Expr! e1; BinaryOperator.Opcode op;
+ BvTerm(out e0);
+ if (StartOf(11)) {
+ RelOp(out x, out op);
+ BvTerm(out e1);
+ e0 = Expr.Binary(x, op, e0, e1);
+ }
+ }
+
+ static void AndOp() {
+ if (t.kind == 58) {
+ Get();
+ } else if (t.kind == 59) {
+ Get();
+ } else Error(109);
+ }
+
+ static void OrOp() {
+ if (t.kind == 60) {
+ Get();
+ } else if (t.kind == 61) {
+ Get();
+ } else Error(110);
+ }
+
+ static void BvTerm(out Expr! e0) {
+ IToken! x; Expr! e1;
+ Term(out e0);
+ while (t.kind == 70) {
+ Get();
+ x = token;
+ Term(out e1);
+ e0 = new BvConcatExpr(x, e0, e1);
+ }
+ }
+
+ static void RelOp(out IToken! x, out BinaryOperator.Opcode op) {
+ x = Token.NoToken; op=BinaryOperator.Opcode.Add/*(dummy)*/;
+ switch (t.kind) {
+ case 62: {
+ Get();
+ x = token; op=BinaryOperator.Opcode.Eq;
+ break;
+ }
+ case 17: {
+ Get();
+ x = token; op=BinaryOperator.Opcode.Lt;
+ break;
+ }
+ case 18: {
+ Get();
+ x = token; op=BinaryOperator.Opcode.Gt;
+ break;
+ }
+ case 63: {
+ Get();
+ x = token; op=BinaryOperator.Opcode.Le;
+ break;
+ }
+ case 64: {
+ Get();
+ x = token; op=BinaryOperator.Opcode.Ge;
+ break;
+ }
+ case 65: {
+ Get();
+ x = token; op=BinaryOperator.Opcode.Neq;
+ break;
+ }
+ case 66: {
+ Get();
+ x = token; op=BinaryOperator.Opcode.Subtype;
+ break;
+ }
+ case 67: {
+ Get();
+ x = token; op=BinaryOperator.Opcode.Neq;
+ break;
+ }
+ case 68: {
+ Get();
+ x = token; op=BinaryOperator.Opcode.Le;
+ break;
+ }
+ case 69: {
+ Get();
+ x = token; op=BinaryOperator.Opcode.Ge;
+ break;
+ }
+ default: Error(111); break;
+ }
+ }
+
+ static void Term(out Expr! e0) {
+ IToken! x; Expr! e1; BinaryOperator.Opcode op;
+ Factor(out e0);
+ while (t.kind == 71 || t.kind == 72) {
+ AddOp(out x, out op);
+ Factor(out e1);
+ e0 = Expr.Binary(x, op, e0, e1);
+ }
+ }
+
+ static void Factor(out Expr! e0) {
+ IToken! x; Expr! e1; BinaryOperator.Opcode op;
+ UnaryExpression(out e0);
+ while (t.kind == 44 || t.kind == 73 || t.kind == 74) {
+ MulOp(out x, out op);
+ UnaryExpression(out e1);
+ e0 = Expr.Binary(x, op, e0, e1);
+ }
+ }
+
+ static void AddOp(out IToken! x, out BinaryOperator.Opcode op) {
+ x = Token.NoToken; op=BinaryOperator.Opcode.Add/*(dummy)*/;
+ if (t.kind == 71) {
+ Get();
+ x = token; op=BinaryOperator.Opcode.Add;
+ } else if (t.kind == 72) {
+ Get();
+ x = token; op=BinaryOperator.Opcode.Sub;
+ } else Error(112);
+ }
+
+ static void UnaryExpression(out Expr! e) {
+ IToken! x;
+ e = dummyExpr;
+
+ if (t.kind == 72) {
+ Get();
+ x = token;
+ UnaryExpression(out e);
+ e = Expr.Binary(x, BinaryOperator.Opcode.Sub, new LiteralExpr(x, BigNum.ZERO), e);
+ } else if (t.kind == 75 || t.kind == 76) {
+ NegOp();
+ x = token;
+ UnaryExpression(out e);
+ e = Expr.Unary(x, UnaryOperator.Opcode.Not, e);
+ } else if (StartOf(12)) {
+ CoercionExpression(out e);
+ } else Error(113);
+ }
+
+ static void MulOp(out IToken! x, out BinaryOperator.Opcode op) {
+ x = Token.NoToken; op=BinaryOperator.Opcode.Add/*(dummy)*/;
+ if (t.kind == 44) {
+ Get();
+ x = token; op=BinaryOperator.Opcode.Mul;
+ } else if (t.kind == 73) {
+ Get();
+ x = token; op=BinaryOperator.Opcode.Div;
+ } else if (t.kind == 74) {
+ Get();
+ x = token; op=BinaryOperator.Opcode.Mod;
+ } else Error(114);
+ }
+
+ static void NegOp() {
+ if (t.kind == 75) {
+ Get();
+ } else if (t.kind == 76) {
+ Get();
+ } else Error(115);
+ }
+
+ static void CoercionExpression(out Expr! e) {
+ IToken! x;
+ Type! coercedTo;
+ BigNum bn;
+
+ ArrayExpression(out e);
+ while (t.kind == 10) {
+ Get();
+ x = token;
+ if (StartOf(2)) {
+ Type(out coercedTo);
+ e = Expr.CoerceType(x, e, coercedTo);
+ } else if (t.kind == 3) {
+ Nat(out bn);
+ if (!(e is LiteralExpr) || !((LiteralExpr)e).isBigNum) {
+ SemErr("arguments of extract need to be integer literals");
+ e = new BvBounds(x, bn, BigNum.ZERO);
+ } else {
+ e = new BvBounds(x, bn, ((LiteralExpr)e).asBigNum);
+ }
+
+ } else Error(116);
+ }
+ }
+
+ static void ArrayExpression(out Expr! e) {
+ IToken! x;
+ Expr! index0 = dummyExpr; Expr! e1;
+ bool store; bool bvExtract;
+ ExprSeq! allArgs = dummyExprSeq;
+
+ AtomExpression(out e);
+ while (t.kind == 15) {
+ Get();
+ x = token; allArgs = new ExprSeq ();
+ allArgs.Add(e);
+ store = false; bvExtract = false;
+ if (StartOf(13)) {
+ if (StartOf(5)) {
+ Expression(out index0);
+ if (index0 is BvBounds)
+ bvExtract = true;
+ else
+ allArgs.Add(index0);
+
+ while (t.kind == 11) {
+ Get();
+ Expression(out e1);
+ if (bvExtract || e1 is BvBounds)
+ SemErr("bitvectors only have one dimension");
+ allArgs.Add(e1);
+
+ }
+ if (t.kind == 49) {
+ Get();
+ Expression(out e1);
+ if (bvExtract || e1 is BvBounds)
+ SemErr("assignment to bitvectors is not possible");
+ allArgs.Add(e1); store = true;
+
+ }
+ } else {
+ Get();
+ Expression(out e1);
+ allArgs.Add(e1); store = true;
+ }
+ }
+ Expect(16);
+ if (store)
+ e = new NAryExpr(x, new MapStore(x, allArgs.Length - 2), allArgs);
+ else if (bvExtract)
+ e = new ExtractExpr(x, e,
+ ((BvBounds)index0).Upper.ToIntSafe,
+ ((BvBounds)index0).Lower.ToIntSafe);
+ else
+ e = new NAryExpr(x, new MapSelect(x, allArgs.Length - 1), allArgs);
+
+ }
+ }
+
+ static void Nat(out BigNum n) {
+ Expect(3);
+ try {
+ n = BigNum.FromString(token.val);
+ } catch (FormatException) {
+ SemErr("incorrectly formatted number");
+ n = BigNum.ZERO;
+ }
+
+ }
+
+ static void AtomExpression(out Expr! e) {
+ IToken! x; int n; BigNum bn;
+ ExprSeq! es; VariableSeq! ds; Trigger trig;
+ TypeVariableSeq! typeParams;
+ IdentifierExpr! id;
+ Bpl.Type! ty;
+ QKeyValue kv;
+ e = dummyExpr;
+
+ switch (t.kind) {
+ case 77: {
+ Get();
+ e = new LiteralExpr(token, false);
+ break;
+ }
+ case 78: {
+ Get();
+ e = new LiteralExpr(token, true);
+ break;
+ }
+ case 3: {
+ Nat(out bn);
+ e = new LiteralExpr(token, bn);
+ break;
+ }
+ case 2: {
+ BvLit(out bn, out n);
+ e = new LiteralExpr(token, bn, n);
+ break;
+ }
+ case 1: {
+ Ident(out x);
+ id = new IdentifierExpr(x, x.val); e = id;
+ if (t.kind == 8) {
+ Get();
+ if (StartOf(5)) {
+ Expressions(out es);
+ e = new NAryExpr(x, new FunctionCall(id), es);
+ } else if (t.kind == 9) {
+ e = new NAryExpr(x, new FunctionCall(id), new ExprSeq());
+ } else Error(117);
+ Expect(9);
+ }
+ break;
+ }
+ case 79: {
+ Get();
+ x = token;
+ Expect(8);
+ Expression(out e);
+ Expect(9);
+ e = new OldExpr(x, e);
+ break;
+ }
+ case 8: {
+ Get();
+ if (StartOf(5)) {
+ Expression(out e);
+ if (e is BvBounds)
+ SemErr("parentheses around bitvector bounds " +
+ "are not allowed");
+ } else if (t.kind == 51 || t.kind == 80) {
+ Forall();
+ x = token;
+ 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 (t.kind == 81 || t.kind == 82) {
+ Exists();
+ x = token;
+ 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 Error(118);
+ Expect(9);
+ break;
+ }
+ default: Error(119); break;
+ }
+ }
+
+ static void BvLit(out BigNum n, out int m) {
+ Expect(2);
+ int pos = token.val.IndexOf("bv");
+ string a = token.val.Substring(0, pos);
+ string b = token.val.Substring(pos + 2);
+ try {
+ n = BigNum.FromString(a);
+ m = Convert.ToInt32(b);
+ } catch (FormatException) {
+ SemErr("incorrectly formatted bitvector");
+ n = BigNum.ZERO;
+ m = 0;
+ }
+
+ }
+
+ static void Forall() {
+ if (t.kind == 51) {
+ Get();
+ } else if (t.kind == 80) {
+ Get();
+ } else Error(120);
+ }
+
+ static void QuantifierBody(IToken! q, out TypeVariableSeq! typeParams, out VariableSeq! ds,
+out QKeyValue kv, out Trigger trig, out Expr! body) {
+ trig = null; typeParams = new TypeVariableSeq ();
+ IToken! tok; Expr! e; ExprSeq! es;
+ kv = null; string key; string value;
+ ds = new VariableSeq ();
+
+ if (t.kind == 17) {
+ TypeParams(out tok, out typeParams);
+ if (t.kind == 1) {
+ BoundVars(q, out ds);
+ }
+ } else if (t.kind == 1) {
+ BoundVars(q, out ds);
+ } else Error(121);
+ QSep();
+ while (t.kind == 25) {
+ AttributeOrTrigger(ref kv, ref trig);
+ }
+ Expression(out body);
+ }
+
+ static void Exists() {
+ if (t.kind == 81) {
+ Get();
+ } else if (t.kind == 82) {
+ Get();
+ } else Error(122);
+ }
+
+ static void AttributeOrTrigger(ref QKeyValue kv, ref Trigger trig) {
+ IToken! tok; Expr! e; ExprSeq! es;
+ string key; string value;
+ List<object!> parameters; object! param;
+
+ Expect(25);
+ tok = token;
+ if (t.kind == 10) {
+ Get();
+ Expect(1);
+ key = token.val; parameters = new List<object!>();
+ if (StartOf(14)) {
+ AttributeParameter(out param);
+ parameters.Add(param);
+ while (t.kind == 11) {
+ Get();
+ AttributeParameter(out param);
+ parameters.Add(param);
+ }
+ }
+ if (key == "nopats") {
+ if (parameters.Count == 1 && parameters[0] is Expr) {
+ e = (Expr)parameters[0];
+ if(trig==null){
+ trig = new Trigger(tok, false, new ExprSeq(e), null);
+ } else {
+ trig.AddLast(new Trigger(tok, false, new ExprSeq(e), null));
+ }
+ } else {
+ SemErr("the 'nopats' quantifier attribute expects a string-literal parameter");
+ }
+ } else {
+ if (kv==null) {
+ kv = new QKeyValue(tok, key, parameters, null);
+ } else {
+ kv.AddLast(new QKeyValue(tok, key, parameters, null));
+ }
+ }
+
+ } else if (StartOf(5)) {
+ Expression(out e);
+ es = new ExprSeq(e);
+ while (t.kind == 11) {
+ Get();
+ Expression(out e);
+ es.Add(e);
+ }
+ if (trig==null) {
+ trig = new Trigger(tok, true, es, null);
+ } else {
+ trig.AddLast(new Trigger(tok, true, es, null));
+ }
+
+ } else Error(123);
+ Expect(26);
+ }
+
+ static void AttributeParameter(out object! o) {
+ o = "error";
+ Expr! e;
+
+ if (t.kind == 4) {
+ Get();
+ o = token.val.Substring(1, token.val.Length-2);
+ } else if (StartOf(5)) {
+ Expression(out e);
+ o = e;
+ } else Error(124);
+ }
+
+ static void QSep() {
+ if (t.kind == 83) {
+ Get();
+ } else if (t.kind == 84) {
+ Get();
+ } else Error(125);
+ }
+
+
+
+ public static void Parse() {
+ Errors.SynErr = new ErrorProc(SynErr);
+ t = new Token();
+ Get();
+ BoogiePL();
+
+ }
+
+ [Microsoft.Contracts.Verify(false)]
+ static void SynErr(int n, string filename, int line, int col) {
+ Errors.count++;
+ Console.Write("{0}({1},{2}): syntax error: ", filename, line, col);
+ string s;
+ switch (n) {
+ case 0: s = "EOF expected"; break;
+ case 1: s = "ident expected"; break;
+ 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 = "{{ expected"; break;
+ case 37: s = "}} 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 = "/ expected"; break;
+ case 74: s = "% expected"; break;
+ case 75: s = "! expected"; break;
+ case 76: s = "\\u00ac expected"; break;
+ case 77: s = "false expected"; break;
+ case 78: s = "true expected"; break;
+ case 79: s = "old expected"; break;
+ case 80: s = "\\u2200 expected"; break;
+ case 81: s = "exists expected"; break;
+ case 82: s = "\\u2203 expected"; break;
+ case 83: s = ":: expected"; break;
+ case 84: s = "\\u2022 expected"; break;
+ case 85: s = "??? expected"; break;
+ case 86: s = "invalid Function"; break;
+ case 87: s = "invalid Procedure"; break;
+ case 88: s = "invalid Type"; break;
+ case 89: s = "invalid TypeAtom"; break;
+ case 90: s = "invalid TypeArgs"; break;
+ case 91: s = "invalid Spec"; break;
+ case 92: s = "invalid SpecPrePost"; break;
+ case 93: s = "invalid SpecPrePost"; break;
+ case 94: s = "invalid SpecPrePost"; break;
+ case 95: s = "invalid SpecBlock"; break;
+ case 96: s = "invalid LabelOrCmd"; break;
+ case 97: s = "invalid StructuredCmd"; break;
+ case 98: s = "invalid TransferCmd"; break;
+ case 99: s = "invalid IfCmd"; break;
+ case 100: s = "invalid Guard"; break;
+ case 101: s = "invalid LabelOrAssign"; break;
+ case 102: s = "invalid CallCmd"; break;
+ case 103: s = "invalid CallCmd"; break;
+ case 104: s = "invalid CallForallArg"; break;
+ case 105: s = "invalid CallOutIdent"; break;
+ case 106: s = "invalid EquivOp"; break;
+ case 107: s = "invalid ImpliesOp"; break;
+ case 108: s = "invalid ExpliesOp"; break;
+ case 109: s = "invalid AndOp"; break;
+ case 110: s = "invalid OrOp"; break;
+ case 111: s = "invalid RelOp"; break;
+ case 112: s = "invalid AddOp"; break;
+ case 113: s = "invalid UnaryExpression"; break;
+ case 114: s = "invalid MulOp"; break;
+ case 115: s = "invalid NegOp"; break;
+ case 116: s = "invalid CoercionExpression"; break;
+ case 117: s = "invalid AtomExpression"; break;
+ case 118: s = "invalid AtomExpression"; break;
+ case 119: s = "invalid AtomExpression"; break;
+ case 120: s = "invalid Forall"; break;
+ case 121: s = "invalid QuantifierBody"; break;
+ case 122: s = "invalid Exists"; break;
+ case 123: s = "invalid AttributeOrTrigger"; break;
+ case 124: s = "invalid AttributeParameter"; break;
+ case 125: s = "invalid QSep"; break;
+
+ default: s = "error " + n; break;
+ }
+ Console.WriteLine(s);
+ }
+
+ static 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,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,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, 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,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,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,x,x, x,x,x,x, x,x,x,x, 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, 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,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,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,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,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,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, T,x,x,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,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,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,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,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,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,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,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,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,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, T,x,x,T, T,T,T,T, 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,x,x, x,x,x,x, x,x,x,x, 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, x,x,x,x, x,x,x}
+
+ };
+
+ [Microsoft.Contracts.Verify(false)]
+ static Parser() {}
+} // end Parser
+
+} // end namespace
diff --git a/Source/Core/PureCollections.ssc b/Source/Core/PureCollections.ssc
new file mode 100644
index 00000000..d51ebe62
--- /dev/null
+++ b/Source/Core/PureCollections.ssc
@@ -0,0 +1,785 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+
+//---------------------------------------------------------------------
+// PureCollections.cs
+// - Mostly pure functions for tuples, sets, maps, Sequences
+// Version 1.0, WS, 3/23/2002
+//---------------------------------------------------------------------
+
+
+using System;
+using System.Collections;
+using Microsoft.Contracts;
+
+namespace PureCollections {
+ //-------------------------------------------------------------------
+ // General types
+ //-------------------------------------------------------------------
+
+ public class MissingCase :Exception{}
+
+ public struct Capacity{
+ public int capacity;
+ public Capacity (int i) {capacity = i;}
+ }
+
+ abstract public class Coll {
+ public object[] elems; // null is used to show empty spots!
+ protected int card;
+ protected Coll() {}
+ protected Coll(object[] elems, int card) {this.elems = elems; this.card = card; }
+ protected Coll(Coll! c)
+ requires c.elems != null;
+ {
+ this.elems = (object[])c.elems.Clone();
+ this.card = c.card;
+ }
+ }
+
+
+ // ------------------------------------------------------------------
+ // Tuple
+ // ------------------------------------------------------------------
+
+ public class Tuple : Coll, IComparable
+ {
+ //public object[] elems;
+
+ //invariant this.elems != null;
+
+ // Constructor - - - - - - - - - - - - - - - - - - - - - - - - - -
+ public Tuple(params object []! ts) {
+ elems = ts;
+ card = ts.Length;}
+ public Tuple(Capacity c) {
+ elems = new object[c.capacity];
+ card = c.capacity;
+ }
+
+ //Equality - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+ [Pure][Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals (object o){
+ assert this.elems != null;
+ if (o == null || !(o is Tuple) || elems.Length != ((!)((Tuple)o).elems).Length)
+ return false;
+
+ Tuple s = (Tuple) o;
+ for(int i = 0; i < elems.Length; i ++)
+ if ( ! Equals(this.elems[i], s.elems[i]))
+ return false;
+ return true;
+ }
+
+ [Pure][Reads(ReadsAttribute.Reads.Nothing)] // ugh, is this right? --KRML
+ public static bool operator == (Tuple s, Tuple t) {return s == null ? t == null : s.Equals(t);}
+ [Pure][Reads(ReadsAttribute.Reads.Nothing)] // ugh, is this right? --KRML
+ public static bool operator != (Tuple s, Tuple t) { return ! (t == s); }
+
+ [Pure][Reads(ReadsAttribute.Reads.Owned)]
+ public override int GetHashCode (){
+ int h =0;
+ assume this.elems != null;
+ for(int i = 0; i < elems.Length; i++)
+ {
+ object elem = elems[i];
+ if (elem != null)
+ h += elem.GetHashCode();
+ }
+ return h;
+ }
+
+ //Compare - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ int IComparable.CompareTo(object o) {
+ assert this.elems != null;
+ if (o == null || !(o is Tuple) || elems.Length != ((!)((Tuple)o).elems).Length)
+ throw new MissingCase();
+
+ Tuple t = (Tuple) o;
+ for(int i = 0; i < elems.Length; i ++) {
+ int c = ((IComparable!) elems[i]).CompareTo(t.elems[i]);
+ if (c < 0) return -1;
+ else if (c > 0) return +1;
+ }
+ return 0;
+ }
+
+ public static bool operator <= (Tuple s, Tuple t) {return s == null ? t == null : ((IComparable) s).CompareTo(t) <= 0;}
+ public static bool operator < (Tuple s, Tuple t) {return s == null ? false : ((IComparable) s).CompareTo(t) < 0;}
+ public static bool operator >= (Tuple s, Tuple t) {return t <= s; }
+ public static bool operator > (Tuple s, Tuple t) { return t < s; }
+
+ //Select and Update - - - - - - - - - - - - - - - - - - - - - - - -
+ public object this[int index]{
+ get{assert this.elems != null; return elems[index];}
+ set{assert this.elems != null; elems[index] = value;}
+ }
+
+ //ToString - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ [Pure][Reads(ReadsAttribute.Reads.Owned)]
+ public override string! ToString() {
+ assert this.elems != null;
+ if (elems.Length==0)
+ return "()";
+
+ string s = "(";
+ for (int i= 0; i< elems.Length-1; i++)
+ s += ((!)elems[i]).ToString() + ", ";
+ return s + ((!)elems[elems.Length-1]).ToString() + ")";
+ }
+ }
+
+ // ------------------------------------------------------------------
+ // Pair
+ public class Pair : Tuple{
+ protected Pair(){}
+ public Pair(object first, object second) {
+ elems = new object[]{first,second};
+ }
+ public object First{
+ get{assert this.elems != null; return elems[0];}
+ set{assert this.elems != null; elems[0]=value;}
+ }
+ public object Second{
+ get{assert this.elems != null; return elems[1];}
+ set{assert this.elems != null; elems[1]=value;}
+ }
+ }
+
+ // --------------------------------------------------------------------
+ // Map
+ // --------------------------------------------------------------------
+
+ public class MapEnumerator: IEnumerator{
+ private Map! map;
+ private int index = -1;
+ public MapEnumerator(Map! m) { map = m;}
+ public bool MoveNext() {
+ do{
+ index++;
+ assert map.elems != null;
+ } while (index < map.elems.Length && map.elems[index] == null);
+ return index < map.elems.Length;
+ }
+ public object Current{ [Pure][Reads(ReadsAttribute.Reads.Owned)] get {assert map.elems != null; return new Pair(map.elems[index],map.vals[index]); }}
+ public void Reset() {index = -1; }
+ }
+
+ public class Map:Coll, IEnumerable, IComparable
+ {
+ public Object[]! vals;
+
+ //invariant this.elems != null;
+
+ // constructors - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ public Map(Capacity c){
+ elems = new Object[c.capacity*2];
+ vals = new Object[c.capacity*2];
+ card = 0;
+ }
+
+ [NotDelayed]
+ public Map(params Pair []! ps){
+ elems = new Object[ps.Length*2];
+ vals = new Object[ps.Length*2];
+ base();
+ card = 0;
+ for(int i = 0; i < ps.Length; i++)
+ Insert( ((!)ps[i]).First, ((!)ps[i]).Second);
+ }
+
+ // iterators - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ [Pure] [GlobalAccess(false)] [Escapes(true,false)]
+ public IEnumerator! GetEnumerator() {
+ return new MapEnumerator(this);
+ }
+ public Pair[] ToArray() {
+ Pair [] n = new Pair[card];
+ int ct = 0;
+ assert this.elems != null;
+ for(int i =0; i < elems.Length ; i++)
+ if (elems[i] != null)
+ n[ct++] = new Pair(elems[i], vals[i]);
+ return n;
+ }
+
+ //(ASM) Update- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ public Map Update(object k, object v) {
+ Map n = new Map(new Capacity(card+1));
+ assert this.elems != null;
+ for (int i = 0; i < elems.Length; i++ )
+ if (elems[i] != null && ! Equals(elems[i], k))
+ n.Insert(elems[i], vals[i]);
+ n.Insert(k,v);
+ return n;
+ }
+
+ //In place Update (and Remove)- - - - - - - - - - - - - - - - - - -
+ public object this[object index]{
+ get{return this.Apply(index);}
+ set{this.Insert(index,value);}
+ }
+
+ public void Remove(object! o) {
+ assert this.elems != null;
+ int h = Math.Abs(o.GetHashCode()) % elems.Length;
+ for (int i = 0; i < elems.Length; i++ ) {
+ int j = (i+ h) % elems.Length;
+ if (elems[j] == null) {
+ break;
+ } else if (Equals(elems[j], o)){
+ elems[j] = null;
+ vals[j] = null;
+ break;
+ }
+ }
+ }
+
+ public void Insert(Object key, Object val) {
+ if (key == null)
+ throw new MissingCase();
+
+ assert this.elems != null;
+ if (elems.Length == 0 || 2*card >= elems.Length){
+ int m = card*2; if (m < 4) m = 4;
+ object [] newElems = new object [m];
+ object [] newVals = new object [m];
+ for (int k = 0; k < elems.Length; k++) {
+ object elem = elems[k];
+ if (elem != null) {
+ int newHash = Math.Abs(elem.GetHashCode()) % newElems.Length;
+ for (int i = 0; i < newElems.Length; i++ ) {
+ int j = (i+ newHash) % newElems.Length;
+ if (newElems[j] == null) {
+ newElems[j] = elem;
+ newVals[j] = vals[k];
+ break;
+ }
+ }
+ }
+ }
+ elems = newElems;
+ vals = newVals;
+ }
+ int h = Math.Abs(key.GetHashCode()) % elems.Length;
+ for (int i = 0; i < elems.Length; i++ ) {
+ int j = (i+ h) % elems.Length;
+ if (elems[j] == null) {
+ elems[j] = key;
+ vals[j] = val;
+ card ++;
+ return;
+ } else if (key.Equals(elems[j])) {
+ vals[j] = val;
+ return;
+ }
+ }
+ }
+
+ //ToString - - - - - - - - - - - - - - - - - - - - - - - - -
+ [Pure][Reads(ReadsAttribute.Reads.Owned)]
+ public override string! ToString() {
+ if (card ==0)
+ return "{|->}";
+ else {
+ string s = "{"; int ct = 0;
+ assert this.elems != null;
+ for(int i =0; i < elems.Length ; i++) {
+ object elem = elems[i];
+ if (elem != null){
+ s += elem.ToString() +"|->" + ((!)vals[i]).ToString() ;
+ s +=(ct!=card-1) ? ", " : "";
+ ct ++;
+ }
+ }
+ return s+"}";
+ }
+ }
+
+ // Subset operations - - - - - - - - - - - - - - - - - - - - - - -
+ // View Map as Set of Pairs
+
+ int IComparable.CompareTo(object o) {
+ if (o == null || !(o is Map))
+ throw new MissingCase();
+ // WS Improve performance!
+ Map t = (Map) o;
+ if (this < t) return -1;
+ else if(this > t) return +1;
+ else return 0;
+ }
+ public static bool operator <= (Map s, Map t){
+ if (s==null) return t==null;
+ if (t==null) return false;
+ assert s.elems != null;
+ for(int i = 0; i < s.elems.Length; i++)
+ if (s.elems[i]!= null) {
+ object o = t.Apply(s.elems[i]);
+ if (o == null || !o.Equals(s.vals[i]))
+ return false;
+ }
+ return true;
+ }
+ public static bool operator < (Map s, Map t){
+ return s == null || t == null ? false : s.card < t.card && s <= t;
+ }
+ public static bool operator >= (Map s, Map t){
+ return t <= s;
+ }
+ public static bool operator > (Map s, Map t){
+ return t < s;
+ }
+
+ // Equality - - - - - - - - - - - - - - - - - - - - - - -
+ [Pure][Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals (Object t){
+ return t != null && t is Map && card == ((Map) t).card && this<= ((Map) t);
+ }
+ [Pure][Reads(ReadsAttribute.Reads.Nothing)] // ugh, is this right? --KRML
+ public static bool operator == (Map s, Map t){
+ if ((object)s==null)
+ if ((object)t==null) return true;
+ else return t.Equals(s);
+ else
+ return s.Equals(t);
+ }
+ [Pure][Reads(ReadsAttribute.Reads.Nothing)] // ugh, is this right? --KRML
+ public static bool operator != (Map s, Map t){
+ return ! (t == s);
+ }
+ [Pure][Reads(ReadsAttribute.Reads.Owned)]
+ public override int GetHashCode (){
+ int h =0;
+ assert this.elems != null;
+ for(int i = 0; i < elems.Length; i++)
+ {
+ object elem = elems[i];
+ if (elem != null)
+ {
+ h += elem.GetHashCode() + ((!)vals[i]).GetHashCode();
+ }
+ }
+ return h;
+ }
+
+ //Ordinary map operations- - - - - - - - - - - - - - - - - - - - - - - -
+
+ [Pure][Reads(ReadsAttribute.Reads.Owned)]
+ public bool Has(Object x) {
+ if (x == null)
+ throw new MissingCase();
+
+ assert this.elems != null;
+ if (elems.Length == 0)
+ return false;
+ int h = Math.Abs(x.GetHashCode()) % elems.Length;
+ for (int i = 0; i < elems.Length; i++ ) {
+ int j = (i+ h) % elems.Length;
+ if (x.Equals(elems[j]))
+ return true;
+ }
+ return false;
+ }
+
+ public object Apply(object x) {
+ if (x == null)
+ throw new MissingCase();
+ assert this.elems != null;
+ if (elems.Length == 0)
+ return null;
+ int h = Math.Abs(x.GetHashCode()) % elems.Length;
+ for (int i = 0; i < elems.Length; i++ ) {
+ int j = (i+ h) % elems.Length;
+ if (elems[j] != null && x.Equals(elems[j]))
+ return vals[j];
+ }
+ return null;
+ }
+
+ public static Map Override(Map! s, Map! t) {
+ Map m = new Map(new Capacity(s.card+t.card));
+ assert s.elems != null;
+ for(int i = 0; i< s.elems.Length; i++)
+ if (s.elems[i] != null)
+ m.Insert(s.elems[i], s.vals[i]);
+ assert t.elems != null;
+ for(int i = 0; i< t.elems.Length; i++)
+ if (t.elems[i] != null)
+ m.Insert(t.elems[i], t.vals[i]);
+ return m;
+ }
+ }
+
+ // --------------------------------------------------------------------
+ // Sequence
+
+ public class SequenceEnumerator: IEnumerator{
+ [Peer] private Sequence! seq;
+ private int index = -1;
+ [Captured]
+ public SequenceEnumerator(Sequence! s) { seq = s;}
+ public bool MoveNext() {
+ index++;
+ //while (index < seq.elems.Length); // Sequences allow nils ... && seq.elems[index] == null);
+ return index < seq.Length;
+ }
+ public object Current{ [Pure][Reads(ReadsAttribute.Reads.Owned)] get {assert seq.elems != null; return seq.elems[index]; }}
+ public void Reset() {index = -1; }
+ }
+
+ public class Sequence:Coll, IEnumerable, IComparable
+ {
+ public Sequence(){elems = new object [4];}
+
+ //invariant this.elems != null;
+
+ //constructors - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ public Sequence(params object []! ds){card = ds.Length; elems = ds; }
+ public Sequence(Sequence! seq) {
+ base(seq);
+ }
+ public Sequence(Capacity c){elems = new object [c.capacity];}
+
+ // Iterators - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ [Pure] [GlobalAccess(false)] [Escapes(true,false)]
+ public IEnumerator! GetEnumerator()
+ ensures Owner.Same(result, this);
+ ensures result.IsNew;
+ {
+ return new SequenceEnumerator(this);
+ }
+
+ public object[] ToArray() {
+ object [] n = new object[card];
+ int ct = 0;
+ assert this.elems != null;
+ for(int i =0; i < elems.Length ; i++)
+ n[ct++] = elems[i];
+ return n;
+ }
+
+ //ASM Update - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ public Sequence Update(int i, object v) {
+ Sequence n = new Sequence(new Capacity(card+1));
+ assert this.elems != null;
+ assert n.elems != null;
+ for (int j = 0; j < elems.Length; j++ )
+ n.elems[j] = elems[j];
+ if (i >= 0 && i < card){
+ n.elems[i] = v;
+ n.card = card;
+ return n;
+ } else if (i == card) {
+ n.elems[i] = v;
+ n.card = card+1;
+ return n;
+ } else
+ throw new Exception("Sequence Update out of range");
+ }
+
+ //In place Update (and Remove) and Length - - - - - - - - - - - - - - -
+ public int Length {
+ get{return this.card;}
+ }
+
+ public object this[int index]{
+ get{assert this.elems != null; return this.elems[index];}
+ set{assert this.elems != null; this.elems[index] = value;}
+ }
+
+ public void Add(object o){
+ assert this.elems != null;
+ int n = this.elems.Length;
+ int i = this.card++;
+ if (i == n){
+ int m = n*2; if (m < 4) m = 4;
+ object [] newElems = new object [m];
+ for (int j = 0; j < n; j++) newElems[j] = elems[j];
+ elems = newElems;
+ }
+ elems[i] = o;
+ }
+
+ public void AddRange(Sequence! seq){
+ foreach (object o in seq) {
+ Add(o);
+ }
+ }
+
+ public void Remove(){
+ if (card == 0)
+ return;
+ card--;
+ }
+
+ // remove the first occurrence of o from this sequence
+ public void Remove(Object x) {
+ if (x == null)
+ throw new MissingCase();
+ assert this.elems != null;
+ for (int i = 0; i < card; i++) {
+ if (x.Equals(elems[i])) {
+ ++i;
+ while (i < card) {
+ elems[i-1] = elems[i];
+ ++i;
+ }
+ card--;
+ elems[card] = null;
+ return;
+ }
+ }
+ }
+
+ public void Truncate(int newLen)
+ requires 0 <= newLen && newLen <= Length;
+ {
+ assert elems != null;
+ for (int i = newLen; i < card; i++) {
+ elems[i] = null;
+ }
+ card = newLen;
+ }
+
+ //ToString - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ [Pure][Reads(ReadsAttribute.Reads.Owned)]
+ public override string! ToString() {
+ string s ="";
+ assert this.elems != null;
+ if (card > 0 && elems[0] is Char) {
+ for(int i =0; i < card ; i++)
+ {
+ object elem = elems[i];
+ if (elem != null) { s +=elem.ToString(); }
+ }
+ return s;
+ } else {
+ s = "[";
+ for(int i =0; i < card-1; i++) {
+ object elem = elems[i];
+ if (elem != null) { s += elem.ToString()+", "; }
+ }
+ if (card > 0)
+ {
+ object last = elems[card-1];
+ if (last != null) { s += last.ToString(); }
+ }
+ s += "]";
+ return s;
+ }
+ }
+ //Equality- - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ [Pure][Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals (object that){
+ return that != null && that is Sequence && ((Sequence) this == (Sequence) that);
+ }
+ [Pure][Reads(ReadsAttribute.Reads.Nothing)] // ugh, is this right? --KRML
+ public static bool operator == (Sequence s, Sequence t){
+ if ((object)s == (object)t) {
+ return true;
+ } else if ((object)s == null || (object)t == null) {
+ return false;
+ }
+ if (s.card != t.card) return false;
+ assert s.elems != null;
+ assert t.elems != null;
+ for(int i = 0; i < s.card; i++)
+ if (! Equals(s.elems[i], t.elems[i]))
+ return false;
+ return true;
+ }
+ [Pure][Reads(ReadsAttribute.Reads.Nothing)] // ugh, is this right? --KRML
+ public static bool operator != (Sequence s, Sequence t){
+ return !(s == t);
+ }
+ [Pure][Reads(ReadsAttribute.Reads.Owned)]
+ public override int GetHashCode (){
+ int h = 0;
+ for(int i = 0; i < card; i++)
+ {
+ assert this.elems != null;
+ object elem = elems[i];
+ if (elem != null) { h += elem.GetHashCode(); }
+ }
+ return h;
+ }
+ //Subset- - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ // View Sequence of T as Set of (Integer,T)
+ int IComparable.CompareTo(object o) {
+ if (o == null || !(o is Sequence))
+ throw new MissingCase();
+ // WS Improve performance!
+ Sequence t = (Sequence) o;
+ if (this < t) return -1;
+ else if(this > t) return +1;
+ else return 0;
+ }
+
+ public static bool operator < (Sequence s, Sequence t){
+ if (s==null) throw new ArgumentNullException("s");
+ if (t==null) throw new ArgumentNullException("t");
+ if (s.card >= t.card) return false;
+ assert s.elems != null;
+ assert t.elems != null;
+ for(int i = 0; i < s.card; i++)
+ if ( ! Equals(s.elems[i], t.elems[i]))
+ return false;
+ return true;
+ }
+ public static bool operator <= (Sequence s, Sequence t){
+ if (s==null) throw new ArgumentNullException("s");
+ if (t==null) throw new ArgumentNullException("t");
+ if (s.card > t.card) return false;
+ assert s.elems != null;
+ assert t.elems != null;
+ for(int i = 0; i < s.card; i++)
+ if ( ! Equals(s.elems[i], t.elems[i]))
+ return false;
+ return true;
+ }
+ public static bool operator > (Sequence s, Sequence t){ return t < s;}
+ public static bool operator >= (Sequence s, Sequence t){ return t <= s;}
+
+ //pure---------------------------------------------------------------
+ [Pure][Reads(ReadsAttribute.Reads.Owned)]
+ public bool Has(object x) { // WS translate to tailrecursion
+ if (x == null)
+ throw new MissingCase();
+ assert this.elems != null;
+ for (int i = 0; i< card; i++)
+ if (x.Equals(elems[i]))
+ return true;
+ return false;
+ }
+
+ // the index of the first occurrence of x in this sequence,
+ // or -1 if x does not occur
+ [Pure][Reads(ReadsAttribute.Reads.Owned)]
+ public int IndexOf(object x) {
+ if (x == null)
+ throw new MissingCase();
+ assert this.elems != null;
+ for (int i = 0; i< card; i++)
+ if (x.Equals(elems[i]))
+ return i;
+ return -1;
+ }
+
+ // the index of the last occurrence of x in this sequence,
+ // or -1 if x does not occur
+ [Pure][Reads(ReadsAttribute.Reads.Owned)]
+ public int LastIndexOf(object x) {
+ if (x == null)
+ throw new MissingCase();
+ assert this.elems != null;
+ for (int i = card - 1; i >= 0; i--)
+ if (x.Equals(elems[i]))
+ return i;
+ return -1;
+ }
+
+ public object Head() {assert this.elems != null; return elems[0]; }
+ public object Last() {assert this.elems != null; return elems[card-1]; }
+
+ public static Sequence Tail(Sequence! s) {
+ Sequence n = new Sequence(new Capacity(s.card-1));
+ assert n.elems != null;
+ assert s.elems != null;
+ for (int i = 1; i< s.card; i++) n.elems[n.card++] = s.elems[i];
+ return n;
+ }
+
+ public static Sequence Front(Sequence! s) {
+ Sequence n = new Sequence(new Capacity(s.card-1));
+ assert n.elems != null;
+ assert s.elems != null;
+ for (int i = 0; i< s.card-1; i++) n.elems[n.card++] = s.elems[i];
+ return n;
+ }
+ public static Sequence Concat(Sequence! s) {
+ Sequence n = new Sequence(new Capacity(s.card));
+ assert n.elems != null;
+ assert s.elems != null;
+ for (int i = 0; i< s.card; i++) {
+ Sequence t = (Sequence!) s.elems[i];
+ assert t.elems != null;
+ for (int j = 0; j < t.card; j ++)
+ n.Add(t.elems[j]);
+ }
+ return n;
+ }
+
+ public static Sequence Reverse(Sequence! s) {
+ Sequence n = new Sequence(new Capacity(s.card));
+ assert n.elems != null;
+ assert s.elems != null;
+ for (int i = s.card-1; i>=0; i--) n.elems[n.card++] = s.elems[i];
+ return n;
+ }
+
+ public static Sequence operator + (Sequence s, Sequence t)
+ {
+ if (s==null) throw new ArgumentNullException("s");
+ if (t == null) throw new ArgumentNullException("t");
+ return Append(t,s);
+ }
+
+ public static Sequence! Append(Sequence! s, Sequence! t) {
+ Sequence! n = new Sequence(new Capacity(s.card + t.card));
+ assert n.elems != null;
+ assert s.elems != null;
+ assert t.elems != null;
+ for (int i = 0; i< s.card; i++) n.elems[n.card++] = s.elems[i];
+ for (int i = 0; i< t.card; i++) n.elems[n.card++] = t.elems[i];
+ return n;
+ }
+ public static Sequence Zip(Sequence! s, Sequence! t) {
+ int min = s.card<t.card ? s.card : t.card;
+ Sequence n = new Sequence(new Capacity(min));
+ assert n.elems != null;
+ assert s.elems != null;
+ assert t.elems != null;
+ for (int i = 0; i< min; i++) n.elems[n.card++] = new Tuple(s.elems[i], t.elems[i]);
+ return n;
+ }
+ public static Tuple Unzip(Sequence! s) {
+ Sequence n0 = new Sequence(new Capacity(s.card));
+ Sequence n1 = new Sequence(new Capacity(s.card));
+ assert s.elems != null;
+ assert n0.elems != null;
+ assert n1.elems != null;
+ for (int i = 0; i< s.card; i++) {
+ n0.elems[n0.card++] = ((!)((Tuple!)s.elems[i]).elems)[0];
+ n1.elems[n1.card++] = ((!)((Tuple!)s.elems[i]).elems)[1];
+ }
+ return new Tuple(n0,n1);
+ }
+
+ public static Sequence FromTo(int from, int to) { //WS hash the result!
+ if (from > to) return new Sequence();
+ Sequence n = new Sequence(new Capacity(to-from+1));
+ assert n.elems != null;
+ for (int i = from; i<= to; i++)
+ n.elems[n.card++] = i;
+ return n;
+ }
+
+ public static Sequence FromStepTo(int from, int step, int to) {
+ Sequence n = new Sequence();
+ int incr = step-from;
+ if (incr >0)
+ for (int i = from; i<= to; i+=incr)
+ n.Add(i);
+ else if (incr < 0)
+ for (int i = to; i>= from; i-=incr)
+ n.Add(i);
+ return n;
+ }
+
+ }
+
+}
diff --git a/Source/Core/Readme.txt b/Source/Core/Readme.txt
new file mode 100644
index 00000000..1b0606a6
--- /dev/null
+++ b/Source/Core/Readme.txt
@@ -0,0 +1,61 @@
+// ----------------------------------------------------------------------------
+// Boogie-PL
+//
+// Readme
+// ws 5/9/03
+// ----------------------------------------------------------------------------
+
+
+This directory cointains the Boogie Procedural Language (BoogiePL)
+implementataion and "1" sample program.
+
+
+Scanner and parser are generated with Coco (ann LL1 parser generator for EBNFs)
+(see http://www.ssw.uni-linz.ac.at/Research/Projects/Coco/CSharp/)
+
+ The input file is
+ BoogiePL.atg
+ then simply call
+ ..\Coco\bin\Debug\Coco.exe BoogiePL.atg
+ it then uses (as input)
+ Scanner.frame
+ Parser.frame
+ as templates to generate an LL1 parser into
+ Scanner.cs
+ Parser.cs
+ as output
+
+The Csharp excutable then contains
+
+ BoogiePL.cs -- main program
+ Absy -- abstract syntax for BoogiePL
+ Error.cs -- error handling (contains still some oldstuff)
+ Parser.cs -- generated parser
+ Scanner.cs -- generated scanner
+ PureCollections.cs -- sets/maps/tuples/ (contains still some oldstuff)
+
+The directory Samples contains one parsing example
+ Parsing1.pl
+Please check it for the syntax, alternatively consult BoogiePL.atg
+
+Here is its output:
+ C:\Boogie> bin\debug\Boogiepl.exe samples\Parsing1.pl
+
+ Boogie Procedural Language Version 0.1 Copyright (c) Microsoft 2003
+ Parsing samples\Parsing1.pl <<<=== here is what is does
+ 0 errors detected
+
+Things left to do:
+
+ BoogiePL needs a tiny context analysis
+ checking names, updates, arities, OLD, etc.
+ (ws will do until 5/8)
+
+ BoogiePL Absy might be too flexible
+ simplify (if one things so..) (Mike/Rustan will do)
+
+ BoogiePL needs more examples/experiences
+ (all of us..)
+
+
+
diff --git a/Source/Core/ResolutionContext.ssc b/Source/Core/ResolutionContext.ssc
new file mode 100644
index 00000000..618f4a3a
--- /dev/null
+++ b/Source/Core/ResolutionContext.ssc
@@ -0,0 +1,518 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+namespace Microsoft.Boogie
+{
+ using System.Collections;
+ using System.Collections.Generic;
+ using System;
+ using Microsoft.SpecSharp.Collections;
+ using Microsoft.Contracts;
+
+ public interface IErrorSink
+ {
+ void Error(IToken! tok, string! msg);
+ }
+
+ public class CheckingContext
+ {
+ // ------------------------------ Error counting ------------------------------
+
+ IErrorSink errorSink;
+ int errors;
+
+ public CheckingContext(IErrorSink errorSink)
+ {
+ this.errorSink = errorSink;
+ }
+
+ public int ErrorCount
+ {
+ get { return errors; }
+ set { errors = value; }
+ }
+
+ public void Error(Absy! subject, string! msg, params object[]! args)
+ {
+ Error(subject.tok, msg, args);
+ }
+
+ public virtual void Error(IToken! tok, string! msg)
+ {
+ errors++;
+ if (errorSink == null) {
+ ConsoleColor col = Console.ForegroundColor;
+ Console.ForegroundColor = ConsoleColor.Red;
+ Console.WriteLine("{0}({1},{2}): Error: {3}",
+ tok.filename, tok.line, tok.col-1,
+ msg);
+ Console.ForegroundColor = col;
+ } else {
+ errorSink.Error(tok, msg);
+ }
+ }
+
+ private string! Format(string! msg, params object[] args) {
+ if (System.Type.GetType("Mono.Runtime") != null) { // MONO
+ // something in mono seems to be broken so that calling
+ // NamedDeclarations.ToString (and similar ToString methods)
+ // causes a stack overflow. We therefore convert those to
+ // strings by hand
+ object[] fixedArgs = new object [((!)args).Length];
+ for (int i = 0; i < args.Length; ++i) {
+ if (args[i] is NamedDeclaration) {
+ fixedArgs[i] = ((NamedDeclaration!)args[i]).Name;
+ } else if (args[i] is Type) {
+ System.IO.StringWriter buffer = new System.IO.StringWriter();
+ using (TokenTextWriter stream = new TokenTextWriter("<buffer>", buffer, false)) {
+ ((Type!)args[i]).Emit(stream);
+ }
+ fixedArgs[i] = buffer.ToString();
+ } else if (args[i] is Expr) {
+ System.IO.StringWriter buffer = new System.IO.StringWriter();
+ using (TokenTextWriter stream = new TokenTextWriter("<buffer>", buffer, false)) {
+ ((Expr!)args[i]).Emit(stream, 0, false);
+ }
+ fixedArgs[i] = buffer.ToString();
+ } else {
+ fixedArgs[i] = args[i];
+ }
+ }
+ args = fixedArgs;
+ }
+ return string.Format(msg, args);
+ }
+
+ public void Error(IToken! tok, string! msg, params object[] args)
+ {
+ Error(tok, Format(msg, args));
+ }
+
+ public void Warning(Absy! subject, string! msg, params object[]! args)
+ {
+ Warning(subject.tok, msg, args);
+ }
+
+ public virtual void Warning(IToken! tok, string! msg)
+ {
+ // warnings are currently always written to the console
+ ConsoleColor col = Console.ForegroundColor;
+ Console.ForegroundColor = ConsoleColor.DarkYellow;
+ Console.WriteLine("{0}({1},{2}): Warning: {3}",
+ tok.filename, tok.line, tok.col-1,
+ msg);
+ Console.ForegroundColor = col;
+ }
+
+ public void Warning(IToken! tok, string! msg, params object[] args)
+ {
+ Warning(tok, Format(msg, args));
+ }
+ }
+
+ public class ResolutionContext : CheckingContext
+ {
+ public ResolutionContext(IErrorSink errorSink)
+ {
+ base(errorSink);
+ }
+
+ // ------------------------------ Boogie 2 Types -------------------------
+
+ // user-defined types, which can be either TypeCtorDecl or TypeSynonymDecl
+ Hashtable /*string->NamedDeclaration*/! types = new Hashtable /*string->NamedDeclaration*/ ();
+
+ private void CheckBvNameClashes(Absy! absy, string! name) {
+ if (name.StartsWith("bv") && name.Length > 2) {
+ bool isBv = true;
+ for (int i = 2; i < name.Length; ++i)
+ if (!char.IsDigit(name[i])) isBv = false;
+ if (isBv)
+ Error(absy, "type name: {0} is registered for bitvectors", name);
+ }
+ }
+
+ public void AddType(NamedDeclaration! td)
+ {
+ assert (td is TypeCtorDecl) || (td is TypeSynonymDecl);
+
+ string! name = (!)td.Name;
+ CheckBvNameClashes(td, name);
+
+ if (types[name] != null)
+ {
+ Error(td, "more than one declaration of type name: {0}", name);
+ }
+ else
+ {
+ types.Add(name, td);
+ }
+ }
+
+ /// <summary>
+ /// Returns the declaration of the named type, or null if
+ /// no such type is declared. Also return null if the type
+ /// declared with the given name is not a constructor but a
+ /// type synonym
+ /// </summary>
+ /// <param name="name"></param>
+ /// <returns></returns>
+ public TypeCtorDecl LookUpType(string! name)
+ {
+ return types[name] as TypeCtorDecl;
+ }
+
+ public TypeSynonymDecl LookUpTypeSynonym(string! name)
+ {
+ return types[name] as TypeSynonymDecl;
+ }
+
+ // ------------------------------ Boogie 2 Type Binders ------------------------------
+
+ List<TypeVariable!>! typeBinders = new List<TypeVariable!>(5);
+
+ public void AddTypeBinder(TypeVariable! td) {
+ CheckBvNameClashes(td, td.Name);
+ if (types.ContainsKey(td.Name)) {
+ Error(td, "name is already reserved for type constructor: {0}", td.Name);
+ return;
+ }
+ for (int i = 0; i < typeBinders.Count; i++) {
+ if (typeBinders[i].Name == td.Name) {
+ Error(td, "more than one declaration of type variable: {0}", td.Name);
+ return;
+ }
+ }
+ typeBinders.Add(td);
+ }
+
+ public int TypeBinderState {
+ get { return typeBinders.Count; }
+ set { typeBinders.RemoveRange(value, typeBinders.Count - value); }
+ }
+
+ /// <summary>
+ /// Returns the declaration of the named type binder, or null if
+ /// no such binder is declared.
+ /// </summary>
+ public TypeVariable LookUpTypeBinder(string! name)
+ {
+ for (int i = typeBinders.Count; 0 <= --i; ) {
+ TypeVariable! td = typeBinders[i];
+ if (td.Name == name) {
+ return td;
+ }
+ }
+ return null; // not present
+ }
+
+ // ------------------------------ Types ------------------------------
+
+ // user-defined types
+ // Hashtable /*string->TypeDecl*/! types = new Hashtable /*string->TypeDecl*/ ();
+/*
+ public void AddType(TypeDecl! td)
+ {
+ string! name = (!)td.Name;
+
+ if (name.StartsWith("bv") && name.Length > 2) {
+ bool isBv = true;
+ for (int i = 2; i < name.Length; ++i)
+ if (!char.IsDigit(name[i])) isBv = false;
+ if (isBv)
+ Error(td, "type name: {0} is registered for bitvectors", name);
+ }
+
+ if (types[name] != null)
+ {
+ Error(td, "more than one declaration of type name: {0}", name);
+ }
+ else
+ {
+ types.Add(name, td);
+ }
+ }
+*/
+ /// <summary>
+ /// Returns the declaration of the named type, or null if
+ /// no such type is declared.
+ /// </summary>
+ /// <param name="name"></param>
+ /// <returns></returns>
+ /* public TypeDecl LookUpType(string! name)
+ {
+ return (TypeDecl)types[name];
+ }
+ */
+ // ------------------------------ Type Binders ------------------------------
+/*
+ List<TypeBinderDecl!>! typeBinders = new List<TypeBinderDecl!>(5);
+
+ public void AddTypeBinder(TypeBinderDecl! td) {
+ for (int i = 0; i < typeBinders.Count; i++) {
+ if (typeBinders[i].Name == td.Name) {
+ Error(td, "more than one declaration of type binder name: {0}", td.Name);
+ return;
+ }
+ }
+ typeBinders.Add(td);
+ }
+
+ public int TypeBinderState {
+ get { return typeBinders.Count; }
+ set { typeBinders.RemoveRange(value, typeBinders.Count - value); }
+ }
+
+ /// <summary>
+ /// Returns the declaration of the named type binder, or null if
+ /// no such binder is declared.
+ /// </summary>
+ public TypeDecl LookUpTypeBinder(string! name)
+ {
+ for (int i = typeBinders.Count; 0 <= --i; ) {
+ TypeBinderDecl td = typeBinders[i];
+ if (td.Name == name) {
+ return td;
+ }
+ }
+ return null; // not present
+ }
+ */
+ // ------------------------------ Variables ------------------------------
+
+ class VarContextNode
+ {
+ public readonly Hashtable /*string->Variable*/! VarSymbols = new Hashtable /*string->Variable*/();
+ public /*maybe null*/ VarContextNode ParentContext;
+ public readonly bool Opaque;
+
+ public VarContextNode(/*maybe null*/ VarContextNode parentContext, bool opaque)
+ {
+ ParentContext = parentContext;
+ Opaque = opaque;
+ }
+ }
+
+ // symbolic constants, global variables, local variables, formals, expression-bound variables
+ VarContextNode! varContext = new VarContextNode(null, false);
+
+ /// <summary>
+ /// Adds a variable context.
+ /// </summary>
+ public void PushVarContext()
+ {
+ varContext = new VarContextNode(varContext, false);
+ }
+
+ /// <summary>
+ /// Adds an opaque variable context, that is, one that blocks all previously pushed contexts.
+ /// </summary>
+ public void PushOpaqueVarContext()
+ {
+ varContext = new VarContextNode(varContext, true);
+ }
+
+ /// <summary>
+ /// Requires there to be more than one variable context.
+ /// </summary>
+ public void PopVarContext()
+ {
+ assert varContext.ParentContext != null;
+ varContext = varContext.ParentContext;
+ }
+
+ public void AddVariable(Variable! var, bool global)
+ {
+ if (FindVariable((!)var.Name, !global) != null)
+ {
+ Error(var, "more than one declaration of variable name: {0}", var.Name);
+ }
+ else
+ {
+ varContext.VarSymbols.Add(var.Name, var);
+ }
+ }
+
+ /// <summary>
+ /// Returns the declaration of the named variable, or null if
+ /// no such variable is declared.
+ /// </summary>
+ /// <param name="name"></param>
+ /// <returns></returns>
+ public Variable LookUpVariable(string! name)
+ {
+ return FindVariable(name, false);
+ }
+
+ Variable FindVariable(string! name, bool ignoreTopLevelVars)
+ {
+ VarContextNode c = varContext;
+ bool lookOnlyForConstants = false;
+ do {
+ if (ignoreTopLevelVars && c.ParentContext == null) {
+ // this is the top level and we're asked to ignore the top level; hence, we're done
+ break;
+ }
+
+ Variable var = (Variable)c.VarSymbols[name];
+ if (var != null && (!lookOnlyForConstants || var is Constant)) {
+ return var;
+ }
+ // not at this level
+
+ if (c.Opaque) {
+ // from here on, only constants can be looked up
+ lookOnlyForConstants = true;
+ }
+ c = c.ParentContext;
+ } while (c != null);
+
+ // not present in the relevant levels
+ return null;
+ }
+
+ // ------------------------------ Functions/Procedures ------------------------------
+
+ // uninterpreted function symbols, procedures
+ Hashtable /*string->DeclWithFormals*/! funcdures = new Hashtable /*string->DeclWithFormals*/ ();
+
+ public void AddProcedure(DeclWithFormals! proc)
+ {
+ if (funcdures[(!)proc.Name] != null)
+ {
+ Error(proc, "more than one declaration of function/procedure name: {0}", proc.Name);
+ }
+ else
+ {
+ funcdures.Add(proc.Name, proc);
+ }
+ }
+
+ /// <summary>
+ /// Returns the declaration of the named function/procedure, or null if
+ /// no such function or procedure is declared.
+ /// </summary>
+ /// <param name="name"></param>
+ /// <returns></returns>
+ public DeclWithFormals LookUpProcedure(string! name)
+ {
+ return (DeclWithFormals)funcdures[name];
+ }
+
+ // ------------------------------ Blocks ------------------------------
+
+ // blocks
+ [Microsoft.Contracts.SpecPublic]
+ /*maybe null*/ Hashtable /*string->Block*/ blocks;
+
+ /// <summary>
+ /// Requires there not to be a procedure context. Creates one.
+ /// </summary>
+ public void StartProcedureContext()
+ {
+ System.Diagnostics.Debug.Assert(blocks == null);
+ blocks = new Hashtable /*string->Block*/ ();
+ }
+
+ /// <summary>
+ /// Requires there to be a procedure context. Removes it.
+ /// </summary>
+ public void EndProcedureContext()
+ {
+ System.Diagnostics.Debug.Assert(blocks != null);
+ blocks = null;
+ }
+
+ /// <summary>
+ /// Requires there to be a procedure context.
+ /// </summary>
+ /// <param name="block"></param>
+ public void AddBlock(Block! block)
+ requires this.blocks != null;
+ {
+ if (blocks[block.Label] != null)
+ {
+ Error(block, "more than one declaration of block name: {0}", block.Label);
+ }
+ else
+ {
+ blocks.Add(block.Label, block);
+ }
+ }
+
+ /// <summary>
+ /// Requires there to be a procedure context.
+ /// Returns the declaration of the named block, or null if
+ /// no such block is declared.
+ /// </summary>
+ /// <param name="name"></param>
+ /// <returns></returns>
+ public Block LookUpBlock(string! name)
+ requires this.blocks != null;
+ {
+ return (Block)blocks[name];
+ }
+
+ // ------------------------------ Flags ------------------------------
+
+ public enum State { StateLess, Single, Two }
+ State stateMode = State.Single;
+
+ /// <summary>
+ /// To increase our confidence in that the caller knows what it's doing, we only allow
+ /// the state mode to be changed in and out of the State.Single mode.
+ /// </summary>
+ public State StateMode {
+ get {
+ return stateMode;
+ }
+ set {
+ assert value != stateMode;
+ assert stateMode == State.Single || value == State.Single;
+ expose (this) {
+ stateMode = value;
+ }
+ }
+ }
+
+ bool triggerMode = false;
+
+ /// <summary>
+ /// Setting TriggerMode is allowed only if the setting has the effect of toggling the
+ /// boolean. That is, TriggerMode can be set to true only if it previously was false,
+ /// and TriggerMode can be set to false only if it previously was true.
+ /// </summary>
+ public bool TriggerMode
+ {
+ get
+ {
+ return triggerMode;
+ }
+ set
+ {
+ assert triggerMode != value;
+ expose (this) {
+ triggerMode = value;
+ }
+ }
+ }
+ }
+
+ public class TypecheckingContext : CheckingContext
+ {
+ public IdentifierExprSeq Frame; // used in checking the assignment targets of implementation bodies
+
+ public TypecheckingContext(IErrorSink errorSink)
+ {
+ base(errorSink);
+ }
+
+ public bool InFrame(Variable! v)
+ requires Frame != null;
+ {
+ return exists{IdentifierExpr! ie in Frame; ie.Decl == v};
+ }
+ }
+}
diff --git a/Source/Core/Scanner.ssc b/Source/Core/Scanner.ssc
new file mode 100644
index 00000000..eb0c8b04
--- /dev/null
+++ b/Source/Core/Scanner.ssc
@@ -0,0 +1,720 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using System;
+using System.IO;
+using System.Collections;
+using System.Collections.Generic;
+using System.Text;
+using Microsoft.Contracts;
+
+
+namespace Microsoft.Boogie {
+
+ [Immutable]
+ public interface IToken {
+ int kind {get; set; } // token kind
+ string filename {get; set; } // token file
+ int pos {get; set; } // token position in the source text (starting at 0)
+ int col {get; set; } // token column (starting at 0)
+ int line {get; set; } // token line (starting at 1)
+ string/*!*/ val {get; set; } // token value
+
+ bool IsValid { get; }
+ }
+
+ [Immutable]
+ public class Token : IToken {
+ int _kind; // token kind
+ string _filename; // token file
+ int _pos; // token position in the source text (starting at 0)
+ int _col; // token column (starting at 0)
+ int _line; // token line (starting at 1)
+ string/*!*/ _val = "foo"; // token value
+
+ public static IToken! NoToken = new Token();
+
+ public Token();
+ public Token(int linenum, int colnum) {
+ this._line = linenum;
+ this._col = colnum;
+ base();
+ }
+
+ public int kind {
+ get { return this._kind; }
+ set { this._kind = value; }
+ }
+
+ public string filename{
+ get { return this._filename; }
+ set { this._filename = value; }
+ }
+
+ public int pos{
+ get { return this._pos; }
+ set { this._pos = value; }
+ }
+
+ public int col{
+ get { return this._col; }
+ set { this._col = value; }
+ }
+
+ public int line{
+ get { return this._line; }
+ set { this._line = value; }
+ }
+
+ public string/*!*/ val{
+ get { return this._val; }
+ set { this._val = value; }
+ }
+
+ public bool IsValid { get { return this._filename != null; } }
+ }
+
+}
+
+namespace BoogiePL {
+
+using Microsoft.Boogie;
+
+public class Buffer {
+ static string/*!*/ buf;
+ static int bufLen;
+ static int pos;
+ public const int eof = '\uffff';
+
+ public static void Fill(StreamReader! reader) {
+ List<string!> defines = new List<string!>();
+ Fill(reader, defines);
+ }
+
+ struct ReadState {
+ public bool hasSeenElse;
+ public bool mayStillIncludeAnotherAlternative;
+ public ReadState(bool hasSeenElse, bool mayStillIncludeAnotherAlternative) {
+ this.hasSeenElse = hasSeenElse;
+ this.mayStillIncludeAnotherAlternative = mayStillIncludeAnotherAlternative;
+ }
+ }
+
+ public static void Fill(StreamReader! reader, List<string!>! defines) {
+ StringBuilder sb = new StringBuilder();
+ List<ReadState>! readState = new List<ReadState>(); // readState.Count is the current nesting level of #if's
+ int ignoreCutoff = -1; // -1 means we're not ignoring; for 0<=n, n means we're ignoring because of something at nesting level n
+ while (true)
+ invariant -1 <= ignoreCutoff && ignoreCutoff < readState.Count;
+ {
+ string s = reader.ReadLine();
+ if (s == null) {
+ if (readState.Count != 0) {
+ sb.AppendLine("#MalformedInput: missing #endif");
+ }
+ break;
+ }
+ string t = s.Trim();
+ if (t.StartsWith("#if")) {
+ ReadState rs = new ReadState(false, false);
+ if (ignoreCutoff != -1) {
+ // we're already in a state of ignoring, so continue to ignore
+ } else if (IfdefConditionSaysToInclude(t.Substring(3).TrimStart(), defines)) {
+ // include this branch
+ } else {
+ ignoreCutoff = readState.Count; // start ignoring
+ rs.mayStillIncludeAnotherAlternative = true; // allow some later "elsif" or "else" branch to be included
+ }
+ readState.Add(rs);
+ sb.AppendLine(); // ignore the #if line
+
+ } else if (t.StartsWith("#elsif")) {
+ ReadState rs;
+ if (readState.Count == 0 || (rs = readState[readState.Count-1]).hasSeenElse) {
+ sb.AppendLine("#MalformedInput: misplaced #elsif"); // malformed input
+ break;
+ }
+ if (ignoreCutoff == -1) {
+ // we had included the previous branch
+ assert !rs.mayStillIncludeAnotherAlternative;
+ ignoreCutoff = readState.Count-1; // start ignoring
+ } else if (rs.mayStillIncludeAnotherAlternative && IfdefConditionSaysToInclude(t.Substring(6).TrimStart(), defines)) {
+ // include this branch, but no subsequent branch at this level
+ ignoreCutoff = -1;
+ rs.mayStillIncludeAnotherAlternative = false;
+ readState[readState.Count-1] = rs;
+ }
+ sb.AppendLine(); // ignore the #elsif line
+
+ } else if (t == "#else") {
+ ReadState rs;
+ if (readState.Count == 0 || (rs = readState[readState.Count-1]).hasSeenElse) {
+ sb.AppendLine("#MalformedInput: misplaced #else"); // malformed input
+ break;
+ }
+ rs.hasSeenElse = true;
+ if (ignoreCutoff == -1) {
+ // we had included the previous branch
+ assert !rs.mayStillIncludeAnotherAlternative;
+ ignoreCutoff = readState.Count-1; // start ignoring
+ } else if (rs.mayStillIncludeAnotherAlternative) {
+ // include this branch
+ ignoreCutoff = -1;
+ rs.mayStillIncludeAnotherAlternative = false;
+ }
+ readState[readState.Count-1] = rs;
+ sb.AppendLine(); // ignore the #else line
+
+ } else if (t == "#endif") {
+ if (readState.Count == 0) {
+ sb.AppendLine("#MalformedInput: misplaced #endif"); // malformed input
+ break;
+ }
+ readState.RemoveAt(readState.Count-1); // pop
+ if (ignoreCutoff == readState.Count) {
+ // we had ignored the branch that ends here; so, now we start including again
+ ignoreCutoff = -1;
+ }
+ sb.AppendLine(); // ignore the #endif line
+
+ } else if (ignoreCutoff == -1) {
+ sb.AppendLine(s); // included line
+
+ } else {
+ sb.AppendLine(); // ignore the line
+ }
+ }
+
+ Fill(sb.ToString());
+ }
+
+ // "arg" is assumed to be trimmed
+ private static bool IfdefConditionSaysToInclude(string! arg, List<string!>! defines) {
+ bool sense = true;
+ while (arg.StartsWith("!")) {
+ sense = !sense;
+ arg = arg.Substring(1).TrimStart();
+ }
+ return defines.Contains(arg) == sense;
+ }
+
+ public static void Fill(string! text) {
+ buf = text;
+ bufLen = buf.Length;
+ pos = 0;
+ }
+
+ public static int Read() {
+ if (pos < bufLen) {
+ return buf[pos++];
+ } else {
+ return eof;
+ }
+ }
+
+ public static string/*!*/ ReadToEOL() {
+ int x = buf.IndexOf('\n', pos);
+ if (x == -1) {
+ string s = buf.Substring(pos);
+ pos = buf.Length;
+ return s;
+ } else {
+ string s = buf.Substring(pos, x+1 - pos); // also include the '\n'
+ pos = x+1;
+ return s;
+ }
+ }
+
+ public static int Pos {
+ get { return pos; }
+ set {
+ if (value < 0) pos = 0; else if (value >= bufLen) pos = bufLen; else pos = value;
+ }
+ }
+}
+
+
+
+public class Scanner {
+ const char EOF = '\0';
+ const char CR = '\r';
+ const char LF = '\n';
+ [Microsoft.Contracts.Verify(false)]
+ static Scanner() {
+ start[0] = 57;
+ start[33] = 41;
+ start[34] = 6;
+ start[35] = 2;
+ start[36] = 2;
+ start[37] = 51;
+ start[38] = 34;
+ start[39] = 2;
+ start[40] = 11;
+ start[41] = 12;
+ start[42] = 24;
+ start[43] = 47;
+ start[44] = 14;
+ start[45] = 49;
+ start[46] = 2;
+ start[47] = 50;
+ start[48] = 9;
+ start[49] = 9;
+ start[50] = 9;
+ start[51] = 9;
+ start[52] = 9;
+ start[53] = 9;
+ start[54] = 9;
+ start[55] = 9;
+ start[56] = 9;
+ start[57] = 9;
+ start[58] = 13;
+ start[59] = 10;
+ start[60] = 17;
+ start[61] = 21;
+ start[62] = 18;
+ start[63] = 2;
+ start[65] = 2;
+ start[66] = 2;
+ start[67] = 2;
+ start[68] = 2;
+ start[69] = 2;
+ start[70] = 2;
+ start[71] = 2;
+ start[72] = 2;
+ start[73] = 2;
+ start[74] = 2;
+ start[75] = 2;
+ start[76] = 2;
+ start[77] = 2;
+ start[78] = 2;
+ start[79] = 2;
+ start[80] = 2;
+ start[81] = 2;
+ start[82] = 2;
+ start[83] = 2;
+ start[84] = 2;
+ start[85] = 2;
+ start[86] = 2;
+ start[87] = 2;
+ start[88] = 2;
+ start[89] = 2;
+ start[90] = 2;
+ start[91] = 15;
+ start[92] = 1;
+ start[93] = 16;
+ start[94] = 2;
+ start[95] = 2;
+ start[96] = 2;
+ start[97] = 2;
+ start[98] = 2;
+ start[99] = 2;
+ start[100] = 2;
+ start[101] = 2;
+ start[102] = 2;
+ start[103] = 2;
+ start[104] = 2;
+ start[105] = 2;
+ start[106] = 2;
+ start[107] = 2;
+ start[108] = 2;
+ start[109] = 2;
+ start[110] = 2;
+ start[111] = 2;
+ start[112] = 2;
+ start[113] = 2;
+ start[114] = 2;
+ start[115] = 2;
+ start[116] = 2;
+ start[117] = 2;
+ start[118] = 2;
+ start[119] = 2;
+ start[120] = 2;
+ start[121] = 2;
+ start[122] = 2;
+ start[123] = 19;
+ start[124] = 37;
+ start[125] = 20;
+ start[126] = 2;
+ start[172] = 52;
+ start[8226] = 56;
+ start[8656] = 33;
+ start[8658] = 32;
+ start[8660] = 29;
+ start[8704] = 53;
+ start[8707] = 54;
+ start[8743] = 36;
+ start[8744] = 39;
+ start[8800] = 44;
+ start[8804] = 45;
+ start[8805] = 46;
+ }
+ const int noSym = 85;
+ static short[] start = new short[16385];
+
+
+ static Token/*!*/ t; // current token
+ static char ch; // current input character
+ static int pos; // column number of current character
+ static int line; // line number of current character
+ static int lineStart; // start position of current line
+ static Queue! oldEols; // EOLs that appeared in a comment;
+ static BitArray/*!*/ ignore; // set of characters to be ignored by the scanner
+ static string Filename;
+
+ ///<summary>
+ ///Initializes the scanner. Note: first fill the Buffer.
+ ///</summary>
+ ///<param name="filename">File name used for error reporting</param>
+ public static void Init (string filename) {
+ Filename = filename;
+ pos = -1; line = 1; lineStart = 0;
+ oldEols = new Queue();
+ NextCh();
+ ignore = new BitArray(16384);
+ ignore[9] = true; ignore[10] = true; ignore[13] = true; ignore[32] = true;
+
+ }
+
+ private static void NextCh() {
+ if (oldEols.Count > 0) {
+ ch = (char) ((!)oldEols.Dequeue());
+ } else {
+ while (true) {
+ ch = (char)Buffer.Read(); pos++;
+ if (ch == Buffer.eof) {
+ ch = EOF;
+ } else if (ch == LF) {
+ line++;
+ lineStart = pos + 1;
+
+ } else if (ch == '#' && pos == lineStart) {
+ int prLine = line;
+ int prColumn = pos - lineStart; // which is 0
+
+ string hashLine = Buffer.ReadToEOL(); pos += hashLine.Length;
+ line++;
+ lineStart = pos + 1;
+
+ hashLine = hashLine.TrimEnd(null);
+ if (hashLine.StartsWith("line ") || hashLine == "line") {
+ // parse #line pragma: #line num [filename]
+ string h = hashLine.Substring(4).TrimStart(null);
+ int x = h.IndexOf(' ');
+ if (x == -1) {
+ x = h.Length; // this will be convenient below when we look for a filename
+ }
+ try {
+ int li = int.Parse(h.Substring(0, x));
+
+ h = h.Substring(x).Trim();
+
+ // act on #line
+ line = li;
+ if (h.Length != 0) {
+ // a filename was specified
+ Filename = h;
+ }
+ continue; // successfully parsed and acted on the #line pragma
+
+ } catch (FormatException) {
+ // just fall down through to produce an error message
+ }
+ Errors.SemErr(Filename, prLine, prColumn, "Malformed (#line num [filename]) pragma: #" + hashLine);
+ continue;
+ }
+
+ Errors.SemErr(Filename, prLine, prColumn, "Unrecognized pragma: #" + hashLine);
+ continue;
+ }
+ return;
+ }
+ }
+ }
+
+
+ static bool Comment0() {
+ int level = 1, line0 = line, lineStart0 = lineStart;
+ NextCh();
+ if (ch == '/') {
+ NextCh();
+ for(;;) {
+ if (ch == 10) {
+ level--;
+ if (level == 0) {
+ while(line0 < line) {oldEols.Enqueue('\r'); oldEols.Enqueue('\n'); line0++;}
+ NextCh(); return true;
+ }
+ NextCh();
+ } else if (ch == EOF) return false;
+ else NextCh();
+ }
+ } else {
+ if (ch==CR) {line--; lineStart = lineStart0;}
+ pos = pos - 2; Buffer.Pos = pos+1; NextCh();
+ }
+ return false;
+ }
+
+ static bool Comment1() {
+ int level = 1, line0 = line, lineStart0 = lineStart;
+ NextCh();
+ if (ch == '*') {
+ NextCh();
+ for(;;) {
+ if (ch == '*') {
+ NextCh();
+ if (ch == '/') {
+ level--;
+ if (level == 0) {
+ while(line0 < line) {oldEols.Enqueue('\r'); oldEols.Enqueue('\n'); line0++;}
+ NextCh(); return true;
+ }
+ NextCh();
+ }
+ } else if (ch == '/') {
+ NextCh();
+ if (ch == '*') {
+ level++; NextCh();
+ }
+ } else if (ch == EOF) return false;
+ else NextCh();
+ }
+ } else {
+ if (ch==CR) {line--; lineStart = lineStart0;}
+ pos = pos - 2; Buffer.Pos = pos+1; NextCh();
+ }
+ return false;
+ }
+
+
+ static 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 = 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 "false": t.kind = 77; break;
+ case "true": t.kind = 78; break;
+ case "old": t.kind = 79; break;
+ case "exists": t.kind = 81; break;
+ default: break;
+
+ }
+ }
+
+ public static Token/*!*/ Scan() {
+ while (ignore[ch]) { NextCh(); }
+ if (ch == '/' && Comment0() || ch == '/' && Comment1() ) return Scan();
+ t = new Token();
+ t.pos = pos; t.col = pos - lineStart + 1; t.line = line; t.filename = Filename;
+ int state = (/*^ (!) ^*/ start)[ch];
+ StringBuilder buf = new StringBuilder(16);
+ buf.Append(ch); NextCh();
+
+ switch (state) {
+ case 0: {t.kind = noSym; goto done;} // NextCh already done
+ case 1:
+ if ((ch >= '#' && ch <= '$' || ch == 39 || ch == '.' || ch == '?' || ch >= 'A' && ch <= 'Z' || ch >= '^' && ch <= 'z' || ch == '~')) {buf.Append(ch); NextCh(); goto case 2;}
+ else {t.kind = noSym; goto done;}
+ case 2:
+ if ((ch >= '#' && ch <= '$' || ch == 39 || ch == '.' || ch >= '0' && ch <= '9' || ch == '?' || ch >= 'A' && ch <= 'Z' || ch >= '^' && ch <= 'z' || ch == '~')) {buf.Append(ch); NextCh(); goto case 2;}
+ else {t.kind = 1; t.val = buf.ToString(); CheckLiteral(); return t;}
+ case 3:
+ if (ch == 'v') {buf.Append(ch); NextCh(); goto case 4;}
+ else {t.kind = noSym; goto done;}
+ case 4:
+ if ((ch >= '0' && ch <= '9')) {buf.Append(ch); NextCh(); goto case 5;}
+ else {t.kind = noSym; goto done;}
+ case 5:
+ if ((ch >= '0' && ch <= '9')) {buf.Append(ch); NextCh(); goto case 5;}
+ else {t.kind = 2; goto done;}
+ case 6:
+ if ((ch == '"')) {buf.Append(ch); NextCh(); goto case 7;}
+ else if ((ch >= ' ' && ch <= '!' || ch >= '#' && ch <= '~')) {buf.Append(ch); NextCh(); goto case 6;}
+ else {t.kind = noSym; goto done;}
+ case 7:
+ {t.kind = 4; goto done;}
+ case 8:
+ if ((ch >= '0' && ch <= '9')) {buf.Append(ch); NextCh(); goto case 8;}
+ else {t.kind = 5; goto done;}
+ case 9:
+ if ((ch >= '0' && ch <= '9')) {buf.Append(ch); NextCh(); goto case 9;}
+ else if (ch == 'b') {buf.Append(ch); NextCh(); goto case 3;}
+ else if (ch == '.') {buf.Append(ch); NextCh(); goto case 8;}
+ else {t.kind = 3; goto done;}
+ case 10:
+ {t.kind = 7; goto done;}
+ case 11:
+ {t.kind = 8; goto done;}
+ case 12:
+ {t.kind = 9; goto done;}
+ case 13:
+ if (ch == '=') {buf.Append(ch); NextCh(); goto case 25;}
+ else if (ch == ':') {buf.Append(ch); NextCh(); goto case 55;}
+ else {t.kind = 10; goto done;}
+ case 14:
+ {t.kind = 11; goto done;}
+ case 15:
+ {t.kind = 15; goto done;}
+ case 16:
+ {t.kind = 16; goto done;}
+ case 17:
+ if (ch == '=') {buf.Append(ch); NextCh(); goto case 26;}
+ else if (ch == ':') {buf.Append(ch); NextCh(); goto case 43;}
+ else {t.kind = 17; goto done;}
+ case 18:
+ if (ch == '=') {buf.Append(ch); NextCh(); goto case 40;}
+ else {t.kind = 18; goto done;}
+ case 19:
+ if (ch == '{') {buf.Append(ch); NextCh(); goto case 22;}
+ else {t.kind = 25; goto done;}
+ case 20:
+ if (ch == '}') {buf.Append(ch); NextCh(); goto case 23;}
+ else {t.kind = 26; goto done;}
+ case 21:
+ if (ch == '=') {buf.Append(ch); NextCh(); goto case 30;}
+ else {t.kind = 29; goto done;}
+ case 22:
+ {t.kind = 36; goto done;}
+ case 23:
+ {t.kind = 37; goto done;}
+ case 24:
+ {t.kind = 44; goto done;}
+ case 25:
+ {t.kind = 49; goto done;}
+ case 26:
+ if (ch == '=') {buf.Append(ch); NextCh(); goto case 27;}
+ else {t.kind = 63; goto done;}
+ case 27:
+ if (ch == '>') {buf.Append(ch); NextCh(); goto case 28;}
+ else {t.kind = 56; goto done;}
+ case 28:
+ {t.kind = 52; goto done;}
+ case 29:
+ {t.kind = 53; goto done;}
+ case 30:
+ if (ch == '>') {buf.Append(ch); NextCh(); goto case 31;}
+ else {t.kind = 62; goto done;}
+ case 31:
+ {t.kind = 54; goto done;}
+ case 32:
+ {t.kind = 55; goto done;}
+ case 33:
+ {t.kind = 57; goto done;}
+ case 34:
+ if (ch == '&') {buf.Append(ch); NextCh(); goto case 35;}
+ else {t.kind = noSym; goto done;}
+ case 35:
+ {t.kind = 58; goto done;}
+ case 36:
+ {t.kind = 59; goto done;}
+ case 37:
+ if (ch == '|') {buf.Append(ch); NextCh(); goto case 38;}
+ else {t.kind = noSym; goto done;}
+ case 38:
+ {t.kind = 60; goto done;}
+ case 39:
+ {t.kind = 61; goto done;}
+ case 40:
+ {t.kind = 64; goto done;}
+ case 41:
+ if (ch == '=') {buf.Append(ch); NextCh(); goto case 42;}
+ else {t.kind = 75; goto done;}
+ case 42:
+ {t.kind = 65; goto done;}
+ case 43:
+ {t.kind = 66; goto done;}
+ case 44:
+ {t.kind = 67; goto done;}
+ case 45:
+ {t.kind = 68; goto done;}
+ case 46:
+ {t.kind = 69; goto done;}
+ case 47:
+ if (ch == '+') {buf.Append(ch); NextCh(); goto case 48;}
+ else {t.kind = 71; goto done;}
+ case 48:
+ {t.kind = 70; goto done;}
+ case 49:
+ {t.kind = 72; goto done;}
+ case 50:
+ {t.kind = 73; goto done;}
+ case 51:
+ {t.kind = 74; goto done;}
+ case 52:
+ {t.kind = 76; goto done;}
+ case 53:
+ {t.kind = 80; goto done;}
+ case 54:
+ {t.kind = 82; goto done;}
+ case 55:
+ {t.kind = 83; goto done;}
+ case 56:
+ {t.kind = 84; goto done;}
+ case 57: {t.kind = 0; goto done;}
+ }
+ done:
+ t.val = buf.ToString();
+ return t;
+ }
+
+} // end Scanner
+
+
+public delegate void ErrorProc(int n, string filename, int line, int col);
+
+public class Errors {
+ public static int count = 0; // number of errors detected
+ public static ErrorProc/*!*/ SynErr; // syntactic errors
+
+ public static void SemErr(string filename, int line, int col, string! msg) { // semantic errors
+ ConsoleColor color = Console.ForegroundColor;
+ Console.ForegroundColor = ConsoleColor.Red;
+ Console.WriteLine("{0}({1},{2}): Error: {3}", filename, line, col, msg);
+ Console.ForegroundColor = color;
+ count++;
+ }
+
+ public static void SemErr(IToken! tok, string! msg) { // semantic errors
+ SemErr(tok.filename, tok.line, tok.col, msg);
+ }
+
+ public static void Exception (string s) {
+ ConsoleColor color = Console.ForegroundColor;
+ Console.ForegroundColor = ConsoleColor.Red;
+ Console.WriteLine(s);
+ Console.ForegroundColor = color;
+ System.Environment.Exit(0);
+ }
+
+} // Errors
+
+} // end namespace
diff --git a/Source/Core/StandardVisitor.ssc b/Source/Core/StandardVisitor.ssc
new file mode 100644
index 00000000..a6068426
--- /dev/null
+++ b/Source/Core/StandardVisitor.ssc
@@ -0,0 +1,503 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------------
+// BoogiePL - StandardVisitor.cs
+//---------------------------------------------------------------------------------------------
+
+using System.Collections.Generic;
+
+namespace Microsoft.Boogie
+{
+ /// <summary>
+ /// Base for all classes that process the Absy using the visitor pattern.
+ /// </summary>
+ public abstract class Visitor
+ {
+ /// <summary>
+ /// Switches on node.NodeType to call a visitor method that has been specialized for node.
+ /// </summary>
+ /// <param name="a">The Absy node to be visited.</param>
+ /// <returns> Returns null if node is null. Otherwise returns an updated node (possibly a different object).</returns>
+ public abstract Absy! Visit (Absy! node);
+
+ /// <summary>
+ /// Transfers the state from one visitor to another. This enables separate visitor instances to cooperative process a single IR.
+ /// </summary>
+ public virtual void TransferStateTo(Visitor targetVisitor)
+ {
+ }
+
+ public virtual ExprSeq! VisitExprSeq(ExprSeq! list)
+ {
+ for( int i = 0, n = list.Length; i < n; i++)
+ list[i] = (Expr)this.Visit( (!) list[i]);
+ return list;
+ }
+ }
+
+ /// <summary>
+ /// Walks an IR, mutuating it into a new form
+ /// </summary>
+ public abstract class StandardVisitor: Visitor
+ {
+ public Visitor callingVisitor;
+
+ public StandardVisitor()
+ {
+ }
+ public StandardVisitor(Visitor callingVisitor)
+ {
+ this.callingVisitor = callingVisitor;
+ }
+ public override Absy! Visit (Absy! node)
+ {
+ return node.StdDispatch(this);
+ }
+ public virtual AIVariableExpr! VisitAIVariableExpr(AIVariableExpr! node)
+ {
+ return node;
+ }
+ public virtual Cmd! VisitAssertCmd(AssertCmd! node)
+ {
+ node.Expr = this.VisitExpr(node.Expr);
+ return node;
+ }
+ public virtual Cmd! VisitAssignCmd(AssignCmd! node)
+ {
+ for (int i = 0; i < node.Lhss.Count; ++i) {
+ node.Lhss[i] = (AssignLhs!)this.Visit(node.Lhss[i]);
+ node.Rhss[i] = (Expr!)this.Visit(node.Rhss[i]);
+ }
+ return node;
+ }
+ public virtual Cmd! VisitAssumeCmd(AssumeCmd! node)
+ {
+ node.Expr = this.VisitExpr(node.Expr);
+ return node;
+ }
+ public virtual AtomicRE! VisitAtomicRE(AtomicRE! node)
+ {
+ node.b = this.VisitBlock(node.b);
+ return node;
+ }
+ public virtual Axiom! VisitAxiom(Axiom! node)
+ {
+ node.Expr = this.VisitExpr(node.Expr);
+ return node;
+ }
+ public virtual Type! VisitBasicType(BasicType! node)
+ {
+ return this.VisitType(node);
+ }
+ public virtual BvConcatExpr! VisitBvConcatExpr(BvConcatExpr! node)
+ {
+ node.E0 = this.VisitExpr(node.E0);
+ node.E1 = this.VisitExpr(node.E1);
+ return node;
+ }
+ public virtual Type! VisitBvType(BvType! node)
+ {
+ return this.VisitType(node);
+ }
+ public virtual Type! VisitBvTypeProxy(BvTypeProxy! node)
+ {
+ // if the type proxy is instantiated with some more
+ // specific type, we visit the instantiation
+ if (node.ProxyFor != null)
+ return (Type)this.Visit(node.ProxyFor);
+ return this.VisitType(node);
+ }
+ public virtual Block! VisitBlock(Block! node)
+ {
+ node.Cmds = this.VisitCmdSeq(node.Cmds);
+ node.TransferCmd = this.VisitTransferCmd((!)node.TransferCmd);
+ return node;
+ }
+ public virtual Expr! VisitBlockExpr(BlockExpr! node)
+ {
+ node.LocVars = this.VisitVariableSeq(node.LocVars);
+ node.Blocks = this.VisitBlockSeq(node.Blocks);
+ return node;
+ }
+ public virtual BlockSeq! VisitBlockSeq(BlockSeq! blockSeq)
+ {
+ for (int i = 0, n = blockSeq.Length; i < n; i++)
+ blockSeq[i] = this.VisitBlock( (!)blockSeq[i]);
+ return blockSeq;
+ }
+ public virtual List<Block!>! VisitBlockList(List<Block!>! blocks)
+ {
+ for (int i = 0, n = blocks.Count; i < n; i++) {
+ blocks[i] = this.VisitBlock(blocks[i]);
+ }
+ return blocks;
+ }
+ public virtual BoundVariable! VisitBoundVariable(BoundVariable! node)
+ {
+ node = (BoundVariable) this.VisitVariable(node);
+ return node;
+ }
+ public virtual Cmd! VisitCallCmd(CallCmd! node)
+ {
+ for (int i = 0; i < node.Ins.Count; ++i)
+ if (node.Ins[i] != null)
+ node.Ins[i] = this.VisitExpr((!)node.Ins[i]);
+ for (int i = 0; i < node.Outs.Count; ++i)
+ if (node.Outs[i] != null)
+ node.Outs[i] = (IdentifierExpr)this.VisitIdentifierExpr((!)node.Outs[i]);
+ node.Proc = this.VisitProcedure((!)node.Proc);
+ return node;
+ }
+ public virtual Cmd! VisitCallForallCmd(CallForallCmd! node)
+ {
+ List<Expr> elist = new List<Expr>(node.Ins.Count);
+ foreach (Expr arg in node.Ins) {
+ if (arg == null) {
+ elist.Add(null);
+ } else {
+ elist.Add(this.VisitExpr(arg));
+ }
+ }
+ node.Ins = elist;
+ node.Proc = this.VisitProcedure((!)node.Proc);
+ return node;
+ }
+ public virtual CmdSeq! VisitCmdSeq(CmdSeq! cmdSeq)
+ {
+ for (int i = 0, n = cmdSeq.Length; i < n; i++)
+ cmdSeq[i] = (Cmd) this.Visit( (!)cmdSeq[i]); // call general Visit so subtypes of Cmd get visited by their particular visitor
+ return cmdSeq;
+ }
+ public virtual Choice! VisitChoice(Choice! node)
+ {
+ node.rs = this.VisitRESeq(node.rs);
+ return node;
+ }
+ public virtual Cmd! VisitCommentCmd(CommentCmd! node)
+ {
+ return node;
+ }
+ public virtual Constant! VisitConstant(Constant! node)
+ {
+ return node;
+ }
+ public virtual CtorType! VisitCtorType(CtorType! node)
+ {
+ for (int i = 0; i < node.Arguments.Length; ++i)
+ node.Arguments[i] = (Type!)this.Visit(node.Arguments[i]);
+ return node;
+ }
+ public virtual Declaration! VisitDeclaration(Declaration! node)
+ {
+ return node;
+ }
+ public virtual List<Declaration!>! VisitDeclarationList(List<Declaration!>! declarationList)
+ {
+ for (int i = 0, n = declarationList.Count; i < n; i++)
+ declarationList[i] = this.VisitDeclaration(declarationList[i]);
+ return declarationList;
+ }
+ public virtual DeclWithFormals! VisitDeclWithFormals(DeclWithFormals! node)
+ {
+ node.InParams = this.VisitVariableSeq(node.InParams);
+ node.OutParams = this.VisitVariableSeq(node.OutParams);
+ return node;
+ }
+ public virtual ExistsExpr! VisitExistsExpr(ExistsExpr! node)
+ {
+ node = (ExistsExpr) this.VisitQuantifierExpr(node);
+ return node;
+ }
+ public virtual ExtractExpr! VisitExtractExpr(ExtractExpr! node)
+ {
+ node.Bitvector = this.VisitExpr(node.Bitvector);
+ return node;
+ }
+ public virtual Expr! VisitExpr(Expr! node)
+ {
+ Expr e = (Expr) this.Visit(node);
+ return e;
+ }
+ public override ExprSeq! VisitExprSeq(ExprSeq! exprSeq)
+ {
+ for (int i = 0, n = exprSeq.Length; i < n; i++)
+ exprSeq[i] = this.VisitExpr( (!)exprSeq[i]);
+ return exprSeq;
+ }
+ public virtual Requires! VisitRequires(Requires! @requires)
+ {
+ @requires.Condition = this.VisitExpr(@requires.Condition);
+ return @requires;
+ }
+ public virtual RequiresSeq! VisitRequiresSeq(RequiresSeq! requiresSeq)
+ {
+ for (int i = 0, n = requiresSeq.Length; i < n; i++)
+ requiresSeq[i] = this.VisitRequires(requiresSeq[i]);
+ return requiresSeq;
+ }
+ public virtual Ensures! VisitEnsures(Ensures! @ensures)
+ {
+ @ensures.Condition = this.VisitExpr(@ensures.Condition);
+ return @ensures;
+ }
+ public virtual EnsuresSeq! VisitEnsuresSeq(EnsuresSeq! ensuresSeq)
+ {
+ for (int i = 0, n = ensuresSeq.Length; i < n; i++)
+ ensuresSeq[i] = this.VisitEnsures(ensuresSeq[i]);
+ return ensuresSeq;
+ }
+ public virtual ForallExpr! VisitForallExpr(ForallExpr! node)
+ {
+ node = (ForallExpr) this.VisitQuantifierExpr(node);
+ return node;
+ }
+ public virtual Formal! VisitFormal(Formal! node)
+ {
+ return node;
+ }
+ public virtual Function! VisitFunction(Function! node)
+ {
+ node = (Function) this.VisitDeclWithFormals(node);
+ if (node.Body != null)
+ node.Body = this.VisitExpr(node.Body);
+ return node;
+ }
+ public virtual GlobalVariable! VisitGlobalVariable(GlobalVariable! node)
+ {
+ node = (GlobalVariable) this.VisitVariable(node);
+ return node;
+ }
+ public virtual GotoCmd! VisitGotoCmd(GotoCmd! node)
+ {
+ node.labelTargets = this.VisitBlockSeq((!)node.labelTargets);
+ return node;
+ }
+ public virtual Cmd! VisitHavocCmd(HavocCmd! node)
+ {
+ node.Vars = this.VisitIdentifierExprSeq(node.Vars);
+ return node;
+ }
+ public virtual Expr! VisitIdentifierExpr(IdentifierExpr! node)
+ {
+ if (node.Decl != null)
+ node.Decl = this.VisitVariable(node.Decl);
+ return node;
+ }
+ public virtual IdentifierExprSeq! VisitIdentifierExprSeq(IdentifierExprSeq! identifierExprSeq)
+ {
+ for (int i = 0, n = identifierExprSeq.Length; i < n; i++)
+ identifierExprSeq[i] = (IdentifierExpr) this.VisitIdentifierExpr( (!)identifierExprSeq[i]);
+ return identifierExprSeq;
+ }
+ public virtual Implementation! VisitImplementation(Implementation! node)
+ {
+ node.LocVars = this.VisitVariableSeq(node.LocVars);
+ node.Blocks = this.VisitBlockList(node.Blocks);
+ node.Proc = this.VisitProcedure((!)node.Proc);
+ node = (Implementation) this.VisitDeclWithFormals(node); // do this first or last?
+ return node;
+ }
+ public virtual LiteralExpr! VisitLiteralExpr(LiteralExpr! node)
+ {
+ return node;
+ }
+
+ public virtual LocalVariable! VisitLocalVariable(LocalVariable! node)
+ {
+ return node;
+ }
+
+ /// <summary>
+ /// Just invoke VisitNAryExpr
+ /// </summary>
+ public virtual Expr! VisitLoopPredicate(LoopPredicate! node)
+ {
+ return this.VisitNAryExpr(node);
+ }
+
+ public virtual AssignLhs! VisitMapAssignLhs(MapAssignLhs! node)
+ {
+ node.Map = (AssignLhs!)this.Visit(node.Map);
+ for (int i = 0; i < node.Indexes.Count; ++i)
+ node.Indexes[i] = (Expr!)this.Visit(node.Indexes[i]);
+ return node;
+ }
+ public virtual MapType! VisitMapType(MapType! node)
+ {
+ // not doing anything about the bound variables ... maybe
+ // these should be visited as well ...
+ //
+ // NOTE: when overriding this method, you have to make sure that
+ // the bound variables of the map type are updated correctly
+ for (int i = 0; i < node.Arguments.Length; ++i)
+ node.Arguments[i] = (Type!)this.Visit(node.Arguments[i]);
+ node.Result = (Type!)this.Visit(node.Result);
+ return node;
+ }
+ public virtual Type! VisitMapTypeProxy(MapTypeProxy! node)
+ {
+ // if the type proxy is instantiated with some more
+ // specific type, we visit the instantiation
+ if (node.ProxyFor != null)
+ return (Type)this.Visit(node.ProxyFor);
+ return this.VisitType(node);
+ }
+
+ public virtual Expr! VisitNAryExpr(NAryExpr! node)
+ {
+ node.Args = this.VisitExprSeq(node.Args);
+// if (node.Type != null) { node.Type = this.VisitType(node.Type); } // BUGBUG? Do this even though it
+ return node;
+ }
+ public virtual Expr! VisitOldExpr(OldExpr! node)
+ {
+ node.Expr = this.VisitExpr(node.Expr);
+ return node;
+ }
+ public virtual Procedure! VisitProcedure(Procedure! node)
+ {
+ node.Ensures = this.VisitEnsuresSeq(node.Ensures);
+ node.InParams = this.VisitVariableSeq(node.InParams);
+ node.Modifies = this.VisitIdentifierExprSeq(node.Modifies);
+ node.OutParams = this.VisitVariableSeq(node.OutParams);
+ node.Requires = this.VisitRequiresSeq(node.Requires);
+ return node;
+ }
+ public virtual Program! VisitProgram(Program! node)
+ {
+ node.TopLevelDeclarations = this.VisitDeclarationList(node.TopLevelDeclarations);
+ return node;
+ }
+ public virtual QuantifierExpr! VisitQuantifierExpr(QuantifierExpr! node)
+ {
+ if (node.Triggers != null) {
+ node.Triggers = this.VisitTrigger(node.Triggers);
+ }
+ node.Body = this.VisitExpr(node.Body);
+ node.Dummies = this.VisitVariableSeq(node.Dummies);
+ //node.Type = this.VisitType(node.Type);
+ return node;
+ }
+ public virtual Cmd! VisitRE(RE! node)
+ {
+ return (Cmd) this.Visit(node); // Call general visit so subtypes get visited by their particular visitor
+ }
+ public virtual RESeq! VisitRESeq(RESeq! reSeq)
+ {
+ for (int i = 0, n = reSeq.Length; i < n; i++)
+ reSeq[i] = (RE) this.VisitRE( (!)reSeq[i]);
+ return reSeq;
+ }
+ public virtual ReturnCmd! VisitReturnCmd(ReturnCmd! node)
+ {
+ return (ReturnCmd) this.VisitTransferCmd(node);
+ }
+ public virtual ReturnExprCmd! VisitReturnExprCmd(ReturnExprCmd! node)
+ {
+ node.Expr = this.VisitExpr(node.Expr);
+ return node;
+ }
+ public virtual Sequential! VisitSequential(Sequential! node)
+ {
+ node.first = (RE) this.VisitRE(node.first);
+ node.second = (RE) this.VisitRE(node.second);
+ return node;
+ }
+ public virtual AssignLhs! VisitSimpleAssignLhs(SimpleAssignLhs! node)
+ {
+ node.AssignedVariable =
+ (IdentifierExpr) this.VisitIdentifierExpr(node.AssignedVariable);
+ return node;
+ }
+ public virtual Cmd! VisitStateCmd(StateCmd! node)
+ {
+ node.Locals = this.VisitVariableSeq(node.Locals);
+ node.Cmds = this.VisitCmdSeq(node.Cmds);
+ return node;
+ }
+ public virtual TransferCmd! VisitTransferCmd(TransferCmd! node)
+ {
+ return node;
+ }
+ public virtual Trigger! VisitTrigger(Trigger! node)
+ {
+ Trigger origNext = node.Next;
+ if (origNext != null) {
+ Trigger newNext = this.VisitTrigger(origNext);
+ if (newNext != origNext) {
+ node = new Trigger(node.tok, node.Pos, node.Tr); // note: this creates sharing between the old and new Tr sequence
+ node.Next = newNext;
+ }
+ }
+ node.Tr = this.VisitExprSeq(node.Tr);
+ return node;
+ }
+ // called by default for all nullary type constructors and type variables
+ public virtual Type! VisitType(Type! node)
+ {
+ return node;
+ }
+ public virtual TypedIdent! VisitTypedIdent(TypedIdent! node)
+ {
+ node.Type = (Type)this.Visit(node.Type);
+ return node;
+ }
+ public virtual Declaration! VisitTypeCtorDecl(TypeCtorDecl! node)
+ {
+ return this.VisitDeclaration(node);
+ }
+ public virtual Type! VisitTypeSynonymAnnotation(TypeSynonymAnnotation! node)
+ {
+ node.ExpandedType = (Type!)this.Visit(node.ExpandedType);
+ for (int i = 0; i < node.Arguments.Length; ++i)
+ node.Arguments[i] = (Type!)this.Visit(node.Arguments[i]);
+ return node;
+ }
+ public virtual Declaration! VisitTypeSynonymDecl(TypeSynonymDecl! node)
+ {
+ return this.VisitDeclaration(node);
+ }
+ public virtual Type! VisitTypeVariable(TypeVariable! node)
+ {
+ return this.VisitType(node);
+ }
+ public virtual Type! VisitTypeProxy(TypeProxy! node)
+ {
+ // if the type proxy is instantiated with some more
+ // specific type, we visit the instantiation
+ if (node.ProxyFor != null)
+ return (Type!)this.Visit(node.ProxyFor);
+ return this.VisitType(node);
+ }
+ public virtual Type! VisitUnresolvedTypeIdentifier(UnresolvedTypeIdentifier! node)
+ {
+ return this.VisitType(node);
+ }
+ public virtual Variable! VisitVariable(Variable! node)
+ {
+ node.TypedIdent = this.VisitTypedIdent(node.TypedIdent);
+ return node;
+ }
+ public virtual VariableSeq! VisitVariableSeq(VariableSeq! variableSeq)
+ {
+ for (int i = 0, n = variableSeq.Length; i < n; i++)
+ variableSeq[i] = this.VisitVariable( (!)variableSeq[i]);
+ return variableSeq;
+ }
+ public virtual Cmd! VisitAssertEnsuresCmd(AssertEnsuresCmd! node)
+ {
+ node.Ensures = this.VisitEnsures(node.Ensures);
+ node.Expr = this.VisitExpr(node.Expr);
+ return node;
+ }
+ public virtual Cmd! VisitAssertRequiresCmd(AssertRequiresCmd! node)
+ {
+ node.Requires = this.VisitRequires(node.Requires);
+ node.Expr = this.VisitExpr(node.Expr);
+ return node;
+ }
+ }
+}
diff --git a/Source/Core/TypeAmbiguitySeeker.ssc b/Source/Core/TypeAmbiguitySeeker.ssc
new file mode 100644
index 00000000..762b9c04
--- /dev/null
+++ b/Source/Core/TypeAmbiguitySeeker.ssc
@@ -0,0 +1,95 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using System;
+
+// Visitor to search for types proxies that could not completely be
+// determined by type inference. If this happens, a warning is
+// generated and the proxies are instantiated in a more or less arbitrary
+// fashion.
+
+namespace Microsoft.Boogie
+{
+
+ public class TypeAmbiguitySeeker : StandardVisitor {
+
+ private readonly InTypeSeeker! inTypeSeeker = new InTypeSeeker ();
+ private readonly TypecheckingContext! TC;
+
+ public TypeAmbiguitySeeker(TypecheckingContext! tc) {
+ TC = tc;
+ }
+
+ private void CheckTypeParams(Absy! node, TypeParamInstantiation! insts) {
+ foreach (TypeVariable! var in insts.FormalTypeParams) {
+ Type! inst = insts[var];
+ inTypeSeeker.FoundAmbiguity = false;
+ inTypeSeeker.Visit(inst);
+ if (inTypeSeeker.FoundAmbiguity)
+ TC.Warning(node,
+ "type parameter {0} is ambiguous, instantiating to {1}",
+ var, inst);
+ }
+ }
+
+ public override Expr! VisitNAryExpr(NAryExpr! node)
+ {
+ CheckTypeParams(node, (!)node.TypeParameters);
+ return base.VisitNAryExpr(node);
+ }
+
+ public override AssignLhs! VisitMapAssignLhs(MapAssignLhs! node) {
+ CheckTypeParams(node, (!)node.TypeParameters);
+ return base.VisitMapAssignLhs(node);
+ }
+ }
+
+ internal class InTypeSeeker : StandardVisitor {
+
+ internal bool FoundAmbiguity = false;
+
+ // called when an uninstantiated proxy was found
+ private Type! Instantiate(Type! node, Type! inst) {
+ FoundAmbiguity = true;
+ bool success = node.Unify(inst);
+ assert success;
+ return node;
+ }
+
+ public override Type! VisitTypeProxy(TypeProxy! node) {
+ if (node.ProxyFor != null)
+ return base.VisitTypeProxy(node);
+
+ return Instantiate(node, Type.Int);
+ }
+
+ public override Type! VisitMapTypeProxy(MapTypeProxy! node) {
+ if (node.ProxyFor != null)
+ return base.VisitMapTypeProxy(node);
+
+ TypeVariableSeq! typeParams = new TypeVariableSeq ();
+ TypeSeq! arguments = new TypeSeq ();
+ for (int i = 0; i < node.Arity; ++i) {
+ TypeVariable! param = new TypeVariable (Token.NoToken, "arg" + i);
+ typeParams.Add(param);
+ arguments.Add(param);
+ }
+ TypeVariable! result = new TypeVariable (Token.NoToken, "res");
+ typeParams.Add(result);
+
+ Type! instantiation = new MapType (Token.NoToken, typeParams, arguments, result);
+
+ return Instantiate(node, instantiation);
+ }
+
+ public override Type! VisitBvTypeProxy(BvTypeProxy! node) {
+ if (node.ProxyFor != null)
+ return base.VisitBvTypeProxy(node);
+
+ return Instantiate(node, new BvType (node.MinBits));
+ }
+ }
+
+} \ No newline at end of file
diff --git a/Source/Core/Util.ssc b/Source/Core/Util.ssc
new file mode 100644
index 00000000..914ccf09
--- /dev/null
+++ b/Source/Core/Util.ssc
@@ -0,0 +1,466 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+namespace Microsoft.Boogie
+{
+ using System;
+ using System.IO;
+ using System.Collections;
+ using Microsoft.Contracts;
+
+ public class TokenTextWriter : IDisposable
+ {
+ string! filename;
+ TextWriter! writer;
+ bool writerOpenedHere = false;
+ bool setTokens = true;
+ int line = 1;
+ int col;
+
+ private const int indent_size = 2;
+ protected static string! Indent (int level)
+ {
+ return new string(' ', (indent_size * level));
+ }
+
+
+ // Keywords, this array *must* be sorted
+ public static readonly string[]! BplKeywords =
+ {
+ "assert",
+ "assume",
+ "axiom",
+ "bool",
+ "break",
+ "call",
+ "cast",
+ "const",
+ "else",
+ "ensures",
+ "exists",
+ "false",
+ "forall",
+ "free",
+ "function",
+ "goto",
+ "havoc",
+ "if",
+ "implementation",
+ "int",
+ "invariant",
+ "modifies",
+ "old",
+ "procedure",
+ "public",
+ "requires",
+ "return",
+ "returns",
+ "true",
+ "type",
+ "unique",
+ "var",
+ "where",
+ "while",
+ };
+
+ private IToken! CurrentToken
+ {
+ get
+ {
+ Token token = new Token();
+ token.filename = filename;
+ token.line = line;
+ token.col = col;
+ return token;
+ }
+ }
+
+ public void SetToken(Absy! absy)
+ {
+ this.SetToken(ref absy.tok);
+ }
+
+ public void SetToken(ref IToken! tok)
+ {
+ if (this.setTokens) {
+ tok = this.CurrentToken;
+ }
+ }
+
+ public static string! SanitizeIdentifier (string! name)
+ {
+ int index = Array.BinarySearch(TokenTextWriter.BplKeywords, name);
+ if (index >= 0) {
+ return "\\" + name;
+ } else if (name.Length > 2 && name[0] == 'b' && name[1] == 'v') {
+ int dummy;
+ return int.TryParse(name.Substring(2), out dummy) ? "\\" + name : name;
+ } else {
+ return name;
+ }
+ }
+
+ public TokenTextWriter(string! filename)
+ {
+ this.filename = filename;
+ this.writer = new StreamWriter(filename);
+ this.writerOpenedHere = true;
+ base();
+ }
+
+ public TokenTextWriter(string! filename, TextWriter! writer, bool setTokens)
+ {
+ this.filename = filename;
+ this.writer = writer;
+ this.setTokens = setTokens;
+ base();
+ }
+
+ public TokenTextWriter(string! filename, TextWriter! writer)
+ {
+ this.filename = filename;
+ this.writer = writer;
+ base();
+ }
+
+ public TokenTextWriter(TextWriter! writer)
+ {
+ this.filename = "<no file>";
+ this.writer = writer;
+ base();
+ }
+
+ public void Write(string! text)
+ {
+ this.writer.Write(text);
+ this.col += text.Length;
+ }
+
+ public void WriteIndent(int level)
+ {
+ this.Write(Indent(level));
+ }
+
+ public void Write(string! text, params object[] args)
+ {
+ this.Write(string.Format(text, args));
+ }
+
+ public void Write(int level, string! text)
+ {
+ this.WriteIndent(level);
+ this.Write(text);
+ }
+
+ public void Write(int level, string! text, params object[] args)
+ {
+ this.WriteIndent(level);
+ this.Write(text, args);
+ }
+
+ public void Write(Absy! node, string! text)
+ {
+ this.SetToken(node);
+ this.Write(text);
+ }
+
+ public void Write(Absy! node, string! text, params string[] args)
+ {
+ this.SetToken(node);
+ this.Write(text, args);
+ }
+
+ public void Write(Absy! node, int level, string! text)
+ {
+ this.WriteIndent(level);
+ this.SetToken(node);
+ this.Write(text);
+ }
+
+ public void Write(Absy! node, int level, string! text, params object[] args)
+ {
+ this.WriteIndent(level);
+ this.SetToken(node);
+ this.Write(text, args);
+ }
+
+ public void WriteLine()
+ {
+ this.writer.WriteLine();
+ this.line++;
+ this.col = 0;
+ }
+
+ public void WriteLine(string! text)
+ {
+ this.writer.WriteLine(text);
+ this.line++;
+ this.col = 0;
+ }
+
+ public void WriteLine(string! text, params object[] args)
+ {
+ this.WriteLine(string.Format(text, args));
+ }
+
+ public void WriteLine(int level, string! text)
+ {
+ this.WriteIndent(level);
+ this.WriteLine(text);
+ }
+
+ public void WriteLine(int level, string! text, params object[] args)
+ {
+ this.WriteIndent(level);
+ this.WriteLine(text, args);
+ }
+
+ public void WriteLine(Absy! node, string! text)
+ {
+ this.SetToken(node);
+ this.WriteLine(text);
+ }
+
+ public void WriteLine(Absy! node, int level, string! text)
+ {
+ this.SetToken(node);
+ this.WriteLine(level, text);
+ }
+
+ public void WriteLine(Absy! node, int level, string! text, params object[] args)
+ {
+ this.SetToken(node);
+ this.WriteLine(level, text, args);
+ }
+
+ public void Close()
+ {
+ this.writer.Close();
+ }
+
+ public void Dispose()
+ {
+ this.Close();
+ }
+ }
+
+ public class Helpers {
+ public static string! BeautifyBplString (string! s) {
+ // strip "^" if it is the first character, change "$result" to "result"
+ if (s.StartsWith("^") || s == "$result") {
+ s = s.Substring(1);
+ } else if (s.StartsWith("call")) {
+ s = s.Substring(s.IndexOf('@') + 1);
+ if (s.StartsWith("formal@")) {
+ s = "(value of formal parameter: " + s.Substring(7) +")";
+ }
+ }
+ // strip "$in" from the end of identifier names
+ if (s.EndsWith("$in")) {
+ return "(initial value of: " + s.Substring(0, s.Length-3) +")";
+ } else {
+ return s;
+ }
+ }
+ public static string! PrettyPrintBplExpr (Expr! e) {
+ // anything that is unknown will just be printed via ToString
+ // OldExpr and QuantifierExpr, ExtractExpr, BvConcatExpr are ignored for now
+ // LiteralExpr is printed as itself by ToString
+ if (e is IdentifierExpr) {
+ string s = e.ToString();
+ return Helpers.BeautifyBplString(s);
+ }
+ else if (e is NAryExpr) {
+ NAryExpr ne = (NAryExpr) e;
+ IAppliable fun = ne.Fun;
+ ExprSeq eSeq = ne.Args;
+ if (fun != null) {
+ if ((fun.FunctionName == "$Length" || fun.FunctionName == "$StringLength" ) && eSeq.Length == 1) {
+ Expr e0 = eSeq[0];
+ if (e0 != null) {
+ string s0 = PrettyPrintBplExpr(e0);
+ return s0 + ".Length";
+ }
+ //unexpected, just fall outside to the default
+ } else if (fun.FunctionName == "$typeof" && eSeq.Length == 1) {
+ Expr e0 = eSeq[0];
+ if (e0 != null) {
+ string s0 = PrettyPrintBplExpr(e0);
+ return "(the dynamic type of: " + s0 + ")";
+ }
+ //unexpected, just fall outside to the default
+ } else if (fun.FunctionName == "IntArrayGet" && eSeq.Length == 2) {
+ Expr e0 = eSeq[0];
+ Expr e1 = eSeq[1];
+ if (e0 != null && e1 != null) {
+ string s0 = PrettyPrintBplExpr(e0);
+ string s1 = PrettyPrintBplExpr(e1);
+ return s0 + "[" + s1 + "]";
+ }
+ //unexpected, just fall outside to the default
+ } else if (fun.FunctionName == "$Is" && eSeq.Length == 2) {
+ Expr e0 = eSeq[0];
+ Expr e1 = eSeq[1];
+ if (e0 != null && e1 != null) {
+ string s0 = PrettyPrintBplExpr(e0);
+ string s1 = PrettyPrintBplExpr(e1);
+ return "(" + s0 + " == null || (" + s0 + " is " + s1 + "))";
+ }
+ //unexpected, just fall outside to the default
+ } else if (fun.FunctionName == "$IsNotNull" && eSeq.Length == 2) {
+ Expr e0 = eSeq[0];
+ Expr e1 = eSeq[1];
+ if (e0 != null && e1 != null) {
+ string s0 = PrettyPrintBplExpr(e0);
+ string s1 = PrettyPrintBplExpr(e1);
+ return "(" + s0 + " is " + s1 +")";
+ }
+ //unexpected, just fall outside to the default
+ } else if (fun is MapSelect && eSeq.Length <= 3) {
+ // only maps with up to two arguments are supported right now (here)
+ if (((!)eSeq[0]).ToString() == "$Heap") {
+ //print Index0.Index1, unless Index1 is "$elements", then just print Index0
+ string s0 = PrettyPrintBplExpr((!)eSeq[1]);
+ if (eSeq.Length > 2) {
+ string s1 = PrettyPrintBplExpr((!)eSeq[2]);
+ if (s1 == "$elements") {
+ return s0;
+ } else {
+ if (eSeq[2] is IdentifierExpr) {
+ // strip the class name out of a fieldname
+ s1 = s1.Substring(s1.LastIndexOf('.') + 1);
+ }
+ return s0 + "." + s1;
+ }
+ }
+ }
+ //unexpected, just fall outside to the default
+ } else if (fun is Microsoft.Boogie.BinaryOperator && eSeq.Length == 2) {
+ Microsoft.Boogie.BinaryOperator f = (Microsoft.Boogie.BinaryOperator) fun;
+ Expr e0 = eSeq[0];
+ Expr e1 = eSeq[1];
+ if (e0 != null && e1 != null) {
+ string s0 = PrettyPrintBplExpr(e0);
+ string s1 = PrettyPrintBplExpr(e1);
+ string op = "";
+ switch (f.Op) {
+ case Microsoft.Boogie.BinaryOperator.Opcode.Add:
+ op = " + ";
+ break;
+ case Microsoft.Boogie.BinaryOperator.Opcode.And:
+ op = " && ";
+ break;
+ case Microsoft.Boogie.BinaryOperator.Opcode.Div:
+ op = " / ";
+ break;
+ case Microsoft.Boogie.BinaryOperator.Opcode.Eq:
+ op = " == ";
+ break;
+ case Microsoft.Boogie.BinaryOperator.Opcode.Ge:
+ op = " >= ";
+ break;
+ case Microsoft.Boogie.BinaryOperator.Opcode.Gt:
+ op = " > ";
+ break;
+ case Microsoft.Boogie.BinaryOperator.Opcode.Iff:
+ op = " <==> ";
+ break;
+ case Microsoft.Boogie.BinaryOperator.Opcode.Imp:
+ op = " ==> ";
+ break;
+ case Microsoft.Boogie.BinaryOperator.Opcode.Le:
+ op = " <= ";
+ break;
+ case Microsoft.Boogie.BinaryOperator.Opcode.Lt:
+ op = " < ";
+ break;
+ case Microsoft.Boogie.BinaryOperator.Opcode.Mod:
+ op = " % ";
+ break;
+ case Microsoft.Boogie.BinaryOperator.Opcode.Mul:
+ op = " * ";
+ break;
+ case Microsoft.Boogie.BinaryOperator.Opcode.Neq:
+ op = " != ";
+ break;
+ case Microsoft.Boogie.BinaryOperator.Opcode.Or:
+ op = " || ";
+ break;
+ case Microsoft.Boogie.BinaryOperator.Opcode.Sub:
+ op = " - ";
+ break;
+ case Microsoft.Boogie.BinaryOperator.Opcode.Subtype:
+ op = " <: ";
+ break;
+ default: op = " ";
+ break;
+ }
+ return "(" + s0 + op + s1 + ")";
+ }
+ //unexpected, just fall outside to the default
+ } else {
+ string s = fun.FunctionName + "(";
+ for (int i = 0; i < eSeq.Length; i++) {
+ Expr ex = eSeq[i];
+ assume ex != null;
+ if (i>0) {
+ s += ", ";
+ }
+ string t = PrettyPrintBplExpr(ex);
+ if (t.StartsWith("(") && t.EndsWith(")")) {
+ t = t.Substring(1, t.Length -2);
+ }
+ s += t;
+ }
+ s += ")";
+ return s;
+ //unexpected, just fall outside to the default
+ }
+ }
+ }
+
+ return e.ToString();
+ }
+
+ private static readonly DateTime StartUp = DateTime.Now;
+
+ public static void ExtraTraceInformation(string! point) {
+ if (CommandLineOptions.Clo.TraceTimes) {
+ DateTime now = DateTime.Now;
+ TimeSpan timeSinceStartUp = now - StartUp;
+ Console.WriteLine(">>> {0} [{1} s]", point, timeSinceStartUp.TotalSeconds);
+ }
+ }
+
+ // Substitute @PROC@ in a filename with the given descName
+ public static string! SubstituteAtPROC(string! descName, string! fileName) {
+ System.Text.StringBuilder! sb =
+ new System.Text.StringBuilder(descName.Length);
+ // quote the name, characters like ^ cause trouble in CMD
+ // while $ could cause trouble in SH
+ foreach (char c in descName) {
+ if (Char.IsLetterOrDigit(c) || c == '.') {
+ sb.Append(c);
+ } else {
+ sb.Append('_');
+ }
+ }
+ string pn = sb.ToString();
+ // We attempt to avoid filenames that are too long, but we only
+ // do it by truncating the @PROC@ replacement, which leaves unchanged
+ // any filename extension specified by the user. We base our
+ // calculations on that there is at most one occurrence of @PROC@.
+ if (180 <= fileName.Length - 6 + pn.Length) {
+ pn = pn.Substring(0, max{180 - (fileName.Length - 6), 0}) + "-n" + sequenceNumber;
+ sequenceNumber++;
+ }
+
+ return fileName.Replace("@PROC@", pn);
+ }
+
+ private static int sequenceNumber = 0;
+
+ }
+}
diff --git a/Source/Core/VCExp.ssc b/Source/Core/VCExp.ssc
new file mode 100644
index 00000000..4b42a639
--- /dev/null
+++ b/Source/Core/VCExp.ssc
@@ -0,0 +1,190 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using System;
+using System.IO;
+using System.Collections;
+using System.Collections.Generic;
+using System.Reflection;
+using System.Text;
+using Microsoft.Contracts;
+using Microsoft.Basetypes;
+
+
+namespace Microsoft.Boogie {
+
+ public class ProverOptions
+ {
+ public class OptionException : Exception {
+ public OptionException(string! msg) { base(msg); }
+ }
+
+ public string/*?*/ LogFilename = null;
+ public bool AppendLogFile = false;
+ public bool SeparateLogFiles = false;
+ // Say (DBG_WAS_VALID) or (DBG_WAS_INVALID) after query
+ public bool ForceLogStatus = false;
+ public int TimeLimit = 0;
+ public int MemoryLimit = 0;
+ public CommandLineOptions.BvHandling BitVectors = CommandLineOptions.BvHandling.None;
+ public int Verbosity = 0;
+
+ private string! stringRepr = "";
+
+ [Pure]
+ public override string! ToString()
+ {
+ return stringRepr;
+ }
+
+ // The usual thing to override.
+ protected virtual bool Parse(string! opt)
+ {
+ return ParseString(opt, "LOG_FILE", ref LogFilename) ||
+ ParseBool(opt, "APPEND_LOG_FILE", ref AppendLogFile) ||
+ ParseBool(opt, "FORCE_LOG_STATUS", ref ForceLogStatus) ||
+ ParseInt(opt, "MEMORY_LIMIT", ref MemoryLimit) ||
+ ParseInt(opt, "VERBOSITY", ref Verbosity) ||
+ ParseInt(opt, "TIME_LIMIT", ref TimeLimit);
+ // || base.Parse(opt)
+ }
+
+ public virtual void Parse(List<string!>! opts)
+ {
+ StringBuilder! sb = new StringBuilder(stringRepr);
+ foreach (string! opt in opts) {
+ if (!Parse(opt)) {
+ ReportError("Unrecognised prover option: " + opt);
+ }
+ sb.Append(opt).Append(" ");
+ }
+ stringRepr = sb.ToString();
+ PostParse();
+ }
+
+ protected virtual void PostParse()
+ {
+ if (LogFilename != null && LogFilename.Contains("@PROC@")) {
+ SeparateLogFiles = true;
+ }
+ }
+
+ protected void ReportError(string! msg)
+ {
+ throw new OptionException(msg);
+ }
+
+ protected virtual bool ParseString(string! opt, string! name, ref string field)
+ {
+ if (opt.Length >= name.Length && opt.StartsWith(name)) {
+ if (opt.Length == name.Length) {
+ field = "";
+ return true;
+ } else if (opt[name.Length] == '=') {
+ field = opt.Substring(name.Length + 1);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ protected virtual bool ParseBool(string! opt, string! name, ref bool field)
+ {
+ string tmp = null;
+ if (ParseString(opt, name, ref tmp))
+ switch (((!)tmp).ToLower()) {
+ case "1":
+ case "true":
+ case "":
+ field = true;
+ return true;
+ case "0":
+ case "false":
+ field = false;
+ return true;
+ default:
+ ReportError("Invalid Boolean option \"" + opt + "\"");
+ return false;
+ }
+ return false;
+ }
+
+ protected virtual bool ParseInt(string! opt, string! name, ref int field)
+ {
+ string tmp = null;
+ int t2;
+ if (ParseString(opt, name, ref tmp)) {
+ if (int.TryParse((!)tmp, out t2)) {
+ field = t2;
+ return true;
+ } else {
+ ReportError("Invalid integer option \"" + opt + "\"");
+ }
+ }
+ return false;
+ }
+
+ static int sequenceNumber = 0;
+ public virtual TextWriter? OpenLog(string/*?*/ descName)
+ {
+ if (LogFilename != null) {
+ string! filename = LogFilename;
+ if (descName != null)
+ filename = Helpers.SubstituteAtPROC(descName, filename);
+ return new StreamWriter(filename, AppendLogFile);
+ } else {
+ return null;
+ }
+ }
+ }
+
+ public abstract class ProverFactory
+ {
+ // Really returns ProverInterface.
+ public abstract object! SpawnProver(ProverOptions! options, object! ctxt);
+
+ // Really returns ProverContext
+ public abstract object! NewProverContext(ProverOptions! options);
+
+ public virtual ProverOptions! BlankProverOptions()
+ {
+ return new ProverOptions();
+ }
+
+ // return true if the prover supports DAG AST as opposed to LET AST
+ public virtual bool SupportsDags
+ {
+ get { return false; }
+ }
+
+ public virtual CommandLineOptions.VCVariety DefaultVCVariety
+ {
+ get
+ ensures result != CommandLineOptions.VCVariety.Unspecified;
+ { return CommandLineOptions.VCVariety.Dag; }
+ }
+
+ public virtual void Close()
+ {
+ }
+
+ public static ProverFactory! Load(string! proverName)
+ ensures result.IsNew && Microsoft.Contracts.Owner.New(result);
+ {
+ string! path;
+ if (proverName.IndexOf("/") > 0 || proverName.IndexOf("\\") > 0) {
+ path = proverName;
+ } else {
+ string! codebase = (!) System.IO.Path.GetDirectoryName(
+ (!)System.Reflection.Assembly.GetExecutingAssembly().Location);
+ path = System.IO.Path.Combine(codebase, "Provers." + proverName + ".dll");
+ }
+ Assembly asm = (!)Assembly.LoadFrom(path);
+ string name = (!)asm.GetName().Name;
+ System.Type factoryType = (!)asm.GetType("Microsoft.Boogie." + name.Replace("Provers.", "") + ".Factory");
+ return (ProverFactory!)Activator.CreateInstance(factoryType);
+ }
+ }
+}
diff --git a/Source/Core/Xml.ssc b/Source/Core/Xml.ssc
new file mode 100644
index 00000000..5714849c
--- /dev/null
+++ b/Source/Core/Xml.ssc
@@ -0,0 +1,292 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using System;
+using System.IO;
+using System.Xml;
+using System.Collections.Generic;
+using Microsoft.Contracts;
+using Cci = System.Compiler;
+
+namespace Microsoft.Boogie
+{
+
+ public class XmlSink {
+ string! filename;
+ [Rep] XmlWriter wr;
+ public bool IsOpen {
+ get { return wr != null; }
+ }
+
+ public XmlSink(string! filename) {
+ this.filename = filename;
+ }
+
+ /// <summary>
+ /// Returns null on success, in which case the caller should eventually invoke Close.
+ /// Returns an error string on failure.
+ /// </summary>
+ public string Open()
+ modifies this.*;
+ ensures IsOpen;
+ {
+ if (wr != null) {
+ Close();
+ }
+ expose (this) {
+ XmlWriterSettings settings = new XmlWriterSettings();
+ settings.Indent = true;
+ wr = XmlWriter.Create(filename, settings);
+ wr.WriteStartDocument();
+ wr.WriteStartElement("boogie");
+ wr.WriteAttributeString("version", CommandLineOptions.VersionNumber);
+ wr.WriteAttributeString("commandLine", Environment.CommandLine);
+ }
+ return null; // success
+ }
+
+ public void Close()
+ modifies this.*;
+ {
+ if (wr != null) {
+ expose (this) {
+ wr.WriteEndDocument();
+ wr.Close();
+ wr = null;
+ }
+ }
+ }
+
+ const string DateTimeFormatString = "u";
+
+ public void WriteStartMethod(string! methodName, DateTime startTime)
+ requires IsOpen;
+ modifies this.*;
+ ensures IsOpen;
+ {
+ assert wr != null;
+ expose (this) {
+ wr.WriteStartElement("method");
+ wr.WriteAttributeString("name", methodName);
+ wr.WriteAttributeString("startTime", startTime.ToString(DateTimeFormatString));
+ }
+ }
+
+ public void WriteEndMethod(string! outcome, DateTime endTime, TimeSpan elapsed)
+ requires IsOpen;
+ modifies this.*;
+ ensures IsOpen;
+ {
+ assert wr != null;
+ expose (this) {
+ wr.WriteStartElement("conclusion");
+ wr.WriteAttributeString("endTime", endTime.ToString(DateTimeFormatString));
+ wr.WriteAttributeString("duration", elapsed.TotalSeconds.ToString());
+ wr.WriteAttributeString("outcome", outcome);
+
+ wr.WriteEndElement(); // outcome
+ wr.WriteEndElement(); // method
+ }
+ }
+
+ public void WriteError(string! message, IToken! errorToken, IToken relatedToken, BlockSeq trace)
+ requires IsOpen && (trace == null || Owner.Different(this, trace));
+ modifies this.*, errorToken.*, relatedToken.*, trace.*;
+ ensures IsOpen;
+ {
+ assert wr != null;
+ expose(this){
+ wr.WriteStartElement("error");
+ wr.WriteAttributeString("message", message);
+ WriteTokenAttributes(errorToken);
+ if (relatedToken != null)
+ {
+ wr.WriteStartElement("related");
+ WriteTokenAttributes(relatedToken);
+ wr.WriteEndElement();
+ }
+ if (trace != null)
+ {
+ wr.WriteStartElement("trace");
+ {
+ foreach (object bo in trace)
+ invariant wr != null;
+ {
+ assume bo is Block;
+ Block b = (Block)bo;
+ wr.WriteStartElement("traceNode");
+ {
+ WriteTokenAttributes(b.tok);
+ wr.WriteAttributeString("label", b.Label);
+ }
+ wr.WriteEndElement();
+ }
+ wr.WriteEndElement();
+ }
+ }
+ wr.WriteEndElement();
+ }
+ }
+
+ public void WriteError(string! message, Cci.Node! offendingNode, BlockSeq trace)
+ requires IsOpen && Owner.Different(this, offendingNode);
+ requires trace == null || Owner.Different(this, trace);
+ modifies this.*, offendingNode.*, trace.*;
+ ensures IsOpen;
+ {
+ assert wr != null;
+ expose(this){
+ wr.WriteStartElement("error");
+ wr.WriteAttributeString("message", message);
+ WriteTokenAttributes(offendingNode);
+ if (trace != null)
+ {
+ wr.WriteStartElement("trace");
+ {
+ foreach (object bo in trace)
+ invariant wr != null;
+ {
+ assume bo is Block;
+ Block b = (Block)bo;
+ wr.WriteStartElement("traceNode");
+ {
+ this.WriteTokenAttributes(b.tok);
+ wr.WriteAttributeString("label", b.Label);
+ }
+ wr.WriteEndElement();
+ }
+ wr.WriteEndElement();
+ }
+ }
+ wr.WriteEndElement();
+ }
+ }
+
+ [Inside]
+ private void WriteTokenAttributes(IToken tok)
+ requires wr != null && wr.IsPeerConsistent;
+ modifies this.0, wr.*;
+ {
+ if (tok != null && tok.filename != null)
+ {
+ wr.WriteAttributeString("file", tok.filename);
+ wr.WriteAttributeString("line", tok.line.ToString());
+ wr.WriteAttributeString("column", tok.col.ToString());
+ }
+ }
+
+ [Inside]
+ private void WriteTokenAttributes(Cci.Node! node)
+ requires wr != null && wr.IsPeerConsistent;
+ modifies this.0, wr.*;
+ {
+ assert wr != null;
+ if (node.SourceContext.Document != null)
+ {
+ wr.WriteAttributeString("file", node.SourceContext.Document.Name);
+ wr.WriteAttributeString("line", node.SourceContext.StartLine.ToString());
+ wr.WriteAttributeString("column", node.SourceContext.StartColumn.ToString());
+ }
+ }
+
+ public void WriteStartInference(string! inferenceName)
+ requires IsOpen;
+ modifies this.*;
+ ensures IsOpen;
+ {
+ assert wr != null;
+ expose (this) {
+ wr.WriteStartElement("inference");
+ wr.WriteAttributeString("name", inferenceName);
+ }
+ }
+
+ public void WriteEndInference()
+ requires IsOpen;
+ modifies this.*;
+ ensures IsOpen;
+ {
+ assert wr != null;
+ expose (this) {
+ wr.WriteEndElement(); // inference
+ }
+ }
+
+ public void WriteContractParaAssignment(string! varName, string val)
+ requires IsOpen;
+ modifies this.*;
+ ensures IsOpen;
+ {
+ assert wr != null;
+ expose (this) {
+ wr.WriteStartElement("assignment");
+ wr.WriteAttributeString("name", varName);
+ wr.WriteAttributeString("value", val);
+ wr.WriteEndElement();
+ }
+ }
+
+ public void WriteStartFile(string! filename)
+ requires IsOpen;
+ modifies this.*;
+ ensures IsOpen;
+ {
+ assert wr != null;
+ expose (this) {
+ wr.WriteStartElement("file");
+ wr.WriteAttributeString("name", filename);
+ }
+ }
+
+ public void WriteEndFile()
+ requires IsOpen;
+ modifies this.*;
+ ensures IsOpen;
+ {
+ assert wr != null;
+ expose (this) {
+ wr.WriteEndElement();
+ }
+ }
+
+ public void WriteFileFragment(string! fragment)
+ requires IsOpen;
+ modifies this.*;
+ ensures IsOpen;
+ {
+ assert wr != null;
+ expose (this) {
+ wr.WriteStartElement("fileFragment");
+ wr.WriteAttributeString("name", fragment);
+ wr.WriteEndElement();
+ }
+ }
+ }
+
+ public class XmlFileScope : IDisposable {
+ [Peer] [SpecPublic] XmlSink sink;
+
+ [Captured]
+ public XmlFileScope(XmlSink? sink, string! filename)
+ requires sink != null ==> sink.IsOpen;
+ modifies sink.*;
+ {
+ if (sink != null) {
+ sink.WriteStartFile(filename); // invoke this method while "sink" is still peer consistent
+ Owner.AssignSame(this, sink);
+ this.sink = sink;
+ }
+ }
+
+ public void Dispose()
+ modifies this.*, sink.*;
+ {
+ if (sink != null) {
+ assume sink.IsOpen;
+ sink.WriteEndFile();
+ }
+ }
+ }
+}
diff --git a/Source/Core/parser.frame b/Source/Core/parser.frame
new file mode 100644
index 00000000..81c7e67c
--- /dev/null
+++ b/Source/Core/parser.frame
@@ -0,0 +1,99 @@
+
+using System;
+using Microsoft.Contracts;
+
+namespace -->namespace {
+
+public class Parser {
+-->constants
+ const bool T = true;
+ const bool x = false;
+ const int minErrDist = 2;
+
+ static Token/*!*/ token; // last recognized token
+ static Token/*!*/ t; // lookahead token
+ static int errDist = minErrDist;
+
+ -->declarations
+
+ static void Error(int n) {
+ if (errDist >= minErrDist) Errors.SynErr(n, t.filename, t.line, t.col);
+ errDist = 0;
+ }
+
+ public static void SemErr(string! msg) {
+ if (errDist >= minErrDist) Errors.SemErr(token.filename, token.line, token.col, msg);
+ errDist = 0;
+ }
+
+ static void Get() {
+ for (;;) {
+ token = t;
+ t = Scanner.Scan();
+ if (t.kind<=maxT) {errDist++; return;}
+-->pragmas
+ t = token;
+ }
+ }
+
+ static void Expect(int n) {
+ if (t.kind==n) Get(); else Error(n);
+ }
+
+ static bool StartOf(int s) {
+ return set[s, t.kind];
+ }
+
+ static void ExpectWeak(int n, int follow) {
+ if (t.kind == n) Get();
+ else {
+ Error(n);
+ while (!StartOf(follow)) Get();
+ }
+ }
+
+ static bool WeakSeparator(int n, int syFol, int repFol) {
+ bool[] s = new bool[maxT+1];
+ if (t.kind == n) {Get(); return true;}
+ else if (StartOf(repFol)) return false;
+ else {
+ for (int i=0; i <= maxT; i++) {
+ s[i] = set[syFol, i] || set[repFol, i] || set[0, i];
+ }
+ Error(n);
+ while (!s[t.kind]) Get();
+ return StartOf(syFol);
+ }
+ }
+
+-->productions
+
+ public static void Parse() {
+ Errors.SynErr = new ErrorProc(SynErr);
+ t = new Token();
+ Get();
+-->parseRoot
+ }
+
+ [Microsoft.Contracts.Verify(false)]
+ static void SynErr(int n, string filename, int line, int col) {
+ Errors.count++;
+ Console.Write("{0}({1},{2}): syntax error: ", filename, line, col);
+ string s;
+ switch (n) {
+-->errors
+ default: s = "error " + n; break;
+ }
+ Console.WriteLine(s);
+ }
+
+ static bool[,]! set = {
+-->initialization
+ };
+
+ [Microsoft.Contracts.Verify(false)]
+ static Parser() {}
+} // end Parser
+
+} // end namespace
+$$$ \ No newline at end of file
diff --git a/Source/Core/scanner.frame b/Source/Core/scanner.frame
new file mode 100644
index 00000000..3753c6e9
--- /dev/null
+++ b/Source/Core/scanner.frame
@@ -0,0 +1,377 @@
+using System;
+using System.IO;
+using System.Collections;
+using System.Collections.Generic;
+using System.Text;
+using Microsoft.Contracts;
+
+
+namespace Microsoft.Boogie {
+
+ [Immutable]
+ public interface IToken {
+ int kind {get; set; } // token kind
+ string filename {get; set; } // token file
+ int pos {get; set; } // token position in the source text (starting at 0)
+ int col {get; set; } // token column (starting at 0)
+ int line {get; set; } // token line (starting at 1)
+ string/*!*/ val {get; set; } // token value
+
+ bool IsValid { get; }
+ }
+
+ [Immutable]
+ public class Token : IToken {
+ int _kind; // token kind
+ string _filename; // token file
+ int _pos; // token position in the source text (starting at 0)
+ int _col; // token column (starting at 0)
+ int _line; // token line (starting at 1)
+ string/*!*/ _val = "foo"; // token value
+
+ public static IToken! NoToken = new Token();
+
+ public Token();
+ public Token(int linenum, int colnum) {
+ this._line = linenum;
+ this._col = colnum;
+ base();
+ }
+
+ public int kind {
+ get { return this._kind; }
+ set { this._kind = value; }
+ }
+
+ public string filename{
+ get { return this._filename; }
+ set { this._filename = value; }
+ }
+
+ public int pos{
+ get { return this._pos; }
+ set { this._pos = value; }
+ }
+
+ public int col{
+ get { return this._col; }
+ set { this._col = value; }
+ }
+
+ public int line{
+ get { return this._line; }
+ set { this._line = value; }
+ }
+
+ public string/*!*/ val{
+ get { return this._val; }
+ set { this._val = value; }
+ }
+
+ public bool IsValid { get { return this._filename != null; } }
+ }
+
+}
+
+namespace -->namespace {
+
+using Microsoft.Boogie;
+
+public class Buffer {
+ static string/*!*/ buf;
+ static int bufLen;
+ static int pos;
+ public const int eof = '\uffff';
+
+ public static void Fill(StreamReader! reader) {
+ List<string!> defines = new List<string!>();
+ Fill(reader, defines);
+ }
+
+ struct ReadState {
+ public bool hasSeenElse;
+ public bool mayStillIncludeAnotherAlternative;
+ public ReadState(bool hasSeenElse, bool mayStillIncludeAnotherAlternative) {
+ this.hasSeenElse = hasSeenElse;
+ this.mayStillIncludeAnotherAlternative = mayStillIncludeAnotherAlternative;
+ }
+ }
+
+ public static void Fill(StreamReader! reader, List<string!>! defines) {
+ StringBuilder sb = new StringBuilder();
+ List<ReadState>! readState = new List<ReadState>(); // readState.Count is the current nesting level of #if's
+ int ignoreCutoff = -1; // -1 means we're not ignoring; for 0<=n, n means we're ignoring because of something at nesting level n
+ while (true)
+ invariant -1 <= ignoreCutoff && ignoreCutoff < readState.Count;
+ {
+ string s = reader.ReadLine();
+ if (s == null) {
+ if (readState.Count != 0) {
+ sb.AppendLine("#MalformedInput: missing #endif");
+ }
+ break;
+ }
+ string t = s.Trim();
+ if (t.StartsWith("#if")) {
+ ReadState rs = new ReadState(false, false);
+ if (ignoreCutoff != -1) {
+ // we're already in a state of ignoring, so continue to ignore
+ } else if (IfdefConditionSaysToInclude(t.Substring(3).TrimStart(), defines)) {
+ // include this branch
+ } else {
+ ignoreCutoff = readState.Count; // start ignoring
+ rs.mayStillIncludeAnotherAlternative = true; // allow some later "elsif" or "else" branch to be included
+ }
+ readState.Add(rs);
+ sb.AppendLine(); // ignore the #if line
+
+ } else if (t.StartsWith("#elsif")) {
+ ReadState rs;
+ if (readState.Count == 0 || (rs = readState[readState.Count-1]).hasSeenElse) {
+ sb.AppendLine("#MalformedInput: misplaced #elsif"); // malformed input
+ break;
+ }
+ if (ignoreCutoff == -1) {
+ // we had included the previous branch
+ assert !rs.mayStillIncludeAnotherAlternative;
+ ignoreCutoff = readState.Count-1; // start ignoring
+ } else if (rs.mayStillIncludeAnotherAlternative && IfdefConditionSaysToInclude(t.Substring(6).TrimStart(), defines)) {
+ // include this branch, but no subsequent branch at this level
+ ignoreCutoff = -1;
+ rs.mayStillIncludeAnotherAlternative = false;
+ readState[readState.Count-1] = rs;
+ }
+ sb.AppendLine(); // ignore the #elsif line
+
+ } else if (t == "#else") {
+ ReadState rs;
+ if (readState.Count == 0 || (rs = readState[readState.Count-1]).hasSeenElse) {
+ sb.AppendLine("#MalformedInput: misplaced #else"); // malformed input
+ break;
+ }
+ rs.hasSeenElse = true;
+ if (ignoreCutoff == -1) {
+ // we had included the previous branch
+ assert !rs.mayStillIncludeAnotherAlternative;
+ ignoreCutoff = readState.Count-1; // start ignoring
+ } else if (rs.mayStillIncludeAnotherAlternative) {
+ // include this branch
+ ignoreCutoff = -1;
+ rs.mayStillIncludeAnotherAlternative = false;
+ }
+ readState[readState.Count-1] = rs;
+ sb.AppendLine(); // ignore the #else line
+
+ } else if (t == "#endif") {
+ if (readState.Count == 0) {
+ sb.AppendLine("#MalformedInput: misplaced #endif"); // malformed input
+ break;
+ }
+ readState.RemoveAt(readState.Count-1); // pop
+ if (ignoreCutoff == readState.Count) {
+ // we had ignored the branch that ends here; so, now we start including again
+ ignoreCutoff = -1;
+ }
+ sb.AppendLine(); // ignore the #endif line
+
+ } else if (ignoreCutoff == -1) {
+ sb.AppendLine(s); // included line
+
+ } else {
+ sb.AppendLine(); // ignore the line
+ }
+ }
+
+ Fill(sb.ToString());
+ }
+
+ // "arg" is assumed to be trimmed
+ private static bool IfdefConditionSaysToInclude(string! arg, List<string!>! defines) {
+ bool sense = true;
+ while (arg.StartsWith("!")) {
+ sense = !sense;
+ arg = arg.Substring(1).TrimStart();
+ }
+ return defines.Contains(arg) == sense;
+ }
+
+ public static void Fill(string! text) {
+ buf = text;
+ bufLen = buf.Length;
+ pos = 0;
+ }
+
+ public static int Read() {
+ if (pos < bufLen) {
+ return buf[pos++];
+ } else {
+ return eof;
+ }
+ }
+
+ public static string/*!*/ ReadToEOL() {
+ int x = buf.IndexOf('\n', pos);
+ if (x == -1) {
+ string s = buf.Substring(pos);
+ pos = buf.Length;
+ return s;
+ } else {
+ string s = buf.Substring(pos, x+1 - pos); // also include the '\n'
+ pos = x+1;
+ return s;
+ }
+ }
+
+ public static int Pos {
+ get { return pos; }
+ set {
+ if (value < 0) pos = 0; else if (value >= bufLen) pos = bufLen; else pos = value;
+ }
+ }
+}
+
+
+
+public class Scanner {
+ const char EOF = '\0';
+ const char CR = '\r';
+ const char LF = '\n';
+ [Microsoft.Contracts.Verify(false)]
+-->declarations
+
+ static Token/*!*/ t; // current token
+ static char ch; // current input character
+ static int pos; // column number of current character
+ static int line; // line number of current character
+ static int lineStart; // start position of current line
+ static Queue! oldEols; // EOLs that appeared in a comment;
+ static BitArray/*!*/ ignore; // set of characters to be ignored by the scanner
+ static string Filename;
+
+ ///<summary>
+ ///Initializes the scanner. Note: first fill the Buffer.
+ ///</summary>
+ ///<param name="filename">File name used for error reporting</param>
+ public static void Init (string filename) {
+ Filename = filename;
+ pos = -1; line = 1; lineStart = 0;
+ oldEols = new Queue();
+ NextCh();
+-->initialization
+ }
+
+ private static void NextCh() {
+ if (oldEols.Count > 0) {
+ ch = (char) ((!)oldEols.Dequeue());
+ } else {
+ while (true) {
+ ch = (char)Buffer.Read(); pos++;
+ if (ch == Buffer.eof) {
+ ch = EOF;
+ } else if (ch == LF) {
+ line++;
+ lineStart = pos + 1;
+
+ } else if (ch == '#' && pos == lineStart) {
+ int prLine = line;
+ int prColumn = pos - lineStart; // which is 0
+
+ string hashLine = Buffer.ReadToEOL(); pos += hashLine.Length;
+ line++;
+ lineStart = pos + 1;
+
+ hashLine = hashLine.TrimEnd(null);
+ if (hashLine.StartsWith("line ") || hashLine == "line") {
+ // parse #line pragma: #line num [filename]
+ string h = hashLine.Substring(4).TrimStart(null);
+ int x = h.IndexOf(' ');
+ if (x == -1) {
+ x = h.Length; // this will be convenient below when we look for a filename
+ }
+ try {
+ int li = int.Parse(h.Substring(0, x));
+
+ h = h.Substring(x).Trim();
+
+ // act on #line
+ line = li;
+ if (h.Length != 0) {
+ // a filename was specified
+ Filename = h;
+ }
+ continue; // successfully parsed and acted on the #line pragma
+
+ } catch (FormatException) {
+ // just fall down through to produce an error message
+ }
+ Errors.SemErr(Filename, prLine, prColumn, "Malformed (#line num [filename]) pragma: #" + hashLine);
+ continue;
+ }
+
+ Errors.SemErr(Filename, prLine, prColumn, "Unrecognized pragma: #" + hashLine);
+ continue;
+ }
+ return;
+ }
+ }
+ }
+
+-->comment
+
+ static void CheckLiteral() {
+ switch (t.val) {
+-->literals
+ }
+ }
+
+ public static Token/*!*/ Scan() {
+ while (ignore[ch]) { NextCh(); }
+-->scan1
+ t = new Token();
+ t.pos = pos; t.col = pos - lineStart + 1; t.line = line; t.filename = Filename;
+ int state = (/*^ (!) ^*/ start)[ch];
+ StringBuilder buf = new StringBuilder(16);
+ buf.Append(ch); NextCh();
+
+ switch (state) {
+ case 0: {t.kind = noSym; goto done;} // NextCh already done
+-->scan2
+ }
+ done:
+ t.val = buf.ToString();
+ return t;
+ }
+
+} // end Scanner
+
+
+public delegate void ErrorProc(int n, string filename, int line, int col);
+
+public class Errors {
+ public static int count = 0; // number of errors detected
+ public static ErrorProc/*!*/ SynErr; // syntactic errors
+
+ public static void SemErr(string filename, int line, int col, string! msg) { // semantic errors
+ ConsoleColor color = Console.ForegroundColor;
+ Console.ForegroundColor = ConsoleColor.Red;
+ Console.WriteLine("{0}({1},{2}): Error: {3}", filename, line, col, msg);
+ Console.ForegroundColor = color;
+ count++;
+ }
+
+ public static void SemErr(IToken! tok, string! msg) { // semantic errors
+ SemErr(tok.filename, tok.line, tok.col, msg);
+ }
+
+ public static void Exception (string s) {
+ ConsoleColor color = Console.ForegroundColor;
+ Console.ForegroundColor = ConsoleColor.Red;
+ Console.WriteLine(s);
+ Console.ForegroundColor = color;
+ System.Environment.Exit(0);
+ }
+
+} // Errors
+
+} // end namespace
+$$$
diff --git a/Source/Dafny.sln b/Source/Dafny.sln
new file mode 100644
index 00000000..307f5d1d
--- /dev/null
+++ b/Source/Dafny.sln
@@ -0,0 +1,26 @@
+
+Microsoft Visual Studio Solution File, Format Version 10.00
+# Visual Studio 2008
+Project("{07C4E3D1-6B67-4060-8A92-940DB82041ED}") = "DafnyDriver", "DafnyDriver\DafnyDriver.sscproj", "{1F1E6F68-E9DF-4181-8CD3-E8C98637084D}"
+EndProject
+Project("{07C4E3D1-6B67-4060-8A92-940DB82041ED}") = "Dafny", "Dafny\DafnyPipeline.sscproj", "{DEAD83C6-1510-4AF9-8F7D-C837DDBB2632}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|.NET = Debug|.NET
+ Release|.NET = Release|.NET
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {1F1E6F68-E9DF-4181-8CD3-E8C98637084D}.Debug|.NET.ActiveCfg = Debug|.NET
+ {1F1E6F68-E9DF-4181-8CD3-E8C98637084D}.Debug|.NET.Build.0 = Debug|.NET
+ {1F1E6F68-E9DF-4181-8CD3-E8C98637084D}.Release|.NET.ActiveCfg = Release|.NET
+ {1F1E6F68-E9DF-4181-8CD3-E8C98637084D}.Release|.NET.Build.0 = Release|.NET
+ {DEAD83C6-1510-4AF9-8F7D-C837DDBB2632}.Debug|.NET.ActiveCfg = Debug|.NET
+ {DEAD83C6-1510-4AF9-8F7D-C837DDBB2632}.Debug|.NET.Build.0 = Debug|.NET
+ {DEAD83C6-1510-4AF9-8F7D-C837DDBB2632}.Release|.NET.ActiveCfg = Release|.NET
+ {DEAD83C6-1510-4AF9-8F7D-C837DDBB2632}.Release|.NET.Build.0 = Release|.NET
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/Source/Dafny.suo b/Source/Dafny.suo
new file mode 100644
index 00000000..b6720c92
--- /dev/null
+++ b/Source/Dafny.suo
Binary files differ
diff --git a/Source/Dafny/Dafny.atg b/Source/Dafny/Dafny.atg
new file mode 100644
index 00000000..3d7630ae
--- /dev/null
+++ b/Source/Dafny/Dafny.atg
@@ -0,0 +1,963 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+
+/*---------------------------------------------------------------------------
+// Dafny
+// Rustan Leino, first created 25 January 2008
+//--------------------------------------------------------------------------*/
+
+using System.Collections.Generic;
+using Microsoft.Boogie;
+
+
+COMPILER Dafny
+
+/*--------------------------------------------------------------------------*/
+
+static List<ClassDecl!>! theClasses = new List<ClassDecl!>();
+
+
+static Expression! dummyExpr = new LiteralExpr(Token.NoToken);
+static Statement! dummyStmt = new ReturnStmt(Token.NoToken);
+static Attributes.Argument! dummyAttrArg = new Attributes.Argument("dummyAttrArg");
+static Scope<string>! parseVarScope = new Scope<string>();
+
+///<summary>
+/// Parses top level declarations from "filename" and appends them to "classes".
+/// Returns the number of parsing errors encountered.
+/// Note: first initialize the Scanner.
+///</summary>
+public static int Parse (string! filename, List<ClassDecl!>! classes) /* throws System.IO.IOException */ {
+ using (System.IO.StreamReader reader = new System.IO.StreamReader(filename)) {
+ BoogiePL.Buffer.Fill(reader);
+ Scanner.Init(filename);
+ return Parse(classes);
+ }
+}
+
+///<summary>
+/// Parses top level declarations and appends them to "classes".
+/// Returns the number of parsing errors encountered.
+/// Note: first initialize the Scanner.
+///</summary>
+public static int Parse (List<ClassDecl!>! classes) {
+ List<ClassDecl!> oldClasses = theClasses;
+ theClasses = classes;
+ Parse();
+ theClasses = oldClasses;
+ return Errors.count;
+}
+
+/*--------------------------------------------------------------------------*/
+CHARACTERS
+ letter = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".
+ digit = "0123456789".
+ special = "'_?`\\".
+ glyph = "`~!@#$%^&*()-_=+[{]}|;:',<.>/?\\".
+
+ cr = '\r'.
+ lf = '\n'.
+ tab = '\t'.
+
+ space = ' '.
+ quote = '"'.
+
+ nondigit = letter + special.
+ nonquote = letter + digit + space + glyph.
+
+
+/*------------------------------------------------------------------------*/
+TOKENS
+ ident = nondigit {nondigit | digit}.
+ digits = digit {digit}.
+ string = quote {nonquote} quote.
+
+COMMENTS FROM "/*" TO "*/" NESTED
+COMMENTS FROM "//" TO lf
+
+IGNORE cr + lf + tab
+
+
+/*------------------------------------------------------------------------*/
+PRODUCTIONS
+
+Dafny
+= (. ClassDecl! c; .)
+ { ClassDecl<out c> (. theClasses.Add(c); .)
+ }
+ EOF
+ .
+
+ClassDecl<out ClassDecl! c>
+= (. Token! id;
+ Attributes attrs = null;
+ List<TypeParameter!> typeArgs = new List<TypeParameter!>();
+ List<MemberDecl!> members = new List<MemberDecl!>();
+ .)
+ "class"
+ { Attribute<ref attrs> }
+ Ident<out id>
+ [ GenericParameters<typeArgs> ]
+ "{"
+ { ClassMemberDecl<members>
+ }
+ "}" (. c = new ClassDecl(id, id.val, typeArgs, members, attrs); .)
+ .
+
+ClassMemberDecl<List<MemberDecl!\>! mm>
+= (. Method! m;
+ Function! f;
+ .)
+ ( FieldDecl<mm>
+ | FunctionDecl<out f> (. mm.Add(f); .)
+ | MethodDecl<out m> (. mm.Add(m); .)
+ | FrameDecl
+ )
+ .
+
+FieldDecl<List<MemberDecl!\>! mm>
+= (. Attributes attrs = null;
+ Token! id; Type! ty;
+ .)
+ "var"
+ { Attribute<ref attrs> }
+ IdentType<out id, out ty> (. mm.Add(new Field(id, id.val, ty, attrs)); .)
+ { "," IdentType<out id, out ty> (. mm.Add(new Field(id, id.val, ty, attrs)); .)
+ }
+ ";"
+ .
+
+IdentType<out Token! id, out Type! ty>
+= Ident<out id>
+ ":"
+ Type<out ty>
+ .
+
+IdentTypeOptional<out BoundVar! var>
+= (. Token! id; Type! ty; Type optType = null;
+ .)
+ Ident<out id>
+ [ ":" Type<out ty> (. optType = ty; .)
+ ]
+ (. var = new BoundVar(id, id.val, optType == null ? new InferredTypeProxy() : optType); .)
+ .
+
+/*------------------------------------------------------------------------*/
+
+GenericParameters<List<TypeParameter!\>! typeArgs>
+= (. Token! id; .)
+ "<"
+ Ident<out id> (. typeArgs.Add(new TypeParameter(id, id.val)); .)
+ { "," Ident<out id> (. typeArgs.Add(new TypeParameter(id, id.val)); .)
+ }
+ ">"
+ .
+
+FrameDecl
+= (. Token! id;
+ Attributes attrs = null;
+ .)
+ "frame"
+ { Attribute<ref attrs> }
+ Ident<out id>
+ "{"
+ /* TBD */
+ "}"
+ .
+
+/*------------------------------------------------------------------------*/
+
+MethodDecl<out Method! m>
+= (. Token! id;
+ Attributes attrs = null;
+ List<TypeParameter!>! typeArgs = new List<TypeParameter!>();
+ List<Formal!> ins = new List<Formal!>();
+ List<Formal!> outs = new List<Formal!>();
+ List<MaybeFreeExpression!> req = new List<MaybeFreeExpression!>();
+ List<Expression!> mod = new List<Expression!>();
+ List<MaybeFreeExpression!> ens = new List<MaybeFreeExpression!>();
+ Statement! bb; Statement body = null;
+ .)
+ "method"
+ { Attribute<ref attrs> }
+ Ident<out id>
+ [ GenericParameters<typeArgs> ]
+ (. parseVarScope.PushMarker(); .)
+ Formals<true, ins>
+ [ "returns"
+ Formals<false, outs>
+ ]
+
+ ( ";" { MethodSpec<req, mod, ens> }
+ | { MethodSpec<req, mod, ens> } BlockStmt<out bb> (. body = bb; .)
+ )
+
+ (. parseVarScope.PopMarker();
+ m = new Method(id, id.val, typeArgs, ins, outs, req, mod, ens, body, attrs);
+ .)
+ .
+
+MethodSpec<List<MaybeFreeExpression!\>! req, List<Expression!\>! mod, List<MaybeFreeExpression!\>! ens>
+= (. Expression! e; bool isFree = false;
+ .)
+ ( "modifies" [ Expression<out e> (. mod.Add(e); .)
+ { "," Expression<out e> (. mod.Add(e); .)
+ }
+ ] ";"
+ | [ "free" (. isFree = true; .)
+ ]
+ ( "requires" Expression<out e> ";" (. req.Add(new MaybeFreeExpression(e, isFree)); .)
+ | "ensures" Expression<out e> ";" (. ens.Add(new MaybeFreeExpression(e, isFree)); .)
+ )
+ )
+ .
+
+Formals<bool incoming, List<Formal!\>! formals>
+= (. Token! id; Type! ty; .)
+ "("
+ [
+ IdentType<out id, out ty> (. formals.Add(new Formal(id, id.val, ty, incoming)); parseVarScope.Push(id.val, id.val); .)
+ { "," IdentType<out id, out ty> (. formals.Add(new Formal(id, id.val, ty, incoming)); parseVarScope.Push(id.val, id.val); .)
+ }
+ ]
+ ")"
+ .
+
+/*------------------------------------------------------------------------*/
+
+Type<out Type! ty>
+= (. ty = new BoolType(); /*keep compiler happy*/
+ .)
+ ( "bool" (. /* yeah, that's it! */ .)
+ | "int" (. ty = new IntType(); .)
+ | ReferenceType<out ty>
+ )
+ .
+
+ReferenceType<out Type! ty>
+= (. Token! x;
+ ty = new BoolType(); /*keep compiler happy*/
+ List<Type!>! gt;
+ .)
+ ( "object" (. ty = new ObjectType(); .)
+
+ | (. gt = new List<Type!>(); .)
+ Ident<out x>
+ [ GenericInstantiation<gt> ] (. ty = new ClassType(x, x.val, gt); .)
+
+ | (. gt = new List<Type!>(); .)
+ "set"
+ GenericInstantiation<gt> (. if (gt.Count != 1) {
+ SemErr("set type expects exactly one type argument");
+ }
+ ty = new SetType(gt[0]);
+ .)
+
+ | (. gt = new List<Type!>(); .)
+ "seq"
+ GenericInstantiation<gt> (. if (gt.Count != 1) {
+ SemErr("seq type expects exactly one type argument");
+ }
+ ty = new SeqType(gt[0]);
+ .)
+ )
+ .
+
+GenericInstantiation<List<Type!\>! gt>
+= (. Type! ty; .)
+ "<"
+ Type<out ty> (. gt.Add(ty); .)
+ { "," Type<out ty> (. gt.Add(ty); .)
+ }
+ ">"
+ .
+
+/*------------------------------------------------------------------------*/
+
+FunctionDecl<out Function! f>
+= (. Attributes attrs = null;
+ Token! id;
+ List<TypeParameter!> typeArgs = new List<TypeParameter!>();
+ List<Formal!> formals = new List<Formal!>();
+ Type! returnType;
+ List<Expression!> reqs = new List<Expression!>();
+ List<Expression!> reads = new List<Expression!>();
+ Expression! bb; Expression body = null;
+ bool use = false;
+ .)
+ "function"
+ { Attribute<ref attrs> }
+ [ "use" (. use = true; .) ]
+ Ident<out id>
+ [ GenericParameters<typeArgs> ]
+ (. parseVarScope.PushMarker(); .)
+ Formals<true, formals>
+ ":"
+ Type<out returnType>
+ ( ";"
+ { FunctionSpec<reqs, reads> }
+ | { FunctionSpec<reqs, reads> }
+ ExtendedExpr<out bb> (. body = bb; .)
+ )
+ (. parseVarScope.PopMarker();
+ f = new Function(id, id.val, use, typeArgs, formals, returnType, reqs, reads, body, attrs);
+ .)
+ .
+
+FunctionSpec<List<Expression!\>! reqs, List<Expression!\>! reads>
+= (. Expression! e; .)
+ ( "requires" Expression<out e> ";" (. reqs.Add(e); .)
+ | ReadsClause<reads>
+ )
+ .
+
+ReadsClause<List<Expression!\>! reads>
+= "reads"
+ [ Expressions<reads> ]
+ ";"
+ .
+
+ExtendedExpr<out Expression! e>
+= (. e = dummyExpr; .)
+ "{"
+ ( IfThenElseExpr<out e>
+ | Expression<out e>
+ )
+ "}"
+ .
+
+IfThenElseExpr<out Expression! e>
+= (. Token! x; Expression! e0; Expression! e1 = dummyExpr; .)
+ "if" (. x = token; .)
+ "(" Expression<out e> ")"
+ ExtendedExpr<out e0>
+ "else"
+ ( IfThenElseExpr<out e1>
+ | ExtendedExpr<out e1>
+ ) (. e = new ITEExpr(x, e, e0, e1); .)
+ .
+
+/*------------------------------------------------------------------------*/
+
+BlockStmt<out Statement! block>
+= (. Token! x;
+ List<Statement!> body = new List<Statement!>();
+ Statement! s;
+ .)
+ (. parseVarScope.PushMarker(); .)
+ "{" (. x = token; .)
+ { Stmt<body>
+ }
+ "}" (. block = new BlockStmt(x, body); .)
+ (. parseVarScope.PopMarker(); .)
+ .
+
+Stmt<List<Statement!\>! ss>
+= (. Statement! s; .)
+ /* By first reading a sequence of block statements, we avoid problems in the generated parser, despite
+ the ambiguity in the grammar. See Note in ConstAtomExpression production.
+ */
+ { BlockStmt<out s> (. ss.Add(s); .)
+ }
+ ( OneStmt<out s> (. ss.Add(s); .)
+ | VarDeclStmts<ss>
+ )
+ .
+
+OneStmt<out Statement! s>
+= (. Token! x; Token! id; string label = null;
+ s = dummyStmt; /* to please the compiler */
+ .)
+ /* This list does not contain BlockStmt, see comment above in Stmt production. */
+ ( AssertStmt<out s>
+ | AssumeStmt<out s>
+ | UseStmt<out s>
+ | AssignStmt<out s>
+ | HavocStmt<out s>
+ | CallStmt<out s>
+ | IfStmt<out s>
+ | WhileStmt<out s>
+ | ForeachStmt<out s>
+ | "label" (. x = token; .)
+ Ident<out id> ":" (. s = new LabelStmt(x, id.val); .)
+ | "break" (. x = token; .)
+ [ Ident<out id> (. label = id.val; .)
+ ] ";" (. s = new BreakStmt(x, label); .)
+ | "return" (. x = token; .)
+ ";" (. s = new ReturnStmt(x); .)
+ )
+ .
+
+AssignStmt<out Statement! s>
+= (. Token! x;
+ Expression! lhs;
+ Expression rhs;
+ Type ty;
+ s = dummyStmt;
+ .)
+ LhsExpr<out lhs>
+ ":=" (. x = token; .)
+ AssignRhs<out rhs, out ty> (. if (rhs != null) {
+ s = new AssignStmt(x, lhs, rhs);
+ } else {
+ assert ty != null;
+ s = new AssignStmt(x, lhs, ty);
+ }
+ .)
+ ";"
+ .
+
+AssignRhs<out Expression e, out Type ty>
+/* ensures e == null <==> ty == null; */
+= (. Expression! ee; Type! tt;
+ e = null; ty = null;
+ .)
+ ( "new" ReferenceType<out tt> (. ty = tt; .)
+ | Expression<out ee> (. e = ee; .)
+ ) (. if (e == null && ty == null) { e = dummyExpr; } .)
+ .
+
+HavocStmt<out Statement! s>
+= (. Token! x; Expression! lhs; .)
+ "havoc" (. x = token; .)
+ LhsExpr<out lhs> ";" (. s = new AssignStmt(x, lhs); .)
+ .
+
+LhsExpr<out Expression! e>
+= Expression<out e> /* TODO: restrict LHS further */
+ .
+
+VarDeclStmts<List<Statement!\>! ss>
+= (. VarDecl! d; .)
+ "var"
+ IdentTypeRhs<out d> (. ss.Add(d); parseVarScope.Push(d.Name, d.Name); .)
+ { "," IdentTypeRhs<out d> (. ss.Add(d); parseVarScope.Push(d.Name, d.Name); .)
+ }
+ ";"
+ .
+
+IdentTypeRhs<out VarDecl! d>
+= (. Token! id; Type! ty; Expression! e;
+ Expression rhs = null; Type newType = null;
+ Type optionalType = null; DeterminedAssignmentRhs optionalRhs = null;
+ .)
+ Ident<out id>
+ [ ":" Type<out ty> (. optionalType = ty; .)
+ ]
+ [ ":="
+ AssignRhs<out rhs, out newType>
+ ]
+ (. if (rhs != null) {
+ assert newType == null;
+ optionalRhs = new ExprRhs(rhs);
+ } else if (newType != null) {
+ optionalRhs = new TypeRhs(newType);
+ } else if (optionalType == null) {
+ optionalType = new InferredTypeProxy();
+ }
+ d = new VarDecl(id, id.val, optionalType, optionalRhs);
+ .)
+ .
+
+IfStmt<out Statement! ifStmt>
+= (. Token! x;
+ Expression guard;
+ Statement! thn;
+ Statement! s;
+ Statement els = null;
+ .)
+ "if" (. x = token; .)
+ Guard<out guard>
+ BlockStmt<out thn>
+ [ "else"
+ ( IfStmt<out s> (. els = s; .)
+ | BlockStmt<out s> (. els = s; .)
+ )
+ ]
+ (. ifStmt = new IfStmt(x, guard, thn, els); .)
+ .
+
+WhileStmt<out Statement! stmt>
+= (. Token! x;
+ Expression guard;
+ bool isFree; Expression! e;
+ List<MaybeFreeExpression!> invariants = new List<MaybeFreeExpression!>();
+ List<Expression!> decreases = new List<Expression!>();
+ Statement! body;
+ .)
+ "while" (. x = token; .)
+ Guard<out guard> (. assume guard == null || Owner.None(guard); .)
+ {( (. isFree = false; .)
+ [ "free" (. isFree = true; .)
+ ]
+ "invariant"
+ Expression<out e> (. invariants.Add(new MaybeFreeExpression(e, isFree)); .)
+ ";"
+ )
+ |
+ (
+ "decreases"
+ Expression<out e> (. decreases.Add(e); .)
+ { "," Expression<out e> (. decreases.Add(e); .)
+ }
+ ";"
+ )
+ }
+ BlockStmt<out body> (. stmt = new WhileStmt(x, guard, invariants, decreases, body); .)
+ .
+
+Guard<out Expression e> /* null represents demonic-choice */
+= (. Expression! ee; e = null; .)
+ "("
+ ( "*" (. e = null; .)
+ | Expression<out ee> (. e = ee; .)
+ )
+ ")"
+ .
+
+CallStmt<out Statement! s>
+= (. Token! x, id;
+ Expression! e;
+ List<IdentifierExpr!> lhs = new List<IdentifierExpr!>();
+ .)
+ "call" (. x = token; .)
+ CallStmtSubExpr<out e>
+
+ [ "," /* call a,b,c,... := ... */
+ (. if (e is IdentifierExpr) {
+ lhs.Add((IdentifierExpr)e);
+ } else if (e is FieldSelectExpr) {
+ SemErr(e.tok, "each LHS of call statement must be a variable, not a field");
+ } else {
+ SemErr(e.tok, "each LHS of call statement must be a variable");
+ }
+ .)
+ Ident<out id> (. lhs.Add(new IdentifierExpr(id, id.val)); .)
+ { "," Ident<out id> (. lhs.Add(new IdentifierExpr(id, id.val)); .)
+ }
+ ":="
+ CallStmtSubExpr<out e>
+
+ | ":=" /* call a := ... */
+ (. if (e is IdentifierExpr) {
+ lhs.Add((IdentifierExpr)e);
+ } else if (e is FieldSelectExpr) {
+ SemErr(e.tok, "each LHS of call statement must be a variable, not a field");
+ } else {
+ SemErr(e.tok, "each LHS of call statement must be a variable");
+ }
+ .)
+ CallStmtSubExpr<out e>
+ ]
+ ";"
+
+ /* "e" has now been parsed as one of: IdentifierExpr, FunctionCallExpr, FieldSelectExpr.
+ It denotes the RHS, so to be legal it must be a FunctionCallExpr. */
+ (. if (e is FunctionCallExpr) {
+ FunctionCallExpr fce = (FunctionCallExpr)e;
+ s = new CallStmt(x, lhs, fce.Receiver, fce.Name, fce.Args); // this actually does an ownership transfer of fce.Args
+ } else {
+ SemErr("RHS of call statement must denote a method invocation");
+ s = new CallStmt(x, lhs, dummyExpr, "dummyMethodName", new List<Expression!>());
+ }
+ .)
+ .
+
+/*------------------------------------------------------------------------*/
+
+ForeachStmt<out Statement! s>
+= (. Token! x, boundVar;
+ Type! ty;
+ Expression! collection;
+ Expression! range;
+ List<PredicateStmt!> bodyPrefix = new List<PredicateStmt!>();
+ AssignStmt bodyAssign = null;
+ .)
+ (. parseVarScope.PushMarker(); .)
+ "foreach" (. x = token;
+ range = new LiteralExpr(x, true);
+ ty = new InferredTypeProxy();
+ .)
+ "(" Ident<out boundVar>
+ [ ":" Type<out ty> ]
+ "in" Expression<out collection>
+ (. parseVarScope.Push(boundVar.val, boundVar.val); .)
+ [ "|" Expression<out range> ]
+ ")"
+ "{"
+ { AssertStmt<out s> (. if (s is PredicateStmt) { bodyPrefix.Add((PredicateStmt)s); } .)
+ | AssumeStmt<out s> (. if (s is PredicateStmt) { bodyPrefix.Add((PredicateStmt)s); } .)
+ | UseStmt<out s> (. if (s is PredicateStmt) { bodyPrefix.Add((PredicateStmt)s); } .)
+ }
+ ( AssignStmt<out s> (. if (s is AssignStmt) { bodyAssign = (AssignStmt)s; } .)
+ | HavocStmt<out s> (. if (s is AssignStmt) { bodyAssign = (AssignStmt)s; } .)
+ )
+ "}" (. s = new ForeachStmt(x, new BoundVar(boundVar, boundVar.val, ty), collection, range, bodyPrefix, bodyAssign); .)
+ (. parseVarScope.PopMarker(); .)
+ .
+
+AssertStmt<out Statement! s>
+= (. Token! x; Expression! e; .)
+ "assert" (. x = token; .)
+ Expression<out e> ";" (. s = new AssertStmt(x, e); .)
+ .
+
+AssumeStmt<out Statement! s>
+= (. Token! x; Expression! e; .)
+ "assume" (. x = token; .)
+ Expression<out e> ";" (. s = new AssumeStmt(x, e); .)
+ .
+
+UseStmt<out Statement! s>
+= (. Token! x; Expression! e; .)
+ "use" (. x = token; .)
+ Expression<out e> ";" (. s = new UseStmt(x, e); .)
+ .
+
+/*------------------------------------------------------------------------*/
+
+Expression<out Expression! e0>
+= (. Token! x; Expression! e1; .)
+ ImpliesExpression<out e0>
+ { EquivOp (. x = token; .)
+ ImpliesExpression<out e1> (. e0 = new BinaryExpr(x, BinaryExpr.Opcode.Iff, e0, e1); .)
+ }
+ .
+
+EquivOp = "<==>" | '\u21d4'.
+
+/*------------------------------------------------------------------------*/
+ImpliesExpression<out Expression! e0>
+= (. Token! x; Expression! e1; .)
+ LogicalExpression<out e0>
+ [ ImpliesOp (. x = token; .)
+ ImpliesExpression<out e1> (. e0 = new BinaryExpr(x, BinaryExpr.Opcode.Imp, e0, e1); .)
+ ]
+ .
+
+ImpliesOp = "==>" | '\u21d2'.
+
+/*------------------------------------------------------------------------*/
+LogicalExpression<out Expression! e0>
+= (. Token! x; Expression! e1; .)
+ RelationalExpression<out e0>
+ [ AndOp (. x = token; .)
+ RelationalExpression<out e1> (. e0 = new BinaryExpr(x, BinaryExpr.Opcode.And, e0, e1); .)
+ { AndOp (. x = token; .)
+ RelationalExpression<out e1> (. e0 = new BinaryExpr(x, BinaryExpr.Opcode.And, e0, e1); .)
+ }
+ | OrOp (. x = token; .)
+ RelationalExpression<out e1> (. e0 = new BinaryExpr(x, BinaryExpr.Opcode.Or, e0, e1); .)
+ { OrOp (. x = token; .)
+ RelationalExpression<out e1> (. e0 = new BinaryExpr(x, BinaryExpr.Opcode.Or, e0, e1); .)
+ }
+ ]
+ .
+
+AndOp = "&&" | '\u2227'.
+OrOp = "||" | '\u2228'.
+
+/*------------------------------------------------------------------------*/
+RelationalExpression<out Expression! e0>
+= (. Token! x; Expression! e1; BinaryExpr.Opcode op; .)
+ Term<out e0>
+ [ RelOp<out x, out op>
+ Term<out e1> (. e0 = new BinaryExpr(x, op, e0, e1); .)
+ ]
+ .
+
+RelOp<out Token! x, out BinaryExpr.Opcode op>
+= (. x = Token.NoToken; op = BinaryExpr.Opcode.Add/*(dummy)*/; .)
+ ( "==" (. x = token; op = BinaryExpr.Opcode.Eq; .)
+ | "<" (. x = token; op = BinaryExpr.Opcode.Lt; .)
+ | ">" (. x = token; op = BinaryExpr.Opcode.Gt; .)
+ | "<=" (. x = token; op = BinaryExpr.Opcode.Le; .)
+ | ">=" (. x = token; op = BinaryExpr.Opcode.Ge; .)
+ | "!=" (. x = token; op = BinaryExpr.Opcode.Neq; .)
+ | "!!" (. x = token; op = BinaryExpr.Opcode.Disjoint; .)
+ | "in" (. x = token; op = BinaryExpr.Opcode.In; .)
+ | '\u2260' (. x = token; op = BinaryExpr.Opcode.Neq; .)
+ | '\u2264' (. x = token; op = BinaryExpr.Opcode.Le; .)
+ | '\u2265' (. x = token; op = BinaryExpr.Opcode.Ge; .)
+ )
+ .
+
+/*------------------------------------------------------------------------*/
+Term<out Expression! e0>
+= (. Token! x; Expression! e1; BinaryExpr.Opcode op; .)
+ Factor<out e0>
+ { AddOp<out x, out op>
+ Factor<out e1> (. e0 = new BinaryExpr(x, op, e0, e1); .)
+ }
+ .
+
+AddOp<out Token! x, out BinaryExpr.Opcode op>
+= (. x = Token.NoToken; op=BinaryExpr.Opcode.Add/*(dummy)*/; .)
+ ( "+" (. x = token; op = BinaryExpr.Opcode.Add; .)
+ | "-" (. x = token; op = BinaryExpr.Opcode.Sub; .)
+ )
+ .
+
+/*------------------------------------------------------------------------*/
+Factor<out Expression! e0>
+= (. Token! x; Expression! e1; BinaryExpr.Opcode op; .)
+ UnaryExpression<out e0>
+ { MulOp<out x, out op>
+ UnaryExpression<out e1> (. e0 = new BinaryExpr(x, op, e0, e1); .)
+ }
+ .
+
+MulOp<out Token! x, out BinaryExpr.Opcode op>
+= (. x = Token.NoToken; op = BinaryExpr.Opcode.Add/*(dummy)*/; .)
+ ( "*" (. x = token; op = BinaryExpr.Opcode.Mul; .)
+ | "/" (. x = token; op = BinaryExpr.Opcode.Div; .)
+ | "%" (. x = token; op = BinaryExpr.Opcode.Mod; .)
+ )
+ .
+
+/*------------------------------------------------------------------------*/
+UnaryExpression<out Expression! e>
+= (. Token! x; e = dummyExpr; .)
+ ( "-" (. x = token; .)
+ UnaryExpression<out e> (. e = new BinaryExpr(x, BinaryExpr.Opcode.Sub, new LiteralExpr(x, 0), e); .)
+ | NegOp (. x = token; .)
+ UnaryExpression<out e> (. e = new UnaryExpr(x, UnaryExpr.Opcode.Not, e); .)
+ | SelectExpression<out e>
+ | ConstAtomExpression<out e>
+ )
+ .
+
+NegOp = "!" | '\u00ac'.
+
+ConstAtomExpression<out Expression! e>
+= (. Token! x; int n; List<Expression!>! elements;
+ e = dummyExpr;
+ .)
+ ( "false" (. e = new LiteralExpr(token, false); .)
+ | "true" (. e = new LiteralExpr(token, true); .)
+ | "null" (. e = new LiteralExpr(token); .)
+ | Nat<out n> (. e = new LiteralExpr(token, n); .)
+ | "fresh" (. x = token; .)
+ "(" Expression<out e> ")" (. e = new FreshExpr(x, e); .)
+ | "|" (. x = token; .)
+ Expression<out e> (. e = new UnaryExpr(x, UnaryExpr.Opcode.SeqLength, e); .)
+ "|"
+ /* Note, the following open-curly-brace causes grammar ambiguities that result in two Coco warnings.
+ One of these is the confusion between BlockStmt and AssignStmt, the former starting with an open
+ curly brace and the latter starting with a left-hand side Expression, which syntactically can
+ start with an open curly brace. The other is the confusion between a quantifier's triggers/attributes
+ and the quantifier's body. The disamiguation I've chosen involves giving priority to BlockStmt
+ (since no semantically legal AssignStmt can have a set constructor as its left-hand side) and to
+ triggers/attributes (which, unfortunately, changes what programs are syntactically allowed, but there
+ is a simple workaround, which is for a user to put parentheses around any quantifier body that begins
+ with a set constructor.
+ */
+ | "{" (. x = token; elements = new List<Expression!>(); .)
+ [ Expressions<elements> ] (. e = new SetDisplayExpr(x, elements); .)
+ "}"
+ | "[" (. x = token; elements = new List<Expression!>(); .)
+ [ Expressions<elements> ] (. e = new SeqDisplayExpr(x, elements); .)
+ "]"
+ )
+ .
+
+/*------------------------------------------------------------------------*/
+
+/* returns one of:
+ -- IdentifierExpr
+ -- FunctionCallExpr
+ -- FieldSelectExpr
+*/
+CallStmtSubExpr<out Expression! e>
+= (. e = dummyExpr; .)
+ ( IdentOrFuncExpression<out e>
+ | ObjectExpression<out e>
+ SelectOrCallSuffix<ref e>
+ )
+ { SelectOrCallSuffix<ref e> }
+ .
+
+SelectExpression<out Expression! e>
+= (. Token! id; e = dummyExpr; .)
+ ( IdentOrFuncExpression<out e>
+ | ObjectExpression<out e>
+ )
+ { SelectOrCallSuffix<ref e> }
+ .
+
+IdentOrFuncExpression<out Expression! e>
+= (. Token! id; e = dummyExpr; List<Expression!>! args; .)
+ Ident<out id>
+ [ "(" (. args = new List<Expression!>(); .)
+ [ Expressions<args> ]
+ ")" (. e = new FunctionCallExpr(id, id.val, new ImplicitThisExpr(id), args); .)
+ ] (. if (e == dummyExpr) {
+ if (parseVarScope.Find(id.val) != null) {
+ e = new IdentifierExpr(id, id.val);
+ } else {
+ e = new FieldSelectExpr(id, new ImplicitThisExpr(id), id.val);
+ }
+ }
+ .)
+ .
+
+SelectOrCallSuffix<ref Expression! e>
+= (. Token! id, x; List<Expression!>! args;
+ Expression e0 = null; Expression e1 = null; Expression! ee; bool anyDots = false;
+ bool func = false;
+ .)
+ ( "."
+ Ident<out id>
+ [ "(" (. args = new List<Expression!>(); func = true; .)
+ [ Expressions<args> ]
+ ")" (. e = new FunctionCallExpr(id, id.val, e, args); .)
+ ] (. if (!func) { e = new FieldSelectExpr(id, e, id.val); } .)
+
+ | "[" (. x = token; .)
+ ( Expression<out ee> (. e0 = ee; .)
+ [ ".." (. anyDots = true; .)
+ [ Expression<out ee> (. e1 = ee; .)
+ ]
+ ]
+ | ".." Expression<out ee> (. anyDots = true; e1 = ee; .)
+ ) (. if (!anyDots) {
+ assert e1 == null;
+ e = new SeqSelectExpr(x, true, e, e0, null);
+ } else {
+ assert e0 != null || e1 != null;
+ e = new SeqSelectExpr(x, false, e, e0, e1);
+ }
+ .)
+ "]"
+ )
+ .
+
+/* ObjectExpression represents those expressions E that could possibly be used in E.f
+ or E(...), except Ident. Since the lookahead is just 1, quantifier expressions are also
+ parsed here. The expression returned is never an lvalue.
+*/
+ObjectExpression<out Expression! e>
+= (. Token! x; e = dummyExpr; .)
+ ( "this" (. e = new ThisExpr(token); .)
+ | "old" (. x = token; .)
+ "("
+ Expression<out e>
+ ")" (. e = new OldExpr(x, e); .)
+ | "(" ( QuantifierGuts<out e>
+ | Expression<out e>
+ )
+ ")"
+ )
+ .
+
+/*------------------------------------------------------------------------*/
+
+QuantifierGuts<out Expression! q>
+= (. Token! x = Token.NoToken;
+ bool univ = false;
+ BoundVar! bv;
+ List<BoundVar!> bvars = new List<BoundVar!>();
+ Token! tok; Expr! e; ExprSeq! es;
+ Attributes attrs = null;
+ Triggers trigs = null;
+ Expression! body;
+ .)
+ ( Forall (. x = token; univ = true; .)
+ | Exists (. x = token; .)
+ )
+ (. parseVarScope.PushMarker(); .)
+ IdentTypeOptional<out bv> (. bvars.Add(bv); parseVarScope.Push(bv.Name, bv.Name); .)
+ { ","
+ IdentTypeOptional<out bv> (. bvars.Add(bv); parseVarScope.Push(bv.Name, bv.Name); .)
+ }
+ QSep
+ /* The grammar is ambiguous in how to resolve triggers/attributes versus the expression body.
+ However, the loop generated by Coco for the next two lines of grammar declarations is still
+ fine--it will loop, picking up as many triggers/attributes it can before going on to parse an
+ expression. This seems good, because there's a simple workaround for quantifier bodies that
+ begin with a set constructor: simply put parentheses around the quantifier body. See also
+ the Note in production ConstAtomExpression.
+ */
+ { AttributeOrTrigger<ref attrs, ref trigs> }
+ Expression<out body>
+ (. if (univ) {
+ q = new ForallExpr(x, bvars, body, trigs, attrs);
+ } else {
+ q = new ExistsExpr(x, bvars, body, trigs, attrs);
+ }
+ parseVarScope.PopMarker();
+ .)
+ .
+
+Forall = "forall" | '\u2200'.
+Exists = "exists" | '\u2203'.
+QSep = "::" | '\u2022'.
+
+Expressions<List<Expression!\>! args>
+= (. Expression! e; .)
+ Expression<out e> (. args.Add(e); .)
+ { "," Expression<out e> (. args.Add(e); .)
+ }
+ .
+
+/*------------------------------------------------------------------------*/
+
+Attribute<ref Attributes attrs>
+= "{"
+ AttributeBody<ref attrs>
+ "}"
+ .
+
+AttributeBody<ref Attributes attrs>
+= (. string aName;
+ List<Attributes.Argument!> aArgs = new List<Attributes.Argument!>();
+ Attributes.Argument! aArg;
+ .)
+ ":" ident (. aName = token.val; .)
+ [ AttributeArg<out aArg> (. aArgs.Add(aArg); .)
+ { "," AttributeArg<out aArg> (. aArgs.Add(aArg); .)
+ }
+ ] (. attrs = new Attributes(aName, aArgs, attrs); .)
+ .
+
+AttributeArg<out Attributes.Argument! arg>
+= (. Expression! e; arg = dummyAttrArg; .)
+ ( string (. arg = new Attributes.Argument(token.val.Substring(1, token.val.Length-2)); .)
+ | Expression<out e> (. arg = new Attributes.Argument(e); .)
+ )
+ .
+
+AttributeOrTrigger<ref Attributes attrs, ref Triggers trigs>
+= (. List<Expression!> es = new List<Expression!>();
+ .)
+ "{"
+ ( AttributeBody<ref attrs>
+ | (. es = new List<Expression!>(); .)
+ Expressions<es> (. trigs = new Triggers(es, trigs); .)
+ )
+ "}"
+ .
+
+/*------------------------------------------------------------------------*/
+
+Ident<out Token! x>
+=
+ ident (. x = token; .)
+ .
+
+Nat<out int n>
+=
+ digits
+ (. try {
+ n = System.Convert.ToInt32(token.val);
+ } catch (System.FormatException) {
+ SemErr("incorrectly formatted number");
+ n = 0;
+ }
+ .)
+ .
+
+END Dafny.
diff --git a/Source/Dafny/DafnyAst.ssc b/Source/Dafny/DafnyAst.ssc
new file mode 100644
index 00000000..8f6821dd
--- /dev/null
+++ b/Source/Dafny/DafnyAst.ssc
@@ -0,0 +1,1049 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using System;
+using System.Collections.Generic;
+using Microsoft.Contracts;
+
+namespace Microsoft.Dafny
+{
+ public class Program {
+ public readonly string! Name;
+ public readonly List<ClassDecl!>! Classes;
+ public Program(string! name, [Captured] List<ClassDecl!>! classes) {
+ Name = name;
+ Classes = classes;
+ }
+ }
+
+ public class Attributes {
+ public readonly string! Name;
+ /*Frozen*/ public readonly List<Argument!>! Args;
+ public readonly Attributes Prev;
+
+ public Attributes(string! name, [Captured] List<Argument!>! args, Attributes prev)
+ {
+ Name = name;
+ Args = args;
+ Prev = prev;
+ }
+
+ public class Argument {
+ public readonly string S;
+ public readonly Expression E;
+ invariant (S == null) != (E == null);
+
+ public Argument(string! s) {
+ S = s;
+ }
+ public Argument(Expression! e) {
+ E = e;
+ }
+ }
+ }
+
+ // ------------------------------------------------------------------------------------------------------
+
+ public abstract class Type {
+ public static readonly BoolType! Bool = new BoolType();
+ public static readonly IntType! Int = new IntType();
+ /// <summary>
+ /// Used in error situations in order to reduce further error messages.
+ /// </summary>
+ [Pure(false)]
+ public static Type! Flexible {
+ get { return new InferredTypeProxy(); }
+ }
+
+ public bool IsRefType {
+ get {
+ if (this is ObjectType) {
+ return true;
+ } else {
+ ClassType ct = this as ClassType;
+ return ct != null && ct.ResolvedParam == null;
+ }
+ }
+ }
+ public bool IsTypeParameter {
+ get
+ ensures result ==> this is ClassType && ((ClassType)this).ResolvedParam != null;
+ {
+ ClassType ct = this as ClassType;
+ return ct != null && ct.ResolvedParam != null;
+ }
+ }
+ }
+
+ public abstract class BasicType : Type {
+ }
+
+ public class BoolType : BasicType {
+ [Pure] public override string! ToString() {
+ return "bool";
+ }
+ }
+
+ public class IntType : BasicType {
+ [Pure] public override string! ToString() {
+ return "int";
+ }
+ }
+
+ public class ObjectType : BasicType {
+ [Pure] public override string! ToString() {
+ return "object";
+ }
+ }
+
+ public abstract class CollectionType : Type {
+ public readonly Type! Arg;
+ public CollectionType(Type! arg) {
+ this.Arg = arg;
+ }
+ }
+
+ public class SetType : CollectionType {
+ public SetType(Type! arg) {
+ base(arg);
+ }
+ [Pure] public override string! ToString() {
+ assume Arg.IsPeerConsistent;
+ return "set<" + Arg + ">";
+ }
+ }
+
+ public class SeqType : CollectionType {
+ public SeqType(Type! arg) {
+ base(arg);
+ }
+ [Pure] public override string! ToString() {
+ assume Arg.IsPeerConsistent;
+ return "seq<" + Arg + ">";
+ }
+ }
+
+ public class ClassType : Type {
+ public readonly Token! tok;
+ public readonly string! Name;
+ [Rep] public readonly List<Type!>! TypeArgs;
+
+ public ClassDecl ResolvedClass; // filled in by resolution, if Name denotes a class and TypeArgs match the type parameters of that class
+ public TypeParameter ResolvedParam; // filled in by resolution, if Name denotes an enclosing type parameter and TypeArgs is the empty list
+
+ public ClassType(Token! tok, string! name, [Captured] List<Type!>! typeArgs) {
+ this.tok = tok;
+ this.Name = name;
+ this.TypeArgs = typeArgs;
+ }
+
+ /// <summary>
+ /// This constructor constructs a resolved class type
+ /// </summary>
+ public ClassType(Token! tok, string! name, ClassDecl! cd, [Captured] List<Type!>! typeArgs) {
+ this.tok = tok;
+ this.Name = name;
+ this.TypeArgs = typeArgs;
+ this.ResolvedClass = cd;
+ }
+
+ /// <summary>
+ /// This constructor constructs a resolved type parameter
+ /// </summary>
+ public ClassType(Token! tok, string! name, TypeParameter! tp) {
+ this.tok = tok;
+ this.Name = name;
+ this.TypeArgs = new List<Type!>();
+ this.ResolvedParam = tp;
+ }
+
+ /// <summary>
+ /// If type denotes a resolved class type, then return that class type.
+ /// Otherwise, return null.
+ /// </summary>
+ public static ClassType DenotesClass(Type! type)
+ ensures result != null ==> result.ResolvedClass != null;
+ {
+ while (true)
+ invariant type.IsPeerConsistent;
+ {
+ TypeProxy pt = type as TypeProxy;
+ if (pt != null && pt.T != null) {
+ type = pt.T;
+ assume type.IsPeerConsistent;
+ } else {
+ break;
+ }
+ }
+ ClassType ct = type as ClassType;
+ if (ct != null && ct.ResolvedClass != null) {
+ return ct;
+ } else {
+ return null;
+ }
+ }
+
+ [Pure] public override string! ToString() {
+ string s = Name;
+ if (TypeArgs.Count != 0) {
+ string sep = "<";
+ foreach (Type t in TypeArgs) {
+ assume t.IsPeerConsistent;
+ s += sep + t;
+ sep = ",";
+ }
+ s += ">";
+ }
+ return s;
+ }
+ }
+
+ public abstract class TypeProxy : Type {
+ public Type T; // filled in during resolution
+ internal TypeProxy() { }
+
+ [Pure] public override string! ToString() {
+ assume T == null || T.IsPeerConsistent;
+ return T == null ? "?" : T.ToString();
+ }
+ }
+
+ public abstract class UnrestrictedTypeProxy : TypeProxy { }
+
+ /// <summary>
+ /// This proxy stands for any type.
+ /// </summary>
+ public class InferredTypeProxy : UnrestrictedTypeProxy {
+ }
+
+ /// <summary>
+ /// This proxy stands for any type, but it originates from an instantiated type parameter.
+ /// </summary>
+ public class ParamTypeProxy : UnrestrictedTypeProxy {
+ TypeParameter! orig;
+ public ParamTypeProxy(TypeParameter! orig) {
+ this.orig = orig;
+ }
+ }
+
+ public abstract class RestrictedTypeProxy : TypeProxy {
+ /// <summary>
+ /// The OrderID is used to simplify the unification code. Each restricted type proxy should use its
+ /// own OrderID.
+ /// </summary>
+ public abstract int OrderID { get; }
+ }
+
+ /// <summary>
+ /// This proxy stands for object or any class type.
+ /// </summary>
+ public class ObjectTypeProxy : RestrictedTypeProxy {
+ public override int OrderID { get { return 0; } }
+ }
+
+ /// <summary>
+ /// This proxy stands for object or any class type or a set or sequence of object or a class type.
+ /// </summary>
+ public class ObjectsTypeProxy : RestrictedTypeProxy {
+ public override int OrderID { get { return 1; } }
+ }
+
+ /// <summary>
+ /// This proxy stands for either:
+ /// set(Arg) or seq(Arg)
+ /// </summary>
+ public class CollectionTypeProxy : RestrictedTypeProxy {
+ public readonly Type! Arg;
+ public CollectionTypeProxy(Type! arg) {
+ Arg = arg;
+ }
+ public override int OrderID { get { return 2; } }
+ }
+
+ /// <summary>
+ /// This proxy stands for either:
+ /// int or set or seq
+ /// if AllowSeq, or:
+ /// int or set
+ /// if !AllowSeq.
+ /// </summary>
+ public class OperationTypeProxy : RestrictedTypeProxy {
+ public readonly bool AllowSeq;
+ public OperationTypeProxy(bool allowSeq) {
+ AllowSeq = allowSeq;
+ }
+ public override int OrderID { get { return 3; } }
+ }
+
+ // ------------------------------------------------------------------------------------------------------
+
+ public abstract class Declaration {
+ public Token! tok;
+ public readonly string! Name;
+ public readonly Attributes Attributes;
+
+ public Declaration(Token! tok, string! name, Attributes attributes) {
+ this.tok = tok;
+ this.Name = name;
+ this.Attributes = attributes;
+ }
+ }
+
+ public class TypeParameter : Declaration {
+ public interface ParentType { }
+ [Peer] ParentType parent;
+ public ParentType Parent {
+ get {
+ return parent;
+ }
+ [param: Captured]
+ set
+ requires Parent == null; // set it only once
+ requires value != null;
+ // BUGBUG: The following line is a workaround to tell the verifier that 'value' is not of an Immutable type.
+ // A proper solution would be to be able to express that in the program (in a specification or attribute) or
+ // to be able to declare 'parent' as [PeerOrImmutable].
+ requires value is ClassDecl || value is Function || value is Method;
+ modifies parent;
+ {
+ parent = value;
+ }
+ }
+ public TypeParameter(Token! tok, string! name) {
+ base(tok, name, null);
+ }
+ }
+
+ public class ClassDecl : Declaration, TypeParameter.ParentType {
+ public List<TypeParameter!>! TypeArgs;
+ public List<MemberDecl!>! Members;
+
+ public ClassDecl(Token! tok, string! name, List<TypeParameter!>! typeArgs, [Captured] List<MemberDecl!>! members, Attributes attributes) {
+ TypeArgs = typeArgs;
+ Members = members;
+ base(tok, name, attributes);
+ }
+ }
+
+ public abstract class MemberDecl : Declaration {
+ public ClassDecl EnclosingClass; // filled in during resolution
+
+ public MemberDecl(Token! tok, string! name, Attributes attributes) {
+ base(tok, name, attributes);
+ }
+ /// <summary>
+ /// Returns className+"."+memberName. Available only after resolution.
+ /// </summary>
+ public string! FullName {
+ get
+ requires EnclosingClass != null;
+ {
+ return EnclosingClass.Name + "." + Name;
+ }
+ }
+ }
+
+ public class Field : MemberDecl {
+ public readonly Type! Type;
+
+ public Field(Token! tok, string! name, Type! type, Attributes attributes) {
+ Type = type;
+ base(tok, name, attributes);
+ }
+ }
+
+ public interface IVariable {
+ string! Name { get; }
+ string! UniqueName { get; }
+ Type! Type { get; }
+ bool IsMutable { get; }
+ }
+
+ public abstract class NonglobalVariable : IVariable {
+ public readonly Token! tok;
+ readonly string! name;
+ public string! Name { get { return name; } }
+ readonly int varId = varIdCount++;
+ public string! UniqueName { get { return name + "#" + varId; } }
+ Type! type;
+ [Pure(false)] // TODO: if Type gets the status of [Frozen], then this attribute is not needed
+ public Type! Type { get {
+ assume type.IsPeerConsistent;
+ while (true)
+ invariant type.IsPeerConsistent;
+ {
+ TypeProxy t = type as TypeProxy;
+ if (t != null && t.T != null) {
+ type = t.T;
+ assume type.IsPeerConsistent;
+ } else {
+ return type;
+ }
+ }
+ } }
+ public abstract bool IsMutable { get; }
+
+ public NonglobalVariable(Token! tok, string! name, Type! type) {
+ this.tok = tok;
+ this.name = name;
+ this.type = type;
+ }
+
+ internal static int varIdCount; // this varIdCount is used for both NonglobalVariable's and VarDecl's.
+ }
+
+ public class Formal : NonglobalVariable {
+ public readonly bool InParam; // true to in-parameter, false for out-parameter
+ public override bool IsMutable { get { return !InParam; } }
+
+ public Formal(Token! tok, string! name, Type! type, bool inParam) {
+ InParam = inParam;
+ base(tok, name, type);
+ }
+ }
+
+ public class BoundVar : NonglobalVariable {
+ public override bool IsMutable { get { return false; } }
+
+ public BoundVar(Token! tok, string! name, Type! type) {
+ base(tok, name, type);
+ }
+ }
+
+ public class Function : MemberDecl, TypeParameter.ParentType {
+ public readonly bool Use;
+ public readonly List<TypeParameter!>! TypeArgs;
+ public readonly List<Formal!>! Formals;
+ public readonly Type! ResultType;
+ public readonly List<Expression!>! Req;
+ public readonly List<Expression!>! Reads;
+ public readonly Expression Body; // an extended expression
+
+ public Function(Token! tok, string! name, bool use, [Captured] List<TypeParameter!>! typeArgs, [Captured] List<Formal!>! formals, Type! resultType,
+ List<Expression!>! req, List<Expression!>! reads, Expression body, Attributes attributes) {
+ this.Use = use;
+ this.TypeArgs = typeArgs;
+ this.Formals = formals;
+ this.ResultType = resultType;
+ this.Req = req;
+ this.Reads = reads;
+ this.Body = body;
+ base(tok, name, attributes);
+ }
+ }
+
+ public class Method : MemberDecl, TypeParameter.ParentType {
+ public readonly List<TypeParameter!>! TypeArgs;
+ public readonly List<Formal!>! Ins;
+ public readonly List<Formal!>! Outs;
+ public readonly List<MaybeFreeExpression!>! Req;
+ public readonly List<Expression!>! Mod;
+ public readonly List<MaybeFreeExpression!>! Ens;
+ public readonly Statement Body;
+
+ public Method(Token! tok, string! name,
+ [Captured] List<TypeParameter!>! typeArgs,
+ [Captured] List<Formal!>! ins, [Captured] List<Formal!>! outs,
+ [Captured] List<MaybeFreeExpression!>! req, [Captured] List<Expression!>! mod, [Captured] List<MaybeFreeExpression!>! ens,
+ [Captured] Statement body,
+ Attributes attributes) {
+ this.TypeArgs = typeArgs;
+ this.Ins = ins;
+ this.Outs = outs;
+ this.Req = req;
+ this.Mod = mod;
+ this.Ens = ens;
+ this.Body = body;
+ base(tok, name, attributes);
+ }
+ }
+
+ // ------------------------------------------------------------------------------------------------------
+
+ public abstract class Statement {
+ public readonly Token! Tok;
+ public Statement(Token! tok) {
+ this.Tok = tok;
+ }
+ }
+
+ public abstract class PredicateStmt : Statement {
+ [Peer] public readonly Expression! Expr;
+ [Captured]
+ public PredicateStmt(Token! tok, Expression! expr)
+ ensures Owner.Same(this, expr);
+ {
+ base(tok);
+ Owner.AssignSame(this, expr);
+ this.Expr = expr;
+ }
+ }
+
+ public class AssertStmt : PredicateStmt {
+ [Captured]
+ public AssertStmt(Token! tok, Expression! expr)
+ ensures Owner.Same(this, expr);
+ {
+ base(tok, expr);
+ }
+ }
+
+ public class AssumeStmt : PredicateStmt {
+ [Captured]
+ public AssumeStmt(Token! tok, Expression! expr)
+ ensures Owner.Same(this, expr);
+ {
+ base(tok, expr);
+ }
+ }
+
+ public class UseStmt : PredicateStmt {
+ [Captured]
+ public UseStmt(Token! tok, Expression! expr)
+ ensures Owner.Same(this, expr);
+ {
+ base(tok, expr);
+ }
+ [Peer] private FunctionCallExpr fce;
+ /// <summary>
+ /// This method assumes the statement has been successfully resolved.
+ /// </summary>
+ [Pure(false)]
+ public FunctionCallExpr! FunctionCallExpr {
+ get {
+ if (fce == null) {
+ Expression expr = Expr;
+ while (true)
+ invariant Owner.Same(this, expr);
+ {
+ if (expr is OldExpr) {
+ expr = ((OldExpr)expr).E;
+ } else {
+ break;
+ }
+ }
+ assume expr is FunctionCallExpr;
+ fce = (FunctionCallExpr)expr;
+ }
+ return fce;
+ }
+ }
+ public bool EvalInOld {
+ get {
+ return Expr is OldExpr;
+ }
+ }
+ }
+
+ public class LabelStmt : Statement {
+ public readonly string! Label;
+ public LabelStmt(Token! tok, string! label) {
+ this.Label = label;
+ base(tok);
+ }
+ }
+
+ public class BreakStmt : Statement {
+ public readonly string TargetLabel;
+ public Statement TargetStmt; // filled in during resolution
+
+ public BreakStmt(Token! tok, string targetLabel) {
+ this.TargetLabel = targetLabel;
+ base(tok);
+ }
+ }
+
+ public class ReturnStmt : Statement {
+ public ReturnStmt(Token! tok) {
+ base(tok);
+ }
+ }
+
+ public abstract class AssignmentRhs {
+ internal AssignmentRhs() { }
+ }
+
+ public abstract class DeterminedAssignmentRhs : AssignmentRhs {
+ internal DeterminedAssignmentRhs() { }
+ }
+
+ public class ExprRhs : DeterminedAssignmentRhs {
+ public readonly Expression! Expr;
+ public ExprRhs(Expression! expr) {
+ Expr = expr;
+ }
+ }
+
+ public class TypeRhs : DeterminedAssignmentRhs {
+ public readonly Type! Type;
+ public TypeRhs(Type! type) {
+ Type = type;
+ }
+ }
+
+ public class HavocRhs : AssignmentRhs {
+ }
+
+ public class AssignStmt : Statement {
+ public readonly Expression! Lhs;
+ public readonly AssignmentRhs! Rhs;
+ public AssignStmt(Token! tok, Expression! lhs, Expression! rhs) { // ordinary assignment statement
+ this.Lhs = lhs;
+ this.Rhs = new ExprRhs(rhs);
+ base(tok);
+ }
+ public AssignStmt(Token! tok, Expression! lhs, Type! type) { // alloc statement
+ this.Lhs = lhs;
+ this.Rhs = new TypeRhs(type);
+ base(tok);
+ }
+ public AssignStmt(Token! tok, Expression! lhs) { // havoc
+ this.Lhs = lhs;
+ this.Rhs = new HavocRhs();
+ base(tok);
+ }
+ }
+
+ public class VarDecl : Statement, IVariable {
+ readonly string! name;
+ public string! Name { get { return name; } }
+ readonly int varId = NonglobalVariable.varIdCount++;
+ public string! UniqueName { get { return name + "#" + varId; } }
+ public readonly Type OptionalType; // this is the type mentioned in the declaration, if any
+ internal Type type; // this is the declared or inferred type of the variable; it is non-null after resolution (even if resolution fails)
+ [Pure(false)]
+ public Type! Type { get {
+ assume type != null; /* we assume object has been resolved */
+ assume type.IsPeerConsistent;
+ while (true)
+ invariant type != null && type.IsPeerConsistent;
+ {
+ TypeProxy t = type as TypeProxy;
+ if (t != null && t.T != null) {
+ type = t.T;
+ assume type.IsPeerConsistent;
+ } else {
+ return type;
+ }
+ }
+ } }
+ public bool IsMutable { get { return true; } }
+
+ public readonly DeterminedAssignmentRhs Rhs;
+ invariant OptionalType != null || Rhs != null;
+
+ public VarDecl(Token! tok, string! name, Type type, DeterminedAssignmentRhs rhs)
+ requires type != null || rhs != null;
+ {
+ this.name = name;
+ this.OptionalType = type;
+ this.Rhs = rhs;
+ base(tok);
+ }
+ }
+
+ public class CallStmt : Statement {
+ public readonly List<IdentifierExpr!>! Lhs;
+ public readonly Expression! Receiver;
+ public readonly string! MethodName;
+ public readonly List<Expression!>! Args;
+ public Method Method; // filled in by resolution
+
+ public CallStmt(Token! tok, List<IdentifierExpr!>! lhs, Expression! receiver, string! methodName, List<Expression!>! args) {
+ this.Lhs = lhs;
+ this.Receiver = receiver;
+ this.MethodName = methodName;
+ this.Args = args;
+ base(tok);
+ }
+ }
+
+ public class BlockStmt : Statement {
+ public readonly List<Statement!>! Body;
+ public BlockStmt(Token! tok, [Captured] List<Statement!>! body) {
+ this.Body = body;
+ base(tok);
+ }
+ }
+
+ public class IfStmt : Statement {
+ public readonly Expression Guard;
+ public readonly Statement! Thn;
+ public readonly Statement Els;
+ invariant Els == null || Els is BlockStmt || Els is IfStmt;
+
+ public IfStmt(Token! tok, Expression guard, Statement! thn, Statement els)
+ requires els == null || els is BlockStmt || els is IfStmt;
+ {
+ this.Guard = guard;
+ this.Thn = thn;
+ this.Els = els;
+ base(tok);
+ }
+ }
+
+ public class WhileStmt : Statement {
+ public readonly Expression Guard;
+ public readonly List<MaybeFreeExpression!>! Invariants;
+ public readonly List<Expression!>! Decreases;
+ public readonly Statement! Body;
+
+ public WhileStmt(Token! tok, Expression guard,
+ List<MaybeFreeExpression!>! invariants, List<Expression!>! decreases,
+ Statement! body) {
+ this.Guard = guard;
+ this.Invariants = invariants;
+ this.Decreases = decreases;
+ this.Body = body;
+ base(tok);
+ }
+ }
+
+ public class ForeachStmt : Statement {
+ public readonly BoundVar! BoundVar;
+ public readonly Expression! Collection;
+ public readonly Expression! Range;
+ public readonly List<PredicateStmt!>! BodyPrefix;
+ public readonly AssignStmt BodyAssign;
+
+ public ForeachStmt(Token! tok, BoundVar! boundVar, Expression! collection, Expression! range, List<PredicateStmt!>! bodyPrefix, AssignStmt bodyAssign) {
+ this.BoundVar = boundVar;
+ this.Collection = collection;
+ this.Range = range;
+ this.BodyPrefix = bodyPrefix;
+ this.BodyAssign = bodyAssign;
+ base(tok);
+ }
+ }
+
+ // ------------------------------------------------------------------------------------------------------
+
+ public abstract class Expression {
+ public readonly Token! tok;
+ protected Type type;
+ public Type Type { // filled in during resolution
+ [Verify(false)] // TODO: how do we allow Type.get to modify type and still be [Pure]?
+ [Additive] // validity of proper subclasses is not required
+ get
+ ensures type == null ==> result == null; // useful in conjunction with postcondition of constructor
+ {
+ while (true) {
+ TypeProxy t = type as TypeProxy;
+ if (t != null && t.T != null) {
+ type = t.T;
+ } else {
+ assume type == null || type.IsPeerConsistent;
+ return type;
+ }
+ }
+ }
+ [NoDefaultContract] // no particular validity of 'this' is required, except that it not be committed
+ set
+ requires this.IsValid;
+ requires Type == null; // set it only once
+ requires value != null && value.IsPeerConsistent;
+ modifies type;
+ {
+ type = value;
+ while (true) {
+ TypeProxy t = type as TypeProxy;
+ if (t != null && t.T != null) {
+ type = t.T;
+ } else {
+ return;
+ }
+ }
+ }
+ }
+
+ public Expression(Token! tok)
+ ensures type == null; // we would have liked to have written Type==null, but that's not admissible or provable
+ {
+ this.tok = tok;
+ }
+ }
+
+ public class LiteralExpr : Expression {
+ public readonly object Value;
+
+ public static bool IsTrue(Expression! e) {
+ if (e is LiteralExpr) {
+ LiteralExpr le = (LiteralExpr)e;
+ return le.Value is bool && (bool)le.Value;
+ } else {
+ return false;
+ }
+ }
+
+ public LiteralExpr(Token! tok) { // represents the Dafny literal "null"
+ this.Value = null;
+ base(tok);
+ }
+
+ public LiteralExpr(Token! tok, int n)
+ requires 0 <= n;
+ {
+ this.Value = n;
+ base(tok);
+ }
+
+ public LiteralExpr(Token! tok, bool b) {
+ this.Value = b;
+ base(tok);
+ }
+ }
+
+ public class ThisExpr : Expression {
+ public ThisExpr(Token! tok) {
+ base(tok);
+ }
+ }
+
+ public class ImplicitThisExpr : ThisExpr {
+ public ImplicitThisExpr(Token! tok) {
+ base(tok);
+ }
+ }
+
+ public class IdentifierExpr : Expression {
+ public readonly string! Name;
+ public IVariable Var; // filled in by resolution
+
+ public IdentifierExpr(Token! tok, string! name) {
+ Name = name;
+ base(tok);
+ }
+ }
+
+ public abstract class DisplayExpression : Expression {
+ public readonly List<Expression!>! Elements;
+ public DisplayExpression(Token! tok, List<Expression!>! elements) {
+ Elements = elements;
+ base(tok);
+ }
+ }
+
+ public class SetDisplayExpr : DisplayExpression {
+ public SetDisplayExpr(Token! tok, List<Expression!>! elements) {
+ base(tok, elements);
+ }
+ }
+
+ public class SeqDisplayExpr : DisplayExpression {
+ public SeqDisplayExpr(Token! tok, List<Expression!>! elements) {
+ base(tok, elements);
+ }
+ }
+
+ public class FieldSelectExpr : Expression {
+ public readonly Expression! Obj;
+ public readonly string! FieldName;
+ public Field Field; // filled in by resolution
+
+ public FieldSelectExpr(Token! tok, Expression! obj, string! fieldName) {
+ this.Obj = obj;
+ this.FieldName = fieldName;
+ base(tok);
+ }
+ }
+
+ public class SeqSelectExpr : Expression {
+ public readonly bool SelectOne; // false means select a range
+ public readonly Expression! Seq;
+ public readonly Expression E0;
+ public readonly Expression E1;
+ invariant SelectOne ==> E1 == null;
+ invariant E0 != null || E1 != null;
+
+ public SeqSelectExpr(Token! tok, bool selectOne, Expression! seq, Expression e0, Expression e1)
+ requires selectOne ==> e1 == null;
+ requires e0 != null || e1 != null;
+ {
+ SelectOne = selectOne;
+ Seq = seq;
+ E0 = e0;
+ E1 = e1;
+ base(tok);
+ }
+ }
+
+ public class FunctionCallExpr : Expression {
+ public readonly string! Name;
+ [Peer] public readonly Expression! Receiver;
+ [Peer] public readonly List<Expression!>! Args;
+ public Function Function; // filled in by resolution
+
+ [Captured]
+ public FunctionCallExpr(Token! tok, string! fn, Expression! receiver, [Captured] List<Expression!>! args)
+ ensures type == null;
+ ensures Owner.Same(this, receiver);
+ {
+ base(tok);
+ this.Name = fn;
+ Owner.AssignSame(this, receiver);
+ this.Receiver = receiver;
+ this.Args = args;
+ }
+ }
+
+ /// <summary>
+ /// UseExpr's are used only temporarily during translation.
+ /// </summary>
+ public class UseExpr : FunctionCallExpr {
+ [NotDelayed] [Captured]
+ public UseExpr(FunctionCallExpr! fce)
+ requires fce.Function != null && fce.Function.Use;
+ {
+ base(fce.tok, fce.Name, fce.Receiver, new List<Expression!>(fce.Args));
+ this.Function = fce.Function;
+ assume Type.Bool.IsPeerConsistent; // This would follow from BoolType being an Immutable type, or from Type.Bool being [Frozen]
+ this.Type = Type.Bool;
+ }
+ }
+
+ public class OldExpr : Expression {
+ [Peer] public readonly Expression! E;
+ [Captured]
+ public OldExpr(Token! tok, Expression! expr) {
+ base(tok);
+ Owner.AssignSame(this, expr);
+ E = expr;
+ }
+ }
+
+ public class FreshExpr : Expression {
+ public readonly Expression! E;
+ public FreshExpr(Token! tok, Expression! expr) {
+ E = expr;
+ base(tok);
+ }
+ }
+
+ public class UnaryExpr : Expression {
+ public enum Opcode { Not, SeqLength }
+ public readonly Opcode Op;
+ public readonly Expression! E;
+
+ public UnaryExpr(Token! tok, Opcode op, Expression! e) {
+ this.Op = op;
+ this.E = e;
+ base(tok);
+ }
+ }
+
+ public class BinaryExpr : Expression {
+ public enum Opcode { Iff, Imp, And, Or,
+ Eq, Neq, Lt, Le, Ge, Gt,
+ Disjoint, In,
+ Add, Sub, Mul, Div, Mod }
+ public readonly Opcode Op;
+ public enum ResolvedOpcode {
+ // logical operators
+ Iff, Imp, And, Or,
+ // non-collection types
+ EqCommon, NeqCommon,
+ // integers
+ Lt, Le, Ge, Gt, Add, Sub, Mul, Div, Mod,
+ // sets
+ SetEq, SetNeq, ProperSubset, Subset, Superset, ProperSuperset, Disjoint, InSet,
+ Union, Intersection, SetDifference,
+ // sequences
+ SeqEq, SeqNeq, ProperPrefix, Prefix, Concat, InSeq
+ }
+ public ResolvedOpcode ResolvedOp; // filled in by resolution
+
+ public static string! OpcodeString(Opcode op) {
+ switch (op) {
+ case Opcode.Iff: return "<==>";
+ case Opcode.Imp: return "==>";
+ case Opcode.And: return "&&";
+ case Opcode.Or: return "||";
+ case Opcode.Eq: return "==";
+ case Opcode.Lt: return "<";
+ case Opcode.Gt: return ">";
+ case Opcode.Le: return "<=";
+ case Opcode.Ge: return ">=";
+ case Opcode.Neq: return "!=";
+ case Opcode.Disjoint: return "!!";
+ case Opcode.In: return "in";
+ case Opcode.Add: return "+";
+ case Opcode.Sub: return "-";
+ case Opcode.Mul: return "*";
+ case Opcode.Div: return "/";
+ case Opcode.Mod: return "%";
+ default:
+ assert false; // unexpected operator
+ }
+ }
+ public readonly Expression! E0;
+ public readonly Expression! E1;
+
+ public BinaryExpr(Token! tok, Opcode op, Expression! e0, Expression! e1) {
+ this.Op = op;
+ this.E0 = e0;
+ this.E1 = e1;
+ base(tok);
+ }
+ }
+
+ public abstract class QuantifierExpr : Expression {
+ public readonly List<BoundVar!>! BoundVars;
+ public readonly Expression! Body;
+ public readonly Triggers Trigs;
+ public readonly Attributes Attributes;
+
+ public QuantifierExpr(Token! tok, List<BoundVar!>! bvars, Expression! body, Triggers trigs, Attributes attrs) {
+ this.BoundVars = bvars;
+ this.Body = body;
+ this.Trigs = trigs;
+ this.Attributes = attrs;
+ base(tok);
+ }
+ }
+
+ public class Triggers {
+ public readonly List<Expression!>! Terms;
+ public readonly Triggers Prev;
+
+ public Triggers(List<Expression!>! terms, Triggers prev) {
+ this.Terms = terms;
+ this.Prev = prev;
+ }
+ }
+
+ public class ForallExpr : QuantifierExpr {
+ public ForallExpr(Token! tok, List<BoundVar!>! bvars, Expression! body, Triggers trig, Attributes attrs) {
+ base(tok, bvars, body, trig, attrs);
+ }
+ }
+
+ public class ExistsExpr : QuantifierExpr {
+ public ExistsExpr(Token! tok, List<BoundVar!>! bvars, Expression! body, Triggers trig, Attributes attrs) {
+ base(tok, bvars, body, trig, attrs);
+ }
+ }
+
+ public class ITEExpr : Expression { // an ITEExpr is an "extended expression" and is only allowed in certain places
+ public readonly Expression! Test;
+ public readonly Expression! Thn;
+ public readonly Expression! Els;
+
+ public ITEExpr(Token! tok, Expression! test, Expression! thn, Expression! els) {
+ this.Test = test;
+ this.Thn = thn;
+ this.Els = els;
+ base(tok);
+ }
+ }
+
+ public class MaybeFreeExpression {
+ public readonly Expression! E;
+ public readonly bool IsFree;
+ public MaybeFreeExpression(Expression! e, bool isFree) {
+ E = e;
+ IsFree = isFree;
+ }
+ }
+}
diff --git a/Source/Dafny/DafnyMain.ssc b/Source/Dafny/DafnyMain.ssc
new file mode 100644
index 00000000..84e366e2
--- /dev/null
+++ b/Source/Dafny/DafnyMain.ssc
@@ -0,0 +1,73 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using System;
+using System.IO;
+using System.Collections.Generic;
+using Microsoft.Contracts;
+using Bpl = Microsoft.Boogie;
+
+namespace Microsoft.Dafny {
+ public class Main {
+ /// <summary>
+ /// Returns null on success, or an error string otherwise.
+ /// </summary>
+ public static string ParseCheck(List<string!>! fileNames, string! programName, out Program program)
+ modifies Bpl.CommandLineOptions.Clo.XmlSink.*;
+ {
+ program = null;
+ Dafny.Errors.count = 0;
+ List<ClassDecl!> classes = new List<ClassDecl!>();
+ foreach (string! dafnyFileName in fileNames){
+ if (Bpl.CommandLineOptions.Clo.XmlSink != null && Bpl.CommandLineOptions.Clo.XmlSink.IsOpen) {
+ Bpl.CommandLineOptions.Clo.XmlSink.WriteFileFragment(dafnyFileName);
+ }
+ if (Bpl.CommandLineOptions.Clo.Trace)
+ {
+ Console.WriteLine("Parsing " + dafnyFileName);
+ }
+
+ int errorCount;
+ try
+ {
+ errorCount = Dafny.Parser.Parse(dafnyFileName, classes);
+ if (errorCount != 0)
+ {
+ return string.Format("{0} parse errors detected in {1}", Dafny.Errors.count, dafnyFileName);
+ }
+ }
+ catch (IOException e)
+ {
+ return string.Format("Error opening file \"{0}\": {1}", dafnyFileName, e.Message);
+ }
+ }
+
+ program = new Program(programName, classes);
+
+ if (Bpl.CommandLineOptions.Clo.DafnyPrintFile != null) {
+ string filename = Bpl.CommandLineOptions.Clo.DafnyPrintFile;
+ if (filename == "-") {
+ Printer pr = new Printer(System.Console.Out);
+ pr.PrintProgram(program);
+ } else {
+ using (TextWriter writer = new System.IO.StreamWriter(filename)) {
+ Printer pr = new Printer(writer);
+ pr.PrintProgram(program);
+ }
+ }
+ }
+
+ if (Bpl.CommandLineOptions.Clo.NoResolve) { return null; }
+
+ Dafny.Resolver r = new Dafny.Resolver();
+ r.ResolveProgram(program);
+ if (r.ErrorCount != 0) {
+ return string.Format("{0} resolution/type errors detected in {1}", r.ErrorCount, programName);
+ }
+
+ return null; // success
+ }
+ }
+}
diff --git a/Source/Dafny/DafnyPipeline.sscproj b/Source/Dafny/DafnyPipeline.sscproj
new file mode 100644
index 00000000..38ff8646
--- /dev/null
+++ b/Source/Dafny/DafnyPipeline.sscproj
@@ -0,0 +1,118 @@
+<?xml version="1.0" encoding="utf-8"?>
+<VisualStudioProject>
+ <XEN ProjectType="Local"
+ SchemaVersion="1.0"
+ Name="Dafny"
+ ProjectGuid="dead83c6-1510-4af9-8f7d-c837ddbb2632"
+ >
+ <Build>
+ <Settings ApplicationIcon=""
+ AssemblyName="DafnyPipeline"
+ OutputType="Library"
+ RootNamespace="DafnyPipeline"
+ StartupObject=""
+ StandardLibraryLocation=""
+ TargetPlatform="v2"
+ TargetPlatformLocation=""
+ >
+ <Config Name="Debug"
+ AllowUnsafeBlocks="False"
+ BaseAddress="285212672"
+ CheckForOverflowUnderflow="False"
+ ConfigurationOverrideFile=""
+ DefineConstants="DEBUG;TRACE"
+ DocumentationFile=""
+ DebugSymbols="True"
+ FileAlignment="4096"
+ IncrementalBuild="True"
+ Optimize="False"
+ OutputPath="bin\debug"
+ RegisterForComInterop="False"
+ RemoveIntegerChecks="false"
+ TreatWarningsAsErrors="False"
+ WarningLevel="4"
+ CheckContractAdmissibility="True"
+ CheckPurity="False"
+ />
+ <Config Name="Release"
+ AllowUnsafeBlocks="false"
+ BaseAddress="285212672"
+ CheckForOverflowUnderflow="false"
+ ConfigurationOverrideFile=""
+ DefineConstants="TRACE"
+ DocumentationFile=""
+ DebugSymbols="false"
+ FileAlignment="4096"
+ IncrementalBuild="false"
+ Optimize="true"
+ OutputPath="bin\release"
+ RegisterForComInterop="false"
+ RemoveIntegerChecks="false"
+ TreatWarningsAsErrors="false"
+ WarningLevel="4"
+ CheckContractAdmissibility="True"
+ CheckPurity="False"
+ />
+ </Settings>
+ <References>
+ <Reference Name="System"
+ AssemblyName="System"
+ Private="false"
+ />
+ <Reference Name="System.Data"
+ AssemblyName="System.Data"
+ Private="false"
+ />
+ <Reference Name="System.Xml"
+ AssemblyName="System.Xml"
+ Private="false"
+ />
+ <Reference Name="Core"
+ AssemblyName="Core"
+ Private="false"
+ HintPath="../Core/bin/Debug/Core.dll"
+ />
+ </References>
+ </Build>
+ <Files>
+ <Include>
+ <File RelPath="DafnyAst.ssc"
+ SubType="Code"
+ BuildAction="Compile"
+ />
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="Scanner.ssc"
+ />
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="Parser.ssc"
+ />
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="DafnyMain.ssc"
+ />
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="Printer.ssc"
+ />
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="Resolver.ssc"
+ />
+ <File BuildAction="None"
+ SubType="Content"
+ RelPath="Dafny.atg"
+ />
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="Translator.ssc"
+ />
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="..\version.ssc"
+ />
+ </Include>
+ </Files>
+ </XEN>
+</VisualStudioProject> \ No newline at end of file
diff --git a/Source/Dafny/Makefile b/Source/Dafny/Makefile
new file mode 100644
index 00000000..fd2141b3
--- /dev/null
+++ b/Source/Dafny/Makefile
@@ -0,0 +1,15 @@
+COCO = ..\..\Binaries\Coco.exe
+ASML = ..\..\Binaries\asmlc.boot.exe
+
+# "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
+
+Parser.ssc: Scanner.frame Parser.frame Dafny.atg
+ $(COCO) Dafny.atg
+ copy Parser.cs Parser.ssc
+ copy Scanner.cs Scanner.ssc
+
+clean:
+ rm -f Scanner.ssc Parser.ssc
diff --git a/Source/Dafny/Parser.ssc b/Source/Dafny/Parser.ssc
new file mode 100644
index 00000000..a7c30d2f
--- /dev/null
+++ b/Source/Dafny/Parser.ssc
@@ -0,0 +1,1592 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using System.Collections.Generic;
+using Microsoft.Boogie;
+using Microsoft.Contracts;
+
+namespace Microsoft.Dafny {
+
+public class Parser {
+ const int maxT = 86;
+
+ const bool T = true;
+ const bool x = false;
+ const int minErrDist = 2;
+
+ static Token/*!*/ token; // last recognized token
+ static Token/*!*/ t; // lookahead token
+ static int errDist = minErrDist;
+
+ static List<ClassDecl!>! theClasses = new List<ClassDecl!>();
+
+
+static Expression! dummyExpr = new LiteralExpr(Token.NoToken);
+static Statement! dummyStmt = new ReturnStmt(Token.NoToken);
+static Attributes.Argument! dummyAttrArg = new Attributes.Argument("dummyAttrArg");
+static Scope<string>! parseVarScope = new Scope<string>();
+
+///<summary>
+/// Parses top level declarations from "filename" and appends them to "classes".
+/// Returns the number of parsing errors encountered.
+/// Note: first initialize the Scanner.
+///</summary>
+public static int Parse (string! filename, List<ClassDecl!>! classes) /* throws System.IO.IOException */ {
+ using (System.IO.StreamReader reader = new System.IO.StreamReader(filename)) {
+ BoogiePL.Buffer.Fill(reader);
+ Scanner.Init(filename);
+ return Parse(classes);
+ }
+}
+
+///<summary>
+/// Parses top level declarations and appends them to "classes".
+/// Returns the number of parsing errors encountered.
+/// Note: first initialize the Scanner.
+///</summary>
+public static int Parse (List<ClassDecl!>! classes) {
+ List<ClassDecl!> oldClasses = theClasses;
+ theClasses = classes;
+ Parse();
+ theClasses = oldClasses;
+ return Errors.count;
+}
+
+/*--------------------------------------------------------------------------*/
+
+
+ static void Error(int n) {
+ if (errDist >= minErrDist) Errors.SynErr(n, t.filename, t.line, t.col);
+ errDist = 0;
+ }
+
+ public static void SemErr(string! msg) {
+ if (errDist >= minErrDist) Errors.SemErr(token.filename, token.line, token.col, msg);
+ errDist = 0;
+ }
+
+ public static void SemErr(Token! tok, string! msg) {
+ if (errDist >= minErrDist) Errors.SemErr(tok.filename, tok.line, tok.col, msg);
+ errDist = 0;
+ }
+
+ static void Get() {
+ for (;;) {
+ token = t;
+ t = Scanner.Scan();
+ if (t.kind<=maxT) {errDist++; return;}
+
+ t = token;
+ }
+ }
+
+ static void Expect(int n) {
+ if (t.kind==n) Get(); else Error(n);
+ }
+
+ static bool StartOf(int s) {
+ return set[s, t.kind];
+ }
+
+ static void ExpectWeak(int n, int follow) {
+ if (t.kind == n) Get();
+ else {
+ Error(n);
+ while (!StartOf(follow)) Get();
+ }
+ }
+
+ static bool WeakSeparator(int n, int syFol, int repFol) {
+ bool[] s = new bool[maxT+1];
+ if (t.kind == n) {Get(); return true;}
+ else if (StartOf(repFol)) return false;
+ else {
+ for (int i=0; i <= maxT; i++) {
+ s[i] = set[syFol, i] || set[repFol, i] || set[0, i];
+ }
+ Error(n);
+ while (!s[t.kind]) Get();
+ return StartOf(syFol);
+ }
+ }
+
+ static void Dafny() {
+ ClassDecl! c;
+ while (t.kind == 4) {
+ ClassDecl(out c);
+ theClasses.Add(c);
+ }
+ Expect(0);
+ }
+
+ static void ClassDecl(out ClassDecl! c) {
+ Token! id;
+ Attributes attrs = null;
+ List<TypeParameter!> typeArgs = new List<TypeParameter!>();
+ List<MemberDecl!> members = new List<MemberDecl!>();
+
+ Expect(4);
+ while (t.kind == 5) {
+ Attribute(ref attrs);
+ }
+ Ident(out id);
+ if (t.kind == 11) {
+ GenericParameters(typeArgs);
+ }
+ Expect(5);
+ while (StartOf(1)) {
+ ClassMemberDecl(members);
+ }
+ Expect(6);
+ c = new ClassDecl(id, id.val, typeArgs, members, attrs);
+ }
+
+ static void Attribute(ref Attributes attrs) {
+ Expect(5);
+ AttributeBody(ref attrs);
+ Expect(6);
+ }
+
+ static void Ident(out Token! x) {
+ Expect(1);
+ x = token;
+ }
+
+ static void GenericParameters(List<TypeParameter!>! typeArgs) {
+ Token! id;
+ Expect(11);
+ Ident(out id);
+ typeArgs.Add(new TypeParameter(id, id.val));
+ while (t.kind == 8) {
+ Get();
+ Ident(out id);
+ typeArgs.Add(new TypeParameter(id, id.val));
+ }
+ Expect(12);
+ }
+
+ static void ClassMemberDecl(List<MemberDecl!>! mm) {
+ Method! m;
+ Function! f;
+
+ if (t.kind == 7) {
+ FieldDecl(mm);
+ } else if (t.kind == 27) {
+ FunctionDecl(out f);
+ mm.Add(f);
+ } else if (t.kind == 14) {
+ MethodDecl(out m);
+ mm.Add(m);
+ } else if (t.kind == 13) {
+ FrameDecl();
+ } else Error(87);
+ }
+
+ static void FieldDecl(List<MemberDecl!>! mm) {
+ Attributes attrs = null;
+ Token! id; Type! ty;
+
+ Expect(7);
+ while (t.kind == 5) {
+ Attribute(ref attrs);
+ }
+ IdentType(out id, out ty);
+ mm.Add(new Field(id, id.val, ty, attrs));
+ while (t.kind == 8) {
+ Get();
+ IdentType(out id, out ty);
+ mm.Add(new Field(id, id.val, ty, attrs));
+ }
+ Expect(9);
+ }
+
+ static void FunctionDecl(out Function! f) {
+ Attributes attrs = null;
+ Token! id;
+ List<TypeParameter!> typeArgs = new List<TypeParameter!>();
+ List<Formal!> formals = new List<Formal!>();
+ Type! returnType;
+ List<Expression!> reqs = new List<Expression!>();
+ List<Expression!> reads = new List<Expression!>();
+ Expression! bb; Expression body = null;
+ bool use = false;
+
+ Expect(27);
+ while (t.kind == 5) {
+ Attribute(ref attrs);
+ }
+ if (t.kind == 28) {
+ Get();
+ use = true;
+ }
+ Ident(out id);
+ if (t.kind == 11) {
+ GenericParameters(typeArgs);
+ }
+ parseVarScope.PushMarker();
+ Formals(true, formals);
+ Expect(10);
+ Type(out returnType);
+ if (t.kind == 9) {
+ Get();
+ while (t.kind == 18 || t.kind == 29) {
+ FunctionSpec(reqs, reads);
+ }
+ } else if (t.kind == 5 || t.kind == 18 || t.kind == 29) {
+ while (t.kind == 18 || t.kind == 29) {
+ FunctionSpec(reqs, reads);
+ }
+ ExtendedExpr(out bb);
+ body = bb;
+ } else Error(88);
+ parseVarScope.PopMarker();
+ f = new Function(id, id.val, use, typeArgs, formals, returnType, reqs, reads, body, attrs);
+
+ }
+
+ static void MethodDecl(out Method! m) {
+ Token! id;
+ Attributes attrs = null;
+ List<TypeParameter!>! typeArgs = new List<TypeParameter!>();
+ List<Formal!> ins = new List<Formal!>();
+ List<Formal!> outs = new List<Formal!>();
+ List<MaybeFreeExpression!> req = new List<MaybeFreeExpression!>();
+ List<Expression!> mod = new List<Expression!>();
+ List<MaybeFreeExpression!> ens = new List<MaybeFreeExpression!>();
+ Statement! bb; Statement body = null;
+
+ Expect(14);
+ while (t.kind == 5) {
+ Attribute(ref attrs);
+ }
+ Ident(out id);
+ if (t.kind == 11) {
+ GenericParameters(typeArgs);
+ }
+ parseVarScope.PushMarker();
+ Formals(true, ins);
+ if (t.kind == 15) {
+ Get();
+ Formals(false, outs);
+ }
+ if (t.kind == 9) {
+ Get();
+ while (StartOf(2)) {
+ MethodSpec(req, mod, ens);
+ }
+ } else if (StartOf(3)) {
+ while (StartOf(2)) {
+ MethodSpec(req, mod, ens);
+ }
+ BlockStmt(out bb);
+ body = bb;
+ } else Error(89);
+ parseVarScope.PopMarker();
+ m = new Method(id, id.val, typeArgs, ins, outs, req, mod, ens, body, attrs);
+
+ }
+
+ static void FrameDecl() {
+ Token! id;
+ Attributes attrs = null;
+
+ Expect(13);
+ while (t.kind == 5) {
+ Attribute(ref attrs);
+ }
+ Ident(out id);
+ Expect(5);
+ Expect(6);
+ }
+
+ static void IdentType(out Token! id, out Type! ty) {
+ Ident(out id);
+ Expect(10);
+ Type(out ty);
+ }
+
+ static void Type(out Type! ty) {
+ ty = new BoolType(); /*keep compiler happy*/
+
+ if (t.kind == 22) {
+ Get();
+
+ } else if (t.kind == 23) {
+ Get();
+ ty = new IntType();
+ } else if (StartOf(4)) {
+ ReferenceType(out ty);
+ } else Error(90);
+ }
+
+ static void IdentTypeOptional(out BoundVar! var) {
+ Token! id; Type! ty; Type optType = null;
+
+ Ident(out id);
+ if (t.kind == 10) {
+ Get();
+ Type(out ty);
+ optType = ty;
+ }
+ var = new BoundVar(id, id.val, optType == null ? new InferredTypeProxy() : optType);
+ }
+
+ static void Formals(bool incoming, List<Formal!>! formals) {
+ Token! id; Type! ty;
+ Expect(20);
+ if (t.kind == 1) {
+ IdentType(out id, out ty);
+ formals.Add(new Formal(id, id.val, ty, incoming)); parseVarScope.Push(id.val, id.val);
+ while (t.kind == 8) {
+ Get();
+ IdentType(out id, out ty);
+ formals.Add(new Formal(id, id.val, ty, incoming)); parseVarScope.Push(id.val, id.val);
+ }
+ }
+ Expect(21);
+ }
+
+ static void MethodSpec(List<MaybeFreeExpression!>! req, List<Expression!>! mod, List<MaybeFreeExpression!>! ens) {
+ Expression! e; bool isFree = false;
+
+ if (t.kind == 16) {
+ Get();
+ if (StartOf(5)) {
+ Expression(out e);
+ mod.Add(e);
+ while (t.kind == 8) {
+ Get();
+ Expression(out e);
+ mod.Add(e);
+ }
+ }
+ Expect(9);
+ } else if (t.kind == 17 || t.kind == 18 || t.kind == 19) {
+ if (t.kind == 17) {
+ Get();
+ isFree = true;
+ }
+ if (t.kind == 18) {
+ Get();
+ Expression(out e);
+ Expect(9);
+ req.Add(new MaybeFreeExpression(e, isFree));
+ } else if (t.kind == 19) {
+ Get();
+ Expression(out e);
+ Expect(9);
+ ens.Add(new MaybeFreeExpression(e, isFree));
+ } else Error(91);
+ } else Error(92);
+ }
+
+ static void BlockStmt(out Statement! block) {
+ Token! x;
+ List<Statement!> body = new List<Statement!>();
+ Statement! s;
+
+ parseVarScope.PushMarker();
+ Expect(5);
+ x = token;
+ while (StartOf(6)) {
+ Stmt(body);
+ }
+ Expect(6);
+ block = new BlockStmt(x, body);
+ parseVarScope.PopMarker();
+ }
+
+ static void Expression(out Expression! e0) {
+ Token! x; Expression! e1;
+ ImpliesExpression(out e0);
+ while (t.kind == 48 || t.kind == 49) {
+ EquivOp();
+ x = token;
+ ImpliesExpression(out e1);
+ e0 = new BinaryExpr(x, BinaryExpr.Opcode.Iff, e0, e1);
+ }
+ }
+
+ static void ReferenceType(out Type! ty) {
+ Token! x;
+ ty = new BoolType(); /*keep compiler happy*/
+ List<Type!>! gt;
+
+ if (t.kind == 24) {
+ Get();
+ ty = new ObjectType();
+ } else if (t.kind == 1) {
+ gt = new List<Type!>();
+ Ident(out x);
+ if (t.kind == 11) {
+ GenericInstantiation(gt);
+ }
+ ty = new ClassType(x, x.val, gt);
+ } else if (t.kind == 25) {
+ gt = new List<Type!>();
+ Get();
+ GenericInstantiation(gt);
+ if (gt.Count != 1) {
+ SemErr("set type expects exactly one type argument");
+ }
+ ty = new SetType(gt[0]);
+
+ } else if (t.kind == 26) {
+ gt = new List<Type!>();
+ Get();
+ GenericInstantiation(gt);
+ if (gt.Count != 1) {
+ SemErr("seq type expects exactly one type argument");
+ }
+ ty = new SeqType(gt[0]);
+
+ } else Error(93);
+ }
+
+ static void GenericInstantiation(List<Type!>! gt) {
+ Type! ty;
+ Expect(11);
+ Type(out ty);
+ gt.Add(ty);
+ while (t.kind == 8) {
+ Get();
+ Type(out ty);
+ gt.Add(ty);
+ }
+ Expect(12);
+ }
+
+ static void FunctionSpec(List<Expression!>! reqs, List<Expression!>! reads) {
+ Expression! e;
+ if (t.kind == 18) {
+ Get();
+ Expression(out e);
+ Expect(9);
+ reqs.Add(e);
+ } else if (t.kind == 29) {
+ ReadsClause(reads);
+ } else Error(94);
+ }
+
+ static void ExtendedExpr(out Expression! e) {
+ e = dummyExpr;
+ Expect(5);
+ if (t.kind == 30) {
+ IfThenElseExpr(out e);
+ } else if (StartOf(5)) {
+ Expression(out e);
+ } else Error(95);
+ Expect(6);
+ }
+
+ static void ReadsClause(List<Expression!>! reads) {
+ Expect(29);
+ if (StartOf(5)) {
+ Expressions(reads);
+ }
+ Expect(9);
+ }
+
+ static void Expressions(List<Expression!>! args) {
+ Expression! e;
+ Expression(out e);
+ args.Add(e);
+ while (t.kind == 8) {
+ Get();
+ Expression(out e);
+ args.Add(e);
+ }
+ }
+
+ static void IfThenElseExpr(out Expression! e) {
+ Token! x; Expression! e0; Expression! e1 = dummyExpr;
+ Expect(30);
+ x = token;
+ Expect(20);
+ Expression(out e);
+ Expect(21);
+ ExtendedExpr(out e0);
+ Expect(31);
+ if (t.kind == 30) {
+ IfThenElseExpr(out e1);
+ } else if (t.kind == 5) {
+ ExtendedExpr(out e1);
+ } else Error(96);
+ e = new ITEExpr(x, e, e0, e1);
+ }
+
+ static void Stmt(List<Statement!>! ss) {
+ Statement! s;
+ while (t.kind == 5) {
+ BlockStmt(out s);
+ ss.Add(s);
+ }
+ if (StartOf(7)) {
+ OneStmt(out s);
+ ss.Add(s);
+ } else if (t.kind == 7) {
+ VarDeclStmts(ss);
+ } else Error(97);
+ }
+
+ static void OneStmt(out Statement! s) {
+ Token! x; Token! id; string label = null;
+ s = dummyStmt; /* to please the compiler */
+
+ switch (t.kind) {
+ case 46: {
+ AssertStmt(out s);
+ break;
+ }
+ case 47: {
+ AssumeStmt(out s);
+ break;
+ }
+ case 28: {
+ UseStmt(out s);
+ break;
+ }
+ case 1: case 2: case 5: case 20: case 45: case 65: case 68: case 69: case 70: case 71: case 72: case 73: case 74: case 78: case 79: {
+ AssignStmt(out s);
+ break;
+ }
+ case 37: {
+ HavocStmt(out s);
+ break;
+ }
+ case 42: {
+ CallStmt(out s);
+ break;
+ }
+ case 30: {
+ IfStmt(out s);
+ break;
+ }
+ case 38: {
+ WhileStmt(out s);
+ break;
+ }
+ case 43: {
+ ForeachStmt(out s);
+ break;
+ }
+ case 32: {
+ Get();
+ x = token;
+ Ident(out id);
+ Expect(10);
+ s = new LabelStmt(x, id.val);
+ break;
+ }
+ case 33: {
+ Get();
+ x = token;
+ if (t.kind == 1) {
+ Ident(out id);
+ label = id.val;
+ }
+ Expect(9);
+ s = new BreakStmt(x, label);
+ break;
+ }
+ case 34: {
+ Get();
+ x = token;
+ Expect(9);
+ s = new ReturnStmt(x);
+ break;
+ }
+ default: Error(98); break;
+ }
+ }
+
+ static void VarDeclStmts(List<Statement!>! ss) {
+ VarDecl! d;
+ Expect(7);
+ IdentTypeRhs(out d);
+ ss.Add(d); parseVarScope.Push(d.Name, d.Name);
+ while (t.kind == 8) {
+ Get();
+ IdentTypeRhs(out d);
+ ss.Add(d); parseVarScope.Push(d.Name, d.Name);
+ }
+ Expect(9);
+ }
+
+ static void AssertStmt(out Statement! s) {
+ Token! x; Expression! e;
+ Expect(46);
+ x = token;
+ Expression(out e);
+ Expect(9);
+ s = new AssertStmt(x, e);
+ }
+
+ static void AssumeStmt(out Statement! s) {
+ Token! x; Expression! e;
+ Expect(47);
+ x = token;
+ Expression(out e);
+ Expect(9);
+ s = new AssumeStmt(x, e);
+ }
+
+ static void UseStmt(out Statement! s) {
+ Token! x; Expression! e;
+ Expect(28);
+ x = token;
+ Expression(out e);
+ Expect(9);
+ s = new UseStmt(x, e);
+ }
+
+ static void AssignStmt(out Statement! s) {
+ Token! x;
+ Expression! lhs;
+ Expression rhs;
+ Type ty;
+ s = dummyStmt;
+
+ LhsExpr(out lhs);
+ Expect(35);
+ x = token;
+ AssignRhs(out rhs, out ty);
+ if (rhs != null) {
+ s = new AssignStmt(x, lhs, rhs);
+ } else {
+ assert ty != null;
+ s = new AssignStmt(x, lhs, ty);
+ }
+
+ Expect(9);
+ }
+
+ static void HavocStmt(out Statement! s) {
+ Token! x; Expression! lhs;
+ Expect(37);
+ x = token;
+ LhsExpr(out lhs);
+ Expect(9);
+ s = new AssignStmt(x, lhs);
+ }
+
+ static void CallStmt(out Statement! s) {
+ Token! x, id;
+ Expression! e;
+ List<IdentifierExpr!> lhs = new List<IdentifierExpr!>();
+
+ Expect(42);
+ x = token;
+ CallStmtSubExpr(out e);
+ if (t.kind == 8 || t.kind == 35) {
+ if (t.kind == 8) {
+ Get();
+ if (e is IdentifierExpr) {
+ lhs.Add((IdentifierExpr)e);
+ } else if (e is FieldSelectExpr) {
+ SemErr(e.tok, "each LHS of call statement must be a variable, not a field");
+ } else {
+ SemErr(e.tok, "each LHS of call statement must be a variable");
+ }
+
+ Ident(out id);
+ lhs.Add(new IdentifierExpr(id, id.val));
+ while (t.kind == 8) {
+ Get();
+ Ident(out id);
+ lhs.Add(new IdentifierExpr(id, id.val));
+ }
+ Expect(35);
+ CallStmtSubExpr(out e);
+ } else {
+ Get();
+ if (e is IdentifierExpr) {
+ lhs.Add((IdentifierExpr)e);
+ } else if (e is FieldSelectExpr) {
+ SemErr(e.tok, "each LHS of call statement must be a variable, not a field");
+ } else {
+ SemErr(e.tok, "each LHS of call statement must be a variable");
+ }
+
+ CallStmtSubExpr(out e);
+ }
+ }
+ Expect(9);
+ if (e is FunctionCallExpr) {
+ FunctionCallExpr fce = (FunctionCallExpr)e;
+ s = new CallStmt(x, lhs, fce.Receiver, fce.Name, fce.Args); // this actually does an ownership transfer of fce.Args
+ } else {
+ SemErr("RHS of call statement must denote a method invocation");
+ s = new CallStmt(x, lhs, dummyExpr, "dummyMethodName", new List<Expression!>());
+ }
+
+ }
+
+ static void IfStmt(out Statement! ifStmt) {
+ Token! x;
+ Expression guard;
+ Statement! thn;
+ Statement! s;
+ Statement els = null;
+
+ Expect(30);
+ x = token;
+ Guard(out guard);
+ BlockStmt(out thn);
+ if (t.kind == 31) {
+ Get();
+ if (t.kind == 30) {
+ IfStmt(out s);
+ els = s;
+ } else if (t.kind == 5) {
+ BlockStmt(out s);
+ els = s;
+ } else Error(99);
+ }
+ ifStmt = new IfStmt(x, guard, thn, els);
+ }
+
+ static void WhileStmt(out Statement! stmt) {
+ Token! x;
+ Expression guard;
+ bool isFree; Expression! e;
+ List<MaybeFreeExpression!> invariants = new List<MaybeFreeExpression!>();
+ List<Expression!> decreases = new List<Expression!>();
+ Statement! body;
+
+ Expect(38);
+ x = token;
+ Guard(out guard);
+ assume guard == null || Owner.None(guard);
+ while (t.kind == 17 || t.kind == 39 || t.kind == 40) {
+ if (t.kind == 17 || t.kind == 39) {
+ isFree = false;
+ if (t.kind == 17) {
+ Get();
+ isFree = true;
+ }
+ Expect(39);
+ Expression(out e);
+ invariants.Add(new MaybeFreeExpression(e, isFree));
+ Expect(9);
+ } else {
+ Get();
+ Expression(out e);
+ decreases.Add(e);
+ while (t.kind == 8) {
+ Get();
+ Expression(out e);
+ decreases.Add(e);
+ }
+ Expect(9);
+ }
+ }
+ BlockStmt(out body);
+ stmt = new WhileStmt(x, guard, invariants, decreases, body);
+ }
+
+ static void ForeachStmt(out Statement! s) {
+ Token! x, boundVar;
+ Type! ty;
+ Expression! collection;
+ Expression! range;
+ List<PredicateStmt!> bodyPrefix = new List<PredicateStmt!>();
+ AssignStmt bodyAssign = null;
+
+ parseVarScope.PushMarker();
+ Expect(43);
+ x = token;
+ range = new LiteralExpr(x, true);
+ ty = new InferredTypeProxy();
+
+ Expect(20);
+ Ident(out boundVar);
+ if (t.kind == 10) {
+ Get();
+ Type(out ty);
+ }
+ Expect(44);
+ Expression(out collection);
+ parseVarScope.Push(boundVar.val, boundVar.val);
+ if (t.kind == 45) {
+ Get();
+ Expression(out range);
+ }
+ Expect(21);
+ Expect(5);
+ while (t.kind == 28 || t.kind == 46 || t.kind == 47) {
+ if (t.kind == 46) {
+ AssertStmt(out s);
+ if (s is PredicateStmt) { bodyPrefix.Add((PredicateStmt)s); }
+ } else if (t.kind == 47) {
+ AssumeStmt(out s);
+ if (s is PredicateStmt) { bodyPrefix.Add((PredicateStmt)s); }
+ } else {
+ UseStmt(out s);
+ if (s is PredicateStmt) { bodyPrefix.Add((PredicateStmt)s); }
+ }
+ }
+ if (StartOf(5)) {
+ AssignStmt(out s);
+ if (s is AssignStmt) { bodyAssign = (AssignStmt)s; }
+ } else if (t.kind == 37) {
+ HavocStmt(out s);
+ if (s is AssignStmt) { bodyAssign = (AssignStmt)s; }
+ } else Error(100);
+ Expect(6);
+ s = new ForeachStmt(x, new BoundVar(boundVar, boundVar.val, ty), collection, range, bodyPrefix, bodyAssign);
+ parseVarScope.PopMarker();
+ }
+
+ static void LhsExpr(out Expression! e) {
+ Expression(out e);
+ }
+
+ static void AssignRhs(out Expression e, out Type ty) {
+ Expression! ee; Type! tt;
+ e = null; ty = null;
+
+ if (t.kind == 36) {
+ Get();
+ ReferenceType(out tt);
+ ty = tt;
+ } else if (StartOf(5)) {
+ Expression(out ee);
+ e = ee;
+ } else Error(101);
+ if (e == null && ty == null) { e = dummyExpr; }
+ }
+
+ static void IdentTypeRhs(out VarDecl! d) {
+ Token! id; Type! ty; Expression! e;
+ Expression rhs = null; Type newType = null;
+ Type optionalType = null; DeterminedAssignmentRhs optionalRhs = null;
+
+ Ident(out id);
+ if (t.kind == 10) {
+ Get();
+ Type(out ty);
+ optionalType = ty;
+ }
+ if (t.kind == 35) {
+ Get();
+ AssignRhs(out rhs, out newType);
+ }
+ if (rhs != null) {
+ assert newType == null;
+ optionalRhs = new ExprRhs(rhs);
+ } else if (newType != null) {
+ optionalRhs = new TypeRhs(newType);
+ } else if (optionalType == null) {
+ optionalType = new InferredTypeProxy();
+ }
+ d = new VarDecl(id, id.val, optionalType, optionalRhs);
+
+ }
+
+ static void Guard(out Expression e) {
+ Expression! ee; e = null;
+ Expect(20);
+ if (t.kind == 41) {
+ Get();
+ e = null;
+ } else if (StartOf(5)) {
+ Expression(out ee);
+ e = ee;
+ } else Error(102);
+ Expect(21);
+ }
+
+ static void CallStmtSubExpr(out Expression! e) {
+ e = dummyExpr;
+ if (t.kind == 1) {
+ IdentOrFuncExpression(out e);
+ } else if (t.kind == 20 || t.kind == 78 || t.kind == 79) {
+ ObjectExpression(out e);
+ SelectOrCallSuffix(ref e);
+ } else Error(103);
+ while (t.kind == 74 || t.kind == 76) {
+ SelectOrCallSuffix(ref e);
+ }
+ }
+
+ static void ImpliesExpression(out Expression! e0) {
+ Token! x; Expression! e1;
+ LogicalExpression(out e0);
+ if (t.kind == 50 || t.kind == 51) {
+ ImpliesOp();
+ x = token;
+ ImpliesExpression(out e1);
+ e0 = new BinaryExpr(x, BinaryExpr.Opcode.Imp, e0, e1);
+ }
+ }
+
+ static void EquivOp() {
+ if (t.kind == 48) {
+ Get();
+ } else if (t.kind == 49) {
+ Get();
+ } else Error(104);
+ }
+
+ static void LogicalExpression(out Expression! e0) {
+ Token! x; Expression! e1;
+ RelationalExpression(out e0);
+ if (StartOf(8)) {
+ if (t.kind == 52 || t.kind == 53) {
+ AndOp();
+ x = token;
+ RelationalExpression(out e1);
+ e0 = new BinaryExpr(x, BinaryExpr.Opcode.And, e0, e1);
+ while (t.kind == 52 || t.kind == 53) {
+ AndOp();
+ x = token;
+ RelationalExpression(out e1);
+ e0 = new BinaryExpr(x, BinaryExpr.Opcode.And, e0, e1);
+ }
+ } else {
+ OrOp();
+ x = token;
+ RelationalExpression(out e1);
+ e0 = new BinaryExpr(x, BinaryExpr.Opcode.Or, e0, e1);
+ while (t.kind == 54 || t.kind == 55) {
+ OrOp();
+ x = token;
+ RelationalExpression(out e1);
+ e0 = new BinaryExpr(x, BinaryExpr.Opcode.Or, e0, e1);
+ }
+ }
+ }
+ }
+
+ static void ImpliesOp() {
+ if (t.kind == 50) {
+ Get();
+ } else if (t.kind == 51) {
+ Get();
+ } else Error(105);
+ }
+
+ static void RelationalExpression(out Expression! e0) {
+ Token! x; Expression! e1; BinaryExpr.Opcode op;
+ Term(out e0);
+ if (StartOf(9)) {
+ RelOp(out x, out op);
+ Term(out e1);
+ e0 = new BinaryExpr(x, op, e0, e1);
+ }
+ }
+
+ static void AndOp() {
+ if (t.kind == 52) {
+ Get();
+ } else if (t.kind == 53) {
+ Get();
+ } else Error(106);
+ }
+
+ static void OrOp() {
+ if (t.kind == 54) {
+ Get();
+ } else if (t.kind == 55) {
+ Get();
+ } else Error(107);
+ }
+
+ static void Term(out Expression! e0) {
+ Token! x; Expression! e1; BinaryExpr.Opcode op;
+ Factor(out e0);
+ while (t.kind == 64 || t.kind == 65) {
+ AddOp(out x, out op);
+ Factor(out e1);
+ e0 = new BinaryExpr(x, op, e0, e1);
+ }
+ }
+
+ static void RelOp(out Token! x, out BinaryExpr.Opcode op) {
+ x = Token.NoToken; op = BinaryExpr.Opcode.Add/*(dummy)*/;
+ switch (t.kind) {
+ case 56: {
+ Get();
+ x = token; op = BinaryExpr.Opcode.Eq;
+ break;
+ }
+ case 11: {
+ Get();
+ x = token; op = BinaryExpr.Opcode.Lt;
+ break;
+ }
+ case 12: {
+ Get();
+ x = token; op = BinaryExpr.Opcode.Gt;
+ break;
+ }
+ case 57: {
+ Get();
+ x = token; op = BinaryExpr.Opcode.Le;
+ break;
+ }
+ case 58: {
+ Get();
+ x = token; op = BinaryExpr.Opcode.Ge;
+ break;
+ }
+ case 59: {
+ Get();
+ x = token; op = BinaryExpr.Opcode.Neq;
+ break;
+ }
+ case 60: {
+ Get();
+ x = token; op = BinaryExpr.Opcode.Disjoint;
+ break;
+ }
+ case 44: {
+ Get();
+ x = token; op = BinaryExpr.Opcode.In;
+ break;
+ }
+ case 61: {
+ Get();
+ x = token; op = BinaryExpr.Opcode.Neq;
+ break;
+ }
+ case 62: {
+ Get();
+ x = token; op = BinaryExpr.Opcode.Le;
+ break;
+ }
+ case 63: {
+ Get();
+ x = token; op = BinaryExpr.Opcode.Ge;
+ break;
+ }
+ default: Error(108); break;
+ }
+ }
+
+ static void Factor(out Expression! e0) {
+ Token! x; Expression! e1; BinaryExpr.Opcode op;
+ UnaryExpression(out e0);
+ while (t.kind == 41 || t.kind == 66 || t.kind == 67) {
+ MulOp(out x, out op);
+ UnaryExpression(out e1);
+ e0 = new BinaryExpr(x, op, e0, e1);
+ }
+ }
+
+ static void AddOp(out Token! x, out BinaryExpr.Opcode op) {
+ x = Token.NoToken; op=BinaryExpr.Opcode.Add/*(dummy)*/;
+ if (t.kind == 64) {
+ Get();
+ x = token; op = BinaryExpr.Opcode.Add;
+ } else if (t.kind == 65) {
+ Get();
+ x = token; op = BinaryExpr.Opcode.Sub;
+ } else Error(109);
+ }
+
+ static void UnaryExpression(out Expression! e) {
+ Token! x; e = dummyExpr;
+ if (t.kind == 65) {
+ Get();
+ x = token;
+ UnaryExpression(out e);
+ e = new BinaryExpr(x, BinaryExpr.Opcode.Sub, new LiteralExpr(x, 0), e);
+ } else if (t.kind == 68 || t.kind == 69) {
+ NegOp();
+ x = token;
+ UnaryExpression(out e);
+ e = new UnaryExpr(x, UnaryExpr.Opcode.Not, e);
+ } else if (StartOf(10)) {
+ SelectExpression(out e);
+ } else if (StartOf(11)) {
+ ConstAtomExpression(out e);
+ } else Error(110);
+ }
+
+ static void MulOp(out Token! x, out BinaryExpr.Opcode op) {
+ x = Token.NoToken; op = BinaryExpr.Opcode.Add/*(dummy)*/;
+ if (t.kind == 41) {
+ Get();
+ x = token; op = BinaryExpr.Opcode.Mul;
+ } else if (t.kind == 66) {
+ Get();
+ x = token; op = BinaryExpr.Opcode.Div;
+ } else if (t.kind == 67) {
+ Get();
+ x = token; op = BinaryExpr.Opcode.Mod;
+ } else Error(111);
+ }
+
+ static void NegOp() {
+ if (t.kind == 68) {
+ Get();
+ } else if (t.kind == 69) {
+ Get();
+ } else Error(112);
+ }
+
+ static void SelectExpression(out Expression! e) {
+ Token! id; e = dummyExpr;
+ if (t.kind == 1) {
+ IdentOrFuncExpression(out e);
+ } else if (t.kind == 20 || t.kind == 78 || t.kind == 79) {
+ ObjectExpression(out e);
+ } else Error(113);
+ while (t.kind == 74 || t.kind == 76) {
+ SelectOrCallSuffix(ref e);
+ }
+ }
+
+ static void ConstAtomExpression(out Expression! e) {
+ Token! x; int n; List<Expression!>! elements;
+ e = dummyExpr;
+
+ switch (t.kind) {
+ case 70: {
+ Get();
+ e = new LiteralExpr(token, false);
+ break;
+ }
+ case 71: {
+ Get();
+ e = new LiteralExpr(token, true);
+ break;
+ }
+ case 72: {
+ Get();
+ e = new LiteralExpr(token);
+ break;
+ }
+ case 2: {
+ Nat(out n);
+ e = new LiteralExpr(token, n);
+ break;
+ }
+ case 73: {
+ Get();
+ x = token;
+ Expect(20);
+ Expression(out e);
+ Expect(21);
+ e = new FreshExpr(x, e);
+ break;
+ }
+ case 45: {
+ Get();
+ x = token;
+ Expression(out e);
+ e = new UnaryExpr(x, UnaryExpr.Opcode.SeqLength, e);
+ Expect(45);
+ break;
+ }
+ case 5: {
+ Get();
+ x = token; elements = new List<Expression!>();
+ if (StartOf(5)) {
+ Expressions(elements);
+ }
+ e = new SetDisplayExpr(x, elements);
+ Expect(6);
+ break;
+ }
+ case 74: {
+ Get();
+ x = token; elements = new List<Expression!>();
+ if (StartOf(5)) {
+ Expressions(elements);
+ }
+ e = new SeqDisplayExpr(x, elements);
+ Expect(75);
+ break;
+ }
+ default: Error(114); break;
+ }
+ }
+
+ static void Nat(out int n) {
+ Expect(2);
+ try {
+ n = System.Convert.ToInt32(token.val);
+ } catch (System.FormatException) {
+ SemErr("incorrectly formatted number");
+ n = 0;
+ }
+
+ }
+
+ static void IdentOrFuncExpression(out Expression! e) {
+ Token! id; e = dummyExpr; List<Expression!>! args;
+ Ident(out id);
+ if (t.kind == 20) {
+ Get();
+ args = new List<Expression!>();
+ if (StartOf(5)) {
+ Expressions(args);
+ }
+ Expect(21);
+ e = new FunctionCallExpr(id, id.val, new ImplicitThisExpr(id), args);
+ }
+ if (e == dummyExpr) {
+ if (parseVarScope.Find(id.val) != null) {
+ e = new IdentifierExpr(id, id.val);
+ } else {
+ e = new FieldSelectExpr(id, new ImplicitThisExpr(id), id.val);
+ }
+ }
+
+ }
+
+ static void ObjectExpression(out Expression! e) {
+ Token! x; e = dummyExpr;
+ if (t.kind == 78) {
+ Get();
+ e = new ThisExpr(token);
+ } else if (t.kind == 79) {
+ Get();
+ x = token;
+ Expect(20);
+ Expression(out e);
+ Expect(21);
+ e = new OldExpr(x, e);
+ } else if (t.kind == 20) {
+ Get();
+ if (StartOf(12)) {
+ QuantifierGuts(out e);
+ } else if (StartOf(5)) {
+ Expression(out e);
+ } else Error(115);
+ Expect(21);
+ } else Error(116);
+ }
+
+ static void SelectOrCallSuffix(ref Expression! e) {
+ Token! id, x; List<Expression!>! args;
+ Expression e0 = null; Expression e1 = null; Expression! ee; bool anyDots = false;
+ bool func = false;
+
+ if (t.kind == 76) {
+ Get();
+ Ident(out id);
+ if (t.kind == 20) {
+ Get();
+ args = new List<Expression!>(); func = true;
+ if (StartOf(5)) {
+ Expressions(args);
+ }
+ Expect(21);
+ e = new FunctionCallExpr(id, id.val, e, args);
+ }
+ if (!func) { e = new FieldSelectExpr(id, e, id.val); }
+ } else if (t.kind == 74) {
+ Get();
+ x = token;
+ if (StartOf(5)) {
+ Expression(out ee);
+ e0 = ee;
+ if (t.kind == 77) {
+ Get();
+ anyDots = true;
+ if (StartOf(5)) {
+ Expression(out ee);
+ e1 = ee;
+ }
+ }
+ } else if (t.kind == 77) {
+ Get();
+ Expression(out ee);
+ anyDots = true; e1 = ee;
+ } else Error(117);
+ if (!anyDots) {
+ assert e1 == null;
+ e = new SeqSelectExpr(x, true, e, e0, null);
+ } else {
+ assert e0 != null || e1 != null;
+ e = new SeqSelectExpr(x, false, e, e0, e1);
+ }
+
+ Expect(75);
+ } else Error(118);
+ }
+
+ static void QuantifierGuts(out Expression! q) {
+ Token! x = Token.NoToken;
+ bool univ = false;
+ BoundVar! bv;
+ List<BoundVar!> bvars = new List<BoundVar!>();
+ Token! tok; Expr! e; ExprSeq! es;
+ Attributes attrs = null;
+ Triggers trigs = null;
+ Expression! body;
+
+ if (t.kind == 80 || t.kind == 81) {
+ Forall();
+ x = token; univ = true;
+ } else if (t.kind == 82 || t.kind == 83) {
+ Exists();
+ x = token;
+ } else Error(119);
+ parseVarScope.PushMarker();
+ IdentTypeOptional(out bv);
+ bvars.Add(bv); parseVarScope.Push(bv.Name, bv.Name);
+ while (t.kind == 8) {
+ Get();
+ IdentTypeOptional(out bv);
+ bvars.Add(bv); parseVarScope.Push(bv.Name, bv.Name);
+ }
+ QSep();
+ while (t.kind == 5) {
+ AttributeOrTrigger(ref attrs, ref trigs);
+ }
+ Expression(out body);
+ if (univ) {
+ q = new ForallExpr(x, bvars, body, trigs, attrs);
+ } else {
+ q = new ExistsExpr(x, bvars, body, trigs, attrs);
+ }
+ parseVarScope.PopMarker();
+
+ }
+
+ static void Forall() {
+ if (t.kind == 80) {
+ Get();
+ } else if (t.kind == 81) {
+ Get();
+ } else Error(120);
+ }
+
+ static void Exists() {
+ if (t.kind == 82) {
+ Get();
+ } else if (t.kind == 83) {
+ Get();
+ } else Error(121);
+ }
+
+ static void QSep() {
+ if (t.kind == 84) {
+ Get();
+ } else if (t.kind == 85) {
+ Get();
+ } else Error(122);
+ }
+
+ static void AttributeOrTrigger(ref Attributes attrs, ref Triggers trigs) {
+ List<Expression!> es = new List<Expression!>();
+
+ Expect(5);
+ if (t.kind == 10) {
+ AttributeBody(ref attrs);
+ } else if (StartOf(5)) {
+ es = new List<Expression!>();
+ Expressions(es);
+ trigs = new Triggers(es, trigs);
+ } else Error(123);
+ Expect(6);
+ }
+
+ static void AttributeBody(ref Attributes attrs) {
+ string aName;
+ List<Attributes.Argument!> aArgs = new List<Attributes.Argument!>();
+ Attributes.Argument! aArg;
+
+ Expect(10);
+ Expect(1);
+ aName = token.val;
+ if (StartOf(13)) {
+ AttributeArg(out aArg);
+ aArgs.Add(aArg);
+ while (t.kind == 8) {
+ Get();
+ AttributeArg(out aArg);
+ aArgs.Add(aArg);
+ }
+ }
+ attrs = new Attributes(aName, aArgs, attrs);
+ }
+
+ static void AttributeArg(out Attributes.Argument! arg) {
+ Expression! e; arg = dummyAttrArg;
+ if (t.kind == 3) {
+ Get();
+ arg = new Attributes.Argument(token.val.Substring(1, token.val.Length-2));
+ } else if (StartOf(5)) {
+ Expression(out e);
+ arg = new Attributes.Argument(e);
+ } else Error(124);
+ }
+
+
+
+ public static void Parse() {
+ Errors.SynErr = new ErrorProc(SynErr);
+ t = new Token();
+ Get();
+ Dafny();
+
+ }
+
+ [Microsoft.Contracts.Verify(false)]
+ static void SynErr(int n, string filename, int line, int col) {
+ Errors.count++;
+ System.Console.Write("{0}({1},{2}): syntax error: ", filename, line, col);
+ string s;
+ switch (n) {
+ case 0: s = "EOF expected"; break;
+ case 1: s = "ident expected"; break;
+ case 2: s = "digits expected"; break;
+ case 3: s = "string expected"; break;
+ case 4: s = "class expected"; break;
+ case 5: s = "{ expected"; break;
+ case 6: s = "} 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 = "frame expected"; break;
+ case 14: s = "method expected"; break;
+ case 15: s = "returns expected"; break;
+ case 16: s = "modifies expected"; break;
+ case 17: s = "free expected"; break;
+ case 18: s = "requires expected"; break;
+ case 19: s = "ensures expected"; break;
+ case 20: s = "( expected"; break;
+ case 21: s = ") expected"; break;
+ case 22: s = "bool expected"; break;
+ case 23: s = "int expected"; break;
+ case 24: s = "object expected"; break;
+ case 25: s = "set expected"; break;
+ case 26: s = "seq expected"; break;
+ case 27: s = "function expected"; break;
+ case 28: s = "use expected"; break;
+ case 29: s = "reads expected"; break;
+ case 30: s = "if expected"; break;
+ case 31: s = "else expected"; break;
+ case 32: s = "label expected"; break;
+ case 33: s = "break expected"; break;
+ case 34: s = "return expected"; break;
+ case 35: s = ":= expected"; break;
+ case 36: s = "new expected"; break;
+ case 37: s = "havoc expected"; break;
+ case 38: s = "while expected"; break;
+ case 39: s = "invariant expected"; break;
+ case 40: s = "decreases expected"; break;
+ case 41: s = "* expected"; break;
+ case 42: s = "call expected"; break;
+ case 43: s = "foreach expected"; break;
+ case 44: s = "in expected"; break;
+ case 45: s = "| expected"; break;
+ case 46: s = "assert expected"; break;
+ case 47: s = "assume expected"; break;
+ case 48: s = "<==> expected"; break;
+ case 49: s = "\\u21d4 expected"; break;
+ case 50: s = "==> expected"; break;
+ case 51: s = "\\u21d2 expected"; break;
+ case 52: s = "&& expected"; break;
+ case 53: s = "\\u2227 expected"; break;
+ case 54: s = "|| expected"; break;
+ case 55: s = "\\u2228 expected"; break;
+ case 56: s = "== expected"; break;
+ case 57: s = "<= expected"; break;
+ case 58: s = ">= expected"; break;
+ case 59: s = "!= expected"; break;
+ case 60: s = "!! expected"; break;
+ case 61: s = "\\u2260 expected"; break;
+ case 62: s = "\\u2264 expected"; break;
+ case 63: s = "\\u2265 expected"; break;
+ case 64: s = "+ expected"; break;
+ case 65: s = "- expected"; break;
+ case 66: s = "/ expected"; break;
+ case 67: s = "% expected"; break;
+ case 68: s = "! expected"; break;
+ case 69: s = "\\u00ac expected"; break;
+ case 70: s = "false expected"; break;
+ case 71: s = "true expected"; break;
+ case 72: s = "null expected"; break;
+ case 73: s = "fresh expected"; break;
+ case 74: s = "[ expected"; break;
+ case 75: s = "] expected"; break;
+ case 76: s = ". expected"; break;
+ case 77: s = ".. expected"; break;
+ case 78: s = "this expected"; break;
+ case 79: s = "old expected"; break;
+ case 80: s = "forall expected"; break;
+ case 81: s = "\\u2200 expected"; break;
+ case 82: s = "exists expected"; break;
+ case 83: s = "\\u2203 expected"; break;
+ case 84: s = ":: expected"; break;
+ case 85: s = "\\u2022 expected"; break;
+ case 86: s = "??? expected"; break;
+ case 87: s = "invalid ClassMemberDecl"; break;
+ case 88: s = "invalid FunctionDecl"; break;
+ case 89: s = "invalid MethodDecl"; break;
+ case 90: s = "invalid Type"; break;
+ case 91: s = "invalid MethodSpec"; break;
+ case 92: s = "invalid MethodSpec"; break;
+ case 93: s = "invalid ReferenceType"; break;
+ case 94: s = "invalid FunctionSpec"; break;
+ case 95: s = "invalid ExtendedExpr"; break;
+ case 96: s = "invalid IfThenElseExpr"; break;
+ case 97: s = "invalid Stmt"; break;
+ case 98: s = "invalid OneStmt"; break;
+ case 99: s = "invalid IfStmt"; break;
+ case 100: s = "invalid ForeachStmt"; break;
+ case 101: s = "invalid AssignRhs"; break;
+ case 102: s = "invalid Guard"; break;
+ case 103: s = "invalid CallStmtSubExpr"; break;
+ case 104: s = "invalid EquivOp"; break;
+ case 105: s = "invalid ImpliesOp"; break;
+ case 106: s = "invalid AndOp"; break;
+ case 107: s = "invalid OrOp"; break;
+ case 108: s = "invalid RelOp"; break;
+ case 109: s = "invalid AddOp"; break;
+ case 110: s = "invalid UnaryExpression"; break;
+ case 111: s = "invalid MulOp"; break;
+ case 112: s = "invalid NegOp"; break;
+ case 113: s = "invalid SelectExpression"; break;
+ case 114: s = "invalid ConstAtomExpression"; break;
+ case 115: s = "invalid ObjectExpression"; break;
+ case 116: s = "invalid ObjectExpression"; break;
+ case 117: s = "invalid SelectOrCallSuffix"; break;
+ case 118: s = "invalid SelectOrCallSuffix"; break;
+ case 119: s = "invalid QuantifierGuts"; break;
+ case 120: s = "invalid Forall"; break;
+ case 121: s = "invalid Exists"; break;
+ case 122: s = "invalid QSep"; break;
+ case 123: s = "invalid AttributeOrTrigger"; break;
+ case 124: s = "invalid AttributeArg"; break;
+
+ default: s = "error " + n; break;
+ }
+ System.Console.WriteLine(s);
+ }
+
+ static 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,T, x,x,x,x, x,T,T,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,x,x, x,x,x,x, x,x,x,x, x,x,x,x, 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,T,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,T,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,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,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,T,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,T,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,T,x, x,x,T,T, x,x,x,x, x,x,x,x},
+ {x,T,T,x, x,T,x,T, x,x,x,x, x,x,x,x, x,x,x,x, T,x,x,x, x,x,x,x, T,x,T,x, T,T,T,x, x,T,T,x, x,x,T,T, x,T,T,T, 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,T,x, x,x,T,T, x,x,x,x, x,x,x,x},
+ {x,T,T,x, x,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, T,x,x,x, x,x,x,x, T,x,T,x, T,T,T,x, x,T,T,x, x,x,T,T, x,T,T,T, 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,T,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,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,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, T,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,T,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,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,T,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,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,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, T,T,T,T, x,x,x,x},
+ {x,T,T,T, x,T,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,T,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,T,x, x,x,T,T, x,x,x,x, x,x,x,x}
+
+ };
+
+ [Microsoft.Contracts.Verify(false)]
+ static Parser() {}
+} // end Parser
+
+} // end namespace
diff --git a/Source/Dafny/Printer.ssc b/Source/Dafny/Printer.ssc
new file mode 100644
index 00000000..4a861553
--- /dev/null
+++ b/Source/Dafny/Printer.ssc
@@ -0,0 +1,663 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using System;
+using System.IO;
+using System.Collections.Generic;
+using Microsoft.Contracts;
+using Bpl = Microsoft.Boogie;
+
+namespace Microsoft.Dafny {
+ class Printer {
+ TextWriter! wr;
+ public Printer(TextWriter! wr) {
+ this.wr = wr;
+ }
+
+ public void PrintProgram(Program! prog) {
+ if (Bpl.CommandLineOptions.Clo.ShowEnv != Bpl.CommandLineOptions.ShowEnvironment.Never) {
+ wr.WriteLine("// " + Bpl.CommandLineOptions.Clo.Version);
+ wr.WriteLine("// " + Bpl.CommandLineOptions.Clo.Environment);
+ }
+ wr.WriteLine("// {0}", prog.Name);
+ foreach (ClassDecl c in prog.Classes) {
+ wr.WriteLine();
+ PrintClass(c);
+ }
+ }
+
+ public void PrintClass(ClassDecl! c) {
+ PrintClassMethodHelper("class", c.Attributes, "", c.Name, c.TypeArgs);
+ if (c.Members.Count == 0) {
+ wr.WriteLine(" { }");
+ } else {
+ int state = 0; // 0 - no members yet; 1 - previous member was a field; 2 - previous member was non-field
+ wr.WriteLine(" {");
+ foreach (MemberDecl m in c.Members) {
+ if (m is Method) {
+ if (state != 0) { wr.WriteLine(); }
+ PrintMethod((Method)m);
+ state = 2;
+ } else if (m is Field) {
+ if (state == 2) { wr.WriteLine(); }
+ PrintField((Field)m);
+ state = 1;
+ } else if (m is Function) {
+ if (state != 0) { wr.WriteLine(); }
+ PrintFunction((Function)m);
+ state = 2;
+ } else {
+ assert false; // unexpected member
+ }
+ }
+ wr.WriteLine("}");
+ }
+ }
+
+ void PrintClassMethodHelper(string! kind, Attributes attrs, string! modifiers, string! name, List<TypeParameter!>! typeArgs) {
+ wr.Write("{0} ", kind);
+ PrintAttributes(attrs);
+ wr.Write(modifiers);
+ wr.Write(name);
+ if (typeArgs.Count != 0) {
+ wr.Write("<");
+ string sep = "";
+ foreach (TypeParameter tp in typeArgs) {
+ wr.Write("{0}{1}", sep, tp.Name);
+ sep = ", ";
+ }
+ wr.Write(">");
+ }
+ }
+
+ public void PrintAttributes(Attributes a) {
+ if (a != null) {
+ PrintAttributes(a.Prev);
+
+ wr.Write("{ :{0}", a.Name);
+ string prefix = " ";
+ foreach (Attributes.Argument arg in a.Args) {
+ wr.Write(prefix);
+ prefix = ", ";
+ if (arg.S != null) {
+ wr.Write("\"{0}\"", arg.S);
+ } else {
+ assert arg.E != null;
+ PrintExpression(arg.E);
+ }
+ }
+ wr.Write(" } ");
+ }
+ }
+
+ public void PrintField(Field! field) {
+ Indent(IndentAmount);
+ wr.Write("var ");
+ PrintAttributes(field.Attributes);
+ wr.Write("{0}: ", field.Name);
+ PrintType(field.Type);
+ wr.WriteLine(";");
+ }
+
+ public void PrintFunction(Function! f) {
+ Indent(IndentAmount);
+ PrintClassMethodHelper("function", f.Attributes, f.Use ? "use " : "", f.Name, f.TypeArgs);
+ PrintFormals(f.Formals);
+ wr.Write(": ");
+ PrintType(f.ResultType);
+ if (f.Body == null) {
+ wr.WriteLine(";");
+ }
+ foreach (Expression r in f.Req) {
+ Indent(2 * IndentAmount);
+ wr.Write("requires ");
+ PrintExpression(r);
+ wr.WriteLine(";");
+ }
+ foreach (Expression r in f.Reads) {
+ Indent(2 * IndentAmount);
+ wr.Write("reads ");
+ PrintExpression(r);
+ wr.WriteLine(";");
+ }
+ if (f.Body != null) {
+ Indent(IndentAmount);
+ PrintExtendedExpr(f.Body, IndentAmount);
+ wr.WriteLine();
+ }
+ }
+
+ // ----------------------------- PrintMethod -----------------------------
+
+ const int IndentAmount = 2;
+ const string! BunchaSpaces = " ";
+ void Indent(int amount)
+ requires 0 <= amount;
+ {
+ while (0 < amount) {
+ wr.Write(BunchaSpaces.Substring(0, amount));
+ amount -= BunchaSpaces.Length;
+ }
+ }
+
+ public void PrintMethod(Method! method) {
+ Indent(IndentAmount);
+ PrintClassMethodHelper("method", method.Attributes, "", method.Name, method.TypeArgs);
+ PrintFormals(method.Ins);
+ if (method.Outs.Count != 0) {
+ if (method.Ins.Count + method.Outs.Count <= 3) {
+ wr.Write(" returns ");
+ } else {
+ wr.WriteLine();
+ Indent(3 * IndentAmount);
+ wr.Write("returns ");
+ }
+ PrintFormals(method.Outs);
+ }
+ wr.WriteLine(method.Body == null ? ";" : ":");
+
+ PrintSpec("requires", method.Req, 2 * IndentAmount);
+ PrintSpec("modifies", method.Mod, 2 * IndentAmount);
+ PrintSpec("ensures", method.Ens, 2 * IndentAmount);
+
+ if (method.Body != null) {
+ Indent(IndentAmount);
+ PrintStatement(method.Body, IndentAmount);
+ wr.WriteLine();
+ }
+ }
+
+ void PrintFormals(List<Formal!>! ff) {
+ wr.Write("(");
+ string sep = "";
+ foreach (Formal f in ff) {
+ wr.Write(sep);
+ sep = ", ";
+ PrintFormal(f);
+ }
+ wr.Write(")");
+ }
+
+ void PrintFormal(Formal! f) {
+ if (!f.Name.StartsWith("#")) {
+ wr.Write("{0}: ", f.Name);
+ }
+ PrintType(f.Type);
+ }
+
+ void PrintSpec(string! kind, List<Expression!>! ee, int indent) {
+ foreach (Expression e in ee) {
+ Indent(indent);
+ wr.Write("{0} ", kind);
+ PrintExpression(e);
+ wr.WriteLine(";");
+ }
+ }
+
+ void PrintSpec(string! kind, List<MaybeFreeExpression!>! ee, int indent) {
+ foreach (MaybeFreeExpression e in ee) {
+ Indent(indent);
+ wr.Write("{0}{1} ", e.IsFree ? "free " : "", kind);
+ PrintExpression(e.E);
+ wr.WriteLine(";");
+ }
+ }
+
+ // ----------------------------- PrintType -----------------------------
+
+ public void PrintType(Type! ty) {
+ wr.Write(ty.ToString());
+ }
+
+ // ----------------------------- PrintStatement -----------------------------
+
+ /// <summary>
+ /// Prints from the current position of the current line.
+ /// If the statement requires several lines, subsequent lines are indented at "indent".
+ /// No newline is printed after the statement.
+ /// </summary>
+ public void PrintStatement(Statement! stmt, int indent) {
+ if (stmt is AssertStmt) {
+ wr.Write("assert ");
+ PrintExpression(((AssertStmt)stmt).Expr);
+ wr.Write(";");
+
+ } else if (stmt is AssumeStmt) {
+ wr.Write("assume ");
+ PrintExpression(((AssertStmt)stmt).Expr);
+ wr.Write(";");
+
+ } else if (stmt is UseStmt) {
+ wr.Write("use ");
+ PrintExpression(((AssertStmt)stmt).Expr);
+ wr.Write(";");
+
+ } else if (stmt is LabelStmt) {
+ wr.Write("label {0}:", ((LabelStmt)stmt).Label);
+
+ } else if (stmt is BreakStmt) {
+ BreakStmt s = (BreakStmt)stmt;
+ if (s.TargetLabel == null) {
+ wr.Write("break;");
+ } else {
+ wr.Write("break {0};", s.TargetLabel);
+ }
+
+ } else if (stmt is ReturnStmt) {
+ wr.Write("return;");
+
+ } else if (stmt is AssignStmt) {
+ AssignStmt s = (AssignStmt)stmt;
+ if (s.Rhs is HavocRhs) {
+ wr.Write("havoc ");
+ PrintExpression(s.Lhs);
+ } else {
+ PrintExpression(s.Lhs);
+ wr.Write(" := ");
+ PrintDeterminedRhs((DeterminedAssignmentRhs)s.Rhs);
+ }
+ wr.Write(";");
+
+ } else if (stmt is VarDecl) {
+ VarDecl s = (VarDecl)stmt;
+ wr.Write("var {0}", s.Name);
+ if (s.OptionalType != null) {
+ wr.Write(": ");
+ PrintType(s.OptionalType);
+ }
+ if (s.Rhs != null) {
+ wr.Write(" := ");
+ PrintDeterminedRhs(s.Rhs);
+ }
+ wr.Write(";");
+
+ } else if (stmt is CallStmt) {
+ CallStmt s = (CallStmt)stmt;
+ wr.Write("call ");
+ if (s.Lhs.Count != 0) {
+ string sep = "";
+ foreach (IdentifierExpr v in s.Lhs) {
+ wr.Write(sep);
+ PrintExpression(v);
+ sep = ", ";
+ }
+ wr.Write(" := ");
+ }
+ if (!(s.Receiver is ThisExpr)) {
+ PrintExpr(s.Receiver, 0x70, false, -1);
+ wr.Write(".");
+ }
+ wr.Write("{0}(", s.MethodName);
+ PrintExpressionList(s.Args);
+ wr.Write(")");
+
+ } else if (stmt is BlockStmt) {
+ wr.WriteLine("{");
+ int ind = indent + IndentAmount;
+ foreach (Statement s in ((BlockStmt)stmt).Body) {
+ Indent(ind);
+ PrintStatement(s, ind);
+ wr.WriteLine();
+ }
+ Indent(indent);
+ wr.Write("}");
+
+ } else if (stmt is IfStmt) {
+ IfStmt s = (IfStmt)stmt;
+ while (true) {
+ wr.Write("if (");
+ PrintGuard(s.Guard);
+ wr.Write(") ");
+ PrintStatement(s.Thn, indent);
+ if (s.Els == null) {
+ break;
+ }
+ wr.Write(" else ");
+ if (s.Els is IfStmt) {
+ s = (IfStmt)s.Els;
+ } else {
+ PrintStatement(s.Els, indent);
+ break;
+ }
+ }
+
+ } else if (stmt is WhileStmt) {
+ WhileStmt s = (WhileStmt)stmt;
+ wr.Write("while (");
+ PrintGuard(s.Guard);
+ wr.WriteLine(")");
+
+ int ind = indent + IndentAmount;
+ PrintSpec("invariant", s.Invariants, ind);
+ if (s.Decreases.Count != 0) {
+ Indent(indent);
+ string sep = "decreases ";
+ foreach (Expression e in s.Decreases) {
+ wr.Write(sep);
+ sep = ", ";
+ PrintExpression(e);
+ }
+ wr.WriteLine(";");
+ }
+ Indent(indent);
+ PrintStatement(s.Body, indent);
+
+ } else if (stmt is ForeachStmt) {
+ ForeachStmt s = (ForeachStmt)stmt;
+ wr.Write("foreach ({0} in ", s.BoundVar);
+ PrintExpression(s.Collection);
+ if (!LiteralExpr.IsTrue(s.Range)) {
+ wr.Write(" | ");
+ PrintExpression(s.Range);
+ }
+ wr.WriteLine(") {");
+ int ind = indent + IndentAmount;
+ foreach (PredicateStmt t in s.BodyPrefix) {
+ Indent(ind);
+ PrintStatement(t, ind);
+ wr.WriteLine();
+ }
+ if (s.BodyAssign != null) {
+ Indent(ind);
+ PrintStatement(s.BodyAssign, ind);
+ wr.WriteLine();
+ }
+ wr.Write("}");
+
+ } else {
+ assert false; // unexpected statement
+ }
+ }
+
+ void PrintDeterminedRhs(DeterminedAssignmentRhs! rhs) {
+ if (rhs is ExprRhs) {
+ PrintExpression(((ExprRhs)rhs).Expr);
+ } else if (rhs is TypeRhs) {
+ wr.Write("new ");
+ PrintType(((TypeRhs)rhs).Type);
+ } else {
+ assert false; // unexpected RHS
+ }
+ }
+
+ void PrintGuard(Expression guard) {
+ if (guard == null) {
+ wr.Write("*");
+ } else {
+ PrintExpression(guard);
+ }
+ }
+
+ // ----------------------------- PrintExpression -----------------------------
+
+ public void PrintExtendedExpr(Expression! expr, int indent) {
+ wr.WriteLine("{");
+ int ind = indent + IndentAmount;
+ Indent(ind);
+ if (expr is ITEExpr) {
+ Expression els = expr; // bogus assignment, just to please the compiler
+ for (ITEExpr ite = (ITEExpr)expr; ite != null; ite = els as ITEExpr) {
+ wr.Write("if (");
+ PrintExpression(ite.Test);
+ wr.Write(") ");
+ PrintExtendedExpr(ite.Thn, ind);
+ wr.Write(" else ");
+ els = ite.Els;
+ }
+ PrintExtendedExpr(els, ind);
+ } else {
+ PrintExpression(expr, ind);
+ wr.WriteLine();
+ }
+ Indent(indent);
+ wr.Write("}");
+ }
+
+ public void PrintExpression(Expression! expr) {
+ PrintExpr(expr, 0, false, -1);
+ }
+
+ /// <summary>
+ /// An indent of -1 means print the entire expression on one line.
+ /// </summary>
+ public void PrintExpression(Expression! expr, int indent) {
+ PrintExpr(expr, 0, false, indent);
+ }
+
+ /// <summary>
+ /// An indent of -1 means print the entire expression on one line.
+ /// </summary>
+ void PrintExpr(Expression! expr, int contextBindingStrength, bool fragileContext, int indent)
+ requires -1 <= indent;
+ {
+ if (expr is LiteralExpr) {
+ LiteralExpr e = (LiteralExpr)expr;
+ if (e.Value == null) {
+ wr.Write("null");
+ } else if (e.Value is bool) {
+ wr.Write((bool)e.Value ? "true" : "false");
+ } else {
+ wr.Write((int)e.Value);
+ }
+
+ } else if (expr is ThisExpr) {
+ wr.Write("this");
+
+ } else if (expr is IdentifierExpr) {
+ wr.Write(((IdentifierExpr)expr).Name);
+
+ } else if (expr is DisplayExpression) {
+ DisplayExpression e = (DisplayExpression)expr;
+ wr.Write(e is SetDisplayExpr ? "{" : "[");
+ PrintExpressionList(e.Elements);
+ wr.Write(e is SetDisplayExpr ? "}" : "]");
+
+ } else if (expr is FieldSelectExpr) {
+ FieldSelectExpr e = (FieldSelectExpr)expr;
+ // determine if parens are needed
+ int opBindingStrength = 0x70;
+ bool parensNeeded = !(e.Obj is ImplicitThisExpr) &&
+ opBindingStrength < contextBindingStrength ||
+ (fragileContext && opBindingStrength == contextBindingStrength);
+
+ if (parensNeeded) { wr.Write("("); }
+ if (!(e.Obj is ImplicitThisExpr)) {
+ PrintExpr(e.Obj, opBindingStrength, false, -1);
+ wr.Write(".");
+ }
+ wr.Write(e.FieldName);
+ if (parensNeeded) { wr.Write(")"); }
+
+ } else if (expr is SeqSelectExpr) {
+ SeqSelectExpr e = (SeqSelectExpr)expr;
+ // determine if parens are needed
+ int opBindingStrength = 0x70;
+ bool parensNeeded = opBindingStrength < contextBindingStrength ||
+ (fragileContext && opBindingStrength == contextBindingStrength);
+
+ if (parensNeeded) { wr.Write("("); }
+ PrintExpr(e.Seq, 00, false, indent); // BOGUS: fix me
+ wr.Write("[");
+ if (e.SelectOne) {
+ assert e.E0 != null;
+ PrintExpression(e.E0);
+ } else {
+ if (e.E0 != null) {
+ PrintExpression(e.E0);
+ }
+ wr.Write(e.E0 != null && e.E1 != null ? " .. " : "..");
+ if (e.E1 != null) {
+ PrintExpression(e.E1);
+ }
+ }
+ wr.Write("]");
+ if (parensNeeded) { wr.Write(")"); }
+
+ } else if (expr is FunctionCallExpr) {
+ FunctionCallExpr e = (FunctionCallExpr)expr;
+ // determine if parens are needed
+ int opBindingStrength = 0x70;
+ bool parensNeeded = !(e.Receiver is ThisExpr) &&
+ opBindingStrength < contextBindingStrength ||
+ (fragileContext && opBindingStrength == contextBindingStrength);
+
+ if (parensNeeded) { wr.Write("("); }
+ if (!(e.Receiver is ThisExpr)) {
+ PrintExpr(e.Receiver, opBindingStrength, false, -1);
+ wr.Write(".");
+ }
+ wr.Write(e.Name);
+ wr.Write("(");
+ PrintExpressionList(e.Args);
+ wr.Write(")");
+ if (parensNeeded) { wr.Write(")"); }
+
+ } else if (expr is OldExpr) {
+ wr.Write("old(");
+ PrintExpression(((OldExpr)expr).E);
+ wr.Write(")");
+
+ } else if (expr is FreshExpr) {
+ wr.Write("fresh(");
+ PrintExpression(((FreshExpr)expr).E);
+ wr.Write(")");
+
+ } else if (expr is UnaryExpr) {
+ UnaryExpr e = (UnaryExpr)expr;
+ if (e.Op == UnaryExpr.Opcode.SeqLength) {
+ wr.Write("|");
+ PrintExpression(e.E);
+ wr.Write("|");
+ } else {
+ // Prefix operator.
+ // determine if parens are needed
+ string op;
+ int opBindingStrength;
+ switch (e.Op) {
+ case UnaryExpr.Opcode.Not:
+ op = "!"; opBindingStrength = 0x60; break;
+ default:
+ assert false; // unexpected unary opcode
+ }
+ bool parensNeeded = opBindingStrength < contextBindingStrength ||
+ (fragileContext && opBindingStrength == contextBindingStrength);
+
+ if (parensNeeded) { wr.Write("("); }
+ wr.Write(op);
+ PrintExpr(e.E, opBindingStrength, false, -1);
+ if (parensNeeded) { wr.Write(")"); }
+ }
+
+ } else if (expr is BinaryExpr) {
+ BinaryExpr e = (BinaryExpr)expr;
+ // determine if parens are needed
+ int opBindingStrength;
+ bool fragileLeftContext = false; // false means "allow same binding power on left without parens"
+ bool fragileRightContext = false; // false means "allow same binding power on right without parens"
+ switch (e.Op)
+ {
+ case BinaryExpr.Opcode.Add:
+ opBindingStrength = 0x40; break;
+ case BinaryExpr.Opcode.Sub:
+ opBindingStrength = 0x40; fragileRightContext = true; break;
+ case BinaryExpr.Opcode.Mul:
+ opBindingStrength = 0x50; break;
+ case BinaryExpr.Opcode.Div:
+ case BinaryExpr.Opcode.Mod:
+ opBindingStrength = 0x50; fragileRightContext = true; break;
+ case BinaryExpr.Opcode.Eq:
+ case BinaryExpr.Opcode.Neq:
+ case BinaryExpr.Opcode.Gt:
+ case BinaryExpr.Opcode.Ge:
+ case BinaryExpr.Opcode.Lt:
+ case BinaryExpr.Opcode.Le:
+ case BinaryExpr.Opcode.Disjoint:
+ case BinaryExpr.Opcode.In:
+ opBindingStrength = 0x30; fragileLeftContext = fragileRightContext = true; break;
+ case BinaryExpr.Opcode.And:
+ opBindingStrength = 0x20; break;
+ case BinaryExpr.Opcode.Or:
+ opBindingStrength = 0x21; break;
+ case BinaryExpr.Opcode.Imp:
+ opBindingStrength = 0x10; fragileLeftContext = true; break;
+ case BinaryExpr.Opcode.Iff:
+ opBindingStrength = 0x00; break;
+ default:
+ assert false; // unexpected binary operator
+ }
+ int opBS = opBindingStrength & 0xF0;
+ int ctxtBS = contextBindingStrength & 0xF0;
+ bool parensNeeded = opBS < ctxtBS ||
+ (opBS == ctxtBS && (opBindingStrength != contextBindingStrength || fragileContext));
+
+ string op = BinaryExpr.OpcodeString(e.Op);
+ if (parensNeeded) { wr.Write("("); }
+ if (0 <= indent && e.Op == BinaryExpr.Opcode.And) {
+ PrintExpr(e.E0, opBindingStrength, fragileLeftContext, indent);
+ wr.WriteLine(" {0}", op);
+ Indent(indent);
+ PrintExpr(e.E1, opBindingStrength, fragileRightContext, indent);
+ } else if (0 <= indent && e.Op == BinaryExpr.Opcode.Imp) {
+ PrintExpr(e.E0, opBindingStrength, fragileLeftContext, indent);
+ wr.WriteLine(" {0}", op);
+ int ind = indent + IndentAmount;
+ Indent(ind);
+ PrintExpr(e.E1, opBindingStrength, fragileRightContext, ind);
+ } else {
+ PrintExpr(e.E0, opBindingStrength, fragileLeftContext, -1);
+ wr.Write(" {0} ", op);
+ PrintExpr(e.E1, opBindingStrength, fragileRightContext, -1);
+ }
+ if (parensNeeded) { wr.Write(")"); }
+
+ } else if (expr is QuantifierExpr) {
+ QuantifierExpr e = (QuantifierExpr)expr;
+ wr.Write(e is ForallExpr ? "(forall " : "(exists ");
+ string sep = "";
+ foreach (BoundVar bv in e.BoundVars) {
+ wr.Write("{0}{1}: ", sep, bv.Name);
+ sep = ", ";
+ PrintType(bv.Type);
+ }
+ wr.Write(" :: ");
+ PrintAttributes(e.Attributes);
+ PrintTriggers(e.Trigs);
+ if (0 <= indent) {
+ int ind = indent + IndentAmount;
+ wr.WriteLine();
+ Indent(ind);
+ PrintExpression(e.Body, ind);
+ } else {
+ PrintExpression(e.Body);
+ }
+ wr.Write(")");
+
+ } else if (expr is ITEExpr) {
+ assert false; // ITE is an extended expression and should be printed only using PrintExtendedExpr
+ } else {
+ assert false; // unexpected expression
+ }
+ }
+
+ void PrintTriggers(Triggers trigs) {
+ if (trigs != null) {
+ PrintTriggers(trigs.Prev);
+
+ wr.Write("{ ");
+ PrintExpressionList(trigs.Terms);
+ wr.Write(" } ");
+ }
+ }
+
+ void PrintExpressionList(List<Expression!>! exprs) {
+ string sep = "";
+ foreach (Expression e in exprs) {
+ wr.Write(sep);
+ sep = ", ";
+ PrintExpression(e);
+ }
+ }
+ }
+}
diff --git a/Source/Dafny/Resolver.ssc b/Source/Dafny/Resolver.ssc
new file mode 100644
index 00000000..66cdabe1
--- /dev/null
+++ b/Source/Dafny/Resolver.ssc
@@ -0,0 +1,1419 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using System;
+using System.Collections.Generic;
+using Microsoft.Contracts;
+
+namespace Microsoft.Dafny {
+ public class Resolver {
+ public int ErrorCount = 0;
+ void Error(Token! tok, string! msg, params object[] args) {
+ ConsoleColor col = Console.ForegroundColor;
+ Console.ForegroundColor = ConsoleColor.Red;
+ Console.WriteLine("{0}({1},{2}): Error: {3}",
+ tok.filename, tok.line, tok.col-1,
+ string.Format(msg, args));
+ Console.ForegroundColor = col;
+ ErrorCount++;
+ }
+ void Error(Declaration! d, string! msg, params object[] args) {
+ Error(d.tok, msg, args);
+ }
+ void Error(Statement! s, string! msg, params object[] args) {
+ Error(s.Tok, msg, args);
+ }
+ void Error(NonglobalVariable! v, string! msg, params object[] args) {
+ Error(v.tok, msg, args);
+ }
+ void Error(Expression! e, string! msg, params object[] args) {
+ Error(e.tok, msg, args);
+ }
+
+ readonly Dictionary<string!,ClassDecl!>! classes = new Dictionary<string!,ClassDecl!>();
+ readonly Dictionary<ClassDecl!,Dictionary<string!,MemberDecl!>!>! classMembers = new Dictionary<ClassDecl!,Dictionary<string!,MemberDecl!>!>();
+
+ public void ResolveProgram(Program! prog) {
+ foreach (ClassDecl cl in prog.Classes) {
+ // register the class name
+ if (classes.ContainsKey(cl.Name)) {
+ Error(cl, "Duplicate class name: {0}", cl.Name);
+ } else {
+ classes.Add(cl.Name, cl);
+ }
+
+ // register the names of the class members
+ Dictionary<string!,MemberDecl!> members = new Dictionary<string!,MemberDecl!>();
+ classMembers.Add(cl, members);
+
+ foreach (MemberDecl m in cl.Members) {
+ if (members.ContainsKey(m.Name)) {
+ Error(m, "Duplicate member name: {0}", m.Name);
+ } else {
+ members.Add(m.Name, m);
+ }
+ }
+ }
+
+ // resolve each class
+ foreach (ClassDecl cl in prog.Classes) {
+ allTypeParameters.PushMarker();
+ ResolveTypeParameters(cl.TypeArgs, true, cl);
+ ResolveClassMemberTypes(cl);
+ allTypeParameters.PopMarker();
+ }
+ foreach (ClassDecl cl in prog.Classes) {
+ allTypeParameters.PushMarker();
+ ResolveTypeParameters(cl.TypeArgs, false, cl);
+ ResolveClassMemberBodies(cl);
+ allTypeParameters.PopMarker();
+ }
+ }
+
+ ClassDecl currentClass;
+ readonly Scope<TypeParameter>! allTypeParameters = new Scope<TypeParameter>();
+ readonly Scope<IVariable>! scope = new Scope<IVariable>();
+ readonly Scope<Statement>! labeledStatements = new Scope<Statement>();
+
+ /// <summary>
+ /// Assumes type parameters have already been pushed
+ /// </summary>
+ void ResolveClassMemberTypes(ClassDecl! cl)
+ requires currentClass == null;
+ ensures currentClass == null;
+ {
+ currentClass = cl;
+ foreach (MemberDecl member in cl.Members) {
+ member.EnclosingClass = cl;
+ if (member is Field) {
+ ResolveType(((Field)member).Type);
+
+ } else if (member is Function) {
+ Function f = (Function)member;
+ allTypeParameters.PushMarker();
+ ResolveTypeParameters(f.TypeArgs, true, f);
+ ResolveFunctionSignature(f);
+ allTypeParameters.PopMarker();
+
+ } else if (member is Method) {
+ Method m = (Method)member;
+ allTypeParameters.PushMarker();
+ ResolveTypeParameters(m.TypeArgs, true, m);
+ ResolveMethodSignature(m);
+ allTypeParameters.PopMarker();
+
+ } else {
+ assert false; // unexpected member type
+ }
+ }
+ currentClass = null;
+ }
+
+ /// <summary>
+ /// Assumes type parameters have already been pushed, and that all types in class members have been resolved
+ /// </summary>
+ void ResolveClassMemberBodies(ClassDecl! cl)
+ requires currentClass == null;
+ ensures currentClass == null;
+ {
+ ResolveAttributes(cl.Attributes, false);
+ currentClass = cl;
+ foreach (MemberDecl member in cl.Members) {
+ ResolveAttributes(member.Attributes, false);
+ if (member is Field) {
+ // nothing more to do
+
+ } else if (member is Function) {
+ Function f = (Function)member;
+ allTypeParameters.PushMarker();
+ ResolveTypeParameters(f.TypeArgs, false, f);
+ ResolveFunction(f);
+ allTypeParameters.PopMarker();
+
+ } else if (member is Method) {
+ Method m = (Method)member;
+ allTypeParameters.PushMarker();
+ ResolveTypeParameters(m.TypeArgs, false, m);
+ ResolveMethod(m);
+ allTypeParameters.PopMarker();
+
+ } else {
+ assert false; // unexpected member type
+ }
+ }
+ currentClass = null;
+ }
+
+ void ResolveAttributes(Attributes attrs, bool twoState) {
+ // order does not matter for resolution, so resolve them in reverse order
+ for (; attrs != null; attrs = attrs.Prev) {
+ foreach (Attributes.Argument aa in attrs.Args) {
+ if (aa.E != null) {
+ ResolveExpression(aa.E, twoState);
+ }
+ }
+ }
+ }
+
+ void ResolveTriggers(Triggers trigs, bool twoState) {
+ // order does not matter for resolution, so resolve them in reverse order
+ for (; trigs != null; trigs = trigs.Prev) {
+ foreach (Expression e in trigs.Terms) {
+ ResolveExpression(e, twoState);
+ }
+ }
+ }
+
+ void ResolveTypeParameters(List<TypeParameter!>! tparams, bool emitErrors, TypeParameter.ParentType! parent) {
+ // push non-duplicated type parameter names
+ foreach (TypeParameter tp in tparams) {
+ if (emitErrors) {
+ // we're seeing this TypeParameter for the first time
+ tp.Parent = parent;
+ }
+ if (!allTypeParameters.Push(tp.Name, tp) && emitErrors) {
+ Error(tp, "Duplicate type-parameter name: {0}", tp.Name);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Assumes type parameters have already been pushed
+ /// </summary>
+ void ResolveFunctionSignature(Function! f) {
+ scope.PushMarker();
+ foreach (Formal p in f.Formals) {
+ if (!scope.Push(p.Name, p)) {
+ Error(p, "Duplicate parameter name: {0}", p.Name);
+ }
+ ResolveType(p.Type);
+ }
+ ResolveType(f.ResultType);
+ scope.PopMarker();
+ }
+
+ /// <summary>
+ /// Assumes type parameters have already been pushed
+ /// </summary>
+ void ResolveFunction(Function! f) {
+ scope.PushMarker();
+ foreach (Formal p in f.Formals) {
+ scope.Push(p.Name, p);
+ }
+ foreach (Expression r in f.Req) {
+ ResolveExpression(r, false);
+ assert r.Type != null; // follows from postcondition of ResolveExpression
+ if (!UnifyTypes(r.Type, Type.Bool)) {
+ Error(r, "Precondition must be a boolean (got {0})", r.Type);
+ }
+ }
+ foreach (Expression r in f.Reads) {
+ ResolveExpression(r, false);
+ Type t = r.Type;
+ assert t != null; // follows from postcondition of ResolveExpression
+ if (t is CollectionType) {
+ t = ((CollectionType)t).Arg;
+ }
+ if (t is ObjectType) {
+ // fine
+ } else if (ClassType.DenotesClass(t) != null) {
+ // fine
+ } else {
+ Error(r, "a reads-clause expression must denote an object or a collection of objects (instead got {0})", r.Type);
+ }
+ }
+ if (f.Body != null) {
+ ResolveExpression(f.Body, false);
+ assert f.Body.Type != null; // follows from postcondition of ResolveExpression
+ if (!UnifyTypes(f.Body.Type, f.ResultType)) {
+ Error(f, "Function body type mismatch (expected {0}, got {1})", f.ResultType, f.Body.Type);
+ }
+ }
+ scope.PopMarker();
+ }
+
+ /// <summary>
+ /// Assumes type parameters have already been pushed
+ /// </summary>
+ void ResolveMethodSignature(Method! m) {
+ scope.PushMarker();
+ // resolve in-parameters
+ foreach (Formal p in m.Ins) {
+ if (!scope.Push(p.Name, p)) {
+ Error(p, "Duplicate parameter name: {0}", p.Name);
+ }
+ ResolveType(p.Type);
+ }
+ // resolve out-parameters
+ foreach (Formal p in m.Outs) {
+ if (!scope.Push(p.Name, p)) {
+ Error(p, "Duplicate parameter name: {0}", p.Name);
+ }
+ ResolveType(p.Type);
+ }
+ scope.PopMarker();
+ }
+
+ /// <summary>
+ /// Assumes type parameters have already been pushed
+ /// </summary>
+ void ResolveMethod(Method! m) {
+ // Add in-parameters to the scope, but don't care about any duplication errors, since they have already been reported
+ scope.PushMarker();
+ foreach (Formal p in m.Ins) {
+ scope.Push(p.Name, p);
+ }
+
+ // Start resolving specification...
+ foreach (MaybeFreeExpression e in m.Req) {
+ ResolveExpression(e.E, false);
+ assert e.E.Type != null; // follows from postcondition of ResolveExpression
+ if (!UnifyTypes(e.E.Type, Type.Bool)) {
+ Error(e.E, "Precondition must be a boolean (got {0})", e.E.Type);
+ }
+ }
+ foreach (Expression e in m.Mod) {
+ ResolveExpression(e, false);
+ Type t = e.Type;
+ assert t != null; // follows from postcondition of ResolveExpression
+ if (t is CollectionType) {
+ t = ((CollectionType)t).Arg;
+ }
+ if (t is ObjectType) {
+ // fine
+ } else if (ClassType.DenotesClass(t) != null) {
+ // fine
+ } else {
+ Error(e, "a modifies-clause expression must denote an object or a collection of objects (instead got {0})", e.Type);
+ }
+ }
+
+ // Add out-parameters to the scope, but don't care about any duplication errors, since they have already been reported
+ foreach (Formal p in m.Outs) {
+ scope.Push(p.Name, p);
+ }
+
+ // ... continue resolving specification
+ foreach (MaybeFreeExpression e in m.Ens) {
+ ResolveExpression(e.E, true);
+ assert e.E.Type != null; // follows from postcondition of ResolveExpression
+ if (!UnifyTypes(e.E.Type, Type.Bool)) {
+ Error(e.E, "Postcondition must be a boolean (got {0})", e.E.Type);
+ }
+ }
+
+ // Resolve body
+ if (m.Body != null) {
+ ResolveStatement(m.Body);
+ }
+
+ scope.PopMarker();
+ }
+
+ public void ResolveType(Type! type) {
+ if (type is BasicType) {
+ // nothing to resolve
+ } else if (type is CollectionType) {
+ ResolveType(((CollectionType)type).Arg);
+ } else if (type is ClassType) {
+ ClassType t = (ClassType)type;
+ foreach (Type tt in t.TypeArgs) {
+ ResolveType(tt);
+ }
+ TypeParameter tp = allTypeParameters.Find(t.Name);
+ if (tp != null) {
+ if (t.TypeArgs.Count == 0) {
+ t.ResolvedParam = tp;
+ } else {
+ Error(t.tok, "Type parameter expects no type arguments: {0}", t.Name);
+ }
+ } else {
+ ClassDecl cl;
+ if (!classes.TryGetValue(t.Name, out cl)) {
+ Error(t.tok, "Undeclared class type or type parameter: {0}", t.Name);
+ } else if (((!)cl).TypeArgs.Count == t.TypeArgs.Count) {
+ t.ResolvedClass = cl;
+ } else {
+ Error(t.tok, "Wrong number of type arguments ({0} instead of {1}) passed to class: {2}", t.TypeArgs.Count, cl.TypeArgs.Count, t.Name);
+ }
+ }
+
+ } else if (type is TypeProxy) {
+ TypeProxy t = (TypeProxy)type;
+ if (t.T != null) {
+ ResolveType(t.T);
+ }
+
+ } else {
+ assert false; // unexpected type
+ }
+ }
+
+ public bool UnifyTypes(Type! a, Type! b) {
+ while (a is TypeProxy) {
+ TypeProxy proxy = (TypeProxy)a;
+ if (proxy.T == null) {
+ // merge a and b; to avoid cycles, first get to the bottom of b
+ while (b is TypeProxy && ((TypeProxy)b).T != null) {
+ b = ((TypeProxy)b).T;
+ }
+ return AssignProxy(proxy, b);
+ } else {
+ a = proxy.T;
+ }
+ }
+
+ while (b is TypeProxy) {
+ TypeProxy proxy = (TypeProxy)b;
+ if (proxy.T == null) {
+ // merge a and b (we have already got to the bottom of a)
+ return AssignProxy(proxy, a);
+ } else {
+ b = proxy.T;
+ }
+ }
+
+#if !NO_CHEAP_OBJECT_WORKAROUND
+ if (a is ObjectType || b is ObjectType) { // TODO: remove this temporary hack
+ // allow anything with object; this is BOGUS
+ return true;
+ }
+#endif
+ // Now, a and b are non-proxies and stand for the same things as the original a and b, respectively.
+
+ if (a is BoolType) {
+ return b is BoolType;
+ } else if (a is IntType) {
+ return b is IntType;
+ } else if (a is ObjectType) {
+ return b is ObjectType;
+ } else if (a is SetType) {
+ return b is SetType && UnifyTypes(((SetType)a).Arg, ((SetType)b).Arg);
+ } else if (a is SeqType) {
+ return b is SeqType && UnifyTypes(((SeqType)a).Arg, ((SeqType)b).Arg);
+ } else if (a is ClassType) {
+ if (!(b is ClassType)) {
+ return false;
+ }
+ ClassType aa = (ClassType)a;
+ ClassType bb = (ClassType)b;
+ if (aa.ResolvedClass != null && aa.ResolvedClass == bb.ResolvedClass) {
+ // these are both resolved class types
+ assert aa.TypeArgs.Count == bb.TypeArgs.Count;
+ bool successSoFar = true;
+ for (int i = 0; i < aa.TypeArgs.Count; i++) {
+ if (!UnifyTypes(aa.TypeArgs[i], bb.TypeArgs[i])) {
+ successSoFar = false;
+ }
+ }
+ return successSoFar;
+ } else if (aa.ResolvedParam != null && aa.ResolvedParam == bb.ResolvedParam) {
+ // these are both resolved type parameters
+ assert aa.TypeArgs.Count == 0 && bb.TypeArgs.Count == 0;
+ return true;
+ } else {
+ // something is wrong; either aa or bb wasn't properly resolved, or they don't unify
+ return false;
+ }
+
+ } else {
+ assert false; // unexpected type
+ }
+ }
+
+ bool AssignProxy(TypeProxy! proxy, Type! t)
+ requires proxy.T == null;
+ requires t is TypeProxy ==> ((TypeProxy)t).T == null;
+ modifies proxy.T, ((TypeProxy)t).T; // might also change t.T if t is a proxy
+ ensures result ==> proxy == t || proxy.T != null || (t is TypeProxy && ((TypeProxy)t).T != null);
+ {
+ if (proxy == t) {
+ // they are already in the same equivalence class
+ return true;
+
+ } else if (proxy is UnrestrictedTypeProxy) {
+ // it's fine to redirect proxy to t (done below)
+
+ } else if (t is UnrestrictedTypeProxy) {
+ // merge proxy and t by redirecting t to proxy, rather than the other way around
+ ((TypeProxy)t).T = proxy;
+ return true;
+
+ } else if (t is RestrictedTypeProxy) {
+ // Both proxy and t are restricted type proxies. To simplify unification, order proxy and t
+ // according to their types.
+ RestrictedTypeProxy r0 = (RestrictedTypeProxy)proxy;
+ RestrictedTypeProxy r1 = (RestrictedTypeProxy)t;
+ if (r0.OrderID <= r1.OrderID) {
+ return AssignRestrictedProxies(r0, r1);
+ } else {
+ return AssignRestrictedProxies(r1, r0);
+ }
+
+ // In the remaining cases, proxy is a restricted proxy and t is a non-proxy
+ } else if (proxy is ObjectTypeProxy) {
+ if (t is ObjectType || ClassType.DenotesClass(t) != null) {
+ // all is fine, proxy can be redirected to t
+ } else {
+ return false;
+ }
+
+ } else if (proxy is ObjectsTypeProxy) {
+ if (t is ObjectType || ClassType.DenotesClass(t) != null) {
+ // all is good
+ } else if (t is CollectionType) {
+ proxy.T = new CollectionTypeProxy(new ObjectTypeProxy());
+ return UnifyTypes(proxy.T, t);
+ }
+
+ } else if (proxy is CollectionTypeProxy) {
+ CollectionTypeProxy collProxy = (CollectionTypeProxy)proxy;
+ if (t is CollectionType) {
+ if (!UnifyTypes(collProxy.Arg, ((CollectionType)t).Arg)) {
+ return false;
+ }
+ } else {
+ return false;
+ }
+
+ } else if (proxy is OperationTypeProxy) {
+ OperationTypeProxy opProxy = (OperationTypeProxy)proxy;
+ if (t is IntType || t is SetType || (opProxy.AllowSeq && t is SeqType)) {
+ // this is the expected case
+ } else {
+ return false;
+ }
+
+ } else {
+ assert false; // unexpected proxy type
+ }
+
+ // do the merge
+ proxy.T = t;
+ return true;
+ }
+
+ bool AssignRestrictedProxies(RestrictedTypeProxy! a, RestrictedTypeProxy! b)
+ requires a != b;
+ requires a.T == null && b.T == null;
+ requires a.OrderID <= b.OrderID;
+ modifies a.T, b.T;
+ ensures result ==> a.T != null || b.T != null;
+ {
+ if (a is ObjectTypeProxy) {
+ if (b is ObjectTypeProxy) {
+ // all is fine
+ a.T = b;
+ return true;
+ } else if (b is ObjectsTypeProxy) {
+ // unify a and b by redirecting b to a, since a gives the stronger requirement
+ b.T = a;
+ return true;
+ } else {
+ return false;
+ }
+
+ } else if (a is ObjectsTypeProxy) {
+ if (b is ObjectsTypeProxy) {
+ // fine
+ a.T = b;
+ return true;
+ } else if (b is CollectionTypeProxy) {
+ // fine provided b's collection-element-type can be unified with object or a class type
+ a.T = new ObjectTypeProxy();
+ return UnifyTypes(a.T, ((CollectionTypeProxy)b).Arg);
+ } else if (b is OperationTypeProxy) {
+ // fine; restrict a to sets of object/class, and restrict b to set/seq of object/class
+ if (((OperationTypeProxy)b).AllowSeq) {
+ a.T = new CollectionTypeProxy(new ObjectTypeProxy());
+ b.T = a.T;
+ } else {
+ a.T = new SetType(new ObjectTypeProxy());
+ b.T = a.T;
+ }
+ return true;
+ } else {
+ assert false; // unexpected restricted-proxy type
+ }
+
+ } else if (a is CollectionTypeProxy) {
+ if (b is CollectionTypeProxy) {
+ a.T = b;
+ return UnifyTypes(((CollectionTypeProxy)a).Arg, ((CollectionTypeProxy)b).Arg);
+ } else if (b is OperationTypeProxy) {
+ if (((OperationTypeProxy)b).AllowSeq) {
+ b.T = a; // a is a stronger constraint than b
+ } else {
+ // a says set<T>,seq<T> and b says int,set; the intersection is set<T>
+ a.T = new SetType(((CollectionTypeProxy)a).Arg);
+ b.T = a.T;
+ }
+ return true;
+ } else {
+ assert false; // unexpected restricted-proxy type
+ }
+
+ } else if (a is OperationTypeProxy) {
+ assert b is OperationTypeProxy; // else we we have unexpected restricted-proxy type
+ if (((OperationTypeProxy)a).AllowSeq ==> ((OperationTypeProxy)b).AllowSeq) {
+ b.T = a;
+ } else {
+ a.T = b; // b has the stronger requirement
+ }
+ return true;
+
+ } else {
+ assert false; // unexpected restricted-proxy type
+ }
+ }
+
+ public void ResolveStatement(Statement! stmt)
+ requires !(stmt is LabelStmt); // these should be handled inside lists of statements
+ {
+ if (stmt is UseStmt) {
+ UseStmt s = (UseStmt)stmt;
+ ResolveExpression(s.Expr, true);
+ assert s.Expr.Type != null; // follows from postcondition of ResolveExpression
+ Expression expr = s.Expr;
+ while (true) {
+ if (expr is OldExpr) {
+ expr = ((OldExpr)expr).E;
+ } else {
+ break;
+ }
+ }
+ FunctionCallExpr fce = expr as FunctionCallExpr;
+ if (fce == null || fce.Function == null || !fce.Function.Use) {
+ Error(s.Expr, "use statement must indicate a function declared as use");
+ }
+ } else if (stmt is PredicateStmt) {
+ PredicateStmt s = (PredicateStmt)stmt;
+ ResolveExpression(s.Expr, true);
+ assert s.Expr.Type != null; // follows from postcondition of ResolveExpression
+ if (!UnifyTypes(s.Expr.Type, Type.Bool)) {
+ Error(s.Expr, "condition is expected to be of type {0}, but is {1}", Type.Bool, s.Expr.Type);
+ }
+
+ } else if (stmt is BreakStmt) {
+ BreakStmt s = (BreakStmt)stmt;
+ if (s.TargetLabel != null) {
+ Statement target = labeledStatements.Find(s.TargetLabel);
+ if (target == null) {
+ Error(s, "break label is undefined or not in scope: {0}", s.TargetLabel);
+ } else {
+ s.TargetStmt = target;
+ }
+ }
+
+ } else if (stmt is ReturnStmt) {
+ // nothing to resolve
+
+ } else if (stmt is AssignStmt) {
+ AssignStmt s = (AssignStmt)stmt;
+ ResolveExpression(s.Lhs, true);
+ assert s.Lhs.Type != null; // follows from postcondition of ResolveExpression
+ // check that LHS denotes a mutable variable or a field
+ if (s.Lhs is IdentifierExpr) {
+ IVariable var = ((IdentifierExpr)s.Lhs).Var;
+ if (var == null) {
+ // the LHS didn't resolve correctly; some error would already have been reported
+ } else if (!var.IsMutable) {
+ Error(stmt, "LHS of assignment must denote a mutable variable or field");
+ }
+ } else if (s.Lhs is FieldSelectExpr) {
+ // LHS is fine, but restrict the RHS to ExprRhs
+ if (!(s.Rhs is ExprRhs)) {
+ Error(stmt, "Assignment to field must have an expression RHS; try using a temporary local variable");
+ }
+ } else {
+ Error(stmt, "LHS of assignment must denote a mutable variable or field");
+ }
+
+ if (s.Rhs is ExprRhs) {
+ ExprRhs rr = (ExprRhs)s.Rhs;
+ ResolveExpression(rr.Expr, true);
+ assert rr.Expr.Type != null; // follows from postcondition of ResolveExpression
+ if (!UnifyTypes(s.Lhs.Type, rr.Expr.Type)) {
+ Error(stmt, "RHS (of type {0}) not assignable to LHS (of type {1})", rr.Expr.Type, s.Lhs.Type);
+ }
+ } else if (s.Rhs is TypeRhs) {
+ TypeRhs rr = (TypeRhs)s.Rhs;
+ ResolveType(rr.Type);
+ if (!UnifyTypes(s.Lhs.Type, rr.Type)) {
+ Error(stmt, "type {0} is not assignable to LHS (of type {1})", rr.Type, s.Lhs.Type);
+ }
+ } else if (s.Rhs is HavocRhs) {
+ // nothing else to do
+ } else {
+ assert false; // unexpected RHS
+ }
+
+ } else if (stmt is VarDecl) {
+ VarDecl s = (VarDecl)stmt;
+ if (s.OptionalType != null) {
+ ResolveType(s.OptionalType);
+ s.type = s.OptionalType;
+ }
+ if (s.Rhs != null) {
+ Type! rhsType;
+ if (s.Rhs is ExprRhs) {
+ ExprRhs rr = (ExprRhs)s.Rhs;
+ ResolveExpression(rr.Expr, true);
+ assert rr.Expr.Type != null; // follows from postcondition of ResolveExpression
+ rhsType = rr.Expr.Type;
+ } else if (s.Rhs is TypeRhs) {
+ TypeRhs rr = (TypeRhs)s.Rhs;
+ ResolveType(rr.Type);
+ rhsType = rr.Type;
+ } else {
+ assert false; // unexpected RHS
+ }
+ if (s.OptionalType == null) {
+ s.type = rhsType;
+ } else if (!UnifyTypes(s.OptionalType, rhsType)) {
+ Error(stmt, "initialization RHS (of type {0}) not assignable to variable (of type {1})", rhsType, s.OptionalType);
+ }
+ }
+ // now that the declaration has been processed, add the name to the scope
+ if (!scope.Push(s.Name, s)) {
+ Error(s, "Duplicate local-variable name: {0}", s.Name);
+ }
+
+ } else if (stmt is CallStmt) {
+ CallStmt s = (CallStmt)stmt;
+
+ // resolve left-hand side
+ Dictionary<string!,object> lhsNameSet = new Dictionary<string!,object>();
+ foreach (IdentifierExpr lhs in s.Lhs) {
+ ResolveExpression(lhs, true);
+ if (lhsNameSet.ContainsKey(lhs.Name)) {
+ Error(s, "Duplicate variable in left-hand side of call statement: {0}", lhs.Name);
+ } else {
+ lhsNameSet.Add(lhs.Name, null);
+ }
+ }
+ // resolve receiver
+ ResolveExpression(s.Receiver, true);
+ assert s.Receiver.Type != null; // follows from postcondition of ResolveExpression
+ // resolve arguments
+ foreach (Expression e in s.Args) {
+ ResolveExpression(e, true);
+ }
+
+ // resolve the method name
+ ClassType ctype;
+ MemberDecl member = ResolveMember(s.Tok, s.Receiver.Type, s.MethodName, out ctype);
+ if (member == null) {
+ // error has already been reported by ResolveMember
+ } else if (!(member is Method)) {
+ Error(s, "member {0} in class {1} does not refer to a method", s.MethodName, ((!)ctype).Name);
+ } else {
+ Method method = (Method)member;
+ s.Method = method;
+ if (method.Ins.Count != s.Args.Count) {
+ Error(s, "wrong number of method arguments (got {0}, expected {1})", s.Args.Count, method.Ins.Count);
+ } else if (method.Outs.Count != s.Lhs.Count) {
+ Error(s, "wrong number of method result arguments (got {0}, expected {1})", s.Lhs.Count, method.Outs.Count);
+ } else {
+ assert ctype != null; // follows from postcondition of ResolveMember
+ // build the type substitution map
+ Dictionary<TypeParameter!,Type!> subst = new Dictionary<TypeParameter!,Type!>();
+ for (int i = 0; i < ctype.TypeArgs.Count; i++) {
+ subst.Add(((!)ctype.ResolvedClass).TypeArgs[i], ctype.TypeArgs[i]);
+ }
+ foreach (TypeParameter p in method.TypeArgs) {
+ subst.Add(p, new ParamTypeProxy(p));
+ }
+ // type check the arguments
+ for (int i = 0; i < method.Ins.Count; i++) {
+ UnifyTypes((!)s.Args[i].Type, SubstType(method.Ins[i].Type, subst));
+ }
+ for (int i = 0; i < method.Outs.Count; i++) {
+ UnifyTypes((!)s.Lhs[i].Type, SubstType(method.Outs[i].Type, subst));
+ }
+ }
+ }
+
+ } else if (stmt is BlockStmt) {
+ scope.PushMarker();
+ int labelsToPop = 0;
+ foreach (Statement ss in ((BlockStmt)stmt).Body) {
+ if (ss is LabelStmt) {
+ LabelStmt ls = (LabelStmt)ss;
+ labeledStatements.PushMarker();
+ bool b = labeledStatements.Push(ls.Label, ls);
+ assert b; // since we just pushed a marker, we expect the Push to succeed
+ labelsToPop++;
+ } else {
+ ResolveStatement(ss);
+ for (; 0 < labelsToPop; labelsToPop--) { labeledStatements.PopMarker(); }
+ }
+ }
+ for (; 0 < labelsToPop; labelsToPop--) { labeledStatements.PopMarker(); }
+ scope.PopMarker();
+
+ } else if (stmt is IfStmt) {
+ IfStmt s = (IfStmt)stmt;
+ if (s.Guard != null) {
+ ResolveExpression(s.Guard, true);
+ assert s.Guard.Type != null; // follows from postcondition of ResolveExpression
+ if (!UnifyTypes(s.Guard.Type, Type.Bool)) {
+ Error(s.Guard, "condition is expected to be of type {0}, but is {1}", Type.Bool, s.Guard.Type);
+ }
+ }
+ ResolveStatement(s.Thn);
+ if (s.Els != null) {
+ ResolveStatement(s.Els);
+ }
+
+ } else if (stmt is WhileStmt) {
+ WhileStmt s = (WhileStmt)stmt;
+ if (s.Guard != null) {
+ ResolveExpression(s.Guard, true);
+ assert s.Guard.Type != null; // follows from postcondition of ResolveExpression
+ if (!UnifyTypes(s.Guard.Type, Type.Bool)) {
+ Error(s.Guard, "condition is expected to be of type {0}, but is {1}", Type.Bool, s.Guard.Type);
+ }
+ }
+ foreach (MaybeFreeExpression inv in s.Invariants) {
+ ResolveExpression(inv.E, true);
+ assert inv.E.Type != null; // follows from postcondition of ResolveExpression
+ if (!UnifyTypes(inv.E.Type, Type.Bool)) {
+ Error(inv.E, "invariant is expected to be of type {0}, but is {1}", Type.Bool, inv.E.Type);
+ }
+ }
+ foreach (Expression e in s.Decreases) {
+ ResolveExpression(e, true);
+ // any type is fine
+ }
+ ResolveStatement(s.Body);
+
+ } else if (stmt is ForeachStmt) {
+ ForeachStmt s = (ForeachStmt)stmt;
+ scope.PushMarker();
+ bool b = scope.Push(s.BoundVar.Name, s.BoundVar);
+ assert b; // since we just pushed a marker, we expect the Push to succeed
+ ResolveType(s.BoundVar.Type);
+
+ ResolveExpression(s.Collection, true);
+ assert s.Collection.Type != null; // follows from postcondition of ResolveExpression
+ if (!UnifyTypes(s.Collection.Type, new CollectionTypeProxy(s.BoundVar.Type))) {
+ Error(s.Collection, "The type is expected to be a collection of {0} (instead got {1})", s.BoundVar.Type, s.Collection.Type);
+ }
+
+ ResolveExpression(s.Range, true);
+ assert s.Range.Type != null; // follows from postcondition of ResolveExpression
+ if (!UnifyTypes(s.Range.Type, Type.Bool)) {
+ Error(s.Range, "range condition is expected to be of type {0}, but is {1}", Type.Bool, s.Range.Type);
+ }
+
+ foreach (PredicateStmt ss in s.BodyPrefix) {
+ ResolveStatement(ss);
+ }
+ if (s.BodyAssign != null) {
+ ResolveStatement(s.BodyAssign);
+ // check for correct usage of BoundVar in LHS and RHS of this assignment
+ FieldSelectExpr lhs = s.BodyAssign.Lhs as FieldSelectExpr;
+ IdentifierExpr obj = lhs == null ? null : lhs.Obj as IdentifierExpr;
+ if (obj != null && obj.Var == s.BoundVar) {
+ // exemplary!
+ } else {
+ Error(s, "assignment inside foreach must assign to a field of the bound variable of the foreach statement");
+ }
+ }
+ scope.PopMarker();
+
+ } else {
+ assert false;
+ }
+ }
+
+ MemberDecl ResolveMember(Token! tok, Type! receiverType, string! memberName, out ClassType ctype)
+ ensures result != null ==> ctype != null && ctype.ResolvedClass != null;
+ {
+ ctype = ClassType.DenotesClass(receiverType);
+ if (ctype == null) {
+ Error(tok, "receiver (of type {0}) must be of a class type", receiverType);
+ } else {
+ assert ctype.ResolvedClass != null; // follows from postcondition of DenotesClass
+ assert ctype.TypeArgs.Count == ctype.ResolvedClass.TypeArgs.Count; // follows from the fact that ctype was resolved
+ MemberDecl member;
+ if (!classMembers[ctype.ResolvedClass].TryGetValue(memberName, out member)) {
+ Error(tok, "member {0} does not exist in class {1}", memberName, ctype.Name);
+ } else {
+ return (!)member;
+ }
+ }
+ ctype = null;
+ return null;
+ }
+
+ Type! SubstType(Type! type, Dictionary<TypeParameter!,Type!>! subst) {
+ if (type is BasicType) {
+ return type;
+ } else if (type is CollectionType) {
+ CollectionType t = (CollectionType)type;
+ Type arg = SubstType(t.Arg, subst);
+ if (arg == t.Arg) {
+ return type;
+ } else if (type is SetType) {
+ return new SetType(arg);
+ } else if (type is SeqType) {
+ return new SeqType(arg);
+ } else {
+ assert false; // unexpected collection type
+ }
+ } else if (type is ClassType) {
+ ClassType t = (ClassType)type;
+ if (t.ResolvedParam != null) {
+ assert t.TypeArgs.Count == 0;
+ Type s;
+ if (subst.TryGetValue(t.ResolvedParam, out s)) {
+ return (!)s;
+ } else {
+ return type;
+ }
+ } else if (t.ResolvedClass != null) {
+ List<Type!> newArgs = null; // allocate it lazily
+ for (int i = 0; i < t.TypeArgs.Count; i++) {
+ Type p = t.TypeArgs[i];
+ Type s = SubstType(p, subst);
+ if (s != p && newArgs == null) {
+ // lazily construct newArgs
+ newArgs = new List<Type!>();
+ for (int j = 0; j < i; j++) {
+ newArgs.Add(t.TypeArgs[j]);
+ }
+ }
+ if (newArgs != null) {
+ newArgs.Add(s);
+ }
+ }
+ if (newArgs == null) {
+ // there were no substitutions
+ return type;
+ } else {
+ return new ClassType(t.tok, t.Name, t.ResolvedClass, newArgs);
+ }
+ } else {
+ // there's neither a resolved param nor a resolved class, which means the ClassType wasn't
+ // properly resolved; just return it
+ return type;
+ }
+ } else if (type is TypeProxy) {
+ TypeProxy t = (TypeProxy)type;
+ if (t.T == null) {
+ return type;
+ } else {
+ // bypass the proxy
+ return SubstType(t.T, subst);
+ }
+ } else {
+ assert false; // unexpected type
+ }
+ }
+
+ public static ClassType! GetThisType(Token! tok, ClassDecl! cl) {
+ List<Type!> args = new List<Type!>();
+ foreach (TypeParameter tp in cl.TypeArgs) {
+ args.Add(new ClassType(tok, tp.Name, tp));
+ }
+ return new ClassType(tok, cl.Name, cl, args);
+ }
+
+ /// <summary>
+ /// "twoState" implies that "old" and "fresh" expressions are allowed
+ /// </summary>
+ void ResolveExpression(Expression! expr, bool twoState)
+ requires currentClass != null;
+ ensures expr.Type != null;
+ {
+ if (expr.Type != null) {
+ // expression has already been resovled
+ return;
+ }
+
+ // The following cases will resolve the subexpressions and will attempt to assign a type of expr. However, if errors occur
+ // and it cannot be determined what the type of expr is, then it is fine to leave expr.Type as null. In that case, the end
+ // of this method will assign proxy type to the expression, which reduces the number of error messages that are produced
+ // while type checking the rest of the program.
+
+ if (expr is LiteralExpr) {
+ LiteralExpr e = (LiteralExpr)expr;
+ if (e.Value == null) {
+ e.Type = new ObjectTypeProxy();
+ } else if (e.Value is int) {
+ e.Type = Type.Int;
+ } else if (e.Value is bool) {
+ e.Type = Type.Bool;
+ } else {
+ assert false; // unexpected literal type
+ }
+
+ } else if (expr is ThisExpr) {
+ expr.Type = GetThisType(expr.tok, currentClass);
+
+ } else if (expr is IdentifierExpr) {
+ IdentifierExpr e = (IdentifierExpr)expr;
+ e.Var = scope.Find(e.Name);
+ if (e.Var == null) {
+ Error(expr, "Identifier does not denote a local variable, parameter, or bound variable: {0}", e.Name);
+ } else {
+ expr.Type = e.Var.Type;
+ }
+
+ } else if (expr is DisplayExpression) {
+ DisplayExpression e = (DisplayExpression)expr;
+ Type elementType = new InferredTypeProxy();
+ foreach (Expression ee in e.Elements) {
+ ResolveExpression(ee, twoState);
+ assert ee.Type != null; // follows from postcondition of ResolveExpression
+ if (!UnifyTypes(elementType, ee.Type)) {
+ Error(ee, "All elements of display must be of the same type (got {0}, but type of previous elements is {1})", ee.Type, elementType);
+ }
+ }
+ if (expr is SetDisplayExpr) {
+ expr.Type = new SetType(elementType);
+ } else {
+ expr.Type = new SeqType(elementType);
+ }
+
+ } else if (expr is FieldSelectExpr) {
+ FieldSelectExpr e = (FieldSelectExpr)expr;
+ ResolveExpression(e.Obj, twoState);
+ assert e.Obj.Type != null; // follows from postcondition of ResolveExpression
+ ClassType ctype;
+ MemberDecl member = ResolveMember(expr.tok, e.Obj.Type, e.FieldName, out ctype);
+ if (member == null) {
+ // error has already been reported by ResolveMember
+ } else if (!(member is Field)) {
+ Error(expr, "member {0} in class {1} does not refer to a field", e.FieldName, ((!)ctype).Name);
+ } else {
+ assert ctype != null && ctype.ResolvedClass != null; // follows from postcondition of ResolveMember
+ e.Field = (Field)member;
+ // build the type substitution map
+ Dictionary<TypeParameter!,Type!> subst = new Dictionary<TypeParameter!,Type!>();
+ for (int i = 0; i < ctype.TypeArgs.Count; i++) {
+ subst.Add(ctype.ResolvedClass.TypeArgs[i], ctype.TypeArgs[i]);
+ }
+ e.Type = SubstType(e.Field.Type, subst);
+ }
+
+ } else if (expr is SeqSelectExpr) {
+ SeqSelectExpr e = (SeqSelectExpr)expr;
+ bool seqErr = false;
+ ResolveExpression(e.Seq, twoState);
+ assert e.Seq.Type != null; // follows from postcondition of ResolveExpression
+ Type elementType = new InferredTypeProxy();
+ if (!UnifyTypes(e.Seq.Type, new SeqType(elementType))) {
+ Error(expr, "sequence selection requires a sequence (got {0})", e.Seq.Type);
+ seqErr = true;
+ }
+ if (e.E0 != null) {
+ ResolveExpression(e.E0, twoState);
+ assert e.E0.Type != null; // follows from postcondition of ResolveExpression
+ if (!UnifyTypes(e.E0.Type, Type.Int)) {
+ Error(e.E0, "sequence selections requires integer indices (got {0})", e.E0.Type);
+ }
+ }
+ if (e.E1 != null) {
+ ResolveExpression(e.E1, twoState);
+ assert e.E1.Type != null; // follows from postcondition of ResolveExpression
+ if (!UnifyTypes(e.E1.Type, Type.Int)) {
+ Error(e.E1, "sequence selections requires integer indices (got {0})", e.E1.Type);
+ }
+ }
+ if (!seqErr) {
+ if (e.SelectOne) {
+ expr.Type = elementType;
+ } else {
+ expr.Type = e.Seq.Type;
+ }
+ }
+
+ } else if (expr is FunctionCallExpr) {
+ FunctionCallExpr e = (FunctionCallExpr)expr;
+ ResolveExpression(e.Receiver, twoState);
+ assert e.Receiver.Type != null; // follows from postcondition of ResolveExpression
+ ClassType ctype;
+ MemberDecl member = ResolveMember(expr.tok, e.Receiver.Type, e.Name, out ctype);
+ if (member == null) {
+ // error has already been reported by ResolveMember
+ } else if (!(member is Function)) {
+ Error(expr, "member {0} in class {1} does not refer to a function", e.Name, ((!)ctype).Name);
+ } else {
+ Function function = (Function)member;
+ e.Function = function;
+ if (function.Formals.Count != e.Args.Count) {
+ Error(expr, "wrong number of function arguments (got {0}, expected {1})", e.Args.Count, function.Formals.Count);
+ } else {
+ assert ctype != null; // follows from postcondition of ResolveMember
+ // build the type substitution map
+ Dictionary<TypeParameter!,Type!> subst = new Dictionary<TypeParameter!,Type!>();
+ for (int i = 0; i < ctype.TypeArgs.Count; i++) {
+ subst.Add(((!)ctype.ResolvedClass).TypeArgs[i], ctype.TypeArgs[i]);
+ }
+ foreach (TypeParameter p in function.TypeArgs) {
+ subst.Add(p, new ParamTypeProxy(p));
+ }
+ // type check the arguments
+ for (int i = 0; i < function.Formals.Count; i++) {
+ Expression farg = e.Args[i];
+ ResolveExpression(farg, twoState);
+ assert farg.Type != null; // follows from postcondition of ResolveExpression
+ UnifyTypes(farg.Type, SubstType(function.Formals[i].Type, subst));
+ }
+ expr.Type = SubstType(function.ResultType, subst);
+ }
+ }
+
+ } else if (expr is OldExpr) {
+ OldExpr e = (OldExpr)expr;
+ if (!twoState) {
+ Error(expr, "old expressions are not allowed in this context");
+ }
+ ResolveExpression(e.E, twoState);
+ expr.Type = e.E.Type;
+
+ } else if (expr is FreshExpr) {
+ FreshExpr e = (FreshExpr)expr;
+ if (!twoState) {
+ Error(expr, "fresh expressions are not allowed in this context");
+ }
+ ResolveExpression(e.E, twoState);
+ // the type of e.E must be either an object or a collection of objects
+ Type t = e.E.Type;
+ assert t != null; // follows from postcondition of ResolveExpression
+ if (t is CollectionType) {
+ t = ((CollectionType)t).Arg;
+ }
+ if (t is ObjectType) {
+ // fine
+ } else if (ClassType.DenotesClass(t) != null) {
+ // fine
+ } else {
+ Error(expr, "the argument of a fresh expression must denote an object or a collection of objects (instead got {0})", e.E.Type);
+ }
+ expr.Type = Type.Bool;
+
+ } else if (expr is UnaryExpr) {
+ UnaryExpr e = (UnaryExpr)expr;
+ ResolveExpression(e.E, twoState);
+ assert e.E.Type != null; // follows from postcondition of ResolveExpression
+ switch (e.Op) {
+ case UnaryExpr.Opcode.Not:
+ if (!UnifyTypes(e.E.Type, Type.Bool)) {
+ Error(expr, "logical negation expects a boolean argument (instead got {0})", e.E.Type);
+ }
+ expr.Type = Type.Bool;
+ break;
+ case UnaryExpr.Opcode.SeqLength:
+ if (!UnifyTypes(e.E.Type, new SeqType(new InferredTypeProxy()))) {
+ Error(expr, "sequence-length operator expects a sequence argument (instead got {0})", e.E.Type);
+ }
+ expr.Type = Type.Int;
+ break;
+ default:
+ assert false; // unexpected unary operator
+ }
+
+ } else if (expr is BinaryExpr) {
+ BinaryExpr e = (BinaryExpr)expr;
+ ResolveExpression(e.E0, twoState);
+ assert e.E0.Type != null; // follows from postcondition of ResolveExpression
+ ResolveExpression(e.E1, twoState);
+ assert e.E1.Type != null; // follows from postcondition of ResolveExpression
+ switch (e.Op) {
+ case BinaryExpr.Opcode.Iff:
+ case BinaryExpr.Opcode.Imp:
+ case BinaryExpr.Opcode.And:
+ case BinaryExpr.Opcode.Or:
+ if (!UnifyTypes(e.E0.Type, Type.Bool)) {
+ Error(expr, "first argument to {0} must be of type bool (instead got {1})", BinaryExpr.OpcodeString(e.Op), e.E0.Type);
+ }
+ if (!UnifyTypes(e.E1.Type, Type.Bool)) {
+ Error(expr, "second argument to {0} must be of type bool (instead got {1})", BinaryExpr.OpcodeString(e.Op), e.E1.Type);
+ }
+ expr.Type = Type.Bool;
+ break;
+
+ case BinaryExpr.Opcode.Eq:
+ case BinaryExpr.Opcode.Neq:
+ if (!UnifyTypes(e.E0.Type, e.E1.Type)) {
+ Error(expr, "arguments must have the same type (got {0} and {1})", e.E0.Type, e.E1.Type);
+ }
+ expr.Type = Type.Bool;
+ break;
+
+ case BinaryExpr.Opcode.Disjoint:
+ if (!UnifyTypes(e.E0.Type, new SetType(new InferredTypeProxy()))) {
+ Error(expr, "arguments must be of a set type (got {0})", e.E0.Type);
+ }
+ if (!UnifyTypes(e.E0.Type, e.E1.Type)) {
+ Error(expr, "arguments must have the same type (got {0} and {1})", e.E0.Type, e.E1.Type);
+ }
+ expr.Type = Type.Bool;
+ break;
+
+ case BinaryExpr.Opcode.Lt:
+ case BinaryExpr.Opcode.Le:
+ case BinaryExpr.Opcode.Add:
+ {
+ bool err = false;
+ if (!UnifyTypes(e.E0.Type, new OperationTypeProxy(true))) {
+ Error(expr, "arguments to {0} must be int or a collection type (instead got {1})", BinaryExpr.OpcodeString(e.Op), e.E0.Type);
+ err = true;
+ }
+ if (!UnifyTypes(e.E1.Type, e.E0.Type)) {
+ Error(expr, "arguments to {0} must have the same type (got {1} and {2})", BinaryExpr.OpcodeString(e.Op), e.E0.Type, e.E1.Type);
+ err = true;
+ }
+ if (e.Op != BinaryExpr.Opcode.Add) {
+ expr.Type = Type.Bool;
+ } else if (!err) {
+ expr.Type = e.E0.Type;
+ }
+ }
+ break;
+
+ case BinaryExpr.Opcode.Sub:
+ case BinaryExpr.Opcode.Mul:
+ case BinaryExpr.Opcode.Gt:
+ case BinaryExpr.Opcode.Ge:
+ {
+ bool err = false;
+ if (!UnifyTypes(e.E0.Type, new OperationTypeProxy(false))) {
+ Error(expr, "arguments to {0} must be int or a set (instead got {1})", BinaryExpr.OpcodeString(e.Op), e.E0.Type);
+ err = true;
+ }
+ if (!UnifyTypes(e.E1.Type, e.E0.Type)) {
+ Error(expr, "arguments to {0} must have the same type (got {1} and {2})", BinaryExpr.OpcodeString(e.Op), e.E0.Type, e.E1.Type);
+ err = true;
+ }
+ if (e.Op == BinaryExpr.Opcode.Gt || e.Op == BinaryExpr.Opcode.Ge) {
+ expr.Type = Type.Bool;
+ } else if (!err) {
+ expr.Type = e.E0.Type;
+ }
+ }
+ break;
+
+ case BinaryExpr.Opcode.In:
+ if (!UnifyTypes(e.E1.Type, new CollectionTypeProxy(e.E0.Type))) {
+ Error(expr, "second argument to {0} must be a set or sequence of type {1} (instead got {2})", BinaryExpr.OpcodeString(e.Op), e.E0.Type, e.E1.Type);
+ }
+ expr.Type = Type.Bool;
+ break;
+
+ case BinaryExpr.Opcode.Div:
+ case BinaryExpr.Opcode.Mod:
+ if (!UnifyTypes(e.E0.Type, Type.Int)) {
+ Error(expr, "first argument to {0} must be of type int (instead got {1})", BinaryExpr.OpcodeString(e.Op), e.E0.Type);
+ }
+ if (!UnifyTypes(e.E1.Type, Type.Int)) {
+ Error(expr, "second argument to {0} must be of type int (instead got {1})", BinaryExpr.OpcodeString(e.Op), e.E1.Type);
+ }
+ expr.Type = Type.Int;
+ break;
+
+ default:
+ assert false; // unexpected operator
+ }
+ e.ResolvedOp = ResolveOp(e.Op, e.E1.Type);
+
+ } else if (expr is QuantifierExpr) {
+ QuantifierExpr e = (QuantifierExpr)expr;
+ scope.PushMarker();
+ foreach (BoundVar v in e.BoundVars) {
+ if (!scope.Push(v.Name, v)) {
+ Error(v, "Duplicate parameter name: {0}", v.Name);
+ }
+ ResolveType(v.Type);
+ }
+ ResolveExpression(e.Body, twoState);
+ assert e.Body.Type != null; // follows from postcondition of ResolveExpression
+ if (!UnifyTypes(e.Body.Type, Type.Bool)) {
+ Error(expr, "body of quantifier must be of type bool (instead got {0})", e.Body.Type);
+ }
+ // Since the body is more likely to infer the types of the bound variables, resolve it
+ // first (above) and only then resolve the attributes and triggers (below).
+ ResolveAttributes(e.Attributes, twoState);
+ ResolveTriggers(e.Trigs, twoState);
+ scope.PopMarker();
+ expr.Type = Type.Bool;
+
+ } else if (expr is ITEExpr) {
+ ITEExpr e = (ITEExpr)expr;
+ assert !twoState;
+ ResolveExpression(e.Test, twoState);
+ assert e.Test.Type != null; // follows from postcondition of ResolveExpression
+ ResolveExpression(e.Thn, twoState);
+ assert e.Thn.Type != null; // follows from postcondition of ResolveExpression
+ ResolveExpression(e.Els, twoState);
+ assert e.Els.Type != null; // follows from postcondition of ResolveExpression
+ if (!UnifyTypes(e.Test.Type, Type.Bool)) {
+ Error(expr, "guard condition in if-then-else expression must be a boolean (instead got {0})", e.Test.Type);
+ }
+ if (!UnifyTypes(e.Thn.Type, Type.Bool)) {
+ Error(expr, "the then branch of an if-then-else expression must be a boolean (instead got {0})", e.Thn.Type);
+ }
+ if (!UnifyTypes(e.Els.Type, Type.Bool)) {
+ Error(expr, "the else branch of an if-then-else expression must be a boolean (instead got {0})", e.Els.Type);
+ }
+ expr.Type = Type.Bool;
+
+ } else {
+ assert false; // unexpected expression
+ }
+
+ if (expr.Type == null) {
+ // some resolution error occurred
+ expr.Type = Type.Flexible;
+ }
+ }
+
+ /// <summary>
+ /// Note: this method is allowed to be called even if "type" does not make sense for "op", as might be the case if
+ /// resolution of the binary expression failed. If so, an arbitrary resolved opcode is returned.
+ /// </summary>
+ BinaryExpr.ResolvedOpcode ResolveOp(BinaryExpr.Opcode op, Type! operandType) {
+ switch (op) {
+ case BinaryExpr.Opcode.Iff: return BinaryExpr.ResolvedOpcode.Iff;
+ case BinaryExpr.Opcode.Imp: return BinaryExpr.ResolvedOpcode.Imp;
+ case BinaryExpr.Opcode.And: return BinaryExpr.ResolvedOpcode.And;
+ case BinaryExpr.Opcode.Or: return BinaryExpr.ResolvedOpcode.Or;
+ case BinaryExpr.Opcode.Eq:
+ if (operandType is SetType) {
+ return BinaryExpr.ResolvedOpcode.SetEq;
+ } else if (operandType is SeqType) {
+ return BinaryExpr.ResolvedOpcode.SeqEq;
+ } else {
+ return BinaryExpr.ResolvedOpcode.EqCommon;
+ }
+ case BinaryExpr.Opcode.Neq:
+ if (operandType is SetType) {
+ return BinaryExpr.ResolvedOpcode.SetNeq;
+ } else if (operandType is SeqType) {
+ return BinaryExpr.ResolvedOpcode.SeqNeq;
+ } else {
+ return BinaryExpr.ResolvedOpcode.NeqCommon;
+ }
+ case BinaryExpr.Opcode.Disjoint: return BinaryExpr.ResolvedOpcode.Disjoint;
+ case BinaryExpr.Opcode.Lt:
+ if (operandType is SetType) {
+ return BinaryExpr.ResolvedOpcode.ProperSubset;
+ } else if (operandType is SeqType) {
+ return BinaryExpr.ResolvedOpcode.ProperPrefix;
+ } else {
+ return BinaryExpr.ResolvedOpcode.Lt;
+ }
+ case BinaryExpr.Opcode.Le:
+ if (operandType is SetType) {
+ return BinaryExpr.ResolvedOpcode.Subset;
+ } else if (operandType is SeqType) {
+ return BinaryExpr.ResolvedOpcode.Prefix;
+ } else {
+ return BinaryExpr.ResolvedOpcode.Le;
+ }
+ case BinaryExpr.Opcode.Add:
+ if (operandType is SetType) {
+ return BinaryExpr.ResolvedOpcode.Union;
+ } else if (operandType is SeqType) {
+ return BinaryExpr.ResolvedOpcode.Concat;
+ } else {
+ return BinaryExpr.ResolvedOpcode.Add;
+ }
+ case BinaryExpr.Opcode.Sub:
+ if (operandType is SetType) {
+ return BinaryExpr.ResolvedOpcode.SetDifference;
+ } else {
+ return BinaryExpr.ResolvedOpcode.Sub;
+ }
+ case BinaryExpr.Opcode.Mul:
+ if (operandType is SetType) {
+ return BinaryExpr.ResolvedOpcode.Intersection;
+ } else {
+ return BinaryExpr.ResolvedOpcode.Mul;
+ }
+ case BinaryExpr.Opcode.Gt:
+ if (operandType is SetType) {
+ return BinaryExpr.ResolvedOpcode.ProperSuperset;
+ } else {
+ return BinaryExpr.ResolvedOpcode.Gt;
+ }
+ case BinaryExpr.Opcode.Ge:
+ if (operandType is SetType) {
+ return BinaryExpr.ResolvedOpcode.Superset;
+ } else {
+ return BinaryExpr.ResolvedOpcode.Ge;
+ }
+ case BinaryExpr.Opcode.In:
+ if (operandType is SetType) {
+ return BinaryExpr.ResolvedOpcode.InSet;
+ } else {
+ return BinaryExpr.ResolvedOpcode.InSeq;
+ }
+ case BinaryExpr.Opcode.Div: return BinaryExpr.ResolvedOpcode.Div;
+ case BinaryExpr.Opcode.Mod: return BinaryExpr.ResolvedOpcode.Mod;
+ default:
+ assert false; // unexpected operator
+ }
+ }
+ }
+
+ class Scope<Thing> where Thing : class {
+ [Rep] readonly List<string>! names = new List<string>(); // a null means a marker
+ [Rep] readonly List<Thing?>! things = new List<Thing?>();
+ invariant names.Count == things.Count;
+
+ public void PushMarker() {
+ names.Add(null);
+ things.Add(null);
+ }
+
+ public void PopMarker() {
+ int n = names.Count;
+ while (true) {
+ n--;
+ if (names[n] == null) {
+ break;
+ }
+ }
+ names.RemoveRange(n, names.Count - n);
+ things.RemoveRange(n, things.Count - n);
+ }
+
+ // Pushes name-->var association and returns "true", if name has not already been pushed since the last marker.
+ // If name already has been pushed since the last marker, does nothing and returns "false".
+ public bool Push(string! name, Thing! thing) {
+ if (Find(name, true) != null) {
+ return false;
+ } else {
+ names.Add(name);
+ things.Add(thing);
+ return true;
+ }
+ }
+
+ Thing? Find(string! name, bool topScopeOnly) {
+ for (int n = names.Count; 0 <= --n; ) {
+ if (names[n] == null) {
+ if (topScopeOnly) {
+ return null; // no present
+ }
+ } else if (names[n] == name) {
+ Thing t = things[n];
+ assert t != null;
+ return t;
+ }
+ }
+ return null; // not present
+ }
+
+ public Thing? Find(string! name) {
+ return Find(name, false);
+ }
+ }
+}
diff --git a/Source/Dafny/Scanner.ssc b/Source/Dafny/Scanner.ssc
new file mode 100644
index 00000000..e026ca7e
--- /dev/null
+++ b/Source/Dafny/Scanner.ssc
@@ -0,0 +1,491 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using System.IO;
+using System.Collections;
+using System.Collections.Generic;
+using System.Text;
+using Microsoft.Contracts;
+using Bpl = Microsoft.Boogie;
+using BoogiePL;
+
+
+namespace Microsoft.Dafny {
+
+ [Immutable]
+ public class Token : Bpl.Token {
+ public Token();
+ public Token(int linenum, int colnum) {
+ base(linenum, colnum);
+ }
+ public new static Token! NoToken = new Token();
+ }
+
+}
+
+namespace Microsoft.Dafny {
+
+
+public class Scanner {
+ const char EOF = '\0';
+ const char CR = '\r';
+ const char LF = '\n';
+
+ [Microsoft.Contracts.Verify(false)]
+ static Scanner() {
+ start[0] = 50;
+ start[33] = 31;
+ start[34] = 3;
+ start[37] = 40;
+ start[38] = 25;
+ start[39] = 1;
+ start[40] = 12;
+ start[41] = 13;
+ start[42] = 15;
+ start[43] = 37;
+ start[44] = 7;
+ start[45] = 38;
+ start[46] = 44;
+ start[47] = 39;
+ start[48] = 2;
+ start[49] = 2;
+ start[50] = 2;
+ start[51] = 2;
+ start[52] = 2;
+ start[53] = 2;
+ start[54] = 2;
+ start[55] = 2;
+ start[56] = 2;
+ start[57] = 2;
+ start[58] = 9;
+ start[59] = 8;
+ start[60] = 10;
+ start[61] = 21;
+ start[62] = 11;
+ start[63] = 1;
+ start[65] = 1;
+ start[66] = 1;
+ start[67] = 1;
+ start[68] = 1;
+ start[69] = 1;
+ start[70] = 1;
+ start[71] = 1;
+ start[72] = 1;
+ start[73] = 1;
+ start[74] = 1;
+ start[75] = 1;
+ start[76] = 1;
+ start[77] = 1;
+ start[78] = 1;
+ start[79] = 1;
+ start[80] = 1;
+ start[81] = 1;
+ start[82] = 1;
+ start[83] = 1;
+ start[84] = 1;
+ start[85] = 1;
+ start[86] = 1;
+ start[87] = 1;
+ start[88] = 1;
+ start[89] = 1;
+ start[90] = 1;
+ start[91] = 42;
+ start[92] = 1;
+ start[93] = 43;
+ start[95] = 1;
+ start[96] = 1;
+ start[97] = 1;
+ start[98] = 1;
+ start[99] = 1;
+ start[100] = 1;
+ start[101] = 1;
+ start[102] = 1;
+ start[103] = 1;
+ start[104] = 1;
+ start[105] = 1;
+ start[106] = 1;
+ start[107] = 1;
+ start[108] = 1;
+ start[109] = 1;
+ start[110] = 1;
+ start[111] = 1;
+ start[112] = 1;
+ start[113] = 1;
+ start[114] = 1;
+ start[115] = 1;
+ start[116] = 1;
+ start[117] = 1;
+ start[118] = 1;
+ start[119] = 1;
+ start[120] = 1;
+ start[121] = 1;
+ start[122] = 1;
+ start[123] = 5;
+ start[124] = 16;
+ start[125] = 6;
+ start[172] = 41;
+ start[8226] = 49;
+ start[8658] = 24;
+ start[8660] = 20;
+ start[8704] = 46;
+ start[8707] = 47;
+ start[8743] = 27;
+ start[8744] = 29;
+ start[8800] = 34;
+ start[8804] = 35;
+ start[8805] = 36;
+ }
+ const int noSym = 86;
+ static short[] start = new short[16385];
+
+
+
+ static Token/*!*/ t; // current token
+ static char ch; // current input character
+ static int pos; // column number of current character
+ static int line; // line number of current character
+ static int lineStart; // start position of current line
+ static Queue! oldEols; // EOLs that appeared in a comment;
+ static BitArray/*!*/ ignore; // set of characters to be ignored by the scanner
+ static string Filename;
+
+ ///<summary>
+ ///Initializes the scanner. Note: first fill the Buffer.
+ ///</summary>
+ ///<param name="filename">File name used for error reporting</param>
+ public static void Init (string filename) {
+ Filename = filename;
+ pos = -1; line = 1; lineStart = 0;
+ oldEols = new Queue();
+ NextCh();
+ ignore = new BitArray(16384);
+ ignore[9] = true; ignore[10] = true; ignore[13] = true; ignore[32] = true;
+
+ }
+
+ private static void NextCh() {
+ if (oldEols.Count > 0) {
+ ch = (char) ((!)oldEols.Dequeue());
+ } else {
+ while (true) {
+ ch = (char)BoogiePL.Buffer.Read(); pos++;
+ if (ch == BoogiePL.Buffer.eof) {
+ ch = EOF;
+ } else if (ch == LF) {
+ line++;
+ lineStart = pos + 1;
+
+ } else if (ch == '#' && pos == lineStart) {
+ int prLine = line;
+ int prColumn = pos - lineStart; // which is 0
+
+ string hashLine = BoogiePL.Buffer.ReadToEOL(); pos += hashLine.Length;
+ line++;
+ lineStart = pos + 1;
+
+ hashLine = hashLine.TrimEnd(null);
+ if (hashLine.StartsWith("line ") || hashLine == "line") {
+ // parse #line pragma: #line num [filename]
+ string h = hashLine.Substring(4).TrimStart(null);
+ int x = h.IndexOf(' ');
+ if (x == -1) {
+ x = h.Length; // this will be convenient below when we look for a filename
+ }
+ try {
+ int li = int.Parse(h.Substring(0, x));
+
+ h = h.Substring(x).Trim();
+
+ // act on #line
+ line = li;
+ if (h.Length != 0) {
+ // a filename was specified
+ Filename = h;
+ }
+ continue; // successfully parsed and acted on the #line pragma
+
+ } catch (System.FormatException) {
+ // just fall down through to produce an error message
+ }
+ Errors.SemErr(Filename, prLine, prColumn, "Malformed (#line num [filename]) pragma: #" + hashLine);
+ continue;
+ }
+
+ Errors.SemErr(Filename, prLine, prColumn, "Unrecognized pragma: #" + hashLine);
+ continue;
+ }
+ return;
+ }
+ }
+ }
+
+
+ static bool Comment0() {
+ int level = 1, line0 = line, lineStart0 = lineStart;
+ NextCh();
+ if (ch == '/') {
+ NextCh();
+ for(;;) {
+ if (ch == 10) {
+ level--;
+ if (level == 0) {
+ while(line0 < line) {oldEols.Enqueue('\r'); oldEols.Enqueue('\n'); line0++;}
+ NextCh(); return true;
+ }
+ NextCh();
+ } else if (ch == EOF) return false;
+ else NextCh();
+ }
+ } else {
+ if (ch==CR) {line--; lineStart = lineStart0;}
+ pos = pos - 2; Buffer.Pos = pos+1; NextCh();
+ }
+ return false;
+ }
+
+ static bool Comment1() {
+ int level = 1, line0 = line, lineStart0 = lineStart;
+ NextCh();
+ if (ch == '*') {
+ NextCh();
+ for(;;) {
+ if (ch == '*') {
+ NextCh();
+ if (ch == '/') {
+ level--;
+ if (level == 0) {
+ while(line0 < line) {oldEols.Enqueue('\r'); oldEols.Enqueue('\n'); line0++;}
+ NextCh(); return true;
+ }
+ NextCh();
+ }
+ } else if (ch == '/') {
+ NextCh();
+ if (ch == '*') {
+ level++; NextCh();
+ }
+ } else if (ch == EOF) return false;
+ else NextCh();
+ }
+ } else {
+ if (ch==CR) {line--; lineStart = lineStart0;}
+ pos = pos - 2; Buffer.Pos = pos+1; NextCh();
+ }
+ return false;
+ }
+
+
+ static void CheckLiteral() {
+ switch (t.val) {
+ case "class": t.kind = 4; break;
+ case "var": t.kind = 7; break;
+ case "frame": t.kind = 13; break;
+ case "method": t.kind = 14; break;
+ case "returns": t.kind = 15; break;
+ case "modifies": t.kind = 16; break;
+ case "free": t.kind = 17; break;
+ case "requires": t.kind = 18; break;
+ case "ensures": t.kind = 19; break;
+ case "bool": t.kind = 22; break;
+ case "int": t.kind = 23; break;
+ case "object": t.kind = 24; break;
+ case "set": t.kind = 25; break;
+ case "seq": t.kind = 26; break;
+ case "function": t.kind = 27; break;
+ case "use": t.kind = 28; break;
+ case "reads": t.kind = 29; break;
+ case "if": t.kind = 30; break;
+ case "else": t.kind = 31; break;
+ case "label": t.kind = 32; break;
+ case "break": t.kind = 33; break;
+ case "return": t.kind = 34; break;
+ case "new": t.kind = 36; break;
+ case "havoc": t.kind = 37; break;
+ case "while": t.kind = 38; break;
+ case "invariant": t.kind = 39; break;
+ case "decreases": t.kind = 40; break;
+ case "call": t.kind = 42; break;
+ case "foreach": t.kind = 43; break;
+ case "in": t.kind = 44; break;
+ case "assert": t.kind = 46; break;
+ case "assume": t.kind = 47; break;
+ case "false": t.kind = 70; break;
+ case "true": t.kind = 71; break;
+ case "null": t.kind = 72; break;
+ case "fresh": t.kind = 73; break;
+ case "this": t.kind = 78; break;
+ case "old": t.kind = 79; break;
+ case "forall": t.kind = 80; break;
+ case "exists": t.kind = 82; break;
+ default: break;
+
+ }
+ }
+
+ public static Token/*!*/ Scan() {
+ while (ignore[ch]) { NextCh(); }
+ if (ch == '/' && Comment0() || ch == '/' && Comment1() ) return Scan();
+ t = new Token();
+ t.pos = pos; t.col = pos - lineStart + 1; t.line = line; t.filename = Filename;
+ int state = (/*^ (!) ^*/ start)[ch];
+ StringBuilder buf = new StringBuilder(16);
+ buf.Append(ch); NextCh();
+
+ switch (state) {
+ case 0: {t.kind = noSym; goto done;} // NextCh already done
+ case 1:
+ if ((ch == 39 || ch >= '0' && ch <= '9' || ch == '?' || ch >= 'A' && ch <= 'Z' || ch == 92 || ch >= '_' && ch <= 'z')) {buf.Append(ch); NextCh(); goto case 1;}
+ else {t.kind = 1; t.val = buf.ToString(); CheckLiteral(); return t;}
+ case 2:
+ if ((ch >= '0' && ch <= '9')) {buf.Append(ch); NextCh(); goto case 2;}
+ else {t.kind = 2; goto done;}
+ case 3:
+ if ((ch == '"')) {buf.Append(ch); NextCh(); goto case 4;}
+ else if ((ch >= ' ' && ch <= '!' || ch >= '#' && ch <= '~')) {buf.Append(ch); NextCh(); goto case 3;}
+ else {t.kind = noSym; goto done;}
+ case 4:
+ {t.kind = 3; goto done;}
+ case 5:
+ {t.kind = 5; goto done;}
+ case 6:
+ {t.kind = 6; goto done;}
+ case 7:
+ {t.kind = 8; goto done;}
+ case 8:
+ {t.kind = 9; goto done;}
+ case 9:
+ if (ch == '=') {buf.Append(ch); NextCh(); goto case 14;}
+ else if (ch == ':') {buf.Append(ch); NextCh(); goto case 48;}
+ else {t.kind = 10; goto done;}
+ case 10:
+ if (ch == '=') {buf.Append(ch); NextCh(); goto case 17;}
+ else {t.kind = 11; goto done;}
+ case 11:
+ if (ch == '=') {buf.Append(ch); NextCh(); goto case 30;}
+ else {t.kind = 12; goto done;}
+ case 12:
+ {t.kind = 20; goto done;}
+ case 13:
+ {t.kind = 21; goto done;}
+ case 14:
+ {t.kind = 35; goto done;}
+ case 15:
+ {t.kind = 41; goto done;}
+ case 16:
+ if (ch == '|') {buf.Append(ch); NextCh(); goto case 28;}
+ else {t.kind = 45; goto done;}
+ case 17:
+ if (ch == '=') {buf.Append(ch); NextCh(); goto case 18;}
+ else {t.kind = 57; goto done;}
+ case 18:
+ if (ch == '>') {buf.Append(ch); NextCh(); goto case 19;}
+ else {t.kind = noSym; goto done;}
+ case 19:
+ {t.kind = 48; goto done;}
+ case 20:
+ {t.kind = 49; goto done;}
+ case 21:
+ if (ch == '=') {buf.Append(ch); NextCh(); goto case 22;}
+ else {t.kind = noSym; goto done;}
+ case 22:
+ if (ch == '>') {buf.Append(ch); NextCh(); goto case 23;}
+ else {t.kind = 56; goto done;}
+ case 23:
+ {t.kind = 50; goto done;}
+ case 24:
+ {t.kind = 51; goto done;}
+ case 25:
+ if (ch == '&') {buf.Append(ch); NextCh(); goto case 26;}
+ else {t.kind = noSym; goto done;}
+ case 26:
+ {t.kind = 52; goto done;}
+ case 27:
+ {t.kind = 53; goto done;}
+ case 28:
+ {t.kind = 54; goto done;}
+ case 29:
+ {t.kind = 55; goto done;}
+ case 30:
+ {t.kind = 58; goto done;}
+ case 31:
+ if (ch == '=') {buf.Append(ch); NextCh(); goto case 32;}
+ else if (ch == '!') {buf.Append(ch); NextCh(); goto case 33;}
+ else {t.kind = 68; goto done;}
+ case 32:
+ {t.kind = 59; goto done;}
+ case 33:
+ {t.kind = 60; goto done;}
+ case 34:
+ {t.kind = 61; goto done;}
+ case 35:
+ {t.kind = 62; goto done;}
+ case 36:
+ {t.kind = 63; goto done;}
+ case 37:
+ {t.kind = 64; goto done;}
+ case 38:
+ {t.kind = 65; goto done;}
+ case 39:
+ {t.kind = 66; goto done;}
+ case 40:
+ {t.kind = 67; goto done;}
+ case 41:
+ {t.kind = 69; goto done;}
+ case 42:
+ {t.kind = 74; goto done;}
+ case 43:
+ {t.kind = 75; goto done;}
+ case 44:
+ if (ch == '.') {buf.Append(ch); NextCh(); goto case 45;}
+ else {t.kind = 76; goto done;}
+ case 45:
+ {t.kind = 77; goto done;}
+ case 46:
+ {t.kind = 81; goto done;}
+ case 47:
+ {t.kind = 83; goto done;}
+ case 48:
+ {t.kind = 84; goto done;}
+ case 49:
+ {t.kind = 85; goto done;}
+ case 50: {t.kind = 0; goto done;}
+ }
+ done:
+ t.val = buf.ToString();
+ return t;
+ }
+
+} // end Scanner
+
+
+public delegate void ErrorProc(int n, string filename, int line, int col);
+
+public class Errors {
+ public static int count = 0; // number of errors detected
+ public static ErrorProc/*!*/ SynErr; // syntactic errors
+
+ public static void SemErr(string filename, int line, int col, string! msg) { // semantic errors
+ System.ConsoleColor color = System.Console.ForegroundColor;
+ System.Console.ForegroundColor = System.ConsoleColor.Red;
+ System.Console.WriteLine("{0}({1},{2}): Error: {3}", filename, line, col, msg);
+ System.Console.ForegroundColor = color;
+ count++;
+ }
+
+ public static void SemErr(Bpl.IToken! tok, string! msg) { // semantic errors
+ SemErr(tok.filename, tok.line, tok.col, msg);
+ }
+
+ public static void Exception (string s) {
+ System.ConsoleColor color = System.Console.ForegroundColor;
+ System.Console.ForegroundColor = System.ConsoleColor.Red;
+ System.Console.WriteLine(s);
+ System.Console.ForegroundColor = color;
+ System.Environment.Exit(0);
+ }
+
+} // Errors
+
+} // end namespace
diff --git a/Source/Dafny/Translator.ssc b/Source/Dafny/Translator.ssc
new file mode 100644
index 00000000..c5f85130
--- /dev/null
+++ b/Source/Dafny/Translator.ssc
@@ -0,0 +1,2446 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using System;
+using System.Collections.Generic;
+using Microsoft.Contracts;
+using Bpl = Microsoft.Boogie;
+
+// TODO: wellformedness checks for function bodies
+// TODO: totality checks for statements
+// TODO: totality checks for pre/post conditions
+
+namespace Microsoft.Dafny {
+ public class Translator {
+ public Translator() {
+ Bpl.Program boogieProgram = ReadPrelude();
+ if (boogieProgram != null) {
+ sink = boogieProgram;
+ predef = FindPredefinedDecls(boogieProgram);
+ }
+ }
+
+ // translation state
+ readonly Dictionary<ClassDecl!,Bpl.Constant!>! classes = new Dictionary<ClassDecl!,Bpl.Constant!>();
+ readonly Dictionary<Field!,Bpl.Constant!>! fields = new Dictionary<Field!,Bpl.Constant!>();
+ readonly Dictionary<Function!,Bpl.Function!>! functions = new Dictionary<Function!,Bpl.Function!>();
+ readonly Dictionary<Method!,Bpl.Procedure!>! methods = new Dictionary<Method!,Bpl.Procedure!>();
+
+ readonly Bpl.Program sink;
+ readonly PredefinedDecls predef;
+ internal class PredefinedDecls {
+ public readonly Bpl.Type! RefType;
+ private readonly Bpl.TypeCtorDecl! seqTypeCtor;
+ public Bpl.Type! SeqType(Token! tok, Bpl.Type! ty) {
+ return new Bpl.CtorType(Token.NoToken, seqTypeCtor, new Bpl.TypeSeq(ty));
+ }
+ readonly Bpl.TypeCtorDecl! fieldName;
+ public Bpl.Type! FieldName(Token! tok, Bpl.Type! ty) {
+ return new Bpl.CtorType(tok, fieldName, new Bpl.TypeSeq(ty));
+ }
+ public readonly Bpl.Type! HeapType;
+ public readonly Bpl.Type! ClassNameType;
+ public readonly Bpl.Expr! Null;
+ private readonly Bpl.Constant! allocField;
+ public Bpl.IdentifierExpr! Alloc(Token! tok) {
+ return new Bpl.IdentifierExpr(tok, allocField);
+ }
+
+ public PredefinedDecls(Bpl.TypeCtorDecl! refType, Bpl.TypeCtorDecl! seqTypeCtor, Bpl.TypeCtorDecl! fieldNameType,
+ Bpl.GlobalVariable! heap, Bpl.TypeCtorDecl! classNameType, Bpl.Constant! allocField) {
+ Bpl.CtorType refT = new Bpl.CtorType(Token.NoToken, refType, new Bpl.TypeSeq());
+ this.RefType = refT;
+ this.seqTypeCtor = seqTypeCtor;
+ this.fieldName = fieldNameType;
+ this.HeapType = heap.TypedIdent.Type;
+ this.ClassNameType = new Bpl.CtorType(Token.NoToken, classNameType, new Bpl.TypeSeq());
+ this.allocField = allocField;
+ this.Null = new Bpl.IdentifierExpr(Token.NoToken, "null", refT);
+ }
+ }
+
+ static PredefinedDecls FindPredefinedDecls(Bpl.Program! prog) {
+ if (prog.Resolve() != 0) {
+ Console.WriteLine("Error: resolution errors encountered in Dafny prelude");
+ return null;
+ }
+
+ Bpl.TypeCtorDecl refType = null;
+ Bpl.TypeCtorDecl seqTypeCtor = null;
+ Bpl.TypeCtorDecl fieldNameType = null;
+ Bpl.TypeCtorDecl classNameType = null;
+ Bpl.GlobalVariable heap = null;
+ Bpl.Constant allocField = null;
+ foreach (Bpl.Declaration d in prog.TopLevelDeclarations) {
+ if (d is Bpl.TypeCtorDecl) {
+ Bpl.TypeCtorDecl dt = (Bpl.TypeCtorDecl)d;
+ if (dt.Name == "Seq") {
+ seqTypeCtor = dt;
+ } else if (dt.Name == "Field") {
+ fieldNameType = dt;
+ } else if (dt.Name == "ClassName") {
+ classNameType = dt;
+ } else if (dt.Name == "ref") {
+ refType = dt;
+ }
+ } else if (d is Bpl.Constant) {
+ Bpl.Constant c = (Bpl.Constant)d;
+ if (c.Name == "alloc") {
+ allocField = c;
+ }
+ } else if (d is Bpl.GlobalVariable) {
+ Bpl.GlobalVariable v = (Bpl.GlobalVariable)d;
+ if (v.Name == "$Heap") {
+ heap = v;
+ }
+ }
+ }
+ if (seqTypeCtor == null) {
+ Console.WriteLine("Error: Dafny prelude is missing declaration of type Seq");
+ } else if (fieldNameType == null) {
+ Console.WriteLine("Error: Dafny prelude is missing declaration of type Field");
+ } else if (classNameType == null) {
+ Console.WriteLine("Error: Dafny prelude is missing declaration of type ClassName");
+ } else if (refType == null) {
+ Console.WriteLine("Error: Dafny prelude is missing declaration of type ref");
+ } else if (heap == null) {
+ Console.WriteLine("Error: Dafny prelude is missing declaration of $Heap");
+ } else if (allocField == null) {
+ Console.WriteLine("Error: Dafny prelude is missing declaration of constant alloc");
+ } else {
+ return new PredefinedDecls(refType, seqTypeCtor, fieldNameType, heap, classNameType, allocField);
+ }
+ return null;
+ }
+
+ static Bpl.Program ReadPrelude() {
+ //using (System.IO.Stream stream = (!) System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream("DafnyPrelude.bpl")) // Use this once Spec#/VSIP supports designating a non-.resx project item as an embedded resource
+ string! codebase = (!) System.IO.Path.GetDirectoryName((!)System.Reflection.Assembly.GetExecutingAssembly().Location);
+ string! preludePath = System.IO.Path.Combine(codebase, "DafnyPrelude.bpl");
+ List<string!> defines = new List<string!>();
+ using (System.IO.Stream stream = new System.IO.FileStream(preludePath, System.IO.FileMode.Open, System.IO.FileAccess.Read))
+ {
+ BoogiePL.Buffer.Fill(new System.IO.StreamReader(stream), defines);
+ BoogiePL.Scanner.Init("<DafnyPrelude.bpl>");
+ Bpl.Program prelude;
+ int errorCount = BoogiePL.Parser.Parse(out prelude);
+ if (prelude == null || errorCount > 0) {
+ return null;
+ } else {
+ return prelude;
+ }
+ }
+ }
+
+ public Bpl.Program! Translate(Program! program) {
+ if (sink == null || predef == null) {
+ // something went wrong during construction, which reads the prelude; an error has
+ // already been printed, so just return an empty program here (which is non-null)
+ return new Bpl.Program();
+ }
+ foreach (ClassDecl c in program.Classes) {
+ AddClassMembers(c);
+ }
+ foreach (ClassDecl c in program.Classes) {
+ foreach (MemberDecl member in c.Members) {
+ if (member is Method) {
+ Method m = (Method)member;
+ if (m.Body != null) {
+ AddMethodImpl(m);
+ }
+ } else if (member is Function) {
+ Function f = (Function)member;
+ AddFrameAxiom(f);
+ // TODO: also need a well-formedness check for the preconditions
+ if (f.Body != null) {
+ AddWellformednessCheck(f);
+ }
+ }
+ }
+ }
+ return sink;
+ }
+
+ void AddClassMembers(ClassDecl! c)
+ requires sink != null && predef != null;
+ {
+ sink.TopLevelDeclarations.Add(GetClass(c));
+
+ foreach (MemberDecl member in c.Members) {
+ if (member is Field) {
+ Field f = (Field)member;
+ Bpl.Constant fc = GetField(f);
+ sink.TopLevelDeclarations.Add(fc);
+
+ AddAllocationAxiom(f);
+
+ } else if (member is Function) {
+ Function f = (Function)member;
+ Bpl.Function useFunc;
+ Bpl.Function func = GetFunction(f, out useFunc);
+ sink.TopLevelDeclarations.Add(func);
+ if (useFunc != null) {
+ sink.TopLevelDeclarations.Add(useFunc);
+ }
+ if (f.Body != null) {
+ ExpressionTranslator etran = new ExpressionTranslator(this, predef, f.tok);
+
+ // axiom (forall $Heap, formals :: f#use(formals) && this != null && $IsHeap($Heap) && Pre($Heap,formals) ==> f(formals) == body)
+ // The antecedent f#use(formals) is included only if the function has been declared as 'use'.
+ // Note, an antecedent $Heap[this,alloc] is intentionally left out: including it would only weaken
+ // the axiom. Moreover, leaving it out does not introduce any soundness problem, because the Dafny
+ // allocation statement changes only an allocation bit and then re-assumes $IsGoodHeap; so if it is
+ // sound after that, then it would also have been sound just before the allocation.
+ Bpl.VariableSeq formals = new Bpl.VariableSeq();
+ Bpl.ExprSeq args = new Bpl.ExprSeq();
+ Bpl.BoundVariable bv = new Bpl.BoundVariable(f.tok, new Bpl.TypedIdent(f.tok, "$Heap", predef.HeapType));
+ formals.Add(bv);
+ args.Add(new Bpl.IdentifierExpr(f.tok, bv));
+ Bpl.BoundVariable bvThis = new Bpl.BoundVariable(f.tok, new Bpl.TypedIdent(f.tok, "this", predef.RefType));
+ formals.Add(bvThis);
+ Bpl.Expr bvThisIdExpr = new Bpl.IdentifierExpr(f.tok, bvThis);
+ args.Add(bvThisIdExpr);
+ foreach (Formal p in f.Formals) {
+ bv = new Bpl.BoundVariable(p.tok, new Bpl.TypedIdent(p.tok, p.UniqueName, TrType(p.Type)));
+ formals.Add(bv);
+ args.Add(new Bpl.IdentifierExpr(p.tok, bv));
+ }
+ Bpl.Expr ante = Bpl.Expr.And(
+ Bpl.Expr.Neq(bvThisIdExpr, predef.Null),
+ FunctionCall(f.tok, BuiltinFunction.IsGoodHeap, null, etran.HeapExpr));
+ foreach (Expression req in f.Req) {
+ ante = Bpl.Expr.And(ante, etran.TrExpr(req));
+ }
+ Bpl.FunctionCall funcID = new Bpl.FunctionCall(new Bpl.IdentifierExpr(f.tok, f.FullName, TrType(f.ResultType)));
+ Bpl.Expr funcAppl = new Bpl.NAryExpr(f.tok, funcID, args);
+ Bpl.Trigger tr;
+ if (f.Use) {
+ Bpl.FunctionCall useID = new Bpl.FunctionCall(new Bpl.IdentifierExpr(f.tok, f.FullName + "#use", TrType(f.ResultType)));
+ Bpl.Expr useAppl = new Bpl.NAryExpr(f.tok, useID, args);
+ ante = Bpl.Expr.And(useAppl, ante);
+ tr = new Bpl.Trigger(f.tok, true, new Bpl.ExprSeq(useAppl));
+ } else {
+ tr = new Bpl.Trigger(f.tok, true, new Bpl.ExprSeq(funcAppl));
+ }
+ Bpl.TypeVariableSeq typeParams = TrTypeParamDecls(f.TypeArgs);
+ Bpl.Expr ax = new Bpl.ForallExpr(f.tok, typeParams, formals, null, tr, Bpl.Expr.Imp(ante, Bpl.Expr.Eq(funcAppl, etran.TrExpr(f.Body))));
+ sink.TopLevelDeclarations.Add(new Bpl.Axiom(f.tok, ax));
+ }
+
+ } else if (member is Method) {
+ Method m = (Method)member;
+ Bpl.Procedure proc = GetMethod(m);
+ sink.TopLevelDeclarations.Add(proc);
+
+ } else {
+ assert false; // unexpected member
+ }
+ }
+ }
+
+ void AddAllocationAxiom(Field! f)
+ requires sink != null && predef != null;
+ {
+ if (f.Type is BoolType || f.Type is IntType || f.Type.IsTypeParameter) {
+ return;
+ }
+
+ Bpl.BoundVariable hVar = new Bpl.BoundVariable(f.tok, new Bpl.TypedIdent(f.tok, "$h", predef.HeapType));
+ Bpl.Expr h = new Bpl.IdentifierExpr(f.tok, hVar);
+ ExpressionTranslator etran = new ExpressionTranslator(this, predef, h);
+ Bpl.BoundVariable oVar = new Bpl.BoundVariable(f.tok, new Bpl.TypedIdent(f.tok, "$o", predef.RefType));
+ Bpl.Expr o = new Bpl.IdentifierExpr(f.tok, oVar);
+
+ // h[o,f]
+ Bpl.Expr oDotF = Bpl.Expr.SelectTok(f.tok, h, o, new Bpl.IdentifierExpr(f.tok, GetField(f)));
+ // $IsGoodHeap(h) && o != null && h[o,alloc]
+ Bpl.Expr ante = Bpl.Expr.And(Bpl.Expr.And(
+ FunctionCall(f.tok, BuiltinFunction.IsGoodHeap, null, h),
+ Bpl.Expr.Neq(o, predef.Null)),
+ etran.IsAlloced(f.tok, o));
+
+ if (f.Type is SetType) {
+ SetType st = (SetType)f.Type;
+ if (st.Arg.IsRefType) {
+ // axiom (forall h: [ref, Field x]x, o: ref, t: ref ::
+ // { h[o,f][t] }
+ // $IsGoodHeap(h) && o != null && h[o,alloc] && h[o,f][t] ==> t == null || h[t, alloc]);
+ Bpl.BoundVariable tVar = new Bpl.BoundVariable(f.tok, new Bpl.TypedIdent(f.tok, "$t", predef.RefType));
+ Bpl.Expr t = new Bpl.IdentifierExpr(f.tok, tVar);
+ Bpl.Expr oDotFsubT = Bpl.Expr.SelectTok(f.tok, oDotF, t);
+
+ Bpl.Trigger tr = new Bpl.Trigger(f.tok, true, new Bpl.ExprSeq(oDotFsubT));
+
+ Bpl.Expr goodRef = etran.GoodRef(f.tok, t, st.Arg);
+ Bpl.Expr body = Bpl.Expr.Imp(Bpl.Expr.And(ante, oDotFsubT), Bpl.Expr.Or(Bpl.Expr.Eq(t, predef.Null), goodRef));
+ Bpl.Expr ax = new Bpl.ForallExpr(f.tok, new Bpl.VariableSeq(hVar, oVar, tVar), tr, body);
+ sink.TopLevelDeclarations.Add(new Bpl.Axiom(f.tok, ax));
+ } else {
+ // TODO: should also handle sets of sets, etc. This will probably require some extra predicates, and these predicates may even replace the above treatment of sets.
+ }
+
+ } else if (f.Type is SeqType) {
+ SeqType st = (SeqType)f.Type;
+ if (st.Arg.IsRefType) {
+ // axiom (forall h: [ref, Field x]x, o: ref, i: int ::
+ // { Seq#Index(h[o,f], i) }
+ // $IsGoodHeap(h) && o != null && h[o,alloc] && 0 <= i && i < Seq#Length(h[o,f]) ==> Seq#Index(h[o,f], i) == null || h[Seq#Index(h[o,f], i), alloc]);
+ Bpl.BoundVariable iVar = new Bpl.BoundVariable(f.tok, new Bpl.TypedIdent(f.tok, "$i", Bpl.Type.Int));
+ Bpl.Expr i = new Bpl.IdentifierExpr(f.tok, iVar);
+ Bpl.Expr oDotFsubI = FunctionCall(f.tok, BuiltinFunction.SeqIndex, predef.RefType, oDotF, i);
+
+ Bpl.Expr range = InSeqRange(f.tok, i, oDotF, null, false);
+
+ Bpl.Trigger tr = new Bpl.Trigger(f.tok, true, new Bpl.ExprSeq(oDotFsubI));
+
+ Bpl.Expr goodRef = etran.GoodRef(f.tok, oDotFsubI, st.Arg);
+ Bpl.Expr body = Bpl.Expr.Imp(Bpl.Expr.And(ante, range), Bpl.Expr.Or(Bpl.Expr.Eq(oDotFsubI, predef.Null), goodRef));
+ Bpl.Expr ax = new Bpl.ForallExpr(f.tok, new Bpl.VariableSeq(hVar, oVar, iVar), tr, body);
+ sink.TopLevelDeclarations.Add(new Bpl.Axiom(f.tok, ax));
+ } else {
+ // TODO: should also handle sequences of sequences, etc. This will probably require some extra predicates, and these predicates may even replace the above treatment of sequences.
+ }
+
+ } else {
+ // reference type:
+ // axiom (forall h: [ref, Field x]x, o: ref ::
+ // { h[o,f] }
+ // $IsGoodHeap(h) && o != null && h[o,alloc] ==> h[o,f] == null || h[h[o,f], alloc]);
+ Bpl.Trigger tr = new Bpl.Trigger(f.tok, true, new Bpl.ExprSeq(oDotF));
+
+ Bpl.Expr goodRef = etran.GoodRef(f.tok, oDotF, f.Type);
+ Bpl.Expr body = Bpl.Expr.Imp(ante, Bpl.Expr.Or(Bpl.Expr.Eq(oDotF, predef.Null), goodRef));
+ Bpl.Expr ax = new Bpl.ForallExpr(f.tok, new Bpl.VariableSeq(hVar, oVar), tr, body);
+ sink.TopLevelDeclarations.Add(new Bpl.Axiom(f.tok, ax));
+ }
+ }
+
+ Bpl.Expr! InSeqRange(Token! tok, Bpl.Expr! index, Bpl.Expr! seq, Bpl.Expr lowerBound, bool includeUpperBound) {
+ if (lowerBound == null) {
+ lowerBound = Bpl.Expr.Literal(0);
+ }
+ Bpl.Expr lower = Bpl.Expr.Le(lowerBound, index);
+ Bpl.Expr upper;
+ if (includeUpperBound) {
+ upper = Bpl.Expr.Le(index, FunctionCall(tok, BuiltinFunction.SeqLength, null, seq));
+ } else {
+ upper = Bpl.Expr.Lt(index, FunctionCall(tok, BuiltinFunction.SeqLength, null, seq));
+ }
+ return Bpl.Expr.And(lower, upper);
+ }
+
+ Method currentMethod = null; // the method whose implementation is currently being translated
+ int loopHeapVarCount = 0;
+ int otherTmpVarCount = 0;
+ Bpl.IdentifierExpr _phvie = null;
+ Bpl.IdentifierExpr! GetPrevHeapVar_IdExpr(Token! tok, Bpl.VariableSeq! locals) // local variable that's shared between statements that need it
+ requires predef != null;
+ {
+ if (_phvie == null) {
+ // the "tok" of the first request for this variable is the one we use
+ Bpl.LocalVariable prevHeapVar = new Bpl.LocalVariable(tok, new Bpl.TypedIdent(tok, "$prevHeap", predef.HeapType));
+ locals.Add(prevHeapVar);
+ _phvie = new Bpl.IdentifierExpr(tok, prevHeapVar);
+ }
+ return _phvie;
+ }
+ Bpl.IdentifierExpr _nwie = null;
+ Bpl.IdentifierExpr! GetNewVar_IdExpr(Token! tok, Bpl.VariableSeq! locals) // local variable that's shared between statements that need it
+ requires predef != null;
+ {
+ if (_nwie == null) {
+ // the "tok" of the first request for this variable is the one we use
+ Bpl.LocalVariable nwVar = new Bpl.LocalVariable(tok, new Bpl.TypedIdent(tok, "$nw", predef.RefType)); // important: no where clause (that's why we're going through the trouble of setting of this variable in the first place)
+ locals.Add(nwVar);
+ _nwie = new Bpl.IdentifierExpr(tok, nwVar);
+ }
+ return _nwie;
+ }
+
+ void AddMethodImpl(Method! m)
+ requires sink != null && predef != null && m.Body != null;
+ requires currentMethod == null && loopHeapVarCount == 0 && _phvie == null && _nwie == null;
+ ensures currentMethod == null && loopHeapVarCount == 0 && _phvie == null && _nwie == null;
+ {
+ Bpl.Procedure proc = GetMethod(m);
+ currentMethod = m;
+
+ Bpl.VariableSeq localVariables = new Bpl.VariableSeq();
+
+ Bpl.StmtList stmts = TrStmt2StmtList(m.Body, localVariables, new ExpressionTranslator(this, predef, m.tok));
+ Bpl.TypeVariableSeq typeParams = TrTypeParamDecls(m.TypeArgs);
+ Bpl.Implementation impl = new Bpl.Implementation(m.tok, proc.Name,
+ typeParams,
+ Bpl.Formal.StripWhereClauses(proc.InParams),
+ Bpl.Formal.StripWhereClauses(proc.OutParams),
+ localVariables, stmts);
+ sink.TopLevelDeclarations.Add(impl);
+
+ currentMethod = null;
+ loopHeapVarCount = 0;
+ otherTmpVarCount = 0;
+ _phvie = null;
+ _nwie = null;
+ }
+
+ /// <summary>
+ /// Generates:
+ /// axiom (forall h0: [ref, Field x]x, h1: [ref, Field x]x, formals... ::
+ /// { F(h0,formals), F(h1,formals) }
+ /// (forall(alpha) o: ref, f: Field alpha :: o != null AND h0[o,alloc] AND o in reads clause of formals in h0 IMPLIES h0[o,f] == h1[o,f]) AND
+ /// (forall(alpha) o: ref, f: Field alpha :: o != null AND h1[o,alloc] AND o in reads clause of formals in h1 IMPLIES h0[o,f] == h1[o,f])
+ /// IMPLIES
+ /// F(h0,formals) == F(h1,formals)
+ /// );
+ /// </summary>
+ void AddFrameAxiom(Function! f)
+ requires sink != null && predef != null;
+ {
+ Bpl.BoundVariable h0Var = new Bpl.BoundVariable(f.tok, new Bpl.TypedIdent(f.tok, "$h0", predef.HeapType));
+ Bpl.BoundVariable h1Var = new Bpl.BoundVariable(f.tok, new Bpl.TypedIdent(f.tok, "$h1", predef.HeapType));
+ Bpl.Expr h0 = new Bpl.IdentifierExpr(f.tok, h0Var);
+ Bpl.Expr h1 = new Bpl.IdentifierExpr(f.tok, h1Var);
+ ExpressionTranslator etran0 = new ExpressionTranslator(this, predef, h0);
+ ExpressionTranslator etran1 = new ExpressionTranslator(this, predef, h1);
+
+ Bpl.TypeVariable alpha = new Bpl.TypeVariable(f.tok, "alpha");
+ Bpl.BoundVariable oVar = new Bpl.BoundVariable(f.tok, new Bpl.TypedIdent(f.tok, "$o", predef.RefType));
+ Bpl.Expr o = new Bpl.IdentifierExpr(f.tok, oVar);
+ Bpl.BoundVariable fieldVar = new Bpl.BoundVariable(f.tok, new Bpl.TypedIdent(f.tok, "$f", predef.FieldName(f.tok, alpha)));
+ Bpl.Expr field = new Bpl.IdentifierExpr(f.tok, fieldVar);
+ Bpl.Expr oNotNull = Bpl.Expr.Neq(o, predef.Null);
+ Bpl.Expr oNotNullAlloced0 = Bpl.Expr.And(oNotNull, etran0.IsAlloced(f.tok, o));
+ Bpl.Expr oNotNullAlloced1 = Bpl.Expr.And(oNotNull, etran1.IsAlloced(f.tok, o));
+ Bpl.Expr unchanged = Bpl.Expr.Eq(Bpl.Expr.SelectTok(f.tok, h0, o, field), Bpl.Expr.SelectTok(f.tok, h1, o, field));
+
+ Bpl.Expr r0 = InRWClause(f.tok, o, f.Reads, etran0);
+ Bpl.Expr r1 = InRWClause(f.tok, o, f.Reads, etran1);
+ Bpl.Expr q0 = new Bpl.ForallExpr(f.tok, new Bpl.TypeVariableSeq(alpha), new Bpl.VariableSeq(oVar, fieldVar),
+ Bpl.Expr.Imp(Bpl.Expr.And(oNotNullAlloced0, r0), unchanged));
+ Bpl.Expr q1 = new Bpl.ForallExpr(f.tok, new Bpl.TypeVariableSeq(alpha), new Bpl.VariableSeq(oVar, fieldVar),
+ Bpl.Expr.Imp(Bpl.Expr.And(oNotNullAlloced1, r1), unchanged));
+
+ // bvars: h0, h1, formals
+ // f0args: h0, formals
+ // f1args: h1, formals
+ Bpl.VariableSeq bvars = new Bpl.VariableSeq();
+ Bpl.ExprSeq f0args = new Bpl.ExprSeq();
+ Bpl.ExprSeq f1args = new Bpl.ExprSeq();
+ Bpl.BoundVariable thVar = new Bpl.BoundVariable(f.tok, new Bpl.TypedIdent(f.tok, "this", predef.RefType));
+ Bpl.Expr th = new Bpl.IdentifierExpr(f.tok, thVar);
+ bvars.Add(h0Var); bvars.Add(h1Var); bvars.Add(thVar);
+ f0args.Add(h0); f0args.Add(th);
+ f1args.Add(h1); f1args.Add(th);
+ foreach (Formal p in f.Formals) {
+ Bpl.BoundVariable bv = new Bpl.BoundVariable(p.tok, new Bpl.TypedIdent(p.tok, p.UniqueName, TrType(p.Type)));
+ bvars.Add(bv);
+ Bpl.Expr formal = new Bpl.IdentifierExpr(p.tok, bv);
+ f0args.Add(formal);
+ f1args.Add(formal);
+ }
+
+ Bpl.FunctionCall fn = new Bpl.FunctionCall(new Bpl.IdentifierExpr(f.tok, f.FullName, TrType(f.ResultType)));
+ Bpl.Expr F0 = new Bpl.NAryExpr(f.tok, fn, f0args);
+ Bpl.Expr F1 = new Bpl.NAryExpr(f.tok, fn, f1args);
+ Bpl.Expr eq = Bpl.Expr.Eq(F0, F1);
+ Bpl.Trigger tr = new Bpl.Trigger(f.tok, true, new Bpl.ExprSeq(F0, F1));
+
+ Bpl.TypeVariableSeq typeParams = TrTypeParamDecls(f.TypeArgs);
+ Bpl.Expr ax = new Bpl.ForallExpr(f.tok, typeParams, bvars, null, tr, Bpl.Expr.Imp(Bpl.Expr.And(q0, q1), eq));
+ sink.TopLevelDeclarations.Add(new Bpl.Axiom(f.tok, ax, "frame axiom for " + f.FullName));
+ }
+
+ Bpl.Expr! InRWClause(Token! tok, Bpl.Expr! o, List<Expression!>! rw, ExpressionTranslator! etran) {
+ Bpl.Expr disjunction = null;
+ foreach (Expression e in rw) {
+ Bpl.Expr disjunct;
+ if (e.Type is SetType) {
+ // old(e)[o]
+ disjunct = etran.TrInSet(tok, o, e, null);
+ } else if (e.Type is SeqType) {
+ // (exists i: int :: 0 <= i && i < Seq#Length(old(e)) ==> Seq#Index(old(e),i) == o)
+ Bpl.Variable iVar = new Bpl.BoundVariable(tok, new Bpl.TypedIdent(tok, "$i", Bpl.Type.Int));
+ Bpl.Expr i = new Bpl.IdentifierExpr(tok, iVar);
+ Bpl.Expr iBounds = InSeqRange(tok, i, etran.TrExpr(e), null, false);
+ Bpl.Expr XsubI = FunctionCall(tok, BuiltinFunction.SeqIndex, TrType(((SeqType)e.Type).Arg), etran.TrExpr(e), i);
+ // TODO: the equality in the next line should be changed to one that understands extensionality
+ disjunct = new Bpl.ExistsExpr(tok, new Bpl.VariableSeq(iVar), Bpl.Expr.Imp(iBounds, Bpl.Expr.Eq(XsubI, o)));
+ } else {
+ // o == old(e)
+ disjunct = Bpl.Expr.Eq(o, etran.TrExpr(e));
+ }
+ disjunct = Bpl.Expr.And(IsTotal(e, etran), disjunct);
+ if (disjunction == null) {
+ disjunction = disjunct;
+ } else {
+ disjunction = Bpl.Expr.Or(disjunction, disjunct);
+ }
+ }
+ if (disjunction == null) {
+ return Bpl.Expr.False;
+ } else {
+ return disjunction;
+ }
+ }
+
+ void AddWellformednessCheck(Function! f)
+ requires sink != null && predef != null;
+ requires f.Body != null;
+ {
+ ExpressionTranslator etran = new ExpressionTranslator(this, predef, f.tok);
+ Bpl.VariableSeq inParams = new Bpl.VariableSeq();
+ Bpl.Expr wh = Bpl.Expr.And(
+ Bpl.Expr.Neq(new Bpl.IdentifierExpr(f.tok, "this", predef.RefType), predef.Null),
+ etran.GoodRef(f.tok, new Bpl.IdentifierExpr(f.tok, "this", predef.RefType), Resolver.GetThisType(f.tok, (!)f.EnclosingClass)));
+ Bpl.Formal thVar = new Bpl.Formal(f.tok, new Bpl.TypedIdent(f.tok, "this", predef.RefType, wh), true);
+ inParams.Add(thVar);
+ foreach (Formal p in f.Formals) {
+ Bpl.Type varType = TrType(p.Type);
+ wh = GetWhereClause(p.tok, new Bpl.IdentifierExpr(p.tok, p.UniqueName, varType), p.Type, etran);
+ inParams.Add(new Bpl.Formal(p.tok, new Bpl.TypedIdent(p.tok, p.UniqueName, varType, wh), true));
+ }
+ Bpl.TypeVariableSeq typeParams = TrTypeParamDecls(f.TypeArgs);
+ Bpl.Procedure proc = new Bpl.Procedure(f.tok, "CheckWellformed$$" + f.FullName, typeParams, inParams, new Bpl.VariableSeq(),
+ new Bpl.RequiresSeq(), new Bpl.IdentifierExprSeq(), new Bpl.EnsuresSeq());
+ sink.TopLevelDeclarations.Add(proc);
+
+ Bpl.VariableSeq localVariables = new Bpl.VariableSeq();
+ Bpl.StmtListBuilder builder = new Bpl.StmtListBuilder();
+
+ CheckWellformed(f.Body, f, Position.Positive, builder, etran);
+
+ Bpl.Implementation impl = new Bpl.Implementation(f.tok, proc.Name,
+ typeParams,
+ Bpl.Formal.StripWhereClauses(proc.InParams),
+ Bpl.Formal.StripWhereClauses(proc.OutParams),
+ localVariables, builder.Collect(f.tok));
+ sink.TopLevelDeclarations.Add(impl);
+ }
+
+ Bpl.Expr! IsTotal(Expression! expr, ExpressionTranslator! etran)
+ requires predef != null;
+ {
+ if (expr is LiteralExpr || expr is ThisExpr || expr is IdentifierExpr) {
+ return Bpl.Expr.True;
+ } else if (expr is DisplayExpression) {
+ DisplayExpression e = (DisplayExpression)expr;
+ return IsTotal(e.Elements, etran);
+ } else if (expr is FieldSelectExpr) {
+ FieldSelectExpr e = (FieldSelectExpr)expr;
+ if (e.Obj is ThisExpr) {
+ return Bpl.Expr.True;
+ } else {
+ return Bpl.Expr.And(IsTotal(e.Obj, etran), Bpl.Expr.Neq(etran.TrExpr(e.Obj), predef.Null));
+ }
+ } else if (expr is SeqSelectExpr) {
+ SeqSelectExpr e = (SeqSelectExpr)expr;
+ Bpl.Expr total = IsTotal(e.Seq, etran);
+ Bpl.Expr seq = etran.TrExpr(e.Seq);
+ Bpl.Expr e0 = null;
+ if (e.E0 != null) {
+ e0 = etran.TrExpr(e.E0);
+ total = BplAnd(total, IsTotal(e.E0, etran));
+ total = BplAnd(total, InSeqRange(expr.tok, e0, seq, null, !e.SelectOne));
+ }
+ if (e.E1 != null) {
+ total = BplAnd(total, IsTotal(e.E1, etran));
+ total = BplAnd(total, InSeqRange(expr.tok, etran.TrExpr(e.E1), seq, e0, true));
+ }
+ return total;
+ } else if (expr is FunctionCallExpr) {
+ FunctionCallExpr e = (FunctionCallExpr)expr;
+ Bpl.Expr r = IsTotal(e.Receiver, etran);
+ if (!(e.Receiver is ThisExpr)) {
+ r = BplAnd(r, Bpl.Expr.Neq(etran.TrExpr(e.Receiver), predef.Null));
+ }
+ // TODO: check reads permissions and check preconditions
+ return BplAnd(r, IsTotal(e.Args, etran));
+ } else if (expr is OldExpr) {
+ OldExpr e = (OldExpr)expr;
+ return new Bpl.OldExpr(expr.tok, IsTotal(e.E, etran));
+ } else if (expr is FreshExpr) {
+ FreshExpr e = (FreshExpr)expr;
+ return IsTotal(e.E, etran);
+ } else if (expr is UnaryExpr) {
+ UnaryExpr e = (UnaryExpr)expr;
+ return IsTotal(e.E, etran);
+ } else if (expr is BinaryExpr) {
+ BinaryExpr e = (BinaryExpr)expr;
+ Bpl.Expr t0 = IsTotal(e.E0, etran);
+ Bpl.Expr t1 = IsTotal(e.E1, etran);
+ Bpl.Expr z = null;
+ switch (e.ResolvedOp) {
+ case BinaryExpr.ResolvedOpcode.And:
+ case BinaryExpr.ResolvedOpcode.Imp:
+ t1 = Bpl.Expr.Imp(etran.TrExpr(e.E0), t1);
+ break;
+ case BinaryExpr.ResolvedOpcode.Or:
+ t1 = Bpl.Expr.Imp(Bpl.Expr.Not(etran.TrExpr(e.E0)), t1);
+ break;
+ case BinaryExpr.ResolvedOpcode.Div:
+ z = Bpl.Expr.Neq(etran.TrExpr(e.E1), Bpl.Expr.Literal(0));
+ break;
+ default:
+ break;
+ }
+ Bpl.Expr r = BplAnd(t0, t1);
+ return z == null ? r : BplAnd(r, z);
+ } else if (expr is QuantifierExpr) {
+ QuantifierExpr e = (QuantifierExpr)expr;
+ Bpl.Expr total = IsTotal(e.Body, etran);
+ if (total != Bpl.Expr.True) {
+ Bpl.VariableSeq bvars = new Bpl.VariableSeq();
+ foreach (BoundVar bv in e.BoundVars) {
+ bvars.Add(new Bpl.BoundVariable(bv.tok, new Bpl.TypedIdent(bv.tok, bv.UniqueName, TrType(bv.Type))));
+ }
+ total = new Bpl.ForallExpr(expr.tok, bvars, total);
+ }
+ return total;
+ } else if (expr is ITEExpr) {
+ ITEExpr e = (ITEExpr)expr;
+ Bpl.Expr total = IsTotal(e.Test, etran);
+ Bpl.Expr test = etran.TrExpr(e.Test);
+ total = BplAnd(total, Bpl.Expr.Imp(test, IsTotal(e.Thn, etran)));
+ total = BplAnd(total, Bpl.Expr.Imp(Bpl.Expr.Not(test), IsTotal(e.Els, etran)));
+ return total;
+ } else {
+ assert false; // unexpected expression
+ }
+ }
+
+ Bpl.Expr! IsTotal(List<Expression!>! exprs, ExpressionTranslator! etran) {
+ Bpl.Expr total = Bpl.Expr.True;
+ foreach (Expression e in exprs) {
+ total = BplAnd(total, IsTotal(e, etran));
+ }
+ return total;
+ }
+
+ Bpl.Expr! BplAnd(Bpl.Expr! a, Bpl.Expr! b) {
+ if (a == Bpl.Expr.True) {
+ return b;
+ } else if (b == Bpl.Expr.True) {
+ return a;
+ } else {
+ return Bpl.Expr.And(a, b);
+ }
+ }
+
+ enum Position { Positive, Negative, Neither }
+ Position Negate(Position pos) {
+ switch (pos) {
+ case Position.Positive: return Position.Negative;
+ case Position.Negative: return Position.Positive;
+ case Position.Neither: return Position.Neither;
+ default: assert false; // unexpected Position
+ }
+ }
+
+ void CheckNonNull(Token! tok, Expression! e, Bpl.StmtListBuilder! builder, ExpressionTranslator! etran)
+ requires predef != null;
+ {
+ if (e is ThisExpr) {
+ // already known to be non-null
+ } else {
+ builder.Add(Assert(tok, Bpl.Expr.Neq(etran.TrExpr(e), predef.Null), "target object may be null"));
+ }
+ }
+
+ void CheckWellformed(Expression! expr, Function func, Position pos, Bpl.StmtListBuilder! builder, ExpressionTranslator! etran) {
+ if (expr is LiteralExpr || expr is ThisExpr || expr is IdentifierExpr) {
+ // always allowed
+ } else if (expr is DisplayExpression) {
+ DisplayExpression e = (DisplayExpression)expr;
+ foreach (Expression el in e.Elements) {
+ CheckWellformed(el, func, Position.Neither, builder, etran);
+ }
+ } else if (expr is FieldSelectExpr) {
+ FieldSelectExpr e = (FieldSelectExpr)expr;
+ CheckWellformed(e.Obj, func, Position.Neither, builder, etran);
+ CheckNonNull(expr.tok, e.Obj, builder, etran);
+ if (func != null) {
+ builder.Add(Assert(expr.tok, InRWClause(expr.tok, etran.TrExpr(e.Obj), func.Reads, etran), "insufficient reads clause to read field"));
+ }
+ } else if (expr is SeqSelectExpr) {
+ SeqSelectExpr e = (SeqSelectExpr)expr;
+ CheckWellformed(e.Seq, func, Position.Neither, builder, etran);
+ Bpl.Expr seq = etran.TrExpr(e.Seq);
+ Bpl.Expr e0 = null;
+ if (e.E0 != null) {
+ e0 = etran.TrExpr(e.E0);
+ CheckWellformed(e.E0, func, Position.Neither, builder, etran);
+ builder.Add(new Bpl.AssertCmd(expr.tok, InSeqRange(expr.tok, e0, seq, null, !e.SelectOne)));
+ }
+ if (e.E1 != null) {
+ CheckWellformed(e.E1, func, Position.Neither, builder, etran);
+ builder.Add(new Bpl.AssertCmd(expr.tok, InSeqRange(expr.tok, etran.TrExpr(e.E1), seq, e0, true)));
+ }
+ } else if (expr is FunctionCallExpr) {
+ FunctionCallExpr e = (FunctionCallExpr)expr;
+ CheckWellformed(e.Receiver, func, Position.Neither, builder, etran);
+ CheckNonNull(expr.tok, e.Receiver, builder, etran);
+ foreach (Expression arg in e.Args) {
+ CheckWellformed(arg, func, Position.Neither, builder, etran);
+ }
+ // TODO: check wellformedness of call (call.reads is subset of reads, and either e.Function returns a boolean and is in a positive position, or e.Function returns something else and the subset is a proper subset)
+ // TODO: and check preconditions of call
+ } else if (expr is OldExpr || expr is FreshExpr) {
+ assert false; // unexpected expression in function body
+ } else if (expr is UnaryExpr) {
+ UnaryExpr e = (UnaryExpr)expr;
+ CheckWellformed(e.E, func, e.Op == UnaryExpr.Opcode.Not ? Negate(pos) : Position.Neither, builder, etran);
+ } else if (expr is BinaryExpr) {
+ BinaryExpr e = (BinaryExpr)expr;
+ CheckWellformed(e.E0, func, e.ResolvedOp == BinaryExpr.ResolvedOpcode.Imp ? Negate(pos) : pos, builder, etran);
+
+ switch (e.ResolvedOp) {
+ case BinaryExpr.ResolvedOpcode.And:
+ case BinaryExpr.ResolvedOpcode.Imp:
+ {
+ Bpl.StmtListBuilder b = new Bpl.StmtListBuilder();
+ CheckWellformed(e.E1, func, pos, b, etran);
+ builder.Add(new Bpl.IfCmd(expr.tok, etran.TrExpr(e.E0), b.Collect(expr.tok), null, null));
+ }
+ break;
+ case BinaryExpr.ResolvedOpcode.Or:
+ {
+ Bpl.StmtListBuilder b = new Bpl.StmtListBuilder();
+ CheckWellformed(e.E1, func, pos, b, etran);
+ builder.Add(new Bpl.IfCmd(expr.tok, Bpl.Expr.Not(etran.TrExpr(e.E0)), b.Collect(expr.tok), null, null));
+ }
+ break;
+ default:
+ CheckWellformed(e.E1, func, pos, builder, etran);
+ break;
+ }
+
+ } else if (expr is QuantifierExpr) {
+#if TODO
+ QuantifierExpr e = (QuantifierExpr)expr;
+ Bpl.Expr total = IsTotal(e.Body, etran);
+ if (total != Bpl.Expr.True) {
+ Bpl.VariableSeq bvars = new Bpl.VariableSeq();
+ foreach (BoundVar bv in e.BoundVars) {
+ // TODO: the following needs to take into account name clashes, for which the Boogie rules are different from the Dafny rules
+ bvars.Add(new Bpl.BoundVariable(bv.tok, new Bpl.TypedIdent(bv.tok, bv.UniqueName, TrType(bv.Type))));
+ }
+ if (expr is ForallExpr) {
+ total = new Bpl.ForallExpr(expr.tok, bvars, total);
+ } else {
+ total = new Bpl.ExistsExpr(expr.tok, bvars, total);
+ }
+ }
+ return total;
+#endif
+ } else if (expr is ITEExpr) {
+#if TODO
+ ITEExpr e = (ITEExpr)expr;
+ Bpl.Expr total = IsTotal(e.Test, etran);
+ total = BplAnd(total, IsTotal(e.Thn, etran));
+ total = BplAnd(total, IsTotal(e.Els, etran));
+ return total;
+#endif
+ } else {
+ assert false; // unexpected expression
+ }
+ }
+
+ Bpl.Constant! GetClass(ClassDecl! cl)
+ requires predef != null;
+ {
+ Bpl.Constant cc;
+ if (classes.TryGetValue(cl, out cc)) {
+ assert cc != null;
+ } else {
+ // TODO: make the following a function when the class has type parameters, so that different instantiations
+ // of a class can be distinguished
+ cc = new Bpl.Constant(cl.tok, new Bpl.TypedIdent(cl.tok, "class." + cl.Name, predef.ClassNameType), true);
+ classes.Add(cl, cc);
+ }
+ return cc;
+ }
+
+ Bpl.Expr GetTypeExpr(Token! tok, Type! type)
+ requires predef != null;
+ {
+ while (true) {
+ TypeProxy tp = type as TypeProxy;
+ if (tp == null) {
+ break;
+ } else if (tp.T == null) {
+ // unresolved proxy
+ // TODO: what to do here?
+ return null;
+ } else {
+ type = tp.T;
+ }
+ }
+
+ if (type is BoolType) {
+ return new Bpl.IdentifierExpr(tok, "class.bool", predef.ClassNameType);
+ } else if (type is IntType) {
+ return new Bpl.IdentifierExpr(tok, "class.int", predef.ClassNameType);
+ } else if (type is ObjectType) {
+ return new Bpl.IdentifierExpr(tok, "class.object", predef.ClassNameType);
+ } else if (type is CollectionType) {
+ CollectionType ct = (CollectionType)type;
+ Bpl.Expr a = GetTypeExpr(tok, ct.Arg);
+ if (a == null) {
+ return null;
+ }
+ Bpl.Expr t = new Bpl.IdentifierExpr(tok, ct is SetType ? "class.set" : "class.seq", predef.ClassNameType);
+ return FunctionCall(tok, BuiltinFunction.TypeTuple, null, t, a);
+ } else {
+ ClassType ct = (ClassType)type;
+ if (ct.ResolvedClass == null) {
+ return null; // TODO: what to do here?
+ }
+ Bpl.Expr t = new Bpl.IdentifierExpr(tok, GetClass(ct.ResolvedClass));
+ foreach (Type arg in ct.TypeArgs) {
+ Bpl.Expr a = GetTypeExpr(tok, arg);
+ if (a == null) {
+ return null;
+ }
+ t = FunctionCall(tok, BuiltinFunction.TypeTuple, null, t, a);
+ }
+ return t;
+ }
+ }
+
+ Bpl.Constant! GetField(Field! f)
+ requires predef != null;
+ {
+ Bpl.Constant fc;
+ if (fields.TryGetValue(f, out fc)) {
+ assert fc != null;
+ } else {
+ Bpl.Type ty = predef.FieldName(f.tok, TrType(f.Type));
+ fc = new Bpl.Constant(f.tok, new Bpl.TypedIdent(f.tok, f.FullName, ty), true);
+ fields.Add(f, fc);
+ }
+ return fc;
+ }
+
+ Bpl.Expr! GetField(FieldSelectExpr! fse)
+ requires fse.Field != null;
+ {
+ return new Bpl.IdentifierExpr(fse.tok, GetField(fse.Field));
+ }
+
+ Bpl.Function! GetFunction(Function! f, out Bpl.Function useF)
+ requires predef != null;
+ {
+ useF = null;
+ Bpl.Function func;
+ if (functions.TryGetValue(f, out func)) {
+ assert func != null;
+ } else {
+ Bpl.TypeVariableSeq typeParams = TrTypeParamDecls(f.TypeArgs);
+ Bpl.VariableSeq args = new Bpl.VariableSeq();
+ args.Add(new Bpl.Formal(f.tok, new Bpl.TypedIdent(f.tok, "$heap", predef.HeapType), true));
+ args.Add(new Bpl.Formal(f.tok, new Bpl.TypedIdent(f.tok, "this", predef.RefType), true));
+ foreach (Formal p in f.Formals) {
+ args.Add(new Bpl.Formal(p.tok, new Bpl.TypedIdent(p.tok, p.UniqueName, TrType(p.Type)), true));
+ }
+ Bpl.Formal res = new Bpl.Formal(f.tok, new Bpl.TypedIdent(f.tok, Bpl.TypedIdent.NoName, TrType(f.ResultType)), false);
+ func = new Bpl.Function(f.tok, f.FullName, typeParams, args, res);
+
+ functions.Add(f, func);
+
+ if (f.Use) {
+ Bpl.Formal boolRes = new Bpl.Formal(f.tok, new Bpl.TypedIdent(f.tok, Bpl.TypedIdent.NoName, Bpl.Type.Bool), false);
+ useF = new Bpl.Function(f.tok, f.FullName + "#use", args, boolRes);
+ }
+ }
+ return func;
+ }
+
+ Bpl.Procedure! GetMethod(Method! m)
+ requires predef != null;
+ {
+ Bpl.Procedure proc;
+ if (methods.TryGetValue(m, out proc)) {
+ assert proc != null;
+ } else {
+ ExpressionTranslator etran = new ExpressionTranslator(this, predef, m.tok);
+
+ Bpl.VariableSeq inParams = new Bpl.VariableSeq();
+ Bpl.VariableSeq outParams = new Bpl.VariableSeq();
+ Bpl.Expr wh = Bpl.Expr.And(
+ Bpl.Expr.Neq(new Bpl.IdentifierExpr(m.tok, "this", predef.RefType), predef.Null),
+ etran.GoodRef(m.tok, new Bpl.IdentifierExpr(m.tok, "this", predef.RefType), Resolver.GetThisType(m.tok, (!)m.EnclosingClass)));
+ Bpl.Formal thVar = new Bpl.Formal(m.tok, new Bpl.TypedIdent(m.tok, "this", predef.RefType, wh), true);
+ inParams.Add(thVar);
+ foreach (Formal p in m.Ins) {
+ Bpl.Type varType = TrType(p.Type);
+ wh = GetWhereClause(p.tok, new Bpl.IdentifierExpr(p.tok, p.UniqueName, varType), p.Type, etran);
+ inParams.Add(new Bpl.Formal(p.tok, new Bpl.TypedIdent(p.tok, p.UniqueName, varType, wh), true));
+ }
+ foreach (Formal p in m.Outs) {
+ Bpl.Type varType = TrType(p.Type);
+ wh = GetWhereClause(p.tok, new Bpl.IdentifierExpr(p.tok, p.UniqueName, varType), p.Type, etran);
+ outParams.Add(new Bpl.Formal(p.tok, new Bpl.TypedIdent(p.tok, p.UniqueName, varType, wh), false));
+ }
+
+ Bpl.RequiresSeq req = new Bpl.RequiresSeq();
+ Bpl.IdentifierExprSeq mod = new Bpl.IdentifierExprSeq();
+ Bpl.EnsuresSeq ens = new Bpl.EnsuresSeq();
+ mod.Add(etran.HeapExpr);
+ string comment = "user-defined preconditions";
+ foreach (MaybeFreeExpression p in m.Req) {
+ Bpl.RequiresSeq pieces = new Bpl.RequiresSeq();
+ if (!p.IsFree) {
+ foreach (Expression se in SplitExpr(p.E, true)) {
+ pieces.Add(Requires(se.tok, false, etran.TrExpr(se), null, null));
+ }
+ }
+ if (pieces.Length == 1) {
+ // add 1 checked precondition (the whole thing)
+ req.Add(Requires(p.E.tok, false, etran.TrExpr(p.E), null, comment));
+ } else {
+ // add 1 free precondition, followed by each piece (if any) as a checked precondition
+ req.Add(Requires(p.E.tok, true, etran.TrExpr(p.E), null, comment));
+ req.AddRange(pieces);
+ }
+ comment = null;
+ }
+ comment = "user-defined postconditions";
+ foreach (MaybeFreeExpression p in m.Ens) {
+ Bpl.EnsuresSeq pieces = new Bpl.EnsuresSeq();
+ if (!p.IsFree) {
+ foreach (Expression se in SplitExpr(p.E, true)) {
+ pieces.Add(Ensures(se.tok, false, etran.TrExpr(se), null, null));
+ }
+ }
+ if (pieces.Length == 1) {
+ ens.Add(Ensures(p.E.tok, false, etran.TrExpr(p.E), comment, null));
+ } else {
+ ens.Add(Ensures(p.E.tok, true, etran.TrExpr(p.E), comment, null));
+ ens.AddRange(pieces);
+ }
+ comment = null;
+ }
+
+ foreach (BoilerplateTriple tri in GetTwoStateBoilerplate(m.tok, m, etran.Old, etran)) {
+ ens.Add(Ensures(tri.tok, tri.IsFree, tri.Expr, tri.ErrorMessage, tri.Comment));
+ }
+
+ Bpl.TypeVariableSeq typeParams = TrTypeParamDecls(m.TypeArgs);
+ proc = new Bpl.Procedure(m.tok, m.FullName, typeParams, inParams, outParams, req, mod, ens);
+
+ methods.Add(m, proc);
+ }
+ return proc;
+ }
+
+ class BoilerplateTriple { // a triple that is now a quintuple
+ public readonly Token! tok;
+ public readonly bool IsFree;
+ public readonly Bpl.Expr! Expr;
+ public readonly string ErrorMessage;
+ invariant IsFree || ErrorMessage != null;
+ public readonly string Comment;
+ public BoilerplateTriple(Token! tok, bool isFree, Bpl.Expr! expr, string errorMessage, string comment)
+ requires isFree || errorMessage != null;
+ {
+ this.tok = tok;
+ IsFree = isFree;
+ Expr = expr;
+ ErrorMessage = errorMessage;
+ Comment = comment;
+ }
+ }
+
+ /// <summary>
+ /// There are 3 states of interest when generating two-state boilerplate:
+ /// S0. the beginning of the method, which is where the modifies clause is interpreted
+ /// S1. the pre-state of the two-state interval
+ /// S2. the post-state of the two-state interval
+ /// This method assumes that etranPre denotes S1, etran denotes S2, and that etran.Old denotes S0.
+ /// </summary>
+ List<BoilerplateTriple!>! GetTwoStateBoilerplate(Token! tok, Method! method, ExpressionTranslator! etranPre, ExpressionTranslator! etran)
+ {
+ List<BoilerplateTriple!> boilerplate = new List<BoilerplateTriple!>();
+
+ boilerplate.Add(new BoilerplateTriple(tok, false, FrameCondition(tok, method.Mod, etranPre, etran), "frame condition does not hold", "frame condition"));
+
+ // free specifications
+ Bpl.Expr heapSucc = FunctionCall(tok, BuiltinFunction.HeapSucc, null, etranPre.HeapExpr, etran.HeapExpr);
+ boilerplate.Add(new BoilerplateTriple(tok, true, heapSucc, null, "boilerplate"));
+
+ return boilerplate;
+ }
+
+ /// <summary>
+ /// There are 3 states of interest when generating a freame condition:
+ /// S0. the beginning of the method, which is where the modifies clause is interpreted
+ /// S1. the pre-state of the two-state interval
+ /// S2. the post-state of the two-state interval
+ /// This method assumes that etranPre denotes S1, etran denotes S2, and that etran.Old denotes S0.
+ /// </summary>
+ Bpl.Expr! FrameCondition(Token! tok, List<Expression!>! modifiesClause, ExpressionTranslator! etranPre, ExpressionTranslator! etran)
+ requires predef != null;
+ {
+ // generate:
+ // (forall<alpha> o: ref, f: Field alpha :: { $Heap[o,f] }
+ // o != null && old($Heap)[o,alloc] ==>
+ // $Heap[o,f] == PreHeap[o,f] ||
+ // o in modifiesClause)
+ Bpl.TypeVariable alpha = new Bpl.TypeVariable(tok, "alpha");
+ Bpl.BoundVariable oVar = new Bpl.BoundVariable(tok, new Bpl.TypedIdent(tok, "$o", predef.RefType));
+ Bpl.IdentifierExpr o = new Bpl.IdentifierExpr(tok, oVar);
+ Bpl.BoundVariable fVar = new Bpl.BoundVariable(tok, new Bpl.TypedIdent(tok, "$f", predef.FieldName(tok, alpha)));
+ Bpl.IdentifierExpr f = new Bpl.IdentifierExpr(tok, fVar);
+
+ Bpl.Expr heapOF = Bpl.Expr.SelectTok(tok, etran.HeapExpr, o, f);
+ Bpl.Expr preHeapOF = Bpl.Expr.SelectTok(tok, etranPre.HeapExpr, o, f);
+ Bpl.Expr ante = Bpl.Expr.And(Bpl.Expr.Neq(o, predef.Null), etran.Old.IsAlloced(tok, o));
+ Bpl.Expr consequent = Bpl.Expr.Eq(heapOF, preHeapOF);
+
+ consequent = Bpl.Expr.Or(consequent, InRWClause(tok, o, modifiesClause, etran.Old));
+
+ Bpl.Trigger tr = new Bpl.Trigger(tok, true, new Bpl.ExprSeq(heapOF));
+ return new Bpl.ForallExpr(tok, new Bpl.TypeVariableSeq(alpha), new Bpl.VariableSeq(oVar, fVar), null, tr, Bpl.Expr.Imp(ante, consequent));
+ }
+
+ // ----- Type ---------------------------------------------------------------------------------
+
+ Bpl.Type! TrType(Type! type)
+ requires predef != null;
+ {
+ while (true) {
+ TypeProxy tp = type as TypeProxy;
+ if (tp == null) {
+ break;
+ } else if (tp.T == null) {
+ // unresolved proxy; just treat as ref, since no particular type information is apparently needed for this type
+ return predef.RefType;
+ } else {
+ type = tp.T;
+ }
+ }
+
+ if (type is BoolType) {
+ return Bpl.Type.Bool;
+ } else if (type is IntType) {
+ return Bpl.Type.Int;
+ } else if (type.IsTypeParameter) {
+ return predef.RefType;
+ } else if (type.IsRefType) {
+ // object and class types translate to ref
+ return predef.RefType;
+ } else if (type is SetType) {
+ return new Bpl.MapType(Token.NoToken, new Bpl.TypeVariableSeq(), new Bpl.TypeSeq(TrType(((SetType)type).Arg)), Bpl.Type.Bool);
+ } else if (type is SeqType) {
+ return predef.SeqType(Token.NoToken, TrType(((SeqType)type).Arg));
+ } else {
+ assert false; // unexpected type
+ }
+ }
+
+ Bpl.TypeVariableSeq! TrTypeParamDecls(List<TypeParameter!>! tps)
+ {
+ Bpl.TypeVariableSeq typeParams = new Bpl.TypeVariableSeq();
+ return typeParams;
+ }
+
+ // ----- Statement ----------------------------------------------------------------------------
+
+ Bpl.AssertCmd! Assert(Token! tok, Bpl.Expr! condition, string! errorMessage)
+ {
+ Bpl.AssertCmd cmd = new Bpl.AssertCmd(tok, condition);
+ cmd.ErrorData = "Error: " + errorMessage;
+ return cmd;
+ }
+
+ Bpl.Ensures! Ensures(Token! tok, bool free, Bpl.Expr! condition, string errorMessage, string comment)
+ {
+ Bpl.Ensures ens = new Bpl.Ensures(tok, free, condition, comment);
+ if (errorMessage != null) {
+ ens.ErrorData = errorMessage;
+ }
+ return ens;
+ }
+
+ Bpl.Requires! Requires(Token! tok, bool free, Bpl.Expr! condition, string errorMessage, string comment)
+ {
+ Bpl.Requires req = new Bpl.Requires(tok, free, condition, comment);
+ if (errorMessage != null) {
+ req.ErrorData = errorMessage;
+ }
+ return req;
+ }
+
+ Bpl.StmtList! TrStmt2StmtList(Statement! block, Bpl.VariableSeq! locals, ExpressionTranslator! etran)
+ requires currentMethod != null && predef != null;
+ {
+ Bpl.StmtListBuilder builder = new Bpl.StmtListBuilder();
+ TrStmt(block, builder, locals, etran);
+ return builder.Collect(block.Tok); // TODO: would be nice to have an end-curly location for "block"
+ }
+
+ void TrStmt(Statement! stmt, Bpl.StmtListBuilder! builder, Bpl.VariableSeq! locals, ExpressionTranslator! etran)
+ requires currentMethod != null && predef != null;
+ {
+ if (stmt is AssertStmt) {
+ AddComment(builder, stmt, "assert statement");
+ AssertStmt s = (AssertStmt)stmt;
+ int pieces = 0;
+ foreach (Expression p in SplitExpr(s.Expr, true)) {
+ builder.Add(Assert(stmt.Tok, IsTotal(p, etran), "assert condition must be well defined")); // totality check
+ builder.Add(new Bpl.AssertCmd(stmt.Tok, etran.TrExpr(p)));
+ pieces++;
+ }
+ if (2 <= pieces) {
+ builder.Add(new Bpl.AssumeCmd(stmt.Tok, etran.TrExpr(s.Expr)));
+ }
+ } else if (stmt is AssumeStmt) {
+ AddComment(builder, stmt, "assume statement");
+ AssumeStmt s = (AssumeStmt)stmt;
+ builder.Add(Assert(stmt.Tok, IsTotal(s.Expr, etran), "assume condition must be well defined")); // totality check
+ builder.Add(new Bpl.AssumeCmd(stmt.Tok, etran.TrExpr(s.Expr)));
+ } else if (stmt is UseStmt) {
+ AddComment(builder, stmt, "use statement");
+ UseStmt s = (UseStmt)stmt;
+ builder.Add(Assert(stmt.Tok, IsTotal(s.Expr, etran), "use expression must be well defined")); // totality check
+ builder.Add(new Bpl.AssumeCmd(stmt.Tok, (s.EvalInOld ? etran.Old : etran).TrUseExpr(s.FunctionCallExpr)));
+ } else if (stmt is LabelStmt) {
+ AddComment(builder, stmt, "label statement"); // TODO: ouch, comments probably mess up what the label labels in the Boogie program
+ builder.AddLabelCmd(((LabelStmt)stmt).Label);
+ } else if (stmt is BreakStmt) {
+ AddComment(builder, stmt, "break statement");
+ builder.Add(new Bpl.BreakCmd(stmt.Tok, ((BreakStmt)stmt).TargetLabel)); // TODO: handle name clashes of labels
+ } else if (stmt is ReturnStmt) {
+ AddComment(builder, stmt, "return statement");
+ builder.Add(new Bpl.ReturnCmd(stmt.Tok));
+ } else if (stmt is AssignStmt) {
+ AddComment(builder, stmt, "assignment statement");
+ AssignStmt s = (AssignStmt)stmt;
+ TrAssignment(stmt.Tok, s.Lhs, s.Rhs, builder, locals, etran);
+ } else if (stmt is VarDecl) {
+ AddComment(builder, stmt, "var-declaration statement");
+ VarDecl s = (VarDecl)stmt;
+ Bpl.Type varType = TrType(s.Type);
+ Bpl.Expr wh = GetWhereClause(stmt.Tok, new Bpl.IdentifierExpr(stmt.Tok, s.UniqueName, varType), s.Type, etran);
+ Bpl.LocalVariable var = new Bpl.LocalVariable(stmt.Tok, new Bpl.TypedIdent(stmt.Tok, s.UniqueName, varType, wh));
+ locals.Add(var);
+ if (s.Rhs != null) {
+ IdentifierExpr ide = new IdentifierExpr(stmt.Tok, var.Name); // allocate an expression for the assignment LHS...
+ ide.Var = s; ide.Type = s.Type; // ... and resolve it right here
+ TrAssignment(stmt.Tok, ide, s.Rhs, builder, locals, etran);
+ }
+
+ } else if (stmt is CallStmt) {
+ AddComment(builder, stmt, "call statement");
+ CallStmt s = (CallStmt)stmt;
+ Bpl.ExprSeq ins = new Bpl.ExprSeq();
+ ins.Add(etran.TrExpr(s.Receiver));
+ for (int i = 0; i < s.Args.Count; i++) {
+ Expression e = s.Args[i];
+ Type t = ((!)s.Method).Ins[i].Type;
+ ins.Add(etran.CondApplyBox(stmt.Tok, etran.TrExpr(e), (!)e.Type, t));
+ }
+ Bpl.IdentifierExprSeq outs = new Bpl.IdentifierExprSeq();
+ List<Bpl.IdentifierExpr> tmpOuts = new List<Bpl.IdentifierExpr>(s.Lhs.Count);
+ for (int i = 0; i < s.Lhs.Count; i++) {
+ Expression e = s.Lhs[i];
+ if (ExpressionTranslator.ModeledAsRef(((!)s.Method).Outs[i].Type) && !ExpressionTranslator.ModeledAsRef((!)e.Type)) {
+ // we need an Unbox
+ Bpl.LocalVariable var = new Bpl.LocalVariable(stmt.Tok, new Bpl.TypedIdent(stmt.Tok, "$tmp#" + otherTmpVarCount, predef.RefType));
+ otherTmpVarCount++;
+ locals.Add(var);
+ Bpl.IdentifierExpr varIdE = new Bpl.IdentifierExpr(stmt.Tok, var.Name, predef.RefType);
+ tmpOuts.Add(varIdE);
+ outs.Add(varIdE);
+ } else {
+ tmpOuts.Add(null);
+ outs.Add(etran.TrExpr(e));
+ }
+ }
+
+ Bpl.CallCmd call = new Bpl.CallCmd(stmt.Tok, ((!)s.Method).FullName, ins, outs);
+ builder.Add(call);
+ for (int i = 0; i < s.Lhs.Count; i++) {
+ Bpl.IdentifierExpr tmpVarIdE = tmpOuts[i];
+ if (tmpVarIdE != null) {
+ IdentifierExpr e = s.Lhs[i];
+ // e := UnBox(tmpVar);
+ Bpl.IdentifierExpr lhs = (Bpl.IdentifierExpr)etran.TrExpr(e); // TODO: is this cast always justified?
+ Bpl.Cmd cmd = Bpl.Cmd.SimpleAssign(stmt.Tok, lhs, FunctionSpecial(stmt.Tok, BuiltinFunction.Unbox, TrType((!)e.Type), tmpVarIdE));
+ builder.Add(cmd);
+ }
+ }
+
+ } else if (stmt is BlockStmt) {
+ foreach (Statement ss in ((BlockStmt)stmt).Body) {
+ TrStmt(ss, builder, locals, etran);
+ }
+ } else if (stmt is IfStmt) {
+ AddComment(builder, stmt, "if statement");
+ IfStmt s = (IfStmt)stmt;
+ Bpl.Expr guard = s.Guard == null ? null : etran.TrExpr(s.Guard);
+ Bpl.StmtList thn = TrStmt2StmtList(s.Thn, locals, etran);
+ Bpl.StmtList els = null;
+ Bpl.IfCmd elsIf = null;
+ if (s.Els != null) {
+ els = TrStmt2StmtList(s.Els, locals, etran);
+ if (els.BigBlocks.Count == 1) {
+ Bpl.BigBlock bb = els.BigBlocks[0];
+ if (bb.LabelName == null && bb.simpleCmds.Length == 0 && bb.ec is Bpl.IfCmd) {
+ elsIf = (Bpl.IfCmd)bb.ec;
+ els = null;
+ }
+ }
+ }
+ builder.Add(new Bpl.IfCmd(stmt.Tok, guard, thn, elsIf, els));
+
+ } else if (stmt is WhileStmt) {
+ AddComment(builder, stmt, "while statement");
+ WhileStmt s = (WhileStmt)stmt;
+
+ Bpl.LocalVariable preLoopHeapVar = new Bpl.LocalVariable(stmt.Tok, new Bpl.TypedIdent(stmt.Tok, "$PreLoopHeap" + loopHeapVarCount, predef.HeapType));
+ locals.Add(preLoopHeapVar);
+ Bpl.IdentifierExpr preLoopHeap = new Bpl.IdentifierExpr(stmt.Tok, preLoopHeapVar);
+ ExpressionTranslator etranPreLoop = new ExpressionTranslator(this, predef, preLoopHeap);
+ builder.Add(Bpl.Cmd.SimpleAssign(stmt.Tok, preLoopHeap, etran.HeapExpr)); // TODO: does this screw up labeled breaks for this loop?
+
+ Bpl.Expr guard = s.Guard == null ? null : etran.TrExpr(s.Guard);
+ List<Bpl.PredicateCmd!> invariants = new List<Bpl.PredicateCmd!>();
+ foreach (MaybeFreeExpression loopInv in s.Invariants) {
+ int pieces = 0;
+ if (!loopInv.IsFree) {
+ foreach (Expression se in SplitExpr(loopInv.E, true)) {
+ invariants.Add(new Bpl.AssertCmd(se.tok, etran.TrExpr(se)));
+ pieces++;
+ }
+ }
+ if (pieces != 1) {
+ invariants.Add(new Bpl.AssumeCmd(loopInv.E.tok, etran.TrExpr(loopInv.E)));
+ }
+ }
+ foreach (BoilerplateTriple tri in GetTwoStateBoilerplate(stmt.Tok, currentMethod, etranPreLoop, etran)) {
+ if (tri.IsFree) {
+ invariants.Add(new Bpl.AssumeCmd(stmt.Tok, tri.Expr));
+ } else {
+ assert tri.ErrorMessage != null; // follows from BoilerplateTriple invariant
+ invariants.Add(Assert(stmt.Tok, tri.Expr, tri.ErrorMessage));
+ }
+ }
+
+ Bpl.StmtList body;
+ if (s.Decreases.Count == 0) {
+ body = TrStmt2StmtList(s.Body, locals, etran);
+ } else {
+ Bpl.StmtListBuilder loopBodyBuilder = new Bpl.StmtListBuilder();
+
+ List<Bpl.IdentifierExpr!> oldBfs = new List<Bpl.IdentifierExpr!>();
+ int c = 0;
+ foreach (Expression e in s.Decreases) {
+ Bpl.LocalVariable bfVar = new Bpl.LocalVariable(e.tok, new Bpl.TypedIdent(e.tok, "$decr" + loopHeapVarCount + "$" + c, TrType((!)e.Type)));
+ locals.Add(bfVar);
+ Bpl.IdentifierExpr bf = new Bpl.IdentifierExpr(e.tok, bfVar);
+ oldBfs.Add(bf);
+ // record value of each decreases expression at beginning of the loop iteration
+ invariants.Add(Assert(e.tok, IsTotal(e, etran), "decreases expression must be well defined at top of each loop iteration")); // totality check
+ Bpl.Cmd cmd = Bpl.Cmd.SimpleAssign(e.tok, bf, etran.TrExpr(e));
+ loopBodyBuilder.Add(cmd);
+
+ c++;
+ }
+ // time for the actual loop body
+ TrStmt(s.Body, loopBodyBuilder, locals, etran);
+ // check definedness of decreases expressions
+ foreach (Expression e in s.Decreases) {
+ // The following totality check implies that the loop invariant stating the same property will hold;
+ // thus, an alternative (perhaps preferable) design would be: add the totality check also just before
+ // the loop, and change the loop invariant to be free.
+ loopBodyBuilder.Add(Assert(e.tok, IsTotal(e, etran), "decreases expression must be well defined at end of loop iteration")); // totality check
+ }
+ // compute eq and less for each component of the lexicographic pair
+ List<Bpl.Expr!> Eq = new List<Bpl.Expr!>();
+ List<Bpl.Expr!> Less = new List<Bpl.Expr!>();
+ for (int i = 0; i < s.Decreases.Count; i++) {
+ Expression e = s.Decreases[i];
+ Bpl.Expr d = etran.TrExpr(e);
+ Bpl.IdentifierExpr bf = oldBfs[i];
+
+ Bpl.Expr less;
+ Bpl.Expr eq;
+ Type ty = (!)e.Type;
+ if (ty is BoolType) {
+ eq = Bpl.Expr.Iff(d, bf);
+ less = Bpl.Expr.And(Bpl.Expr.Not(d), bf);
+ } else if (ty is IntType) {
+ eq = Bpl.Expr.Eq(d, bf);
+ less = Bpl.Expr.Lt(d, bf);
+ } else if (ty is SetType) {
+ eq = FunctionCall(stmt.Tok, BuiltinFunction.SetEqual, null, d, bf);
+ less = etran.ProperSubset(stmt.Tok, d, bf);
+ } else if (ty is SeqType) {
+ Bpl.Expr e0 = FunctionCall(stmt.Tok, BuiltinFunction.SeqLength, null, d);
+ Bpl.Expr e1 = FunctionCall(stmt.Tok, BuiltinFunction.SeqLength, null, bf);
+ eq = Bpl.Expr.Eq(e0, e1);
+ less = Bpl.Expr.Lt(e0, e1);
+ } else {
+ // reference type
+ Bpl.Expr e0 = Bpl.Expr.Neq(d, predef.Null);
+ Bpl.Expr e1 = Bpl.Expr.Neq(bf, predef.Null);
+ eq = Bpl.Expr.Iff(e0, e1);
+ less = Bpl.Expr.And(Bpl.Expr.Not(e0), e1);
+ }
+ Eq.Add(eq);
+ Less.Add(less);
+ }
+ // check: 0 <= old(decreases)
+ // more precisely, for component k of the lexicographic decreases function, check:
+ // 0 <= old(dec(k)) || dec0 < old(dec0) || dec1 < old(dec1) || ... || dec(k-1) < old(dec((k-1) || old(dec(k)) == dec(k)
+ for (int k = 0; k < s.Decreases.Count; k++) {
+ Expression e = s.Decreases[k];
+ // we only need to check lower bound for integers--sets, sequences, booleans, and references all have natural lower bounds
+ if (e.Type is IntType) {
+ Bpl.IdentifierExpr bf = oldBfs[k];
+ Bpl.Expr bounded = Bpl.Expr.Le(Bpl.Expr.Literal(0), bf);
+ for (int i = 0; i < k; i++) {
+ bounded = Bpl.Expr.Or(bounded, Less[i]);
+ }
+ Bpl.Cmd cmd = Assert(e.tok, Bpl.Expr.Or(bounded, Eq[k]), "decreases expression must be bounded below by 0");
+ loopBodyBuilder.Add(cmd);
+ }
+ }
+ // check: decreases < old(decreases)
+ Bpl.Expr decrCheck = null;
+ for (int i = s.Decreases.Count; 0 <= --i; )
+ invariant i != s.Decreases.Count ==> decrCheck != null;
+ {
+ Bpl.Expr less = Less[i];
+ Bpl.Expr eq = Eq[i];
+ if (decrCheck == null) {
+ decrCheck = less;
+ } else {
+ // decrCheck = less || (eq && decrCheck)
+ decrCheck = Bpl.Expr.Or(less, Bpl.Expr.And(eq, decrCheck));
+ }
+ }
+ assert decrCheck != null; // follows from loop invariant and the fact that s.Decreases.Count != 0
+ loopBodyBuilder.Add(Assert(stmt.Tok, decrCheck, "decreases expression might not decrease"));
+
+ body = loopBodyBuilder.Collect(stmt.Tok);
+ }
+
+ builder.Add(new Bpl.WhileCmd(stmt.Tok, guard, invariants, body));
+ loopHeapVarCount++;
+
+ } else if (stmt is ForeachStmt) {
+ AddComment(builder, stmt, "foreach statement");
+ ForeachStmt s = (ForeachStmt)stmt;
+ // assert/assume (forall o: ref :: o in S ==> Expr);
+ // var oldHeap := $Heap;
+ // havoc $Heap;
+ // assume $HeapSucc(oldHeap, $Heap);
+ // assume (forall o: ref, f: Field :: $Heap[o,f] = oldHeap[o,f] || (f = F && o in S));
+ // assume (forall o: ref :: o != null && o in S ==> $Heap[o,F] = RHS[$Heap := oldHeap]);
+ // Note, $Heap[o,alloc] is intentionally omitted from the antecedent of the quantifier in the previous line. That
+ // allocatedness property should hold automatically, because the set/seq quantified is a program expression, which
+ // will have been constructed from allocated objects.
+ // For sets, "o in S" means just that. For sequences, "o in S" is:
+ // (exists i :: { Seq#Index(S,i) } 0 <= i && i < Seq#Length(S) && Seq#Index(S,i) == o)
+
+ Bpl.BoundVariable oVar = new Bpl.BoundVariable(stmt.Tok, new Bpl.TypedIdent(stmt.Tok, s.BoundVar.UniqueName, TrType(s.BoundVar.Type)));
+ Bpl.IdentifierExpr o = new Bpl.IdentifierExpr(stmt.Tok, oVar);
+
+ Bpl.Expr oInS;
+ if (s.Collection.Type is SetType) {
+ oInS = etran.TrInSet(stmt.Tok, o, s.Collection, null);
+ } else {
+ Bpl.BoundVariable iVar = new Bpl.BoundVariable(stmt.Tok, new Bpl.TypedIdent(stmt.Tok, "$i", Bpl.Type.Int));
+ Bpl.IdentifierExpr i = new Bpl.IdentifierExpr(stmt.Tok, iVar);
+ Bpl.Expr S = etran.TrExpr(s.Collection);
+ Bpl.Expr range = InSeqRange(stmt.Tok, i, S, null, false);
+ Bpl.Expr Si = FunctionCall(stmt.Tok, BuiltinFunction.SeqIndex, TrType(((SeqType!)s.Collection.Type).Arg), S, i);
+ Bpl.Trigger tr = new Bpl.Trigger(stmt.Tok, true, new Bpl.ExprSeq(Si));
+ // TODO: in the next line, the == should be replaced by something that understands extensionality, for sets and sequences
+ oInS = new Bpl.ExistsExpr(stmt.Tok, new Bpl.VariableSeq(iVar), tr, Bpl.Expr.And(range, Bpl.Expr.Eq(Si, o)));
+ }
+
+ foreach (PredicateStmt ps in s.BodyPrefix) {
+ int pieces = 0;
+ if (ps is AssertStmt) {
+ foreach (Expression se in SplitExpr(ps.Expr, true)) {
+ Bpl.Expr e = etran.TrExpr(se);
+ Bpl.Expr q = new Bpl.ForallExpr(se.tok, new Bpl.VariableSeq(oVar), Bpl.Expr.Imp(oInS, e));
+ builder.Add(new Bpl.AssertCmd(se.tok, q));
+ pieces++;
+ }
+ }
+ if (pieces != 1) {
+ Bpl.Expr e;
+ if (ps is UseStmt) {
+ UseStmt us = (UseStmt)ps;
+ e = (us.EvalInOld ? etran.Old : etran).TrUseExpr(us.FunctionCallExpr);
+ } else {
+ e = etran.TrExpr(ps.Expr);
+ }
+ Bpl.Expr q = new Bpl.ForallExpr(ps.Expr.tok, new Bpl.VariableSeq(oVar), Bpl.Expr.Imp(oInS, e));
+ builder.Add(new Bpl.AssumeCmd(ps.Expr.tok, q));
+ }
+ }
+
+ Bpl.IdentifierExpr prevHeap = GetPrevHeapVar_IdExpr(stmt.Tok, locals);
+ builder.Add(Bpl.Cmd.SimpleAssign(stmt.Tok, prevHeap, etran.HeapExpr));
+ builder.Add(new Bpl.HavocCmd(stmt.Tok, new Bpl.IdentifierExprSeq((Bpl.IdentifierExpr/*TODO: this cast is rather dubious*/)etran.HeapExpr)));
+ builder.Add(new Bpl.AssumeCmd(stmt.Tok, FunctionCall(stmt.Tok, BuiltinFunction.HeapSucc, null, prevHeap, etran.HeapExpr)));
+
+ // Here comes: assume (forall<alpha> o: ref, f: Field alpha :: $Heap[o,f] = oldHeap[o,f] || (f = F && o in S));
+ Bpl.TypeVariable alpha = new Bpl.TypeVariable(stmt.Tok, "alpha");
+ Bpl.BoundVariable fVar = new Bpl.BoundVariable(stmt.Tok, new Bpl.TypedIdent(stmt.Tok, "$f", predef.FieldName(stmt.Tok, alpha)));
+ Bpl.IdentifierExpr f = new Bpl.IdentifierExpr(stmt.Tok, fVar);
+ Bpl.Expr heapOF = Bpl.Expr.SelectTok(stmt.Tok, etran.HeapExpr, o, f);
+ Bpl.Expr oldHeapOF = Bpl.Expr.SelectTok(stmt.Tok, prevHeap, o, f);
+ Bpl.Expr body = Bpl.Expr.Or(
+ Bpl.Expr.Eq(heapOF, oldHeapOF),
+ Bpl.Expr.And(
+ Bpl.Expr.Eq(f, GetField((FieldSelectExpr)((!)s.BodyAssign).Lhs)),
+ oInS));
+ Bpl.Expr qq = new Bpl.ForallExpr(stmt.Tok, new Bpl.TypeVariableSeq(alpha), new Bpl.VariableSeq(oVar, fVar), body);
+ builder.Add(new Bpl.AssumeCmd(stmt.Tok, qq));
+
+ // Here comes: assume (forall o: ref :: o != null && o in S ==> $Heap[o,F] = RHS[$Heap := oldHeap]);
+ Bpl.Expr heapOField = Bpl.Expr.SelectTok(stmt.Tok, etran.HeapExpr, o, GetField((FieldSelectExpr)(s.BodyAssign).Lhs));
+ ExpressionTranslator oldEtran = new ExpressionTranslator(this, predef, prevHeap);
+ body = Bpl.Expr.Imp(
+ Bpl.Expr.And(Bpl.Expr.Neq(o, predef.Null), oInS),
+ Bpl.Expr.Eq(heapOField, oldEtran.TrExpr(((ExprRhs)s.BodyAssign.Rhs).Expr)));
+ qq = new Bpl.ForallExpr(stmt.Tok, new Bpl.VariableSeq(oVar), body);
+ builder.Add(new Bpl.AssumeCmd(stmt.Tok, qq));
+
+ } else {
+ assert false; // unexpected statement
+ }
+ }
+
+ void AddComment(Bpl.StmtListBuilder! builder, Statement! stmt, string! comment) {
+ builder.Add(new Bpl.CommentCmd(string.Format("----- {0} ----- {1}({2},{3})", comment, stmt.Tok.filename, stmt.Tok.line, stmt.Tok.col)));
+ }
+
+ Bpl.Expr GetWhereClause(Token! tok, Bpl.Expr! x, Type! type, ExpressionTranslator! etran)
+ requires predef != null;
+ {
+ if (type is TypeProxy) {
+ // unresolved proxy
+ assert ((TypeProxy)type).T == null;
+ // omit where clause (in other places, unresolved proxies are treated as a reference type; we could do that here too, but
+ // we might as well leave out the where clause altogether)
+ return null;
+ } else if (type is BoolType || type is IntType) {
+ return null;
+ } else if (type is SetType) {
+ SetType st = (SetType)type;
+ if (st.Arg.IsRefType) {
+ // (forall t: ref :: { x[t] } x[t] ==> t == null || $Heap[t,alloc])
+ Bpl.BoundVariable tVar = new Bpl.BoundVariable(tok, new Bpl.TypedIdent(tok, "$t", predef.RefType));
+ Bpl.Expr t = new Bpl.IdentifierExpr(tok, tVar);
+ Bpl.Expr xSubT = Bpl.Expr.SelectTok(tok, x, t);
+
+ Bpl.Trigger tr = new Bpl.Trigger(tok, true, new Bpl.ExprSeq(xSubT));
+
+ Bpl.Expr goodRef = etran.GoodRef(tok, t, st.Arg);
+ Bpl.Expr body = Bpl.Expr.Imp(xSubT, Bpl.Expr.Or(Bpl.Expr.Eq(t, predef.Null), goodRef));
+ return new Bpl.ForallExpr(tok, new Bpl.VariableSeq(tVar), tr, body);
+ } else {
+ // TODO: should also handle sets of sets, etc.
+ return null;
+ }
+
+ } else if (type is SeqType) {
+ SeqType st = (SeqType)type;
+ if (st.Arg.IsRefType) {
+ // (forall i: int :: { Seq#Index(x,i) }
+ // 0 <= i && i < Seq#Length(x) ==> Seq#Index(x,i) == null || $Heap[Seq#Index(x,i), alloc])
+ Bpl.BoundVariable iVar = new Bpl.BoundVariable(tok, new Bpl.TypedIdent(tok, "$i", Bpl.Type.Int));
+ Bpl.Expr i = new Bpl.IdentifierExpr(tok, iVar);
+ Bpl.Expr xSubI = FunctionCall(tok, BuiltinFunction.SeqIndex, predef.RefType, x, i);
+
+ Bpl.Expr range = InSeqRange(tok, i, x, null, false);
+
+ Bpl.Trigger tr = new Bpl.Trigger(tok, true, new Bpl.ExprSeq(xSubI));
+
+ Bpl.Expr goodRef = etran.GoodRef(tok, xSubI, st.Arg);
+ Bpl.Expr body = Bpl.Expr.Imp(range, Bpl.Expr.Or(Bpl.Expr.Eq(xSubI, predef.Null), goodRef));
+ return new Bpl.ForallExpr(tok, new Bpl.VariableSeq(iVar), tr, body);
+ } else {
+ // TODO: should also handle sequences or sequences, etc.
+ return null;
+ }
+
+ } else if (type.IsRefType) {
+ // reference type:
+ // x == null || $Heap[x,alloc]
+ return Bpl.Expr.Or(Bpl.Expr.Eq(x, predef.Null), etran.GoodRef(tok, x, type));
+ } else {
+ // type parameter
+ return null;
+ }
+ }
+
+ void TrAssignment(Token! tok, Expression! lhs, AssignmentRhs! rhs, Bpl.StmtListBuilder! builder, Bpl.VariableSeq! locals,
+ ExpressionTranslator! etran)
+ requires predef != null;
+ {
+ if (rhs is ExprRhs) {
+ builder.Add(Assert(tok, IsTotal(lhs, etran), "LHS expression must be well defined")); // totality check
+ builder.Add(Assert(tok, IsTotal(((ExprRhs)rhs).Expr, etran), "RHS expression must be well defined")); // totality check
+ Bpl.Expr bRhs = etran.TrExpr(((ExprRhs)rhs).Expr);
+ if (lhs is IdentifierExpr) {
+ Bpl.IdentifierExpr bLhs = (Bpl.IdentifierExpr)etran.TrExpr(lhs); // TODO: is this cast always justified?
+ Bpl.Cmd cmd = Bpl.Cmd.SimpleAssign(tok, bLhs, bRhs);
+ builder.Add(cmd);
+ } else {
+ Bpl.NAryExpr bLhs = (Bpl.NAryExpr)etran.TrExpr(lhs); // TODO: is this cast always justified?
+ assert bLhs.Args.Length == 3; // we're expecting h[o,f]
+ Bpl.IdentifierExpr h = (Bpl.IdentifierExpr!)bLhs.Args[0]; // TODO: is this cast always justified?
+ Bpl.Cmd cmd = Bpl.Cmd.MapAssign(tok, h, (!)bLhs.Args[1], (!)bLhs.Args[2], bRhs);
+ builder.Add(cmd);
+ // assume $IsGoodHeap($Heap);
+ builder.Add(AssumeGoodHeap(tok, etran));
+ }
+
+ } else if (rhs is HavocRhs) {
+ assert lhs is IdentifierExpr; // for this kind of RHS, the LHS is restricted to be a simple variable
+ Bpl.IdentifierExpr x = (Bpl.IdentifierExpr)etran.TrExpr(lhs); // TODO: is this cast always justified?
+ builder.Add(new Bpl.HavocCmd(tok, new Bpl.IdentifierExprSeq(x)));
+
+ } else {
+ assert rhs is TypeRhs; // otherwise, an unexpected AssignmentRhs
+ assert lhs is IdentifierExpr; // for this kind of RHS, the LHS is restricted to be a simple variable
+
+ Bpl.IdentifierExpr nw = GetNewVar_IdExpr(tok, locals);
+ builder.Add(new Bpl.HavocCmd(tok, new Bpl.IdentifierExprSeq(nw)));
+ // assume $nw != null && !$Heap[$nw, alloc] && dtype($nw) == RHS;
+ Bpl.Expr nwNotNull = Bpl.Expr.Neq(nw, predef.Null);
+ builder.Add(new Bpl.AssumeCmd(tok, Bpl.Expr.And(nwNotNull, etran.GoodRef_Class(tok, nw, (ClassType)((TypeRhs)rhs).Type, true))));
+ // $Heap[$nw, alloc] := true;
+ Bpl.Expr alloc = predef.Alloc(tok);
+ Bpl.Cmd cmd = Bpl.Cmd.MapAssign(tok, (Bpl.IdentifierExpr/*TODO: this cast is dubious*/)etran.HeapExpr, nw, alloc, Bpl.Expr.True);
+ builder.Add(cmd);
+ // x := $nw;
+ Bpl.IdentifierExpr x = (Bpl.IdentifierExpr)etran.TrExpr(lhs); // TODO: is this cast always justified?
+ builder.Add(Bpl.Cmd.SimpleAssign(tok, x, nw));
+ // assume $IsGoodHeap($Heap);
+ builder.Add(AssumeGoodHeap(tok, etran));
+ }
+ }
+
+ Bpl.AssumeCmd! AssumeGoodHeap(Token! tok, ExpressionTranslator! etran) {
+ return new Bpl.AssumeCmd(tok, FunctionCall(tok, BuiltinFunction.IsGoodHeap, null, etran.HeapExpr));
+ }
+
+ // ----- Expression ---------------------------------------------------------------------------
+
+ internal class ExpressionTranslator {
+ public readonly Bpl.Expr! HeapExpr;
+ public readonly PredefinedDecls! predef;
+ public readonly Translator! translator;
+ public ExpressionTranslator(Translator! translator, PredefinedDecls! predef, Token! heapToken) {
+ this.translator = translator;
+ this.predef = predef;
+ HeapExpr = new Bpl.IdentifierExpr(heapToken, "$Heap", predef.HeapType);
+ }
+
+ public ExpressionTranslator(Translator! translator, PredefinedDecls! predef, Bpl.Expr! heap) {
+ this.translator = translator;
+ this.predef = predef;
+ this.HeapExpr = heap;
+ }
+
+ ExpressionTranslator oldEtran;
+ public ExpressionTranslator! Old {
+ get {
+ if (oldEtran == null) {
+ oldEtran = new ExpressionTranslator(translator, predef, new Bpl.OldExpr(HeapExpr.tok, HeapExpr));
+ }
+ return oldEtran;
+ }
+ }
+
+ public Bpl.Expr! TrExpr(Expression! expr)
+ requires predef != null;
+ {
+ if (expr is LiteralExpr) {
+ LiteralExpr e = (LiteralExpr)expr;
+ if (e.Value == null) {
+ return predef.Null;
+ } else if (e.Value is bool) {
+ return Bpl.Expr.Literal((bool)e.Value);
+ } else if (e.Value is int) {
+ return Bpl.Expr.Literal((int)e.Value);
+ } else {
+ assert false; // unexpected literal
+ }
+
+ } else if (expr is ThisExpr) {
+ return new Bpl.IdentifierExpr(expr.tok, "this", predef.RefType);
+
+ } else if (expr is IdentifierExpr) {
+ IdentifierExpr e = (IdentifierExpr)expr;
+ return TrVar(expr.tok, (!)e.Var);
+
+ } else if (expr is SetDisplayExpr) {
+ SetDisplayExpr e = (SetDisplayExpr)expr;
+ Bpl.Expr s = translator.FunctionCall(expr.tok, BuiltinFunction.SetEmpty, translator.TrType((!)expr.Type));
+ foreach (Expression ee in e.Elements) {
+ Bpl.Expr ss = TrExpr(ee);
+ s = translator.FunctionCall(expr.tok, BuiltinFunction.SetUnionOne, translator.TrType(expr.Type), s, ss);
+ }
+ return s;
+
+ } else if (expr is SeqDisplayExpr) {
+ SeqDisplayExpr e = (SeqDisplayExpr)expr;
+ Bpl.Expr s = translator.FunctionCall(expr.tok, BuiltinFunction.SeqEmpty, translator.TrType((!)expr.Type));
+ int i = 0;
+ foreach (Expression ee in e.Elements) {
+ Bpl.Expr ss = TrExpr(ee);
+ s = translator.FunctionCall(expr.tok, BuiltinFunction.SeqBuild, translator.TrType(expr.Type), s, Bpl.Expr.Literal(i), ss, Bpl.Expr.Literal(i+1));
+ i++;
+ }
+ return s;
+
+ } else if (expr is FieldSelectExpr) {
+ FieldSelectExpr e = (FieldSelectExpr)expr;
+ return Bpl.Expr.SelectTok(expr.tok, HeapExpr, TrExpr(e.Obj), new Bpl.IdentifierExpr(expr.tok, translator.GetField((!)e.Field)));
+
+ } else if (expr is SeqSelectExpr) {
+ SeqSelectExpr e = (SeqSelectExpr)expr;
+ Bpl.Expr seq = TrExpr(e.Seq);
+ Bpl.Type elType = translator.TrType(((SeqType!)e.Seq.Type).Arg);
+ Bpl.Expr e0 = e.E0 == null ? null : TrExpr(e.E0);
+ Bpl.Expr e1 = e.E1 == null ? null : TrExpr(e.E1);
+ if (e.SelectOne) {
+ assert e1 == null;
+ return translator.FunctionCall(expr.tok, BuiltinFunction.SeqIndex, elType, seq, e0);
+ } else {
+ if (e1 != null) {
+ seq = translator.FunctionCall(expr.tok, BuiltinFunction.SeqTake, elType, seq, e1);
+ }
+ if (e0 != null) {
+ seq = translator.FunctionCall(expr.tok, BuiltinFunction.SeqDrop, elType, seq, e0);
+ }
+ return seq;
+ }
+
+ } else if (expr is FunctionCallExpr) {
+ FunctionCallExpr e = (FunctionCallExpr)expr;
+ string nm = ((!)e.Function).FullName + (e is UseExpr ? "#use" : "");
+ Bpl.IdentifierExpr id = new Bpl.IdentifierExpr(expr.tok, nm, translator.TrType((!)e.Type));
+ Bpl.ExprSeq args = new Bpl.ExprSeq();
+ args.Add(HeapExpr);
+ args.Add(TrExpr(e.Receiver));
+ for (int i = 0; i < e.Args.Count; i++) {
+ Expression ee = e.Args[i];
+ Type t = e.Function.Formals[i].Type;
+ args.Add(CondApplyBox(expr.tok, TrExpr(ee), (!)ee.Type, t));
+ }
+ Bpl.Expr result = new Bpl.NAryExpr(expr.tok, new Bpl.FunctionCall(id), args);
+ return CondApplyUnbox(expr.tok, result, e.Function.ResultType, expr.Type);
+
+ } else if (expr is OldExpr) {
+ OldExpr e = (OldExpr)expr;
+ return new Bpl.OldExpr(expr.tok, TrExpr(e.E));
+
+ } else if (expr is FreshExpr) {
+ FreshExpr e = (FreshExpr)expr;
+ Bpl.Expr oldHeap = new Bpl.OldExpr(expr.tok, HeapExpr);
+ if (e.E.Type is SetType) {
+ // generate: (forall $o: ref :: $o != null && X[$o] ==> !old($Heap)[$o,alloc])
+ // TODO: trigger?
+ Bpl.Variable oVar = new Bpl.BoundVariable(expr.tok, new Bpl.TypedIdent(expr.tok, "$o", predef.RefType));
+ Bpl.Expr o = new Bpl.IdentifierExpr(expr.tok, oVar);
+ Bpl.Expr oNotNull = Bpl.Expr.Neq(o, predef.Null);
+ Bpl.Expr oInSet = TrInSet(expr.tok, o, e.E, null);
+ Bpl.Expr oIsFresh = Bpl.Expr.Not(IsAlloced(expr.tok, o, oldHeap));
+ Bpl.Expr body = Bpl.Expr.Imp(Bpl.Expr.And(oNotNull, oInSet), oIsFresh);
+ return new Bpl.ForallExpr(expr.tok, new Bpl.VariableSeq(oVar), body);
+ } else if (e.E.Type is SeqType) {
+ // generate: (forall $i: int :: 0 <= $i && $i < Seq#Length(X) && Seq#Index(X,$i) != null ==> !old($Heap)[Seq#Index(X,$i),alloc])
+ // TODO: trigger?
+ Bpl.Variable iVar = new Bpl.BoundVariable(expr.tok, new Bpl.TypedIdent(expr.tok, "$i", Bpl.Type.Int));
+ Bpl.Expr i = new Bpl.IdentifierExpr(expr.tok, iVar);
+ Bpl.Expr iBounds = translator.InSeqRange(expr.tok, i, TrExpr(e.E), null, false);
+ Bpl.Expr XsubI = translator.FunctionCall(expr.tok, BuiltinFunction.SeqIndex, predef.RefType, TrExpr(e.E), i);
+ Bpl.Expr oIsFresh = Bpl.Expr.Not(IsAlloced(expr.tok, XsubI, oldHeap));
+ Bpl.Expr body = Bpl.Expr.Imp(Bpl.Expr.And(iBounds, XsubI), oIsFresh);
+ return new Bpl.ForallExpr(expr.tok, new Bpl.VariableSeq(iVar), body);
+ } else {
+ // generate: x == null || !old($Heap)[x]
+ Bpl.Expr oNotNull = Bpl.Expr.Neq(TrExpr(e.E), predef.Null);
+ Bpl.Expr oIsFresh = Bpl.Expr.Not(IsAlloced(expr.tok, TrExpr(e.E), oldHeap));
+ return Bpl.Expr.Or(oNotNull, oIsFresh);
+ }
+
+ } else if (expr is UnaryExpr) {
+ UnaryExpr e = (UnaryExpr)expr;
+ Bpl.Expr arg = TrExpr(e.E);
+ switch (e.Op) {
+ case UnaryExpr.Opcode.Not:
+ return Bpl.Expr.Not(arg);
+ case UnaryExpr.Opcode.SeqLength:
+ return translator.FunctionCall(expr.tok, BuiltinFunction.SeqLength, null, arg);
+ default:
+ assert false; // unexpected unary expression
+ }
+
+ } else if (expr is BinaryExpr) {
+ BinaryExpr e = (BinaryExpr)expr;
+ Bpl.Expr e0 = TrExpr(e.E0);
+ if (e.ResolvedOp == BinaryExpr.ResolvedOpcode.InSet) {
+ return TrInSet(expr.tok, e0, e.E1, e.E0.Type); // let TrInSet translate e.E1
+ }
+ Bpl.Expr e1 = TrExpr(e.E1);
+ switch (e.ResolvedOp) {
+ case BinaryExpr.ResolvedOpcode.Iff:
+ return Bpl.Expr.Iff(e0, e1);
+ case BinaryExpr.ResolvedOpcode.Imp:
+ return Bpl.Expr.Imp(e0, e1);
+ case BinaryExpr.ResolvedOpcode.And:
+ return Bpl.Expr.And(e0, e1);
+ case BinaryExpr.ResolvedOpcode.Or:
+ return Bpl.Expr.Or(e0, e1);
+
+ case BinaryExpr.ResolvedOpcode.EqCommon:
+ return Bpl.Expr.Eq(e0, e1);
+ case BinaryExpr.ResolvedOpcode.NeqCommon:
+ return Bpl.Expr.Neq(e0, e1);
+
+ case BinaryExpr.ResolvedOpcode.Lt:
+ return Bpl.Expr.Lt(e0, e1);
+ case BinaryExpr.ResolvedOpcode.Le:
+ return Bpl.Expr.Le(e0, e1);
+ case BinaryExpr.ResolvedOpcode.Ge:
+ return Bpl.Expr.Ge(e0, e1);
+ case BinaryExpr.ResolvedOpcode.Gt:
+ return Bpl.Expr.Gt(e0, e1);
+ case BinaryExpr.ResolvedOpcode.Add:
+ return Bpl.Expr.Add(e0, e1);
+ case BinaryExpr.ResolvedOpcode.Sub:
+ return Bpl.Expr.Sub(e0, e1);
+ case BinaryExpr.ResolvedOpcode.Mul:
+ return Bpl.Expr.Mul(e0, e1);
+ case BinaryExpr.ResolvedOpcode.Div:
+ return Bpl.Expr.Div(e0, e1);
+ case BinaryExpr.ResolvedOpcode.Mod:
+ return Bpl.Expr.Mod(e0, e1);
+
+ case BinaryExpr.ResolvedOpcode.SetEq:
+ return translator.FunctionCall(expr.tok, BuiltinFunction.SetEqual, null, e0, e1);
+ case BinaryExpr.ResolvedOpcode.SetNeq:
+ return Bpl.Expr.Not(translator.FunctionCall(expr.tok, BuiltinFunction.SetEqual, null, e0, e1));
+ case BinaryExpr.ResolvedOpcode.ProperSubset:
+ return ProperSubset(expr.tok, e0, e1);
+ case BinaryExpr.ResolvedOpcode.Subset:
+ return translator.FunctionCall(expr.tok, BuiltinFunction.SetSubset, null, e0, e1);
+ case BinaryExpr.ResolvedOpcode.Superset:
+ return translator.FunctionCall(expr.tok, BuiltinFunction.SetSubset, null, e1, e0);
+ case BinaryExpr.ResolvedOpcode.ProperSuperset:
+ return Bpl.Expr.And(
+ translator.FunctionCall(expr.tok, BuiltinFunction.SetSubset, null, e1, e0),
+ Bpl.Expr.Not(translator.FunctionCall(expr.tok, BuiltinFunction.SetEqual, null, e0, e1)));
+ case BinaryExpr.ResolvedOpcode.Disjoint:
+ return translator.FunctionCall(expr.tok, BuiltinFunction.SetDisjoint, null, e0, e1);
+ case BinaryExpr.ResolvedOpcode.InSet:
+ assert false; // this case handled above
+ case BinaryExpr.ResolvedOpcode.Union:
+ return translator.FunctionCall(expr.tok, BuiltinFunction.SetUnion, translator.TrType(((SetType!)expr.Type).Arg), e0, e1);
+ case BinaryExpr.ResolvedOpcode.Intersection:
+ return translator.FunctionCall(expr.tok, BuiltinFunction.SetIntersection, translator.TrType(((SetType!)expr.Type).Arg), e0, e1);
+ case BinaryExpr.ResolvedOpcode.SetDifference:
+ return translator.FunctionCall(expr.tok, BuiltinFunction.SetDifference, translator.TrType(((SetType!)expr.Type).Arg), e0, e1);
+
+ case BinaryExpr.ResolvedOpcode.SeqEq:
+ return translator.FunctionCall(expr.tok, BuiltinFunction.SeqEqual, null, e0, e1);
+ case BinaryExpr.ResolvedOpcode.SeqNeq:
+ return Bpl.Expr.Not(translator.FunctionCall(expr.tok, BuiltinFunction.SeqEqual, null, e0, e1));
+ case BinaryExpr.ResolvedOpcode.ProperPrefix:
+ return ProperPrefix(expr.tok, e0, e1);
+ case BinaryExpr.ResolvedOpcode.Prefix:
+ {
+ Bpl.Expr len0 = translator.FunctionCall(expr.tok, BuiltinFunction.SeqLength, null, e0);
+ Bpl.Expr len1 = translator.FunctionCall(expr.tok, BuiltinFunction.SeqLength, null, e1);
+ return Bpl.Expr.And(
+ Bpl.Expr.Le(len0, len1),
+ translator.FunctionCall(expr.tok, BuiltinFunction.SeqSameUntil, null, e0, e1, len0));
+ }
+ case BinaryExpr.ResolvedOpcode.Concat:
+ return translator.FunctionCall(expr.tok, BuiltinFunction.SeqAppend, translator.TrType(((SeqType!)expr.Type).Arg), e0, e1);
+ case BinaryExpr.ResolvedOpcode.InSeq:
+ return translator.FunctionCall(expr.tok, BuiltinFunction.SeqContains, null, e1, e0);
+
+ default:
+ assert false; // unexpected binary expression
+ }
+
+ } else if (expr is QuantifierExpr) {
+ QuantifierExpr e = (QuantifierExpr)expr;
+ Bpl.VariableSeq bvars = new Bpl.VariableSeq();
+ foreach (BoundVar bv in e.BoundVars) {
+ bvars.Add(new Bpl.BoundVariable(bv.tok, new Bpl.TypedIdent(bv.tok, bv.UniqueName, translator.TrType(bv.Type))));
+ }
+ Bpl.QKeyValue kv = TrAttributes(e.Attributes);
+ Bpl.Trigger tr = null;
+ for (Triggers trigs = e.Trigs; trigs != null; trigs = trigs.Prev) {
+ Bpl.ExprSeq tt = new Bpl.ExprSeq();
+ foreach (Expression term in trigs.Terms) {
+ tt.Add(TrExpr(term));
+ }
+ tr = new Bpl.Trigger(expr.tok, true, tt, tr);
+ }
+ Bpl.Expr body = TrExpr(e.Body);
+
+ if (e is ForallExpr) {
+ return new Bpl.ForallExpr(expr.tok, new Bpl.TypeVariableSeq(), bvars, kv, tr, body);
+ } else {
+ assert e is ExistsExpr;
+ return new Bpl.ExistsExpr(expr.tok, new Bpl.TypeVariableSeq(), bvars, kv, tr, body);
+ }
+
+ } else if (expr is ITEExpr) {
+ ITEExpr e = (ITEExpr)expr;
+ Bpl.Expr g = TrExpr(e.Test);
+ Bpl.Expr thn = TrExpr(e.Thn);
+ Bpl.Expr els = TrExpr(e.Els);
+ Bpl.Expr yea = Bpl.Expr.Imp(g, thn);
+ Bpl.Expr nay = Bpl.Expr.Imp(Bpl.Expr.Not(g), els);
+ return Bpl.Expr.And(yea, nay);
+
+ } else {
+ assert false; // unexpected expression
+ }
+ }
+
+ public Bpl.Expr! ProperSubset(Token! tok, Bpl.Expr! e0, Bpl.Expr! e1) {
+ return Bpl.Expr.And(
+ translator.FunctionCall(tok, BuiltinFunction.SetSubset, null, e0, e1),
+ Bpl.Expr.Not(translator.FunctionCall(tok, BuiltinFunction.SetEqual, null, e0, e1)));
+ }
+ public Bpl.Expr! ProperPrefix(Token! tok, Bpl.Expr! e0, Bpl.Expr! e1) {
+ Bpl.Expr len0 = translator.FunctionCall(tok, BuiltinFunction.SeqLength, null, e0);
+ Bpl.Expr len1 = translator.FunctionCall(tok, BuiltinFunction.SeqLength, null, e1);
+ return Bpl.Expr.And(
+ Bpl.Expr.Lt(len0, len1),
+ translator.FunctionCall(tok, BuiltinFunction.SeqSameUntil, null, e0, e1, len0));
+ }
+
+ public Bpl.Expr! TrUseExpr(FunctionCallExpr! e) {
+ Bpl.IdentifierExpr id = new Bpl.IdentifierExpr(e.tok, ((!)e.Function).FullName + "#use", translator.TrType((!)e.Type));
+ Bpl.ExprSeq args = new Bpl.ExprSeq();
+ args.Add(HeapExpr);
+ args.Add(TrExpr(e.Receiver));
+ foreach (Expression ee in e.Args) {
+ args.Add(TrExpr(ee));
+ }
+ return new Bpl.NAryExpr(e.tok, new Bpl.FunctionCall(id), args);
+ }
+
+ public Bpl.Expr! CondApplyBox(Token! tok, Bpl.Expr! e, Type! fromType, Type! toType) {
+ if (!ModeledAsRef(fromType) && ModeledAsRef(toType)) {
+ return translator.FunctionCall(tok, BuiltinFunction.Box, null, e);
+ } else {
+ return e;
+ }
+ }
+
+ public Bpl.Expr! CondApplyUnbox(Token! tok, Bpl.Expr! e, Type! fromType, Type! toType) {
+ if (ModeledAsRef(fromType) && !ModeledAsRef(toType)) {
+ return translator.FunctionSpecial(tok, BuiltinFunction.Unbox, translator.TrType(toType), e);
+ } else {
+ return e;
+ }
+ }
+
+ public static bool ModeledAsRef(Type! t) {
+ return !(t is BoolType || t is IntType || t is CollectionType);
+ }
+
+ public Bpl.Expr! TrVar(Token! tok, IVariable! var) {
+ return new Bpl.IdentifierExpr(tok, var.UniqueName, translator.TrType(var.Type));
+ }
+
+ /// <summary>
+ /// Translate like s[elmt], but try to avoid as many set functions as possible in the
+ /// translation, because such functions can mess up triggering.
+ /// If elmtType is non-null, boxing according to elmtType is applied as appropriate.
+ /// </summary>
+ public Bpl.Expr! TrInSet(Token! tok, Bpl.Expr! elmt, Expression! s, Type elmtType) {
+ if (s is BinaryExpr) {
+ BinaryExpr bin = (BinaryExpr)s;
+ switch (bin.ResolvedOp) {
+ case BinaryExpr.ResolvedOpcode.Union:
+ return Bpl.Expr.Or(TrInSet(tok, elmt, bin.E0, elmtType), TrInSet(tok, elmt, bin.E1, elmtType));
+ case BinaryExpr.ResolvedOpcode.Intersection:
+ return Bpl.Expr.And(TrInSet(tok, elmt, bin.E0, elmtType), TrInSet(tok, elmt, bin.E1, elmtType));
+ case BinaryExpr.ResolvedOpcode.SetDifference:
+ return Bpl.Expr.And(TrInSet(tok, elmt, bin.E0, elmtType), Bpl.Expr.Not(TrInSet(tok, elmt, bin.E1, elmtType)));
+ default:
+ break;
+ }
+ } else if (s is SetDisplayExpr) {
+ SetDisplayExpr disp = (SetDisplayExpr)s;
+ Bpl.Expr disjunction = null;
+ foreach (Expression a in disp.Elements) {
+ Bpl.Expr disjunct = Bpl.Expr.Eq(elmt, TrExpr(a));
+ if (disjunction == null) {
+ disjunction = disjunct;
+ } else {
+ disjunction = Bpl.Expr.Or(disjunction, disjunct);
+ }
+ }
+ if (disjunction == null) {
+ return Bpl.Expr.False;
+ } else {
+ return disjunction;
+ }
+ }
+ return Bpl.Expr.SelectTok(tok, TrExpr(s), elmt);
+ }
+
+ Bpl.QKeyValue TrAttributes(Attributes attrs) {
+ Bpl.QKeyValue kv = null;
+ while (attrs != null) {
+ List<object!> parms = new List<object!>();
+ foreach (Attributes.Argument arg in attrs.Args) {
+ if (arg.E != null) {
+ parms.Add(TrExpr(arg.E));
+ } else {
+ parms.Add((!)arg.S);
+ }
+ }
+ kv = new Bpl.QKeyValue(Token.NoToken, attrs.Name, parms, kv);
+ attrs = attrs.Prev;
+ }
+ return kv;
+ }
+
+ // --------------- help routines ---------------
+
+ public Bpl.Expr! IsAlloced(Token! tok, Bpl.Expr! e) {
+ return IsAlloced(tok, e, HeapExpr);
+ }
+
+ Bpl.Expr! IsAlloced(Token! tok, Bpl.Expr! e, Bpl.Expr! heap) {
+ return Bpl.Expr.SelectTok(tok, heap, e, predef.Alloc(tok));
+ }
+
+ public Bpl.Expr! GoodRef(Token! tok, Bpl.Expr! e, Type! type) {
+ Bpl.Expr goodRef;
+ if (type is ClassType && ((ClassType)type).ResolvedClass != null) {
+ // Heap[e, alloc] && dtype(e) == T
+ return GoodRef_Class(tok, e, (ClassType)type, false);
+ } else {
+ // Heap[e, alloc]
+ return IsAlloced(tok, e);
+ }
+ }
+
+ public Bpl.Expr! GoodRef_Class(Token! tok, Bpl.Expr! e, ClassType! type, bool isNew)
+ requires type.ResolvedClass != null;
+ {
+ // Heap[e, alloc]
+ Bpl.Expr r = IsAlloced(tok, e);
+ if (isNew) {
+ r = Bpl.Expr.Not(r); // use the conjunct: !Heap[e, alloc]
+ }
+
+ // dtype(e) == C
+ Bpl.Expr dtypeFunc = translator.FunctionCall(tok, BuiltinFunction.DynamicType, null, e);
+ Bpl.Expr dtype = Bpl.Expr.Eq(dtypeFunc, new Bpl.IdentifierExpr(tok, translator.GetClass(type.ResolvedClass)));
+ r = Bpl.Expr.And(r, dtype);
+
+ // dtypeParams(e, #) == T
+ int n = 0;
+ foreach (Type arg in type.TypeArgs) {
+ Bpl.Expr tpFunc = translator.FunctionCall(tok, BuiltinFunction.TypeParams, null, e, Bpl.Expr.Literal(n));
+ Bpl.Expr ta = translator.GetTypeExpr(tok, arg);
+ if (ta != null) {
+ r = Bpl.Expr.And(r, Bpl.Expr.Eq(tpFunc, ta));
+ }
+ n++;
+ }
+
+ return r;
+ }
+
+ public Bpl.Expr TypeAlloced(Token! tok, Bpl.Expr! e, Type! type) {
+ while (true) {
+ TypeProxy proxy = type as TypeProxy;
+ if (proxy == null) {
+ break;
+ } else if (proxy.T == null) {
+ return null;
+ } else {
+ type = proxy.T;
+ }
+ }
+
+ Bpl.BoundVariable bv = null;
+ Bpl.Expr ante = null;
+ if (type.IsRefType) { // object or class type
+ // e == null || $Heap[e, alloc]
+ // This is done below
+
+ } else if (type is SetType) {
+ // (forall tp: ref :: e[tp] ==> tp == null || $Heap[tp, alloc])
+ bv = new Bpl.BoundVariable(tok, new Bpl.TypedIdent(tok, "$tp", predef.RefType));
+ Bpl.Expr tp = new Bpl.IdentifierExpr(tok, bv);
+ ante = Bpl.Expr.SelectTok(tok, e, tp); // note, this means the set-inclusion does not undergo the set-inclusion expansion optimization done by TrInSet
+ e = tp;
+
+ } else if (type is SeqType) {
+ // (forall i: int :: Seq#Index(e,i) == null || $Heap[Seq#Index(e,i), alloc])
+ bv = new Bpl.BoundVariable(tok, new Bpl.TypedIdent(tok, "$i", Bpl.Type.Int));
+ e = translator.FunctionCall(tok, BuiltinFunction.SeqIndex, predef.RefType, e, new Bpl.IdentifierExpr(tok, bv));
+
+ } else {
+ return null;
+ }
+
+ Bpl.Expr r = Bpl.Expr.Or(Bpl.Expr.Eq(e, predef.Null), GoodRef(tok, e, type));
+ if (ante != null) {
+ r = Bpl.Expr.Imp(ante, r);
+ }
+ if (bv != null) {
+ r = new Bpl.ForallExpr(tok, new Bpl.VariableSeq(bv), r);
+ }
+ return r;
+ }
+ }
+
+ enum BuiltinFunction {
+ SetEmpty,
+ SetUnionOne,
+ SetUnion,
+ SetIntersection,
+ SetDifference,
+ SetEqual,
+ SetSubset,
+ SetDisjoint,
+
+ SeqLength,
+ SeqEmpty,
+ SeqBuild,
+ SeqAppend,
+ SeqIndex,
+ SeqContains,
+ SeqDrop,
+ SeqTake,
+ SeqEqual,
+ SeqSameUntil,
+
+ Box,
+ Unbox,
+
+ IsGoodHeap,
+ HeapSucc,
+
+ DynamicType, // allocated type
+ TypeParams, // type parameters to allocated type
+ TypeTuple
+ }
+
+ Bpl.NAryExpr! FunctionCall(Token! tok, BuiltinFunction f, Bpl.Type typeInstantiation, params Bpl.Expr[]! args)
+ requires predef != null;
+ {
+ switch (f) {
+ case BuiltinFunction.SetEmpty:
+ assert args.Length == 0;
+ assert typeInstantiation != null;
+ return FunctionCall(tok, "Set#Empty",
+ new Bpl.MapType(tok, new Bpl.TypeVariableSeq(), new Bpl.TypeSeq(typeInstantiation), Bpl.Type.Bool), args);
+ case BuiltinFunction.SetUnionOne:
+ assert args.Length == 2;
+ assert typeInstantiation != null;
+ return FunctionCall(tok, "Set#UnionOne",
+ new Bpl.MapType(tok, new Bpl.TypeVariableSeq(), new Bpl.TypeSeq(typeInstantiation), Bpl.Type.Bool), args);
+ case BuiltinFunction.SetUnion:
+ assert args.Length == 2;
+ assert typeInstantiation != null;
+ return FunctionCall(tok, "Set#Union",
+ new Bpl.MapType(tok, new Bpl.TypeVariableSeq(), new Bpl.TypeSeq(typeInstantiation), Bpl.Type.Bool), args);
+ case BuiltinFunction.SetIntersection:
+ assert args.Length == 2;
+ assert typeInstantiation != null;
+ return FunctionCall(tok, "Set#Intersection",
+ new Bpl.MapType(tok, new Bpl.TypeVariableSeq(), new Bpl.TypeSeq(typeInstantiation), Bpl.Type.Bool), args);
+ case BuiltinFunction.SetDifference:
+ assert args.Length == 2;
+ assert typeInstantiation != null;
+ return FunctionCall(tok, "Set#Difference",
+ new Bpl.MapType(tok, new Bpl.TypeVariableSeq(), new Bpl.TypeSeq(typeInstantiation), Bpl.Type.Bool), args);
+ case BuiltinFunction.SetEqual:
+ assert args.Length == 2;
+ assert typeInstantiation == null;
+ return FunctionCall(tok, "Set#Equal", Bpl.Type.Bool, args);
+ case BuiltinFunction.SetSubset:
+ assert args.Length == 2;
+ assert typeInstantiation == null;
+ return FunctionCall(tok, "Set#Subset", Bpl.Type.Bool, args);
+ case BuiltinFunction.SetDisjoint:
+ assert args.Length == 2;
+ assert typeInstantiation == null;
+ return FunctionCall(tok, "Set#Disjoint", Bpl.Type.Bool, args);
+
+ case BuiltinFunction.SeqLength:
+ assert args.Length == 1;
+ assert typeInstantiation == null;
+ return FunctionCall(tok, "Seq#Length", Bpl.Type.Int, args);
+ case BuiltinFunction.SeqEmpty:
+ assert args.Length == 0;
+ assert typeInstantiation != null;
+ return FunctionCall(tok, "Seq#Empty",
+ new Bpl.MapType(tok, new Bpl.TypeVariableSeq(), new Bpl.TypeSeq(typeInstantiation), Bpl.Type.Bool), args);
+ case BuiltinFunction.SeqBuild:
+ assert args.Length == 4;
+ assert typeInstantiation != null;
+ return FunctionCall(tok, "Seq#Build", predef.SeqType(tok, typeInstantiation), args);
+ case BuiltinFunction.SeqAppend:
+ assert args.Length == 2;
+ assert typeInstantiation != null;
+ return FunctionCall(tok, "Seq#Append", predef.SeqType(tok, typeInstantiation), args);
+ case BuiltinFunction.SeqIndex:
+ assert args.Length == 2;
+ assert typeInstantiation != null;
+ return FunctionCall(tok, "Seq#Index", typeInstantiation, args);
+ case BuiltinFunction.SeqContains:
+ assert args.Length == 2;
+ assert typeInstantiation == null;
+ return FunctionCall(tok, "Seq#Contains", Bpl.Type.Bool, args);
+ case BuiltinFunction.SeqDrop:
+ assert args.Length == 2;
+ assert typeInstantiation != null;
+ return FunctionCall(tok, "Seq#Drop", predef.SeqType(tok, typeInstantiation), args);
+ case BuiltinFunction.SeqTake:
+ assert args.Length == 2;
+ assert typeInstantiation != null;
+ return FunctionCall(tok, "Seq#Take", predef.SeqType(tok, typeInstantiation), args);
+ case BuiltinFunction.SeqEqual:
+ assert args.Length == 2;
+ assert typeInstantiation == null;
+ return FunctionCall(tok, "Seq#Equal", Bpl.Type.Bool, args);
+ case BuiltinFunction.SeqSameUntil:
+ assert args.Length == 3;
+ assert typeInstantiation == null;
+ return FunctionCall(tok, "Seq#SameUntil", Bpl.Type.Bool, args);
+
+ case BuiltinFunction.Box:
+ assert args.Length == 1;
+ assert typeInstantiation == null;
+ return FunctionCall(tok, "$Box", predef.RefType, args);
+ case BuiltinFunction.Unbox:
+ assert false; // Unbox should be handled by a call to FunctionSpecial
+
+ case BuiltinFunction.IsGoodHeap:
+ assert args.Length == 1;
+ assert typeInstantiation == null;
+ return FunctionCall(tok, "$IsGoodHeap", Bpl.Type.Bool, args);
+ case BuiltinFunction.HeapSucc:
+ assert args.Length == 2;
+ assert typeInstantiation == null;
+ return FunctionCall(tok, "$HeapSucc", Bpl.Type.Bool, args);
+
+ case BuiltinFunction.DynamicType:
+ assert args.Length == 1;
+ return FunctionCall(tok, "dtype", predef.ClassNameType, args);
+ case BuiltinFunction.TypeParams:
+ assert args.Length == 2;
+ return FunctionCall(tok, "TypeParams", predef.ClassNameType, args);
+ case BuiltinFunction.TypeTuple:
+ assert args.Length == 2;
+ return FunctionCall(tok, "TypeTuple", predef.ClassNameType, args);
+
+ default:
+ assert false; // unexpected built-in function
+ }
+ }
+
+ Bpl.NAryExpr! FunctionSpecial(Token! tok, BuiltinFunction f, Bpl.Type! resultType, params Bpl.Expr[]! args)
+ {
+ switch (f) {
+ case BuiltinFunction.Unbox:
+ assert args.Length == 1;
+ return Bpl.Expr.CoerceType(tok, FunctionCall(tok, "$Unbox", resultType, args), resultType);
+ default:
+ assert false; // unexpected enum value
+ }
+ }
+
+ Bpl.NAryExpr! FunctionCall(Token! tok, string! function, Bpl.Type! returnType, params Bpl.Expr[]! args)
+ {
+ return new Bpl.NAryExpr(tok, new Bpl.FunctionCall(new Bpl.IdentifierExpr(tok, function, returnType)), new Bpl.ExprSeq(args));
+ }
+
+ public IEnumerable<Expression!>! SplitExpr(Expression! expr, bool expandFunctions)
+ requires expr.Type is BoolType;
+ {
+ if (expr is BinaryExpr) {
+ BinaryExpr bin = (BinaryExpr)expr;
+ if (bin.ResolvedOp == BinaryExpr.ResolvedOpcode.And) {
+ foreach (Expression e in SplitExpr(bin.E0, expandFunctions)) {
+ yield return e;
+ }
+ assert bin != null; // the necessity of this cast is a compiler bug, but perhaps an irrepairable one
+ foreach (Expression e in SplitExpr(bin.E1, expandFunctions)) {
+ yield return e;
+ }
+ yield break;
+
+ } else if (bin.ResolvedOp == BinaryExpr.ResolvedOpcode.Imp) {
+ foreach (Expression e in SplitExpr(bin.E1, expandFunctions)) {
+ assert bin != null;
+ BinaryExpr redistributedExpr = new BinaryExpr(e.tok, bin.Op, bin.E0, e);
+ redistributedExpr.ResolvedOp = bin.ResolvedOp; redistributedExpr.Type = bin.Type; // resolve on the fly
+ yield return redistributedExpr;
+ }
+ yield break;
+ }
+
+ } else if (expr is ITEExpr) {
+ ITEExpr ite = (ITEExpr)expr;
+ foreach (Expression e in SplitExpr(ite.Thn, expandFunctions)) {
+ assert ite != null; // the necessity of this cast is a compiler bug, but perhaps an irrepairable one
+ BinaryExpr bin = new BinaryExpr(e.tok, BinaryExpr.Opcode.Imp, ite.Test, e);
+ bin.ResolvedOp = BinaryExpr.ResolvedOpcode.Imp; bin.Type = ite.Type; // resolve on the fly
+ yield return bin;
+ }
+ assert ite != null; // the necessity of this cast is a compiler bug, but perhaps an irrepairable one
+ Expression negatedGuard = new UnaryExpr(ite.Test.tok, UnaryExpr.Opcode.Not, ite.Test);
+ negatedGuard.Type = ite.Test.Type; // resolve on the fly
+ foreach (Expression e in SplitExpr(ite.Els, expandFunctions)) {
+ assert ite != null; // the necessity of this cast is a compiler bug, but perhaps an irrepairable one
+ assert negatedGuard != null; // the necessity of this cast is a compiler bug, but perhaps an irrepairable one
+ BinaryExpr bin = new BinaryExpr(e.tok, BinaryExpr.Opcode.Imp, negatedGuard, e);
+ bin.ResolvedOp = BinaryExpr.ResolvedOpcode.Imp; bin.Type = ite.Type; // resolve on the fly
+ yield return bin;
+ }
+ yield break;
+
+ } else if (expr is OldExpr) {
+ foreach (Expression se in SplitExpr(((OldExpr)expr).E, expandFunctions)) {
+ OldExpr oe = new OldExpr(expr.tok, se);
+ oe.Type = se.Type;
+ yield return oe;
+ }
+ yield break;
+
+ } else if (expandFunctions && expr is FunctionCallExpr) {
+ FunctionCallExpr fexp = (FunctionCallExpr)expr;
+ assert fexp.Function != null; // filled in during resolution
+ if (fexp.Function.Body != null) {
+ // inline this body
+ Dictionary<IVariable,Expression!> substMap = new Dictionary<IVariable,Expression!>();
+ assert fexp.Args.Count == fexp.Function.Formals.Count;
+ for (int i = 0; i < fexp.Function.Formals.Count; i++) {
+ substMap.Add(fexp.Function.Formals[i], fexp.Args[i]);
+ }
+ Expression body = Substitute(fexp.Function.Body, fexp.Receiver, substMap);
+ foreach (Expression se in SplitExpr(body, false)) {
+ assert fexp != null && fexp.Function != null; // already checked above, but the compiler seems to have forgotten that
+ if (fexp.Function.Use) {
+ BinaryExpr imp = new BinaryExpr(expr.tok, BinaryExpr.Opcode.Imp, new UseExpr(fexp), se);
+ imp.ResolvedOp = BinaryExpr.ResolvedOpcode.Imp;
+ imp.Type = Type.Bool;
+ yield return imp;
+ } else {
+ yield return se;
+ }
+ }
+ assert fexp != null && fexp.Function != null; // already checked above, but the compiler seems to have forgotten that
+ if (fexp.Function.Use) {
+ UnaryExpr ue = new UnaryExpr(expr.tok, UnaryExpr.Opcode.Not, new UseExpr(fexp));
+ ue.Type = Type.Bool;
+ BinaryExpr imp = new BinaryExpr(expr.tok, BinaryExpr.Opcode.Imp, ue, expr);
+ imp.ResolvedOp = BinaryExpr.ResolvedOpcode.Imp;
+ imp.Type = Type.Bool;
+ yield return imp;
+ }
+ yield break;
+ }
+ }
+
+ yield return expr;
+ }
+
+ static Expression! Substitute(Expression! expr, Expression! receiverReplacement, Dictionary<IVariable,Expression!>! substMap) {
+ Expression newExpr = null; // set to non-null value only if substitution has any effect; if non-null, newExpr will be resolved at end
+
+ if (expr is LiteralExpr) {
+ // nothing to substitute
+ } else if (expr is ThisExpr) {
+ return receiverReplacement;
+ } else if (expr is IdentifierExpr) {
+ IdentifierExpr e = (IdentifierExpr)expr;
+ Expression substExpr;
+ if (substMap.TryGetValue(e.Var, out substExpr)) {
+ return (!)substExpr;
+ }
+ } else if (expr is DisplayExpression) {
+ DisplayExpression e = (DisplayExpression)expr;
+ List<Expression!> newElements = SubstituteExprList(e.Elements, receiverReplacement, substMap);
+ DisplayExpression newDisplayExpr;
+ if (newElements != e.Elements) {
+ if (expr is SetDisplayExpr) {
+ newExpr = new SetDisplayExpr(expr.tok, newElements);
+ } else {
+ newExpr = new SeqDisplayExpr(expr.tok, newElements);
+ }
+ }
+
+ } else if (expr is FieldSelectExpr) {
+ FieldSelectExpr fse = (FieldSelectExpr)expr;
+ Expression substE = Substitute(fse.Obj, receiverReplacement, substMap);
+ if (substE != fse.Obj) {
+ FieldSelectExpr fseNew = new FieldSelectExpr(fse.tok, substE, fse.FieldName);
+ fseNew.Field = fse.Field; // resolve on the fly (and fseExpr.Type is set at end of method)
+ newExpr = fseNew;
+ }
+
+ } else if (expr is SeqSelectExpr) {
+ SeqSelectExpr sse = (SeqSelectExpr)expr;
+ Expression seq = Substitute(sse.Seq, receiverReplacement, substMap);
+ Expression e0 = sse.E0 == null ? null : Substitute(sse.E0, receiverReplacement, substMap);
+ Expression e1 = sse.E1 == null ? null : Substitute(sse.E1, receiverReplacement, substMap);
+ if (seq != sse.Seq || e0 != sse.E0 || e1 != sse.E1) {
+ newExpr = new SeqSelectExpr(sse.tok, sse.SelectOne, seq, e0, e1);
+ }
+
+ } else if (expr is FunctionCallExpr) {
+ FunctionCallExpr e = (FunctionCallExpr)expr;
+ Expression receiver = Substitute(e.Receiver, receiverReplacement, substMap);
+ List<Expression!> newArgs = SubstituteExprList(e.Args, receiverReplacement, substMap);
+ if (receiver != e.Receiver || newArgs != e.Args) {
+ FunctionCallExpr newFce = new FunctionCallExpr(expr.tok, e.Name, receiver, newArgs);
+ newFce.Function = e.Function; // resolve on the fly (and set newFce.Type below, at end)
+ newExpr = newFce;
+ }
+
+ } else if (expr is OldExpr) {
+ OldExpr e = (OldExpr)expr;
+ Expression se = Substitute(e.E, receiverReplacement, substMap);
+ if (se != e.E) {
+ newExpr = new OldExpr(expr.tok, se);
+ }
+ } else if (expr is FreshExpr) {
+ FreshExpr e = (FreshExpr)expr;
+ Expression se = Substitute(e.E, receiverReplacement, substMap);
+ if (se != e.E) {
+ newExpr = new FreshExpr(expr.tok, se);
+ }
+ } else if (expr is UnaryExpr) {
+ UnaryExpr e = (UnaryExpr)expr;
+ Expression se = Substitute(e.E, receiverReplacement, substMap);
+ if (se != e.E) {
+ newExpr = new UnaryExpr(expr.tok, e.Op, se);
+ }
+ } else if (expr is BinaryExpr) {
+ BinaryExpr e = (BinaryExpr)expr;
+ Expression e0 = Substitute(e.E0, receiverReplacement, substMap);
+ Expression e1 = Substitute(e.E1, receiverReplacement, substMap);
+ if (e0 != e.E0 || e1 != e.E1) {
+ BinaryExpr newBin = new BinaryExpr(expr.tok, e.Op, e0, e1);
+ newBin.ResolvedOp = e.ResolvedOp; // part of what needs to be done to resolve on the fly (newBin.Type is set below, at end)
+ newExpr = newBin;
+ }
+
+ } else if (expr is QuantifierExpr) {
+ QuantifierExpr e = (QuantifierExpr)expr;
+ Expression newBody = Substitute(e.Body, receiverReplacement, substMap);
+ Triggers newTrigs = SubstTriggers(e.Trigs, receiverReplacement, substMap);
+ Attributes newAttrs = SubstAttributes(e.Attributes, receiverReplacement, substMap);
+ if (newBody != e.Body || newTrigs != e.Trigs || newAttrs != e.Attributes) {
+ if (expr is ForallExpr) {
+ newExpr = new ForallExpr(expr.tok, e.BoundVars, newBody, newTrigs, newAttrs);
+ } else {
+ newExpr = new ExistsExpr(expr.tok, e.BoundVars, newBody, newTrigs, newAttrs);
+ }
+ }
+
+ } else if (expr is ITEExpr) {
+ ITEExpr e = (ITEExpr)expr;
+ Expression test = Substitute(e.Test, receiverReplacement, substMap);
+ Expression thn = Substitute(e.Thn, receiverReplacement, substMap);
+ Expression els = Substitute(e.Els, receiverReplacement, substMap);
+ if (test != e.Test || thn != e.Thn || els != e.Els) {
+ newExpr = new ITEExpr(expr.tok, test, thn, els);
+ }
+ }
+
+ if (newExpr == null) {
+ return expr;
+ } else {
+ newExpr.Type = expr.Type; // resolve on the fly (any additional resolution must be done above)
+ return newExpr;
+ }
+ }
+
+ static List<Expression!>! SubstituteExprList(List<Expression!>! elist,
+ Expression! receiverReplacement, Dictionary<IVariable,Expression!>! substMap) {
+ List<Expression!> newElist = null; // initialized lazily
+ for (int i = 0; i < elist.Count; i++)
+ invariant newElist == null || newElist.Count == i;
+ {
+ Expression substE = Substitute(elist[i], receiverReplacement, substMap);
+ if (substE != elist[i] && newElist == null) {
+ newElist = new List<Expression!>();
+ for (int j = 0; j < i; j++) {
+ newElist.Add(elist[j]);
+ }
+ }
+ if (newElist != null) {
+ newElist.Add(substE);
+ }
+ }
+ if (newElist == null) {
+ return elist;
+ } else {
+ return newElist;
+ }
+ }
+
+ static Triggers SubstTriggers(Triggers trigs, Expression! receiverReplacement, Dictionary<IVariable,Expression!>! substMap) {
+ if (trigs != null) {
+ List<Expression!> terms = SubstituteExprList(trigs.Terms, receiverReplacement, substMap);
+ Triggers prev = SubstTriggers(trigs.Prev, receiverReplacement, substMap);
+ if (terms != trigs.Terms || prev != trigs.Prev) {
+ return new Triggers(terms, prev);
+ }
+ }
+ return trigs;
+ }
+
+ static Attributes SubstAttributes(Attributes attrs, Expression! receiverReplacement, Dictionary<IVariable,Expression!>! substMap) {
+ if (attrs != null) {
+ List<Attributes.Argument!> newArgs = new List<Attributes.Argument!>(); // allocate it eagerly, what the heck, it doesn't seem worth the extra complexity in the code to do it lazily for the infrequently occurring attributes
+ bool anyArgSubst = false;
+ foreach (Attributes.Argument arg in attrs.Args) {
+ Attributes.Argument newArg = arg;
+ if (arg.E != null) {
+ Expression newE = Substitute(arg.E, receiverReplacement, substMap);
+ if (newE != arg.E) {
+ newArg = new Attributes.Argument(newE);
+ anyArgSubst = true;
+ }
+ }
+ newArgs.Add(newArg);
+ }
+ if (!anyArgSubst) {
+ newArgs = attrs.Args;
+ }
+
+ Attributes prev = SubstAttributes(attrs.Prev, receiverReplacement, substMap);
+ if (newArgs != attrs.Args || prev != attrs.Prev) {
+ return new Attributes(attrs.Name, newArgs, prev);
+ }
+ }
+ return attrs;
+ }
+
+ }
+}
diff --git a/Source/Dafny/parser.frame b/Source/Dafny/parser.frame
new file mode 100644
index 00000000..de0ba1fb
--- /dev/null
+++ b/Source/Dafny/parser.frame
@@ -0,0 +1,103 @@
+
+using Microsoft.Contracts;
+
+namespace Microsoft.-->namespace {
+
+public class Parser {
+-->constants
+ const bool T = true;
+ const bool x = false;
+ const int minErrDist = 2;
+
+ static Token/*!*/ token; // last recognized token
+ static Token/*!*/ t; // lookahead token
+ static int errDist = minErrDist;
+
+ -->declarations
+
+ static void Error(int n) {
+ if (errDist >= minErrDist) Errors.SynErr(n, t.filename, t.line, t.col);
+ errDist = 0;
+ }
+
+ public static void SemErr(string! msg) {
+ if (errDist >= minErrDist) Errors.SemErr(token.filename, token.line, token.col, msg);
+ errDist = 0;
+ }
+
+ public static void SemErr(Token! tok, string! msg) {
+ if (errDist >= minErrDist) Errors.SemErr(tok.filename, tok.line, tok.col, msg);
+ errDist = 0;
+ }
+
+ static void Get() {
+ for (;;) {
+ token = t;
+ t = Scanner.Scan();
+ if (t.kind<=maxT) {errDist++; return;}
+-->pragmas
+ t = token;
+ }
+ }
+
+ static void Expect(int n) {
+ if (t.kind==n) Get(); else Error(n);
+ }
+
+ static bool StartOf(int s) {
+ return set[s, t.kind];
+ }
+
+ static void ExpectWeak(int n, int follow) {
+ if (t.kind == n) Get();
+ else {
+ Error(n);
+ while (!StartOf(follow)) Get();
+ }
+ }
+
+ static bool WeakSeparator(int n, int syFol, int repFol) {
+ bool[] s = new bool[maxT+1];
+ if (t.kind == n) {Get(); return true;}
+ else if (StartOf(repFol)) return false;
+ else {
+ for (int i=0; i <= maxT; i++) {
+ s[i] = set[syFol, i] || set[repFol, i] || set[0, i];
+ }
+ Error(n);
+ while (!s[t.kind]) Get();
+ return StartOf(syFol);
+ }
+ }
+
+-->productions
+
+ public static void Parse() {
+ Errors.SynErr = new ErrorProc(SynErr);
+ t = new Token();
+ Get();
+-->parseRoot
+ }
+
+ [Microsoft.Contracts.Verify(false)]
+ static void SynErr(int n, string filename, int line, int col) {
+ Errors.count++;
+ System.Console.Write("{0}({1},{2}): syntax error: ", filename, line, col);
+ string s;
+ switch (n) {
+-->errors
+ default: s = "error " + n; break;
+ }
+ System.Console.WriteLine(s);
+ }
+
+ static bool[,]! set = {
+-->initialization
+ };
+
+ [Microsoft.Contracts.Verify(false)]
+ static Parser() {}
+} // end Parser
+
+} // end namespace
+$$$ \ No newline at end of file
diff --git a/Source/Dafny/scanner.frame b/Source/Dafny/scanner.frame
new file mode 100644
index 00000000..a526c7f2
--- /dev/null
+++ b/Source/Dafny/scanner.frame
@@ -0,0 +1,170 @@
+using System.IO;
+using System.Collections;
+using System.Collections.Generic;
+using System.Text;
+using Microsoft.Contracts;
+using Bpl = Microsoft.Boogie;
+using BoogiePL;
+
+
+namespace Microsoft.Dafny {
+
+ [Immutable]
+ public class Token : Bpl.Token {
+ public Token();
+ public Token(int linenum, int colnum) {
+ base(linenum, colnum);
+ }
+ public new static Token! NoToken = new Token();
+ }
+
+}
+
+namespace Microsoft.-->namespace {
+
+
+public class Scanner {
+ const char EOF = '\0';
+ const char CR = '\r';
+ const char LF = '\n';
+
+ [Microsoft.Contracts.Verify(false)]
+-->declarations
+
+
+ static Token/*!*/ t; // current token
+ static char ch; // current input character
+ static int pos; // column number of current character
+ static int line; // line number of current character
+ static int lineStart; // start position of current line
+ static Queue! oldEols; // EOLs that appeared in a comment;
+ static BitArray/*!*/ ignore; // set of characters to be ignored by the scanner
+ static string Filename;
+
+ ///<summary>
+ ///Initializes the scanner. Note: first fill the Buffer.
+ ///</summary>
+ ///<param name="filename">File name used for error reporting</param>
+ public static void Init (string filename) {
+ Filename = filename;
+ pos = -1; line = 1; lineStart = 0;
+ oldEols = new Queue();
+ NextCh();
+-->initialization
+ }
+
+ private static void NextCh() {
+ if (oldEols.Count > 0) {
+ ch = (char) ((!)oldEols.Dequeue());
+ } else {
+ while (true) {
+ ch = (char)BoogiePL.Buffer.Read(); pos++;
+ if (ch == BoogiePL.Buffer.eof) {
+ ch = EOF;
+ } else if (ch == LF) {
+ line++;
+ lineStart = pos + 1;
+
+ } else if (ch == '#' && pos == lineStart) {
+ int prLine = line;
+ int prColumn = pos - lineStart; // which is 0
+
+ string hashLine = BoogiePL.Buffer.ReadToEOL(); pos += hashLine.Length;
+ line++;
+ lineStart = pos + 1;
+
+ hashLine = hashLine.TrimEnd(null);
+ if (hashLine.StartsWith("line ") || hashLine == "line") {
+ // parse #line pragma: #line num [filename]
+ string h = hashLine.Substring(4).TrimStart(null);
+ int x = h.IndexOf(' ');
+ if (x == -1) {
+ x = h.Length; // this will be convenient below when we look for a filename
+ }
+ try {
+ int li = int.Parse(h.Substring(0, x));
+
+ h = h.Substring(x).Trim();
+
+ // act on #line
+ line = li;
+ if (h.Length != 0) {
+ // a filename was specified
+ Filename = h;
+ }
+ continue; // successfully parsed and acted on the #line pragma
+
+ } catch (System.FormatException) {
+ // just fall down through to produce an error message
+ }
+ Errors.SemErr(Filename, prLine, prColumn, "Malformed (#line num [filename]) pragma: #" + hashLine);
+ continue;
+ }
+
+ Errors.SemErr(Filename, prLine, prColumn, "Unrecognized pragma: #" + hashLine);
+ continue;
+ }
+ return;
+ }
+ }
+ }
+
+-->comment
+
+ static void CheckLiteral() {
+ switch (t.val) {
+-->literals
+ }
+ }
+
+ public static Token/*!*/ Scan() {
+ while (ignore[ch]) { NextCh(); }
+-->scan1
+ t = new Token();
+ t.pos = pos; t.col = pos - lineStart + 1; t.line = line; t.filename = Filename;
+ int state = (/*^ (!) ^*/ start)[ch];
+ StringBuilder buf = new StringBuilder(16);
+ buf.Append(ch); NextCh();
+
+ switch (state) {
+ case 0: {t.kind = noSym; goto done;} // NextCh already done
+-->scan2
+ }
+ done:
+ t.val = buf.ToString();
+ return t;
+ }
+
+} // end Scanner
+
+
+public delegate void ErrorProc(int n, string filename, int line, int col);
+
+public class Errors {
+ public static int count = 0; // number of errors detected
+ public static ErrorProc/*!*/ SynErr; // syntactic errors
+
+ public static void SemErr(string filename, int line, int col, string! msg) { // semantic errors
+ System.ConsoleColor color = System.Console.ForegroundColor;
+ System.Console.ForegroundColor = System.ConsoleColor.Red;
+ System.Console.WriteLine("{0}({1},{2}): Error: {3}", filename, line, col, msg);
+ System.Console.ForegroundColor = color;
+ count++;
+ }
+
+ public static void SemErr(Bpl.IToken! tok, string! msg) { // semantic errors
+ SemErr(tok.filename, tok.line, tok.col, msg);
+ }
+
+ public static void Exception (string s) {
+ System.ConsoleColor color = System.Console.ForegroundColor;
+ System.Console.ForegroundColor = System.ConsoleColor.Red;
+ System.Console.WriteLine(s);
+ System.Console.ForegroundColor = color;
+ System.Environment.Exit(0);
+ }
+
+} // Errors
+
+} // end namespace
+$$$
diff --git a/Source/DafnyDriver/DafnyDriver.ssc b/Source/DafnyDriver/DafnyDriver.ssc
new file mode 100644
index 00000000..06280e74
--- /dev/null
+++ b/Source/DafnyDriver/DafnyDriver.ssc
@@ -0,0 +1,681 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------------
+// OnlyDafny OnlyDafny.ssc
+// - main program for taking a Dafny program and verifying it
+//---------------------------------------------------------------------------------------------
+
+namespace Microsoft.Boogie
+{
+ using System;
+ using System.IO;
+ using System.Collections;
+ using System.Collections.Generic;
+ using PureCollections;
+ using Microsoft.Boogie;
+ using Microsoft.Boogie.AbstractInterpretation;
+ using System.Diagnostics;
+ using VC;
+ using Cci = System.Compiler;
+ using AI = Microsoft.AbstractInterpretationFramework;
+
+/*
+ The following assemblies are referenced because they are needed at runtime, not at compile time:
+ BaseTypes
+ Provers.Z3
+ System.Compiler.Framework
+*/
+
+ public class OnlyDafny
+ {
+ // ------------------------------------------------------------------------
+ // Main
+
+ public static void Main (string[]! args)
+ {
+ assert forall{int i in (0:args.Length); args[i] != null};
+ CommandLineOptions.Clo.RunningBoogieFromCommandLine = true;
+ if (CommandLineOptions.Clo.Parse(args) != 1)
+ {
+ goto END;
+ }
+ if (CommandLineOptions.Clo.Files.Count == 0)
+ {
+ ErrorWriteLine("*** Error: No input files were specified.");
+ goto END;
+ }
+ if (CommandLineOptions.Clo.XmlSink != null) {
+ string errMsg = CommandLineOptions.Clo.XmlSink.Open();
+ if (errMsg != null) {
+ ErrorWriteLine("*** Error: " + errMsg);
+ goto END;
+ }
+ }
+ if (!CommandLineOptions.Clo.DontShowLogo)
+ {
+ Console.WriteLine(CommandLineOptions.Clo.Version);
+ }
+ if (CommandLineOptions.Clo.ShowEnv == CommandLineOptions.ShowEnvironment.Always)
+ {
+ Console.WriteLine("---Command arguments");
+ foreach (string! arg in args)
+ {
+ Console.WriteLine(arg);
+ }
+ Console.WriteLine("--------------------");
+ }
+
+ SelectPlatform(CommandLineOptions.Clo);
+
+ // Make sure the Spec# runtime is initialized.
+ // This happens when the static constructor for the Runtime type is executed.
+ // Otherwise, if a reference happens to get chased to it, it is loaded twice
+ // and then the types in it do not get unique representations.
+ if (System.Type.GetType("Mono.Runtime") == null) { // MONO
+ Cci.AssemblyNode a = Microsoft.SpecSharp.Runtime.RuntimeAssembly;
+ assert a != null;
+ }
+
+ foreach (string! file in CommandLineOptions.Clo.Files)
+ {
+ string extension = Path.GetExtension(file);
+ if (extension != null) { extension = extension.ToLower(); }
+ if (extension != ".dfy")
+ {
+ ErrorWriteLine("*** Error: '{0}': Filename extension '{1}' is not supported. Input files must be Dafny programs (.dfy).", file,
+ extension == null ? "" : extension);
+ goto END;
+ }
+ }
+ CommandLineOptions.Clo.RunningBoogieOnSsc = false;
+ ProcessFiles(CommandLineOptions.Clo.Files);
+
+ END:
+ if (CommandLineOptions.Clo.XmlSink != null) {
+ CommandLineOptions.Clo.XmlSink.Close();
+ }
+ if (CommandLineOptions.Clo.Wait)
+ {
+ Console.WriteLine("Press Enter to exit.");
+ Console.ReadLine();
+ }
+ }
+
+ public static void ErrorWriteLine(string! s) {
+ if (!s.Contains("Error: ") && !s.Contains("Error BP")) {
+ Console.WriteLine(s);
+ return;
+ }
+
+ // split the string up into its first line and the remaining lines
+ string remaining = null;
+ int i = s.IndexOf('\r');
+ if (0 <= i) {
+ remaining = s.Substring(i+1);
+ if (remaining.StartsWith("\n")) {
+ remaining = remaining.Substring(1);
+ }
+ s = s.Substring(0, i);
+ }
+
+ ConsoleColor col = Console.ForegroundColor;
+ Console.ForegroundColor = ConsoleColor.Red;
+ Console.WriteLine(s);
+ Console.ForegroundColor = col;
+
+ if (remaining != null) {
+ Console.WriteLine(remaining);
+ }
+ }
+
+ public static void ErrorWriteLine(string! format, params object[] args) {
+ string s = string.Format(format, args);
+ ErrorWriteLine(s);
+ }
+
+ public static void AdvisoryWriteLine(string! format, params object[] args) {
+ ConsoleColor col = Console.ForegroundColor;
+ Console.ForegroundColor = ConsoleColor.Yellow;
+ Console.WriteLine(format, args);
+ Console.ForegroundColor = col;
+ }
+
+ public static void SelectPlatform(CommandLineOptions! options)
+ {
+ if (options.TargetPlatformLocation != null) {
+ // Make sure static constructor runs before we start setting locations, etc.
+ System.Compiler.SystemTypes.Clear();
+
+ switch (options.TargetPlatform){
+ case CommandLineOptions.PlatformType.v1: Microsoft.SpecSharp.TargetPlatform.SetToV1(options.TargetPlatformLocation); break;
+ case CommandLineOptions.PlatformType.v11: Microsoft.SpecSharp.TargetPlatform.SetToV1_1(options.TargetPlatformLocation); break;
+ case CommandLineOptions.PlatformType.v2: Microsoft.SpecSharp.TargetPlatform.SetToV2(options.TargetPlatformLocation); break;
+ case CommandLineOptions.PlatformType.cli1: Microsoft.SpecSharp.TargetPlatform.SetToPostV1_1(options.TargetPlatformLocation); break;
+ }
+
+ if (options.StandardLibraryLocation != null && options.StandardLibraryLocation.Length > 0){
+ System.Compiler.SystemAssemblyLocation.Location = options.StandardLibraryLocation;
+ }
+ System.Compiler.SystemCompilerRuntimeAssemblyLocation.Location = options.TargetPlatformLocation + @"\System.Compiler.Runtime.dll";
+
+ System.Compiler.SystemTypes.Initialize(true, true);
+ }
+ }
+
+ static string! GetErrorLine(Cci.ErrorNode! node)
+ requires node.SourceContext.Document != null ==> node.SourceContext.Document.Name != null;
+ {
+ string message = node.GetMessage(System.Threading.Thread.CurrentThread.CurrentUICulture);
+ string kind;
+ if (message.Contains("(trace position)")) {
+ kind = "Related information";
+ } else {
+ kind = "Error";
+ }
+ if (node.SourceContext.Document != null) {
+ return string.Format("{0}({1},{2}): {3}: {4}", Path.GetFileName((!)node.SourceContext.Document.Name), node.SourceContext.StartLine, node.SourceContext.StartColumn, kind, message);
+ } else {
+ return string.Format("{0}: {1}", kind, message);
+ }
+ }
+
+ enum FileType { Unknown, Cil, Bpl, Dafny };
+
+ class ErrorReporter
+ {
+ public Cci.ErrorNodeList! errors = new Cci.ErrorNodeList();
+ public int errorsReported;
+
+ public void ReportErrors()
+ {
+ //sort the portion of the array that will be reported to make output more deterministic
+ errors.Sort(errorsReported,errors.Count-errorsReported);
+ for(;errorsReported < errors.Count; errorsReported++) {
+ Cci.ErrorNode error = errors[errorsReported];
+ if (error != null)
+ ErrorWriteLine(GetErrorLine(error));
+ }
+ }
+ }
+
+ static void ProcessFiles (List<string!>! fileNames)
+ {
+ using (XmlFileScope xf = new XmlFileScope(CommandLineOptions.Clo.XmlSink, fileNames[fileNames.Count-1])) {
+ Dafny.Program dafnyProgram;
+ string err = Dafny.Main.ParseCheck(fileNames, "synthetic program", out dafnyProgram);
+ if (err != null) {
+ ErrorWriteLine(err);
+ } else if (dafnyProgram != null) {
+ Dafny.Translator translator = new Dafny.Translator();
+ Program boogieProgram = translator.Translate(dafnyProgram);
+ if (CommandLineOptions.Clo.PrintFile != null)
+ {
+ PrintBplFile(CommandLineOptions.Clo.PrintFile, boogieProgram, false);
+ }
+
+ string! bplFilename;
+ if (CommandLineOptions.Clo.PrintFile != null) {
+ bplFilename = CommandLineOptions.Clo.PrintFile;
+ } else {
+ string baseName = (!)Path.GetFileName(fileNames[fileNames.Count-1]);
+ baseName = (!)Path.ChangeExtension(baseName, "bpl");
+ bplFilename = Path.Combine(Path.GetTempPath(), baseName);
+ }
+
+ int errorCount, verified, inconclusives, timeOuts, outOfMemories;
+ PipelineOutcome oc = BoogiePipelineWithRerun(boogieProgram, bplFilename, null/*new ErrorReporter()*/, out errorCount, out verified, out inconclusives, out timeOuts, out outOfMemories);
+ switch (oc) {
+ case PipelineOutcome.Done:
+ case PipelineOutcome.VerificationCompleted:
+ WriteTrailer(verified, errorCount, inconclusives, timeOuts, outOfMemories);
+ break;
+ default:
+ // error has already been reported to user
+ break;
+ }
+ }
+ }
+ }
+
+
+ static void PrintBplFile (string! filename, Program! program, bool allowPrintDesugaring)
+ {
+ bool oldPrintDesugaring = CommandLineOptions.Clo.PrintDesugarings;
+ if (!allowPrintDesugaring) {
+ CommandLineOptions.Clo.PrintDesugarings = false;
+ }
+ using (TokenTextWriter writer = filename == "-" ?
+ new TokenTextWriter("<console>", Console.Out) :
+ new TokenTextWriter(filename))
+ {
+ writer.WriteLine("// " + CommandLineOptions.Clo.Version);
+ writer.WriteLine("// " + CommandLineOptions.Clo.Environment);
+ writer.WriteLine();
+ program.Emit(writer);
+ }
+ CommandLineOptions.Clo.PrintDesugarings = oldPrintDesugaring;
+ }
+
+
+ static bool ProgramHasDebugInfo (Program! program)
+ {
+ // We inspect the last declaration because the first comes from the prelude and therefore always has source context.
+ return program.TopLevelDeclarations.Count > 0 &&
+ ((!)program.TopLevelDeclarations[program.TopLevelDeclarations.Count - 1]).tok.IsValid;
+ }
+
+
+ /// <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; }
+ Console.WriteLine(s);
+ }
+
+ static void WriteTrailer(int verified, int errors, int inconclusives, int timeOuts, int outOfMemories)
+ requires 0 <= errors && 0 <= inconclusives && 0 <= timeOuts && 0 <= outOfMemories;
+ {
+ Console.WriteLine();
+ Console.Write("{0} finished with {1} verified, {2} error{3}", CommandLineOptions.Clo.ToolName, verified, errors, errors == 1 ? "" : "s");
+ if (inconclusives != 0) {
+ Console.Write(", {0} inconclusive{1}", inconclusives, inconclusives == 1 ? "" : "s");
+ }
+ if (timeOuts != 0) {
+ Console.Write(", {0} time out{1}", timeOuts, timeOuts == 1 ? "" : "s");
+ }
+ if (outOfMemories != 0) {
+ Console.Write(", {0} out of memory", outOfMemories);
+ }
+ Console.WriteLine();
+ Console.Out.Flush();
+ }
+
+
+
+ static void ReportBplError(Absy! node, string! message, bool error)
+ {
+ IToken tok = node.tok;
+ string s;
+ if (tok == null) {
+ s = message;
+ } else {
+ s = string.Format("{0}({1},{2}): {3}", tok.filename, tok.line, tok.col, message);
+ }
+ if (error) {
+ ErrorWriteLine(s);
+ } else {
+ Console.WriteLine(s);
+ }
+ }
+
+ /// <summary>
+ /// 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)
+ {
+ BoogiePL.Errors.count = 0;
+ Program program = null;
+ bool okay = true;
+ foreach (string bplFileName in fileNames) {
+ if (!suppressTraceOutput) {
+ if (CommandLineOptions.Clo.XmlSink != null) {
+ CommandLineOptions.Clo.XmlSink.WriteFileFragment(bplFileName);
+ }
+ if (CommandLineOptions.Clo.Trace) {
+ Console.WriteLine("Parsing " + bplFileName);
+ }
+ }
+
+ Program programSnippet;
+ int errorCount;
+ try {
+ errorCount = BoogiePL.Parser.Parse(bplFileName, out programSnippet);
+ if (programSnippet == null || errorCount != 0) {
+ Console.WriteLine("{0} parse errors detected in {1}", BoogiePL.Errors.count, bplFileName);
+ okay = false;
+ continue;
+ }
+ } catch (IOException e) {
+ ErrorWriteLine("Error opening file \"{0}\": {1}", bplFileName, e.Message);
+ okay = false;
+ continue;
+ }
+ if (program == null) {
+ program = programSnippet;
+ } else if (programSnippet != null) {
+ program.TopLevelDeclarations.AddRange(programSnippet.TopLevelDeclarations);
+ }
+ }
+ if (!okay) {
+ return null;
+ } else if (program == null) {
+ return new Program();
+ } else {
+ return program;
+ }
+ }
+
+ /// <summary>
+ /// Resolve, type check, infer invariants for, and verify the given Boogie program.
+ /// The intention is that this Boogie program has been produced by translation from something
+ /// else. Hence, any resolution errors and type checking errors are due to errors in
+ /// the translation.
+ /// The method prints errors for resolution and type checking errors, but still returns
+ /// their error code.
+ /// </summary>
+ static PipelineOutcome BoogiePipelineWithRerun (Program! program, string! bplFileName,
+ ErrorReporter errorReporter,
+ out int errorCount, out int verified, out int inconclusives, out int timeOuts, out int outOfMemories)
+ ensures 0 <= inconclusives && 0 <= timeOuts;
+ {
+ errorCount = verified = inconclusives = timeOuts = outOfMemories = 0;
+ PipelineOutcome oc = ResolveAndTypecheck(program, bplFileName);
+ switch (oc) {
+ case PipelineOutcome.Done:
+ return oc;
+
+ case PipelineOutcome.ResolutionError:
+ case PipelineOutcome.TypeCheckingError:
+ {
+ PrintBplFile(bplFileName, program, false);
+ Console.WriteLine();
+ Console.WriteLine("*** Encountered internal translation error - re-running Boogie to get better debug information");
+ Console.WriteLine();
+
+ List<string!>! fileNames = new List<string!> ();
+ fileNames.Add(bplFileName);
+ Program reparsedProgram = ParseBoogieProgram(fileNames, true);
+ if (reparsedProgram != null) {
+ ResolveAndTypecheck(reparsedProgram, bplFileName);
+ }
+ }
+ return oc;
+
+ case PipelineOutcome.ResolvedAndTypeChecked:
+ return InferAndVerify(program, errorReporter, out errorCount, out verified, out inconclusives, out timeOuts, out outOfMemories);
+
+ default:
+ assert false; // unexpected outcome
+ }
+ }
+
+
+ enum PipelineOutcome { Done, ResolutionError, TypeCheckingError, ResolvedAndTypeChecked, FatalError, VerificationCompleted }
+
+ /// <summary>
+ /// Resolves and type checks the given Boogie program. Any errors are reported to the
+ /// console. Returns:
+ /// - Done if no errors occurred, and command line specified no resolution or no type checking.
+ /// - ResolutionError if a resolution error occurred
+ /// - TypeCheckingError if a type checking error occurred
+ /// - ResolvedAndTypeChecked if both resolution and type checking succeeded
+ /// </summary>
+ static PipelineOutcome ResolveAndTypecheck (Program! program, string! bplFileName)
+ {
+ // ---------- Resolve ------------------------------------------------------------
+
+ if (CommandLineOptions.Clo.NoResolve) { return PipelineOutcome.Done; }
+
+ int errorCount = program.Resolve();
+ if (errorCount != 0) {
+ Console.WriteLine("{0} name resolution errors detected in {1}", errorCount, bplFileName);
+ return PipelineOutcome.ResolutionError;
+ }
+
+ // ---------- Type check ------------------------------------------------------------
+
+ if (CommandLineOptions.Clo.NoTypecheck) { return PipelineOutcome.Done; }
+
+ errorCount = program.Typecheck();
+ 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 PrintDesugaring option is engaged, print the file here, after resolution and type checking
+ PrintBplFile(CommandLineOptions.Clo.PrintFile, program, true);
+ }
+
+ return PipelineOutcome.ResolvedAndTypeChecked;
+ }
+
+ /// <summary>
+ /// Given a resolved and type checked Boogie program, infers invariants for the program
+ /// and then attempts to verify it. Returns:
+ /// - Done if command line specified no verification
+ /// - FatalError if a fatal error occurred, in which case an error has been printed to console
+ /// - VerificationCompleted if inference and verification completed, in which the out
+ /// parameters contain meaningful values
+ /// </summary>
+ static PipelineOutcome InferAndVerify (Program! program,
+ ErrorReporter errorReporter,
+ out int errorCount, out int verified, out int inconclusives, out int timeOuts, out int outOfMemories)
+ ensures 0 <= inconclusives && 0 <= timeOuts;
+ {
+ errorCount = verified = inconclusives = timeOuts = outOfMemories = 0;
+
+ // ---------- Infer invariants --------------------------------------------------------
+
+ // Abstract interpretation -> Always use (at least) intervals, if not specified otherwise (e.g. with the "/noinfer" switch)
+ Microsoft.Boogie.AbstractInterpretation.AbstractInterpretation.RunAbstractInterpretation(program);
+
+ if (CommandLineOptions.Clo.LoopUnrollCount != -1) {
+ program.UnrollLoops(CommandLineOptions.Clo.LoopUnrollCount);
+ }
+
+ if (CommandLineOptions.Clo.PrintInstrumented) {
+ program.Emit(new TokenTextWriter(Console.Out));
+ }
+
+ // ---------- Verify ------------------------------------------------------------
+
+ if (!CommandLineOptions.Clo.Verify) { return PipelineOutcome.Done; }
+
+ #region Verify each implementation
+
+#if ROB_DEBUG
+ string now = DateTime.Now.ToString().Replace(' ','-').Replace('/','-').Replace(':','-');
+ System.IO.StreamWriter w = new System.IO.StreamWriter(@"\temp\batch_"+now+".bpl");
+ program.Emit(new TokenTextWriter(w));
+ w.Close();
+#endif
+
+ 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);
+ }
+ }
+ catch (ProverException e)
+ {
+ ErrorWriteLine("Fatal Error: ProverException: {0}", e);
+ return PipelineOutcome.FatalError;
+ }
+
+ foreach ( Declaration! decl in program.TopLevelDeclarations )
+ {
+ Implementation impl = decl as Implementation;
+ if (impl != null && CommandLineOptions.Clo.UserWantsToCheckRoutine((!)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) {
+ start = DateTime.Now;
+ if (CommandLineOptions.Clo.Trace) {
+ Console.WriteLine();
+ Console.WriteLine("Verifying {0} ...", impl.Name);
+ }
+ if (CommandLineOptions.Clo.XmlSink != null) {
+ CommandLineOptions.Clo.XmlSink.WriteStartMethod(impl.Name, start);
+ }
+ }
+
+ ConditionGeneration.Outcome outcome;
+ try
+ {
+ outcome = vcgen.VerifyImplementation(impl, program, out errors);
+ }
+ catch (VCGenException e)
+ {
+ ReportBplError(impl, String.Format("Error BP5010: {0} Encountered in implementation {1}.", e.Message, impl.Name), true);
+ errors = null;
+ outcome = VCGen.Outcome.Inconclusive;
+ }
+ 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;
+ }
+
+ string! timeIndication = "";
+ DateTime end = DateTime.Now;
+ TimeSpan elapsed = end - start;
+ if (CommandLineOptions.Clo.Trace || CommandLineOptions.Clo.XmlSink != null) {
+ if (CommandLineOptions.Clo.Trace) {
+ timeIndication = string.Format(" [{0} s] ", elapsed.TotalSeconds);
+ }
+ }
+
+
+ switch (outcome) {
+ default:
+ assert false; // unexpected outcome
+ case VCGen.Outcome.Correct:
+ Inform(String.Format("{0}verified", timeIndication));
+ verified++;
+ break;
+ case VCGen.Outcome.TimedOut:
+ timeOuts++;
+ Inform(String.Format("{0}timed out", timeIndication));
+ break;
+ case VCGen.Outcome.OutOfMemory:
+ outOfMemories++;
+ Inform(String.Format("{0}out of memory", timeIndication));
+ break;
+ case VCGen.Outcome.Inconclusive:
+ inconclusives++;
+ Inform(String.Format("{0}inconclusive", timeIndication));
+ break;
+ case VCGen.Outcome.Errors:
+ assert errors != null; // guaranteed by postcondition of VerifyImplementation
+ if (errorReporter != null)
+ {
+// assert translatedProgram != null;
+// ErrorReporting h = new ErrorReporting();
+// h.errorReportingWithTrace(translatedProgram, errors, impl);
+
+ errorReporter.ReportErrors();
+ }
+ else
+ {
+ // BP1xxx: Parsing errors
+ // BP2xxx: Name resolution errors
+ // BP3xxx: Typechecking errors
+ // BP4xxx: Abstract interpretation errors (Is there such a thing?)
+ // BP5xxx: Verification errors
+
+ errors.Sort(new CounterexampleComparer());
+ foreach (Counterexample error in errors)
+ {
+ if (error is CallCounterexample)
+ {
+ CallCounterexample! err = (CallCounterexample) error;
+ ReportBplError(err.FailingCall, "Error BP5002: A precondition for this call might not hold.", true);
+ ReportBplError(err.FailingRequires, "Related location: This is the precondition that might not hold.", false);
+ if (CommandLineOptions.Clo.XmlSink != null) {
+ CommandLineOptions.Clo.XmlSink.WriteError("precondition violation", err.FailingCall.tok, err.FailingRequires.tok, error.Trace);
+ }
+ }
+ else if (error is ReturnCounterexample)
+ {
+ ReturnCounterexample! err = (ReturnCounterexample) error;
+ ReportBplError(err.FailingReturn, "Error BP5003: A postcondition might not hold at this return statement.", true);
+ ReportBplError(err.FailingEnsures, "Related location: This is the postcondition that might not hold.", false);
+ if (CommandLineOptions.Clo.XmlSink != null) {
+ CommandLineOptions.Clo.XmlSink.WriteError("postcondition violation", err.FailingReturn.tok, err.FailingEnsures.tok, error.Trace);
+ }
+ }
+ else // error is AssertCounterexample
+ {
+ AssertCounterexample! err = (AssertCounterexample) error;
+ if (err.FailingAssert is LoopInitAssertCmd) {
+ ReportBplError(err.FailingAssert, "Error BP5004: This loop invariant might not hold on entry.", true);
+ if (CommandLineOptions.Clo.XmlSink != null) {
+ CommandLineOptions.Clo.XmlSink.WriteError("loop invariant entry violation", err.FailingAssert.tok, null, error.Trace);
+ }
+ }
+ else if (err.FailingAssert is LoopInvMaintainedAssertCmd) {
+ // this assertion is a loop invariant which is not maintained
+ ReportBplError(err.FailingAssert, "Error BP5005: This loop invariant might not be maintained by the loop.", true);
+ if (CommandLineOptions.Clo.XmlSink != null) {
+ CommandLineOptions.Clo.XmlSink.WriteError("loop invariant maintenance violation", err.FailingAssert.tok, null, error.Trace);
+ }
+ } else {
+ string msg = err.FailingAssert.ErrorData as string;
+ if (msg == null) {
+ msg = "Error BP5001: This assertion might not hold.";
+ }
+ ReportBplError(err.FailingAssert, msg, true);
+ if (CommandLineOptions.Clo.XmlSink != null) {
+ CommandLineOptions.Clo.XmlSink.WriteError("assertion violation", err.FailingAssert.tok, null, error.Trace);
+ }
+ }
+ }
+ if (CommandLineOptions.Clo.EnhancedErrorMessages == 1) {
+ foreach (string! info in error.relatedInformation) {
+ Console.WriteLine(" " + info);
+ }
+ }
+ if (CommandLineOptions.Clo.ErrorTrace > 0) {
+ Console.WriteLine("Execution trace:");
+ foreach (Block! b in error.Trace) {
+ if (b.tok == null) {
+ Console.WriteLine(" <intermediate block>");
+ } else {
+ // for ErrorTrace == 1 restrict the output;
+ // do not print tokens with -17:-4 as their location because they have been
+ // introduced in the translation and do not give any useful feedback to the user
+ if (!(CommandLineOptions.Clo.ErrorTrace == 1 && b.tok.line == -17 && b.tok.col == -4)) {
+ Console.WriteLine(" {0}({1},{2}): {3}", b.tok.filename, b.tok.line, b.tok.col, b.Label);
+ }
+ }
+ }
+ }
+ errorCount++;
+ }
+ }
+ Inform(String.Format("{0}error{1}", timeIndication, errors.Count == 1 ? "" : "s"));
+ break;
+ }
+ if (CommandLineOptions.Clo.XmlSink != null) {
+ CommandLineOptions.Clo.XmlSink.WriteEndMethod(outcome.ToString().ToLowerInvariant(), end, elapsed);
+ }
+ if (outcome == VCGen.Outcome.Errors || CommandLineOptions.Clo.Trace) {
+ Console.Out.Flush();
+ }
+ }
+ }
+ vcgen.Close();
+ ((!)CommandLineOptions.Clo.TheProverFactory).Close();
+
+ #endregion
+
+ return PipelineOutcome.VerificationCompleted;
+ }
+
+ }
+}
diff --git a/Source/DafnyDriver/DafnyDriver.sscproj b/Source/DafnyDriver/DafnyDriver.sscproj
new file mode 100644
index 00000000..9beb51a0
--- /dev/null
+++ b/Source/DafnyDriver/DafnyDriver.sscproj
@@ -0,0 +1,124 @@
+<?xml version="1.0" encoding="utf-8"?>
+<VisualStudioProject>
+ <XEN ProjectType="Local"
+ SchemaVersion="1.0"
+ Name="DafnyDriver"
+ ProjectGuid="1f1e6f68-e9df-4181-8cd3-e8c98637084d"
+ >
+ <Build>
+ <Settings ApplicationIcon=""
+ AssemblyName="Dafny"
+ OutputType="Exe"
+ RootNamespace="Dafny"
+ StartupObject=""
+ StandardLibraryLocation=""
+ TargetPlatform="v2"
+ TargetPlatformLocation=""
+ >
+ <Config Name="Debug"
+ AllowUnsafeBlocks="False"
+ BaseAddress="285212672"
+ CheckForOverflowUnderflow="False"
+ ConfigurationOverrideFile=""
+ DefineConstants="DEBUG;TRACE"
+ DocumentationFile=""
+ DebugSymbols="True"
+ FileAlignment="4096"
+ IncrementalBuild="True"
+ Optimize="False"
+ OutputPath="..\..\Binaries"
+ RegisterForComInterop="False"
+ RemoveIntegerChecks="false"
+ TreatWarningsAsErrors="False"
+ WarningLevel="4"
+ CheckContractAdmissibility="True"
+ CheckPurity="False"
+ />
+ <Config Name="Release"
+ AllowUnsafeBlocks="false"
+ BaseAddress="285212672"
+ CheckForOverflowUnderflow="false"
+ ConfigurationOverrideFile=""
+ DefineConstants="TRACE"
+ DocumentationFile=""
+ DebugSymbols="false"
+ FileAlignment="4096"
+ IncrementalBuild="false"
+ Optimize="true"
+ OutputPath="bin\release"
+ RegisterForComInterop="false"
+ RemoveIntegerChecks="false"
+ TreatWarningsAsErrors="false"
+ WarningLevel="4"
+ CheckContractAdmissibility="True"
+ CheckPurity="False"
+ />
+ </Settings>
+ <References>
+ <Reference Name="System"
+ AssemblyName="System"
+ Private="false"
+ />
+ <Reference Name="System.Data"
+ AssemblyName="System.Data"
+ Private="false"
+ />
+ <Reference Name="System.Xml"
+ AssemblyName="System.Xml"
+ Private="false"
+ />
+ <Reference Name="System.Compiler"
+ AssemblyName="System.Compiler"
+ Private="false"
+ HintPath="../../Binaries/System.Compiler.dll"
+ />
+ <Reference Name="Microsoft.SpecSharp"
+ AssemblyName="Microsoft.SpecSharp"
+ Private="false"
+ HintPath="../../Binaries/Microsoft.SpecSharp.dll"
+ />
+ <Reference Name="System.Compiler.Framework"
+ AssemblyName="System.Compiler.Framework"
+ Private="false"
+ HintPath="../../Binaries/System.Compiler.Framework.dll"
+ />
+ <Reference Name="AbsInt"
+ AssemblyName="AbsInt"
+ Private="false"
+ HintPath="../AbsInt/bin/Debug/AbsInt.dll"
+ />
+ <Reference Name="AIFramework"
+ AssemblyName="AIFramework"
+ Private="false"
+ HintPath="../AIFramework/bin/debug/AIFramework.dll"
+ />
+ <Reference Name="Core"
+ AssemblyName="Core"
+ Private="false"
+ HintPath="../Core/bin/Debug/Core.dll"
+ />
+ <Reference Name="VCGeneration"
+ AssemblyName="VCGeneration"
+ Private="false"
+ HintPath="../VCGeneration/bin/debug/VCGeneration.dll"
+ />
+ <Reference Name="Dafny"
+ Project="{DEAD83C6-1510-4AF9-8F7D-C837DDBB2632}"
+ Private="true"
+ />
+ </References>
+ </Build>
+ <Files>
+ <Include>
+ <File RelPath="DafnyDriver.ssc"
+ SubType="Code"
+ BuildAction="Compile"
+ />
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="..\version.ssc"
+ />
+ </Include>
+ </Files>
+ </XEN>
+</VisualStudioProject> \ No newline at end of file
diff --git a/Source/Graph/Graph.ssc b/Source/Graph/Graph.ssc
new file mode 100644
index 00000000..c9795f15
--- /dev/null
+++ b/Source/Graph/Graph.ssc
@@ -0,0 +1,746 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using System;
+using System.Collections.Generic;
+using Microsoft.SpecSharp.Collections;
+using Microsoft.Contracts;
+using System.Text; // for StringBuilder
+namespace Graphing{
+
+internal static class Util{
+ private static string! ListToString<T>(IEnumerable<T> xs){
+ StringBuilder sb = new StringBuilder();
+ sb.Append("[");
+ bool first = true;
+ foreach(T! x in xs){
+ 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){
+ StringBuilder sb = new StringBuilder();
+ sb.Append("{");
+ bool first = true;
+ foreach (KeyValuePair<Node,List<Node>> de in d){
+ if (!first) sb.Append(", ");
+ 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 { assume IsSet; return Value; }
+ set { Value = value; IsSet = true; }
+ }
+ public void UnSet() {
+ IsSet = false;
+ }
+}
+
+internal 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 { assume this.immediateDominatorMap != null; return this.immediateDominatorMap; }
+ }
+ public bool DominatedBy(Node dominee, Node dominator){
+ assume this.nodeToPostOrderNumber != null;
+ assume this.doms != null;
+ int domineeNum = this.nodeToPostOrderNumber[dominee];
+ int dominatorNum = this.nodeToPostOrderNumber[dominator];
+ if (domineeNum == dominatorNum) return true;
+ int currentNodeNum = this.doms[domineeNum];
+ do {
+ if (currentNodeNum == dominatorNum) return true;
+ currentNodeNum = this.doms[currentNodeNum];
+ } while (currentNodeNum != this.sourceNum);
+ return false;
+ }
+ private Dictionary<Node,List<Node>>? domMap = null;
+ [Pure][Reads(ReadsAttribute.Reads.Owned)]
+ public override string ToString(){
+ assume this.doms != null;
+ int[] localDoms = this.doms;
+ 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(", ");
+ 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){
+ if (0 < i) Console.Write(", ");
+ Console.Write(x.ToString());
+ i++;
+ }
+ Console.WriteLine("]");
+ }
+ public string! ListToString<T>(IEnumerable<T> xs){
+ StringBuilder sb = new StringBuilder();
+ sb.Append("[");
+ bool first = true;
+ foreach(T! x in xs){
+ 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>();
+ Dictionary<Node,bool> visited = new Dictionary<Node,bool>(n);
+ int currentNumber = 1;
+ assume this.source != null;
+ this.PostOrderVisit(this.source, visited, ref currentNumber);
+ 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, Dictionary<Node,bool> visited, ref int currentNumber){
+ if (visited.ContainsKey(n)) return;
+ visited[n] = true;
+ foreach(Node! child in this.graph.Successors(n)){
+ PostOrderVisit(child, visited, ref currentNumber);
+ }
+ assume this.postOrderNumberToNode != null;
+ assume this.nodeToPostOrderNumber != null;
+ this.postOrderNumberToNode[currentNumber].Val = n;
+ this.nodeToPostOrderNumber[n] = currentNumber;
+ currentNumber++;
+ return;
+ }
+}
+public class Graph<Node> {
+ private Set<Pair<Node!,Node!>> es;
+ private Set<Node> ns;
+ private Node source;
+ private bool reducible;
+ private Set<Node> headers;
+ private Map<Node,Set<Node>> backEdgeNodes;
+ private Map<Pair<Node!,Node!>,Set<Node>> naturalLoops;
+ private DomRelation<Node>? dominatorMap = null;
+ private Dictionary<Node, Set<Node>> predCache = new Dictionary<Node, Set<Node>>();
+ private Dictionary<Node, Set<Node>> succCache = new Dictionary<Node, Set<Node>>();
+ private bool predComputed;
+
+ private class PreHeader {
+ Node! myHeader;
+ internal PreHeader(Node! h) { myHeader = h; }
+
+ [Pure][Reads(ReadsAttribute.Reads.Owned)]
+ public override string! ToString() { return "#" + myHeader.ToString(); }
+ }
+
+ public Graph(Set<Pair<Node!,Node!>> edges)
+ {
+ 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>{ Pair<Node,Node> p in edges; p.First } + new Set<Node>{ Pair<Node,Node> p in edges; p.Second };
+
+ //
+ Set<Node> temp = new Set<Node>();
+ foreach (Pair<Node!,Node!> p in edges){
+ temp.Add(p.First);
+ temp.Add(p.Second);
+ }
+ ns = temp;
+ }
+ public Graph()
+ { es = new Set<Pair<Node!,Node!>>(); ns = new Set<Node>(); }
+
+ // BUGBUG: Set<T>.ToString() should return a non-null string
+ [Pure][Reads(ReadsAttribute.Reads.Owned)]
+ public override string! ToString() { return "" + es.ToString(); }
+
+ public void AddSource(Node! x)
+ {
+ // 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)
+ {
+ //es += Set<Edge>{<source,dest>};
+ //ns += Set<Node>{source, dest};
+ es.Add(new Pair<Node!,Node!>(source,dest));
+ ns.Add(source);
+ ns.Add(dest);
+ predComputed = false;
+ }
+
+ public Set<Node> Nodes { get { return ns; } }
+ public IEnumerable<Pair<Node!,Node!>> Edges { get { return es; } }
+
+ public bool Edge(Node! x, Node! y) {
+ // original A#
+ // return <x,y> in es;
+ return es.Contains(new Pair<Node!,Node!>(x,y));
+ }
+
+ private void ComputePredSuccCaches()
+ {
+ if (predComputed) return;
+ predComputed = true;
+ predCache = new Dictionary<Node, Set<Node>>();
+ succCache = new Dictionary<Node, Set<Node>>();
+
+ foreach (Node n in Nodes) {
+ predCache[n] = new Set<Node>();
+ succCache[n] = new Set<Node>();
+ }
+
+ foreach(Pair<Node!,Node!> p in Edges){
+ Set<Node> tmp;
+
+ tmp = predCache[p.Second];
+ tmp.Add(p.First);
+ predCache[p.Second] = tmp;
+
+ tmp = succCache[p.First];
+ tmp.Add(p.Second);
+ succCache[p.First] = tmp;
+ }
+ }
+
+ internal IEnumerable<Node> Predecessors(Node n)
+ {
+ // original A#
+ //Set<Node> result = Set{ x : x in Nodes, Edge(x,n) };
+
+ ComputePredSuccCaches();
+ return predCache[n];
+ }
+
+ internal IEnumerable<Node> Successors(Node n)
+ {
+ ComputePredSuccCaches();
+ return succCache[n];
+ }
+
+ internal DomRelation<Node> /*Map<Node,Set<Node>>*/ DominatorMap
+ {
+ get {
+ 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 {
+ 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) {
+ 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 (Pair<Node!,Node!> e in this.Edges){
+ Node! target = e.Second;
+ 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()
+ {
+ Pair<bool,Seq<Node>> result = this.TopSort();
+ return result.First ? result.Second : (IEnumerable<Node>)new Seq<Node>();
+ }
+ // From AsmL distribution example
+ private Pair<bool,Seq<Node>> TopSort()
+ {
+ Seq<Node> S = new Seq<Node>();
+ Set<Node> V = this.Nodes;
+ Set<Node> X = new Set<Node>();
+ foreach (Node! n in V){ X.Add(n); }
+ bool change = true;
+ while ( change )
+ // invariant: X = V - S
+ {
+ change = false;
+ if (X.Count > 0){
+ foreach (Node! n in X){
+ // see if n has any incoming edges from any other node in X
+ bool inDegreeZero = true;
+ foreach(Node! u in X){
+ 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 Pair<bool,Seq<Node>>(false,new Seq<Node>());
+ }
+ }
+ }
+ return new Pair<bool,Seq<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, pp. 670--671]
+ // returns map D s.t. d in D(n) iff d dom n
+ //
+ static private Map<Node,Set<Node>> OldComputeDominators(Graph<Node> g, Node! source){
+ assert g.source != null;
+ Set<Node> N = g.Nodes;
+ Set<Node> nonSourceNodes = N - new Set<Node>(source);
+ Map<Node,Set<Node>> D = new Map<Node,Set<Node>>();
+ D[source] = new Set<Node>(source);
+ foreach (Node! n in nonSourceNodes){
+ D[n] = N;
+ }
+ bool change = true;
+ while ( change ){
+ change = false;
+ foreach (Node! n in nonSourceNodes){
+
+ // original A#
+ //Set<Set<Node>> allPreds = new Set<Set<Node>>{ Node p in this.Predecessors(n) ; D[p] };
+
+ Set<Set<Node>> allPreds = new Set<Set<Node>>();
+ foreach(Node! p in g.Predecessors(n)) allPreds.Add(D[p]);
+ Set<Node> temp = new Set<Node>(n) + Set<Node>.BigIntersect(allPreds);
+ if ( temp != D[n] ){
+ change = true;
+ D[n] = temp;
+ }
+ }
+ }
+ return D;
+ }
+
+ // [Dragon, Fig. 10.15, p. 604. Algorithm for constructing the natural loop.]
+ static Set<Node> NaturalLoop(Graph<Node> g, Pair<Node!,Node!> backEdge)
+ {
+ Node! n = backEdge.First;
+ Node! d = backEdge.Second;
+ Seq<Node> stack = new Seq<Node>();
+ Set<Node> loop = new Set<Node>(d);
+ if ( !n.Equals(d) ) // then n is not in loop
+ {
+ loop.Add(n);
+ stack = new Seq<Node>(n) + stack; // push n onto stack
+ }
+ while ( stack.Count > 0) // not empty
+ {
+ Node m = stack.Head;
+ stack = stack.Tail; // pop stack
+ foreach (Node! p in g.Predecessors(m))
+ {
+ if ( !(loop.Contains(p)) )
+ {
+ loop.Add(p);
+ stack = new Seq<Node>(p) + stack; // push p onto stack
+ }
+ }
+ }
+ return loop;
+ }
+
+ internal struct ReducibleResult{
+ internal bool reducible;
+ internal Set<Node> headers;
+ internal Map<Node,Set<Node>> backEdgeNodes;
+ internal Map<Pair<Node!,Node!>,Set<Node>> naturalLoops;
+ internal ReducibleResult(bool b,
+ Set<Node> headers,
+ Map<Node,Set<Node>> backEdgeNodes,
+ Map<Pair<Node!,Node!>,Set<Node>> naturalLoops){
+ this.reducible = b;
+ this.headers = headers;
+ this.backEdgeNodes = backEdgeNodes;
+ this.naturalLoops = naturalLoops;
+ }
+
+ }
+
+ // [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);
+ }
+
+ // [Dragon, p. 606]
+ static ReducibleResult ComputeReducible(Graph<Node> g,
+ Node source,
+ DomRelation<Node>! DomRelation) {
+
+ //Console.WriteLine("[" + DateTime.Now +"]: begin ComputeReducible");
+ IEnumerable<Pair<Node!,Node!>> edges = g.Edges;
+ Set<Pair<Node!,Node!>> backEdges = new Set<Pair<Node!,Node!>>();
+ Set<Pair<Node!,Node!>> nonBackEdges = new Set<Pair<Node!,Node!>>();
+ foreach (Pair<Node!,Node!> e in edges){
+ Node x = e.First;
+ Node y = e.Second; // 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);
+ }
+ }
+ if ( !Acyclic(new Graph<Node>(nonBackEdges), source) ){
+ return new ReducibleResult(false,
+ new Set<Node>(),
+ new Map<Node,Set<Node>>(),
+ new Map<Pair<Node!,Node!>,Set<Node>>());
+ }else{
+ // original A#:
+ //Set<Node> headers = Set{ d : <n,d> in backEdges };
+ Set<Node> headers = new Set<Node>();
+ foreach(Pair<Node!,Node!> e in backEdges)
+ headers.Add(e.Second);
+ // original A#:
+ //Map<Node,Set<Node>> backEdgeNodes = Map{ h -> bs : h in headers, bs = Set<Node>{ b : <b,x> in backEdges, x == h } };
+ Map<Node,Set<Node>> backEdgeNodes = new Map<Node,Set<Node>>();
+ foreach(Node! h in headers){
+ Set<Node> bs = new Set<Node>();
+ foreach(Pair<Node!,Node!> backedge in backEdges){
+ if (backedge.Second.Equals(h)){
+ bs.Add(backedge.First);
+ }
+ }
+ backEdgeNodes.Add(h,bs);
+ }
+
+ // original A#:
+ //Map<Pair<Node,Node>,Set<Node>> naturalLoops = Map{ e -> NaturalLoop(g,e) : e in backEdges };
+ Map<Pair<Node!,Node!>,Set<Node>> naturalLoops = new Map<Pair<Node!,Node!>,Set<Node>>();
+ foreach (Pair<Node!,Node!> e in backEdges){
+ naturalLoops.Add(e,NaturalLoop(g,e));
+ }
+
+ //Console.WriteLine("[" + DateTime.Now +"]: end ComputeReducible");
+ return new ReducibleResult(true, headers, backEdgeNodes, naturalLoops);
+ }
+ }
+
+ public bool Reducible { get { return reducible; } }
+ public IEnumerable<Node> Headers { get { return headers; } }
+ public IEnumerable<Node> BackEdgeNodes(Node! h){
+ // original A#:
+ //return h in backEdgeNodes ? backEdgeNodes[h] : null;
+ return (backEdgeNodes.ContainsKey(h) ? backEdgeNodes[h] : (IEnumerable<Node>)new Seq<Node>());
+ }
+ public IEnumerable<Node> NaturalLoops(Node! header, Node! backEdgeNode)
+ {
+ Pair<Node!,Node!> e = new Pair<Node!,Node!>(backEdgeNode,header);
+ return naturalLoops.ContainsKey(e) ? naturalLoops[e] : (IEnumerable<Node>)new Seq<Node>();
+ }
+
+ 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;
+ return;
+ }
+
+
+} // end: class Graph
+
+public class GraphProgram
+{
+ static void TestGraph<T>(T! source, params Pair<T!,T!>[] edges){
+ Set<Pair<T!,T!>> es = new Set<Pair<T!,T!>>();
+ foreach (Pair<T!,T!> e in edges) 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<Pair<int,int>>{ new Pair<int,int>(1,2), new Pair<int,int>(1,3), new Pair<int,int>(2,3) });
+
+ Console.WriteLine("");
+ TestGraph<char>('a',
+ new Pair<char,char>('a','b'),
+ new Pair<char,char>('a','c'),
+ new Pair<char,char>('b','c')
+ );
+
+ Console.WriteLine("");
+ TestGraph<char>('a',
+ new Pair<char,char>('a','b'),
+ new Pair<char,char>('a','c'),
+ new Pair<char,char>('b','d'),
+ new Pair<char,char>('c','e'),
+ new Pair<char,char>('c','f'),
+ new Pair<char,char>('d','e'),
+ new Pair<char,char>('e','d'),
+ new Pair<char,char>('e','f'),
+ new Pair<char,char>('f','e')
+ );
+
+ Console.WriteLine("");
+ TestGraph<char>('a',
+ new Pair<char,char>('a','b'),
+ new Pair<char,char>('a','c'),
+ new Pair<char,char>('b','c'),
+ new Pair<char,char>('c','b')
+ );
+
+ Console.WriteLine("");
+ TestGraph<int>(1,
+ new Pair<int,int>(1,2),
+ new Pair<int,int>(1,3),
+ new Pair<int,int>(2,3)
+ );
+
+ Console.WriteLine("");
+ TestGraph<int>(1,
+ new Pair<int,int>(1,2),
+ new Pair<int,int>(1,3),
+ new Pair<int,int>(2,3),
+ new Pair<int,int>(3,2)
+ );
+
+ Console.WriteLine("");
+ TestGraph<int>(2,
+ new Pair<int,int>(2,3),
+ new Pair<int,int>(2,4),
+ new Pair<int,int>(3,2)
+ );
+
+ Console.WriteLine("");
+ TestGraph<char>('a',
+ new Pair<char,char>('a','b'),
+ new Pair<char,char>('a','c'),
+ new Pair<char,char>('b','c'),
+ new Pair<char,char>('b','b')
+ );
+
+
+ }
+}
+
+}
diff --git a/Source/Graph/Graph.sscproj b/Source/Graph/Graph.sscproj
new file mode 100644
index 00000000..137c9b0e
--- /dev/null
+++ b/Source/Graph/Graph.sscproj
@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="utf-8"?>
+<VisualStudioProject>
+ <XEN ProjectType="Local"
+ SchemaVersion="1.0"
+ Name="Graph"
+ ProjectGuid="4c28fb90-630e-4b55-a937-11a011b79765"
+ >
+ <Build>
+ <Settings ApplicationIcon=""
+ AssemblyName="Graph"
+ OutputType="Library"
+ RootNamespace="Graph"
+ StartupObject=""
+ StandardLibraryLocation=""
+ TargetPlatform="v2"
+ TargetPlatformLocation=""
+ ShadowedAssembly=""
+ >
+ <Config Name="Debug"
+ AllowUnsafeBlocks="False"
+ BaseAddress="285212672"
+ CheckForOverflowUnderflow="False"
+ ConfigurationOverrideFile=""
+ DefineConstants="DEBUG;TRACE"
+ DocumentationFile=""
+ DebugSymbols="True"
+ FileAlignment="4096"
+ IncrementalBuild="True"
+ Optimize="False"
+ OutputPath="bin\debug"
+ RegisterForComInterop="False"
+ RemoveIntegerChecks="false"
+ TreatWarningsAsErrors="False"
+ WarningLevel="4"
+ ReferenceTypesAreNonNullByDefault="True"
+ RunProgramVerifier="False"
+ RunProgramVerifierWhileEditing="False"
+ ProgramVerifierCommandLineOptions=""
+ AllowPointersToManagedStructures="False"
+ CheckContractAdmissibility="True"
+ CheckPurity="False"
+ />
+ <Config Name="Release"
+ AllowUnsafeBlocks="false"
+ BaseAddress="285212672"
+ CheckForOverflowUnderflow="false"
+ ConfigurationOverrideFile=""
+ DefineConstants="TRACE"
+ DocumentationFile=""
+ DebugSymbols="false"
+ FileAlignment="4096"
+ IncrementalBuild="false"
+ Optimize="true"
+ OutputPath="bin\release"
+ RegisterForComInterop="false"
+ RemoveIntegerChecks="false"
+ TreatWarningsAsErrors="false"
+ WarningLevel="4"
+ />
+ </Settings>
+ <References>
+ <Reference Name="System"
+ AssemblyName="System"
+ Private="false"
+ />
+ <Reference Name="System.Data"
+ AssemblyName="System.Data"
+ Private="false"
+ />
+ <Reference Name="System.Xml"
+ AssemblyName="System.Xml"
+ Private="false"
+ />
+ </References>
+ </Build>
+ <Files>
+ <Include>
+ <File RelPath="Graph.ssc"
+ SubType="Code"
+ BuildAction="Compile"
+ />
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="..\version.ssc"
+ />
+ </Include>
+ </Files>
+ </XEN>
+</VisualStudioProject> \ No newline at end of file
diff --git a/Source/Houdini/Checker.ssc b/Source/Houdini/Checker.ssc
new file mode 100644
index 00000000..03c2beda
--- /dev/null
+++ b/Source/Houdini/Checker.ssc
@@ -0,0 +1,460 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using System;
+using Microsoft.Contracts;
+using System.Collections.Generic;
+using Microsoft.Boogie;
+using Microsoft.Boogie.Simplify.AST;
+using VC;
+using Microsoft.Boogie.Z3;
+using Microsoft.AbstractInterpretationFramework;
+using Microsoft.Boogie.AbstractInterpretation;
+using System.Collections;
+using System.Compiler;
+using System.IO;
+using System.Threading;
+
+namespace Microsoft.Boogie.Houdini {
+
+ public abstract class HdnCheckerFactory {
+ public static HdnChecker! BuildHdnChecker(Checker! checker) {
+ if (checker.TheoremProver is Z3ThreadTheoremProver)
+ return new HoudiniZ3ApiChecker(checker);
+ else if (checker.TheoremProver is Z3ProcessTheoremProver) {
+ if (CommandLineOptions.Clo.houdiniFlags.incremental) {
+ return new HoudiniZ3CheckerIncr(checker);
+ } else {
+ return new HoudiniZ3Checker(checker);
+ }
+ } else
+ throw new Exception("HdnChecker only works with z3");
+ }
+ }
+
+ public abstract class HdnChecker {
+ public abstract void PrepareCheck(string! _descriptiveName,
+ VCExpr! _vc, ProverInterface.ErrorHandler! _handler);
+ public abstract void PushAxiom(VCExpr! vc);
+ public abstract void Pop();
+ public abstract void Check();
+ public abstract ProverInterface.Outcome ReadOutcome()
+ throws UnexpectedProverOutputException;
+ }
+
+ public class HoudiniZ3ApiChecker:HdnChecker {
+
+ private Z3ThreadTheoremProver! z3prover;
+
+ private ProverInterface.ErrorHandler handler;
+ private ProverInterface.Outcome outcome;
+ private UnexpectedProverOutputException outputExn;
+
+ internal HoudiniZ3ApiChecker(Checker! checker)
+ requires checker.TheoremProver!=null;
+ requires checker.TheoremProver is Z3ThreadTheoremProver;
+ {
+ this.z3prover = (Z3ThreadTheoremProver)checker.TheoremProver;
+ }
+
+ public override void PrepareCheck(string! _descriptiveName, VCExpr! _vc, ProverInterface.ErrorHandler! _handler) {
+ handler = _handler;
+ z3prover.LogComment(_descriptiveName);
+ z3prover.PrepareCheck(_descriptiveName,_vc);
+ }
+
+ public override void PushAxiom(VCExpr! vc) {
+ z3prover.PushAxiom(vc);
+ }
+
+ public override void Pop() {
+ z3prover.Pop();
+ }
+
+ public override void Check() {
+ z3prover.BeginPreparedCheck();
+ try {
+ outcome = z3prover.CheckOutcome((!)handler);
+ } catch (UnexpectedProverOutputException e) {
+ outputExn = e;
+ }
+ }
+
+ public override ProverInterface.Outcome ReadOutcome()
+ throws UnexpectedProverOutputException;
+ {
+ if (outputExn != null) {
+ throw outputExn;
+ }
+ return outcome;
+ }
+ }
+
+ // version of Z3PTP exposing more of the prover process functionality
+ public class Z3ProcessTPExposed : Z3ProcessTheoremProver {
+
+ [NotDelayed]
+ public Z3ProcessTPExposed (TextWriter/*?*/ logFileWriter, VCExpressionGenerator! gen, DeclFreeProverContext! ctx, int timeout, bool typed)
+ throws UnexpectedProverOutputException;
+ {
+ base(logFileWriter, gen, ctx, timeout, typed, "z3.exe");
+ }
+
+
+ //MOVED Directly Z3 ProverInterface for now...
+ //To introduce this cleanly, need to add a new subproject under Provers
+ //and must use the commandline option for that, instead of saying /prover:z3
+ //That way, the class is constructed in class Checker the same way
+ //all the other provers are constructed
+
+ }
+
+ public class Z3ExposedFactory : Z3.Factory {
+
+ }
+
+
+ //Old version
+ public class HoudiniZ3Checker:HdnChecker {
+ private Stack<VCExpr!>! axioms = new Stack<VCExpr!>();
+ private Checker! checker;
+ private string descriptiveName;
+ private VCExpr conjecture;
+ private ProverInterface.ErrorHandler handler;
+
+ internal HoudiniZ3Checker(Checker! checker)
+ requires checker.TheoremProver!=null;
+ requires checker.TheoremProver is Z3ProcessTheoremProver;
+ {
+ this.checker = checker;
+ }
+
+ public override void PrepareCheck(string! _descriptiveName, VCExpr! _vc, ProverInterface.ErrorHandler! _handler)
+ {
+ this.descriptiveName = _descriptiveName;
+ this.conjecture = _vc;
+ this.handler = _handler;
+ }
+ public override void PushAxiom(VCExpr! vc) {
+ axioms.Push(vc);
+ }
+ public override void Pop() {
+ axioms.Pop();
+ }
+ private VCExpr! BuildVCAxioms(Stack<VCExpr!>! axioms)
+ requires axioms.Count>0;
+ {
+ VCExpr vc_axioms = null;
+ foreach (VCExpr! axiom in axioms) {
+ if (vc_axioms==null)
+ vc_axioms=axiom;
+ else
+ vc_axioms = checker.VCExprGen.And(vc_axioms,axiom);
+ }
+ return (!)vc_axioms;
+ }
+
+ public override void Check()
+ {
+ assert (descriptiveName!=null);
+ assert (conjecture!=null);
+ assert (handler!=null);
+ outcome = ProverInterface.Outcome.Undetermined;
+
+ VCExpr! vc;
+ if (axioms.Count>0) {
+ VCExpr vc_axioms = BuildVCAxioms(axioms);
+ vc = checker.VCExprGen.Implies(vc_axioms,conjecture);
+ } else
+ vc = conjecture;
+
+ checker.BeginCheck(descriptiveName,vc,handler);
+ WaitHandle.WaitAny(new WaitHandle[] {checker.ProverDone});
+ }
+
+ private ProverInterface.Outcome outcome;
+ private UnexpectedProverOutputException outputExn;
+
+ public override ProverInterface.Outcome ReadOutcome()
+ throws UnexpectedProverOutputException;
+ {
+ try {
+ outcome = checker.ReadOutcome();
+ } catch (UnexpectedProverOutputException e) {
+ throw e;
+ }
+ return outcome;
+ }
+ }
+
+ //new version
+ public class HoudiniZ3CheckerIncr:HdnChecker {
+ private Checker! checker;
+ private string descriptiveName;
+ private VCExpr conjecture;
+ private ProverInterface.ErrorHandler handler;
+
+ // Hack to delay the exception throwing (from Push/Pop...) for now
+ private UnexpectedProverOutputException delayedExc;
+ private Z3ProcessTheoremProver! thmProver;
+
+ internal HoudiniZ3CheckerIncr(Checker! checker)
+ requires checker.TheoremProver!=null;
+ requires checker.TheoremProver is Z3ProcessTheoremProver;
+ {
+ this.checker = checker;
+ this.thmProver = (Z3ProcessTheoremProver!)checker.TheoremProver;
+ }
+
+ private void delayException(UnexpectedProverOutputException exc) {
+ if (delayedExc == null) { delayedExc = exc; }
+ }
+
+ public override void PrepareCheck(string! _descriptiveName, VCExpr! _vc,
+ ProverInterface.ErrorHandler! _handler)
+ {
+ this.descriptiveName = _descriptiveName;
+ this.conjecture = _vc;
+ this.handler = _handler;
+ this.thmProver.LogComment(_descriptiveName);
+ try {
+ this.thmProver.PrepareCheck(_descriptiveName,_vc);
+ } catch (UnexpectedProverOutputException exc) {
+ delayException(exc);
+ }
+ }
+ public override void PushAxiom(VCExpr! vc) {
+ string! vcStr = vc.ToString();
+ try {
+ thmProver.PushAxioms(vcStr);
+ } catch (UnexpectedProverOutputException exc) {
+ delayException(exc);
+ }
+ }
+ public override void Pop() {
+ try {
+ thmProver.PopAxioms();
+ } catch (UnexpectedProverOutputException exc) {
+ delayException(exc);
+ }
+ }
+
+ public override void Check()
+ {
+ assert (descriptiveName!=null);
+ assert (conjecture!=null);
+ assert (handler!=null);
+ outcome = ProverInterface.Outcome.Undetermined;
+
+ VCExpr! vc = checker.VCExprGen.False;
+ checker.BeginCheck(descriptiveName,vc,handler);
+ WaitHandle.WaitAny(new WaitHandle[] {checker.ProverDone});
+ }
+
+ private ProverInterface.Outcome outcome;
+ private UnexpectedProverOutputException outputExn;
+
+ public override ProverInterface.Outcome ReadOutcome()
+ throws UnexpectedProverOutputException;
+ {
+ // HACK
+ if (delayedExc != null) {
+ UnexpectedProverOutputException temp = delayedExc;
+ delayedExc = null;
+ throw temp;
+ }
+ // Normal stuff
+ try {
+ outcome = checker.ReadOutcome();
+ } catch (UnexpectedProverOutputException e) {
+ throw e;
+ }
+ return outcome;
+ }
+ }
+
+ public abstract class HdnVCGenFactory {
+ public abstract HdnVCGen! BuildVCGen(Program! program, string logFilePath, bool appendLogFile);
+ }
+ public class Z3APIHdnVCGenFactory:HdnVCGenFactory {
+ public override HdnVCGen! BuildVCGen(Program! program, string logFilePath, bool appendLogFile) {
+ return new Z3ApiHdnVCGen(program, logFilePath, appendLogFile);
+ }
+ }
+ public class Z3HdnVCGenFactory:HdnVCGenFactory {
+ public override HdnVCGen! BuildVCGen(Program! program, string logFilePath, bool appendLogFile) {
+ return new Z3HdnVCGen(program, logFilePath, appendLogFile);
+ }
+ }
+
+ public abstract class HdnVCGen {
+ public abstract void PrepareVerification(Implementation! impl, Program! program);
+ public abstract void PushAxiom(Axiom! axiom);
+ public abstract void Pop();
+ public abstract VC.VCGen.Outcome Verify(out List<Counterexample!>? errors)
+ throws UnexpectedProverOutputException;
+
+ }
+
+ public class Z3HdnVCGen: HdnVCGen {
+ private Program! program;
+ private string logFilePath;
+ private bool appendLogFile;
+ private Implementation implementation;
+ private Axiom axiom;
+
+ private ExtVCGen vcgen;
+
+ public Z3HdnVCGen(Program! program, string logFilePath, bool appendLogFile) {
+ this.program = program;
+ this.logFilePath = logFilePath;
+ this.appendLogFile= appendLogFile;
+ }
+
+ public override void PrepareVerification(Implementation! impl, Program! program) {
+ this.implementation = impl;
+ this.program = program;
+ this.vcgen = new ExtVCGen(program,logFilePath,appendLogFile);
+ this.vcgen.PrepareVerification(this.implementation,this.program);
+ //watch out for > 1 call -- don't want CFG conversion to happen too many times!!!
+ }
+
+ public override void PushAxiom(Axiom! axiom) {
+ assert this.vcgen != null;
+ this.axiom=axiom;
+ this.vcgen.PushAxiom(this.axiom);
+ }
+
+ public override void Pop() {
+ assert this.vcgen != null;
+ this.vcgen.Pop();
+ this.axiom = null;
+ }
+
+ public override VC.VCGen.Outcome Verify(out List<Counterexample!>? errors)
+ throws UnexpectedProverOutputException; {
+ assert(this.vcgen!=null);
+
+ return vcgen.Verify(out errors);
+ }
+
+ }
+
+ public class Z3ApiHdnVCGen: HdnVCGen {
+ private ExtVCGen! vcgen;
+
+ public Z3ApiHdnVCGen(Program! program, string logFilePath, bool appendLogFile) {
+ this.vcgen = new ExtVCGen(program,logFilePath,appendLogFile);
+ }
+
+ public override void PrepareVerification(Implementation! impl, Program! program) {
+ vcgen.PrepareVerification(impl,program);
+ }
+
+ public override void PushAxiom(Axiom! axiom) {
+ vcgen.PushAxiom(axiom);
+ }
+
+ public override void Pop() {
+ vcgen.Pop();
+ }
+
+ public override VC.VCGen.Outcome Verify(out List<Counterexample!>? errors)
+ throws UnexpectedProverOutputException; {
+ return vcgen.Verify(out errors);
+ }
+
+ }
+
+
+
+ public class ExtVCGen : VCGen {
+
+ private HdnChecker hdnChecker;
+ private VCExpressionGenerator gen;
+ CounterexampleCollector! collector = new CounterexampleCollector();
+
+ public ExtVCGen(Program! program, string logFilePath, bool appendLogFile) {
+ base(program,logFilePath,appendLogFile);
+ }
+
+ public void PrepareVerification(Implementation! impl, Program! program) {
+ collector.OnProgress("HdnVCGen", 0, 0, 0.0);
+ if (CommandLineOptions.Clo.SoundnessSmokeTest) {
+ throw new Exception("HoudiniVCGen does not support Soundness smoke test.");
+ }
+
+ ConvertCFG2DAG(impl, program);
+ Hashtable/*TransferCmd->ReturnCmd*/ gotoCmdOrigins = PassifyImpl(impl, program);
+ Hashtable/*<int, Absy!>*/! label2absy;
+ Checker! checker = new Checker(program, this.logFilePath, this.appendLogFile, impl, CommandLineOptions.Clo.ProverKillTime);
+ VCExpr! vc = GenerateVC(impl, out label2absy, checker);
+
+ ErrorReporter reporter;
+ if (CommandLineOptions.Clo.vcVariety == CommandLineOptions.VCVariety.Local) {
+ reporter = new ErrorReporterLocal(gotoCmdOrigins, label2absy, impl.Blocks, incarnationOriginMap, collector);
+ } else {
+ reporter = new ErrorReporter(gotoCmdOrigins, label2absy, impl.Blocks, incarnationOriginMap, collector);
+ }
+ this.gen = checker.VCExprGen;
+ this.hdnChecker = HdnCheckerFactory.BuildHdnChecker(checker);
+ this.hdnChecker.PrepareCheck((!) impl.Name, vc, reporter);
+ }
+
+
+ public void PushAxiom(Axiom! axiom)
+ {
+ assume (hdnChecker!=null);
+ assume (gen!=null);
+ VCExpr vc = axiom.Expr.VCView(gen);
+ this.hdnChecker.PushAxiom(vc);
+ }
+ public void Pop() {
+ assume (hdnChecker!=null);
+ hdnChecker.Pop();
+ }
+
+ public Outcome Verify(out List<Counterexample!>? errors)
+ throws UnexpectedProverOutputException; {
+ assume (hdnChecker!=null);
+ collector.examples.Clear();
+ hdnChecker.Check();
+ ProverInterface.Outcome proverOutcome;
+ proverOutcome = hdnChecker.ReadOutcome();
+ Outcome verifyOutcome = ReadOutcome(proverOutcome);
+ if (verifyOutcome == Outcome.Errors) {
+ assume (collector.examples!=null);
+ if (collector.examples.Count == 0) {
+ string memStr = System.Convert.ToString(System.GC.GetTotalMemory(false));
+ if (memStr != null)
+ memStr = "?";
+ throw new UnexpectedProverOutputException("Outcome.Errors w/ 0 counter examples. " + memStr + " memory used");
+ }
+ errors = collector.examples;
+ } else {
+ errors = null;
+ }
+ return verifyOutcome;
+ }
+
+ private Outcome ReadOutcome(ProverInterface.Outcome proverOutcome) {
+ switch (proverOutcome) {
+ case ProverInterface.Outcome.Valid:
+ return Outcome.Correct;
+ case ProverInterface.Outcome.Invalid:
+ return Outcome.Errors;
+ case ProverInterface.Outcome.TimeOut:
+ return Outcome.TimedOut;
+ case ProverInterface.Outcome.Undetermined:
+ return Outcome.Inconclusive;
+ default:
+ throw new Exception("Unknown Prover Interface outcome while reading outcome.");
+ }
+ }
+
+ }
+
+
+} \ No newline at end of file
diff --git a/Source/Houdini/Houdini.ssc b/Source/Houdini/Houdini.ssc
new file mode 100644
index 00000000..bd8348be
--- /dev/null
+++ b/Source/Houdini/Houdini.ssc
@@ -0,0 +1,1188 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using System;
+using Microsoft.Contracts;
+using System.Collections.Generic;
+using Microsoft.Boogie;
+using Microsoft.Boogie.Simplify.AST;
+using VC;
+using Microsoft.Boogie.Z3;
+using Microsoft.AbstractInterpretationFramework;
+using Microsoft.Boogie.AbstractInterpretation;
+using System.Collections;
+using System.Compiler;
+using System.IO;
+
+namespace Microsoft.Boogie.Houdini
+{
+
+ class ReadOnlyDictionary<K,V> {
+ private Dictionary<K,V>! dictionary;
+ public ReadOnlyDictionary(Dictionary<K,V>! dictionary) {
+ this.dictionary = dictionary;
+ }
+
+ public Dictionary<K,V>.KeyCollection Keys {
+ get { return this.dictionary.Keys; }
+ }
+
+ public bool TryGetValue(K k, out V? v) {
+ return this.dictionary.TryGetValue(k, out v);
+ }
+
+ public bool ContainsKey(K k) {
+ return this.dictionary.ContainsKey(k);
+ }
+ }
+
+ public class CallGraph {
+
+ private IGraphNavigator! aiCallGraph;
+
+ public CallGraph(IGraphNavigator! aiCallGraph) {
+ this.aiCallGraph = aiCallGraph;
+ }
+
+ public IEnumerable! PreviousNodes(Implementation! n) {
+ return (!)this.aiCallGraph.PreviousNodes(n);
+ }
+ public IEnumerable! NextNodes(Implementation! n) {
+ return (!)this.aiCallGraph.NextNodes(n);
+ }
+
+ }
+
+ public abstract class HoudiniObserver {
+ public virtual void UpdateStart(Program! program, int numConstants) {}
+ public virtual void UpdateIteration() {}
+ public virtual void UpdateImplementation(Implementation! implementation) {}
+ public virtual void UpdateAssignment(Dictionary<string!,bool>! assignment) {}
+ public virtual void UpdateOutcome(VCGen.Outcome outcome) {}
+ public virtual void UpdateEnqueue(Implementation! implementation) {}
+ public virtual void UpdateDequeue() {}
+ public virtual void UpdateConstant(string! constantName) {}
+ public virtual void UpdateEnd(bool isNormalEnd) {}
+ public virtual void UpdateFlushStart() {}
+ public virtual void UpdateFlushFinish() {}
+ public virtual void SeeException(string! msg){}
+ }
+
+ public class IterationTimer <K> {
+ private Dictionary<K, List<double>!>! times;
+
+ public IterationTimer () {
+ times = new Dictionary<K, List<double>!>();
+ }
+
+ public void AddTime(K key, double timeMS) {
+ List<double> oldList;
+ times.TryGetValue(key, out oldList);
+ if (oldList == null) {
+ oldList = new List<double>();
+ } else {
+ times.Remove(key);
+ }
+ oldList.Add(timeMS);
+ times.Add(key, oldList);
+ }
+
+ public void PrintTimes(TextWriter! wr) {
+ wr.WriteLine ("Total procedures: {0}", times.Count);
+ double total = 0;
+ int totalIters = 0;
+ foreach(KeyValuePair<K, List<double>!> kv in times) {
+ int curIter = 0;
+ wr.WriteLine("Times for {0}:", kv.Key);
+ foreach(double v in kv.Value) {
+ wr.WriteLine(" ({0})\t{1}ms", curIter, v);
+ total += v;
+ curIter++;
+ }
+ totalIters += curIter;
+ }
+ total = total / 1000.0;
+ wr.WriteLine ("Total time: {0} (s)", total);
+ wr.WriteLine ("Avg: {0} (s/iter)", total/totalIters);
+ }
+ }
+
+ public class HoudiniTimer : HoudiniObserver {
+ private DateTime startT;
+ private Implementation curImp;
+ private IterationTimer<string!>! times;
+ private TextWriter! wr;
+
+ public HoudiniTimer(TextWriter! wr) {
+ this.wr = wr;
+ times = new IterationTimer<string!>();
+ }
+ public override void UpdateIteration() {
+ startT = DateTime.Now;
+ }
+ public override void UpdateImplementation(Implementation! implementation){
+ curImp = implementation;
+ }
+ public override void UpdateOutcome (VCGen.Outcome o) {
+ assert curImp != null;
+ DateTime endT = DateTime.Now;
+ times.AddTime(curImp.Name, (endT - startT).TotalMilliseconds); // assuming names are unique
+ }
+ public void PrintTimes() {
+ wr.WriteLine("-----------------------------------------");
+ wr.WriteLine("Times for each iteration for each procedure");
+ wr.WriteLine("-----------------------------------------");
+ times.PrintTimes(wr);
+ }
+ }
+
+ public class HoudiniTextReporter: HoudiniObserver {
+ private TextWriter! wr;
+ private int currentIteration = -1;
+
+ public HoudiniTextReporter(TextWriter! wr) {
+ this.wr = wr;
+ }
+ public override void UpdateStart(Program! program, int numConstants) {
+ wr.WriteLine("Houdini started:" + program.ToString() + " #constants: " + numConstants.ToString());
+ currentIteration = -1;
+ wr.Flush();
+ }
+ public override void UpdateIteration() {
+ currentIteration++;
+ wr.WriteLine("---------------------------------------");
+ wr.WriteLine("Houdini iteration #" + currentIteration);
+ wr.Flush();
+ }
+ public override void UpdateImplementation(Implementation! implementation){
+ wr.WriteLine("implementation under analysis :" + implementation.Name);
+ wr.Flush();
+ }
+ public override void UpdateAssignment(Dictionary<string!,bool>! assignment) {
+ bool firstTime = true;
+ wr.Write("assignment under analysis : axiom (");
+ foreach (KeyValuePair<string!,bool> kv in assignment) {
+ if (!firstTime) wr.Write(" && "); else firstTime = false;
+ string! valString; // ugliness to get it lower cased
+ if (kv.Value) valString = "true"; else valString = "false";
+ wr.Write(kv.Key + " == " + valString);
+ }
+ wr.WriteLine(");");
+ wr.Flush();
+ }
+ public override void UpdateOutcome(VCGen.Outcome outcome) {
+ wr.WriteLine("analysis outcome :" + outcome);
+ wr.Flush();
+ }
+ public override void UpdateEnqueue(Implementation! implementation) {
+ wr.WriteLine("worklist enqueue :" + implementation.Name);
+ wr.Flush();
+ }
+ public override void UpdateDequeue() {
+ wr.WriteLine("worklist dequeue");
+ wr.Flush();
+ }
+ public override void UpdateConstant(string! constantName) {
+ wr.WriteLine("constant disabled : " + constantName);
+ wr.Flush();
+ }
+ public override void UpdateEnd(bool isNormalEnd) {
+ wr.WriteLine("Houdini ended: " + (isNormalEnd ? "Normal" : "Abnormal"));
+ wr.WriteLine("Number of iterations: " + (this.currentIteration+1));
+ wr.Flush();
+ }
+ public override void UpdateFlushStart() {
+ wr.WriteLine("***************************************");
+ wr.WriteLine("Flushing remaining implementations");
+ wr.Flush();
+ }
+ public override void UpdateFlushFinish() {
+ wr.WriteLine("***************************************");
+ wr.WriteLine("Flushing finished");
+ wr.Flush();
+ }
+ public override void SeeException(string! msg) {
+ wr.WriteLine("Caught exception: " + msg);
+ wr.Flush();
+ }
+
+ }
+
+
+ public abstract class ObservableHoudini {
+ private List<HoudiniObserver!>! observers= new List<HoudiniObserver!>();
+
+ public void AddObserver(HoudiniObserver! observer) {
+ if (!observers.Contains(observer))
+ observers.Add(observer);
+ }
+ private delegate void NotifyDelegate(HoudiniObserver! observer);
+
+ private void Notify(NotifyDelegate! notifyDelegate) {
+ foreach (HoudiniObserver! observer in observers) {
+ notifyDelegate(observer);
+ }
+ }
+ protected void NotifyStart(Program! program, int numConstants) {
+ NotifyDelegate notifyDelegate = (NotifyDelegate) delegate (HoudiniObserver! r) { r.UpdateStart(program, numConstants); };
+ Notify(notifyDelegate);
+ }
+ protected void NotifyIteration() {
+ Notify((NotifyDelegate) delegate (HoudiniObserver! r) { r.UpdateIteration(); });
+ }
+ protected void NotifyImplementation(Implementation! implementation) {
+ Notify((NotifyDelegate) delegate (HoudiniObserver! r) { r.UpdateImplementation(implementation); });
+ }
+ protected void NotifyAssignment(Dictionary<string!,bool>! assignment) {
+ Notify((NotifyDelegate) delegate (HoudiniObserver! r) { r.UpdateAssignment(assignment); });
+ }
+ protected void NotifyOutcome(VCGen.Outcome outcome) {
+ Notify((NotifyDelegate) delegate (HoudiniObserver! r) { r.UpdateOutcome(outcome); });
+ }
+ protected void NotifyEnqueue(Implementation! implementation){
+ Notify((NotifyDelegate) delegate (HoudiniObserver! r) { r.UpdateEnqueue(implementation); });
+ }
+ protected void NotifyDequeue(){
+ Notify((NotifyDelegate) delegate (HoudiniObserver! r) { r.UpdateDequeue(); });
+ }
+ protected void NotifyConstant(string! constantName){
+ Notify((NotifyDelegate) delegate (HoudiniObserver! r) { r.UpdateConstant(constantName); });
+ }
+ protected void NotifyEnd(bool isNormalEnd) {
+ Notify((NotifyDelegate) delegate (HoudiniObserver! r) { r.UpdateEnd(isNormalEnd); });
+ }
+ protected void NotifyFlushStart() {
+ Notify((NotifyDelegate) delegate (HoudiniObserver! r) { r.UpdateFlushStart(); });
+ }
+ protected void NotifyFlushFinish() {
+ Notify((NotifyDelegate) delegate (HoudiniObserver! r) { r.UpdateFlushFinish(); });
+ }
+
+ protected void NotifyException(string! msg) {
+ Notify((NotifyDelegate) delegate (HoudiniObserver! r) { r.SeeException(msg); });
+ }
+ }
+
+ public enum HoudiniProver { Z3, Z3API }
+
+ public class Houdini : ObservableHoudini {
+
+ private Program! program;
+
+ private ReadOnlyDictionary<string!,IdentifierExpr!>! houdiniConstants;
+ private ReadOnlyDictionary<Implementation!,HdnVCGen!>! vcgenSessions;
+ private CallGraph! callGraph;
+ private bool continueAtError;
+ private HoudiniProver houdiniProver;
+ private HdnVCGenFactory! vcgenFactory;
+
+ public Houdini(Program! program, CallGraph! callgraph, bool continueAtError, HoudiniProver houdiniProver) {
+ this.program=program;
+ this.callGraph = callgraph;
+ this.continueAtError = continueAtError;
+ this.houdiniProver = houdiniProver;
+ HdnVCGenFactory factory;
+ switch (this.houdiniProver) {
+ case HoudiniProver.Z3:
+ factory = new Z3HdnVCGenFactory();
+ break;
+ case HoudiniProver.Z3API:
+ default:
+ factory = new Z3APIHdnVCGenFactory();
+ break;
+ }
+ this.vcgenFactory = factory;
+ HoudiniHelper helper = new HoudiniHelper(factory);
+ this.houdiniConstants = helper.CollectExistentialConstants(program);
+ this.vcgenSessions = helper.PrepareVCGenSessions(program);
+ }
+
+ private Queue<Implementation!>! BuildWorkList(Program! program) {
+ Queue<Implementation!>! queue = new Queue<Implementation!>();
+ foreach ( Declaration! decl in program.TopLevelDeclarations ) {
+ Implementation impl = decl as Implementation;
+ if (impl!=null) {
+ queue.Enqueue(impl);
+ }
+ }
+ return queue;
+ }
+
+ private class HoudiniHelper {
+ private HdnVCGenFactory! vcgenFactory;
+ public HoudiniHelper(HdnVCGenFactory! vcgenFactory) {
+ this.vcgenFactory = vcgenFactory;
+ }
+
+ public ReadOnlyDictionary<Implementation!,HdnVCGen!>! PrepareVCGenSessions(Program! program) {
+ Dictionary<Implementation!,HdnVCGen!>! vcgenSessions = new Dictionary<Implementation!,HdnVCGen!>();
+
+ foreach ( Declaration! decl in program.TopLevelDeclarations ) {
+ Implementation impl = decl as Implementation;
+ if (impl!=null) {
+ // make a different simplify log file for each function
+ String simplifyLog = null;
+ if (CommandLineOptions.Clo.SimplifyLogFilePath != null) {
+ simplifyLog = impl.ToString() + CommandLineOptions.Clo.SimplifyLogFilePath;
+ }
+ HdnVCGen! vcgen = vcgenFactory.BuildVCGen(program, simplifyLog, CommandLineOptions.Clo.SimplifyLogFileAppend);
+ vcgen.PrepareVerification(impl,program);
+ vcgenSessions.Add(impl,vcgen);
+ }
+ }
+ return new ReadOnlyDictionary<Implementation!,HdnVCGen!>(vcgenSessions);
+ }
+
+ public ReadOnlyDictionary<string!,IdentifierExpr!>! CollectExistentialConstants(Program! program) {
+ Dictionary<string!,IdentifierExpr!>! existentialConstants = new Dictionary<string!,IdentifierExpr!>();
+ foreach ( Declaration! decl in program.TopLevelDeclarations ) {
+ Constant constant = decl as Constant;
+ if (constant!=null) {
+ bool result=false;
+ if (constant.CheckBooleanAttribute("existential",ref result)) {
+ if (result==true)
+ existentialConstants.Add(constant.Name, new IdentifierExpr(Token.NoToken,constant));
+ }
+ }
+ }
+ return new ReadOnlyDictionary<string!,IdentifierExpr!>(existentialConstants);
+ }
+ }
+
+ private bool MatchCandidate(Expr boogieExpr, out string candidateConstant) {
+ candidateConstant = null;
+ IExpr antecedent;
+ IExpr expr = boogieExpr as IExpr;
+ if (expr!=null && ExprUtil.Match(expr, Prop.Implies, out antecedent)) {
+ IdentifierExpr.ConstantFunApp constantFunApp = antecedent as IdentifierExpr.ConstantFunApp;
+ if ((constantFunApp !=null) && (houdiniConstants.ContainsKey(constantFunApp.IdentifierExpr.Name))) {
+ candidateConstant = constantFunApp.IdentifierExpr.Name;
+ return true;
+ }
+ }
+ return false;
+ }
+
+
+ private Axiom! BuildAxiom(Dictionary<string!,bool>! currentAssignment) {
+ Expr axiom = null;
+ foreach (KeyValuePair<string!,bool> kv in currentAssignment) {
+ IdentifierExpr constantExpr;
+ houdiniConstants.TryGetValue(kv.Key,out constantExpr);
+ assume (constantExpr!=null);
+ Expr valueExpr = new LiteralExpr(Token.NoToken, kv.Value);
+ Expr constantAssignment = Expr.Binary(Token.NoToken,BinaryOperator.Opcode.Eq,constantExpr,valueExpr);
+ if (axiom==null)
+ axiom = constantAssignment;
+ else
+ axiom = Expr.Binary(Token.NoToken,BinaryOperator.Opcode.And,axiom,constantAssignment);
+ }
+ if (axiom==null)
+ axiom = new LiteralExpr(Token.NoToken, true);
+ return new Axiom(Token.NoToken,axiom);
+ }
+
+ private Dictionary<string!,bool>! BuildAssignment(Dictionary<string!,IdentifierExpr!>.KeyCollection! constants) {
+ Dictionary<string!,bool>! initial = new Dictionary<string!,bool>();
+ foreach (string! constant in constants)
+ initial.Add(constant,true);
+ return initial;
+ }
+
+ private VCGen.Outcome VerifyUsingAxiom(Implementation! implementation, Axiom! axiom, out List<Counterexample!>? errors) {
+ HdnVCGen vcgen;
+ vcgenSessions.TryGetValue(implementation,out vcgen);
+ if(vcgen==null)
+ throw new Exception("HdnVCGen not found for implementation: " + implementation.Name);
+ vcgen.PushAxiom(axiom);
+ VCGen.Outcome outcome = TryCatchVerify(vcgen, out errors);
+ vcgen.Pop();
+ return outcome;
+ }
+
+ // the main procedure that checks a procedure and updates the
+ // assignment and the worklist
+ private VCGen.Outcome HoudiniVerifyCurrent(HoudiniState! current,
+ Program! program,
+ out List<Counterexample!>? errors,
+ out bool exc) {
+ HdnVCGen vcgen;
+ if (current.Implementation == null)
+ throw new Exception("HoudiniVerifyCurrent has null implementation");
+
+ Implementation! implementation = current.Implementation;
+ vcgenSessions.TryGetValue(implementation,out vcgen);
+ if(vcgen==null)
+ throw new Exception("HdnVCGen not found for implementation: " + implementation.Name);
+
+ VCGen.Outcome outcome = HoudiniVerifyCurrentAux(current, program, vcgen, out errors, out exc);
+ return outcome;
+ }
+
+ private VCGen.Outcome VerifyCurrent(HoudiniState! current,
+ Program! program,
+ out List<Counterexample!>? errors,
+ out bool exc) {
+ HdnVCGen vcgen;
+ if (current.Implementation != null) {
+ Implementation! implementation = current.Implementation;
+ vcgenSessions.TryGetValue(implementation,out vcgen);
+ if(vcgen==null)
+ throw new Exception("HdnVCGen not found for implementation: " + implementation.Name);
+
+ VCGen.Outcome outcome = TrySpinSameFunc(current, program, vcgen, out errors, out exc);
+ return outcome;
+ } else {
+ throw new Exception("VerifyCurrent has null implementation");
+ }
+ }
+
+ private bool IsOutcomeNotHoudini(VCGen.Outcome outcome, List<Counterexample!>? errors) {
+ switch (outcome) {
+ case VCGen.Outcome.Correct:
+ return false;
+ break;
+ case VCGen.Outcome.Errors:
+ assume (errors!=null);
+ foreach (Counterexample error in errors) {
+ if (ExtractRefutedAnnotation(error)==null)
+ return true;
+ }
+ return false;
+ break;
+ case VCGen.Outcome.TimedOut:
+ case VCGen.Outcome.Inconclusive:
+ default:
+ return true;
+ break;
+ }
+ }
+
+
+ // returns true if at least one of the violations is non-candidate
+ private bool AnyNonCandidateViolation(VCGen.Outcome outcome, List<Counterexample!>? errors) {
+ switch (outcome) {
+ case VCGen.Outcome.Errors:
+ assert (errors!=null);
+ foreach (Counterexample error in errors) {
+ if (ExtractRefutedAnnotation(error)==null)
+ return true;
+ }
+ return false;
+ break;
+ case VCGen.Outcome.Correct:
+ case VCGen.Outcome.TimedOut:
+ case VCGen.Outcome.Inconclusive:
+ default:
+ return false;
+ break;
+ }
+ }
+
+
+ private List<Counterexample!> emptyList = new List<Counterexample!>();
+
+ // Record most current Non-Candidate errors found by Boogie, etc.
+ private void UpdateHoudiniOutcome(HoudiniOutcome! houdiniOutcome,
+ Implementation! implementation,
+ VCGen.Outcome verificationOutcome,
+ List<Counterexample!>? errors) {
+ string! implName = implementation.ToString();
+ houdiniOutcome.implementationOutcomes.Remove(implName);
+ List<Counterexample!> nonCandidateErrors = new List<Counterexample!>();
+
+ switch (verificationOutcome) {
+ case VCGen.Outcome.Errors:
+ assume (errors!=null);
+ foreach (Counterexample! error in errors) {
+ if (ExtractRefutedAnnotation(error)==null)
+ nonCandidateErrors.Add(error);
+ }
+ break;
+ case VCGen.Outcome.TimedOut:
+ case VCGen.Outcome.Correct:
+ case VCGen.Outcome.Inconclusive:
+ default:
+ break;
+ }
+ houdiniOutcome.implementationOutcomes.Add(implName,
+ new VCGenOutcome(verificationOutcome, nonCandidateErrors));
+
+ }
+
+ private void FlushWorkList(HoudiniState! current) {
+ this.NotifyFlushStart();
+ Axiom axiom = BuildAxiom(current.Assignment);
+ while (current.WorkList.Count>0) {
+ this.NotifyIteration();
+
+ current.Implementation= current.WorkList.Peek();
+ this.NotifyImplementation(current.Implementation);
+
+ List<Counterexample!>? errors;
+ VCGen.Outcome outcome = VerifyUsingAxiom(current.Implementation,axiom,out errors);
+ UpdateHoudiniOutcome(current.Outcome,current.Implementation,outcome,errors);
+ this.NotifyOutcome(outcome);
+
+ current.WorkList.Dequeue();
+ this.NotifyDequeue();
+
+ }
+ this.NotifyFlushFinish();
+ }
+
+ private void UpdateAssignment(HoudiniState! current, RefutedAnnotation! refAnnot){
+ current.Assignment.Remove(refAnnot.Constant);
+ current.Assignment.Add(refAnnot.Constant,false);
+ this.NotifyConstant(refAnnot.Constant);
+ }
+
+ private void AddToWorkList(HoudiniState! current, Implementation! imp) {
+ if (!current.WorkList.Contains(imp) && !current.isBlackListed(imp.Name)) {
+ current.WorkList.Enqueue(imp);
+ this.NotifyEnqueue(imp);
+ }
+ }
+
+ private void UpdateWorkList(HoudiniState! current,
+ VCGen.Outcome outcome,
+ List<Counterexample!>? errors) {
+ assume (current.Implementation!=null);
+
+ switch (outcome) {
+ case VCGen.Outcome.Correct:
+ current.WorkList.Dequeue();
+ this.NotifyDequeue();
+ break;
+ case VCGen.Outcome.Errors:
+ assume (errors!=null);
+ bool dequeue = false;
+ foreach (Counterexample! error in errors) {
+ RefutedAnnotation refutedAnnotation = ExtractRefutedAnnotation(error);
+ if (refutedAnnotation!=null) {
+ foreach (Implementation! implementation in FindImplementationsToEnqueue(refutedAnnotation,current.Implementation))
+ { AddToWorkList(current, implementation); }
+ UpdateAssignment(current, refutedAnnotation);
+ }
+ else {
+ dequeue = true; //once one non-houdini error is hit dequeue?!
+ }
+ }
+ if (dequeue) {
+ current.WorkList.Dequeue();
+ this.NotifyDequeue();
+ }
+ break;
+ case VCGen.Outcome.TimedOut:
+ // TODO: reset session instead of blocking timed out funcs?
+ current.addToBlackList(current.Implementation.Name);
+ current.WorkList.Dequeue();
+ this.NotifyDequeue();
+ break;
+ case VCGen.Outcome.OutOfMemory:
+ case VCGen.Outcome.Inconclusive:
+ current.WorkList.Dequeue();
+ this.NotifyDequeue();
+ break;
+ default:
+ throw new Exception("Unknown vcgen outcome");
+ }
+ }
+
+
+ private void AddRelatedToWorkList(HoudiniState! current, RefutedAnnotation! refutedAnnotation) {
+ assume (current.Implementation != null);
+ foreach (Implementation! implementation in FindImplementationsToEnqueue(refutedAnnotation,current.Implementation)) {
+ AddToWorkList(current, implementation);
+ }
+ }
+
+
+ // Updates the worklist and current assignment
+ // @return true if the current function is kept on the queue
+ private bool UpdateAssignmentWorkList(HoudiniState! current,
+ VCGen.Outcome outcome,
+ List<Counterexample!>? errors) {
+ assume (current.Implementation!=null);
+ bool dequeue = true;
+
+ switch (outcome) {
+ case VCGen.Outcome.Correct:
+ //yeah, dequeue
+ break;
+ case VCGen.Outcome.Errors:
+ assume (errors!=null);
+ foreach (Counterexample! error in errors) {
+ RefutedAnnotation refutedAnnotation = ExtractRefutedAnnotation(error);
+ if (refutedAnnotation!=null) { // some candidate annotation removed
+ AddRelatedToWorkList(current, refutedAnnotation);
+ UpdateAssignment(current, refutedAnnotation);
+ dequeue = false;
+ }
+ }
+ break;
+
+ case VCGen.Outcome.TimedOut:
+ // TODO: reset session instead of blocking timed out funcs?
+ current.addToBlackList(current.Implementation.Name);
+ break;
+ case VCGen.Outcome.Inconclusive:
+ case VCGen.Outcome.OutOfMemory:
+ break;
+ default:
+ throw new Exception("Unknown vcgen outcome");
+ }
+ if (dequeue) {
+ current.WorkList.Dequeue();
+ this.NotifyDequeue();
+ }
+ return !dequeue;
+ }
+
+
+
+ private class HoudiniState {
+ private Queue<Implementation!>! _workList;
+ private Set<string!>! blackList;
+ private Dictionary<string!,bool>! _assignment;
+ private Implementation _implementation;
+ private HoudiniOutcome! _outcome;
+
+ public HoudiniState(Queue<Implementation!>! workList, Dictionary<string!,bool>! currentAssignment) {
+ this._workList = workList;
+ this._assignment = currentAssignment;
+ this._implementation = null;
+ this._outcome = new HoudiniOutcome();
+ this.blackList = new Set<string!>();
+ }
+
+ public Queue<Implementation!>! WorkList {
+ get { return this._workList; }
+ }
+ public Dictionary<string!,bool>! Assignment {
+ get { return this._assignment; }
+ }
+ public Implementation Implementation {
+ get { return this._implementation; }
+ set { this._implementation = value; }
+ }
+ public HoudiniOutcome! Outcome {
+ get { return this._outcome; }
+ }
+ public bool isBlackListed(string! funcName) {
+ return blackList.Contains(funcName);
+ }
+ public void addToBlackList(string! funcName) {
+ blackList.Add(funcName);
+ }
+ }
+
+ private void PrintBadList(string kind, List<string!>! list) {
+ if(list.Count != 0) {
+ Console.WriteLine("----------------------------------------");
+ Console.WriteLine("Functions: {0}", kind);
+ foreach(string! fname in list) {
+ Console.WriteLine("\t{0}", fname);
+ }
+ Console.WriteLine("----------------------------------------");
+ }
+ }
+
+ private void PrintBadOutcomes(List<string!>! timeouts, List<string!>! inconc, List<string!>! errors) {
+ PrintBadList("TimedOut", timeouts);
+ PrintBadList("Inconclusive", inconc);
+ PrintBadList("Errors", errors);
+ }
+
+ public HoudiniOutcome! VerifyProgram (Program! program) {
+ HoudiniOutcome outcome;
+ switch (this.houdiniProver) {
+ case HoudiniProver.Z3:
+ outcome = VerifyProgramSameFuncFirst(program);
+ //outcome = PerformHoudiniInference(program);
+ break;
+ case HoudiniProver.Z3API: // not that stable
+ outcome = VerifyProgramUnorderedWork(program);
+ break;
+ default:
+ throw new Exception("Unknown HoudiniProver: " + this.houdiniProver.ToString());
+ }
+ PrintBadOutcomes(outcome.ListOfTimeouts, outcome.ListOfInconclusives, outcome.ListOfErrors);
+ return outcome;
+ }
+
+ // Old main loop
+ public HoudiniOutcome! VerifyProgramUnorderedWork (Program! program) {
+ HoudiniState current = new HoudiniState(BuildWorkList(program),BuildAssignment((!)houdiniConstants.Keys));
+ this.NotifyStart(program, houdiniConstants.Keys.Count);
+
+ while (current.WorkList.Count>0) {
+ System.GC.Collect();
+ this.NotifyIteration();
+
+ Axiom axiom = BuildAxiom(current.Assignment);
+ this.NotifyAssignment(current.Assignment);
+
+ current.Implementation= current.WorkList.Peek();
+ this.NotifyImplementation(current.Implementation);
+
+ List<Counterexample!>? errors;
+ VCGen.Outcome outcome = VerifyUsingAxiom(current.Implementation, axiom, out errors);
+ this.NotifyOutcome(outcome);
+
+ UpdateHoudiniOutcome(current.Outcome,current.Implementation,outcome,errors);
+ if (IsOutcomeNotHoudini(outcome,errors) && !continueAtError) {
+ current.WorkList.Dequeue();
+ this.NotifyDequeue();
+ FlushWorkList(current);
+ } else
+ UpdateWorkList(current,outcome,errors);
+ }
+ this.NotifyEnd(true);
+ current.Outcome.assignment = current.Assignment;
+ return current.Outcome;
+ }
+
+ // New main loop
+ public HoudiniOutcome! VerifyProgramSameFuncFirst (Program! program) {
+ HoudiniState current = new HoudiniState(BuildWorkList(program),BuildAssignment((!)houdiniConstants.Keys));
+ this.NotifyStart(program, houdiniConstants.Keys.Count);
+
+ while (current.WorkList.Count>0) {
+ bool exceptional = false;
+ System.GC.Collect();
+ this.NotifyIteration();
+
+ current.Implementation = current.WorkList.Peek();
+ this.NotifyImplementation(current.Implementation);
+
+ List<Counterexample!>? errors;
+ VCGen.Outcome outcome = VerifyCurrent(current, program, out errors, out exceptional);
+
+ // updates to worklist already done in VerifyCurrent, unless there was an exception
+ if (exceptional) {
+ this.NotifyOutcome(outcome);
+ UpdateHoudiniOutcome(current.Outcome, current.Implementation, outcome, errors);
+ if (IsOutcomeNotHoudini(outcome,errors) && !continueAtError){
+ current.WorkList.Dequeue();
+ this.NotifyDequeue();
+ FlushWorkList(current);
+ } else {
+ UpdateAssignmentWorkList(current, outcome, errors);
+ }
+ exceptional = false;
+ }
+ }
+ this.NotifyEnd(true);
+ current.Outcome.assignment = current.Assignment;
+ return current.Outcome;
+ }
+
+ //Clean houdini (Based on "Houdini Spec in Boogie" email 10/22/08
+ //Aborts when there is a violation of non-candidate assertion
+ //This can be used in eager mode (continueAfterError) by simply making
+ //all non-candidate annotations as unchecked (free requires/ensures, assumes)
+ public HoudiniOutcome! PerformHoudiniInference(Program! program) {
+ HoudiniState current = new HoudiniState(BuildWorkList(program),BuildAssignment((!)houdiniConstants.Keys));
+ this.NotifyStart(program, houdiniConstants.Keys.Count);
+
+ Console.WriteLine("Using the new houdini algorithm\n");
+
+ while (current.WorkList.Count > 0) {
+ bool exceptional = false;
+ System.GC.Collect();
+ this.NotifyIteration();
+
+ current.Implementation = current.WorkList.Peek();
+ this.NotifyImplementation(current.Implementation);
+
+ List<Counterexample!>? errors;
+ VCGen.Outcome outcome = HoudiniVerifyCurrent(current, program, out errors, out exceptional);
+
+ // updates to worklist already done in VerifyCurrent, unless there was an exception
+ if (exceptional) {
+ this.NotifyOutcome(outcome);
+ UpdateHoudiniOutcome(current.Outcome, current.Implementation, outcome, errors);
+ if (AnyNonCandidateViolation(outcome, errors)) { //abort
+ current.WorkList.Dequeue();
+ this.NotifyDequeue();
+ FlushWorkList(current);
+ } else { //continue
+ UpdateAssignmentWorkList(current, outcome, errors);
+ }
+ }
+ }
+ this.NotifyEnd(true);
+ current.Outcome.assignment = current.Assignment;
+ return current.Outcome;
+ }
+
+
+ private List<Implementation!>! FindImplementationsToEnqueue(RefutedAnnotation! refutedAnnotation, Implementation! currentImplementation) {
+ List<Implementation!>! implementations = new List<Implementation!>();
+ switch (refutedAnnotation.Kind) {
+ case RefutedAnnotationKind.REQUIRES:
+ foreach (Implementation! callee in callGraph.NextNodes(currentImplementation)) {
+ assume (callee.Proc!=null);
+ if (callee.Proc.Equals(refutedAnnotation.CalleeProc))
+ implementations.Add(callee);
+ }
+ break;
+ case RefutedAnnotationKind.ENSURES:
+ foreach (Implementation! caller in callGraph.PreviousNodes(currentImplementation))
+ implementations.Add(caller);
+ break;
+ case RefutedAnnotationKind.ASSERT: //the implementation is already in queue
+ break;
+ default:
+ throw new Exception("Unknown Refuted annotation kind:" + refutedAnnotation.Kind);
+ break;
+ }
+ return implementations;
+ }
+
+ private enum RefutedAnnotationKind { REQUIRES, ENSURES, ASSERT};
+
+ private class RefutedAnnotation {
+ private string! _constant;
+ private RefutedAnnotationKind _kind;
+ private Procedure _callee;
+
+ private RefutedAnnotation(string! constant, RefutedAnnotationKind kind, Procedure callee) {
+ this._constant = constant;
+ this._kind = kind;
+ this._callee = callee;
+ }
+ public RefutedAnnotationKind Kind {
+ get { return this._kind; }
+ }
+ public string! Constant {
+ get { return this._constant; }
+ }
+ public Procedure CalleeProc {
+ get { return this._callee; }
+ }
+ public static RefutedAnnotation BuildRefutedRequires(string! constant, Procedure! callee) {
+ return new RefutedAnnotation(constant,RefutedAnnotationKind.REQUIRES,callee);
+ }
+ public static RefutedAnnotation BuildRefutedEnsures(string! constant) {
+ return new RefutedAnnotation(constant,RefutedAnnotationKind.ENSURES, null);
+ }
+ public static RefutedAnnotation BuildRefutedAssert(string! constant) {
+ return new RefutedAnnotation(constant,RefutedAnnotationKind.ASSERT, null);
+ }
+
+ }
+
+ private void PrintRefutedCall(CallCounterexample! err, XmlSink! xmlOut) {
+ Expr! cond = err.FailingRequires.Condition;
+ string houdiniConst;
+ if (MatchCandidate(cond, out houdiniConst)) {
+ xmlOut.WriteError("precondition violation", err.FailingCall.tok, err.FailingRequires.tok, err.Trace);
+ }
+ }
+
+ private void PrintRefutedReturn(ReturnCounterexample! err, XmlSink! xmlOut) {
+ Expr! cond = err.FailingEnsures.Condition;
+ string houdiniConst;
+ if (MatchCandidate(cond, out houdiniConst)) {
+ xmlOut.WriteError("postcondition violation", err.FailingReturn.tok, err.FailingEnsures.tok, err.Trace);
+ }
+ }
+
+ private void PrintRefutedAssert(AssertCounterexample! err, XmlSink! xmlOut) {
+ Expr cond = err.FailingAssert.OrigExpr;
+ string houdiniConst;
+ if (MatchCandidate(cond, out houdiniConst)) {
+ xmlOut.WriteError("postcondition violation", err.FailingAssert.tok, err.FailingAssert.tok, err.Trace);
+ }
+ }
+
+
+ private void DebugRefutedCandidates(Implementation! curFunc, List<Counterexample!> errors) {
+ XmlSink xmlRefuted = CommandLineOptions.Clo.XmlRefuted;
+ if (xmlRefuted != null && errors != null) {
+ DateTime start = DateTime.Now;
+ xmlRefuted.WriteStartMethod(curFunc.ToString(), start);
+
+ foreach (Counterexample! error in errors) {
+ CallCounterexample ce = error as CallCounterexample;
+ if (ce != null) PrintRefutedCall(ce, xmlRefuted);
+ ReturnCounterexample re = error as ReturnCounterexample;
+ if (re != null) PrintRefutedReturn(re, xmlRefuted);
+ AssertCounterexample ae = error as AssertCounterexample;
+ if (ae != null) PrintRefutedAssert(ae, xmlRefuted);
+ }
+
+ DateTime end = DateTime.Now;
+ xmlRefuted.WriteEndMethod("errors", end, end.Subtract(start));
+ }
+ }
+
+ private RefutedAnnotation ExtractRefutedAnnotation(Counterexample error) {
+ string houdiniConstant;
+ CallCounterexample callCounterexample = error as CallCounterexample;
+ if (callCounterexample!=null) {
+ Procedure! failingProcedure = (!)callCounterexample.FailingCall.Proc;
+ Requires! failingRequires = (!)callCounterexample.FailingRequires;
+ if (MatchCandidate(failingRequires.Condition,out houdiniConstant)) {
+ assert (houdiniConstant!=null);
+ return RefutedAnnotation.BuildRefutedRequires(houdiniConstant, failingProcedure);
+ }
+ }
+ ReturnCounterexample returnCounterexample = error as ReturnCounterexample;
+ if (returnCounterexample!=null) {
+ Ensures failingEnsures =returnCounterexample.FailingEnsures;
+ if (MatchCandidate(failingEnsures.Condition,out houdiniConstant)) {
+ assert (houdiniConstant!=null);
+ return RefutedAnnotation.BuildRefutedEnsures(houdiniConstant);
+ }
+ }
+ AssertCounterexample assertCounterexample = error as AssertCounterexample;
+ if (assertCounterexample!=null) {
+ AssertCmd failingAssert = assertCounterexample.FailingAssert;
+ if (MatchCandidate(failingAssert.OrigExpr,out houdiniConstant)) {
+ assert (houdiniConstant!=null);
+ return RefutedAnnotation.BuildRefutedAssert(houdiniConstant);
+ }
+ }
+
+ return null;
+ }
+
+ private VCGen.Outcome TryCatchVerify(HdnVCGen! vcgen, out List<Counterexample!>? errors) {
+ VCGen.Outcome outcome;
+ try {
+ outcome = vcgen.Verify(out errors);
+ } catch (VCGenException e) {
+ assume(e!=null);
+ errors = null;
+ outcome = VCGen.Outcome.Inconclusive;
+ } catch (UnexpectedProverOutputException upo) {
+ assume(upo!=null);
+ errors = null;
+ outcome = VCGen.Outcome.Inconclusive;
+ }
+ return outcome;
+ }
+
+ //version of TryCatchVerify that spins on the same function
+ //as long as the current assignment is changing
+ private VCGen.Outcome TrySpinSameFunc(HoudiniState! current,
+ Program! program,
+ HdnVCGen! vcgen,
+ out List<Counterexample!>? errors,
+ out bool exceptional) {
+ assert (current.Implementation != null);
+ VCGen.Outcome outcome;
+ bool pushed = false;
+ errors = null;
+ outcome = VCGen.Outcome.Inconclusive;
+ try {
+ bool trySameFunc = true;
+ bool pastFirstIter = false; //see if this new loop is even helping
+
+ do {
+ if (pastFirstIter) {
+ System.GC.Collect();
+ this.NotifyIteration();
+ }
+ Axiom! currentAx = BuildAxiom(current.Assignment);
+ this.NotifyAssignment(current.Assignment);
+
+ vcgen.PushAxiom(currentAx);
+ pushed = true;
+ outcome = vcgen.Verify(out errors);
+ vcgen.Pop();
+ pushed = false;
+ this.NotifyOutcome(outcome);
+
+ DebugRefutedCandidates(current.Implementation, errors);
+ UpdateHoudiniOutcome(current.Outcome, current.Implementation, outcome, errors);
+ if (!continueAtError && IsOutcomeNotHoudini(outcome,errors)) {
+ current.WorkList.Dequeue();
+ this.NotifyDequeue();
+ trySameFunc = false;
+ FlushWorkList(current);
+ } else {
+ trySameFunc = UpdateAssignmentWorkList(current, outcome, errors);
+ //reset for the next round
+ errors = null;
+ outcome = VCGen.Outcome.Inconclusive;
+ }
+ pastFirstIter = true;
+ } while (trySameFunc && current.WorkList.Count > 0);
+
+ } catch (VCGenException e) {
+ assume(e!=null);
+ if (pushed){
+ vcgen.Pop(); // what if session is dead?
+ }
+ NotifyException("VCGen");
+ exceptional = true;
+ return outcome;
+ } catch (UnexpectedProverOutputException upo) {
+ assume(upo!=null);
+ if (pushed){
+ vcgen.Pop();
+ }
+ NotifyException("UnexpectedProverOutput");
+ exceptional = true;
+ return outcome;
+ }
+ exceptional = false;
+ return outcome;
+ }
+
+
+
+ //Similar to TrySpinSameFunc except no Candidate logic
+ private VCGen.Outcome HoudiniVerifyCurrentAux(HoudiniState! current,
+ Program! program,
+ HdnVCGen! vcgen,
+ out List<Counterexample!>? errors,
+ out bool exceptional) {
+ assert (current.Implementation != null);
+ VCGen.Outcome outcome;
+ bool pushed = false;
+ errors = null;
+ outcome = VCGen.Outcome.Inconclusive;
+ try {
+ bool trySameFunc = true;
+ bool pastFirstIter = false; //see if this new loop is even helping
+
+ do {
+ if (pastFirstIter) {
+ System.GC.Collect();
+ this.NotifyIteration();
+ }
+
+ Axiom! currentAx = BuildAxiom(current.Assignment);
+ this.NotifyAssignment(current.Assignment);
+
+ //check the VC with the current assignment
+ vcgen.PushAxiom(currentAx);
+ pushed = true;
+ outcome = vcgen.Verify(out errors);
+ vcgen.Pop();
+ pushed = false;
+ this.NotifyOutcome(outcome);
+
+ DebugRefutedCandidates(current.Implementation, errors);
+ UpdateHoudiniOutcome(current.Outcome, current.Implementation, outcome, errors);
+
+ if (AnyNonCandidateViolation(outcome, errors)) { //abort
+ current.WorkList.Dequeue();
+ this.NotifyDequeue();
+ trySameFunc = false;
+ FlushWorkList(current);
+ } else { //continue
+ trySameFunc = UpdateAssignmentWorkList(current, outcome, errors);
+ //reset for the next round
+ errors = null;
+ outcome = VCGen.Outcome.Inconclusive;
+ }
+ pastFirstIter = true;
+ } while (trySameFunc && current.WorkList.Count > 0);
+
+ } catch (VCGenException e) {
+ assume(e!=null);
+ if (pushed){
+ vcgen.Pop(); // what if session is dead?
+ }
+ NotifyException("VCGen");
+ exceptional = true;
+ return outcome;
+ } catch (UnexpectedProverOutputException upo) {
+ assume(upo!=null);
+ if (pushed){
+ vcgen.Pop();
+ }
+ NotifyException("UnexpectedProverOutput");
+ exceptional = true;
+ return outcome;
+ }
+ exceptional = false;
+ return outcome;
+ }
+ }
+
+ public enum HoudiniOutcomeKind { Done, FatalError, VerificationCompleted }
+
+ public class VCGenOutcome {
+ public VCGen.Outcome outcome;
+ public List<Counterexample!> errors;
+ public VCGenOutcome(VCGen.Outcome outcome, List<Counterexample!> errors) {
+ this.outcome = outcome;
+ this.errors = errors;
+ }
+ }
+
+ public class HoudiniOutcome {
+ // final assignment
+ public Dictionary<string!,bool>! assignment = new Dictionary<string!,bool>();
+ // boogie errors
+ public Dictionary<string!,VCGenOutcome!>! implementationOutcomes = new Dictionary<string!,VCGenOutcome!>();
+ // outcome kind
+ public HoudiniOutcomeKind kind;
+
+ // statistics
+
+ private int CountResults(VCGen.Outcome outcome) {
+ int outcomeCount=0;
+ foreach (VCGenOutcome! verifyOutcome in implementationOutcomes.Values) {
+ if (verifyOutcome.outcome==outcome)
+ outcomeCount++;
+ }
+ return outcomeCount;
+ }
+
+ private List<string!>! ListOutcomeMatches(VCGen.Outcome outcome) {
+ List<string!>! result = new List<string!>();
+ foreach (KeyValuePair<string!, VCGenOutcome!> kvpair in implementationOutcomes) {
+ if (kvpair.Value.outcome==outcome)
+ result.Add(kvpair.Key);
+ }
+ return result;
+ }
+
+ public int ErrorCount {
+ get {
+ return CountResults(VCGen.Outcome.Errors);
+ }
+ }
+ public int Verified {
+ get {
+ return CountResults(VCGen.Outcome.Correct);
+ }
+ }
+ public int Inconclusives {
+ get {
+ return CountResults(VCGen.Outcome.Inconclusive);
+ }
+ }
+ public int TimeOuts {
+ get {
+ return CountResults(VCGen.Outcome.TimedOut);
+ }
+ }
+ public List<string!>! ListOfTimeouts {
+ get {
+ return ListOutcomeMatches(VCGen.Outcome.TimedOut);
+ }
+ }
+ public List<string!>! ListOfInconclusives {
+ get {
+ return ListOutcomeMatches(VCGen.Outcome.Inconclusive);
+ }
+ }
+ public List<string!>! ListOfErrors {
+ get {
+ return ListOutcomeMatches(VCGen.Outcome.Errors);
+ }
+ }
+ }
+
+}
diff --git a/Source/Houdini/Houdini.sscproj b/Source/Houdini/Houdini.sscproj
new file mode 100644
index 00000000..3f68bb91
--- /dev/null
+++ b/Source/Houdini/Houdini.sscproj
@@ -0,0 +1,118 @@
+<?xml version="1.0" encoding="utf-8"?>
+<VisualStudioProject>
+ <XEN ProjectType="Local"
+ SchemaVersion="1.0"
+ Name="Houdini"
+ ProjectGuid="40454b39-4f61-48b2-bde3-e9271b24f469"
+ >
+ <Build>
+ <Settings ApplicationIcon=""
+ AssemblyName="Houdini"
+ OutputType="Library"
+ RootNamespace="Houdini"
+ StartupObject=""
+ StandardLibraryLocation=""
+ TargetPlatform="v2"
+ TargetPlatformLocation=""
+ >
+ <Config Name="Debug"
+ AllowUnsafeBlocks="False"
+ BaseAddress="285212672"
+ CheckForOverflowUnderflow="False"
+ ConfigurationOverrideFile=""
+ DefineConstants="DEBUG;TRACE"
+ DocumentationFile=""
+ DebugSymbols="True"
+ FileAlignment="4096"
+ IncrementalBuild="True"
+ Optimize="False"
+ OutputPath="bin\debug"
+ RegisterForComInterop="False"
+ RemoveIntegerChecks="false"
+ TreatWarningsAsErrors="False"
+ WarningLevel="4"
+ CheckContractAdmissibility="True"
+ CheckPurity="False"
+ />
+ <Config Name="Release"
+ AllowUnsafeBlocks="false"
+ BaseAddress="285212672"
+ CheckForOverflowUnderflow="false"
+ ConfigurationOverrideFile=""
+ DefineConstants="TRACE"
+ DocumentationFile=""
+ DebugSymbols="false"
+ FileAlignment="4096"
+ IncrementalBuild="false"
+ Optimize="true"
+ OutputPath="bin\release"
+ RegisterForComInterop="false"
+ RemoveIntegerChecks="false"
+ TreatWarningsAsErrors="false"
+ WarningLevel="4"
+ CheckContractAdmissibility="True"
+ CheckPurity="False"
+ />
+ </Settings>
+ <References>
+ <Reference Name="System"
+ AssemblyName="System"
+ Private="false"
+ />
+ <Reference Name="System.Data"
+ AssemblyName="System.Data"
+ Private="false"
+ />
+ <Reference Name="System.Xml"
+ AssemblyName="System.Xml"
+ Private="false"
+ />
+ <Reference Name="Core"
+ Project="{47BC34F1-A173-40BE-84C2-9332B4418387}"
+ Private="true"
+ />
+ <Reference Name="VCGeneration"
+ Project="{F65666DE-FB56-457C-8782-09BE243450FC}"
+ Private="true"
+ />
+ <Reference Name="Simplify"
+ Project="{F75666DE-FB56-457C-8782-09BE243450FC}"
+ Private="true"
+ />
+ <Reference Name="AIFramework"
+ Project="{24B55172-AD8B-47D1-8952-5A95CFDB9B31}"
+ Private="true"
+ />
+ <Reference Name="AbsInt"
+ Project="{11D06232-2039-4BCA-853B-C596E2A4EDB0}"
+ Private="true"
+ />
+ <Reference Name="System.Compiler.Framework"
+ AssemblyName="System.Compiler.Framework"
+ Private="false"
+ HintPath="../../Binaries/System.Compiler.Framework.dll"
+ />
+ <Reference Name="Z3"
+ Project="{F75666DE-CD56-457C-8782-09BE243450FC}"
+ Private="true"
+ />
+ </References>
+ </Build>
+ <Files>
+ <Include>
+ <File RelPath="Houdini.ssc"
+ SubType="Code"
+ BuildAction="Compile"
+ />
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="Checker.ssc"
+ />
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="..\version.ssc"
+ />
+ </Include>
+ </Files>
+ </XEN>
+</VisualStudioProject> \ No newline at end of file
diff --git a/Source/Provers/SMTLib/ProverInterface.ssc b/Source/Provers/SMTLib/ProverInterface.ssc
new file mode 100644
index 00000000..b55cc403
--- /dev/null
+++ b/Source/Provers/SMTLib/ProverInterface.ssc
@@ -0,0 +1,240 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Threading;
+using System.IO;
+using ExternalProver;
+using System.Diagnostics;
+using Microsoft.Contracts;
+using Microsoft.Boogie.AbstractInterpretation;
+using Microsoft.Boogie;
+using Microsoft.Boogie.VCExprAST;
+using Microsoft.Boogie.Clustering;
+using Microsoft.Boogie.TypeErasure;
+using Microsoft.Boogie.Simplify;
+
+namespace Microsoft.Boogie.SMTLib
+{
+ public class SMTLibProcessTheoremProver : LogProverInterface
+ {
+ private readonly DeclFreeProverContext! ctx;
+
+ [NotDelayed]
+ public SMTLibProcessTheoremProver(ProverOptions! options, VCExpressionGenerator! gen,
+ DeclFreeProverContext! ctx)
+ {
+ InitializeGlobalInformation("UnivBackPred2.smt");
+
+ this.ctx = ctx;
+
+ 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);
+ base(options, "", "", "", "", gen);
+ }
+
+ public override ProverContext! Context { get {
+ return ctx;
+ } }
+
+ private readonly TypeAxiomBuilder! AxBuilder;
+ private readonly UniqueNamer! Namer;
+ private readonly TypeDeclCollector! DeclCollector;
+
+ private void FeedTypeDeclsToProver() {
+ foreach (string! s in DeclCollector.GetNewDeclarations())
+ AddTypeDecl(s);
+ }
+
+ public override void BeginCheck(string! descriptiveName, VCExpr! vc, ErrorHandler! handler) {
+ TextWriter! output = OpenOutputFile(descriptiveName);
+
+ string! name =
+ MakeBenchmarkNameSafe(SMTLibExprLineariser.MakeIdPrintable(descriptiveName));
+ WriteLineAndLog(output, "(benchmark " + name);
+ WriteLineAndLog(output, _backgroundPredicates);
+
+ if (!AxiomsAreSetup) {
+ AddAxiom(VCExpr2String(ctx.Axioms, -1));
+ AxiomsAreSetup = true;
+ }
+
+ string vcString = ":formula (not " + VCExpr2String(vc, 1) + ")";
+ string! prelude = ctx.GetProverCommands(true);
+ WriteLineAndLog(output, prelude);
+
+ foreach (string! s in TypeDecls) {
+ WriteLineAndLog(output, s);
+ }
+ foreach (string! s in Axioms) {
+ WriteLineAndLog(output, ":assumption");
+ WriteLineAndLog(output, s);
+ }
+
+ WriteLineAndLog(output, vcString);
+ WriteLineAndLog(output, ")");
+
+ output.Close();
+ }
+
+ // certain words that should not occur in the name of a benchmark
+ // because some solvers don't like them
+ private readonly static List<string!>! BadBenchmarkWords = new List<string!> ();
+ static SMTLibProcessTheoremProver() {
+ BadBenchmarkWords.Add("Array"); BadBenchmarkWords.Add("Arrray");
+ }
+
+ private string! MakeBenchmarkNameSafe(string! name) {
+ for (int i = 0; i < BadBenchmarkWords.Count; i = i + 2)
+ name = name.Replace(BadBenchmarkWords[i], BadBenchmarkWords[i+1]);
+ return name;
+ }
+
+ private TextWriter! OpenOutputFile(string! descriptiveName) {
+ string filename = CommandLineOptions.Clo.SMTLibOutputPath;
+ filename = Helpers.SubstituteAtPROC(descriptiveName, (!)filename);
+ return new StreamWriter(filename, false);
+ }
+
+ private void WriteLineAndLog(TextWriter! output, string! msg) {
+ LogActivity(msg);
+ output.WriteLine(msg);
+ }
+
+ [NoDefaultContract]
+ public override Outcome CheckOutcome(ErrorHandler! handler)
+ throws UnexpectedProverOutputException; {
+ return Outcome.Undetermined;
+ }
+
+ protected string! VCExpr2String(VCExpr! expr, int polarity) {
+ DateTime start = DateTime.Now;
+ 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;
+ default:
+ eraser = new TypeEraserPremisses((TypeAxiomBuilderPremisses)AxBuilder, gen);
+ break;
+ }
+ VCExpr! exprWithoutTypes = eraser.Erase(expr, polarity);
+
+ LetBindingSorter! letSorter = new LetBindingSorter(gen);
+ VCExpr! sortedExpr = letSorter.Mutate(exprWithoutTypes, true);
+ VCExpr! sortedAxioms = letSorter.Mutate(AxBuilder.GetNewAxioms(), true);
+
+ DeclCollector.Collect(sortedAxioms);
+ DeclCollector.Collect(sortedExpr);
+ FeedTypeDeclsToProver();
+
+ AddAxiom(SMTLibExprLineariser.ToString(sortedAxioms, Namer));
+ string! res = SMTLibExprLineariser.ToString(sortedExpr, Namer);
+
+ if (CommandLineOptions.Clo.Trace) {
+ DateTime end = DateTime.Now;
+ TimeSpan elapsed = end - start;
+ Console.WriteLine("finished [{0} s] ", elapsed.TotalSeconds);
+ }
+ return res;
+ }
+
+ // the list of all known axioms, where have to be included in each
+ // verification condition
+ private readonly List<string!>! Axioms = new List<string!> ();
+ private bool AxiomsAreSetup = false;
+
+ // similarly, a list of function/predicate declarations
+ private readonly List<string!>! TypeDecls = new List<string!> ();
+
+ protected void AddAxiom(string! axiom) {
+ Axioms.Add(axiom);
+// if (thmProver != null) {
+// LogActivity(":assume " + axiom);
+// thmProver.AddAxioms(axiom);
+// }
+ }
+
+ protected void AddTypeDecl(string! decl) {
+ TypeDecls.Add(decl);
+ // if (thmProver != null) {
+ // LogActivity(decl);
+ // thmProver.Feed(decl, 0);
+ // }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ private static string! _backgroundPredicates;
+
+ static void InitializeGlobalInformation(string! backgroundPred)
+ ensures _backgroundPredicates != null;
+ //throws ProverException, System.IO.FileNotFoundException;
+ {
+ if (_backgroundPredicates == null) {
+ string! codebaseString =
+ (!) Path.GetDirectoryName((!)System.Reflection.Assembly.GetExecutingAssembly().Location);
+
+ // Initialize '_backgroundPredicates'
+ string univBackPredPath = Path.Combine(codebaseString, backgroundPred);
+ using (StreamReader reader = new System.IO.StreamReader(univBackPredPath))
+ {
+ _backgroundPredicates = reader.ReadToEnd();
+ }
+ }
+ }
+ }
+
+ public class Factory : ProverFactory
+ {
+
+ public override object! SpawnProver(ProverOptions! options, object! ctxt)
+ {
+ return this.SpawnProver(options,
+ ((DeclFreeProverContext!)ctxt).ExprGen,
+ (DeclFreeProverContext!)ctxt);
+ }
+
+ public override object! NewProverContext(ProverOptions! options) {
+ if (CommandLineOptions.Clo.BracketIdsInVC < 0) {
+ CommandLineOptions.Clo.BracketIdsInVC = 0;
+ }
+
+ VCExpressionGenerator! gen = new VCExpressionGenerator ();
+ List<string!>! proverCommands = new List<string!> ();
+// TODO: what is supported?
+// proverCommands.Add("all");
+// proverCommands.Add("simplify");
+// proverCommands.Add("simplifyLike");
+ VCGenerationOptions! genOptions = new VCGenerationOptions(proverCommands);
+
+ return new DeclFreeProverContext(gen, genOptions);
+ }
+
+ protected virtual SMTLibProcessTheoremProver! SpawnProver(ProverOptions! options,
+ VCExpressionGenerator! gen,
+ DeclFreeProverContext! ctx) {
+ return new SMTLibProcessTheoremProver(options, gen, ctx);
+ }
+ }
+}
diff --git a/Source/Provers/SMTLib/SMTLib.sscproj b/Source/Provers/SMTLib/SMTLib.sscproj
new file mode 100644
index 00000000..d618b0dd
--- /dev/null
+++ b/Source/Provers/SMTLib/SMTLib.sscproj
@@ -0,0 +1,116 @@
+<?xml version="1.0" encoding="utf-8"?>
+<VisualStudioProject>
+ <XEN ProjectType="Local"
+ SchemaVersion="1.0"
+ Name="SMTLib"
+ ProjectGuid="13c3a68c-462a-4cda-a480-738046e37c5a"
+ >
+ <Build>
+ <Settings ApplicationIcon=""
+ AssemblyName="Provers.SMTLib"
+ OutputType="Library"
+ RootNamespace="Microsoft.Boogie.SMTLib"
+ StartupObject=""
+ StandardLibraryLocation=""
+ TargetPlatform="v2"
+ TargetPlatformLocation=""
+ ShadowedAssembly=""
+ NoStandardLibraries="False"
+ >
+ <Config Name="Debug"
+ AllowUnsafeBlocks="False"
+ BaseAddress="285212672"
+ CheckForOverflowUnderflow="False"
+ ConfigurationOverrideFile=""
+ DefineConstants="DEBUG;TRACE"
+ DocumentationFile=""
+ DebugSymbols="True"
+ FileAlignment="4096"
+ IncrementalBuild="True"
+ Optimize="False"
+ OutputPath="bin\debug"
+ RegisterForComInterop="False"
+ RemoveIntegerChecks="false"
+ TreatWarningsAsErrors="False"
+ WarningLevel="4"
+ CheckContractAdmissibility="True"
+ CheckPurity="False"
+ />
+ <Config Name="Release"
+ AllowUnsafeBlocks="false"
+ BaseAddress="285212672"
+ CheckForOverflowUnderflow="false"
+ ConfigurationOverrideFile=""
+ DefineConstants="TRACE"
+ DocumentationFile=""
+ DebugSymbols="false"
+ FileAlignment="4096"
+ IncrementalBuild="false"
+ Optimize="true"
+ OutputPath="bin\release"
+ RegisterForComInterop="false"
+ RemoveIntegerChecks="false"
+ TreatWarningsAsErrors="false"
+ WarningLevel="4"
+ CheckContractAdmissibility="True"
+ CheckPurity="False"
+ />
+ </Settings>
+ <References>
+ <Reference Name="System"
+ AssemblyName="System"
+ Private="false"
+ />
+ <Reference Name="System.Data"
+ AssemblyName="System.Data"
+ Private="false"
+ />
+ <Reference Name="System.Xml"
+ AssemblyName="System.Xml"
+ Private="false"
+ />
+ <Reference Name="Basetypes"
+ Project="{0C692837-77EC-415F-BF04-395E3ED06E9A}"
+ Private="true"
+ />
+ <Reference Name="Core"
+ Project="{47BC34F1-A173-40BE-84C2-9332B4418387}"
+ Private="true"
+ />
+ <Reference Name="VCExpr"
+ Project="{CF42B700-10AA-4DA9-8992-48A800251C11}"
+ Private="true"
+ />
+ <Reference Name="VCGeneration"
+ Project="{F65666DE-FB56-457C-8782-09BE243450FC}"
+ Private="true"
+ />
+ <Reference Name="Mscorlib.Contracts"
+ AssemblyName="Mscorlib.Contracts"
+ Private="false"
+ HintPath="../../../Binaries/Mscorlib.Contracts.dll"
+ />
+ <Reference Name="Simplify"
+ Project="{F75666DE-FB56-457C-8782-09BE243450FC}"
+ Private="true"
+ />
+ </References>
+ </Build>
+ <Files>
+ <Include>
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="ProverInterface.ssc"
+ />
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="SMTLibLineariser.ssc"
+ />
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="TypeDeclCollector.ssc"
+ />
+ </Include>
+ </Files>
+ </XEN>
+</VisualStudioProject> \ No newline at end of file
diff --git a/Source/Provers/SMTLib/SMTLibLineariser.ssc b/Source/Provers/SMTLib/SMTLibLineariser.ssc
new file mode 100644
index 00000000..cbf69107
--- /dev/null
+++ b/Source/Provers/SMTLib/SMTLibLineariser.ssc
@@ -0,0 +1,635 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using System;
+using System.Text;
+using System.IO;
+using System.Collections;
+using System.Collections.Generic;
+using Microsoft.Contracts;
+using Microsoft.Basetypes;
+using Microsoft.Boogie.VCExprAST;
+
+// Method to turn VCExprs into strings that can be fed into SMT
+// solvers. This is currently quite similar to the
+// SimplifyLikeLineariser (but the code is independent)
+
+namespace Microsoft.Boogie.SMTLib
+{
+
+ // Options for the linearisation
+ public class LineariserOptions {
+
+ public readonly bool AsTerm;
+ public LineariserOptions! SetAsTerm(bool newVal) {
+ if (newVal)
+ return DefaultTerm;
+ else
+ return Default;
+ }
+
+ internal LineariserOptions(bool asTerm) {
+ this.AsTerm = asTerm;
+ }
+
+ public static readonly LineariserOptions! Default = new LineariserOptions (false);
+ internal static readonly LineariserOptions! DefaultTerm = new LineariserOptions (true);
+ }
+
+
+ ////////////////////////////////////////////////////////////////////////////////////////
+
+ // Lineariser for expressions. The result (bool) is currently not used for anything
+ public class SMTLibExprLineariser : IVCExprVisitor<bool, LineariserOptions!> {
+
+ public static string! ToString(VCExpr! e, UniqueNamer! namer) {
+ StringWriter sw = new StringWriter();
+ SMTLibExprLineariser! lin = new SMTLibExprLineariser (sw, namer);
+ lin.Linearise(e, LineariserOptions.Default);
+ return (!)sw.ToString();
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////////////
+
+ private readonly TextWriter! wr;
+ private SMTLibOpLineariser OpLinObject = null;
+ private IVCExprOpVisitor<bool, LineariserOptions!>! OpLineariser { get {
+ if (OpLinObject == null)
+ OpLinObject = new SMTLibOpLineariser (this, wr);
+ return OpLinObject;
+ } }
+
+ internal readonly UniqueNamer! Namer;
+
+ public SMTLibExprLineariser(TextWriter! wr, UniqueNamer! namer) {
+ this.wr = wr;
+ this.Namer = namer;
+ }
+
+ public void Linearise(VCExpr! expr, LineariserOptions! options) {
+ expr.Accept<bool, LineariserOptions!>(this, options);
+ }
+
+ public void LineariseAsTerm(VCExpr! expr, LineariserOptions! options) {
+ Linearise(expr, options.SetAsTerm(true));
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////////
+
+ internal static string! TypeToString(Type! t) {
+ if (t.IsBool)
+ return "TermBool";
+ else if (t.IsInt)
+ return "Int";
+ else if (t.IsBv)
+ assert false; // bitvectors are currently not handled for SMT-Lib solvers
+ else {
+ // at this point, only the types U, T should be left
+ System.IO.StringWriter buffer = new System.IO.StringWriter();
+ using (TokenTextWriter stream = new TokenTextWriter("<buffer>", buffer, false)) {
+ t.Emit(stream);
+ }
+ return "boogie" + buffer.ToString();
+ }
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////////
+
+ public static string! MakeIdPrintable(string! s) {
+ // make sure that no keywords are used as identifiers
+ switch(s) {
+ case andName:
+ case orName:
+ case notName:
+ case impliesName:
+ case iffName:
+ case eqName:
+ case distinctName:
+ case TRUEName:
+ case FALSEName:
+ case "Array":
+ s = "nonkeyword_" + s;
+ break;
+ }
+
+ string! newS = "";
+ foreach (char ch in s) {
+ if (Char.IsLetterOrDigit(ch) || ch == '.' || ch == '\'' || ch == '_')
+ newS = newS + ch;
+ else
+ // replace everything else with a .
+ newS = newS + '.';
+ }
+
+ // ensure that the first character is not . or _ (some SMT-solvers do
+ // not like that, e.g., yices and cvc3)
+ if (newS[0] == '.' || newS[0] == '_')
+ newS = "x" + newS;
+
+ return newS;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////////
+
+ /// <summary>
+ /// The name for logical conjunction in Simplify
+ /// </summary>
+ internal const string! andName = "and"; // conjunction
+ internal const string! orName = "or"; // disjunction
+ internal const string! notName = "not"; // negation
+ internal const string! impliesName = "implies"; // implication
+ internal const string! iffName = "iff"; // logical equivalence
+ internal const string! eqName = "="; // equality
+ internal const string! lessName = "<";
+ internal const string! greaterName = ">";
+ internal const string! atmostName = "<=";
+ internal const string! atleastName = ">=";
+ internal const string! TRUEName = "true"; // nullary predicate that is always true
+ internal const string! FALSEName = "false"; // nullary predicate that is always false
+ internal const string! subtypeName = "UOrdering2";
+ internal const string! subtypeArgsName = "UOrdering3";
+
+ internal const string! distinctName = "distinct";
+
+ internal const string! boolTrueName = "boolTrue";
+ internal const string! boolFalseName = "boolFalse";
+ internal const string! boolAndName = "boolAnd";
+ internal const string! boolOrName = "boolOr";
+ internal const string! boolNotName = "boolNot";
+ internal const string! boolIffName = "boolIff";
+ internal const string! boolImpliesName = "boolImplies";
+ internal const string! termUEqual = "UEqual";
+ internal const string! termTEqual = "TEqual";
+ internal const string! termIntEqual = "IntEqual";
+ internal const string! termLessName = "intLess";
+ internal const string! termGreaterName = "intGreater";
+ internal const string! termAtmostName = "intAtMost";
+ internal const string! termAtleastName = "intAtLeast";
+ internal const string! intAddName = "+";
+ internal const string! intSubName = "-";
+ internal const string! intMulName = "*";
+ internal const string! intDivName = "boogieIntDiv";
+ internal const string! intModName = "boogieIntMod";
+
+ internal void AssertAsTerm(string! x, LineariserOptions! options) {
+ if (!options.AsTerm)
+ System.Diagnostics.Debug.Fail("One should never write " + x + " as a formula!");
+ }
+
+ internal void AssertAsFormula(string! x, LineariserOptions! options) {
+ if (options.AsTerm)
+ System.Diagnostics.Debug.Fail("One should never write " + x + " as a term!");
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////////
+
+ public bool Visit(VCExprLiteral! node, LineariserOptions! options) {
+ if (options.AsTerm) {
+
+ if (node == VCExpressionGenerator.True)
+ wr.Write("{0}", boolTrueName);
+ else if (node == VCExpressionGenerator.False)
+ wr.Write("{0}", boolFalseName);
+ else if (node is VCExprIntLit) {
+ // some SMT-solvers do not understand negative literals
+ // (e.g., yices)
+ BigNum lit = ((VCExprIntLit)node).Val;
+ if (lit.IsNegative)
+ wr.Write("({0} 0 {1})", intSubName, lit.Abs);
+ else
+ wr.Write(lit);
+ } else
+ assert false;
+
+ } else {
+
+ if (node == VCExpressionGenerator.True)
+ wr.Write("{0}", TRUEName);
+ else if (node == VCExpressionGenerator.False)
+ wr.Write("{0}", FALSEName);
+ else if (node is VCExprIntLit) {
+ System.Diagnostics.Debug.Fail("One should never write IntLit as a predicate!");
+ } else
+ assert false;
+
+ }
+
+ return true;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////////
+
+ public bool Visit(VCExprNAry! node, LineariserOptions! options) {
+ VCExprOp! op = node.Op;
+
+ if (!options.AsTerm &&
+ (op.Equals(VCExpressionGenerator.AndOp) ||
+ op.Equals(VCExpressionGenerator.OrOp))) {
+ // handle these operators without recursion
+
+ wr.Write("({0}",
+ op.Equals(VCExpressionGenerator.AndOp) ? andName : orName);
+ IEnumerator! enumerator = new VCExprNAryUniformOpEnumerator (node);
+ while (enumerator.MoveNext()) {
+ VCExprNAry naryExpr = enumerator.Current as VCExprNAry;
+ if (naryExpr == null || !naryExpr.Op.Equals(op)) {
+ wr.Write(" ");
+ Linearise((VCExpr!)enumerator.Current, options);
+ }
+ }
+
+ wr.Write(")");
+
+ return true;
+ }
+
+ return node.Accept<bool, LineariserOptions!>(OpLineariser, options);
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////////
+
+ public bool Visit(VCExprVar! node, LineariserOptions! options) {
+ string! printedName = Namer.GetName(node, MakeIdPrintable(node.Name));
+
+ if (options.AsTerm ||
+ // formula variables are easy to identify in SMT-Lib
+ printedName[0] == '$')
+ wr.Write("{0}", printedName);
+ else
+ wr.Write("({0} {1} {2})", eqName, printedName, boolTrueName);
+
+ return true;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////////
+
+ public bool Visit(VCExprQuantifier! node, LineariserOptions! options) {
+ AssertAsFormula(node.Quan.ToString(), options);
+ assert node.TypeParameters.Count == 0;
+
+ Namer.PushScope(); try {
+
+ string! kind = node.Quan == Quantifier.ALL ? "forall" : "exists";
+ wr.Write("({0} ", kind);
+
+ for (int i = 0; i < node.BoundVars.Count; i++)
+ {
+ VCExprVar! var = node.BoundVars[i];
+ // ensure that the variable name starts with ?
+ string! printedName = Namer.GetLocalName(var, "?" + MakeIdPrintable(var.Name));
+ assert printedName[0] == '?';
+ wr.Write("({0} {1}) ", printedName, TypeToString(var.Type));
+ }
+
+ /* if (options.QuantifierIds) {
+ // only needed for Z3
+ VCQuantifierInfos! infos = node.Infos;
+ if (infos.qid != null) {
+ wr.Write("(QID ");
+ wr.Write(infos.qid);
+ wr.Write(") ");
+ }
+ if (0 <= infos.uniqueId) {
+ wr.Write("(SKOLEMID ");
+ wr.Write(infos.uniqueId);
+ wr.Write(") ");
+ }
+ } */
+
+ Linearise(node.Body, options);
+
+ WriteTriggers(node.Triggers, options);
+ wr.Write(")");
+
+ return true;
+
+ } finally {
+ Namer.PopScope();
+ }
+ }
+
+ private void WriteTriggers(List<VCTrigger!>! triggers, LineariserOptions! options) {
+ // first, count how many neg/pos triggers there are
+ int negTriggers = 0;
+ int posTriggers = 0;
+ foreach (VCTrigger! vcTrig in triggers) {
+ if (vcTrig.Pos) {
+ posTriggers++;
+ } else {
+ negTriggers++;
+ }
+ }
+
+ if (posTriggers > 0) {
+ foreach (VCTrigger! vcTrig in triggers) {
+ if (vcTrig.Pos) {
+ wr.Write(" :pat {");
+ foreach (VCExpr! e in vcTrig.Exprs) {
+ wr.Write(" ");
+ LineariseAsTerm(e, options);
+ }
+ wr.Write(" } ");
+ }
+ }
+ } else if (negTriggers > 0) {
+ // if also positive triggers are given, the SMT solver (at least Z3)
+ // will ignore the negative patterns and output a warning. Therefore
+ // we never specify both negative and positive triggers
+ foreach (VCTrigger! vcTrig in triggers) {
+ if (!vcTrig.Pos) {
+ wr.Write(" :nopat { ");
+ assert vcTrig.Exprs.Count == 1;
+ wr.Write(" ");
+ LineariseAsTerm(vcTrig.Exprs[0], options);
+ wr.Write(" } ");
+ }
+ }
+ }
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////////
+
+ public bool Visit(VCExprLet! node, LineariserOptions! options) {
+ Namer.PushScope(); try {
+
+ foreach (VCExprLetBinding! b in node) {
+ bool formula = b.V.Type.IsBool;
+
+ wr.Write("({0} (", formula ? "flet" : "let");
+ string! printedName = Namer.GetLocalName(b.V, "$" + MakeIdPrintable(b.V.Name));
+ assert printedName[0] == '$';
+
+ wr.Write("{0} ", printedName);
+ Linearise(b.E, options.SetAsTerm(!formula));
+ wr.Write(") ");
+ }
+ Linearise(node.Body, options);
+
+ for (int i = 0; i < node.Length; ++i)
+ wr.Write(")");
+
+ return true;
+
+ } finally {
+ Namer.PopScope();
+ }
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////////
+
+ // Lineariser for operator terms. The result (bool) is currently not used for anything
+ internal class SMTLibOpLineariser : IVCExprOpVisitor<bool, LineariserOptions!> {
+ private readonly SMTLibExprLineariser! ExprLineariser;
+ private readonly TextWriter! wr;
+
+ public SMTLibOpLineariser(SMTLibExprLineariser! ExprLineariser, TextWriter! wr) {
+ this.ExprLineariser = ExprLineariser;
+ this.wr = wr;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////
+
+ private void WriteApplication(string! op, IEnumerable<VCExpr!>! args,
+ LineariserOptions! options,
+ bool argsAsTerms) {
+ WriteApplication(op, op, args, options, argsAsTerms);
+ }
+
+ private void WriteApplication(string! op, IEnumerable<VCExpr!>! args,
+ LineariserOptions! options) {
+ WriteApplication(op, op, args, options, options.AsTerm);
+ }
+
+ private void WriteTermApplication(string! op, IEnumerable<VCExpr!>! args,
+ LineariserOptions! options) {
+ ExprLineariser.AssertAsTerm(op, options);
+ WriteApplication(op, op, args, options, options.AsTerm);
+ }
+
+ private void WriteApplication(string! termOp, string! predOp,
+ IEnumerable<VCExpr!>! args, LineariserOptions! options) {
+ WriteApplication(termOp, predOp, args, options, options.AsTerm);
+ }
+
+ private void WriteApplication(string! termOp, string! predOp,
+ IEnumerable<VCExpr!>! args, LineariserOptions! options,
+ // change the AsTerm option for the arguments?
+ bool argsAsTerms) {
+ string! opName = options.AsTerm ? termOp : predOp;
+ LineariserOptions! newOptions = options.SetAsTerm(argsAsTerms);
+
+ bool hasArgs = false;
+ foreach (VCExpr! e in args) {
+ if (!hasArgs)
+ wr.Write("({0}", opName);
+ wr.Write(" ");
+ ExprLineariser.Linearise(e, newOptions);
+ hasArgs = true;
+ }
+
+ if (hasArgs)
+ wr.Write(")");
+ else
+ wr.Write("{0}", opName);
+ }
+
+ // write an application that can only be a term.
+ // if the expression is supposed to be printed as a formula,
+ // it is turned into an equation (EQ (f args) |@true|)
+ private void WriteApplicationTermOnly(string! termOp,
+ IEnumerable<VCExpr!>! args, LineariserOptions! options) {
+ if (!options.AsTerm)
+ // Write: (EQ (f args) |@true|)
+ // where "args" are written as terms
+ wr.Write("({0} ", eqName);
+
+ WriteApplication(termOp, args, options, true);
+
+ if (!options.AsTerm)
+ wr.Write(" {0})", boolTrueName);
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////
+
+ public bool VisitNotOp (VCExprNAry! node, LineariserOptions! options) {
+ WriteApplication(boolNotName, notName, node, options); // arguments can be both terms and formulas
+ return true;
+ }
+
+ private bool PrintEq(VCExprNAry! node, LineariserOptions! options) {
+ if (options.AsTerm) {
+ // use equality on terms, also if the arguments have type bool
+ assert node[0].Type.Equals(node[1].Type);
+ if (node[0].Type.IsBool) {
+ WriteApplication(boolIffName, node, options);
+ } else if (node[0].Type.IsInt) {
+ WriteApplication(termIntEqual, node, options);
+ } else {
+ // TODO: make this less hackish
+ CtorType t = node[0].Type as CtorType;
+ if (t != null && t.Decl.Name.Equals("U")) {
+ WriteApplication(termUEqual, node, options);
+ } else if (t != null && t.Decl.Name.Equals("T")) {
+ WriteApplication(termTEqual, node, options);
+ } else {
+ assert false; // unknown type
+ }
+ }
+ } else {
+ if (node[0].Type.IsBool) {
+ assert node[1].Type.IsBool;
+ // use equivalence
+ WriteApplication(iffName, node, options);
+ } else {
+ // use equality and write the arguments as terms
+ WriteApplication(eqName, node, options, true);
+ }
+ }
+
+ return true;
+ }
+
+ public bool VisitEqOp (VCExprNAry! node, LineariserOptions! options) {
+ return PrintEq(node, options);
+ }
+
+ public bool VisitNeqOp (VCExprNAry! node, LineariserOptions! options) {
+ wr.Write("({0} ", options.AsTerm ? boolNotName : notName);
+ PrintEq(node, options);
+ wr.Write(")");
+ return true;
+ }
+
+ public bool VisitAndOp (VCExprNAry! node, LineariserOptions! options) {
+ assert options.AsTerm;
+ WriteApplication(boolAndName, andName, node, options);
+ return true;
+ }
+
+ public bool VisitOrOp (VCExprNAry! node, LineariserOptions! options) {
+ assert options.AsTerm;
+ WriteApplication(boolOrName, orName, node, options);
+ return true;
+ }
+
+ public bool VisitImpliesOp (VCExprNAry! node, LineariserOptions! options) {
+ WriteApplication(boolImpliesName, impliesName, node, options);
+ return true;
+ }
+
+ public bool VisitDistinctOp (VCExprNAry! node, LineariserOptions! options) {
+ ExprLineariser.AssertAsFormula(distinctName, options);
+
+ if (node.Length < 2) {
+ ExprLineariser.Linearise(VCExpressionGenerator.True, options);
+ } else {
+ wr.Write("({0}", distinctName);
+ foreach (VCExpr! e in node) {
+ wr.Write(" ");
+ ExprLineariser.LineariseAsTerm(e, options);
+ }
+ wr.Write(")");
+ }
+
+ return true;
+ }
+
+ public bool VisitLabelOp (VCExprNAry! node, LineariserOptions! options) {
+ // VCExprLabelOp! op = (VCExprLabelOp)node.Op;
+ // TODO
+ // wr.Write(String.Format("({0} |{1}| ", op.pos ? "LBLPOS" : "LBLNEG", op.label));
+ ExprLineariser.Linearise(node[0], options);
+ // wr.Write(")");
+ return true;
+ }
+
+ public bool VisitSelectOp (VCExprNAry! node, LineariserOptions! options) {
+ assert false; // should not occur in the output
+ }
+
+ public bool VisitStoreOp (VCExprNAry! node, LineariserOptions! options) {
+ assert false; // should not occur in the output
+ }
+
+ public bool VisitBvOp (VCExprNAry! node, LineariserOptions! options) {
+ assert false; // TODO
+ }
+
+ public bool VisitBvExtractOp(VCExprNAry! node, LineariserOptions! options) {
+ assert false; // TODO
+ }
+
+ public bool VisitBvConcatOp (VCExprNAry! node, LineariserOptions! options) {
+ assert false; // TODO
+ }
+
+ public bool VisitAddOp (VCExprNAry! node, LineariserOptions! options) {
+ WriteTermApplication(intAddName, node, options);
+ return true;
+ }
+
+ public bool VisitSubOp (VCExprNAry! node, LineariserOptions! options) {
+ WriteTermApplication(intSubName, node, options);
+ return true;
+ }
+
+ public bool VisitMulOp (VCExprNAry! node, LineariserOptions! options) {
+ WriteTermApplication(intMulName, node, options);
+ return true;
+ }
+
+ public bool VisitDivOp (VCExprNAry! node, LineariserOptions! options) {
+ WriteTermApplication(intDivName, node, options);
+ return true;
+ }
+
+ public bool VisitModOp (VCExprNAry! node, LineariserOptions! options) {
+ WriteTermApplication(intModName, node, options);
+ return true;
+ }
+
+ public bool VisitLtOp (VCExprNAry! node, LineariserOptions! options) {
+ WriteApplication(termLessName, lessName, node, options, true); // arguments are always terms
+ return true;
+ }
+
+ public bool VisitLeOp (VCExprNAry! node, LineariserOptions! options) {
+ WriteApplication(termAtmostName, atmostName, node, options, true); // arguments are always terms
+ return true;
+ }
+
+ public bool VisitGtOp (VCExprNAry! node, LineariserOptions! options) {
+ WriteApplication(termGreaterName, greaterName, node, options, true); // arguments are always terms
+ return true;
+ }
+
+ public bool VisitGeOp (VCExprNAry! node, LineariserOptions! options) {
+ WriteApplication(termAtleastName, atleastName, node, options, true); // arguments are always terms
+ return true;
+ }
+
+ public bool VisitSubtypeOp (VCExprNAry! node, LineariserOptions! options) {
+ WriteApplication(subtypeName, node, options, true); // arguments are always terms
+ return true;
+ }
+
+ public bool VisitSubtype3Op (VCExprNAry! node, LineariserOptions! options) {
+ WriteApplication(subtypeArgsName, node, options, true); // arguments are always terms
+ return true;
+ }
+
+ public bool VisitBoogieFunctionOp (VCExprNAry! node, LineariserOptions! options) {
+ VCExprBoogieFunctionOp! op = (VCExprBoogieFunctionOp)node.Op;
+ string! printedName = ExprLineariser.Namer.GetName(op.Func, MakeIdPrintable(op.Func.Name));
+
+ // arguments are always terms
+ WriteApplicationTermOnly(printedName, node, options);
+ return true;
+ }
+
+ }
+ }
+
+}
diff --git a/Source/Provers/SMTLib/TypeDeclCollector.ssc b/Source/Provers/SMTLib/TypeDeclCollector.ssc
new file mode 100644
index 00000000..08c0e6a3
--- /dev/null
+++ b/Source/Provers/SMTLib/TypeDeclCollector.ssc
@@ -0,0 +1,107 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics;
+using Microsoft.Contracts;
+using Microsoft.Boogie.VCExprAST;
+
+namespace Microsoft.Boogie.SMTLib
+{
+ // Visitor for collecting the occurring function symbols in a VCExpr,
+ // and for creating the corresponding declarations
+
+ public class TypeDeclCollector : BoundVarTraversingVCExprVisitor<bool, bool> {
+
+ private readonly UniqueNamer! Namer;
+
+ public TypeDeclCollector(UniqueNamer! namer) {
+ this.Namer = namer;
+ }
+
+ // not used
+ protected override bool StandardResult(VCExpr! node, bool arg) {
+ return true;
+ }
+
+ private readonly List<string!>! AllDecls = new List<string!> ();
+ private readonly List<string!>! IncDecls = new List<string!> ();
+
+ private readonly IDictionary<Function!, bool>! KnownFunctions =
+ new Dictionary<Function!, bool> ();
+ private readonly IDictionary<VCExprVar!, bool>! KnownVariables =
+ new Dictionary<VCExprVar!, bool> ();
+
+ public List<string!>! AllDeclarations { get {
+ List<string!>! res = new List<string!> ();
+ res.AddRange(AllDecls);
+ return res;
+ } }
+
+ public List<string!>! GetNewDeclarations() {
+ List<string!>! res = new List<string!> ();
+ res.AddRange(IncDecls);
+ IncDecls.Clear();
+ return res;
+ }
+
+ private void AddDeclaration(string! decl) {
+ AllDecls.Add(decl);
+ IncDecls.Add(decl);
+ }
+
+ public void Collect(VCExpr! expr) {
+ Traverse(expr, true);
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+
+ private static string! TypeToString(Type! t) {
+ return SMTLibExprLineariser.TypeToString(t);
+ }
+
+ public override bool Visit(VCExprNAry! node, bool arg) {
+ // there are a couple of cases where operators have to be
+ // registered by generating appropriate statements
+
+ VCExprBoogieFunctionOp op = node.Op as VCExprBoogieFunctionOp;
+ if (op != null && !KnownFunctions.ContainsKey(op.Func)) {
+ Function! f = op.Func;
+ string! printedName = Namer.GetName(f, SMTLibExprLineariser.MakeIdPrintable(f.Name));
+ string! decl = ":extrafuns ((" + printedName;
+
+ foreach (Variable! v in f.InParams) {
+ decl += " " + TypeToString(v.TypedIdent.Type);
+ }
+ assert f.OutParams.Length == 1;
+ foreach (Variable! v in f.OutParams) {
+ decl += " " + TypeToString(v.TypedIdent.Type);
+ }
+
+ decl += "))";
+
+ AddDeclaration(decl);
+ KnownFunctions.Add(f, true);
+ }
+
+ return base.Visit(node, arg);
+ }
+
+ public override bool Visit(VCExprVar! node, bool arg) {
+ if (!BoundTermVars.Contains(node) && !KnownVariables.ContainsKey(node)) {
+ string! printedName = Namer.GetName(node, SMTLibExprLineariser.MakeIdPrintable(node.Name));
+ string! decl =
+ ":extrafuns ((" + printedName + " " + TypeToString(node.Type) + "))";
+ AddDeclaration(decl);
+ KnownVariables.Add(node, true);
+ }
+
+ return base.Visit(node, arg);
+ }
+ }
+
+} \ No newline at end of file
diff --git a/Source/Provers/Simplify/Let2ImpliesVisitor.ssc b/Source/Provers/Simplify/Let2ImpliesVisitor.ssc
new file mode 100644
index 00000000..8443d950
--- /dev/null
+++ b/Source/Provers/Simplify/Let2ImpliesVisitor.ssc
@@ -0,0 +1,183 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics;
+using Microsoft.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);
+ }
+
+ public VCExpr! Mutate(VCExpr! expr) {
+ 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>();
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ public override VCExpr! Visit(VCExprVar! node,
+ VCExprSubstitution! substitution) {
+ VCExpr! res = base.Visit(node, substitution);
+
+ 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) {
+ // 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);
+ polarity = -polarity;
+ VCExpr! newArg1 = Mutate(node[1], substitution);
+
+ 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) {
+ // first sort the bindings to be able to apply substitutions
+ LetBindingSorter! letSorter = new LetBindingSorter (Gen);
+ VCExpr! newNode = letSorter.Mutate(originalNode, true);
+ 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!> ();
+
+ foreach (VCExprLetBinding! binding in node) {
+ // in all cases we apply the substitution up to this point
+ // to the bound formula
+ VCExpr! newE = Mutate(binding.E, substitution);
+
+ if (binding.V.Type.IsBool) {
+ // a bound formula is handled using an implication; we introduce
+ // a fresh variable to avoid clashes
+ assert polarity > 0;
+
+ VCExprVar! newVar = Gen.Variable(binding.V.Name, Type.Bool);
+ substitution[binding.V] = newVar;
+
+ bindings.Add(Gen.LetBinding(newVar, newE));
+ } else {
+ // a bound term is substituted
+ substitution[binding.V] = newE;
+ }
+ }
+
+ VCExpr! newBody = Mutate(node.Body, substitution);
+
+ // 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) {
+ OccurrenceTypes occ;
+ if (VarOccurrences.TryGetValue(b.V, out occ))
+ assert occ == OccurrenceTypes.None || occ == OccurrenceTypes.Pos;
+ }
+
+ return Gen.Implies(Gen.AsImplications(bindings), newBody);
+
+ } finally {
+ substitution.PopScope();
+ }
+ }
+ }
+
+} \ No newline at end of file
diff --git a/Source/Provers/Simplify/Prover.ssc b/Source/Provers/Simplify/Prover.ssc
new file mode 100644
index 00000000..f89d6a42
--- /dev/null
+++ b/Source/Provers/Simplify/Prover.ssc
@@ -0,0 +1,606 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using System;
+using System.IO;
+using System.Diagnostics;
+using System.Collections;
+using System.Collections.Generic;
+using util;
+using Microsoft.Contracts;
+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>
+ public abstract class ProverProcess
+ {
+ [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
+ requires IsPeerConsistent;
+ modifies this.*;
+ {
+ expose (this) {
+ simplify.Refresh();
+#if WHIDBEY
+ return simplify.PeakVirtualMemorySize64;
+#else
+ return simplify.PeakPagedMemorySize64;
+#endif
+ }
+ }
+ }
+
+ public bool HasExited {
+ get { return simplify.HasExited; }
+ }
+
+ public ProverProcess(ProcessStartInfo! psi, string! proverPath)
+ { // throws ProverException
+ 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.*;
+ {
+ expose (this) {
+ toSimplify.Flush();
+ if (this.simplify != null)
+ {
+ if (!simplify.HasExited)
+ {
+ this.Kill();
+ }
+ simplify.Close();
+ }
+ }
+ }
+
+ [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 static void ReportWarning(string! w)
+ modifies Console.Out.*, Console.Error.*;
+ {
+ switch (CommandLineOptions.Clo.PrintProverWarnings) {
+ case CommandLineOptions.ProverWarnings.None:
+ break;
+ case CommandLineOptions.ProverWarnings.Stdout:
+ Console.WriteLine("Prover warning: " + w);
+ break;
+ case CommandLineOptions.ProverWarnings.Stderr:
+ Console.Error.WriteLine("Prover warning: " + w);
+ break;
+ default:
+ assume false; // unexpected case
+ }
+ }
+
+ public virtual void AddAxioms(string! s)
+ modifies this.*;
+ modifies Console.Out.*, Console.Error.*;
+ throws UnexpectedProverOutputException;
+ {
+ expose (this) {
+ toSimplify.Write("(BG_PUSH ");
+ toSimplify.Write(s);
+ toSimplify.WriteLine(")");
+ }
+ }
+
+ public virtual void Feed(string! s, int statementCount)
+ modifies this.*;
+ modifies Console.Out.*, Console.Error.*;
+ throws UnexpectedProverOutputException;
+ {
+ expose (this) {
+ toSimplify.Write(s);
+ }
+ }
+
+ public virtual void PopAxioms()
+ modifies this.*;
+ modifies Console.Out.*, Console.Error.*;
+ throws UnexpectedProverOutputException;
+ {
+ expose (this) {
+ toSimplify.WriteLine("(BG_POP)");
+ }
+ }
+
+ public void ToFlush()
+ modifies this.*;
+ {
+ expose (this) {
+ toSimplify.Flush();
+ }
+ }
+
+ 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.*;
+ {
+ 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.*;
+ throws UnexpectedProverOutputException;
+
+ 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)
+ {
+ 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"
+ invariant 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 '|'
+ assume j < labels.Length; // there should now be a '+' or '@'
+ ch = labels[j];
+ }
+ assume ch == '+' || ch == '@';
+ j++; // skip the '+' or '@'
+ int k = labels.IndexOfAny(new char[]{'|', ' ', ')'}, j);
+ 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)
+ requires 1 <= s.Length;
+ modifies this.*;
+ throws UnexpectedProverOutputException;
+ {
+ 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)
+ {
+ expose (this) {
+ expectBuffer = new char[len];
+ }
+ }
+ try
+ {
+ string s0;
+ expose (this) {
+ fromSimplify.ReadBlock(expectBuffer, 0, len);
+ s0 = new string(expectBuffer, 0, len);
+ }
+ 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.*;
+ {
+ expose (this) {
+ return fromSimplify.Read();
+ }
+ }
+
+ private void KillProver(object state)
+ {
+ expose (this) {
+ this.readTimedOut = true;
+ simplify.Kill();
+ }
+ }
+
+ protected int FromReadChar(int timeout)
+ requires -1 <= timeout;
+ modifies this.*;
+ {
+ expose (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;
+ }
+ }
+
+ protected string! FromReadLine()
+ modifies this.*;
+ {
+ expose (this) {
+ string s = fromSimplify.ReadLine();
+ if (s == null) {
+ // this is what ReadLine returns if all characters have been read
+ s = "";
+ }
+ return s;
+ }
+ }
+
+ protected string! FromStdErrorAll ()
+ modifies this.*;
+ {
+ expose (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;
+ }
+ // there is no StdErrorReader available
+ else {
+ return "";
+ }
+ }
+ }
+
+ protected void ToWriteLine(string! s)
+ modifies this.*;
+ {
+ expose (this) {
+ toSimplify.WriteLine(s);
+ }
+ }
+ }
+
+ // derived by Z3ProverProcess
+ public class SimplifyProverProcess : ProverProcess {
+ public SimplifyProverProcess(string! proverPath, bool dummy)
+ { // throws ProverException
+ ProcessStartInfo psi = new ProcessStartInfo(proverPath, "-labelsonly");
+ psi.CreateNoWindow = true;
+ psi.UseShellExecute = false;
+ psi.RedirectStandardInput = true;
+ psi.RedirectStandardOutput = true;
+ psi.RedirectStandardError = true;
+ 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();
+ }
+
+ base(psi, proverPath);
+ }
+
+ public override string! OptionComments()
+ {
+ // 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)
+ modifies Console.Out.*, Console.Error.*;
+ throws UnexpectedProverOutputException;
+ {
+ this(proverPath, true);
+ EatPrompt();
+ }
+
+ private void EatPrompt()
+ modifies this.*;
+ modifies Console.Out.*, Console.Error.*;
+ throws UnexpectedProverOutputException;
+ {
+ // 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);
+ }
+
+ Expect(ch, ">\t");
+ }
+
+ public override void AddAxioms(string! s)
+ throws UnexpectedProverOutputException;
+ {
+ //ToWriteLine("(PROMPT_OFF)");
+ base.AddAxioms(s);
+ //ToWriteLine("(PROMPT_ON)");
+ EatPrompt();
+ }
+
+ public override void Feed(string! s, int statementCount)
+ throws UnexpectedProverOutputException;
+ {
+ //ToWriteLine("(PROMPT_OFF)");
+ base.Feed(s, statementCount);
+ //ToWriteLine("(PROMPT_ON)");
+ for (int i = 0; i < statementCount; i++) {
+ EatPrompt();
+ }
+ }
+
+ public override void PopAxioms()
+ throws UnexpectedProverOutputException;
+ {
+ base.PopAxioms();
+ EatPrompt();
+ }
+
+ protected override void DoBeginCheck(string! descriptiveName, string! formula)
+ {
+ //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)
+ throws UnexpectedProverOutputException;
+ {
+ ProverOutcome outcome;
+
+ if (this.simplify == null) {
+ return ProverOutcome.Inconclusive;
+ }
+
+ int ch = FromReadChar();
+ while (ch == 'W')
+ {
+ ch = ConsumeWarnings(ch);
+ }
+ 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.*;
+ throws UnexpectedProverOutputException;
+ {
+ 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)
+ requires ch == 'W';
+ modifies this.*;
+ modifies Console.Out.*, Console.Error.*;
+ throws UnexpectedProverOutputException;
+ {
+ 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)
+ }
+ ReportWarning(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;
+ }
+ }
+
+}
+
diff --git a/Source/Provers/Simplify/ProverInterface.ssc b/Source/Provers/Simplify/ProverInterface.ssc
new file mode 100644
index 00000000..df7f86d6
--- /dev/null
+++ b/Source/Provers/Simplify/ProverInterface.ssc
@@ -0,0 +1,633 @@
+//-----------------------------------------------------------------------------
+//
+// 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 Microsoft.Contracts;
+using Microsoft.Boogie.AbstractInterpretation;
+using Microsoft.Boogie.Simplify;
+using Microsoft.Boogie.VCExprAST;
+using Microsoft.Boogie.TypeErasure;
+
+namespace Microsoft.Boogie.Simplify
+{
+ public abstract class LogProverInterface : ProverInterface
+ {
+ [NotDelayed]
+ protected LogProverInterface(ProverOptions! options,
+ string! openComment, string! closeComment,
+ string! openActivity, string! closeActivity,
+ VCExpressionGenerator! gen)
+ 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;
+ base();
+
+ 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;
+ [Microsoft.Contracts.StrictReadonly]
+ private readonly string! openCommentString;
+ [Microsoft.Contracts.StrictReadonly]
+ private readonly string! closeCommentString;
+ [Microsoft.Contracts.StrictReadonly]
+ private readonly string! openActivityString;
+ [Microsoft.Contracts.StrictReadonly]
+ private readonly string! closeActivityString;
+ [Microsoft.Contracts.StrictReadonly]
+ protected readonly ProverOptions! options;
+ [Microsoft.Contracts.StrictReadonly]
+ private readonly List<string!>/*?*/ commonPrefix;
+
+ public void LogActivity(string! s) {
+ LogActivity(s, false);
+ }
+
+ public void LogCommon(string! s) {
+ LogActivity(s, true);
+ }
+
+ private void LogActivity(string! s, bool common) {
+ 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)
+ {
+ LogComment(comment, false);
+ }
+
+ public void LogCommonComment(string! comment)
+ {
+ LogComment(comment, true);
+ }
+
+ private void LogComment(string! comment, bool common)
+ {
+ 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)
+ {
+ if (commonPrefix != null) {
+ if (logFileWriter != null) {
+ logFileWriter.Close();
+ }
+ logFileWriter = options.OpenLog(descName);
+ if (logFileWriter != null) {
+ foreach (string! s in commonPrefix)
+ logFileWriter.WriteLine(s);
+ }
+ }
+ LogComment("Proof obligation: " + descName);
+ }
+
+ public override void Close() {
+ if (logFileWriter != null) {
+ logFileWriter.Close();
+ logFileWriter = null;
+ }
+ }
+
+ public override VCExpressionGenerator! VCExprGen
+ {
+ get { return this.gen; }
+ }
+ }
+
+ // -----------------------------------------------------------------------------------------------
+ // -----------------------------------------------------------------------------------------------
+ // -----------------------------------------------------------------------------------------------
+
+ public abstract class ProcessTheoremProver : LogProverInterface
+ {
+ private static string! _proverPath;
+
+ protected AxiomVCExprTranslator! vcExprTranslator { get {
+ return (AxiomVCExprTranslator!)ctx.exprTranslator;
+ } }
+
+ protected abstract AxiomVCExprTranslator! SpawnVCExprTranslator();
+
+ protected void FeedNewAxiomsDecls2Prover() throws UnexpectedProverOutputException; {
+ if (thmProver == null)
+ return;
+ foreach (string! s in vcExprTranslator.NewTypeDecls) {
+ LogCommon(s);
+ thmProver.Feed(s, 0);
+ }
+ foreach (string! s in vcExprTranslator.NewAxioms) {
+ LogBgPush(s);
+ thmProver.AddAxioms(s);
+ }
+ }
+
+ protected static string! CodebaseString() {
+ return Path.GetDirectoryName((!)System.Reflection.Assembly.GetExecutingAssembly().Location);
+ }
+
+ private static IDictionary<string!, string!>! BackgroundPredicates =
+ new Dictionary<string!, string!> ();
+
+ protected static string! GetBackgroundPredicate(string! filename) {
+ 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 (!)res;
+ }
+
+ static void InitializeGlobalInformation(string! proverExe)
+ ensures _proverPath != null;
+ //throws ProverException, System.IO.FileNotFoundException;
+ {
+ if (_proverPath == null) {
+ // Initialize '_proverPath'
+ _proverPath = Path.Combine(CodebaseString(), proverExe);
+ if (!File.Exists(_proverPath))
+ {
+ _proverPath = Path.Combine(@"c:\Program Files\Microsoft Research\Z3-2.0\bin", proverExe);
+ }
+ if (!File.Exists(_proverPath))
+ {
+ throw new ProverException("Cannot find executable: " + _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)
+ throws UnexpectedProverOutputException;
+ {
+ BackgroundPredFilename = backgroundPred;
+ InitializeGlobalInformation(proverExe);
+ this.ctx = ctx;
+ base(options, "; ", "", "", "", gen);
+
+ // 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();
+ 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)
+ {
+ vcExprTranslator.AddAxiom( vcExprTranslator.translate(vc,1) );
+ }
+
+ [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) {
+ expose (this) {
+ thmProver.Close();
+ thmProver = null;
+ currentProverHasBeenABadBoy = false;
+ }
+ }
+ base.Close();
+ }
+
+ private UnexpectedProverOutputException proverException;
+
+ public override void BeginCheck(string! descriptiveName, VCExpr! vc, ErrorHandler! handler)
+ {
+ this.NewProblem(descriptiveName);
+ this.proverException = null;
+
+ try {
+ this.ResurrectProver();
+
+ string vcString = vcExprTranslator.translate(vc, 1);
+
+ Helpers.ExtraTraceInformation("Sending data to theorem prover");
+
+ FeedNewAxiomsDecls2Prover();
+ string! prelude = ctx.GetProverCommands(false);
+ vcString = prelude + vcString;
+ LogActivity(vcString);
+
+ assert thmProver != null;
+ thmProver.BeginCheck(descriptiveName, vcString);
+
+ 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)
+ throws UnexpectedProverOutputException;
+ {
+ 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;
+ }
+ }
+
+ assume proverException != null;
+ LogComment("***** Unexpected prover output");
+ expose (this) {
+ currentProverHasBeenABadBoy = true; // this will cause the next resurrect to restart the prover
+ }
+ throw proverException;
+ }
+
+ protected virtual void ResurrectProver()
+ throws UnexpectedProverOutputException;
+ {
+ expose (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++;
+ }
+ FireUpNewProver();
+ }
+ }
+
+ protected abstract ProverProcess! CreateProverProcess(string! proverPath);
+
+ public void LogBgPush(string! s) {
+ LogCommon("(BG_PUSH ");
+ LogCommon(s);
+ LogCommon(")");
+ }
+
+ [NoDefaultContract]
+ private void FireUpNewProver()
+ requires IsExposed;
+ requires thmProver == null;
+ throws UnexpectedProverOutputException;
+ {
+ 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')) {
+ LogCommonComment(s);
+ }
+ foreach (string! parmsetting in thmProver.ParameterSettings) {
+ LogCommon(parmsetting);
+ }
+ }
+ foreach (string! parmsetting in thmProver.ParameterSettings) {
+ thmProver.Feed(parmsetting, 0);
+ }
+ thmProver.Feed(GetBackgroundPredicate(BackgroundPredFilename), 3);
+ string! incProverCommands = ctx.GetProverCommands(false);
+ string! proverCommands = ctx.GetProverCommands(true);
+ string! prelude = ctx.GetProverCommands(false);
+
+ 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));
+ LogCommon(prelude);
+ LogCommon(proverCommands);
+
+ foreach (string! s in vcExprTranslator.AllTypeDecls)
+ LogCommon(s);
+ foreach (string! s in vcExprTranslator.AllAxioms)
+ LogBgPush(s);
+
+ LogCommonComment("Initialized all axioms.");
+ } else {
+ LogCommon(incProverCommands);
+ }
+
+ thmProver.Feed(prelude, 0);
+ thmProver.Feed(proverCommands, 0);
+
+ foreach (string! s in vcExprTranslator.AllTypeDecls)
+ thmProver.Feed(s, 0);
+ foreach (string! s in vcExprTranslator.AllAxioms)
+ 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 { return this.ctx; }
+ }
+ }
+
+ public class SimplifyTheoremProver : ProcessTheoremProver
+ {
+ [NotDelayed]
+ public SimplifyTheoremProver(ProverOptions! options, VCExpressionGenerator! gen, DeclFreeProverContext! ctx)
+ throws UnexpectedProverOutputException;
+ {
+ base(options, gen, ctx, "simplify.exe", "UnivBackPred2.sx");
+ }
+
+ protected override ProverProcess! CreateProverProcess(string! proverPath) {
+ return new SimplifyProverProcess(proverPath);
+ }
+
+ protected override AxiomVCExprTranslator! SpawnVCExprTranslator() {
+ 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) {
+ 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;
+
+ public List<string!>! NewAxioms { get {
+ List<string!>! res = NewAxiomsAttr;
+ NewAxiomsAttr = new List<string!> ();
+ return res;
+ } }
+
+ // 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) {
+ AllAxioms.Add(axiom);
+ NewAxiomsAttr.Add(axiom);
+ }
+
+ public void AddTypeDecl(string! typeDecl) {
+ AllTypeDecls.Add(typeDecl);
+ NewTypeDeclsAttr.Add(typeDecl);
+ }
+ }
+
+ // -----------------------------------------------------------------------------------------------
+ // -----------------------------------------------------------------------------------------------
+ // -----------------------------------------------------------------------------------------------
+
+ public class SimplifyVCExprTranslator : AxiomVCExprTranslator {
+ public SimplifyVCExprTranslator(VCExpressionGenerator! gen) {
+ 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);
+ Gen = tl.Gen;
+ AxBuilder = (TypeAxiomBuilder)tl.AxBuilder.Clone();
+ Namer = (UniqueNamer)tl.Namer.Clone();
+ LitAbstracter = (BigLiteralAbstracter)tl.LitAbstracter.Clone();
+ }
+
+ public override Object! Clone() {
+ return new SimplifyVCExprTranslator(this);
+ }
+
+ private readonly VCExpressionGenerator! Gen;
+ private readonly TypeAxiomBuilder! AxBuilder;
+ private readonly UniqueNamer! Namer;
+ private readonly BigLiteralAbstracter! LitAbstracter;
+
+ public override string! translate(VCExpr! expr, int polarity) {
+ Let2ImpliesMutator! letImplier = new Let2ImpliesMutator (Gen);
+
+ // handle the types in the VCExpr
+ TypeEraser! eraser;
+ switch (CommandLineOptions.Clo.TypeEncodingMethod) {
+ case CommandLineOptions.TypeEncoding.Arguments:
+ eraser = new TypeEraserArguments((TypeAxiomBuilderArguments)AxBuilder, Gen);
+ break;
+ default:
+ eraser = new TypeEraserPremisses((TypeAxiomBuilderPremisses)AxBuilder, Gen);
+ break;
+ }
+ VCExpr! exprWithoutTypes = eraser.Erase(expr, polarity);
+
+ TermFormulaFlattener! flattener = new TermFormulaFlattener (Gen);
+ VCExpr! exprWithLet = flattener.Flatten(exprWithoutTypes);
+ VCExpr! exprWithoutLet = letImplier.Mutate(exprWithLet);
+
+ // big integer literals
+ VCExpr! exprWithoutBigLits = LitAbstracter.Abstract(exprWithoutLet);
+ AddAxiom(SimplifyLikeExprLineariser.ToSimplifyString(LitAbstracter.GetNewAxioms(),
+ Namer));
+
+ // type axioms
+ VCExpr! axiomsWithLet = flattener.Flatten(AxBuilder.GetNewAxioms());
+ VCExpr! axiomsWithoutLet = letImplier.Mutate(axiomsWithLet);
+
+ AddAxiom(SimplifyLikeExprLineariser.ToSimplifyString(axiomsWithoutLet, Namer));
+ return SimplifyLikeExprLineariser.ToSimplifyString(exprWithoutBigLits, Namer);
+ }
+ }
+
+ // -----------------------------------------------------------------------------------------------
+ // -----------------------------------------------------------------------------------------------
+ // -----------------------------------------------------------------------------------------------
+
+ public class Factory : ProverFactory
+ {
+ public override object! SpawnProver(ProverOptions! options, object! ctxt)
+ {
+ return new SimplifyTheoremProver(options,
+ ((DeclFreeProverContext!)ctxt).ExprGen,
+ (DeclFreeProverContext!)ctxt);
+ }
+
+ public override object! NewProverContext(ProverOptions! options) {
+ if (CommandLineOptions.Clo.BracketIdsInVC < 0) {
+ CommandLineOptions.Clo.BracketIdsInVC = 1;
+ }
+ VCExpressionGenerator! gen = new VCExpressionGenerator();
+ List<string!>! proverCommands = new List<string!> ();
+ proverCommands.Add("all");
+ proverCommands.Add("simplify");
+ proverCommands.Add("simplifyLike");
+ 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.sscproj b/Source/Provers/Simplify/Simplify.sscproj
new file mode 100644
index 00000000..675a766b
--- /dev/null
+++ b/Source/Provers/Simplify/Simplify.sscproj
@@ -0,0 +1,135 @@
+<?xml version="1.0" encoding="utf-8"?>
+<VisualStudioProject>
+ <XEN ProjectType="Local"
+ SchemaVersion="1.0"
+ Name="Simplify"
+ ProjectGuid="f75666de-fb56-457c-8782-09be243450fc"
+ >
+ <Build>
+ <Settings ApplicationIcon=""
+ AssemblyName="Provers.Simplify"
+ OutputType="Library"
+ RootNamespace="Microsoft.Boogie.Simplify"
+ StartupObject=""
+ StandardLibraryLocation=""
+ TargetPlatform="v2"
+ TargetPlatformLocation=""
+ ShadowedAssembly=""
+ NoStandardLibraries="False"
+ >
+ <Config Name="Debug"
+ AllowUnsafeBlocks="False"
+ BaseAddress="285212672"
+ CheckForOverflowUnderflow="False"
+ ConfigurationOverrideFile=""
+ DefineConstants="DEBUG;TRACE"
+ DocumentationFile=""
+ DebugSymbols="True"
+ FileAlignment="4096"
+ IncrementalBuild="True"
+ Optimize="False"
+ OutputPath="bin\debug"
+ RegisterForComInterop="False"
+ RemoveIntegerChecks="false"
+ TreatWarningsAsErrors="False"
+ WarningLevel="4"
+ ReferenceTypesAreNonNullByDefault="False"
+ RunProgramVerifier="False"
+ RunProgramVerifierWhileEditing="False"
+ ProgramVerifierCommandLineOptions=""
+ AllowPointersToManagedStructures="False"
+ CheckContractAdmissibility="True"
+ CheckPurity="False"
+ />
+ <Config Name="Release"
+ AllowUnsafeBlocks="false"
+ BaseAddress="285212672"
+ CheckForOverflowUnderflow="false"
+ ConfigurationOverrideFile=""
+ DefineConstants="TRACE"
+ DocumentationFile=""
+ DebugSymbols="false"
+ FileAlignment="4096"
+ IncrementalBuild="false"
+ Optimize="true"
+ OutputPath="bin\release"
+ RegisterForComInterop="false"
+ RemoveIntegerChecks="false"
+ TreatWarningsAsErrors="false"
+ WarningLevel="4"
+ />
+ </Settings>
+ <References>
+ <Reference Name="System"
+ AssemblyName="System"
+ Private="false"
+ />
+ <Reference Name="System.Data"
+ AssemblyName="System.Data"
+ Private="false"
+ />
+ <Reference Name="System.Xml"
+ AssemblyName="System.Xml"
+ Private="false"
+ />
+ <Reference Name="Core"
+ Project="{47BC34F1-A173-40BE-84C2-9332B4418387}"
+ Private="true"
+ />
+ <Reference Name="AIFramework"
+ Project="{24B55172-AD8B-47D1-8952-5A95CFDB9B31}"
+ Private="true"
+ />
+ <Reference Name="Graph"
+ Project="{4C28FB90-630E-4B55-A937-11A011B79765}"
+ Private="true"
+ />
+ <Reference Name="Mscorlib.Contracts"
+ AssemblyName="Mscorlib.Contracts"
+ Private="false"
+ HintPath="../../../Binaries/Mscorlib.Contracts.dll"
+ />
+ <Reference Name="System.Contracts"
+ AssemblyName="System.Contracts"
+ Private="false"
+ HintPath="../../../Binaries/System.Contracts.dll"
+ />
+ <Reference Name="VCGeneration"
+ Project="{F65666DE-FB56-457C-8782-09BE243450FC}"
+ Private="true"
+ />
+ <Reference Name="Basetypes"
+ Project="{0C692837-77EC-415F-BF04-395E3ED06E9A}"
+ Private="true"
+ />
+ <Reference Name="VCExpr"
+ Project="{CF42B700-10AA-4DA9-8992-48A800251C11}"
+ Private="true"
+ />
+ </References>
+ </Build>
+ <Files>
+ <Include>
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="Prover.ssc"
+ />
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="ProverInterface.ssc"
+ />
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="..\..\version.ssc"
+ />
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="Let2ImpliesVisitor.ssc"
+ />
+ </Include>
+ </Files>
+ <Target Name="AfterBuild"
+ >
+ </Target>
+ </XEN>
+</VisualStudioProject> \ No newline at end of file
diff --git a/Source/Provers/Z3/Inspector.ssc b/Source/Provers/Z3/Inspector.ssc
new file mode 100644
index 00000000..ca7fc084
--- /dev/null
+++ b/Source/Provers/Z3/Inspector.ssc
@@ -0,0 +1,130 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using System;
+using System.IO;
+using System.Diagnostics;
+using System.Collections;
+using System.Collections.Generic;
+using util;
+using Microsoft.Contracts;
+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 Dictionary<string!,bool>! Labels = new Dictionary<string!,bool>();
+
+ public static Dictionary<string!,bool>! FindLabels(VCExpr! expr) {
+ FindLabelsVisitor! visitor = new FindLabelsVisitor();
+ visitor.Traverse(expr, true);
+ return visitor.Labels;
+ }
+
+ protected override bool StandardResult(VCExpr! node, bool arg) {
+ VCExprNAry nary = node as VCExprNAry;
+ if (nary != null) {
+ VCExprLabelOp lab = nary.Op as VCExprLabelOp;
+ if (lab != null) {
+ Labels[lab.label] = lab.pos;
+ }
+ }
+ return true;
+ }
+ }
+
+ internal class Inspector {
+ [Rep] protected readonly Process! inspector;
+ [Rep] readonly TextReader! fromInspector;
+ [Rep] readonly TextWriter! toInspector;
+
+ public Inspector(Z3InstanceOptions! opts)
+ {
+ ProcessStartInfo! psi = new ProcessStartInfo(opts.Inspector);
+ 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)
+ {
+ Dictionary<string!,bool>! labels = FindLabelsVisitor.FindLabels(vc);
+ toInspector.WriteLine("PROBLEM " + descriptiveName);
+ toInspector.WriteLine("TOKEN BEGIN");
+ foreach (string! lab in labels.Keys) {
+ 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
+ if (!val.Contains(" ")) val = null;
+
+ 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 {
+ assume false;
+ }
+ if (val == null) { val = ""; }
+
+ if (absy is LoopInitAssertCmd) {
+ val += " (loop entry)";
+ } else if (absy is LoopInvMaintainedAssertCmd) {
+ val += " (loop body)";
+ } else if (absy is AssertRequiresCmd && val == "") {
+ AssertRequiresCmd req = (AssertRequiresCmd)absy;
+ IToken t2 = req.Requires.tok;
+ val = string.Format("precondition {0}({1},{2})", t2.filename, t2.line, t2.col);
+ }
+
+ 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)
+ {
+ toInspector.WriteLine(line);
+ toInspector.Flush();
+ }
+ }
+}
diff --git a/Source/Provers/Z3/Prover.ssc b/Source/Provers/Z3/Prover.ssc
new file mode 100644
index 00000000..d3212a9c
--- /dev/null
+++ b/Source/Provers/Z3/Prover.ssc
@@ -0,0 +1,870 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using System;
+using System.IO;
+using System.Diagnostics;
+using System.Collections;
+using System.Collections.Generic;
+using System.Text;
+using util;
+using Microsoft.Contracts;
+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;
+
+ private string! cmdLineArgs = "";
+ class OptionValue {
+ public readonly string! Option;
+ public readonly string! Value;
+ public OptionValue(string! option, string! value) { Option = option; Value = value; }
+ }
+ static void AddOption(List<OptionValue!>! parms, string! option, string! value)
+ modifies parms.*;
+ {
+ OptionValue ov = new OptionValue(option, value);
+ Owner.AssignSame(ov, Owner.ElementProxy(parms));
+ parms.Add(ov);
+ }
+ private List<OptionValue!>! parameterSettings;
+
+ // [NotDelayed]
+ [Captured]
+ public Z3ProverProcess(Z3InstanceOptions! opts, Inspector? inspector)
+ requires inspector != null ==> Owner.Same(opts, inspector);
+ { // throws ProverException
+ string! z3args = OptionChar() + "si";
+ List<OptionValue!> parms = new List<OptionValue!>();
+
+ if (opts.V2) {
+ AddOption(parms, "MODEL_PARTIAL", "true");
+ AddOption(parms, "MODEL_VALUE_COMPLETION", "false");
+ AddOption(parms, "MODEL_HIDE_UNUSED_PARTITIONS", "false");
+ AddOption(parms, "MODEL_V1", "true");
+ AddOption(parms, "ASYNC_COMMANDS", "false");
+ } else {
+ AddOption(parms, "PARTIAL_MODELS", "true");
+ AddOption(parms, "MODEL_VALUE_COMPLETION", "false");
+ AddOption(parms, "HIDE_UNUSED_PARTITIONS", "false");
+ }
+
+ if (opts.V2) {
+ // 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(parms, "PHASE_SELECTION", "0");
+ AddOption(parms, "RESTART_STRATEGY", "0");
+ AddOption(parms, "RESTART_FACTOR", "|1.5|");
+
+ // 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(parms, "NNF_SK_HACK", "true");
+
+ // More or less like MAM=0.
+ AddOption(parms, "QI_EAGER_THRESHOLD", "100");
+
+ // Make the integer model more diverse by default, speeds up some benchmarks a lot.
+ AddOption(parms, "ARITH_RANDOM_INITIAL_VALUE", "true");
+
+ // The left-to-right structural case-splitting strategy.
+ AddOption(parms, "SORT_AND_OR", "false");
+ AddOption(parms, "CASE_SPLIT", "3");
+
+ // In addition delay adding unit conflicts.
+ AddOption(parms, "DELAY_UNITS", "true");
+ AddOption(parms, "DELAY_UNITS_THRESHOLD", "16");
+
+ if (opts.Inspector != null) {
+ AddOption(parms, "PROGRESS_SAMPLING_FREQ", "100");
+ }
+ } else {
+ z3args += " " + OptionChar() + "mam:" + CommandLineOptions.Clo.Z3mam;
+ }
+
+ if (0 <= CommandLineOptions.Clo.ProverCCLimit) {
+ z3args += " " + OptionChar() + "@ " +
+ OptionChar() + "cex:" + CommandLineOptions.Clo.ProverCCLimit;
+ }
+ if (0 <= opts.Timeout) {
+ z3args += " " + OptionChar() + "t:" + opts.Timeout;
+ }
+ if (opts.Typed) {
+ AddOption(parms, "TYPE_CHECK", "true");
+ if (opts.BitVectors == CommandLineOptions.BvHandling.Z3Native) {
+ if (opts.V2) {
+ AddOption(parms, "BV_REFLECT", "true");
+ } else {
+ AddOption(parms, "REFLECT_BV_OPS", "true");
+ }
+ }
+ }
+ if (CommandLineOptions.Clo.PrintErrorModel >= 1 || CommandLineOptions.Clo.EnhancedErrorMessages == 1 || CommandLineOptions.Clo.ContractInfer) {
+ z3args += " " + OptionChar() + "m";
+ expectingModel = true;
+ }
+ // Z3 version 1.3 does not support SETPARAMETER in the input, so we tack on the OPTION=value pairs to z3args
+ if (opts.V1) {
+ foreach (OptionValue opt in parms) {
+ z3args += string.Format(" \"{0}={1}\"", opt.Option, opt.Value);
+ }
+ }
+
+ foreach (string! opt in CommandLineOptions.Clo.Z3Options) {
+ 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(parms, opt.Substring(0, eq), opt.Substring(eq + 1));
+ }
+ z3args += " \"" + opt + "\"";
+ }
+
+
+ cmdLineArgs = z3args;
+ parameterSettings = parms;
+
+ string exePath = opts.ExeName;
+ if (!File.Exists(exePath)){
+ exePath = @"c:\Program Files\Microsoft Research\Z3-2.0\bin";
+ }
+
+ ProcessStartInfo! psi = new ProcessStartInfo(exePath, z3args);
+ psi.CreateNoWindow = true;
+ psi.UseShellExecute = false;
+ psi.RedirectStandardInput = true;
+ psi.RedirectStandardOutput = true;
+ psi.RedirectStandardError = true;
+
+ base(psi, opts.ExeName);
+
+ Owner.AssignSame(this, opts);
+ this.opts = opts;
+ this.inspector = inspector;
+ }
+
+ public override string! OptionComments()
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.AppendFormat("Z3 command line: {0} {1}\nUser supplied Z3 options:",
+ opts.ExeName, cmdLineArgs);
+ assume CommandLineOptions.Clo.IsPeerConsistent;
+ foreach (string! opt in CommandLineOptions.Clo.Z3Options) {
+ sb.Append(" ").Append(opt);
+ }
+ sb.AppendFormat("\nProver options: {0}\n", opts.ToString());
+ return sb.ToString();
+ }
+
+ [Pure(false)]
+ public override IEnumerable<string!>! ParameterSettings {
+ get {
+ if (opts.V2) {
+ 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() {
+ assume Environment.OSVersion != null;
+ switch (Environment.OSVersion.Platform) {
+ case PlatformID.Unix:
+ return "-";
+ default:
+ return "/";
+ }
+ }
+
+ protected override void DoBeginCheck(string! descriptiveName, string! formula)
+ {
+ 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)
+ {
+ Console.WriteLine("Z3: " + msg);
+ }
+
+ public override ProverOutcome CheckOutcome(Microsoft.Boogie.ProverInterface.ErrorHandler! handler)
+ throws UnexpectedProverOutputException;
+ {
+ 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;
+ }
+
+ 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);
+ ReportWarning(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')
+ invariant 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("Invalid")) {
+ isInvalid = true;
+ continue;
+ }
+ }
+
+ if (isInvalid && line == ".") {
+ return ProverOutcome.NotValid;
+ }
+
+ if (isInvalid && line.StartsWith("labels: (")) {
+ List<string!>! l = ParseLabels(line);
+ 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 .
+ 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.*;
+ ensures result == "." || result.StartsWith("labels: (") || result == "END_OF_MODEL";
+ throws UnexpectedProverOutputException;
+ {
+ //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>();
+ Owner.AssignSame(Owner.ElementProxy(partitionToValue), 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!>();
+ Owner.AssignSame(emptyList, 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)
+ requires Owner.Same(Owner.ElementProxy(partitionToValue), Owner.ElementProxy(valueToPartition));
+ modifies this.*, identifierToPartition.*, partitionToIdentifiers.*, partitionToValue.*, 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);
+ assume false;
+ }
+ }
+
+ int j = ParseModelZidAndIdentifiers(zID, s, identifierToPartition, partitionToIdentifiers);
+
+ j = s.IndexOf(" -> ", j);
+ if (0 <= j) {
+ j += 4;
+ }
+ 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) {
+ 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;
+ 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;
+ Owner.AssignSame(boxedFalse, Owner.ElementProxy(partitionToValue));
+ partitionToValue.Add(boxedFalse);
+ 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 {
+ 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);
+ assume Owner.None(boxedN);
+ Owner.AssignSame(boxedN, Owner.ElementProxy(partitionToValue));
+ partitionToValue.Add(boxedN);
+ 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);
+ Owner.AssignSame(bitV, Owner.ElementProxy(partitionToValue));
+ partitionToValue.Add(bitV);
+ 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);
+ assume false;
+ }
+
+ }
+ }
+
+ private static int ParseModelZidAndIdentifiers(int zID, string! s,
+ Dictionary<string!, int>! identifierToPartition,
+ List<List<string!>>! partitionToIdentifiers)
+ modifies identifierToPartition.*, partitionToIdentifiers.*;
+ ensures 0 <= result && result <= s.Length;
+ {
+ List<string!> identifiers = new List<string!>();
+ int j = s.IndexOf('{', 0) + 1; // skip the '{', if present, and set j to 0 otherwise
+ if (1 <= j) {
+ // There is a list of ID's.
+ assume j < s.Length; // there should be more characters; the ending '}', for one
+ //ID*
+ while (true)
+ invariant identifiers.IsPeerConsistent && identifierToPartition.IsPeerConsistent && partitionToIdentifiers.IsPeerConsistent;
+ invariant 0 <= j && j < s.Length;
+ {
+ int k = s.IndexOfAny(new char[]{' ', '}'}, j);
+ assume j <= k;
+ string id = s.Substring(j, k-j);
+ j = k+1;
+ 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;
+ }
+ assume j < s.Length; // there should be more characters; the ending '}', for one
+ }//end ID*
+ }
+ Owner.AssignSame(identifiers, 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.*;
+ ensures result == "." || result.StartsWith("labels: (") || result == "END_OF_MODEL";
+ throws UnexpectedProverOutputException;
+ {
+ // 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);
+ assume 0 <= j;
+ string id = s.Substring(0, j);
+ // id is stored into definedFunctions once the function definition for it has
+ // been completely parsed,
+
+ // 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)
+ invariant 0 <= j && j <= s.Length;
+ {
+ j = s.IndexOfAny(new Char[]{'*', '-'}, j);
+ // true because this always ends with a "->":
+ 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:
+ assume j < s.Length;
+ int k = s.IndexOf(' ', j);
+ // by input string format:
+ 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:
+ 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:
+ 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
+ Owner.AssignSame(argumentsAndResult, 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
+ 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)
+ {
+ this.partitionNames = new string?[partitionToIdentifiers.Count];
+ this.prevPartitionNames = new string?[partitionToIdentifiers.Count];
+ }
+
+ private string?[]! partitionNames;
+ private string?[]! prevPartitionNames;
+
+ 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)
+ {
+ 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)
+ {
+ 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];
+
+ // 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! name in pti)
+ possible_names.Add(name);
+ }
+
+ // Then also look for functions,
+ // and then collect possible functional definitions
+ foreach (KeyValuePair<string!, List<List<int>>!> kv in definedFunctions) {
+ 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)
+ if (NameBadness(s) < NameBadness(best)) best = s;
+ if (best.Length < 120)
+ partitionNames[pos] = best;
+ }
+ }
+
+ return (!)partitionNames[pos];
+ }
+
+ private void PrintReadableModel (TextWriter! writer) {
+ writer.WriteLine("Z3 error model: ");
+ SetNames();
+ writer.WriteLine("partitions:");
+ 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];
+ 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) {
+ if (definedFunctions[name].Count == 1) continue; // skip functions with only the else-> clause
+ foreach (List<int>! parms in definedFunctions[name]) {
+ 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) {
+ if (CommandLineOptions.Clo.PrintErrorModel == 4) {
+ PrintReadableModel(writer);
+ return;
+ }
+
+ writer.WriteLine("Z3 error model: ");
+
+ writer.WriteLine("partitions:");
+ assert partitionToIdentifiers.Count == partitionToValue.Count;
+ for (int i = 0; i < partitionToIdentifiers.Count; i++){
+ writer.Write("*"+i);
+ List<string!> pti = partitionToIdentifiers[i];
+ if (pti != null && pti.Count != 0) {
+ 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("}");
+ }
+ // temp object needed for non-null checking
+ object tempPTVI = partitionToValue[i];
+ if (tempPTVI != null) {
+ if (tempPTVI.ToString() == "True") {
+ writer.Write(" -> " + "true" + "");
+ } else if (tempPTVI.ToString() == "False") {
+ writer.Write(" -> " + "false" + "");
+ } else if (tempPTVI is BigNum) {
+ writer.Write(" -> " + tempPTVI + ":int");
+ } else {
+ writer.Write(" -> " + tempPTVI + "");
+ }
+ } else {
+ writer.Write(" ");
+ }
+ writer.WriteLine();
+ }
+
+ writer.WriteLine("function interpretations:");
+ foreach (KeyValuePair<string!, List<List<int>>!> kvp in definedFunctions) {
+ writer.WriteLine(kvp.Key + " -> {");
+ List<List<int>> kvpValue = kvp.Value;
+ if (kvpValue != null) {
+ foreach(List<int> l in kvpValue) {
+ writer.Write(" ");
+ if (l != null) {
+ for (int i = 0; i < l.Count - 1; i++) {
+ writer.Write("*"+l[i] + " ");
+ }
+ if (l.Count == 1) {
+ writer.WriteLine("else -> #unspecified");
+ } else {
+ writer.WriteLine("-> "+ "*" + l[l.Count - 1]);
+ }
+ }
+ }
+ }
+ writer.WriteLine("}");
+ }
+ writer.WriteLine("END_OF_MODEL");
+ writer.WriteLine(".");
+
+ if (CommandLineOptions.Clo.PrintErrorModel >= 2) {
+ writer.WriteLine("identifierToPartition:");
+ foreach (KeyValuePair<string!, int> kvp in identifierToPartition) {
+ writer.WriteLine(kvp.Key + " : " + "*" + kvp.Value);
+ }
+
+ writer.WriteLine("valueToPartition:");
+ foreach (KeyValuePair<object, int> kvp in valueToPartition) {
+ writer.WriteLine(kvp.Key + " : " + "*" + kvp.Value);
+ }
+ writer.WriteLine("End of model.");
+ }
+ }
+ }
+
+
+}
+
+
diff --git a/Source/Provers/Z3/ProverInterface.ssc b/Source/Provers/Z3/ProverInterface.ssc
new file mode 100644
index 00000000..02b4f505
--- /dev/null
+++ b/Source/Provers/Z3/ProverInterface.ssc
@@ -0,0 +1,320 @@
+//-----------------------------------------------------------------------------
+//
+// 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 Microsoft.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;
+
+ [NotDelayed]
+ public Z3ProcessTheoremProver(VCExpressionGenerator! gen,
+ DeclFreeProverContext! ctx, Z3InstanceOptions! opts)
+ throws UnexpectedProverOutputException;
+ {
+ this.opts = opts;
+ string! backPred = opts.Typed ? "TypedUnivBackPred2.sx" : "UnivBackPred2.sx";
+ base(opts, gen, ctx, opts.ExeName, backPred);
+ }
+
+ private void FireUpInspector()
+ {
+ if (inspector == null && opts.Inspector != null) {
+ inspector = new Inspector(opts);
+ }
+ }
+
+ protected override Microsoft.Boogie.Simplify.ProverProcess! CreateProverProcess(string! proverPath) {
+ opts.ExeName = proverPath;
+ FireUpInspector();
+ if (inspector != null) {
+ inspector.NewProver();
+ }
+ return new Z3ProverProcess(opts, inspector);
+ }
+
+ protected override AxiomVCExprTranslator! SpawnVCExprTranslator() {
+ return new Z3VCExprTranslator(gen, opts);
+ }
+
+ public override void BeginCheck(string! descriptiveName, VCExpr! vc, ErrorHandler! handler)
+ {
+ 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 bool Typed {
+ get {
+ return CommandLineOptions.Clo.Z3types || BitVectors == CommandLineOptions.BvHandling.Z3Native;
+ }
+ }
+ public bool V1 = false;
+ public bool V2 = false; // default set in PostParse
+ public bool DistZ3 = false;
+ public string! ExeName = "z3.exe";
+ public bool InverseImplies = false;
+ public string? Inspector = null;
+
+ protected override bool Parse(string! opt)
+ {
+ return ParseBool(opt, "V1", ref V1) ||
+ ParseBool(opt, "V2", ref V2) ||
+ ParseBool(opt, "REVERSE_IMPLIES", ref InverseImplies) ||
+ ParseString(opt, "INSPECTOR", ref Inspector) ||
+ ParseBool(opt, "DIST", ref DistZ3) ||
+ base.Parse(opt);
+ }
+
+ protected override void PostParse()
+ {
+ base.PostParse();
+
+ if (!V1 && !V2) {
+ V2 = true; // default
+ } else if (V1 && V2) {
+ ReportError("V1 and V2 requested at the same time");
+ } else if (V1 && DistZ3) {
+ ReportError("V1 and DistZ3 requested at the same time");
+ }
+ if (V1) {
+ ExeName = "z3-v1.3.exe";
+ }
+ if (DistZ3) {
+ ExeName = "z3-dist.exe";
+ CommandLineOptions.Clo.RestartProverPerVC = true;
+ }
+
+ }
+ }
+
+ internal class Z3LineariserOptions : LineariserOptions {
+ private readonly Z3InstanceOptions! opts;
+
+ public override CommandLineOptions.BvHandling Bitvectors { get {
+ return opts.BitVectors;
+ } }
+
+ internal Z3LineariserOptions(bool asTerm, Z3InstanceOptions !opts, List<VCExprVar!>! letVariables) {
+ base(asTerm);
+ this.opts = opts;
+ this.LetVariablesAttr = letVariables;
+ }
+
+ public override bool UseWeights { get {
+ return opts.V2;
+ } }
+
+ public override bool UseTypes { get {
+ return opts.Typed;
+ } }
+
+ public override bool QuantifierIds { get {
+ return true;
+ } }
+
+ public override bool InverseImplies { get {
+ return opts.InverseImplies;
+ } }
+
+ public override LineariserOptions! SetAsTerm(bool newVal) {
+ 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 {
+ return LetVariablesAttr;
+ } }
+
+ public override LineariserOptions! AddLetVariable(VCExprVar! furtherVar) {
+ List<VCExprVar!>! allVars = new List<VCExprVar!> ();
+ allVars.AddRange(LetVariables);
+ allVars.Add(furtherVar);
+ return new Z3LineariserOptions(AsTerm, opts, allVars);
+ }
+ }
+
+ // -----------------------------------------------------------------------------------------------
+ // -----------------------------------------------------------------------------------------------
+ // -----------------------------------------------------------------------------------------------
+
+ public class Z3VCExprTranslator : AxiomVCExprTranslator {
+ public Z3VCExprTranslator(VCExpressionGenerator! gen, Z3InstanceOptions! opts) {
+ 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, opts.BitVectors == CommandLineOptions.BvHandling.Z3Native);
+ }
+
+ private Z3VCExprTranslator(Z3VCExprTranslator! tl) {
+ base(tl);
+ 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() {
+ return new Z3VCExprTranslator(this);
+ }
+
+ private readonly Z3InstanceOptions! Opts;
+ private readonly VCExpressionGenerator! Gen;
+ private readonly TypeAxiomBuilder! AxBuilder;
+ private readonly UniqueNamer! Namer;
+ private readonly TypeDeclCollector! DeclCollector;
+
+ public override string! translate(VCExpr! expr, int polarity) {
+ DateTime start = DateTime.Now;
+ 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;
+
+ LetBindingSorter! letSorter = new LetBindingSorter(Gen);
+ VCExpr! sortedExpr = letSorter.Mutate(exprWithoutTypes, true);
+ VCExpr! sortedAxioms = letSorter.Mutate(AxBuilder.GetNewAxioms(), true);
+
+ if (Opts.Typed) {
+ DeclCollector.Collect(sortedAxioms);
+ DeclCollector.Collect(sortedExpr);
+ FeedTypeDeclsToProver();
+ } else {
+ TermFormulaFlattener! flattener = new TermFormulaFlattener (Gen);
+ sortedExpr = flattener.Flatten(sortedExpr);
+ sortedAxioms = flattener.Flatten(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);
+
+ if (CommandLineOptions.Clo.Trace) {
+ TimeSpan elapsed = DateTime.Now - start;
+ Console.WriteLine("finished [{0} s] ", elapsed.TotalSeconds);
+ }
+ return res;
+ }
+
+ private void FeedTypeDeclsToProver() {
+ foreach (string! s in DeclCollector.GetNewDeclarations())
+ AddTypeDecl(s);
+ }
+ }
+
+ // -----------------------------------------------------------------------------------------------
+ // -----------------------------------------------------------------------------------------------
+ // -----------------------------------------------------------------------------------------------
+
+ public class Factory : ProverFactory
+ {
+
+ public override object! SpawnProver(ProverOptions! popts, object! ctxt)
+ {
+ Z3InstanceOptions opts = (Z3InstanceOptions!)popts;
+ return this.SpawnProver(((DeclFreeProverContext!)ctxt).ExprGen,
+ (DeclFreeProverContext!)ctxt,
+ opts);
+ }
+
+ public override object! NewProverContext(ProverOptions! options) {
+ if (CommandLineOptions.Clo.BracketIdsInVC < 0) {
+ CommandLineOptions.Clo.BracketIdsInVC = 0;
+ }
+
+ Z3InstanceOptions opts = (Z3InstanceOptions!)options;
+ VCExpressionGenerator! gen = new VCExpressionGenerator ();
+ List<string!>! proverCommands = new List<string!> ();
+ proverCommands.Add("all");
+ proverCommands.Add("z3");
+ proverCommands.Add("simplifyLike");
+ if (opts.BitVectors == CommandLineOptions.BvHandling.Z3Native)
+ proverCommands.Add("bvDefSem");
+ if (opts.BitVectors == CommandLineOptions.BvHandling.ToInt)
+ proverCommands.Add("bvInt");
+ VCGenerationOptions! genOptions = new VCGenerationOptions(proverCommands);
+
+ return new DeclFreeProverContext(gen, genOptions);
+ }
+
+ public override ProverOptions! BlankProverOptions()
+ {
+ return new Z3InstanceOptions();
+ }
+
+ protected virtual Z3ProcessTheoremProver! SpawnProver(VCExpressionGenerator! gen,
+ DeclFreeProverContext! ctx,
+ Z3InstanceOptions! opts) {
+ return new Z3ProcessTheoremProver(gen, ctx, opts);
+ }
+ }
+}
diff --git a/Source/Provers/Z3/TypeDeclCollector.ssc b/Source/Provers/Z3/TypeDeclCollector.ssc
new file mode 100644
index 00000000..86307b45
--- /dev/null
+++ b/Source/Provers/Z3/TypeDeclCollector.ssc
@@ -0,0 +1,212 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics;
+using Microsoft.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;
+
+ private readonly bool NativeBv;
+
+ public TypeDeclCollector(UniqueNamer! namer, bool nativeBv) {
+ this.Namer = namer;
+ this.NativeBv = nativeBv;
+ AllDecls = new List<string!> ();
+ IncDecls = new List<string!> ();
+ KnownFunctions = new Dictionary<Function!, bool> ();
+ KnownVariables = new Dictionary<VCExprVar!, bool> ();
+ KnownTypes = new Dictionary<Type!, bool> ();
+ KnownBvOps = new Dictionary<string!, bool> ();
+ }
+
+ internal TypeDeclCollector(UniqueNamer! namer, TypeDeclCollector! coll) {
+ this.Namer = namer;
+ this.NativeBv = coll.NativeBv;
+ AllDecls = new List<string!> (coll.AllDecls);
+ IncDecls = new List<string!> (coll.IncDecls);
+ KnownFunctions = new Dictionary<Function!, bool> (coll.KnownFunctions);
+ KnownVariables = new Dictionary<VCExprVar!, bool> (coll.KnownVariables);
+ KnownTypes = new Dictionary<Type!, bool> (coll.KnownTypes);
+ KnownBvOps = new Dictionary<string!, bool> (coll.KnownBvOps);
+ }
+
+ // not used
+ protected override bool StandardResult(VCExpr! node, bool arg) {
+ return true;
+ }
+
+ private readonly List<string!>! AllDecls;
+ private readonly List<string!>! IncDecls;
+
+ private readonly IDictionary<Function!, bool>! KnownFunctions;
+ private readonly IDictionary<VCExprVar!, bool>! KnownVariables;
+
+ // bitvector types have to be registered as well
+ private readonly IDictionary<Type!, bool>! KnownTypes;
+
+ // the names of registered BvConcatOps and BvExtractOps
+ private readonly IDictionary<string!, bool>! KnownBvOps;
+
+ public List<string!>! AllDeclarations { get {
+ List<string!>! res = new List<string!> ();
+ res.AddRange(AllDecls);
+ return res;
+ } }
+
+ public List<string!>! GetNewDeclarations() {
+ List<string!>! res = new List<string!> ();
+ res.AddRange(IncDecls);
+ IncDecls.Clear();
+ return res;
+ }
+
+ private void AddDeclaration(string! decl) {
+ AllDecls.Add(decl);
+ IncDecls.Add(decl);
+ }
+
+ public void Collect(VCExpr! expr) {
+ Traverse(expr, true);
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+
+ private static string! TypeToString(Type! t) {
+ return SimplifyLikeExprLineariser.TypeToString(t);
+ }
+
+ private void RegisterType(Type! type)
+ {
+ if (!type.IsBv || !NativeBv) return;
+
+ if (!KnownTypes.ContainsKey(type)) {
+ 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, true);
+ }
+ }
+
+ public override bool Visit(VCExprNAry! node, bool arg) {
+ // there are a couple of cases where operators have to be
+ // registered by generating appropriate Z3 statements
+
+ if (node.Op.Equals(VCExpressionGenerator.BvConcatOp)) {
+ //
+ if (NativeBv) {
+ RegisterType(node[0].Type);
+ RegisterType(node[1].Type);
+ RegisterType(node.Type);
+
+ string name = SimplifyLikeExprLineariser.BvConcatOpName(node);
+ if (!KnownBvOps.ContainsKey(name)) {
+ AddDeclaration("(DEFOP " + name +
+ " " + TypeToString(node[0].Type) +
+ " " + TypeToString(node[1].Type) +
+ " " + TypeToString(node.Type) +
+ " :BUILTIN concat)");
+ KnownBvOps.Add(name, true);
+ }
+ }
+ //
+ } else if (node.Op is VCExprBvExtractOp) {
+ //
+ if (NativeBv) {
+ RegisterType(node[0].Type);
+ RegisterType(node.Type);
+
+ VCExprBvExtractOp! op = (VCExprBvExtractOp)node.Op;
+ string name = SimplifyLikeExprLineariser.BvExtractOpName(node);
+ if (!KnownBvOps.ContainsKey(name)) {
+ AddDeclaration("(DEFOP " + name +
+ " " + TypeToString(node[0].Type) +
+ " " + TypeToString(node.Type) +
+ " :BUILTIN extract " +
+ (op.End - 1) + " " + op.Start + ")");
+ KnownBvOps.Add(name, true);
+ }
+ }
+ //
+ } else {
+ //
+ VCExprBoogieFunctionOp op = node.Op as VCExprBoogieFunctionOp;
+ if (op != null && !KnownFunctions.ContainsKey(op.Func)) {
+ Function! f = op.Func;
+ string! printedName = Namer.GetName(f, f.Name);
+ string! decl = "(DEFOP " + SimplifyLikeExprLineariser.MakeIdPrintable(printedName);
+
+ foreach (Variable! v in f.InParams) {
+ decl += " " + TypeToString(v.TypedIdent.Type);
+ RegisterType(v.TypedIdent.Type);
+ }
+ assert f.OutParams.Length == 1;
+ foreach (Variable! v in f.OutParams) {
+ 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, true);
+ }
+ //
+ }
+
+ return base.Visit(node, arg);
+ }
+
+ private string? ExtractBuiltin(Function! f) {
+ if (NativeBv) {
+ return f.FindStringAttribute("bvbuiltin");
+ } else {
+ return null;
+ }
+ }
+
+ public override bool Visit(VCExprVar! node, bool arg) {
+ if (!BoundTermVars.Contains(node) && !KnownVariables.ContainsKey(node)) {
+ RegisterType(node.Type);
+ string! printedName = Namer.GetName(node, node.Name);
+ string! decl =
+ "(DEFOP " + SimplifyLikeExprLineariser.MakeIdPrintable(printedName)
+ + " " + TypeToString(node.Type) + ")";
+ AddDeclaration(decl);
+ KnownVariables.Add(node, true);
+ }
+
+ return base.Visit(node, arg);
+ }
+ }
+
+} \ No newline at end of file
diff --git a/Source/Provers/Z3/Z3.sscproj b/Source/Provers/Z3/Z3.sscproj
new file mode 100644
index 00000000..5370a640
--- /dev/null
+++ b/Source/Provers/Z3/Z3.sscproj
@@ -0,0 +1,140 @@
+<?xml version="1.0" encoding="utf-8"?>
+<VisualStudioProject>
+ <XEN ProjectType="Local"
+ SchemaVersion="1.0"
+ Name="Z3"
+ ProjectGuid="f75666de-cd56-457c-8782-09be243450fc"
+ >
+ <Build>
+ <Settings ApplicationIcon=""
+ AssemblyName="Provers.Z3"
+ OutputType="Library"
+ RootNamespace="Microsoft.Boogie.Z3"
+ StartupObject=""
+ StandardLibraryLocation=""
+ TargetPlatform="v2"
+ TargetPlatformLocation=""
+ ShadowedAssembly=""
+ NoStandardLibraries="False"
+ >
+ <Config Name="Debug"
+ AllowUnsafeBlocks="False"
+ BaseAddress="285212672"
+ CheckForOverflowUnderflow="False"
+ ConfigurationOverrideFile=""
+ DefineConstants="DEBUG;TRACE"
+ DocumentationFile=""
+ DebugSymbols="True"
+ FileAlignment="4096"
+ IncrementalBuild="True"
+ Optimize="False"
+ OutputPath="bin\debug"
+ RegisterForComInterop="False"
+ RemoveIntegerChecks="false"
+ TreatWarningsAsErrors="False"
+ WarningLevel="4"
+ ReferenceTypesAreNonNullByDefault="False"
+ RunProgramVerifier="False"
+ RunProgramVerifierWhileEditing="False"
+ ProgramVerifierCommandLineOptions=""
+ AllowPointersToManagedStructures="False"
+ CheckContractAdmissibility="True"
+ CheckPurity="False"
+ />
+ <Config Name="Release"
+ AllowUnsafeBlocks="false"
+ BaseAddress="285212672"
+ CheckForOverflowUnderflow="false"
+ ConfigurationOverrideFile=""
+ DefineConstants="TRACE"
+ DocumentationFile=""
+ DebugSymbols="false"
+ FileAlignment="4096"
+ IncrementalBuild="false"
+ Optimize="true"
+ OutputPath="bin\release"
+ RegisterForComInterop="false"
+ RemoveIntegerChecks="false"
+ TreatWarningsAsErrors="false"
+ WarningLevel="4"
+ />
+ </Settings>
+ <References>
+ <Reference Name="System"
+ AssemblyName="System"
+ Private="false"
+ />
+ <Reference Name="System.Data"
+ AssemblyName="System.Data"
+ Private="false"
+ />
+ <Reference Name="System.Xml"
+ AssemblyName="System.Xml"
+ Private="false"
+ />
+ <Reference Name="Core"
+ Project="{47BC34F1-A173-40BE-84C2-9332B4418387}"
+ Private="true"
+ />
+ <Reference Name="AIFramework"
+ Project="{24B55172-AD8B-47D1-8952-5A95CFDB9B31}"
+ Private="true"
+ />
+ <Reference Name="Graph"
+ Project="{4C28FB90-630E-4B55-A937-11A011B79765}"
+ Private="true"
+ />
+ <Reference Name="Mscorlib.Contracts"
+ AssemblyName="Mscorlib.Contracts"
+ Private="false"
+ HintPath="../../../Binaries/Mscorlib.Contracts.dll"
+ />
+ <Reference Name="System.Contracts"
+ AssemblyName="System.Contracts"
+ Private="false"
+ HintPath="../../../Binaries/System.Contracts.dll"
+ />
+ <Reference Name="VCGeneration"
+ Project="{F65666DE-FB56-457C-8782-09BE243450FC}"
+ Private="true"
+ />
+ <Reference Name="Simplify"
+ Project="{F75666DE-FB56-457C-8782-09BE243450FC}"
+ Private="true"
+ />
+ <Reference Name="Basetypes"
+ Project="{0C692837-77EC-415F-BF04-395E3ED06E9A}"
+ Private="true"
+ />
+ <Reference Name="VCExpr"
+ Project="{CF42B700-10AA-4DA9-8992-48A800251C11}"
+ Private="true"
+ />
+ </References>
+ </Build>
+ <Files>
+ <Include>
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="Prover.ssc"
+ />
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="ProverInterface.ssc"
+ />
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="..\..\version.ssc"
+ />
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="TypeDeclCollector.ssc"
+ />
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="Inspector.ssc"
+ />
+ </Include>
+ </Files>
+ </XEN>
+</VisualStudioProject> \ No newline at end of file
diff --git a/Source/VCExpr/BigLiteralAbstracter.ssc b/Source/VCExpr/BigLiteralAbstracter.ssc
new file mode 100644
index 00000000..fac34a8d
--- /dev/null
+++ b/Source/VCExpr/BigLiteralAbstracter.ssc
@@ -0,0 +1,198 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using System;
+using System.Text;
+using System.IO;
+using System.Collections;
+using System.Collections.Generic;
+using Microsoft.Contracts;
+using Microsoft.Basetypes;
+
+// Code for replacing large integer literals in VCExpr with
+// constants. This is necessary for Simplify, which cannot deal with
+// literals larger than 32 bits
+
+namespace Microsoft.Boogie.VCExprAST
+{
+
+ public class BigLiteralAbstracter : MutatingVCExprVisitor<bool>, ICloneable {
+
+ public BigLiteralAbstracter(VCExpressionGenerator! gen) {
+ base(gen);
+ DummyVar = gen.Variable("x", Type.Int);
+ IncAxioms = new List<VCExpr!> ();
+ Literals = new List<KeyValuePair<BigNum, VCExprVar!>> ();
+ }
+
+ private BigLiteralAbstracter(BigLiteralAbstracter! abstracter) {
+ base(abstracter.Gen);
+ DummyVar = abstracter.DummyVar;
+ IncAxioms = new List<VCExpr!> (abstracter.IncAxioms);
+ Literals = new List<KeyValuePair<BigNum, VCExprVar!>> (abstracter.Literals);
+ }
+
+ public Object! Clone() {
+ return new BigLiteralAbstracter(this);
+ }
+
+ private static readonly BigNum ConstantDistance = BigNum.FromLong(100000);
+ private static readonly BigNum NegConstantDistance = BigNum.FromLong(-100000);
+ // distance twice plus one
+ private static readonly BigNum ConstantDistanceTPO = BigNum.FromLong(200001);
+ private static readonly BigNum ConstantDistancePO = BigNum.FromLong(100001);
+
+ public VCExpr! Abstract(VCExpr! expr) {
+ return Mutate(expr, true);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ // list in which axioms are incrementally collected
+ private readonly List<VCExpr!>! IncAxioms;
+
+ private void AddAxiom(VCExpr! axiom) {
+ IncAxioms.Add(axiom);
+ }
+
+ // Return all axioms that were added since the last time NewAxioms
+ // was called
+ public VCExpr! GetNewAxioms() {
+ VCExpr! res = Gen.NAry(VCExpressionGenerator.AndOp, IncAxioms);
+ IncAxioms.Clear();
+ return res;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ // All named integer literals known to the visitor, in ascending
+ // order. Such literals are always positive, and the distance
+ // between two literals is always more than ConstantDistance.
+ private readonly List<KeyValuePair<BigNum, VCExprVar!>>! Literals;
+
+ private class EntryComparerC : IComparer<KeyValuePair<BigNum, VCExprVar!>> {
+ public int Compare(KeyValuePair<BigNum, VCExprVar!> a,
+ KeyValuePair<BigNum, VCExprVar!> b) {
+ return a.Key.CompareTo(b.Key);
+ }
+ }
+
+ private static readonly EntryComparerC EntryComparer = new EntryComparerC ();
+
+ // variable used when searching for entries in the literal list
+ private readonly VCExprVar! DummyVar;
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ // Construct an expression to represent the given (large) integer
+ // literal. Constants are defined and axiomatised if necessary
+ private VCExpr! Represent(BigNum lit)
+ requires NegConstantDistance > lit || lit > ConstantDistance; {
+
+ if (lit.IsNegative)
+ return Gen.Function(VCExpressionGenerator.SubOp,
+ Gen.Integer(BigNum.ZERO), RepresentPos(lit.Neg));
+ else
+ return RepresentPos(lit);
+ }
+
+ private VCExpr! RepresentPos(BigNum lit)
+ requires lit > ConstantDistance; {
+
+ int index = GetIndexFor(lit);
+ if (index >= 0)
+ // precise match
+ return Literals[index].Value;
+
+ // check whether a constant is defined that is at most
+ // ConstantDistance away from lit
+ index = ~index;
+ VCExpr res = null;
+ BigNum resDistance = ConstantDistancePO;
+
+ if (index > 0) {
+ BigNum dist = lit - Literals[index - 1].Key;
+ if (dist < resDistance) {
+ resDistance = dist;
+ res = Gen.Function(VCExpressionGenerator.AddOp,
+ Literals[index - 1].Value, Gen.Integer(dist));
+ }
+ }
+
+ if (index < Literals.Count) {
+ BigNum dist = Literals[index].Key - lit;
+ if (dist < resDistance) {
+ resDistance = dist;
+ res = Gen.Function(VCExpressionGenerator.SubOp,
+ Literals[index].Value, Gen.Integer(dist));
+ }
+ }
+
+ if (res != null)
+ return res;
+
+ // otherwise, define a new constant to represent this literal
+ return AddConstantFor(lit);
+ }
+
+ private VCExpr! AddConstantFor(BigNum lit)
+ requires lit > ConstantDistance; {
+
+ VCExprVar! res = Gen.Variable("int#" + lit, Type.Int);
+ int index = GetIndexFor(lit);
+ assert index < 0;
+ index = ~index;
+
+ Literals.Insert(index, new KeyValuePair<BigNum, VCExprVar!>(lit, res));
+
+ // relate the new constant to the predecessor and successor
+ if (index > 0)
+ DefineRelationship(Literals[index - 1].Value, Literals[index - 1].Key,
+ res, lit);
+ else
+ DefineRelationship(Gen.Integer(BigNum.ZERO), BigNum.ZERO, res, lit);
+
+ if (index < Literals.Count - 1)
+ DefineRelationship(res, lit,
+ Literals[index + 1].Value, Literals[index + 1].Key);
+
+ return res;
+ }
+
+ private void DefineRelationship(VCExpr! aExpr, BigNum aValue,
+ VCExpr! bExpr, BigNum bValue)
+ requires aValue < bValue; {
+
+ BigNum dist = bValue - aValue;
+ VCExpr! distExpr = Gen.Function(VCExpressionGenerator.SubOp, bExpr, aExpr);
+ if (dist <= ConstantDistanceTPO)
+ // constants that are sufficiently close to each other are put
+ // into a precise relationship
+ AddAxiom(Gen.Eq(distExpr, Gen.Integer(dist)));
+ else
+ AddAxiom(Gen.Function(VCExpressionGenerator.GtOp,
+ distExpr, Gen.Integer(ConstantDistanceTPO)));
+ }
+
+ private int GetIndexFor(BigNum lit) {
+ return Literals.BinarySearch(new KeyValuePair<BigNum, VCExprVar!>
+ (lit, DummyVar),
+ EntryComparer);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ public override VCExpr! Visit(VCExprLiteral! node, bool arg) {
+ VCExprIntLit intLit = node as VCExprIntLit;
+ if (intLit != null) {
+ if (NegConstantDistance > intLit.Val || intLit.Val > ConstantDistance)
+ return Represent(intLit.Val);
+ }
+ return node;
+ }
+
+ }
+
+} \ No newline at end of file
diff --git a/Source/VCExpr/Boogie2VCExpr.ssc b/Source/VCExpr/Boogie2VCExpr.ssc
new file mode 100644
index 00000000..b344c03d
--- /dev/null
+++ b/Source/VCExpr/Boogie2VCExpr.ssc
@@ -0,0 +1,853 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using System;
+using System.Text;
+using System.IO;
+using System.Collections;
+using System.Collections.Generic;
+using Microsoft.Contracts;
+using Microsoft.Basetypes;
+
+// A translator from the Boogie AST to the VCExpr AST.
+// This was previously realised in the methods AbsyExpr.VCView
+
+namespace Microsoft.Boogie.VCExprAST
+{
+ using Microsoft.Boogie;
+
+ public class VCGenerationOptions {
+ private readonly List<string!>! SupportedProverCommands;
+
+ public bool IsProverCommandSupported(string! kind)
+ {
+ return SupportedProverCommands.Contains(kind);
+ }
+
+ public bool IsAnyProverCommandSupported(string! kinds)
+ {
+ if (kinds.IndexOf(',') < 0) {
+ return IsProverCommandSupported(kinds);
+ } else {
+ return exists{string k in kinds.Split(',', ' '); IsProverCommandSupported(k)};
+ }
+ }
+
+ public VCGenerationOptions(List<string!>! supportedProverCommands) {
+ this.SupportedProverCommands = supportedProverCommands;
+ }
+ }
+
+ public class Boogie2VCExprTranslator : StandardVisitor, ICloneable {
+ // Stack on which the various Visit-methods put the result of the translation
+ private readonly Stack<VCExpr!>! SubExpressions = new Stack<VCExpr!> ();
+
+ private void Push(VCExpr! expr) {
+ SubExpressions.Push(expr);
+ }
+
+ private VCExpr! Pop() {
+ return SubExpressions.Pop();
+ }
+
+ public VCExpr! Translate(Expr! expr) {
+ this.Visit(expr);
+ return Pop();
+ }
+
+ public List<VCExpr!>! Translate(ExprSeq! exprs) {
+ List<VCExpr!>! res = new List<VCExpr!> ();
+ foreach(Expr e in exprs)
+ res.Add(Translate((!)e));
+ return res;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////
+
+ internal readonly VCExpressionGenerator! Gen;
+
+ public Boogie2VCExprTranslator(VCExpressionGenerator! gen,
+ VCGenerationOptions! genOptions) {
+ this.Gen = gen;
+ this.GenerationOptions = genOptions;
+ UnboundVariables = new VariableMapping<Variable> ();
+ BoundVariables = new VariableMapping<BoundVariable> ();
+ Formals = new VariableMapping<Formal> ();
+ }
+
+ private Boogie2VCExprTranslator(Boogie2VCExprTranslator! tl) {
+ this.Gen = tl.Gen;
+ this.GenerationOptions = tl.GenerationOptions;
+ UnboundVariables =
+ (VariableMapping<Variable>)tl.UnboundVariables.Clone();
+ BoundVariables = new VariableMapping<BoundVariable> ();
+ Formals = new VariableMapping<Formal> ();
+ }
+
+ public object! Clone() {
+ return new Boogie2VCExprTranslator(this);
+ }
+
+ private IAppliableTranslator IAppTranslatorAttr = null;
+ private IAppliableTranslator! IAppTranslator { get {
+ if (IAppTranslatorAttr == null)
+ IAppTranslatorAttr = new IAppliableTranslator (this);
+ return IAppTranslatorAttr;
+ } }
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // Class for handling occurring variables
+
+ private class VariableMapping<VarKind> : ICloneable {
+ private readonly List<Dictionary<VarKind!, VCExprVar!>!>! Mapping;
+
+ public VariableMapping() {
+ List<Dictionary<VarKind!, VCExprVar!>!>! mapping =
+ new List<Dictionary<VarKind!, VCExprVar!>!> ();
+ mapping.Add(new Dictionary<VarKind!, VCExprVar!> ());
+ this.Mapping = mapping;
+ }
+
+ private VariableMapping(VariableMapping<VarKind>! vm) {
+ List<Dictionary<VarKind!, VCExprVar!>!>! mapping =
+ new List<Dictionary<VarKind!, VCExprVar!>!> ();
+ foreach (Dictionary<VarKind!, VCExprVar!>! d in vm.Mapping)
+ mapping.Add(new Dictionary<VarKind!, VCExprVar!> (d));
+ this.Mapping = mapping;
+ }
+
+ public object! Clone() {
+ return new VariableMapping<VarKind> (this);
+ }
+
+ public void PushScope() {
+ Mapping.Add(new Dictionary<VarKind!, VCExprVar!> ());
+ }
+
+ public void PopScope() {
+ assume Mapping.Count > 0;
+ Mapping.RemoveAt(Mapping.Count - 1);
+ }
+
+ public void Bind(VarKind! boogieVar, VCExprVar! vcExprVar)
+ requires !Contains(boogieVar); {
+ Mapping[Mapping.Count - 1].Add(boogieVar, vcExprVar);
+ }
+
+ public VCExprVar! Lookup(VarKind! boogieVar) {
+ VCExprVar res = LookupHelp(boogieVar);
+ assume res != null;
+ return res;
+ }
+
+ [Pure]
+ public bool Contains(VarKind! boogieVar) {
+ return LookupHelp(boogieVar) != null;
+ }
+
+ public bool TryGetValue(VarKind! boogieVar, out VCExprVar res) {
+ res = LookupHelp(boogieVar);
+ return res != null;
+ }
+
+ [Pure]
+ private VCExprVar LookupHelp(VarKind! boogieVar) {
+ VCExprVar res;
+ foreach (Dictionary<VarKind!, VCExprVar!>! d in Mapping) {
+ if (d.TryGetValue(boogieVar, out res))
+ return res;
+ }
+ return null;
+ }
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+
+ private readonly VariableMapping<Variable>! UnboundVariables;
+ private readonly VariableMapping<BoundVariable>! BoundVariables;
+ // used when translating the bodies of function expansions
+ private readonly VariableMapping<Formal>! Formals;
+
+ internal void PushBoundVariableScope() {
+ BoundVariables.PushScope();
+ }
+ internal void PopBoundVariableScope() {
+ BoundVariables.PopScope();
+ }
+
+ internal void PushFormalsScope() {
+ Formals.PushScope();
+ }
+ internal void PopFormalsScope() {
+ Formals.PopScope();
+ }
+
+ public VCExprVar! BindVariable(Variable! boogieVar) {
+ if (boogieVar is BoundVariable) {
+ VCExprVar! newVar = Gen.Variable(boogieVar.Name, boogieVar.TypedIdent.Type);
+ BoundVariables.Bind((BoundVariable)boogieVar, newVar);
+ return newVar;
+ } else if (boogieVar is Formal) {
+ VCExprVar! newVar = Gen.Variable(boogieVar.Name, boogieVar.TypedIdent.Type);
+ Formals.Bind((Formal)boogieVar, newVar);
+ return newVar;
+ } else {
+ // only bound variables and formals are declared explicitly
+ assert false;
+ }
+ }
+
+ public VCExprVar! LookupVariable(Variable! boogieVar) {
+
+ BoundVariable bv = boogieVar as BoundVariable;
+ if (bv != null) {
+ return BoundVariables.Lookup(bv);
+ }
+ VCExprVar res;
+ Formal fml = boogieVar as Formal;
+ if (fml != null && Formals.TryGetValue(fml, out res))
+ return (!)res;
+
+ // global variables, local variables, incarnations, etc. are
+ // bound the first time they occur
+ if (!UnboundVariables.TryGetValue(boogieVar, out res)) {
+ res = new VCExprVar (boogieVar.Name, boogieVar.TypedIdent.Type);
+ UnboundVariables.Bind(boogieVar, res);
+ }
+ return (!)res;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////
+
+ internal readonly VCGenerationOptions! GenerationOptions;
+
+ ///////////////////////////////////////////////////////////////////////////////////
+
+ public override LiteralExpr! VisitLiteralExpr(LiteralExpr! node) {
+ Push(TranslateLiteralExpr(node));
+ return node;
+ }
+ private VCExpr! TranslateLiteralExpr(LiteralExpr! node) {
+ if ( node.Val is bool )
+ {
+ bool b = (bool) node.Val;
+ if ( b ) {
+ return VCExpressionGenerator.True;
+ } else {
+ return VCExpressionGenerator.False;
+ }
+ }
+ else if ( node.Val is BigNum )
+ {
+ return Gen.Integer(node.asBigNum);
+ }
+ else if ( node.Val is BvConst )
+ {
+ return Gen.Bitvector((BvConst)node.Val);
+ }
+ else
+ {
+ System.Diagnostics.Debug.Assert(false, "unknown kind of literal " + node.tok.ToString());
+ assert false;
+ }
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////
+
+ public override AIVariableExpr! VisitAIVariableExpr(AIVariableExpr! node)
+ {
+ assert false;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////
+
+ public override Expr! VisitIdentifierExpr(IdentifierExpr! node) {
+ assume node.Decl != null; // the expression has to be resolved
+ Push(LookupVariable(node.Decl));
+ return node;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////
+
+ // Because of our scheme for numbering incarnations of variables, the pre-state
+ // value of a variable x is always just "x". (The first update to it in a method
+ // causes it to become "x0". So we just remove old expressions with a visitor
+ // before transforming it into a VCExpr.
+ public override Expr! VisitOldExpr(OldExpr! node)
+ {
+ assert false;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////
+
+ public override Expr! VisitNAryExpr(NAryExpr! node)
+ {
+ Push(TranslateNAryExpr(node));
+ return node;
+ }
+
+ public override Expr! VisitLoopPredicate(LoopPredicate! node)
+ {
+ return this.VisitNAryExpr(node);
+ }
+
+ private VCExpr! TranslateNAryExpr(NAryExpr! node) {
+ int n = node.Args.Length;
+ List<VCExpr!>! vcs = new List<VCExpr!> (n);
+ for(int i = 0; i < n; i++)
+ {
+ vcs.Add(Translate((!)node.Args[i]));
+ }
+
+ if (node.Type == null) {
+ System.Console.WriteLine("*** type is null for {0}", node);
+ assert false;
+ }
+
+ return IAppTranslator.Translate(node.Fun, node.Type, vcs,
+ ToList((!)node.TypeParameters));
+ }
+
+
+ private static List<Type!>! EMPTY_TYPE_LIST = new List<Type!> ();
+
+ private List<Type!>! ToList(TypeParamInstantiation! insts) {
+ if (insts.FormalTypeParams.Count == 0)
+ return EMPTY_TYPE_LIST;
+
+ List<Type!>! typeArgs = new List<Type!> ();
+ foreach (TypeVariable! var in insts.FormalTypeParams)
+ typeArgs.Add(insts[var]);
+ return typeArgs;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////
+
+ public override QuantifierExpr! VisitQuantifierExpr(QuantifierExpr! node) {
+ Push(TranslateQuantifierExpr(node));
+ return node;
+ }
+
+ public override ExistsExpr! VisitExistsExpr(ExistsExpr! node)
+ {
+ node = (ExistsExpr) this.VisitQuantifierExpr(node);
+ return node;
+ }
+
+ public override ForallExpr! VisitForallExpr(ForallExpr! node)
+ {
+ node = (ForallExpr) this.VisitQuantifierExpr(node);
+ return node;
+ }
+
+ private VCExpr! TranslateQuantifierExpr(QuantifierExpr! node)
+ {
+ List<TypeVariable!>! typeParams = new List<TypeVariable!> ();
+ foreach (TypeVariable! v in node.TypeParameters)
+ typeParams.Add(v);
+
+ PushBoundVariableScope();
+
+ List<VCExprVar!>! boundVars = new List<VCExprVar!> ();
+ foreach (Variable! v in node.Dummies)
+ boundVars.Add(BindVariable(v));
+
+ try {
+ List<VCTrigger!>! triggers = TranslateTriggers(node.Triggers);
+ VCExpr! body = Translate(node.Body);
+ VCQuantifierInfos! infos = GenerateQuantifierInfos(node);
+
+ Quantifier quan;
+ if (node is ForallExpr)
+ quan = Quantifier.ALL;
+ else if (node is ExistsExpr)
+ quan = Quantifier.EX;
+ else
+ assert false;
+
+ return Gen.Quantify(quan, typeParams, boundVars, triggers, infos, body);
+ } finally {
+ PopBoundVariableScope();
+ }
+ }
+
+ private List<VCTrigger!>! TranslateTriggers(Trigger node)
+ {
+ List<VCTrigger!>! res = new List<VCTrigger!> ();
+ Trigger curTrigger = node;
+ while (curTrigger != null) {
+ res.Add(Gen.Trigger(curTrigger.Pos, Translate(curTrigger.Tr)));
+ curTrigger = curTrigger.Next;
+ }
+ return res;
+ }
+
+ private VCQuantifierInfos! GenerateQuantifierInfos(QuantifierExpr! node) {
+ string qid = getQidNameFromQKeyValue(node.Dummies, node.Attributes);
+ return new VCQuantifierInfos(qid, node.SkolemId, false, node.Attributes);
+ }
+
+ private string getQidNameFromQKeyValue(VariableSeq! vars, QKeyValue attributes) {
+ // Check for a 'qid, name' pair in keyvalues
+ string qid = QKeyValue.FindStringAttribute(attributes, "qid");
+ if (qid == null && vars.Length != 0){
+ // generate default name (line:column position in .bpl file)
+ Variable v = vars[0];
+ assert v != null; // Rustan's claim!
+ // Include the first 8 characters of the filename in QID (helpful in case we use /concat)
+ // We limit it to 8, so the SX file doesn't grow too big, and who on earth would need
+ // more than 8 characters in a filename anyways.
+ int max = 8;
+ StringBuilder buf = new StringBuilder(max + 20);
+ string filename = v.tok.filename;
+ if (filename == null) filename = "unknown";
+ for (int i = 0; i < filename.Length; ++i) {
+ if (filename[i] == '/' || filename[i] == '\\') buf.Length = 0;
+ if (buf.Length < max && char.IsLetterOrDigit(filename[i]))
+ buf.Append(filename[i]);
+ }
+ buf.Append('.').Append(v.Line).Append(':').Append(v.Col);
+ qid = buf.ToString();
+ }
+ return qid;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////
+
+ public override ExtractExpr! VisitExtractExpr(ExtractExpr! node)
+ {
+ Push(TranslateExtractExpr(node));
+ return node;
+ }
+
+ private VCExpr! TranslateExtractExpr(ExtractExpr! node)
+ requires node.Start <= node.End; {
+ VCExpr! bv = Translate(node.Bitvector);
+ return Gen.BvExtract(bv, ((!)node.Bitvector.Type).BvBits, node.Start, node.End);
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////
+
+ public override BvConcatExpr! VisitBvConcatExpr(BvConcatExpr! node)
+ {
+ Push(TranslateBvConcatExpr(node));
+ return node;
+ }
+
+ private VCExpr! TranslateBvConcatExpr(BvConcatExpr! node) {
+ VCExpr! bv0 = Translate(node.E0);
+ VCExpr! bv1 = Translate(node.E1);
+ return Gen.BvConcat(bv0, bv1);
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////
+ // all the other cases should never happen
+
+ public override Cmd! VisitAssertCmd(AssertCmd! node)
+ {
+ assert false;
+ }
+ public override Cmd! VisitAssignCmd(AssignCmd! node)
+ {
+ assert false;
+ }
+ public override Cmd! VisitAssumeCmd(AssumeCmd! node)
+ {
+ assert false;
+ }
+ public override AtomicRE! VisitAtomicRE(AtomicRE! node)
+ {
+ assert false;
+ }
+ public override Axiom! VisitAxiom(Axiom! node)
+ {
+ assert false;
+ }
+ public override Type! VisitBasicType(BasicType! node)
+ {
+ assert false;
+ }
+ public override Type! VisitBvType(BvType! node)
+ {
+ assert false;
+ }
+ public override Block! VisitBlock(Block! node)
+ {
+ assert false;
+ }
+ public override Expr! VisitBlockExpr(BlockExpr! node)
+ {
+ assert false;
+ }
+ public override BlockSeq! VisitBlockSeq(BlockSeq! blockSeq)
+ {
+ assert false;
+ }
+ public override List<Block!>! VisitBlockList(List<Block!>! blocks)
+ {
+ assert false;
+ }
+ public override BoundVariable! VisitBoundVariable(BoundVariable! node)
+ {
+ assert false;
+ }
+ public override Cmd! VisitCallCmd(CallCmd! node)
+ {
+ assert false;
+ }
+ public override Cmd! VisitCallForallCmd(CallForallCmd! node)
+ {
+ assert false;
+ }
+ public override CmdSeq! VisitCmdSeq(CmdSeq! cmdSeq)
+ {
+ assert false;
+ }
+ public override Choice! VisitChoice(Choice! node)
+ {
+ assert false;
+ }
+ public override Cmd! VisitCommentCmd(CommentCmd! node)
+ {
+ assert false;
+ }
+ public override Constant! VisitConstant(Constant! node)
+ {
+ assert false;
+ }
+ public override CtorType! VisitCtorType(CtorType! node)
+ {
+ assert false;
+ }
+ public override Declaration! VisitDeclaration(Declaration! node)
+ {
+ assert false;
+ }
+ public override List<Declaration!>! VisitDeclarationList(List<Declaration!>! declarationList)
+ {
+ assert false;
+ }
+ public override DeclWithFormals! VisitDeclWithFormals(DeclWithFormals! node)
+ {
+ assert false;
+ }
+ public override Requires! VisitRequires(Requires! @requires)
+ {
+ assert false;
+ }
+ public override RequiresSeq! VisitRequiresSeq(RequiresSeq! requiresSeq)
+ {
+ assert false;
+ }
+ public override Ensures! VisitEnsures(Ensures! @ensures)
+ {
+ assert false;
+ }
+ public override EnsuresSeq! VisitEnsuresSeq(EnsuresSeq! ensuresSeq)
+ {
+ assert false;
+ }
+ public override Formal! VisitFormal(Formal! node)
+ {
+ assert false;
+ }
+ public override Function! VisitFunction(Function! node)
+ {
+ assert false;
+ }
+ public override GlobalVariable! VisitGlobalVariable(GlobalVariable! node)
+ {
+ assert false;
+ }
+ public override GotoCmd! VisitGotoCmd(GotoCmd! node)
+ {
+ assert false;
+ }
+ public override Cmd! VisitHavocCmd(HavocCmd! node)
+ {
+ assert false;
+ }
+ public override Implementation! VisitImplementation(Implementation! node)
+ {
+ assert false;
+ }
+ public override LocalVariable! VisitLocalVariable(LocalVariable! node)
+ {
+ assert false;
+ }
+ public override AssignLhs! VisitMapAssignLhs(MapAssignLhs! node)
+ {
+ assert false;
+ }
+ public override MapType! VisitMapType(MapType! node)
+ {
+ assert false;
+ }
+ public override Procedure! VisitProcedure(Procedure! node)
+ {
+ assert false;
+ }
+ public override Program! VisitProgram(Program! node)
+ {
+ assert false;
+ }
+ public override Cmd! VisitRE(RE! node)
+ {
+ assert false;
+ }
+ public override RESeq! VisitRESeq(RESeq! reSeq)
+ {
+ assert false;
+ }
+ public override ReturnCmd! VisitReturnCmd(ReturnCmd! node)
+ {
+ assert false;
+ }
+ public override ReturnExprCmd! VisitReturnExprCmd(ReturnExprCmd! node)
+ {
+ assert false;
+ }
+ public override Sequential! VisitSequential(Sequential! node)
+ {
+ assert false;
+ }
+ public override AssignLhs! VisitSimpleAssignLhs(SimpleAssignLhs! node)
+ {
+ assert false;
+ }
+ public override Cmd! VisitStateCmd(StateCmd! node)
+ {
+ assert false;
+ }
+ public override TransferCmd! VisitTransferCmd(TransferCmd! node)
+ {
+ assert false;
+ }
+ public override Trigger! VisitTrigger(Trigger! node)
+ {
+ assert false;
+ }
+ public override Type! VisitType(Type! node)
+ {
+ assert false;
+ }
+ public override TypedIdent! VisitTypedIdent(TypedIdent! node)
+ {
+ assert false;
+ }
+ public override Type! VisitTypeSynonymAnnotation(TypeSynonymAnnotation! node)
+ {
+ assert false;
+ }
+ public override Type! VisitTypeVariable(TypeVariable! node)
+ {
+ assert false;
+ }
+ public override Variable! VisitVariable(Variable! node)
+ {
+ assert false;
+ }
+ public override VariableSeq! VisitVariableSeq(VariableSeq! variableSeq)
+ {
+ assert false;
+ }
+ public override Cmd! VisitAssertEnsuresCmd(AssertEnsuresCmd! node)
+ {
+ assert false;
+ }
+ public override Cmd! VisitAssertRequiresCmd(AssertRequiresCmd! node)
+ {
+ assert false;
+ }
+
+ }
+
+
+ /////////////////////////////////////////////////////////////////////////////////
+
+ public class IAppliableTranslator : IAppliableVisitor<VCExpr!> {
+
+ private readonly Boogie2VCExprTranslator! BaseTranslator;
+
+ private VCExpressionGenerator! Gen { get {
+ return BaseTranslator.Gen;
+ } }
+ private VCGenerationOptions! GenerationOptions { get {
+ return BaseTranslator.GenerationOptions;
+ } }
+
+ public IAppliableTranslator(Boogie2VCExprTranslator! baseTranslator) {
+ this.BaseTranslator = baseTranslator;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////
+
+ private List<VCExpr!>! args = new List<VCExpr!>();
+ private List<Type!>! typeArgs = new List<Type!>();
+
+ public VCExpr! Translate(IAppliable! app, Type! ty, List<VCExpr!>! args, List<Type!>! typeArgs) {
+
+ List<VCExpr!>! oldArgs = this.args;
+ List<Type!>! oldTypeArgs = this.typeArgs;
+ this.args = args;
+ this.typeArgs = typeArgs;
+ VCExpr! result = app.Dispatch<VCExpr!>(this);
+ this.args = oldArgs;
+ this.typeArgs = oldTypeArgs;
+ return result;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////
+
+
+
+ public VCExpr! Visit(UnaryOperator! unaryOperator) {
+ assert unaryOperator.Op == UnaryOperator.Opcode.Not && this.args.Count == 1;
+ return Gen.Not(this.args);
+ }
+
+ public VCExpr! Visit(BinaryOperator! binaryOperator) {
+ return TranslateBinaryOperator(binaryOperator, this.args);
+ }
+
+ public VCExpr! Visit(FunctionCall! functionCall) {
+ return TranslateFunctionCall(functionCall, this.args, this.typeArgs);
+ }
+
+ public VCExpr! Visit(LoopPredicateName! loopPredicateName) {
+ return Gen.Variable(loopPredicateName.Name, Type.Bool); // We generate a variable. Intuition: it is a second order variable
+ }
+
+ public VCExpr! Visit(MapSelect! mapSelect) {
+ return Gen.Select(this.args, this.typeArgs);
+ }
+
+ public VCExpr! Visit(MapStore! mapStore) {
+ return Gen.Store(this.args, this.typeArgs);
+ }
+
+ public VCExpr! Visit(TypeCoercion! typeCoercion) {
+ assert this.args.Count == 1;
+ return this.args[0];
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////
+
+ private VCExpr! TranslateBinaryOperator(BinaryOperator! app, List<VCExpr!>! args) {
+ assert args.Count == 2;
+
+ switch (app.Op) {
+ case BinaryOperator.Opcode.Add:
+ return Gen.Function(VCExpressionGenerator.AddOp, args);
+ case BinaryOperator.Opcode.Sub:
+ return Gen.Function(VCExpressionGenerator.SubOp, args);
+ case BinaryOperator.Opcode.Mul:
+ return Gen.Function(VCExpressionGenerator.MulOp, args);
+ case BinaryOperator.Opcode.Div:
+ return Gen.Function(VCExpressionGenerator.DivOp, args);
+ case BinaryOperator.Opcode.Mod:
+ return Gen.Function(VCExpressionGenerator.ModOp, args);
+ case BinaryOperator.Opcode.Eq:
+ case BinaryOperator.Opcode.Iff:
+ // we don't distinguish between equality and equivalence at this point
+ return Gen.Function(VCExpressionGenerator.EqOp, args);
+ case BinaryOperator.Opcode.Neq:
+ return Gen.Function(VCExpressionGenerator.NeqOp, args);
+ case BinaryOperator.Opcode.Lt:
+ return Gen.Function(VCExpressionGenerator.LtOp, args);
+ case BinaryOperator.Opcode.Le:
+ return Gen.Function(VCExpressionGenerator.LeOp, args);
+ case BinaryOperator.Opcode.Ge:
+ return Gen.Function(VCExpressionGenerator.GeOp, args);
+ case BinaryOperator.Opcode.Gt:
+ return Gen.Function(VCExpressionGenerator.GtOp, args);
+ case BinaryOperator.Opcode.Imp:
+ return Gen.Function(VCExpressionGenerator.ImpliesOp, args);
+ case BinaryOperator.Opcode.And:
+ return Gen.Function(VCExpressionGenerator.AndOp, args);
+ case BinaryOperator.Opcode.Or:
+ return Gen.Function(VCExpressionGenerator.OrOp, args);
+ case BinaryOperator.Opcode.Subtype:
+ return Gen.Function(VCExpressionGenerator.SubtypeOp, args);
+ default:
+ assert false; // unexpected binary operator
+ }
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////
+
+ private VCExpr! TranslateFunctionCall(FunctionCall! app,
+ List<VCExpr!>! args, List<Type!>! typeArgs) {
+ assert app.Func != null; // resolution must have happened
+
+ VCExpr res = ApplyExpansion(app, args, typeArgs);
+ if (res != null)
+ return res;
+
+ VCExprOp! functionOp = Gen.BoogieFunctionOp(app.Func);
+ return Gen.Function(functionOp, args, typeArgs);
+ }
+
+ private VCExpr ApplyExpansion(FunctionCall! app,
+ List<VCExpr!>! args, List<Type!>! typeArgs) {
+ assert app.Func != null; // resolution must have happened
+
+ if (app.Func.doingExpansion) {
+ System.Console.WriteLine("*** detected expansion loop on {0}", app.Func);
+ return null;
+ }
+
+ Expansion exp = FindExpansion(app.Func);
+ if (exp == null)
+ return null;
+
+ VCExpr! translatedBody;
+ VCExprSubstitution! subst = new VCExprSubstitution();
+ try {
+ BaseTranslator.PushFormalsScope();
+ BaseTranslator.PushBoundVariableScope();
+ app.Func.doingExpansion = true;
+
+ // first bind the formals to VCExpr variables, which are later
+ // substituted with the actual parameters
+ for (int i = 0; i < exp.formals.Length; ++i)
+ subst[BaseTranslator.BindVariable((!)exp.formals[i])] = args[i];
+
+ // recursively translate the body of the expansion
+ translatedBody = BaseTranslator.Translate(exp.body);
+ } finally {
+ BaseTranslator.PopFormalsScope();
+ BaseTranslator.PopBoundVariableScope();
+ app.Func.doingExpansion = false;
+ }
+
+ // substitute the formals with the actual parameters in the body
+ assert typeArgs.Count == exp.TypeParameters.Length;
+ for (int i = 0; i < typeArgs.Count; ++i)
+ subst[exp.TypeParameters[i]] = typeArgs[i];
+ SubstitutingVCExprVisitor! substituter = new SubstitutingVCExprVisitor (Gen);
+ return substituter.Mutate(translatedBody, subst);
+ }
+
+ private Expansion? FindExpansion(Function! func)
+ {
+ if (func.expansions == null) return null;
+
+ Expansion? exp = null;
+ foreach (Expansion! e in func.expansions) {
+ if (e.ignore == null || !GenerationOptions.IsAnyProverCommandSupported(e.ignore)) {
+ if (exp == null) {
+ exp = e;
+ } else {
+ System.Console.WriteLine("*** more than one possible expansion for {0}", func);
+ return null;
+ }
+ }
+ }
+
+ return exp;
+ }
+ }
+}
diff --git a/Source/VCExpr/Clustering.ssc b/Source/VCExpr/Clustering.ssc
new file mode 100644
index 00000000..7692ceb1
--- /dev/null
+++ b/Source/VCExpr/Clustering.ssc
@@ -0,0 +1,449 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using System;
+using System.Text;
+using System.IO;
+using System.Collections;
+using System.Collections.Generic;
+using Microsoft.Contracts;
+using Microsoft.Basetypes;
+using Microsoft.Boogie.VCExprAST;
+
+// Code for managing and clusterings sets of terms; this is used to
+// compress the input given to the theorem prover
+
+namespace Microsoft.Boogie.Clustering
+{
+ using Microsoft.Boogie.VCExprAST;
+
+
+ public class SubtermCollector : BoundVarTraversingVCExprVisitor<bool, bool> {
+
+ private readonly VCExpressionGenerator! Gen;
+
+ public SubtermCollector(VCExpressionGenerator! gen) {
+ Gen = gen;
+ }
+
+ // variables that are global and treated like constants
+ private readonly IDictionary<VCExprVar!, VCExprVar!>! GlobalVariables =
+ new Dictionary<VCExprVar!, VCExprVar!> ();
+
+ private readonly IDictionary<VCExprOp!, TermClustersSameHead!>! SubtermClusters =
+ new Dictionary<VCExprOp!, TermClustersSameHead!> ();
+
+ public void UnifyClusters() {
+ foreach (KeyValuePair<VCExprOp!, TermClustersSameHead!> pair
+ in SubtermClusters)
+ pair.Value.UnifyClusters();
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ protected override bool StandardResult(VCExpr! node, bool arg) {
+ return false; // by default, do not collect terms containing node
+ }
+
+ public override bool Visit(VCExprLiteral! node, bool arg) {
+ return true;
+ }
+
+ public override bool Visit(VCExprNAry! node, bool arg) {
+ VCExprBoogieFunctionOp op = node.Op as VCExprBoogieFunctionOp;
+ if (op == null) {
+ base.Visit(node, arg);
+ return false;
+ }
+
+ bool res = true;
+ foreach (VCExpr! subexpr in node)
+ res &= this.Traverse(subexpr, arg);
+
+ if (res) {
+ TermClustersSameHead clusters;
+ if (!SubtermClusters.TryGetValue(op, out clusters)) {
+ clusters = new TermClustersSameHead(op, GlobalVariables, Gen);
+ SubtermClusters.Add(op, clusters);
+ }
+ ((!)clusters).AddExpr(node);
+ }
+
+ return res;
+ }
+
+ public override bool Visit(VCExprVar! node, bool arg) {
+ if (!BoundTermVars.Contains(node))
+ GlobalVariables[node] = node;
+ return true;
+ }
+
+ [Pure]
+ public override string! ToString()
+ {
+ string! res = "";
+ foreach (KeyValuePair<VCExprOp!, TermClustersSameHead!> pair
+ in SubtermClusters)
+ res = res + pair.Value + "\n";
+ return res;
+ }
+ }
+
+ //////////////////////////////////////////////////////////////////////////////
+
+ // Class for managing and clustering a set of terms that all start
+ // with the same function symbol
+ internal class TermClustersSameHead {
+
+ public readonly VCExprOp! Op;
+ private readonly VCExpressionGenerator! Gen;
+
+ public TermClustersSameHead(VCExprOp! op,
+ IDictionary<VCExprVar!, VCExprVar!>! globalVars,
+ VCExpressionGenerator! gen) {
+ Op = op;
+ GlobalVariables = globalVars;
+ Gen = gen;
+ }
+
+ // variables that are global and treated like constants
+ private readonly IDictionary<VCExprVar!, VCExprVar!>! GlobalVariables;
+
+ private readonly List<Cluster>! Clusters = new List<Cluster> ();
+
+ private struct Cluster {
+ public readonly VCExprNAry! Generator;
+ public readonly int Size;
+
+ public Cluster(VCExprNAry! generator, int size) {
+ Generator = generator;
+ Size = size;
+ }
+ }
+
+ private int Distance(Cluster a, Cluster b) {
+ AntiUnificationVisitor! visitor = new AntiUnificationVisitor (Gen);
+ visitor.AntiUnify(a.Generator, b.Generator);
+
+ int reprSizeA, reprSizeB;
+ visitor.RepresentationSize(GlobalVariables, out reprSizeA, out reprSizeB);
+ return (a.Size - 1) * reprSizeA + (b.Size - 1) * reprSizeB;
+ }
+
+ private bool EqualUpToRenaming(Cluster a, Cluster b) {
+ AntiUnificationVisitor! visitor = new AntiUnificationVisitor (Gen);
+ visitor.AntiUnify(a.Generator, b.Generator);
+ return visitor.RepresentationIsRenaming(GlobalVariables);
+ }
+
+ private Cluster Merge(Cluster a, Cluster b) {
+ AntiUnificationVisitor! visitor = new AntiUnificationVisitor (Gen);
+ VCExpr! generator = visitor.AntiUnify(a.Generator, b.Generator);
+ VCExprNAry generatorNAry = generator as VCExprNAry;
+ assert generatorNAry != null && Op.Equals(generatorNAry.Op);
+ return new Cluster(generatorNAry, a.Size + b.Size);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ public void AddExpr(VCExprNAry! expr)
+ requires Op.Equals(expr.Op); {
+
+ Cluster c = new Cluster (expr, 1);
+ for (int i = 0; i < Clusters.Count; ++i) {
+ Cluster d = Clusters[i];
+ if (EqualUpToRenaming(c, d)) {
+ Clusters[i] = new Cluster (d.Generator, d.Size + 1);
+ return;
+ }
+ }
+
+ Clusters.Add(c);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ private struct ClusteringMatrix {
+
+ private readonly VCExpressionGenerator! Gen;
+ private readonly IDictionary<VCExprVar!, VCExprVar!>! GlobalVariables;
+
+ public readonly List<Cluster>! Clusters;
+ public readonly bool[]! RemainingClusters;
+
+ public readonly Distance[,]! Distances;
+
+ public struct Distance {
+ public readonly int Dist;
+ public readonly VCExprNAry! Generator;
+
+ public Distance(Cluster a, Cluster b,
+ IDictionary<VCExprVar!, VCExprVar!>! globalVars,
+ VCExpressionGenerator! gen) {
+ AntiUnificationVisitor! visitor = new AntiUnificationVisitor (gen);
+ Generator = (VCExprNAry)visitor.AntiUnify(a.Generator, b.Generator);
+
+ int reprSizeA, reprSizeB;
+ visitor.RepresentationSize(globalVars, out reprSizeA, out reprSizeB);
+ Dist = (a.Size - 1) * reprSizeA + (b.Size - 1) * reprSizeB;
+ }
+ }
+
+ public ClusteringMatrix(List<Cluster>! clusters,
+ IDictionary<VCExprVar!, VCExprVar!>! globalVars,
+ VCExpressionGenerator! gen) {
+ List<Cluster>! c = new List<Cluster> ();
+ c.AddRange(clusters);
+ Clusters = c;
+
+ GlobalVariables = globalVars;
+ Gen = gen;
+
+ bool[] remaining = new bool [clusters.Count];
+ RemainingClusters = remaining;
+ for (int i = 0; i < remaining.Length; ++i)
+ remaining[i] = true;
+
+ Distance[,]! distances = new Distance [clusters.Count, clusters.Count];
+ Distances = distances;
+ for (int i = 1; i < clusters.Count; ++i)
+ for (int j = 0; j < i; ++j)
+ distances[i, j] =
+ new Distance (clusters[i], clusters[j], GlobalVariables, Gen);
+ }
+
+ public void UnifyClusters(int maxDist) {
+ while (true) {
+ int i, j;
+ int minDist = FindMinDistance(out i, out j);
+
+ if (minDist > maxDist)
+ return;
+
+ MergeClusters(i, j);
+ }
+ }
+
+ public void ResultingClusters(List<Cluster>! clusters) {
+ clusters.Clear();
+ for (int i = 0; i < Clusters.Count; ++i)
+ if (RemainingClusters[i])
+ clusters.Add(Clusters[i]);
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+
+ private void Update(int i) {
+ for (int j = 0; j < i; ++j) {
+ if (RemainingClusters[j])
+ Distances[i, j] =
+ new Distance (Clusters[i], Clusters[j], GlobalVariables, Gen);
+ }
+ for (int j = i + 1; j < Clusters.Count; ++j) {
+ if (RemainingClusters[j])
+ Distances[j, i] =
+ new Distance (Clusters[j], Clusters[i], GlobalVariables, Gen);
+ }
+ }
+
+ private int FindMinDistance(out int c0, out int c1) {
+ int minDist = int.MaxValue;
+ c0 = -1;
+ c1 = -1;
+
+ for (int i = 0; i < Clusters.Count; ++i)
+ if (RemainingClusters[i]) {
+ for (int j = 0; j < i; ++j)
+ if (RemainingClusters[j]) {
+ if (Distances[i, j].Dist < minDist) {
+ minDist = Distances[i, j].Dist;
+ c0 = i;
+ c1 = j;
+ }
+ }
+ }
+
+ assert c0 == -1 && c1 == -1 || c0 > c1 && c1 >= 0;
+ return minDist;
+ }
+
+ private void MergeClusters(int i, int j)
+ requires j >= 0 && i > j &&
+ RemainingClusters[i] && RemainingClusters[j]; {
+ Clusters[i] = new Cluster (Distances[i, j].Generator,
+ Clusters[i].Size + Clusters[j].Size);
+ RemainingClusters[j] = false;
+ Update(i);
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ public void UnifyClusters() {
+ ClusteringMatrix matrix =
+ new ClusteringMatrix (Clusters, GlobalVariables, Gen);
+ matrix.UnifyClusters(50);
+ matrix.ResultingClusters(Clusters);
+ }
+
+ [Pure]
+ public override string! ToString()
+ {
+ string! res = "";
+ foreach (Cluster c in Clusters)
+ res = res + c.Generator + "\t" + c.Size + "\n";
+ return res;
+ }
+ }
+
+ //////////////////////////////////////////////////////////////////////////////
+
+ internal class AntiUnificationVisitor : TraversingVCExprVisitor<VCExpr!, VCExpr!> {
+
+ private readonly VCExpressionGenerator! Gen;
+
+ public AntiUnificationVisitor(VCExpressionGenerator! gen) {
+ Gen = gen;
+ }
+
+ // Sub-expressions in the first and second expression to be
+ // anti-unified that are replaced with variables
+ private readonly IDictionary<ExprPair, VCExprVar!>! Representation =
+ new Dictionary<ExprPair, VCExprVar!> ();
+
+ private struct ExprPair {
+ public readonly VCExpr! Expr0, Expr1;
+ public ExprPair(VCExpr! expr0, VCExpr! expr1) {
+ Expr0 = expr0;
+ Expr1 = expr1;
+ }
+ [Pure][Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals(object that) {
+ if (that is ExprPair) {
+ ExprPair thatPair = (ExprPair)that;
+ return this.Expr0.Equals(thatPair.Expr0) &&
+ this.Expr1.Equals(thatPair.Expr1);
+ }
+ return false;
+ }
+ [Pure]
+ public override int GetHashCode() {
+ return Expr0.GetHashCode() + Expr1.GetHashCode() * 13;
+ }
+ }
+
+ public void Reset() {
+ Representation.Clear ();
+ }
+
+ public bool RepresentationIsRenaming(IDictionary<VCExprVar!, VCExprVar!>! globalVars) {
+ if (!forall{KeyValuePair<ExprPair, VCExprVar!> pair in Representation;
+ pair.Key.Expr0 is VCExprVar &&
+ pair.Key.Expr1 is VCExprVar &&
+ !globalVars.ContainsKey((VCExprVar!)pair.Key.Expr0) &&
+ !globalVars.ContainsKey((VCExprVar!)pair.Key.Expr1)})
+ return false;
+ // check that all substituted variables are distinct
+ // TODO: optimise
+ return
+ forall{KeyValuePair<ExprPair, VCExprVar!> pair1 in Representation;
+ forall{KeyValuePair<ExprPair, VCExprVar!> pair2 in Representation;
+ pair1.Value.Equals(pair2.Value) || !pair1.Key.Expr0.Equals(pair2.Key.Expr0)
+ && !pair1.Key.Expr1.Equals(pair2.Key.Expr1)
+ }};
+ }
+
+ public void RepresentationSize(IDictionary<VCExprVar!, VCExprVar!>! globalVars,
+ out int expr0Size, out int expr1Size) {
+ ReprSizeComputingVisitor! size0Visitor = new ReprSizeComputingVisitor ();
+ ReprSizeComputingVisitor! size1Visitor = new ReprSizeComputingVisitor ();
+
+ foreach (KeyValuePair<ExprPair, VCExprVar!> pair in Representation) {
+ size0Visitor.ComputeSize(pair.Key.Expr0, globalVars);
+ size1Visitor.ComputeSize(pair.Key.Expr1, globalVars);
+ }
+
+ expr0Size = size0Visitor.Size;
+ expr1Size = size1Visitor.Size;
+ }
+
+ public VCExpr! AntiUnify(VCExpr! s, VCExpr! t)
+ requires s.Type.Equals(t.Type); {
+ return Traverse(s, t);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ private VCExprVar! AbstractWithVariable(VCExpr! s, VCExpr! t)
+ requires s.Type.Equals(t.Type); {
+
+ ExprPair pair = new ExprPair (s, t);
+ VCExprVar repr;
+ if (!Representation.TryGetValue(pair, out repr)) {
+ repr = Gen.Variable("abs" + Representation.Count, s.Type);
+ Representation.Add(pair, repr);
+ }
+ return (!)repr;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ public override VCExpr! Visit(VCExprLiteral! node, VCExpr! that) {
+ if (node.Equals(that))
+ return node;
+ return AbstractWithVariable(node, that);
+ }
+
+ public override VCExpr! Visit(VCExprNAry! node, VCExpr! that) {
+ VCExprNAry thatNAry = that as VCExprNAry;
+ if (thatNAry != null && node.Op.Equals(thatNAry.Op)) {
+ // type parameters should already have been eliminated at this
+ // stage
+ assert node.TypeParamArity == 0 && thatNAry.TypeParamArity == 0 &&
+ node.Arity == thatNAry.Arity;
+
+ List<VCExpr!>! unifiedArgs = new List<VCExpr!> ();
+ for (int i = 0; i < node.Arity; ++i)
+ unifiedArgs.Add(Traverse(node[i], thatNAry[i]));
+
+ return Gen.Function(node.Op, unifiedArgs);
+ }
+ return AbstractWithVariable(node, that);
+ }
+
+ public override VCExpr! Visit(VCExprVar! node, VCExpr! that) {
+ if (node.Equals(that))
+ return node;
+ return AbstractWithVariable(node, that);
+ }
+
+ protected override VCExpr! StandardResult(VCExpr! node, VCExpr! that) {
+ assert false; // not handled here
+ }
+ }
+
+ //////////////////////////////////////////////////////////////////////////////
+
+ internal class ReprSizeComputingVisitor
+ : TraversingVCExprVisitor<bool,
+ // variables considered as global constants
+ IDictionary<VCExprVar!, VCExprVar!>!> {
+
+ public int Size = 0;
+
+ public void ComputeSize(VCExpr! expr,
+ IDictionary<VCExprVar!, VCExprVar!>! globalVars) {
+ Traverse(expr, globalVars);
+ }
+
+ protected override bool StandardResult(VCExpr! node,
+ IDictionary<VCExprVar!, VCExprVar!>! globalVars) {
+ VCExprVar nodeAsVar = node as VCExprVar;
+ if (nodeAsVar == null || globalVars.ContainsKey(nodeAsVar))
+ Size = Size + 1;
+ return true;
+ }
+ }
+} \ No newline at end of file
diff --git a/Source/VCExpr/LetBindingSorter.ssc b/Source/VCExpr/LetBindingSorter.ssc
new file mode 100644
index 00000000..96eb0af2
--- /dev/null
+++ b/Source/VCExpr/LetBindingSorter.ssc
@@ -0,0 +1,135 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using System;
+using System.Text;
+using System.IO;
+using System.Collections;
+using System.Collections.Generic;
+using Microsoft.Contracts;
+using Microsoft.Basetypes;
+
+// Sort the bindings in a let-expression so that terms bound earlier do
+// not contain variables bound later
+
+namespace Microsoft.Boogie.VCExprAST
+{
+
+ // (argument is not used)
+ public class LetBindingSorter : MutatingVCExprVisitor<bool> {
+
+ private readonly FreeVariableCollector! FreeVarCollector =
+ new FreeVariableCollector ();
+
+ private List<VCExprVar!>! FreeVarsIn(VCExpr! expr) {
+ FreeVarCollector.Collect(expr);
+ List<VCExprVar!>! freeVars = new List<VCExprVar!> (FreeVarCollector.FreeTermVars.Keys);
+ FreeVarCollector.Reset();
+ return freeVars;
+ }
+
+ public LetBindingSorter(VCExpressionGenerator! gen) {
+ base(gen);
+ }
+
+ public override VCExpr! Visit(VCExprLet! node, bool arg) {
+ IDictionary<VCExprVar!, Binding!> boundVars =
+ new Dictionary<VCExprVar!, Binding!> ();
+
+ // recurse and collect the free variables in bound terms and formulae
+ foreach (VCExprLetBinding! binding in node) {
+ VCExpr! newE = Mutate(binding.E, arg);
+ Binding! b = new Binding (binding.V, newE, FreeVarsIn(newE));
+ boundVars.Add(b.V, b);
+ }
+
+ // generate the occurrence edges
+ foreach (KeyValuePair<VCExprVar!, Binding!> pair in boundVars) {
+ Binding! b = pair.Value;
+ foreach (VCExprVar! v in b.FreeVars) {
+ Binding b2;
+ if (boundVars.TryGetValue(v, out b2)) {
+ ((!)b2).Occurrences.Add(b);
+ b.InvOccurrencesNum = b.InvOccurrencesNum + 1;
+ }
+ }
+ }
+
+ // topological sort
+ Stack<Binding!> rootBindings = new Stack<Binding!> ();
+ foreach (KeyValuePair<VCExprVar!, Binding!> pair in boundVars)
+ if (pair.Value.InvOccurrencesNum == 0)
+ rootBindings.Push(pair.Value);
+
+ List<Binding!>! sortedBindings = new List<Binding!> ();
+ while (rootBindings.Count > 0) {
+ Binding! b = rootBindings.Pop();
+ sortedBindings.Add(b);
+ foreach (Binding! b2 in b.Occurrences) {
+ b2.InvOccurrencesNum = b2.InvOccurrencesNum - 1;
+ if (b2.InvOccurrencesNum == 0)
+ rootBindings.Push(b2);
+ }
+ }
+
+ if (exists{KeyValuePair<VCExprVar!, Binding!> pair in boundVars;
+ pair.Value.InvOccurrencesNum > 0})
+ System.Diagnostics.Debug.Fail("Cyclic let-bindings");
+
+ assert node.Length == sortedBindings.Count;
+
+ // check which of the bindings can be dropped
+ VCExpr! newBody = Mutate(node.Body, arg);
+
+ IDictionary<VCExprVar!, VCExprVar!>! usedVars =
+ new Dictionary<VCExprVar!, VCExprVar!> ();
+ foreach (VCExprVar! v in FreeVarsIn(newBody))
+ if (!usedVars.ContainsKey(v))
+ usedVars.Add(v, v);
+
+ for (int i = sortedBindings.Count - 1; i >= 0; --i) {
+ if (usedVars.ContainsKey(sortedBindings[i].V)) {
+ foreach (VCExprVar! v in sortedBindings[i].FreeVars)
+ if (!usedVars.ContainsKey(v))
+ usedVars.Add(v, v);
+ } else {
+ sortedBindings.RemoveAt(i);
+ }
+ }
+
+ // assemble the resulting let-expression
+ List<VCExprLetBinding!>! newBindings = new List<VCExprLetBinding!> ();
+ foreach (Binding b in sortedBindings)
+ newBindings.Add(Gen.LetBinding(b.V, b.E));
+
+ return Gen.Let(newBindings, newBody);
+ }
+
+ private class Binding {
+ public readonly VCExprVar! V;
+ public readonly VCExpr! E;
+ public readonly List<VCExprVar!>! FreeVars;
+
+ // list of all bound expression in which the variable V occurs
+ // (outgoing edges)
+ public readonly List<Binding>! Occurrences;
+
+ // number of variables that are bound in this let-expression
+ // and that occur in FreeVars
+ // (incoming edges)
+ public int InvOccurrencesNum;
+
+ public Binding(VCExprVar! v, VCExpr! e, List<VCExprVar!>! freeVars) {
+ this.V = v;
+ this.E = e;
+ this.FreeVars = freeVars;
+ this.Occurrences = new List<Binding> ();
+ this.InvOccurrencesNum = 0;
+ }
+ }
+
+ }
+
+}
diff --git a/Source/VCExpr/NameClashResolver.ssc b/Source/VCExpr/NameClashResolver.ssc
new file mode 100644
index 00000000..28a974a6
--- /dev/null
+++ b/Source/VCExpr/NameClashResolver.ssc
@@ -0,0 +1,129 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using System;
+using System.Text;
+using System.IO;
+using System.Collections;
+using System.Collections.Generic;
+using Microsoft.Contracts;
+using Microsoft.Basetypes;
+
+// Visitor that establishes unique variable (or constant) names in a VCExpr.
+// This is done by adding a counter as suffix if name clashes occur
+
+// TODO: also handle type variables here
+
+namespace Microsoft.Boogie.VCExprAST {
+ using TEHelperFuns = Microsoft.Boogie.TypeErasure.HelperFuns;
+
+ public class UniqueNamer : ICloneable {
+
+ public UniqueNamer() {
+ GlobalNames = new Dictionary<Object!, string!> ();
+ LocalNames = TEHelperFuns.ToList(new Dictionary<Object!, string!> ()
+ as IDictionary<Object!, string!>);
+ UsedNames = new Dictionary<string!, bool> ();
+ CurrentCounters = new Dictionary<string!, int> ();
+ }
+
+ private UniqueNamer(UniqueNamer! namer) {
+ GlobalNames = new Dictionary<Object!, string!> (namer.GlobalNames);
+
+ List<IDictionary<Object!, string!>!>! localNames =
+ new List<IDictionary<Object!, string!>!> ();
+ LocalNames = localNames;
+
+ foreach (IDictionary<Object!, string!>! d in namer.LocalNames)
+ localNames.Add(new Dictionary<Object!, string!> (d));
+
+ UsedNames = new Dictionary<string!, bool> (namer.UsedNames);
+ CurrentCounters = new Dictionary<string!, int> (namer.CurrentCounters);
+ }
+
+ public Object! Clone() {
+ return new UniqueNamer (this);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ private readonly IDictionary<Object!, string!>! GlobalNames;
+ private readonly List<IDictionary<Object!, string!>!>! LocalNames;
+
+ // dictionary of all names that have already been used
+ // (locally or globally)
+ private readonly IDictionary<string!, bool>! UsedNames;
+ private readonly IDictionary<string!, int>! CurrentCounters;
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ public void PushScope() {
+ LocalNames.Add(new Dictionary<Object!, string!> ());
+ }
+
+ public void PopScope() {
+ LocalNames.RemoveAt(LocalNames.Count - 1);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ private string! NextFreeName(string! baseName) {
+ string! candidate;
+ int counter;
+
+ if (CurrentCounters.TryGetValue(baseName, out counter)) {
+ candidate = baseName + "@@" + counter;
+ counter = counter + 1;
+ } else {
+ candidate = baseName;
+ counter = 0;
+ }
+
+ bool dummy;
+ while (UsedNames.TryGetValue(candidate, out dummy)) {
+ candidate = baseName + "@@" + counter;
+ counter = counter + 1;
+ }
+
+ UsedNames.Add(candidate, true);
+ CurrentCounters[baseName] = counter;
+ return candidate;
+ }
+
+ // retrieve the name of a thingie; if it does not have a name yet,
+ // generate a unique name for it (as close as possible to its inherent
+ // name) and register it globally
+ public string! GetName(Object! thingie, string! inherentName) {
+ string res = this[thingie];
+
+ if (res != null)
+ return res;
+
+ // if the object is not yet registered, create a name for it
+ res = NextFreeName(inherentName);
+ GlobalNames.Add(thingie, res);
+
+ return res;
+ }
+
+ [Pure]
+ public string this[Object! thingie] { get {
+ string res;
+ for (int i = LocalNames.Count - 1; i >= 0; --i) {
+ if (LocalNames[i].TryGetValue(thingie, out res))
+ return res;
+ }
+
+ GlobalNames.TryGetValue(thingie, out res);
+ return res;
+ } }
+
+ public string! GetLocalName(Object! thingie, string! inherentName) {
+ string! res = NextFreeName(inherentName);
+ LocalNames[LocalNames.Count - 1][thingie] = res;
+ return res;
+ }
+ }
+}
diff --git a/Source/VCExpr/SimplifyLikeLineariser.ssc b/Source/VCExpr/SimplifyLikeLineariser.ssc
new file mode 100644
index 00000000..7aff8e87
--- /dev/null
+++ b/Source/VCExpr/SimplifyLikeLineariser.ssc
@@ -0,0 +1,795 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using System;
+using System.Text;
+using System.IO;
+using System.Collections;
+using System.Collections.Generic;
+using Microsoft.Contracts;
+using Microsoft.Basetypes;
+using Microsoft.Boogie.VCExprAST;
+
+// a naive method to turn VCExprs into strings that can be fed into Simplify
+
+namespace Microsoft.Boogie.VCExprAST
+{
+
+ // Options for the linearisation. Here one can choose, for instance,
+ // whether Simplify or Z3 output is to be produced
+ public abstract class LineariserOptions {
+
+ public readonly bool AsTerm;
+ public abstract LineariserOptions! SetAsTerm(bool newVal);
+
+ public abstract bool QuantifierIds { get; }
+
+ public virtual bool UseWeights { get { return false; } }
+
+ public virtual bool InverseImplies { get { return false; } }
+
+ // whether to include type specifications in quantifiers
+ public abstract bool UseTypes { get; }
+
+ public virtual CommandLineOptions.BvHandling Bitvectors { get {
+ return CommandLineOptions.BvHandling.None;
+ } }
+
+ // variables representing formulas in let-bindings have to be
+ // printed in a different way than other variables
+ public virtual List<VCExprVar!>! LetVariables { get {
+ return EmptyList;
+ } }
+
+ public virtual LineariserOptions! AddLetVariable(VCExprVar! furtherVar) {
+ return this;
+ }
+
+ private static readonly List<VCExprVar!>! EmptyList = new List<VCExprVar!>();
+
+ public bool NativeBv { get {
+ return Bitvectors == CommandLineOptions.BvHandling.Z3Native;
+ } }
+
+ public bool IntBv { get {
+ return Bitvectors == CommandLineOptions.BvHandling.ToInt;
+ } }
+
+ ////////////////////////////////////////////////////////////////////////////////////////
+
+ protected LineariserOptions(bool asTerm) {
+ this.AsTerm = asTerm;
+ }
+
+ public static readonly LineariserOptions! SimplifyDefault = new SimplifyOptions (false);
+ internal static readonly LineariserOptions! SimplifyDefaultTerm = new SimplifyOptions (true);
+
+ ////////////////////////////////////////////////////////////////////////////////////////
+
+ private class SimplifyOptions : LineariserOptions {
+ internal SimplifyOptions(bool asTerm) {
+ base(asTerm);
+ }
+ public override bool QuantifierIds { get {
+ return false;
+ } }
+ public override bool UseTypes { get {
+ return false;
+ } }
+ public override LineariserOptions! SetAsTerm(bool newVal) {
+ if (newVal)
+ return SimplifyDefaultTerm;
+ else
+ return SimplifyDefault;
+ }
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////////////
+
+ // Lineariser for expressions. The result (bool) is currently not used for anything
+ public class SimplifyLikeExprLineariser : IVCExprVisitor<bool, LineariserOptions!> {
+
+ public static string! ToSimplifyString(VCExpr! e, UniqueNamer! namer) {
+ StringWriter sw = new StringWriter();
+ SimplifyLikeExprLineariser! lin = new SimplifyLikeExprLineariser (sw, namer);
+ lin.Linearise(e, LineariserOptions.SimplifyDefault);
+ return (!)sw.ToString();
+ }
+
+ public static string! ToString(VCExpr! e, LineariserOptions! options,
+ UniqueNamer! namer) {
+ StringWriter sw = new StringWriter();
+ SimplifyLikeExprLineariser! lin = new SimplifyLikeExprLineariser (sw, namer);
+ lin.Linearise(e, options);
+ return (!)sw.ToString();
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////////////
+
+ private readonly TextWriter! wr;
+ private SimplifyLikeOpLineariser OpLinObject = null;
+ private IVCExprOpVisitor<bool, LineariserOptions!>! OpLineariser { get {
+ if (OpLinObject == null)
+ OpLinObject = new SimplifyLikeOpLineariser (this, wr);
+ return OpLinObject;
+ } }
+
+ internal readonly UniqueNamer! Namer;
+
+ public SimplifyLikeExprLineariser(TextWriter! wr, UniqueNamer! namer) {
+ this.wr = wr;
+ this.Namer = namer;
+ }
+
+ public void Linearise(VCExpr! expr, LineariserOptions! options) {
+ expr.Accept<bool, LineariserOptions!>(this, options);
+ }
+
+ public void LineariseAsTerm(VCExpr! expr, LineariserOptions! options) {
+ Linearise(expr, options.SetAsTerm(true));
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////////
+
+ public static string! MakeIdPrintable(string! s) {
+ // make sure that no keywords are used as identifiers
+ switch(s) {
+ case andName:
+ case orName:
+ case notName:
+ case impliesName:
+ case iffName:
+ case eqName:
+ case neqName:
+ case distinctName:
+ case TRUEName:
+ case FALSEName:
+ s = "nonkeyword_" + s;
+ break;
+ }
+
+ if (CommandLineOptions.Clo.BracketIdsInVC == 0) {
+ // In this form, we go with any identifier, so we don't ever bother about brackets.
+ // Except: @true and @false are always written with brackets
+ return s;
+ }
+ bool looksLikeOperator = true;
+ bool looksLikeSimpleId = true;
+ bool useBrackets = false;
+ foreach (char ch in s) {
+ switch (ch) {
+ case '=':
+ case '<':
+ case '>':
+ case '+':
+ case '-':
+ case '*':
+ case '/':
+ case '%':
+ case ':':
+ // looks like operator, not simple id
+ looksLikeSimpleId = false;
+ break;
+ default:
+ if (Char.IsLetterOrDigit(ch)) {
+ // looks like simple id, not operator
+ looksLikeOperator = false;
+ } else {
+ // looks like neither operator nor simple id
+ looksLikeOperator = false;
+ looksLikeSimpleId = false;
+ }
+ break;
+ }
+ if (!looksLikeOperator && !looksLikeSimpleId) {
+ useBrackets = true;
+ break;
+ }
+ }
+ if (useBrackets) {
+ return "|" + s + "|";
+ } else {
+ return s;
+ }
+ }
+
+ public static string! TypeToString(Type! t) {
+ if (t.IsBool)
+ return "$bool";
+ else if (t.IsInt)
+ return "$int";
+ else if (t.IsBv)
+ return "$bv" + t.BvBits;
+ else {
+ // at this point, only the types U, T, and bitvector types should be left
+ if (CommandLineOptions.Clo.TypeEncodingMethod == CommandLineOptions.TypeEncoding.Monomorphic)
+ return "U";
+ else {
+ System.IO.StringWriter buffer = new System.IO.StringWriter();
+ using (TokenTextWriter stream = new TokenTextWriter("<buffer>", buffer, false)) {
+ t.Emit(stream);
+ }
+ return buffer.ToString();
+ }
+ }
+ }
+
+ public static string! BvConcatOpName(VCExprNAry! node)
+ requires node.Op.Equals(VCExpressionGenerator.BvConcatOp); {
+ int bits1 = node[0].Type.BvBits;
+ int bits2 = node[1].Type.BvBits;
+ return "$bv" + (bits1 + bits2) + "_concat[" + bits1 + "." + bits2 + "]";
+ }
+
+ public static string! BvExtractOpName(VCExprNAry! node)
+ requires node.Op is VCExprBvExtractOp; {
+ VCExprBvExtractOp! op = (VCExprBvExtractOp)node.Op;
+ return "$bv" + node.Type.BvBits + "_extract[" + op.Start + ":" + op.End + "]";
+ }
+
+ internal void WriteId(string! s) {
+ wr.Write(MakeIdPrintable(s));
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////////
+
+ /// <summary>
+ /// The name for logical conjunction in Simplify
+ /// </summary>
+ internal const string! andName = "AND"; // conjunction
+ internal const string! orName = "OR"; // disjunction
+ internal const string! notName = "NOT"; // negation
+ internal const string! impliesName = "IMPLIES"; // implication
+ internal const string! iffName = "IFF"; // logical equivalence
+ internal const string! eqName = "EQ"; // equality
+ internal const string! neqName = "NEQ"; // inequality
+ internal const string! lessName = "<";
+ internal const string! greaterName = ">";
+ internal const string! atmostName = "<=";
+ internal const string! atleastName = ">=";
+ internal const string! TRUEName = "TRUE"; // nullary predicate that is always true
+ internal const string! FALSEName = "FALSE"; // nullary predicate that is always false
+ internal const string! subtypeName = "<:";
+ internal const string! subtypeArgsName = "<::";
+
+ internal const string! distinctName = "DISTINCT";
+ /// <summary>
+ /// name of the main inclusion relation
+ /// </summary>
+ internal const string! boolTrueName = "|@true|";
+ internal const string! boolFalseName = "|@false|";
+ internal const string! boolAndName = "boolAnd";
+ internal const string! boolOrName = "boolOr";
+ internal const string! boolNotName = "boolNot";
+ internal const string! termEqName = "anyEqual";
+ internal const string! termNeqName = "anyNeq";
+ internal const string! termLessName = "intLess";
+ internal const string! termGreaterName = "intGreater";
+ internal const string! termAtmostName = "intAtMost";
+ internal const string! termAtleastName = "intAtLeast";
+ internal const string! intAddName = "+";
+ internal const string! intAddNameReflect = "Reflect$Add";
+ internal const string! intSubName = "-";
+ internal const string! intMulName = "*";
+ internal const string! intDivName = "/";
+ internal const string! intModName = "%";
+
+ internal void AssertAsTerm(string! x, LineariserOptions! options) {
+ if (!options.AsTerm)
+ System.Diagnostics.Debug.Fail("One should never write " + x + " as a formula!");
+ }
+
+ internal void AssertAsFormula(string! x, LineariserOptions! options) {
+ if (options.AsTerm)
+ System.Diagnostics.Debug.Fail("One should never write " + x + " as a term!");
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////////
+
+ public bool Visit(VCExprLiteral! node, LineariserOptions! options) {
+ if (options.AsTerm) {
+
+ if (node == VCExpressionGenerator.True)
+ wr.Write(options.UseTypes ? TRUEName : boolTrueName);
+ else if (node == VCExpressionGenerator.False)
+ wr.Write(options.UseTypes ? FALSEName : boolFalseName);
+ else if (node is VCExprIntLit) {
+ wr.Write(((VCExprIntLit)node).Val);
+ } else
+ assert false;
+
+ } else {
+
+ if (node == VCExpressionGenerator.True)
+ wr.Write(TRUEName);
+ else if (node == VCExpressionGenerator.False)
+ wr.Write(FALSEName);
+ else if (node is VCExprIntLit) {
+ System.Diagnostics.Debug.Fail("One should never write IntLit as a predicate!");
+ } else
+ assert false;
+
+ }
+
+ return true;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////////
+
+ public bool Visit(VCExprNAry! node, LineariserOptions! options) {
+ VCExprOp! op = node.Op;
+
+ if (!options.AsTerm &&
+ (op.Equals(VCExpressionGenerator.AndOp) ||
+ op.Equals(VCExpressionGenerator.OrOp))) {
+ // handle these operators without recursion
+
+ wr.Write("({0}",
+ op.Equals(VCExpressionGenerator.AndOp) ? andName : orName);
+ IEnumerator! enumerator = new VCExprNAryUniformOpEnumerator (node);
+ while (enumerator.MoveNext()) {
+ VCExprNAry naryExpr = enumerator.Current as VCExprNAry;
+ if (naryExpr == null || !naryExpr.Op.Equals(op)) {
+ wr.Write(" ");
+ Linearise((VCExpr!)enumerator.Current, options);
+ }
+ }
+
+ wr.Write(")");
+
+ return true;
+ }
+
+ return node.Accept<bool, LineariserOptions!>(OpLineariser, options);
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////////
+
+ public bool Visit(VCExprVar! node, LineariserOptions! options) {
+ string! printedName = Namer.GetName(node, node.Name);
+
+ if (options.AsTerm ||
+ // variables for formulas bound in a let-binding are never
+ // written as an equation
+ options.LetVariables.Contains(node) ||
+ // if variables are properly typed, they cannot be written as
+ // equation either
+ options.UseTypes) {
+ WriteId(printedName);
+ } else {
+ wr.Write("({0} ", eqName);
+ WriteId(printedName);
+ wr.Write(" {0})", boolTrueName);
+ }
+
+ return true;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////////
+
+ public bool Visit(VCExprQuantifier! node, LineariserOptions! options) {
+ AssertAsFormula(node.Quan.ToString(), options);
+ assert node.TypeParameters.Count == 0;
+
+ Namer.PushScope(); try {
+
+ string! kind = node.Quan == Quantifier.ALL ? "FORALL" : "EXISTS";
+ wr.Write("({0} (", kind);
+
+ for (int i = 0; i < node.BoundVars.Count; i++)
+ {
+ VCExprVar! var = node.BoundVars[i];
+ string! printedName = Namer.GetLocalName(var, var.Name);
+ if (i != 0)
+ wr.Write(" ");
+ WriteId(printedName);
+ if (options.UseTypes)
+ wr.Write(" :TYPE {0}", TypeToString(var.Type));
+ }
+ wr.Write(") ");
+
+ WriteTriggers(node.Triggers, options);
+
+ if (options.QuantifierIds) {
+ // only needed for Z3
+ VCQuantifierInfos! infos = node.Infos;
+ if (infos.qid != null) {
+ wr.Write("(QID ");
+ wr.Write(infos.qid);
+ wr.Write(") ");
+ }
+ if (0 <= infos.uniqueId) {
+ wr.Write("(SKOLEMID ");
+ wr.Write(infos.uniqueId);
+ wr.Write(") ");
+ }
+ }
+
+ if (options.UseWeights) {
+ int weight = QKeyValue.FindIntAttribute(node.Infos.attributes, "weight", 1);
+ if (weight != 1) {
+ wr.Write("(WEIGHT ");
+ wr.Write(weight);
+ wr.Write(") ");
+ }
+ }
+
+ Linearise(node.Body, options);
+ wr.Write(")");
+
+ return true;
+
+ } finally {
+ Namer.PopScope();
+ }
+ }
+
+ private void WriteTriggers(List<VCTrigger!>! triggers, LineariserOptions! options) {
+ // first, count how many neg/pos triggers there are
+ int negTriggers = 0;
+ int posTriggers = 0;
+ foreach (VCTrigger! vcTrig in triggers) {
+ if (vcTrig.Pos) {
+ posTriggers++;
+ } else {
+ negTriggers++;
+ }
+ }
+
+ if (posTriggers > 0) {
+ wr.Write("(PATS");
+ foreach (VCTrigger! vcTrig in triggers) {
+ if (vcTrig.Pos) {
+ if (vcTrig.Exprs.Count > 1) {
+ wr.Write(" (MPAT");
+ }
+ foreach (VCExpr! e in vcTrig.Exprs) {
+ wr.Write(" ");
+ LineariseAsTerm(e, options);
+ }
+ if (vcTrig.Exprs.Count > 1) {
+ wr.Write(")");
+ }
+ }
+ }
+ wr.Write(") ");
+ } else if (negTriggers > 0) {
+ // if also positive triggers are given, the SMT solver (at least Z3)
+ // will ignore the negative patterns and output a warning. Therefore
+ // we never specify both negative and positive triggers
+ wr.Write("(NOPATS");
+ foreach (VCTrigger! vcTrig in triggers) {
+ if (!vcTrig.Pos) {
+ wr.Write(" ");
+ assert vcTrig.Exprs.Count == 1;
+ LineariseAsTerm(vcTrig.Exprs[0], options);
+ }
+ }
+ wr.Write(") ");
+ }
+
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////////
+
+ public bool Visit(VCExprLet! node, LineariserOptions! options) {
+ Namer.PushScope(); try {
+
+ wr.Write("(LET (");
+
+ LineariserOptions! optionsWithVars = options;
+ foreach (VCExprVar! var in node.BoundVars)
+ optionsWithVars = optionsWithVars.AddLetVariable(var);
+
+ string s = "(";
+ foreach (VCExprLetBinding! b in node) {
+ wr.Write(s);
+ string! printedName = Namer.GetLocalName(b.V, b.V.Name);
+
+ bool formula = b.V.Type.IsBool;
+ if (formula)
+ wr.Write("FORMULA ");
+ else
+ wr.Write("TERM ");
+ WriteId(printedName);
+ wr.Write(" ");
+ Linearise(b.E, optionsWithVars.SetAsTerm(!formula));
+ wr.Write(")");
+ s = " (";
+ }
+ wr.Write(") ");
+ Linearise(node.Body, optionsWithVars);
+ wr.Write(")");
+
+ return true;
+
+ } finally {
+ Namer.PopScope();
+ }
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////////
+
+ // Lineariser for operator terms. The result (bool) is currently not used for anything
+ internal class SimplifyLikeOpLineariser : IVCExprOpVisitor<bool, LineariserOptions!> {
+ private readonly SimplifyLikeExprLineariser! ExprLineariser;
+ private readonly TextWriter! wr;
+
+ public SimplifyLikeOpLineariser(SimplifyLikeExprLineariser! ExprLineariser, TextWriter! wr) {
+ this.ExprLineariser = ExprLineariser;
+ this.wr = wr;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////
+
+ private void WriteApplication(string! op, IEnumerable<VCExpr!>! args,
+ LineariserOptions! options,
+ bool argsAsTerms) {
+ WriteApplication(op, op, args, options, argsAsTerms);
+ }
+
+ private void WriteApplication(string! op, IEnumerable<VCExpr!>! args,
+ LineariserOptions! options) {
+ WriteApplication(op, op, args, options, options.AsTerm);
+ }
+
+ private void WriteTermApplication(string! op, IEnumerable<VCExpr!>! args,
+ LineariserOptions! options) {
+ ExprLineariser.AssertAsTerm(op, options);
+ WriteApplication(op, op, args, options, options.AsTerm);
+ }
+
+ private void WriteApplication(string! termOp, string! predOp,
+ IEnumerable<VCExpr!>! args, LineariserOptions! options) {
+ WriteApplication(termOp, predOp, args, options, options.AsTerm);
+ }
+
+ private void WriteApplication(string! termOp, string! predOp,
+ IEnumerable<VCExpr!>! args, LineariserOptions! options,
+ // change the AsTerm option for the arguments?
+ bool argsAsTerms) {
+ wr.Write("({0}", options.AsTerm ? termOp : predOp);
+
+ LineariserOptions! newOptions = options.SetAsTerm(argsAsTerms);
+ foreach (VCExpr! e in args) {
+ wr.Write(" ");
+ ExprLineariser.Linearise(e, newOptions);
+ }
+
+ wr.Write(")");
+ }
+
+ // write an application that can only be a term.
+ // if the expression is supposed to be printed as a formula,
+ // it is turned into an equation (EQ (f args) |@true|)
+ private void WriteApplicationTermOnly(string! termOp,
+ IEnumerable<VCExpr!>! args, LineariserOptions! options) {
+ if (!options.AsTerm)
+ // Write: (EQ (f args) |@true|)
+ // where "args" are written as terms
+ wr.Write("({0} ", eqName);
+
+ WriteApplication(termOp, args, options, true);
+
+ if (!options.AsTerm)
+ wr.Write(" {0})", boolTrueName);
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////
+
+ public bool VisitNotOp (VCExprNAry! node, LineariserOptions! options) {
+ WriteApplication(boolNotName, notName, node, options); // arguments can be both terms and formulas
+ return true;
+ }
+
+ public bool VisitEqOp (VCExprNAry! node, LineariserOptions! options) {
+ if (options.AsTerm) {
+ // use equality on terms, also if the arguments have type bool
+ WriteApplication(termEqName, node, options);
+ } else {
+ if (node[0].Type.IsBool) {
+ assert node[1].Type.IsBool;
+ // use equivalence
+ WriteApplication(iffName, node, options);
+ } else {
+ assert !node[1].Type.IsBool;
+ // use equality and write the arguments as terms
+ WriteApplication(eqName, node, options, true);
+ }
+ }
+
+ return true;
+ }
+
+ public bool VisitNeqOp (VCExprNAry! node, LineariserOptions! options) {
+ if (options.AsTerm) {
+ // use equality on terms, also if the arguments have type bool
+ WriteApplication(termNeqName, node, options);
+ } else {
+ if (node[0].Type.IsBool) {
+ assert node[1].Type.IsBool;
+ // use equivalence and negate the whole thing
+ wr.Write("({0} ", notName);
+ WriteApplication(iffName, node, options);
+ wr.Write(")");
+ } else {
+ // use equality and write the arguments as terms
+ WriteApplication(neqName, node, options, true);
+ }
+ }
+
+ return true;
+ }
+
+ public bool VisitAndOp (VCExprNAry! node, LineariserOptions! options) {
+ assert options.AsTerm;
+ WriteApplication(boolAndName, andName, node, options); // arguments can be both terms and formulas
+ return true;
+ }
+
+ public bool VisitOrOp (VCExprNAry! node, LineariserOptions! options) {
+ assert options.AsTerm;
+ WriteApplication(boolOrName, orName, node, options); // arguments can be both terms and formulas
+ return true;
+ }
+
+ public bool VisitImpliesOp (VCExprNAry! node, LineariserOptions! options) {
+ if (options.AsTerm) {
+ wr.Write("({0} ({1} ", boolOrName, boolNotName);
+ ExprLineariser.Linearise(node[0], options);
+ wr.Write(") ");
+ ExprLineariser.Linearise(node[1], options);
+ wr.Write(")");
+ } else if (options.InverseImplies) {
+ wr.Write("({0} ", orName);
+ ExprLineariser.Linearise(node[1], options);
+ wr.Write(" ({0} ", notName);
+ ExprLineariser.Linearise(node[0], options);
+ wr.Write("))");
+ } else {
+ WriteApplication(impliesName, node, options);
+ }
+ return true;
+ }
+
+ public bool VisitDistinctOp (VCExprNAry! node, LineariserOptions! options) {
+ ExprLineariser.AssertAsFormula(distinctName, options);
+
+ if (node.Length < 2) {
+ ExprLineariser.Linearise(VCExpressionGenerator.True, options);
+ } else {
+ wr.Write("({0}", distinctName);
+ foreach (VCExpr! e in node) {
+ wr.Write(" ");
+ ExprLineariser.LineariseAsTerm(e, options);
+ }
+ wr.Write(")");
+ }
+
+ return true;
+ }
+
+ public bool VisitLabelOp (VCExprNAry! node, LineariserOptions! options) {
+ VCExprLabelOp! op = (VCExprLabelOp)node.Op;
+ wr.Write(String.Format("({0} |{1}| ", op.pos ? "LBLPOS" : "LBLNEG", op.label));
+ ExprLineariser.Linearise(node[0], options); wr.Write(")");
+ return true;
+ }
+
+ public bool VisitSelectOp (VCExprNAry! node, LineariserOptions! options) {
+ assert false; // should not occur in the output
+ }
+
+ public bool VisitStoreOp (VCExprNAry! node, LineariserOptions! options) {
+ assert false; // should not occur in the output
+ }
+
+ public bool VisitBvOp (VCExprNAry! node, LineariserOptions! options) {
+ WriteTermApplication("$make_bv" + node.Type.BvBits, node, options);
+ return true;
+ }
+
+ public bool VisitBvExtractOp(VCExprNAry! node, LineariserOptions! options) {
+ WriteTermApplication(BvExtractOpName(node), node, options);
+ return true;
+ }
+
+ public bool VisitBvConcatOp (VCExprNAry! node, LineariserOptions! options) {
+ WriteTermApplication(BvConcatOpName(node), node, options);
+ return true;
+ }
+
+ public bool VisitAddOp (VCExprNAry! node, LineariserOptions! options) {
+ if (CommandLineOptions.Clo.ReflectAdd) {
+ WriteTermApplication(intAddNameReflect, node, options);
+ } else {
+ WriteTermApplication(intAddName, node, options);
+ }
+ return true;
+ }
+
+ public bool VisitSubOp (VCExprNAry! node, LineariserOptions! options) {
+ WriteTermApplication(intSubName, node, options);
+ return true;
+ }
+
+ public bool VisitMulOp (VCExprNAry! node, LineariserOptions! options) {
+ WriteTermApplication(intMulName, node, options);
+ return true;
+ }
+
+ public bool VisitDivOp (VCExprNAry! node, LineariserOptions! options) {
+ WriteTermApplication(intDivName, node, options);
+ return true;
+ }
+
+ public bool VisitModOp (VCExprNAry! node, LineariserOptions! options) {
+ WriteTermApplication(intModName, node, options);
+ return true;
+ }
+
+ public bool VisitLtOp (VCExprNAry! node, LineariserOptions! options) {
+ WriteApplication(termLessName, lessName, node, options, true); // arguments are always terms
+ return true;
+ }
+
+ public bool VisitLeOp (VCExprNAry! node, LineariserOptions! options) {
+ WriteApplication(termAtmostName, atmostName, node, options, true); // arguments are always terms
+ return true;
+ }
+
+ public bool VisitGtOp (VCExprNAry! node, LineariserOptions! options) {
+ WriteApplication(termGreaterName, greaterName, node, options, true); // arguments are always terms
+ return true;
+ }
+
+ public bool VisitGeOp (VCExprNAry! node, LineariserOptions! options) {
+ WriteApplication(termAtleastName, atleastName, node, options, true); // arguments are always terms
+ return true;
+ }
+
+ public bool VisitSubtypeOp (VCExprNAry! node, LineariserOptions! options) {
+ WriteApplication(subtypeName, node, options, true); // arguments are always terms
+ return true;
+ }
+
+ public bool VisitSubtype3Op (VCExprNAry! node, LineariserOptions! options) {
+ WriteApplication(subtypeArgsName, node, options, true); // arguments are always terms
+ return true;
+ }
+
+ public bool VisitBoogieFunctionOp (VCExprNAry! node, LineariserOptions! options) {
+ VCExprBoogieFunctionOp! op = (VCExprBoogieFunctionOp)node.Op;
+ string! funcName = op.Func.Name;
+ string? bvzName = op.Func.FindStringAttribute("external");
+ string! printedName = ExprLineariser.Namer.GetName(op.Func, funcName);
+ if (bvzName != null) printedName = bvzName;
+
+ if (options.UseTypes) {
+ // we use term notation for arguments whose type is not bool, and
+ // formula notation for boolean arguments
+
+ wr.Write("(");
+ ExprLineariser.WriteId(printedName);
+
+ foreach (VCExpr! e in node) {
+ wr.Write(" ");
+ ExprLineariser.Linearise(e, options.SetAsTerm(!e.Type.IsBool));
+ }
+
+ wr.Write(")");
+ } else {
+ // arguments are always terms
+ WriteApplicationTermOnly(SimplifyLikeExprLineariser.MakeIdPrintable(printedName),
+ node, options);
+ }
+ return true;
+ }
+
+ }
+ }
+
+}
diff --git a/Source/VCExpr/TermFormulaFlattening.ssc b/Source/VCExpr/TermFormulaFlattening.ssc
new file mode 100644
index 00000000..bfb8cb3a
--- /dev/null
+++ b/Source/VCExpr/TermFormulaFlattening.ssc
@@ -0,0 +1,222 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using System;
+using System.Text;
+using System.IO;
+using System.Collections;
+using System.Collections.Generic;
+using Microsoft.Contracts;
+using Microsoft.Basetypes;
+using Microsoft.Boogie.VCExprAST;
+
+// Ensure that no formulas (expressions of type boolean that are not
+// just a variable) occur with terms (expressions of some other
+// type). This is done by introducing let-binders for boolean
+// variables.
+
+namespace Microsoft.Boogie.VCExprAST
+{
+
+ public struct FlattenerState {
+ public readonly int Polarity;
+ public readonly bool InTerm;
+
+ public static FlattenerState INITIAL = new FlattenerState(1, false);
+
+ public FlattenerState(int polarity, bool inTerm) {
+ Polarity = polarity;
+ InTerm = inTerm;
+ }
+
+ public FlattenerState TogglePolarity { get {
+ return new FlattenerState(-Polarity, InTerm);
+ } }
+
+ public FlattenerState ZeroPolarity { get {
+ return new FlattenerState(0, InTerm);
+ } }
+
+ public FlattenerState EnterTerm { get {
+ return new FlattenerState(Polarity, true);
+ } }
+ }
+
+ //////////////////////////////////////////////////////////////////////////////
+
+ public class TermFormulaFlattener : MutatingVCExprVisitor<FlattenerState> {
+
+ public TermFormulaFlattener(VCExpressionGenerator! gen) {
+ base(gen);
+ }
+
+ private readonly IDictionary<VCExpr!, VCExprVar!>! Bindings =
+ new Dictionary<VCExpr!, VCExprVar!> ();
+
+ private int varNameCounter = 0;
+
+ public VCExpr! Flatten(VCExpr! expr) {
+ VCExpr! res = Mutate(expr, FlattenerState.INITIAL);
+ while (Bindings.Count > 0) {
+ List<VCExprLetBinding!>! letBindings = new List<VCExprLetBinding!> ();
+ foreach (KeyValuePair<VCExpr!, VCExprVar!> pair in Bindings)
+ letBindings.Add(Gen.LetBinding(pair.Value, pair.Key));
+ Bindings.Clear();
+ res = AddBindings(letBindings, res, FlattenerState.INITIAL);
+ }
+ return res;
+ }
+
+ private VCExprVar! GetVarFor(VCExpr! expr) requires expr.Type.IsBool; {
+ VCExprVar res;
+ if (!Bindings.TryGetValue(expr, out res)) {
+ string! name = "flt" + varNameCounter;
+ varNameCounter = varNameCounter + 1;
+ res = Gen.Variable(name, Type.Bool);
+ Bindings.Add(expr, res);
+ }
+ return (!)res;
+ }
+
+ // Remove all let-bindings from the field bindings whose rhs
+ // contains any of the specified variables
+ private List<VCExprLetBinding!>!
+ RemoveBindingsWithVars(List<VCExprVar!>! boundVars,
+ List<TypeVariable!>! boundTypeVars) {
+
+ List<VCExprLetBinding!>! res = new List<VCExprLetBinding!> ();
+ FreeVariableCollector! coll = new FreeVariableCollector ();
+
+ foreach (KeyValuePair<VCExpr!, VCExprVar!> pair in Bindings) {
+ coll.Collect(pair.Key);
+ if (exists{VCExprVar! var in boundVars; coll.FreeTermVars.ContainsKey(var)} ||
+ exists{TypeVariable! var in boundTypeVars; coll.FreeTypeVars.Contains(var)})
+ res.Add(Gen.LetBinding(pair.Value, pair.Key));
+ coll.Reset();
+ }
+
+ foreach (VCExprLetBinding! b in res)
+ Bindings.Remove(b.E);
+
+ return res;
+ }
+
+ // Add bindings to a formula using an implication or
+ // conjunction. The bindings themselves will be flattened as well,
+ // which might introduce further bindings
+ private VCExpr! AddBindings(List<VCExprLetBinding!>! bindings,
+ VCExpr! body,
+ FlattenerState state)
+ requires body.Type.IsBool; {
+
+ List<VCExprLetBinding!>! mutatedBindings = FlattenBindings(bindings, state);
+ VCExpr! bindingEquations = Gen.AsEquations(mutatedBindings);
+ switch(state.Polarity) {
+ case 1:
+ return Gen.Implies(bindingEquations, body);
+ case -1:
+ return Gen.And(bindingEquations, body);
+ case 0:
+ // also add explicit quantifiers for the bound variables
+ List<VCExprVar!>! vars = new List<VCExprVar!> ();
+ foreach (VCExprLetBinding! binding in mutatedBindings)
+ vars.Add(binding.V);
+ return Gen.Forall(vars, new List<VCTrigger!>(),
+ Gen.Implies(bindingEquations, body));
+ }
+ assert false;
+ }
+
+ private List<VCExprLetBinding!>! FlattenBindings(List<VCExprLetBinding!>! bindings,
+ FlattenerState state) {
+ FlattenerState stateInBindings = state.ZeroPolarity;
+ List<VCExprLetBinding!>! mutatedBindings = new List<VCExprLetBinding!> ();
+ foreach (VCExprLetBinding! b in bindings)
+ mutatedBindings.Add(Gen.LetBinding(b.V, Mutate(b.E, stateInBindings)));
+ return mutatedBindings;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ public override VCExpr! Visit(VCExprNAry! node, FlattenerState state) {
+ // track the polarity to know whether implications or conjunctions
+ // are to be introduced
+
+ if (node.Op.Equals(VCExpressionGenerator.NotOp))
+ return Gen.Not(Mutate(node[0], state.TogglePolarity));
+
+ if (node.Op.Equals(VCExpressionGenerator.ImpliesOp)) {
+ VCExpr! newArg0 = Mutate(node[0], state.TogglePolarity);
+ VCExpr! newArg1 = Mutate(node[1], state);
+ return Gen.Implies(newArg0, newArg1);
+ }
+
+ if (!node.Type.IsBool)
+ state = state.EnterTerm;
+
+ 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)
+ return base.Visit(node, state.ZeroPolarity);
+
+ return base.Visit(node, state);
+ }
+
+ public override VCExpr! Visit(VCExprQuantifier! node, FlattenerState state) {
+ if (state.InTerm)
+ return GetVarFor(node);
+
+ // we only flatten within the matrix of the quantified formula,
+ // not within the triggers (since SMT-solvers do not seem to
+ // appreciate triggers with let-binders)
+ VCExpr! newBody = Mutate(node.Body, state);
+
+ // Check whether any of the extracted terms contain variables
+ // bound by this quantifier. In this case, we have to add
+ // let-binders and remove the extracted terms
+ bool cont = true;
+ while (cont) {
+ List<VCExprLetBinding!>! localBindings =
+ RemoveBindingsWithVars(node.BoundVars, node.TypeParameters);
+ if (localBindings.Count > 0)
+ newBody = AddBindings(localBindings, newBody, state);
+ else
+ cont = false;
+ }
+
+ return Gen.Quantify(node.Quan, node.TypeParameters,
+ node.BoundVars, node.Triggers,
+ node.Infos, newBody);
+ }
+
+ public override VCExpr! Visit(VCExprLet! node, FlattenerState state) {
+ if (state.InTerm)
+ return GetVarFor(node);
+
+ VCExprLet! prelimRes = (VCExprLet!)base.Visit(node, state);
+
+ List<VCExprLetBinding!>! allBindings = new List<VCExprLetBinding!> ();
+ allBindings.AddRange(prelimRes);
+
+ // Check whether any of the extracted terms contain variables
+ // bound by this binder. In this case, we have to add
+ // let-binders and remove the extracted terms
+ bool cont = true;
+ while (cont) {
+ List<VCExprLetBinding!>! localBindings =
+ RemoveBindingsWithVars(prelimRes.BoundVars, new List<TypeVariable!> ());
+ if (localBindings.Count > 0)
+ allBindings.AddRange(FlattenBindings(localBindings, state));
+ else
+ cont = false;
+ }
+
+ return Gen.Let(allBindings, prelimRes.Body);
+ }
+
+ }
+
+} \ No newline at end of file
diff --git a/Source/VCExpr/TypeErasure.ssc b/Source/VCExpr/TypeErasure.ssc
new file mode 100644
index 00000000..9cbd829a
--- /dev/null
+++ b/Source/VCExpr/TypeErasure.ssc
@@ -0,0 +1,1160 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using System;
+using System.Text;
+using System.IO;
+using System.Collections;
+using System.Collections.Generic;
+using Microsoft.Contracts;
+using Microsoft.Basetypes;
+using Microsoft.Boogie.VCExprAST;
+
+// different classes for erasing complex types in VCExprs, replacing them
+// with axioms that can be handled by theorem provers and SMT solvers
+
+namespace Microsoft.Boogie.TypeErasure
+{
+ using Microsoft.Boogie.VCExprAST;
+
+ // some functionality that is needed in many places (and that should
+ // really be provided by the Spec# container classes; maybe one
+ // could integrate the functions in a nicer way?)
+ public class HelperFuns {
+
+ public static Function! BoogieFunction(string! name, List<TypeVariable!>! typeParams,
+ params Type[]! types)
+ requires types.Length > 0;
+ requires forall{int i in (0:types.Length); types[i] != null};
+ {
+ VariableSeq! args = new VariableSeq ();
+ for (int i = 0; i < types.Length - 1; ++i)
+ args.Add(new Formal (Token.NoToken,
+ new TypedIdent (Token.NoToken, "arg" + i, (!)types[i]),
+ true));
+ Formal! result = new Formal (Token.NoToken,
+ new TypedIdent (Token.NoToken, "res",
+ (!)types[types.Length - 1]),
+ false);
+ return new Function (Token.NoToken, name, ToSeq(typeParams), args, result);
+ }
+
+ public static Function! BoogieFunction(string! name, params Type[]! types) {
+ return BoogieFunction(name, new List<TypeVariable!> (), types);
+ }
+
+ // boogie function where all arguments and the result have the same type U
+ public static Function! UniformBoogieFunction(string! name, int arity, Type! U) {
+ Type[]! types = new Type [arity + 1];
+ for (int i = 0; i < arity + 1; ++i)
+ types[i] = U;
+ return BoogieFunction(name, types);
+ }
+
+ public static List<VCExprVar!>! GenVarsForInParams(Function! fun,
+ VCExpressionGenerator! gen) {
+ List<VCExprVar!>! arguments = new List<VCExprVar!> (fun.InParams.Length);
+ foreach (Formal! f in fun.InParams) {
+ VCExprVar! var = gen.Variable(f.Name, f.TypedIdent.Type);
+ arguments.Add(var);
+ }
+ return arguments;
+ }
+
+ public static List<T!>! ToList<T> (params T[]! args) {
+ List<T!>! res = new List<T!> (args.Length);
+ foreach (T t in args)
+ res.Add((!)t);
+ return res;
+ }
+
+ public static List<TypeVariable!>! ToList(TypeVariableSeq! seq) {
+ List<TypeVariable!>! res = new List<TypeVariable!> (seq.Length);
+ foreach (TypeVariable! var in seq)
+ res.Add(var);
+ return res;
+ }
+
+ public static TypeVariableSeq! ToSeq(List<TypeVariable!>! list) {
+ TypeVariableSeq! res = new TypeVariableSeq ();
+ foreach (TypeVariable! var in list)
+ res.Add(var);
+ return res;
+ }
+
+ public static List<T>! Intersect<T>(List<T>! a, List<T>! b) {
+ List<T>! res = new List<T> (Math.Min(a.Count, b.Count));
+ foreach (T x in a)
+ if (b.Contains(x))
+ res.Add(x);
+ res.TrimExcess();
+ return res;
+ }
+
+ public static List<KeyValuePair<T1, T2>>! ToPairList<T1, T2>(IDictionary<T1, T2>! dict) {
+ List<KeyValuePair<T1, T2>>! res = new List<KeyValuePair<T1, T2>> (dict);
+ return res;
+ }
+
+ public static void AddRangeWithoutDups<T>(IEnumerable<T>! fromList, List<T>! toList) {
+ foreach (T t in fromList)
+ if (!toList.Contains(t))
+ toList.Add(t);
+ }
+
+ public static void AddFreeVariablesWithoutDups(Type! type, List<TypeVariable!>! toList) {
+ foreach (TypeVariable! var in type.FreeVariables) {
+ if (!toList.Contains(var))
+ toList.Add(var);
+ }
+ }
+
+ public static List<VCExpr!>! ToVCExprList(List<VCExprVar!>! list) {
+ List<VCExpr!>! res = new List<VCExpr!> (list.Count);
+ foreach (VCExprVar! var in list)
+ res.Add(var);
+ return res;
+ }
+
+ public static List<VCExprVar!>! VarVector(string! baseName, int num, Type! type,
+ VCExpressionGenerator! gen) {
+ List<VCExprVar!>! res = new List<VCExprVar!> (num);
+ for (int i = 0; i < num; ++i)
+ res.Add(gen.Variable(baseName + i, type));
+ return res;
+ }
+
+ public static List<VCExprVar!>! VarVector(string! baseName, List<Type!>! types,
+ VCExpressionGenerator! gen) {
+ List<VCExprVar!>! res = new List<VCExprVar!> (types.Count);
+ for (int i = 0; i < types.Count; ++i)
+ res.Add(gen.Variable(baseName + i, types[i]));
+ return res;
+ }
+ }
+
+ //////////////////////////////////////////////////////////////////////////////
+
+ internal struct TypeCtorRepr {
+ // function that represents the application of the type constructor
+ // to smaller types
+ public readonly Function! Ctor;
+ // left-inverse functions that extract the subtypes of a compound type
+ public readonly List<Function!>! Dtors;
+
+ public TypeCtorRepr(Function! ctor, List<Function!>! dtors)
+ requires ctor.InParams.Length == dtors.Count; {
+ this.Ctor = ctor;
+ this.Dtors = dtors;
+ }
+ }
+
+ //////////////////////////////////////////////////////////////////////////////
+
+ // The class responsible for creating and keeping track of all
+ // axioms related to the type system. This abstract class is made
+ // concrete in two subclasses, one for type erasure with type
+ // premisses in quantifiers (the semantic approach), and one for
+ // type erasure with explicit type arguments of polymorphic
+ // functions (the syntacted approach).
+ public abstract class TypeAxiomBuilder : ICloneable {
+
+ protected readonly VCExpressionGenerator! Gen;
+
+ internal abstract MapTypeAbstractionBuilder! MapTypeAbstracter { get; }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Type Axioms
+
+ // list in which all typed axioms are collected
+ private readonly List<VCExpr!>! AllTypeAxioms;
+
+ // list in which type axioms are incrementally collected
+ private readonly List<VCExpr!>! IncTypeAxioms;
+
+ internal void AddTypeAxiom(VCExpr! axiom) {
+ AllTypeAxioms.Add(axiom);
+ IncTypeAxioms.Add(axiom);
+ }
+
+ // Return all axioms that were added since the last time NewAxioms
+ // was called
+ public VCExpr! GetNewAxioms() {
+ VCExpr! res = Gen.NAry(VCExpressionGenerator.AndOp, IncTypeAxioms);
+ IncTypeAxioms.Clear();
+ return res;
+ }
+
+ // mapping from a type to its constructor number/index
+ private readonly Function! Ctor;
+ private BigNum CurrentCtorNum;
+
+ private VCExpr! GenCtorAssignment(VCExpr! typeRepr) {
+ if (CommandLineOptions.Clo.TypeEncodingMethod
+ == CommandLineOptions.TypeEncoding.None)
+ return VCExpressionGenerator.True;
+
+ VCExpr! res = Gen.Eq(Gen.Function(Ctor, typeRepr),
+ Gen.Integer(CurrentCtorNum));
+ CurrentCtorNum = CurrentCtorNum + BigNum.ONE;
+ return res;
+ }
+
+ private VCExpr! GenCtorAssignment(Function! typeRepr) {
+ if (CommandLineOptions.Clo.TypeEncodingMethod
+ == CommandLineOptions.TypeEncoding.None)
+ return VCExpressionGenerator.True;
+
+ List<VCExprVar!>! quantifiedVars = HelperFuns.GenVarsForInParams(typeRepr, Gen);
+ VCExpr! eq =
+ GenCtorAssignment(Gen.Function(typeRepr,
+ HelperFuns.ToVCExprList(quantifiedVars)));
+
+ if (typeRepr.InParams.Length == 0)
+ return eq;
+
+ return Gen.Forall(quantifiedVars, new List<VCTrigger!> (),
+ "ctor:" + typeRepr.Name, eq);
+ }
+
+ // generate an axiom (forall x0, x1, ... :: invFun(fun(x0, x1, ...) == xi)
+ protected VCExpr! GenLeftInverseAxiom(Function! fun, Function! invFun, int dtorNum) {
+ List<VCExprVar!>! quantifiedVars = HelperFuns.GenVarsForInParams(fun, Gen);
+
+ VCExpr! funApp = Gen.Function(fun, HelperFuns.ToVCExprList(quantifiedVars));
+ VCExpr! lhs = Gen.Function(invFun, funApp);
+ VCExpr! rhs = quantifiedVars[dtorNum];
+ VCExpr! eq = Gen.Eq(lhs, rhs);
+
+ List<VCTrigger!>! triggers = HelperFuns.ToList(Gen.Trigger(true, HelperFuns.ToList(funApp)));
+ return Gen.Forall(quantifiedVars, triggers, "typeInv:" + invFun.Name, eq);
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+
+ // the type of everything that is not int, bool, or a type
+ private readonly TypeCtorDecl! UDecl;
+ public readonly Type! U;
+
+ // the type of types
+ private readonly TypeCtorDecl! TDecl;
+ public readonly Type! T;
+
+ public abstract Type! TypeAfterErasure(Type! type);
+ public abstract bool UnchangedType(Type! type);
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Symbols for representing types
+
+ private readonly IDictionary<Type!, VCExpr!>! BasicTypeReprs;
+
+ private VCExpr! GetBasicTypeRepr(Type! type)
+ requires type.IsBasic || type.IsBv; {
+ VCExpr res;
+ if (!BasicTypeReprs.TryGetValue(type, out res)) {
+ res = Gen.Function(HelperFuns.BoogieFunction(type.ToString() + "Type", T));
+ AddTypeAxiom(GenCtorAssignment(res));
+ BasicTypeReprs.Add(type, res);
+ }
+ return (!)res;
+ }
+
+ private readonly IDictionary<TypeCtorDecl!, TypeCtorRepr>! TypeCtorReprs;
+
+ internal TypeCtorRepr GetTypeCtorReprStruct(TypeCtorDecl! decl) {
+ TypeCtorRepr reprSet;
+ if (!TypeCtorReprs.TryGetValue(decl, out reprSet)) {
+ Function! ctor = HelperFuns.UniformBoogieFunction(decl.Name + "Type", decl.Arity, T);
+ AddTypeAxiom(GenCtorAssignment(ctor));
+
+ List<Function!>! dtors = new List<Function!>(decl.Arity);
+ for (int i = 0; i < decl.Arity; ++i) {
+ Function! dtor = HelperFuns.UniformBoogieFunction(decl.Name + "TypeInv" + i, 1, T);
+ dtors.Add(dtor);
+ AddTypeAxiom(GenLeftInverseAxiom(ctor, dtor, i));
+ }
+
+ reprSet = new TypeCtorRepr(ctor, dtors);
+ TypeCtorReprs.Add(decl, reprSet);
+ }
+
+ return reprSet;
+ }
+
+ public Function! GetTypeCtorRepr(TypeCtorDecl! decl) {
+ return GetTypeCtorReprStruct(decl).Ctor;
+ }
+
+ public Function! GetTypeDtor(TypeCtorDecl! decl, int num) {
+ return GetTypeCtorReprStruct(decl).Dtors[num];
+ }
+
+ // mapping from free type variables to VCExpr variables
+ private readonly IDictionary<TypeVariable!, VCExprVar!>! TypeVariableMapping;
+
+ public VCExprVar! Typed2Untyped(TypeVariable! var) {
+ VCExprVar res;
+ if (!TypeVariableMapping.TryGetValue(var, out res)) {
+ res = new VCExprVar (var.Name, T);
+ TypeVariableMapping.Add(var, res);
+ }
+ return (!)res;
+ }
+
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Symbols for representing variables and constants
+
+ // Globally defined variables
+ private readonly IDictionary<VCExprVar!, VCExprVar!>! Typed2UntypedVariables;
+
+ // This method must only be used for free (unbound) variables
+ public VCExprVar! Typed2Untyped(VCExprVar! var) {
+ VCExprVar res;
+ if (!Typed2UntypedVariables.TryGetValue(var, out res)) {
+ res = Gen.Variable(var.Name, TypeAfterErasure(var.Type));
+ Typed2UntypedVariables.Add(var, res);
+ AddVarTypeAxiom(res, var.Type);
+ }
+ return (!)res;
+ }
+
+ protected abstract void AddVarTypeAxiom(VCExprVar! var, Type! originalType);
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Translation function from types to their term representation
+
+ public VCExpr! Type2Term(Type! type,
+ IDictionary<TypeVariable!, VCExpr!>! varMapping) {
+ //
+ if (type.IsBasic || type.IsBv) {
+ //
+ return GetBasicTypeRepr(type);
+ //
+ } else if (type.IsCtor) {
+ //
+ CtorType ctype = type.AsCtor;
+ Function! repr = GetTypeCtorRepr(ctype.Decl);
+ List<VCExpr!>! args = new List<VCExpr!> (ctype.Arguments.Length);
+ foreach (Type! t in ctype.Arguments)
+ args.Add(Type2Term(t, varMapping));
+ return Gen.Function(repr, args);
+ //
+ } else if (type.IsVariable) {
+ //
+ VCExpr res;
+ if (!varMapping.TryGetValue(type.AsVariable, out res))
+ // then the variable is free and we bind it at this point to a term
+ // variable
+ res = Typed2Untyped(type.AsVariable);
+ return (!)res;
+ //
+ } else if (type.IsMap) {
+ //
+ return Type2Term(MapTypeAbstracter.AbstractMapType(type.AsMap), varMapping);
+ //
+ } else {
+ System.Diagnostics.Debug.Fail("Don't know how to handle this type: " + type);
+ assert false; // please the compiler
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ public TypeAxiomBuilder(VCExpressionGenerator! gen) {
+ this.Gen = gen;
+ AllTypeAxioms = new List<VCExpr!> ();
+ IncTypeAxioms = new List<VCExpr!> ();
+ BasicTypeReprs = new Dictionary<Type!, VCExpr!> ();
+ CurrentCtorNum = BigNum.ZERO;
+ TypeCtorReprs = new Dictionary<TypeCtorDecl!, TypeCtorRepr> ();
+ TypeVariableMapping = new Dictionary<TypeVariable!, VCExprVar!> ();
+ Typed2UntypedVariables = new Dictionary<VCExprVar!, VCExprVar!> ();
+
+ TypeCtorDecl! uDecl = new TypeCtorDecl(Token.NoToken, "U", 0);
+ UDecl = uDecl;
+ Type! u = new CtorType (Token.NoToken, uDecl, new TypeSeq ());
+ U = u;
+
+ TypeCtorDecl! tDecl = new TypeCtorDecl(Token.NoToken, "T", 0);
+ TDecl = tDecl;
+ Type! t = new CtorType (Token.NoToken, tDecl, new TypeSeq ());
+ T = t;
+
+ Ctor = HelperFuns.BoogieFunction("Ctor", t, Type.Int);
+ }
+
+ public virtual void Setup() {
+ GetBasicTypeRepr(Type.Int);
+ GetBasicTypeRepr(Type.Bool);
+ }
+
+ // constructor to allow cloning
+ internal TypeAxiomBuilder(TypeAxiomBuilder! builder) {
+ Gen = builder.Gen;
+ AllTypeAxioms = new List<VCExpr!> (builder.AllTypeAxioms);
+ IncTypeAxioms = new List<VCExpr!> (builder.IncTypeAxioms);
+
+ UDecl = builder.UDecl;
+ U = builder.U;
+
+ TDecl = builder.TDecl;
+ T = builder.T;
+
+ Ctor = builder.Ctor;
+ CurrentCtorNum = builder.CurrentCtorNum;
+
+ BasicTypeReprs = new Dictionary<Type!, VCExpr!> (builder.BasicTypeReprs);
+ TypeCtorReprs = new Dictionary<TypeCtorDecl!, TypeCtorRepr> (builder.TypeCtorReprs);
+
+ TypeVariableMapping =
+ new Dictionary<TypeVariable!, VCExprVar!> (builder.TypeVariableMapping);
+ Typed2UntypedVariables =
+ new Dictionary<VCExprVar!, VCExprVar!> (builder.Typed2UntypedVariables);
+ }
+
+ public abstract Object! Clone();
+ }
+
+ //////////////////////////////////////////////////////////////////////////////
+
+ // Subclass of the TypeAxiomBuilder that provides all functionality
+ // to deal with native sorts of a theorem prover (that are the only
+ // types left after erasing all other types). Currently, these are:
+ //
+ // U ... sort of all individuals/objects/values
+ // T ... sort of all types
+ // int ... integers
+ // bool ... booleans
+
+ public abstract class TypeAxiomBuilderIntBoolU : TypeAxiomBuilder {
+
+ public TypeAxiomBuilderIntBoolU(VCExpressionGenerator! gen) {
+ base(gen);
+ TypeCasts = new Dictionary<Type!, TypeCastSet> ();
+ }
+
+ // constructor to allow cloning
+ internal TypeAxiomBuilderIntBoolU(TypeAxiomBuilderIntBoolU! builder) {
+ base(builder);
+ TypeCasts = new Dictionary<Type!, TypeCastSet> (builder.TypeCasts);
+ }
+
+ public override void Setup() {
+ base.Setup();
+
+ GetTypeCasts(Type.Int);
+ GetTypeCasts(Type.Bool);
+ }
+
+ // generate inverse axioms for casts (castToU(castFromU(x)) = x, under certain premisses)
+ protected abstract VCExpr! GenReverseCastAxiom(Function! castToU, Function! castFromU);
+
+ protected VCExpr! GenReverseCastEq(Function! castToU, Function! castFromU,
+ out VCExprVar! var, out List<VCTrigger!>! triggers) {
+ var = Gen.Variable("x", U);
+
+ VCExpr! lhs = Gen.Function(castToU, Gen.Function(castFromU, var));
+ triggers = HelperFuns.ToList(Gen.Trigger(true, HelperFuns.ToList(lhs)));
+
+ return Gen.Eq(lhs, var);
+ }
+
+ protected abstract VCExpr! GenCastTypeAxioms(Function! castToU, Function! castFromU);
+
+ ///////////////////////////////////////////////////////////////////////////
+ // storage of type casts for types that are supposed to be left over in the
+ // VCs (like int, bool, bitvectors)
+
+ private readonly IDictionary<Type!, TypeCastSet>! TypeCasts;
+
+ private TypeCastSet GetTypeCasts(Type! type) {
+ TypeCastSet res;
+ if (!TypeCasts.TryGetValue(type, out res)) {
+ Function! castToU = HelperFuns.BoogieFunction(type.ToString() + "_2_U", type, U);
+ Function! castFromU = HelperFuns.BoogieFunction("U_2_" + type.ToString(), U, type);
+
+ AddTypeAxiom(GenLeftInverseAxiom(castToU, castFromU, 0));
+ AddTypeAxiom(GenReverseCastAxiom(castToU, castFromU));
+ AddTypeAxiom(GenCastTypeAxioms(castToU, castFromU));
+
+ res = new TypeCastSet (castToU, castFromU);
+ TypeCasts.Add(type, res);
+ }
+ return res;
+ }
+
+ public Function! CastTo(Type! type)
+ requires UnchangedType(type); {
+ return GetTypeCasts(type).CastFromU;
+ }
+
+ public Function! CastFrom(Type! type)
+ requires UnchangedType(type); {
+ return GetTypeCasts(type).CastToU;
+ }
+
+ private struct TypeCastSet {
+ public readonly Function! CastToU;
+ public readonly Function! CastFromU;
+
+ public TypeCastSet(Function! castToU, Function! castFromU) {
+ CastToU = castToU;
+ CastFromU = castFromU;
+ }
+ }
+
+ public bool IsCast(Function! fun) {
+ if (fun.InParams.Length != 1)
+ return false;
+ Type! inType = ((!)fun.InParams[0]).TypedIdent.Type;
+ if (inType.Equals(U)) {
+ Type! outType = ((!)fun.OutParams[0]).TypedIdent.Type;
+ if (!TypeCasts.ContainsKey(outType))
+ return false;
+ return fun.Equals(CastTo(outType));
+ } else {
+ if (!TypeCasts.ContainsKey(inType))
+ return false;
+ Type! outType = ((!)fun.OutParams[0]).TypedIdent.Type;
+ if (!outType.Equals(U))
+ return false;
+ return fun.Equals(CastFrom(inType));
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ // the only types that we allow in "untyped" expressions are U,
+ // Type.Int, and Type.Bool
+
+ public override Type! TypeAfterErasure(Type! type) {
+ if (UnchangedType(type))
+ // these types are kept
+ return type;
+ else
+ // all other types are replaced by U
+ return U;
+ }
+
+ [Pure]
+ public override bool UnchangedType(Type! type) {
+ return type.IsInt || type.IsBool || type.IsBv;
+ }
+
+ public VCExpr! Cast(VCExpr! expr, Type! toType)
+ requires expr.Type.Equals(U) || UnchangedType(expr.Type);
+ requires toType.Equals(U) || UnchangedType(toType);
+ {
+ if (expr.Type.Equals(toType))
+ return expr;
+
+ if (toType.Equals(U)) {
+ return Gen.Function(CastFrom(expr.Type), expr);
+ } else {
+ assert expr.Type.Equals(U);
+ return Gen.Function(CastTo(toType), expr);
+ }
+ }
+
+ public List<VCExpr!>! CastSeq(List<VCExpr!>! exprs, Type! toType) {
+ List<VCExpr!>! res = new List<VCExpr!> (exprs.Count);
+ foreach (VCExpr! expr in exprs)
+ res.Add(Cast(expr, toType));
+ return res;
+ }
+
+
+ }
+
+ //////////////////////////////////////////////////////////////////////////////
+ // Class for computing most general abstractions of map types. An abstraction
+ // of a map type t is a maptype t' in which closed proper subtypes have been replaced
+ // with type variables. E.g., an abstraction of <a>[C a, int]a would be <a>[C a, b]a.
+ // We subsequently consider most general abstractions as ordinary parametrised types,
+ // i.e., "<a>[C a, b]a" would be considered as a type "M b" with polymorphically typed
+ // access functions
+ //
+ // select<a,b>(M b, C a, b) returns (a)
+ // store<a,b>(M b, C a, b, a) returns (M b)
+
+ internal abstract class MapTypeAbstractionBuilder {
+
+ protected readonly TypeAxiomBuilder! AxBuilder;
+ protected readonly VCExpressionGenerator! Gen;
+
+ internal MapTypeAbstractionBuilder(TypeAxiomBuilder! axBuilder,
+ VCExpressionGenerator! gen) {
+ this.AxBuilder = axBuilder;
+ this.Gen = gen;
+ AbstractionVariables = new List<TypeVariable!> ();
+ ClassRepresentations = new Dictionary<MapType!, MapTypeClassRepresentation> ();
+ }
+
+ // constructor for cloning
+ internal MapTypeAbstractionBuilder(TypeAxiomBuilder! axBuilder,
+ VCExpressionGenerator! gen,
+ MapTypeAbstractionBuilder! builder) {
+ this.AxBuilder = axBuilder;
+ this.Gen = gen;
+ AbstractionVariables =
+ new List<TypeVariable!> (builder.AbstractionVariables);
+ ClassRepresentations =
+ new Dictionary<MapType!, MapTypeClassRepresentation> (builder.ClassRepresentations);
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Type variables used in the abstractions. We use the same variables in the
+ // same order in all abstractions in order to obtain comparable abstractions
+ // (equals, hashcode)
+
+ private readonly List<TypeVariable!>! AbstractionVariables;
+
+ private TypeVariable! AbstractionVariable(int num)
+ requires num >= 0; {
+ while (AbstractionVariables.Count <= num)
+ AbstractionVariables.Add(new TypeVariable (Token.NoToken,
+ "aVar" + AbstractionVariables.Count));
+ return AbstractionVariables[num];
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // The untyped representation of a class of map types, i.e., of a map type
+ // <a0, a1, ...>[A0, A1, ...] R, where the argument types and the result type
+ // possibly contain free type variables. For each such class, a separate type
+ // constructor and separate select/store functions are introduced.
+
+ protected struct MapTypeClassRepresentation {
+ public readonly TypeCtorDecl! RepresentingType;
+ public readonly Function! Select;
+ public readonly Function! Store;
+
+ public MapTypeClassRepresentation(TypeCtorDecl! representingType,
+ Function! select, Function! store) {
+ this.RepresentingType = representingType;
+ this.Select = select;
+ this.Store = store;
+ }
+ }
+
+ private readonly IDictionary<MapType!, MapTypeClassRepresentation>! ClassRepresentations;
+
+ protected MapTypeClassRepresentation GetClassRepresentation(MapType! abstractedType) {
+ MapTypeClassRepresentation res;
+ if (!ClassRepresentations.TryGetValue(abstractedType, out res)) {
+ int num = ClassRepresentations.Count;
+ TypeCtorDecl! synonym =
+ new TypeCtorDecl(Token.NoToken, "MapType" + num, abstractedType.FreeVariables.Length);
+
+ Function! select, store;
+ GenSelectStoreFunctions(abstractedType, synonym, out select, out store);
+
+ res = new MapTypeClassRepresentation(synonym, select, store);
+ ClassRepresentations.Add(abstractedType, res);
+ }
+ return res;
+ }
+
+ // the actual select and store functions are generated by the
+ // concrete subclasses of this class
+ protected abstract void GenSelectStoreFunctions(MapType! abstractedType,
+ TypeCtorDecl! synonymDecl,
+ out Function! select, out Function! store);
+
+ ///////////////////////////////////////////////////////////////////////////
+
+ public Function! Select(MapType! rawType, out TypeSeq! instantiations) {
+ return AbstractAndGetRepresentation(rawType, out instantiations).Select;
+ }
+
+ public Function! Store(MapType! rawType, out TypeSeq! instantiations) {
+ return AbstractAndGetRepresentation(rawType, out instantiations).Store;
+ }
+
+ private MapTypeClassRepresentation
+ AbstractAndGetRepresentation(MapType! rawType, out TypeSeq! instantiations) {
+ instantiations = new TypeSeq ();
+ MapType! abstraction = ThinOutMapType(rawType, instantiations);
+ return GetClassRepresentation(abstraction);
+ }
+
+ public CtorType! AbstractMapType(MapType! rawType) {
+ TypeSeq! instantiations = new TypeSeq ();
+ MapType! abstraction = ThinOutMapType(rawType, instantiations);
+
+ MapTypeClassRepresentation repr = GetClassRepresentation(abstraction);
+ assume repr.RepresentingType.Arity == instantiations.Length;
+ return new CtorType(Token.NoToken, repr.RepresentingType, instantiations);
+ }
+
+ // TODO: cache the result of this operation
+ protected MapType! ThinOutMapType(MapType! rawType,
+ TypeSeq! instantiations) {
+ TypeSeq! newArguments = new TypeSeq ();
+ foreach (Type! subtype in rawType.Arguments)
+ newArguments.Add(ThinOutType(subtype, rawType.TypeParameters,
+ instantiations));
+ Type! newResult = ThinOutType(rawType.Result, rawType.TypeParameters,
+ instantiations);
+ return new MapType(Token.NoToken, rawType.TypeParameters, newArguments, newResult);
+ }
+
+ private Type! ThinOutType(Type! rawType, TypeVariableSeq! boundTypeParams,
+ // the instantiations of inserted type variables,
+ // the order corresponds to the order in which
+ // "AbstractionVariable(int)" delivers variables
+ TypeSeq! instantiations) {
+
+ if (CommandLineOptions.Clo.Monomorphize && AxBuilder.UnchangedType(rawType))
+ return rawType;
+
+ if (forall{TypeVariable! var in rawType.FreeVariables;
+ !boundTypeParams.Has(var)}) {
+ // Bingo!
+ // if the type does not contain any bound variables, we can simply
+ // replace it with a type variable
+ TypeVariable! abstractionVar = AbstractionVariable(instantiations.Length);
+ assume !boundTypeParams.Has(abstractionVar);
+ instantiations.Add(rawType);
+ return abstractionVar;
+ }
+
+ if (rawType.IsVariable) {
+ //
+ // then the variable has to be bound, we cannot do anything
+ TypeVariable! rawVar = rawType.AsVariable;
+ assume boundTypeParams.Has(rawVar);
+ return rawVar;
+ //
+ } else if (rawType.IsMap) {
+ //
+ // recursively abstract this map type and continue abstracting
+ CtorType! abstraction = AbstractMapType(rawType.AsMap);
+ return ThinOutType(abstraction, boundTypeParams, instantiations);
+ //
+ } else if (rawType.IsCtor) {
+ //
+ // traverse the subtypes
+ CtorType! rawCtorType = rawType.AsCtor;
+ TypeSeq! newArguments = new TypeSeq ();
+ foreach (Type! subtype in rawCtorType.Arguments)
+ newArguments.Add(ThinOutType(subtype, boundTypeParams,
+ instantiations));
+ return new CtorType(Token.NoToken, rawCtorType.Decl, newArguments);
+ //
+ } else {
+ System.Diagnostics.Debug.Fail("Don't know how to handle this type: " + rawType);
+ return rawType; // compiler appeasement policy
+ }
+ }
+
+ }
+
+ //////////////////////////////////////////////////////////////////////////////
+
+ public class VariableBindings {
+ public readonly IDictionary<VCExprVar!, VCExprVar!>! VCExprVarBindings;
+ public readonly IDictionary<TypeVariable!, VCExpr!>! TypeVariableBindings;
+
+ public VariableBindings(IDictionary<VCExprVar!, VCExprVar!>! vcExprVarBindings,
+ IDictionary<TypeVariable!, VCExpr!>! typeVariableBindings) {
+ this.VCExprVarBindings = vcExprVarBindings;
+ this.TypeVariableBindings = typeVariableBindings;
+ }
+
+ public VariableBindings() {
+ this (new Dictionary<VCExprVar!, VCExprVar!> (),
+ new Dictionary<TypeVariable!, VCExpr!> ());
+ }
+
+ public VariableBindings! Clone() {
+ IDictionary<VCExprVar!, VCExprVar!>! newVCExprVarBindings =
+ new Dictionary<VCExprVar!, VCExprVar!> ();
+ foreach (KeyValuePair<VCExprVar!, VCExprVar!> pair in VCExprVarBindings)
+ newVCExprVarBindings.Add(pair);
+ IDictionary<TypeVariable!, VCExpr!>! newTypeVariableBindings =
+ new Dictionary<TypeVariable!, VCExpr!> ();
+ foreach (KeyValuePair<TypeVariable!, VCExpr!> pair in TypeVariableBindings)
+ newTypeVariableBindings.Add(pair);
+ return new VariableBindings(newVCExprVarBindings, newTypeVariableBindings);
+ }
+ }
+
+ //////////////////////////////////////////////////////////////////////////////
+
+ // The central class for turning types VCExprs into untyped
+ // VCExprs. This class makes use of the type axiom builder to manage
+ // the available types and symbols.
+
+ public abstract class TypeEraser : MutatingVCExprVisitor<VariableBindings!> {
+
+ protected readonly TypeAxiomBuilderIntBoolU! AxBuilder;
+
+ protected abstract OpTypeEraser! OpEraser { get; }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ public TypeEraser(TypeAxiomBuilderIntBoolU! axBuilder, VCExpressionGenerator! gen) {
+ base(gen);
+ AxBuilder = axBuilder;
+ }
+
+ public VCExpr! Erase(VCExpr! expr, int polarity)
+ requires polarity >= -1 && polarity <= 1; {
+ this.Polarity = polarity;
+ return Mutate(expr, new VariableBindings ());
+ }
+
+ internal int Polarity = 1; // 1 for positive, -1 for negative, 0 for both
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ public override VCExpr! Visit(VCExprLiteral! node, VariableBindings! bindings) {
+ assume node.Type == Type.Bool || node.Type == Type.Int;
+ return node;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ public override VCExpr! Visit(VCExprNAry! node, VariableBindings! bindings) {
+ VCExprOp! op = node.Op;
+ if (op == VCExpressionGenerator.AndOp || op == VCExpressionGenerator.OrOp)
+ // more efficient on large conjunctions/disjunctions
+ return base.Visit(node, bindings);
+
+ // the visitor that handles all other operators
+ return node.Accept<VCExpr!, VariableBindings!>(OpEraser, bindings);
+ }
+
+ // this method is called by MutatingVCExprVisitor.Visit(VCExprNAry, ...)
+ protected override VCExpr! UpdateModifiedNode(VCExprNAry! originalNode,
+ List<VCExpr!>! newSubExprs,
+ bool changed,
+ VariableBindings! bindings) {
+ assume originalNode.Op == VCExpressionGenerator.AndOp ||
+ originalNode.Op == VCExpressionGenerator.OrOp;
+ return Gen.Function(originalNode.Op,
+ AxBuilder.Cast(newSubExprs[0], Type.Bool),
+ AxBuilder.Cast(newSubExprs[1], Type.Bool));
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ public override VCExpr! Visit(VCExprVar! node, VariableBindings! bindings) {
+ VCExprVar res;
+ if (!bindings.VCExprVarBindings.TryGetValue(node, out res))
+ return AxBuilder.Typed2Untyped(node);
+ return (!)res;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ protected bool IsUniversalQuantifier(VCExprQuantifier! node) {
+ return Polarity == 1 && node.Quan == Quantifier.EX ||
+ Polarity == -1 && node.Quan == Quantifier.ALL;
+ }
+
+ protected List<VCExprVar!>! BoundVarsAfterErasure(List<VCExprVar!>! oldBoundVars,
+ // the mapping between old and new variables
+ // is added to this bindings-object
+ VariableBindings! bindings) {
+ List<VCExprVar!>! newBoundVars = new List<VCExprVar!> (oldBoundVars.Count);
+ foreach (VCExprVar! var in oldBoundVars) {
+ Type! newType = AxBuilder.TypeAfterErasure(var.Type);
+ VCExprVar! newVar = Gen.Variable(var.Name, newType);
+ newBoundVars.Add(newVar);
+ bindings.VCExprVarBindings.Add(var, newVar);
+ }
+ return newBoundVars;
+ }
+
+ // We check whether casts Int2U or Bool2U on the bound variables
+ // occur in triggers. In case a trigger like f(Int2U(x)) occurs,
+ // it may be better to give variable x the type U and remove the
+ // cast. The following method returns true if the quantifier
+ // should be translated again with a different typing
+ protected bool RedoQuantifier(VCExprQuantifier! node,
+ VCExprQuantifier! newNode,
+ // the bound vars that actually occur in the body or
+ // in any of the triggers
+ List<VCExprVar!>! occurringVars,
+ VariableBindings! oldBindings,
+ out VariableBindings! newBindings,
+ out List<VCExprVar!>! newBoundVars) {
+ List<VCExprVar!> castVariables =
+ VariableCastCollector.FindCastVariables(node, newNode, AxBuilder);
+ if (castVariables.Count == 0) {
+ newBindings = oldBindings; // to make the compiler happy
+ newBoundVars = newNode.BoundVars; // to make the compiler happy
+ return false;
+ }
+
+ // redo everything with a different typing ...
+
+ newBindings = oldBindings.Clone();
+ newBoundVars = new List<VCExprVar!> (node.BoundVars.Count);
+ foreach (VCExprVar! var in node.BoundVars) {
+ Type! newType =
+ castVariables.Contains(var) ? AxBuilder.U
+ : AxBuilder.TypeAfterErasure(var.Type);
+ VCExprVar! newVar = Gen.Variable(var.Name, newType);
+ newBoundVars.Add(newVar);
+ newBindings.VCExprVarBindings.Add(var, newVar);
+ }
+
+ return true;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ public override VCExpr! Visit(VCExprLet! node, VariableBindings! bindings) {
+ VariableBindings! newVarBindings = bindings.Clone();
+
+ List<VCExprVar!>! newBoundVars = new List<VCExprVar!> (node.BoundVars.Count);
+ foreach (VCExprVar! var in node.BoundVars) {
+ Type! newType = AxBuilder.TypeAfterErasure(var.Type);
+ VCExprVar! newVar = Gen.Variable(var.Name, newType);
+ newBoundVars.Add(newVar);
+ newVarBindings.VCExprVarBindings.Add(var, newVar);
+ }
+
+ List<VCExprLetBinding!>! newbindings = new List<VCExprLetBinding!> (node.Length);
+ for (int i = 0; i < node.Length; ++i) {
+ VCExprLetBinding! binding = node[i];
+ VCExprVar! newVar = newBoundVars[i];
+ Type! newType = newVar.Type;
+
+ VCExpr! newE = AxBuilder.Cast(Mutate(binding.E, newVarBindings), newType);
+ newbindings.Add(Gen.LetBinding(newVar, newE));
+ }
+
+ VCExpr! newbody = Mutate(node.Body, newVarBindings);
+ return Gen.Let(newbindings, newbody);
+ }
+ }
+
+ //////////////////////////////////////////////////////////////////////////////
+
+ public abstract class OpTypeEraser : StandardVCExprOpVisitor<VCExpr!, VariableBindings!> {
+
+ protected readonly TypeAxiomBuilderIntBoolU! AxBuilder;
+
+ protected readonly TypeEraser! Eraser;
+ protected readonly VCExpressionGenerator! Gen;
+
+ public OpTypeEraser(TypeEraser! eraser, TypeAxiomBuilderIntBoolU! axBuilder,
+ VCExpressionGenerator! gen) {
+ this.AxBuilder = axBuilder;
+ this.Eraser = eraser;
+ this.Gen = gen;
+ }
+
+ protected override VCExpr! StandardResult(VCExprNAry! node, VariableBindings! bindings) {
+ System.Diagnostics.Debug.Fail("Don't know how to erase types in this expression: " + node);
+ assert false; // to please the compiler
+ }
+
+ private List<VCExpr!>! MutateSeq(VCExprNAry! node, VariableBindings! bindings,
+ int newPolarity) {
+ int oldPolarity = Eraser.Polarity;
+ Eraser.Polarity = newPolarity;
+ List<VCExpr!>! newArgs = Eraser.MutateSeq(node, bindings);
+ Eraser.Polarity = oldPolarity;
+ return newArgs;
+ }
+
+ private VCExpr! CastArguments(VCExprNAry! node, Type! argType, VariableBindings! bindings,
+ int newPolarity) {
+ return Gen.Function(node.Op,
+ AxBuilder.CastSeq(MutateSeq(node, bindings, newPolarity),
+ argType));
+ }
+
+ // Cast the arguments of the node to their old type if necessary and possible; otherwise use
+ // their new type (int, bool, or U)
+ private VCExpr! CastArgumentsToOldType(VCExprNAry! node, VariableBindings! bindings,
+ int newPolarity)
+ requires node.Arity > 0; {
+
+ List<VCExpr!>! newArgs = MutateSeq(node, bindings, newPolarity);
+ Type! oldType = node[0].Type;
+ if (AxBuilder.UnchangedType(oldType) &&
+ forall{int i in (1:node.Arity); node[i].Type.Equals(oldType)})
+ return Gen.Function(node.Op, AxBuilder.CastSeq(newArgs, oldType));
+ else
+ return Gen.Function(node.Op, AxBuilder.CastSeq(newArgs, AxBuilder.U));
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+
+ public override VCExpr! VisitNotOp (VCExprNAry! node, VariableBindings! bindings) {
+ return CastArguments(node, Type.Bool, bindings, -Eraser.Polarity);
+ }
+ public override VCExpr! VisitEqOp (VCExprNAry! node, VariableBindings! bindings) {
+ return CastArgumentsToOldType(node, bindings, 0);
+ }
+ public override VCExpr! VisitNeqOp (VCExprNAry! node, VariableBindings! bindings) {
+ return CastArgumentsToOldType(node, bindings, 0);
+ }
+ public override VCExpr! VisitImpliesOp (VCExprNAry! node, VariableBindings! bindings) {
+ // UGLY: the code for tracking polarities should be factored out
+ List<VCExpr!>! newArgs = new List<VCExpr!> (2);
+ Eraser.Polarity = -Eraser.Polarity;
+ newArgs.Add(Eraser.Mutate(node[0], bindings));
+ Eraser.Polarity = -Eraser.Polarity;
+ newArgs.Add(Eraser.Mutate(node[1], bindings));
+ return Gen.Function(node.Op, AxBuilder.CastSeq(newArgs, Type.Bool));
+ }
+ public override VCExpr! VisitDistinctOp (VCExprNAry! node, VariableBindings! bindings) {
+ return CastArgumentsToOldType(node, bindings, 0);
+ }
+ public override VCExpr! VisitLabelOp (VCExprNAry! node, VariableBindings! bindings) {
+ // argument of the label operator should always be a formula
+ // (at least for Simplify ... should this be ensured at a later point?)
+ return CastArguments(node, Type.Bool, bindings, Eraser.Polarity);
+ }
+ public override VCExpr! VisitAddOp (VCExprNAry! node, VariableBindings! bindings) {
+ return CastArguments(node, Type.Int, bindings, 0);
+ }
+ public override VCExpr! VisitSubOp (VCExprNAry! node, VariableBindings! bindings) {
+ return CastArguments(node, Type.Int, bindings, 0);
+ }
+ public override VCExpr! VisitMulOp (VCExprNAry! node, VariableBindings! bindings) {
+ return CastArguments(node, Type.Int, bindings, 0);
+ }
+ public override VCExpr! VisitDivOp (VCExprNAry! node, VariableBindings! bindings) {
+ return CastArguments(node, Type.Int, bindings, 0);
+ }
+ public override VCExpr! VisitModOp (VCExprNAry! node, VariableBindings! bindings) {
+ return CastArguments(node, Type.Int, bindings, 0);
+ }
+ public override VCExpr! VisitLtOp (VCExprNAry! node, VariableBindings! bindings) {
+ return CastArguments(node, Type.Int, bindings, 0);
+ }
+ public override VCExpr! VisitLeOp (VCExprNAry! node, VariableBindings! bindings) {
+ return CastArguments(node, Type.Int, bindings, 0);
+ }
+ public override VCExpr! VisitGtOp (VCExprNAry! node, VariableBindings! bindings) {
+ return CastArguments(node, Type.Int, bindings, 0);
+ }
+ public override VCExpr! VisitGeOp (VCExprNAry! node, VariableBindings! bindings) {
+ return CastArguments(node, Type.Int, bindings, 0);
+ }
+ public override VCExpr! VisitSubtypeOp (VCExprNAry! node, VariableBindings! bindings) {
+ return CastArguments(node, AxBuilder.U, bindings, 0);
+ }
+ public override VCExpr! VisitBvOp (VCExprNAry! node, VariableBindings! bindings) {
+ return CastArgumentsToOldType(node, bindings, 0);
+ }
+ public override VCExpr! VisitBvExtractOp(VCExprNAry! node, VariableBindings! bindings) {
+ return CastArgumentsToOldType(node, bindings, 0);
+ }
+ public override VCExpr! VisitBvConcatOp (VCExprNAry! node, VariableBindings! bindings) {
+ List<VCExpr!>! newArgs = MutateSeq(node, bindings, 0);
+
+ // each argument is cast to its old type
+ assert newArgs.Count == node.Arity && newArgs.Count == 2;
+ VCExpr! arg0 = AxBuilder.Cast(newArgs[0], node[0].Type);
+ VCExpr! arg1 = AxBuilder.Cast(newArgs[1], node[1].Type);
+
+ return Gen.Function(node.Op, arg0, arg1);
+ }
+
+ }
+
+ //////////////////////////////////////////////////////////////////////////////
+
+ /// <summary>
+ /// Collect all variables x occurring in expressions of the form Int2U(x) or Bool2U(x), and
+ /// collect all variables x occurring outside such forms.
+ /// </summary>
+ internal class VariableCastCollector : TraversingVCExprVisitor<bool, bool> {
+ /// <summary>
+ /// Determine those bound variables in "oldNode" <em>all</em> of whose relevant uses
+ /// have to be cast in potential triggers in "newNode". It is assume that
+ /// the bound variables of "oldNode" correspond to the first bound
+ /// variables of "newNode".
+ /// </summary>
+ public static List<VCExprVar!>! FindCastVariables(VCExprQuantifier! oldNode,
+ VCExprQuantifier! newNode,
+ TypeAxiomBuilderIntBoolU! axBuilder) {
+ VariableCastCollector! collector = new VariableCastCollector(axBuilder);
+ if (exists{VCTrigger! trigger in newNode.Triggers; trigger.Pos}) {
+ // look in the given triggers
+ foreach (VCTrigger! trigger in newNode.Triggers)
+ if (trigger.Pos)
+ foreach (VCExpr! expr in trigger.Exprs)
+ collector.Traverse(expr, true);
+ } else {
+ // look in the body of the quantifier
+ collector.Traverse(newNode.Body, true);
+ }
+
+ List<VCExprVar!>! castVariables = new List<VCExprVar!> (collector.varsInCasts.Count);
+ foreach (VCExprVar! castVar in collector.varsInCasts) {
+ int i = newNode.BoundVars.IndexOf(castVar);
+ if (0 <= i && i < oldNode.BoundVars.Count && !collector.varsOutsideCasts.ContainsKey(castVar))
+ castVariables.Add(oldNode.BoundVars[i]);
+ }
+ return castVariables;
+ }
+
+ public VariableCastCollector(TypeAxiomBuilderIntBoolU! axBuilder) {
+ this.AxBuilder = axBuilder;
+ }
+
+ readonly List<VCExprVar!>! varsInCasts = new List<VCExprVar!> ();
+ readonly Dictionary<VCExprVar!,object>! varsOutsideCasts = new Dictionary<VCExprVar!,object> ();
+
+ readonly TypeAxiomBuilderIntBoolU! AxBuilder;
+
+ protected override bool StandardResult(VCExpr! node, bool arg) {
+ return true; // not used
+ }
+
+ public override bool Visit(VCExprNAry! node, bool arg) {
+ if (node.Op is VCExprBoogieFunctionOp) {
+ Function! func = ((VCExprBoogieFunctionOp)node.Op).Func;
+ if ((AxBuilder.IsCast(func)) && node[0] is VCExprVar) {
+ VCExprVar castVar = (VCExprVar)node[0];
+ if (!varsInCasts.Contains(castVar))
+ varsInCasts.Add(castVar);
+ return true;
+ }
+ } else if (node.Op is VCExprNAryOp) {
+ VCExpressionGenerator.SingletonOp op = VCExpressionGenerator.SingletonOpDict[node.Op];
+ switch(op) {
+ // the following operators cannot be used in triggers, so disregard any uses of variables as direct arguments
+ case VCExpressionGenerator.SingletonOp.NotOp:
+ case VCExpressionGenerator.SingletonOp.EqOp:
+ case VCExpressionGenerator.SingletonOp.NeqOp:
+ case VCExpressionGenerator.SingletonOp.AndOp:
+ case VCExpressionGenerator.SingletonOp.OrOp:
+ case VCExpressionGenerator.SingletonOp.ImpliesOp:
+ case VCExpressionGenerator.SingletonOp.LtOp:
+ case VCExpressionGenerator.SingletonOp.LeOp:
+ case VCExpressionGenerator.SingletonOp.GtOp:
+ case VCExpressionGenerator.SingletonOp.GeOp:
+ foreach (VCExpr n in node) {
+ if (!(n is VCExprVar)) { // don't recurse on VCExprVar argument
+ n.Accept<bool,bool>(this, arg);
+ }
+ }
+ return true;
+ default:
+ break;
+ }
+ }
+ return base.Visit(node, arg);
+ }
+
+ public override bool Visit(VCExprVar! node, bool arg) {
+ if (!varsOutsideCasts.ContainsKey(node))
+ varsOutsideCasts.Add(node, null);
+ return true;
+ }
+ }
+
+}
diff --git a/Source/VCExpr/TypeErasureArguments.ssc b/Source/VCExpr/TypeErasureArguments.ssc
new file mode 100644
index 00000000..434866f8
--- /dev/null
+++ b/Source/VCExpr/TypeErasureArguments.ssc
@@ -0,0 +1,618 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using System;
+using System.Text;
+using System.IO;
+using System.Collections;
+using System.Collections.Generic;
+using Microsoft.Contracts;
+using Microsoft.Basetypes;
+using Microsoft.Boogie.VCExprAST;
+
+// Erasure of types using explicit type parameters for functions
+
+namespace Microsoft.Boogie.TypeErasure
+{
+ using Microsoft.Boogie.VCExprAST;
+ using HFNS = Microsoft.Boogie.VCExprAST.HelperFuns;
+
+ public class TypeAxiomBuilderArguments : TypeAxiomBuilderIntBoolU {
+
+ public TypeAxiomBuilderArguments(VCExpressionGenerator! gen) {
+ base(gen);
+ Typed2UntypedFunctions = new Dictionary<Function!, Function!> ();
+ }
+
+ // constructor to allow cloning
+ [NotDelayed]
+ internal TypeAxiomBuilderArguments(TypeAxiomBuilderArguments! builder) {
+ Typed2UntypedFunctions =
+ new Dictionary<Function!, Function!> (builder.Typed2UntypedFunctions);
+ base(builder);
+
+ MapTypeAbstracterAttr =
+ builder.MapTypeAbstracterAttr == null ?
+ null : new MapTypeAbstractionBuilderArguments(this, builder.Gen,
+ builder.MapTypeAbstracterAttr);
+ }
+
+ public override Object! Clone() {
+ return new TypeAxiomBuilderArguments(this);
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////
+
+ // generate axioms of the kind "forall x:U. {Int2U(U2Int(x))} Int2U(U2Int(x))==x"
+ // (this makes use of the assumption that only well-typed terms are generated
+ // by the SMT-solver, i.e., that U2Int is only applied to terms that actually
+ // are of type int)
+ protected override VCExpr! GenReverseCastAxiom(Function! castToU,
+ Function! castFromU) {
+ List<VCTrigger!>! triggers;
+ VCExprVar! var;
+ VCExpr! eq = GenReverseCastEq(castToU, castFromU, out var, out triggers);
+ return Gen.Forall(HelperFuns.ToList(var), triggers, "cast:" + castFromU.Name, eq);
+ }
+
+ protected override VCExpr! GenCastTypeAxioms(Function! castToU,
+ Function! castFromU) {
+ // nothing
+ return VCExpressionGenerator.True;
+ }
+
+ private MapTypeAbstractionBuilderArguments MapTypeAbstracterAttr = null;
+
+ internal override MapTypeAbstractionBuilder! MapTypeAbstracter { get {
+ if (MapTypeAbstracterAttr == null)
+ MapTypeAbstracterAttr = new MapTypeAbstractionBuilderArguments (this, Gen);
+ return MapTypeAbstracterAttr;
+ } }
+
+ protected override void AddVarTypeAxiom(VCExprVar! var, Type! originalType) {
+ // no axioms are needed for variable or function types
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Symbols for representing functions
+
+ // Globally defined functions
+ private readonly IDictionary<Function!, Function!>! Typed2UntypedFunctions;
+
+ public Function! Typed2Untyped(Function! fun) {
+ Function res;
+ if (!Typed2UntypedFunctions.TryGetValue(fun, out res)) {
+ assert fun.OutParams.Length == 1;
+
+ // if all of the parameters are int or bool, the function does
+ // not have to be changed
+ if (forall{Formal f in fun.InParams; UnchangedType(((!)f).TypedIdent.Type)} &&
+ UnchangedType(((!)fun.OutParams[0]).TypedIdent.Type)) {
+ res = fun;
+ } else {
+ Type[]! types = new Type [fun.TypeParameters.Length + fun.InParams.Length + 1];
+
+ int i = 0;
+ // the first arguments are the explicit type parameters
+ for (int j = 0; j < fun.TypeParameters.Length; ++j) {
+ types[i] = T;
+ i = i + 1;
+ }
+ // followed by the actual parameters
+ foreach (Variable! x in fun.InParams) {
+ types[i] = TypeAfterErasure(x.TypedIdent.Type);
+ i = i + 1;
+ }
+
+ types[types.Length - 1] = TypeAfterErasure(((!)fun.OutParams[0]).TypedIdent.Type);
+
+ res = HelperFuns.BoogieFunction(fun.Name, types);
+ res.Attributes = fun.Attributes;
+ }
+
+ Typed2UntypedFunctions.Add(fun, res);
+ }
+ return (!)res;
+ }
+
+ }
+
+ //////////////////////////////////////////////////////////////////////////////
+
+ internal class MapTypeAbstractionBuilderArguments : MapTypeAbstractionBuilder {
+
+ private readonly TypeAxiomBuilderArguments! AxBuilderArguments;
+
+ internal MapTypeAbstractionBuilderArguments(TypeAxiomBuilderArguments! axBuilder,
+ VCExpressionGenerator! gen) {
+ base(axBuilder, gen);
+ this.AxBuilderArguments = axBuilder;
+ }
+
+ // constructor for cloning
+ internal MapTypeAbstractionBuilderArguments(TypeAxiomBuilderArguments! axBuilder,
+ VCExpressionGenerator! gen,
+ MapTypeAbstractionBuilderArguments! builder) {
+ base(axBuilder, gen, builder);
+ this.AxBuilderArguments = axBuilder;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ protected override void GenSelectStoreFunctions(MapType! abstractedType,
+ TypeCtorDecl! synonym,
+ out Function! select,
+ out Function! store) {
+ string! baseName = synonym.Name;
+ int typeParamNum = abstractedType.FreeVariables.Length +
+ abstractedType.TypeParameters.Length;
+ int arity = typeParamNum + abstractedType.Arguments.Length;
+
+ Type![]! selectTypes = new Type! [arity + 2];
+ Type![]! storeTypes = new Type! [arity + 3];
+
+ int i = 0;
+ // Fill in the free variables and type parameters
+ for (; i < typeParamNum; i++) {
+ selectTypes[i] = AxBuilder.T;
+ storeTypes[i] = AxBuilder.T;
+ }
+ // Fill in the map type
+ selectTypes[i] = AxBuilder.U;
+ storeTypes[i] = AxBuilder.U;
+ i++;
+ // Fill in the index types
+ foreach (Type! type in abstractedType.Arguments)
+ {
+ if (CommandLineOptions.Clo.Monomorphize && AxBuilder.UnchangedType(type))
+ {
+ selectTypes[i] = type;
+ storeTypes[i] = type;
+ }
+ else
+ {
+ selectTypes[i] = AxBuilder.U;
+ storeTypes[i] = AxBuilder.U;
+ }
+ i++;
+ }
+ // Fill in the output type for select function which also happens
+ // to be the type of the last argument to the store function
+ if (CommandLineOptions.Clo.Monomorphize && AxBuilder.UnchangedType(abstractedType.Result))
+ {
+ selectTypes[i] = abstractedType.Result;
+ storeTypes[i] = abstractedType.Result;
+ }
+ else
+ {
+ selectTypes[i] = AxBuilder.U;
+ storeTypes[i] = AxBuilder.U;
+ }
+ i++;
+ // Fill in the map type which is the output of the store function
+ storeTypes[i] = AxBuilder.U;
+ NonNullType.AssertInitialized(selectTypes);
+ NonNullType.AssertInitialized(storeTypes);
+
+ select = HelperFuns.BoogieFunction(baseName + "Select", selectTypes);
+ store = HelperFuns.BoogieFunction(baseName + "Store", storeTypes);
+
+ AxBuilder.AddTypeAxiom(GenMapAxiom0(select, store,
+ abstractedType.TypeParameters.Length, abstractedType.FreeVariables.Length));
+ AxBuilder.AddTypeAxiom(GenMapAxiom1(select, store,
+ abstractedType.TypeParameters.Length, abstractedType.FreeVariables.Length));
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // The normal axioms of the theory of arrays (right now without extensionality)
+
+ private VCExpr! Select(Function! select, List<VCExprVar!>! types,
+ VCExpr! map, List<VCExprVar!>! indexes) {
+ List<VCExpr!>! selectArgs = new List<VCExpr!> ();
+ selectArgs.AddRange(HelperFuns.ToVCExprList(types));
+ selectArgs.Add(map);
+ selectArgs.AddRange(HelperFuns.ToVCExprList(indexes));
+ return Gen.Function(select, selectArgs);
+ }
+
+ private VCExpr! Store(Function! store, List<VCExprVar!>! types,
+ VCExpr! map, List<VCExprVar!>! indexes, VCExpr! val) {
+ List<VCExpr!>! storeArgs = new List<VCExpr!> ();
+ storeArgs.AddRange(HelperFuns.ToVCExprList(types));
+ storeArgs.Add(map);
+ storeArgs.AddRange(HelperFuns.ToVCExprList(indexes));
+ storeArgs.Add(val);
+ return Gen.Function(store, storeArgs);
+ }
+
+ private VCExpr! GenMapAxiom0(Function! select, Function! store,
+ // bound type variables in the map type
+ int mapTypeParamNum,
+ // free type variables in the map
+ // type (abstraction)
+ int mapAbstractionVarNum) {
+ int arity = select.InParams.Length - 1 - mapTypeParamNum - mapAbstractionVarNum;
+ List<VCExprVar!>! types =
+ HelperFuns.VarVector("t", mapTypeParamNum + mapAbstractionVarNum,
+ AxBuilder.T, Gen);
+
+ List<Type!> indexTypes = new List<Type!>();
+ for (int i = mapTypeParamNum + mapAbstractionVarNum + 1; i < select.InParams.Length; i++)
+ {
+ indexTypes.Add(((!)select.InParams[i]).TypedIdent.Type);
+ }
+ assert arity == indexTypes.Count;
+
+ List<VCExprVar!>! indexes = HelperFuns.VarVector("x", indexTypes, Gen);
+
+ VCExprVar! m = Gen.Variable("m", AxBuilder.U);
+ VCExprVar! val = Gen.Variable("val", ((!)select.OutParams[0]).TypedIdent.Type);
+
+ VCExpr! storeExpr = Store(store, types, m, indexes, val);
+ VCExpr! selectExpr = Select(select, types, storeExpr, indexes);
+
+ List<VCExprVar!>! quantifiedVars = new List<VCExprVar!> ();
+ quantifiedVars.AddRange(types);
+ quantifiedVars.Add(val);
+ quantifiedVars.Add(m);
+ quantifiedVars.AddRange(indexes);
+
+ VCExpr! eq = Gen.Eq(selectExpr, val);
+ return Gen.Forall(quantifiedVars, new List<VCTrigger!> (),
+ "mapAx0:" + select.Name, eq);
+ }
+
+ private VCExpr! GenMapAxiom1(Function! select, Function! store,
+ // bound type variables in the map
+ // type
+ int mapTypeParamNum,
+ // free type variables in the map
+ // type (abstraction)
+ int mapAbstractionVarNum) {
+ int arity = select.InParams.Length - 1 - mapTypeParamNum - mapAbstractionVarNum;
+
+ List<VCExprVar!>! freeTypeVars =
+ HelperFuns.VarVector("u", mapAbstractionVarNum, AxBuilder.T, Gen);
+ List<VCExprVar!>! boundTypeVars0 =
+ HelperFuns.VarVector("s", mapTypeParamNum, AxBuilder.T, Gen);
+ List<VCExprVar!>! boundTypeVars1 =
+ HelperFuns.VarVector("t", mapTypeParamNum, AxBuilder.T, Gen);
+
+ List<VCExprVar!>! types0 = new List<VCExprVar!> (boundTypeVars0);
+ types0.AddRange(freeTypeVars);
+
+ List<VCExprVar!>! types1 = new List<VCExprVar!> (boundTypeVars1);
+ types1.AddRange(freeTypeVars);
+
+ List<Type!> indexTypes = new List<Type!>();
+ for (int i = mapTypeParamNum + mapAbstractionVarNum + 1; i < select.InParams.Length; i++)
+ {
+ indexTypes.Add(((!)select.InParams[i]).TypedIdent.Type);
+ }
+ assert arity == indexTypes.Count;
+
+ List<VCExprVar!>! indexes0 = HelperFuns.VarVector("x", indexTypes, Gen);
+ List<VCExprVar!>! indexes1 = HelperFuns.VarVector("y", indexTypes, Gen);
+
+ VCExprVar! m = Gen.Variable("m", AxBuilder.U);
+ VCExprVar! val = Gen.Variable("val", ((!)select.OutParams[0]).TypedIdent.Type);
+
+ VCExpr! storeExpr = Store(store, types0, m, indexes0, val);
+ VCExpr! selectWithoutStoreExpr = Select(select, types1, m, indexes1);
+ VCExpr! selectExpr = Select(select, types1, storeExpr, indexes1);
+
+ VCExpr! selectEq = Gen.Eq(selectExpr, selectWithoutStoreExpr);
+
+ List<VCExprVar!>! quantifiedVars = new List<VCExprVar!> ();
+ quantifiedVars.AddRange(freeTypeVars);
+ quantifiedVars.AddRange(boundTypeVars0);
+ quantifiedVars.AddRange(boundTypeVars1);
+ quantifiedVars.Add(val);
+ quantifiedVars.Add(m);
+ quantifiedVars.AddRange(indexes0);
+ quantifiedVars.AddRange(indexes1);
+
+ List<VCTrigger!>! triggers = new List<VCTrigger!> ();
+
+ // different value arguments or different type arguments are sufficient
+ // to conclude that that value of the map at some point (after an update)
+ // has not changed
+
+ List<VCExpr!>! indexEqs = new List<VCExpr!> ();
+ for (int i = 0; i < mapTypeParamNum; ++i)
+ indexEqs.Add(Gen.Eq(boundTypeVars0[i], boundTypeVars1[i]));
+ for (int i = 0; i < arity; ++i)
+ indexEqs.Add(Gen.Eq(indexes0[i], indexes1[i]));
+
+ VCExpr! axiom = VCExpressionGenerator.True;
+ int n = 0;
+ foreach (VCExpr! indexesEq in indexEqs) {
+ VCExpr! matrix = Gen.Or(indexesEq, selectEq);
+ VCExpr! conjunct = Gen.Forall(quantifiedVars, triggers,
+ "mapAx1:" + select.Name + ":" + n, matrix);
+ axiom = Gen.AndSimp(axiom, conjunct);
+ n = n + 1;
+ }
+
+ return axiom;
+ }
+ }
+
+ //////////////////////////////////////////////////////////////////////////////
+
+ public class TypeEraserArguments : TypeEraser {
+
+ private readonly TypeAxiomBuilderArguments! AxBuilderArguments;
+
+ private OpTypeEraser OpEraserAttr = null;
+ protected override OpTypeEraser! OpEraser { get {
+ if (OpEraserAttr == null)
+ OpEraserAttr = new OpTypeEraserArguments(this, AxBuilderArguments, Gen);
+ return OpEraserAttr;
+ } }
+
+ public TypeEraserArguments(TypeAxiomBuilderArguments! axBuilder,
+ VCExpressionGenerator! gen) {
+ base(axBuilder, gen);
+ this.AxBuilderArguments = axBuilder;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ public override VCExpr! Visit(VCExprQuantifier! node,
+ VariableBindings! oldBindings) {
+ VariableBindings! bindings = oldBindings.Clone();
+
+ // bound term variables are replaced with bound term variables
+ // typed in a simpler way
+ List<VCExprVar!>! newBoundVars =
+ BoundVarsAfterErasure(node.BoundVars, bindings);
+
+ // type variables are replaced with ordinary quantified variables
+ GenBoundVarsForTypeParams(node.TypeParameters, newBoundVars, bindings);
+ VCExpr! newNode = HandleQuantifier(node, newBoundVars, bindings);
+
+ if (!(newNode is VCExprQuantifier) || !IsUniversalQuantifier(node))
+ return newNode;
+
+ VariableBindings! bindings2;
+ if (!RedoQuantifier(node, (VCExprQuantifier)newNode, node.BoundVars, oldBindings,
+ out bindings2, out newBoundVars))
+ return newNode;
+
+ GenBoundVarsForTypeParams(node.TypeParameters, newBoundVars, bindings2);
+ return HandleQuantifier(node, newBoundVars, bindings2);
+ }
+
+ private void GenBoundVarsForTypeParams(List<TypeVariable!>! typeParams,
+ List<VCExprVar!>! newBoundVars,
+ VariableBindings! bindings) {
+ foreach (TypeVariable! tvar in typeParams) {
+ VCExprVar! var = Gen.Variable(tvar.Name, AxBuilder.T);
+ newBoundVars.Add(var);
+ bindings.TypeVariableBindings.Add(tvar, var);
+ }
+ }
+
+ private VCExpr! HandleQuantifier(VCExprQuantifier! node,
+ List<VCExprVar!>! newBoundVars,
+ VariableBindings! bindings) {
+ List<VCTrigger!>! newTriggers = MutateTriggers(node.Triggers, bindings);
+ VCExpr! newBody = Mutate(node.Body, bindings);
+ newBody = AxBuilder.Cast(newBody, Type.Bool);
+
+ if (newBoundVars.Count == 0) // might happen that no bound variables are left
+ return newBody;
+ return Gen.Quantify(node.Quan, new List<TypeVariable!> (), newBoundVars,
+ newTriggers, node.Infos, newBody);
+ }
+ }
+
+ //////////////////////////////////////////////////////////////////////////////
+
+ public class OpTypeEraserArguments : OpTypeEraser {
+
+ protected readonly TypeAxiomBuilderArguments! AxBuilderArguments;
+
+ public OpTypeEraserArguments(TypeEraserArguments! eraser,
+ TypeAxiomBuilderArguments! axBuilder,
+ VCExpressionGenerator! gen) {
+ base(eraser, axBuilder, gen);
+ this.AxBuilderArguments = axBuilder;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ private VCExpr! AssembleOpExpression(OpTypesPair opTypes,
+ IEnumerable<VCExpr!>! oldArgs,
+ VariableBindings! bindings) {
+ // UGLY: the code for tracking polarities should be factored out
+ int oldPolarity = Eraser.Polarity;
+ Eraser.Polarity = 0;
+
+ List<VCExpr!>! newArgs = new List<VCExpr!> ();
+ // explicit type parameters
+ foreach (Type! t in opTypes.Types)
+ newArgs.Add(AxBuilder.Type2Term(t, bindings.TypeVariableBindings));
+
+ // and the actual value parameters
+ Function! newFun = ((VCExprBoogieFunctionOp)opTypes.Op).Func;
+ // ^ we only allow this operator at this point
+ int i = opTypes.Types.Count;
+ foreach (VCExpr! arg in oldArgs) {
+ newArgs.Add(AxBuilder.Cast(Eraser.Mutate(arg, bindings),
+ ((!)newFun.InParams[i]).TypedIdent.Type));
+ i = i + 1;
+ }
+
+ Eraser.Polarity = oldPolarity;
+ return Gen.Function(opTypes.Op, newArgs);
+ }
+
+ // for the time being, we store both the types of the arguments and the explicit
+ // type parameters (for most operators, this is more than actually necessary)
+ private OpTypesPair OriginalOpTypes(VCExprNAry! node) {
+ List<Type!>! originalTypes = new List<Type!> ();
+ foreach (VCExpr! expr in node)
+ originalTypes.Add(expr.Type);
+ originalTypes.AddRange(node.TypeArguments);
+ return new OpTypesPair (node.Op, originalTypes);
+ }
+
+ private VCExpr! EqualTypes(Type! t0, Type! t1, VariableBindings! bindings) {
+ if (t0.Equals(t1))
+ return VCExpressionGenerator.True;
+ VCExpr! t0Expr = AxBuilder.Type2Term(t0, bindings.TypeVariableBindings);
+ VCExpr! t1Expr = AxBuilder.Type2Term(t1, bindings.TypeVariableBindings);
+ return Gen.Eq(t0Expr, t1Expr);
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+
+ public override VCExpr! VisitEqOp (VCExprNAry! node, VariableBindings! bindings) {
+ // we also have to state that the types are equal, because the
+ // translation does not contain any information about the
+ // relationship between values and types
+ return Gen.AndSimp(base.VisitEqOp(node, bindings),
+ EqualTypes(node[0].Type, node[1].Type, bindings));
+ }
+
+ public override VCExpr! VisitNeqOp (VCExprNAry! node, VariableBindings! bindings) {
+ // we also have to state that the types are (un)equal, because the
+ // translation does not contain any information about the
+ // relationship between values and types
+ return Gen.OrSimp(base.VisitNeqOp(node, bindings),
+ Gen.Not(EqualTypes(node[0].Type, node[1].Type, bindings)));
+ }
+
+ public override VCExpr! VisitSubtypeOp (VCExprNAry! node, VariableBindings! bindings) {
+ // UGLY: the code for tracking polarities should be factored out
+ int oldPolarity = Eraser.Polarity;
+ Eraser.Polarity = 0;
+
+ VCExpr! res =
+ Gen.Function(VCExpressionGenerator.Subtype3Op,
+ AxBuilder.Type2Term(node[0].Type,
+ bindings.TypeVariableBindings),
+ AxBuilder.Cast(Eraser.Mutate(node[0], bindings),
+ AxBuilder.U),
+ AxBuilder.Cast(Eraser.Mutate(node[1], bindings),
+ AxBuilder.U));
+
+ Eraser.Polarity = oldPolarity;
+ return res;
+ }
+
+ public override VCExpr! VisitSelectOp (VCExprNAry! node, VariableBindings! bindings) {
+ OpTypesPair originalOpTypes = OriginalOpTypes(node);
+ OpTypesPair newOpTypes;
+
+ if (!NewOpCache.TryGetValue(originalOpTypes, out newOpTypes)) {
+ MapType! rawType = node[0].Type.AsMap;
+ TypeSeq! abstractionInstantiation;
+ Function! select =
+ AxBuilder.MapTypeAbstracter.Select(rawType, out abstractionInstantiation);
+
+ newOpTypes = TypesPairForSelectStore(node, select, abstractionInstantiation);
+ NewOpCache.Add(originalOpTypes, newOpTypes);
+ }
+
+ return AssembleOpExpression(newOpTypes, node, bindings);
+ }
+
+ public override VCExpr! VisitStoreOp (VCExprNAry! node, VariableBindings! bindings) {
+ OpTypesPair originalOpTypes = OriginalOpTypes(node);
+ OpTypesPair newOpTypes;
+
+ if (!NewOpCache.TryGetValue(originalOpTypes, out newOpTypes)) {
+ MapType! rawType = node[0].Type.AsMap;
+ TypeSeq! abstractionInstantiation;
+ Function! store =
+ AxBuilder.MapTypeAbstracter.Store(rawType, out abstractionInstantiation);
+
+ newOpTypes = TypesPairForSelectStore(node, store, abstractionInstantiation);
+ NewOpCache.Add(originalOpTypes, newOpTypes);
+ }
+
+ return AssembleOpExpression(newOpTypes, node, bindings);
+ }
+
+ private OpTypesPair TypesPairForSelectStore(VCExprNAry! node, Function! untypedOp,
+ // instantiation of the abstract map type parameters
+ TypeSeq! abstractionInstantiation) {
+ List<Type!>! inferredTypeArgs = new List<Type!> ();
+ foreach (Type! t in node.TypeArguments)
+// inferredTypeArgs.Add(AxBuilder.MapTypeAbstracter.AbstractMapTypeRecursively(t));
+ inferredTypeArgs.Add(t);
+ foreach (Type! t in abstractionInstantiation)
+ inferredTypeArgs.Add(t);
+
+ assert untypedOp.InParams.Length == inferredTypeArgs.Count + node.Arity;
+ return new OpTypesPair (Gen.BoogieFunctionOp(untypedOp), inferredTypeArgs);
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+
+ public override VCExpr! VisitBoogieFunctionOp (VCExprNAry! node, VariableBindings! bindings) {
+ OpTypesPair originalOpTypes = OriginalOpTypes(node);
+ OpTypesPair newOpTypes;
+
+ if (!NewOpCache.TryGetValue(originalOpTypes, out newOpTypes)) {
+ Function! oriFun = ((VCExprBoogieFunctionOp)node.Op).Func;
+
+ List<Type!>! inferredTypeArgs = new List<Type!> ();
+ foreach (Type! t in node.TypeArguments)
+// inferredTypeArgs.Add(AxBuilder.MapTypeAbstracter.AbstractMapTypeRecursively(t));
+ inferredTypeArgs.Add(t);
+
+ VCExprOp! newOp = Gen.BoogieFunctionOp(AxBuilderArguments.Typed2Untyped(oriFun));
+ newOpTypes = new OpTypesPair (newOp, inferredTypeArgs);
+
+ NewOpCache.Add(originalOpTypes, newOpTypes);
+ }
+
+ return AssembleOpExpression(newOpTypes, node, bindings);
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+
+ // cache from the typed operators to the untyped operators with
+ // explicit type arguments. the keys are pairs of the typed
+ // operator and the actual types of the argument expressions, the
+ // values are pairs of the new operators and the types that have
+ // to be given as explicit type arguments
+ private readonly IDictionary<OpTypesPair, OpTypesPair>! NewOpCache =
+ new Dictionary<OpTypesPair, OpTypesPair>();
+
+ private struct OpTypesPair {
+ public readonly VCExprOp! Op;
+ public readonly List<Type!>! Types;
+
+ public OpTypesPair(VCExprOp! op, List<Type!>! types) {
+ this.Op = op;
+ this.Types = types;
+ this.HashCode = HFNS.PolyHash(op.GetHashCode(), 17, types);
+ }
+
+ [Pure][Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals(object that) {
+ if (that is OpTypesPair) {
+ OpTypesPair thatPair = (OpTypesPair)that;
+ return this.Op.Equals(thatPair.Op) &&
+ HFNS.SameElements(this.Types, thatPair.Types);
+ }
+ return false;
+ }
+
+ private readonly int HashCode;
+
+ [Pure]
+ public override int GetHashCode() {
+ return HashCode;
+ }
+ }
+ }
+
+}
diff --git a/Source/VCExpr/TypeErasurePremisses.ssc b/Source/VCExpr/TypeErasurePremisses.ssc
new file mode 100644
index 00000000..16ec87e6
--- /dev/null
+++ b/Source/VCExpr/TypeErasurePremisses.ssc
@@ -0,0 +1,1025 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using System;
+using System.Text;
+using System.IO;
+using System.Collections;
+using System.Collections.Generic;
+using Microsoft.Contracts;
+using Microsoft.Basetypes;
+using Microsoft.Boogie.VCExprAST;
+
+// Erasure of types using premisses (forall x :: type(x)=T ==> p(x))
+
+namespace Microsoft.Boogie.TypeErasure
+{
+ using Microsoft.Boogie.VCExprAST;
+
+ // When using type premisses, we can distinguish two kinds of type
+ // parameters of a function or map: parameters that occur in the
+ // formal argument types of the function are "implicit" because they
+ // can be inferred from the actual argument types; parameters that
+ // only occur in the result type of the function are "explicit"
+ // because they are not inferrable and have to be given to the
+ // function as additional arguments.
+ //
+ // The following structure is used to store the untyped version of a
+ // typed function, together with the lists of implicit and explicit
+ // type parameters (in the same order as they occur in the signature
+ // of the original function).
+
+ internal struct UntypedFunction {
+ public readonly Function! Fun;
+ // type parameters that can be extracted from the value parameters
+ public readonly List<TypeVariable!>! ImplicitTypeParams;
+ // type parameters that have to be given explicitly
+ public readonly List<TypeVariable!>! ExplicitTypeParams;
+
+ public UntypedFunction(Function! fun,
+ List<TypeVariable!>! implicitTypeParams,
+ List<TypeVariable!>! explicitTypeParams) {
+ Fun = fun;
+ ImplicitTypeParams = implicitTypeParams;
+ ExplicitTypeParams = explicitTypeParams;
+ }
+ }
+
+ public class TypeAxiomBuilderPremisses : TypeAxiomBuilderIntBoolU {
+
+ public TypeAxiomBuilderPremisses(VCExpressionGenerator! gen) {
+ base(gen);
+ TypeFunction = HelperFuns.BoogieFunction("dummy", Type.Int);
+ Typed2UntypedFunctions = new Dictionary<Function!, UntypedFunction> ();
+ MapTypeAbstracterAttr = null;
+ }
+
+ // constructor to allow cloning
+ [NotDelayed]
+ internal TypeAxiomBuilderPremisses(TypeAxiomBuilderPremisses! builder) {
+ TypeFunction = builder.TypeFunction;
+ Typed2UntypedFunctions =
+ new Dictionary<Function!, UntypedFunction> (builder.Typed2UntypedFunctions);
+ base(builder);
+
+ MapTypeAbstracterAttr =
+ builder.MapTypeAbstracterAttr == null ?
+ null : new MapTypeAbstractionBuilderPremisses(this, builder.Gen,
+ builder.MapTypeAbstracterAttr);
+ }
+
+ public override Object! Clone() {
+ return new TypeAxiomBuilderPremisses(this);
+ }
+
+ public override void Setup() {
+ TypeFunction = HelperFuns.BoogieFunction("type", U, T);
+ base.Setup();
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ // generate axioms of the kind "forall x:U. {Int2U(U2Int(x))}
+ // type(x)=int ==> Int2U(U2Int(x))==x"
+ protected override VCExpr! GenReverseCastAxiom(Function! castToU, Function! castFromU) {
+ List<VCTrigger!>! triggers;
+ VCExprVar! var;
+ VCExpr! eq = GenReverseCastEq(castToU, castFromU, out var, out triggers);
+ VCExpr! premiss;
+ if (CommandLineOptions.Clo.TypeEncodingMethod
+ == CommandLineOptions.TypeEncoding.None)
+ premiss = VCExpressionGenerator.True;
+ else
+ premiss = GenVarTypeAxiom(var, ((!)castFromU.OutParams[0]).TypedIdent.Type,
+ // we don't have any bindings available
+ new Dictionary<TypeVariable!, VCExpr!> ());
+ VCExpr! matrix = Gen.ImpliesSimp(premiss, eq);
+ return Gen.Forall(HelperFuns.ToList(var), triggers, "cast:" + castFromU.Name, matrix);
+ }
+
+ protected override VCExpr! GenCastTypeAxioms(Function! castToU, Function! castFromU) {
+ Type! fromType = ((!)castToU.InParams[0]).TypedIdent.Type;
+ return GenFunctionAxiom(castToU, new List<TypeVariable!> (), new List<TypeVariable!> (),
+ HelperFuns.ToList(fromType), fromType);
+ }
+
+ private MapTypeAbstractionBuilderPremisses MapTypeAbstracterAttr;
+
+ internal override MapTypeAbstractionBuilder! MapTypeAbstracter { get {
+ if (MapTypeAbstracterAttr == null)
+ MapTypeAbstracterAttr = new MapTypeAbstractionBuilderPremisses (this, Gen);
+ return MapTypeAbstracterAttr;
+ } }
+
+ internal MapTypeAbstractionBuilderPremisses! MapTypeAbstracterPremisses { get {
+ return (MapTypeAbstractionBuilderPremisses)MapTypeAbstracter;
+ } }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ // function that maps individuals to their type
+ // the field is overwritten with its actual value in "Setup"
+ private Function! TypeFunction;
+
+ public VCExpr! TypeOf(VCExpr! expr) {
+ return Gen.Function(TypeFunction, expr);
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Generate type premisses and type parameter bindings for quantifiers, functions, procedures
+
+ // let-bindings to extract the instantiations of type parameters
+ public List<VCExprLetBinding!>!
+ GenTypeParamBindings(// the original bound variables and (implicit) type parameters
+ List<TypeVariable!>! typeParams, List<VCExprVar!>! oldBoundVars,
+ // VariableBindings to which the translation
+ // TypeVariable -> VCExprVar is added
+ VariableBindings! bindings) {
+ // type variables are replaced with ordinary variables that are bound using a
+ // let-expression
+ foreach (TypeVariable! tvar in typeParams)
+ bindings.TypeVariableBindings.Add(tvar, Gen.Variable(tvar.Name, T));
+
+ // extract the values of type variables from the term variables
+ List<VCExprVar!>! UtypedVars = new List<VCExprVar!> (oldBoundVars.Count);
+ List<Type!>! originalTypes = new List<Type!> (oldBoundVars.Count);
+ for (int i = 0; i < oldBoundVars.Count; ++i) {
+ VCExprVar! newVar = bindings.VCExprVarBindings[oldBoundVars[i]];
+ if (newVar.Type.Equals(U)) {
+ UtypedVars.Add(newVar);
+ originalTypes.Add(oldBoundVars[i].Type);
+ }
+ }
+
+ UtypedVars.TrimExcess();
+ originalTypes.TrimExcess();
+
+ return BestTypeVarExtractors(typeParams, originalTypes, UtypedVars,
+ bindings);
+ }
+
+
+ public VCExpr! AddTypePremisses(List<VCExprLetBinding!>! typeVarBindings,
+ VCExpr! typePremisses, bool universal,
+ VCExpr! body) {
+ VCExpr! bodyWithPremisses;
+ if (universal)
+ bodyWithPremisses = Gen.ImpliesSimp(typePremisses, body);
+ else
+ bodyWithPremisses = Gen.AndSimp(typePremisses, body);
+
+ return Gen.Let(typeVarBindings, bodyWithPremisses);
+ }
+
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Extract the instantiations of type variables from the concrete types of
+ // term variables. E.g., for a function f<a>(x : C a), we would extract the
+ // instantiation of "a" by looking at the concrete type of "x".
+
+ public List<VCExprLetBinding!>!
+ BestTypeVarExtractors(List<TypeVariable!>! vars, List<Type!>! types,
+ List<VCExprVar!>! concreteTypeSources,
+ VariableBindings! bindings) {
+ List<VCExprLetBinding!>! typeParamBindings = new List<VCExprLetBinding!> ();
+ foreach (TypeVariable! var in vars) {
+ VCExpr extractor = BestTypeVarExtractor(var, types, concreteTypeSources);
+ if (extractor != null)
+ typeParamBindings.Add(
+ Gen.LetBinding((VCExprVar)bindings.TypeVariableBindings[var],
+ extractor));
+ }
+ return typeParamBindings;
+ }
+
+ private VCExpr BestTypeVarExtractor(TypeVariable! var, List<Type!>! types,
+ List<VCExprVar!>! concreteTypeSources) {
+ List<VCExpr!> allExtractors = TypeVarExtractors(var, types, concreteTypeSources);
+ if (allExtractors.Count == 0)
+ return null;
+
+ VCExpr bestExtractor = allExtractors[0];
+ int bestExtractorSize = SizeComputingVisitor.ComputeSize(bestExtractor);
+ for (int i = 1; i < allExtractors.Count; ++i) {
+ int newSize = SizeComputingVisitor.ComputeSize(allExtractors[i]);
+ if (newSize < bestExtractorSize) {
+ bestExtractor = allExtractors[i];
+ bestExtractorSize = newSize;
+ }
+ }
+
+ return bestExtractor;
+ }
+
+ private List<VCExpr!>! TypeVarExtractors(TypeVariable! var, List<Type!>! types,
+ List<VCExprVar!>! concreteTypeSources)
+ requires types.Count == concreteTypeSources.Count; {
+ List<VCExpr!>! res = new List<VCExpr!>();
+ for (int i = 0; i < types.Count; ++i)
+ TypeVarExtractors(var, types[i], TypeOf(concreteTypeSources[i]), res);
+
+ return res;
+ }
+
+ private void TypeVarExtractors(TypeVariable! var, Type! completeType,
+ VCExpr! innerTerm, List<VCExpr!>! extractors) {
+ if (completeType.IsVariable) {
+ if (var.Equals(completeType)) {
+ extractors.Add(innerTerm);
+ } // else nothing
+ } else if (completeType.IsBasic) {
+ // nothing
+ } else if (completeType.IsCtor) {
+ CtorType! ctorType = completeType.AsCtor;
+ if (ctorType.Arguments.Length > 0) {
+ // otherwise there are no chances of extracting any
+ // instantiations from this type
+ TypeCtorRepr repr = GetTypeCtorReprStruct(ctorType.Decl);
+ for (int i = 0; i < ctorType.Arguments.Length; ++i) {
+ VCExpr! newInnerTerm = Gen.Function(repr.Dtors[i], innerTerm);
+ TypeVarExtractors(var, ctorType.Arguments[i], newInnerTerm, extractors);
+ }
+ }
+ } else if (completeType.IsMap) {
+ TypeVarExtractors(var, MapTypeAbstracter.AbstractMapType(completeType.AsMap),
+ innerTerm, extractors);
+ } else {
+ System.Diagnostics.Debug.Fail("Don't know how to handle this type: " + completeType);
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Symbols for representing functions
+
+ // Globally defined functions
+ private readonly IDictionary<Function!, UntypedFunction>! Typed2UntypedFunctions;
+
+ // distinguish between implicit and explicit type parameters
+ internal static void SeparateTypeParams(List<Type!>! valueArgumentTypes,
+ TypeVariableSeq! allTypeParams,
+ out List<TypeVariable!>! implicitParams,
+ out List<TypeVariable!>! explicitParams) {
+ TypeVariableSeq! varsInInParamTypes = new TypeVariableSeq ();
+ foreach (Type! t in valueArgumentTypes)
+ varsInInParamTypes.AppendWithoutDups(t.FreeVariables);
+
+ implicitParams = new List<TypeVariable!> (allTypeParams.Length);
+ explicitParams = new List<TypeVariable!> (allTypeParams.Length);
+
+ foreach (TypeVariable! var in allTypeParams) {
+ if (varsInInParamTypes.Has(var))
+ implicitParams.Add(var);
+ else
+ explicitParams.Add(var);
+ }
+
+ implicitParams.TrimExcess();
+ explicitParams.TrimExcess();
+ }
+
+ internal UntypedFunction Typed2Untyped(Function! fun) {
+ UntypedFunction res;
+ if (!Typed2UntypedFunctions.TryGetValue(fun, out res)) {
+ assert fun.OutParams.Length == 1;
+
+ // if all of the parameters are int or bool, the function does
+ // not have to be changed
+ if (forall{Formal f in fun.InParams; UnchangedType(((!)f).TypedIdent.Type)} &&
+ UnchangedType(((!)fun.OutParams[0]).TypedIdent.Type) &&
+ fun.TypeParameters.Length == 0) {
+ res = new UntypedFunction(fun, new List<TypeVariable!> (), new List<TypeVariable!> ());
+ } else {
+ List<Type!>! argTypes = new List<Type!> ();
+ foreach (Variable! v in fun.InParams)
+ argTypes.Add(v.TypedIdent.Type);
+
+ List<TypeVariable!>! implicitParams, explicitParams;
+ SeparateTypeParams(argTypes, fun.TypeParameters, out implicitParams, out explicitParams);
+
+ Type[]! types = new Type [explicitParams.Count + fun.InParams.Length + 1];
+ int i = 0;
+ for (int j = 0; j < explicitParams.Count; ++j) {
+ types[i] = T;
+ i = i + 1;
+ }
+ for (int j = 0; j < fun.InParams.Length; ++i, ++j)
+ types[i] = TypeAfterErasure(((!)fun.InParams[j]).TypedIdent.Type);
+ types[types.Length - 1] = TypeAfterErasure(((!)fun.OutParams[0]).TypedIdent.Type);
+
+ Function! untypedFun = HelperFuns.BoogieFunction(fun.Name, types);
+ untypedFun.Attributes = fun.Attributes;
+ res = new UntypedFunction(untypedFun, implicitParams, explicitParams);
+ if (U.Equals(types[types.Length - 1]))
+ AddTypeAxiom(GenFunctionAxiom(res, fun));
+ }
+
+ Typed2UntypedFunctions.Add(fun, res);
+ }
+ return res;
+ }
+
+ private VCExpr! GenFunctionAxiom(UntypedFunction fun, Function! originalFun) {
+ List<Type!>! originalInTypes = new List<Type!> (originalFun.InParams.Length);
+ foreach (Formal! f in originalFun.InParams)
+ originalInTypes.Add(f.TypedIdent.Type);
+
+ return GenFunctionAxiom(fun.Fun, fun.ImplicitTypeParams, fun.ExplicitTypeParams,
+ originalInTypes,
+ ((!)originalFun.OutParams[0]).TypedIdent.Type);
+ }
+
+ internal VCExpr! GenFunctionAxiom(Function! fun,
+ List<TypeVariable!>! implicitTypeParams,
+ List<TypeVariable!>! explicitTypeParams,
+ List<Type!>! originalInTypes,
+ Type! originalResultType)
+ requires originalInTypes.Count +
+ explicitTypeParams.Count ==
+ fun.InParams.Length; {
+
+ if (CommandLineOptions.Clo.TypeEncodingMethod == CommandLineOptions.TypeEncoding.None) {
+ return VCExpressionGenerator.True;
+ }
+
+ List<VCExprVar!>! typedInputVars = new List<VCExprVar!>(originalInTypes.Count);
+ int i = 0;
+ foreach (Type! t in originalInTypes) {
+ typedInputVars.Add(Gen.Variable("arg" + i, t));
+ i = i + 1;
+ }
+
+ VariableBindings! bindings = new VariableBindings ();
+
+ // type parameters that have to be given explicitly are replaced
+ // with universally quantified type variables
+ List<VCExprVar!>! boundVars = new List<VCExprVar!> (explicitTypeParams.Count + typedInputVars.Count);
+ foreach (TypeVariable! var in explicitTypeParams) {
+ VCExprVar! newVar = Gen.Variable(var.Name, T);
+ boundVars.Add(newVar);
+ bindings.TypeVariableBindings.Add(var, newVar);
+ }
+
+
+ // bound term variables are replaced with bound term variables typed in
+ // a simpler way
+ foreach (VCExprVar! var in typedInputVars) {
+ Type! newType = TypeAfterErasure(var.Type);
+ VCExprVar! newVar = Gen.Variable(var.Name, newType);
+ boundVars.Add(newVar);
+ bindings.VCExprVarBindings.Add(var, newVar);
+ }
+
+ List<VCExprLetBinding!>! typeVarBindings =
+ GenTypeParamBindings(implicitTypeParams, typedInputVars, bindings);
+
+ VCExpr! funApp = Gen.Function(fun, HelperFuns.ToVCExprList(boundVars));
+ VCExpr! conclusion = Gen.Eq(TypeOf(funApp),
+ Type2Term(originalResultType, bindings.TypeVariableBindings));
+ VCExpr conclusionWithPremisses =
+ // leave out antecedents of function type axioms ... they don't appear necessary,
+ // because a function can always be extended to all U-values (right?)
+// AddTypePremisses(typeVarBindings, typePremisses, true, conclusion);
+ Gen.Let(typeVarBindings, conclusion);
+
+ if (boundVars.Count > 0) {
+ List<VCTrigger!>! triggers =
+ HelperFuns.ToList(Gen.Trigger(true, HelperFuns.ToList(funApp)));
+ return Gen.Forall(boundVars, triggers,
+ "funType:" + fun.Name, conclusionWithPremisses);
+ } else {
+ return conclusionWithPremisses;
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ protected override void AddVarTypeAxiom(VCExprVar! var, Type! originalType) {
+ if (CommandLineOptions.Clo.TypeEncodingMethod == CommandLineOptions.TypeEncoding.None) return;
+ AddTypeAxiom(GenVarTypeAxiom(var, originalType,
+ // we don't have any bindings available
+ new Dictionary<TypeVariable!, VCExpr!> ()));
+ }
+
+ public VCExpr! GenVarTypeAxiom(VCExprVar! var, Type! originalType,
+ IDictionary<TypeVariable!, VCExpr!>! varMapping) {
+ if (!var.Type.Equals(originalType)) {
+ VCExpr! typeRepr = Type2Term(originalType, varMapping);
+ return Gen.Eq(TypeOf(var), typeRepr);
+ }
+ return VCExpressionGenerator.True;
+ }
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+
+ internal class MapTypeAbstractionBuilderPremisses : MapTypeAbstractionBuilder {
+
+ private readonly TypeAxiomBuilderPremisses! AxBuilderPremisses;
+
+ internal MapTypeAbstractionBuilderPremisses(TypeAxiomBuilderPremisses! axBuilder,
+ VCExpressionGenerator! gen) {
+ base(axBuilder, gen);
+ this.AxBuilderPremisses = axBuilder;
+ }
+
+ // constructor for cloning
+ internal MapTypeAbstractionBuilderPremisses(TypeAxiomBuilderPremisses! axBuilder,
+ VCExpressionGenerator! gen,
+ MapTypeAbstractionBuilderPremisses! builder) {
+ base(axBuilder, gen, builder);
+ this.AxBuilderPremisses = axBuilder;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ // Determine the type parameters of a map type that have to be
+ // given explicitly when applying the select function (the
+ // parameters that only occur in the result type of the
+ // map). These parameters are given as a list of indexes sorted in
+ // ascending order; the index i refers to the i'th bound variable
+ // in a type <a0, a1, ..., an>[...]...
+ public List<int>! ExplicitSelectTypeParams(MapType! type) {
+ List<int> res;
+ if (!explicitSelectTypeParamsCache.TryGetValue(type, out res)) {
+ List<TypeVariable!>! explicitParams, implicitParams;
+ TypeAxiomBuilderPremisses.SeparateTypeParams(type.Arguments.ToList(),
+ type.TypeParameters,
+ out implicitParams,
+ out explicitParams);
+ res = new List<int> (explicitParams.Count);
+ foreach (TypeVariable! var in explicitParams)
+ res.Add(type.TypeParameters.IndexOf(var));
+ explicitSelectTypeParamsCache.Add(type, res);
+ }
+ return (!)res;
+ }
+
+ private IDictionary<MapType!, List<int>!>! explicitSelectTypeParamsCache =
+ new Dictionary<MapType!, List<int>!> ();
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ protected override void GenSelectStoreFunctions(MapType! abstractedType,
+ TypeCtorDecl! synonym,
+ out Function! select,
+ out Function! store) {
+ Type! mapTypeSynonym;
+ List<TypeVariable!>! typeParams;
+ List<Type!>! originalInTypes;
+ GenTypeAxiomParams(abstractedType, synonym, out mapTypeSynonym,
+ out typeParams, out originalInTypes);
+
+ // select
+ List<TypeVariable!>! explicitSelectParams;
+ select = CreateAccessFun(typeParams, originalInTypes,
+ abstractedType.Result, synonym.Name + "Select",
+ out explicitSelectParams);
+
+ // store, which gets one further argument: the assigned rhs
+ originalInTypes.Add(abstractedType.Result);
+
+ List<TypeVariable!>! explicitStoreParams;
+ store = CreateAccessFun(typeParams, originalInTypes,
+ mapTypeSynonym, synonym.Name + "Store",
+ out explicitStoreParams);
+
+ // the store function does not have any explicit type parameters
+ assert explicitStoreParams.Count == 0;
+
+ AxBuilder.AddTypeAxiom(GenMapAxiom0(select, store,
+ abstractedType.Result,
+ explicitSelectParams));
+ AxBuilder.AddTypeAxiom(GenMapAxiom1(select, store,
+ abstractedType.Result,
+ explicitSelectParams));
+ }
+
+ protected void GenTypeAxiomParams(MapType! abstractedType, TypeCtorDecl! synonymDecl,
+ out Type! mapTypeSynonym,
+ out List<TypeVariable!>! typeParams,
+ out List<Type!>! originalIndexTypes) {
+ typeParams = new List<TypeVariable!> (abstractedType.TypeParameters.Length + abstractedType.FreeVariables.Length);
+ typeParams.AddRange(abstractedType.TypeParameters.ToList());
+ typeParams.AddRange(abstractedType.FreeVariables.ToList());
+
+ originalIndexTypes = new List<Type!> (abstractedType.Arguments.Length + 1);
+ TypeSeq! mapTypeParams = new TypeSeq ();
+ foreach (TypeVariable! var in abstractedType.FreeVariables)
+ mapTypeParams.Add(var);
+ mapTypeSynonym = new CtorType (Token.NoToken, synonymDecl, mapTypeParams);
+ originalIndexTypes.Add(mapTypeSynonym);
+ originalIndexTypes.AddRange(abstractedType.Arguments.ToList());
+ }
+
+ // method to actually create the select or store function
+ private Function! CreateAccessFun(List<TypeVariable!>! originalTypeParams,
+ List<Type!>! originalInTypes,
+ Type! originalResult,
+ string! name,
+ out List<TypeVariable!>! explicitTypeParams) {
+ // select and store are basically handled like normal functions: the type
+ // parameters are split into the implicit parameters, and into the parameters
+ // that have to be given explicitly
+ List<TypeVariable!>! implicitParams;
+ TypeAxiomBuilderPremisses.SeparateTypeParams(originalInTypes,
+ HelperFuns.ToSeq(originalTypeParams),
+ out implicitParams,
+ out explicitTypeParams);
+ Type[]! ioTypes = new Type [explicitTypeParams.Count + originalInTypes.Count + 1];
+ int i = 0;
+ for (; i < explicitTypeParams.Count; ++i)
+ ioTypes[i] = AxBuilder.T;
+ foreach (Type! type in originalInTypes)
+ {
+ if (CommandLineOptions.Clo.Monomorphize && AxBuilder.UnchangedType(type))
+ ioTypes[i] = type;
+ else
+ ioTypes[i] = AxBuilder.U;
+ i++;
+ }
+ if (CommandLineOptions.Clo.Monomorphize && AxBuilder.UnchangedType(originalResult))
+ ioTypes[i] = originalResult;
+ else
+ ioTypes[i] = AxBuilder.U;
+
+ Function! res = HelperFuns.BoogieFunction(name, ioTypes);
+
+ if (AxBuilder.U.Equals(ioTypes[i]))
+ {
+ AxBuilder.AddTypeAxiom(
+ AxBuilderPremisses.GenFunctionAxiom(res,
+ implicitParams, explicitTypeParams,
+ originalInTypes, originalResult));
+ }
+ return res;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // The normal axioms of the theory of arrays (without extensionality)
+
+ private VCExpr! Select(Function! select,
+ // in general, the select function has to
+ // receive explicit type parameters (which
+ // are here already represented as VCExpr
+ // of type T)
+ List<VCExpr!>! typeParams,
+ VCExpr! map,
+ List<VCExprVar!>! indexes) {
+ List<VCExpr!>! selectArgs = new List<VCExpr!> (typeParams.Count + indexes.Count + 1);
+ selectArgs.AddRange(typeParams);
+ selectArgs.Add(map);
+ selectArgs.AddRange(HelperFuns.ToVCExprList(indexes));
+ return Gen.Function(select, selectArgs);
+ }
+
+ private VCExpr! Store(Function! store,
+ VCExpr! map,
+ List<VCExprVar!>! indexes,
+ VCExpr! val) {
+ List<VCExpr!>! storeArgs = new List<VCExpr!> (indexes.Count + 2);
+ storeArgs.Add(map);
+ storeArgs.AddRange(HelperFuns.ToVCExprList(indexes));
+ storeArgs.Add(val);
+ return Gen.Function(store, storeArgs);
+ }
+
+ private VCExpr! GenMapAxiom0(Function! select, Function! store,
+ Type! mapResult,
+ List<TypeVariable!>! explicitSelectParams) {
+ int arity = store.InParams.Length - 2;
+ VCExprVar! typedVal = Gen.Variable("val", mapResult);
+ VCExprVar! val = Gen.Variable("val", ((!)select.OutParams[0]).TypedIdent.Type);
+
+ VariableBindings! bindings = new VariableBindings ();
+ bindings.VCExprVarBindings.Add(typedVal, val);
+
+ // explicit type parameters are handled using a let-binder
+ List<VCExprLetBinding!>! letBindings =
+ AxBuilderPremisses.GenTypeParamBindings(explicitSelectParams,
+ HelperFuns.ToList(typedVal),
+ bindings);
+ List<VCExpr!>! typeParams = new List<VCExpr!> (explicitSelectParams.Count);
+ foreach (TypeVariable! var in explicitSelectParams)
+ typeParams.Add(bindings.TypeVariableBindings[var]);
+
+ List<Type!> indexTypes = new List<Type!>();
+ for (int i = 1; i < store.InParams.Length-1; i++)
+ {
+ indexTypes.Add(((!)store.InParams[i]).TypedIdent.Type);
+ }
+ assert arity == indexTypes.Count;
+
+ List<VCExprVar!> indexes = HelperFuns.VarVector("x", indexTypes, Gen);
+ VCExprVar! m = Gen.Variable("m", AxBuilder.U);
+
+ VCExpr! storeExpr = Store(store, m, indexes, val);
+ VCExpr! selectExpr = Select(select, typeParams, storeExpr, indexes);
+
+ List<VCExprVar!>! quantifiedVars = new List<VCExprVar!> (indexes.Count + 2);
+ quantifiedVars.Add(val);
+ quantifiedVars.Add(m);
+ quantifiedVars.AddRange(indexes);
+
+ VCExpr! eq = Gen.Eq(selectExpr, val);
+ VCExpr! letEq = Gen.Let(letBindings, eq);
+ return Gen.Forall(quantifiedVars, new List<VCTrigger!> (),
+ "mapAx0:" + select.Name, letEq);
+ }
+
+ private VCExpr! GenMapAxiom1(Function! select, Function! store,
+ Type! mapResult,
+ List<TypeVariable!>! explicitSelectParams) {
+ int arity = store.InParams.Length - 2;
+
+ List<Type!> indexTypes = new List<Type!>();
+ for (int i = 1; i < store.InParams.Length-1; i++)
+ {
+ indexTypes.Add(((!)store.InParams[i]).TypedIdent.Type);
+ }
+ assert indexTypes.Count == arity;
+
+ List<VCExprVar!>! indexes0 = HelperFuns.VarVector("x", indexTypes, Gen);
+ List<VCExprVar!>! indexes1 = HelperFuns.VarVector("y", indexTypes, Gen);
+ VCExprVar! m = Gen.Variable("m", AxBuilder.U);
+ VCExprVar! val = Gen.Variable("val", ((!)select.OutParams[0]).TypedIdent.Type);
+
+ // extract the explicit type parameters from the actual result type ...
+ VCExprVar! typedVal = Gen.Variable("val", mapResult);
+ VariableBindings! bindings = new VariableBindings ();
+ bindings.VCExprVarBindings.Add(typedVal, val);
+
+ List<VCExprLetBinding!>! letBindings =
+ AxBuilderPremisses.GenTypeParamBindings(explicitSelectParams,
+ HelperFuns.ToList(typedVal),
+ bindings);
+
+ // ... and quantify the introduced term variables for type
+ // parameters universally
+ List<VCExprVar!>! typeParams = new List<VCExprVar!> (explicitSelectParams.Count);
+ List<VCExpr!>! typeParamsExpr = new List<VCExpr!> (explicitSelectParams.Count);
+ foreach (TypeVariable! var in explicitSelectParams) {
+ VCExprVar! newVar = (VCExprVar)bindings.TypeVariableBindings[var];
+ typeParams.Add(newVar);
+ typeParamsExpr.Add(newVar);
+ }
+
+ VCExpr! storeExpr = Store(store, m, indexes0, val);
+ VCExpr! selectWithoutStoreExpr = Select(select, typeParamsExpr, m, indexes1);
+ VCExpr! selectExpr = Select(select, typeParamsExpr, storeExpr, indexes1);
+
+ VCExpr! selectEq = Gen.Eq(selectExpr, selectWithoutStoreExpr);
+
+ List<VCExprVar!>! quantifiedVars = new List<VCExprVar!> (indexes0.Count + indexes1.Count + 2);
+ quantifiedVars.Add(val);
+ quantifiedVars.Add(m);
+ quantifiedVars.AddRange(indexes0);
+ quantifiedVars.AddRange(indexes1);
+ quantifiedVars.AddRange(typeParams);
+
+ List<VCTrigger!>! triggers = new List<VCTrigger!> ();
+
+ VCExpr! axiom = VCExpressionGenerator.True;
+
+ // first non-interference criterium: the queried location is
+ // different from the assigned location
+ for (int i = 0; i < arity; ++i) {
+ VCExpr! indexesEq = Gen.Eq(indexes0[i], indexes1[i]);
+ VCExpr! matrix = Gen.Or(indexesEq, selectEq);
+ VCExpr! conjunct = Gen.Forall(quantifiedVars, triggers,
+ "mapAx1:" + select.Name + ":" + i, matrix);
+ axiom = Gen.AndSimp(axiom, conjunct);
+ }
+
+ // second non-interference criterion: the queried type is
+ // different from the assigned type
+ VCExpr! typesEq = VCExpressionGenerator.True;
+ foreach (VCExprLetBinding! b in letBindings)
+ typesEq = Gen.AndSimp(typesEq, Gen.Eq(b.V, b.E));
+ VCExpr! matrix2 = Gen.Or(typesEq, selectEq);
+ VCExpr! conjunct2 = Gen.Forall(quantifiedVars, triggers,
+ "mapAx2:" + select.Name, matrix2);
+ axiom = Gen.AndSimp(axiom, conjunct2);
+
+ return axiom;
+ }
+
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+
+ public class TypeEraserPremisses : TypeEraser {
+
+ private readonly TypeAxiomBuilderPremisses! AxBuilderPremisses;
+
+ private OpTypeEraser OpEraserAttr = null;
+ protected override OpTypeEraser! OpEraser { get {
+ if (OpEraserAttr == null)
+ OpEraserAttr = new OpTypeEraserPremisses(this, AxBuilderPremisses, Gen);
+ return OpEraserAttr;
+ } }
+
+ public TypeEraserPremisses(TypeAxiomBuilderPremisses! axBuilder,
+ VCExpressionGenerator! gen) {
+ base(axBuilder, gen);
+ this.AxBuilderPremisses = axBuilder;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ public override VCExpr! Visit(VCExprQuantifier! node,
+ VariableBindings! oldBindings) {
+ VariableBindings bindings = oldBindings.Clone();
+
+ // determine the bound vars that actually occur in the body or
+ // in any of the triggers (if some variables do not occur, we
+ // need to take special care of type parameters that only occur
+ // in the types of such variables)
+ FreeVariableCollector coll = new FreeVariableCollector ();
+ coll.Collect(node.Body);
+ foreach (VCTrigger trigger in node.Triggers) {
+ if (trigger.Pos)
+ foreach (VCExpr! e in trigger.Exprs)
+ coll.Collect(e);
+ }
+
+ List<VCExprVar!> occurringVars = new List<VCExprVar!> (node.BoundVars.Count);
+ foreach (VCExprVar var in node.BoundVars)
+ if (coll.FreeTermVars.ContainsKey(var))
+ occurringVars.Add(var);
+
+ occurringVars.TrimExcess();
+
+ // bound term variables are replaced with bound term variables typed in
+ // a simpler way
+ List<VCExprVar!>! newBoundVars =
+ BoundVarsAfterErasure(occurringVars, bindings);
+ VCExpr! newNode = HandleQuantifier(node, occurringVars,
+ newBoundVars, bindings);
+
+ if (!(newNode is VCExprQuantifier) || !IsUniversalQuantifier(node))
+ return newNode;
+
+ VariableBindings! bindings2;
+ if (!RedoQuantifier(node, (VCExprQuantifier)newNode, occurringVars, oldBindings,
+ out bindings2, out newBoundVars))
+ return newNode;
+
+ return HandleQuantifier(node, occurringVars,
+ newBoundVars, bindings2);
+ }
+
+ private VCExpr! GenTypePremisses(List<VCExprVar!>! oldBoundVars,
+ List<VCExprVar!>! newBoundVars,
+ IDictionary<TypeVariable!, VCExpr!>!
+ typeVarTranslation,
+ List<VCExprLetBinding!>! typeVarBindings,
+ out List<VCTrigger!>! triggers) {
+ // build a substitution of the type variables that it can be checked
+ // whether type premisses are trivial
+ VCExprSubstitution! typeParamSubstitution = new VCExprSubstitution ();
+ foreach (VCExprLetBinding! binding in typeVarBindings)
+ typeParamSubstitution[binding.V] = binding.E;
+ SubstitutingVCExprVisitor! substituter = new SubstitutingVCExprVisitor (Gen);
+
+ List<VCExpr!>! typePremisses = new List<VCExpr!> (newBoundVars.Count);
+ triggers = new List<VCTrigger!> (newBoundVars.Count);
+
+ for (int i = 0; i < newBoundVars.Count; ++i) {
+ VCExprVar! oldVar = oldBoundVars[i];
+ VCExprVar! newVar = newBoundVars[i];
+
+ VCExpr! typePremiss =
+ AxBuilderPremisses.GenVarTypeAxiom(newVar, oldVar.Type,
+ typeVarTranslation);
+
+ if (!IsTriviallyTrue(substituter.Mutate(typePremiss,
+ typeParamSubstitution))) {
+ typePremisses.Add(typePremiss);
+ // generate a negative trigger for the variable occurrence
+ // in the type premiss
+ triggers.Add(Gen.Trigger(false,
+ HelperFuns.ToList(AxBuilderPremisses.TypeOf(newVar))));
+ }
+ }
+
+ typePremisses.TrimExcess();
+ triggers.TrimExcess();
+
+ return Gen.NAry(VCExpressionGenerator.AndOp, typePremisses);
+ }
+
+ // these optimisations should maybe be moved into a separate
+ // visitor (peep-hole optimisations)
+ private bool IsTriviallyTrue(VCExpr! expr) {
+ if (expr.Equals(VCExpressionGenerator.True))
+ return true;
+
+ if (expr is VCExprNAry) {
+ VCExprNAry! naryExpr = (VCExprNAry)expr;
+ if (naryExpr.Op.Equals(VCExpressionGenerator.EqOp) &&
+ naryExpr[0].Equals(naryExpr[1]))
+ return true;
+ }
+
+ return false;
+ }
+
+ private VCExpr! HandleQuantifier(VCExprQuantifier! node,
+ List<VCExprVar!>! occurringVars,
+ List<VCExprVar!>! newBoundVars,
+ VariableBindings! bindings) {
+ List<VCExprLetBinding!>! typeVarBindings =
+ AxBuilderPremisses.GenTypeParamBindings(node.TypeParameters,
+ occurringVars, bindings);
+
+ // Check whether some of the type parameters could not be
+ // determined from the bound variable types. In this case, we
+ // quantify explicitly over these variables
+ if (typeVarBindings.Count < node.TypeParameters.Count) {
+ foreach (TypeVariable! var in node.TypeParameters) {
+ if (!exists{VCExprLetBinding! b in typeVarBindings; b.V.Equals(var)})
+ newBoundVars.Add((VCExprVar)bindings.TypeVariableBindings[var]);
+ }
+ }
+
+ // the lists of old and new bound variables for which type
+ // antecedents are to be generated
+ List<VCExprVar!>! varsWithTypeSpecs = new List<VCExprVar!> ();
+ List<VCExprVar!>! newVarsWithTypeSpecs = new List<VCExprVar!> ();
+ if (!IsUniversalQuantifier(node) ||
+ CommandLineOptions.Clo.TypeEncodingMethod
+ == CommandLineOptions.TypeEncoding.Predicates) {
+ foreach (VCExprVar! oldVar in occurringVars) {
+ varsWithTypeSpecs.Add(oldVar);
+ newVarsWithTypeSpecs.Add(bindings.VCExprVarBindings[oldVar]);
+ }
+ } // else, no type antecedents are created for any variables
+
+ List<VCTrigger!>! furtherTriggers;
+ VCExpr! typePremisses =
+ GenTypePremisses(varsWithTypeSpecs, newVarsWithTypeSpecs,
+ bindings.TypeVariableBindings,
+ typeVarBindings, out furtherTriggers);
+
+ List<VCTrigger!>! newTriggers = MutateTriggers(node.Triggers, bindings);
+ newTriggers.AddRange(furtherTriggers);
+ newTriggers = AddLets2Triggers(newTriggers, typeVarBindings);
+
+ VCExpr! newBody = Mutate(node.Body, bindings);
+
+ // assemble the new quantified formula
+
+ if (CommandLineOptions.Clo.TypeEncodingMethod
+ == CommandLineOptions.TypeEncoding.None) {
+ typePremisses = VCExpressionGenerator.True;
+ }
+
+ VCExpr! bodyWithPremisses =
+ AxBuilderPremisses.AddTypePremisses(typeVarBindings, typePremisses,
+ node.Quan == Quantifier.ALL,
+ AxBuilder.Cast(newBody, Type.Bool));
+
+ if (newBoundVars.Count == 0) // might happen that no bound variables are left
+ return bodyWithPremisses;
+
+ foreach(VCExprVar! v in newBoundVars) {
+ if (v.Type == AxBuilderPremisses.U) {
+ newTriggers.Add(Gen.Trigger(false, AxBuilderPremisses.Cast(v, Type.Int)));
+ newTriggers.Add(Gen.Trigger(false, AxBuilderPremisses.Cast(v, Type.Bool)));
+ }
+ }
+
+ return Gen.Quantify(node.Quan, new List<TypeVariable!> (), newBoundVars,
+ newTriggers, node.Infos, bodyWithPremisses);
+ }
+
+ // check whether we need to add let-binders for any of the type
+ // parameters to the triggers (otherwise, the triggers will
+ // contain unbound/dangling variables for such parameters)
+ private List<VCTrigger!>! AddLets2Triggers(List<VCTrigger!>! triggers,
+ List<VCExprLetBinding!>! typeVarBindings) {
+ List<VCTrigger!>! triggersWithLets = new List<VCTrigger!> (triggers.Count);
+
+ foreach (VCTrigger! t in triggers) {
+ List<VCExpr!>! exprsWithLets = new List<VCExpr!> (t.Exprs.Count);
+
+ bool changed = false;
+ foreach (VCExpr! e in t.Exprs) {
+ Dictionary<VCExprVar!,object>! freeVars =
+ FreeVariableCollector.FreeTermVariables(e);
+
+ if (exists{VCExprLetBinding! b in typeVarBindings;
+ freeVars.ContainsKey(b.V)}) {
+ exprsWithLets.Add(Gen.Let(typeVarBindings, e));
+ changed = true;
+ } else {
+ exprsWithLets.Add(e);
+ }
+ }
+
+ if (changed)
+ triggersWithLets.Add(Gen.Trigger(t.Pos, exprsWithLets));
+ else
+ triggersWithLets.Add(t);
+ }
+
+ return triggersWithLets;
+ }
+
+ }
+
+ //////////////////////////////////////////////////////////////////////////////
+
+ public class OpTypeEraserPremisses : OpTypeEraser {
+
+ private TypeAxiomBuilderPremisses! AxBuilderPremisses;
+
+ public OpTypeEraserPremisses(TypeEraserPremisses! eraser,
+ TypeAxiomBuilderPremisses! axBuilder,
+ VCExpressionGenerator! gen) {
+ base(eraser, axBuilder, gen);
+ this.AxBuilderPremisses = axBuilder;
+ }
+
+ private VCExpr! HandleFunctionOp(Function! newFun,
+ List<Type!>! typeArgs,
+ IEnumerable<VCExpr!>! oldArgs,
+ VariableBindings! bindings) {
+ // UGLY: the code for tracking polarities should be factored out
+ int oldPolarity = Eraser.Polarity;
+ Eraser.Polarity = 0;
+
+ List<VCExpr!>! newArgs = new List<VCExpr!> (typeArgs.Count);
+
+ // translate the explicit type arguments
+ foreach (Type! t in typeArgs)
+ newArgs.Add(AxBuilder.Type2Term(t, bindings.TypeVariableBindings));
+
+ // recursively translate the value arguments
+ foreach (VCExpr! arg in oldArgs) {
+ Type! newType = ((!)newFun.InParams[newArgs.Count]).TypedIdent.Type;
+ newArgs.Add(AxBuilder.Cast(Eraser.Mutate(arg, bindings), newType));
+ }
+
+ Eraser.Polarity = oldPolarity;
+ return Gen.Function(newFun, newArgs);
+ }
+
+ public override VCExpr! VisitSelectOp (VCExprNAry! node,
+ VariableBindings! bindings) {
+ MapType! mapType = node[0].Type.AsMap;
+ TypeSeq! instantiations; // not used
+ Function! select =
+ AxBuilder.MapTypeAbstracter.Select(mapType, out instantiations);
+
+ List<int>! explicitTypeParams =
+ AxBuilderPremisses.MapTypeAbstracterPremisses
+ .ExplicitSelectTypeParams(mapType);
+ assert select.InParams.Length == explicitTypeParams.Count + node.Arity;
+
+ List<Type!>! typeArgs = new List<Type!> (explicitTypeParams.Count);
+ foreach (int i in explicitTypeParams)
+ typeArgs.Add(node.TypeArguments[i]);
+ return HandleFunctionOp(select, typeArgs, node, bindings);
+ }
+
+ public override VCExpr! VisitStoreOp (VCExprNAry! node,
+ VariableBindings! bindings) {
+ TypeSeq! instantiations; // not used
+ Function! store =
+ AxBuilder.MapTypeAbstracter.Store(node[0].Type.AsMap, out instantiations);
+ return HandleFunctionOp(store,
+ // the store function never has explicit
+ // type parameters
+ new List<Type!> (),
+ node, bindings);
+ }
+
+ public override VCExpr! VisitBoogieFunctionOp (VCExprNAry! node,
+ VariableBindings! bindings) {
+ Function! oriFun = ((VCExprBoogieFunctionOp)node.Op).Func;
+ UntypedFunction untypedFun = AxBuilderPremisses.Typed2Untyped(oriFun);
+ assert untypedFun.Fun.InParams.Length ==
+ untypedFun.ExplicitTypeParams.Count + node.Arity;
+
+ List<Type!>! typeArgs =
+ ExtractTypeArgs(node,
+ oriFun.TypeParameters, untypedFun.ExplicitTypeParams);
+ return HandleFunctionOp(untypedFun.Fun, typeArgs, node, bindings);
+ }
+
+ private List<Type!>! ExtractTypeArgs(VCExprNAry! node,
+ TypeVariableSeq! allTypeParams,
+ List<TypeVariable!>! explicitTypeParams) {
+ List<Type!>! res = new List<Type!> (explicitTypeParams.Count);
+ foreach (TypeVariable! var in explicitTypeParams)
+ // this lookup could be optimised
+ res.Add(node.TypeArguments[allTypeParams.IndexOf(var)]);
+ return res;
+ }
+ }
+
+
+}
diff --git a/Source/VCExpr/VCExpr.sscproj b/Source/VCExpr/VCExpr.sscproj
new file mode 100644
index 00000000..3f3a903a
--- /dev/null
+++ b/Source/VCExpr/VCExpr.sscproj
@@ -0,0 +1,141 @@
+<?xml version="1.0" encoding="utf-8"?>
+<VisualStudioProject>
+ <XEN ProjectType="Local"
+ SchemaVersion="1.0"
+ Name="VCExpr"
+ ProjectGuid="cf42b700-10aa-4da9-8992-48a800251c11"
+ >
+ <Build>
+ <Settings ApplicationIcon=""
+ AssemblyName="VCExpr"
+ OutputType="Library"
+ RootNamespace="VCExpr"
+ StartupObject=""
+ StandardLibraryLocation=""
+ TargetPlatform="v2"
+ TargetPlatformLocation=""
+ >
+ <Config Name="Debug"
+ AllowUnsafeBlocks="False"
+ BaseAddress="285212672"
+ CheckForOverflowUnderflow="False"
+ ConfigurationOverrideFile=""
+ DefineConstants="DEBUG;TRACE"
+ DocumentationFile=""
+ DebugSymbols="True"
+ FileAlignment="4096"
+ IncrementalBuild="True"
+ Optimize="False"
+ OutputPath="bin\debug"
+ RegisterForComInterop="False"
+ RemoveIntegerChecks="false"
+ TreatWarningsAsErrors="False"
+ WarningLevel="4"
+ CheckContractAdmissibility="True"
+ CheckPurity="False"
+ />
+ <Config Name="Release"
+ AllowUnsafeBlocks="false"
+ BaseAddress="285212672"
+ CheckForOverflowUnderflow="false"
+ ConfigurationOverrideFile=""
+ DefineConstants="TRACE"
+ DocumentationFile=""
+ DebugSymbols="false"
+ FileAlignment="4096"
+ IncrementalBuild="false"
+ Optimize="true"
+ OutputPath="bin\release"
+ RegisterForComInterop="false"
+ RemoveIntegerChecks="false"
+ TreatWarningsAsErrors="false"
+ WarningLevel="4"
+ CheckContractAdmissibility="True"
+ CheckPurity="False"
+ />
+ </Settings>
+ <References>
+ <Reference Name="System"
+ AssemblyName="System"
+ Private="false"
+ />
+ <Reference Name="System.Data"
+ AssemblyName="System.Data"
+ Private="false"
+ />
+ <Reference Name="System.Xml"
+ AssemblyName="System.Xml"
+ Private="false"
+ />
+ <Reference Name="Core"
+ Project="{47BC34F1-A173-40BE-84C2-9332B4418387}"
+ Private="true"
+ />
+ <Reference Name="Basetypes"
+ Project="{0C692837-77EC-415F-BF04-395E3ED06E9A}"
+ Private="true"
+ />
+ </References>
+ </Build>
+ <Files>
+ <Include>
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="VCExprAST.ssc"
+ />
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="VCExprASTVisitors.ssc"
+ />
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="Boogie2VCExpr.ssc"
+ />
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="VCExprASTPrinter.ssc"
+ />
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="SimplifyLikeLineariser.ssc"
+ />
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="TypeErasure.ssc"
+ />
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="NameClashResolver.ssc"
+ />
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="LetBindingSorter.ssc"
+ />
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="TypeErasurePremisses.ssc"
+ />
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="TypeErasureArguments.ssc"
+ />
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="TermFormulaFlattening.ssc"
+ />
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="Clustering.ssc"
+ />
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="BigLiteralAbstracter.ssc"
+ />
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="..\version.ssc"
+ />
+ </Include>
+ </Files>
+ </XEN>
+</VisualStudioProject> \ No newline at end of file
diff --git a/Source/VCExpr/VCExprAST.ssc b/Source/VCExpr/VCExprAST.ssc
new file mode 100644
index 00000000..330c76c4
--- /dev/null
+++ b/Source/VCExpr/VCExprAST.ssc
@@ -0,0 +1,1285 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using System;
+using System.Text;
+using System.IO;
+using System.Collections;
+using System.Collections.Generic;
+using Microsoft.Contracts;
+using Microsoft.Basetypes;
+
+// Prover-independent syntax trees for representing verification conditions
+// The language can be seen as a simple polymorphically typed first-order logic,
+// very similar to the expression language of Boogie
+
+namespace Microsoft.Boogie
+{
+ using Microsoft.Boogie.VCExprAST;
+
+ public class VCExpressionGenerator
+ {
+ public static readonly VCExpr! False = new VCExprLiteral (Type.Bool);
+ public static readonly VCExpr! True = new VCExprLiteral (Type.Bool);
+
+ public VCExpr! Integer(BigNum x) {
+ return new VCExprIntLit(x);
+ }
+
+ public VCExpr! Function(VCExprOp! op,
+ List<VCExpr!>! arguments,
+ List<Type!>! typeArguments) {
+ if (typeArguments.Count > 0)
+ return new VCExprMultiAry(op, arguments, typeArguments);
+
+ switch (arguments.Count) {
+ case 0: return new VCExprNullary(op);
+ case 1: return new VCExprUnary(op, arguments);
+ case 2: return new VCExprBinary(op, arguments);
+ default: return new VCExprMultiAry(op, arguments);
+ }
+ }
+
+ public VCExpr! Function(VCExprOp! op, List<VCExpr!>! arguments) {
+ return Function(op, arguments, VCExprNAry.EMPTY_TYPE_LIST);
+ }
+
+ public VCExpr! Function(VCExprOp! op, params VCExpr[]! arguments)
+ requires forall{int i in (0:arguments.Length); arguments[i] != null};
+ {
+ return Function(op,
+ HelperFuns.ToNonNullList(arguments),
+ VCExprNAry.EMPTY_TYPE_LIST);
+ }
+
+ public VCExpr! Function(VCExprOp! op, VCExpr[]! arguments, Type[]! typeArguments)
+ requires forall{int i in (0:arguments.Length); arguments[i] != null};
+ requires forall{int i in (0:typeArguments.Length); typeArguments[i] != null};
+ {
+ return Function(op,
+ HelperFuns.ToNonNullList(arguments),
+ HelperFuns.ToNonNullList(typeArguments));
+ }
+
+ public VCExpr! Function(Function! op, List<VCExpr!>! arguments) {
+ return Function(BoogieFunctionOp(op), arguments, VCExprNAry.EMPTY_TYPE_LIST);
+ }
+
+ public VCExpr! Function(Function! op, params VCExpr[]! arguments)
+ requires forall{int i in (0:arguments.Length); arguments[i] != null};
+ {
+ return Function(BoogieFunctionOp(op), arguments);
+ }
+
+
+ // The following method should really be called "ReduceLeft". It must
+ // only be used for the binary operators "and" and "or"
+ public VCExpr! NAry(VCExprOp! op, List<VCExpr!>! args) {
+ return NAry(op, args.ToArray());
+ }
+
+ public VCExpr! NAry(VCExprOp! op, params VCExpr[]! args)
+ requires forall{int i in (0:args.Length); args[i] != null};
+ requires op == AndOp || op == OrOp; {
+ bool and = (op == AndOp);
+
+ VCExpr! e = and ? True : False;
+ foreach (VCExpr a in args) {
+ e = and ? AndSimp(e, (!)a) : OrSimp(e, (!)a);
+ }
+ return e;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+
+ public static readonly VCExprOp! NotOp = new VCExprNAryOp (1, Type.Bool);
+ public static readonly VCExprOp! EqOp = new VCExprNAryOp (2, Type.Bool);
+ public static readonly VCExprOp! NeqOp = new VCExprNAryOp (2, Type.Bool);
+ public static readonly VCExprOp! AndOp = new VCExprNAryOp (2, Type.Bool);
+ public static readonly VCExprOp! OrOp = new VCExprNAryOp (2, Type.Bool);
+ public static readonly VCExprOp! ImpliesOp = new VCExprNAryOp (2, Type.Bool);
+
+ public VCExprDistinctOp! DistinctOp(int arity) {
+ return new VCExprDistinctOp (arity);
+ }
+
+ public VCExpr! Not(List<VCExpr!>! args)
+ requires args.Count == 1; {
+ return Function(NotOp, args);
+ }
+
+ public VCExpr! Not(VCExpr! e0) {
+ return Function(NotOp, e0);
+ }
+ public VCExpr! Eq(VCExpr! e0, VCExpr! e1) {
+ return Function(EqOp, e0, e1);
+ }
+ public VCExpr! Neq(VCExpr! e0, VCExpr! e1) {
+ return Function(NeqOp, e0, e1);
+ }
+ public VCExpr! And(VCExpr! e0, VCExpr! e1) {
+ return Function(AndOp, e0, e1);
+ }
+ public VCExpr! Or(VCExpr! e0, VCExpr! e1) {
+ return Function(OrOp, e0, e1);
+ }
+ public VCExpr! Implies(VCExpr! e0, VCExpr! e1) {
+ return Function(ImpliesOp, e0, e1);
+ }
+ public VCExpr! Distinct(List<VCExpr!>! args) {
+ if (args.Count <= 1)
+ // trivial case
+ return True;
+ return Function(DistinctOp(args.Count), args);
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Versions of the propositional operators that automatically simplify in
+ // certain cases (if one of the operators is True or False)
+
+ public VCExpr! NotSimp(VCExpr! e0) {
+ if (e0.Equals(True))
+ return False;
+ if (e0.Equals(False))
+ return True;
+ return Not(e0);
+ }
+ public VCExpr! AndSimp(VCExpr! e0, VCExpr! e1) {
+ if (e0.Equals(True))
+ return e1;
+ if (e1.Equals(True))
+ return e0;
+ if (e0.Equals(False) || e1.Equals(False))
+ return False;
+ return And(e0, e1);
+ }
+ public VCExpr! OrSimp(VCExpr! e0, VCExpr! e1) {
+ if (e0.Equals(False))
+ return e1;
+ if (e1.Equals(False))
+ return e0;
+ if (e0.Equals(True) || e1.Equals(True))
+ return True;
+ return Or(e0, e1);
+ }
+ public VCExpr! ImpliesSimp(VCExpr! e0, VCExpr! e1) {
+ if (e0.Equals(True))
+ return e1;
+ if (e1.Equals(False))
+ return NotSimp(e0);
+ if (e0.Equals(False) || e1.Equals(True))
+ return True;
+ return Implies(e0, e1);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // 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! ModOp = new VCExprNAryOp (2, Type.Int);
+ 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);
+ public static readonly VCExprOp! GeOp = new VCExprNAryOp (2, Type.Bool);
+ public static readonly VCExprOp! SubtypeOp = new VCExprNAryOp (2, Type.Bool);
+ // ternary version of the subtype operator, the first argument of which gives
+ // the type of the compared terms
+ public static readonly VCExprOp! Subtype3Op = new VCExprNAryOp (3, Type.Bool);
+
+ public VCExprOp! BoogieFunctionOp(Function! func) {
+ return new VCExprBoogieFunctionOp(func);
+ }
+
+ // Bitvector nodes
+
+ public VCExpr! Bitvector(BvConst! bv) {
+ return Function(new VCExprBvOp(bv.Bits), Integer(bv.Value));
+ }
+
+ public VCExpr! BvExtract(VCExpr! bv, int bits, int start, int end) {
+ return Function(new VCExprBvExtractOp (start, end), bv);
+ }
+
+ public static readonly VCExprBvConcatOp! BvConcatOp = new VCExprBvConcatOp();
+ public VCExpr! BvConcat(VCExpr! bv1, VCExpr! bv2) {
+ return Function(BvConcatOp, bv1, bv2);
+ }
+
+ public VCExpr! AtMost(VCExpr! smaller, VCExpr! greater) {
+ return Function(SubtypeOp, smaller, greater);
+ }
+
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // Dispatcher for the visitor
+
+ // the declared singleton operators
+ internal enum SingletonOp { NotOp, EqOp, NeqOp, AndOp, OrOp, ImpliesOp,
+ AddOp, SubOp, MulOp,
+ DivOp, ModOp, LtOp, LeOp, GtOp, GeOp, SubtypeOp,
+ Subtype3Op, BvConcatOp };
+ internal static Dictionary<VCExprOp!, SingletonOp>! SingletonOpDict;
+
+ static VCExpressionGenerator() {
+ SingletonOpDict = new Dictionary<VCExprOp!, SingletonOp> ();
+ SingletonOpDict.Add(NotOp, SingletonOp.NotOp);
+ SingletonOpDict.Add(EqOp, SingletonOp.EqOp);
+ SingletonOpDict.Add(NeqOp, SingletonOp.NeqOp);
+ 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(ModOp, SingletonOp.ModOp);
+ 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(BvConcatOp,SingletonOp.BvConcatOp);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+
+
+ // Let-bindings
+
+ public VCExprLetBinding! LetBinding(VCExprVar! v, VCExpr! e) {
+ return new VCExprLetBinding(v, e);
+ }
+
+ // A "real" let expression. All let-bindings happen simultaneously, i.e.,
+ // at this level the order of the bindings does not matter. It is possible to
+ // create expressions like "let x = y, y = 5 in ...". All bound variables are
+ // bound in all bound terms/formulas and can occur there, but the dependencies
+ // have to be acyclic
+ public VCExpr! Let(List<VCExprLetBinding!>! bindings, VCExpr! body) {
+ if (bindings.Count == 0)
+ // no empty let-bindings
+ return body;
+ return new VCExprLet(bindings, body);
+ }
+
+ public VCExpr! Let(VCExpr! body, params VCExprLetBinding[]! bindings)
+ requires forall{int i in (0:bindings.Length); bindings[i] != null};
+ {
+ return Let(HelperFuns.ToNonNullList(bindings), body);
+ }
+
+
+ /// <summary>
+ /// In contrast to the previous method, the following methods are not a general LET.
+ /// Instead, it
+ /// is a boolean "LET b = P in Q", where P and Q are predicates, that is allowed to be
+ /// encoded as "(b == P) ==> Q" or even as "(P ==> b) ==> Q"
+ /// (or "(P ==> b) and Q" in negative positions).
+ /// The method assumes that the variables in the bindings are unique in the entire formula
+ /// to be produced, which allows the implementation to ignore scope issues in the event that
+ /// it needs to generate an alternate expression for LET.
+ /// </summary>
+
+
+ // Turn let-bindings let v = E in ... into implications E ==> v
+ public VCExpr! AsImplications(List<VCExprLetBinding!>! bindings) {
+ VCExpr! antecedents = True;
+ foreach (VCExprLetBinding b in bindings)
+ // turn "LET_binding v = E" into "v <== E"
+ antecedents = AndSimp(antecedents, Implies(b.E, b.V));
+ return antecedents;
+ }
+
+ // Turn let-bindings let v = E in ... into equations v == E
+ public VCExpr! AsEquations(List<VCExprLetBinding!>! bindings) {
+ VCExpr! antecedents = True;
+ foreach (VCExprLetBinding b in bindings)
+ // turn "LET_binding v = E" into "v <== E"
+ antecedents = AndSimp(antecedents, Eq(b.E, b.V));
+ return antecedents;
+ }
+
+
+
+ // Maps
+
+ public VCExpr! Select(params VCExpr[]! allArgs)
+ requires forall{int i in (0:allArgs.Length); allArgs[i] != null};
+ {
+ return Function(new VCExprSelectOp(allArgs.Length - 1, 0),
+ HelperFuns.ToNonNullList(allArgs),
+ VCExprNAry.EMPTY_TYPE_LIST);
+ }
+
+ public VCExpr! Select(VCExpr[]! allArgs, Type[]! typeArgs)
+ requires 1 <= allArgs.Length;
+ requires forall{int i in (0:allArgs.Length); allArgs[i] != null};
+ requires forall{int i in (0:typeArgs.Length); typeArgs[i] != null};
+ {
+ return Function(new VCExprSelectOp(allArgs.Length - 1, typeArgs.Length),
+ allArgs, typeArgs);
+ }
+
+ public VCExpr! Select(List<VCExpr!>! allArgs, List<Type!>! typeArgs)
+ requires 1 <= allArgs.Count;
+ {
+ return Function(new VCExprSelectOp(allArgs.Count - 1, typeArgs.Count),
+ allArgs, typeArgs);
+ }
+
+ public VCExpr! Store(params VCExpr[]! allArgs)
+ requires forall{int i in (0:allArgs.Length); allArgs[i] != null};
+ {
+ return Function(new VCExprStoreOp(allArgs.Length - 2, 0),
+ HelperFuns.ToNonNullList(allArgs),
+ VCExprNAry.EMPTY_TYPE_LIST);
+ }
+
+ public VCExpr! Store(VCExpr[]! allArgs, Type[]! typeArgs)
+ requires 2 <= allArgs.Length;
+ requires forall{int i in (0:allArgs.Length); allArgs[i] != null};
+ requires forall{int i in (0:typeArgs.Length); typeArgs[i] != null};
+ {
+ return Function(new VCExprStoreOp(allArgs.Length - 2, typeArgs.Length),
+ allArgs, typeArgs);
+ }
+
+ public VCExpr! Store(List<VCExpr!>! allArgs, List<Type!>! typeArgs)
+ requires 2 <= allArgs.Count;
+ {
+ return Function(new VCExprStoreOp(allArgs.Count - 2, typeArgs.Count),
+ allArgs, typeArgs);
+ }
+
+
+ // Labels
+
+ public VCExprLabelOp! LabelOp(bool pos, string! l) {
+ return new VCExprLabelOp(pos, l);
+ }
+
+ public VCExpr! LabelNeg(string! label, VCExpr! e) {
+ return Function(LabelOp(false, label), e);
+ }
+ public VCExpr! LabelPos(string! label, VCExpr! e) {
+ return Function(LabelOp(true, label), e);
+ }
+
+ // Quantifiers
+
+ public VCExpr! Quantify(Quantifier quan,
+ List<TypeVariable!>! typeParams, List<VCExprVar!>! vars,
+ List<VCTrigger!>! triggers, VCQuantifierInfos! infos,
+ VCExpr! body) {
+ return new VCExprQuantifier(quan, typeParams, vars, triggers, infos, body);
+ }
+
+ public VCExpr! Forall(List<TypeVariable!>! typeParams, List<VCExprVar!>! vars,
+ List<VCTrigger!>! triggers, VCQuantifierInfos! infos,
+ VCExpr! body) {
+ return Quantify(Quantifier.ALL, typeParams, vars, triggers, infos, body);
+ }
+ public VCExpr! Forall(List<VCExprVar!>! vars,
+ List<VCTrigger!>! triggers,
+ string! qid, VCExpr! body) {
+ return Quantify(Quantifier.ALL, new List<TypeVariable!> (), vars,
+ triggers, new VCQuantifierInfos (qid, -1, false, null), body);
+ }
+ public VCExpr! Forall(List<VCExprVar!>! vars,
+ List<VCTrigger!>! triggers,
+ VCExpr! body) {
+ return Quantify(Quantifier.ALL, new List<TypeVariable!> (), vars,
+ triggers, new VCQuantifierInfos (null, -1, false, null), body);
+ }
+ public VCExpr! Forall(VCExprVar! var, VCTrigger! trigger, VCExpr! body) {
+ return Forall(HelperFuns.ToNonNullList(var), HelperFuns.ToNonNullList(trigger), body);
+ }
+ public VCExpr! Exists(List<TypeVariable!>! typeParams, List<VCExprVar!>! vars,
+ List<VCTrigger!>! triggers, VCQuantifierInfos! infos,
+ VCExpr! body) {
+ return Quantify(Quantifier.EX, typeParams, vars, triggers, infos, body);
+ }
+ public VCExpr! Exists(List<VCExprVar!>! vars,
+ List<VCTrigger!>! triggers,
+ VCExpr! body) {
+ return Quantify(Quantifier.EX, new List<TypeVariable!> (), vars,
+ triggers, new VCQuantifierInfos (null, -1, false, null), body);
+ }
+ public VCExpr! Exists(VCExprVar! var, VCTrigger! trigger, VCExpr! body) {
+ return Exists(HelperFuns.ToNonNullList(var), HelperFuns.ToNonNullList(trigger), body);
+ }
+
+ public VCTrigger! Trigger(bool pos, List<VCExpr!>! exprs) {
+ return new VCTrigger(pos, exprs);
+ }
+
+ public VCTrigger! Trigger(bool pos, params VCExpr[]! exprs)
+ requires forall{int i in (0:exprs.Length); exprs[i] != null};
+ {
+ return Trigger(pos, HelperFuns.ToNonNullList(exprs));
+ }
+
+ // Reference to a bound or free variable
+
+ public VCExprVar! Variable(string! name, Type! type) {
+ return new VCExprVar(name, type);
+ }
+ }
+}
+
+namespace Microsoft.Boogie.VCExprAST
+{
+
+ public class HelperFuns {
+ public static bool SameElements(IEnumerable! a, IEnumerable! b) {
+ IEnumerator ia = a.GetEnumerator();
+ IEnumerator ib = b.GetEnumerator();
+ while (true) {
+ if (ia.MoveNext()) {
+ if (ib.MoveNext()) {
+ if (!((!)ia.Current).Equals(ib.Current))
+ return false;
+ } else {
+ return false;
+ }
+ } else {
+ return !ib.MoveNext();
+ }
+ }
+ return true;
+ }
+
+ public static int PolyHash(int init, int factor, IEnumerable! a) {
+ int res = init;
+ foreach(object x in a)
+ res = res * factor + ((!)x).GetHashCode();
+ return res;
+ }
+
+ public static List<T>! ToList<T>(IEnumerable<T>! l) {
+ List<T>! res = new List<T> ();
+ foreach (T x in l)
+ res.Add(x);
+ return res;
+ }
+
+ public static TypeSeq! ToTypeSeq(VCExpr[]! exprs, int startIndex)
+ requires forall{int i in (0:exprs.Length); exprs[i] != null};
+ {
+ TypeSeq! res = new TypeSeq ();
+ for (int i = startIndex; i < exprs.Length; ++i)
+ res.Add(((!)exprs[i]).Type);
+ return res;
+ }
+
+ public static List<T!>! ToNonNullList<T> (params T[]! args) {
+ List<T!>! res = new List<T!> (args.Length);
+ foreach (T t in args)
+ res.Add((!)t);
+ return res;
+ }
+
+ public static IDictionary<A, B>! Clone<A,B>(IDictionary<A,B>! dict) {
+ IDictionary<A,B>! res = new Dictionary<A,B> (dict.Count);
+ foreach (KeyValuePair<A,B> pair in dict)
+ res.Add(pair);
+ return res;
+ }
+ }
+
+ public abstract class VCExpr {
+ public abstract Type! Type { get; }
+
+ public abstract Result Accept<Result, Arg>(IVCExprVisitor<Result, Arg>! visitor, Arg arg);
+
+ [Pure]
+ public override string! ToString() {
+ StringWriter! sw = new StringWriter();
+ VCExprPrinter! printer = new VCExprPrinter ();
+ printer.Print(this, sw);
+ return (!)sw.ToString();
+ }
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////
+ // Literal expressions
+
+ public class VCExprLiteral : VCExpr {
+ private readonly Type! LitType;
+ public override Type! Type { get { return LitType; } }
+ internal VCExprLiteral(Type! type) {
+ this.LitType = type;
+ }
+ public override Result Accept<Result, Arg>(IVCExprVisitor<Result, Arg>! visitor, Arg arg) {
+ return visitor.Visit(this, arg);
+ }
+ }
+
+ public class VCExprIntLit : VCExprLiteral
+ {
+ public readonly BigNum Val;
+ internal VCExprIntLit(BigNum val) {
+ base(Type.Int);
+ this.Val = val;
+ }
+ [Pure][Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals(object that) {
+ if (Object.ReferenceEquals(this, that))
+ return true;
+ if (that is VCExprIntLit)
+ return Val == ((VCExprIntLit)that).Val;
+ return false;
+ }
+ [Pure]
+ public override int GetHashCode() {
+ return Val.GetHashCode() * 72321;
+ }
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////
+ // Operator expressions with fixed arity
+
+ public abstract class VCExprNAry : VCExpr, IEnumerable<VCExpr!> {
+ public readonly VCExprOp! Op;
+ public int Arity { get { return Op.Arity; } }
+ public int TypeParamArity { get { return Op.TypeParamArity; } }
+ public int Length { get { return Arity; } }
+ // the sub-expressions of the expression
+ public abstract VCExpr! this[int index] { get; }
+
+ // the type arguments
+ public abstract List<Type!>! TypeArguments { get; }
+
+ [Pure] [GlobalAccess(false)] [Escapes(true,false)]
+ public IEnumerator<VCExpr!>! GetEnumerator() {
+ for (int i = 0; i < Arity; ++i)
+ yield return this[i];
+ }
+ [Pure] [GlobalAccess(false)] [Escapes(true,false)]
+ IEnumerator! System.Collections.IEnumerable.GetEnumerator() {
+ for (int i = 0; i < Arity; ++i)
+ yield return this[i];
+ }
+
+ [Pure][Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals(object that) {
+ if (Object.ReferenceEquals(this, that))
+ return true;
+ if (that is VCExprNAry) {
+ // we compare the subterms iteratively (not recursively)
+ // to avoid stack overflows
+
+ VCExprNAryEnumerator enum0 = new VCExprNAryEnumerator(this);
+ VCExprNAryEnumerator enum1 = new VCExprNAryEnumerator((VCExprNAry)that);
+
+ while (true) {
+ bool next0 = enum0.MoveNext();
+ bool next1 = enum1.MoveNext();
+ if (next0 != next1)
+ return false;
+ if (!next0)
+ return true;
+
+ VCExprNAry nextExprNAry0 = enum0.Current as VCExprNAry;
+ VCExprNAry nextExprNAry1 = enum1.Current as VCExprNAry;
+
+ if ((nextExprNAry0 == null) != (nextExprNAry1 == null))
+ return false;
+ if (nextExprNAry0 != null && nextExprNAry1 != null) {
+ if (!nextExprNAry0.Op.Equals(nextExprNAry1.Op))
+ return false;
+ } else {
+ if (!((!)enum0.Current).Equals(enum1.Current))
+ return false;
+ }
+ }
+ }
+ return false;
+ }
+ [Pure]
+ public override int GetHashCode() {
+ return HelperFuns.PolyHash(Op.GetHashCode() * 123 + Arity * 61521,
+ 3, this);
+ }
+
+ internal VCExprNAry(VCExprOp! op) {
+ this.Op = op;
+ }
+ public override Result Accept<Result, Arg>(IVCExprVisitor<Result, Arg>! visitor, Arg arg) {
+ return visitor.Visit(this, arg);
+ }
+ public Result Accept<Result, Arg>(IVCExprOpVisitor<Result, Arg>! visitor, Arg arg) {
+ return Op.Accept(this, visitor, arg);
+ }
+
+ internal static readonly List<Type!>! EMPTY_TYPE_LIST = new List<Type!> ();
+ internal static readonly List<VCExpr!>! EMPTY_VCEXPR_LIST = new List<VCExpr!> ();
+ }
+
+ // We give specialised implementations for nullary, unary and binary expressions
+
+ internal class VCExprNullary : VCExprNAry {
+ private readonly Type! ExprType;
+ public override Type! Type { get { return ExprType; } }
+ public override VCExpr! this[int index] { get {
+ assert false; // no arguments
+ } }
+
+ // the type arguments
+ public override List<Type!>! TypeArguments { get {
+ return EMPTY_TYPE_LIST;
+ } }
+
+ internal VCExprNullary(VCExprOp! op)
+ requires op.Arity == 0 && op.TypeParamArity == 0; {
+ base(op);
+ this.ExprType = op.InferType(EMPTY_VCEXPR_LIST, EMPTY_TYPE_LIST);
+ }
+ }
+
+ internal class VCExprUnary : VCExprNAry {
+ private readonly VCExpr! Argument;
+ private readonly Type! ExprType;
+ public override Type! Type { get { return ExprType; } }
+ public override VCExpr! this[int index] { get {
+ assume index == 0;
+ return Argument;
+ } }
+
+ // the type arguments
+ public override List<Type!>! TypeArguments { get {
+ return EMPTY_TYPE_LIST;
+ } }
+
+ internal VCExprUnary(VCExprOp! op, List<VCExpr!>! arguments)
+ requires op.Arity == 1 && op.TypeParamArity == 0 && arguments.Count == 1; {
+ base(op);
+ this.Argument = arguments[0];
+ this.ExprType =
+ op.InferType(arguments, EMPTY_TYPE_LIST);
+ }
+
+ internal VCExprUnary(VCExprOp! op, VCExpr! argument)
+ requires op.Arity == 1 && op.TypeParamArity == 0; {
+ base(op);
+ this.Argument = argument;
+ // PR: could be optimised so that the argument does
+ // not have to be boxed in an array each time
+ this.ExprType =
+ op.InferType(HelperFuns.ToNonNullList(argument), EMPTY_TYPE_LIST);
+ }
+ }
+
+ internal class VCExprBinary : VCExprNAry {
+ private readonly VCExpr! Argument0;
+ private readonly VCExpr! Argument1;
+ private readonly Type! ExprType;
+ public override Type! Type { get { return ExprType; } }
+ public override VCExpr! this[int index] { get {
+ switch (index) {
+ case 0: return Argument0;
+ case 1: return Argument1;
+ default: assert false;
+ }
+ } }
+
+ // the type arguments
+ public override List<Type!>! TypeArguments { get {
+ return EMPTY_TYPE_LIST;
+ } }
+
+ internal VCExprBinary(VCExprOp! op, List<VCExpr!>! arguments)
+ requires op.Arity == 2 && op.TypeParamArity == 0 && arguments.Count == 2; {
+ base(op);
+ this.Argument0 = arguments[0];
+ this.Argument1 = arguments[1];
+ this.ExprType = op.InferType(arguments, EMPTY_TYPE_LIST);
+ }
+
+ internal VCExprBinary(VCExprOp! op, VCExpr! argument0, VCExpr! argument1)
+ requires op.Arity == 2 && op.TypeParamArity == 0; {
+ base(op);
+ this.Argument0 = argument0;
+ this.Argument1 = argument1;
+ // PR: could be optimised so that the arguments do
+ // not have to be boxed in an array each time
+ this.ExprType =
+ op.InferType(HelperFuns.ToNonNullList(argument0, argument1),
+ EMPTY_TYPE_LIST);
+ }
+ }
+
+ internal class VCExprMultiAry : VCExprNAry {
+ private readonly List<VCExpr!>! Arguments;
+ private readonly List<Type!>! TypeArgumentsAttr;
+
+ private readonly Type! ExprType;
+ public override Type! Type { get { return ExprType; } }
+ public override VCExpr! this[int index] { get {
+ assume index >= 0 && index < Arity;
+ return (!)Arguments[index];
+ } }
+
+ // the type arguments
+ public override List<Type!>! TypeArguments { get {
+ return TypeArgumentsAttr;
+ } }
+
+ internal VCExprMultiAry(VCExprOp! op, List<VCExpr!>! arguments) {
+ this(op, arguments, EMPTY_TYPE_LIST);
+ }
+ internal VCExprMultiAry(VCExprOp! op, List<VCExpr!>! arguments, List<Type!>! typeArguments)
+ requires (arguments.Count > 2 || typeArguments.Count > 0);
+ requires op.Arity == arguments.Count;
+ requires op.TypeParamArity == typeArguments.Count;
+ {
+ base(op);
+ this.Arguments = arguments;
+ this.TypeArgumentsAttr = typeArguments;
+ this.ExprType = op.InferType(arguments, typeArguments);
+ }
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////
+ // The various operators available
+
+ public abstract class VCExprOp {
+ // the number of value parameters
+ public abstract int Arity { get; }
+ // the number of type parameters
+ public abstract int TypeParamArity { get; }
+
+ public abstract Type! InferType(List<VCExpr!>! args, List<Type!>! typeArgs);
+
+ public virtual Result Accept<Result, Arg>
+ (VCExprNAry! expr, IVCExprOpVisitor<Result, Arg>! visitor, Arg arg) {
+ VCExpressionGenerator.SingletonOp op;
+ if (VCExpressionGenerator.SingletonOpDict.TryGetValue(this, out op)) {
+ switch(op) {
+ case VCExpressionGenerator.SingletonOp.NotOp:
+ return visitor.VisitNotOp(expr, arg);
+ case VCExpressionGenerator.SingletonOp.EqOp:
+ return visitor.VisitEqOp(expr, arg);
+ case VCExpressionGenerator.SingletonOp.NeqOp:
+ return visitor.VisitNeqOp(expr, arg);
+ case VCExpressionGenerator.SingletonOp.AndOp:
+ return visitor.VisitAndOp(expr, arg);
+ case VCExpressionGenerator.SingletonOp.OrOp:
+ return visitor.VisitOrOp(expr, arg);
+ case VCExpressionGenerator.SingletonOp.ImpliesOp:
+ return visitor.VisitImpliesOp(expr, arg);
+ case VCExpressionGenerator.SingletonOp.AddOp:
+ return visitor.VisitAddOp(expr, arg);
+ case VCExpressionGenerator.SingletonOp.SubOp:
+ return visitor.VisitSubOp(expr, arg);
+ case VCExpressionGenerator.SingletonOp.MulOp:
+ return visitor.VisitMulOp(expr, arg);
+ case VCExpressionGenerator.SingletonOp.DivOp:
+ return visitor.VisitDivOp(expr, arg);
+ case VCExpressionGenerator.SingletonOp.ModOp:
+ return visitor.VisitModOp(expr, arg);
+ case VCExpressionGenerator.SingletonOp.LtOp:
+ return visitor.VisitLtOp(expr, arg);
+ case VCExpressionGenerator.SingletonOp.LeOp:
+ return visitor.VisitLeOp(expr, arg);
+ case VCExpressionGenerator.SingletonOp.GtOp:
+ return visitor.VisitGtOp(expr, arg);
+ case VCExpressionGenerator.SingletonOp.GeOp:
+ return visitor.VisitGeOp(expr, arg);
+ case VCExpressionGenerator.SingletonOp.SubtypeOp:
+ return visitor.VisitSubtypeOp(expr, arg);
+ case VCExpressionGenerator.SingletonOp.Subtype3Op:
+ return visitor.VisitSubtype3Op(expr, arg);
+ case VCExpressionGenerator.SingletonOp.BvConcatOp:
+ return visitor.VisitBvConcatOp(expr, arg);
+ default:
+ assert false;
+ }
+ } else {
+ assert false;
+ }
+ }
+ }
+
+ public class VCExprNAryOp : VCExprOp {
+ private readonly Type! OpType;
+ private readonly int OpArity;
+
+ public override int Arity { get { return OpArity; } }
+ public override int TypeParamArity { get { return 0; } }
+ public override Type! InferType(List<VCExpr!>! args, List<Type!>! typeArgs) {
+ return OpType;
+ }
+
+ internal VCExprNAryOp(int arity, Type! type) {
+ this.OpArity = arity;
+ this.OpType = type;
+ }
+ }
+
+ public class VCExprDistinctOp : VCExprNAryOp {
+ internal VCExprDistinctOp(int arity) {
+ base(arity, Type.Bool);
+ }
+ [Pure][Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals(object that) {
+ if (Object.ReferenceEquals(this, that))
+ return true;
+ if (that is VCExprDistinctOp)
+ return Arity == ((VCExprDistinctOp)that).Arity;
+ return false;
+ }
+ [Pure]
+ public override int GetHashCode() {
+ return Arity * 917632481;
+ }
+ public override Result Accept<Result, Arg>
+ (VCExprNAry! expr, IVCExprOpVisitor<Result, Arg>! visitor, Arg arg) {
+ return visitor.VisitDistinctOp(expr, arg);
+ }
+ }
+
+ public class VCExprLabelOp : VCExprOp {
+ public override int Arity { get { return 1; } }
+ public override int TypeParamArity { get { return 0; } }
+ public override Type! InferType(List<VCExpr!>! args, List<Type!>! typeArgs) {
+ return args[0].Type;
+ }
+
+ public readonly bool pos;
+ public readonly string! label;
+
+ [Pure][Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals(object that) {
+ if (Object.ReferenceEquals(this, that))
+ return true;
+ if (that is VCExprLabelOp) {
+ VCExprLabelOp! thatOp = (VCExprLabelOp)that;
+ return this.pos == thatOp.pos && this.label.Equals(thatOp.label);
+ }
+ return false;
+ }
+ [Pure]
+ public override int GetHashCode() {
+ return (pos ? 9817231 : 7198639) + label.GetHashCode();
+ }
+
+ internal VCExprLabelOp(bool pos, string! l) {
+ this.pos = pos;
+ this.label = pos ? "+" + l : "@" + l;
+ }
+ public override Result Accept<Result, Arg>
+ (VCExprNAry! expr, IVCExprOpVisitor<Result, Arg>! visitor, Arg arg) {
+ return visitor.VisitLabelOp(expr, arg);
+ }
+ }
+
+ public class VCExprSelectOp : VCExprOp {
+ private readonly int MapArity;
+ private readonly int MapTypeParamArity;
+ public override int Arity { get { return MapArity + 1; } }
+ public override int TypeParamArity { get { return MapTypeParamArity; } }
+
+ public override Type! InferType(List<VCExpr!>! args, List<Type!>! typeArgs) {
+ MapType! mapType = args[0].Type.AsMap;
+ assert TypeParamArity == mapType.TypeParameters.Length;
+ IDictionary<TypeVariable!, Type!>! subst = new Dictionary<TypeVariable!, Type!> ();
+ for (int i = 0; i < TypeParamArity; ++i)
+ subst.Add(mapType.TypeParameters[i], typeArgs[i]);
+ return mapType.Result.Substitute(subst);
+ }
+
+ [Pure][Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals(object that) {
+ if (Object.ReferenceEquals(this, that))
+ return true;
+ if (that is VCExprSelectOp)
+ return Arity == ((VCExprSelectOp)that).Arity &&
+ TypeParamArity == ((VCExprSelectOp)that).TypeParamArity;
+ return false;
+ }
+ [Pure]
+ public override int GetHashCode() {
+ return Arity * 1212481 + TypeParamArity * 298741;
+ }
+
+ internal VCExprSelectOp(int arity, int typeParamArity)
+ requires 0 <= arity && 0 <= typeParamArity;
+ {
+ this.MapArity = arity;
+ this.MapTypeParamArity = typeParamArity;
+ }
+ public override Result Accept<Result, Arg>
+ (VCExprNAry! expr, IVCExprOpVisitor<Result, Arg>! visitor, Arg arg) {
+ return visitor.VisitSelectOp(expr, arg);
+ }
+ }
+
+ public class VCExprStoreOp : VCExprOp {
+ private readonly int MapArity;
+ private readonly int MapTypeParamArity;
+ public override int Arity { get { return MapArity + 2; } }
+ // stores never need explicit type parameters, because also the
+ // rhs is a value argument
+ public override int TypeParamArity { get { return MapTypeParamArity; } }
+
+ public override Type! InferType(List<VCExpr!>! args, List<Type!>! typeArgs) {
+ return args[0].Type;
+ }
+
+ [Pure][Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals(object that) {
+ if (Object.ReferenceEquals(this, that))
+ return true;
+ if (that is VCExprStoreOp)
+ return Arity == ((VCExprStoreOp)that).Arity;
+ return false;
+ }
+ [Pure]
+ public override int GetHashCode() {
+ return Arity * 91361821;
+ }
+
+ internal VCExprStoreOp(int arity, int typeParamArity)
+ requires 0 <= arity && 0 <= typeParamArity;
+ {
+ this.MapArity = arity;
+ this.MapTypeParamArity = typeParamArity;
+ }
+ public override Result Accept<Result, Arg>
+ (VCExprNAry! expr, IVCExprOpVisitor<Result, Arg>! visitor, Arg arg) {
+ return visitor.VisitStoreOp(expr, arg);
+ }
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////
+ // Bitvector operators
+
+ public class VCExprBvOp : VCExprOp {
+ public readonly int Bits;
+
+ public override int Arity { get { return 1; } }
+ public override int TypeParamArity { get { return 0; } }
+ public override Type! InferType(List<VCExpr!>! args, List<Type!>! typeArgs) {
+ return Type.GetBvType(Bits);
+ }
+
+ [Pure][Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals(object that) {
+ if (Object.ReferenceEquals(this, that))
+ return true;
+ if (that is VCExprBvOp)
+ return this.Bits == ((VCExprBvOp)that).Bits;
+ return false;
+ }
+ [Pure]
+ public override int GetHashCode() {
+ return Bits * 81748912;
+ }
+
+ internal VCExprBvOp(int bits) {
+ this.Bits = bits;
+ }
+ public override Result Accept<Result, Arg>
+ (VCExprNAry! expr, IVCExprOpVisitor<Result, Arg>! visitor, Arg arg) {
+ return visitor.VisitBvOp(expr, arg);
+ }
+ }
+
+ public class VCExprBvExtractOp : VCExprOp {
+ public readonly int Start;
+ public readonly int End;
+
+ public override int Arity { get { return 1; } }
+ public override int TypeParamArity { get { return 0; } }
+ public override Type! InferType(List<VCExpr!>! args, List<Type!>! typeArgs) {
+ return Type.GetBvType(End - Start);
+ }
+
+ [Pure][Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals(object that) {
+ if (Object.ReferenceEquals(this, that))
+ return true;
+ if (that is VCExprBvExtractOp) {
+ VCExprBvExtractOp! thatExtract = (VCExprBvExtractOp)that;
+ return this.Start == thatExtract.Start && this.End == thatExtract.End;
+ }
+ return false;
+ }
+ [Pure]
+ public override int GetHashCode() {
+ return Start * 81912 + End * 978132;
+ }
+
+ internal VCExprBvExtractOp(int start, int end) {
+ this.Start = start;
+ this.End = end;
+ }
+ public override Result Accept<Result, Arg>
+ (VCExprNAry! expr, IVCExprOpVisitor<Result, Arg>! visitor, Arg arg) {
+ return visitor.VisitBvExtractOp(expr, arg);
+ }
+ }
+
+ // singleton class
+ public class VCExprBvConcatOp : VCExprOp {
+ public override int Arity { get { return 2; } }
+ public override int TypeParamArity { get { return 0; } }
+ public override Type! InferType(List<VCExpr!>! args, List<Type!>! typeArgs) {
+ return Type.GetBvType(args[0].Type.BvBits + args[1].Type.BvBits);
+ }
+ internal VCExprBvConcatOp() {}
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////
+ // References to user-defined Boogie functions
+
+ public class VCExprBoogieFunctionOp : VCExprOp {
+ public readonly Function! Func;
+
+ public override int Arity { get { return Func.InParams.Length; } }
+ public override int TypeParamArity { get { return Func.TypeParameters.Length; } }
+ public override Type! InferType(List<VCExpr!>! args, List<Type!>! typeArgs) {
+ assert TypeParamArity == Func.TypeParameters.Length;
+ if (TypeParamArity == 0)
+ return ((!)Func.OutParams[0]).TypedIdent.Type;
+ IDictionary<TypeVariable!, Type!>! subst = new Dictionary<TypeVariable!, Type!> (TypeParamArity);
+ for (int i = 0; i < TypeParamArity; ++i)
+ subst.Add(Func.TypeParameters[i], typeArgs[i]);
+ return ((!)Func.OutParams[0]).TypedIdent.Type.Substitute(subst);
+ }
+
+ [Pure][Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals(object that) {
+ if (Object.ReferenceEquals(this, that))
+ return true;
+ if (that is VCExprBoogieFunctionOp)
+ return this.Func.Equals(((VCExprBoogieFunctionOp)that).Func);
+ return false;
+ }
+ [Pure]
+ public override int GetHashCode() {
+ return Func.GetHashCode() + 18731;
+ }
+
+ // we require that the result type of the expression is specified, because we
+ // do not want to perform full type inference at this point
+ internal VCExprBoogieFunctionOp(Function! func) {
+ this.Func = func;
+ }
+ public override Result Accept<Result, Arg>
+ (VCExprNAry! expr, IVCExprOpVisitor<Result, Arg>! visitor, Arg arg) {
+ return visitor.VisitBoogieFunctionOp(expr, arg);
+ }
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////
+ // Binders (quantifiers and let-expressions). We introduce our own class for
+ // term variables, but use the Boogie-AST class for type variables
+
+ public class VCExprVar : VCExpr {
+ // the name of the variable. Note that the name is not used for comparison,
+ // i.e., there can be two distinct variables with the same name
+ public readonly string! Name;
+ private readonly Type! VarType;
+ public override Type! Type { get { return VarType; } }
+
+ internal VCExprVar(string! name, Type! type) {
+ this.Name = name;
+ this.VarType = type;
+ }
+ public override Result Accept<Result, Arg>(IVCExprVisitor<Result, Arg>! visitor, Arg arg) {
+ return visitor.Visit(this, arg);
+ }
+ }
+
+ public abstract class VCExprBinder : VCExpr {
+ public readonly VCExpr! Body;
+ public readonly List<TypeVariable!>! TypeParameters;
+ public readonly List<VCExprVar!>! BoundVars;
+
+ public override Type! Type { get { return Body.Type; } }
+
+ internal VCExprBinder(List<TypeVariable!>! typeParams,
+ List<VCExprVar!>! boundVars,
+ VCExpr! body)
+ requires boundVars.Count + typeParams.Count > 0; { // only nontrivial binders ...
+ this.TypeParameters = typeParams;
+ this.BoundVars = boundVars;
+ this.Body = body;
+ }
+ }
+
+ public class VCTrigger {
+ public readonly bool Pos;
+ public readonly List<VCExpr!>! Exprs;
+
+ [Pure][Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals(object that) {
+ if (Object.ReferenceEquals(this, that))
+ return true;
+ if (that is VCTrigger) {
+ VCTrigger! thatTrigger = (VCTrigger)that;
+ return this.Pos == thatTrigger.Pos &&
+ HelperFuns.SameElements(this.Exprs, thatTrigger.Exprs);
+ }
+ return false;
+ }
+ [Pure]
+ public override int GetHashCode() {
+ return (Pos ? 913821 : 871334) +
+ HelperFuns.PolyHash(123, 7, this.Exprs);
+ }
+
+ public VCTrigger(bool pos, List<VCExpr!>! exprs) {
+ this.Pos = pos;
+ this.Exprs = exprs;
+ }
+ }
+
+ public class VCQuantifierInfos {
+ public readonly string qid;
+ public readonly int uniqueId;
+ public readonly bool bvZ3Native;
+ public QKeyValue attributes;
+
+ public VCQuantifierInfos(string qid, int uniqueId, bool bvZ3Native, QKeyValue attributes) {
+ this.qid = qid;
+ this.uniqueId = uniqueId;
+ this.bvZ3Native = bvZ3Native;
+ this.attributes = attributes;
+ }
+ }
+
+ public enum Quantifier { ALL, EX };
+
+ public class VCExprQuantifier : VCExprBinder {
+ public readonly Quantifier Quan;
+
+ public readonly List<VCTrigger!>! Triggers;
+ public readonly VCQuantifierInfos! Infos;
+
+ // Equality is /not/ modulo bound renaming at this point
+ [Pure][Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals(object that) {
+ if (Object.ReferenceEquals(this, that))
+ return true;
+ if (that is VCExprQuantifier) {
+ VCExprQuantifier! thatQuan = (VCExprQuantifier)that;
+ return this.Quan == thatQuan.Quan &&
+ HelperFuns.SameElements(this.Triggers, thatQuan.Triggers) &&
+ HelperFuns.SameElements(this.TypeParameters, thatQuan.TypeParameters) &&
+ HelperFuns.SameElements(this.BoundVars, thatQuan.BoundVars) &&
+ this.Body.Equals(thatQuan.Body);
+ }
+ return false;
+ }
+ [Pure]
+ public override int GetHashCode() {
+ return Quan.GetHashCode() +
+ HelperFuns.PolyHash(973219, 7, TypeParameters) +
+ HelperFuns.PolyHash(998431, 9, BoundVars) +
+ HelperFuns.PolyHash(123, 11, Triggers);
+ }
+
+ internal VCExprQuantifier(Quantifier kind,
+ List<TypeVariable!>! typeParams,
+ List<VCExprVar!>! boundVars,
+ List<VCTrigger!>! triggers,
+ VCQuantifierInfos! infos,
+ VCExpr! body) {
+ base(typeParams, boundVars, body);
+ this.Quan = kind;
+ this.Triggers = triggers;
+ this.Infos = infos;
+ }
+ public override Result Accept<Result, Arg>(IVCExprVisitor<Result, Arg>! visitor, Arg arg) {
+ return visitor.Visit(this, arg);
+ }
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////
+ // Let-Bindings
+
+ public class VCExprLetBinding {
+ public readonly VCExprVar! V;
+ public readonly VCExpr! E;
+
+ [Pure][Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals(object that) {
+ if (Object.ReferenceEquals(this, that))
+ return true;
+ if (that is VCExprLetBinding) {
+ VCExprLetBinding! thatB = (VCExprLetBinding)that;
+ return this.V.Equals(thatB.V) && this.E.Equals(thatB.E);
+ }
+ return false;
+ }
+ [Pure]
+ public override int GetHashCode() {
+ return V.GetHashCode() * 71261 + E.GetHashCode();
+ }
+
+ internal VCExprLetBinding(VCExprVar! v, VCExpr! e) {
+ this.V = v;
+ this.E = e;
+ assert v.Type.Equals(e.Type);
+ }
+ }
+
+ public class VCExprLet : VCExprBinder, IEnumerable<VCExprLetBinding!> {
+ private readonly List<VCExprLetBinding!>! Bindings;
+
+ public int Length { get { return Bindings.Count; } }
+ public VCExprLetBinding! this[int index] { get {
+ return Bindings[index];
+ } }
+
+ [Pure][Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals(object that) {
+ if (Object.ReferenceEquals(this, that))
+ return true;
+ if (that is VCExprLet) {
+ VCExprLet! thatLet = (VCExprLet)that;
+ return this.Body.Equals(thatLet.Body) &&
+ HelperFuns.SameElements(this, (VCExprLet)that);
+ }
+ return false;
+ }
+ [Pure]
+ public override int GetHashCode() {
+ return HelperFuns.PolyHash(Body.GetHashCode(), 9, Bindings);
+ }
+
+ [Pure] [GlobalAccess(false)] [Escapes(true,false)]
+ public IEnumerator<VCExprLetBinding!>! GetEnumerator() {
+ return Bindings.GetEnumerator();
+ }
+ [Pure] [GlobalAccess(false)] [Escapes(true,false)]
+ IEnumerator! System.Collections.IEnumerable.GetEnumerator() {
+ return Bindings.GetEnumerator();
+ }
+
+ private static List<VCExprVar!>! toSeq(List<VCExprLetBinding!>! bindings) {
+ List<VCExprVar!>! res = new List<VCExprVar!> ();
+ foreach (VCExprLetBinding! b in bindings)
+ res.Add(b.V);
+ return res;
+ }
+
+ internal VCExprLet(List<VCExprLetBinding!>! bindings,
+ VCExpr! body) {
+ base(new List<TypeVariable!> (), toSeq(bindings), body);
+ this.Bindings = bindings;
+ }
+ public override Result Accept<Result, Arg>(IVCExprVisitor<Result, Arg>! visitor, Arg arg) {
+ return visitor.Visit(this, arg);
+ }
+ }
+}
diff --git a/Source/VCExpr/VCExprASTPrinter.ssc b/Source/VCExpr/VCExprASTPrinter.ssc
new file mode 100644
index 00000000..1c143516
--- /dev/null
+++ b/Source/VCExpr/VCExprASTPrinter.ssc
@@ -0,0 +1,240 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using System;
+using System.Text;
+using System.IO;
+using System.Collections;
+using System.Collections.Generic;
+using Microsoft.Contracts;
+using Microsoft.Basetypes;
+
+// A simple visitor for turning a VCExpr into a human-readable string
+// (S-expr syntax)
+
+namespace Microsoft.Boogie.VCExprAST
+{
+
+ public class VCExprPrinter : IVCExprVisitor<bool, TextWriter!> {
+ private VCExprOpPrinter OpPrinterVar = null;
+ private VCExprOpPrinter! OpPrinter { get {
+ if (OpPrinterVar == null)
+ OpPrinterVar = new VCExprOpPrinter(this);
+ return OpPrinterVar;
+ } }
+
+ public void Print(VCExpr! expr, TextWriter! wr) {
+ expr.Accept<bool, TextWriter!>(this, wr);
+ }
+
+ public bool Visit(VCExprLiteral! node, TextWriter! wr) {
+ if (node == VCExpressionGenerator.True)
+ wr.Write("true");
+ else if (node == VCExpressionGenerator.False)
+ wr.Write("false");
+ else if (node is VCExprIntLit) {
+ wr.Write(((VCExprIntLit)node).Val);
+ } else
+ assert false;
+ return true;
+ }
+ public bool Visit(VCExprNAry! node, TextWriter! wr) {
+ VCExprOp! op = node.Op;
+
+ if (op.Equals(VCExpressionGenerator.AndOp) ||
+ op.Equals(VCExpressionGenerator.OrOp)) {
+ // handle these operators without recursion
+
+ wr.Write("({0}",
+ op.Equals(VCExpressionGenerator.AndOp) ? "And" : "Or");
+ IEnumerator! enumerator = new VCExprNAryUniformOpEnumerator (node);
+ while (enumerator.MoveNext()) {
+ VCExprNAry naryExpr = enumerator.Current as VCExprNAry;
+ if (naryExpr == null || !naryExpr.Op.Equals(op)) {
+ wr.Write(" ");
+ Print((VCExpr!)enumerator.Current, wr);
+ }
+ }
+
+ wr.Write(")");
+
+ return true;
+ }
+
+ return node.Accept<bool, TextWriter!>(OpPrinter, wr);
+ }
+ public bool Visit(VCExprVar! node, TextWriter! wr) {
+ wr.Write(node.Name);
+ return true;
+ }
+ public bool Visit(VCExprQuantifier! node, TextWriter! wr) {
+ string! quan = node.Quan == Quantifier.ALL ? "Forall" : "Exists";
+
+ wr.Write("({0} ", quan);
+
+ if (node.TypeParameters.Count > 0) {
+ wr.Write("<");
+ string! sep = "";
+ foreach (TypeVariable! v in node.TypeParameters) {
+ wr.Write(sep);
+ sep = ", ";
+ wr.Write("{0}", v.Name);
+ }
+ wr.Write("> ");
+ }
+
+ if (node.BoundVars.Count > 0) {
+ string! sep = "";
+ foreach (VCExprVar! v in node.BoundVars) {
+ wr.Write(sep);
+ sep = ", ";
+ Print(v, wr);
+ }
+ wr.Write(" ");
+ }
+
+ wr.Write(":: ");
+
+ if (node.Triggers.Count > 0) {
+ wr.Write("{0} ", "{");
+ string! sep = "";
+ foreach (VCTrigger! t in node.Triggers) {
+ wr.Write(sep);
+ sep = ", ";
+ string! sep2 = "";
+ foreach (VCExpr! e in t.Exprs) {
+ wr.Write(sep2);
+ sep2 = "+";
+ Print(e, wr);
+ }
+ }
+ wr.Write(" {0} ", "}");
+ }
+
+ Print(node.Body, wr);
+ wr.Write(")");
+ return true;
+ }
+ public bool Visit(VCExprLet! node, TextWriter! wr) {
+ wr.Write("(Let ");
+
+ string! sep = "";
+ foreach (VCExprLetBinding! b in node) {
+ wr.Write(sep);
+ sep = ", ";
+ Print(b.V, wr);
+ wr.Write(" = ");
+ Print(b.E, wr);
+ }
+ wr.Write(" ");
+
+ Print(node.Body, wr);
+ wr.Write(")");
+ return true;
+ }
+ }
+
+ public class VCExprOpPrinter : IVCExprOpVisitor<bool, TextWriter!> {
+ private VCExprPrinter! ExprPrinter;
+
+ public VCExprOpPrinter(VCExprPrinter! exprPrinter) {
+ this.ExprPrinter = exprPrinter;
+ }
+
+ private bool PrintNAry(string! op, VCExprNAry! node, TextWriter! wr) {
+ wr.Write("({0}", op);
+ foreach (VCExpr! arg in node) {
+ wr.Write(" ");
+ ExprPrinter.Print(arg, wr);
+ }
+ wr.Write(")");
+ return true;
+ }
+
+ public bool VisitNotOp (VCExprNAry! node, TextWriter! wr) {
+ return PrintNAry("!", node, wr);
+ }
+ public bool VisitEqOp (VCExprNAry! node, TextWriter! wr) {
+ return PrintNAry("==", node, wr);
+ }
+ public bool VisitNeqOp (VCExprNAry! node, TextWriter! wr) {
+ return PrintNAry("!=", node, wr);
+ }
+ public bool VisitAndOp (VCExprNAry! node, TextWriter! wr) {
+ assert false;
+ }
+ public bool VisitOrOp (VCExprNAry! node, TextWriter! wr) {
+ assert false;
+ }
+ public bool VisitImpliesOp (VCExprNAry! node, TextWriter! wr) {
+ return PrintNAry("Implies", node, wr);
+ }
+ public bool VisitDistinctOp (VCExprNAry! node, TextWriter! wr) {
+ return PrintNAry("Distinct", node, wr);
+ }
+ public bool VisitLabelOp (VCExprNAry! node, TextWriter! wr) {
+ VCExprLabelOp! op = (VCExprLabelOp)node.Op;
+ return PrintNAry("Label " + op.label, node, wr);
+ }
+ public bool VisitSelectOp (VCExprNAry! node, TextWriter! wr) {
+ return PrintNAry("Select", node, wr);
+ }
+ public bool VisitStoreOp (VCExprNAry! node, TextWriter! wr) {
+ return PrintNAry("Store", node, wr);
+ }
+ public bool VisitBvOp (VCExprNAry! node, TextWriter! wr) {
+ return PrintNAry("Bv", node, wr);
+ }
+ public bool VisitBvExtractOp(VCExprNAry! node, TextWriter! wr) {
+ return PrintNAry("BvExtract", node, wr);
+ }
+ public bool VisitBvConcatOp (VCExprNAry! node, TextWriter! wr) {
+ return PrintNAry("BvConcat", node, wr);
+ }
+ public bool VisitAddOp (VCExprNAry! node, TextWriter! wr) {
+ if (CommandLineOptions.Clo.ReflectAdd) {
+ return PrintNAry("Reflect$Add", node, wr);
+ } else {
+ return PrintNAry("+", node, wr);
+ }
+ }
+ public bool VisitSubOp (VCExprNAry! node, TextWriter! wr) {
+ return PrintNAry("-", node, wr);
+ }
+ public bool VisitMulOp (VCExprNAry! node, TextWriter! wr) {
+ return PrintNAry("*", node, wr);
+ }
+ public bool VisitDivOp (VCExprNAry! node, TextWriter! wr) {
+ return PrintNAry("/", node, wr);
+ }
+ public bool VisitModOp (VCExprNAry! node, TextWriter! wr) {
+ return PrintNAry("%", node, wr);
+ }
+ public bool VisitLtOp (VCExprNAry! node, TextWriter! wr) {
+ return PrintNAry("<", node, wr);
+ }
+ public bool VisitLeOp (VCExprNAry! node, TextWriter! wr) {
+ return PrintNAry("<=", node, wr);
+ }
+ public bool VisitGtOp (VCExprNAry! node, TextWriter! wr) {
+ return PrintNAry(">", node, wr);
+ }
+ public bool VisitGeOp (VCExprNAry! node, TextWriter! wr) {
+ return PrintNAry(">=", node, wr);
+ }
+ public bool VisitSubtypeOp (VCExprNAry! node, TextWriter! wr) {
+ return PrintNAry("<:", node, wr);
+ }
+ public bool VisitSubtype3Op (VCExprNAry! node, TextWriter! wr) {
+ return PrintNAry("<::", node, wr);
+ }
+ public bool VisitBoogieFunctionOp (VCExprNAry! node, TextWriter! wr) {
+ VCExprBoogieFunctionOp! op = (VCExprBoogieFunctionOp)node.Op;
+ return PrintNAry(op.Func.Name, node, wr);
+ }
+ }
+
+
+} \ No newline at end of file
diff --git a/Source/VCExpr/VCExprASTVisitors.ssc b/Source/VCExpr/VCExprASTVisitors.ssc
new file mode 100644
index 00000000..cbb4ab8f
--- /dev/null
+++ b/Source/VCExpr/VCExprASTVisitors.ssc
@@ -0,0 +1,999 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using System;
+using System.Text;
+using System.IO;
+using System.Collections;
+using System.Collections.Generic;
+using Microsoft.Contracts;
+using Microsoft.Basetypes;
+
+// Some visitor skeletons for the VCExpression AST
+
+namespace Microsoft.Boogie.VCExprAST
+{
+ using Microsoft.Boogie;
+
+ public interface IVCExprVisitor<Result, Arg> {
+ Result Visit(VCExprLiteral! node, Arg arg);
+ Result Visit(VCExprNAry! node, Arg arg);
+ Result Visit(VCExprVar! node, Arg arg);
+ Result Visit(VCExprQuantifier! node, Arg arg);
+ Result Visit(VCExprLet! node, Arg arg);
+ }
+
+ public interface IVCExprOpVisitor<Result, Arg> {
+ Result VisitNotOp (VCExprNAry! node, Arg arg);
+ Result VisitEqOp (VCExprNAry! node, Arg arg);
+ Result VisitNeqOp (VCExprNAry! node, Arg arg);
+ Result VisitAndOp (VCExprNAry! node, Arg arg);
+ Result VisitOrOp (VCExprNAry! node, Arg arg);
+ Result VisitImpliesOp (VCExprNAry! node, Arg arg);
+ Result VisitDistinctOp (VCExprNAry! node, Arg arg);
+ Result VisitLabelOp (VCExprNAry! node, Arg arg);
+ Result VisitSelectOp (VCExprNAry! node, Arg arg);
+ Result VisitStoreOp (VCExprNAry! node, Arg arg);
+ Result VisitBvOp (VCExprNAry! node, Arg arg);
+ Result VisitBvExtractOp(VCExprNAry! node, Arg arg);
+ Result VisitBvConcatOp (VCExprNAry! node, Arg arg);
+ Result VisitAddOp (VCExprNAry! node, Arg arg);
+ Result VisitSubOp (VCExprNAry! node, Arg arg);
+ Result VisitMulOp (VCExprNAry! node, Arg arg);
+ Result VisitDivOp (VCExprNAry! node, Arg arg);
+ Result VisitModOp (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 VisitBoogieFunctionOp (VCExprNAry! node, Arg arg);
+ }
+
+ //////////////////////////////////////////////////////////////////////////////
+ // Standard implementations that make it easier to create own visitors
+
+ // Simple traversal of VCExprs. The Visit implementations work
+ // recursively, apart from the implementation for VCExprNAry that
+ // uses a stack when applied to nested nodes with the same
+ // operator, e.g., (AND (AND (AND ...) ...) ...). This is necessary
+ // to avoid stack overflows
+
+ public abstract class TraversingVCExprVisitor<Result, Arg>
+ : IVCExprVisitor<Result, Arg> {
+ protected abstract Result StandardResult(VCExpr! node, Arg arg);
+
+ public Result Traverse(VCExpr! node, Arg arg) {
+ return node.Accept(this, arg);
+ }
+
+ public virtual Result Visit(VCExprLiteral! node, Arg arg) {
+ return StandardResult(node, arg);
+ }
+
+ public virtual Result Visit(VCExprNAry! node, Arg arg) {
+ Result res = StandardResult(node, arg);
+
+ if (node.TypeParamArity == 0) {
+ VCExprOp! op = node.Op;
+
+ IEnumerator enumerator = new VCExprNAryUniformOpEnumerator(node);
+ enumerator.MoveNext();
+
+ while (enumerator.MoveNext()) {
+ VCExpr! expr = (VCExpr!)enumerator.Current;
+ VCExprNAry naryExpr = expr as VCExprNAry;
+ if (naryExpr == null || !naryExpr.Op.Equals(op)) {
+ expr.Accept(this, arg);
+ } else {
+ StandardResult(expr, arg);
+ }
+ }
+ } else {
+ foreach (VCExpr! e in node)
+ e.Accept(this, arg);
+ }
+
+ return res;
+ }
+
+ public virtual Result Visit(VCExprVar! node, Arg arg) {
+ return StandardResult(node, arg);
+ }
+ public virtual Result Visit(VCExprQuantifier! node, Arg arg) {
+ Result res = StandardResult(node, arg);
+ foreach (VCTrigger! trigger in node.Triggers)
+ foreach (VCExpr! expr in trigger.Exprs)
+ expr.Accept(this, arg);
+ node.Body.Accept(this, arg);
+ return res;
+ }
+ public virtual Result Visit(VCExprLet! node, Arg arg) {
+ Result res = StandardResult(node, arg);
+ // visit the bound expressions first
+ foreach (VCExprLetBinding! binding in node)
+ binding.E.Accept(this, arg);
+ node.Body.Accept(this, arg);
+ return res;
+ }
+ }
+
+ //////////////////////////////////////////////////////////////////////////////
+ // Class to iterate over the nodes of a tree of VCExprNAry. This is
+ // used to avoid handling such VCExpr recursively, which can easily
+ // lead to stack overflows
+
+ public class VCExprNAryEnumerator : IEnumerator {
+
+ private readonly VCExprNAry! CompleteExpr;
+ private VCExpr CurrentExpr = null;
+ private readonly Stack<VCExpr!>! ExprTodo = new Stack<VCExpr!> ();
+
+ public VCExprNAryEnumerator(VCExprNAry! completeExpr) {
+ this.CompleteExpr = completeExpr;
+ Stack<VCExpr!>! exprTodo = new Stack<VCExpr!> ();
+ exprTodo.Push(completeExpr);
+ ExprTodo = exprTodo;
+ }
+
+ // Method using which a subclass can decide whether the
+ // subexpressions of an expression should be enumerated as well
+ // The default is to enumerate all nodes
+ protected virtual bool Descend(VCExprNAry! expr) {
+ return true;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ public bool MoveNext() {
+ if (ExprTodo.Count == 0)
+ return false;
+
+ CurrentExpr = ExprTodo.Pop();
+ VCExprNAry currentNAry = CurrentExpr as VCExprNAry;
+ if (currentNAry != null && Descend(currentNAry)) {
+ for (int i = currentNAry.Arity - 1; i >= 0; --i)
+ ExprTodo.Push(currentNAry[i]);
+ }
+
+ return true;
+ }
+
+ public object Current {
+ [Pure][Reads(ReadsAttribute.Reads.Owned)]
+ get {
+ return (!)CurrentExpr;
+ } }
+
+ public void Reset() {
+ ExprTodo.Clear();
+ CurrentExpr = null;
+ ExprTodo.Push(CompleteExpr);
+ }
+ }
+
+
+ //////////////////////////////////////////////////////////////////////////////
+
+ public class VCExprNAryUniformOpEnumerator : VCExprNAryEnumerator {
+ private readonly VCExprOp! Op;
+ public VCExprNAryUniformOpEnumerator(VCExprNAry! completeExpr) {
+ base(completeExpr);
+ this.Op = completeExpr.Op;
+ }
+ protected override bool Descend(VCExprNAry! expr) {
+ return expr.Op.Equals(Op) &&
+ // we never skip nodes with type parameters
+ // (those are too interesting ...)
+ expr.TypeParamArity == 0;
+ }
+ }
+
+ //////////////////////////////////////////////////////////////////////////////
+ // Visitor that knows about the variables bound at each location in a VCExpr
+
+ public abstract class BoundVarTraversingVCExprVisitor<Result, Arg>
+ : TraversingVCExprVisitor<Result, Arg> {
+ // Maps with all variables bound above a certain location in the VCExpression.
+ // The value of the map tells how often a particular symbol was bound
+ private readonly IDictionary<VCExprVar!, int>! BoundTermVarsDict =
+ new Dictionary<VCExprVar!, int> ();
+ private readonly IDictionary<TypeVariable!, int>! BoundTypeVarsDict =
+ new Dictionary<TypeVariable!, int> ();
+
+ protected ICollection<VCExprVar!>! BoundTermVars { get {
+ return BoundTermVarsDict.Keys;
+ } }
+ protected ICollection<TypeVariable!>! BoundTypeVars { get {
+ return BoundTypeVarsDict.Keys;
+ } }
+
+ private void AddBoundVar<T>(IDictionary<T!, int>! dict, T! sym) {
+ int n;
+ if (dict.TryGetValue(sym, out n))
+ dict[sym] = n + 1;
+ else
+ dict[sym] = 1;
+ }
+
+ private void RemoveBoundVar<T>(IDictionary<T!, int>! dict, T! sym) {
+ int n;
+ bool b = dict.TryGetValue(sym, out n);
+ assert b && n > 0;
+ if (n == 1)
+ dict.Remove(sym);
+ else
+ dict[sym] = n - 1;
+ }
+
+ public override Result Visit(VCExprQuantifier! node, Arg arg) {
+ // we temporarily add bound (term and type) variables to the
+ // corresponding lists
+ foreach (VCExprVar! v in node.BoundVars)
+ AddBoundVar<VCExprVar>(BoundTermVarsDict, v);
+ foreach (TypeVariable! v in node.TypeParameters)
+ AddBoundVar<TypeVariable>(BoundTypeVarsDict, v);
+
+ Result res;
+ try {
+ res = VisitAfterBinding(node, arg);
+ } finally {
+ foreach (VCExprVar! v in node.BoundVars)
+ RemoveBoundVar<VCExprVar>(BoundTermVarsDict, v);
+ foreach (TypeVariable! v in node.TypeParameters)
+ RemoveBoundVar<TypeVariable>(BoundTypeVarsDict, v);
+ }
+ return res;
+ }
+ public override Result Visit(VCExprLet! node, Arg arg) {
+ // we temporarily add bound term variables to the
+ // corresponding lists
+ foreach (VCExprVar! v in node.BoundVars)
+ AddBoundVar<VCExprVar>(BoundTermVarsDict, v);
+
+ Result res;
+ try {
+ res = VisitAfterBinding(node, arg);
+ } finally {
+ foreach (VCExprVar! v in node.BoundVars)
+ RemoveBoundVar<VCExprVar>(BoundTermVarsDict, v);
+ }
+ return res;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ // The possibility is provided to look at a (quantifier or let) node
+ // after its bound variables have been registered
+ // (when overriding the normal visit-methods, the node will be visited
+ // before the binding happens)
+
+ protected virtual Result VisitAfterBinding(VCExprQuantifier! node, Arg arg) {
+ return base.Visit(node, arg);
+ }
+
+ protected virtual Result VisitAfterBinding(VCExprLet! node, Arg arg) {
+ return base.Visit(node, arg);
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ // General visitor for recursively collecting information in a VCExpr.
+ // As the visitor is not used anywhere for the time being, it maybe should
+ // be removed
+
+ public abstract class CollectingVCExprVisitor<Result, Arg>
+ : IVCExprVisitor<Result, Arg> {
+ protected abstract Result CombineResults(List<Result>! results, Arg arg);
+
+ public Result Collect(VCExpr! node, Arg arg) {
+ return node.Accept(this, arg);
+ }
+
+ public virtual Result Visit(VCExprLiteral! node, Arg arg) {
+ return CombineResults(new List<Result> (), arg);
+ }
+ public virtual Result Visit(VCExprNAry! node, Arg arg) {
+ List<Result>! results = new List<Result> ();
+ foreach (VCExpr! subnode in node)
+ results.Add(subnode.Accept(this, arg));
+ return CombineResults(results, arg);
+ }
+ public virtual Result Visit(VCExprVar! node, Arg arg) {
+ return CombineResults(new List<Result> (), arg);
+ }
+ public virtual Result Visit(VCExprQuantifier! node, Arg arg) {
+ List<Result>! result = new List<Result> ();
+ result.Add(node.Body.Accept(this, arg));
+ foreach (VCTrigger! trigger in node.Triggers)
+ foreach (VCExpr! expr in trigger.Exprs)
+ result.Add(expr.Accept(this, arg));
+ return CombineResults(result, arg);
+ }
+ public virtual Result Visit(VCExprLet! node, Arg arg) {
+ List<Result>! results = new List<Result> ();
+ // visit the bound expressions first
+ foreach (VCExprLetBinding! binding in node)
+ results.Add(binding.E.Accept(this, arg));
+ results.Add(node.Body.Accept(this, arg));
+ return CombineResults(results, arg);
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ public class SizeComputingVisitor : TraversingVCExprVisitor<bool, bool> {
+
+ private int Size = 0;
+
+ public static int ComputeSize(VCExpr! expr) {
+ SizeComputingVisitor! visitor = new SizeComputingVisitor();
+ visitor.Traverse(expr, true);
+ return visitor.Size;
+ }
+
+ protected override bool StandardResult(VCExpr! node, bool arg) {
+ Size = Size + 1;
+ return true;
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ // Collect all free term and type variables in a VCExpr. Type variables
+ // can occur free either in the types of bound variables, or in the type
+ // parameters of VCExprNAry.
+
+ // the result and argument (of type bool) are not used currently
+ public class FreeVariableCollector : BoundVarTraversingVCExprVisitor<bool, bool> {
+ public readonly Dictionary<VCExprVar!,object>! FreeTermVars = new Dictionary<VCExprVar!,object> ();
+ public readonly List<TypeVariable!>! FreeTypeVars = new List<TypeVariable!> ();
+
+ // not used
+ protected override bool StandardResult(VCExpr! node, bool arg) {
+ return true;
+ }
+
+ public static Dictionary<VCExprVar!,object>! FreeTermVariables(VCExpr! node) {
+ FreeVariableCollector collector = new FreeVariableCollector ();
+ collector.Traverse(node, true);
+ return collector.FreeTermVars;
+ }
+
+ public static List<TypeVariable!>! FreeTypeVariables(VCExpr! node) {
+ FreeVariableCollector collector = new FreeVariableCollector ();
+ collector.Traverse(node, true);
+ return collector.FreeTypeVars;
+ }
+
+ public void Reset() {
+ FreeTermVars.Clear();
+ FreeTypeVars.Clear();
+ }
+
+ public void Collect(VCExpr! node) {
+ Traverse(node, true);
+ }
+
+ public void Collect(Type! type) {
+ AddTypeVariables(type.FreeVariables.ToList());
+ }
+
+ /////////////////////////////////////////////////////////////////////////
+
+ private void CollectTypeVariables(IEnumerable<VCExprVar!>! boundVars) {
+ foreach (VCExprVar! var in boundVars)
+ Collect(var.Type);
+ }
+
+ private void AddTypeVariables(IEnumerable<TypeVariable!>! typeVars) {
+ foreach (TypeVariable! tvar in typeVars)
+ if (!BoundTypeVars.Contains(tvar) && !FreeTypeVars.Contains(tvar))
+ FreeTypeVars.Add(tvar);
+ }
+
+ public override bool Visit(VCExprVar! node, bool arg) {
+ if (!BoundTermVars.Contains(node) && !FreeTermVars.ContainsKey(node)) {
+ FreeTermVars.Add(node, null);
+ Collect(node.Type);
+ }
+ return true;
+ }
+
+ public override bool Visit(VCExprNAry! node, bool arg) {
+ foreach (Type! t in node.TypeArguments)
+ Collect(t);
+ return base.Visit(node, arg);
+ }
+
+ protected override bool VisitAfterBinding(VCExprQuantifier! node, bool arg) {
+ CollectTypeVariables(node.BoundVars);
+ return base.VisitAfterBinding(node, arg);
+ }
+
+ protected override bool VisitAfterBinding(VCExprLet! node, bool arg) {
+ CollectTypeVariables(node.BoundVars);
+ return base.VisitAfterBinding(node, arg);
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Framework for mutating VCExprs
+
+ // The Visit implementations in the following visitor work
+ // recursively, apart from the implementation for VCExprNAry that
+ // uses its own stack when applied to nested nodes with the same
+ // operator, e.g., (AND (AND (AND ...) ...) ...). This is necessary
+ // to avoid stack overflows (like in TraversingVCExprVisitor)
+
+ public abstract class MutatingVCExprVisitor<Arg>
+ : IVCExprVisitor<VCExpr!, Arg> {
+ protected readonly VCExpressionGenerator! Gen;
+
+ public MutatingVCExprVisitor(VCExpressionGenerator! gen) {
+ this.Gen = gen;
+ }
+
+ public VCExpr! Mutate(VCExpr! expr, Arg arg) {
+ return expr.Accept(this, arg);
+ }
+
+ public List<VCExpr!>! MutateSeq(IEnumerable<VCExpr!>! exprs, Arg arg) {
+ List<VCExpr!>! res = new List<VCExpr!> ();
+ foreach (VCExpr! expr in exprs)
+ res.Add(expr.Accept(this, arg));
+ return res;
+ }
+
+ private List<VCExpr!>! MutateList(List<VCExpr!>! exprs, Arg arg) {
+ bool changed = false;
+ List<VCExpr!>! res = new List<VCExpr!> ();
+ foreach (VCExpr! expr in exprs) {
+ VCExpr! newExpr = expr.Accept(this, arg);
+ if (!Object.ReferenceEquals(expr, newExpr))
+ changed = true;
+ res.Add(newExpr);
+ }
+ if (!changed)
+ return exprs;
+ return res;
+ }
+
+ public virtual VCExpr! Visit(VCExprLiteral! node, Arg arg) {
+ return node;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ // Special element used to mark the positions in the todo-stack where
+ // results have to be popped from the result-stack.
+ private static readonly VCExpr! CombineResultsMarker = new VCExprLiteral (Type.Bool);
+
+ // The todo-stack contains records of the shape
+ //
+ // arg0
+ // arg1
+ // arg2
+ // ...
+ // CombineResultsMarker
+ // f(arg0, arg1, arg2, ...) (the original expression)
+
+ private readonly Stack<VCExpr!>! NAryExprTodoStack = new Stack<VCExpr!> ();
+ private readonly Stack<VCExpr!>! NAryExprResultStack = new Stack<VCExpr!> ();
+
+ private void PushTodo(VCExprNAry! exprTodo) {
+ NAryExprTodoStack.Push(exprTodo);
+ NAryExprTodoStack.Push(CombineResultsMarker);
+ for (int i = exprTodo.Arity - 1; i >= 0; --i)
+ NAryExprTodoStack.Push(exprTodo[i]);
+ }
+
+ public virtual VCExpr! Visit(VCExprNAry! node, Arg arg) {
+ VCExprOp! op = node.Op;
+ int initialStackSize = NAryExprTodoStack.Count;
+ int initialResultStackSize = NAryExprResultStack.Count;
+
+ PushTodo(node);
+
+ while (NAryExprTodoStack.Count > initialStackSize) {
+ VCExpr! subExpr = NAryExprTodoStack.Pop();
+
+ if (Object.ReferenceEquals(subExpr, CombineResultsMarker)) {
+ //
+ // assemble a result
+ VCExprNAry! originalExpr = (VCExprNAry)NAryExprTodoStack.Pop();
+ bool changed = false;
+ List<VCExpr!>! newSubExprs = new List<VCExpr!> ();
+
+ for (int i = op.Arity - 1; i >= 0; --i) {
+ VCExpr! nextSubExpr = NAryExprResultStack.Pop();
+ if (!Object.ReferenceEquals(nextSubExpr, originalExpr[i]))
+ changed = true;
+ newSubExprs.Insert(0, nextSubExpr);
+ }
+
+ NAryExprResultStack.Push(UpdateModifiedNode(originalExpr, newSubExprs, changed, arg));
+ //
+ } else {
+ //
+ VCExprNAry narySubExpr = subExpr as VCExprNAry;
+ if (narySubExpr != null && narySubExpr.Op.Equals(op) &&
+ // as in VCExprNAryUniformOpEnumerator, all expressions with
+ // type parameters are allowed to be inspected more closely
+ narySubExpr.TypeParamArity == 0) {
+ PushTodo(narySubExpr);
+ } else {
+ NAryExprResultStack.Push(subExpr.Accept(this, arg));
+ }
+ //
+ }
+ }
+
+ assert NAryExprTodoStack.Count == initialStackSize &&
+ NAryExprResultStack.Count == initialResultStackSize + 1;
+ return NAryExprResultStack.Pop();
+ }
+
+ protected virtual VCExpr! UpdateModifiedNode(VCExprNAry! originalNode,
+ List<VCExpr!>! newSubExprs,
+ // has any of the subexpressions changed?
+ bool changed,
+ Arg arg) {
+ if (changed)
+ return Gen.Function(originalNode.Op,
+ newSubExprs, originalNode.TypeArguments);
+ else
+ return originalNode;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ public virtual VCExpr! Visit(VCExprVar! node, Arg arg) {
+ return node;
+ }
+
+ protected List<VCTrigger!>! MutateTriggers(List<VCTrigger!>! triggers, Arg arg) {
+ List<VCTrigger!>! newTriggers = new List<VCTrigger!> ();
+ bool changed = false;
+ foreach (VCTrigger! trigger in triggers) {
+ List<VCExpr!>! exprs = trigger.Exprs;
+ List<VCExpr!>! newExprs = MutateList(exprs, arg);
+ if (Object.ReferenceEquals(exprs, newExprs)) {
+ newTriggers.Add(trigger);
+ } else {
+ newTriggers.Add(Gen.Trigger(trigger.Pos, newExprs));
+ changed = true;
+ }
+ }
+ if (!changed)
+ return triggers;
+ return newTriggers;
+ }
+
+ public virtual VCExpr! Visit(VCExprQuantifier! node, Arg arg) {
+ bool changed = false;
+
+ VCExpr! body = node.Body;
+ VCExpr! newbody = body.Accept(this, arg);
+ if (!Object.ReferenceEquals(body, newbody))
+ changed = true;
+
+ // visit the trigger expressions as well
+ List<VCTrigger!>! triggers = node.Triggers;
+ List<VCTrigger!>! newTriggers = MutateTriggers(triggers, arg);
+ if (!Object.ReferenceEquals(triggers, newTriggers))
+ changed = true;
+
+ if (!changed)
+ return node;
+ return Gen.Quantify(node.Quan, node.TypeParameters, node.BoundVars,
+ newTriggers, node.Infos, newbody);
+ }
+
+ public virtual VCExpr! Visit(VCExprLet! node, Arg arg) {
+ bool changed = false;
+
+ VCExpr! body = node.Body;
+ VCExpr! newbody = body.Accept(this, arg);
+ if (!Object.ReferenceEquals(body, newbody))
+ changed = true;
+
+ List<VCExprLetBinding!>! newbindings = new List<VCExprLetBinding!> ();
+ for (int i = 0; i < node.Length; ++i) {
+ VCExprLetBinding! binding = node[i];
+ VCExpr! e = binding.E;
+ VCExpr! newE = e.Accept(this, arg);
+ if (Object.ReferenceEquals(e, newE)) {
+ newbindings.Add(binding);
+ } else {
+ changed = true;
+ newbindings.Add(Gen.LetBinding(binding.V, newE));
+ }
+ }
+
+ if (!changed)
+ return node;
+ return Gen.Let(newbindings, newbody);
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Substitutions and a visitor for applying substitutions. A substitution can
+ // substitute both type variables and term variables
+
+ public class VCExprSubstitution {
+ private readonly List<IDictionary<VCExprVar!, VCExpr!>!>! TermSubsts;
+ private readonly List<IDictionary<TypeVariable!, Type!>!>! TypeSubsts;
+
+ public VCExprSubstitution(IDictionary<VCExprVar!, VCExpr!>! termSubst,
+ IDictionary<TypeVariable!, Type!>! typeSubst) {
+ List<IDictionary<VCExprVar!, VCExpr!>!>! termSubsts =
+ new List<IDictionary<VCExprVar!, VCExpr!>!> ();
+ termSubsts.Add(termSubst);
+ List<IDictionary<TypeVariable!, Type!>!>! typeSubsts =
+ new List<IDictionary<TypeVariable!, Type!>!> ();
+ typeSubsts.Add(typeSubst);
+ this.TermSubsts = termSubsts;
+ this.TypeSubsts = typeSubsts;
+ }
+
+ public VCExprSubstitution() {
+ this(new Dictionary<VCExprVar!, VCExpr!> (), new Dictionary<TypeVariable!, Type!> ());
+ }
+
+ public void PushScope() {
+ TermSubsts.Add(new Dictionary<VCExprVar!, VCExpr!> ());
+ TypeSubsts.Add(new Dictionary<TypeVariable!, Type!> ());
+ }
+
+ public void PopScope() {
+ TermSubsts.RemoveAt(TermSubsts.Count - 1);
+ TypeSubsts.RemoveAt(TypeSubsts.Count - 1);
+ }
+
+ public VCExpr this[VCExprVar! var] {
+ get {
+ VCExpr res;
+ for (int i = TermSubsts.Count - 1; i >= 0; --i) {
+ if (TermSubsts[i].TryGetValue(var, out res))
+ return res;
+ }
+ return null;
+ }
+ set {
+ TermSubsts[TermSubsts.Count - 1][var] = (!)value;
+ }
+ }
+
+ public Type this[TypeVariable! var] {
+ get {
+ Type res;
+ for (int i = TypeSubsts.Count - 1; i >= 0; --i) {
+ if (TypeSubsts[i].TryGetValue(var, out res))
+ return res;
+ }
+ return null;
+ }
+ set {
+ TypeSubsts[TypeSubsts.Count - 1][var] = (!)value;
+ }
+ }
+
+ public bool ContainsKey(VCExprVar! var) {
+ return this[var] != null;
+ }
+
+ public bool ContainsKey(TypeVariable! var) {
+ return this[var] != null;
+ }
+
+ public bool TermSubstIsEmpty { get {
+ return forall{IDictionary<VCExprVar!, VCExpr!>! dict in TermSubsts;
+ dict.Count == 0};
+ } }
+
+ public bool TypeSubstIsEmpty { get {
+ return forall{IDictionary<TypeVariable!, Type!>! dict in TypeSubsts;
+ dict.Count == 0};
+ } }
+
+ public IDictionary<TypeVariable!, Type!>! ToTypeSubst { get {
+ IDictionary<TypeVariable!, Type!>! res = new Dictionary<TypeVariable!, Type!> ();
+ foreach (IDictionary<TypeVariable!, Type!>! dict in TypeSubsts)
+ foreach (KeyValuePair<TypeVariable!, Type!> pair in dict)
+ // later ones overwrite earlier ones
+ res[pair.Key] = pair.Value;
+ return res;
+ } }
+
+ // the variables that are not mapped to themselves
+ public IEnumerable<VCExprVar!>! TermDomain { get {
+ Dictionary<VCExprVar!, bool>! domain = new Dictionary<VCExprVar!, bool> ();
+ foreach (IDictionary<VCExprVar!, VCExpr!>! dict in TermSubsts)
+ foreach (VCExprVar! var in dict.Keys)
+ if (!var.Equals(this[var]))
+ domain.Add(var, true);
+ return domain.Keys;
+ } }
+
+ // the variables that are not mapped to themselves
+ public IEnumerable<TypeVariable!>! TypeDomain { get {
+ Dictionary<TypeVariable!, bool>! domain = new Dictionary<TypeVariable!, bool> ();
+ foreach (IDictionary<TypeVariable!, Type!>! dict in TypeSubsts)
+ foreach (TypeVariable! var in dict.Keys)
+ if (!var.Equals(this[var]))
+ domain.Add(var, true);
+ return domain.Keys;
+ } }
+
+ public FreeVariableCollector! Codomains { get {
+ FreeVariableCollector! coll = new FreeVariableCollector ();
+ foreach (VCExprVar! var in TermDomain)
+ coll.Collect((!)this[var]);
+ foreach (TypeVariable! var in TypeDomain)
+ coll.Collect((!)this[var]);
+ return coll;
+ } }
+
+ public VCExprSubstitution! Clone() {
+ VCExprSubstitution! res = new VCExprSubstitution ();
+ foreach (IDictionary<VCExprVar!, VCExpr!>! dict in TermSubsts)
+ res.TermSubsts.Add(HelperFuns.Clone(dict));
+ foreach (IDictionary<TypeVariable!, Type!>! dict in TypeSubsts)
+ res.TypeSubsts.Add(HelperFuns.Clone(dict));
+ return res;
+ }
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////
+
+ public class SubstitutingVCExprVisitor
+ : MutatingVCExprVisitor<VCExprSubstitution!> {
+ public SubstitutingVCExprVisitor(VCExpressionGenerator! gen) {
+ base(gen);
+ }
+
+ // when descending across a binder, we have to check that no collisions
+ // or variable capture can occur. if this might happen, we replace the
+ // term and type variables bound by the binder with fresh variables
+ private bool CollisionPossible(IEnumerable<TypeVariable!>! typeParams,
+ IEnumerable<VCExprVar!>! boundVars,
+ VCExprSubstitution! substitution) {
+ // variables can be shadowed by a binder
+ if (exists{TypeVariable! var in typeParams; substitution.ContainsKey(var)} ||
+ exists{VCExprVar! var in boundVars; substitution.ContainsKey(var)})
+ return true;
+ // compute the codomain of the substitution
+ FreeVariableCollector! coll = substitution.Codomains;
+ // variables could be captured when applying the substitution
+ return exists{TypeVariable! var in typeParams; coll.FreeTypeVars.Contains(var)} ||
+ exists{VCExprVar! var in boundVars; coll.FreeTermVars.ContainsKey(var)};
+ }
+
+ // can be overwritten if names of bound variables are to be changed
+ protected virtual string! ChooseNewVariableName(string! oldName) {
+ return oldName;
+ }
+
+ // handle type parameters in VCExprNAry
+ protected override VCExpr! UpdateModifiedNode(VCExprNAry! originalNode,
+ List<VCExpr!>! newSubExprs,
+ bool changed,
+ VCExprSubstitution! substitution) {
+ List<Type!>! typeParams = new List<Type!> ();
+ foreach (Type! t in originalNode.TypeArguments) {
+ Type! newType = t.Substitute(substitution.ToTypeSubst);
+ if (!ReferenceEquals(t, newType))
+ changed = true;
+ typeParams.Add(newType);
+ }
+ if (changed)
+ return Gen.Function(originalNode.Op, newSubExprs, typeParams);
+ else
+ return originalNode;
+ }
+
+ public override VCExpr! Visit(VCExprQuantifier! node,
+ VCExprSubstitution! substitution) {
+ // the default is to refresh bound variables only if necessary
+ // because of collisions
+ return Visit(node, substitution, false);
+ }
+
+ public VCExpr! Visit(VCExprQuantifier! node,
+ VCExprSubstitution! substitution,
+ bool refreshBoundVariables) {
+ substitution.PushScope(); try {
+
+ List<TypeVariable!>! typeParams = node.TypeParameters;
+ bool refreshAllVariables = refreshBoundVariables ||
+ CollisionPossible(node.TypeParameters, node.BoundVars, substitution);
+ if (refreshAllVariables) {
+ // we introduce fresh type variables to ensure that none gets captured
+ typeParams = new List<TypeVariable!> ();
+ foreach (TypeVariable! var in node.TypeParameters) {
+ TypeVariable! freshVar =
+ new TypeVariable (Token.NoToken, ChooseNewVariableName(var.Name));
+ typeParams.Add(freshVar);
+ substitution[var] = freshVar;
+ // this might overwrite other elements of the substitution, deliberately
+ }
+ }
+
+ List<VCExprVar!>! boundVars = node.BoundVars;
+ if (refreshAllVariables || !substitution.TypeSubstIsEmpty) {
+ // collisions are possible, or we also substitute type variables. in this case
+ // the bound term variables have to be replaced with fresh variables with the
+ // right types
+ boundVars = new List<VCExprVar!> ();
+ IDictionary<TypeVariable!, Type!>! typeSubst = substitution.ToTypeSubst;
+ foreach (VCExprVar! var in node.BoundVars) {
+ VCExprVar! freshVar =
+ Gen.Variable(ChooseNewVariableName(var.Name),
+ var.Type.Substitute(typeSubst));
+ boundVars.Add(freshVar);
+ substitution[var] = freshVar;
+ // this might overwrite other elements of the substitution, deliberately
+ }
+ }
+
+ List<VCTrigger!>! newTriggers = new List<VCTrigger!> ();
+ foreach (VCTrigger! trigger in node.Triggers)
+ newTriggers.Add(Gen.Trigger(trigger.Pos, MutateSeq(trigger.Exprs, substitution)));
+
+ VCExpr! newBody = Mutate(node.Body, substitution);
+
+ return Gen.Quantify(node.Quan, typeParams, boundVars,
+ newTriggers, node.Infos, newBody);
+
+ } finally {
+ substitution.PopScope();
+ }
+ }
+
+ public override VCExpr! Visit(VCExprVar! node,
+ VCExprSubstitution! substitution) {
+ VCExpr res = substitution[node];
+ if (res != null)
+ return res;
+ return node;
+ }
+
+ public override VCExpr! Visit(VCExprLet! node,
+ VCExprSubstitution! substitution) {
+ // the default is to refresh bound variables only if necessary
+ // because of collisions
+ return Visit(node, substitution, false);
+ }
+
+ public VCExpr! Visit(VCExprLet! node,
+ VCExprSubstitution! substitution,
+ bool refreshBoundVariables) {
+ // let-expressions do not have type parameters (fortunately ...)
+ substitution.PushScope (); try {
+
+ bool refreshAllVariables =
+ refreshBoundVariables ||
+ !substitution.TypeSubstIsEmpty ||
+ CollisionPossible(new List<TypeVariable!> (), node.BoundVars, substitution);
+
+ List<VCExprVar!>! newBoundVars = node.BoundVars;
+ if (refreshAllVariables) {
+ // collisions are possible, or we also substitute type variables. in this case
+ // the bound term variables have to be replaced with fresh variables with the
+ // right types
+ newBoundVars = new List<VCExprVar!> ();
+ IDictionary<TypeVariable!, Type!>! typeSubst = substitution.ToTypeSubst;
+ foreach (VCExprVar! var in node.BoundVars) {
+ VCExprVar! freshVar =
+ Gen.Variable(ChooseNewVariableName(var.Name),
+ var.Type.Substitute(typeSubst));
+ newBoundVars.Add(freshVar);
+ substitution[var] = freshVar;
+ // this might overwrite other elements of the substitution, deliberately
+ }
+ }
+
+ List<VCExprLetBinding!>! newbindings = new List<VCExprLetBinding!> ();
+ for (int i = 0; i < node.Length; ++i) {
+ VCExprLetBinding! binding = node[i];
+ newbindings.Add(Gen.LetBinding(newBoundVars[i], Mutate(binding.E, substitution)));
+ }
+
+ VCExpr! newBody = Mutate(node.Body, substitution);
+ return Gen.Let(newbindings, newBody);
+
+ } finally {
+ substitution.PopScope();
+ }
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ public abstract class StandardVCExprOpVisitor<Result, Arg>
+ : IVCExprOpVisitor<Result, Arg> {
+ protected abstract Result StandardResult(VCExprNAry! node, Arg arg);
+
+ public virtual Result VisitNotOp (VCExprNAry! node, Arg arg) {
+ return StandardResult(node, arg);
+ }
+ public virtual Result VisitEqOp (VCExprNAry! node, Arg arg) {
+ return StandardResult(node, arg);
+ }
+ public virtual Result VisitNeqOp (VCExprNAry! node, Arg arg) {
+ return StandardResult(node, arg);
+ }
+ public virtual Result VisitAndOp (VCExprNAry! node, Arg arg) {
+ return StandardResult(node, arg);
+ }
+ public virtual Result VisitOrOp (VCExprNAry! node, Arg arg) {
+ return StandardResult(node, arg);
+ }
+ public virtual Result VisitImpliesOp (VCExprNAry! node, Arg arg) {
+ return StandardResult(node, arg);
+ }
+ public virtual Result VisitDistinctOp (VCExprNAry! node, Arg arg) {
+ return StandardResult(node, arg);
+ }
+ public virtual Result VisitLabelOp (VCExprNAry! node, Arg arg) {
+ return StandardResult(node, arg);
+ }
+ public virtual Result VisitSelectOp (VCExprNAry! node, Arg arg) {
+ return StandardResult(node, arg);
+ }
+ public virtual Result VisitStoreOp (VCExprNAry! node, Arg arg) {
+ return StandardResult(node, arg);
+ }
+ public virtual Result VisitBvOp (VCExprNAry! node, Arg arg) {
+ return StandardResult(node, arg);
+ }
+ public virtual Result VisitBvExtractOp(VCExprNAry! node, Arg arg) {
+ return StandardResult(node, arg);
+ }
+ public virtual Result VisitBvConcatOp (VCExprNAry! node, Arg arg) {
+ return StandardResult(node, arg);
+ }
+ public virtual Result VisitAddOp (VCExprNAry! node, Arg arg) {
+ return StandardResult(node, arg);
+ }
+ public virtual Result VisitSubOp (VCExprNAry! node, Arg arg) {
+ return StandardResult(node, arg);
+ }
+ public virtual Result VisitMulOp (VCExprNAry! node, Arg arg) {
+ return StandardResult(node, arg);
+ }
+ public virtual Result VisitDivOp (VCExprNAry! node, Arg arg) {
+ return StandardResult(node, arg);
+ }
+ public virtual Result VisitModOp (VCExprNAry! node, Arg arg) {
+ return StandardResult(node, arg);
+ }
+ public virtual Result VisitLtOp (VCExprNAry! node, Arg arg) {
+ return StandardResult(node, arg);
+ }
+ public virtual Result VisitLeOp (VCExprNAry! node, Arg arg) {
+ return StandardResult(node, arg);
+ }
+ public virtual Result VisitGtOp (VCExprNAry! node, Arg arg) {
+ return StandardResult(node, arg);
+ }
+ public virtual Result VisitGeOp (VCExprNAry! node, Arg arg) {
+ return StandardResult(node, arg);
+ }
+ public virtual Result VisitSubtypeOp (VCExprNAry! node, Arg arg) {
+ return StandardResult(node, arg);
+ }
+ public virtual Result VisitSubtype3Op (VCExprNAry! node, Arg arg) {
+ return StandardResult(node, arg);
+ }
+ public virtual Result VisitBoogieFunctionOp (VCExprNAry! node, Arg arg) {
+ return StandardResult(node, arg);
+ }
+ }
+
+}
+
+
diff --git a/Source/VCGeneration/Check.ssc b/Source/VCGeneration/Check.ssc
new file mode 100644
index 00000000..f0d6c558
--- /dev/null
+++ b/Source/VCGeneration/Check.ssc
@@ -0,0 +1,375 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Threading;
+using System.IO;
+using System.Diagnostics;
+using Microsoft.Contracts;
+using Microsoft.Boogie.AbstractInterpretation;
+using Microsoft.Boogie.VCExprAST;
+
+namespace Microsoft.Boogie
+{
+ /// <summary>
+ /// Interface to the theorem prover specialized to Boogie.
+ ///
+ /// This class creates the appropriate background axioms. There
+ /// should be one instance per BoogiePL program.
+ /// </summary>
+ public sealed class Checker
+ {
+ private readonly VCExpressionGenerator! gen;
+
+ private ProverInterface! thmProver;
+ private CommandLineOptions.BvHandling bitvectors;
+ private int timeout;
+
+ // state for the async interface
+ private volatile ProverInterface.Outcome outcome;
+ private volatile bool busy;
+ private volatile bool hasOutput;
+ private volatile UnexpectedProverOutputException outputExn;
+ private DateTime proverStart;
+ private TimeSpan proverRunTime;
+ private volatile ProverInterface.ErrorHandler handler;
+ private volatile bool closed;
+
+ public readonly AutoResetEvent! ProverDone = new AutoResetEvent(false);
+
+ private static CommandLineOptions.BvHandling BvHandlingForImpl(Implementation! impl)
+ {
+ bool force_int = false;
+ bool force_native = false;
+ ((!)impl.Proc).CheckBooleanAttribute("forceBvInt", ref force_int);
+ impl.Proc.CheckBooleanAttribute("forceBvZ3Native", ref force_native);
+ impl.CheckBooleanAttribute("forceBvInt", ref force_int);
+ impl.CheckBooleanAttribute("forceBvZ3Native", ref force_native);
+ if (force_native) return CommandLineOptions.BvHandling.Z3Native;
+ if (force_int) return CommandLineOptions.BvHandling.ToInt;
+ return CommandLineOptions.Clo.Bitvectors;
+ }
+
+ public bool WillingToHandle(Implementation! impl, int timeout)
+ {
+ return !closed && timeout == this.timeout && bitvectors == BvHandlingForImpl(impl);
+ }
+
+ public VCExpressionGenerator! VCExprGen
+ {
+ get { return this.gen; }
+ }
+ public ProverInterface! TheoremProver
+ {
+ get { return this.thmProver; }
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////
+ // We share context information for the same program between different Checkers
+
+ private struct ContextCacheKey {
+ public readonly Program! program;
+ public readonly CommandLineOptions.BvHandling bitvectors;
+
+ public ContextCacheKey(Program! prog,
+ CommandLineOptions.BvHandling bitvectors) {
+ this.program = prog;
+ this.bitvectors = bitvectors;
+ }
+
+ [Pure][Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals(object that) {
+ if (that is ContextCacheKey) {
+ ContextCacheKey thatKey = (ContextCacheKey)that;
+ return this.program.Equals(thatKey.program) &&
+ this.bitvectors.Equals(thatKey.bitvectors);
+ }
+ return false;
+ }
+
+ [Pure]
+ public override int GetHashCode() {
+ return this.program.GetHashCode() + this.bitvectors.GetHashCode();
+ }
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////
+
+ /// <summary>
+ /// Constructor. Initialize a the checker with the program and log file.
+ /// </summary>
+ public Checker(VC.ConditionGeneration! vcgen, Program! prog, string/*?*/ logFilePath, bool appendLogFile, Implementation! impl, int timeout)
+ {
+ this.bitvectors = BvHandlingForImpl(impl);
+ this.timeout = timeout;
+
+ ProverOptions! options = ((!)CommandLineOptions.Clo.TheProverFactory).BlankProverOptions();
+
+ if (logFilePath != null) {
+ options.LogFilename = logFilePath;
+ if (appendLogFile)
+ options.AppendLogFile = appendLogFile;
+ }
+
+ options.Parse(CommandLineOptions.Clo.ProverOptions);
+
+ if (timeout > 0) {
+ options.TimeLimit = timeout * 1000;
+ }
+ options.BitVectors = this.bitvectors;
+
+ ContextCacheKey key = new ContextCacheKey (prog, this.bitvectors);
+ ProverContext ctx;
+ ProverInterface prover;
+
+ if (vcgen.CheckerCommonState == null) {
+ vcgen.CheckerCommonState = new Dictionary<ContextCacheKey, ProverContext!> ();
+ }
+ IDictionary<ContextCacheKey, ProverContext!>! cachedContexts = (IDictionary<ContextCacheKey, ProverContext!>) vcgen.CheckerCommonState;
+
+ if (cachedContexts.TryGetValue(key, out ctx)) {
+ ctx = (ProverContext!)((!)ctx).Clone();
+ prover = (ProverInterface)
+ CommandLineOptions.Clo.TheProverFactory.SpawnProver(options, ctx);
+ } else {
+ ctx = (ProverContext!)CommandLineOptions.Clo.TheProverFactory.NewProverContext(options);
+
+ // set up the context
+ foreach (Declaration! decl in prog.TopLevelDeclarations) {
+ TypeCtorDecl t = decl as TypeCtorDecl;
+ if (t != null) {
+ ctx.DeclareType(t, null);
+ }
+ }
+ foreach (Declaration! decl in prog.TopLevelDeclarations) {
+ Constant c = decl as Constant;
+ if (c != null) {
+ ctx.DeclareConstant(c, c.Unique, null);
+ } else {
+ Function f = decl as Function;
+ if (f != null) {
+ ctx.DeclareFunction(f, null);
+ }
+ }
+ }
+ foreach (Declaration! decl in prog.TopLevelDeclarations) {
+ bool expand = false;
+ Axiom ax = decl as Axiom;
+ decl.CheckBooleanAttribute("inline", ref expand);
+ if (!expand && ax != null) {
+ ctx.AddAxiom(ax, null);
+ }
+ }
+ foreach (Declaration! decl in prog.TopLevelDeclarations) {
+ GlobalVariable v = decl as GlobalVariable;
+ if (v != null) {
+ ctx.DeclareGlobalVariable(v, null);
+ }
+ }
+
+ // we first generate the prover and then store a clone of the
+ // context in the cache, so that the prover can setup stuff in
+ // the context to be cached
+ prover = (ProverInterface)
+ CommandLineOptions.Clo.TheProverFactory.SpawnProver(options, ctx);
+ cachedContexts.Add(key, (ProverContext!)ctx.Clone());
+ }
+
+ this.thmProver = prover;
+ this.gen = prover.VCExprGen;
+
+ // base();
+ }
+
+
+ /// <summary>
+ /// Clean-up.
+ /// </summary>
+ public void Close()
+ {
+ this.closed = true;
+ thmProver.Close();
+ }
+
+ /// <summary>
+ /// Push a Verification Condition as an Axiom
+ /// (Required for Doomed Program Point detection)
+ /// </summary>
+ public void PushVCExpr(VCExpr! vc)
+ {
+ //thmProver.Context.AddAxiom(vc);
+ thmProver.PushVCExpression(vc);
+ }
+
+ public bool IsBusy
+ {
+ get { return busy; }
+ }
+
+ public bool Closed
+ {
+ get { return closed; }
+ }
+
+ public bool HasOutput
+ {
+ get { return hasOutput; }
+ }
+
+ public TimeSpan ProverRunTime
+ {
+ get { return proverRunTime; }
+ }
+
+ private void WaitForOutput(object dummy)
+ {
+ try {
+ outcome = thmProver.CheckOutcome((!)handler);
+ } catch (UnexpectedProverOutputException e) {
+ outputExn = e;
+ }
+
+ switch (outcome) {
+ case ProverInterface.Outcome.Valid:
+ thmProver.LogComment("Valid");
+ break;
+ case ProverInterface.Outcome.Invalid:
+ thmProver.LogComment("Invalid");
+ break;
+ case ProverInterface.Outcome.TimeOut:
+ thmProver.LogComment("Timed out");
+ break;
+ case ProverInterface.Outcome.OutOfMemory:
+ thmProver.LogComment("Out of memory");
+ break;
+ case ProverInterface.Outcome.Undetermined:
+ thmProver.LogComment("Undetermined");
+ break;
+ }
+
+ assert busy;
+ hasOutput = true;
+ proverRunTime = DateTime.Now - proverStart;
+
+ ProverDone.Set();
+ }
+
+ public void BeginCheck(string! descriptiveName, VCExpr! vc, ProverInterface.ErrorHandler! handler)
+ requires !IsBusy;
+ {
+ assert !busy;
+ busy = true;
+ hasOutput = false;
+ outputExn = null;
+ this.handler = handler;
+
+ proverStart = DateTime.Now;
+ thmProver.BeginCheck(descriptiveName, vc, handler);
+ // gen.ClearSharedFormulas(); PR: don't know yet what to do with this guy
+
+ ThreadPool.QueueUserWorkItem(WaitForOutput);
+ }
+
+ public ProverInterface.Outcome ReadOutcome()
+ throws UnexpectedProverOutputException;
+ requires IsBusy;
+ requires HasOutput;
+ {
+ hasOutput = false;
+ busy = false;
+
+ if (outputExn != null) {
+ throw outputExn;
+ }
+
+ return outcome;
+ }
+ }
+
+ // -----------------------------------------------------------------------------------------------
+ // -----------------------------------------------------------------------------------------------
+ // -----------------------------------------------------------------------------------------------
+
+ public class ErrorModel {
+ public Dictionary<string!, int>! identifierToPartition;
+ public List<List<string!>>! partitionToIdentifiers;
+ public List<Object>! partitionToValue;
+ public Dictionary<object, int>! valueToPartition;
+ public Dictionary<string!, List<List<int>>!>! definedFunctions;
+
+ public ErrorModel(Dictionary<string!, int>! identifierToPartition, List<List<string!>>! partitionToIdentifiers, List<Object>! partitionToValue, Dictionary<object, int>! valueToPartition, Dictionary<string!, List<List<int>>!>! definedFunctions) {
+ this.identifierToPartition = identifierToPartition;
+ this.partitionToIdentifiers = partitionToIdentifiers;
+ this.partitionToValue = partitionToValue;
+ this.valueToPartition = valueToPartition;
+ this.definedFunctions = definedFunctions;
+ }
+
+ public virtual void Print(TextWriter! writer) { }
+ }
+
+ public abstract class ProverInterface
+ {
+ public enum Outcome { Valid, Invalid, TimeOut, OutOfMemory, Undetermined }
+
+ public class ErrorHandler
+ {
+ public virtual void OnModel(IList<string!>! labels, ErrorModel errModel)
+ {
+ }
+
+ public virtual void OnResourceExceeded(string! message)
+ {
+ }
+
+ public virtual Absy! Label2Absy(string! label)
+ {
+ throw new System.NotImplementedException();
+ }
+ }
+
+ public abstract void BeginCheck(string! descriptiveName, VCExpr! vc, ErrorHandler! handler);
+ [NoDefaultContract]
+ public abstract Outcome CheckOutcome(ErrorHandler! handler);
+ throws UnexpectedProverOutputException;
+
+ public virtual void LogComment(string! comment) {
+ }
+
+ public virtual void Close() {
+ }
+
+ /// <summary>
+ /// MSchaef: Allows to Push a VCExpression as Axiom on the prover stack (beta)
+ /// for now it is only implemented by ProcessTheoremProver and still requires some
+ /// testing
+ /// </summary>
+ public virtual void PushVCExpression(VCExpr! vc) {}
+
+ public abstract ProverContext! Context { get; }
+ public abstract VCExpressionGenerator! VCExprGen { get; }
+ }
+
+ public class ProverException : Exception
+ {
+ public ProverException(string s) : base(s)
+ {
+ }
+ }
+ public class UnexpectedProverOutputException : ProverException, ICheckedException
+ {
+ public UnexpectedProverOutputException(string s) : base(s)
+ {
+ }
+ }
+ public class ProverDiedException : UnexpectedProverOutputException
+ {
+ public ProverDiedException() : base("Prover died with no further output, perhaps it ran out of memory or was killed.")
+ {
+ }
+ }
+}
diff --git a/Source/VCGeneration/ConditionGeneration.ssc b/Source/VCGeneration/ConditionGeneration.ssc
new file mode 100644
index 00000000..2129b1fb
--- /dev/null
+++ b/Source/VCGeneration/ConditionGeneration.ssc
@@ -0,0 +1,790 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Threading;
+using System.IO;
+using Microsoft.Boogie;
+using Graphing;
+using AI = Microsoft.AbstractInterpretationFramework;
+using Microsoft.Contracts;
+using Microsoft.Basetypes;
+using Microsoft.Boogie.VCExprAST;
+
+namespace Microsoft.Boogie
+{
+ public abstract class Counterexample
+ {
+ [Peer] public BlockSeq! Trace;
+ [Peer] public List<string!>! relatedInformation;
+
+ internal Counterexample(BlockSeq! trace)
+ {
+ this.Trace = trace;
+ this.relatedInformation = new List<string!>();
+ // base();
+ }
+
+ public abstract int GetLocation();
+ }
+
+ public class CounterexampleComparer : IComparer<Counterexample!>
+ {
+ public int Compare(Counterexample! c1, Counterexample! c2) {
+ if (c1.GetLocation() == c2.GetLocation()) return 0;
+ if (c1.GetLocation() > c2.GetLocation()) return 1;
+ return -1;
+ }
+ }
+
+ public class AssertCounterexample : Counterexample
+ {
+ [Peer] public AssertCmd! FailingAssert;
+
+ public AssertCounterexample(BlockSeq! trace, AssertCmd! failingAssert)
+ : base(trace)
+ {
+ this.FailingAssert = failingAssert;
+ // base(trace);
+ }
+
+ public override int GetLocation() {
+ return FailingAssert.tok.line * 1000 + FailingAssert.tok.col;
+ }
+ }
+
+ public class CallCounterexample : Counterexample
+ {
+ public CallCmd! FailingCall;
+ public Requires! FailingRequires;
+
+ public CallCounterexample(BlockSeq! trace, CallCmd! failingCall, Requires! failingRequires)
+ : base(trace)
+ requires !failingRequires.Free;
+ {
+ this.FailingCall = failingCall;
+ this.FailingRequires = failingRequires;
+ // base(trace);
+ }
+
+ public override int GetLocation() {
+ return FailingCall.tok.line * 1000 + FailingCall.tok.col;
+ }
+ }
+
+ public class ReturnCounterexample : Counterexample
+ {
+ public TransferCmd! FailingReturn;
+ public Ensures! FailingEnsures;
+
+ public ReturnCounterexample(BlockSeq! trace, TransferCmd! failingReturn, Ensures! failingEnsures)
+ : base(trace)
+ requires !failingEnsures.Free;
+ {
+ this.FailingReturn = failingReturn;
+ this.FailingEnsures = failingEnsures;
+ // base(trace);
+ }
+
+ public override int GetLocation() {
+ return FailingReturn.tok.line * 1000 + FailingReturn.tok.col;
+ }
+ }
+
+ public class VerifierCallback
+ {
+ // reason == null means this is genuine counterexample returned by the prover
+ // other reason means it's time out/memory out/crash
+ public virtual void OnCounterexample(Counterexample! ce, string? reason)
+ {
+ }
+
+ // called in case resource is exceeded and we don't have counterexample
+ public virtual void OnTimeout(string! reason)
+ {
+ }
+
+ public virtual void OnOutOfMemory(string! reason)
+ {
+ }
+
+ public virtual void OnProgress(string phase, int step, int totalSteps, double progressEstimate)
+ {
+ }
+
+ public virtual void OnUnreachableCode(Implementation! impl)
+ {
+ }
+ }
+}
+
+////////////////////////////////////////////
+
+namespace VC
+{
+ using Bpl = Microsoft.Boogie;
+
+ public class VCGenException : Exception
+ {
+ public VCGenException(string s) : base(s)
+ {
+ }
+ }
+
+ public abstract class ConditionGeneration
+ {
+ protected internal object CheckerCommonState;
+
+ public enum Outcome { Correct, Errors, TimedOut, OutOfMemory, Inconclusive }
+
+ protected readonly List<Checker!>! provers = new List<Checker!>();
+ protected Implementation current_impl = null;
+
+
+ // shared across each implementation; created anew for each implementation
+ protected Hashtable /*Variable -> int*/ variable2SequenceNumber;
+ public Dictionary<Incarnation, Absy!>! incarnationOriginMap = new Dictionary<Incarnation, Absy!>();
+
+ // used only by FindCheckerFor
+ protected Program! program;
+ protected string/*?*/ logFilePath;
+ protected bool appendLogFile;
+
+ public ConditionGeneration(Program! p)
+ {
+ program = p;
+ }
+
+ /// <summary>
+ /// Takes an implementation and constructs a verification condition and sends
+ /// it to the theorem prover.
+ /// Returns null if "impl" is correct. Otherwise, returns a list of counterexamples,
+ /// each counterexample consisting of an array of labels.
+ /// </summary>
+ /// <param name="impl"></param>
+ public Outcome VerifyImplementation(Implementation! impl, Program! program, out List<Counterexample!>? errors)
+ ensures result == Outcome.Errors ==> errors != null;
+ throws UnexpectedProverOutputException;
+ {
+ Helpers.ExtraTraceInformation("Starting implementation verification");
+
+ CounterexampleCollector collector = new CounterexampleCollector();
+ Outcome outcome = VerifyImplementation(impl, program, collector);
+ if (outcome == Outcome.Errors) {
+ errors = collector.examples;
+ } else {
+ errors = null;
+ }
+
+ Helpers.ExtraTraceInformation("Finished implementation verification");
+ return outcome;
+ }
+
+ public abstract Outcome VerifyImplementation(Implementation! impl, Program! program, VerifierCallback! callback)
+ throws UnexpectedProverOutputException;
+
+
+/////////////////////////////////// Common Methods and Classes //////////////////////////////////////////
+
+ protected Checker! FindCheckerFor(Implementation! impl, int timeout)
+ {
+ int i = 0;
+ while (i < provers.Count) {
+ if (provers[i].Closed) {
+ provers.RemoveAt(i);
+ continue;
+ } else {
+ if (!provers[i].IsBusy && provers[i].WillingToHandle(impl, timeout)) return provers[i];
+ }
+ ++i;
+ }
+ string? log = logFilePath;
+ if (log != null && !log.Contains("@PROC@") && provers.Count > 0)
+ log = log + "." + provers.Count;
+ Checker! ch = new Checker(this, program, log, appendLogFile, impl, timeout);
+ provers.Add(ch);
+ return ch;
+ }
+
+
+ public void Close() { foreach (Checker! prover in provers) prover.Close(); }
+
+
+ protected class CounterexampleCollector : VerifierCallback
+ {
+ public readonly List<Counterexample!>! examples = new List<Counterexample!>();
+ public override void OnCounterexample(Counterexample! ce, string? reason)
+ {
+ examples.Add(ce);
+ }
+
+ public override void OnUnreachableCode(Implementation! impl)
+ {
+ System.Console.WriteLine("found unreachable code:");
+ EmitImpl(impl, false);
+ // TODO report error about next to last in seq
+ }
+ }
+
+ protected static void EmitImpl(Implementation! impl, bool printDesugarings) {
+ int oldPrintUnstructured = CommandLineOptions.Clo.PrintUnstructured;
+ CommandLineOptions.Clo.PrintUnstructured = 2; // print only the unstructured program
+ bool oldPrintDesugaringSetting = CommandLineOptions.Clo.PrintDesugarings;
+ CommandLineOptions.Clo.PrintDesugarings = printDesugarings;
+ impl.Emit(new TokenTextWriter("<console>", Console.Out, false), 0);
+ CommandLineOptions.Clo.PrintDesugarings = oldPrintDesugaringSetting;
+ CommandLineOptions.Clo.PrintUnstructured = oldPrintUnstructured;
+ }
+
+
+ protected Block! GenerateUnifiedExit(Implementation! impl, Hashtable! gotoCmdOrigins)
+ {
+ Block/*?*/ exitBlock = null;
+ #region Create a unified exit block, if there's more than one
+ {
+ int returnBlocks = 0;
+ foreach ( Block b in impl.Blocks )
+ {
+ if ( b.TransferCmd is ReturnCmd )
+ {
+ exitBlock = b;
+ returnBlocks++;
+ }
+ }
+ if ( returnBlocks > 1 )
+ {
+ string unifiedExitLabel = "GeneratedUnifiedExit";
+ Block! unifiedExit = new Block(new Token(-17, -4),unifiedExitLabel,new CmdSeq(),new ReturnCmd(Token.NoToken));
+
+ foreach ( Block b in impl.Blocks )
+ {
+ if ( b.TransferCmd is ReturnCmd )
+ {
+ StringSeq labels = new StringSeq();
+ labels.Add(unifiedExitLabel);
+ BlockSeq bs = new BlockSeq();
+ bs.Add(unifiedExit);
+ GotoCmd go = new GotoCmd(Token.NoToken,labels,bs);
+ gotoCmdOrigins[go] = b.TransferCmd;
+ b.TransferCmd = go;
+ unifiedExit.Predecessors.Add(b);
+ }
+ }
+
+ exitBlock = unifiedExit;
+ impl.Blocks.Add(unifiedExit);
+ }
+ assert exitBlock != null;
+ }
+ return exitBlock;
+ #endregion
+ }
+
+ /// <summary>
+ /// Helperfunction to restore the predecessor relations after loop unrolling
+ /// </summary>
+ protected void ComputePredecessors(List<Block!>! blocks)
+ {
+ #region Compute and store the Predecessor Relation on the blocks
+ // This code just here to try things out.
+ // Compute the predecessor relation for each block
+ // Store it in the Predecessors field within each block
+ foreach (Block b in blocks)
+ {
+ GotoCmd gtc = b.TransferCmd as GotoCmd;
+ if (gtc != null)
+ {
+ assume gtc.labelTargets != null;
+ foreach (Block! dest in gtc.labelTargets)
+ {
+ dest.Predecessors.Add(b);
+ }
+ }
+ }
+ #endregion Compute and store the Predecessor Relation on the blocks
+ }
+
+ protected static void ResetPredecessors(List<Block!>! blocks)
+ {
+ foreach (Block! b in blocks) {
+ b.Predecessors = new BlockSeq();
+ }
+ foreach (Block! b in blocks) {
+ foreach (Block! ch in Exits(b)) {
+ ch.Predecessors.Add(b);
+ }
+ }
+ }
+
+ protected static IEnumerable! Exits(Block! b)
+ {
+ GotoCmd g = b.TransferCmd as GotoCmd;
+ if (g != null) {
+ return (!)g.labelTargets;
+ }
+ return new List<Block!>();
+ }
+
+
+ protected Variable! CreateIncarnation(Variable! x, Absy a)
+ requires this.variable2SequenceNumber != null;
+ requires this.current_impl != null;
+ requires a is Block || a is AssignCmd || a is HavocCmd;
+ {
+ int currentIncarnationNumber =
+ variable2SequenceNumber.ContainsKey(x)
+ ?
+ (int) ((!)variable2SequenceNumber[x])
+ :
+ -1;
+ Variable v = new Incarnation(x,currentIncarnationNumber + 1);
+ variable2SequenceNumber[x] = currentIncarnationNumber + 1;
+ Debug.Assert(current_impl != null, "The field current_impl wasn't set.");
+ current_impl.LocVars.Add(v);
+ incarnationOriginMap.Add((Incarnation) v, a);
+ return v;
+ }
+
+ /// <summary>
+ /// Compute the incarnation map at the beginning of block "b" from the incarnation blocks of the
+ /// predecessors of "b".
+ ///
+ /// The predecessor map b.map for block "b" is defined as follows:
+ /// b.map.Domain == Union{Block p in b.predecessors; p.map.Domain}
+ /// Forall{Variable v in b.map.Domain;
+ /// b.map[v] == (v in Intersection{Block p in b.predecessors; p.map}.Domain
+ /// ? b.predecessors[0].map[v]
+ /// : new Variable())}
+ /// Every variable that b.map maps to a fresh variable requires a fixup in all predecessor blocks.
+ /// </summary>
+ /// <param name="b"></param>
+ /// <param name="block2Incarnation">Gives incarnation maps for b's predecessors.</param>
+ /// <returns></returns>
+ protected Hashtable! /*Variable -> Expr*/ ComputeIncarnationMap(Block! b, Hashtable! /*Variable -> Expr*/ block2Incarnation)
+ {
+ if (b.Predecessors.Length == 0)
+ {
+ return new Hashtable /*Variable -> Expr*/ ();
+ }
+
+ Hashtable /*Variable -> Expr*/ incarnationMap = null;
+ Set /*Variable*/ fixUps = new Set /*Variable*/ ();
+ foreach (Block! pred in b.Predecessors)
+ {
+ Debug.Assert(block2Incarnation.Contains(pred), "Passive Transformation found a block whose predecessors have not been processed yet.");
+ Hashtable /*Variable -> Expr*/ predMap = (Hashtable! /*Variable -> Expr*/) block2Incarnation[pred];
+ if (incarnationMap == null)
+ {
+ incarnationMap = (Hashtable /*Variable -> Expr*/)predMap.Clone();
+ continue;
+ }
+
+ ArrayList /*Variable*/ conflicts = new ArrayList /*Variable*/ ();
+ foreach (Variable! v in incarnationMap.Keys)
+ {
+ if (!predMap.Contains(v))
+ {
+ // conflict!!
+ conflicts.Add(v);
+ fixUps.Add(v);
+ }
+ }
+ // Now that we're done with enumeration, we'll do all the removes
+ foreach (Variable! v in conflicts)
+ {
+ incarnationMap.Remove(v);
+ }
+ foreach (Variable! v in predMap.Keys)
+ {
+ if (!incarnationMap.Contains(v))
+ {
+ // v was not in the domain of the precessors seen so far, so it needs to be fixed up
+ fixUps.Add(v);
+ }
+ else
+ {
+ // v in incarnationMap ==> all pred blocks (up to now) all agree on its incarnation
+ if (predMap[v] != incarnationMap[v])
+ {
+ // conflict!!
+ incarnationMap.Remove(v);
+ fixUps.Add(v);
+ }
+ }
+ }
+ }
+
+ #region Second, for all variables in the fixups list, introduce a new incarnation and push it back into the preds.
+ foreach (Variable! v in fixUps )
+ {
+ Variable v_prime = CreateIncarnation(v, b);
+ IdentifierExpr ie = new IdentifierExpr(v_prime.tok, v_prime);
+ assert incarnationMap != null;
+ incarnationMap[v] = ie;
+ foreach (Block! pred in b.Predecessors )
+ {
+ #region Create an assume command equating v_prime with its last incarnation in pred
+ #region Create an identifier expression for the last incarnation in pred
+ Hashtable /*Variable -> Expr*/ predMap = (Hashtable! /*Variable -> Expr*/) block2Incarnation[pred];
+ Expr pred_incarnation_exp;
+ Expr o = (Expr) predMap[v];
+ if (o == null)
+ {
+ Variable predIncarnation = v;
+ IdentifierExpr ie2 = new IdentifierExpr(predIncarnation.tok, predIncarnation);
+ pred_incarnation_exp = ie2;
+ }
+ else
+ {
+ pred_incarnation_exp = o;
+ }
+ #endregion
+ #region Create an identifier expression for the new incarnation
+ IdentifierExpr v_prime_exp = new IdentifierExpr(v_prime.tok, v_prime);
+ #endregion
+ #region Create the assume command itself
+ Expr e = Expr.Binary(Token.NoToken,
+ BinaryOperator.Opcode.Eq,
+ v_prime_exp,
+ pred_incarnation_exp
+ );
+ AssumeCmd ac = new AssumeCmd(v.tok,e);
+ pred.Cmds.Add(ac);
+ #endregion
+ #endregion
+ }
+ }
+ #endregion
+
+ assert incarnationMap != null;
+ return incarnationMap;
+ }
+
+ Hashtable preHavocIncarnationMap = null; // null = the previous command was not an HashCmd. Otherwise, a *copy* of the map before the havoc statement
+
+ protected void TurnIntoPassiveBlock(Block! b, Hashtable! /*Variable -> Expr*/ incarnationMap, Substitution! oldFrameSubst)
+ {
+ #region Walk forward over the commands in this block and convert them to passive commands
+
+ CmdSeq passiveCmds = new CmdSeq();
+ foreach (Cmd! c in b.Cmds)
+ { // walk forward over the commands because the map gets modified in a forward direction
+ TurnIntoPassiveCmd(c, incarnationMap, oldFrameSubst, passiveCmds);
+ }
+ b.Cmds = passiveCmds;
+
+ #endregion
+ }
+
+
+ protected void Convert2PassiveCmd(Implementation! impl)
+ {
+ #region Convert to Passive Commands
+
+ #region Topological sort -- need to process in a linearization of the partial order
+ Graph<Block> dag = new Graph<Block>();
+ dag.AddSource((!)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;
+ if (gtc != null)
+ {
+ assume gtc.labelTargets != null;
+ foreach (Block! dest in gtc.labelTargets)
+ {
+ dag.AddEdge(b,dest);
+ }
+ }
+ }
+ IEnumerable! sortedNodes = dag.TopologicalSort();
+ //Debug.Assert( sortedNodes != null, "Topological Sort returned null." );
+ #endregion
+
+ // Create substitution for old expressions
+ Hashtable/*Variable!->Expr!*/ oldFrameMap = new Hashtable();
+ assume impl.Proc != null;
+ foreach (IdentifierExpr! ie in impl.Proc.Modifies) {
+ oldFrameMap.Add((!)ie.Decl, ie);
+ }
+ Substitution oldFrameSubst = Substituter.SubstitutionFromHashtable(oldFrameMap);
+
+ // Now we can process the nodes in an order so that we're guaranteed to have
+ // processed all of a node's predecessors before we process the node.
+ Hashtable /*Block -> IncarnationMap*/ block2Incarnation = new Hashtable/*Block -> IncarnationMap*/();
+ foreach (Block! b in sortedNodes )
+ {
+ Debug.Assert( !block2Incarnation.Contains(b) );
+ Hashtable /*Variable -> Expr*/ incarnationMap = ComputeIncarnationMap(b, block2Incarnation);
+
+ #region Each block's map needs to be available to successor blocks
+ block2Incarnation.Add(b,incarnationMap);
+ #endregion Each block's map needs to be available to successor blocks
+
+ TurnIntoPassiveBlock(b, incarnationMap, oldFrameSubst);
+ }
+
+ // We no longer need the where clauses on the out parameters, so we remove them to restore the situation from before VC generation
+ foreach (Formal! f in impl.OutParams) {
+ f.TypedIdent.WhereExpr = null;
+ }
+ #endregion Convert to Passive Commands
+
+ #region Debug Tracing
+ if (CommandLineOptions.Clo.TraceVerify)
+ {
+ Console.WriteLine("after conversion to passive commands");
+ EmitImpl(impl, true);
+ }
+ #endregion
+ }
+
+ /// <summary>
+ /// Turn a command into a passive command, and it remembers the previous step, to see if it is a havoc or not. In the case, it remebers the incarnation map BEFORE the havoc
+ /// </summary>
+ protected void TurnIntoPassiveCmd(Cmd! c, Hashtable /*Variable -> Expr*/! incarnationMap, Substitution! oldFrameSubst, CmdSeq! passiveCmds)
+ {
+ Substitution incarnationSubst = Substituter.SubstitutionFromHashtable(incarnationMap);
+ #region assert/assume P |--> assert/assume P[x := in(x)], out := in
+ if ( c is PredicateCmd )
+ {
+ Debug.Assert( c is AssertCmd || c is AssumeCmd, "Internal Error: Found a PredicateCmd h is not an assert or an assume." );
+
+ PredicateCmd! pc = (PredicateCmd) c.Clone();
+
+ if(pc is AssumeCmd && pc.Expr is LoopPredicate // Check if the PredicateCmd is in the form of "assume J", with J loop invariant predicate
+ && this.preHavocIncarnationMap != null) // Furthermore, the command just before was a (list of) havoc statements
+ {
+ LoopPredicate! lp = (LoopPredicate!) pc.Expr;
+ lp.SetPreAndPostHavocIncarnationMaps(this.preHavocIncarnationMap, (Hashtable /*Variable -> Expr*/!) incarnationMap.Clone());
+ }
+
+ Expr! copy = Substituter.ApplyReplacingOldExprs(incarnationSubst, oldFrameSubst, pc.Expr);
+ if (pc is AssertCmd) {
+ ((AssertCmd) pc).OrigExpr = pc.Expr;
+ assert ((AssertCmd) pc).IncarnationMap == null;
+ ((AssertCmd) pc).IncarnationMap = (Hashtable /*Variable -> Expr*/!) incarnationMap.Clone();
+ }
+ pc.Expr = copy;
+ passiveCmds.Add(pc);
+ }
+ #endregion
+ #region x1 := E1, x2 := E2, ... |--> assume x1' = E1[in] & x2' = E2[in], out := in( x |-> x' ) [except as noted below]
+ else if ( c is AssignCmd )
+ {
+ AssignCmd! assign = ((AssignCmd)c).AsSimpleAssignCmd; // first remove map assignments
+ #region Substitute all variables in E with the current map
+ List<Expr!>! copies = new List<Expr!> ();
+ foreach (Expr! e in assign.Rhss)
+ copies.Add(Substituter.ApplyReplacingOldExprs(incarnationSubst,
+ oldFrameSubst,
+ e));
+ #endregion
+
+ List<Expr!>! assumptions = new List<Expr!> ();
+ // it might be too slow to create a new dictionary each time ...
+ IDictionary<Variable!, Expr!>! newIncarnationMappings =
+ new Dictionary<Variable!, Expr!> ();
+
+ for (int i = 0; i < assign.Lhss.Count; ++i) {
+ IdentifierExpr! lhsIdExpr =
+ ((SimpleAssignLhs!)assign.Lhss[i]).AssignedVariable;
+ Variable! lhs = (!)lhsIdExpr.Decl;
+ Expr! rhs = assign.Rhss[i];
+
+ // don't create incarnations for assignments of literals or single variables.
+ if (rhs is LiteralExpr) {
+ incarnationMap[lhs] = rhs;
+ } else if (rhs is IdentifierExpr) {
+ IdentifierExpr! ie = (IdentifierExpr) rhs;
+ if ( incarnationMap.ContainsKey((!)ie.Decl) )
+ newIncarnationMappings[lhs] = (Expr!)incarnationMap[ie.Decl];
+ else
+ newIncarnationMappings[lhs] = ie;
+ } else {
+ IdentifierExpr x_prime_exp = null;
+ #region Make a new incarnation, x', for variable x, but only if x is *not* already an incarnation
+ if ( lhs is Incarnation ) {
+ // incarnations are already written only once, no need to make an incarnation of an incarnation
+ x_prime_exp = lhsIdExpr;
+ }
+ else
+ {
+ Variable v = CreateIncarnation(lhs, c);
+ x_prime_exp = new IdentifierExpr(lhsIdExpr.tok, v);
+ newIncarnationMappings[lhs] = x_prime_exp;
+ }
+ #endregion
+ #region Create an assume command with the new variable
+ assumptions.Add(Expr.Eq(x_prime_exp, copies[i]));
+ #endregion
+ }
+ }
+
+ foreach (KeyValuePair<Variable!, Expr!> pair in newIncarnationMappings)
+ incarnationMap[pair.Key] = pair.Value;
+
+ if (assumptions.Count > 0) {
+ Expr! assumption = assumptions[0];
+ for (int i = 1; i < assumptions.Count; ++i)
+ assumption = Expr.And(assumption, assumptions[i]);
+ passiveCmds.Add(new AssumeCmd(c.tok, assumption));
+ }
+ }
+ #endregion
+ #region havoc w |--> assume whereClauses, out := in( w |-> w' )
+ else if ( c is HavocCmd )
+ {
+ if(this.preHavocIncarnationMap == null) // Save a copy of the incarnation map (at the top of a sequence of havoc statements)
+ this.preHavocIncarnationMap = (Hashtable) incarnationMap.Clone();
+
+ HavocCmd! hc = (HavocCmd) c;
+ IdentifierExprSeq havocVars = hc.Vars;
+ // First, compute the new incarnations
+ foreach (IdentifierExpr! ie in havocVars)
+ {
+ if ( !(ie.Decl is Incarnation) )
+ {
+ Variable x = (!)ie.Decl;
+ Variable x_prime = CreateIncarnation(x, c);
+ incarnationMap[x] = new IdentifierExpr(x_prime.tok, x_prime);
+ }
+ }
+ // Then, perform the assume of the where clauses, using the updated incarnations
+ Substitution updatedIncarnationSubst = Substituter.SubstitutionFromHashtable(incarnationMap);
+ foreach (IdentifierExpr! ie in havocVars)
+ {
+ if ( !(ie.Decl is Incarnation) )
+ {
+ Variable x = (!)ie.Decl;
+ Bpl.Expr w = x.TypedIdent.WhereExpr;
+ if (w != null) {
+ Expr copy = Substituter.ApplyReplacingOldExprs(updatedIncarnationSubst, oldFrameSubst, w);
+ passiveCmds.Add(new AssumeCmd(c.tok, copy));
+ }
+ }
+ }
+ }
+ #endregion
+ else if (c is CommentCmd)
+ {
+ // comments are just for debugging and don't affect verification
+ }
+ else if (c is SugaredCmd)
+ {
+ SugaredCmd! sug = (SugaredCmd)c;
+ Cmd! cmd = sug.Desugaring;
+ TurnIntoPassiveCmd(cmd, incarnationMap, oldFrameSubst, passiveCmds);
+ }
+ else if (c is StateCmd)
+ {
+ this.preHavocIncarnationMap = null; // we do not need to remeber the previous incarnations
+ StateCmd! st = (StateCmd)c;
+ // account for any where clauses among the local variables
+ foreach (Variable! v in st.Locals) {
+ Expr w = v.TypedIdent.WhereExpr;
+ if (w != null) {
+ passiveCmds.Add(new AssumeCmd(v.tok, w));
+ }
+ }
+ // do the sub-commands
+ foreach (Cmd! s in st.Cmds) {
+ TurnIntoPassiveCmd(s, incarnationMap, oldFrameSubst, passiveCmds);
+ }
+ // remove the local variables from the incarnation map
+ foreach (Variable! v in st.Locals) {
+ incarnationMap.Remove(v);
+ }
+ }
+ #region There shouldn't be any other types of commands at this point
+ else
+ {
+ Debug.Fail("Internal Error: Passive transformation handed a command that is not one of assert,assume,havoc,assign." );
+ }
+ #endregion
+
+
+ #region We rember if we have put an havoc statement into a passive form
+
+ if(! (c is HavocCmd) )
+ this.preHavocIncarnationMap = null;
+ // else: it has already been set by the case for the HavocCmd
+ #endregion
+ }
+
+ /// <summary>
+ /// Creates a new block to add to impl.Blocks, where impl is the implementation that contains
+ /// succ. Caller must do the add to impl.Blocks.
+ /// </summary>
+ protected Block! CreateBlockBetween(int predIndex, Block! succ)
+ requires 0 <= predIndex && predIndex < succ.Predecessors.Length;
+ {
+ Block! pred = (!) succ.Predecessors[predIndex];
+
+ string! newBlockLabel = pred.Label + "_@2_" + succ.Label;
+
+ // successor of newBlock list
+ StringSeq ls = new StringSeq();
+ ls.Add(succ.Label);
+ BlockSeq bs = new BlockSeq();
+ bs.Add(succ);
+
+ Block newBlock = new Block(
+ new Token(-17, -4),
+ newBlockLabel,
+ new CmdSeq(),
+ new GotoCmd(Token.NoToken,ls,bs)
+ );
+
+ // predecessors of newBlock
+ BlockSeq ps = new BlockSeq();
+ ps.Add(pred);
+ newBlock.Predecessors = ps;
+
+ // fix successors of pred
+ #region Change the edge "pred->succ" to "pred->newBlock"
+ GotoCmd gtc = (GotoCmd!) pred.TransferCmd;
+ assume gtc.labelTargets != null;
+ assume gtc.labelNames != null;
+ for ( int i = 0, n = gtc.labelTargets.Length; i < n; i++ )
+ {
+ if ( gtc.labelTargets[i] == succ )
+ {
+ gtc.labelTargets[i] = newBlock;
+ gtc.labelNames[i] = newBlockLabel;
+ break;
+ }
+ }
+ #endregion Change the edge "pred->succ" to "pred->newBlock"
+
+ // fix predecessors of succ
+ succ.Predecessors[predIndex] = newBlock;
+
+ return newBlock;
+ }
+
+ protected void AddBlocksBetween(Implementation! impl)
+ {
+ #region Introduce empty blocks before all blocks with more than one predecessor
+ List<Block!> tweens = new List<Block!>();
+ foreach ( Block b in impl.Blocks )
+ {
+ int nPreds = b.Predecessors.Length;
+ if ( nPreds > 1 )
+ {
+ for (int i = 0; i < nPreds; i++ )
+ {
+ tweens.Add(CreateBlockBetween(i, b));
+ }
+ }
+ }
+ impl.Blocks.AddRange(tweens); // must wait until iteration is done before changing the list
+ #endregion
+ }
+
+ }
+} \ No newline at end of file
diff --git a/Source/VCGeneration/Context.ssc b/Source/VCGeneration/Context.ssc
new file mode 100644
index 00000000..be32cabe
--- /dev/null
+++ b/Source/VCGeneration/Context.ssc
@@ -0,0 +1,199 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+using Microsoft.Contracts;
+using Microsoft.Boogie.VCExprAST;
+
+namespace Microsoft.Boogie
+{
+ /// <summary>
+ /// The methods of this class are called in the following order:
+ /// DeclareType*
+ /// (DeclareConstant DeclareFunction)*
+ /// AddAxiom*
+ /// DeclareGlobalVariable*
+ /// At this time, all "attributes" are passed in as null.
+ /// </summary>
+ public abstract class ProverContext : ICloneable {
+ protected virtual void ProcessDeclaration(Declaration! decl) {}
+ public virtual void DeclareType(TypeCtorDecl! t, string attributes) { ProcessDeclaration(t); }
+ public virtual void DeclareConstant(Constant! c, bool uniq, string attributes) { ProcessDeclaration(c); }
+ public virtual void DeclareFunction(Function! f, string attributes) { ProcessDeclaration(f); }
+ public virtual void AddAxiom(Axiom! a, string attributes) { ProcessDeclaration(a); }
+ public abstract void AddAxiom(VCExpr! vc);
+ public virtual void DeclareGlobalVariable(GlobalVariable! v, string attributes) { ProcessDeclaration(v); }
+
+ public abstract VCExpressionGenerator! ExprGen { get; }
+ public abstract Boogie2VCExprTranslator! BoogieExprTranslator { get; }
+ public abstract VCGenerationOptions! VCGenOptions { get; }
+
+ public abstract object! Clone();
+ }
+
+ // -----------------------------------------------------------------------------------------------
+ // -----------------------------------------------------------------------------------------------
+ // -----------------------------------------------------------------------------------------------
+
+ /// <summary>
+ /// This ProverContext subclass is intended for use with untyped provers that do not require names
+ /// to be declared before use. It constructs its context from unique constants and given axioms.
+ /// </summary>
+ public class DeclFreeProverContext : ProverContext {
+ protected VCExpressionGenerator! gen;
+ protected VCGenerationOptions! genOptions;
+ protected Boogie2VCExprTranslator! translator;
+
+ protected OrderingAxiomBuilder! orderingAxiomBuilder;
+
+ StringBuilder! proverCommands;
+ StringBuilder! incrementalProverCommands;
+
+ protected List<Variable!>! distincts;
+ protected List<VCExpr!>! axiomConjuncts;
+
+ public VCExprTranslator exprTranslator;
+
+ public DeclFreeProverContext(VCExpressionGenerator! gen,
+ VCGenerationOptions! genOptions) {
+ this.gen = gen;
+ this.genOptions = genOptions;
+ Boogie2VCExprTranslator! t = new Boogie2VCExprTranslator (gen, genOptions);
+ this.translator = t;
+ OrderingAxiomBuilder! oab = new OrderingAxiomBuilder(gen, t);
+ oab.Setup();
+ this.orderingAxiomBuilder = oab;
+
+ proverCommands = new StringBuilder();
+ incrementalProverCommands = new StringBuilder();
+
+ distincts = new List<Variable!>();
+ axiomConjuncts = new List<VCExpr!>();
+
+ exprTranslator = null;
+ }
+
+ private DeclFreeProverContext(DeclFreeProverContext! ctxt) {
+ this.gen = ctxt.gen;
+ this.genOptions = ctxt.genOptions;
+ Boogie2VCExprTranslator! t = (Boogie2VCExprTranslator)ctxt.translator.Clone();
+ this.translator = t;
+ this.orderingAxiomBuilder = new OrderingAxiomBuilder(ctxt.gen, t, ctxt.orderingAxiomBuilder);
+
+ StringBuilder! cmds = new StringBuilder ();
+ cmds.Append(ctxt.proverCommands);
+ proverCommands = cmds;
+ StringBuilder! incCmds = new StringBuilder ();
+ incCmds.Append(ctxt.incrementalProverCommands);
+ incrementalProverCommands = incCmds;
+
+ distincts = new List<Variable!>(ctxt.distincts);
+ axiomConjuncts = new List<VCExpr!>(ctxt.axiomConjuncts);
+
+ if (ctxt.exprTranslator == null)
+ exprTranslator = null;
+ else
+ exprTranslator = (VCExprTranslator!)ctxt.exprTranslator.Clone();
+ }
+
+ public override object! Clone() {
+ return new DeclFreeProverContext(this);
+ }
+
+ internal protected void SayToProver(string! msg)
+ {
+ msg = msg + "\r\n";
+ proverCommands.Append(msg);
+ incrementalProverCommands.Append(msg);
+ }
+
+ protected override void ProcessDeclaration(Declaration! decl)
+ {
+ for (QKeyValue a = decl.Attributes; a != null; a = a.Next) {
+ if (a.Key == "prover" && a.Params.Count == 1) {
+ string cmd = a.Params[0] as string;
+ if (cmd != null) {
+ int pos = cmd.IndexOf(':');
+ if (pos <= 0)
+ throw new ProverException("Invalid syntax of :prover string: `" + cmd + "'");
+ string kind = cmd.Substring(0, pos);
+ if (genOptions.IsAnyProverCommandSupported(kind))
+ SayToProver(cmd.Substring(pos + 1));
+ }
+ }
+ }
+ }
+
+ public override void DeclareFunction(Function! f, string attributes) {
+ base.ProcessDeclaration(f);
+ }
+
+ public override void DeclareConstant(Constant! c, bool uniq, string attributes) {
+ base.DeclareConstant(c, uniq, attributes);
+ orderingAxiomBuilder.AddConstant(c);
+
+ // TODO: make separate distinct lists for names coming from different types
+ // e.g., one for strings, one for ints, one for program types.
+ if (uniq){
+ distincts.Add(c);
+ }
+ }
+
+ public override void AddAxiom(Axiom! ax, string attributes) {
+ base.AddAxiom(ax, attributes);
+
+ string ignore = ax.FindStringAttribute("ignore");
+ if (ignore != null && genOptions.IsAnyProverCommandSupported(ignore)) {
+ return;
+ }
+
+ axiomConjuncts.Add(translator.Translate(ax.Expr));
+ }
+
+ public override void AddAxiom(VCExpr! vc)
+ {
+ axiomConjuncts.Add(vc);
+ }
+
+ public VCExpr! Axioms {
+ get {
+ VCExpr axioms = gen.NAry(VCExpressionGenerator.AndOp, axiomConjuncts);
+ List<VCExpr!>! distinctVars = new List<VCExpr!> ();
+ foreach (Variable! v in distincts)
+ distinctVars.Add(translator.LookupVariable(v));
+ axioms = gen.AndSimp(gen.Distinct(distinctVars), axioms);
+ if (CommandLineOptions.Clo.TypeEncodingMethod != CommandLineOptions.TypeEncoding.Monomorphic)
+ axioms = gen.AndSimp(orderingAxiomBuilder.Axioms, axioms);
+ return axioms;
+ }
+ }
+
+ public string! GetProverCommands(bool full) {
+ string! res = (full ? proverCommands : incrementalProverCommands).ToString();
+ incrementalProverCommands.Length = 0;
+ return res;
+ }
+
+ public override VCExpressionGenerator! ExprGen { get {
+ return gen;
+ } }
+ public override Boogie2VCExprTranslator! BoogieExprTranslator { get {
+ return translator;
+ } }
+ public override VCGenerationOptions! VCGenOptions { get {
+ return genOptions;
+ } }
+ }
+
+ // Translator from VCExpressions to strings, which are implemented
+ // by the various provers
+ public abstract class VCExprTranslator : ICloneable {
+ public abstract string! translate(VCExpr! expr, int polarity);
+ public abstract Object! Clone();
+ }
+}
diff --git a/Source/VCGeneration/OrderingAxioms.ssc b/Source/VCGeneration/OrderingAxioms.ssc
new file mode 100644
index 00000000..e4fc54f8
--- /dev/null
+++ b/Source/VCGeneration/OrderingAxioms.ssc
@@ -0,0 +1,285 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+using Microsoft.Contracts;
+using Microsoft.Boogie.VCExprAST;
+
+// Class for constructing and collecting the axioms of the partial
+// order <:. The class also manages "unique" attributes of constants
+// and generated the necessary assumptions for the theorem prover.
+
+// TODO: there should be an interface so that different ways to handle
+// ordering relations can be accessed uniformly
+
+namespace Microsoft.Boogie
+{
+
+ public class OrderingAxiomBuilder {
+
+ private readonly VCExpressionGenerator! Gen;
+ private readonly Boogie2VCExprTranslator! Translator;
+
+ public OrderingAxiomBuilder(VCExpressionGenerator! gen,
+ Boogie2VCExprTranslator! translator) {
+ this.Gen = gen;
+ this.Translator = translator;
+ OneStepFuns = new Dictionary<Type!, Function!> ();
+ Constants = new List<Constant!> ();
+ CompleteConstantsOpen = new List<Constant!> ();
+ AllAxioms = new List<VCExpr!> ();
+ IncAxioms = new List<VCExpr!> ();
+ }
+
+ public OrderingAxiomBuilder(VCExpressionGenerator! gen,
+ Boogie2VCExprTranslator! translator,
+ OrderingAxiomBuilder! builder) {
+ this.Gen = gen;
+ this.Translator = translator;
+ OneStepFuns = new Dictionary<Type!, Function!> (builder.OneStepFuns);
+ Constants = new List<Constant!> (builder.Constants);
+ CompleteConstantsOpen = new List<Constant!> (builder.CompleteConstantsOpen);
+ AllAxioms = new List<VCExpr!> (builder.AllAxioms);
+ IncAxioms = new List<VCExpr!> (builder.IncAxioms);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ // Used to axiomatise the disjoint-sub-dag specs that are
+ // described by parents with the "unique" flag
+ private readonly IDictionary<Type!, Function!>! OneStepFuns;
+
+ private Function! OneStepFunFor(Type! t) {
+ Function res;
+ if (!OneStepFuns.TryGetValue(t, out res)) {
+ VariableSeq! args = new VariableSeq ();
+ args.Add(new Formal (Token.NoToken,
+ new TypedIdent (Token.NoToken, "arg0", t),
+ true));
+ args.Add(new Formal (Token.NoToken,
+ new TypedIdent (Token.NoToken, "arg1", t),
+ true));
+ Formal! result = new Formal (Token.NoToken,
+ new TypedIdent (Token.NoToken, "res", t),
+ false);
+ res = new Function (Token.NoToken, "oneStep",
+ new TypeVariableSeq (), args, result);
+ OneStepFuns.Add(t, res);
+ }
+ return (!)res;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ private readonly List<Constant!>! Constants = new List<Constant!> ();
+
+ // A list to handle constants whose direct children are fully
+ // specified (the "complete" keyword). Constants are removed from
+ // the list as soon as the corresponding axiom has been generated,
+ // which means that from this point on no further children can be
+ // added
+ private readonly List<Constant!>! CompleteConstantsOpen = new List<Constant!> ();
+
+ // list in which all axioms are collected
+ private readonly List<VCExpr!>! AllAxioms = new List<VCExpr!> ();
+
+ // list in which axioms are incrementally collected
+ private readonly List<VCExpr!>! IncAxioms = new List<VCExpr!> ();
+
+ private void AddAxiom(VCExpr! axiom) {
+ if (axiom.Equals(VCExpressionGenerator.True))
+ return;
+ AllAxioms.Add(axiom);
+ IncAxioms.Add(axiom);
+ }
+
+ // Return all axioms that were added since the last time NewAxioms
+ // was called
+ public VCExpr! GetNewAxioms() {
+ CloseChildrenCompleteConstants();
+ VCExpr! res = Gen.NAry(VCExpressionGenerator.AndOp, IncAxioms);
+ IncAxioms.Clear();
+ return res;
+ }
+
+ // return all axioms
+ public VCExpr! Axioms { get {
+ CloseChildrenCompleteConstants();
+ return Gen.NAry(VCExpressionGenerator.AndOp, AllAxioms);
+ } }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ // Generate the normal axioms for a partial order relation
+ public void Setup() {
+ TypeVariable! alpha = new TypeVariable(Token.NoToken, "alpha");
+ List<TypeVariable!>! typeParams = new List<TypeVariable!> ();
+ typeParams.Add(alpha);
+
+ List<VCTrigger!>! triggers = new List<VCTrigger!> ();
+
+ VCExprVar! x = Gen.Variable("x", alpha);
+ VCExprVar! y = Gen.Variable("y", alpha);
+ VCExprVar! z = Gen.Variable("z", alpha);
+
+ List<VCExprVar!>! boundVars = new List<VCExprVar!> ();
+
+ // reflexivity
+ boundVars.Add(x);
+ AddAxiom(Gen.Forall(typeParams, boundVars, triggers,
+ new VCQuantifierInfos ("bg:subtype-refl", -1, false, null),
+ Gen.AtMost(x, x)));
+
+ // transitivity
+ boundVars = new List<VCExprVar!> ();
+ boundVars.Add(x); boundVars.Add(y); boundVars.Add(z);
+ triggers = new List<VCTrigger!> ();
+ triggers.Add(Gen.Trigger(true, Gen.AtMost(x, y), Gen.AtMost(y, z)));
+ VCExpr! body = Gen.Implies(Gen.And(Gen.AtMost(x, y), Gen.AtMost(y, z)),
+ Gen.AtMost(x, z));
+ AddAxiom(Gen.Forall(typeParams, boundVars, triggers,
+ new VCQuantifierInfos ("bg:subtype-trans", -1, false, null),
+ body));
+
+ // anti-symmetry
+ boundVars = new List<VCExprVar!> ();
+ boundVars.Add(x); boundVars.Add(y);
+ triggers = new List<VCTrigger!> ();
+ triggers.Add(Gen.Trigger(true, Gen.AtMost(x, y), Gen.AtMost(y, x)));
+ body = Gen.Implies(Gen.And(Gen.AtMost(x, y), Gen.AtMost(y, x)),
+ Gen.Eq(x, y));
+ AddAxiom(Gen.Forall(typeParams, boundVars, triggers,
+ new VCQuantifierInfos ("bg:subtype-antisymm", -1, false, null),
+ body));
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ public void AddConstant(Constant! c) {
+ AddAxiom(GenParentConstraints(c));
+ Constants.Add(c);
+ if (c.ChildrenComplete)
+ CompleteConstantsOpen.Add(c);
+
+ // ensure that no further children are added to closed
+ // children-complete constants
+ assert !(c.Parents != null &&
+ exists{ConstantParent! p in c.Parents;
+ ((Constant!)p.Parent.Decl).ChildrenComplete &&
+ !CompleteConstantsOpen.Contains((Constant)p.Parent.Decl)});
+ }
+
+ // Generate the constraints telling that parents of a constant are
+ // strictly greater than the constant itself, and are the minimal
+ // elements with this property
+ private VCExpr! GenParentConstraints(Constant! c) {
+ VCExpr! res = VCExpressionGenerator.True;
+
+ if (c.Parents == null)
+ return res;
+
+ VCExprVar! cAsVar = Translator.LookupVariable(c);
+ VCExprVar! w = Gen.Variable("w", c.TypedIdent.Type);
+
+ // Parents of c are proper ancestors of c
+ foreach (ConstantParent! p in c.Parents) {
+ VCExprVar! par = Translator.LookupVariable((!)p.Parent.Decl);
+ res = Gen.AndSimp(res, Gen.Neq(cAsVar, par));
+ res = Gen.AndSimp(res, Gen.AtMost(cAsVar, par));
+ }
+
+ // Parents are direct ancestors of c (no other elements are in
+ // between c and a parent)
+ foreach (ConstantParent! p in c.Parents) {
+ VCExprVar! par = Translator.LookupVariable((!)p.Parent.Decl);
+ VCExpr! antecedent1 = Gen.AtMost(cAsVar, w);
+ VCExpr! antecedent2 = Gen.AtMost(w, par);
+ VCExpr! body = Gen.Implies(Gen.And(antecedent1, antecedent2),
+ Gen.Or(Gen.Eq(cAsVar, w), Gen.Eq(par, w)));
+ res = Gen.AndSimp(res,
+ Gen.Forall(w,
+ Gen.Trigger(true, antecedent1, antecedent2),
+ body));
+ }
+
+ // Ancestors of c are only c itself and the ancestors of the
+ // parents of c
+ VCExpr! minAncestors = Gen.Eq(cAsVar, w);
+ foreach (ConstantParent! p in c.Parents)
+ minAncestors =
+ Gen.Or(minAncestors,
+ Gen.AtMost(Translator.LookupVariable((!)p.Parent.Decl), w));
+
+ VCExpr! antecedent = Gen.AtMost(cAsVar, w);
+ res = Gen.AndSimp(res,
+ Gen.Forall(w,
+ Gen.Trigger(true, antecedent),
+ Gen.Implies(antecedent, minAncestors)));
+
+ // Constraints for unique child-parent edges
+ foreach (ConstantParent! p in c.Parents) {
+ if (p.Unique)
+ res =
+ Gen.AndSimp(res,
+ GenUniqueParentConstraint(c, (Constant!)p.Parent.Decl));
+ }
+
+ return res;
+ }
+
+ // Generate axioms that state that all direct children of c are
+ // specified; this is the dual of the axiom stating that all direct
+ // ancestors of a constant are known
+ private VCExpr! GenCompleteChildrenConstraints(Constant! c)
+ requires c.ChildrenComplete; {
+
+ VCExprVar! cAsVar = Translator.LookupVariable(c);
+ VCExprVar! w = Gen.Variable("w", c.TypedIdent.Type);
+
+ VCExpr! maxDescendants = Gen.Eq(cAsVar, w);
+ foreach (Constant! d in Constants) {
+ if (d.Parents != null &&
+ exists{ConstantParent! p in d.Parents; c.Equals(p.Parent.Decl)})
+ maxDescendants = Gen.Or(maxDescendants,
+ Gen.AtMost(w, Translator.LookupVariable(d)));
+ }
+
+ VCExpr! antecedent = Gen.AtMost(w, cAsVar);
+ return Gen.Forall(w,
+ Gen.Trigger(true, antecedent),
+ Gen.Implies(antecedent, maxDescendants));
+ }
+
+ private void CloseChildrenCompleteConstants() {
+ foreach (Constant! c in CompleteConstantsOpen)
+ AddAxiom(GenCompleteChildrenConstraints(c));
+ CompleteConstantsOpen.Clear();
+ }
+
+ // Generate the axiom ensuring that the sub-dags underneath unique
+ // child-parent edges are all disjoint
+ private VCExpr! GenUniqueParentConstraint(Constant! child, Constant! parent)
+ requires child.TypedIdent.Type.Equals(parent.TypedIdent.Type); {
+
+ VCExprVar! w = Gen.Variable("w", child.TypedIdent.Type);
+
+ VCExpr! antecedent =
+ Gen.AtMost(w, Translator.LookupVariable(child));
+ VCExpr! succedent =
+ Gen.Eq(Gen.Function(OneStepFunFor(child.TypedIdent.Type),
+ Translator.LookupVariable(parent), w),
+ Translator.LookupVariable(child));
+
+ return Gen.Forall(w,
+ Gen.Trigger(true, antecedent),
+ Gen.Implies(antecedent, succedent));
+ }
+
+ }
+
+}
diff --git a/Source/VCGeneration/VC.ssc b/Source/VCGeneration/VC.ssc
new file mode 100644
index 00000000..617e52e6
--- /dev/null
+++ b/Source/VCGeneration/VC.ssc
@@ -0,0 +1,3215 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Threading;
+using System.IO;
+using Microsoft.Boogie;
+using Graphing;
+using AI = Microsoft.AbstractInterpretationFramework;
+using Microsoft.Contracts;
+using Microsoft.Basetypes;
+using Microsoft.Boogie.VCExprAST;
+
+
+namespace VC
+{
+ using Bpl = Microsoft.Boogie;
+
+ public class VCGen : ConditionGeneration
+ {
+
+ /// <summary>
+ /// Constructor. Initializes the theorem prover.
+ /// </summary>
+ public VCGen(Program! program, string/*?*/ logFilePath, bool appendLogFile)
+ // throws ProverException
+ {
+ base(program);
+ this.appendLogFile = appendLogFile;
+ this.logFilePath = logFilePath;
+ // base();
+ }
+
+ private static AssumeCmd! AssertTurnedIntoAssume(AssertCmd! assrt)
+ {
+ Expr! expr = assrt.Expr;
+
+ switch (CommandLineOptions.Clo.UseSubsumption) {
+ case CommandLineOptions.SubsumptionOption.Never:
+ expr = Expr.True;
+ break;
+ case CommandLineOptions.SubsumptionOption.Always:
+ break;
+ case CommandLineOptions.SubsumptionOption.NotForQuantifiers:
+ if (expr is QuantifierExpr) {
+ expr = Expr.True;
+ }
+ break;
+ default:
+ assert false; // unexpected case
+ }
+
+ return new AssumeCmd(assrt.tok, expr);
+ }
+
+ /// <summary>
+ /// Get the where clauses from the in- and out-parameters as
+ /// a sequence of assume commands.
+ /// As a side effect, this method adds these where clauses to the out parameters.
+ /// </summary>
+ /// <param name="impl"></param>
+ private static CmdSeq! GetParamWhereClauses(Implementation! impl)
+ requires impl.Proc != null;
+ {
+ TokenTextWriter debugWriter = null;
+ if (CommandLineOptions.Clo.PrintWithUniqueASTIds) {
+ debugWriter = new TokenTextWriter("<console>", Console.Out, false);
+ debugWriter.WriteLine("Effective precondition from where-clauses:");
+ }
+
+ Substitution formalProcImplSubst = Substituter.SubstitutionFromHashtable(impl.GetImplFormalMap());
+ CmdSeq! whereClauses = new CmdSeq();
+
+ // where clauses of in-parameters
+ foreach (Formal! f in impl.Proc.InParams)
+ {
+ if (f.TypedIdent.WhereExpr != null) {
+ Expr e = Substituter.Apply(formalProcImplSubst, f.TypedIdent.WhereExpr);
+ Cmd c = new AssumeCmd(f.tok, e);
+ whereClauses.Add(c);
+
+ if (debugWriter != null) { c.Emit(debugWriter, 1); }
+ }
+ }
+
+ // where clauses of out-parameters
+ assert impl.OutParams.Length == impl.Proc.OutParams.Length;
+ for (int i = 0; i < impl.OutParams.Length; i++) {
+ Variable f = (!)impl.Proc.OutParams[i];
+ if (f.TypedIdent.WhereExpr != null) {
+ Expr e = Substituter.Apply(formalProcImplSubst, f.TypedIdent.WhereExpr);
+ Cmd c = new AssumeCmd(f.tok, e);
+ whereClauses.Add(c);
+
+ Variable fi = (!)impl.OutParams[i];
+ assume fi.TypedIdent.WhereExpr == null;
+ fi.TypedIdent.WhereExpr = e;
+
+ if (debugWriter != null) { c.Emit(debugWriter, 1); }
+ }
+ }
+
+ if (debugWriter != null) { debugWriter.WriteLine(); }
+
+ return whereClauses;
+ }
+
+ private static void
+ ThreadInBlockExpr(Implementation! impl,
+ Block! targetBlock,
+ BlockExpr! blockExpr,
+ bool replaceWithAssert,
+ TokenTextWriter debugWriter){
+ // Go through blockExpr and for all blocks that have a "return e"
+ // as their transfer command:
+ // Replace all "return e" with "assert/assume e"
+ // Change the transfer command to "goto targetBlock"
+ // Then add all of the blocks in blockExpr to the implementation (at the end)
+ foreach (Block! b in blockExpr.Blocks){
+ ReturnExprCmd rec = b.TransferCmd as ReturnExprCmd;
+ if (rec != null){ // otherwise it is a goto command
+ if (replaceWithAssert){
+ Ensures! ens = new Ensures(rec.tok, false, rec.Expr, null);
+ Cmd! c = new AssertEnsuresCmd(ens);
+ b.Cmds.Add(c);
+ }else{
+ b.Cmds.Add(new AssumeCmd(rec.tok, rec.Expr));
+ }
+ b.TransferCmd = new GotoCmd(Token.NoToken,
+ new StringSeq(targetBlock.Label),
+ new BlockSeq(targetBlock));
+ targetBlock.Predecessors.Add(b);
+ }
+ impl.Blocks.Add(b);
+ }
+ if (debugWriter != null){
+ blockExpr.Emit(debugWriter, 1,false);
+ }
+ return;
+ }
+
+ private static void AddAsPrefix(Block! b, CmdSeq! cs){
+ CmdSeq newCommands = new CmdSeq();
+ newCommands.AddRange(cs);
+ newCommands.AddRange(b.Cmds);
+ b.Cmds = newCommands;
+ }
+
+ /// <summary>
+ /// Modifies an implementation by inserting all preconditions
+ /// as assume statements at the beginning of the implementation
+ /// </summary>
+ /// <param name="impl"></param>
+ private static void InjectPreconditions(Implementation! impl)
+ requires impl.Proc != null;
+ {
+ TokenTextWriter debugWriter = null;
+ if (CommandLineOptions.Clo.PrintWithUniqueASTIds) {
+ debugWriter = new TokenTextWriter("<console>", Console.Out, false);
+ debugWriter.WriteLine("Effective precondition:");
+ }
+
+ Substitution formalProcImplSubst = Substituter.SubstitutionFromHashtable(impl.GetImplFormalMap());
+
+ Block! originalEntryPoint = (!) impl.Blocks[0];
+ Block! currentEntryPoint = (!) impl.Blocks[0];
+ CmdSeq! currentClump = new CmdSeq(); // to hold onto contiguous "regular" preconditions
+
+ // (free and checked) requires clauses
+ for (int i = impl.Proc.Requires.Length-1; 0 <= i; i--){
+
+ // need to process the preconditions from bottom up, because
+ // for any that are BlockExprs, we need to thread them on
+ // to the top of the implementation
+
+ Requires req = impl.Proc.Requires[i];
+ Expr! e = Substituter.Apply(formalProcImplSubst, req.Condition);
+ BlockExpr be = req.Condition as BlockExpr;
+ if (be != null){
+ if (currentClump.Length > 0){
+ AddAsPrefix(currentEntryPoint, currentClump);
+ currentClump = new CmdSeq();
+ }
+ ThreadInBlockExpr(impl,currentEntryPoint, be,false,debugWriter);
+ currentEntryPoint = (!)be.Blocks[0];
+ }else{
+ Cmd! c = new AssumeCmd(req.tok, e);
+ currentClump.Add(c);
+ if (debugWriter != null) { c.Emit(debugWriter, 1); }
+ }
+
+ }
+
+ if (currentClump.Length > 0){
+ AddAsPrefix(currentEntryPoint, currentClump);
+ }
+
+ if (currentEntryPoint != originalEntryPoint){
+ string EntryLabel = "PreconditionGeneratedEntry";
+ Block! newEntry = new Block(new Token(-17, -4),EntryLabel,new CmdSeq(),
+ new GotoCmd(Token.NoToken,
+ new StringSeq(currentEntryPoint.Label),
+ new BlockSeq(currentEntryPoint)));
+ currentEntryPoint.Predecessors.Add(newEntry);
+ List<Block!> newBody = new List<Block!>();
+ newBody.Add(newEntry);
+ newBody.AddRange(impl.Blocks);
+ impl.Blocks = newBody;
+ }
+
+ if (debugWriter != null) { debugWriter.WriteLine(); }
+
+ return;
+ }
+ /// <summary>
+ /// Modifies an implementation by inserting all postconditions
+ /// as assert statements at the end of the implementation
+ /// </summary>
+ /// <param name="impl"></param>
+ /// <param name="unifiedExitblock">The unified exit block that has
+ /// already been constructed for the implementation (and so
+ /// is already an element of impl.Blocks)
+ /// </param>
+ private static void InjectPostConditions(Implementation! impl, Block! unifiedExitBlock, Hashtable/*TransferCmd->ReturnCmd*/! gotoCmdOrigins)
+ requires impl.Proc != null;
+ {
+ TokenTextWriter debugWriter = null;
+ if (CommandLineOptions.Clo.PrintWithUniqueASTIds) {
+ debugWriter = new TokenTextWriter("<console>", Console.Out, false);
+ debugWriter.WriteLine("Effective postcondition:");
+ }
+
+ string ExitLabel = "ReallyLastGeneratedExit";
+ Block! newExit = new Block(new Token(-17, -4),ExitLabel,new CmdSeq(),new ReturnCmd(Token.NoToken));
+ impl.Blocks.Add(newExit);
+ Block! currentEntryPoint = newExit;
+ CmdSeq! currentClump = new CmdSeq(); // to hold onto contiguous "regular" postconditions
+
+ Substitution formalProcImplSubst = Substituter.SubstitutionFromHashtable(impl.GetImplFormalMap());
+
+ // (free and checked) ensures clauses
+ for (int i = impl.Proc.Ensures.Length-1; 0 <= i; i--){
+
+ // need to process the postconditions from bottom up, because
+ // for any that are BlockExprs, we need to thread them on
+ // to the top of the implementation
+
+ Ensures ens = (impl.Proc).Ensures[i];
+ if (!ens.Free) { // free ensures aren't needed for verifying the implementation
+ Expr! e = Substituter.Apply(formalProcImplSubst, ens.Condition);
+ BlockExpr be = ens.Condition as BlockExpr;
+ if (be != null){
+ if (currentClump.Length > 0){
+ AddAsPrefix(currentEntryPoint, currentClump);
+ currentClump = new CmdSeq();
+ }
+ ThreadInBlockExpr(impl,currentEntryPoint,be,true,debugWriter);
+ currentEntryPoint = (!)be.Blocks[0];
+ }else{
+ Ensures! ensCopy = (Ensures!) ens.Clone();
+ ensCopy.Condition = e;
+ Cmd! c = new AssertEnsuresCmd(ensCopy);
+ ((AssertEnsuresCmd) c).ErrorDataEnhanced = ensCopy.ErrorDataEnhanced;
+ currentClump.Add(c);
+ if (debugWriter != null) { c.Emit(debugWriter, 1); }
+ }
+ }
+
+ }
+
+ if (currentClump.Length > 0){
+ AddAsPrefix(currentEntryPoint, currentClump);
+ }
+
+ GotoCmd gtc = new GotoCmd(Token.NoToken,
+ new StringSeq(currentEntryPoint.Label),
+ new BlockSeq(currentEntryPoint));
+ gotoCmdOrigins[gtc] = unifiedExitBlock.TransferCmd;
+ unifiedExitBlock.TransferCmd = gtc;
+ currentEntryPoint.Predecessors.Add(unifiedExitBlock);
+
+ if (debugWriter != null) { debugWriter.WriteLine(); }
+
+ return;
+ }
+
+
+ /// <summary>
+ /// Get the pre-condition of an implementation, including the where clauses from the in-parameters.
+ /// </summary>
+ /// <param name="impl"></param>
+ private static CmdSeq! GetPre(Implementation! impl)
+ requires impl.Proc != null;
+ {
+ TokenTextWriter debugWriter = null;
+ if (CommandLineOptions.Clo.PrintWithUniqueASTIds) {
+ debugWriter = new TokenTextWriter("<console>", Console.Out, false);
+ debugWriter.WriteLine("Effective precondition:");
+ }
+
+ Substitution formalProcImplSubst = Substituter.SubstitutionFromHashtable(impl.GetImplFormalMap());
+ CmdSeq! pre = new CmdSeq();
+
+ // (free and checked) requires clauses
+ foreach (Requires! req in impl.Proc.Requires)
+ {
+ Expr! e = Substituter.Apply(formalProcImplSubst, req.Condition);
+ Cmd! c = new AssumeCmd(req.tok, e);
+ pre.Add(c);
+
+ if (debugWriter != null) { c.Emit(debugWriter, 1); }
+ }
+
+ if (debugWriter != null) { debugWriter.WriteLine(); }
+
+ return pre;
+ }
+
+ /// <summary>
+ /// Get the post-condition of an implementation.
+ /// </summary>
+ /// <param name="impl"></param>
+ private static CmdSeq! GetPost(Implementation! impl)
+ requires impl.Proc != null;
+ {
+ if (CommandLineOptions.Clo.PrintWithUniqueASTIds) { Console.WriteLine("Effective postcondition:"); }
+
+ // Construct an Expr for the post-condition
+ Substitution formalProcImplSubst = Substituter.SubstitutionFromHashtable(impl.GetImplFormalMap());
+ CmdSeq! post = new CmdSeq();
+ foreach (Ensures! ens in impl.Proc.Ensures)
+ {
+ if (!ens.Free) {
+ Expr! e = Substituter.Apply(formalProcImplSubst, ens.Condition);
+ Ensures! ensCopy = (Ensures!) ens.Clone();
+ ensCopy.Condition = e;
+ Cmd! c = new AssertEnsuresCmd(ensCopy);
+ ((AssertEnsuresCmd) c).ErrorDataEnhanced = ensCopy.ErrorDataEnhanced;
+ post.Add(c);
+
+ if (CommandLineOptions.Clo.PrintWithUniqueASTIds) { c.Emit(new TokenTextWriter("<console>", Console.Out, false), 1); }
+ }
+ }
+
+ if (CommandLineOptions.Clo.PrintWithUniqueASTIds) { Console.WriteLine(); }
+
+ return post;
+ }
+
+
+ #region Soundness smoke tester
+ class SmokeTester
+ {
+ VCGen! parent;
+ Implementation! impl;
+ Block! initial;
+ Program! program;
+ int id;
+ Dictionary<Block!, Block!>! copies = new Dictionary<Block!, Block!>();
+ Dictionary<Block!, bool>! visited = new Dictionary<Block!, bool>();
+ VerifierCallback! callback;
+
+ internal SmokeTester(VCGen! par, Implementation! i, Program! prog, VerifierCallback! callback)
+ {
+ parent = par;
+ impl = i;
+ initial = i.Blocks[0];
+ program = prog;
+ this.callback = callback;
+ }
+
+ internal void Copy()
+ {
+ CloneBlock(impl.Blocks[0]);
+ initial = GetCopiedBlocks()[0];
+ }
+
+ internal void Test()
+ throws UnexpectedProverOutputException;
+ {
+ DFS(initial);
+ }
+
+ void TopologicalSortImpl()
+ {
+ Graph<Block> dag = new Graph<Block>();
+ dag.AddSource((!)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;
+ if (gtc != null)
+ {
+ assume gtc.labelTargets != null;
+ foreach (Block! dest in gtc.labelTargets)
+ {
+ dag.AddEdge(b,dest);
+ }
+ }
+ }
+ impl.Blocks = new List<Block!>();
+ foreach (Block! b in dag.TopologicalSort()) {
+ impl.Blocks.Add(b);
+ }
+ }
+
+ void Emit()
+ {
+ TopologicalSortImpl();
+ EmitImpl(impl, false);
+ }
+
+ // this one copies forward
+ Block! CloneBlock(Block! b)
+ {
+ Block fake_res;
+ if (copies.TryGetValue(b, out fake_res)) {
+ return (!)fake_res;
+ }
+ Block! res;
+ res = new Block(b.tok, b.Label, new CmdSeq(b.Cmds), null);
+ copies[b] = res;
+ if (b.TransferCmd is GotoCmd) {
+ foreach (Block! ch in (!)((GotoCmd)b.TransferCmd).labelTargets) {
+ CloneBlock(ch);
+ }
+ }
+ foreach (Block! p in b.Predecessors) {
+ res.Predecessors.Add(CloneBlock(p));
+ }
+ return res;
+ }
+
+ // this one copies backwards
+ Block! CopyBlock(Block! b)
+ {
+ Block fake_res;
+ if (copies.TryGetValue(b, out fake_res)) {
+ // fake_res should be Block! but the compiler fails
+ return (!)fake_res;
+ }
+ Block! res;
+ CmdSeq seq = new CmdSeq();
+ foreach (Cmd! c in b.Cmds) {
+ AssertCmd turn = c as AssertCmd;
+ if (!turnAssertIntoAssumes || turn == null) {
+ seq.Add(c);
+ } else {
+ seq.Add(AssertTurnedIntoAssume(turn));
+ }
+ }
+ res = new Block(b.tok, b.Label, seq, null);
+ copies[b] = res;
+ foreach (Block! p in b.Predecessors) {
+ res.Predecessors.Add(CopyBlock(p));
+ }
+ return res;
+ }
+
+ List<Block!>! GetCopiedBlocks()
+ {
+ // the order of nodes in res is random (except for the first one, being the entry)
+ List<Block!> res = new List<Block!>();
+ res.Add(copies[initial]);
+
+ foreach (KeyValuePair<Block!,Block!> kv in copies) {
+ GotoCmd go = kv.Key.TransferCmd as GotoCmd;
+ ReturnCmd ret = kv.Key.TransferCmd as ReturnCmd;
+ if (kv.Key != initial) {
+ res.Add(kv.Value);
+ }
+ if (go != null) {
+ GotoCmd copy = new GotoCmd(go.tok, new StringSeq(), new BlockSeq());
+ kv.Value.TransferCmd = copy;
+ foreach (Block! b in (!)go.labelTargets) {
+ Block c;
+ if (copies.TryGetValue(b, out c)) {
+ copy.AddTarget((!)c);
+ }
+ }
+ } else if (ret != null) {
+ kv.Value.TransferCmd = ret;
+ } else {
+ assume false;
+ }
+ }
+
+ copies.Clear();
+
+ return res;
+ }
+
+ // check if e is true, false, !true, !false
+ // if so return true and the value of the expression in val
+ bool BooleanEval(Expr! e, ref bool val)
+ {
+ LiteralExpr lit = e as LiteralExpr;
+ NAryExpr call = e as NAryExpr;
+
+ if (lit != null && lit.isBool) {
+ val = lit.asBool;
+ return true;
+ } else if (call != null &&
+ call.Fun is UnaryOperator &&
+ ((UnaryOperator)call.Fun).Op == UnaryOperator.Opcode.Not &&
+ BooleanEval((!)call.Args[0], ref val)) {
+ val = !val;
+ return true;
+ }
+ // this is for the 0bv32 != 0bv32 generated by vcc
+ else if (call != null &&
+ call.Fun is BinaryOperator &&
+ ((BinaryOperator)call.Fun).Op == BinaryOperator.Opcode.Neq &&
+ call.Args[0] is LiteralExpr &&
+ ((!)call.Args[0]).Equals(call.Args[1]))
+ {
+ val = false;
+ return true;
+ }
+
+ return false;
+ }
+
+ bool IsFalse(Expr! e)
+ {
+ bool val = false;
+ return BooleanEval(e, ref val) && !val;
+ }
+
+ bool CheckUnreachable(Block! cur, CmdSeq! seq)
+ throws UnexpectedProverOutputException;
+ {
+ DateTime start = DateTime.Now;
+ if (CommandLineOptions.Clo.Trace) {
+ System.Console.Write(" soundness smoke test #{0} ... ", id);
+ }
+ callback.OnProgress("smoke", id, id, 0.0);
+
+ Token tok = new Token();
+ tok.val = "soundness smoke test assertion";
+ seq.Add(new AssertCmd(tok, Expr.False));
+ Block! copy = CopyBlock(cur);
+ copy.Cmds = seq;
+ List<Block!>! backup = impl.Blocks;
+ impl.Blocks = GetCopiedBlocks();
+ copy.TransferCmd = new ReturnCmd(Token.NoToken);
+ if (CommandLineOptions.Clo.TraceVerify) {
+ System.Console.WriteLine();
+ System.Console.WriteLine(" --- smoke #{0}, before passify", id);
+ Emit();
+ }
+ parent.current_impl = impl;
+ parent.PassifyImpl(impl, program);
+ Hashtable! label2Absy;
+ Checker! ch = parent.FindCheckerFor(impl, CommandLineOptions.Clo.SmokeTimeout);
+ VCExpr! vc = parent.GenerateVC(impl, out label2Absy, ch);
+ impl.Blocks = backup;
+
+ if (CommandLineOptions.Clo.TraceVerify) {
+ System.Console.WriteLine(" --- smoke #{0}, after passify", id);
+ Emit();
+ }
+ ch.BeginCheck((!) impl.Name + "_smoke" + id++, vc, new ErrorHandler(label2Absy));
+ ch.ProverDone.WaitOne();
+ ProverInterface.Outcome outcome = ch.ReadOutcome();
+ parent.current_impl = null;
+
+ DateTime end = DateTime.Now;
+ TimeSpan elapsed = end - start;
+ if (CommandLineOptions.Clo.Trace) {
+ System.Console.WriteLine(" [{0} s] {1}", elapsed.TotalSeconds,
+ outcome == ProverInterface.Outcome.Valid ? "OOPS" :
+ "OK" + (outcome == ProverInterface.Outcome.Invalid ? "" : " (" + outcome + ")"));
+ }
+
+ if (outcome == ProverInterface.Outcome.Valid) {
+ // copy it again, so we get the version with calls, assignments and such
+ copy = CopyBlock(cur);
+ copy.Cmds = seq;
+ impl.Blocks = GetCopiedBlocks();
+ TopologicalSortImpl();
+ callback.OnUnreachableCode(impl);
+ impl.Blocks = backup;
+ return true;
+ }
+ return false;
+ }
+
+ const bool turnAssertIntoAssumes = false;
+
+ void DFS(Block! cur)
+ throws UnexpectedProverOutputException;
+ {
+ if (visited.ContainsKey(cur)) return;
+ visited[cur] = true;
+
+ CmdSeq! seq = new CmdSeq();
+ foreach (Cmd! cmd_ in cur.Cmds) {
+ Cmd! cmd = cmd_;
+ AssertCmd assrt = cmd as AssertCmd;
+ AssumeCmd assm = cmd as AssumeCmd;
+ CallCmd call = cmd as CallCmd;
+
+ bool assumeFalse = false;
+
+ if (assrt != null) {
+ // we're not going any further
+ // it's clear the user expected unreachable code here
+ // it's not clear where did he expect it, maybe it would be right to insert
+ // a check just one command before
+ if (IsFalse(assrt.Expr)) return;
+
+ if (turnAssertIntoAssumes) {
+ cmd = AssertTurnedIntoAssume(assrt);
+ }
+ } else if (assm != null) {
+ if (IsFalse(assm.Expr)) assumeFalse = true;
+ } else if (call != null) {
+ foreach (Ensures! e in ((!)call.Proc).Ensures) {
+ if (IsFalse(e.Condition)) assumeFalse = true;
+ }
+ }
+
+ if (assumeFalse) {
+ CheckUnreachable(cur, seq);
+ return;
+ }
+
+ seq.Add(cmd);
+ }
+
+
+ GotoCmd go = cur.TransferCmd as GotoCmd;
+ ReturnCmd ret = cur.TransferCmd as ReturnCmd;
+
+ assume !(go!= null&&go.labelTargets==null&&go.labelNames!=null&&go.labelNames.Length>0) ;
+
+ if (ret != null || (go != null && ((!)go.labelTargets).Length == 0)) {
+ // we end in return, so there will be no more places to check
+ CheckUnreachable(cur, seq);
+ } else if (go != null) {
+ bool needToCheck = true;
+ // if all of our children have more than one parent, then
+ // we're in the right place to check
+ foreach (Block! target in (!)go.labelTargets) {
+ if (target.Predecessors.Length == 1) {
+ needToCheck = false;
+ }
+ }
+ if (needToCheck) {
+ CheckUnreachable(cur, seq);
+ }
+ foreach (Block! target in go.labelTargets) {
+ DFS(target);
+ }
+ }
+ }
+
+ class ErrorHandler : ProverInterface.ErrorHandler {
+ Hashtable! label2Absy;
+
+ public ErrorHandler(Hashtable! label2Absy) {
+ this.label2Absy = label2Absy;
+ }
+
+ public override Absy! Label2Absy(string! label) {
+ int id = int.Parse(label);
+ return (Absy!) label2Absy[id];
+ }
+ }
+ }
+
+
+ #endregion
+
+ #region Splitter
+ class Split
+ {
+ class BlockStats {
+ public bool big_block;
+ public int id;
+ public double assertion_cost;
+ public double assumption_cost; // before multiplier
+ public double incomming_paths;
+ public List<Block!>! virtual_successors = new List<Block!>();
+ public List<Block!>! virtual_predecesors = new List<Block!>();
+ public Dictionary<Block!,bool>? reachable_blocks;
+ public readonly Block! block;
+
+ public BlockStats(Block! b, int i)
+ {
+ block = b;
+ assertion_cost = -1;
+ id = i;
+ }
+ }
+
+ readonly List<Block!>! blocks;
+ readonly List<Block!>! big_blocks = new List<Block!>();
+ readonly Dictionary<Block!, BlockStats!>! stats = new Dictionary<Block!, BlockStats!>();
+ readonly int id;
+ static int current_id;
+ Block? split_block;
+ bool assert_to_assume;
+ List<Block!>! assumized_branches = new List<Block!>();
+ public AssertCmd? first_assert;
+
+ double score;
+ bool score_computed;
+ double total_cost;
+ int assertion_count;
+ double assertion_cost; // without multiplication by paths
+ Hashtable/*TransferCmd->ReturnCmd*/! gotoCmdOrigins;
+ VCGen! parent;
+ Implementation! impl;
+
+ Dictionary<Block!, Block!>! copies = new Dictionary<Block!, Block!>();
+ bool doing_slice;
+ double slice_initial_limit;
+ double slice_limit;
+ bool slice_pos;
+ Dictionary<Block!, bool>! protected_from_assert_to_assume = new Dictionary<Block!,bool>();
+ Dictionary<Block!, bool>! keep_at_all = new Dictionary<Block!,bool>();
+
+ // async interface
+ private Checker checker;
+ private int splitNo;
+ internal ErrorReporter reporter;
+
+ public Split(List<Block!>! blocks, Hashtable/*TransferCmd->ReturnCmd*/! gotoCmdOrigins, VCGen! par, Implementation! impl)
+ {
+ this.blocks = blocks;
+ this.gotoCmdOrigins = gotoCmdOrigins;
+ this.parent = par;
+ this.impl = impl;
+ this.id = current_id++;
+ }
+
+ public double Cost
+ {
+ get {
+ ComputeBestSplit();
+ return total_cost;
+ }
+ }
+
+ public bool LastChance
+ {
+ get {
+ ComputeBestSplit();
+ return assertion_count == 1 && score < 0;
+ }
+ }
+
+ public string Stats
+ {
+ get {
+ ComputeBestSplit();
+ return string.Format("(cost:{0:0}/{1:0}{2})", total_cost, assertion_cost, LastChance ? " last" : "");
+ }
+ }
+
+ public void DumpDot(int no)
+ {
+ using (System.IO.StreamWriter sw = System.IO.File.CreateText(string.Format("split.{0}.dot", no))) {
+ sw.WriteLine("digraph G {");
+
+ ComputeBestSplit();
+ List<Block!> saved = assumized_branches;
+ assumized_branches = new List<Block!>();
+ DoComputeScore(false);
+ assumized_branches = saved;
+
+ foreach (Block! b in big_blocks) {
+ BlockStats s = GetBlockStats(b);
+ foreach (Block! t in s.virtual_successors) {
+ sw.WriteLine("n{0} -> n{1};", s.id, GetBlockStats(t).id);
+ }
+ sw.WriteLine("n{0} [label=\"{1}:\\n({2:0.0}+{3:0.0})*{4:0.0}\"{5}];",
+ s.id, b.Label,
+ s.assertion_cost, s.assumption_cost, s.incomming_paths,
+ s.assertion_cost > 0 ? ",shape=box" : "");
+
+ }
+ sw.WriteLine("}");
+ sw.Close();
+ }
+
+ string filename = string.Format("split.{0}.bpl", no);
+ using (System.IO.StreamWriter sw = System.IO.File.CreateText(filename)) {
+ int oldPrintUnstructured = CommandLineOptions.Clo.PrintUnstructured;
+ CommandLineOptions.Clo.PrintUnstructured = 2; // print only the unstructured program
+ bool oldPrintDesugaringSetting = CommandLineOptions.Clo.PrintDesugarings;
+ CommandLineOptions.Clo.PrintDesugarings = false;
+ List<Block!> backup = impl.Blocks;
+ impl.Blocks = blocks;
+ impl.Emit(new TokenTextWriter(filename, sw, false), 0);
+ impl.Blocks = backup;
+ CommandLineOptions.Clo.PrintDesugarings = oldPrintDesugaringSetting;
+ CommandLineOptions.Clo.PrintUnstructured = oldPrintUnstructured;
+ }
+ }
+
+ int bsid;
+ BlockStats! GetBlockStats(Block! b)
+ {
+ BlockStats s;
+ if (!stats.TryGetValue(b, out s)) {
+ s = new BlockStats(b, bsid++);
+ stats[b] = s;
+ }
+ return (!)s;
+ }
+
+ double AssertionCost(PredicateCmd c)
+ {
+ return 1.0;
+ }
+
+ void CountAssertions(Block! b)
+ {
+ BlockStats s = GetBlockStats(b);
+ if (s.assertion_cost >= 0) return; // already done
+ s.big_block = true;
+ s.assertion_cost = 0;
+ s.assumption_cost = 0;
+ foreach (Cmd c in b.Cmds) {
+ if (c is AssertCmd) {
+ double cost = AssertionCost((AssertCmd)c);
+ s.assertion_cost += cost;
+ assertion_count++;
+ assertion_cost += cost;
+ } else if (c is AssumeCmd) {
+ s.assumption_cost += AssertionCost((AssumeCmd)c);
+ }
+ }
+ foreach (Block! b in Exits(b)) {
+ s.virtual_successors.Add(b);
+ }
+ if (s.virtual_successors.Count == 1) {
+ Block next = s.virtual_successors[0];
+ BlockStats se = GetBlockStats(next);
+ CountAssertions(next);
+ if (next.Predecessors.Length > 1 || se.virtual_successors.Count != 1) return;
+ s.virtual_successors[0] = se.virtual_successors[0];
+ s.assertion_cost += se.assertion_cost;
+ s.assumption_cost += se.assumption_cost;
+ se.big_block = false;
+ }
+ }
+
+ Dictionary<Block!,bool>! ComputeReachableNodes(Block! b)
+ {
+ BlockStats s = GetBlockStats(b);
+ if (s.reachable_blocks != null) {
+ return s.reachable_blocks;
+ }
+ Dictionary<Block!, bool> blocks = new Dictionary<Block!, bool>();
+ s.reachable_blocks = blocks;
+ blocks[b] = true;
+ foreach (Block! succ in Exits(b)) {
+ foreach (Block! r in ComputeReachableNodes(succ).Keys) {
+ blocks[r] = true;
+ }
+ }
+ return blocks;
+ }
+
+ double ProverCost(double vc_cost)
+ {
+ return vc_cost * vc_cost;
+ }
+
+ void ComputeBestSplit()
+ {
+ if (score_computed) return;
+ score_computed = true;
+
+ assertion_count = 0;
+
+ foreach (Block! b in blocks) {
+ CountAssertions(b);
+ }
+
+ foreach (Block! b in blocks) {
+ BlockStats bs = GetBlockStats(b);
+ if (bs.big_block) {
+ big_blocks.Add(b);
+ foreach (Block! ch in bs.virtual_successors) {
+ BlockStats chs = GetBlockStats(ch);
+ if (!chs.big_block) {
+ Console.WriteLine("non-big {0} accessed from {1}", ch, b);
+ DumpDot(-1);
+ assert false;
+ }
+ chs.virtual_predecesors.Add(b);
+ }
+ }
+ }
+
+ assumized_branches.Clear();
+ total_cost = ProverCost(DoComputeScore(false));
+
+ score = double.PositiveInfinity;
+ Block? best_split = null;
+ List<Block!>! saved_branches = new List<Block!>();
+
+ foreach (Block! b in big_blocks) {
+ GotoCmd gt = b.TransferCmd as GotoCmd;
+ if (gt == null) continue;
+ BlockSeq targ = (!)gt.labelTargets;
+ if (targ.Length < 2) continue;
+ // caution, we only consider two first exits
+
+ double left0, right0, left1, right1;
+ split_block = b;
+
+ assumized_branches.Clear();
+ assumized_branches.Add((!)targ[0]);
+ left0 = DoComputeScore(true);
+ right0 = DoComputeScore(false);
+
+ assumized_branches.Clear();
+ for (int idx = 1; idx < targ.Length; idx++) {
+ assumized_branches.Add((!)targ[idx]);
+ }
+ left1 = DoComputeScore(true);
+ right1 = DoComputeScore(false);
+
+ double current_score = ProverCost(left1) + ProverCost(right1);
+ double other_score = ProverCost(left0) + ProverCost(right0);
+
+ if (other_score < current_score) {
+ current_score = other_score;
+ assumized_branches.Clear();
+ assumized_branches.Add((!)targ[0]);
+ }
+
+ if (current_score < score) {
+ score = current_score;
+ best_split = split_block;
+ saved_branches.Clear();
+ saved_branches.AddRange(assumized_branches);
+ }
+ }
+
+ if (CommandLineOptions.Clo.VcsPathSplitMult * score > total_cost) {
+ split_block = null;
+ score = -1;
+ } else {
+ assumized_branches = saved_branches;
+ split_block = best_split;
+ }
+ }
+
+ void UpdateIncommingPaths(BlockStats! s)
+ {
+ if (s.incomming_paths < 0.0) {
+ int count = 0;
+ s.incomming_paths = 0.0;
+ if (!keep_at_all.ContainsKey(s.block)) return;
+ foreach (Block! b in s.virtual_predecesors) {
+ BlockStats! ch = GetBlockStats(b);
+ UpdateIncommingPaths(ch);
+ if (ch.incomming_paths > 0.0) {
+ s.incomming_paths += ch.incomming_paths;
+ count++;
+ }
+ }
+ if (count > 1) {
+ s.incomming_paths *= CommandLineOptions.Clo.VcsPathJoinMult;
+ }
+ }
+ }
+
+ void ComputeBlockSetsHelper(Block! b, bool allow_small)
+ {
+ if (keep_at_all.ContainsKey(b)) return;
+ keep_at_all[b] = true;
+
+ if (allow_small) {
+ foreach (Block! ch in Exits(b)) {
+ if (b == split_block && assumized_branches.Contains(ch)) continue;
+ ComputeBlockSetsHelper(ch, allow_small);
+ }
+ } else {
+ foreach (Block! ch in GetBlockStats(b).virtual_successors) {
+ if (b == split_block && assumized_branches.Contains(ch)) continue;
+ ComputeBlockSetsHelper(ch, allow_small);
+ }
+ }
+ }
+
+ void ComputeBlockSets(bool allow_small)
+ {
+ protected_from_assert_to_assume.Clear();
+ keep_at_all.Clear();
+
+ Debug.Assert(split_block == null || GetBlockStats(split_block).big_block);
+ Debug.Assert(GetBlockStats(blocks[0]).big_block);
+
+ if (assert_to_assume) {
+ foreach (Block! b in allow_small ? blocks : big_blocks) {
+ if (ComputeReachableNodes(b).ContainsKey((!)split_block)) {
+ keep_at_all[b] = true;
+ }
+ }
+
+ foreach (Block! b in assumized_branches) {
+ foreach (Block! r in ComputeReachableNodes(b).Keys) {
+ if (allow_small || GetBlockStats(r).big_block) {
+ keep_at_all[r] = true;
+ protected_from_assert_to_assume[r] = true;
+ }
+ }
+ }
+ } else {
+ ComputeBlockSetsHelper(blocks[0], allow_small);
+ }
+ }
+
+ bool ShouldAssumize(Block! b)
+ {
+ return assert_to_assume && !protected_from_assert_to_assume.ContainsKey(b);
+ }
+
+ double DoComputeScore(bool aa)
+ {
+ assert_to_assume = aa;
+ ComputeBlockSets(false);
+
+ foreach (Block! b in big_blocks) {
+ GetBlockStats(b).incomming_paths = -1.0;
+ }
+
+ GetBlockStats(blocks[0]).incomming_paths = 1.0;
+
+ double cost = 0.0;
+ foreach (Block! b in big_blocks) {
+ if (keep_at_all.ContainsKey(b)) {
+ BlockStats s = GetBlockStats(b);
+ UpdateIncommingPaths(s);
+ double local = s.assertion_cost;
+ if (ShouldAssumize(b)) {
+ local = (s.assertion_cost + s.assumption_cost) * CommandLineOptions.Clo.VcsAssumeMult;
+ } else {
+ local = s.assumption_cost * CommandLineOptions.Clo.VcsAssumeMult + s.assertion_cost;
+ }
+ local = local + local * s.incomming_paths * CommandLineOptions.Clo.VcsPathCostMult;
+ cost += local;
+ }
+ }
+
+ return cost;
+ }
+
+ CmdSeq! SliceCmds(Block! b)
+ {
+ CmdSeq! seq = b.Cmds;
+ if (!doing_slice && !ShouldAssumize(b)) return seq;
+ CmdSeq! res = new CmdSeq();
+ foreach (Cmd! c in seq) {
+ AssertCmd a = c as AssertCmd;
+ Cmd! the_new = c;
+ bool swap = false;
+ if (a != null) {
+ if (doing_slice) {
+ double cost = AssertionCost(a);
+ bool first = (slice_limit - cost) >= 0 || slice_initial_limit == slice_limit;
+ slice_limit -= cost;
+ swap = slice_pos == first;
+ } else if (assert_to_assume) {
+ swap = true;
+ } else {
+ assert false;
+ }
+
+ if (swap) {
+ the_new = AssertTurnedIntoAssume(a);
+ }
+ }
+ res.Add(the_new);
+ }
+ return res;
+ }
+
+ Block! CloneBlock(Block! b)
+ {
+ Block res;
+ if (copies.TryGetValue(b, out res)) {
+ return (!)res;
+ }
+ res = new Block(b.tok, b.Label, SliceCmds(b), b.TransferCmd);
+ GotoCmd gt = b.TransferCmd as GotoCmd;
+ copies[b] = res;
+ if (gt != null) {
+ GotoCmd newGoto = new GotoCmd(gt.tok, new StringSeq(), new BlockSeq());
+ res.TransferCmd = newGoto;
+ int pos = 0;
+ foreach (Block! ch in (!)gt.labelTargets) {
+ assert doing_slice ||
+ (!assert_to_assume ==> (keep_at_all.ContainsKey(ch) || assumized_branches.Contains(ch)));
+ if (doing_slice ||
+ ((b != split_block || assumized_branches.Contains(ch) == assert_to_assume) &&
+ keep_at_all.ContainsKey(ch))) {
+ newGoto.AddTarget(CloneBlock(ch));
+ }
+ pos++;
+ }
+ }
+ return res;
+ }
+
+ Split! DoSplit()
+ {
+ copies.Clear();
+ CloneBlock(blocks[0]);
+ List<Block!> newBlocks = new List<Block!>();
+ Hashtable newGotoCmdOrigins = new Hashtable();
+ foreach (Block! b in blocks) {
+ Block tmp;
+ if (copies.TryGetValue(b, out tmp)) {
+ newBlocks.Add((!)tmp);
+ if (gotoCmdOrigins.ContainsKey(b)) {
+ newGotoCmdOrigins[tmp] = gotoCmdOrigins[b];
+ }
+
+ foreach (Block! p in b.Predecessors) {
+ Block tmp2;
+ if (copies.TryGetValue(p, out tmp2)) {
+ tmp.Predecessors.Add(tmp2);
+ }
+ }
+ }
+ }
+
+ return new Split(newBlocks, newGotoCmdOrigins, parent, impl);
+ }
+
+ Split! SplitAt(int idx)
+ {
+ assert_to_assume = idx == 0;
+ doing_slice = false;
+ ComputeBlockSets(true);
+
+ return DoSplit();
+ }
+
+ Split! SliceAsserts(double limit, bool pos)
+ {
+ slice_pos = pos;
+ slice_limit = limit;
+ slice_initial_limit = limit;
+ doing_slice = true;
+ Split! r = DoSplit();
+
+ /*
+ Console.WriteLine("split {0} / {1} -->", limit, pos);
+ List<Block!> tmp = impl.Blocks;
+ impl.Blocks = r.blocks;
+ EmitImpl(impl, false);
+ impl.Blocks = tmp;
+ */
+
+ return r;
+ }
+
+ void Print()
+ {
+ List<Block!> tmp = impl.Blocks;
+ impl.Blocks = blocks;
+ EmitImpl(impl, false);
+ impl.Blocks = tmp;
+ }
+
+ public Counterexample! ToCounterexample()
+ {
+ BlockSeq trace = new BlockSeq();
+ foreach (Block! b in blocks) {
+ trace.Add(b);
+ }
+ foreach (Block! b in blocks) {
+ foreach (Cmd! c in b.Cmds) {
+ if (c is AssertCmd) {
+ return AssertCmdToCounterexample((AssertCmd)c, (!)b.TransferCmd, trace, null, new Dictionary<Incarnation, Absy!>());
+ }
+ }
+ }
+ assume false;
+ }
+
+ public static List<Split!>! DoSplit(Split! initial, double max_cost, int max)
+ {
+ List<Split!> res = new List<Split!>();
+ res.Add(initial);
+
+ while (res.Count < max) {
+ Split best = null;
+ int best_idx = 0, pos = 0;
+ foreach (Split! s in res) {
+ s.ComputeBestSplit(); // TODO check total_cost first
+ if (s.total_cost > max_cost &&
+ (best == null || best.total_cost < s.total_cost) &&
+ (s.assertion_count > 1 || s.split_block != null)) {
+ best = s;
+ best_idx = pos;
+ }
+ pos++;
+ }
+
+ if (best == null) break; // no split found
+
+ Split! s0, s1;
+
+ bool split_stats = CommandLineOptions.Clo.TraceVerify;
+
+ if (split_stats) {
+ Console.WriteLine("{0} {1} -->", best.split_block == null ? "SLICE" : ("SPLIT@" + best.split_block.Label), best.Stats);
+ if (best.split_block != null) {
+ GotoCmd g = best.split_block.TransferCmd as GotoCmd;
+ if (g != null) {
+ Console.Write(" exits: ");
+ foreach (Block! b in (!)g.labelTargets) {
+ Console.Write("{0} ", b.Label);
+ }
+ Console.WriteLine("");
+ Console.Write(" assumized: ");
+ foreach (Block! b in best.assumized_branches) {
+ Console.Write("{0} ", b.Label);
+ }
+ Console.WriteLine("");
+ }
+ }
+ }
+
+ if (best.split_block != null) {
+ s0 = best.SplitAt(0);
+ s1 = best.SplitAt(1);
+ } else {
+ best.split_block = null;
+ s0 = best.SliceAsserts(best.assertion_cost / 2, true);
+ s1 = best.SliceAsserts(best.assertion_cost / 2, false);
+ }
+
+ if (true) {
+ List<Block!> ss = new List<Block!>();
+ ss.Add(s0.blocks[0]);
+ ss.Add(s1.blocks[0]);
+ try {
+ best.SoundnessCheck(new Dictionary<PureCollections.Tuple!, bool>(), best.blocks[0], ss);
+ } catch (System.Exception e) {
+ Console.WriteLine(e);
+ best.DumpDot(-1);
+ s0.DumpDot(-2);
+ s1.DumpDot(-3);
+ assert false;
+ }
+ }
+
+ if (split_stats) {
+ s0.ComputeBestSplit();
+ s1.ComputeBestSplit();
+ Console.WriteLine(" --> {0}", s0.Stats);
+ Console.WriteLine(" --> {0}", s1.Stats);
+ }
+
+ if (CommandLineOptions.Clo.TraceVerify) {
+ best.Print();
+ }
+
+ res[best_idx] = s0;
+ res.Add(s1);
+ }
+
+ return res;
+ }
+
+ public Checker! Checker
+ {
+ get {
+ assert checker != null;
+ return checker;
+ }
+ }
+
+ public WaitHandle ProverDone
+ {
+ get {
+ assert checker != null;
+ return checker.ProverDone;
+ }
+ }
+
+ public void ReadOutcome(ref Outcome cur_outcome, out bool prover_failed)
+ throws UnexpectedProverOutputException;
+ {
+ ProverInterface.Outcome outcome = ((!)checker).ReadOutcome();
+
+ if (CommandLineOptions.Clo.Trace && splitNo >= 0) {
+ System.Console.WriteLine(" --> split #{0} done, [{1} s] {2}", splitNo, checker.ProverRunTime.TotalSeconds, outcome);
+ }
+
+ if (CommandLineOptions.Clo.VcsDumpSplits) {
+ DumpDot(splitNo);
+ }
+
+ prover_failed = false;
+
+ switch (outcome) {
+ case ProverInterface.Outcome.Valid:
+ return;
+ case ProverInterface.Outcome.Invalid:
+ cur_outcome = Outcome.Errors;
+ return;
+ case ProverInterface.Outcome.OutOfMemory:
+ prover_failed = true;
+ if (cur_outcome != Outcome.Errors && cur_outcome != Outcome.Inconclusive)
+ cur_outcome = Outcome.OutOfMemory;
+ return;
+ case ProverInterface.Outcome.TimeOut:
+ prover_failed = true;
+ if (cur_outcome != Outcome.Errors && cur_outcome != Outcome.Inconclusive)
+ cur_outcome = Outcome.TimedOut;
+ return;
+ case ProverInterface.Outcome.Undetermined:
+ prover_failed = true;
+ if (cur_outcome != Outcome.Errors)
+ cur_outcome = Outcome.Inconclusive;
+ return;
+ default:
+ assert false;
+ }
+ }
+
+ public void BeginCheck(VerifierCallback! callback, int no, int timeout)
+ {
+ splitNo = no;
+
+ impl.Blocks = blocks;
+
+ checker = parent.FindCheckerFor(impl, timeout);
+
+ Hashtable/*<int, Absy!>*/! label2absy;
+ VCExpr! vc = parent.GenerateVC(impl, out label2absy, checker);
+
+ if (CommandLineOptions.Clo.vcVariety == CommandLineOptions.VCVariety.Local) {
+ reporter = new ErrorReporterLocal(gotoCmdOrigins, label2absy, impl.Blocks, parent.incarnationOriginMap, callback);
+ } else {
+ reporter = new ErrorReporter(gotoCmdOrigins, label2absy, impl.Blocks, parent.incarnationOriginMap, callback);
+ }
+
+ if (CommandLineOptions.Clo.TraceVerify && no >= 0)
+ {
+ Console.WriteLine("-- after split #{0}", no);
+ Print();
+ }
+
+ string! desc = (!) impl.Name;
+ if (no >= 0)
+ desc += "_split" + no;
+ checker.BeginCheck(desc, vc, reporter);
+
+ }
+
+ private void SoundnessCheck(Dictionary<PureCollections.Tuple!, bool>! cache, Block! orig, List<Block!>! copies)
+ {
+ {
+ PureCollections.Tuple t = new PureCollections.Tuple(new PureCollections.Capacity(1 + copies.Count));
+ int i = 0;
+ t[i++] = orig;
+ foreach (Block! b in copies) {
+ t[i++] = b;
+ }
+ if (cache.ContainsKey(t)) { return; }
+ cache[t] = true;
+ }
+
+ for (int i = 0; i < orig.Cmds.Length; ++i) {
+ Cmd cmd = orig.Cmds[i];
+ if (cmd is AssertCmd) {
+ int found = 0;
+ foreach (Block! c in copies) {
+ if (c.Cmds[i] == cmd) {
+ found++;
+ }
+ }
+ if (found == 0) {
+ throw new System.Exception(string.Format("missing assertion: {0}({1})", cmd.tok.filename, cmd.tok.line));
+ }
+ }
+ }
+
+ foreach (Block! exit in Exits(orig)) {
+ List<Block!>! newcopies = new List<Block!>();
+ foreach (Block! c in copies) {
+ foreach (Block! cexit in Exits(c)) {
+ if (cexit.Label == exit.Label) {
+ newcopies.Add(cexit);
+ }
+ }
+ }
+ if (newcopies.Count == 0) {
+ throw new System.Exception("missing exit " + exit.Label);
+ }
+ SoundnessCheck(cache, exit, newcopies);
+ }
+ }
+ }
+ #endregion
+
+
+ protected VCExpr! GenerateVC(Implementation! impl, out Hashtable/*<int, Absy!>*/! label2absy, Checker! ch)
+ {
+ TypecheckingContext tc = new TypecheckingContext(null);
+ impl.Typecheck(tc);
+
+ label2absy = new Hashtable/*<int, Absy!>*/();
+ VCExpr! vc;
+ switch (CommandLineOptions.Clo.vcVariety) {
+ case CommandLineOptions.VCVariety.Structured:
+ vc = VCViaStructuredProgram(impl, label2absy, ch.TheoremProver.Context);
+ break;
+ case CommandLineOptions.VCVariety.Block:
+ vc = FlatBlockVC(impl, label2absy, false, false, false, ch.TheoremProver.Context);
+ break;
+ case CommandLineOptions.VCVariety.BlockReach:
+ vc = FlatBlockVC(impl, label2absy, false, true, false, ch.TheoremProver.Context);
+ break;
+ case CommandLineOptions.VCVariety.Local:
+ vc = FlatBlockVC(impl, label2absy, true, false, false, ch.TheoremProver.Context);
+ break;
+ case CommandLineOptions.VCVariety.BlockNested:
+ vc = NestedBlockVC(impl, label2absy, false, ch.TheoremProver.Context);
+ break;
+ case CommandLineOptions.VCVariety.BlockNestedReach:
+ vc = NestedBlockVC(impl, label2absy, true, ch.TheoremProver.Context);
+ break;
+ case CommandLineOptions.VCVariety.Dag:
+ if (((!)CommandLineOptions.Clo.TheProverFactory).SupportsDags) {
+ vc = DagVC((!)impl.Blocks[0], label2absy, new Hashtable/*<Block, VCExpr!>*/(), ch.TheoremProver.Context);
+ } else {
+ vc = LetVC((!)impl.Blocks[0], label2absy, ch.TheoremProver.Context);
+ }
+ break;
+ case CommandLineOptions.VCVariety.Doomed:
+ vc = FlatBlockVC(impl, label2absy, false, false, true, ch.TheoremProver.Context);
+ break;
+ default:
+ assert false; // unexpected enumeration value
+ }
+ return vc;
+ }
+
+ void CheckIntAttributeOnImpl(Implementation! impl, string! name, ref int val)
+ {
+ if (!((!)impl.Proc).CheckIntAttribute(name, ref val) || !impl.CheckIntAttribute(name, ref val)) {
+ Console.WriteLine("ignoring ill-formed {:{0} ...} attribute on {1}, parameter should be an int", name, impl.Name);
+ }
+ }
+
+
+ public override Outcome VerifyImplementation(Implementation! impl, Program! program, VerifierCallback! callback)
+ throws UnexpectedProverOutputException;
+ {
+ if (impl.SkipVerification) {
+ return Outcome.Inconclusive; // not sure about this one
+ }
+
+ callback.OnProgress("VCgen", 0, 0, 0.0);
+
+ ConvertCFG2DAG(impl, program);
+
+ SmokeTester smoke_tester = null;
+ if (CommandLineOptions.Clo.SoundnessSmokeTest) {
+ smoke_tester = new SmokeTester(this, impl, program, callback);
+ smoke_tester.Copy();
+ }
+
+ Hashtable/*TransferCmd->ReturnCmd*/ gotoCmdOrigins = PassifyImpl(impl, program);
+
+ double max_vc_cost = CommandLineOptions.Clo.VcsMaxCost;
+ int tmp_max_vc_cost = -1, max_splits = CommandLineOptions.Clo.VcsMaxSplits,
+ max_kg_splits = CommandLineOptions.Clo.VcsMaxKeepGoingSplits;
+ CheckIntAttributeOnImpl(impl, "vcs_max_cost", ref tmp_max_vc_cost);
+ CheckIntAttributeOnImpl(impl, "vcs_max_splits", ref max_splits);
+ CheckIntAttributeOnImpl(impl, "vcs_max_keep_going_splits", ref max_kg_splits);
+ if (tmp_max_vc_cost >= 0) {
+ max_vc_cost = tmp_max_vc_cost;
+ }
+
+ Outcome outcome = Outcome.Correct;
+
+ int cores = CommandLineOptions.Clo.VcsCores;
+ Stack<Split!> work = new Stack<Split!>();
+ List<Split!> currently_running = new List<Split!>();
+ ResetPredecessors(impl.Blocks);
+ work.Push(new Split(impl.Blocks, gotoCmdOrigins, this, impl));
+
+ bool keep_going = max_kg_splits > 1;
+ int total = 0;
+ int no = max_splits == 1 && !keep_going ? -1 : 0;
+ bool first_round = true;
+ bool do_splitting = keep_going || max_splits > 1;
+ double remaining_cost = 0.0, proven_cost = 0.0;
+
+ if (do_splitting) {
+ remaining_cost = work.Peek().Cost;
+ }
+
+ while (work.Count > 0 || currently_running.Count > 0) {
+ bool prover_failed = false;
+ Split! s;
+
+ if (work.Count > 0 && currently_running.Count < cores) {
+ s = work.Pop();
+
+ if (first_round && max_splits > 1) {
+ prover_failed = true;
+ remaining_cost -= s.Cost;
+ } else {
+ if (CommandLineOptions.Clo.Trace && no >= 0) {
+ System.Console.WriteLine(" checking split {1}/{2}, {3:0.00}%, {0} ...",
+ s.Stats, no + 1, total, 100 * proven_cost / (proven_cost + remaining_cost));
+ }
+ callback.OnProgress("VCprove", no < 0 ? 0 : no, total, proven_cost / (remaining_cost + proven_cost));
+
+ s.BeginCheck(callback, no,
+ (keep_going && s.LastChance) ? CommandLineOptions.Clo.VcsFinalAssertTimeout :
+ keep_going ? CommandLineOptions.Clo.VcsKeepGoingTimeout :
+ CommandLineOptions.Clo.ProverKillTime);
+
+ no++;
+
+ currently_running.Add(s);
+ }
+ } else {
+ WaitHandle[] handles = new WaitHandle[currently_running.Count];
+ for (int i = 0; i < currently_running.Count; ++i) {
+ handles[i] = currently_running[i].ProverDone;
+ }
+ int index = WaitHandle.WaitAny(handles);
+ s = currently_running[index];
+ currently_running.RemoveAt(index);
+
+ if (do_splitting) {
+ remaining_cost -= s.Cost;
+ }
+
+ s.ReadOutcome(ref outcome, out prover_failed);
+
+ if (do_splitting) {
+ if (prover_failed) {
+ // even if the prover fails, we have learned something, i.e., it is
+ // annoying to watch Boogie say Timeout, 0.00% a couple of times
+ proven_cost += s.Cost / 100;
+ } else {
+ proven_cost += s.Cost;
+ }
+ }
+ callback.OnProgress("VCprove", no < 0 ? 0 : no, total, proven_cost / (remaining_cost + proven_cost));
+
+ if (prover_failed && !first_round && s.LastChance) {
+ string! msg = "some timeout";
+ if (s.reporter != null && s.reporter.resourceExceededMessage != null) {
+ msg = s.reporter.resourceExceededMessage;
+ }
+ callback.OnCounterexample(s.ToCounterexample(), msg);
+ outcome = Outcome.Errors;
+ break;
+ }
+
+ assert prover_failed || outcome == Outcome.Correct || outcome == Outcome.Errors;
+ }
+
+ if (prover_failed) {
+ int splits = first_round && max_splits > 1 ? max_splits : max_kg_splits;
+
+ if (splits > 1) {
+ List<Split!> tmp = Split.DoSplit(s, max_vc_cost, splits);
+ max_vc_cost = 1.0; // for future
+ first_round = false;
+ //tmp.Sort(new Comparison<Split!>(Split.Compare));
+ foreach (Split! a in tmp) {
+ work.Push(a);
+ total++;
+ remaining_cost += a.Cost;
+ }
+ if (outcome != Outcome.Errors) {
+ outcome = Outcome.Correct;
+ }
+ } else {
+ assert outcome != Outcome.Correct;
+ if (outcome == Outcome.TimedOut) {
+ string! msg = "some timeout";
+ if (s.reporter != null && s.reporter.resourceExceededMessage != null) {
+ msg = s.reporter.resourceExceededMessage;
+ }
+ callback.OnTimeout(msg);
+ } else if (outcome == Outcome.OutOfMemory) {
+ string! msg = "out of memory";
+ if (s.reporter != null && s.reporter.resourceExceededMessage != null) {
+ msg = s.reporter.resourceExceededMessage;
+ }
+ callback.OnOutOfMemory(msg);
+ }
+
+ break;
+ }
+ }
+ }
+
+ if (outcome == Outcome.Correct && smoke_tester != null) {
+ smoke_tester.Test();
+ }
+
+ callback.OnProgress("done", 0, 0, 1.0);
+
+ return outcome;
+ }
+
+ public class ErrorReporter : ProverInterface.ErrorHandler {
+ Hashtable/*TransferCmd->ReturnCmd*/! gotoCmdOrigins;
+ Hashtable/*<int, Absy!>*/! label2absy;
+ List<Block!>! blocks;
+ protected Dictionary<Incarnation, Absy!>! incarnationOriginMap;
+ protected VerifierCallback! callback;
+ internal string? resourceExceededMessage;
+ static private System.IO.TextWriter? modelWriter;
+
+ static protected TextWriter! ModelWriter {
+ get {
+ if (ErrorReporter.modelWriter == null)
+ ErrorReporter.modelWriter = CommandLineOptions.Clo.PrintErrorModelFile == null ? Console.Out : new StreamWriter(CommandLineOptions.Clo.PrintErrorModelFile, false);
+ return ErrorReporter.modelWriter;
+ }
+ }
+
+ public ErrorReporter(Hashtable/*TransferCmd->ReturnCmd*/! gotoCmdOrigins,
+ Hashtable/*<int, Absy!>*/! label2absy,
+ List<Block!>! blocks,
+ Dictionary<Incarnation, Absy!>! incarnationOriginMap,
+ VerifierCallback! callback)
+ {
+ this.gotoCmdOrigins = gotoCmdOrigins;
+ this.label2absy = label2absy;
+ this.blocks = blocks;
+ this.incarnationOriginMap = incarnationOriginMap;
+ this.callback = callback;
+ // base();
+ }
+
+ public override void OnModel(IList<string!>! labels, ErrorModel errModel) {
+ if (CommandLineOptions.Clo.PrintErrorModel >= 1 && errModel != null) {
+ errModel.Print(ErrorReporter.ModelWriter);
+ ErrorReporter.ModelWriter.Flush();
+ }
+ Hashtable traceNodes = new Hashtable();
+ foreach (string! s in labels) {
+ Absy! absy =Label2Absy(s);
+ if (traceNodes.ContainsKey(absy))
+ System.Console.WriteLine("Warning: duplicate label: " + s + " read while tracing nodes");
+ else
+ traceNodes.Add(absy, null);
+ }
+
+ BlockSeq! trace = new BlockSeq();
+ Block! entryBlock = (!) this.blocks[0];
+ assert traceNodes.Contains(entryBlock);
+ trace.Add(entryBlock);
+
+ Counterexample newCounterexample = TraceCounterexample(entryBlock, traceNodes, trace, errModel, incarnationOriginMap);
+
+ if (newCounterexample == null) return;
+
+ #region Map passive program errors back to original program errors
+ ReturnCounterexample returnExample = newCounterexample as ReturnCounterexample;
+ if (returnExample != null)
+ {
+ foreach (Block! b in returnExample.Trace) {
+ assume b.TransferCmd != null;
+ ReturnCmd cmd = (ReturnCmd) gotoCmdOrigins[b.TransferCmd];
+ if (cmd != null)
+ {
+ returnExample.FailingReturn = cmd;
+ break;
+ }
+ }
+ }
+ #endregion
+ callback.OnCounterexample(newCounterexample, null);
+ }
+
+ public override Absy! Label2Absy(string! label)
+ {
+ int id = int.Parse(label);
+ return (Absy!) label2absy[id];
+ }
+
+ public override void OnResourceExceeded(string! msg)
+ {
+ resourceExceededMessage = msg;
+ }
+ }
+
+ public class ErrorReporterLocal : ErrorReporter {
+ public ErrorReporterLocal(Hashtable/*TransferCmd->ReturnCmd*/! gotoCmdOrigins,
+ Hashtable/*<int, Absy!>*/! label2absy,
+ List<Block!>! blocks,
+ Dictionary<Incarnation, Absy!>! incarnationOriginMap,
+ VerifierCallback! callback)
+ {
+ base(gotoCmdOrigins, label2absy, blocks, incarnationOriginMap, callback); // here for aesthetic purposes
+ }
+
+ public override void OnModel(IList<string!>! labels, ErrorModel errModel) {
+ // We ignore the error model here for enhanced error message purposes.
+ // It is only printed to the command line.
+ if (CommandLineOptions.Clo.PrintErrorModel >= 1 && errModel != null) {
+ if (CommandLineOptions.Clo.PrintErrorModelFile != null) {
+ errModel.Print(ErrorReporter.ModelWriter);
+ ErrorReporter.ModelWriter.Flush();
+ }
+ }
+ List<Block!> traceNodes = new List<Block!>();
+ List<AssertCmd!> assertNodes = new List<AssertCmd!>();
+ foreach (string! s in labels) {
+ Absy node = Label2Absy(s);
+ if (node is Block) {
+ Block b = (Block)node;
+ traceNodes.Add(b);
+ } else {
+ AssertCmd a = (AssertCmd)node;
+ assertNodes.Add(a);
+ }
+ }
+ assert assertNodes.Count > 0;
+ assert traceNodes.Count == assertNodes.Count;
+
+ foreach (AssertCmd a in assertNodes) {
+ // find the corresponding Block (assertNodes.Count is likely to be 1, or small in any case, so just do a linear search here)
+ foreach (Block b in traceNodes) {
+ if (b.Cmds.Has(a)) {
+ BlockSeq trace = new BlockSeq();
+ trace.Add(b);
+ Counterexample newCounterexample = AssertCmdToCounterexample(a, (!)b.TransferCmd, trace, errModel, incarnationOriginMap);
+ callback.OnCounterexample(newCounterexample, null);
+ goto NEXT_ASSERT;
+ }
+ }
+ assert false; // there was no block that contains the assert
+ NEXT_ASSERT: {}
+ }
+ }
+ }
+
+ protected void ConvertCFG2DAG(Implementation! impl, Program! program)
+ {
+ impl.PruneUnreachableBlocks(); // This is needed for VCVariety.BlockNested, and is otherwise just an optimization
+
+ current_impl = impl;
+ variable2SequenceNumber = new Hashtable/*Variable -> int*/();
+ incarnationOriginMap = new Dictionary<Incarnation, Absy!>();
+
+ #region Debug Tracing
+ if (CommandLineOptions.Clo.TraceVerify)
+ {
+ Console.WriteLine("original implementation");
+ EmitImpl(impl, false);
+ }
+ #endregion
+
+ #region Debug Tracing
+ if (CommandLineOptions.Clo.TraceVerify)
+ {
+ Console.WriteLine("after desugaring sugared commands like procedure calls");
+ EmitImpl(impl, true);
+ }
+ #endregion
+
+ ComputePredecessors(impl.Blocks);
+
+ #region Convert program CFG into a DAG
+
+ #region Use the graph library to figure out where the (natural) loops are
+
+ #region Create the graph by adding the source node and each edge
+ Graph<Block>! g = GraphFromImpl(impl);
+ #endregion
+
+ g.ComputeLoops(); // this is the call that does all of the processing
+ if (!g.Reducible)
+ {
+ throw new VCGenException("Irreducible flow graphs are unsupported.");
+ }
+
+ #endregion
+
+ #region Cut the backedges, push assert/assume statements from loop header into predecessors, change them all into assume statements at top of loop, introduce havoc statements
+ foreach (Block! header in (!) g.Headers)
+ {
+ IDictionary<Block!,object> backEdgeNodes = new Dictionary<Block!,object>();
+ foreach (Block! b in (!) g.BackEdgeNodes(header)) { backEdgeNodes.Add(b, null); }
+
+ #region Find the (possibly empty) prefix of assert commands in the header, replace each assert with an assume of the same condition
+ CmdSeq prefixOfPredicateCmdsInit = new CmdSeq();
+ CmdSeq prefixOfPredicateCmdsMaintained = new CmdSeq();
+ for (int i = 0, n = header.Cmds.Length; i < n; i++)
+ {
+ PredicateCmd a = header.Cmds[i] as PredicateCmd;
+ if (a != null)
+ {
+ if (a is AssumeCmd) {
+ prefixOfPredicateCmdsInit.Add(a);
+ prefixOfPredicateCmdsMaintained.Add(a);
+ } else {
+ Bpl.AssertCmd c = (AssertCmd) a;
+ Bpl.AssertCmd b = new Bpl.LoopInitAssertCmd(c.tok, c.Expr);
+ b.ErrorData = c.ErrorData;
+ prefixOfPredicateCmdsInit.Add(b);
+ b = new Bpl.LoopInvMaintainedAssertCmd(c.tok, c.Expr);
+ b.ErrorData = c.ErrorData;
+ prefixOfPredicateCmdsMaintained.Add(b);
+ header.Cmds[i] = new AssumeCmd(c.tok,c.Expr);
+ }
+ }
+ else if ( header.Cmds[i] is CommentCmd )
+ {
+ // ignore
+ }
+ else
+ {
+ break; // stop when an assignment statement (or any other non-predicate cmd) is encountered
+ }
+ }
+ #endregion
+
+ #region Copy the prefix of predicate commands into each predecessor. Do this *before* cutting the backedge!!
+ for ( int predIndex = 0, n = header.Predecessors.Length; predIndex < n; predIndex++ )
+ {
+ Block! pred = (!)header.Predecessors[predIndex];
+
+ // Create a block between header and pred for the predicate commands if header has more than one successor
+ // or if pred is a back edge node
+ GotoCmd gotocmd = pred.TransferCmd as GotoCmd;
+ if ((backEdgeNodes.ContainsKey(pred)) || (gotocmd != null && gotocmd.labelNames != null && gotocmd.labelNames.Length > 1))
+ {
+ Block! newBlock = CreateBlockBetween(predIndex, header);
+ impl.Blocks.Add(newBlock);
+
+ // if pred is a back edge node, then now newBlock is the back edge node
+ if (backEdgeNodes.ContainsKey(pred))
+ {
+ backEdgeNodes.Remove(pred);
+ backEdgeNodes.Add(newBlock,null);
+ }
+
+ pred = newBlock;
+ }
+ // Add the predicate commands
+ if (backEdgeNodes.ContainsKey(pred)){
+ pred.Cmds.AddRange(prefixOfPredicateCmdsMaintained);
+ }
+ else {
+ pred.Cmds.AddRange(prefixOfPredicateCmdsInit);
+ }
+ }
+ #endregion
+
+ #region Cut the back edge
+ foreach (Block! backEdgeNode in (!)backEdgeNodes.Keys)
+ {
+ Debug.Assert(backEdgeNode.TransferCmd is GotoCmd,"An node was identified as the source for a backedge, but it does not have a goto command.");
+ GotoCmd gtc = backEdgeNode.TransferCmd as GotoCmd;
+ if (gtc != null && gtc.labelTargets != null && gtc.labelTargets.Length > 1 )
+ {
+ // then remove the backedge by removing the target block from the list of gotos
+ BlockSeq remainingTargets = new BlockSeq();
+ StringSeq remainingLabels = new StringSeq();
+ assume gtc.labelNames != null;
+ for (int i = 0, n = gtc.labelTargets.Length; i < n; i++)
+ {
+ if ( gtc.labelTargets[i] != header )
+ {
+ remainingTargets.Add(gtc.labelTargets[i]);
+ remainingLabels.Add(gtc.labelNames[i]);
+ }
+ }
+ gtc.labelTargets = remainingTargets;
+ gtc.labelNames = remainingLabels;
+ }
+ else
+ {
+ // This backedge is the only out-going edge from this node.
+ // Add an "assume false" statement to the end of the statements
+ // inside of the block and change the goto command to a return command.
+ AssumeCmd ac = new AssumeCmd(Token.NoToken,Expr.False);
+ backEdgeNode.Cmds.Add(ac);
+ backEdgeNode.TransferCmd = new ReturnCmd(Token.NoToken);
+ }
+ #region Remove the backedge node from the list of predecessor nodes in the header
+ BlockSeq newPreds = new BlockSeq();
+ foreach ( Block p in header.Predecessors )
+ {
+ if ( p != backEdgeNode )
+ newPreds.Add(p);
+ }
+ header.Predecessors = newPreds;
+ #endregion
+ }
+ #endregion
+
+ #region Collect all variables that are assigned to in all of the natural loops for which this is the header
+ VariableSeq varsToHavoc = new VariableSeq();
+ foreach (Block! backEdgeNode in (!) g.BackEdgeNodes(header))
+ {
+ foreach ( Block! b in g.NaturalLoops(header,backEdgeNode) )
+ {
+ foreach ( Cmd! c in b.Cmds )
+ {
+ c.AddAssignedVariables(varsToHavoc);
+ }
+ }
+ }
+ IdentifierExprSeq havocExprs = new IdentifierExprSeq();
+ foreach ( Variable! v in varsToHavoc )
+ {
+ IdentifierExpr ie = new IdentifierExpr(Token.NoToken, v);
+ if(!havocExprs.Has(ie))
+ havocExprs.Add(ie);
+ }
+ // pass the token of the enclosing loop header to the HavocCmd so we can reconstruct
+ // the source location for this later on
+ HavocCmd hc = new HavocCmd(header.tok,havocExprs);
+ CmdSeq newCmds = new CmdSeq();
+ newCmds.Add(hc);
+ foreach ( Cmd c in header.Cmds )
+ {
+ newCmds.Add(c);
+ }
+ header.Cmds = newCmds;
+ #endregion
+ }
+ #endregion
+ #endregion Convert program CFG into a DAG
+
+ #region Debug Tracing
+ if (CommandLineOptions.Clo.TraceVerify)
+ {
+ Console.WriteLine("after conversion into a DAG");
+ EmitImpl(impl, true);
+ }
+ #endregion
+ }
+
+ protected Hashtable/*TransferCmd->ReturnCmd*/! PassifyImpl(Implementation! impl, Program! program)
+ {
+ Hashtable/*TransferCmd->ReturnCmd*/ gotoCmdOrigins = new Hashtable/*TransferCmd->ReturnCmd*/();
+ Block/*?*/ exitBlock = GenerateUnifiedExit(impl, gotoCmdOrigins);
+
+ #region Debug Tracing
+ if (CommandLineOptions.Clo.TraceVerify)
+ {
+ Console.WriteLine("after creating a unified exit block");
+ EmitImpl(impl, true);
+ }
+ #endregion
+
+ #region Insert pre- and post-conditions and where clauses as assume and assert statements
+ {
+ CmdSeq cc = new CmdSeq();
+ // where clauses of global variables
+ foreach (Declaration d in program.TopLevelDeclarations) {
+ GlobalVariable gvar = d as GlobalVariable;
+ if (gvar != null && gvar.TypedIdent.WhereExpr != null) {
+ Cmd c = new AssumeCmd(gvar.tok, gvar.TypedIdent.WhereExpr);
+ cc.Add(c);
+ }
+ }
+ // where clauses of in- and out-parameters
+ cc.AddRange(GetParamWhereClauses(impl));
+ // where clauses of local variables
+ foreach (Variable! lvar in impl.LocVars) {
+ if (lvar.TypedIdent.WhereExpr != null) {
+ Cmd c = new AssumeCmd(lvar.tok, lvar.TypedIdent.WhereExpr);
+ cc.Add(c);
+ }
+ }
+
+ InjectPreconditions(impl);
+ //cc.AddRange(GetPre(impl));
+
+ Block! entryBlock = (!) impl.Blocks[0];
+ cc.AddRange(entryBlock.Cmds);
+ entryBlock.Cmds = cc;
+
+ InjectPostConditions(impl,exitBlock,gotoCmdOrigins);
+ //CmdSeq! post = GetPost(impl);
+ //exitBlock.Cmds.AddRange(post);
+ }
+ #endregion
+
+ #region Debug Tracing
+ if (CommandLineOptions.Clo.TraceVerify)
+ {
+ Console.WriteLine("after inserting pre- and post-conditions");
+ EmitImpl(impl, true);
+ }
+ #endregion
+
+ AddBlocksBetween(impl);
+
+ #region Debug Tracing
+ if (CommandLineOptions.Clo.TraceVerify)
+ {
+ Console.WriteLine("after adding empty blocks before all blocks with more than one predecessor");
+ EmitImpl(impl, true);
+ }
+ #endregion
+
+ Convert2PassiveCmd(impl);
+
+ #region Peep-hole optimizations
+ if (CommandLineOptions.Clo.RemoveEmptyBlocks){
+ #region Get rid of empty blocks
+ {
+ Block! entryBlock = (!) impl.Blocks[0];
+ RemoveEmptyBlocks(entryBlock);
+ impl.PruneUnreachableBlocks();
+ }
+ #endregion Get rid of empty blocks
+
+ #region Debug Tracing
+ if (CommandLineOptions.Clo.TraceVerify)
+ {
+ Console.WriteLine("after peep-hole optimizations");
+ EmitImpl(impl, true);
+ }
+ #endregion
+ }
+ #endregion Peep-hole optimizations
+
+// #region Constant Folding
+// #endregion
+// #region Debug Tracing
+// if (CommandLineOptions.Clo.TraceVerify)
+// {
+// Console.WriteLine("after constant folding");
+// EmitImpl(impl, true);
+// }
+// #endregion
+
+ return gotoCmdOrigins;
+ }
+
+ static Counterexample TraceCounterexample(Block! b, Hashtable! traceNodes, BlockSeq! trace, ErrorModel errModel, Dictionary<Incarnation, Absy!>! incarnationOriginMap)
+ {
+ // After translation, all potential errors come from asserts.
+ CmdSeq! cmds = b.Cmds;
+ TransferCmd! transferCmd = (!)b.TransferCmd;
+ for (int i = 0; i < cmds.Length; i++)
+ {
+ Cmd! cmd = (!) cmds[i];
+
+ // Skip if 'cmd' not contained in the trace or not an assert
+ if (!(cmd is AssertCmd) || !traceNodes.Contains(cmd))
+ continue;
+
+ return AssertCmdToCounterexample((AssertCmd)cmd, transferCmd, trace, errModel, incarnationOriginMap);
+ }
+
+ GotoCmd gotoCmd = transferCmd as GotoCmd;
+ if (gotoCmd != null)
+ {
+ foreach (Block! bb in (!)gotoCmd.labelTargets)
+ {
+ if (traceNodes.Contains(bb)){
+ trace.Add(bb);
+ return TraceCounterexample(bb, traceNodes, trace, errModel, incarnationOriginMap);
+ }
+ }
+ }
+
+ return null;
+
+ // Debug.Fail("Could not find failing node.");
+ // throw new Microsoft.Contracts.AssertException();
+ }
+
+
+ static void /*return printable error!*/ ApplyEnhancedErrorPrintingStrategy (Bpl.Expr! expr, Hashtable /*Variable -> Expr*/! incarnationMap, MiningStrategy errorDataEnhanced, ErrorModel! errModel, Dictionary<Expr!, object>! exprToPrintableValue, List<string!>! relatedInformation, bool printInternalStateDumpOnce, Dictionary<Incarnation, Absy!>! incarnationOriginMap) {
+ if (errorDataEnhanced is ListOfMiningStrategies) {
+ ListOfMiningStrategies loms = (ListOfMiningStrategies) errorDataEnhanced;
+ List<MiningStrategy>! l = loms.msList;
+ for (int i = 0; i < l.Count; i++) {
+ MiningStrategy ms = l[i];
+ if (ms != null) {
+ ApplyEnhancedErrorPrintingStrategy(expr, incarnationMap, l[i], errModel, exprToPrintableValue, relatedInformation, false, incarnationOriginMap);
+ }
+ }
+ }
+ else if (errorDataEnhanced is EEDTemplate /*EDEverySubExpr*/) {
+ EEDTemplate eedT = (EEDTemplate) errorDataEnhanced;
+ string reason = eedT.reason;
+ List<Bpl.Expr!> listOfExprs = eedT.exprList;
+ if (listOfExprs != null) {
+ List<string> holeFillers = new List<string>();
+ for (int i = 0; i < listOfExprs.Count; i++) {
+ bool alreadySet = false;
+ foreach (KeyValuePair<Bpl.Expr!, object> kvp in exprToPrintableValue) {
+ Bpl.Expr! e = kvp.Key;
+ Bpl.Expr! f = listOfExprs[i];
+ // the strings are compared instead of the actual expressions because
+ // the expressions might not be identical, but their print-out strings will be
+ if (e.ToString() == f.ToString()) {
+ object o = kvp.Value;
+ if (o != null) {
+ holeFillers.Add(o.ToString());
+ alreadySet = true;
+ break;
+ }
+ }
+ }
+ if (!alreadySet) {
+ // no information about that Expression found, so put in <unknown>
+ holeFillers.Add("<unknown>");
+ }
+ }
+ reason = FormatReasonString(reason, holeFillers);
+ }
+ if (reason != null) {
+ relatedInformation.Add("(related information): "+reason);
+ }
+ } else {
+ // define new templates here!
+ }
+
+ if (printInternalStateDumpOnce) {
+ ComputeAndTreatHeapSuccessions(incarnationMap, errModel, incarnationOriginMap, relatedInformation);
+
+ // default action: print all values!
+ foreach (KeyValuePair<Bpl.Expr!, object> kvp in exprToPrintableValue) {
+ object o = kvp.Value;
+ if (o != null) {
+ // We do not want to print LiteralExprs because that gives things like 0 == 0.
+ // If both arguments to the string.Format are the same it is also useless,
+ // as that would print e.g. $a == $a.
+ if (!(kvp.Key is LiteralExpr)&& kvp.Key.ToString() != o.ToString()) {
+ string boogieExpr;
+ // check whether we are handling BPL or SSC input
+ if (CommandLineOptions.Clo.RunningBoogieOnSsc) {
+ boogieExpr = Helpers.PrettyPrintBplExpr(kvp.Key);
+ } else {
+ boogieExpr = kvp.Key.ToString();
+ }
+ relatedInformation.Add("(internal state dump): "+string.Format("{0} == {1}", boogieExpr, o));
+ }
+ }
+ }
+ }
+ }
+
+ static void ComputeAndTreatHeapSuccessions(System.Collections.Hashtable! incarnationMap, ErrorModel! errModel, Dictionary<Incarnation, Absy!>! incarnationOriginMap, List<string!>! relatedInformation) {
+ List<int> heapSuccList = ComputeHeapSuccessions(incarnationMap, errModel);
+ TreatHeapSuccessions(heapSuccList, incarnationMap, errModel, incarnationOriginMap, relatedInformation);
+ }
+
+ static List<int> ComputeHeapSuccessions(System.Collections.Hashtable! incarnationMap, ErrorModel! errModel) {
+ // find the heap variable
+ Variable heap = null;
+ ICollection ic = incarnationMap.Keys;
+ foreach (object o in ic) {
+ if (o is GlobalVariable) {
+ GlobalVariable gv = (GlobalVariable) o;
+ if (gv.Name == "$Heap") {
+ heap = gv;
+ }
+ }
+ }
+ List<int> heapIdSuccession = new List<int>();
+ if (heap == null) {
+ // without knowing the name of the current heap we cannot create a heap succession!
+ } else {
+ object oHeap = incarnationMap[heap];
+ if (oHeap != null) {
+ string currentHeap = oHeap.ToString();
+ int currentHeapId;
+ if (errModel.identifierToPartition.TryGetValue(currentHeap, out currentHeapId)) {
+ while (currentHeapId != -1) {
+ if (!heapIdSuccession.Contains(currentHeapId)) {
+ heapIdSuccession.Add(currentHeapId);
+ currentHeapId = ComputePredecessorHeapId(currentHeapId, errModel);
+ } else {
+ // looping behavior, just stop here and do not add this value (again!)
+ break;
+ }
+ }
+ }
+ }
+ }
+ if (heapIdSuccession.Count > 0) {
+ int heapId = heapIdSuccession[heapIdSuccession.Count-1];
+ List<string!> strl = errModel.partitionToIdentifiers[heapId];
+ if (strl != null && strl.Contains("$Heap")) {
+ // we have a proper succession of heaps that starts with $Heap
+ return heapIdSuccession;
+ } else {
+ // no proper heap succession, not starting with $Heap!
+ return null;
+ }
+ } else {
+ // no heap succession found because either the $Heap does not have a current incarnation
+ // or because (unlikely!) the model is somehow messed up
+ return null;
+ }
+ }
+
+ static int ComputePredecessorHeapId(int id, ErrorModel! errModel) {
+ //check "$HeapSucc" and "store2" functions:
+ List<int> heapSuccPredIdList = new List<int>();
+ List<List<int>> heapSuccFunc;
+ errModel.definedFunctions.TryGetValue("$HeapSucc", out heapSuccFunc);
+ if (heapSuccFunc != null) {
+ foreach (List<int> heapSuccFuncDef in heapSuccFunc) {
+ // do not look at the else case of the function def, so check .Count
+ if (heapSuccFuncDef != null && heapSuccFuncDef.Count == 3 && heapSuccFuncDef[1] == id) {
+ // make sure each predecessor is put into the list at most once
+ if (!heapSuccPredIdList.Contains(heapSuccFuncDef[0])) {
+ heapSuccPredIdList.Add(heapSuccFuncDef[0]);
+ }
+ }
+ }
+ }
+ List<int> store2PredIdList = new List<int>();;
+ List<List<int>> store2Func;
+ errModel.definedFunctions.TryGetValue("store2", out store2Func);
+ if (store2Func != null) {
+ foreach (List<int> store2FuncDef in store2Func) {
+ // do not look at the else case of the function def, so check .Count
+ if (store2FuncDef != null && store2FuncDef.Count == 5 && store2FuncDef[4] == id) {
+ // make sure each predecessor is put into the list at most once
+ if (!store2PredIdList.Contains(store2FuncDef[0])) {
+ store2PredIdList.Add(store2FuncDef[0]);
+ }
+ }
+ }
+ }
+ if (heapSuccPredIdList.Count + store2PredIdList.Count > 0) {
+ if (store2PredIdList.Count == 1) {
+ return store2PredIdList[0];
+ } else if (store2PredIdList.Count == 0) {
+ if (heapSuccPredIdList.Count == 1) {
+ return heapSuccPredIdList[0];
+ } else { //(heapSuccPredIdList.Count > 1)
+ if (heapSuccPredIdList.Count == 2) {
+ // if one of the 2 is a self-loop, take the other!
+ if (heapSuccPredIdList[0] == id) {
+ return heapSuccPredIdList[1];
+ } else if (heapSuccPredIdList[1] == id) {
+ return heapSuccPredIdList[0];
+ } else {
+ //no self-loop, two different predecessors, cannot choose
+ return -1;
+ }
+ } else {
+ // at least 3 different predecessors available, one of them could be a self-loop, but
+ // we cannot choose between the other 2 (or more) candidates
+ return -1;
+ }
+ }
+ } else {
+ // more than one result in the succession coming from store2, no way
+ // to decide which is right, end here
+ return -1;
+ }
+ } else {
+ // no predecessor found
+ return -1;
+ }
+ }
+
+ static void TreatHeapSuccessions (List<int> heapSuccessionList, System.Collections.Hashtable! incarnationMap, ErrorModel! errModel, Dictionary<Incarnation, Absy!>! incarnationOriginMap, List<string!>! relatedInformation) {
+ if (heapSuccessionList == null) {
+ // empty list of heap successions, nothing we can do!
+ return;
+ }
+ // primarily look for $o and $f (with skolem-id stuff) and then look where they were last changed!
+ // find the o and f variables
+ Variable dollarO = null;
+ Variable dollarF = null;
+ ICollection ic = incarnationMap.Keys;
+ foreach (object o in ic) {
+ if (o is BoundVariable) {
+ BoundVariable bv = (BoundVariable) o;
+ if (bv.Name == "$o") {
+ dollarO = bv;
+ }
+ else if (bv.Name == "$f") {
+ dollarF = bv;
+ }
+ }
+ }
+ if (dollarO == null || dollarF == null) {
+ // without knowing the name of the current incarnation of $Heap, $o and $f we don't do anything here
+ } else {
+ object objO = incarnationMap[dollarO];
+ object objF = incarnationMap[dollarF];
+ if (objO != null && objF != null) {
+ int zidO = errModel.identifierToPartition[objO.ToString()];
+ int zidF = errModel.identifierToPartition[objF.ToString()];
+
+ List<List<int>> select2Func = null;
+ if (errModel.definedFunctions.TryGetValue("select2", out select2Func) && select2Func != null) {
+ // check for all changes to $o.$f!
+ List<int> heapsChangedOFZid = new List<int>();
+ int oldValueZid = -1;
+ int newValueZid = -1;
+
+ for (int i = 0; i < heapSuccessionList.Count; i++) {
+ bool foundValue = false;
+ foreach (List<int> f in select2Func) {
+ if (f != null && f.Count == 4 && f[0] == heapSuccessionList[i] && f[1] == zidO && f[2] == zidF) {
+ newValueZid = f[3];
+ foundValue = true;
+ break;
+ }
+ }
+ if (!foundValue) {
+ // get default of the function once Leo&Nikolaj have changed it so the default is type correct
+ // for now treat it as a -1 !
+ // the last element of select2Func is the else case, it has only 1 element, so grab that:
+ // newValueZid = (select2Func[select2Func.Count-1])[0];
+ newValueZid = -1;
+ }
+
+ if (oldValueZid != newValueZid) {
+ // there was a change here, record that in the list:
+ if (oldValueZid != -1) {
+ // don't record a change at the "initial" location, which refers to the $Heap in
+ // its current incarnation, and is marked by the oldValueZid being uninitialized
+ heapsChangedOFZid.Add(heapSuccessionList[i-1]);
+ }
+ oldValueZid = newValueZid;
+ }
+ }
+
+ foreach (int id in heapsChangedOFZid) {
+ //get the heap name out of the errModel for this zid:
+ List<string!> l = errModel.partitionToIdentifiers[id];
+ List<string!> heaps = new List<string!>();
+ if (l!=null) {
+ foreach (string s in l) {
+ if (s.StartsWith("$Heap")) {
+ heaps.Add(s);
+ }
+ }
+ }
+ // easy case first:
+ if (heaps.Count == 1) {
+ string heapName = heaps[0];
+ // we have a string with the name of the heap, but we need to get the
+ // source location out of a map that uses Incarnations!
+
+ ICollection incOrgMKeys = incarnationOriginMap.Keys;
+ foreach (Incarnation inc in incOrgMKeys) {
+ if (inc!= null) {
+ if (inc.Name == heapName) {
+ Absy source = null;
+ incarnationOriginMap.TryGetValue(inc, out source);
+ if (source != null) {
+ if (source is Block) {
+ Block b = (Block) source;
+ string fileName = b.tok.filename;
+ if (fileName != null) {
+ fileName = fileName.Substring(fileName.LastIndexOf('\\') + 1);
+ }
+ relatedInformation.Add("(related information): Changed $o.$f here: " + fileName + "(" + b.tok.line + "," + b.tok.col + ")");
+ } else if (source is Cmd) {
+ Cmd c = (Cmd) source;
+ string fileName = c.tok.filename;
+ if (fileName != null) {
+ fileName = fileName.Substring(fileName.LastIndexOf('\\') + 1);
+ }
+ relatedInformation.Add("(related information) Changed $o.$f here: " + fileName + "(" + c.tok.line + "," + c.tok.col + ")");
+ } else {
+ assert false;
+ }
+ }
+ }
+ }
+ }
+ } else {
+ // more involved! best use some of the above code and try to synchronize joint parts
+ // here there is more than one "$Heap@i" in the partition, check if they all agree on one
+ // source location or maybe if some of them are joins (i.e. blocks) that should be ignored
+ }
+
+ }
+ }
+ }
+ }
+ }
+
+ static string FormatReasonString (string reason, List<string> holeFillers) {
+ if (holeFillers != null) {
+ // in case all elements of holeFillers are "<unknown>" we can not say anything useful
+ // so just say nothing and return null
+ bool allUnknown = true;
+ foreach (string s in holeFillers) {
+ if (s != "<unknown>") {
+ allUnknown = false;
+ break;
+ }
+ }
+ if (allUnknown) {
+ return null;
+ }
+ string[] a = holeFillers.ToArray();
+ reason = string.Format(reason, a);
+ }
+ return reason;
+ }
+
+ static object ValueFromZID (ErrorModel! errModel, int id) {
+ return ValueFromZID(errModel, id, null);
+ }
+
+ static object ValueFromZID (ErrorModel! errModel, int id, string searchForAlternate) {
+ object o = errModel.partitionToValue[id];
+ if (o != null) {
+ return o;
+ } else {
+ // more elaborate scheme to find something better, as in: look at the identifiers that
+ // this partition maps to, or similar things!
+
+ //treatment for 'null':
+ int idForNull = -1;
+ if (errModel.valueToPartition.TryGetValue("nullObject", out idForNull) && idForNull == id) {
+ return "nullObject";
+ }
+
+ string returnStr = null;
+
+ // "good identifiers" if there is no value found are 'unique consts' or
+ // '$in' parameters; '$in' parameters are treated, unclear how to get 'unique const' info
+ List<string!> identifiers = errModel.partitionToIdentifiers[id];
+ if (identifiers != null) {
+ foreach (string s in identifiers) {
+ //$in parameters are (more) interesting than other identifiers, return the
+ // first one found
+ if (s.EndsWith("$in")) {
+ returnStr = s;
+ break;
+ }
+ }
+ }
+
+ // try to get mappings from one identifier to another if there are exactly
+ // two identifiers in the partition, where one of them is the identifier for which
+ // we search for alternate encodings (third parameter of the method) [or an incarnation
+ // of such an identifier]
+ if (returnStr == null && searchForAlternate != null && identifiers != null && identifiers.Count == 2) {
+ if (identifiers[0] == searchForAlternate || identifiers[0].StartsWith(searchForAlternate + ".sk.")) {
+ returnStr = identifiers[1];
+ } else if (identifiers[1] == searchForAlternate || identifiers[1].StartsWith(searchForAlternate + ".sk.")) {
+ returnStr = identifiers[0];
+ }
+ }
+
+ if (returnStr != null) {
+ return Helpers.BeautifyBplString(returnStr);
+ }
+
+ return null;
+ }
+ }
+
+ static int TreatInterpretedFunction(string! functionName, List<int>! zargs, ErrorModel! errModel) {
+ if (zargs.Count != 2) {
+ //all interpreted functions are binary, so there have to be exactly two arguments
+ return -1;
+ }
+ else {
+ object arg0 = ValueFromZID(errModel, zargs[0]);
+ object arg1 = ValueFromZID(errModel, zargs[1]);
+ if (arg0 is BigNum && arg1 is BigNum) {
+ BigNum arg0i = (BigNum)arg0;
+ BigNum arg1i = (BigNum)arg1;
+ BigNum result;
+ if (functionName == "+") {
+ result = arg0i + arg1i;
+ } else if (functionName == "-") {
+ result = arg0i - arg1i;
+ } else /*if (functionName == "*")*/ {
+ result = arg0i * arg1i;
+ }
+ int returnId = -1;
+ if (errModel.valueToPartition.TryGetValue(result, out returnId)) {
+ return returnId;
+ } else {
+ return -1;
+ }
+ }
+ else {
+ //both arguments need to be integers for this to work!
+ return -1;
+ }
+ }
+ }
+
+ static int TreatFunction (string! functionName, List<int>! zargs, bool undefined, ErrorModel! errModel) {
+ List<List<int>> functionDef;
+ if ((!errModel.definedFunctions.TryGetValue(functionName, out functionDef) && functionName != "+" && functionName != "-" && functionName != "*") || undefined) {
+ // no fitting function found or one of the arguments is undefined
+ return -1;
+ } else {
+ if (functionName == "+" || functionName == "-" || functionName == "*") {
+ return TreatInterpretedFunction(functionName, zargs, errModel);
+ }
+ assert functionDef != null;
+ foreach (List<int> pWiseF in functionDef) {
+ assert pWiseF != null;
+ // else case in the function definition:
+ if (pWiseF.Count == 1) {
+ return pWiseF[0];
+ }
+ // number of arguments is exactly the right number
+ assert zargs.Count == pWiseF.Count - 1;
+ if (forall{int i in (0: zargs.Count); zargs[i] == pWiseF[i]}) {
+ return pWiseF[pWiseF.Count - 1];
+ }
+ }
+ // all functions should have an 'else ->' case defined, therefore this should be
+ // unreachable code!
+ assert false;
+ }
+ }
+
+ //returned int is zID
+ static int GetValuesFromModel (Bpl.Expr! expr, Hashtable /*Variable -> Expr*/! incarnationMap, ErrorModel! errModel, Dictionary<Bpl.Expr!, object>! exprToPrintableValue)
+ modifies exprToPrintableValue.*;
+ {
+ // call GetValuesFromModel on all proper subexpressions, returning their value,
+ // so they only have to be computed once!
+ if (expr is LiteralExpr) {
+ // nothing needs to be added to the exprToPrintableValue map, because e.g. 0 -> 0 is not interesting
+ object o = ((LiteralExpr) expr).Val;
+ if (o == null) {
+ o = "nullObject";
+ }
+ int idForExprVal;
+ if (errModel.valueToPartition.TryGetValue(o, out idForExprVal)) {
+ return idForExprVal;
+ } else {
+ return -1;
+ }
+ }
+ else if (expr is IdentifierExpr) {
+ // if the expression expr is in the incarnation map, then use its incarnation,
+ // otherwise just use the actual expression
+ string s = ((IdentifierExpr) expr).Name;
+ object o = null;
+ Variable v = ((IdentifierExpr) expr).Decl;
+ if (v != null && incarnationMap.ContainsKey(v)) {
+ if (incarnationMap[v] is IdentifierExpr!) {
+ s = ((IdentifierExpr!) incarnationMap[v]).Name;
+ } else if (incarnationMap[v] is LiteralExpr!) {
+ o = ((LiteralExpr!) incarnationMap[v]).Val;
+ }
+ }
+ // if o is not null, then we got a LiteralExpression, that needs separate treatment
+ if (o == null) {
+ // if the expression (respectively its incarnation) is mapped to some partition
+ // then return that id, else return the error code -1
+ if (errModel.identifierToPartition.ContainsKey(s)) {
+ int i = errModel.identifierToPartition[s];
+ // if the key is already in the map we can assume that it is the same map we would
+ // get now and thus just ignore it
+ if (!exprToPrintableValue.ContainsKey(expr)) {
+ exprToPrintableValue.Add(expr, ValueFromZID(errModel, i, ((IdentifierExpr) expr).Name));
+ }
+ return i;
+ } else {
+ return -1;
+ }
+ } else if (errModel.valueToPartition.ContainsKey(o)) {
+ int i = errModel.valueToPartition[o];
+ if (!exprToPrintableValue.ContainsKey(expr))
+ exprToPrintableValue.Add(expr, ValueFromZID(errModel, i));
+ return i;
+ } else {
+ return -1;
+ }
+ }
+ else if (expr is Bpl.NAryExpr) {
+ Bpl.NAryExpr e = (Bpl.NAryExpr)expr;
+ List<int> zargs = new List<int>();
+ bool undefined = false;
+ // do the recursion first
+ foreach (Expr argument in ((NAryExpr) expr).Args) {
+ int zid = -1;
+ if (argument != null) {
+ zid = GetValuesFromModel(argument, incarnationMap, errModel, exprToPrintableValue);
+ }
+ // if one of the arguments is 'undefined' then return -1 ('noZid') for this
+ // but make sure the recursion is complete first1
+ if (zid == -1) {
+ undefined = true;
+ }
+ zargs.Add(zid);
+ }
+ IAppliable! fun = e.Fun;
+ string functionName = fun.FunctionName; // PR: convert to select1, select2, etc in case of a map?
+ // same as IndexedExpr:
+ int id = TreatFunction(functionName, zargs, undefined, errModel);
+ if (id != -1 && !exprToPrintableValue.ContainsKey(expr)) {
+ exprToPrintableValue.Add(expr, ValueFromZID(errModel, id));
+ }
+ return id;
+ }
+ else if (expr is Bpl.OldExpr) {
+ //Bpl.OldExpr e = (Bpl.OldExpr)expr;
+ // We do not know which heap is the old heap and what the latest state change was,
+ // therefore we cannot return anything useful here!
+ return -1;
+ }
+ else if (expr is Bpl.QuantifierExpr) {
+ Bpl.QuantifierExpr q = (Bpl.QuantifierExpr)expr;
+ for (int i = 0; i < q.Dummies.Length; i++) {
+ Bpl.Variable v = q.Dummies[i];
+ if (v != null) {
+ // add to the incarnation map a connection between the bound variable v
+ // of the quantifier and its skolemized incarnation, if available,
+ // i.e., search through the list of identifiers in the model and look for
+ // v.sk.(q.SkolemId), only pick those that are directly associated to a value
+ // DISCLAIMER: of course it is very well possible that one of these incarnations
+ // could be used without actually having a value, but it seems better to pick those
+ // with a value, that is they are more likely to contribute useful information to
+ // the output
+ List<Bpl.IdentifierExpr!> quantVarIncarnationList = new List<Bpl.IdentifierExpr!>();
+ List<int> incarnationZidList = new List<int>();
+ int numberOfNonNullValueIncarnations = 0;
+ for (int j = 0; j < errModel.partitionToIdentifiers.Count; j++){
+ List<string!> pti = errModel.partitionToIdentifiers[j];
+ if (pti != null) {
+ for (int k = 0; k < pti.Count; k++) {
+ // look for v.sk.(q.SkolemId)
+ // if there is more than one look at if there is exactly one with a non-null value
+ // associated, see above explanation
+ if (pti[k].StartsWith(v + ".sk." + q.SkolemId) &&
+ errModel.partitionToValue[errModel.identifierToPartition[pti[k]]] != null) {
+ quantVarIncarnationList.Add(new Bpl.IdentifierExpr(Bpl.Token.NoToken, pti[k], new Bpl.UnresolvedTypeIdentifier(Token.NoToken, "TName")));
+ incarnationZidList.Add(j);
+ if (errModel.partitionToValue[errModel.identifierToPartition[pti[k]]] != null) {
+ numberOfNonNullValueIncarnations++;
+ }
+ }
+ }
+ }
+ }
+ // only one such variable found, associate it with v
+ if (quantVarIncarnationList.Count == 1) {
+ incarnationMap[v] = quantVarIncarnationList[0];
+ } else if (quantVarIncarnationList.Count > 1 && numberOfNonNullValueIncarnations == 1) {
+ // if there are multiple candidate incarnations and exactly one of them has a value
+ // we can pick that one; otherwise it is not clear how to pick one out of multiple
+ // incarnations without a value or out of multiple incarnations with a value associated
+ for (int n = 0; n < incarnationZidList.Count; n++) {
+ if (errModel.partitionToValue[incarnationZidList[n]] != null) {
+ // quantVarIncarnationList and incarnationZidList are indexed in lockstep, so if
+ // for the associated zid the partitionToValue map is non-null then that is the one
+ // thus distinguished incarnation we want to put into the incarnationMap
+ incarnationMap[v] = quantVarIncarnationList[n];
+ break;
+ }
+ }
+ }
+ }
+ }
+ // generate the value of the body but do not return that outside
+ GetValuesFromModel(q.Body, incarnationMap, errModel, exprToPrintableValue);
+ // the quantifier cannot contribute any one value to the rest of the
+ // expression, thus just return -1
+ return -1;
+ }
+ else if (expr is Bpl.ExtractExpr) {
+ Bpl.ExtractExpr ex = (Bpl.ExtractExpr) expr;
+ Bpl.Expr e0 = ex.Bitvector;
+ Bpl.Expr e1 = new LiteralExpr(Token.NoToken, BigNum.FromInt(ex.Start));
+ Bpl.Expr e2 = new LiteralExpr(Token.NoToken, BigNum.FromInt(ex.End));
+ string functionName = "$bv_extract";
+ List<int> zargs = new List<int>();
+ bool undefined = false;
+
+ int zid = -1;
+ zid = GetValuesFromModel(e0, incarnationMap, errModel, exprToPrintableValue);
+ if (zid == -1) {
+ undefined = true;
+ }
+ zargs.Add(zid);
+
+ zid = -1;
+ zid = GetValuesFromModel(e1, incarnationMap, errModel, exprToPrintableValue);
+ if (zid == -1) {
+ undefined = true;
+ }
+ zargs.Add(zid);
+
+ zid = -1;
+ zid = GetValuesFromModel(e2, incarnationMap, errModel, exprToPrintableValue);
+ if (zid == -1) {
+ undefined = true;
+ }
+ zargs.Add(zid);
+
+ //same as NAryExpr:
+ int id = TreatFunction(functionName, zargs, undefined, errModel);
+ if (id != -1 && !exprToPrintableValue.ContainsKey(expr)) {
+ exprToPrintableValue.Add(expr, ValueFromZID(errModel, id));
+ }
+ return id;
+ }
+ else if (expr is Bpl.BvConcatExpr) {
+ // see comment above
+ Bpl.BvConcatExpr bvc = (Bpl.BvConcatExpr) expr;
+ string functionName = "$bv_concat";
+ List<int> zargs = new List<int>();
+ bool undefined = false;
+
+ int zid = -1;
+ zid = GetValuesFromModel(bvc.E0, incarnationMap, errModel, exprToPrintableValue);
+ if (zid == -1) {
+ undefined = true;
+ }
+ zargs.Add(zid);
+
+ zid = -1;
+ zid = GetValuesFromModel(bvc.E0, incarnationMap, errModel, exprToPrintableValue);
+ if (zid == -1) {
+ undefined = true;
+ }
+ zargs.Add(zid);
+
+ //same as NAryExpr:
+ int id = TreatFunction(functionName, zargs, undefined, errModel);
+ if (id != -1 && !exprToPrintableValue.ContainsKey(expr)) {
+ exprToPrintableValue.Add(expr, ValueFromZID(errModel, id));
+ }
+ return id;
+ }
+ else {
+ assert false; // unexpected Bpl.Expr
+ }
+ return -1;
+ }
+
+ static Counterexample! AssertCmdToCounterexample (AssertCmd! cmd, TransferCmd! transferCmd, BlockSeq! trace, ErrorModel errModel, Dictionary<Incarnation, Absy!>! incarnationOriginMap) {
+ List<string!>! relatedInformation = new List<string!>();
+ if (CommandLineOptions.Clo.EnhancedErrorMessages == 1) {
+ if (cmd.OrigExpr != null && cmd.IncarnationMap != null && errModel != null) {
+
+ // get all possible information first
+ Dictionary<Expr!, object> exprToPrintableValue = new Dictionary<Expr!, object>();
+ GetValuesFromModel(cmd.OrigExpr, cmd.IncarnationMap, errModel, exprToPrintableValue);
+ // then apply the strategies
+ ApplyEnhancedErrorPrintingStrategy(cmd.OrigExpr, cmd.IncarnationMap, cmd.ErrorDataEnhanced, errModel, exprToPrintableValue, relatedInformation, true, incarnationOriginMap);
+ }
+ }
+
+ // See if it is a special assert inserted in translation
+ if (cmd is AssertRequiresCmd)
+ {
+ AssertRequiresCmd! assertCmd = (AssertRequiresCmd)cmd;
+ CallCounterexample cc = new CallCounterexample(trace, assertCmd.Call, assertCmd.Requires);
+ cc.relatedInformation = relatedInformation;
+ return cc;
+ }
+ else if (cmd is AssertEnsuresCmd)
+ {
+ AssertEnsuresCmd! assertCmd = (AssertEnsuresCmd)cmd;
+ ReturnCounterexample rc = new ReturnCounterexample(trace, transferCmd, assertCmd.Ensures);
+ rc.relatedInformation = relatedInformation;
+ return rc;
+ }
+ else
+ {
+ AssertCounterexample ac = new AssertCounterexample(trace, (AssertCmd)cmd);
+ ac.relatedInformation = relatedInformation;
+ return ac;
+ }
+ }
+
+// static void EmitImpl(Implementation! impl, bool printDesugarings) {
+// int oldPrintUnstructured = CommandLineOptions.Clo.PrintUnstructured;
+// CommandLineOptions.Clo.PrintUnstructured = 2; // print only the unstructured program
+// bool oldPrintDesugaringSetting = CommandLineOptions.Clo.PrintDesugarings;
+// CommandLineOptions.Clo.PrintDesugarings = printDesugarings;
+// impl.Emit(new TokenTextWriter("<console>", Console.Out, false), 0);
+// CommandLineOptions.Clo.PrintDesugarings = oldPrintDesugaringSetting;
+// CommandLineOptions.Clo.PrintUnstructured = oldPrintUnstructured;
+// }
+
+ static VCExpr! LetVC(Block! startBlock,
+ Hashtable/*<int, Absy!>*/! label2absy,
+ ProverContext! proverCtxt)
+ {
+ Hashtable/*<Block, LetVariable!>*/! blockVariables = new Hashtable/*<Block, LetVariable!!>*/();
+ List<VCExprLetBinding!>! bindings = new List<VCExprLetBinding!>();
+ VCExpr startCorrect = LetVC(startBlock, label2absy, blockVariables, bindings, proverCtxt);
+ return proverCtxt.ExprGen.Let(bindings, startCorrect);
+ }
+
+ static VCExpr! LetVC(Block! block,
+ Hashtable/*<int, Absy!>*/! label2absy,
+ Hashtable/*<Block, VCExprVar!>*/! blockVariables,
+ List<VCExprLetBinding!>! bindings,
+ ProverContext! proverCtxt)
+ {
+ VCExpressionGenerator! gen = proverCtxt.ExprGen;
+ VCExprVar v = (VCExprVar)blockVariables[block];
+ if (v == null) {
+ /*
+ * For block A (= block), generate:
+ * LET_binding A_correct = wp(A_body, (/\ S \in Successors(A) :: S_correct))
+ * with the side effect of adding the let bindings to "bindings" for any
+ * successor not yet visited.
+ */
+ VCExpr SuccCorrect;
+ GotoCmd gotocmd = block.TransferCmd as GotoCmd;
+ if (gotocmd == null) {
+ SuccCorrect = VCExpressionGenerator.True;
+ } else {
+ assert gotocmd.labelTargets != null;
+ List<VCExpr!> SuccCorrectVars = new List<VCExpr!>(gotocmd.labelTargets.Length);
+ foreach (Block! successor in gotocmd.labelTargets) {
+ VCExpr s = LetVC(successor, label2absy, blockVariables, bindings, proverCtxt);
+ SuccCorrectVars.Add(s);
+ }
+ SuccCorrect = gen.NAry(VCExpressionGenerator.AndOp, SuccCorrectVars);
+ }
+
+ VCContext context = new VCContext(label2absy, proverCtxt);
+ VCExpr vc = Wlp.Block(block, SuccCorrect, context);
+
+ v = gen.Variable(block.Label + "_correct", Bpl.Type.Bool);
+ bindings.Add(gen.LetBinding(v, vc));
+ blockVariables.Add(block, v);
+ }
+ return v;
+ }
+
+ static VCExpr! DagVC(Block! block,
+ Hashtable/*<int, Absy!>*/! label2absy,
+ Hashtable/*<Block, VCExpr!>*/! blockEquations,
+ ProverContext! proverCtxt)
+ {
+ VCExpressionGenerator! gen = proverCtxt.ExprGen;
+ VCExpr vc = (VCExpr)blockEquations[block];
+ if (vc != null) {
+ return vc;
+ }
+
+ /*
+ * For block A (= block), generate:
+ * wp(A_body, (/\ S \in Successors(A) :: DagVC(S)))
+ */
+ VCExpr SuccCorrect = null;
+ GotoCmd gotocmd = block.TransferCmd as GotoCmd;
+ if (gotocmd != null)
+ {
+ foreach (Block! successor in (!)gotocmd.labelTargets) {
+ VCExpr c = DagVC(successor, label2absy, blockEquations, proverCtxt);
+ SuccCorrect = SuccCorrect == null ? c : gen.And(SuccCorrect, c);
+ }
+ }
+ if (SuccCorrect == null) {
+ SuccCorrect = VCExpressionGenerator.True;
+ }
+
+ VCContext context = new VCContext(label2absy, proverCtxt);
+ vc = Wlp.Block(block, SuccCorrect, context);
+
+ // gen.MarkAsSharedFormula(vc); PR: don't know yet what to do with this guy
+
+ blockEquations.Add(block, vc);
+ return vc;
+ }
+
+ static VCExpr! FlatBlockVC(Implementation! impl,
+ Hashtable/*<int, Absy!>*/! label2absy,
+ bool local, bool reach, bool doomed,
+ ProverContext! proverCtxt)
+ requires local ==> !reach; // "reach" must be false for local
+ {
+ VCExpressionGenerator! gen = proverCtxt.ExprGen;
+ Hashtable/* Block --> VCExprVar */ BlkCorrect = BlockVariableMap(impl.Blocks, "_correct", gen);
+ Hashtable/* Block --> VCExprVar */ BlkReached = reach ? BlockVariableMap(impl.Blocks, "_reached", gen) : null;
+
+ List<Block!> blocks = impl.Blocks;
+ // block sorting is now done on the VCExpr
+ // if (!local && ((!)CommandLineOptions.Clo.TheProverFactory).NeedsBlockSorting) {
+ // blocks = SortBlocks(blocks);
+ // }
+
+ VCExpr proofObligation;
+ if (!local) {
+ proofObligation = (VCExprVar!)BlkCorrect[impl.Blocks[0]];
+ } else {
+ List<VCExpr!> conjuncts = new List<VCExpr!>(blocks.Count);
+ foreach (Block! b in blocks) {
+ VCExpr v = (VCExprVar!)BlkCorrect[b];
+ conjuncts.Add(v);
+ }
+ proofObligation = gen.NAry(VCExpressionGenerator.AndOp, conjuncts);
+ }
+
+ VCContext! context = new VCContext(label2absy, proverCtxt);
+
+ List<VCExprLetBinding!> programSemantics = new List<VCExprLetBinding!>(blocks.Count);
+ foreach (Block! b in blocks) {
+ /*
+ * In block mode,
+ * For a return block A, generate:
+ * A_correct <== wp(A_body, true) [post-condition has been translated into an assert]
+ * For all other blocks, generate:
+ * A_correct <== wp(A_body, (/\ S \in Successors(A) :: S_correct))
+ *
+ * In doomed mode, proceed as in block mode, except for a return block A, generate:
+ * A_correct <== wp(A_body, false) [post-condition has been translated into an assert]
+ *
+ * In block reach mode, the wp(A_body,...) in the equations above change to:
+ * A_reached ==> wp(A_body,...)
+ * and the conjunction above changes to:
+ * (/\ S \in Successors(A) :: S_correct \/ (\/ T \in Successors(A) && T != S :: T_reached))
+ *
+ * In local mode, generate:
+ * A_correct <== wp(A_body, true)
+ */
+ VCExpr! SuccCorrect;
+ if (local) {
+ SuccCorrect = VCExpressionGenerator.True;
+ } else {
+ SuccCorrect = SuccessorsCorrect(b, BlkCorrect, BlkReached, doomed, gen);
+ }
+
+ VCExpr wlp = Wlp.Block(b, SuccCorrect, context);
+ if (BlkReached != null) {
+ wlp = gen.Implies((VCExprVar!)BlkReached[b], wlp);
+ }
+
+ VCExprVar okVar = (VCExprVar!)BlkCorrect[b];
+ VCExprLetBinding binding = gen.LetBinding(okVar, wlp);
+ programSemantics.Add(binding);
+ }
+
+ return gen.Let(programSemantics, proofObligation);
+ }
+
+ private static Hashtable/* Block --> VCExprVar */! BlockVariableMap(List<Block!>! blocks, string! suffix,
+ Microsoft.Boogie.VCExpressionGenerator! gen)
+ {
+ Hashtable/* Block --> VCExprVar */ map = new Hashtable/* Block --> (Let)Variable */();
+ foreach (Block! b in blocks)
+ {
+ VCExprVar! v = gen.Variable(b.Label+suffix, Bpl.Type.Bool);
+ map.Add(b, v);
+ }
+ return map;
+ }
+
+ private static VCExpr! SuccessorsCorrect(
+ Block! b,
+ Hashtable/* Block --> VCExprVar */! BlkCorrect,
+ Hashtable/* Block --> VCExprVar */ BlkReached,
+ bool doomed,
+ Microsoft.Boogie.VCExpressionGenerator! gen)
+ {
+ VCExpr SuccCorrect = null;
+ GotoCmd gotocmd = b.TransferCmd as GotoCmd;
+ if (gotocmd != null)
+ {
+ foreach (Block! successor in (!)gotocmd.labelTargets)
+ {
+ // c := S_correct
+ VCExpr c = (VCExprVar!)BlkCorrect[successor];
+ if (BlkReached != null)
+ {
+ // c := S_correct \/ Sibling0_reached \/ Sibling1_reached \/ ...;
+ foreach (Block! successorSibling in gotocmd.labelTargets)
+ {
+ if (successorSibling != successor)
+ {
+ c = gen.Or(c, (VCExprVar!)BlkReached[successorSibling]);
+ }
+ }
+ }
+ SuccCorrect = SuccCorrect == null ? c : gen.And(SuccCorrect, c);
+ }
+ }
+ if (SuccCorrect == null) {
+ return VCExpressionGenerator.True;
+ } else if (doomed) {
+ return VCExpressionGenerator.False;
+ } else {
+ return SuccCorrect;
+ }
+ }
+
+ static VCExpr! NestedBlockVC(Implementation! impl,
+ Hashtable/*<int, Absy!>*/! label2absy,
+ bool reach,
+ ProverContext! proverCtxt)
+ requires impl.Blocks.Count != 0;
+ {
+ VCExpressionGenerator! gen = proverCtxt.ExprGen;
+ Graph<Block>! g = GraphFromImpl(impl);
+
+ Hashtable/* Block --> VCExprVar */ BlkCorrect = BlockVariableMap(impl.Blocks, "_correct", gen);
+ Hashtable/* Block --> VCExprVar */ BlkReached = reach ? BlockVariableMap(impl.Blocks, "_reached", gen) : null;
+
+ Block! startBlock = (!) impl.Blocks[0];
+ VCExpr proofObligation = (VCExprVar!)BlkCorrect[startBlock];
+
+ VCContext! context = new VCContext(label2absy, proverCtxt);
+
+ Hashtable/*Block->int*/ totalOrder = new Hashtable/*Block->int*/();
+ {
+ List<Block!> blocks = impl.Blocks;
+ // block sorting is now done on the VCExpr
+ // if (((!)CommandLineOptions.Clo.TheProverFactory).NeedsBlockSorting) {
+ // blocks = SortBlocks(blocks);
+ // }
+ int i = 0;
+ foreach (Block b in blocks) {
+ totalOrder[b] = i;
+ i++;
+ }
+ }
+
+ VCExprLetBinding programSemantics = NestedBlockEquation((!)impl.Blocks[0], BlkCorrect, BlkReached, totalOrder, context, g, gen);
+ List<VCExprLetBinding!> ps = new List<VCExprLetBinding!>(1);
+ ps.Add(programSemantics);
+
+ return gen.Let(ps, proofObligation);
+ }
+
+ private static VCExprLetBinding! NestedBlockEquation(Block! b,
+ Hashtable/*Block-->VCExprVar*/! BlkCorrect,
+ Hashtable/*Block-->VCExprVar*/ BlkReached,
+ Hashtable/*Block->int*/! totalOrder,
+ VCContext! context,
+ Graph<Block>! g,
+ Microsoft.Boogie.VCExpressionGenerator! gen)
+ {
+ /*
+ * For a block b, return:
+ * LET_BINDING b_correct = wp(b_body, X)
+ * where X is:
+ * LET (THOSE d \in DirectDominates(b) :: BlockEquation(d))
+ * IN (/\ s \in Successors(b) :: s_correct)
+ *
+ * When the VC-expression generator does not support LET expresions, this
+ * will eventually turn into:
+ * b_correct <== wp(b_body, X)
+ * where X is:
+ * (/\ s \in Successors(b) :: s_correct)
+ * <==
+ * (/\ d \in DirectDominatees(b) :: BlockEquation(d))
+ *
+ * In both cases above, if BlkReached is non-null, then the wp expression
+ * is instead:
+ * b_reached ==> wp(b_body, X)
+ */
+
+ VCExpr! SuccCorrect = SuccessorsCorrect(b, BlkCorrect, null, false, gen);
+
+ List<VCExprLetBinding!> bindings = new List<VCExprLetBinding!>();
+ foreach (Block! dominee in GetSortedBlocksImmediatelyDominatedBy(g, b, totalOrder))
+ {
+ VCExprLetBinding c = NestedBlockEquation(dominee, BlkCorrect, BlkReached, totalOrder, context, g, gen);
+ bindings.Add(c);
+ }
+
+ VCExpr X = gen.Let(bindings, SuccCorrect);
+ VCExpr wlp = Wlp.Block(b, X, context);
+ if (BlkReached != null) {
+ wlp = gen.Implies((VCExprVar!)BlkReached[b], wlp);
+ }
+ VCExprVar okVar = (VCExprVar!)BlkCorrect[b];
+ return gen.LetBinding(okVar, wlp);
+ }
+
+ /// <summary>
+ /// Returns a list of g.ImmediatelyDominatedBy(b), but in a sorted order, hoping to steer around
+ /// the nondeterminism problems we've been seeing by using just this call.
+ /// </summary>
+ static List<Block!>! GetSortedBlocksImmediatelyDominatedBy(Graph<Block>! g, Block! b, Hashtable/*Block->int*/! totalOrder) {
+ List<Block!> list = new List<Block!>();
+ foreach (Block! dominee in g.ImmediatelyDominatedBy(b)) {
+ list.Add(dominee);
+ }
+ list.Sort(new Comparison<Block!>(delegate (Block! x, Block! y) {return (int)(!)totalOrder[x] - (int)(!)totalOrder[y];} ));
+ return list;
+ }
+
+ static VCExpr! VCViaStructuredProgram
+ (Implementation! impl, Hashtable/*<int, Absy!>*/! label2absy,
+ ProverContext! proverCtxt)
+ {
+ #region Convert block structure back to a "regular expression"
+ RE! r = DAG2RE.Transform((!)impl.Blocks[0]);
+ #endregion
+
+ VCContext! ctxt = new VCContext(label2absy, proverCtxt);
+ #region Send wlp(program,true) to Simplify
+ return Wlp.RegExpr(r, VCExpressionGenerator.True, ctxt);
+ #endregion
+ }
+
+ /// <summary>
+ /// Remove the empty blocks reachable from the block.
+ /// It changes the visiting state of the blocks, so that if you want to visit again the blocks, you have to reset them...
+ /// </summary>
+ static BlockSeq! RemoveEmptyBlocks(Block! b)
+ {
+ assert b.TraversingStatus == Block.VisitState.ToVisit;
+ BlockSeq! retVal = removeEmptyBlocksWorker(b);
+
+ return retVal;
+ }
+
+ private static BlockSeq! removeEmptyBlocksWorker(Block! b)
+ {
+ BlockSeq bs = new BlockSeq();
+ GotoCmd gtc = b.TransferCmd as GotoCmd;
+
+ // b has no successors
+ if (gtc == null || gtc.labelTargets == null || gtc.labelTargets.Length == 0)
+ {
+ if (b.Cmds.Length != 0){ // only empty blocks are removed...
+ bs.Add(b);
+ }
+ return bs;
+ }
+ else if(b.TraversingStatus == Block.VisitState.ToVisit) // if b has some successors and we have not seen it so far...
+ {
+ b.TraversingStatus = Block.VisitState.BeingVisited;
+
+ // recursively call this method on each successor
+ // merge result into a *set* of blocks
+ Dictionary<Block,bool> mergedSuccessors = new Dictionary<Block,bool>();
+ foreach (Block! dest in gtc.labelTargets){
+ BlockSeq! ys = removeEmptyBlocksWorker(dest);
+ foreach (Block successor in ys){
+ if (!mergedSuccessors.ContainsKey(successor))
+ mergedSuccessors.Add(successor,true);
+ }
+ }
+ b.TraversingStatus = Block.VisitState.AlreadyVisited;
+
+ BlockSeq setOfSuccessors = new BlockSeq();
+ if (mergedSuccessors.Keys != null)
+ {
+ foreach (Block d in mergedSuccessors.Keys)
+ setOfSuccessors.Add(d);
+ }
+ if (b.Cmds.Length == 0)
+ return setOfSuccessors;
+ // otherwise, update the list of successors of b to be the blocks in setOfSuccessors
+ gtc.labelTargets = setOfSuccessors;
+ gtc.labelNames = new StringSeq();
+ foreach (Block! d in setOfSuccessors)
+ gtc.labelNames.Add(d.Label);
+ return new BlockSeq(b);
+ }
+ else // b has some successors, but we are already visiting it, or we have already visited it...
+ {
+ return new BlockSeq(b);
+ }
+ }
+
+ static Graph<Block>! GraphFromImpl(Implementation! impl) {
+ Graph<Block>! g = new Graph<Block>();
+ g.AddSource((!)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;
+ if (gtc != null)
+ {
+ foreach (Block! dest in (!)gtc.labelTargets)
+ {
+ g.AddEdge(b,dest);
+ }
+ }
+ }
+ return g;
+ }
+
+
+ static void DumpMap(Hashtable /*Variable->Expr*/! map) {
+ foreach (DictionaryEntry de in map) {
+ Variable! v = (Variable!)de.Key;
+ Expr! e = (Expr!)de.Value;
+ Console.Write(" ");
+ v.Emit(new TokenTextWriter("<console>", Console.Out, false), 0);
+ Console.Write(" --> ");
+ e.Emit(new TokenTextWriter("<console>", Console.Out, false));
+ Console.WriteLine();
+ }
+ }
+ }
+}
diff --git a/Source/VCGeneration/VCDoomed.ssc b/Source/VCGeneration/VCDoomed.ssc
new file mode 100644
index 00000000..0706bf2f
--- /dev/null
+++ b/Source/VCGeneration/VCDoomed.ssc
@@ -0,0 +1,817 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Threading;
+using System.IO;
+using Microsoft.Boogie;
+using Graphing;
+using AI = Microsoft.AbstractInterpretationFramework;
+using Microsoft.Contracts;
+using Microsoft.Basetypes;
+using Microsoft.Boogie.VCExprAST;
+
+namespace VC
+{
+ public class DCGen : ConditionGeneration
+ {
+
+ private Dictionary<Block, Variable!>! m_BlockReachabilityMap;
+
+
+ /// <summary>
+ /// Constructor. Initializes the theorem prover.
+ /// </summary>
+ public DCGen(Program! program, string/*?*/ logFilePath, bool appendLogFile)
+ {
+ base(program);
+ this.appendLogFile = appendLogFile;
+ this.logFilePath = logFilePath;
+ m_BlockReachabilityMap = new Dictionary<Block, Variable!>();
+ }
+
+ private class DummyErrorHandler : ProverInterface.ErrorHandler
+ {
+ public override void OnModel(IList<string!>! labels, ErrorModel errModel)
+ {}
+ public override void OnResourceExceeded(string! message)
+ {}
+ public override Absy! Label2Absy(string! label)
+ {
+ Absy! a = new Block();
+ return a;
+ }
+ }
+
+ /// <summary>
+ /// MSchaef: Todo: Write a good Comment
+ /// </summary>
+ public override Outcome VerifyImplementation(Implementation! impl, Program! program, VerifierCallback! callback)
+ throws UnexpectedProverOutputException;
+ {
+ // MSchaef: Just a Hack, errh is not used in this context, but required by the checker
+ DummyErrorHandler errh = new DummyErrorHandler();
+ callback.OnProgress("Whatever this stands for",0,0,0);
+ #region Transform the Program into loop-free passive form
+ variable2SequenceNumber = new Hashtable/*Variable -> int*/();
+ incarnationOriginMap = new Dictionary<Incarnation, Absy!>();
+ List<Block!>! cblocks = new List<Block!>();
+
+ impl.Blocks = DCProgramTransformer.Convert2Dag(impl, program, cblocks);
+ ComputePredecessors(impl.Blocks);
+
+ m_BlockReachabilityMap = new Dictionary<Block, Variable!>();
+ PassifyProgram(impl, program);
+ #endregion
+
+ Checker! checker = FindCheckerFor(impl, 1000);
+// Checker! checker = new Checker(this, program, logFilePath, false, impl, 1000);
+
+ Hashtable label2absy;
+ VCExpr! vc = GenerateEVC(impl, out label2absy, checker);
+
+ checker.PushVCExpr(vc);
+
+
+ foreach (Block! b in impl.Blocks)
+ {
+ #region Find out if one needs to check this one, or if the error is propagated (HACK)
+ if (!cblocks.Contains(b)) continue;
+
+ bool _needscheck = false;
+ foreach (Block! b_ in b.Predecessors)
+ {
+ GotoCmd gtc = b_.TransferCmd as GotoCmd;
+ if (gtc!=null && gtc.labelTargets!=null && gtc.labelTargets.Length>1)
+ {
+ _needscheck=true; break;
+ }
+ }
+ if (!_needscheck) continue;
+ #endregion
+
+ Variable v = null;
+ m_BlockReachabilityMap.TryGetValue(b, out v);
+ assert v!=null;
+
+ VCExpr! currentlabel = checker.TheoremProver.Context.BoogieExprTranslator.LookupVariable(v);
+ checker.BeginCheck(b.Label, currentlabel, errh);
+ WaitHandle[] wh = new WaitHandle[1];
+ ProverInterface.Outcome o = ProverInterface.Outcome.Undetermined;
+
+ wh[0] = checker.ProverDone;
+ WaitHandle.WaitAny(wh);
+ try {
+ o = checker.ReadOutcome();
+ } catch (UnexpectedProverOutputException e)
+ {
+ Console.WriteLine(e.ToString());
+ }
+
+ switch (o)
+ {
+ case ProverInterface.Outcome.Valid:
+ {
+ Console.WriteLine("In Function {0}", impl.Name);
+ Console.WriteLine("\t Block {0} has a guaranteed error!", b.Label);
+ break;
+ }
+ case ProverInterface.Outcome.Invalid:
+ {
+ break;
+ }
+ default:
+ {
+ Console.WriteLine("I'm confused about Block {0}.", b.Label);
+ break;
+ }
+ }
+
+ }
+ checker.Close();
+ return Outcome.Correct;
+ }
+
+ protected Hashtable/*TransferCmd->ReturnCmd*/! PassifyImpl(Implementation! impl, Program! program)
+ {
+ return new Hashtable();
+ }
+
+
+ #region Loop Removal
+ /// <summary>
+ /// This class is accessed only via the static method Convert2Dag
+ /// It converts the program into a loopfree one by unrolling the loop threetimes and adding the appropriate havoc
+ /// statements. The first and the last unrolling represent the first and last iteration of the loop. The second
+ /// unrolling stands for any other iteration.
+ /// </summary>
+ private class DCProgramTransformer
+ {
+ public static List<Block!>! Convert2Dag(Implementation! impl, Program! program, List<Block!>! checkableBlocks)
+ {
+ Block! start = impl.Blocks[0];
+ Dictionary<Block,GraphNode!> gd = new Dictionary<Block,GraphNode!>();
+ Set/*Block*/! beingVisited = new Set/*Block*/();
+ GraphNode gStart = GraphNode.ComputeGraphInfo(null, start, gd, beingVisited);
+
+ DCProgramTransformer pt = new DCProgramTransformer(checkableBlocks);
+ pt.LoopUnrolling(gStart, new Dictionary<GraphNode, Block!>(), true, "");
+ pt.Blocks.Reverse();
+
+ return pt.Blocks;
+ }
+
+ List<Block!>! Blocks;
+
+ private List<Block!>! m_checkableBlocks;
+
+
+ DCProgramTransformer(List<Block!>! checkableBlocks)
+ {
+ Blocks = new List<Block!>();
+ m_checkableBlocks = checkableBlocks;
+ }
+
+
+ #region Loop Unrolling Methods
+ private Block! LoopUnrolling(GraphNode! node, Dictionary<GraphNode, Block!>! visited, bool unrollable, String! prefix)
+ {
+ Block newb;
+ if (visited.TryGetValue(node, out newb))
+ {
+ assert newb!=null;
+ return newb;
+ } else
+ {
+ if (node.IsCutPoint)
+ {
+ // compute the loop body and the blocks leaving the loop
+
+ List<GraphNode!>! loopNodes = new List<GraphNode!>();
+ GatherLoopBodyNodes(node, node, loopNodes);
+
+ List<GraphNode!>! exitNodes = GatherLoopExitNodes(loopNodes);
+
+ // Continue Unrolling after the current loop
+ Dictionary<GraphNode, Block!>! _visited = new Dictionary<GraphNode, Block!>();
+ foreach (GraphNode! g in exitNodes)
+ {
+ Block b = LoopUnrolling(g, visited, unrollable, prefix);
+ _visited.Add(g,b);
+ }
+ newb = UnrollCurrentLoop(node, _visited, loopNodes,unrollable, prefix);
+ visited.Add(node,newb);
+ } else
+ {
+ BlockSeq! newSuccs = new BlockSeq();
+ foreach(GraphNode! g in node.Succecessors)
+ {
+ newSuccs.Add( LoopUnrolling(g,visited,unrollable,prefix) );
+ }
+ newb = new Block(node.Block.tok, node.Block.Label + prefix , node.Body, node.Block.TransferCmd);
+ assert newb!=null; assert newb.TransferCmd!=null;
+ if (newSuccs.Length == 0)
+ newb.TransferCmd = new ReturnCmd(newb.TransferCmd.tok);
+ else
+ newb.TransferCmd = new GotoCmd(newb.TransferCmd.tok, newSuccs);
+
+ visited.Add(node, newb);
+ Blocks.Add(newb);
+ if (unrollable)
+ {
+ m_checkableBlocks.Add(newb);
+ }
+ }
+ }
+ assert newb!=null;
+ //newb.checkable = unrollable;
+ return newb;
+ }
+
+ private Block! UnrollCurrentLoop(GraphNode! cutPoint, Dictionary<GraphNode, Block!>! visited,
+ List<GraphNode!>! loopNodes, bool unrollable, String! prefix)
+ {
+ if (unrollable)
+ {
+ Dictionary<GraphNode, Block!>! visited1 = new Dictionary<GraphNode, Block!>(visited);
+ Dictionary<GraphNode, Block!>! visited2 = new Dictionary<GraphNode, Block!>(visited);
+ Dictionary<GraphNode, Block!>! visited3 = new Dictionary<GraphNode, Block!>(visited);
+
+ Block! loopend = ConstructLoopExitBlock(cutPoint, loopNodes, visited, prefix+"#Last");
+
+ Block! last = UnrollOnce(cutPoint, loopend,visited1,false, prefix+"#Last");
+ AddHavocCmd(last,loopNodes);
+
+
+ Block! arb = UnrollOnce(cutPoint, last,visited2,true, prefix+"#Arb");
+ AddHavocCmd(arb,loopNodes);
+
+
+ BlockSeq! succ = new BlockSeq();
+ succ.Add(last); succ.Add(arb);
+ assert arb.TransferCmd!=null;
+ Block! tmp = new Block(arb.tok, arb.Label + prefix+"#Dummy" , new CmdSeq(), new GotoCmd(arb.TransferCmd.tok, succ));
+ Blocks.Add(tmp);
+ m_checkableBlocks.Add(tmp);
+
+ Block! first = UnrollOnce(cutPoint, tmp,visited3,false, prefix+"#First");
+
+ return first;
+
+ } else
+ {
+ Dictionary<GraphNode, Block!>! visited_ = new Dictionary<GraphNode, Block!>(visited);
+ Block! loopend = AbstractIteration(cutPoint, prefix+"#UR");
+ Block! ret = UnrollOnce(cutPoint, loopend,visited_,false, prefix);
+ AddHavocCmd(ret, loopNodes);
+ return ret;
+ }
+ }
+
+ private Block! UnrollOnce(GraphNode! node, Block! nextIter, Dictionary<GraphNode, Block!>! visited, bool unrollable, String! prefix)
+ {
+ visited.Add(node, nextIter);
+ Block newb;
+ BlockSeq! newSuccs = new BlockSeq();
+ foreach(GraphNode! g in node.Succecessors)
+ {
+ newSuccs.Add( LoopUnrolling(g,visited,unrollable,prefix) );
+ }
+ newb = new Block(node.Block.tok, node.Block.Label + prefix , node.Body, node.Block.TransferCmd);
+ assert newb!=null; assert newb.TransferCmd!=null;
+ if (newSuccs.Length == 0)
+ newb.TransferCmd = new ReturnCmd(newb.TransferCmd.tok);
+ else
+ newb.TransferCmd = new GotoCmd(newb.TransferCmd.tok, newSuccs);
+
+ Blocks.Add(newb);
+ if (unrollable) m_checkableBlocks.Add(newb);
+ return newb;
+ }
+
+ private Block! AbstractIteration(GraphNode! node, String! prefix)
+ {
+ CmdSeq body = new CmdSeq();
+ foreach (Cmd! c in node.Body)
+ {
+ if (c is PredicateCmd || c is CommentCmd)
+ body.Add(c);
+ else
+ break;
+ }
+ body.Add(new AssumeCmd(node.Block.tok, Expr.False) );
+ TransferCmd! tcmd = new ReturnCmd(node.Block.tok);
+ Block! b = new Block(node.Block.tok, node.Block.Label + prefix, body, tcmd);
+ Blocks.Add(b);
+ return b;
+ }
+
+ private Block! ConstructLoopExitBlock(GraphNode! cutPoint, List<GraphNode!>! loopNodes,
+ Dictionary<GraphNode, Block!>! visited, String! prefix)
+ {
+ BlockSeq! newSucc = new BlockSeq();
+ Block! orig = cutPoint.Block;
+
+ // detect the block after the loop
+ // FixMe: What happens when using break commands?
+ foreach (GraphNode! g in cutPoint.Succecessors)
+ {
+ if (!loopNodes.Contains(g))
+ {
+ Block b;
+ if (visited.TryGetValue(g,out b) )
+ newSucc.Add(b);
+ }
+ }
+ TransferCmd tcmd;
+ assert orig.TransferCmd!=null;
+ if (newSucc.Length==0)
+ tcmd = new ReturnCmd(orig.TransferCmd.tok);
+ else
+ tcmd = new GotoCmd(orig.TransferCmd.tok, newSucc);
+ // FixMe: Genertate IToken for counterexample creation
+ Block! newb = new Block(orig.tok, orig.Label+prefix+"#Leave", orig.Cmds, tcmd);
+ Blocks.Add(newb);
+ m_checkableBlocks.Add(newb);
+ return newb;
+ }
+
+
+ private void GatherLoopBodyNodes(GraphNode! current, GraphNode! cutPoint, List<GraphNode!>! loopNodes)
+ {
+ loopNodes.Add(current);
+ if (false) System.Diagnostics.Debugger.Break();
+ foreach (GraphNode! g in current.Predecessors)
+ {
+ if (cutPoint.firstPredecessor == g || g == cutPoint || loopNodes.Contains(g) ) continue;
+ GatherLoopBodyNodes(g, cutPoint, loopNodes);
+ }
+ }
+
+ private List<GraphNode!>! GatherLoopExitNodes(List<GraphNode!>! loopNodes)
+ {
+ List<GraphNode!>! exitnodes = new List<GraphNode!>();
+
+ foreach (GraphNode! g in loopNodes)
+ {
+ foreach (GraphNode! s in g.Succecessors)
+ {
+ if (!loopNodes.Contains(s) /*&& !exitnodes.Contains(s)*/ ) exitnodes.Add(s);
+ }
+ }
+ return exitnodes;
+ }
+
+ private void AddHavocCmd(Block! b, List<GraphNode!>! loopNodes)
+ {
+ List<Block!>! loopBlocks = new List<Block!>();
+ foreach (GraphNode! g in loopNodes) loopBlocks.Add(g.Block);
+ HavocCmd! hcmd = HavocLoopTargets(loopBlocks,b.tok);
+ CmdSeq! body = new CmdSeq();
+ body.Add(hcmd);
+ body.AddRange(b.Cmds);
+ b.Cmds = body;
+ }
+
+ private HavocCmd! HavocLoopTargets(List<Block!>! bl, IToken! tok)
+ {
+ VariableSeq varsToHavoc = new VariableSeq();
+ foreach ( Block! b in bl )
+ {
+ foreach ( Cmd! c in b.Cmds )
+ {
+ c.AddAssignedVariables(varsToHavoc);
+ }
+ }
+ IdentifierExprSeq havocExprs = new IdentifierExprSeq();
+ foreach ( Variable! v in varsToHavoc )
+ {
+ IdentifierExpr ie = new IdentifierExpr(Token.NoToken, v);
+ if(!havocExprs.Has(ie))
+ havocExprs.Add(ie);
+ }
+ // pass the token of the enclosing loop header to the HavocCmd so we can reconstruct
+ // the source location for this later on
+ return new HavocCmd(tok,havocExprs);
+ }
+
+ #endregion
+
+
+ #region GraphNode
+ private class GraphNode
+ {
+ public readonly Block! Block;
+ public readonly CmdSeq! Body;
+ public bool IsCutPoint; // is set during ComputeGraphInfo
+ [Rep] public readonly List<GraphNode!>! Predecessors = new List<GraphNode!>();
+ [Rep] public readonly List<GraphNode!>! Succecessors = new List<GraphNode!>();
+ public GraphNode firstPredecessor;
+
+ GraphNode(Block! b, CmdSeq! body)
+ {
+ Block = b; Body = body;
+ IsCutPoint = false;
+ }
+
+ static CmdSeq! GetOptimizedBody(CmdSeq! cmds)
+ {
+ int n = 0;
+ foreach (Cmd c in cmds)
+ {
+ n++;
+ PredicateCmd pc = c as PredicateCmd;
+ if (pc != null && pc.Expr is LiteralExpr && ((LiteralExpr)pc.Expr).IsFalse)
+ {
+ // return a sequence consisting of the commands seen so far
+ Cmd[] s = new Cmd[n];
+ for (int i = 0; i < n; i++)
+ {
+ s[i] = cmds[i];
+ }
+ return new CmdSeq(s);
+ }
+ }
+ return cmds;
+ }
+
+ public static GraphNode! ComputeGraphInfo(GraphNode from, Block! b, Dictionary<Block,GraphNode!>! gd, Set /*Block*/! beingVisited)
+ {
+ GraphNode g;
+ if (gd.TryGetValue(b, out g))
+ {
+ assume from != null;
+ assert g != null;
+ g.Predecessors.Add(from);
+ if (g.firstPredecessor==null)
+ g.firstPredecessor = from;
+
+ if (beingVisited.Contains(b))
+ g.IsCutPoint = true; // it's a cut point
+ } else
+ {
+ CmdSeq body = GetOptimizedBody(b.Cmds);
+ g = new GraphNode(b, body);
+ gd.Add(b, g);
+ if (from != null)
+ {
+ g.Predecessors.Add(from);
+ if (from==null)
+ g.firstPredecessor = g;
+
+ if (g.firstPredecessor==null)
+ g.firstPredecessor = from;
+
+ }
+ if (body != b.Cmds)
+ {
+ // the body was optimized -- there is no way through this block
+ } else
+ {
+ beingVisited.Add(b);
+ GotoCmd gcmd = b.TransferCmd as GotoCmd;
+ if (gcmd != null)
+ {
+ assume gcmd.labelTargets != null;
+ foreach (Block! succ in gcmd.labelTargets)
+ {
+ g.Succecessors.Add( ComputeGraphInfo(g, succ, gd, beingVisited) );
+ }
+ }
+ beingVisited.Remove(b);
+ }
+ }
+ return g;
+ }
+ }
+ #endregion
+
+ }
+ #endregion
+
+ #region Program Passification
+
+ private Hashtable/*TransferCmd->ReturnCmd*/! PassifyProgram(Implementation! impl,
+ Program! program)
+ {
+ Hashtable gotoCmdOrigins = new Hashtable();
+ Block! exitBlock = GenerateUnifiedExit(impl, gotoCmdOrigins);
+ AddBlocksBetween(impl);
+ GenerateReachabilityPredicates(impl, exitBlock);
+
+ current_impl = impl;
+ Convert2PassiveCmd(impl);
+ impl = current_impl;
+ return new Hashtable();
+ }
+
+ /// <summary>
+ /// Add additional variable to allow checking as described in the paper
+ /// "It's doomed; we can prove it"
+ /// </summary>
+ private void GenerateReachabilityPredicates(Implementation! impl, Block! exitBlock)
+ {
+ ExprSeq! es = new ExprSeq();
+ Cmd eblockcond = null;
+
+ foreach (Block! b in impl.Blocks)
+ {
+ //if (b.Predecessors.Length==0) continue;
+ //if (b.Cmds.Length == 0 ) continue;
+
+ Variable v_ = new LocalVariable(Token.NoToken,
+ new TypedIdent(b.tok, b.Label+"__ivebeenthere",new BasicType(SimpleType.Bool) ) );
+
+ impl.LocVars.Add(v_);
+
+ m_BlockReachabilityMap[b] = v_;
+
+ IdentifierExpr! lhs = new IdentifierExpr(b.tok, v_);
+
+ es.Add( new IdentifierExpr(b.tok, v_) );
+
+ List<AssignLhs!>! lhsl = new List<AssignLhs!>();
+ lhsl.Add(new SimpleAssignLhs(Token.NoToken, lhs) );
+ List<Expr!>! rhsl = new List<Expr!>();
+ rhsl.Add(Expr.True);
+
+ if (b!=exitBlock)
+ {
+ CmdSeq cs = new CmdSeq(new AssignCmd(Token.NoToken, lhsl, rhsl));
+ cs.AddRange(b.Cmds);
+ b.Cmds = cs;
+ } else
+ {
+ eblockcond = new AssignCmd(Token.NoToken, lhsl, rhsl);
+ }
+
+ //checkBlocks.Add(new CheckableBlock(v_,b));
+ }
+ if (es.Length==0) return;
+
+ Expr aexp = null;
+
+ if (es.Length==1)
+ {
+ aexp = es[0];
+ } else if (es.Length==2)
+ {
+ aexp = Expr.Binary(Token.NoToken,
+ BinaryOperator.Opcode.And,
+ (!)es[0],
+ (!)es[1]);
+ } else
+ {
+ aexp = Expr.True;
+ foreach (Expr e_ in es)
+ {
+ aexp = Expr.Binary(Token.NoToken,
+ BinaryOperator.Opcode.And,
+ (!)e_, aexp);
+ }
+ }
+ assert (aexp!=null);
+ assert (eblockcond!=null);
+
+ AssumeCmd ac = new AssumeCmd(Token.NoToken, aexp);
+
+ assert(exitBlock!=null);
+
+ CmdSeq cseq = new CmdSeq(eblockcond);
+ cseq.AddRange(exitBlock.Cmds);
+ cseq.Add(ac);
+
+ exitBlock.Cmds = cseq;
+ }
+
+ #endregion
+
+ #region Error Verification Condition Generation
+
+ VCExpr! GenerateEVC(Implementation! impl, out Hashtable label2absy, Checker! ch)
+ {
+ TypecheckingContext tc = new TypecheckingContext(null);
+ impl.Typecheck(tc);
+ label2absy = new Hashtable/*<int, Absy!>*/();
+ VCExpr! vc;
+ switch (CommandLineOptions.Clo.vcVariety) {
+ case CommandLineOptions.VCVariety.Structured:
+ //vc = VCViaStructuredProgram(impl, label2absy, ch.TheoremProver.Context);
+ //break;
+ Console.WriteLine("Not Implemented: This should be unreachable");
+ assert false;
+ case CommandLineOptions.VCVariety.Block:
+ //vc = FlatBlockVC(impl, label2absy, false, false, false, ch.TheoremProver.Context);
+ Console.WriteLine("Not Implemented: This should be unreachable");
+ assert false;
+ break;
+ case CommandLineOptions.VCVariety.BlockReach:
+ //vc = FlatBlockVC(impl, label2absy, false, true, false, ch.TheoremProver.Context);
+ Console.WriteLine("Not Implemented: This should be unreachable");
+ assert false;
+ break;
+ case CommandLineOptions.VCVariety.Local:
+ //vc = FlatBlockVC(impl, label2absy, true, false, false, ch.TheoremProver.Context);
+ Console.WriteLine("Not Implemented: This should be unreachable");
+ assert false;
+ break;
+ case CommandLineOptions.VCVariety.BlockNested:
+// vc = NestedBlockVC(impl, label2absy, false, ch.TheoremProver.Context);
+// break;
+ Console.WriteLine("Not Implemented: This should be unreachable");
+ assert false;
+ case CommandLineOptions.VCVariety.BlockNestedReach:
+// vc = NestedBlockVC(impl, label2absy, true, ch.TheoremProver.Context);
+// break;
+ Console.WriteLine("Not Implemented: This should be unreachable");
+ assert false;
+ case CommandLineOptions.VCVariety.Dag:
+ if (((!)CommandLineOptions.Clo.TheProverFactory).SupportsDags)
+ {
+// vc = DagVC((!)impl.Blocks[0], label2absy, new Hashtable/*<Block, VCExpr!>*/(), ch.TheoremProver.Context);
+ Console.WriteLine("Not Implemented: This should be unreachable");
+ assert false;
+ } else {
+ vc = LetVC((!)impl.Blocks[0], label2absy, ch.TheoremProver.Context);
+ }
+ break;
+ case CommandLineOptions.VCVariety.Doomed:
+ //vc = FlatBlockVC(impl, label2absy, false, false, true, ch.TheoremProver.Context);
+ vc = LetVC((!)impl.Blocks[0], label2absy, ch.TheoremProver.Context);
+ break;
+ default:
+ assert false; // unexpected enumeration value
+ }
+ return vc;
+ }
+
+ private Hashtable/* Block --> VCExprVar */! BlockVariableMap(List<Block!>! blocks, string! suffix,
+ Microsoft.Boogie.VCExpressionGenerator! gen)
+ {
+ Hashtable/* Block --> VCExprVar */ map = new Hashtable/* Block --> (Let)Variable */();
+ foreach (Block! b in blocks)
+ {
+ VCExprVar! v = gen.Variable(b.Label+suffix, Microsoft.Boogie.Type.Bool);
+ map.Add(b, v);
+ }
+ return map;
+ }
+
+ VCExpr! FlatBlockVC(Implementation! impl,
+ Hashtable/*<int, Absy!>*/! label2absy,
+ bool local, bool reach, bool doomed,
+ ProverContext! proverCtxt)
+ requires local ==> !reach; // "reach" must be false for local
+ {
+ VCExpressionGenerator! gen = proverCtxt.ExprGen;
+ Hashtable/* Block --> VCExprVar */ BlkCorrect = BlockVariableMap(impl.Blocks, "_correct", gen);
+ Hashtable/* Block --> VCExprVar */ BlkReached = reach ? BlockVariableMap(impl.Blocks, "_reached", gen) : null;
+
+ List<Block!> blocks = impl.Blocks;
+ // block sorting is now done on the VCExpr
+ // if (!local && ((!)CommandLineOptions.Clo.TheProverFactory).NeedsBlockSorting) {
+ // blocks = SortBlocks(blocks);
+ // }
+
+ VCExpr proofObligation;
+ if (!local) {
+ proofObligation = (VCExprVar!)BlkCorrect[impl.Blocks[0]];
+ } else {
+ List<VCExpr!> conjuncts = new List<VCExpr!>(blocks.Count);
+ foreach (Block! b in blocks) {
+ VCExpr v = (VCExprVar!)BlkCorrect[b];
+ conjuncts.Add(v);
+ }
+ proofObligation = gen.NAry(VCExpressionGenerator.AndOp, conjuncts);
+ }
+
+ VCContext! context = new VCContext(label2absy, proverCtxt);
+// m_Context = context;
+
+ List<VCExprLetBinding!> programSemantics = new List<VCExprLetBinding!>(blocks.Count);
+ foreach (Block! b in blocks) {
+ VCExpr! SuccCorrect;
+ if (local) {
+ SuccCorrect = VCExpressionGenerator.False; // Martin: Changed from true to false
+ } else {
+ SuccCorrect = SuccessorsCorrect(b, BlkCorrect, BlkReached, doomed, gen);
+ }
+
+ VCExpr wlp = Wlp.Block(b, SuccCorrect, context);
+ if (BlkReached != null) {
+ //wlp = gen.Implies((VCExprVar!)BlkReached[b], wlp);
+ }
+
+ VCExprVar okVar = (VCExprVar!)BlkCorrect[b];
+ VCExprLetBinding binding = gen.LetBinding(okVar, wlp);
+ programSemantics.Add(binding);
+ }
+
+ return gen.Let(programSemantics, proofObligation);
+ }
+
+ static VCExpr! SuccessorsCorrect(
+ Block! b,
+ Hashtable/* Block --> VCExprVar */! BlkCorrect,
+ Hashtable/* Block --> VCExprVar */ BlkReached,
+ bool doomed,
+ Microsoft.Boogie.VCExpressionGenerator! gen)
+ {
+ VCExpr SuccCorrect = null;
+ GotoCmd gotocmd = b.TransferCmd as GotoCmd;
+ if (gotocmd != null)
+ {
+ foreach (Block! successor in (!)gotocmd.labelTargets)
+ {
+ // c := S_correct
+ VCExpr c = (VCExprVar!)BlkCorrect[successor];
+
+ if (BlkReached != null)
+ {
+ // c := S_correct \/ Sibling0_reached \/ Sibling1_reached \/ ...;
+ foreach (Block! successorSibling in gotocmd.labelTargets)
+ {
+ if (successorSibling != successor)
+ {
+ //don't know what this is good for
+ // c = gen.Or(c, (VCExprVar!)BlkReached[successorSibling]);
+ }
+ }
+ }
+ SuccCorrect = SuccCorrect == null ? c : gen.And(SuccCorrect, c);
+ }
+ }
+ if (SuccCorrect == null) {
+ //return VCExpressionGenerator.True;
+ return VCExpressionGenerator.False;
+ } else if (doomed) {
+ return VCExpressionGenerator.False;
+ } else {
+ return SuccCorrect;
+ }
+ }
+
+
+
+ VCExpr! LetVC(Block! startBlock,
+ Hashtable/*<int, Absy!>*/! label2absy,
+ ProverContext! proverCtxt)
+ {
+ Hashtable/*<Block, LetVariable!>*/! blockVariables = new Hashtable/*<Block, LetVariable!!>*/();
+ List<VCExprLetBinding!>! bindings = new List<VCExprLetBinding!>();
+ VCExpr startCorrect = LetVC(startBlock, label2absy, blockVariables, bindings, proverCtxt);
+ //return proverCtxt.ExprGen.Let(bindings, startCorrect);
+ return proverCtxt.ExprGen.Let(bindings, proverCtxt.ExprGen.Not(startCorrect) );
+ }
+
+ VCExpr! LetVC(Block! block,
+ Hashtable/*<int, Absy!>*/! label2absy,
+ Hashtable/*<Block, VCExprVar!>*/! blockVariables,
+ List<VCExprLetBinding!>! bindings,
+ ProverContext! proverCtxt)
+ {
+ VCExpressionGenerator! gen = proverCtxt.ExprGen;
+ VCExprVar v = (VCExprVar)blockVariables[block];
+ if (v == null) {
+ /*
+ * For block A (= block), generate:
+ * LET_binding A_correct = wp(A_body, (/\ S \in Successors(A) :: S_correct))
+ * with the side effect of adding the let bindings to "bindings" for any
+ * successor not yet visited.
+ */
+ VCExpr SuccCorrect;
+ GotoCmd gotocmd = block.TransferCmd as GotoCmd;
+ if (gotocmd == null) {
+ SuccCorrect = VCExpressionGenerator.False; // FixMe: changed from true to false
+ } else {
+ assert gotocmd.labelTargets != null;
+ List<VCExpr!> SuccCorrectVars = new List<VCExpr!>(gotocmd.labelTargets.Length);
+ foreach (Block! successor in gotocmd.labelTargets) {
+ VCExpr s = LetVC(successor, label2absy, blockVariables, bindings, proverCtxt);
+ SuccCorrectVars.Add(s);
+ }
+ SuccCorrect = gen.NAry(VCExpressionGenerator.AndOp, SuccCorrectVars);
+ }
+
+ VCContext context = new VCContext(label2absy, proverCtxt);
+// m_Context = context;
+ VCExpr vc = Wlp.Block(block, SuccCorrect, context);
+
+ v = gen.Variable(block.Label + "_correct", Microsoft.Boogie.Type.Bool);
+ bindings.Add(gen.LetBinding(v, vc));
+ blockVariables.Add(block, v);
+ }
+ return v;
+ }
+
+
+
+ #endregion
+
+ }
+} \ No newline at end of file
diff --git a/Source/VCGeneration/VCGeneration.sscproj b/Source/VCGeneration/VCGeneration.sscproj
new file mode 100644
index 00000000..70f4055d
--- /dev/null
+++ b/Source/VCGeneration/VCGeneration.sscproj
@@ -0,0 +1,142 @@
+<?xml version="1.0" encoding="utf-8"?>
+<VisualStudioProject>
+ <XEN ProjectType="Local"
+ SchemaVersion="1.0"
+ Name="VCGeneration"
+ ProjectGuid="f65666de-fb56-457c-8782-09be243450fc"
+ >
+ <Build>
+ <Settings ApplicationIcon=""
+ AssemblyName="VCGeneration"
+ OutputType="Library"
+ RootNamespace="VCGeneration"
+ StartupObject=""
+ StandardLibraryLocation=""
+ TargetPlatform="v2"
+ TargetPlatformLocation=""
+ >
+ <Config Name="Debug"
+ AllowUnsafeBlocks="False"
+ BaseAddress="285212672"
+ CheckForOverflowUnderflow="False"
+ ConfigurationOverrideFile=""
+ DefineConstants="DEBUG;TRACE"
+ DocumentationFile=""
+ DebugSymbols="True"
+ FileAlignment="4096"
+ IncrementalBuild="True"
+ Optimize="False"
+ OutputPath="bin\debug"
+ RegisterForComInterop="False"
+ RemoveIntegerChecks="false"
+ TreatWarningsAsErrors="False"
+ WarningLevel="4"
+ ReferenceTypesAreNonNullByDefault="False"
+ RunProgramVerifier="False"
+ RunProgramVerifierWhileEditing="False"
+ ProgramVerifierCommandLineOptions=""
+ AllowPointersToManagedStructures="False"
+ CheckContractAdmissibility="True"
+ CheckPurity="False"
+ />
+ <Config Name="Release"
+ AllowUnsafeBlocks="false"
+ BaseAddress="285212672"
+ CheckForOverflowUnderflow="false"
+ ConfigurationOverrideFile=""
+ DefineConstants="TRACE"
+ DocumentationFile=""
+ DebugSymbols="false"
+ FileAlignment="4096"
+ IncrementalBuild="false"
+ Optimize="true"
+ OutputPath="bin\release"
+ RegisterForComInterop="false"
+ RemoveIntegerChecks="false"
+ TreatWarningsAsErrors="false"
+ WarningLevel="4"
+ />
+ </Settings>
+ <References>
+ <Reference Name="System"
+ AssemblyName="System"
+ Private="false"
+ />
+ <Reference Name="System.Data"
+ AssemblyName="System.Data"
+ Private="false"
+ />
+ <Reference Name="System.Xml"
+ AssemblyName="System.Xml"
+ Private="false"
+ />
+ <Reference Name="Core"
+ Project="{47BC34F1-A173-40BE-84C2-9332B4418387}"
+ Private="true"
+ />
+ <Reference Name="AIFramework"
+ Project="{24B55172-AD8B-47D1-8952-5A95CFDB9B31}"
+ Private="true"
+ />
+ <Reference Name="Graph"
+ Project="{4C28FB90-630E-4B55-A937-11A011B79765}"
+ Private="true"
+ />
+ <Reference Name="Mscorlib.Contracts"
+ AssemblyName="Mscorlib.Contracts"
+ Private="false"
+ HintPath="../../Binaries/Mscorlib.Contracts.dll"
+ />
+ <Reference Name="System.Contracts"
+ AssemblyName="System.Contracts"
+ Private="false"
+ HintPath="../../Binaries/System.Contracts.dll"
+ />
+ <Reference Name="Basetypes"
+ Project="{0C692837-77EC-415F-BF04-395E3ED06E9A}"
+ Private="true"
+ />
+ <Reference Name="VCExpr"
+ Project="{CF42B700-10AA-4DA9-8992-48A800251C11}"
+ Private="true"
+ />
+ </References>
+ </Build>
+ <Files>
+ <Include>
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="Check.ssc"
+ />
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="VC.ssc"
+ />
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="Wlp.ssc"
+ />
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="..\version.ssc"
+ />
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="Context.ssc"
+ />
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="OrderingAxioms.ssc"
+ />
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="ConditionGeneration.ssc"
+ />
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="VCDoomed.ssc"
+ />
+ </Include>
+ </Files>
+ </XEN>
+</VisualStudioProject> \ No newline at end of file
diff --git a/Source/VCGeneration/Wlp.ssc b/Source/VCGeneration/Wlp.ssc
new file mode 100644
index 00000000..d7692245
--- /dev/null
+++ b/Source/VCGeneration/Wlp.ssc
@@ -0,0 +1,131 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using System;
+using System.Collections;
+using Microsoft.Boogie;
+using Microsoft.Boogie.VCExprAST;
+using Microsoft.Contracts;
+
+namespace VC {
+ public class VCContext
+ {
+ [Rep] public readonly Hashtable/*<int, Absy!>*/! Label2absy;
+ [Rep] public readonly ProverContext! Ctxt;
+
+ public VCContext(Hashtable/*<int, Absy!>*/! label2absy, ProverContext! ctxt)
+ {
+ this.Label2absy = label2absy;
+ this.Ctxt = ctxt;
+ // base();
+ }
+ }
+
+ #region A class to compute wlp of a passive command program
+
+ public class Wlp
+ {
+ public static VCExpr! Block(Block! b, VCExpr! N, VCContext! ctxt)
+ modifies ctxt.*;
+ {
+ VCExpressionGenerator! gen = ctxt.Ctxt.ExprGen;
+ VCExpr! res = N;
+
+ for (int i = b.Cmds.Length; --i>=0; )
+ {
+ res = Cmd((!) b.Cmds[i], res, ctxt);
+ }
+
+ int id = b.UniqueId;
+ expose (ctxt) {
+ ctxt.Label2absy[id] = b;
+ return gen.Implies(gen.LabelPos((!)id.ToString(), VCExpressionGenerator.True), res);
+ }
+ }
+
+ /// <summary>
+ /// Computes the wlp for an assert or assume command "cmd".
+ /// </summary>
+ public static VCExpr! Cmd(Cmd! cmd, VCExpr! N, VCContext! ctxt)
+ {
+ VCExpressionGenerator! gen = ctxt.Ctxt.ExprGen;
+ if (cmd is AssertCmd) {
+ AssertCmd ac = (AssertCmd)cmd;
+ VCExpr C = ctxt.Ctxt.BoogieExprTranslator.Translate(ac.Expr);
+ if (CommandLineOptions.Clo.vcVariety == CommandLineOptions.VCVariety.Doomed) {
+ return gen.Implies(C, N);
+ } else {
+ int id = ac.UniqueId;
+ ctxt.Label2absy[id] = ac;
+ switch (CommandLineOptions.Clo.UseSubsumption) {
+ case CommandLineOptions.SubsumptionOption.Never:
+ break;
+ case CommandLineOptions.SubsumptionOption.Always:
+ N = gen.Implies(C, N);
+ break;
+ case CommandLineOptions.SubsumptionOption.NotForQuantifiers:
+ if (!(C is VCExprQuantifier)) {
+ N = gen.Implies(C, N);
+ }
+ break;
+ default:
+ assert false; // unexpected case
+ }
+// (MSchaef) Hack: This line might be useless, but at least it is not harmfull
+// need to test it
+ if (CommandLineOptions.Clo.vcVariety == CommandLineOptions.VCVariety.Doomed) return gen.Implies(C, N);
+
+ return gen.And(gen.LabelNeg((!)id.ToString(), C), N);
+ }
+
+ } else if (cmd is AssumeCmd) {
+ AssumeCmd ac = (AssumeCmd)cmd;
+ return gen.Implies(ctxt.Ctxt.BoogieExprTranslator.Translate(ac.Expr), N);
+
+ } else {
+ assert false; // unexpected command
+ }
+ }
+
+ public static VCExpr! RegExpr(RE! r, VCExpr! N, VCContext! ctxt)
+ {
+ if ( r is AtomicRE )
+ {
+ AtomicRE ar = (AtomicRE) r;
+ return Block(ar.b, N, ctxt);
+ }
+ else if ( r is Sequential )
+ {
+ Sequential s = (Sequential) r;
+ return RegExpr(s.first, RegExpr(s.second, N, ctxt), ctxt);
+ }
+ else if ( r is Choice )
+ {
+ Choice ch = (Choice) r;
+ VCExpr! res;
+ if (ch.rs == null || ch.rs.Length==0)
+ {
+ res = N;
+ }
+ else
+ {
+ VCExpr currentWLP = RegExpr((!)ch.rs[0], N, ctxt);
+ for (int i = 1, n = ch.rs.Length; i < n; i++)
+ {
+ currentWLP = ctxt.Ctxt.ExprGen.And(currentWLP, RegExpr((!)ch.rs[i], N, ctxt));
+ }
+ res = currentWLP;
+ }
+ return res;
+ }
+ else
+ {
+ assert false; // unexpected RE subtype
+ }
+ }
+ }
+ #endregion
+
+}
diff --git a/Source/XAHA/XAHA.ssc b/Source/XAHA/XAHA.ssc
new file mode 100644
index 00000000..35dbaf1c
--- /dev/null
+++ b/Source/XAHA/XAHA.ssc
@@ -0,0 +1,601 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+//XAHA: eXperimental Automated History Abstraction
+
+/* The top-level declarations of the initial file contain:
+Declaration of one constant totalPhases of type int.
+An axiom may be present saying what value (any natural number) does totalPhases have.
+Declarations of shared variables v1:tp1,...,vm:tpm.
+Functions
+A(i:int,p:int,V1:[int]tp1,...,Vm:[int]tpm,V1':[int]tp1,...,Vm':[int]tpm)
+and
+G(i:int,p:int,V1:[int]tp1,...,Vm:[int]tpm,V1':[int]tp1,...,Vm':[int]tpm).
+The order of the variables in the declarations of A and G should coincide with the order
+in which the variables were declared. I.e. if the top-level declaration order is
+a:A,c:C,d:D,b:B, then A should be declared as A(int,int, A,C,D,B, A,C,D,B).
+Probably axioms specifying A(i,p,...) as the rely predicate for thread number i (0<=i<n) and phase number p (0<=p<totalPhases).
+Probably axioms specifying G(i,p,v1,...,vm) as the guarantee predicate for thread number i (0<=i<n) and phase number p (0<=p<totalPhases).
+Function describing the initial condition on the shared variables.
+Init(tp1,...,tpm);
+Procedures T0(),...,T(n-1)() such that each modifies a subset of v1,...,vm.
+All procedures except T0, ...,T(n-1) should be inlined and there should be no procedure calls.
+
+The generated output is one large BoogiePL file, written to a standard output,
+which is the intrumentation of the threads T0,...,T(n-1) with phase description checking code.
+*/
+
+
+
+
+namespace Microsoft.Boogie.XAHA {
+ using System;
+ using Microsoft.Boogie;
+ using Microsoft.Basetypes;
+ using Microsoft.Contracts;
+ using System.Collections.Generic;
+ using PureCollections;
+
+ //class which implements the history-based verification procedure
+ public class clXAHA {
+ const string! totalPhasesName="totalPhases";
+ const string! currentPhaseVarName="phase";
+ const string! threadNoVarName="threadNo";
+ Program! prg;
+
+ //initializes the internal data structures needed for processing
+ public clXAHA(Program! program) {
+ prg=program;
+ }
+
+ //Checks whether the described format has been met. If not, prints a
+ //correspondent error message to the standard error stream.
+ //Otherwise generates to the output_file (or standard output if null)
+ //another program whose correctness implies the correct specification and
+ //the correctness of the original multithreaded program.
+ public bool CheckFormatAndGenerateInstrumentation(string output_file) {
+ Constant decl_totalPhases=FindTopLevelConstByName(totalPhasesName);
+ if(decl_totalPhases==null) {
+ Console.Error.WriteLine("The constant "+totalPhasesName+" was not found as a top-level declaration of the program.");
+ return false;
+ }
+ //Check whether we are doing a bounded verification and, if yes, how many
+ //phased do we have.
+ int phases_no;
+ bool phase_number_finite=
+ GetValueOfVarFromAxiom(totalPhasesName,out phases_no);
+ string! history_pre_prefix,history_post_prefix;
+ List<Variable!>! sharedVars=GetSharedVars(out history_pre_prefix,out history_post_prefix);
+ //find predicates A and G
+ Function A=GetTopLevelFunction("A");
+ if(A==null) { Console.Error.WriteLine("The rely predicate A was not found."); return false; };
+ if(!CheckFormat(A,sharedVars)) { Console.Error.WriteLine("The rely predicate A doesn't have the right format."); return false; };
+ Function G=GetTopLevelFunction("G");
+ if(G==null) { Console.Error.WriteLine("The guarantee predicate G was not found."); return false; };
+ if(!CheckFormat(G,sharedVars)) { Console.Error.WriteLine("The guarantee predicate G doesn't have the right format."); return false; };
+ //determine how many threads are there. All procedures should be inlined.
+ //So any procedure other than T1,...,Tn is useless.
+ int n;
+ if(!CheckThreads(out n)) {
+ Console.Error.WriteLine("Error while checking procedure format.");
+ return false;
+ }
+ TokenTextWriter outstream=((output_file!=null) && (output_file.Trim()!=""))?
+ (new TokenTextWriter(output_file)):
+ (new TokenTextWriter("<console>", Console.Out));
+ if(outstream==null) { Console.Error.WriteLine("Out of memory"); return false; }
+ if(!InstrumentizeThreads(outstream,n,sharedVars,history_pre_prefix,history_post_prefix,phase_number_finite)) {
+ Console.Error.WriteLine("Thread instrumentation failed.");
+ return false;
+ }
+ if(!PrintInterleaving(outstream,n,sharedVars,history_pre_prefix,history_post_prefix,n,phase_number_finite,phases_no)) {
+ Console.Error.WriteLine("Interleaving printing failed.");
+ return false;
+ }
+ outstream.Close();
+ return true;
+ }
+
+ //In the program, find a top-level constant declaration named s and
+ //returns it.
+ public Constant FindTopLevelConstByName(string s) {
+ foreach (Declaration d in prg.TopLevelDeclarations) {
+ if((d is Constant) && d!=null) {
+ Constant dd=(Constant)d;
+ if(dd.Name==s) return dd;
+ }
+ }
+ return null;
+ }
+
+ //In the program, find a top-level axiom speaking about a certain constant
+ //like "axiom c==digits". If such an axiom is found, returns true and fills the value
+ //by digits, otherwise returns false.
+ bool GetValueOfVarFromAxiom(string s,out int value) {
+ foreach (Declaration d in prg.TopLevelDeclarations) {
+ if((d is Axiom) && (d!=null)) {
+ Axiom a=(Axiom)d;
+ Expr e=a.Expr;
+ if((e is NAryExpr) && (e!=null)) {
+ NAryExpr ne=(NAryExpr)e;
+ IAppliable f=ne.Fun;
+ if((f is BinaryOperator) && (f!=null)) {
+ BinaryOperator bo=(BinaryOperator)f;
+ if(bo.Op==BinaryOperator.Opcode.Eq) {
+ ExprSeq args=ne.Args;
+ Expr lhs=(Expr)(args.Head());
+ Expr rhs=(Expr)(args.Last());
+ //Console.Error.WriteLine(lhs.ToString());
+ if((lhs is IdentifierExpr) && (lhs!=null)) {
+ IdentifierExpr! ie=(IdentifierExpr)lhs;
+ if(ie.Name==s) {
+ if((rhs is LiteralExpr)&&(rhs!=null)) {
+ LiteralExpr! lrrhs=(LiteralExpr)rhs;
+ if((lrrhs.Val is BigNum) && (lrrhs!=null)) {
+ value=((BigNum)(lrrhs.Val)).ToIntSafe;
+ return true;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ value=-1;
+ return false;
+ }
+
+ //returns the set of all possible variables of the program, whenever shared or local
+ //Set! GetAllVars() {
+ //
+ // }
+
+ //Returns the set of all shared variables (except the constants) of the program.
+ //In the pre_prefix, returns "H_", in the post_prefix, returns "HP_".
+ //TODO: In pre_prefix and post_prefix, return such strings p,p' such that for any shared
+ //variable x, px is neither a shared, nor a local variable and p'x is neither a shared nor
+ //a local variable.
+ List<Variable!>! GetSharedVars(out string! pre_prefix, out string! post_prefix) {
+ List<Variable!>! retval=new List<Variable!>();
+ foreach(Declaration d in prg.TopLevelDeclarations) {
+ if((d is Variable) && !(d is Constant) && (d!=null)) {
+ retval.Add((Variable)d);
+ }
+ }
+ pre_prefix="H_";
+ post_prefix="HP_";
+ return retval;
+ }
+
+ //returns the first function which is declared on the top level and which is called fname.
+ Function GetTopLevelFunction(string fname) {
+ foreach(Declaration d in prg.TopLevelDeclarations) {
+ if((d is Function) && (d!=null)) {
+ Function! f=(Function)d;
+ if(f.Name==fname) return f;
+ }
+ }
+ return null;
+ }//end of GetTopLevelFunction
+
+
+ //returns true if f is declared as
+ //f(int,int,[int]tv1,...,[int]tvm,[int]tv1,...,[int]tvm) returns (bool);
+ //where m is the number of shared variables and
+ //tv1,...,tvm are types of the m shared variables.
+ bool CheckFormat(Function! f,List<Variable!>! sharedVars) {
+ VariableSeq! inparams=f.InParams;
+ //first check the correct number
+ int m=sharedVars.Count;
+ if(inparams.Length!=(2+2*m)) {
+ Console.Error.WriteLine("Bad number of arguments in "+f.Name); return false;
+ }
+ //now check the types of the first portion
+ List<Variable!>.Enumerator sv_ptr=sharedVars.GetEnumerator(); sv_ptr.MoveNext();
+ SequenceEnumerator! pr_ptr=(SequenceEnumerator!)(inparams.GetEnumerator()); pr_ptr.MoveNext();
+ //check that the first two arguments are of type int, i.e. the thread and the phase numbers
+ Variable! pr_var=(Variable!)(pr_ptr.Current);
+ if(pr_var.TypedIdent.Type.ToString()!="int") {
+ Console.Error.WriteLine("Error in function "+f.Name+
+ ": the first argument denotes a thread number and should be of type int.");
+ return false;
+ }
+ pr_ptr.MoveNext();
+ pr_var=(Variable)(pr_ptr.Current);
+ if(pr_var.TypedIdent.Type.ToString()!="int") {
+ Console.Error.WriteLine("Error in function "+f.Name+
+ ": the second argument denotes a phase number and should be of type int.");
+ return false;
+ }
+ pr_ptr.MoveNext();
+ for(int i=0;i<m;i++) {
+ Variable! sh_var=sv_ptr.Current;
+ pr_var=(Variable)(pr_ptr.Current);
+ string sh_type=sh_var.TypedIdent.Type.ToString();
+ string pr_type=pr_var.TypedIdent.Type.ToString();
+ if(pr_type!=("[int]"+sh_type)) {
+ Console.Error.WriteLine("In the declaration of "+f.Name+", the type "+pr_type+
+ " does not coincide with [int]"+sh_type);
+ return false;
+ }
+ sv_ptr.MoveNext();
+ pr_ptr.MoveNext();
+ }
+ //now check the types of the second portion
+ sv_ptr=sharedVars.GetEnumerator(); sv_ptr.MoveNext();
+ for(int i=0;i<m;i++) {
+ Variable! sh_var=sv_ptr.Current;
+ pr_var=(Variable)pr_ptr.Current;
+ string sh_type=sh_var.TypedIdent.Type.ToString();
+ string pr_type=pr_var.TypedIdent.Type.ToString();
+ if(pr_type!=("[int]"+sh_type)) {
+ Console.Error.WriteLine("In the declaration of "+f.Name+", the type "+pr_type+
+ " does not coincide with [int]"+sh_type);
+ return false;
+ }
+ sv_ptr.MoveNext();
+ pr_ptr.MoveNext();
+ }
+ //check that the return value is (bool);
+ VariableSeq! outparams=f.OutParams;
+ if(outparams.Length!=1) {
+ Console.Error.WriteLine("The function "+f.Name+" should have exactly one out parameter.");
+ return false;
+ }
+ Variable! rv=(Variable!)(outparams.Head());
+ string rv_type=rv.TypedIdent.Type.ToString();
+ if(rv_type != "bool") {
+ Console.Error.WriteLine("The function "+f.Name+" should return bool. Currently, it returns "+rv_type+".");
+ return false;
+ }
+ return true;
+ }//end of CheckFormat
+
+
+ //checks that all procedures are exactly T0,...,T(n-1) for some n in some order.
+ //Returns true, if it is so. In number_of_threads, returns the number of threads.
+ bool CheckThreads(out int number_of_threads) {
+ number_of_threads=0;
+ bool[] threads_specified=new bool[1] {false};
+ foreach(Declaration d in prg.TopLevelDeclarations) {
+ if((d is Procedure) && (d!=null)) {
+ Procedure! p=(Procedure)d;
+ if(p.Name[0]!='T') {
+ Console.Error.WriteLine("A procedure discovered which is not a thread.");
+ return false;
+ }
+ string probably_number=p.Name.Substring(1,p.Name.Length-1);
+ int no_of_procedure;
+ if(!Int32.TryParse(probably_number,out no_of_procedure)) {
+ Console.Error.WriteLine("The procedure "+p.Name+" has a bad name. After T a number should follow.");
+ return false;
+ }
+ VariableSeq! inparams=p.InParams;
+ if(inparams.Length>0) {
+ Console.Error.WriteLine("The thread "+p.Name+" has arguments. It should not.");
+ return false;
+ }
+ VariableSeq! outparams=p.OutParams;
+ if(outparams.Length>0) {
+ Console.Error.WriteLine("The thread "+p.Name+" returns some value. It should not.");
+ return false;
+ }
+ if(no_of_procedure>=number_of_threads) {
+ number_of_threads=no_of_procedure+1;
+ Array.Resize(ref threads_specified,number_of_threads);
+ if(threads_specified==null) {
+ Console.Error.WriteLine("Out of memory");
+ return false;
+ }
+ threads_specified[no_of_procedure]=true;
+ } else {
+ if(threads_specified[no_of_procedure]) {
+ Console.Error.WriteLine("Procedure "+p.Name+" was specified at least twice.");
+ return false;
+ } else threads_specified[no_of_procedure]=true;
+ }
+ }
+ }
+ //now check whether all threads were specified
+ for(int i=0;i<number_of_threads;i++)
+ if(!threads_specified[i]) {
+ Console.Error.WriteLine("Thread number "+i.ToString()+" was not specified.");
+ return false;
+ }
+ return true;
+ }//end CheckThreads
+
+ //Copy the non-procedural code from the input to the output, insert the prelude, go
+ //through the implementations, instrumentize them statement by statement.
+ bool InstrumentizeThreads(TokenTextWriter! outstream, int number_of_threads,List<Variable!>! sharedVars,
+ string! history_pre_prefix,string! history_post_prefix,bool phase_number_finite) {
+ outstream.SetToken(prg);
+ bool first = true;
+ bool implementation_seen=false;
+ foreach(Declaration d in prg.TopLevelDeclarations) {
+ if(d==null) {outstream.WriteLine(); continue;}
+ if(first) first=false; else outstream.WriteLine();
+ if(d is Implementation) {
+ if(!implementation_seen) {
+ implementation_seen=true;
+ EmitPrelude(outstream,sharedVars,history_pre_prefix,history_post_prefix,phase_number_finite);
+ }
+ Implementation! ipl=(Implementation)d;
+ int thread_no=Convert.ToInt32(ipl.Name.Substring(1,ipl.Name.Length-1));
+ outstream.WriteLine("procedure "+ipl.Name+"()");
+ InstrumentizeStartSeq(outstream,1,sharedVars,history_pre_prefix,history_post_prefix,thread_no);
+ if(!InstrumentizeImplInternals(outstream,1,ipl,thread_no)) return false;
+ } else if(d is Procedure) continue;
+ else d.Emit(outstream,0);
+ }//foreach
+ return true;
+ }//end InstrumentizeThreads()
+
+
+ //Print declarations of history variables, phase variable, instrumentation functions.
+ void EmitPrelude(TokenTextWriter! outstream, List<Variable!>! sharedVars,
+ string! history_pre_prefix, string! history_post_prefix,bool phase_number_finite) {
+ //write history variables
+ if(sharedVars.Count>0) {
+ outstream.Write("var ");
+ EmitVarList(outstream,sharedVars,history_pre_prefix,null,"[int]");
+ outstream.WriteLine(";");
+ outstream.Write("var ");
+ EmitVarList(outstream,sharedVars,history_post_prefix,null,"[int]");
+ outstream.WriteLine(";");
+ }
+ outstream.WriteLine("var "+currentPhaseVarName+":int;");
+ outstream.WriteLine();
+ //write the assume rely procedure
+ outstream.WriteLine("procedure{:inline 999} AssumeRely("+threadNoVarName+":int)");
+ outstream.Write("modifies ");
+ EmitVarList(outstream,sharedVars,null,null,null); outstream.Write(", ");
+ EmitVarList(outstream,sharedVars,history_pre_prefix,null,null); outstream.WriteLine(";");
+ outstream.WriteLine("{");
+ outstream.Write(" havoc ");
+ EmitVarList(outstream,sharedVars,null,null,null); outstream.WriteLine(";");
+ foreach(Variable! v in sharedVars)
+ outstream.WriteLine(" "+history_pre_prefix+v.Name+"["+currentPhaseVarName+"]:="+v.Name+";");
+ outstream.Write(" assume A("+threadNoVarName+","+currentPhaseVarName+",");
+ EmitVarList(outstream,sharedVars,history_pre_prefix,null,null);
+ outstream.Write(",");
+ EmitVarList(outstream,sharedVars,history_post_prefix,null,null);
+ outstream.WriteLine(");"); outstream.WriteLine("}");
+ outstream.WriteLine();
+ //write the CheckGuarantee procedure
+ outstream.WriteLine("procedure {:inline 999} CheckGuarantee("+threadNoVarName+":int)");
+ outstream.Write("modifies ");
+ EmitVarList(outstream,sharedVars,history_post_prefix,null,null); outstream.WriteLine(";");
+ outstream.WriteLine("{");
+ foreach(Variable! v in sharedVars)
+ outstream.WriteLine(" "+history_post_prefix+v.Name+"["+currentPhaseVarName+"]:="+v.Name+";");
+ outstream.Write(" assert G("+threadNoVarName+","+currentPhaseVarName+", ");
+ EmitVarList(outstream,sharedVars,history_pre_prefix,null,null);
+ outstream.Write(",");
+ EmitVarList(outstream,sharedVars,history_post_prefix,null,null);
+ outstream.WriteLine(");"); outstream.WriteLine("}");
+ outstream.WriteLine();
+ //write the MayUpdateProcedure
+ outstream.WriteLine("procedure {:inline 999} MayUpdate("+threadNoVarName+":int)");
+ outstream.Write("modifies "+currentPhaseVarName);
+ if(sharedVars.Count>0) {
+ outstream.Write(", "); EmitVarList(outstream,sharedVars,history_pre_prefix,null,null); outstream.Write(", ");
+ EmitVarList(outstream,sharedVars,history_post_prefix,null,null); outstream.Write(", ");
+ EmitVarList(outstream,sharedVars,null,null,null);
+ }
+ outstream.WriteLine(";"); outstream.WriteLine("{");
+ outstream.WriteLine(" goto updating,not_updating;");
+ outstream.WriteLine(" updating:");
+ outstream.WriteLine(" call CheckGuarantee("+threadNoVarName+");");
+ outstream.WriteLine(" if(("+currentPhaseVarName+"+1)<"+totalPhasesName+") {");
+ outstream.WriteLine(" "+currentPhaseVarName+":="+currentPhaseVarName+"+1;");
+ outstream.WriteLine(" call AssumeRely("+threadNoVarName+");");
+ outstream.WriteLine(" }");
+ outstream.WriteLine(" not_updating:");
+ outstream.WriteLine("}");
+ outstream.WriteLine();
+ //write the instrumentation for the assume predicate
+ outstream.WriteLine("procedure {:inline 999} MayUpdateAssume("+threadNoVarName+":int,condition:bool)");
+ outstream.Write("modifies "+currentPhaseVarName);
+ if(sharedVars.Count>0) {
+ outstream.Write(", "); EmitVarList(outstream,sharedVars,history_pre_prefix,null,null); outstream.Write(", ");
+ EmitVarList(outstream,sharedVars,history_post_prefix,null,null); outstream.Write(", ");
+ EmitVarList(outstream,sharedVars,null,null,null);
+ }
+ outstream.WriteLine(";"); outstream.WriteLine("{");
+ outstream.WriteLine(" if(condition) { call MayUpdate("+threadNoVarName+"); }");
+ outstream.WriteLine(" else { call CheckGuarantee("+threadNoVarName+"); assume false; }");
+ outstream.WriteLine("}");
+ outstream.WriteLine();
+ }//end EmitPrelude(...)
+
+
+ //Print a comma-separated variable list vars to outstream.
+ //Before each variable prints prefix, after each variable prints suffix if available.
+ //If type_prefix is not null, also output the types, prefixing them with type_prefix.
+ void EmitVarList(TokenTextWriter! outstream, List<Variable!>! vars, string var_prefix,
+ string var_suffix,string type_prefix) {
+ bool first=true;
+ foreach(Variable! v in vars) {
+ if(v.Name==null) continue;
+ if(first) first=false; else outstream.Write(", ");
+ outstream.Write(((var_prefix==null)?"":var_prefix)+v.Name+((var_suffix==null)?"":var_suffix));
+ if(type_prefix!=null) outstream.Write(":"+type_prefix+v.TypedIdent.Type.ToString());
+ }
+ }//end EmitVarList(...)
+
+ //prints the indented start sequence of the thread thread_no
+ void InstrumentizeStartSeq(TokenTextWriter! outstream,int level,List<Variable!>! sharedVars,
+ string! history_pre_prefix, string! history_post_prefix, int thread_no) {
+ outstream.Write("modifies "+currentPhaseVarName);
+ if(sharedVars.Count>0) {
+ outstream.Write(", "); EmitVarList(outstream,sharedVars,null,null,null);
+ outstream.Write(", "); EmitVarList(outstream,sharedVars,history_pre_prefix,null,null);
+ outstream.Write(", "); EmitVarList(outstream,sharedVars,history_post_prefix,null,null);
+ }
+ outstream.WriteLine(";");
+ outstream.WriteLine("{");
+ WriteIndent(outstream,level); outstream.WriteLine(currentPhaseVarName+":=0;");
+ WriteIndent(outstream,level); outstream.WriteLine("call AssumeRely("+thread_no.ToString()+");");
+ }//end InstrumentizeStartSeq(...)
+
+ //prints 2+level whitespaces
+ void WriteIndent(TokenTextWriter! outstream,int level) {
+ for(int i=0;i<level;i++) outstream.Write(" ");
+ }//end WriteIndent
+
+ //goes through the list of statements of procedure impl, instrumetizes them according to the history-algorithm
+ bool InstrumentizeImplInternals(TokenTextWriter! outstream,int level,Implementation! impl,int thread_no) {
+ foreach(Block! b in impl.Blocks) {
+ WriteIndent(outstream,level); outstream.WriteLine(b.Label+":");
+ if(!InstrumentizeCmdSeq(outstream,level,b.Cmds,thread_no,(b.TransferCmd==null || (b.TransferCmd is ReturnCmd)))) {
+ Console.Error.WriteLine("Error processing thread "+thread_no.ToString()+".");
+ return false;
+ }
+ if(b.TransferCmd!=null && !(b.TransferCmd is ReturnCmd))
+ if(!InstrumentizeTransferCmd(outstream,level,b.TransferCmd,thread_no)) return false;
+ }
+ outstream.WriteLine("}");
+ return true;
+ }//end InstrumentizeStmtSeq(...)
+
+ //Instrumentizing a sequence of commands. If last_cmd_seq==true, then the last statement should be
+ //instrumentized as a statement without successors
+ bool InstrumentizeCmdSeq(TokenTextWriter! outstream, int level, CmdSeq! cmds,
+ int thread_no, bool last_cmd_seq) {
+ SequenceEnumerator! curr_cmd=(SequenceEnumerator)(cmds.GetEnumerator()); curr_cmd.MoveNext();
+ Cmd cmd; int i=0;
+ for(;(i+1)<cmds.Length;i++) {
+ cmd=(Cmd)curr_cmd.Current;
+ if(cmd!=null) {
+ if(!InstrumentizeCmd(outstream,level,cmd,thread_no,false)) return false;
+ }
+ curr_cmd.MoveNext();
+ }
+ if(i<cmds.Length) {
+ cmd=(Cmd)(curr_cmd.Current);
+ if(cmd!=null)
+ if(!InstrumentizeCmd(outstream,level,cmd,thread_no,last_cmd_seq)) return false;
+ }
+ return true;
+ }//end InstrumentizeCmdSeq(...)
+
+ //instrumentizes the goto statement
+ bool InstrumentizeTransferCmd(TokenTextWriter! outstream,int level,TransferCmd! cmd,int thread_no) {
+ if(cmd is GotoCmd) {
+ WriteIndent(outstream,level); outstream.WriteLine("call MayUpdate("+thread_no.ToString()+");");
+ cmd.Emit(outstream,level);
+ } else {
+ Console.Error.Write("Unknown command: ");
+ TokenTextWriter ttw=new TokenTextWriter("<console_error>",Console.Error);
+ if(ttw!=null) { cmd.Emit(ttw,0); ttw.Close(); }
+ else Console.Error.Write("Out of memory");
+ return false;
+ }
+ return true;
+ }//end InstrumentizeTransferCmd(...)
+
+ //Instrumentize a single command. If last_cmd==true, this statement is the last in the thread.
+ bool InstrumentizeCmd(TokenTextWriter! outstream,int level,Cmd! cmd,int thread_no,bool last_cmd) {
+ if((cmd is AssertCmd) || (cmd is HavocCmd) || (cmd is SimpleAssignCmd)||(cmd is ArrayAssignCmd)) {
+ cmd.Emit(outstream,level);
+ WriteIndent(outstream,level);
+ if(last_cmd) outstream.WriteLine("call CheckGuarantee("+thread_no.ToString()+");");
+ else outstream.WriteLine("call MayUpdate("+thread_no.ToString()+");");
+ } else if(cmd is AssumeCmd) {
+ WriteIndent(outstream,level);
+ if(last_cmd) outstream.Write("call CheckGuarantee("+thread_no.ToString()+");");
+ else {
+ outstream.Write("call MayUpdateAssume(");
+ outstream.Write(thread_no.ToString()+",");
+ PredicateCmd! pcmd=(PredicateCmd)cmd;
+ pcmd.Expr.Emit(outstream);
+ outstream.WriteLine(");");
+ }
+ } else {
+ Console.Error.Write("Unknown command: ");
+ cmd.Emit(new TokenTextWriter("<console>",Console.Error),0);
+ return false;
+ }
+ return true;
+ }//end InstrumentizeCmd(...)
+
+ //Prints the procedure which checks the correct interleaving of the specifications
+ bool PrintInterleaving(TokenTextWriter! outstream,int number_of_threads,List<Variable!>! sharedVars,
+ string! history_pre_prefix,string! history_post_prefix,int n, bool phase_number_finite,
+ int phases_no) {
+ outstream.WriteLine();
+ outstream.WriteLine("procedure Interleave()");
+ outstream.Write("modifies "); EmitVarList(outstream,sharedVars,null,null,null); outstream.Write(",");
+ EmitVarList(outstream,sharedVars,history_pre_prefix,null,null); outstream.Write(",");
+ EmitVarList(outstream,sharedVars,history_post_prefix,null,null); outstream.WriteLine(";");
+ outstream.WriteLine("{");
+ outstream.WriteLine(" var "+threadNoVarName+":int, "+currentPhaseVarName+":[int]int,");
+ EmitVarList(outstream,sharedVars,history_pre_prefix,null,"[int][int]"); outstream.Write(",");
+ EmitVarList(outstream,sharedVars,history_post_prefix,null,"[int][int]"); outstream.WriteLine(";");
+ outstream.Write(" assume Init("); EmitVarList(outstream,sharedVars,null,null,null); outstream.WriteLine(");");
+ for(int i=0;i<n;i++) {
+ WriteIndent(outstream,1);
+ outstream.WriteLine(currentPhaseVarName+"["+i.ToString()+"]:=0;");
+ }
+ if(phase_number_finite)
+ for(int i=0;i<phases_no*n;i++) {
+ PrintSinglePhaseCode(outstream,1,sharedVars,history_pre_prefix,history_post_prefix,n,true);
+ outstream.WriteLine();
+ }
+ else {
+ outstream.WriteLine(" while(true) {");
+ PrintSinglePhaseCode(outstream,2,sharedVars,history_pre_prefix,history_post_prefix,n,false);
+ outstream.WriteLine(" }");
+ }
+ outstream.WriteLine("}");
+ return true;
+ }//end PrintInterleaving(...)
+
+ //print a code which checks the relies for some thread for its one phase
+ void PrintSinglePhaseCode(TokenTextWriter! outstream, int level,List<Variable!>! sharedVars,
+ string! history_pre_prefix,string! history_post_prefix, int n,
+ bool phase_number_finite) {
+ WriteIndent(outstream,level); outstream.WriteLine("havoc "+threadNoVarName+";");
+ WriteIndent(outstream,level); outstream.Write("assume ");
+ for(int i=0;(i+1)<n;i++)
+ outstream.Write(threadNoVarName+"=="+i.ToString()+" || ");
+ outstream.WriteLine(threadNoVarName+"=="+(n-1).ToString()+";");
+
+ if(phase_number_finite) {
+ WriteIndent(outstream,level);
+ outstream.WriteLine("assume "+currentPhaseVarName+"["+threadNoVarName+"]<"+totalPhasesName+";");
+ }
+ foreach(Variable! v in sharedVars) {
+ WriteIndent(outstream,level);
+ outstream.WriteLine(history_pre_prefix+v.Name+"["+threadNoVarName+"]:="+
+ history_pre_prefix+v.Name+"["+threadNoVarName+"]["+currentPhaseVarName+"["+threadNoVarName+"]:="+v.Name+"];");
+ }
+
+ WriteIndent(outstream,level);
+ outstream.Write("assert A("+threadNoVarName+","+currentPhaseVarName+"["+threadNoVarName+"],");
+ EmitVarList(outstream,sharedVars,history_pre_prefix,"["+threadNoVarName+"]",null); outstream.Write(",");
+ EmitVarList(outstream,sharedVars,history_post_prefix,"["+threadNoVarName+"]",null); outstream.WriteLine(");");
+
+ WriteIndent(outstream,level);
+ outstream.Write("assume G("+threadNoVarName+","+currentPhaseVarName+"["+threadNoVarName+"],");
+ EmitVarList(outstream,sharedVars,history_pre_prefix,"["+threadNoVarName+"]",null); outstream.Write(",");
+ EmitVarList(outstream,sharedVars,history_post_prefix,"["+threadNoVarName+"]",null); outstream.WriteLine(");");
+
+ WriteIndent(outstream,level); outstream.Write("havoc ");
+ EmitVarList(outstream,sharedVars,null,null,null); outstream.WriteLine(";");
+
+ foreach(Variable! v in sharedVars) {
+ WriteIndent(outstream,level);
+ outstream.WriteLine("assume "+history_post_prefix+v.Name+"["+threadNoVarName+"]["+currentPhaseVarName+"["+threadNoVarName+"]]=="+v.Name+";");
+ }
+ WriteIndent(outstream,level);
+ outstream.WriteLine(currentPhaseVarName+"["+threadNoVarName+"]:="+currentPhaseVarName+"["+threadNoVarName+"]+1;");
+ }//end PrintSinglePhaseCode(...)
+
+ }//end class
+}//end namespace
diff --git a/Source/XAHA/XAHA.sscproj b/Source/XAHA/XAHA.sscproj
new file mode 100644
index 00000000..402217cd
--- /dev/null
+++ b/Source/XAHA/XAHA.sscproj
@@ -0,0 +1,93 @@
+<?xml version="1.0" encoding="utf-8"?>
+<VisualStudioProject>
+ <XEN ProjectType="Local"
+ SchemaVersion="1.0"
+ Name="XAHA"
+ ProjectGuid="bc052cd8-7d87-4520-aff9-d3ac81161905"
+ >
+ <Build>
+ <Settings ApplicationIcon=""
+ AssemblyName="XAHA"
+ OutputType="Library"
+ RootNamespace="XAHA"
+ StartupObject=""
+ StandardLibraryLocation=""
+ TargetPlatform="v2"
+ TargetPlatformLocation=""
+ >
+ <Config Name="Debug"
+ AllowUnsafeBlocks="False"
+ BaseAddress="285212672"
+ CheckForOverflowUnderflow="False"
+ ConfigurationOverrideFile=""
+ DefineConstants="DEBUG;TRACE"
+ DocumentationFile=""
+ DebugSymbols="True"
+ FileAlignment="4096"
+ IncrementalBuild="True"
+ Optimize="False"
+ OutputPath="bin\debug"
+ RegisterForComInterop="False"
+ RemoveIntegerChecks="false"
+ TreatWarningsAsErrors="False"
+ WarningLevel="4"
+ CheckContractAdmissibility="True"
+ CheckPurity="False"
+ />
+ <Config Name="Release"
+ AllowUnsafeBlocks="false"
+ BaseAddress="285212672"
+ CheckForOverflowUnderflow="false"
+ ConfigurationOverrideFile=""
+ DefineConstants="TRACE"
+ DocumentationFile=""
+ DebugSymbols="false"
+ FileAlignment="4096"
+ IncrementalBuild="false"
+ Optimize="true"
+ OutputPath="bin\release"
+ RegisterForComInterop="false"
+ RemoveIntegerChecks="false"
+ TreatWarningsAsErrors="false"
+ WarningLevel="4"
+ CheckContractAdmissibility="True"
+ CheckPurity="False"
+ />
+ </Settings>
+ <References>
+ <Reference Name="System"
+ AssemblyName="System"
+ Private="false"
+ />
+ <Reference Name="System.Data"
+ AssemblyName="System.Data"
+ Private="false"
+ />
+ <Reference Name="System.Xml"
+ AssemblyName="System.Xml"
+ Private="false"
+ />
+ <Reference Name="Core"
+ Project="{47BC34F1-A173-40BE-84C2-9332B4418387}"
+ Private="true"
+ />
+ <Reference Name="Basetypes"
+ Project="{0C692837-77EC-415F-BF04-395E3ED06E9A}"
+ Private="true"
+ />
+ </References>
+ </Build>
+ <Files>
+ <Include>
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="XAHA.ssc"
+ />
+ <File BuildAction="Compile"
+ SubType="Code"
+ RelPath="..\version.ssc"
+ />
+ </Include>
+ </Files>
+ </XEN>
+</VisualStudioProject> \ No newline at end of file
diff --git a/Source/foo.txt b/Source/foo.txt
new file mode 100644
index 00000000..99d2b9ea
--- /dev/null
+++ b/Source/foo.txt
@@ -0,0 +1,93 @@
+Change 3641 by REDMOND\mbarnett@mbarnettx60 on 2009/07/14 16:08:17
+
+ Added copyright notices to all source files.
+
+Affected files ...
+
+... //depot/projects/BoogieBranches/CodePlex/Source/AbsInt/AbstractInterpretation.ssc#4 edit
+... //depot/projects/BoogieBranches/CodePlex/Source/AbsInt/ExprFactories.ssc#3 edit
+... //depot/projects/BoogieBranches/CodePlex/Source/AbsInt/LoopInvariantsOnDemand.ssc#2 edit
+... //depot/projects/BoogieBranches/CodePlex/Source/AbsInt/Traverse.ssc#2 edit
+... //depot/projects/BoogieBranches/CodePlex/Source/AIFramework/CommonFunctionSymbols.ssc#3 edit
+... //depot/projects/BoogieBranches/CodePlex/Source/AIFramework/Expr.ssc#2 edit
+... //depot/projects/BoogieBranches/CodePlex/Source/AIFramework/Functional.ssc#2 edit
+... //depot/projects/BoogieBranches/CodePlex/Source/AIFramework/Lattice.ssc#2 edit
+... //depot/projects/BoogieBranches/CodePlex/Source/AIFramework/Logger.ssc#2 edit
+... //depot/projects/BoogieBranches/CodePlex/Source/AIFramework/MultiLattice.ssc#2 edit
+... //depot/projects/BoogieBranches/CodePlex/Source/AIFramework/Mutable.ssc#2 edit
+... //depot/projects/BoogieBranches/CodePlex/Source/AIFramework/Polyhedra/LinearConstraint.ssc#2 edit
+... //depot/projects/BoogieBranches/CodePlex/Source/AIFramework/Polyhedra/LinearConstraintSystem.ssc#2 edit
+... //depot/projects/BoogieBranches/CodePlex/Source/AIFramework/Polyhedra/PolyhedraAbstraction.ssc#2 edit
+... //depot/projects/BoogieBranches/CodePlex/Source/AIFramework/Polyhedra/SimplexTableau.ssc#2 edit
+... //depot/projects/BoogieBranches/CodePlex/Source/AIFramework/VariableMap/ConstantAbstraction.ssc#2 edit
+... //depot/projects/BoogieBranches/CodePlex/Source/AIFramework/VariableMap/ConstantExpressions.ssc#2 edit
+... //depot/projects/BoogieBranches/CodePlex/Source/AIFramework/VariableMap/DynamicTypeLattice.ssc#2 edit
+... //depot/projects/BoogieBranches/CodePlex/Source/AIFramework/VariableMap/Intervals.ssc#2 edit
+... //depot/projects/BoogieBranches/CodePlex/Source/AIFramework/VariableMap/MicroLattice.ssc#2 edit
+... //depot/projects/BoogieBranches/CodePlex/Source/AIFramework/VariableMap/Nullness.ssc#2 edit
+... //depot/projects/BoogieBranches/CodePlex/Source/AIFramework/VariableMap/VariableMapLattice.ssc#2 edit
+... //depot/projects/BoogieBranches/CodePlex/Source/Basetypes/BigNum.ssc#2 edit
+... //depot/projects/BoogieBranches/CodePlex/Source/Basetypes/Rational.ssc#2 edit
+... //depot/projects/BoogieBranches/CodePlex/Source/Basetypes/Set.ssc#2 edit
+... //depot/projects/BoogieBranches/CodePlex/Source/BoogieDriver/BoogieDriver.ssc#3 edit
+... //depot/projects/BoogieBranches/CodePlex/Source/Core/Absy.ssc#2 edit
+... //depot/projects/BoogieBranches/CodePlex/Source/Core/AbsyCmd.ssc#2 edit
+... //depot/projects/BoogieBranches/CodePlex/Source/Core/AbsyExpr.ssc#3 edit
+... //depot/projects/BoogieBranches/CodePlex/Source/Core/AbsyType.ssc#2 edit
+... //depot/projects/BoogieBranches/CodePlex/Source/Core/CommandLineOptions.ssc#3 edit
+... //depot/projects/BoogieBranches/CodePlex/Source/Core/Duplicator.ssc#2 edit
+... //depot/projects/BoogieBranches/CodePlex/Source/Core/GraphAlgorithms.ssc#2 edit
+... //depot/projects/BoogieBranches/CodePlex/Source/Core/Inline.ssc#2 edit
+... //depot/projects/BoogieBranches/CodePlex/Source/Core/LoopUnroll.ssc#2 edit
+... //depot/projects/BoogieBranches/CodePlex/Source/Core/OOLongUtil.ssc#2 edit
+... //depot/projects/BoogieBranches/CodePlex/Source/Core/Parser.ssc#2 edit
+... //depot/projects/BoogieBranches/CodePlex/Source/Core/PureCollections.ssc#2 edit
+... //depot/projects/BoogieBranches/CodePlex/Source/Core/ResolutionContext.ssc#2 edit
+... //depot/projects/BoogieBranches/CodePlex/Source/Core/Scanner.ssc#2 edit
+... //depot/projects/BoogieBranches/CodePlex/Source/Core/StandardVisitor.ssc#2 edit
+... //depot/projects/BoogieBranches/CodePlex/Source/Core/TypeAmbiguitySeeker.ssc#2 edit
+... //depot/projects/BoogieBranches/CodePlex/Source/Core/Util.ssc#2 edit
+... //depot/projects/BoogieBranches/CodePlex/Source/Core/VCExp.ssc#2 edit
+... //depot/projects/BoogieBranches/CodePlex/Source/Core/Xml.ssc#2 edit
+... //depot/projects/BoogieBranches/CodePlex/Source/Dafny/Dafny.atg#2 edit
+... //depot/projects/BoogieBranches/CodePlex/Source/Dafny/DafnyAst.ssc#2 edit
+... //depot/projects/BoogieBranches/CodePlex/Source/Dafny/DafnyMain.ssc#2 edit
+... //depot/projects/BoogieBranches/CodePlex/Source/Dafny/Parser.ssc#2 edit
+... //depot/projects/BoogieBranches/CodePlex/Source/Dafny/Printer.ssc#2 edit
+... //depot/projects/BoogieBranches/CodePlex/Source/Dafny/Resolver.ssc#2 edit
+... //depot/projects/BoogieBranches/CodePlex/Source/Dafny/Scanner.ssc#2 edit
+... //depot/projects/BoogieBranches/CodePlex/Source/Dafny/Translator.ssc#2 edit
+... //depot/projects/BoogieBranches/CodePlex/Source/DafnyDriver/DafnyDriver.ssc#3 edit
+... //depot/projects/BoogieBranches/CodePlex/Source/Graph/Graph.ssc#2 edit
+... //depot/projects/BoogieBranches/CodePlex/Source/Provers/Simplify/Let2ImpliesVisitor.ssc#2 edit
+... //depot/projects/BoogieBranches/CodePlex/Source/Provers/Simplify/Prover.ssc#2 edit
+... //depot/projects/BoogieBranches/CodePlex/Source/Provers/Simplify/ProverInterface.ssc#3 edit
+... //depot/projects/BoogieBranches/CodePlex/Source/Provers/SMTLib/ProverInterface.ssc#2 edit
+... //depot/projects/BoogieBranches/CodePlex/Source/Provers/SMTLib/SMTLibLineariser.ssc#3 edit
+... //depot/projects/BoogieBranches/CodePlex/Source/Provers/SMTLib/TypeDeclCollector.ssc#2 edit
+... //depot/projects/BoogieBranches/CodePlex/Source/Provers/Z3/Inspector.ssc#2 edit
+... //depot/projects/BoogieBranches/CodePlex/Source/Provers/Z3/Prover.ssc#3 edit
+... //depot/projects/BoogieBranches/CodePlex/Source/Provers/Z3/ProverInterface.ssc#2 edit
+... //depot/projects/BoogieBranches/CodePlex/Source/Provers/Z3/TypeDeclCollector.ssc#2 edit
+... //depot/projects/BoogieBranches/CodePlex/Source/VCExpr/BigLiteralAbstracter.ssc#2 edit
+... //depot/projects/BoogieBranches/CodePlex/Source/VCExpr/Boogie2VCExpr.ssc#3 edit
+... //depot/projects/BoogieBranches/CodePlex/Source/VCExpr/Clustering.ssc#2 edit
+... //depot/projects/BoogieBranches/CodePlex/Source/VCExpr/LetBindingSorter.ssc#2 edit
+... //depot/projects/BoogieBranches/CodePlex/Source/VCExpr/NameClashResolver.ssc#2 edit
+... //depot/projects/BoogieBranches/CodePlex/Source/VCExpr/SimplifyLikeLineariser.ssc#3 edit
+... //depot/projects/BoogieBranches/CodePlex/Source/VCExpr/TermFormulaFlattening.ssc#2 edit
+... //depot/projects/BoogieBranches/CodePlex/Source/VCExpr/TypeErasure.ssc#3 edit
+... //depot/projects/BoogieBranches/CodePlex/Source/VCExpr/TypeErasureArguments.ssc#2 edit
+... //depot/projects/BoogieBranches/CodePlex/Source/VCExpr/TypeErasurePremisses.ssc#2 edit
+... //depot/projects/BoogieBranches/CodePlex/Source/VCExpr/VCExprAST.ssc#3 edit
+... //depot/projects/BoogieBranches/CodePlex/Source/VCExpr/VCExprASTPrinter.ssc#3 edit
+... //depot/projects/BoogieBranches/CodePlex/Source/VCExpr/VCExprASTVisitors.ssc#3 edit
+... //depot/projects/BoogieBranches/CodePlex/Source/VCGeneration/Check.ssc#2 edit
+... //depot/projects/BoogieBranches/CodePlex/Source/VCGeneration/ConditionGeneration.ssc#2 edit
+... //depot/projects/BoogieBranches/CodePlex/Source/VCGeneration/Context.ssc#2 edit
+... //depot/projects/BoogieBranches/CodePlex/Source/VCGeneration/OrderingAxioms.ssc#2 edit
+... //depot/projects/BoogieBranches/CodePlex/Source/VCGeneration/VC.ssc#3 edit
+... //depot/projects/BoogieBranches/CodePlex/Source/VCGeneration/VCDoomed.ssc#2 edit
+... //depot/projects/BoogieBranches/CodePlex/Source/VCGeneration/Wlp.ssc#2 edit
+... //depot/projects/BoogieBranches/CodePlex/Source/version.ssc#2 edit
+
diff --git a/Source/version.ssc b/Source/version.ssc
new file mode 100644
index 00000000..bad3d890
--- /dev/null
+++ b/Source/version.ssc
@@ -0,0 +1,8 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using System.Reflection;
+[assembly: AssemblyVersion("1.0.21125.0")]
+[assembly: AssemblyFileVersion("1.0.21125.0")]
diff --git a/Test/CollectBenchmarks.py b/Test/CollectBenchmarks.py
new file mode 100644
index 00000000..d5c8a233
--- /dev/null
+++ b/Test/CollectBenchmarks.py
@@ -0,0 +1,295 @@
+#! /usr/bin/python
+
+# 13 Aug 2006 Alexander Fuchs
+#
+# creates bpl and prover files for all test cases
+# and puts these into a zip file
+
+import sys;
+import os;
+import shutil;
+import re;
+import zipfile;
+
+
+#PROVER_NAME = "smt"
+PROVER_NAME = "simplify"
+
+# constants
+# prefix of temporary files created by boogie
+PREFIX_TMP = "boogie_tmp"
+
+# prefix of files put into package
+PREFIX_PGK = "boogie"
+
+# arguments to runtest so that boogie creates problem specifications
+BOOGIE_ARG0 = "/prover:blank /print:" + PREFIX_TMP + ".@TIME@.bpl /proverLog:" + PREFIX_TMP + ".@TIME@.simplify"
+BOOGIE_ARG1 = "/prover:smt /print:" + PREFIX_TMP + ".@TIME@.bpl /proverLog:" + PREFIX_TMP + ".@TIME@.jjsmt"
+
+# file containing the directories with tests
+TESTS_FILE = "alltests.txt"
+
+# marker in boogie generated proover files to denote end of background axioms
+START_OF_AXIOMS = "; Boogie universal background predicate"
+END_OF_AXIOMS = "; Initialized all axioms."
+
+# assumptions:
+# files: problems, runtest
+# calling boogie: parameters and filename only
+
+
+
+
+
+# call runtests to create the bpl/prover specifications:
+# - /print creates the boogie bpl file
+# - /proverLog creates the prover verification condition
+# @TIME@ is used to create a unique file name per test case
+def runtests(parameters):
+ boogie_arg = BOOGIE_ARG0
+ if PROVER_NAME == "simplify":
+ boogie_arg = BOOGIE_ARG0
+ if PROVER_NAME == "smt":
+ boogie_arg = BOOGIE_ARG1
+ if os.name == "nt":
+ command = "runtestall.bat " + " ".join(parameters) + " " + boogie_arg
+ else:
+ command = "./rtestall " + " ".join(parameters) + " " + boogie_arg
+
+ print command
+
+ os.system(command)
+
+
+# evaluates a call to boogie, which is of the form:
+# ; Command Line Options: -nologo /print:boogie_testcase.@TIME@.bpl /proverLog:boogie_testcase.@TIME@.'prover' SimpleAssignments0.dll /infer:i
+#
+# returns (file_name, parameters), where
+# - file_name: the called file name (e.g. SimpleAssignments0.dll)
+# - parameters: boogie parameters except for nologo, print, proverLog
+def process_boogie_call(line):
+ match = re.match("; Command Line Options:(?P<parameters>.*)$", line)
+ parameters = match.group("parameters")
+ parameters = re.split("\s", parameters)
+
+ copy = []
+ for parameter in parameters:
+ # file names on DOS seem not to like containing ":", so replace by "_"
+ parameter = re.sub(":", "_", parameter)
+ # ignore these parameters
+ if parameter == "":
+ ()
+ elif re.match("-nologo", parameter):
+ ()
+ elif re.match("/nologo", parameter):
+ ()
+ elif re.match("/print", parameter):
+ ()
+ elif re.match("/proverLog", parameter):
+ ()
+ elif re.match("-prover", parameter):
+ ()
+ elif re.match("/prover", parameter):
+ ()
+
+ # keep any other parameter
+ elif re.match("-", parameter):
+ copy.append(parameter)
+ elif re.match("/", parameter):
+ copy.append("-" + parameter[1:])
+
+ # get the file name
+ elif re.match("[a-zA-Z]", parameter):
+ file_name = parameter
+
+ # don't know what that is
+ else:
+ raise ("process_parameters: unknown argument: " + parameter)
+
+ # couldn't find the file name???
+ if not file_name:
+ raise ("split_parameters: file_name not found in: " + parameters)
+
+ else:
+ return (file_name, copy)
+
+
+
+
+# evaluates the file name on which boogie was called, which is of the form:
+# SimpleAssignments0.dll
+#
+# returns (file_name, is_dll):
+# - file_name: the file name, e.g. SimpleAssignments0
+# - is_dll: if it was a dll or exe, and not a bpl file
+def process_file_name(file_name):
+ if re.match("^[a-zA-Z].*\.dll$", file_name.lower()):
+ return (file_name[:-4], 1)
+ elif re.match("^[a-zA-Z].*\.exe$", file_name.lower()):
+ return (file_name[:-4], 1)
+ elif re.match("^[a-zA-Z].*\.bpl$", file_name.lower()):
+ return (file_name[:-4], 0)
+ else:
+ return (file_name, 1)
+# else:
+# raise ("process_file_name: neither dll nor bpl: " + file_name)
+
+
+
+# creates the package name for a package file (without extension)
+# the file name creation scheme used here is not unique,
+# so a unique id is added in addition
+names = {}
+def create_pgk_name(suite, problem_name, condition_name, parameters, extension):
+ # things like LESS, less happen, doesn't work under Windows
+ name = (problem_name + condition_name + extension).lower()
+ if name in names:
+ names[name] = names[name] + 1
+ name_id = "_" + repr(names[name])
+ else:
+ names[name] = 0
+ name_id = ""
+
+ if condition_name != "":
+ condition_name = "_" + condition_name
+
+ return os.path.join(suite, PREFIX_PGK + "_" + problem_name + condition_name + "".join(parameters) + name_id + "." + extension)
+
+
+
+# creates the bpl package file and adds it to the manifest
+def create_bpl(suite, source_name, problem_name, is_dll, parameters, manifest):
+ # create unique problem file_name
+ target_name = create_pgk_name(suite, problem_name, "", parameters, "bpl")
+
+ # copy bpl
+ if is_dll:
+ # started from dll/exe, so rename converted bpl
+ source_name = os.path.join(suite, source_name[:-1-len(PROVER_NAME)] + ".bpl")
+ os.rename(source_name, target_name)
+ else:
+ # started from existing bpl, so just copy it
+ source_name = os.path.join(suite, problem_name + ".bpl")
+ shutil.copy(source_name, target_name)
+
+ manifest.append(target_name)
+
+
+
+def create_simplify(suite, problem_name, parameters, file, manifest):
+ # get background axioms
+ background = []
+ next = file.readline()
+ if (re.match("; -------------------------------------------------------------------------", next)):
+ next = file.readline()
+ if (re.match(START_OF_AXIOMS, next)):
+ while(not re.match(END_OF_AXIOMS, next)):
+ background.append(next)
+ next = file.readline()
+
+ next = file.readline()
+
+
+ # get individual queries
+ name = next
+ while(name):
+ query = file.readline()
+ status = file.readline()
+
+ # create simplify file for this query
+ match = re.match("; (?P<name>\S+)", name)
+ condition_name = match.group("name")
+ query_file_name = create_pgk_name(suite, problem_name, condition_name, parameters, PROVER_NAME)
+
+ query_file = open(query_file_name, 'w')
+ query_file.writelines(background)
+ query_file.write(name)
+ query_file.write(query)
+ query_file.write(status)
+ query_file.close()
+
+ manifest.append(query_file_name)
+
+ name = file.readline()
+
+
+
+
+
+#
+# main
+#
+
+# create problem specifications
+runtests(sys.argv[1:])
+
+# list of created files
+manifest = []
+# list of generated bpl files
+bpl_files = []
+
+# go into each test directory
+suites = open(TESTS_FILE)
+for suite in suites.readlines():
+ suite = re.split("\s", suite)[0]
+ #print suite
+
+ # find the created simplify input files
+ files = os.listdir(suite)
+
+ prover_files = filter(lambda file: re.search(PREFIX_TMP + ("\S+\.%s$" % PROVER_NAME) , file), files)
+ prover_files.sort()
+
+ new_bpl_files = filter(lambda file: re.search(PREFIX_TMP + "\S+\.bpl$" , file), files)
+ bpl_files.extend(map(lambda file: os.path.join(suite, file), new_bpl_files))
+
+
+ # process each prover input file
+ for prover_file in prover_files:
+ # parse header
+ file = open(os.path.join(suite, prover_file))
+ line = file.readline()
+ line = file.readline()
+ (file_name, parameters) = process_boogie_call(line)
+ (problem_name, is_dll) = process_file_name(file_name)
+
+ # create bpl file
+ create_bpl(suite, prover_file, problem_name, is_dll, parameters, manifest)
+
+ # keep prover file for all queries
+ target_name = create_pgk_name(suite, problem_name, "", parameters, PROVER_NAME)
+ manifest.append(target_name)
+
+ # split prover file into individual queries
+ if PROVER_NAME == "simplify":
+ create_simplify(suite, problem_name, parameters, file, manifest)
+ file.close()
+
+ os.rename(os.path.join(suite, prover_file), target_name)
+
+suites.close()
+
+
+
+#print "\n".join(manifest)
+
+# create package
+#print "zipping"
+zipFile = zipfile.ZipFile("boogie-benchmarks.zip", 'w', zipfile.ZIP_DEFLATED)
+for file_name in manifest:
+ zipFile.write(file_name)
+zipFile.close()
+
+# clean up
+for file_name in manifest:
+ os.remove(file_name)
+
+
+# some bpl files are create with /noVerify,
+# and then no prover file is generated,
+# so these files are just ignored and removed
+for file_name in bpl_files:
+ try:
+ os.remove(file_name)
+ except OSError:
+ ()
diff --git a/Test/CompareAll b/Test/CompareAll
new file mode 100644
index 00000000..1dfebd87
--- /dev/null
+++ b/Test/CompareAll
@@ -0,0 +1,22 @@
+#!/usr/bin/bash
+
+# ALL_TESTS=`cat alltests.txt | grep -E "^[[:alnum:]-]+\W+Use\W" | awk '{print $1}'`
+ALL_TESTS=`cat alltests.txt | grep -E "^[^[:space:]]+[[:space:]]+(Use|Long)[[:space:]]" | awk '{print $1}'`
+
+echo ---------- All tests ---------- > Answer-all
+for t in ${ALL_TESTS} ; do
+ echo ====================================================================== >> Answer-all
+ echo ======================================== $t >> Answer-all
+ echo ====================================================================== >> Answer-all
+ cat $t/Answer >> Answer-all
+done
+
+echo ---------- All tests ---------- > Output-all
+for t in ${ALL_TESTS} ; do
+ echo ====================================================================== >> Output-all
+ echo ======================================== $t >> Output-all
+ echo ====================================================================== >> Output-all
+ cat $t/Output >> Output-all
+done
+
+echo All answers collected in Answer-all and all outputs in Output-all
diff --git a/Test/aitest0/Answer b/Test/aitest0/Answer
new file mode 100644
index 00000000..58750460
--- /dev/null
+++ b/Test/aitest0/Answer
@@ -0,0 +1,111 @@
+var GlobalFlag: bool;
+
+const A: int;
+
+const B: int;
+
+const C: int;
+
+procedure Join(b: bool);
+ modifies GlobalFlag;
+
+
+
+implementation Join(b: bool)
+{
+ var x: int;
+ var y: int;
+ var z: int;
+
+ start:
+ assume true;
+ GlobalFlag := true;
+ x := 3;
+ y := 4;
+ z := x + y;
+ assume x == 3 && y == 4 && z == 7;
+ goto Then, Else;
+
+ Then:
+ assume x == 3 && y == 4 && z == 7;
+ assume b <==> true;
+ x := x + 1;
+ assume x == 4 && y == 4 && z == 7;
+ goto join;
+
+ Else:
+ assume x == 3 && y == 4 && z == 7;
+ assume b <==> false;
+ y := 4;
+ assume x == 3 && y == 4 && z == 7;
+ goto join;
+
+ join:
+ assume y == 4 && z == 7;
+ assert y == 4;
+ assert z == 7;
+ assert GlobalFlag <==> true;
+ assume y == 4 && z == 7;
+ return;
+}
+
+
+
+procedure Loop();
+
+
+
+implementation Loop()
+{
+ var c: int;
+ var i: int;
+
+ start:
+ assume true;
+ c := 0;
+ i := 0;
+ assume c == 0 && i == 0;
+ goto test;
+
+ test: // cut point
+ assume c == 0;
+ assume c == 0;
+ goto Then, Else;
+
+ Then:
+ assume c == 0;
+ assume i < 10;
+ i := i + 1;
+ assume c == 0;
+ goto test;
+
+ Else:
+ assume c == 0;
+ assume c == 0;
+ return;
+}
+
+
+
+procedure Evaluate();
+
+
+
+implementation Evaluate()
+{
+ var i: int;
+
+ start:
+ assume true;
+ i := 5;
+ i := 3 * i + 1;
+ i := 3 * (i + 1);
+ i := 1 + 3 * i;
+ i := (i + 1) * 3;
+ assume i == 465;
+ return;
+}
+
+
+
+Boogie program verifier finished with 0 verified, 0 errors
diff --git a/Test/aitest0/Output b/Test/aitest0/Output
new file mode 100644
index 00000000..58750460
--- /dev/null
+++ b/Test/aitest0/Output
@@ -0,0 +1,111 @@
+var GlobalFlag: bool;
+
+const A: int;
+
+const B: int;
+
+const C: int;
+
+procedure Join(b: bool);
+ modifies GlobalFlag;
+
+
+
+implementation Join(b: bool)
+{
+ var x: int;
+ var y: int;
+ var z: int;
+
+ start:
+ assume true;
+ GlobalFlag := true;
+ x := 3;
+ y := 4;
+ z := x + y;
+ assume x == 3 && y == 4 && z == 7;
+ goto Then, Else;
+
+ Then:
+ assume x == 3 && y == 4 && z == 7;
+ assume b <==> true;
+ x := x + 1;
+ assume x == 4 && y == 4 && z == 7;
+ goto join;
+
+ Else:
+ assume x == 3 && y == 4 && z == 7;
+ assume b <==> false;
+ y := 4;
+ assume x == 3 && y == 4 && z == 7;
+ goto join;
+
+ join:
+ assume y == 4 && z == 7;
+ assert y == 4;
+ assert z == 7;
+ assert GlobalFlag <==> true;
+ assume y == 4 && z == 7;
+ return;
+}
+
+
+
+procedure Loop();
+
+
+
+implementation Loop()
+{
+ var c: int;
+ var i: int;
+
+ start:
+ assume true;
+ c := 0;
+ i := 0;
+ assume c == 0 && i == 0;
+ goto test;
+
+ test: // cut point
+ assume c == 0;
+ assume c == 0;
+ goto Then, Else;
+
+ Then:
+ assume c == 0;
+ assume i < 10;
+ i := i + 1;
+ assume c == 0;
+ goto test;
+
+ Else:
+ assume c == 0;
+ assume c == 0;
+ return;
+}
+
+
+
+procedure Evaluate();
+
+
+
+implementation Evaluate()
+{
+ var i: int;
+
+ start:
+ assume true;
+ i := 5;
+ i := 3 * i + 1;
+ i := 3 * (i + 1);
+ i := 1 + 3 * i;
+ i := (i + 1) * 3;
+ assume i == 465;
+ return;
+}
+
+
+
+Boogie program verifier finished with 0 verified, 0 errors
diff --git a/Test/aitest0/constants.bpl b/Test/aitest0/constants.bpl
new file mode 100644
index 00000000..3a47bfcd
--- /dev/null
+++ b/Test/aitest0/constants.bpl
@@ -0,0 +1,69 @@
+// Test the constant propagation AI
+
+var GlobalFlag : bool;
+
+const A, B, C:int; // Consts
+
+procedure Join (b : bool)
+ modifies GlobalFlag;
+{
+ var x, y, z:int;
+
+ start:
+ GlobalFlag := true;
+ x := 3;
+ y := 4;
+ z := x + y;
+ goto Then, Else; // if (b)
+
+ Then:
+ assume b == true;
+ x := x + 1;
+ goto join;
+
+ Else:
+ assume b == false;
+ y := 4;
+ goto join;
+
+ join:
+ assert y == 4;
+ assert z == 7;
+ assert GlobalFlag == true;
+ return;
+}
+
+
+procedure Loop ()
+{
+ var c, i: int;
+
+ start:
+ c := 0; i := 0;
+ goto test;
+
+ test:
+ // if (i < 10);
+ goto Then, Else;
+
+ Then:
+ assume (i < 10);
+ i := i + 1;
+ goto test;
+
+ Else:
+ return;
+}
+
+procedure Evaluate ()
+{
+ var i : int;
+
+ start:
+ i := 5;
+ i := 3 * i + 1;
+ i := 3 * (i + 1);
+ i := 1 + 3 * i;
+ i := (i + 1) * 3;
+ return;
+}
diff --git a/Test/aitest0/runtest.bat b/Test/aitest0/runtest.bat
new file mode 100644
index 00000000..15f36ab0
--- /dev/null
+++ b/Test/aitest0/runtest.bat
@@ -0,0 +1,6 @@
+@echo off
+setlocal
+
+set BGEXE=..\..\Binaries\Boogie.exe
+
+%BGEXE% %* -infer:c -printInstrumented -noVerify constants.bpl
diff --git a/Test/aitest1/Answer b/Test/aitest1/Answer
new file mode 100644
index 00000000..4e5c8f27
--- /dev/null
+++ b/Test/aitest1/Answer
@@ -0,0 +1,510 @@
+-------------------- ineq.bpl --------------------
+procedure SimpleLoop();
+
+
+
+implementation SimpleLoop()
+{
+ var i: int;
+
+ start:
+ assume true;
+ i := 0;
+ assume i == 0;
+ goto test;
+
+ test: // cut point
+ assume 0 <= i;
+ assume 0 <= i;
+ goto Then, Else;
+
+ Then:
+ assume 0 <= i;
+ assume i < 10;
+ i := i + 1;
+ assume i <= 10 && 1 <= i;
+ goto test;
+
+ Else:
+ assume 0 <= i;
+ assume !(i < 10);
+ assume 10 <= i;
+ return;
+}
+
+
+
+procedure VariableBoundLoop(n: int);
+
+
+
+implementation VariableBoundLoop(n: int)
+{
+ var i: int;
+
+ start:
+ assume true;
+ i := 0;
+ assume i == 0;
+ goto test;
+
+ test: // cut point
+ assume 0 <= i;
+ assume 0 <= i;
+ goto Then, Else;
+
+ Then:
+ assume 0 <= i;
+ assume i < n;
+ i := i + 1;
+ assume i <= n && 1 <= i;
+ goto test;
+
+ Else:
+ assume 0 <= i;
+ assume !(i < n);
+ assume n <= i && 0 <= i;
+ return;
+}
+
+
+
+procedure Foo();
+
+
+
+implementation Foo()
+{
+ var i: int;
+
+ start:
+ assume true;
+ i := 3 * i + 1;
+ i := 3 * (i + 1);
+ i := 1 + 3 * i;
+ i := (i + 1) * 3;
+ assume true;
+ return;
+}
+
+
+
+procedure FooToo();
+
+
+
+implementation FooToo()
+{
+ var i: int;
+
+ start:
+ assume true;
+ i := 5;
+ i := 3 * i + 1;
+ i := 3 * (i + 1);
+ i := 1 + 3 * i;
+ i := (i + 1) * 3;
+ assume 1 / 3 * i == 155;
+ return;
+}
+
+
+
+procedure FooTooStepByStep();
+
+
+
+implementation FooTooStepByStep()
+{
+ var i: int;
+
+ L0:
+ assume true;
+ i := 5;
+ assume i == 5;
+ goto L1;
+
+ L1:
+ assume i == 5;
+ i := 3 * i + 1;
+ assume i == 16;
+ goto L2;
+
+ L2:
+ assume i == 16;
+ i := 3 * (i + 1);
+ assume 1 / 3 * i == 17;
+ goto L3;
+
+ L3:
+ assume 1 / 3 * i == 17;
+ i := 1 + 3 * i;
+ assume i == 154;
+ goto L4;
+
+ L4:
+ assume i == 154;
+ i := (i + 1) * 3;
+ assume 1 / 3 * i == 155;
+ return;
+}
+
+
+
+Boogie program verifier finished with 0 verified, 0 errors
+-------------------- Linear0.bpl --------------------
+var x: int;
+
+var y: int;
+
+procedure p();
+
+
+
+implementation p()
+{
+
+ start:
+ assume true;
+ assume true;
+ return;
+}
+
+
+
+Boogie program verifier finished with 0 verified, 0 errors
+-------------------- Linear1.bpl --------------------
+var x: int;
+
+var y: int;
+
+procedure p();
+
+
+
+implementation p()
+{
+
+ start:
+ assume true;
+ assume x * x == y;
+ assume true;
+ return;
+}
+
+
+
+Boogie program verifier finished with 0 verified, 0 errors
+-------------------- Linear2.bpl --------------------
+var x: int;
+
+var y: int;
+
+procedure p();
+
+
+
+implementation p()
+{
+
+ start:
+ assume true;
+ assume x == 8;
+ assume x == 8;
+ return;
+}
+
+
+
+Boogie program verifier finished with 0 verified, 0 errors
+-------------------- Linear3.bpl --------------------
+var x: int;
+
+var y: int;
+
+procedure p();
+
+
+
+implementation p()
+{
+
+ start:
+ assume true;
+ assume x < y;
+ assume x + 1 <= y;
+ return;
+}
+
+
+
+Boogie program verifier finished with 0 verified, 0 errors
+-------------------- Linear4.bpl --------------------
+var x: int;
+
+var y: int;
+
+procedure p();
+ modifies x;
+
+
+
+implementation p()
+{
+
+ A:
+ assume true;
+ assume x < y;
+ assume x + 1 <= y;
+ goto B;
+
+ B:
+ assume x + 1 <= y;
+ x := x * x;
+ assume true;
+ return;
+}
+
+
+
+Boogie program verifier finished with 0 verified, 0 errors
+-------------------- Linear5.bpl --------------------
+var x: int;
+
+var y: int;
+
+procedure p();
+ modifies x;
+
+
+
+implementation p()
+{
+
+ A:
+ assume true;
+ assume 0 - 1 <= x;
+ assume -1 <= x;
+ goto B;
+
+ B:
+ assume -1 <= x;
+ assume x < y;
+ assume x + 1 <= y && -1 <= x;
+ goto C;
+
+ C:
+ assume x + 1 <= y && -1 <= x;
+ x := x * x;
+ assume 0 <= y;
+ goto D;
+
+ D:
+ assume 0 <= y;
+ x := y;
+ assume x == y && 0 <= y;
+ return;
+}
+
+
+
+Boogie program verifier finished with 0 verified, 0 errors
+-------------------- Linear6.bpl --------------------
+var x: int;
+
+var y: int;
+
+var z: int;
+
+procedure p();
+ modifies x;
+
+
+
+implementation p()
+{
+
+ A:
+ assume true;
+ x := 8;
+ assume x == 8;
+ goto B, C;
+
+ B:
+ assume x == 8;
+ x := 9;
+ assume x == 9;
+ goto D;
+
+ C:
+ assume x == 8;
+ x := 10;
+ assume x == 10;
+ goto D;
+
+ D:
+ assume 9 <= x && x <= 10;
+ assume 9 <= x && x <= 10;
+ return;
+}
+
+
+
+Boogie program verifier finished with 0 verified, 0 errors
+-------------------- Linear7.bpl --------------------
+var x: int;
+
+var y: int;
+
+var z: int;
+
+procedure p();
+
+
+
+implementation p()
+{
+
+ A:
+ assume true;
+ assume true;
+ goto B, C;
+
+ B:
+ assume true;
+ assume x <= 0;
+ assume x <= 0;
+ goto D;
+
+ C:
+ assume true;
+ assume y <= 0;
+ assume y <= 0;
+ goto D;
+
+ D:
+ assume true;
+ assume true;
+ return;
+}
+
+
+
+Boogie program verifier finished with 0 verified, 0 errors
+-------------------- Linear8.bpl --------------------
+procedure foo();
+
+
+
+implementation foo()
+{
+ var i: int;
+ var j: int;
+ var n: int;
+
+ A:
+ assume true;
+ n := 0;
+ assume n == 0;
+ goto B;
+
+ B:
+ assume n == 0;
+ j := 0;
+ assume j == 0 && n == 0;
+ goto C;
+
+ C:
+ assume j == 0 && n == 0;
+ i := j + 1;
+ assume i == j + 1 && j == 0 && n == 0;
+ goto D;
+
+ D:
+ assume i == j + 1 && j == 0 && n == 0;
+ i := i + 1;
+ assume i == j + 2 && j == 0 && n == 0;
+ goto E;
+
+ E:
+ assume i == j + 2 && j == 0 && n == 0;
+ i := i + 1;
+ assume i == j + 3 && j == 0 && n == 0;
+ goto F;
+
+ F:
+ assume i == j + 3 && j == 0 && n == 0;
+ i := i + 1;
+ assume i == j + 4 && j == 0 && n == 0;
+ goto G;
+
+ G:
+ assume i == j + 4 && j == 0 && n == 0;
+ i := i + 1;
+ assume i == j + 5 && j == 0 && n == 0;
+ goto H;
+
+ H:
+ assume i == j + 5 && j == 0 && n == 0;
+ j := j + 1;
+ assume i == j + 4 && j == 1 && n == 0;
+ goto I;
+
+ I:
+ assume i == j + 4 && j == 1 && n == 0;
+ assume i == j + 4 && j == 1 && n == 0;
+ return;
+}
+
+
+
+Boogie program verifier finished with 0 verified, 0 errors
+-------------------- Linear9.bpl --------------------
+procedure foo();
+
+
+
+implementation foo()
+{
+ var i: int;
+ var j: int;
+ var n: int;
+
+ entry:
+ assume true;
+ assume n >= 4;
+ i := 0;
+ j := i + 1;
+ assume j == i + 1 && i == 0 && 4 <= n;
+ goto exit, loop0;
+
+ loop0: // cut point
+ assume 4 <= n && 0 <= i && j == i + 1;
+ assume j <= n;
+ assume j <= n && 4 <= n && 0 <= i && j == i + 1;
+ goto loop1;
+
+ loop1:
+ assume j <= n && 4 <= n && 0 <= i && j == i + 1;
+ i := i + 1;
+ assume 1 <= i && j == i && j <= n && 4 <= n;
+ goto loop2;
+
+ loop2:
+ assume j <= n && 4 <= n && 1 <= i && j == i;
+ j := j + 1;
+ assume j <= n + 1 && j == i + 1 && 4 <= n && 1 <= i;
+ goto loop0, exit;
+
+ exit:
+ assume j <= n + 1 && 4 <= n && 0 <= i && j == i + 1;
+ assume j <= n + 1 && 4 <= n && 0 <= i && j == i + 1;
+ return;
+}
+
+
+
+Boogie program verifier finished with 0 verified, 0 errors
+-------------------- Bound.bpl --------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
diff --git a/Test/aitest1/Bound.bpl b/Test/aitest1/Bound.bpl
new file mode 100644
index 00000000..02b2c460
--- /dev/null
+++ b/Test/aitest1/Bound.bpl
@@ -0,0 +1,28 @@
+const TEST: name;
+
+procedure P()
+{
+var i: int;
+var N: int;
+
+start:
+ assume N >= 0;
+ i := 0;
+ assert i <= N;
+ goto LoopHead;
+
+LoopHead:
+ goto LoopBody, AfterLoop;
+
+LoopBody:
+ assume i < N;
+ i := i + 1;
+ goto LoopHead;
+
+AfterLoop:
+ assume !(i < N);
+ assert i == N;
+ return;
+}
+
+type name; \ No newline at end of file
diff --git a/Test/aitest1/Linear0.bpl b/Test/aitest1/Linear0.bpl
new file mode 100644
index 00000000..7a11c803
--- /dev/null
+++ b/Test/aitest1/Linear0.bpl
@@ -0,0 +1,10 @@
+// Simple test file for checking the inference of linear constraints.
+
+var x: int;
+var y: int;
+
+procedure p()
+{
+ start:
+ return;
+}
diff --git a/Test/aitest1/Linear1.bpl b/Test/aitest1/Linear1.bpl
new file mode 100644
index 00000000..0cbb4a07
--- /dev/null
+++ b/Test/aitest1/Linear1.bpl
@@ -0,0 +1,11 @@
+// Simple test file for checking the inference of linear constraints.
+
+var x: int;
+var y: int;
+
+procedure p()
+{
+ start:
+ assume x*x == y; // not a linear condition
+ return;
+}
diff --git a/Test/aitest1/Linear2.bpl b/Test/aitest1/Linear2.bpl
new file mode 100644
index 00000000..9e02c9e2
--- /dev/null
+++ b/Test/aitest1/Linear2.bpl
@@ -0,0 +1,11 @@
+// Simple test file for checking the inference of linear constraints.
+
+var x: int;
+var y: int;
+
+procedure p()
+{
+ start:
+ assume x == 8;
+ return;
+}
diff --git a/Test/aitest1/Linear3.bpl b/Test/aitest1/Linear3.bpl
new file mode 100644
index 00000000..c6b7a441
--- /dev/null
+++ b/Test/aitest1/Linear3.bpl
@@ -0,0 +1,11 @@
+// Simple test file for checking the inference of linear constraints.
+
+var x: int;
+var y: int;
+
+procedure p()
+{
+ start:
+ assume x < y;
+ return;
+}
diff --git a/Test/aitest1/Linear4.bpl b/Test/aitest1/Linear4.bpl
new file mode 100644
index 00000000..c8c4605c
--- /dev/null
+++ b/Test/aitest1/Linear4.bpl
@@ -0,0 +1,15 @@
+// Simple test file for checking the inference of linear constraints.
+
+var x: int;
+var y: int;
+
+procedure p()
+ modifies x;
+{
+ A:
+ assume x < y;
+ goto B;
+ B:
+ x := x*x;
+ return;
+}
diff --git a/Test/aitest1/Linear5.bpl b/Test/aitest1/Linear5.bpl
new file mode 100644
index 00000000..4f04999c
--- /dev/null
+++ b/Test/aitest1/Linear5.bpl
@@ -0,0 +1,21 @@
+// Simple test file for checking the inference of linear constraints.
+
+var x: int;
+var y: int;
+
+procedure p()
+ modifies x;
+{
+ A:
+ assume -1 <= x;
+ goto B;
+ B:
+ assume x < y;
+ goto C;
+ C:
+ x := x*x;
+ goto D;
+ D:
+ x := y;
+ return;
+}
diff --git a/Test/aitest1/Linear6.bpl b/Test/aitest1/Linear6.bpl
new file mode 100644
index 00000000..83e52a9a
--- /dev/null
+++ b/Test/aitest1/Linear6.bpl
@@ -0,0 +1,21 @@
+// Simple test file for checking the inference of linear constraints.
+
+var x: int;
+var y: int;
+var z: int;
+
+procedure p()
+ modifies x;
+{
+A:
+ x := 8;
+ goto B, C;
+B:
+ x := 9;
+ goto D;
+C:
+ x := 10;
+ goto D;
+D:
+ return;
+}
diff --git a/Test/aitest1/Linear7.bpl b/Test/aitest1/Linear7.bpl
new file mode 100644
index 00000000..b1bcaaaf
--- /dev/null
+++ b/Test/aitest1/Linear7.bpl
@@ -0,0 +1,19 @@
+// Simple test file for checking the inference of linear constraints.
+
+var x: int;
+var y: int;
+var z: int;
+
+procedure p()
+{
+A:
+ goto B, C;
+B:
+ assume x <= 0;
+ goto D;
+C:
+ assume y <= 0;
+ goto D;
+D:
+ return;
+}
diff --git a/Test/aitest1/Linear8.bpl b/Test/aitest1/Linear8.bpl
new file mode 100644
index 00000000..4bc3f887
--- /dev/null
+++ b/Test/aitest1/Linear8.bpl
@@ -0,0 +1,42 @@
+
+procedure foo () returns ()
+{
+ var i: int;
+ var j: int;
+ var n: int;
+
+A: // true
+ n := 0;
+ goto B;
+
+B: // n = 0
+ j := 0;
+ goto C;
+
+C: // n = 0 AND j = 0
+ i := j + 1;
+ goto D;
+
+D: // n = 0 AND j = 0 AND i = j + 1
+ i := i + 1;
+ goto E;
+
+E: // n = 0 AND j = 0 AND i = j + 2
+ i := i + 1;
+ goto F;
+
+F: // n = 0 AND j = 0 AND i = j + 3
+ i := i + 1;
+ goto G;
+
+G: // n = 0 AND j = 0 AND i = j + 4
+ i := i + 1;
+ goto H;
+
+H: // n = 0 AND j = 0 AND i = j + 1
+ j := j + 1;
+ goto I;
+
+I: // n = 0 AND j = 1 AND i = j + 4
+ return;
+}
diff --git a/Test/aitest1/Linear9.bpl b/Test/aitest1/Linear9.bpl
new file mode 100644
index 00000000..e48a7a0c
--- /dev/null
+++ b/Test/aitest1/Linear9.bpl
@@ -0,0 +1,29 @@
+procedure foo () returns ()
+{
+ var i: int;
+ var j: int;
+ var n: int;
+entry:
+ assume n >= 4;
+ i := 0;
+ j := i + 1;
+ // n >= 4 AND i = 0 AND j = i+1
+ goto exit, loop0;
+
+loop0:
+ // n >= 4 AND i >= 0 AND j = i+1
+ assume j <= n;
+ goto loop1;
+loop1:
+ // n >= 4 AND i >= 0 AND j = i+1 AND j <= n
+ i := i + 1;
+ goto loop2;
+loop2:
+ j := j + 1;
+ // n >= 4 AND i >= 1 AND j = i+1 AND j <= n+1
+ goto loop0, exit;
+
+exit:
+ // n >= 4 AND i >= 0 AND j = i+1 AND j <= n+1
+ return;
+}
diff --git a/Test/aitest1/Output b/Test/aitest1/Output
new file mode 100644
index 00000000..4e5c8f27
--- /dev/null
+++ b/Test/aitest1/Output
@@ -0,0 +1,510 @@
+-------------------- ineq.bpl --------------------
+procedure SimpleLoop();
+
+
+
+implementation SimpleLoop()
+{
+ var i: int;
+
+ start:
+ assume true;
+ i := 0;
+ assume i == 0;
+ goto test;
+
+ test: // cut point
+ assume 0 <= i;
+ assume 0 <= i;
+ goto Then, Else;
+
+ Then:
+ assume 0 <= i;
+ assume i < 10;
+ i := i + 1;
+ assume i <= 10 && 1 <= i;
+ goto test;
+
+ Else:
+ assume 0 <= i;
+ assume !(i < 10);
+ assume 10 <= i;
+ return;
+}
+
+
+
+procedure VariableBoundLoop(n: int);
+
+
+
+implementation VariableBoundLoop(n: int)
+{
+ var i: int;
+
+ start:
+ assume true;
+ i := 0;
+ assume i == 0;
+ goto test;
+
+ test: // cut point
+ assume 0 <= i;
+ assume 0 <= i;
+ goto Then, Else;
+
+ Then:
+ assume 0 <= i;
+ assume i < n;
+ i := i + 1;
+ assume i <= n && 1 <= i;
+ goto test;
+
+ Else:
+ assume 0 <= i;
+ assume !(i < n);
+ assume n <= i && 0 <= i;
+ return;
+}
+
+
+
+procedure Foo();
+
+
+
+implementation Foo()
+{
+ var i: int;
+
+ start:
+ assume true;
+ i := 3 * i + 1;
+ i := 3 * (i + 1);
+ i := 1 + 3 * i;
+ i := (i + 1) * 3;
+ assume true;
+ return;
+}
+
+
+
+procedure FooToo();
+
+
+
+implementation FooToo()
+{
+ var i: int;
+
+ start:
+ assume true;
+ i := 5;
+ i := 3 * i + 1;
+ i := 3 * (i + 1);
+ i := 1 + 3 * i;
+ i := (i + 1) * 3;
+ assume 1 / 3 * i == 155;
+ return;
+}
+
+
+
+procedure FooTooStepByStep();
+
+
+
+implementation FooTooStepByStep()
+{
+ var i: int;
+
+ L0:
+ assume true;
+ i := 5;
+ assume i == 5;
+ goto L1;
+
+ L1:
+ assume i == 5;
+ i := 3 * i + 1;
+ assume i == 16;
+ goto L2;
+
+ L2:
+ assume i == 16;
+ i := 3 * (i + 1);
+ assume 1 / 3 * i == 17;
+ goto L3;
+
+ L3:
+ assume 1 / 3 * i == 17;
+ i := 1 + 3 * i;
+ assume i == 154;
+ goto L4;
+
+ L4:
+ assume i == 154;
+ i := (i + 1) * 3;
+ assume 1 / 3 * i == 155;
+ return;
+}
+
+
+
+Boogie program verifier finished with 0 verified, 0 errors
+-------------------- Linear0.bpl --------------------
+var x: int;
+
+var y: int;
+
+procedure p();
+
+
+
+implementation p()
+{
+
+ start:
+ assume true;
+ assume true;
+ return;
+}
+
+
+
+Boogie program verifier finished with 0 verified, 0 errors
+-------------------- Linear1.bpl --------------------
+var x: int;
+
+var y: int;
+
+procedure p();
+
+
+
+implementation p()
+{
+
+ start:
+ assume true;
+ assume x * x == y;
+ assume true;
+ return;
+}
+
+
+
+Boogie program verifier finished with 0 verified, 0 errors
+-------------------- Linear2.bpl --------------------
+var x: int;
+
+var y: int;
+
+procedure p();
+
+
+
+implementation p()
+{
+
+ start:
+ assume true;
+ assume x == 8;
+ assume x == 8;
+ return;
+}
+
+
+
+Boogie program verifier finished with 0 verified, 0 errors
+-------------------- Linear3.bpl --------------------
+var x: int;
+
+var y: int;
+
+procedure p();
+
+
+
+implementation p()
+{
+
+ start:
+ assume true;
+ assume x < y;
+ assume x + 1 <= y;
+ return;
+}
+
+
+
+Boogie program verifier finished with 0 verified, 0 errors
+-------------------- Linear4.bpl --------------------
+var x: int;
+
+var y: int;
+
+procedure p();
+ modifies x;
+
+
+
+implementation p()
+{
+
+ A:
+ assume true;
+ assume x < y;
+ assume x + 1 <= y;
+ goto B;
+
+ B:
+ assume x + 1 <= y;
+ x := x * x;
+ assume true;
+ return;
+}
+
+
+
+Boogie program verifier finished with 0 verified, 0 errors
+-------------------- Linear5.bpl --------------------
+var x: int;
+
+var y: int;
+
+procedure p();
+ modifies x;
+
+
+
+implementation p()
+{
+
+ A:
+ assume true;
+ assume 0 - 1 <= x;
+ assume -1 <= x;
+ goto B;
+
+ B:
+ assume -1 <= x;
+ assume x < y;
+ assume x + 1 <= y && -1 <= x;
+ goto C;
+
+ C:
+ assume x + 1 <= y && -1 <= x;
+ x := x * x;
+ assume 0 <= y;
+ goto D;
+
+ D:
+ assume 0 <= y;
+ x := y;
+ assume x == y && 0 <= y;
+ return;
+}
+
+
+
+Boogie program verifier finished with 0 verified, 0 errors
+-------------------- Linear6.bpl --------------------
+var x: int;
+
+var y: int;
+
+var z: int;
+
+procedure p();
+ modifies x;
+
+
+
+implementation p()
+{
+
+ A:
+ assume true;
+ x := 8;
+ assume x == 8;
+ goto B, C;
+
+ B:
+ assume x == 8;
+ x := 9;
+ assume x == 9;
+ goto D;
+
+ C:
+ assume x == 8;
+ x := 10;
+ assume x == 10;
+ goto D;
+
+ D:
+ assume 9 <= x && x <= 10;
+ assume 9 <= x && x <= 10;
+ return;
+}
+
+
+
+Boogie program verifier finished with 0 verified, 0 errors
+-------------------- Linear7.bpl --------------------
+var x: int;
+
+var y: int;
+
+var z: int;
+
+procedure p();
+
+
+
+implementation p()
+{
+
+ A:
+ assume true;
+ assume true;
+ goto B, C;
+
+ B:
+ assume true;
+ assume x <= 0;
+ assume x <= 0;
+ goto D;
+
+ C:
+ assume true;
+ assume y <= 0;
+ assume y <= 0;
+ goto D;
+
+ D:
+ assume true;
+ assume true;
+ return;
+}
+
+
+
+Boogie program verifier finished with 0 verified, 0 errors
+-------------------- Linear8.bpl --------------------
+procedure foo();
+
+
+
+implementation foo()
+{
+ var i: int;
+ var j: int;
+ var n: int;
+
+ A:
+ assume true;
+ n := 0;
+ assume n == 0;
+ goto B;
+
+ B:
+ assume n == 0;
+ j := 0;
+ assume j == 0 && n == 0;
+ goto C;
+
+ C:
+ assume j == 0 && n == 0;
+ i := j + 1;
+ assume i == j + 1 && j == 0 && n == 0;
+ goto D;
+
+ D:
+ assume i == j + 1 && j == 0 && n == 0;
+ i := i + 1;
+ assume i == j + 2 && j == 0 && n == 0;
+ goto E;
+
+ E:
+ assume i == j + 2 && j == 0 && n == 0;
+ i := i + 1;
+ assume i == j + 3 && j == 0 && n == 0;
+ goto F;
+
+ F:
+ assume i == j + 3 && j == 0 && n == 0;
+ i := i + 1;
+ assume i == j + 4 && j == 0 && n == 0;
+ goto G;
+
+ G:
+ assume i == j + 4 && j == 0 && n == 0;
+ i := i + 1;
+ assume i == j + 5 && j == 0 && n == 0;
+ goto H;
+
+ H:
+ assume i == j + 5 && j == 0 && n == 0;
+ j := j + 1;
+ assume i == j + 4 && j == 1 && n == 0;
+ goto I;
+
+ I:
+ assume i == j + 4 && j == 1 && n == 0;
+ assume i == j + 4 && j == 1 && n == 0;
+ return;
+}
+
+
+
+Boogie program verifier finished with 0 verified, 0 errors
+-------------------- Linear9.bpl --------------------
+procedure foo();
+
+
+
+implementation foo()
+{
+ var i: int;
+ var j: int;
+ var n: int;
+
+ entry:
+ assume true;
+ assume n >= 4;
+ i := 0;
+ j := i + 1;
+ assume j == i + 1 && i == 0 && 4 <= n;
+ goto exit, loop0;
+
+ loop0: // cut point
+ assume 4 <= n && 0 <= i && j == i + 1;
+ assume j <= n;
+ assume j <= n && 4 <= n && 0 <= i && j == i + 1;
+ goto loop1;
+
+ loop1:
+ assume j <= n && 4 <= n && 0 <= i && j == i + 1;
+ i := i + 1;
+ assume 1 <= i && j == i && j <= n && 4 <= n;
+ goto loop2;
+
+ loop2:
+ assume j <= n && 4 <= n && 1 <= i && j == i;
+ j := j + 1;
+ assume j <= n + 1 && j == i + 1 && 4 <= n && 1 <= i;
+ goto loop0, exit;
+
+ exit:
+ assume j <= n + 1 && 4 <= n && 0 <= i && j == i + 1;
+ assume j <= n + 1 && 4 <= n && 0 <= i && j == i + 1;
+ return;
+}
+
+
+
+Boogie program verifier finished with 0 verified, 0 errors
+-------------------- Bound.bpl --------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
diff --git a/Test/aitest1/ineq.bpl b/Test/aitest1/ineq.bpl
new file mode 100644
index 00000000..a417aaf3
--- /dev/null
+++ b/Test/aitest1/ineq.bpl
@@ -0,0 +1,81 @@
+// Test the polyhedra domain for linear inequalities
+
+
+procedure SimpleLoop ()
+{
+ var i : int;
+
+ start:
+ i := 0;
+ goto test;
+
+ test:
+ goto Then, Else;
+
+ Then:
+ assume i < 10;
+ i := i + 1;
+ goto test;
+
+ Else:
+ assume ! (i < 10);
+ return;
+}
+
+
+procedure VariableBoundLoop (n : int)
+{
+ var i : int;
+
+ start:
+ i := 0;
+ goto test;
+
+ test:
+ goto Then, Else;
+
+ Then:
+ assume i < n;
+ i := i + 1;
+ goto test;
+
+ Else:
+ assume ! (i < n);
+ return;
+}
+
+procedure Foo ()
+{
+ var i : int;
+
+ start:
+ i := 3 * i + 1;
+ i := 3 * (i + 1);
+ i := 1 + 3 * i;
+ i := (i + 1) * 3 ;
+ return;
+}
+
+procedure FooToo ()
+{
+ var i : int;
+
+ start:
+ i := 5;
+ i := 3 * i + 1;
+ i := 3 * (i + 1);
+ i := 1 + 3 * i;
+ i := (i + 1) * 3 ;
+ return;
+}
+
+procedure FooTooStepByStep ()
+{
+ var i : int;
+
+ L0: i := 5; goto L1;
+ L1: i := 3 * i + 1; goto L2;
+ L2: i := 3 * (i + 1); goto L3;
+ L3: i := 1 + 3 * i; goto L4;
+ L4: i := (i + 1) * 3; return;
+}
diff --git a/Test/aitest1/runtest.bat b/Test/aitest1/runtest.bat
new file mode 100644
index 00000000..f2a4d3e5
--- /dev/null
+++ b/Test/aitest1/runtest.bat
@@ -0,0 +1,17 @@
+@echo off
+setlocal
+
+set BGEXE=..\..\Binaries\Boogie.exe
+
+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 -printInstrumented -noVerify %%f
+)
+
+for %%f in (Bound.bpl) do (
+ echo -------------------- %%f --------------------
+ %BGEXE% %* -infer:p %%f
+)
+
diff --git a/Test/aitest9/Output b/Test/aitest9/Output
new file mode 100644
index 00000000..dd10a8b3
--- /dev/null
+++ b/Test/aitest9/Output
@@ -0,0 +1,26 @@
+
+-------------------- VarMapFixPoint.bpl --------------------
+VarMapFixPoint.bpl(11,5): Error BP5005: This loop invariant might not be maintained by the loop.
+Execution trace:
+ VarMapFixPoint.bpl(5,3): start
+ VarMapFixPoint.bpl(10,3): LoopHead
+ VarMapFixPoint.bpl(14,3): LoopBody
+
+Boogie program verifier finished with 1 verified, 1 error
+
+-------------------- TestIntervals.bpl --------------------
+TestIntervals.bpl(23,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ TestIntervals.bpl(5,5): anon0
+ TestIntervals.bpl(6,3): anon9_LoopHead
+ TestIntervals.bpl(6,3): anon9_LoopDone
+ TestIntervals.bpl(11,5): anon2
+ TestIntervals.bpl(12,14): anon10_Then
+ TestIntervals.bpl(13,3): anon4
+ TestIntervals.bpl(13,14): anon11_Then
+ TestIntervals.bpl(14,3): anon6
+ TestIntervals.bpl(14,14): anon12_Then
+ TestIntervals.bpl(17,5): anon8
+ TestIntervals.bpl(21,3): Next
+
+Boogie program verifier finished with 0 verified, 1 error
diff --git a/Test/aitest9/TestIntervals.bpl b/Test/aitest9/TestIntervals.bpl
new file mode 100644
index 00000000..b989e16c
--- /dev/null
+++ b/Test/aitest9/TestIntervals.bpl
@@ -0,0 +1,24 @@
+procedure P()
+{
+ var a: int, b: int, c: int;
+
+ a := 0;
+ while (*) {
+ a := a + 1;
+ }
+ // a in [0, infty]
+
+ b := 0;
+ if (*) { b := b + 1; }
+ if (*) { b := b + 1; }
+ if (*) { b := b + 1; }
+ // b in [0, 3]
+
+ c := a - b;
+ // c in [-3, infty]
+ goto Next;
+
+ Next:
+ assert -3 <= c;
+ assert c <= 0; // error (there was once an error in the Intervals which thought this assertion to be true)
+}
diff --git a/Test/aitest9/VarMapFixpoint.bpl b/Test/aitest9/VarMapFixpoint.bpl
new file mode 100644
index 00000000..6b53467d
--- /dev/null
+++ b/Test/aitest9/VarMapFixpoint.bpl
@@ -0,0 +1,58 @@
+procedure main()
+{
+ var x: int, y: int, z: int;
+
+ start:
+ x := 2;
+ y := 6;
+ goto LoopHead;
+
+ LoopHead:
+ assert y < 10; // error: the loop body sets y to an arbitrary value
+ goto LoopBody, LoopEnd;
+
+ LoopBody:
+ havoc y;
+ goto LoopHead;
+
+ LoopEnd:
+ return;
+}
+
+procedure SimpleWhile5() returns (returnValue: int)
+{
+ var i: int;
+
+ start:
+ returnValue := 1;
+ havoc i;
+ goto LoopHead;
+
+ LoopHead:
+ goto LoopBody, LoopEnd;
+
+ LoopBody:
+ // here, we would simply like to "assume 1 <= i", but the interval domain doesn't interpret
+ // assume commands, so we start a loop
+ i := 1;
+ goto IncLoopHead;
+
+ IncLoopHead:
+ goto IncI, IncDone;
+
+ IncI:
+ i := i + 1;
+ goto IncLoopHead;
+
+ IncDone:
+ // now we have 1 <= i
+ assert 1 <= i;
+
+ returnValue := returnValue * i;
+ i := i - 1;
+ goto LoopHead;
+
+ LoopEnd:
+ assert returnValue >= 1;
+ return;
+}
diff --git a/Test/aitest9/answer b/Test/aitest9/answer
new file mode 100644
index 00000000..dd10a8b3
--- /dev/null
+++ b/Test/aitest9/answer
@@ -0,0 +1,26 @@
+
+-------------------- VarMapFixPoint.bpl --------------------
+VarMapFixPoint.bpl(11,5): Error BP5005: This loop invariant might not be maintained by the loop.
+Execution trace:
+ VarMapFixPoint.bpl(5,3): start
+ VarMapFixPoint.bpl(10,3): LoopHead
+ VarMapFixPoint.bpl(14,3): LoopBody
+
+Boogie program verifier finished with 1 verified, 1 error
+
+-------------------- TestIntervals.bpl --------------------
+TestIntervals.bpl(23,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ TestIntervals.bpl(5,5): anon0
+ TestIntervals.bpl(6,3): anon9_LoopHead
+ TestIntervals.bpl(6,3): anon9_LoopDone
+ TestIntervals.bpl(11,5): anon2
+ TestIntervals.bpl(12,14): anon10_Then
+ TestIntervals.bpl(13,3): anon4
+ TestIntervals.bpl(13,14): anon11_Then
+ TestIntervals.bpl(14,3): anon6
+ TestIntervals.bpl(14,14): anon12_Then
+ TestIntervals.bpl(17,5): anon8
+ TestIntervals.bpl(21,3): Next
+
+Boogie program verifier finished with 0 verified, 1 error
diff --git a/Test/aitest9/runtest.bat b/Test/aitest9/runtest.bat
new file mode 100644
index 00000000..bafa6961
--- /dev/null
+++ b/Test/aitest9/runtest.bat
@@ -0,0 +1,11 @@
+@echo off
+setlocal
+
+set BOOGIEDIR=..\..\Binaries
+set BPLEXE=%BOOGIEDIR%\Boogie.exe
+
+for %%f in (VarMapFixPoint.bpl TestIntervals.bpl) do (
+ echo.
+ echo -------------------- %%f --------------------
+ %BPLEXE% %* %%f /infer:i
+)
diff --git a/Test/alltests.txt b/Test/alltests.txt
new file mode 100644
index 00000000..2a7e11bd
--- /dev/null
+++ b/Test/alltests.txt
@@ -0,0 +1,22 @@
+test0 Use Name resolution tests
+test1 Use Typechecking tests
+test2 Use VC generation
+test7 Use Some tests for VCVariety.BlockNested
+test20 Use Types introduced in Boogie2
+test21 Use Verify Boogie 2 programs
+aitest0 Use Constant propagation test
+aitest1 Use Linear ineqality test
+aitest9 Use Test for the abstract domain of intervals
+lock Use SLAM example
+test13 Use ExistsUnique
+inline Use Procedure inlining
+textbook Use Some textbook examples
+test15 Use Benchmarks for error messages
+bitvectors Use Smoke tests for bitvectors
+smoke Use Soundness smoke testing
+test16 Use Tests methodology of visible-state semantics and loop unrolling
+test17 Postponed Tests inference of parameterized contracts
+z3api Postponed Test for Z3 Managed .NET API prover
+houdini Postponed Test for Houdini decision procedure
+dafny0 Use Dafny programs
+havoc0 Use HAVOC-generated bpl files
diff --git a/Test/bitvectors/Answer b/Test/bitvectors/Answer
new file mode 100644
index 00000000..9ad91f5b
--- /dev/null
+++ b/Test/bitvectors/Answer
@@ -0,0 +1,62 @@
+-------------------- arrays.bpl --------------------
+
+Boogie program verifier finished with 2 verified, 0 errors
+-------------------- bv0.bpl --------------------
+bv0.bpl(4,3): Error: mismatched types in assignment command (cannot assign bv31 to bv32)
+bv0.bpl(5,3): Error: mismatched types in assignment command (cannot assign int to bv32)
+bv0.bpl(6,4): Error: mismatched types in assignment command (cannot assign bv1 to bv32)
+bv0.bpl(7,10): Error: start index in extract must be no bigger than the end index
+bv0.bpl(8,4): Error: mismatched types in assignment command (cannot assign bv1 to bv32)
+bv0.bpl(9,4): Error: mismatched types in assignment command (cannot assign bv1 to bv32)
+bv0.bpl(10,4): Error: mismatched types in assignment command (cannot assign concat$bvproxy#10 to bv32)
+7 type checking errors detected in bv0.bpl
+-------------------- bv1.bpl --------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
+-------------------- bv2.bpl --------------------
+bv2.bpl(4,13): Error: bitvector bounds in illegal position
+bv2.bpl(6,13): Error: undeclared type: x
+bv2.bpl(7,14): Error: bitvector bounds in illegal position
+3 name resolution errors detected in bv2.bpl
+-------------------- bv3.bpl --------------------
+bv3.bpl(2,5): Error: type name: bv16 is registered for bitvectors
+1 name resolution errors detected in bv3.bpl
+-------------------- bv4.bpl --------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
+-------------------- bv7.bpl --------------------
+bv7.bpl(4,14): Error: arguments of extract need to be integer literals
+bv7.bpl(5,15): Error: parentheses around bitvector bounds are not allowed
+2 parse errors detected in bv7.bpl
+-------------------- vcc0.bpl --------------------
+vcc0.bpl(553,22): syntax error: [ expected
+vcc0.bpl(553,28): syntax error: ] expected
+vcc0.bpl(555,29): syntax error: [ expected
+vcc0.bpl(557,28): syntax error: [ expected
+vcc0.bpl(557,37): syntax error: ] expected
+5 parse errors detected in vcc0.bpl
+-------------------- vcc0.bpl - toInt --------------------
+vcc0.bpl(553,22): syntax error: [ expected
+vcc0.bpl(553,28): syntax error: ] expected
+vcc0.bpl(555,29): syntax error: [ expected
+vcc0.bpl(557,28): syntax error: [ expected
+vcc0.bpl(557,37): syntax error: ] expected
+5 parse errors detected in vcc0.bpl
+-------------------- bv4.bpl - /bv:n --------------------
+bv4.bpl(3,6): Error: no bitvector handling specified, please use /bv:i or /bv:z flag
+bv4.bpl(3,13): Error: no bitvector handling specified, please use /bv:i or /bv:z flag
+bv4.bpl(5,6): Error: no bitvector handling specified, please use /bv:i or /bv:z flag
+bv4.bpl(5,14): Error: no bitvector handling specified, please use /bv:i or /bv:z flag
+4 type checking errors detected in bv4.bpl
+-------------------- bv5.bpl --------------------
+bv5.bpl(10,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ bv5.bpl(5,12): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+-------------------- bv6.bpl --------------------
+bv6.bpl(8,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ bv6.bpl(5,5): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
diff --git a/Test/bitvectors/Output b/Test/bitvectors/Output
new file mode 100644
index 00000000..9ad91f5b
--- /dev/null
+++ b/Test/bitvectors/Output
@@ -0,0 +1,62 @@
+-------------------- arrays.bpl --------------------
+
+Boogie program verifier finished with 2 verified, 0 errors
+-------------------- bv0.bpl --------------------
+bv0.bpl(4,3): Error: mismatched types in assignment command (cannot assign bv31 to bv32)
+bv0.bpl(5,3): Error: mismatched types in assignment command (cannot assign int to bv32)
+bv0.bpl(6,4): Error: mismatched types in assignment command (cannot assign bv1 to bv32)
+bv0.bpl(7,10): Error: start index in extract must be no bigger than the end index
+bv0.bpl(8,4): Error: mismatched types in assignment command (cannot assign bv1 to bv32)
+bv0.bpl(9,4): Error: mismatched types in assignment command (cannot assign bv1 to bv32)
+bv0.bpl(10,4): Error: mismatched types in assignment command (cannot assign concat$bvproxy#10 to bv32)
+7 type checking errors detected in bv0.bpl
+-------------------- bv1.bpl --------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
+-------------------- bv2.bpl --------------------
+bv2.bpl(4,13): Error: bitvector bounds in illegal position
+bv2.bpl(6,13): Error: undeclared type: x
+bv2.bpl(7,14): Error: bitvector bounds in illegal position
+3 name resolution errors detected in bv2.bpl
+-------------------- bv3.bpl --------------------
+bv3.bpl(2,5): Error: type name: bv16 is registered for bitvectors
+1 name resolution errors detected in bv3.bpl
+-------------------- bv4.bpl --------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
+-------------------- bv7.bpl --------------------
+bv7.bpl(4,14): Error: arguments of extract need to be integer literals
+bv7.bpl(5,15): Error: parentheses around bitvector bounds are not allowed
+2 parse errors detected in bv7.bpl
+-------------------- vcc0.bpl --------------------
+vcc0.bpl(553,22): syntax error: [ expected
+vcc0.bpl(553,28): syntax error: ] expected
+vcc0.bpl(555,29): syntax error: [ expected
+vcc0.bpl(557,28): syntax error: [ expected
+vcc0.bpl(557,37): syntax error: ] expected
+5 parse errors detected in vcc0.bpl
+-------------------- vcc0.bpl - toInt --------------------
+vcc0.bpl(553,22): syntax error: [ expected
+vcc0.bpl(553,28): syntax error: ] expected
+vcc0.bpl(555,29): syntax error: [ expected
+vcc0.bpl(557,28): syntax error: [ expected
+vcc0.bpl(557,37): syntax error: ] expected
+5 parse errors detected in vcc0.bpl
+-------------------- bv4.bpl - /bv:n --------------------
+bv4.bpl(3,6): Error: no bitvector handling specified, please use /bv:i or /bv:z flag
+bv4.bpl(3,13): Error: no bitvector handling specified, please use /bv:i or /bv:z flag
+bv4.bpl(5,6): Error: no bitvector handling specified, please use /bv:i or /bv:z flag
+bv4.bpl(5,14): Error: no bitvector handling specified, please use /bv:i or /bv:z flag
+4 type checking errors detected in bv4.bpl
+-------------------- bv5.bpl --------------------
+bv5.bpl(10,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ bv5.bpl(5,12): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+-------------------- bv6.bpl --------------------
+bv6.bpl(8,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ bv6.bpl(5,5): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
diff --git a/Test/bitvectors/arrays.bpl b/Test/bitvectors/arrays.bpl
new file mode 100644
index 00000000..dc304d27
--- /dev/null
+++ b/Test/bitvectors/arrays.bpl
@@ -0,0 +1,41 @@
+const unique f1 : Field int;
+const unique f2 : Field bv32;
+const unique f3 : Field bool;
+
+const unique r1 : ref;
+const unique r2 : ref;
+
+var H : <x>[ref,Field x]x;
+
+procedure foo()
+ modifies H;
+{
+ var i : int;
+ var b : bv32;
+ var c : bool;
+
+ H[r1, f1] := 3;
+ H[r1, f2] := 77bv32;
+ H[r1, f3] := true;
+ i := H[r1,f1];
+ b := H[r1,f2];
+ c := H[r1,f3];
+ assert i == 3;
+ assert b == 77bv32;
+ assert H[r1,f3];
+}
+
+var B : [bv32]bv32;
+
+procedure bar()
+ modifies B;
+{
+ var b : bv32;
+
+ B[42bv32] := 77bv32;
+ b := B[42bv32];
+ assert b == 77bv32;
+}
+
+
+type Field a, ref; \ No newline at end of file
diff --git a/Test/bitvectors/bv0.bpl b/Test/bitvectors/bv0.bpl
new file mode 100644
index 00000000..43bf734a
--- /dev/null
+++ b/Test/bitvectors/bv0.bpl
@@ -0,0 +1,13 @@
+procedure foo2(x : bv32) returns(r : bv32)
+{
+ block1:
+ r := 17bv31; // Error
+ r := 17; // Error
+ r := x[1:0]; // Error
+ r := x[0:1]; // Error
+ r := x[55:54]; // Error
+ r := x[33:32]; // Error
+ r := 17bv10 ++ 17bv42 ++ 13bv22; // Error
+ return;
+}
+
diff --git a/Test/bitvectors/bv1.bpl b/Test/bitvectors/bv1.bpl
new file mode 100644
index 00000000..6c9ea70b
--- /dev/null
+++ b/Test/bitvectors/bv1.bpl
@@ -0,0 +1,17 @@
+procedure foo(x : bv32) returns(r : bv32)
+{
+ var q : bv64;
+
+ block1:
+ r := 17bv32;
+ assert r == r;
+ assert r[32:0] == r[32:0];
+ assert 0bv2 ++ r[12:0] == 0bv2 ++ r[12:0];
+ r := 17bv10 ++ 17bv22;
+ // r := 17;
+ q := 420000000000bv64;
+ q := 8444249301319680000bv64;
+ q := 16444249301319680000bv64;
+ return;
+}
+
diff --git a/Test/bitvectors/bv2.bpl b/Test/bitvectors/bv2.bpl
new file mode 100644
index 00000000..f1888c2b
--- /dev/null
+++ b/Test/bitvectors/bv2.bpl
@@ -0,0 +1,11 @@
+procedure foo2(x : bv32) returns(r : bv32)
+{
+ block1:
+ r := x[-1:1]; // Error
+// r := x[x:1]; // Error
+ r := x[1:x]; // Error
+ r := x[1+1:3]; // Error
+ return;
+}
+
+
diff --git a/Test/bitvectors/bv3.bpl b/Test/bitvectors/bv3.bpl
new file mode 100644
index 00000000..93e06077
--- /dev/null
+++ b/Test/bitvectors/bv3.bpl
@@ -0,0 +1,3 @@
+type bv;
+type bv16;
+
diff --git a/Test/bitvectors/bv4.bpl b/Test/bitvectors/bv4.bpl
new file mode 100644
index 00000000..f38891ff
--- /dev/null
+++ b/Test/bitvectors/bv4.bpl
@@ -0,0 +1,23 @@
+
+function a() returns(bv32);
+axiom a() == a();
+
+axiom 0bv5 != 1bv5;
+
+
+// -------------------------
+type $x;
+function g() returns($x);
+type Field x;
+var $gmem : <x>[ref, Field x] x;
+const unique f : Field $x;
+
+procedure qq()
+ modifies $gmem;
+{
+ $gmem[null, f] := g();
+}
+
+
+type ref;
+const null : ref;
diff --git a/Test/bitvectors/bv5.bpl b/Test/bitvectors/bv5.bpl
new file mode 100644
index 00000000..f9240e1c
--- /dev/null
+++ b/Test/bitvectors/bv5.bpl
@@ -0,0 +1,11 @@
+
+procedure P() returns () {
+ var m : <a>[a]int;
+
+ m[23bv5] := 17;
+ m[21bv5] := 19;
+ m[21bv6] := -3;
+
+ assert m[23bv5] == 17;
+ assert m[21bv6] == 3; // should not be provable
+}
diff --git a/Test/bitvectors/bv6.bpl b/Test/bitvectors/bv6.bpl
new file mode 100644
index 00000000..ca8f8367
--- /dev/null
+++ b/Test/bitvectors/bv6.bpl
@@ -0,0 +1,9 @@
+
+procedure Q() returns () {
+ var x : bv32, y : bv16;
+
+ x := y ++ y;
+ assert x[16:0] == y;
+ assert x == x[16:0] ++ y;
+ assert x[17:1] == y; // should not be verifiable
+} \ No newline at end of file
diff --git a/Test/bitvectors/bv7.bpl b/Test/bitvectors/bv7.bpl
new file mode 100644
index 00000000..2302cf2f
--- /dev/null
+++ b/Test/bitvectors/bv7.bpl
@@ -0,0 +1,9 @@
+procedure foo2(x : bv32) returns(r : bv32)
+{
+ block1:
+ r := x[x:1]; // Error
+ r := x[(1:13)]; // Error
+ return;
+}
+
+
diff --git a/Test/bitvectors/runtest.bat b/Test/bitvectors/runtest.bat
new file mode 100644
index 00000000..0b05e986
--- /dev/null
+++ b/Test/bitvectors/runtest.bat
@@ -0,0 +1,21 @@
+@echo off
+setlocal
+
+set BGEXE=..\..\Binaries\Boogie.exe
+
+for %%f in (arrays.bpl bv0.bpl bv1.bpl bv2.bpl bv3.bpl bv4.bpl bv7.bpl vcc0.bpl) do (
+ echo -------------------- %%f --------------------
+ %BGEXE% /proverWarnings:1 /bv:z %* /logPrefix:-0 %%f
+)
+
+echo -------------------- vcc0.bpl - toInt --------------------
+%BGEXE% /proverWarnings:1 /bv:i /proc:foo %* /logPrefix:-1 vcc0.bpl
+
+echo -------------------- bv4.bpl - /bv:n --------------------
+%BGEXE% /bv:n %* /logPrefix:-1 bv4.bpl
+
+echo -------------------- bv5.bpl --------------------
+%BGEXE% /bv:z %* /logPrefix:-1 bv5.bpl
+
+echo -------------------- bv6.bpl --------------------
+%BGEXE% /bv:z %* /logPrefix:-1 bv6.bpl
diff --git a/Test/bitvectors/vcc0.bpl b/Test/bitvectors/vcc0.bpl
new file mode 100644
index 00000000..c0db5ebf
--- /dev/null
+++ b/Test/bitvectors/vcc0.bpl
@@ -0,0 +1,883 @@
+// -----------------------------------------------------------------------
+// Verified C prelude
+// version 42
+// -----------------------------------------------------------------------
+
+// ldc is left off, use 17bv32 and the like
+// bv to/from int functions are not provided by z3
+// Use ==/!= instead of ceq/cne.i4/i8 (could be axiomatized, but that would just slow things down)
+
+// Functions starting with $_ are internal to the prelude. The rest is the interface.
+
+// -----------------------------------------------------------------------
+// Types
+// -----------------------------------------------------------------------
+
+type $ptr;
+type $mem;
+
+// -----------------------------------------------------------------------
+// Pointers and memory model
+// -----------------------------------------------------------------------
+
+const $ldnull:$ptr;
+
+function $ld.i1(m:$mem, p:$ptr) returns(bv32);
+function $ld.i2(m:$mem, p:$ptr) returns(bv32);
+function $ld.i4(m:$mem, p:$ptr) returns(bv32);
+function $ld.i8(m:$mem, p:$ptr) returns(bv64);
+function $ld.u1(m:$mem, p:$ptr) returns(bv32);
+function $ld.u2(m:$mem, p:$ptr) returns(bv32);
+function $ld.ptr(m:$mem, p:$ptr) returns($ptr);
+
+function $st.i1(m:$mem, p:$ptr, v:bv32) returns($mem);
+function $st.i2(m:$mem, p:$ptr, v:bv32) returns($mem);
+function $st.i4(m:$mem, p:$ptr, v:bv32) returns($mem);
+function $st.i8(m:$mem, p:$ptr, v:bv64) returns($mem);
+function $st.ptr(m:$mem, p:$ptr, v:$ptr) returns($mem);
+
+function $add.ptr(p:$ptr, off:bv64, elsize:bv64) returns($ptr);
+function $sub.ptr(p1:$ptr, p2:$ptr) returns(bv64);
+
+function $_ptr(r:ref, off:bv64) returns($ptr);
+function $offset(p:$ptr) returns(bv64);
+function $base(p:$ptr) returns(ref);
+function $_end(p:$ptr, len:bv64) returns(bv64);
+
+axiom $ldnull == $_ptr(null, 0bv64);
+
+axiom (forall p:$ptr, q:$ptr :: { $sub.ptr(p, q) }
+ $base(p) == $base(q) ==> $sub.ptr(p, q) == $sub.i8($offset(p), $offset(q)));
+
+axiom (forall p:$ptr, o:bv64, sz:bv64 :: { $add.ptr(p, o, sz) }
+ $add.ptr(p, o, sz) == $_ptr($base(p), $add.i8($offset(p), $mul.i8(o, sz))));
+
+axiom (forall i:bv64, r:ref :: $offset($_ptr(r, i)) == i);
+axiom (forall i:bv64, r:ref :: $base($_ptr(r, i)) == r);
+axiom (forall p:$ptr, len:bv64 :: { $_end(p, len) } $_end(p, len) == $add.i8($offset(p), len));
+
+// expensive, do we need it?
+//axiom (forall p1: $ptr, p2: $ptr:: { $offset(p1), $offset(p2) }
+// ($base(p1) == $base(p2) && $offset(p1) == $offset(p2)) ==> p1 == p2);
+
+// -----------------------------------------------------------------------
+// Native Z3 BV memory model
+// -----------------------------------------------------------------------
+
+function {:bvbuiltin "sign_extend 24"} $_sign_extend.8.32(v:bv8) returns(bv32);
+function {:bvbuiltin "sign_extend 16"} $_sign_extend.16.32(v:bv16) returns(bv32);
+function {:bvbuiltin "sign_extend 32"} $_sign_extend.32.64(v:bv32) returns(bv64);
+
+function $_get_byte(m:$mem, r:ref, off:bv64) returns(bv8);
+function $_set_byte(m:$mem, r:ref, off:bv64, v:bv8) returns($mem);
+
+axiom {:ignore "bvInt"} (forall m:$mem, r:ref, off:bv64, v:bv8 ::
+ $_get_byte($_set_byte(m, r, off, v), r, off) == v);
+
+axiom {:ignore "bvInt"} (forall m:$mem, r1:ref, r2:ref, off1:bv64, off2:bv64, v:bv8 ::
+ r1 != r2 ==>
+ $_get_byte($_set_byte(m, r1, off1, v), r2, off2) == $_get_byte(m, r2, off2));
+
+axiom {:ignore "bvInt"} (forall m:$mem, r1:ref, r2:ref, off1:bv64, off2:bv64, v:bv8 ::
+ off1 != off2 ==>
+ $_get_byte($_set_byte(m, r1, off1, v), r2, off2) == $_get_byte(m, r2, off2));
+
+axiom {:ignore "bvInt"} (forall m:$mem, p:$ptr :: { $ld.i4(m, p) }
+ $ld.i4(m, p) ==
+ $_get_byte(m, $base(p), $add.i8($offset(p), 3bv64)) ++ $_get_byte(m, $base(p), $add.i8($offset(p), 2bv64)) ++
+ $_get_byte(m, $base(p), $add.i8($offset(p), 1bv64)) ++ $_get_byte(m, $base(p), $offset(p)));
+
+axiom {:ignore "bvInt"} (forall m:$mem, p:$ptr :: { $ld.i8(m, p) }
+ $ld.i8(m, p) ==
+ $_get_byte(m, $base(p), $add.i8($offset(p), 7bv64)) ++ $_get_byte(m, $base(p), $add.i8($offset(p), 6bv64)) ++
+ $_get_byte(m, $base(p), $add.i8($offset(p), 5bv64)) ++ $_get_byte(m, $base(p), $add.i8($offset(p), 4bv64)) ++
+ $_get_byte(m, $base(p), $add.i8($offset(p), 3bv64)) ++ $_get_byte(m, $base(p), $add.i8($offset(p), 2bv64)) ++
+ $_get_byte(m, $base(p), $add.i8($offset(p), 1bv64)) ++ $_get_byte(m, $base(p), $offset(p)));
+
+axiom {:ignore "bvInt"} (forall m:$mem, p:$ptr :: { $ld.u2(m, p) }
+ $ld.u2(m, p) == 0bv16 ++ $_get_byte(m, $base(p), $add.i8($offset(p), 1bv64)) ++ $_get_byte(m, $base(p), $offset(p)));
+
+axiom {:ignore "bvInt"} (forall m:$mem, p:$ptr :: { $ld.u1(m, p) }
+ $ld.u1(m, p) == 0bv24 ++ $_get_byte(m, $base(p), $offset(p)));
+
+axiom {:ignore "bvInt"} (forall m:$mem, p:$ptr :: { $ld.i2(m, p) }
+ $ld.i2(m, p) == $conv.i4.to.i2($ld.u2(m, p)));
+
+axiom {:ignore "bvInt"} (forall m:$mem, p:$ptr :: { $ld.i1(m, p) }
+ $ld.i1(m, p) == $conv.i4.to.i1($ld.u1(m, p)));
+
+axiom {:ignore "bvInt"} (forall m:$mem, p:$ptr, v:bv32 :: { $st.i1(m, p, v) }
+ $st.i1(m, p, v) == $_set_byte(m, $base(p), $offset(p), v[8:0]));
+
+axiom {:ignore "bvInt"} (forall m:$mem, p:$ptr, v:bv32 :: { $st.i2(m, p, v) }
+ $st.i2(m, p, v) ==
+ $_set_byte($_set_byte(m, $base(p), $offset(p), v[8:0]), $base(p), $add.i8($offset(p), 1bv64), v[16:8]));
+
+axiom {:ignore "bvInt"} (forall m:$mem, p:$ptr, v:bv32 :: { $st.i4(m, p, v) }
+ $st.i4(m, p, v) ==
+ $_set_byte(
+ $_set_byte(
+ $_set_byte(
+ $_set_byte(m,
+ $base(p), $offset(p), v[8:0]),
+ $base(p), $add.i8($offset(p), 1bv64), v[16:8]),
+ $base(p), $add.i8($offset(p), 2bv64), v[24:16]),
+ $base(p), $add.i8($offset(p), 3bv64), v[32:24]));
+
+axiom {:ignore "bvInt"} (forall m:$mem, p:$ptr, v:bv64 :: { $st.i8(m, p, v) }
+ $st.i8(m, p, v) ==
+ $_set_byte(
+ $_set_byte(
+ $_set_byte(
+ $_set_byte(
+ $_set_byte(
+ $_set_byte(
+ $_set_byte(
+ $_set_byte(m,
+ $base(p), $offset(p), v[8:0]),
+ $base(p), $add.i8($offset(p), 1bv64), v[16:8]),
+ $base(p), $add.i8($offset(p), 2bv64), v[24:16]),
+ $base(p), $add.i8($offset(p), 3bv64), v[32:24]),
+ $base(p), $add.i8($offset(p), 4bv64), v[40:32]),
+ $base(p), $add.i8($offset(p), 5bv64), v[48:40]),
+ $base(p), $add.i8($offset(p), 6bv64), v[56:48]),
+ $base(p), $add.i8($offset(p), 7bv64), v[64:56]));
+
+
+
+axiom {:ignore "bvInt"} (forall v:bv32 :: { $conv.i4.to.i1(v) } $conv.i4.to.i1(v) == $_sign_extend.8.32(v[8:0]));
+axiom {:ignore "bvInt"} (forall v:bv32 :: { $conv.i4.to.i2(v) } $conv.i4.to.i2(v) == $_sign_extend.16.32(v[16:0]));
+axiom {:ignore "bvInt"} (forall v:bv64 :: { $conv.i8.to.i1(v) } $conv.i8.to.i1(v) == $_sign_extend.8.32(v[8:0]));
+axiom {:ignore "bvInt"} (forall v:bv64 :: { $conv.i8.to.i2(v) } $conv.i8.to.i2(v) == $_sign_extend.16.32(v[16:0]));
+
+axiom {:ignore "bvInt"} (forall v:bv32 :: { $conv.i4.to.i8(v) } $conv.i4.to.i8(v) == $_sign_extend.32.64(v));
+axiom {:ignore "bvInt"} (forall v:bv32 :: { $conv.i4.to.u8(v) } $conv.i4.to.u8(v) == 0bv32 ++ v);
+axiom {:ignore "bvInt"} (forall v:bv64 :: { $conv.i8.to.i4(v) } $conv.i8.to.i4(v) == v[32:0]);
+axiom {:ignore "bvInt"} (forall v:bv32 :: { $conv.i4.to.u1(v) } $conv.i4.to.u1(v) == 0bv24 ++ v[8:0]);
+axiom {:ignore "bvInt"} (forall v:bv32 :: { $conv.i4.to.u2(v) } $conv.i4.to.u2(v) == 0bv16 ++ v[16:0]);
+axiom {:ignore "bvInt"} (forall v:bv64 :: { $conv.i8.to.u1(v) } $conv.i8.to.u1(v) == 0bv24 ++ v[8:0]);
+axiom {:ignore "bvInt"} (forall v:bv64 :: { $conv.i8.to.u2(v) } $conv.i8.to.u2(v) == 0bv16 ++ v[16:0]);
+
+// -----------------------------------------------------------------------
+// BV-->int memory model
+// -----------------------------------------------------------------------
+
+function $_ld.i(m:$mem, p:$ptr, len:int) returns(int);
+function $_st.i(m:$mem, p:$ptr, len:int, v:int) returns($mem);
+function $_shl(x:int, y:int) returns(int);
+function $_shr(x:int, y:int) returns(int);
+function $_or(x:int, y:int) returns(int);
+function $_xor(x:int, y:int) returns(int);
+function $_and(x:int, y:int) returns(int);
+function $_not(x:int) returns(int);
+
+function $_ioffset(p:$ptr) returns(int);
+
+function {:bvint "id"} $_int.to.bv32(v:int) returns(bv32);
+function {:bvint "id"} $_int.to.bv64(v:int) returns(bv64);
+function {:bvint "id"} $_bv32.to.int(v:bv32) returns(int);
+function {:bvint "id"} $_bv64.to.int(v:bv64) returns(int);
+
+axiom {:ignore "bvDefSem"} (forall p:$ptr :: { $_ioffset(p) } $_ioffset(p) == $_bv64.to.int($offset(p)));
+
+axiom {:ignore "bvDefSem"} (forall m:$mem, len:int, v:int, p:$ptr ::
+ $_ld.i($_st.i(m, p, len, v), p, len) == v);
+
+axiom {:ignore "bvDefSem"} (forall m:$mem, l1:int, l2:int, v:int, p1:$ptr, p2:$ptr ::
+ ($base(p1) != $base(p2) || $_ioffset(p1) + l1 <= $_ioffset(p2) || $_ioffset(p2) + l2 <= $_ioffset(p1)) ==>
+ $_ld.i($_st.i(m, p1, l1, v), p2, l2) == $_ld.i(m, p2, l2));
+
+// Arithmetic axioms for int mapping
+axiom {:ignore "bvDefSem"} (forall i: int :: { $_shl(i, 0) } $_shl(i, 0) == i);
+axiom {:ignore "bvDefSem"} (forall i: int, j: int :: { $_shl(i, j) } 1 <= j ==> $_shl(i, j) == $_shl(i, j - 1) * 2);
+axiom {:ignore "bvDefSem"} (forall i: int :: { $_shr(i, 0) } $_shr(i, 0) == i);
+axiom {:ignore "bvDefSem"} (forall i: int, j: int :: { $_shr(i, j) } 1 <= j ==> 2 * $_shr(i, j) <= $_shr(i, j - 1) && $_shr(i, j - 1) <= 2 * $_shr(i, j) + 1);
+
+axiom {:ignore "bvDefSem"} (forall i: int, j: int :: { i / j } i > 0 && j > 0 ==> i - j < (i / j) * j && (i / j) * j <= i);
+
+// from Spec# prelude, needs review
+axiom {:ignore "bvDefSem"} (forall x: int, y: int :: { x % y } { x / y } x % y == x - x / y * y);
+axiom {:ignore "bvDefSem"} (forall x: int, y: int :: { x % y } 0 <= x && 0 < y ==> 0 <= x % y && x % y < y);
+axiom {:ignore "bvDefSem"} (forall x: int, y: int :: { x % y } 0 <= x && y < 0 ==> 0 <= x % y && x % y < 0 - y);
+axiom {:ignore "bvDefSem"} (forall x: int, y: int :: { x % y } x <= 0 && 0 < y ==> 0 - y < x % y && x % y <= 0);
+axiom {:ignore "bvDefSem"} (forall x: int, y: int :: { x % y } x <= 0 && y < 0 ==> y < x % y && x % y <= 0);
+axiom {:ignore "bvDefSem"} (forall x: int, y: int :: { (x + y) % y } 0 <= x && 0 <= y ==> (x + y) % y == x % y);
+axiom {:ignore "bvDefSem"} (forall x: int, y: int :: { (y + x) % y } 0 <= x && 0 <= y ==> (y + x) % y == x % y);
+axiom {:ignore "bvDefSem"} (forall x: int, y: int :: { (x - y) % y } 0 <= x - y && 0 <= y ==> (x - y) % y == x % y);
+axiom {:ignore "bvDefSem"} (forall a: int, b: int, d: int :: { a % d, b % d } 2 <= d && a % d == b % d && a < b ==> a + d <= b);
+axiom {:ignore "bvDefSem"} (forall x: int, y: int :: { $_and(x, y) } 0 <= x || 0 <= y ==> 0 <= $_and(x, y));
+axiom {:ignore "bvDefSem"} (forall x: int, y: int :: { $_or(x, y) } 0 <= x && 0 <= y ==> 0 <= $_or(x, y) && $_or(x, y) <= x + y);
+
+axiom {:ignore "bvDefSem"} (forall x: int :: { $_or(x, $_not(x)) } $_or(x, $_not(x)) == $_not(0));
+axiom {:ignore "bvDefSem"} (forall x: int :: { $_and(x, $_not(x)) } $_and(x, $_not(x)) == 0);
+axiom {:ignore "bvDefSem"} (forall x: int :: { $_or(x, 0) } $_or(x, 0) == x);
+axiom {:ignore "bvDefSem"} (forall x: int :: { $_or(x, $_not(0)) } $_or(x, $_not(0)) == $_not(0));
+axiom {:ignore "bvDefSem"} (forall x: int :: { $_and(x, 0) } $_and(x, 0) == 0);
+axiom {:ignore "bvDefSem"} (forall x: int :: { $_and(x, $_not(0)) } $_and(x, $_not(0)) == x);
+axiom {:ignore "bvDefSem"} (forall x: int :: { $_xor(x, 0) } $_xor(x, 0) == x);
+axiom {:ignore "bvDefSem"} (forall x: int :: { $_xor(x, $_not(0)) } $_xor(x, $_not(0)) == $_not(x));
+axiom {:ignore "bvDefSem"} (forall x: int :: { $_not($_not(x)) } $_not($_not(x)) == x);
+axiom {:ignore "bvDefSem"} (forall x: int, y: int :: { $_or(x, y) } $_or(x, y) == $_or(y, x));
+axiom {:ignore "bvDefSem"} (forall x: int, y: int :: { $_xor(x, y) } $_xor(x, y) == $_xor(y, x));
+axiom {:ignore "bvDefSem"} (forall x: int, y: int :: { $_and(x, y) } $_and(x, y) == $_and(y, x));
+
+axiom {:ignore "bvDefSem"} (forall p:$ptr, m:$mem :: $ld.i1(m, p) == $_int.to.bv32($_ld.i(m, p, 1)));
+axiom {:ignore "bvDefSem"} (forall p:$ptr, m:$mem, v:bv32 :: $st.i1(m, p, v) == $_st.i(m, p, 1, $_bv32.to.int(v)));
+axiom {:ignore "bvDefSem"} (forall p:$ptr, m:$mem :: $ld.u1(m, p) == $_int.to.bv32($_ld.i(m, p, 1)));
+axiom {:ignore "bvDefSem"} (forall p:$ptr, m:$mem :: $ld.i2(m, p) == $_int.to.bv32($_ld.i(m, p, 2)));
+axiom {:ignore "bvDefSem"} (forall p:$ptr, m:$mem, v:bv32 :: $st.i2(m, p, v) == $_st.i(m, p, 2, $_bv32.to.int(v)));
+axiom {:ignore "bvDefSem"} (forall p:$ptr, m:$mem :: $ld.u2(m, p) == $_int.to.bv32($_ld.i(m, p, 2)));
+axiom {:ignore "bvDefSem"} (forall p:$ptr, m:$mem :: $ld.i4(m, p) == $_int.to.bv32($_ld.i(m, p, 4)));
+axiom {:ignore "bvDefSem"} (forall p:$ptr, m:$mem, v:bv32 :: $st.i4(m, p, v) == $_st.i(m, p, 4, $_bv32.to.int(v)));
+axiom {:ignore "bvDefSem"} (forall p:$ptr, m:$mem :: $ld.i8(m, p) == $_int.to.bv64($_ld.i(m, p, 8)));
+axiom {:ignore "bvDefSem"} (forall p:$ptr, m:$mem, v:bv64 :: $st.i8(m, p, v) == $_st.i(m, p, 8, $_bv64.to.int(v)));
+
+
+// -----------------------------------------------------------------------
+// Utilities
+// -----------------------------------------------------------------------
+
+function $ite.i4(cond:bool, then:bv32, else_:bv32) returns(bv32);
+function $ite.i8(cond:bool, then:bv64, else_:bv64) returns(bv64);
+function $ite.ptr(cond:bool, then:$ptr, else_:$ptr) returns($ptr);
+
+/*
+axiom (forall cond:bool, then:bv32, else_:bv32 ::
+ cond ==> $ite.i4(cond, then, else_) == then);
+axiom (forall cond:bool, then:bv32, else_:bv32 ::
+ !cond ==> $ite.i4(cond, then, else_) == else_);
+
+axiom (forall cond:bool, then:bv64, else_:bv64 ::
+ cond ==> $ite.i8(cond, then, else_) == then);
+axiom (forall cond:bool, then:bv64, else_:bv64 ::
+ !cond ==> $ite.i8(cond, then, else_) == else_);
+
+axiom (forall cond:bool, then:$ptr, else_:$ptr ::
+ cond ==> $ite.ptr(cond, then, else_) == then);
+axiom (forall cond:bool, then:$ptr, else_:$ptr ::
+ !cond ==> $ite.ptr(cond, then, else_) == else_);
+*/
+
+// -----------------------------------------------------------------------
+// Conversions
+// -----------------------------------------------------------------------
+
+function {:bvint "id"} $conv.i4.to.i1(v:bv32) returns(bv32);
+function {:bvint "id"} $conv.i4.to.i2(v:bv32) returns(bv32);
+function {:bvint "id"} $conv.i8.to.i1(v:bv64) returns(bv32);
+function {:bvint "id"} $conv.i8.to.i2(v:bv64) returns(bv32);
+function {:bvint "id"} $conv.i4.to.i8(v:bv32) returns(bv64);
+function {:bvint "id"} $conv.i4.to.u8(v:bv32) returns(bv64);
+function {:bvint "id"} $conv.i8.to.i4(v:bv64) returns(bv32);
+function {:bvint "id"} $conv.i4.to.u1(v:bv32) returns(bv32);
+function {:bvint "id"} $conv.i4.to.u2(v:bv32) returns(bv32);
+function {:bvint "id"} $conv.i8.to.u1(v:bv64) returns(bv32);
+function {:bvint "id"} $conv.i8.to.u2(v:bv64) returns(bv32);
+
+function $conv.ptr.to.i8(p:$ptr) returns(bv64);
+function $_conv.base.to.i8(p:ref) returns(bv64);
+function $conv.i8.to.ptr(p:bv64) returns($ptr);
+
+function $conv.bool.to.i4(v:bool) returns(bv32);
+function $conv.i4.to.bool(v:bv32) returns(bool);
+
+// TODO: use patterns here?
+axiom (forall p:$ptr :: $conv.i8.to.ptr($conv.ptr.to.i8(p)) == p);
+axiom (forall p:bv64 :: $conv.ptr.to.i8($conv.i8.to.ptr(p)) == p);
+
+axiom (forall p:$ptr :: $conv.ptr.to.i8(p) == $add.i8($_conv.base.to.i8($base(p)), $offset(p)));
+// TODO what about i4?
+
+axiom ($conv.ptr.to.i8($ldnull) == 0bv64);
+axiom ($conv.i8.to.ptr(0bv64) == $ldnull);
+
+axiom (forall m:$mem, p:$ptr :: { $ld.ptr(m, p) } $ld.ptr(m, p) == $conv.i8.to.ptr($ld.i8(m, p)));
+axiom (forall m:$mem, p:$ptr, v:$ptr :: { $st.ptr(m, p, v) } $st.ptr(m, p, v) == $st.i8(m, p, $conv.ptr.to.i8(v)));
+
+axiom $conv.bool.to.i4(true) == 1bv32;
+axiom $conv.bool.to.i4(false) == 0bv32;
+axiom $conv.i4.to.bool(0bv32) == false;
+axiom (forall v:bv32 :: v != 0bv32 ==> $conv.i4.to.bool(v) == true);
+
+// -----------------------------------------------------------------------
+// Arithetmic
+// -----------------------------------------------------------------------
+
+const $min.u1:bv32;
+axiom $min.u1 == 0bv32;
+const $max.u1:bv32;
+axiom $max.u1 == 255bv32;
+const $min.i1:bv32;
+axiom $min.i1 == $neg.i4(128bv32);
+const $max.i1:bv32;
+axiom $max.i1 == 127bv32;
+
+const $min.u2:bv32;
+axiom $min.u2 == 0bv32;
+const $max.u2:bv32;
+axiom $max.u2 == 65535bv32;
+const $min.i2:bv32;
+axiom $min.i2 == $neg.i4(32768bv32);
+const $max.i2:bv32;
+axiom $max.i2 == 32767bv32;
+
+const $min.u4:bv32;
+axiom $min.u4 == 0bv32;
+const $max.u4:bv32;
+axiom $max.u4 == 4294967295bv32;
+const $min.i4:bv32;
+axiom $min.i4 == $neg.i4(2147483648bv32);
+const $max.i4:bv32;
+axiom $max.i4 == 2147483647bv32;
+
+const $min.u8:bv64;
+axiom $min.u8 == 0bv64;
+const $max.u8:bv64;
+axiom $max.u8 == 18446744073709551615bv64;
+const $min.i8:bv64;
+axiom $min.i8 == $neg.i8(9223372036854775808bv64);
+const $max.i8:bv64;
+axiom $max.i8 == 9223372036854775807bv64;
+
+function {:bvbuiltin "bvadd"} {:bvint "+"} $add.i4(x:bv32, y:bv32) returns(bv32);
+function $check.add.i4(x:bv32, y:bv32) returns(bool);
+function $check.add.u4(x:bv32, y:bv32) returns(bool);
+function {:bvbuiltin "bvadd"} {:bvint "+"} $add.i8(x:bv64, y:bv64) returns(bv64);
+function $check.add.i8(x:bv64, y:bv64) returns(bool);
+function $check.add.u8(x:bv64, y:bv64) returns(bool);
+function {:bvbuiltin "bvsub"} {:bvint "-"} $sub.i4(x:bv32, y:bv32) returns(bv32);
+function $check.sub.i4(x:bv32, y:bv32) returns(bool);
+function $check.sub.u4(x:bv32, y:bv32) returns(bool);
+function {:bvbuiltin "bvsub"} {:bvint "-"} $sub.i8(x:bv64, y:bv64) returns(bv64);
+function $check.sub.i8(x:bv64, y:bv64) returns(bool);
+function $check.sub.u8(x:bv64, y:bv64) returns(bool);
+function {:bvbuiltin "bvmul"} {:bvint "*"} $mul.i4(x:bv32, y:bv32) returns(bv32);
+function $check.mul.i4(x:bv32, y:bv32) returns(bool);
+function $check.mul.u4(x:bv32, y:bv32) returns(bool);
+function {:bvbuiltin "bvmul"} {:bvint "*"} $mul.i8(x:bv64, y:bv64) returns(bv64);
+function $check.mul.i8(x:bv64, y:bv64) returns(bool);
+function $check.mul.u8(x:bv64, y:bv64) returns(bool);
+function {:bvbuiltin "bvand"} {:bvint "$_and"} $and.i4(x:bv32, y:bv32) returns(bv32);
+function {:bvbuiltin "bvand"} {:bvint "$_and"} $and.i8(x:bv64, y:bv64) returns(bv64);
+function {:bvbuiltin "bvor"} {:bvint "$_or"} $or.i4(x:bv32, y:bv32) returns(bv32);
+function {:bvbuiltin "bvor"} {:bvint "$_or"} $or.i8(x:bv64, y:bv64) returns(bv64);
+function {:bvbuiltin "bvxor"} {:bvint "$_xor"} $xor.i4(x:bv32, y:bv32) returns(bv32);
+function {:bvbuiltin "bvxor"} {:bvint "$_xor"} $xor.i8(x:bv64, y:bv64) returns(bv64);
+function {:bvbuiltin "bvshl"} {:bvint "$_shl"} $shl.i4(x:bv32, y:bv32) returns(bv32);
+function {:bvbuiltin "bvshl"} {:bvint "$_shl"} $shl.i8(x:bv64, y:bv64) returns(bv64);
+function {:bvbuiltin "bvsdiv"} {:bvint "/"} $div.i4(x:bv32, y:bv32) returns(bv32);
+function {:bvbuiltin "bvudiv"} {:bvint "/"} $div.u4(x:bv32, y:bv32) returns(bv32);
+function $check.div.i4(x:bv32, y:bv32) returns(bool);
+function {:bvbuiltin "bvsdiv"} {:bvint "/"} $div.i8(x:bv64, y:bv64) returns(bv64);
+function {:bvbuiltin "bvudiv"} {:bvint "/"} $div.u8(x:bv64, y:bv64) returns(bv64);
+function $check.div.i8(x:bv64, y:bv64) returns(bool);
+function {:bvbuiltin "bvsrem"} {:bvint "%"} $rem.i4(x:bv32, y:bv32) returns(bv32);
+function {:bvbuiltin "bvurem"} {:bvint "%"} $rem.u4(x:bv32, y:bv32) returns(bv32);
+function $check.rem.i4(x:bv32, y:bv32) returns(bool);
+function {:bvbuiltin "bvsrem"} {:bvint "%"} $rem.i8(x:bv64, y:bv64) returns(bv64);
+function {:bvbuiltin "bvurem"} {:bvint "%"} $rem.u8(x:bv64, y:bv64) returns(bv64);
+function $check.rem.i8(x:bv64, y:bv64) returns(bool);
+function {:bvbuiltin "bvashr"} {:bvint "$_shr"} $shr.i4(x:bv32, y:bv32) returns(bv32);
+function {:bvbuiltin "bvlshr"} {:bvint "$_shr"} $shr.u4(x:bv32, y:bv32) returns(bv32);
+function {:bvbuiltin "bvashr"} {:bvint "$_shr"} $shr.i8(x:bv64, y:bv64) returns(bv64);
+function {:bvbuiltin "bvlshr"} {:bvint "$_shr"} $shr.u8(x:bv64, y:bv64) returns(bv64);
+function {:bvbuiltin "bvneg"} {:bvint "- 0"} $neg.i4(x:bv32) returns(bv32);
+function {:bvbuiltin "bvneg"} {:bvint "- 0"} $neg.i8(x:bv64) returns(bv64);
+function {:bvbuiltin "bvnot"} {:bvint "$_not"} $not.i4(x:bv32) returns(bv32);
+function {:bvbuiltin "bvnot"} {:bvint "$_not"} $not.i8(x:bv64) returns(bv64);
+function {:bvbuiltin "bvsgt"} {:bvint ">"} $cgt.i4(x:bv32, y:bv32) returns(bool);
+function {:bvbuiltin "bvugt"} {:bvint ">"} $cgt.u4(x:bv32, y:bv32) returns(bool);
+function {:bvbuiltin "bvsgt"} {:bvint ">"} $cgt.i8(x:bv64, y:bv64) returns(bool);
+function {:bvbuiltin "bvugt"} {:bvint ">"} $cgt.u8(x:bv64, y:bv64) returns(bool);
+function {:bvbuiltin "bvslt"} {:bvint "<"} $clt.i4(x:bv32, y:bv32) returns(bool);
+function {:bvbuiltin "bvult"} {:bvint "<"} $clt.u4(x:bv32, y:bv32) returns(bool);
+function {:bvbuiltin "bvslt"} {:bvint "<"} $clt.i8(x:bv64, y:bv64) returns(bool);
+function {:bvbuiltin "bvult"} {:bvint "<"} $clt.u8(x:bv64, y:bv64) returns(bool);
+function {:bvbuiltin "bvsge"} {:bvint ">="} $cge.i4(x:bv32, y:bv32) returns(bool);
+function {:bvbuiltin "bvuge"} {:bvint ">="} $cge.u4(x:bv32, y:bv32) returns(bool);
+function {:bvbuiltin "bvsge"} {:bvint ">="} $cge.i8(x:bv64, y:bv64) returns(bool);
+function {:bvbuiltin "bvuge"} {:bvint ">="} $cge.u8(x:bv64, y:bv64) returns(bool);
+function {:bvbuiltin "bvsle"} {:bvint "<="} $cle.i4(x:bv32, y:bv32) returns(bool);
+function {:bvbuiltin "bvule"} {:bvint "<="} $cle.u4(x:bv32, y:bv32) returns(bool);
+function {:bvbuiltin "bvsle"} {:bvint "<="} $cle.i8(x:bv64, y:bv64) returns(bool);
+function {:bvbuiltin "bvule"} {:bvint "<="} $cle.u8(x:bv64, y:bv64) returns(bool);
+
+function $_inrange.i1(bv32) returns(bool);
+axiom {:ignore "bvDefSem"} (forall x:bv32 :: { $_inrange.i1(x) } $_inrange.i1(x) <==> $cle.i4($min.i1, x) && $cle.i4(x, $max.i1));
+
+function $_inrange.u1(bv32) returns(bool);
+axiom {:ignore "bvDefSem"} (forall x:bv32 :: { $_inrange.u1(x) } $_inrange.u1(x) <==> $cle.u4($min.u1, x) && $cle.u4(x, $max.u1));
+
+function $_inrange.i2(bv32) returns(bool);
+axiom {:ignore "bvDefSem"} (forall x:bv32 :: { $_inrange.i2(x) } $_inrange.i2(x) <==> $cle.i4($min.i2, x) && $cle.i4(x, $max.i2));
+
+function $_inrange.u2(bv32) returns(bool);
+axiom {:ignore "bvDefSem"} (forall x:bv32 :: { $_inrange.u2(x) } $_inrange.u2(x) <==> $cle.u4($min.u2, x) && $cle.u4(x, $max.u2));
+
+function $_inrange.i4(bv32) returns(bool);
+axiom {:ignore "bvDefSem"} (forall x:bv32 :: { $_inrange.i4(x) } $_inrange.i4(x) <==> $cle.i4($min.i4, x) && $cle.i4(x, $max.i4));
+
+function $_inrange.u4(bv32) returns(bool);
+axiom {:ignore "bvDefSem"} (forall x:bv32 :: { $_inrange.u4(x) } $_inrange.u4(x) <==> $cle.u4($min.u4, x) && $cle.u4(x, $max.u4));
+
+function $_inrange.i8(bv64) returns(bool);
+axiom {:ignore "bvDefSem"} (forall x:bv64 :: { $_inrange.i8(x) } $_inrange.i8(x) <==> $cle.i8($min.i8, x) && $cle.i8(x, $max.i8));
+
+function $_inrange.u8(bv64) returns(bool);
+axiom {:ignore "bvDefSem"} (forall x:bv64 :: { $_inrange.u8(x) } $_inrange.u8(x) <==> $cle.u8($min.u8, x) && $cle.u8(x, $max.u8));
+axiom {:ignore "bvDefSem"} (forall x:bv32, y:bv32 :: { $check.add.i4(x, y) } $check.add.i4(x, y) <==> $_inrange.i4($add.i4(x, y)));
+axiom {:ignore "bvDefSem"} (forall x:bv32, y:bv32 :: { $check.add.u4(x, y) } $check.add.u4(x, y) <==> $_inrange.u4($add.i4(x, y)));
+axiom {:ignore "bvDefSem"} (forall x:bv64, y:bv64 :: { $check.add.i8(x, y) } $check.add.i8(x, y) <==> $_inrange.i8($add.i8(x, y)));
+axiom {:ignore "bvDefSem"} (forall x:bv64, y:bv64 :: { $check.add.u8(x, y) } $check.add.u8(x, y) <==> $_inrange.u8($add.i8(x, y)));
+axiom {:ignore "bvDefSem"} (forall x:bv32, y:bv32 :: { $check.sub.i4(x, y) } $check.sub.i4(x, y) <==> $_inrange.i4($sub.i4(x, y)));
+axiom {:ignore "bvDefSem"} (forall x:bv32, y:bv32 :: { $check.sub.u4(x, y) } $check.sub.u4(x, y) <==> $_inrange.u4($sub.i4(x, y)));
+axiom {:ignore "bvDefSem"} (forall x:bv64, y:bv64 :: { $check.sub.i8(x, y) } $check.sub.i8(x, y) <==> $_inrange.i8($sub.i8(x, y)));
+axiom {:ignore "bvDefSem"} (forall x:bv64, y:bv64 :: { $check.sub.u8(x, y) } $check.sub.u8(x, y) <==> $_inrange.u8($sub.i8(x, y)));
+axiom {:ignore "bvDefSem"} (forall x:bv32, y:bv32 :: { $check.mul.i4(x, y) } $check.mul.i4(x, y) <==> $_inrange.i4($mul.i4(x, y)));
+axiom {:ignore "bvDefSem"} (forall x:bv32, y:bv32 :: { $check.mul.u4(x, y) } $check.mul.u4(x, y) <==> $_inrange.u4($mul.i4(x, y)));
+axiom {:ignore "bvDefSem"} (forall x:bv64, y:bv64 :: { $check.mul.i8(x, y) } $check.mul.i8(x, y) <==> $_inrange.i8($mul.i8(x, y)));
+axiom {:ignore "bvDefSem"} (forall x:bv64, y:bv64 :: { $check.mul.u8(x, y) } $check.mul.u8(x, y) <==> $_inrange.u8($mul.i8(x, y)));
+
+function $check.conv.i4.to.i1(bv32) returns(bool);
+axiom (forall x:bv32 :: { $check.conv.i4.to.i1(x) }
+ $check.conv.i4.to.i1(x) <==> $cle.i4(($min.i1), x) && $cle.i4(x, ($max.i1)));
+
+function $check.conv.i4.to.u1(bv32) returns(bool);
+axiom (forall x:bv32 :: { $check.conv.i4.to.u1(x) }
+ $check.conv.i4.to.u1(x) <==> $cle.i4(($min.u1), x) && $cle.i4(x, ($max.u1)));
+
+function $check.conv.i4.to.i2(bv32) returns(bool);
+axiom (forall x:bv32 :: { $check.conv.i4.to.i2(x) }
+ $check.conv.i4.to.i2(x) <==> $cle.i4(($min.i2), x) && $cle.i4(x, ($max.i2)));
+
+function $check.conv.i4.to.u2(bv32) returns(bool);
+axiom (forall x:bv32 :: { $check.conv.i4.to.u2(x) }
+ $check.conv.i4.to.u2(x) <==> $cle.i4(($min.u2), x) && $cle.i4(x, ($max.u2)));
+
+function $check.conv.i4.to.u4(bv32) returns(bool);
+axiom (forall x:bv32 :: { $check.conv.i4.to.u4(x) }
+ $check.conv.i4.to.u4(x) <==> $cle.i4(0bv32, x));
+
+function $check.conv.i4.to.u8(bv32) returns(bool);
+axiom (forall x:bv32 :: { $check.conv.i4.to.u8(x) }
+ $check.conv.i4.to.u8(x) <==> $cle.i4(0bv32, x));
+
+function $check.conv.u4.to.i1(bv32) returns(bool);
+axiom (forall x:bv32 :: { $check.conv.u4.to.i1(x) }
+ $check.conv.u4.to.i1(x) <==> $cle.u4(x, ($max.i1)));
+
+function $check.conv.u4.to.u1(bv32) returns(bool);
+axiom (forall x:bv32 :: { $check.conv.u4.to.u1(x) }
+ $check.conv.u4.to.u1(x) <==> $cle.u4(x, ($max.u1)));
+
+function $check.conv.u4.to.i2(bv32) returns(bool);
+axiom (forall x:bv32 :: { $check.conv.u4.to.i2(x) }
+ $check.conv.u4.to.i2(x) <==> $cle.u4(x, ($max.i2)));
+
+function $check.conv.u4.to.u2(bv32) returns(bool);
+axiom (forall x:bv32 :: { $check.conv.u4.to.u2(x) }
+ $check.conv.u4.to.u2(x) <==> $cle.u4(x, ($max.u2)));
+
+function $check.conv.u4.to.i4(bv32) returns(bool);
+axiom (forall x:bv32 :: { $check.conv.u4.to.i4(x) }
+ $check.conv.u4.to.i4(x) <==> $cle.u4(x, ($max.i4)));
+
+function $check.conv.i8.to.i1(bv64) returns(bool);
+axiom (forall x:bv64 :: { $check.conv.i8.to.i1(x) }
+ $check.conv.i8.to.i1(x) <==> $cle.i8($conv.i4.to.i8($min.i1), x) && $cle.i8(x, $conv.i4.to.i8($max.i1)));
+
+function $check.conv.i8.to.u1(bv64) returns(bool);
+axiom (forall x:bv64 :: { $check.conv.i8.to.u1(x) }
+ $check.conv.i8.to.u1(x) <==> $cle.i8($conv.i4.to.u8($min.u1), x) && $cle.i8(x, $conv.i4.to.u8($max.u1)));
+
+function $check.conv.i8.to.i2(bv64) returns(bool);
+axiom (forall x:bv64 :: { $check.conv.i8.to.i2(x) }
+ $check.conv.i8.to.i2(x) <==> $cle.i8($conv.i4.to.i8($min.i2), x) && $cle.i8(x, $conv.i4.to.i8($max.i2)));
+
+function $check.conv.i8.to.u2(bv64) returns(bool);
+axiom (forall x:bv64 :: { $check.conv.i8.to.u2(x) }
+ $check.conv.i8.to.u2(x) <==> $cle.i8($conv.i4.to.u8($min.u2), x) && $cle.i8(x, $conv.i4.to.u8($max.u2)));
+
+function $check.conv.i8.to.i4(bv64) returns(bool);
+axiom (forall x:bv64 :: { $check.conv.i8.to.i4(x) }
+ $check.conv.i8.to.i4(x) <==> $cle.i8($conv.i4.to.i8($min.i4), x) && $cle.i8(x, $conv.i4.to.i8($max.i4)));
+
+function $check.conv.i8.to.u4(bv64) returns(bool);
+axiom (forall x:bv64 :: { $check.conv.i8.to.u4(x) }
+ $check.conv.i8.to.u4(x) <==> $cle.i8($conv.i4.to.u8($min.u4), x) && $cle.i8(x, $conv.i4.to.u8($max.u4)));
+
+function $check.conv.i8.to.u8(bv64) returns(bool);
+axiom (forall x:bv64 :: { $check.conv.i8.to.u8(x) }
+ $check.conv.i8.to.u8(x) <==> $cle.i8(0bv64, x));
+
+function $check.conv.u8.to.i1(bv64) returns(bool);
+axiom (forall x:bv64 :: { $check.conv.u8.to.i1(x) }
+ $check.conv.u8.to.i1(x) <==> $cle.u8(x, $conv.i4.to.i8($max.i1)));
+
+function $check.conv.u8.to.u1(bv64) returns(bool);
+axiom (forall x:bv64 :: { $check.conv.u8.to.u1(x) }
+ $check.conv.u8.to.u1(x) <==> $cle.u8(x, $conv.i4.to.u8($max.u1)));
+
+function $check.conv.u8.to.i2(bv64) returns(bool);
+axiom (forall x:bv64 :: { $check.conv.u8.to.i2(x) }
+ $check.conv.u8.to.i2(x) <==> $cle.u8(x, $conv.i4.to.i8($max.i2)));
+
+function $check.conv.u8.to.u2(bv64) returns(bool);
+axiom (forall x:bv64 :: { $check.conv.u8.to.u2(x) }
+ $check.conv.u8.to.u2(x) <==> $cle.u8(x, $conv.i4.to.u8($max.u2)));
+
+function $check.conv.u8.to.i4(bv64) returns(bool);
+axiom (forall x:bv64 :: { $check.conv.u8.to.i4(x) }
+ $check.conv.u8.to.i4(x) <==> $cle.u8(x, $conv.i4.to.i8($max.i4)));
+
+function $check.conv.u8.to.u4(bv64) returns(bool);
+axiom (forall x:bv64 :: { $check.conv.u8.to.u4(x) }
+ $check.conv.u8.to.u4(x) <==> $cle.u8(x, $conv.i4.to.u8($max.u4)));
+
+function $check.conv.u8.to.i8(bv64) returns(bool);
+axiom (forall x:bv64 :: { $check.conv.u8.to.i8(x) }
+ $check.conv.u8.to.i8(x) <==> $cle.u8(x, ($max.i8)));
+
+axiom (forall x:bv32, y:bv32 :: { $check.div.i4(x, y) } $check.div.i4(x, y) <==> ! (x == $min.i4 && y == $neg.i4(1bv32)));
+axiom (forall x:bv32, y:bv32 :: { $check.rem.i4(x, y) } $check.rem.i4(x, y) <==> ! (x == $min.i4 && y == $neg.i4(1bv32)));
+
+axiom (forall x:bv64, y:bv64 :: { $check.div.i8(x, y) } $check.div.i8(x, y) <==> ! (x == $min.i8 && y == $neg.i8(1bv64)));
+axiom (forall x:bv64, y:bv64 :: { $check.rem.i8(x, y) } $check.rem.i8(x, y) <==> ! (x == $min.i8 && y == $neg.i8(1bv64)));
+
+
+// -----------------------------------------------------------------------
+// malloc/free
+// -----------------------------------------------------------------------
+
+var $mem : $mem;
+var $gmem : [$ptr,<x>name]x;
+
+const unique $_size : <bv64>name;
+
+function $valid(m:[$ptr,<x>name]x, p:$ptr, l:bv64) returns(bool);
+// we cannot use array, as boogie/z3 does not support bv arrays
+function $size(m:[$ptr,<x>name]x, p:ref) returns(bv64);
+function $allocated(m:[$ptr,<x>name]x, p:$ptr) returns(bool);
+function $is_fresh(oldalloc:[$ptr,<x>name]x, newalloc:[$ptr,<x>name]x, p:$ptr) returns(bool);
+function $same_region(mdst:$mem, dst:$ptr, msrc:$mem, src:$ptr, len:bv64) returns(bool);
+function $always_allocated(p:$ptr, sz:bv64) returns(bool);
+
+// For writes(set) the postcondition is:
+// ensures $only_region_changed_or_new(set, old($gmem), old($mem), $mem);
+//
+// For reads(set) the postcondition is:
+// ensures $contains(##readsSet, set);
+//
+// For frees(p1;p2;...) the postcondition is:
+// ensures (forall r:ref :: { $size($gmem, r) }
+// $size($gmem, r) == $size(old($gmem), r) ||
+// $size(old($gmem), r) == 0bv64 ||
+// (r == $base(p1) && $offset(p1) == 0bv64) ||
+// (r == $base(p2) && $offset(p2) == 0bv64) ||
+// ...);
+//
+// The sets are constructed using $region, $union, $empty and $universe.
+
+axiom (forall alloc:[$ptr,<x>name]x, p:$ptr, len:bv64 ::
+ { $valid(alloc, p, len) }
+ $valid(alloc, p, len) <==>
+ p != $ldnull &&
+ $cgt.u8(len, 0bv64) && $cge.u8($offset(p), 0bv64) && // for int model
+ $cgt.u8($add.i8($offset(p), len), $offset(p)) &&
+ $cle.u8($add.i8($offset(p), len), $size(alloc, $base(p))));
+
+axiom (forall oldalloc:[$ptr,<x>name]x, newalloc:[$ptr,<x>name]x, p:$ptr :: { $is_fresh(oldalloc, newalloc, p) }
+ $is_fresh(oldalloc, newalloc, p) <==>
+ !$allocated(oldalloc, p) && $allocated(newalloc, p));
+
+axiom (forall m:[$ptr,<x>name]x, p:ref :: { $size(m, p) }
+ $size(m, p) == m[$_ptr(p, 0bv64), $_size]);
+
+axiom (forall m:[$ptr,<x>name]x, p:$ptr :: { $allocated(m, p) }
+ $allocated(m, p) <==> $size(m, $base(p)) != 0bv64);
+
+// this one is here to help discharge false aliasing accustions between globals
+// and freshly allocated memory
+axiom (forall g:$ptr, sz:bv64 :: { $always_allocated(g, sz) }
+ $always_allocated(g, sz) <==>
+ (forall a:[$ptr,<x>name]x :: $allocated(a, g)) &&
+ (forall a:[$ptr,<x>name]x :: $size(a, $base(g)) == sz));
+
+procedure $malloc(size:bv64) returns (p:$ptr);
+ modifies $gmem;
+ ensures p != $ldnull ==>
+ $base(p) != null &&
+ $size(old($gmem), $base(p)) == 0bv64 &&
+ $size($gmem, $base(p)) == size &&
+ $offset(p) == 0bv64 &&
+ (forall r:ref :: { $size($gmem, r) }
+ r != $base(p) ==> $size(old($gmem), r) == $size($gmem, r));
+ ensures p == $ldnull ==>
+ old($gmem) == $gmem;
+
+procedure $free(p:$ptr);
+ modifies $gmem;
+ requires p == $ldnull || $size($gmem, $base(p)) != 0bv64;
+ ensures
+ p != $ldnull ==>
+ $size($gmem, $base(p)) == 0bv64 &&
+ (forall r:ref :: { $size($gmem, r) }
+ r != $base(p) ==> $size(old($gmem), r) == $size($gmem, r));
+ ensures
+ p == $ldnull ==>
+ old($gmem) == $gmem;
+
+axiom (forall mdst:$mem, dst:$ptr, msrc:$mem, src:$ptr, len:bv64 ::
+ { $same_region(mdst, dst, msrc, src, len) }
+ $same_region(mdst, dst, msrc, src, len) <==>
+ (forall p:$ptr :: { $ld.i1(mdst, p) }
+ $contains($region(p, 1bv64), $region(dst, len)) ==> $ld.i1(mdst, p) == $ld.i1(msrc, $add.ptr(src, $sub.ptr(p, dst), 1bv64))) &&
+ (forall p:$ptr :: { $ld.u1(mdst, p) }
+ $contains($region(p, 1bv64), $region(dst, len)) ==> $ld.u1(mdst, p) == $ld.u1(msrc, $add.ptr(src, $sub.ptr(p, dst), 1bv64))) &&
+ (forall p:$ptr :: { $ld.i2(mdst, p) }
+ $contains($region(p, 2bv64), $region(dst, len)) ==> $ld.i2(mdst, p) == $ld.i2(msrc, $add.ptr(src, $sub.ptr(p, dst), 1bv64))) &&
+ (forall p:$ptr :: { $ld.u2(mdst, p) }
+ $contains($region(p, 2bv64), $region(dst, len)) ==> $ld.u2(mdst, p) == $ld.u2(msrc, $add.ptr(src, $sub.ptr(p, dst), 1bv64))) &&
+ (forall p:$ptr :: { $ld.i4(mdst, p) }
+ $contains($region(p, 4bv64), $region(dst, len)) ==> $ld.i4(mdst, p) == $ld.i4(msrc, $add.ptr(src, $sub.ptr(p, dst), 1bv64))) &&
+ (forall p:$ptr :: { $ld.i8(mdst, p) }
+ $contains($region(p, 8bv64), $region(dst, len)) ==> $ld.i8(mdst, p) == $ld.i8(msrc, $add.ptr(src, $sub.ptr(p, dst), 1bv64))) &&
+ (forall p:$ptr :: { $ld.ptr(mdst, p) }
+ $contains($region(p, 8bv64), $region(dst, len)) ==> $ld.ptr(mdst, p) == $ld.ptr(msrc, $add.ptr(src, $sub.ptr(p, dst), 1bv64))));
+
+
+procedure $memmove(dest: $ptr, src: $ptr, noOfBytes: bv64);
+ modifies $mem;
+ requires $valid($gmem, dest, noOfBytes) && $valid($gmem, src, noOfBytes);
+ ensures $same_region($mem, dest, old($mem), src, noOfBytes);
+ ensures $only_region_changed($region(dest, noOfBytes), old($mem), $mem);
+
+procedure $memcpy(dest: $ptr, src: $ptr, noOfBytes: bv64);
+ modifies $mem;
+ requires !$overlaps($region(dest, noOfBytes), $region(src, noOfBytes));
+ requires $valid($gmem, dest, noOfBytes) && $valid($gmem, src, noOfBytes);
+ ensures $same_region($mem, dest, old($mem), src, noOfBytes);
+ ensures $only_region_changed($region(dest, noOfBytes), old($mem), $mem);
+
+// -----------------------------------------------------------------------
+// Writes clause handling
+// -----------------------------------------------------------------------
+
+// region is a set of memory locations
+type $region;
+
+function $region(p:$ptr, len:bv64) returns($region);
+function $overlaps(r1:$region, r2:$region) returns(bool);
+// check if big contains small
+function $contains(small:$region, big:$region) returns(bool);
+function $only_region_changed(r:$region, oldmem:$mem, newmem:$mem) returns(bool);
+function $only_region_changed_or_new(r:$region, oldalloc:[$ptr,<x>name]x, oldmem:$mem, newmem:$mem) returns(bool);
+function $nothing_in_region_changed(r:$region, oldmem:$mem, newmem:$mem) returns(bool);
+function $alloc_grows(oldalloc:[$ptr,<x>name]x, newalloc:[$ptr,<x>name]x) returns(bool);
+
+function $union(r1:$region, r2:$region) returns($region);
+function $empty() returns($region);
+function $universe() returns($region);
+
+// NOTE $empty() is very different from $region(whatever, 0), for example $region(whatever, 0) is not contained in $empty()
+
+axiom (forall r:$region :: !$overlaps($empty(), r));
+axiom (forall r:$region :: !$overlaps(r, $empty()));
+axiom (forall r:$region :: r != $empty() ==> $overlaps($universe(), r));
+axiom (forall r:$region :: r != $empty() ==> $overlaps(r, $universe()));
+axiom (forall r:$region :: $contains($empty(), r));
+axiom (forall r:$region :: $contains(r, $empty()) ==> r == $empty());
+axiom (forall r:$region :: $contains($universe(), r) ==> r == $universe());
+axiom (forall r:$region :: $contains(r, $universe()));
+
+// the triggers should do the structural induction
+axiom (forall ptr1:$ptr, len1:bv64, ptr2:$ptr, len2:bv64 ::
+ { $overlaps($region(ptr1, len1), $region(ptr2, len2)) }
+ $overlaps($region(ptr1, len1), $region(ptr2, len2)) <==>
+ $base(ptr1) == $base(ptr2) &&
+ ((
+ $cle.u8($offset(ptr1), $add.i8($offset(ptr1), len1)) &&
+ $cle.u8($offset(ptr1), $offset(ptr2)) &&
+ $clt.u8($offset(ptr2), $add.i8($offset(ptr1), len1))
+ ) || (
+ $cle.u8($offset(ptr2), $add.i8($offset(ptr2), len2)) &&
+ $cle.u8($offset(ptr2), $offset(ptr1)) &&
+ $clt.u8($offset(ptr1), $add.i8($offset(ptr2), len2))
+ ) ||
+ (
+ $cgt.u8($offset(ptr1), $add.i8($offset(ptr1), len1)) &&
+ ( $cle.u8($offset(ptr2), $add.i8($offset(ptr1), len1)) ||
+ $cge.u8($add.i8($offset(ptr2), len2), $offset(ptr1))
+ ))
+ ||
+ (
+ $cgt.u8($offset(ptr2), $add.i8($offset(ptr2), len2)) &&
+ ( $cle.u8($offset(ptr1), $add.i8($offset(ptr2), len2)) ||
+ $cge.u8($add.i8($offset(ptr1), len1), $offset(ptr2))
+ ))
+ ));
+
+axiom (forall r1:$region, r2:$region, r3:$region ::
+ { $overlaps($union(r1, r2), r3) }
+ $overlaps($union(r1, r2), r3) <==> $overlaps(r1, r3) || $overlaps(r2, r3));
+
+axiom (forall r1:$region, r2:$region, r3:$region ::
+ { $overlaps(r3, $union(r1, r2)) }
+ $overlaps(r3, $union(r1, r2)) <==> $overlaps(r3, r1) || $overlaps(r3, r2));
+
+axiom (forall big:$ptr, bigl:bv64, small:$ptr, smalll:bv64 ::
+ { $contains($region(small, smalll), $region(big, bigl)) }
+ $contains($region(small, smalll), $region(big, bigl)) <==>
+ $base(big) == $base(small) &&
+ $cle.u8($offset(big), $offset(small)) &&
+ $cle.u8($offset(small), $_end(big, bigl)) &&
+ $cle.u8($offset(big), $_end(small, smalll)) &&
+ $cle.u8($_end(small, smalll), $_end(big, bigl)));
+
+axiom (forall r1:$region, r2:$region, r3:$region ::
+ { $contains(r1, $union(r2, r3)) }
+ $contains(r1, $union(r2, r3)) <==> $contains(r1, r2) || $contains(r1, r3));
+
+axiom (forall r1:$region, r2:$region, r3:$region ::
+ { $contains($union(r1, r2), r3) }
+ $contains($union(r1, r2), r3) <==> $contains(r1, r3) && $contains(r2, r3));
+
+axiom (forall r:$region, oldmem:$mem, newmem:$mem ::
+ { $only_region_changed(r, oldmem, newmem) }
+ $only_region_changed(r, oldmem, newmem) <==>
+
+ (forall p:$ptr :: { $ld.i1(oldmem, p) } { $ld.i1(newmem, p) } // TODO maybe we want only newmem?
+ $overlaps($region(p, 1bv64), r) || $ld.i1(oldmem, p) == $ld.i1(newmem, p)) &&
+ (forall p:$ptr :: { $ld.u1(oldmem, p) } { $ld.u1(newmem, p) } // TODO maybe we want only newmem?
+ $overlaps($region(p, 1bv64), r) || $ld.u1(oldmem, p) == $ld.u1(newmem, p)) &&
+ (forall p:$ptr :: { $ld.i2(oldmem, p) } { $ld.i2(newmem, p) } // TODO maybe we want only newmem?
+ $overlaps($region(p, 2bv64), r) || $ld.i2(oldmem, p) == $ld.i2(newmem, p)) &&
+ (forall p:$ptr :: { $ld.u2(oldmem, p) } { $ld.u2(newmem, p) } // TODO maybe we want only newmem?
+ $overlaps($region(p, 2bv64), r) || $ld.u2(oldmem, p) == $ld.u2(newmem, p)) &&
+ (forall p:$ptr :: { $ld.i4(oldmem, p) } { $ld.i4(newmem, p) } // TODO maybe we want only newmem?
+ $overlaps($region(p, 4bv64), r) || $ld.i4(oldmem, p) == $ld.i4(newmem, p)) &&
+ (forall p:$ptr :: { $ld.i8(oldmem, p) } { $ld.i8(newmem, p) } // TODO maybe we want only newmem?
+ $overlaps($region(p, 8bv64), r) || $ld.i8(oldmem, p) == $ld.i8(newmem, p)) &&
+ (forall p:$ptr :: { $ld.ptr(oldmem, p) } { $ld.ptr(newmem, p) } // TODO maybe we want only newmem?
+ $overlaps($region(p, 8bv64), r) || $ld.ptr(oldmem, p) == $ld.ptr(newmem, p)));
+
+
+axiom (forall r:$region, oldalloc:[$ptr,<x>name]x, oldmem:$mem, newmem:$mem ::
+ { $only_region_changed_or_new(r, oldalloc, oldmem, newmem) }
+ $only_region_changed_or_new(r, oldalloc, oldmem, newmem) <==>
+
+ (forall p:$ptr :: { $ld.i1(oldmem, p) } { $ld.i1(newmem, p) } // TODO maybe we want only newmem?
+ !$allocated(oldalloc, p) || $overlaps($region(p, 1bv64), r) || $ld.i1(oldmem, p) == $ld.i1(newmem, p)) &&
+ (forall p:$ptr :: { $ld.u1(oldmem, p) } { $ld.u1(newmem, p) } // TODO maybe we want only newmem?
+ !$allocated(oldalloc, p) || $overlaps($region(p, 1bv64), r) || $ld.u1(oldmem, p) == $ld.u1(newmem, p)) &&
+ (forall p:$ptr :: { $ld.i2(oldmem, p) } { $ld.i2(newmem, p) } // TODO maybe we want only newmem?
+ !$allocated(oldalloc, p) || $overlaps($region(p, 2bv64), r) || $ld.i2(oldmem, p) == $ld.i2(newmem, p)) &&
+ (forall p:$ptr :: { $ld.u2(oldmem, p) } { $ld.u2(newmem, p) } // TODO maybe we want only newmem?
+ !$allocated(oldalloc, p) || $overlaps($region(p, 2bv64), r) || $ld.u2(oldmem, p) == $ld.u2(newmem, p)) &&
+ (forall p:$ptr :: { $ld.i4(oldmem, p) } { $ld.i4(newmem, p) } // TODO maybe we want only newmem?
+ !$allocated(oldalloc, p) || $overlaps($region(p, 4bv64), r) || $ld.i4(oldmem, p) == $ld.i4(newmem, p)) &&
+ (forall p:$ptr :: { $ld.i8(oldmem, p) } { $ld.i8(newmem, p) } // TODO maybe we want only newmem?
+ !$allocated(oldalloc, p) || $overlaps($region(p, 8bv64), r) || $ld.i8(oldmem, p) == $ld.i8(newmem, p)) &&
+ (forall p:$ptr :: { $ld.ptr(oldmem, p) } { $ld.ptr(newmem, p) } // TODO maybe we want only newmem?
+ !$allocated(oldalloc, p) || $overlaps($region(p, 8bv64), r) || $ld.ptr(oldmem, p) == $ld.ptr(newmem, p)));
+
+
+axiom (forall r:$region, oldmem:$mem, newmem:$mem ::
+ { $nothing_in_region_changed(r, oldmem, newmem) }
+ $nothing_in_region_changed(r, oldmem, newmem) <==>
+
+ (forall p:$ptr :: { $ld.i1(oldmem, p) } { $ld.i1(newmem, p) } // TODO maybe we want only newmem?
+ !$contains($region(p, 1bv64), r) || $ld.i1(oldmem, p) == $ld.i1(newmem, p)) &&
+ (forall p:$ptr :: { $ld.u1(oldmem, p) } { $ld.u1(newmem, p) } // TODO maybe we want only newmem?
+ !$contains($region(p, 1bv64), r) || $ld.u1(oldmem, p) == $ld.u1(newmem, p)) &&
+ (forall p:$ptr :: { $ld.i2(oldmem, p) } { $ld.i2(newmem, p) } // TODO maybe we want only newmem?
+ !$contains($region(p, 2bv64), r) || $ld.i2(oldmem, p) == $ld.i2(newmem, p)) &&
+ (forall p:$ptr :: { $ld.u2(oldmem, p) } { $ld.u2(newmem, p) } // TODO maybe we want only newmem?
+ !$contains($region(p, 2bv64), r) || $ld.u2(oldmem, p) == $ld.u2(newmem, p)) &&
+ (forall p:$ptr :: { $ld.i4(oldmem, p) } { $ld.i4(newmem, p) } // TODO maybe we want only newmem?
+ !$contains($region(p, 4bv64), r) || $ld.i4(oldmem, p) == $ld.i4(newmem, p)) &&
+ (forall p:$ptr :: { $ld.i8(oldmem, p) } { $ld.i8(newmem, p) } // TODO maybe we want only newmem?
+ !$contains($region(p, 8bv64), r) || $ld.i8(oldmem, p) == $ld.i8(newmem, p)) &&
+ (forall p:$ptr :: { $ld.ptr(oldmem, p) } { $ld.ptr(newmem, p) } // TODO maybe we want only newmem?
+ !$contains($region(p, 8bv64), r) || $ld.ptr(oldmem, p) == $ld.ptr(newmem, p)));
+
+
+
+axiom (forall oldalloc:[$ptr,<x>name]x, newalloc:[$ptr,<x>name]x ::
+ { $alloc_grows(oldalloc, newalloc) }
+ $alloc_grows(oldalloc, newalloc) <==>
+ (forall p:ref :: { $size(newalloc, p) }
+ $size(oldalloc, p) == 0bv64 || $size(oldalloc, p) == $size(newalloc, p)));
+
+
+// -----------------------------------------------------------------------
+// That`s all folks!
+// -----------------------------------------------------------------------
+
+
+procedure x(a : bv64, b: bv64)
+{
+ block1 : return;
+}
+
+procedure a(a : bv32, b: bv32)
+{
+ block1 :
+ // OK:
+ assert a == a;
+ assert a[32:16] ++ a[16:0] == a;
+ assert 0bv32 != 1bv32;
+ // Error:
+ assert $add.i4(a, b) == $add.i4(b, a);
+ assert $and.i4(a, b) == $and.i4(b, a);
+ assert $add.i4(a, 0bv32) == a;
+ return;
+}
+
+procedure b(a : bv64, b: bv64)
+{
+ block1 :
+ assert a == a;
+ assert a[64:16] ++ a[16:0] == a;
+ assert $add.i8(a, b) == $add.i8(b, a);
+ assert $and.i8(a, b) == $and.i8(b, a);
+ return;
+}
+
+// Example usage of the memory model:
+procedure foo()
+ modifies $mem, $gmem;
+{
+ var p :$ptr;
+ var q :bv32;
+
+ block1:
+
+ call p := $malloc(8bv64);
+
+ if (p == $ldnull) { return; }
+
+ assert $valid($gmem, p, 4bv64);
+
+ $mem := $st.i1($mem, p, 42bv32);
+ q := $ld.u1($mem, p);
+ assert q == 42bv32;
+
+
+ p := $add.ptr(p, 4bv64, 1bv64);
+ assert $valid($gmem, p, 4bv64);
+ $mem := $st.i4($mem, p, $add.i4(q, 42bv32));
+ q := $ld.i4($mem, p);
+ assert q == 84bv32;
+
+ call $free(p);
+
+ return;
+}
+
+procedure mem_model(mem:$mem, p:$ptr, a:bv32, b:bv64)
+{
+ assert $ld.i4($st.i4(mem, p, a), p) == a;
+ assert $ld.i2($st.i2(mem, p, a), p)[16:0] == a[16:0];
+ return;
+}
diff --git a/Test/ccnet.runtestall.bat b/Test/ccnet.runtestall.bat
new file mode 100644
index 00000000..03b717e1
--- /dev/null
+++ b/Test/ccnet.runtestall.bat
@@ -0,0 +1,2 @@
+set BOOGIE=%CD%\..
+runtestall.bat %*
diff --git a/Test/dafny0/Answer b/Test/dafny0/Answer
new file mode 100644
index 00000000..64c43c87
--- /dev/null
+++ b/Test/dafny0/Answer
@@ -0,0 +1,100 @@
+
+-------------------- Simple.dfy --------------------
+// synthetic program
+
+class MyClass<T, U> {
+ var x: int;
+
+ method M(s: bool, lotsaObjects: set<object>)
+ returns (t: object, u: set<int>, v: seq<MyClass<bool,U>>):
+ requires s;
+ modifies this;
+ modifies lotsaObjects;
+ ensures t == t;
+ ensures old(null) != this;
+ {
+ x := 12;
+ while (x < 100)
+ invariant x <= 100;
+ {
+ x := x + 17;
+ if (x % 20 == 3) {
+ x := this.x + 1;
+ } else {
+ this.x := x + 0;
+ }
+ call t, u, v := M(true, lotsaObjects)
+ var to: MyClass<T,U>;
+ call to, u, v := M(true, lotsaObjects)
+ call to, u, v := to.M(true, lotsaObjects)
+ }
+ }
+}
+
+Dafny program verifier finished with 0 verified, 0 errors
+
+-------------------- BQueue.bpl --------------------
+
+Boogie program verifier finished with 8 verified, 0 errors
+
+-------------------- SmallTests.dfy --------------------
+
+Dafny program verifier finished with 3 verified, 0 errors
+
+-------------------- Queue.dfy --------------------
+
+Dafny program verifier finished with 12 verified, 0 errors
+
+-------------------- ListCopy.dfy --------------------
+
+Dafny program verifier finished with 2 verified, 0 errors
+
+-------------------- BinaryTree.dfy --------------------
+
+Dafny program verifier finished with 13 verified, 0 errors
+
+-------------------- ListReverse.dfy --------------------
+
+Dafny program verifier finished with 1 verified, 0 errors
+
+-------------------- ListContents.dfy --------------------
+
+Dafny program verifier finished with 5 verified, 0 errors
+
+-------------------- SchorrWaite.dfy --------------------
+
+Dafny program verifier finished with 4 verified, 0 errors
+
+-------------------- Termination.dfy --------------------
+
+Dafny program verifier finished with 5 verified, 0 errors
+
+-------------------- Use.dfy --------------------
+Use.dfy(12,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ (0,0): anon0
+Use.dfy(25,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ (0,0): anon0
+Use.dfy(50,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ (0,0): anon0
+
+Dafny program verifier finished with 6 verified, 3 errors
+
+-------------------- DTypes.dfy --------------------
+DTypes.dfy(15,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ (0,0): anon0
+DTypes.dfy(28,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ (0,0): anon0
+DTypes.dfy(54,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ (0,0): anon0
+
+Dafny program verifier finished with 5 verified, 3 errors
+
+-------------------- TypeParameters.dfy --------------------
+
+Dafny program verifier finished with 3 verified, 0 errors
diff --git a/Test/dafny0/BQueue.bpl b/Test/dafny0/BQueue.bpl
new file mode 100644
index 00000000..21c1c58a
--- /dev/null
+++ b/Test/dafny0/BQueue.bpl
@@ -0,0 +1,430 @@
+// BQueue.bpl
+// A queue program specified in the style of dynamic frames.
+// Rustan Leino, Michal Moskal, and Wolfram Schulte, 2007.
+
+// ---------------------------------------------------------------
+
+type ref;
+const null: ref;
+
+type Field x;
+
+// this variable represents the heap; read its type as \forall \alpha. ref * Field \alpha --> \alpha
+type HeapType = <x>[ref, Field x]x;
+var H: HeapType;
+
+// every object has an 'alloc' field, which says whether or not the object has been allocated
+const unique alloc: Field bool;
+
+// for simplicity, we say that every object has one field representing its abstract value and one
+// field representing its footprint (aka frame aka data group).
+
+const unique abstractValue: Field Seq;
+const unique footprint: Field [ref]bool;
+
+// ---------------------------------------------------------------
+
+type T; // the type of the elements of the queue
+const NullT: T; // some value of type T
+
+// ---------------------------------------------------------------
+
+// Queue:
+const unique head: Field ref;
+const unique tail: Field ref;
+const unique mynodes: Field [ref]bool;
+// Node:
+const unique data: Field T;
+const unique next: Field ref;
+
+function ValidQueue(HeapType, ref) returns (bool);
+axiom (forall h: HeapType, q: ref ::
+ { ValidQueue(h, q) }
+ q != null && h[q,alloc] ==>
+ (ValidQueue(h, q) <==>
+ h[q,head] != null && h[h[q,head],alloc] &&
+ h[q,tail] != null && h[h[q,tail],alloc] &&
+ h[h[q,tail], next] == null &&
+ // The following line can be suppressed now that we have a ValidFootprint invariant
+ (forall o: ref :: { h[q,footprint][o] } o != null && h[q,footprint][o] ==> h[o,alloc]) &&
+ h[q,footprint][q] &&
+ h[q,mynodes][h[q,head]] && h[q,mynodes][h[q,tail]] &&
+ (forall n: ref :: { h[q,mynodes][n] }
+ h[q,mynodes][n] ==>
+ n != null && h[n,alloc] && ValidNode(h, n) &&
+ SubSet(h[n,footprint], h[q,footprint]) &&
+ !h[n,footprint][q] &&
+ (h[n,next] == null ==> n == h[q,tail])
+ ) &&
+ (forall n: ref :: { h[n,next] }
+ h[q,mynodes][n] ==>
+ (h[n,next] != null ==> h[q,mynodes][h[n,next]])
+ ) &&
+ h[q,abstractValue] == h[h[q,head],abstractValue]
+ ));
+
+// frame axiom for ValidQueue
+axiom (forall h0: HeapType, h1: HeapType, n: ref ::
+ { ValidQueue(h0,n), ValidQueue(h1,n) }
+ (forall<alpha> o: ref, f: Field alpha :: o != null && h0[o,alloc] && h0[n,footprint][o]
+ ==> h0[o,f] == h1[o,f])
+ &&
+ (forall<alpha> o: ref, f: Field alpha :: o != null && h1[o,alloc] && h1[n,footprint][o]
+ ==> h0[o,f] == h1[o,f])
+ ==>
+ ValidQueue(h0,n) == ValidQueue(h1,n));
+
+function ValidNode(HeapType, ref) returns (bool);
+axiom (forall h: HeapType, n: ref ::
+ { ValidNode(h, n) }
+ n != null && h[n,alloc] ==>
+ (ValidNode(h, n) <==>
+ // The following line can be suppressed now that we have a ValidFootprint invariant
+ (forall o: ref :: { h[n,footprint][o] } o != null && h[n,footprint][o] ==> h[o,alloc]) &&
+ h[n,footprint][n] &&
+ (h[n,next] != null ==>
+ h[h[n,next],alloc] &&
+ SubSet(h[h[n,next], footprint], h[n,footprint]) &&
+ !h[h[n,next], footprint][n]) &&
+ (h[n,next] == null ==> EqualSeq(h[n,abstractValue], EmptySeq)) &&
+ (h[n,next] != null ==> EqualSeq(h[n,abstractValue],
+ Append(Singleton(h[h[n,next],data]), h[h[n,next],abstractValue])))
+ ));
+
+// frame axiom for ValidNode
+axiom (forall h0: HeapType, h1: HeapType, n: ref ::
+ { ValidNode(h0,n), ValidNode(h1,n) }
+ (forall<alpha> o: ref, f: Field alpha :: o != null && h0[o,alloc] && h0[n,footprint][o]
+ ==> h0[o,f] == h1[o,f])
+ &&
+ (forall<alpha> o: ref, f: Field alpha :: o != null && h1[o,alloc] && h1[n,footprint][o]
+ ==> h0[o,f] == h1[o,f])
+ ==>
+ ValidNode(h0,n) == ValidNode(h1,n));
+
+// ---------------------------------------------------------------
+
+procedure MakeQueue() returns (q: ref)
+ requires ValidFootprints(H);
+ modifies H;
+ ensures ValidFootprints(H);
+ ensures ModifiesOnlySet(old(H), H, EmptySet);
+ ensures q != null && H[q,alloc];
+ ensures AllNewSet(old(H), H[q,footprint]);
+ ensures ValidQueue(H, q);
+ ensures Length(H[q,abstractValue]) == 0;
+{
+ var n: ref;
+
+ assume Fresh(H,q);
+ H[q,alloc] := true;
+
+ call n := MakeNode(NullT);
+ H[q,head] := n;
+ H[q,tail] := n;
+ H[q,mynodes] := SingletonSet(n);
+ H[q,footprint] := UnionSet(SingletonSet(q), H[n,footprint]);
+ H[q,abstractValue] := H[n,abstractValue];
+}
+
+procedure IsEmpty(q: ref) returns (isEmpty: bool)
+ requires ValidFootprints(H);
+ requires q != null && H[q,alloc] && ValidQueue(H, q);
+ ensures isEmpty <==> Length(H[q,abstractValue]) == 0;
+{
+ isEmpty := H[q,head] == H[q,tail];
+}
+
+procedure Enqueue(q: ref, t: T)
+ requires ValidFootprints(H);
+ requires q != null && H[q,alloc] && ValidQueue(H, q);
+ modifies H;
+ ensures ValidFootprints(H);
+ ensures ModifiesOnlySet(old(H), H, old(H)[q,footprint]);
+ ensures DifferenceIsNew(old(H), old(H)[q,footprint], H[q,footprint]);
+ ensures ValidQueue(H, q);
+ ensures EqualSeq(H[q,abstractValue], Append(old(H)[q,abstractValue], Singleton(t)));
+{
+ var n: ref;
+
+ call n := MakeNode(t);
+
+ // foreach m in q.mynodes { m.footprint := m.footprint U n.footprint }
+ call BulkUpdateFootprint(H[q,mynodes], H[n,footprint]);
+ H[q,footprint] := UnionSet(H[q,footprint], H[n,footprint]);
+
+ // foreach m in q.mynodes { m.abstractValue := Append(m.abstractValue, Singleton(t)) }
+ call BulkUpdateAbstractValue(H[q,mynodes], t);
+ H[q,abstractValue] := H[H[q,head],abstractValue];
+
+ H[q,mynodes] := UnionSet(H[q,mynodes], SingletonSet(n));
+
+ H[H[q,tail], next] := n;
+ H[q,tail] := n;
+}
+
+procedure BulkUpdateFootprint(targetSet: [ref]bool, delta: [ref]bool);
+ requires ValidFootprints(H);
+ modifies H;
+ ensures ValidFootprints(H);
+ ensures ModifiesOnlySetField(old(H), H, targetSet, footprint);
+ ensures (forall o: ref ::
+ o != null && old(H)[o,alloc] && targetSet[o]
+ ==> H[o,footprint] == UnionSet(old(H)[o,footprint], delta));
+
+procedure BulkUpdateAbstractValue(targetSet: [ref]bool, t: T);
+ requires ValidFootprints(H);
+ modifies H;
+ ensures ValidFootprints(H);
+ ensures ModifiesOnlySetField(old(H), H, targetSet, abstractValue);
+ ensures (forall o: ref ::
+ o != null && old(H)[o,alloc] && targetSet[o]
+ ==> EqualSeq(H[o,abstractValue], Append(old(H)[o,abstractValue], Singleton(t))));
+
+procedure Front(q: ref) returns (t: T)
+ requires ValidFootprints(H);
+ requires q != null && H[q,alloc] && ValidQueue(H, q);
+ requires 0 < Length(H[q,abstractValue]);
+ ensures t == Index(H[q,abstractValue], 0);
+{
+ t := H[H[H[q,head], next], data];
+}
+
+procedure Dequeue(q: ref)
+ requires ValidFootprints(H);
+ requires q != null && H[q,alloc] && ValidQueue(H, q);
+ requires 0 < Length(H[q,abstractValue]);
+ modifies H;
+ ensures ValidFootprints(H);
+ ensures ModifiesOnlySet(old(H), H, old(H)[q,footprint]);
+ ensures DifferenceIsNew(old(H), old(H)[q,footprint], H[q,footprint]);
+ ensures ValidQueue(H, q);
+ ensures EqualSeq(H[q,abstractValue], Drop(old(H)[q,abstractValue], 1));
+{
+ var n: ref;
+
+ n := H[H[q,head], next];
+ H[q,head] := n;
+ // we could also remove old(H)[q,head] from H[q,mynodes], and similar for the footprints
+ H[q,abstractValue] := H[n,abstractValue];
+}
+
+// --------------------------------------------------------------------------------
+
+procedure MakeNode(t: T) returns (n: ref)
+ requires ValidFootprints(H);
+ modifies H;
+ ensures ValidFootprints(H);
+ ensures ModifiesOnlySet(old(H), H, EmptySet);
+ ensures n != null && H[n,alloc];
+ ensures AllNewSet(old(H), H[n,footprint]);
+ ensures ValidNode(H, n);
+ ensures H[n,data] == t && H[n,next] == null;
+{
+ assume Fresh(H,n);
+ H[n,alloc] := true;
+
+ H[n,next] := null;
+ H[n,data] := t;
+ H[n,footprint] := SingletonSet(n);
+ H[n,abstractValue] := EmptySeq;
+}
+
+// --------------------------------------------------------------------------------
+
+procedure Main(t: T, u: T, v: T)
+ requires ValidFootprints(H);
+ modifies H;
+ ensures ValidFootprints(H);
+ ensures ModifiesOnlySet(old(H), H, EmptySet);
+{
+ var q0, q1: ref;
+ var w: T;
+
+ call q0 := MakeQueue();
+ call q1 := MakeQueue();
+
+ call Enqueue(q0, t);
+ call Enqueue(q0, u);
+
+ call Enqueue(q1, v);
+
+ assert Length(H[q0,abstractValue]) == 2;
+
+ call w := Front(q0);
+ assert w == t;
+ call Dequeue(q0);
+
+ call w := Front(q0);
+ assert w == u;
+
+ assert Length(H[q0,abstractValue]) == 1;
+ assert Length(H[q1,abstractValue]) == 1;
+}
+
+// --------------------------------------------------------------------------------
+
+procedure Main2(t: T, u: T, v: T, q0: ref, q1: ref)
+ requires q0 != null && H[q0,alloc] && ValidQueue(H, q0);
+ requires q1 != null && H[q1,alloc] && ValidQueue(H, q1);
+ requires DisjointSet(H[q0,footprint], H[q1,footprint]);
+ requires Length(H[q0,abstractValue]) == 0;
+
+ requires ValidFootprints(H);
+ modifies H;
+ ensures ValidFootprints(H);
+ ensures ModifiesOnlySet(old(H), H, UnionSet(old(H)[q0,footprint], old(H)[q1,footprint]));
+{
+ var w: T;
+
+ call Enqueue(q0, t);
+ call Enqueue(q0, u);
+
+ call Enqueue(q1, v);
+
+ assert Length(H[q0,abstractValue]) == 2;
+
+ call w := Front(q0);
+ assert w == t;
+ call Dequeue(q0);
+
+ call w := Front(q0);
+ assert w == u;
+
+ assert Length(H[q0,abstractValue]) == 1;
+ assert Length(H[q1,abstractValue]) == old(Length(H[q1,abstractValue])) + 1;
+}
+
+// ---------------------------------------------------------------
+
+// Helpful predicates used in specs
+
+function ModifiesOnlySet(oldHeap: HeapType, newHeap: HeapType, set: [ref]bool) returns (bool);
+axiom (forall oldHeap: HeapType, newHeap: HeapType, set: [ref]bool ::
+ { ModifiesOnlySet(oldHeap, newHeap, set) }
+ ModifiesOnlySet(oldHeap, newHeap, set) <==>
+ NoDeallocs(oldHeap, newHeap) &&
+ (forall<alpha> o: ref, f: Field alpha :: { newHeap[o,f] }
+ o != null && oldHeap[o,alloc] ==>
+ oldHeap[o,f] == newHeap[o,f] || set[o]));
+
+function ModifiesOnlySetField<alpha>(oldHeap: HeapType, newHeap: HeapType,
+ set: [ref]bool, field: Field alpha) returns (bool);
+axiom (forall<alpha> oldHeap: HeapType, newHeap: HeapType, set: [ref]bool, field: Field alpha ::
+ { ModifiesOnlySetField(oldHeap, newHeap, set, field) }
+ ModifiesOnlySetField(oldHeap, newHeap, set, field) <==>
+ NoDeallocs(oldHeap, newHeap) &&
+ (forall<beta> o: ref, f: Field beta :: { newHeap[o,f] }
+ o != null && oldHeap[o,alloc] ==>
+ oldHeap[o,f] == newHeap[o,f] || (set[o] && f == field)));
+
+function NoDeallocs(oldHeap: HeapType, newHeap: HeapType) returns (bool);
+axiom (forall oldHeap: HeapType, newHeap: HeapType ::
+ { NoDeallocs(oldHeap, newHeap) }
+ NoDeallocs(oldHeap, newHeap) <==>
+ (forall o: ref :: { newHeap[o,alloc] }
+ o != null && oldHeap[o,alloc] ==> newHeap[o,alloc]));
+
+function AllNewSet(oldHeap: HeapType, set: [ref]bool) returns (bool);
+axiom (forall oldHeap: HeapType, set: [ref]bool ::
+ { AllNewSet(oldHeap, set) }
+ AllNewSet(oldHeap, set) <==>
+ (forall o: ref :: { oldHeap[o,alloc] }
+ o != null && set[o] ==> !oldHeap[o,alloc]));
+
+function DifferenceIsNew(oldHeap: HeapType, oldSet: [ref]bool, newSet: [ref]bool) returns (bool);
+axiom (forall oldHeap: HeapType, oldSet: [ref]bool, newSet: [ref]bool ::
+ { DifferenceIsNew(oldHeap, oldSet, newSet) }
+ DifferenceIsNew(oldHeap, oldSet, newSet) <==>
+ (forall o: ref :: { oldHeap[o,alloc] }
+ o != null && !oldSet[o] && newSet[o] ==> !oldHeap[o,alloc]));
+
+function ValidFootprints(h: HeapType) returns (bool);
+axiom (forall h: HeapType ::
+ { ValidFootprints(h) }
+ ValidFootprints(h) <==>
+ (forall o: ref, r: ref :: { h[o,footprint][r] }
+ o != null && h[o,alloc] && r != null && h[o,footprint][r] ==> h[r,alloc]));
+
+function Fresh(h: HeapType, o: ref) returns (bool);
+axiom (forall h: HeapType, o: ref ::
+ { Fresh(h,o) }
+ Fresh(h,o) <==>
+ o != null && !h[o,alloc] && h[o,footprint] == SingletonSet(o));
+
+// ---------------------------------------------------------------
+
+const EmptySet: [ref]bool;
+axiom (forall o: ref :: { EmptySet[o] } !EmptySet[o]);
+
+function SingletonSet(ref) returns ([ref]bool);
+axiom (forall r: ref :: { SingletonSet(r) } SingletonSet(r)[r]);
+axiom (forall r: ref, o: ref :: { SingletonSet(r)[o] } SingletonSet(r)[o] <==> r == o);
+
+function UnionSet([ref]bool, [ref]bool) returns ([ref]bool);
+axiom (forall a: [ref]bool, b: [ref]bool, o: ref :: { UnionSet(a,b)[o] }
+ UnionSet(a,b)[o] <==> a[o] || b[o]);
+
+function SubSet([ref]bool, [ref]bool) returns (bool);
+axiom(forall a: [ref]bool, b: [ref]bool :: { SubSet(a,b) }
+ SubSet(a,b) <==> (forall o: ref :: {a[o]} {b[o]} a[o] ==> b[o]));
+
+function EqualSet([ref]bool, [ref]bool) returns (bool);
+axiom(forall a: [ref]bool, b: [ref]bool :: { EqualSet(a,b) }
+ EqualSet(a,b) <==> (forall o: ref :: {a[o]} {b[o]} a[o] <==> b[o]));
+
+function DisjointSet([ref]bool, [ref]bool) returns (bool);
+axiom (forall a: [ref]bool, b: [ref]bool :: { DisjointSet(a,b) }
+ DisjointSet(a,b) <==> (forall o: ref :: {a[o]} {b[o]} !a[o] || !b[o]));
+
+// ---------------------------------------------------------------
+
+// Sequence of T
+type Seq;
+
+function Length(Seq) returns (int);
+axiom (forall s: Seq :: { Length(s) } 0 <= Length(s));
+
+const EmptySeq: Seq;
+axiom Length(EmptySeq) == 0;
+axiom (forall s: Seq :: { Length(s) } Length(s) == 0 ==> s == EmptySeq);
+
+function Singleton(T) returns (Seq);
+axiom (forall t: T :: { Length(Singleton(t)) } Length(Singleton(t)) == 1);
+
+function Append(Seq, Seq) returns (Seq);
+axiom (forall s0: Seq, s1: Seq :: { Length(Append(s0,s1)) }
+ Length(Append(s0,s1)) == Length(s0) + Length(s1));
+
+function Index(Seq, int) returns (T);
+axiom (forall t: T :: { Index(Singleton(t), 0) } Index(Singleton(t), 0) == t);
+axiom (forall s0: Seq, s1: Seq, n: int :: { Index(Append(s0,s1), n) }
+ (n < Length(s0) ==> Index(Append(s0,s1), n) == Index(s0, n)) &&
+ (Length(s0) <= n ==> Index(Append(s0,s1), n) == Index(s1, n - Length(s0))));
+
+function EqualSeq(Seq, Seq) returns (bool);
+axiom (forall s0: Seq, s1: Seq :: { EqualSeq(s0,s1) }
+ EqualSeq(s0,s1) <==>
+ Length(s0) == Length(s1) &&
+ (forall j: int :: { Index(s0,j) } { Index(s1,j) }
+ 0 <= j && j < Length(s0) ==> Index(s0,j) == Index(s1,j)));
+
+function Take(Seq, howMany: int) returns (Seq);
+axiom (forall s: Seq, n: int :: { Length(Take(s,n)) }
+ 0 <= n ==>
+ (n <= Length(s) ==> Length(Take(s,n)) == n) &&
+ (Length(s) < n ==> Length(Take(s,n)) == Length(s)));
+axiom (forall s: Seq, n: int, j: int :: { Index(Take(s,n), j) }
+ 0 <= j && j < n && j < Length(s) ==>
+ Index(Take(s,n), j) == Index(s, j));
+
+function Drop(Seq, howMany: int) returns (Seq);
+axiom (forall s: Seq, n: int :: { Length(Drop(s,n)) }
+ 0 <= n ==>
+ (n <= Length(s) ==> Length(Drop(s,n)) == Length(s) - n) &&
+ (Length(s) < n ==> Length(Drop(s,n)) == 0));
+axiom (forall s: Seq, n: int, j: int :: { Index(Drop(s,n), j) }
+ 0 <= n && 0 <= j && j < Length(s)-n ==>
+ Index(Drop(s,n), j) == Index(s, j+n));
+
+// ---------------------------------------------------------------
diff --git a/Test/dafny0/BinaryTree.dfy b/Test/dafny0/BinaryTree.dfy
new file mode 100644
index 00000000..b3bcc823
--- /dev/null
+++ b/Test/dafny0/BinaryTree.dfy
@@ -0,0 +1,245 @@
+class IntSet {
+ var contents: set<int>;
+ var footprint: set<object>;
+
+ var root: Node;
+
+ function Valid(): bool
+ reads this, footprint;
+ {
+ this in footprint &&
+ (root == null ==> contents == {}) &&
+ (root != null ==>
+ root in footprint && root.Valid() &&
+ contents == root.contents &&
+ root.footprint <= footprint && !(this in root.footprint))
+ }
+
+ method Init()
+ modifies this;
+ ensures Valid() && fresh(footprint - {this});
+ ensures contents == {};
+ {
+ root := null;
+ footprint := {this};
+ contents := {};
+ }
+
+ method Find(x: int) returns (present: bool)
+ requires Valid();
+ ensures present <==> x in contents;
+ {
+ if (root == null) {
+ present := false;
+ } else {
+ call present := root.Find(x);
+ }
+ }
+
+ method Insert(x: int)
+ requires Valid();
+ modifies footprint;
+ ensures Valid() && fresh(footprint - old(footprint));
+ ensures contents == old(contents) + {x};
+ {
+ var t;
+ call t := InsertHelper(x, root);
+ root := t;
+ contents := root.contents;
+ footprint := root.footprint + {this};
+ }
+
+ method InsertHelper(x: int, n: Node) returns (m: Node)
+ requires n == null || n.Valid();
+ modifies n.footprint;
+ ensures m != null && m.Valid();
+ ensures n == null ==> fresh(m.footprint) && m.contents == {x};
+ ensures n != null ==> m == n && n.contents == old(n.contents) + {x};
+ ensures n != null ==> fresh(n.footprint - old(n.footprint));
+ {
+ if (n == null) {
+ m := new Node;
+ call m.Init(x);
+ } else if (x == n.data) {
+ m := n;
+ } else {
+ if (x < n.data) {
+ var t;
+ call t := InsertHelper(x, n.left);
+ n.left := t;
+ n.footprint := n.footprint + n.left.footprint;
+ } else {
+ var t;
+ call t := InsertHelper(x, n.right);
+ n.right := t;
+ n.footprint := n.footprint + n.right.footprint;
+ }
+ n.contents := n.contents + {x};
+ m := n;
+ }
+ }
+
+ method Remove(x: int)
+ requires Valid();
+ modifies footprint;
+ ensures Valid() && fresh(footprint - old(footprint));
+ ensures contents == old(contents) - {x};
+ {
+ if (root != null) {
+ var newRoot;
+ call newRoot := root.Remove(x);
+ root := newRoot;
+ if (root == null) {
+ contents := {};
+ footprint := {this};
+ } else {
+ contents := root.contents;
+ footprint := root.footprint + {this};
+ }
+ }
+ }
+}
+
+class Node {
+ var contents: set<int>;
+ var footprint: set<object>;
+
+ var data: int;
+ var left: Node;
+ var right: Node;
+
+ function Valid(): bool
+ reads this, footprint;
+ {
+ this in footprint &&
+ !(null in footprint) &&
+ (left != null ==>
+ left in footprint && left.Valid() &&
+ left.footprint <= footprint && !(this in left.footprint) &&
+ (forall y :: y in left.contents ==> y < data)) &&
+ (right != null ==>
+ right in footprint && right.Valid() &&
+ right.footprint <= footprint && !(this in right.footprint) &&
+ (forall y :: y in right.contents ==> data < y)) &&
+ (left == null && right == null ==>
+ contents == {data}) &&
+ (left != null && right == null ==>
+ contents == left.contents + {data}) &&
+ (left == null && right != null ==>
+ contents == {data} + right.contents) &&
+ (left != null && right != null ==>
+ left.footprint !! right.footprint &&
+ contents == left.contents + {data} + right.contents)
+ }
+
+ method Init(x: int)
+ modifies this;
+ ensures Valid() && fresh(footprint - {this});
+ ensures contents == {x};
+ {
+ data := x;
+ left := null;
+ right := null;
+ contents := {x};
+ footprint := {this};
+ }
+
+ method Find(x: int) returns (present: bool)
+ requires Valid();
+ ensures present <==> x in contents;
+ {
+ if (x == data) {
+ present := true;
+ } else if (left != null && x < data) {
+ call present := left.Find(x);
+ } else if (right != null && data < x) {
+ call present := right.Find(x);
+ } else {
+ present := false;
+ }
+ }
+
+ method Remove(x: int) returns (node: Node)
+ requires Valid();
+ modifies footprint;
+ ensures fresh(footprint - old(footprint));
+ ensures node != null ==> node.Valid();
+ ensures node == null ==> old(contents) <= {x};
+ ensures node != null ==> node.footprint <= footprint && node.contents == old(contents) - {x};
+ {
+ node := this;
+ if (left != null && x < data) {
+ var t;
+ call t := left.Remove(x);
+ left := t;
+ contents := contents - {x};
+ if (left != null) { footprint := footprint + left.footprint; }
+ } else if (right != null && data < x) {
+ var t;
+ call t := right.Remove(x);
+ right := t;
+ contents := contents - {x};
+ if (right != null) { footprint := footprint + right.footprint; }
+ } else if (x == data) {
+ if (left == null && right == null) {
+ node := null;
+ } else if (left == null) {
+ node := right;
+ } else if (right == null) {
+ node := left;
+ } else {
+ // rotate
+ var min, r;
+ call min, r := right.RemoveMin();
+ data := min; right := r;
+ contents := contents - {x};
+ if (right != null) { footprint := footprint + right.footprint; }
+ }
+ }
+ }
+
+ method RemoveMin() returns (min: int, node: Node)
+ requires Valid();
+ modifies footprint;
+ ensures fresh(footprint - old(footprint));
+ ensures node != null ==> node.Valid();
+ ensures node == null ==> old(contents) == {min};
+ ensures node != null ==> node.footprint <= footprint && node.contents == old(contents) - {min};
+ ensures min in old(contents) && (forall x :: x in old(contents) ==> min <= x);
+ {
+ if (left == null) {
+ min := data;
+ node := right;
+ } else {
+ var t;
+ call min, t := left.RemoveMin();
+ left := t;
+ node := this;
+ contents := contents - {min};
+ if (left != null) { footprint := footprint + left.footprint; }
+ }
+ }
+}
+
+class Main {
+ method Client0(x: int)
+ {
+ var s := new IntSet;
+ call s.Init();
+
+ call s.Insert(12);
+ call s.Insert(24);
+ var present;
+ call present := s.Find(x);
+ assert present <==> x == 12 || x == 24;
+ }
+
+ method Client1(s: IntSet, x: int)
+ requires s != null && s.Valid();
+ modifies s.footprint;
+ {
+ call s.Insert(x);
+ call s.Insert(24);
+ assert old(s.contents) - {x,24} == s.contents - {x,24};
+ }
+}
diff --git a/Test/dafny0/DTypes.dfy b/Test/dafny0/DTypes.dfy
new file mode 100644
index 00000000..f6e0a2b4
--- /dev/null
+++ b/Test/dafny0/DTypes.dfy
@@ -0,0 +1,74 @@
+class C {
+ var n: set<Node>;
+
+ method M(v: Stack)
+ requires v != null;
+ {
+ var o: object := v;
+ assert !(o in n); // should be known from the types involved
+ }
+
+ method N(v: Stack)
+ /* this time without the precondition */
+ {
+ var o: object := v;
+ assert !(o in n); // error: v may be null
+ }
+
+ method A0(a: CP<int,C>, b: CP<int,object>)
+ {
+ var x: object := a;
+ var y: object := b;
+ assert x == y ==> x == null;
+ }
+
+ method A1(a: CP<int,C>)
+ {
+ var x: object := a;
+ assert (forall b: CP<int,Stack> :: x == b ==> b == null); // error (we don't add a type antecedent to
+ // quantifiers; is that what we want?)
+ }
+
+ var a2x: set<CP<C,Node>>;
+ method A2(b: set<CP<Node,C>>)
+ requires !(null in b);
+ {
+ var x: set<object> := a2x;
+ var y: set<object> := b;
+ assert x * y == {};
+ }
+
+ method A3(b: set<CP<Node,C>>)
+ /* this time without the precondition */
+ {
+ var x: set<object> := a2x;
+ var y: set<object> := b;
+ assert x * y <= {null};
+ }
+
+ method A4(b: set<CP<Node,C>>)
+ /* again, without the precondition */
+ {
+ var x: set<object> := a2x;
+ var y: set<object> := b;
+ assert x * y == {}; // error
+ }
+
+ method A5()
+ {
+ var a := new CP<int,C>;
+ var b := new CP<int,object>;
+ while (a != null) {
+ var x: object := a;
+ var y: object := b;
+ assert x == y ==> x == null;
+ a := a; // make 'a' a loop target
+ }
+ }
+}
+
+class Stack { }
+class Node { }
+
+class CP<T,U> {
+}
diff --git a/Test/dafny0/ListContents.dfy b/Test/dafny0/ListContents.dfy
new file mode 100644
index 00000000..6cb7c5a0
--- /dev/null
+++ b/Test/dafny0/ListContents.dfy
@@ -0,0 +1,92 @@
+class Node<T> {
+ var list: seq<T>;
+ var footprint: set<Node<T>>;
+
+ var data: T;
+ var next: Node<T>;
+
+ function Valid(): bool
+ reads this, footprint;
+ {
+ this in this.footprint && !(null in this.footprint) &&
+ (next == null ==> list == [data]) &&
+ (next != null ==>
+ next in footprint && next.footprint <= footprint &&
+ !(this in next.footprint) &&
+ list == [data] + next.list &&
+ next.Valid())
+ }
+
+ method Init(d: T)
+ modifies this;
+ ensures Valid() && fresh(footprint - {this});
+ ensures list == [d];
+ {
+ data := d;
+ next := null;
+ list := [d];
+ footprint := {this};
+ }
+
+ method SkipHead() returns (r: Node<T>)
+ requires Valid();
+ ensures r == null ==> |list| == 1;
+ ensures r != null ==> r.Valid() && r.footprint <= footprint;
+ ensures r != null ==> r.list == list[1..];
+ {
+ r := next;
+ }
+
+ method Prepend(d: T) returns (r: Node<T>)
+ requires Valid();
+ ensures r.Valid() && fresh(r.footprint - old(footprint));
+ ensures r.list == [d] + list;
+ {
+ r := new Node<T>;
+ r.data := d;
+ r.next := this;
+ r.footprint := {r} + this.footprint;
+ r.list := [r.data] + this.list;
+ }
+
+ method ReverseInPlace() returns (reverse: Node<T>)
+ requires Valid();
+ modifies footprint;
+ ensures reverse != null && reverse.Valid();
+ ensures fresh(reverse.footprint - old(footprint));
+ ensures |reverse.list| == |old(list)|;
+ ensures (forall i :: 0 <= i && i < |old(list)| ==> old(list)[i] == reverse.list[|old(list)|-1-i]);
+ {
+ var current := next;
+ reverse := this;
+ reverse.next := null;
+ reverse.footprint := {reverse};
+ reverse.list := [data];
+
+ while (current != null)
+ invariant reverse != null && reverse.Valid();
+ invariant reverse.footprint <= old(footprint);
+ invariant current == null ==> |old(list)| == |reverse.list|;
+ invariant current != null ==>
+ current.Valid() &&
+ current in old(footprint) && current.footprint <= old(footprint) &&
+ current.footprint !! reverse.footprint &&
+ |old(list)| == |reverse.list| + |current.list| &&
+ (forall i :: 0 <= i && i < |current.list| ==> current.list[i] == old(list)[|reverse.list|+i]);
+ invariant
+ (forall i :: 0 <= i && i < |reverse.list| ==> old(list)[i] == reverse.list[|reverse.list|-1-i]);
+ {
+ var nx := current.next;
+ assert nx != null ==> (forall i :: 0 <= i && i < |nx.list| ==> current.list[1+i] == nx.list[i]);
+
+ // ..., reverse, current, nx, ...
+ assert current.data == current.list[0];
+ current.next := reverse;
+ current.footprint := {current} + reverse.footprint;
+ current.list := [current.data] + reverse.list;
+
+ reverse := current;
+ current := nx;
+ }
+ }
+}
diff --git a/Test/dafny0/ListCopy.dfy b/Test/dafny0/ListCopy.dfy
new file mode 100644
index 00000000..f3c64fe2
--- /dev/null
+++ b/Test/dafny0/ListCopy.dfy
@@ -0,0 +1,54 @@
+class Node {
+ var nxt: Node;
+
+ method Init()
+ modifies this;
+ ensures nxt == null;
+ {
+ nxt := null;
+ }
+
+ method Copy(root: Node) returns (result: Node)
+ {
+ var existingRegion: set<Node>;
+ assume root == null || root in existingRegion;
+ assume (forall o: Node :: o != null && o in existingRegion && o.nxt != null ==> o.nxt in existingRegion);
+
+ var newRoot := null;
+ var oldListPtr := root;
+ var newRegion: set<Node> := {};
+
+ if (oldListPtr != null) {
+ newRoot := new Node;
+ call newRoot.Init();
+ newRegion := newRegion + {newRoot};
+ var prev := newRoot;
+
+ while (oldListPtr != null)
+ invariant newRoot in newRegion;
+ invariant (forall o: Node :: o in newRegion ==> o != null);
+ invariant (forall o: Node :: o in newRegion && o.nxt != null ==> o.nxt in newRegion);
+ invariant prev in newRegion;
+ invariant fresh(newRegion);
+ invariant newRegion !! existingRegion;
+ {
+ var tmp := new Node;
+ call tmp.Init();
+
+ newRegion := newRegion + {tmp};
+ prev.nxt := tmp;
+
+ prev := tmp;
+ oldListPtr := oldListPtr.nxt;
+ }
+ }
+ result := newRoot;
+ assert result == null || result in newRegion;
+
+ // everything in newRegion is fresh
+ assert fresh(newRegion);
+
+ // newRegion # exisitingRegion
+ assert newRegion !! existingRegion;
+ }
+}
diff --git a/Test/dafny0/ListReverse.dfy b/Test/dafny0/ListReverse.dfy
new file mode 100644
index 00000000..af61a7a3
--- /dev/null
+++ b/Test/dafny0/ListReverse.dfy
@@ -0,0 +1,26 @@
+
+class Node {
+ var nxt: Node;
+
+ method ReverseInPlace(x: Node, r: set<Node>) returns (reverse: Node)
+ requires !(null in r);
+ requires x == null || x in r;
+ requires (forall y :: y in r ==> y.nxt == null || y.nxt in r); // region closure
+ modifies r;
+ ensures reverse == null || reverse in r;
+ ensures (forall y :: y in r ==> y.nxt == null || y.nxt in r); // region closure
+ {
+ var current := x;
+ reverse := null;
+ while (current != null)
+ invariant current == null || current in r;
+ invariant reverse == null || reverse in r;
+ invariant (forall y :: y in r ==> y.nxt == null || y.nxt in r); // region closure
+ {
+ var tmp := current.nxt;
+ current.nxt := reverse;
+ reverse := current;
+ current := tmp;
+ }
+ }
+}
diff --git a/Test/dafny0/Output b/Test/dafny0/Output
new file mode 100644
index 00000000..64c43c87
--- /dev/null
+++ b/Test/dafny0/Output
@@ -0,0 +1,100 @@
+
+-------------------- Simple.dfy --------------------
+// synthetic program
+
+class MyClass<T, U> {
+ var x: int;
+
+ method M(s: bool, lotsaObjects: set<object>)
+ returns (t: object, u: set<int>, v: seq<MyClass<bool,U>>):
+ requires s;
+ modifies this;
+ modifies lotsaObjects;
+ ensures t == t;
+ ensures old(null) != this;
+ {
+ x := 12;
+ while (x < 100)
+ invariant x <= 100;
+ {
+ x := x + 17;
+ if (x % 20 == 3) {
+ x := this.x + 1;
+ } else {
+ this.x := x + 0;
+ }
+ call t, u, v := M(true, lotsaObjects)
+ var to: MyClass<T,U>;
+ call to, u, v := M(true, lotsaObjects)
+ call to, u, v := to.M(true, lotsaObjects)
+ }
+ }
+}
+
+Dafny program verifier finished with 0 verified, 0 errors
+
+-------------------- BQueue.bpl --------------------
+
+Boogie program verifier finished with 8 verified, 0 errors
+
+-------------------- SmallTests.dfy --------------------
+
+Dafny program verifier finished with 3 verified, 0 errors
+
+-------------------- Queue.dfy --------------------
+
+Dafny program verifier finished with 12 verified, 0 errors
+
+-------------------- ListCopy.dfy --------------------
+
+Dafny program verifier finished with 2 verified, 0 errors
+
+-------------------- BinaryTree.dfy --------------------
+
+Dafny program verifier finished with 13 verified, 0 errors
+
+-------------------- ListReverse.dfy --------------------
+
+Dafny program verifier finished with 1 verified, 0 errors
+
+-------------------- ListContents.dfy --------------------
+
+Dafny program verifier finished with 5 verified, 0 errors
+
+-------------------- SchorrWaite.dfy --------------------
+
+Dafny program verifier finished with 4 verified, 0 errors
+
+-------------------- Termination.dfy --------------------
+
+Dafny program verifier finished with 5 verified, 0 errors
+
+-------------------- Use.dfy --------------------
+Use.dfy(12,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ (0,0): anon0
+Use.dfy(25,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ (0,0): anon0
+Use.dfy(50,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ (0,0): anon0
+
+Dafny program verifier finished with 6 verified, 3 errors
+
+-------------------- DTypes.dfy --------------------
+DTypes.dfy(15,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ (0,0): anon0
+DTypes.dfy(28,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ (0,0): anon0
+DTypes.dfy(54,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ (0,0): anon0
+
+Dafny program verifier finished with 5 verified, 3 errors
+
+-------------------- TypeParameters.dfy --------------------
+
+Dafny program verifier finished with 3 verified, 0 errors
diff --git a/Test/dafny0/Queue.dfy b/Test/dafny0/Queue.dfy
new file mode 100644
index 00000000..ab83a75d
--- /dev/null
+++ b/Test/dafny0/Queue.dfy
@@ -0,0 +1,205 @@
+// Queue.dfy
+// Dafny version of Queue.bpl
+// Rustan Leino, 2008
+
+class Queue<T> {
+ var head: Node<T>;
+ var tail: Node<T>;
+
+ var contents: seq<T>;
+ var footprint: set<object>;
+ var spine: set<Node<T>>;
+
+ function Valid(): bool
+ reads this, footprint;
+ {
+ this in footprint && spine <= footprint &&
+ head != null && head in spine &&
+ tail != null && tail in spine &&
+ tail.next == null &&
+ (forall n :: // { n in spine }
+ n in spine ==>
+ n != null && n.Valid() &&
+ n.footprint <= footprint &&
+ (n.next == null ==> n == tail)) &&
+ (forall n :: // { n.next }
+ n in spine ==>
+ n.next != null ==> n.next in spine) &&
+ contents == head.tailContents
+ }
+
+ method Init()
+ modifies this;
+ ensures Valid() && fresh(footprint - {this});
+ ensures |contents| == 0;
+ {
+ var n := new Node<T>;
+ call n.Init();
+ head := n;
+ tail := n;
+ contents := n.tailContents;
+ footprint := {this} + n.footprint;
+ spine := {n};
+ }
+
+ method Rotate()
+ requires Valid();
+ requires 0 < |contents|;
+ modifies footprint;
+ ensures Valid() && fresh(footprint - old(footprint));
+ ensures contents == old(contents)[1..] + old(contents)[..1];
+ {
+ var t: T;
+ call t := Front();
+ call Dequeue();
+ call Enqueue(t);
+ }
+
+ method RotateAny()
+ requires Valid();
+ requires 0 < |contents|;
+ modifies footprint;
+ ensures Valid() && fresh(footprint - old(footprint));
+ ensures (exists i :: 0 <= i && i <= |contents| &&
+ contents == old(contents)[i..] + old(contents)[..i]);
+ {
+ var t: T;
+ call t := Front();
+ call Dequeue();
+ call Enqueue(t);
+ }
+
+ method IsEmpty() returns (isEmpty: bool)
+ requires Valid();
+ ensures isEmpty <==> |contents| == 0;
+ {
+ isEmpty := head == tail;
+ }
+
+ method Enqueue(t: T)
+ requires Valid();
+ modifies footprint;
+ ensures Valid() && fresh(footprint - old(footprint));
+ ensures contents == old(contents) + [t];
+ {
+ var n := new Node<T>;
+ call n.Init(); n.data := t;
+ tail.next := n;
+ tail := n;
+
+ foreach (m in spine) {
+ m.tailContents := m.tailContents + [t];
+ }
+ contents := head.tailContents;
+
+ foreach (m in spine) {
+ m.footprint := m.footprint + n.footprint;
+ }
+ footprint := footprint + n.footprint;
+
+ spine := spine + {n};
+ }
+
+ method Front() returns (t: T)
+ requires Valid();
+ requires 0 < |contents|;
+ ensures t == contents[0];
+ {
+ t := head.next.data;
+ }
+
+ method Dequeue()
+ requires Valid();
+ requires 0 < |contents|;
+ modifies footprint;
+ ensures Valid() && fresh(footprint - old(footprint));
+ ensures contents == old(contents)[1..];
+ {
+ var n := head.next;
+ head := n;
+ contents := n.tailContents;
+ }
+}
+
+class Node<T> {
+ var data: T;
+ var next: Node<T>;
+
+ var tailContents: seq<T>;
+ var footprint: set<object>;
+
+ function Valid(): bool
+ reads this, footprint;
+ {
+ this in footprint &&
+ (next != null ==> next in footprint && next.footprint <= footprint) &&
+ (next == null ==> tailContents == []) &&
+ (next != null ==> tailContents == [next.data] + next.tailContents)
+ }
+
+ method Init()
+ modifies this;
+ ensures Valid() && fresh(footprint - {this});
+ ensures next == null;
+ {
+ next := null;
+ tailContents := [];
+ footprint := {this};
+ }
+}
+
+class Main<U> {
+ method A<T>(t: T, u: T, v: T)
+ {
+ var q0 := new Queue<T>;
+ call q0.Init();
+ var q1 := new Queue<T>;
+ call q1.Init();
+
+ call q0.Enqueue(t);
+ call q0.Enqueue(u);
+
+ call q1.Enqueue(v);
+
+ assert |q0.contents| == 2;
+
+ var w;
+ call w := q0.Front();
+ assert w == t;
+ call q0.Dequeue();
+
+ call w := q0.Front();
+ assert w == u;
+
+ assert |q0.contents| == 1;
+ assert |q1.contents| == 1;
+ }
+
+ method Main2(t: U, u: U, v: U, q0: Queue<U>, q1: Queue<U>)
+ requires q0 != null && q0.Valid();
+ requires q1 != null && q1.Valid();
+ requires q0.footprint !! q1.footprint;
+ requires |q0.contents| == 0;
+ modifies q0.footprint, q1.footprint;
+ ensures fresh(q0.footprint - old(q0.footprint));
+ ensures fresh(q1.footprint - old(q1.footprint));
+ {
+ call q0.Enqueue(t);
+ call q0.Enqueue(u);
+
+ call q1.Enqueue(v);
+
+ assert |q0.contents| == 2;
+
+ var w;
+ call w := q0.Front();
+ assert w == t;
+ call q0.Dequeue();
+
+ call w := q0.Front();
+ assert w == u;
+
+ assert |q0.contents| == 1;
+ assert |q1.contents| == old(|q1.contents|) + 1;
+ }
+}
diff --git a/Test/dafny0/SchorrWaite.dfy b/Test/dafny0/SchorrWaite.dfy
new file mode 100644
index 00000000..db5928f4
--- /dev/null
+++ b/Test/dafny0/SchorrWaite.dfy
@@ -0,0 +1,229 @@
+// Rustan Leino
+// 7 November 2008
+// Schorr-Waite and other marking algorithms, written and verified in Dafny.
+// Copyright (c) 2008, Microsoft.
+
+class Node {
+ var marked: bool;
+ var childrenVisited: int;
+ var children: seq<Node>;
+}
+
+class Main {
+ method RecursiveMark(root: Node, S: set<Node>)
+ requires root in S;
+ // S is closed under 'children':
+ requires (forall n :: n in S ==> n != null &&
+ (forall ch :: ch in n.children ==> ch == null || ch in S));
+ requires (forall n :: n in S ==> ! n.marked && n.childrenVisited == 0);
+ modifies S;
+ ensures root.marked;
+ // nodes reachable from 'root' are marked:
+ ensures (forall n :: n in S && n.marked ==>
+ (forall ch :: ch in n.children && ch != null ==> ch in S && ch.marked));
+ ensures (forall n :: n in S ==>
+ n.childrenVisited == old(n.childrenVisited) &&
+ n.children == old(n.children));
+ {
+ call RecursiveMarkWorker(root, S, {});
+ }
+
+ method RecursiveMarkWorker(root: Node, S: set<Node>, stackNodes: set<Node>)
+ requires root != null && root in S;
+ requires (forall n :: n in S ==> n != null &&
+ (forall ch :: ch in n.children ==> ch == null || ch in S));
+ requires (forall n :: n in S && n.marked ==>
+ n in stackNodes ||
+ (forall ch :: ch in n.children && ch != null ==> ch in S && ch.marked));
+ modifies S;
+ ensures root.marked;
+ // nodes reachable from 'root' are marked:
+ ensures (forall n :: n in S && n.marked ==>
+ n in stackNodes ||
+ (forall ch :: ch in n.children && ch != null ==> ch in S && ch.marked));
+ ensures (forall n: Node :: old(n.marked) ==> n.marked);
+ ensures (forall n :: n in S ==>
+ n.childrenVisited == old(n.childrenVisited) &&
+ n.children == old(n.children));
+ {
+ if (! root.marked) {
+ root.marked := true;
+ var i := 0;
+ while (i < |root.children|)
+ invariant root.marked && i <= |root.children|;
+ invariant (forall n :: n in S && n.marked ==>
+ n == root ||
+ n in stackNodes ||
+ (forall ch :: ch in n.children && ch != null ==> ch in S && ch.marked));
+ invariant (forall j :: 0 <= j && j < i ==>
+ root.children[j] == null || root.children[j].marked);
+ invariant (forall n: Node :: old(n.marked) ==> n.marked);
+ invariant (forall n :: n in S ==>
+ n.childrenVisited == old(n.childrenVisited) &&
+ n.children == old(n.children));
+ {
+ var c := root.children[i];
+ if (c != null) {
+ call RecursiveMarkWorker(c, S, stackNodes + {root});
+ }
+ }
+ }
+ }
+
+ // ---------------------------------------------------------------------------------
+
+ method IterativeMark(root: Node, S: set<Node>)
+ requires root in S;
+ // S is closed under 'children':
+ requires (forall n :: n in S ==> n != null &&
+ (forall ch :: ch in n.children ==> ch == null || ch in S));
+ requires (forall n :: n in S ==> ! n.marked && n.childrenVisited == 0);
+ modifies S;
+ ensures root.marked;
+ // nodes reachable from 'root' are marked:
+ ensures (forall n :: n in S && n.marked ==>
+ (forall ch :: ch in n.children && ch != null ==> ch in S && ch.marked));
+ ensures (forall n :: n in S ==>
+ n.childrenVisited == old(n.childrenVisited) &&
+ n.children == old(n.children));
+ {
+ var t := root;
+ t.marked := true;
+ var stackNodes := [];
+ var unmarkedNodes := S - {t}; // used as ghost variable
+ while (true)
+ invariant root.marked && t in S && !(t in stackNodes);
+ // stackNodes has no duplicates:
+ invariant (forall i, j :: 0 <= i && i < j && j < |stackNodes| ==>
+ stackNodes[i] != stackNodes[j]);
+ invariant (forall n :: n in stackNodes ==> n in S);
+ invariant (forall n :: n in stackNodes || n == t ==>
+ n.marked &&
+ 0 <= n.childrenVisited && n.childrenVisited <= |n.children| &&
+ (forall j :: 0 <= j && j < n.childrenVisited ==>
+ n.children[j] == null || n.children[j].marked));
+ invariant (forall n :: n in stackNodes ==> n.childrenVisited < |n.children|);
+ // nodes on the stack are linked:
+ invariant (forall j :: 0 <= j && j+1 < |stackNodes| ==>
+ stackNodes[j].children[stackNodes[j].childrenVisited] == stackNodes[j+1]);
+ invariant 0 < |stackNodes| ==>
+ stackNodes[|stackNodes|-1].children[stackNodes[|stackNodes|-1].childrenVisited] == t;
+ invariant (forall n :: n in S && n.marked && !(n in stackNodes) && n != t ==>
+ (forall ch :: ch in n.children && ch != null ==> ch in S && ch.marked));
+ invariant (forall n :: n in S && !(n in stackNodes) && n != t ==>
+ n.childrenVisited == old(n.childrenVisited));
+ invariant (forall n: Node :: n.children == old(n.children));
+ invariant (forall n :: n in S && !n.marked ==> n in unmarkedNodes);
+ decreases unmarkedNodes, stackNodes, |t.children| - t.childrenVisited;
+ {
+ if (t.childrenVisited == |t.children|) {
+ // pop
+ t.childrenVisited := 0;
+ if (|stackNodes| == 0) {
+ return;
+ }
+ t := stackNodes[|stackNodes| - 1];
+ stackNodes := stackNodes[..|stackNodes| - 1];
+ t.childrenVisited := t.childrenVisited + 1;
+ } else if (t.children[t.childrenVisited] == null || t.children[t.childrenVisited].marked) {
+ // just advance to next child
+ t.childrenVisited := t.childrenVisited + 1;
+ } else {
+ // push
+ stackNodes := stackNodes + [t];
+ t := t.children[t.childrenVisited];
+ t.marked := true;
+ unmarkedNodes := unmarkedNodes - {t};
+ }
+ }
+ }
+
+ // ---------------------------------------------------------------------------------
+
+ method SchorrWaite(root: Node, S: set<Node>)
+ requires root in S;
+ // S is closed under 'children':
+ requires (forall n :: n in S ==> n != null &&
+ (forall ch :: ch in n.children ==> ch == null || ch in S));
+ requires (forall n :: n in S ==> ! n.marked && n.childrenVisited == 0);
+ modifies S;
+ ensures root.marked;
+ // nodes reachable from 'root' are marked:
+ ensures (forall n :: n in S && n.marked ==>
+ (forall ch :: ch in n.children && ch != null ==> ch in S && ch.marked));
+ ensures (forall n :: n in S ==>
+ n.childrenVisited == old(n.childrenVisited) &&
+ n.children == old(n.children));
+ {
+ var t := root;
+ var p: Node := null; // parent of t in original graph
+ t.marked := true;
+ var stackNodes := []; // used as ghost variable
+ var unmarkedNodes := S - {t}; // used as ghost variable
+ while (true)
+ invariant root.marked && t != null && t in S && !(t in stackNodes);
+ invariant |stackNodes| == 0 <==> p == null;
+ invariant 0 < |stackNodes| ==> p == stackNodes[|stackNodes|-1];
+ // stackNodes has no duplicates:
+ invariant (forall i, j :: 0 <= i && i < j && j < |stackNodes| ==>
+ stackNodes[i] != stackNodes[j]);
+ invariant (forall n :: n in stackNodes ==> n in S);
+ invariant (forall n :: n in stackNodes || n == t ==>
+ n.marked &&
+ 0 <= n.childrenVisited && n.childrenVisited <= |n.children| &&
+ (forall j :: 0 <= j && j < n.childrenVisited ==>
+ n.children[j] == null || n.children[j].marked));
+ invariant (forall n :: n in stackNodes ==> n.childrenVisited < |n.children|);
+ invariant (forall n :: n in S && n.marked && !(n in stackNodes) && n != t ==>
+ (forall ch :: ch in n.children && ch != null ==> ch in S && ch.marked));
+ invariant (forall n :: n in S && !(n in stackNodes) && n != t ==>
+ n.childrenVisited == old(n.childrenVisited));
+ invariant (forall n :: n in stackNodes || n.children == old(n.children));
+ invariant (forall n :: n in stackNodes ==>
+ |n.children| == old(|n.children|) &&
+ (forall j :: 0 <= j && j < |n.children| ==>
+ j == n.childrenVisited || n.children[j] == old(n.children[j])));
+ // the current values of m.children[m.childrenVisited] for m's on the stack:
+ invariant 0 < |stackNodes| ==> stackNodes[0].children[stackNodes[0].childrenVisited] == null;
+ invariant (forall k :: 0 < k && k < |stackNodes| ==>
+ stackNodes[k].children[stackNodes[k].childrenVisited] == stackNodes[k-1]);
+ // the original values of m.children[m.childrenVisited] for m's on the stack:
+ invariant (forall k :: 0 <= k && k+1 < |stackNodes| ==>
+ old(stackNodes[k].children)[stackNodes[k].childrenVisited] == stackNodes[k+1]);
+ invariant 0 < |stackNodes| ==>
+ old(stackNodes[|stackNodes|-1].children)[stackNodes[|stackNodes|-1].childrenVisited] == t;
+ invariant (forall n :: n in S && !n.marked ==> n in unmarkedNodes);
+ decreases unmarkedNodes, stackNodes, |t.children| - t.childrenVisited;
+ {
+ if (t.childrenVisited == |t.children|) {
+ // pop
+ t.childrenVisited := 0;
+ if (p == null) {
+ return;
+ }
+ var oldP := p.children[p.childrenVisited];
+ // p.children[p.childrenVisited] := t;
+ p.children := p.children[..p.childrenVisited] + [t] + p.children[p.childrenVisited + 1..];
+ t := p;
+ p := oldP;
+ stackNodes := stackNodes[..|stackNodes| - 1];
+ t.childrenVisited := t.childrenVisited + 1;
+
+ } else if (t.children[t.childrenVisited] == null || t.children[t.childrenVisited].marked) {
+ // just advance to next child
+ t.childrenVisited := t.childrenVisited + 1;
+ } else {
+ // push
+
+ var newT := t.children[t.childrenVisited];
+ // t.children[t.childrenVisited] := p;
+ t.children := t.children[..t.childrenVisited] + [p] + t.children[t.childrenVisited + 1..];
+ p := t;
+ stackNodes := stackNodes + [t];
+ t := newT;
+ t.marked := true;
+ unmarkedNodes := unmarkedNodes - {t};
+ }
+ }
+ }
+}
diff --git a/Test/dafny0/Simple.dfy b/Test/dafny0/Simple.dfy
new file mode 100644
index 00000000..9f89543c
--- /dev/null
+++ b/Test/dafny0/Simple.dfy
@@ -0,0 +1,29 @@
+// My first Dafny program
+// Rustan Leino, 27 January 2008
+
+class MyClass<T,U> {
+ var x: int;
+
+ method M(s: bool, lotsaObjects: set<object>) returns (t: object, u: set<int>, v: seq<MyClass<bool,U>>)
+ requires s;
+ modifies this, lotsaObjects;
+ ensures t == t;
+ ensures old(null) != this;
+ {
+ x := 12;
+ while (x < 100)
+ invariant x <= 100;
+ {
+ x := x + 17;
+ if (x % 20 == 3) {
+ x := this.x + 1;
+ } else {
+ this.x := x + 0;
+ }
+ call t, u, v := M(true, lotsaObjects);
+ var to: MyClass<T,U>;
+ call to, u, v := this.M(true, lotsaObjects);
+ call to, u, v := to.M(true, lotsaObjects);
+ }
+ }
+}
diff --git a/Test/dafny0/SmallTests.dfy b/Test/dafny0/SmallTests.dfy
new file mode 100644
index 00000000..a2cfc741
--- /dev/null
+++ b/Test/dafny0/SmallTests.dfy
@@ -0,0 +1,26 @@
+class Node {
+ var next: Node;
+
+ function IsList(r: set<Node>): bool
+ reads this, r;
+ {
+ next != null ==> next.IsList(r - {this})
+ }
+
+ method Test(n: Node, nodes: set<Node>)
+ {
+ assume nodes == nodes - {n};
+ // the next line needs the Set extensionality axiom, the antecedent of
+ // which is supplied by the previous line
+ assert IsList(nodes) == IsList(nodes - {n});
+ }
+
+ method Create()
+ modifies this;
+ {
+ next := null;
+ var tmp: Node;
+ tmp := new Node;
+ assert tmp != this; // was once a bug in the Dafny checker
+ }
+}
diff --git a/Test/dafny0/Termination.dfy b/Test/dafny0/Termination.dfy
new file mode 100644
index 00000000..43fe63df
--- /dev/null
+++ b/Test/dafny0/Termination.dfy
@@ -0,0 +1,80 @@
+class Termination {
+ method A(N: int)
+ requires 0 <= N;
+ {
+ var i := 0;
+ while (i < N)
+ invariant i <= N;
+ decreases N - i;
+ {
+ i := i + 1;
+ }
+ }
+
+ method B(N: int)
+ requires 0 <= N;
+ {
+ var i := N;
+ while (true)
+ invariant 0 <= i;
+ decreases i;
+ {
+ i := i - 1;
+ if (!(0 <= i)) {
+ break;
+ }
+ }
+ assert i == -1;
+ }
+
+ method Lex() {
+ var x: int, y: int;
+ call x := Update();
+ call y := Update();
+ while (!(x == 0 && y == 0))
+ invariant 0 <= x && 0 <= y;
+ decreases x, y;
+ {
+ if (0 < y) {
+ y := y - 1;
+ } else {
+ x := x - 1;
+ call y := Update();
+ }
+ }
+ }
+
+ method Update() returns (r: int)
+ ensures 0 <= r;
+ {
+ r := 8;
+ }
+
+ method M() {
+ var b := true;
+ var i := 500;
+ var r := new Termination;
+ var s := {12, 200};
+ var q := [5, 8, 13];
+ while (true)
+ decreases b, i, r;
+// invariant b ==> 0 <= i;
+ decreases s, q;
+ {
+ if (12 in s) {
+ s := s - {12};
+ } else if (b) {
+ b := !b;
+ i := i + 1;
+ } else if (20 <= i) {
+ i := i - 20;
+ } else if (r != null) {
+ r := null;
+ } else if (|q| != 0) {
+ q := q[1..];
+ } else {
+ break;
+ }
+ }
+ }
+}
diff --git a/Test/dafny0/TypeParameters.dfy b/Test/dafny0/TypeParameters.dfy
new file mode 100644
index 00000000..a5764be5
--- /dev/null
+++ b/Test/dafny0/TypeParameters.dfy
@@ -0,0 +1,22 @@
+class C<U> {
+ method M<T>(x: T, u: U) returns (y: T)
+ ensures x == y && u == u;
+ {
+ y := x;
+ }
+
+ function F<X>(x: X, u: U): bool
+ {
+ x == x && u == u
+ }
+
+ method Main(u: U)
+ {
+ var t := F(3,u) && F(this,u);
+ var kz;
+ call kz := M(t,u);
+ assert kz && (G() || !G());
+ }
+
+ function G<Y>(): Y;
+}
diff --git a/Test/dafny0/Use.dfy b/Test/dafny0/Use.dfy
new file mode 100644
index 00000000..1d2d264f
--- /dev/null
+++ b/Test/dafny0/Use.dfy
@@ -0,0 +1,70 @@
+class T {
+ var x: int;
+
+ function use F(y: int): int {
+ 2*y
+ }
+
+ method M(s: set<T>) {
+ use F(4);
+ use F(5);
+ assert F(5) == 10;
+ assert F(7) == 14; // error (definition not engaged)
+ }
+
+ function use G(y: int): bool {
+ 0 <= y
+ }
+
+ method N(s: set<T>) {
+ use G(4);
+ use G(5);
+ use G(-5);
+ assert G(5);
+ assert !G(-5);
+ assert G(7); // error (definition not engaged)
+ }
+
+ function use H(): int
+ reads this;
+ {
+ x
+ }
+
+ method Q0()
+ modifies this;
+ {
+ var t := x;
+ use H();
+ assert H() == t;
+
+ x := x + 1;
+ assert old(H()) == t;
+ }
+
+ method Q1()
+ modifies this;
+ {
+ x := x + 1;
+ use H();
+ assert H() == old(H()) + 1; // error: does not know what old(H()) is
+ }
+
+ method Q2()
+ modifies this;
+ {
+ use H();
+ x := x + 1;
+ use H();
+ assert H() == old(H()) + 1;
+ }
+
+ method Q3()
+ modifies this;
+ {
+ x := x + 1;
+ use H();
+ use old(H());
+ assert H() == old(H()) + 1;
+ }
+}
diff --git a/Test/dafny0/runtest.bat b/Test/dafny0/runtest.bat
new file mode 100644
index 00000000..a6cfa2c0
--- /dev/null
+++ b/Test/dafny0/runtest.bat
@@ -0,0 +1,27 @@
+@echo off
+setlocal
+
+set BOOGIEDIR=..\..\Binaries
+set DAFNY_EXE=%BOOGIEDIR%\Dafny.exe
+set BPLEXE=%BOOGIEDIR%\Boogie.exe
+
+for %%f in (Simple.dfy) do (
+ echo.
+ echo -------------------- %%f --------------------
+ %DAFNY_EXE% %* /dprint:- /env:0 /noVerify %%f
+)
+
+for %%f in (BQueue.bpl) do (
+ echo.
+ echo -------------------- %%f --------------------
+ %BPLEXE% %* %%f
+)
+
+for %%f in (SmallTests.dfy Queue.dfy ListCopy.dfy
+ BinaryTree.dfy ListReverse.dfy ListContents.dfy
+ SchorrWaite.dfy Termination.dfy Use.dfy DTypes.dfy
+ TypeParameters.dfy) do (
+ echo.
+ echo -------------------- %%f --------------------
+ %DAFNY_EXE% %* %%f
+)
diff --git a/Test/filter.pl b/Test/filter.pl
new file mode 100644
index 00000000..c95a7e4f
--- /dev/null
+++ b/Test/filter.pl
@@ -0,0 +1,38 @@
+$numargs = $#ARGV + 1;
+
+($numargs == 2) || die "usage: filter.pl input-log output-log\n";
+
+$input = $ARGV[0];
+$output = $ARGV[1];
+
+open(IN, "<$input") || die "can't open $input";
+open(OUT, ">$output") || die "can't open $output";
+
+my @array = ();
+
+while (<IN>) {
+ s/^\s*.:.*\\//;
+ s/^Microsoft .*//;
+ s/^for Microsoft \(R\) .NET.*//;
+ s/^Copyright \(C\).*//;
+ if ($_ !~ m/^\s*$/) # don't write out blank lines
+ {
+ push(@array, ($_));
+ }
+}
+
+#
+# if we want to compare only sorted output uncomment this
+#@sorted = sort(@array);
+@sorted = @array;
+
+
+# eliminate duplicates in the output
+$last = "";
+foreach (@sorted)
+{
+ if ($_ ne $last) {
+ print(OUT $_);
+ $last = $_;
+ }
+}
diff --git a/Test/havoc0/Answer b/Test/havoc0/Answer
new file mode 100644
index 00000000..80fd4aa3
--- /dev/null
+++ b/Test/havoc0/Answer
@@ -0,0 +1,12 @@
+
+Boogie program verifier finished with 1 verified, 0 errors
+
+Boogie program verifier finished with 1 verified, 0 errors
+
+Boogie program verifier finished with 1 verified, 0 errors
+
+Boogie program verifier finished with 1 verified, 0 errors
+
+Boogie program verifier finished with 1 verified, 0 errors
+
+Boogie program verifier finished with 1 verified, 0 errors
diff --git a/Test/havoc0/KbdCreateClassObject.bpl b/Test/havoc0/KbdCreateClassObject.bpl
new file mode 100644
index 00000000..a7f6e9c2
--- /dev/null
+++ b/Test/havoc0/KbdCreateClassObject.bpl
@@ -0,0 +1,5155 @@
+type byte, name;
+function OneByteToInt(byte) returns (int);
+function TwoBytesToInt(byte, byte) returns (int);
+function FourBytesToInt(byte, byte, byte, byte) returns (int);
+axiom(forall b0:byte, c0:byte :: {OneByteToInt(b0), OneByteToInt(c0)} OneByteToInt(b0) == OneByteToInt(c0) ==> b0 == c0);
+axiom(forall b0:byte, b1: byte, c0:byte, c1:byte :: {TwoBytesToInt(b0, b1), TwoBytesToInt(c0, c1)} TwoBytesToInt(b0, b1) == TwoBytesToInt(c0, c1) ==> b0 == c0 && b1 == c1);
+axiom(forall b0:byte, b1: byte, b2:byte, b3:byte, c0:byte, c1:byte, c2:byte, c3:byte :: {FourBytesToInt(b0, b1, b2, b3), FourBytesToInt(c0, c1, c2, c3)} FourBytesToInt(b0, b1, b2, b3) == FourBytesToInt(c0, c1, c2, c3) ==> b0 == c0 && b1 == c1 && b2 == c2 && b3 == c3);
+
+// Mutable
+var Mem_BYTE:[int]byte;
+var alloc:[int]name;
+
+
+function Field(int) returns (name);
+function Base(int) returns (int);
+
+// Constants
+const unique UNALLOCATED:name;
+const unique ALLOCATED: name;
+const unique FREED:name;
+
+const unique BYTE:name;
+
+function Equal([int]bool, [int]bool) returns (bool);
+function Subset([int]bool, [int]bool) returns (bool);
+function Disjoint([int]bool, [int]bool) returns (bool);
+
+function Empty() returns ([int]bool);
+function SetTrue() returns ([int]bool);
+function Singleton(int) returns ([int]bool);
+function Reachable([int,int]bool, int) returns ([int]bool);
+function Union([int]bool, [int]bool) returns ([int]bool);
+function Intersection([int]bool, [int]bool) returns ([int]bool);
+function Difference([int]bool, [int]bool) returns ([int]bool);
+function Dereference([int]bool, [int]int) returns ([int]bool);
+function Inverse(f:[int]int, x:int) returns ([int]bool);
+
+function AtLeast(int, int) returns ([int]bool);
+function Rep(int, int) returns (int);
+axiom(forall n:int, x:int, y:int :: {AtLeast(n,x)[y]} AtLeast(n,x)[y] ==> x <= y && Rep(n,x) == Rep(n,y));
+axiom(forall n:int, x:int, y:int :: {AtLeast(n,x),Rep(n,x),Rep(n,y)} x <= y && Rep(n,x) == Rep(n,y) ==> AtLeast(n,x)[y]);
+axiom(forall n:int, x:int :: {AtLeast(n,x)} AtLeast(n,x)[x]);
+axiom(forall n:int, x:int, z:int :: {PLUS(x,n,z)} Rep(n,x) == Rep(n,PLUS(x,n,z)));
+axiom(forall n:int, x:int :: {Rep(n,x)} (exists k:int :: Rep(n,x) - x == n*k));
+
+/*
+function AtLeast(int, int) returns ([int]bool);
+function ModEqual(int, int, int) returns (bool);
+axiom(forall n:int, x:int :: ModEqual(n,x,x));
+axiom(forall n:int, x:int, y:int :: {ModEqual(n,x,y)} ModEqual(n,x,y) ==> ModEqual(n,y,x));
+axiom(forall n:int, x:int, y:int, z:int :: {ModEqual(n,x,y), ModEqual(n,y,z)} ModEqual(n,x,y) && ModEqual(n,y,z) ==> ModEqual(n,x,z));
+axiom(forall n:int, x:int, z:int :: {PLUS(x,n,z)} ModEqual(n,x,PLUS(x,n,z)));
+axiom(forall n:int, x:int, y:int :: {ModEqual(n,x,y)} ModEqual(n,x,y) ==> (exists k:int :: x - y == n*k));
+axiom(forall x:int, n:int, y:int :: {AtLeast(n,x)[y]}{ModEqual(n,x,y)} AtLeast(n,x)[y] <==> x <= y && ModEqual(n,x,y));
+axiom(forall x:int, n:int :: {AtLeast(n,x)} AtLeast(n,x)[x]);
+*/
+
+function Array(int, int, int) returns ([int]bool);
+axiom(forall x:int, n:int, z:int :: {Array(x,n,z)} z <= 0 ==> Equal(Array(x,n,z), Empty()));
+axiom(forall x:int, n:int, z:int :: {Array(x,n,z)} z > 0 ==> Equal(Array(x,n,z), Difference(AtLeast(n,x),AtLeast(n,PLUS(x,n,z)))));
+
+
+axiom(forall x:int :: !Empty()[x]);
+
+axiom(forall x:int :: SetTrue()[x]);
+
+axiom(forall x:int, y:int :: {Singleton(y)[x]} Singleton(y)[x] <==> x == y);
+axiom(forall y:int :: {Singleton(y)} Singleton(y)[y]);
+
+/* this formulation of Union IS more complete than the earlier one */
+/* (A U B)[e], A[d], A U B = Singleton(c), d != e */
+axiom(forall x:int, S:[int]bool, T:[int]bool :: {Union(S,T)[x]}{Union(S,T),S[x]}{Union(S,T),T[x]} Union(S,T)[x] <==> S[x] || T[x]);
+axiom(forall x:int, S:[int]bool, T:[int]bool :: {Intersection(S,T)[x]}{Intersection(S,T),S[x]}{Intersection(S,T),T[x]} Intersection(S,T)[x] <==> S[x] && T[x]);
+axiom(forall x:int, S:[int]bool, T:[int]bool :: {Difference(S,T)[x]}{Difference(S,T),S[x]}{Difference(S,T),T[x]} Difference(S,T)[x] <==> S[x] && !T[x]);
+
+axiom(forall S:[int]bool, T:[int]bool :: {Equal(S,T)} Equal(S,T) <==> Subset(S,T) && Subset(T,S));
+axiom(forall x:int, S:[int]bool, T:[int]bool :: {S[x],Subset(S,T)}{T[x],Subset(S,T)} S[x] && Subset(S,T) ==> T[x]);
+axiom(forall S:[int]bool, T:[int]bool :: {Subset(S,T)} Subset(S,T) || (exists x:int :: S[x] && !T[x]));
+axiom(forall x:int, S:[int]bool, T:[int]bool :: {S[x],Disjoint(S,T)}{T[x],Disjoint(S,T)} !(S[x] && Disjoint(S,T) && T[x]));
+axiom(forall S:[int]bool, T:[int]bool :: {Disjoint(S,T)} Disjoint(S,T) || (exists x:int :: S[x] && T[x]));
+
+axiom(forall f:[int]int, x:int :: {Inverse(f,f[x])} Inverse(f,f[x])[x]);
+axiom(forall f:[int]int, x:int, y:int :: {Inverse(f,y), f[x]} Inverse(f,y)[x] ==> f[x] == y);
+axiom(forall f:[int]int, x:int, y:int :: {Inverse(f[x := y],y)} Equal(Inverse(f[x := y],y), Union(Inverse(f,y), Singleton(x))));
+axiom(forall f:[int]int, x:int, y:int, z:int :: {Inverse(f[x := y],z)} y == z || Equal(Inverse(f[x := y],z), Difference(Inverse(f,z), Singleton(x))));
+
+
+axiom(forall x:int, S:[int]bool, M:[int]int :: {Dereference(S,M)[x]} Dereference(S,M)[x] ==> (exists y:int :: x == M[y] && S[y]));
+axiom(forall x:int, S:[int]bool, M:[int]int :: {M[x], S[x], Dereference(S,M)} S[x] ==> Dereference(S,M)[M[x]]);
+axiom(forall x:int, y:int, S:[int]bool, M:[int]int :: {Dereference(S,M[x := y])} !S[x] ==> Equal(Dereference(S,M[x := y]), Dereference(S,M)));
+axiom(forall x:int, y:int, S:[int]bool, M:[int]int :: {Dereference(S,M[x := y])}
+ S[x] && Equal(Intersection(Inverse(M,M[x]), S), Singleton(x)) ==> Equal(Dereference(S,M[x := y]), Union(Difference(Dereference(S,M), Singleton(M[x])), Singleton(y))));
+axiom(forall x:int, y:int, S:[int]bool, M:[int]int :: {Dereference(S,M[x := y])}
+ S[x] && !Equal(Intersection(Inverse(M,M[x]), S), Singleton(x)) ==> Equal(Dereference(S,M[x := y]), Union(Dereference(S,M), Singleton(y))));
+
+function Unified([name][int]int) returns ([int]int);
+axiom(forall M:[name][int]int, x:int :: {Unified(M)[x]} Unified(M)[x] == M[Field(x)][x]);
+axiom(forall M:[name][int]int, x:int, y:int :: {Unified(M[Field(x) := M[Field(x)][x := y]])} Unified(M[Field(x) := M[Field(x)][x := y]]) == Unified(M)[x := y]);
+// Memory model
+
+var Mem: [name][int]int;
+
+function Match(a:int, t:name) returns (bool);
+function HasType(v:int, t:name, m:[name][int]int) returns (bool);
+function Values(t:name, m:[name][int]int) returns ([int]bool);
+function T.Ptr(t:name) returns (name);
+
+axiom(forall v:int, t:name, m:[name][int]int :: {Values(t, m)[v]} Values(t, m)[v] ==> HasType(v, t, m));
+axiom(forall v:int, t:name, m:[name][int]int :: {HasType(v, t, m), Values(t, m)} HasType(v, t, m) ==> Values(t, m)[v]);
+
+axiom(forall a:int, t:name :: {Match(a, T.Ptr(t))} Match(a, T.Ptr(t)) <==> Field(a) == T.Ptr(t));
+axiom(forall v:int, t:name, m:[name][int]int :: {HasType(v, T.Ptr(t), m)} HasType(v, T.Ptr(t), m) <==> (v == 0 || (v > 0 && Match(v, t))));
+
+axiom(forall v:int, t:name, m1:[name][int]int, m2:[name][int]int :: {HasType(v, t, m1), HasType(v, t, m2)}
+ (HasType(v, t, m1) <==> HasType(v, t, m2)));
+
+// Field declarations
+
+const unique T.Guid_WMIGUIDREGINFO:name;
+const unique T.InstanceCount_WMIGUIDREGINFO:name;
+const unique T.Flags_WMIGUIDREGINFO:name;
+const unique T.OperationID__ACCESS_STATE:name;
+const unique T.SecurityEvaluated__ACCESS_STATE:name;
+const unique T.GenerateAudit__ACCESS_STATE:name;
+const unique T.GenerateOnClose__ACCESS_STATE:name;
+const unique T.PrivilegesAllocated__ACCESS_STATE:name;
+const unique T.Flags__ACCESS_STATE:name;
+const unique T.RemainingDesiredAccess__ACCESS_STATE:name;
+const unique T.PreviouslyGrantedAccess__ACCESS_STATE:name;
+const unique T.OriginalDesiredAccess__ACCESS_STATE:name;
+const unique T.SubjectSecurityContext__ACCESS_STATE:name;
+const unique T.SecurityDescriptor__ACCESS_STATE:name;
+const unique T.AuxData__ACCESS_STATE:name;
+const unique T.Privileges__ACCESS_STATE:name;
+const unique T.AuditPrivileges__ACCESS_STATE:name;
+const unique T.ObjectName__ACCESS_STATE:name;
+const unique T.ObjectTypeName__ACCESS_STATE:name;
+const unique T.InterfaceType__CM_FULL_RESOURCE_DESCRIPTOR:name;
+const unique T.BusNumber__CM_FULL_RESOURCE_DESCRIPTOR:name;
+const unique T.PartialResourceList__CM_FULL_RESOURCE_DESCRIPTOR:name;
+const unique T.Type__CM_PARTIAL_RESOURCE_DESCRIPTOR:name;
+const unique T.ShareDisposition__CM_PARTIAL_RESOURCE_DESCRIPTOR:name;
+const unique T.Flags__CM_PARTIAL_RESOURCE_DESCRIPTOR:name;
+const unique T.u__CM_PARTIAL_RESOURCE_DESCRIPTOR:name;
+const unique T.Version__CM_PARTIAL_RESOURCE_LIST:name;
+const unique T.Revision__CM_PARTIAL_RESOURCE_LIST:name;
+const unique T.Count__CM_PARTIAL_RESOURCE_LIST:name;
+const unique T.PartialDescriptors__CM_PARTIAL_RESOURCE_LIST:name;
+const unique T.Count__CM_RESOURCE_LIST:name;
+const unique T.List__CM_RESOURCE_LIST:name;
+const unique T.Size__DEVICE_CAPABILITIES:name;
+const unique T.Version__DEVICE_CAPABILITIES:name;
+const unique T.DeviceD1__DEVICE_CAPABILITIES:name;
+const unique T.DeviceD2__DEVICE_CAPABILITIES:name;
+const unique T.LockSupported__DEVICE_CAPABILITIES:name;
+const unique T.EjectSupported__DEVICE_CAPABILITIES:name;
+const unique T.Removable__DEVICE_CAPABILITIES:name;
+const unique T.DockDevice__DEVICE_CAPABILITIES:name;
+const unique T.UniqueID__DEVICE_CAPABILITIES:name;
+const unique T.SilentInstall__DEVICE_CAPABILITIES:name;
+const unique T.RawDeviceOK__DEVICE_CAPABILITIES:name;
+const unique T.SurpriseRemovalOK__DEVICE_CAPABILITIES:name;
+const unique T.WakeFromD0__DEVICE_CAPABILITIES:name;
+const unique T.WakeFromD1__DEVICE_CAPABILITIES:name;
+const unique T.WakeFromD2__DEVICE_CAPABILITIES:name;
+const unique T.WakeFromD3__DEVICE_CAPABILITIES:name;
+const unique T.HardwareDisabled__DEVICE_CAPABILITIES:name;
+const unique T.NonDynamic__DEVICE_CAPABILITIES:name;
+const unique T.WarmEjectSupported__DEVICE_CAPABILITIES:name;
+const unique T.NoDisplayInUI__DEVICE_CAPABILITIES:name;
+const unique T.Reserved__DEVICE_CAPABILITIES:name;
+const unique T.Address__DEVICE_CAPABILITIES:name;
+const unique T.UINumber__DEVICE_CAPABILITIES:name;
+const unique T.DeviceState__DEVICE_CAPABILITIES:name;
+const unique T.SystemWake__DEVICE_CAPABILITIES:name;
+const unique T.DeviceWake__DEVICE_CAPABILITIES:name;
+const unique T.D1Latency__DEVICE_CAPABILITIES:name;
+const unique T.D2Latency__DEVICE_CAPABILITIES:name;
+const unique T.D3Latency__DEVICE_CAPABILITIES:name;
+const unique T.Self__DEVICE_EXTENSION:name;
+const unique T.TrueClassDevice__DEVICE_EXTENSION:name;
+const unique T.TopPort__DEVICE_EXTENSION:name;
+const unique T.PDO__DEVICE_EXTENSION:name;
+const unique T.RemoveLock__DEVICE_EXTENSION:name;
+const unique T.PnP__DEVICE_EXTENSION:name;
+const unique T.Started__DEVICE_EXTENSION:name;
+const unique T.AllowDisable__DEVICE_EXTENSION:name;
+const unique T.WaitWakeSpinLock__DEVICE_EXTENSION:name;
+const unique T.TrustedSubsystemCount__DEVICE_EXTENSION:name;
+const unique T.InputCount__DEVICE_EXTENSION:name;
+const unique T.SymbolicLinkName__DEVICE_EXTENSION:name;
+const unique T.InputData__DEVICE_EXTENSION:name;
+const unique T.DataIn__DEVICE_EXTENSION:name;
+const unique T.DataOut__DEVICE_EXTENSION:name;
+const unique T.KeyboardAttributes__DEVICE_EXTENSION:name;
+const unique T.IndicatorParameters__DEVICE_EXTENSION:name;
+const unique T.SpinLock__DEVICE_EXTENSION:name;
+const unique T.ReadQueue__DEVICE_EXTENSION:name;
+const unique T.SequenceNumber__DEVICE_EXTENSION:name;
+const unique T.DeviceState__DEVICE_EXTENSION:name;
+const unique T.SystemState__DEVICE_EXTENSION:name;
+const unique T.UnitId__DEVICE_EXTENSION:name;
+const unique T.WmiLibInfo__DEVICE_EXTENSION:name;
+const unique T.SystemToDeviceState__DEVICE_EXTENSION:name;
+const unique T.MinDeviceWakeState__DEVICE_EXTENSION:name;
+const unique T.MinSystemWakeState__DEVICE_EXTENSION:name;
+const unique T.WaitWakeIrp__DEVICE_EXTENSION:name;
+const unique T.ExtraWaitWakeIrp__DEVICE_EXTENSION:name;
+const unique T.TargetNotifyHandle__DEVICE_EXTENSION:name;
+const unique T.Link__DEVICE_EXTENSION:name;
+const unique T.File__DEVICE_EXTENSION:name;
+const unique T.Enabled__DEVICE_EXTENSION:name;
+const unique T.OkayToLogOverflow__DEVICE_EXTENSION:name;
+const unique T.WaitWakeEnabled__DEVICE_EXTENSION:name;
+const unique T.SurpriseRemoved__DEVICE_EXTENSION:name;
+const unique T.Type__DEVICE_OBJECT:name;
+const unique T.Size__DEVICE_OBJECT:name;
+const unique T.ReferenceCount__DEVICE_OBJECT:name;
+const unique T.DriverObject__DEVICE_OBJECT:name;
+const unique T.NextDevice__DEVICE_OBJECT:name;
+const unique T.AttachedDevice__DEVICE_OBJECT:name;
+const unique T.CurrentIrp__DEVICE_OBJECT:name;
+const unique T.Timer__DEVICE_OBJECT:name;
+const unique T.Flags__DEVICE_OBJECT:name;
+const unique T.Characteristics__DEVICE_OBJECT:name;
+const unique T.Vpb__DEVICE_OBJECT:name;
+const unique T.DeviceExtension__DEVICE_OBJECT:name;
+const unique T.DeviceType__DEVICE_OBJECT:name;
+const unique T.StackSize__DEVICE_OBJECT:name;
+const unique T.Queue__DEVICE_OBJECT:name;
+const unique T.AlignmentRequirement__DEVICE_OBJECT:name;
+const unique T.DeviceQueue__DEVICE_OBJECT:name;
+const unique T.Dpc__DEVICE_OBJECT:name;
+const unique T.ActiveThreadCount__DEVICE_OBJECT:name;
+const unique T.SecurityDescriptor__DEVICE_OBJECT:name;
+const unique T.DeviceLock__DEVICE_OBJECT:name;
+const unique T.SectorSize__DEVICE_OBJECT:name;
+const unique T.Spare1__DEVICE_OBJECT:name;
+const unique T.DeviceObjectExtension__DEVICE_OBJECT:name;
+const unique T.Reserved__DEVICE_OBJECT:name;
+const unique T.Type__DEVOBJ_EXTENSION:name;
+const unique T.Size__DEVOBJ_EXTENSION:name;
+const unique T.DeviceObject__DEVOBJ_EXTENSION:name;
+const unique T.__unnamed_4_a97c65a1__DISPATCHER_HEADER:name;
+const unique T.SignalState__DISPATCHER_HEADER:name;
+const unique T.WaitListHead__DISPATCHER_HEADER:name;
+const unique T.DriverObject__DRIVER_EXTENSION:name;
+const unique T.AddDevice__DRIVER_EXTENSION:name;
+const unique T.Count__DRIVER_EXTENSION:name;
+const unique T.ServiceKeyName__DRIVER_EXTENSION:name;
+const unique T.Type__DRIVER_OBJECT:name;
+const unique T.Size__DRIVER_OBJECT:name;
+const unique T.DeviceObject__DRIVER_OBJECT:name;
+const unique T.Flags__DRIVER_OBJECT:name;
+const unique T.DriverStart__DRIVER_OBJECT:name;
+const unique T.DriverSize__DRIVER_OBJECT:name;
+const unique T.DriverSection__DRIVER_OBJECT:name;
+const unique T.DriverExtension__DRIVER_OBJECT:name;
+const unique T.DriverName__DRIVER_OBJECT:name;
+const unique T.HardwareDatabase__DRIVER_OBJECT:name;
+const unique T.FastIoDispatch__DRIVER_OBJECT:name;
+const unique T.DriverInit__DRIVER_OBJECT:name;
+const unique T.DriverStartIo__DRIVER_OBJECT:name;
+const unique T.DriverUnload__DRIVER_OBJECT:name;
+const unique T.MajorFunction__DRIVER_OBJECT:name;
+const unique T.SystemResourcesList__ERESOURCE:name;
+const unique T.OwnerTable__ERESOURCE:name;
+const unique T.ActiveCount__ERESOURCE:name;
+const unique T.Flag__ERESOURCE:name;
+const unique T.SharedWaiters__ERESOURCE:name;
+const unique T.ExclusiveWaiters__ERESOURCE:name;
+const unique T.OwnerEntry__ERESOURCE:name;
+const unique T.ActiveEntries__ERESOURCE:name;
+const unique T.ContentionCount__ERESOURCE:name;
+const unique T.NumberOfSharedWaiters__ERESOURCE:name;
+const unique T.NumberOfExclusiveWaiters__ERESOURCE:name;
+const unique T.__unnamed_4_52c594f7__ERESOURCE:name;
+const unique T.SpinLock__ERESOURCE:name;
+const unique T.SizeOfFastIoDispatch__FAST_IO_DISPATCH:name;
+const unique T.FastIoCheckIfPossible__FAST_IO_DISPATCH:name;
+const unique T.FastIoRead__FAST_IO_DISPATCH:name;
+const unique T.FastIoWrite__FAST_IO_DISPATCH:name;
+const unique T.FastIoQueryBasicInfo__FAST_IO_DISPATCH:name;
+const unique T.FastIoQueryStandardInfo__FAST_IO_DISPATCH:name;
+const unique T.FastIoLock__FAST_IO_DISPATCH:name;
+const unique T.FastIoUnlockSingle__FAST_IO_DISPATCH:name;
+const unique T.FastIoUnlockAll__FAST_IO_DISPATCH:name;
+const unique T.FastIoUnlockAllByKey__FAST_IO_DISPATCH:name;
+const unique T.FastIoDeviceControl__FAST_IO_DISPATCH:name;
+const unique T.AcquireFileForNtCreateSection__FAST_IO_DISPATCH:name;
+const unique T.ReleaseFileForNtCreateSection__FAST_IO_DISPATCH:name;
+const unique T.FastIoDetachDevice__FAST_IO_DISPATCH:name;
+const unique T.FastIoQueryNetworkOpenInfo__FAST_IO_DISPATCH:name;
+const unique T.AcquireForModWrite__FAST_IO_DISPATCH:name;
+const unique T.MdlRead__FAST_IO_DISPATCH:name;
+const unique T.MdlReadComplete__FAST_IO_DISPATCH:name;
+const unique T.PrepareMdlWrite__FAST_IO_DISPATCH:name;
+const unique T.MdlWriteComplete__FAST_IO_DISPATCH:name;
+const unique T.FastIoReadCompressed__FAST_IO_DISPATCH:name;
+const unique T.FastIoWriteCompressed__FAST_IO_DISPATCH:name;
+const unique T.MdlReadCompleteCompressed__FAST_IO_DISPATCH:name;
+const unique T.MdlWriteCompleteCompressed__FAST_IO_DISPATCH:name;
+const unique T.FastIoQueryOpen__FAST_IO_DISPATCH:name;
+const unique T.ReleaseForModWrite__FAST_IO_DISPATCH:name;
+const unique T.AcquireForCcFlush__FAST_IO_DISPATCH:name;
+const unique T.ReleaseForCcFlush__FAST_IO_DISPATCH:name;
+const unique T.Count__FAST_MUTEX:name;
+const unique T.Owner__FAST_MUTEX:name;
+const unique T.Contention__FAST_MUTEX:name;
+const unique T.Gate__FAST_MUTEX:name;
+const unique T.OldIrql__FAST_MUTEX:name;
+const unique T.CreationTime__FILE_BASIC_INFORMATION:name;
+const unique T.LastAccessTime__FILE_BASIC_INFORMATION:name;
+const unique T.LastWriteTime__FILE_BASIC_INFORMATION:name;
+const unique T.ChangeTime__FILE_BASIC_INFORMATION:name;
+const unique T.FileAttributes__FILE_BASIC_INFORMATION:name;
+const unique T.CreationTime__FILE_NETWORK_OPEN_INFORMATION:name;
+const unique T.LastAccessTime__FILE_NETWORK_OPEN_INFORMATION:name;
+const unique T.LastWriteTime__FILE_NETWORK_OPEN_INFORMATION:name;
+const unique T.ChangeTime__FILE_NETWORK_OPEN_INFORMATION:name;
+const unique T.AllocationSize__FILE_NETWORK_OPEN_INFORMATION:name;
+const unique T.EndOfFile__FILE_NETWORK_OPEN_INFORMATION:name;
+const unique T.FileAttributes__FILE_NETWORK_OPEN_INFORMATION:name;
+const unique T.Type__FILE_OBJECT:name;
+const unique T.Size__FILE_OBJECT:name;
+const unique T.DeviceObject__FILE_OBJECT:name;
+const unique T.Vpb__FILE_OBJECT:name;
+const unique T.FsContext__FILE_OBJECT:name;
+const unique T.FsContext2__FILE_OBJECT:name;
+const unique T.SectionObjectPointer__FILE_OBJECT:name;
+const unique T.PrivateCacheMap__FILE_OBJECT:name;
+const unique T.FinalStatus__FILE_OBJECT:name;
+const unique T.RelatedFileObject__FILE_OBJECT:name;
+const unique T.LockOperation__FILE_OBJECT:name;
+const unique T.DeletePending__FILE_OBJECT:name;
+const unique T.ReadAccess__FILE_OBJECT:name;
+const unique T.WriteAccess__FILE_OBJECT:name;
+const unique T.DeleteAccess__FILE_OBJECT:name;
+const unique T.SharedRead__FILE_OBJECT:name;
+const unique T.SharedWrite__FILE_OBJECT:name;
+const unique T.SharedDelete__FILE_OBJECT:name;
+const unique T.Flags__FILE_OBJECT:name;
+const unique T.FileName__FILE_OBJECT:name;
+const unique T.CurrentByteOffset__FILE_OBJECT:name;
+const unique T.Waiters__FILE_OBJECT:name;
+const unique T.Busy__FILE_OBJECT:name;
+const unique T.LastLock__FILE_OBJECT:name;
+const unique T.Lock__FILE_OBJECT:name;
+const unique T.Event__FILE_OBJECT:name;
+const unique T.CompletionContext__FILE_OBJECT:name;
+const unique T.IrpListLock__FILE_OBJECT:name;
+const unique T.IrpList__FILE_OBJECT:name;
+const unique T.FileObjectExtension__FILE_OBJECT:name;
+const unique T.AllocationSize__FILE_STANDARD_INFORMATION:name;
+const unique T.EndOfFile__FILE_STANDARD_INFORMATION:name;
+const unique T.NumberOfLinks__FILE_STANDARD_INFORMATION:name;
+const unique T.DeletePending__FILE_STANDARD_INFORMATION:name;
+const unique T.Directory__FILE_STANDARD_INFORMATION:name;
+const unique T.Debug__GLOBALS:name;
+const unique T.GrandMaster__GLOBALS:name;
+const unique T.AssocClassList__GLOBALS:name;
+const unique T.NumAssocClass__GLOBALS:name;
+const unique T.Opens__GLOBALS:name;
+const unique T.NumberLegacyPorts__GLOBALS:name;
+const unique T.Mutex__GLOBALS:name;
+const unique T.ConnectOneClassToOnePort__GLOBALS:name;
+const unique T.SendOutputToAllPorts__GLOBALS:name;
+const unique T.PortsServiced__GLOBALS:name;
+const unique T.InitExtension__GLOBALS:name;
+const unique T.RegistryPath__GLOBALS:name;
+const unique T.BaseClassName__GLOBALS:name;
+const unique T.BaseClassBuffer__GLOBALS:name;
+const unique T.LegacyDeviceList__GLOBALS:name;
+const unique T.Data1__GUID:name;
+const unique T.Data2__GUID:name;
+const unique T.Data3__GUID:name;
+const unique T.Data4__GUID:name;
+const unique T.PrivilegeCount__INITIAL_PRIVILEGE_SET:name;
+const unique T.Control__INITIAL_PRIVILEGE_SET:name;
+const unique T.Privilege__INITIAL_PRIVILEGE_SET:name;
+const unique T.Size__INTERFACE:name;
+const unique T.Version__INTERFACE:name;
+const unique T.Context__INTERFACE:name;
+const unique T.InterfaceReference__INTERFACE:name;
+const unique T.InterfaceDereference__INTERFACE:name;
+const unique T.Port__IO_COMPLETION_CONTEXT:name;
+const unique T.Key__IO_COMPLETION_CONTEXT:name;
+const unique T.Common__IO_REMOVE_LOCK:name;
+const unique T.Dbg__IO_REMOVE_LOCK:name;
+const unique T.Removed__IO_REMOVE_LOCK_COMMON_BLOCK:name;
+const unique T.Reserved__IO_REMOVE_LOCK_COMMON_BLOCK:name;
+const unique T.IoCount__IO_REMOVE_LOCK_COMMON_BLOCK:name;
+const unique T.RemoveEvent__IO_REMOVE_LOCK_COMMON_BLOCK:name;
+const unique T.Signature__IO_REMOVE_LOCK_DBG_BLOCK:name;
+const unique T.HighWatermark__IO_REMOVE_LOCK_DBG_BLOCK:name;
+const unique T.MaxLockedTicks__IO_REMOVE_LOCK_DBG_BLOCK:name;
+const unique T.AllocateTag__IO_REMOVE_LOCK_DBG_BLOCK:name;
+const unique T.LockList__IO_REMOVE_LOCK_DBG_BLOCK:name;
+const unique T.Spin__IO_REMOVE_LOCK_DBG_BLOCK:name;
+const unique T.LowMemoryCount__IO_REMOVE_LOCK_DBG_BLOCK:name;
+const unique T.Reserved1__IO_REMOVE_LOCK_DBG_BLOCK:name;
+const unique T.Reserved2__IO_REMOVE_LOCK_DBG_BLOCK:name;
+const unique T.Blocks__IO_REMOVE_LOCK_DBG_BLOCK:name;
+const unique T.Option__IO_RESOURCE_DESCRIPTOR:name;
+const unique T.Type__IO_RESOURCE_DESCRIPTOR:name;
+const unique T.ShareDisposition__IO_RESOURCE_DESCRIPTOR:name;
+const unique T.Spare1__IO_RESOURCE_DESCRIPTOR:name;
+const unique T.Flags__IO_RESOURCE_DESCRIPTOR:name;
+const unique T.Spare2__IO_RESOURCE_DESCRIPTOR:name;
+const unique T.u__IO_RESOURCE_DESCRIPTOR:name;
+const unique T.Version__IO_RESOURCE_LIST:name;
+const unique T.Revision__IO_RESOURCE_LIST:name;
+const unique T.Count__IO_RESOURCE_LIST:name;
+const unique T.Descriptors__IO_RESOURCE_LIST:name;
+const unique T.ListSize__IO_RESOURCE_REQUIREMENTS_LIST:name;
+const unique T.InterfaceType__IO_RESOURCE_REQUIREMENTS_LIST:name;
+const unique T.BusNumber__IO_RESOURCE_REQUIREMENTS_LIST:name;
+const unique T.SlotNumber__IO_RESOURCE_REQUIREMENTS_LIST:name;
+const unique T.Reserved__IO_RESOURCE_REQUIREMENTS_LIST:name;
+const unique T.AlternativeLists__IO_RESOURCE_REQUIREMENTS_LIST:name;
+const unique T.List__IO_RESOURCE_REQUIREMENTS_LIST:name;
+const unique T.SecurityQos__IO_SECURITY_CONTEXT:name;
+const unique T.AccessState__IO_SECURITY_CONTEXT:name;
+const unique T.DesiredAccess__IO_SECURITY_CONTEXT:name;
+const unique T.FullCreateOptions__IO_SECURITY_CONTEXT:name;
+const unique T.MajorFunction__IO_STACK_LOCATION:name;
+const unique T.MinorFunction__IO_STACK_LOCATION:name;
+const unique T.Flags__IO_STACK_LOCATION:name;
+const unique T.Control__IO_STACK_LOCATION:name;
+const unique T.Parameters__IO_STACK_LOCATION:name;
+const unique T.DeviceObject__IO_STACK_LOCATION:name;
+const unique T.FileObject__IO_STACK_LOCATION:name;
+const unique T.CompletionRoutine__IO_STACK_LOCATION:name;
+const unique T.Context__IO_STACK_LOCATION:name;
+const unique T.__unnamed_4_d99b6e2b__IO_STATUS_BLOCK:name;
+const unique T.Information__IO_STATUS_BLOCK:name;
+const unique T.Type__IRP:name;
+const unique T.Size__IRP:name;
+const unique T.MdlAddress__IRP:name;
+const unique T.Flags__IRP:name;
+const unique T.AssociatedIrp__IRP:name;
+const unique T.ThreadListEntry__IRP:name;
+const unique T.IoStatus__IRP:name;
+const unique T.RequestorMode__IRP:name;
+const unique T.PendingReturned__IRP:name;
+const unique T.StackCount__IRP:name;
+const unique T.CurrentLocation__IRP:name;
+const unique T.Cancel__IRP:name;
+const unique T.CancelIrql__IRP:name;
+const unique T.ApcEnvironment__IRP:name;
+const unique T.AllocationFlags__IRP:name;
+const unique T.UserIosb__IRP:name;
+const unique T.UserEvent__IRP:name;
+const unique T.Overlay__IRP:name;
+const unique T.CancelRoutine__IRP:name;
+const unique T.UserBuffer__IRP:name;
+const unique T.Tail__IRP:name;
+const unique T.Type__KAPC:name;
+const unique T.SpareByte0__KAPC:name;
+const unique T.Size__KAPC:name;
+const unique T.SpareByte1__KAPC:name;
+const unique T.SpareLong0__KAPC:name;
+const unique T.Thread__KAPC:name;
+const unique T.ApcListEntry__KAPC:name;
+const unique T.KernelRoutine__KAPC:name;
+const unique T.RundownRoutine__KAPC:name;
+const unique T.NormalRoutine__KAPC:name;
+const unique T.NormalContext__KAPC:name;
+const unique T.SystemArgument1__KAPC:name;
+const unique T.SystemArgument2__KAPC:name;
+const unique T.ApcStateIndex__KAPC:name;
+const unique T.ApcMode__KAPC:name;
+const unique T.Inserted__KAPC:name;
+const unique T.Type__KDEVICE_QUEUE:name;
+const unique T.Size__KDEVICE_QUEUE:name;
+const unique T.DeviceListHead__KDEVICE_QUEUE:name;
+const unique T.Lock__KDEVICE_QUEUE:name;
+const unique T.Busy__KDEVICE_QUEUE:name;
+const unique T.DeviceListEntry__KDEVICE_QUEUE_ENTRY:name;
+const unique T.SortKey__KDEVICE_QUEUE_ENTRY:name;
+const unique T.Inserted__KDEVICE_QUEUE_ENTRY:name;
+const unique T.Type__KDPC:name;
+const unique T.Importance__KDPC:name;
+const unique T.Number__KDPC:name;
+const unique T.DpcListEntry__KDPC:name;
+const unique T.DeferredRoutine__KDPC:name;
+const unique T.DeferredContext__KDPC:name;
+const unique T.SystemArgument1__KDPC:name;
+const unique T.SystemArgument2__KDPC:name;
+const unique T.DpcData__KDPC:name;
+const unique T.Header__KEVENT:name;
+const unique T.KeyboardIdentifier__KEYBOARD_ATTRIBUTES:name;
+const unique T.KeyboardMode__KEYBOARD_ATTRIBUTES:name;
+const unique T.NumberOfFunctionKeys__KEYBOARD_ATTRIBUTES:name;
+const unique T.NumberOfIndicators__KEYBOARD_ATTRIBUTES:name;
+const unique T.NumberOfKeysTotal__KEYBOARD_ATTRIBUTES:name;
+const unique T.InputDataQueueLength__KEYBOARD_ATTRIBUTES:name;
+const unique T.KeyRepeatMinimum__KEYBOARD_ATTRIBUTES:name;
+const unique T.KeyRepeatMaximum__KEYBOARD_ATTRIBUTES:name;
+const unique T.Type__KEYBOARD_ID:name;
+const unique T.Subtype__KEYBOARD_ID:name;
+const unique T.UnitId__KEYBOARD_INDICATOR_PARAMETERS:name;
+const unique T.LedFlags__KEYBOARD_INDICATOR_PARAMETERS:name;
+const unique T.UnitId__KEYBOARD_INPUT_DATA:name;
+const unique T.MakeCode__KEYBOARD_INPUT_DATA:name;
+const unique T.Flags__KEYBOARD_INPUT_DATA:name;
+const unique T.Reserved__KEYBOARD_INPUT_DATA:name;
+const unique T.ExtraInformation__KEYBOARD_INPUT_DATA:name;
+const unique T.UnitId__KEYBOARD_TYPEMATIC_PARAMETERS:name;
+const unique T.Rate__KEYBOARD_TYPEMATIC_PARAMETERS:name;
+const unique T.Delay__KEYBOARD_TYPEMATIC_PARAMETERS:name;
+const unique T.Header__KSEMAPHORE:name;
+const unique T.Limit__KSEMAPHORE:name;
+const unique T.__unnamed_8_58ee4a31__LARGE_INTEGER:name;
+const unique T.u__LARGE_INTEGER:name;
+const unique T.QuadPart__LARGE_INTEGER:name;
+const unique T.Flink__LIST_ENTRY:name;
+const unique T.Blink__LIST_ENTRY:name;
+const unique T.LowPart__LUID:name;
+const unique T.HighPart__LUID:name;
+const unique T.Luid__LUID_AND_ATTRIBUTES:name;
+const unique T.Attributes__LUID_AND_ATTRIBUTES:name;
+const unique T.Next__MDL:name;
+const unique T.Size__MDL:name;
+const unique T.MdlFlags__MDL:name;
+const unique T.Process__MDL:name;
+const unique T.MappedSystemVa__MDL:name;
+const unique T.StartVa__MDL:name;
+const unique T.ByteCount__MDL:name;
+const unique T.ByteOffset__MDL:name;
+const unique T.OwnerThread__OWNER_ENTRY:name;
+const unique T.__unnamed_4_6f9ac8e1__OWNER_ENTRY:name;
+const unique T.File__PORT:name;
+const unique T.Port__PORT:name;
+const unique T.Enabled__PORT:name;
+const unique T.Reserved__PORT:name;
+const unique T.Free__PORT:name;
+const unique T.SequenceD1__POWER_SEQUENCE:name;
+const unique T.SequenceD2__POWER_SEQUENCE:name;
+const unique T.SequenceD3__POWER_SEQUENCE:name;
+const unique T.SystemState__POWER_STATE:name;
+const unique T.DeviceState__POWER_STATE:name;
+const unique T.PrivilegeCount__PRIVILEGE_SET:name;
+const unique T.Control__PRIVILEGE_SET:name;
+const unique T.Privilege__PRIVILEGE_SET:name;
+const unique T.DataSectionObject__SECTION_OBJECT_POINTERS:name;
+const unique T.SharedCacheMap__SECTION_OBJECT_POINTERS:name;
+const unique T.ImageSectionObject__SECTION_OBJECT_POINTERS:name;
+const unique T.Length__SECURITY_QUALITY_OF_SERVICE:name;
+const unique T.ImpersonationLevel__SECURITY_QUALITY_OF_SERVICE:name;
+const unique T.ContextTrackingMode__SECURITY_QUALITY_OF_SERVICE:name;
+const unique T.EffectiveOnly__SECURITY_QUALITY_OF_SERVICE:name;
+const unique T.ClientToken__SECURITY_SUBJECT_CONTEXT:name;
+const unique T.ImpersonationLevel__SECURITY_SUBJECT_CONTEXT:name;
+const unique T.PrimaryToken__SECURITY_SUBJECT_CONTEXT:name;
+const unique T.ProcessAuditId__SECURITY_SUBJECT_CONTEXT:name;
+const unique T.__unnamed_4_3a2fdc5e__SYSTEM_POWER_STATE_CONTEXT:name;
+const unique T.Length__UNICODE_STRING:name;
+const unique T.MaximumLength__UNICODE_STRING:name;
+const unique T.Buffer__UNICODE_STRING:name;
+const unique T.Type__VPB:name;
+const unique T.Size__VPB:name;
+const unique T.Flags__VPB:name;
+const unique T.VolumeLabelLength__VPB:name;
+const unique T.DeviceObject__VPB:name;
+const unique T.RealDevice__VPB:name;
+const unique T.SerialNumber__VPB:name;
+const unique T.ReferenceCount__VPB:name;
+const unique T.VolumeLabel__VPB:name;
+const unique T.WaitQueueEntry__WAIT_CONTEXT_BLOCK:name;
+const unique T.DeviceRoutine__WAIT_CONTEXT_BLOCK:name;
+const unique T.DeviceContext__WAIT_CONTEXT_BLOCK:name;
+const unique T.NumberOfMapRegisters__WAIT_CONTEXT_BLOCK:name;
+const unique T.DeviceObject__WAIT_CONTEXT_BLOCK:name;
+const unique T.CurrentIrp__WAIT_CONTEXT_BLOCK:name;
+const unique T.BufferChainingDpc__WAIT_CONTEXT_BLOCK:name;
+const unique T.GuidCount__WMILIB_CONTEXT:name;
+const unique T.GuidList__WMILIB_CONTEXT:name;
+const unique T.QueryWmiRegInfo__WMILIB_CONTEXT:name;
+const unique T.QueryWmiDataBlock__WMILIB_CONTEXT:name;
+const unique T.SetWmiDataBlock__WMILIB_CONTEXT:name;
+const unique T.SetWmiDataItem__WMILIB_CONTEXT:name;
+const unique T.ExecuteWmiMethod__WMILIB_CONTEXT:name;
+const unique T.WmiFunctionControl__WMILIB_CONTEXT:name;
+const unique T.Reserved___unnamed_12_0d6a30de:name;
+const unique T.MessageCount___unnamed_12_0d6a30de:name;
+const unique T.Vector___unnamed_12_0d6a30de:name;
+const unique T.Affinity___unnamed_12_0d6a30de:name;
+const unique T.Start___unnamed_12_17f5c211:name;
+const unique T.Length48___unnamed_12_17f5c211:name;
+const unique T.Start___unnamed_12_1fb42e39:name;
+const unique T.Length___unnamed_12_1fb42e39:name;
+const unique T.Reserved___unnamed_12_1fb42e39:name;
+const unique T.Start___unnamed_12_2a1563c6:name;
+const unique T.Length___unnamed_12_2a1563c6:name;
+const unique T.DataSize___unnamed_12_31347272:name;
+const unique T.Reserved1___unnamed_12_31347272:name;
+const unique T.Reserved2___unnamed_12_31347272:name;
+const unique T.Raw___unnamed_12_429aadc0:name;
+const unique T.Translated___unnamed_12_429aadc0:name;
+const unique T.Start___unnamed_12_4719de1a:name;
+const unique T.Length___unnamed_12_4719de1a:name;
+const unique T.Data___unnamed_12_4be56faa:name;
+const unique T.Data___unnamed_12_5ce25b92:name;
+const unique T.Generic___unnamed_12_7a698b72:name;
+const unique T.Port___unnamed_12_7a698b72:name;
+const unique T.Interrupt___unnamed_12_7a698b72:name;
+const unique T.MessageInterrupt___unnamed_12_7a698b72:name;
+const unique T.Memory___unnamed_12_7a698b72:name;
+const unique T.Dma___unnamed_12_7a698b72:name;
+const unique T.DevicePrivate___unnamed_12_7a698b72:name;
+const unique T.BusNumber___unnamed_12_7a698b72:name;
+const unique T.DeviceSpecificData___unnamed_12_7a698b72:name;
+const unique T.Memory40___unnamed_12_7a698b72:name;
+const unique T.Memory48___unnamed_12_7a698b72:name;
+const unique T.Memory64___unnamed_12_7a698b72:name;
+const unique T.Start___unnamed_12_87c0de8d:name;
+const unique T.Length64___unnamed_12_87c0de8d:name;
+const unique T.Start___unnamed_12_98bfc55a:name;
+const unique T.Length40___unnamed_12_98bfc55a:name;
+const unique T.Priority___unnamed_12_ab1bd9d7:name;
+const unique T.Reserved1___unnamed_12_ab1bd9d7:name;
+const unique T.Reserved2___unnamed_12_ab1bd9d7:name;
+const unique T.Level___unnamed_12_b0429be9:name;
+const unique T.Vector___unnamed_12_b0429be9:name;
+const unique T.Affinity___unnamed_12_b0429be9:name;
+const unique T.ListEntry___unnamed_12_b43e8de8:name;
+const unique T.__unnamed_4_f19b65c1___unnamed_12_b43e8de8:name;
+const unique T.Level___unnamed_12_bfdb39ee:name;
+const unique T.Vector___unnamed_12_bfdb39ee:name;
+const unique T.Affinity___unnamed_12_bfdb39ee:name;
+const unique T.Start___unnamed_12_cd42b3c3:name;
+const unique T.Length___unnamed_12_cd42b3c3:name;
+const unique T.__unnamed_12_429aadc0___unnamed_12_e668effc:name;
+const unique T.Channel___unnamed_12_e80d029e:name;
+const unique T.Port___unnamed_12_e80d029e:name;
+const unique T.Reserved1___unnamed_12_e80d029e:name;
+const unique T.Length___unnamed_16_07c0bcc5:name;
+const unique T.MinBusNumber___unnamed_16_07c0bcc5:name;
+const unique T.MaxBusNumber___unnamed_16_07c0bcc5:name;
+const unique T.Reserved___unnamed_16_07c0bcc5:name;
+const unique T.InterfaceType___unnamed_16_29cb9f2f:name;
+const unique T.Size___unnamed_16_29cb9f2f:name;
+const unique T.Version___unnamed_16_29cb9f2f:name;
+const unique T.Interface___unnamed_16_29cb9f2f:name;
+const unique T.InterfaceSpecificData___unnamed_16_29cb9f2f:name;
+const unique T.SecurityContext___unnamed_16_30f11dbf:name;
+const unique T.Options___unnamed_16_30f11dbf:name;
+const unique T.FileAttributes___unnamed_16_30f11dbf:name;
+const unique T.ShareAccess___unnamed_16_30f11dbf:name;
+const unique T.EaLength___unnamed_16_30f11dbf:name;
+const unique T.DriverContext___unnamed_16_35034f68:name;
+const unique T.Length___unnamed_16_487a9498:name;
+const unique T.FileName___unnamed_16_487a9498:name;
+const unique T.FileInformationClass___unnamed_16_487a9498:name;
+const unique T.FileIndex___unnamed_16_487a9498:name;
+const unique T.OutputBufferLength___unnamed_16_5f6a8844:name;
+const unique T.InputBufferLength___unnamed_16_5f6a8844:name;
+const unique T.FsControlCode___unnamed_16_5f6a8844:name;
+const unique T.Type3InputBuffer___unnamed_16_5f6a8844:name;
+const unique T.Length___unnamed_16_7177b9f3:name;
+const unique T.FileInformationClass___unnamed_16_7177b9f3:name;
+const unique T.FileObject___unnamed_16_7177b9f3:name;
+const unique T.__unnamed_4_43913aa5___unnamed_16_7177b9f3:name;
+const unique T.Length___unnamed_16_88e91ef6:name;
+const unique T.Key___unnamed_16_88e91ef6:name;
+const unique T.ByteOffset___unnamed_16_88e91ef6:name;
+const unique T.Length___unnamed_16_8c506c98:name;
+const unique T.Key___unnamed_16_8c506c98:name;
+const unique T.ByteOffset___unnamed_16_8c506c98:name;
+const unique T.WhichSpace___unnamed_16_9ac2e5f8:name;
+const unique T.Buffer___unnamed_16_9ac2e5f8:name;
+const unique T.Offset___unnamed_16_9ac2e5f8:name;
+const unique T.Length___unnamed_16_9ac2e5f8:name;
+const unique T.Create___unnamed_16_b93842ad:name;
+const unique T.Read___unnamed_16_b93842ad:name;
+const unique T.Write___unnamed_16_b93842ad:name;
+const unique T.QueryDirectory___unnamed_16_b93842ad:name;
+const unique T.NotifyDirectory___unnamed_16_b93842ad:name;
+const unique T.QueryFile___unnamed_16_b93842ad:name;
+const unique T.SetFile___unnamed_16_b93842ad:name;
+const unique T.QueryEa___unnamed_16_b93842ad:name;
+const unique T.SetEa___unnamed_16_b93842ad:name;
+const unique T.QueryVolume___unnamed_16_b93842ad:name;
+const unique T.SetVolume___unnamed_16_b93842ad:name;
+const unique T.FileSystemControl___unnamed_16_b93842ad:name;
+const unique T.LockControl___unnamed_16_b93842ad:name;
+const unique T.DeviceIoControl___unnamed_16_b93842ad:name;
+const unique T.QuerySecurity___unnamed_16_b93842ad:name;
+const unique T.SetSecurity___unnamed_16_b93842ad:name;
+const unique T.MountVolume___unnamed_16_b93842ad:name;
+const unique T.VerifyVolume___unnamed_16_b93842ad:name;
+const unique T.Scsi___unnamed_16_b93842ad:name;
+const unique T.QueryQuota___unnamed_16_b93842ad:name;
+const unique T.SetQuota___unnamed_16_b93842ad:name;
+const unique T.QueryDeviceRelations___unnamed_16_b93842ad:name;
+const unique T.QueryInterface___unnamed_16_b93842ad:name;
+const unique T.DeviceCapabilities___unnamed_16_b93842ad:name;
+const unique T.FilterResourceRequirements___unnamed_16_b93842ad:name;
+const unique T.ReadWriteConfig___unnamed_16_b93842ad:name;
+const unique T.SetLock___unnamed_16_b93842ad:name;
+const unique T.QueryId___unnamed_16_b93842ad:name;
+const unique T.QueryDeviceText___unnamed_16_b93842ad:name;
+const unique T.UsageNotification___unnamed_16_b93842ad:name;
+const unique T.WaitWake___unnamed_16_b93842ad:name;
+const unique T.PowerSequence___unnamed_16_b93842ad:name;
+const unique T.Power___unnamed_16_b93842ad:name;
+const unique T.StartDevice___unnamed_16_b93842ad:name;
+const unique T.WMI___unnamed_16_b93842ad:name;
+const unique T.Others___unnamed_16_b93842ad:name;
+const unique T.Length___unnamed_16_b9c62eab:name;
+const unique T.Key___unnamed_16_b9c62eab:name;
+const unique T.ByteOffset___unnamed_16_b9c62eab:name;
+const unique T.__unnamed_4_7d9d0c7e___unnamed_16_bb584060:name;
+const unique T.Type___unnamed_16_bb584060:name;
+const unique T.State___unnamed_16_bb584060:name;
+const unique T.ShutdownType___unnamed_16_bb584060:name;
+const unique T.OutputBufferLength___unnamed_16_dba55c7c:name;
+const unique T.InputBufferLength___unnamed_16_dba55c7c:name;
+const unique T.IoControlCode___unnamed_16_dba55c7c:name;
+const unique T.Type3InputBuffer___unnamed_16_dba55c7c:name;
+const unique T.DeviceQueueEntry___unnamed_16_e70c268b:name;
+const unique T.__unnamed_16_35034f68___unnamed_16_e70c268b:name;
+const unique T.Argument1___unnamed_16_e734d694:name;
+const unique T.Argument2___unnamed_16_e734d694:name;
+const unique T.Argument3___unnamed_16_e734d694:name;
+const unique T.Argument4___unnamed_16_e734d694:name;
+const unique T.ProviderId___unnamed_16_eac6dbea:name;
+const unique T.DataPath___unnamed_16_eac6dbea:name;
+const unique T.BufferSize___unnamed_16_eac6dbea:name;
+const unique T.Buffer___unnamed_16_eac6dbea:name;
+const unique T.Length___unnamed_16_f6cae4c2:name;
+const unique T.EaList___unnamed_16_f6cae4c2:name;
+const unique T.EaListLength___unnamed_16_f6cae4c2:name;
+const unique T.EaIndex___unnamed_16_f6cae4c2:name;
+const unique T.Length___unnamed_16_fe36e4f4:name;
+const unique T.StartSid___unnamed_16_fe36e4f4:name;
+const unique T.SidList___unnamed_16_fe36e4f4:name;
+const unique T.SidListLength___unnamed_16_fe36e4f4:name;
+const unique T.Abandoned___unnamed_1_29794256:name;
+const unique T.Absolute___unnamed_1_29794256:name;
+const unique T.NpxIrql___unnamed_1_29794256:name;
+const unique T.Signalling___unnamed_1_29794256:name;
+const unique T.Inserted___unnamed_1_2dc63b48:name;
+const unique T.DebugActive___unnamed_1_2dc63b48:name;
+const unique T.DpcActive___unnamed_1_2dc63b48:name;
+const unique T.Size___unnamed_1_2ef8da39:name;
+const unique T.Hand___unnamed_1_2ef8da39:name;
+const unique T.Lock___unnamed_1_faa7dc71:name;
+const unique T.MinimumVector___unnamed_20_f4d2e6d8:name;
+const unique T.MaximumVector___unnamed_20_f4d2e6d8:name;
+const unique T.AffinityPolicy___unnamed_20_f4d2e6d8:name;
+const unique T.PriorityPolicy___unnamed_20_f4d2e6d8:name;
+const unique T.TargetedProcessors___unnamed_20_f4d2e6d8:name;
+const unique T.Length___unnamed_24_41cbc8c0:name;
+const unique T.Alignment___unnamed_24_41cbc8c0:name;
+const unique T.MinimumAddress___unnamed_24_41cbc8c0:name;
+const unique T.MaximumAddress___unnamed_24_41cbc8c0:name;
+const unique T.Length48___unnamed_24_5419c914:name;
+const unique T.Alignment48___unnamed_24_5419c914:name;
+const unique T.MinimumAddress___unnamed_24_5419c914:name;
+const unique T.MaximumAddress___unnamed_24_5419c914:name;
+const unique T.Length___unnamed_24_67a5ff10:name;
+const unique T.Alignment___unnamed_24_67a5ff10:name;
+const unique T.MinimumAddress___unnamed_24_67a5ff10:name;
+const unique T.MaximumAddress___unnamed_24_67a5ff10:name;
+const unique T.Port___unnamed_24_72c3976e:name;
+const unique T.Memory___unnamed_24_72c3976e:name;
+const unique T.Interrupt___unnamed_24_72c3976e:name;
+const unique T.Dma___unnamed_24_72c3976e:name;
+const unique T.Generic___unnamed_24_72c3976e:name;
+const unique T.DevicePrivate___unnamed_24_72c3976e:name;
+const unique T.BusNumber___unnamed_24_72c3976e:name;
+const unique T.ConfigData___unnamed_24_72c3976e:name;
+const unique T.Memory40___unnamed_24_72c3976e:name;
+const unique T.Memory48___unnamed_24_72c3976e:name;
+const unique T.Memory64___unnamed_24_72c3976e:name;
+const unique T.Length64___unnamed_24_a26050bb:name;
+const unique T.Alignment64___unnamed_24_a26050bb:name;
+const unique T.MinimumAddress___unnamed_24_a26050bb:name;
+const unique T.MaximumAddress___unnamed_24_a26050bb:name;
+const unique T.Length___unnamed_24_b8f476db:name;
+const unique T.Alignment___unnamed_24_b8f476db:name;
+const unique T.MinimumAddress___unnamed_24_b8f476db:name;
+const unique T.MaximumAddress___unnamed_24_b8f476db:name;
+const unique T.Length40___unnamed_24_d09044b4:name;
+const unique T.Alignment40___unnamed_24_d09044b4:name;
+const unique T.MinimumAddress___unnamed_24_d09044b4:name;
+const unique T.MaximumAddress___unnamed_24_d09044b4:name;
+const unique T.ReplaceIfExists___unnamed_2_46cc4597:name;
+const unique T.AdvanceOnly___unnamed_2_46cc4597:name;
+const unique T.__unnamed_16_e70c268b___unnamed_40_7218f704:name;
+const unique T.Thread___unnamed_40_7218f704:name;
+const unique T.AuxiliaryBuffer___unnamed_40_7218f704:name;
+const unique T.__unnamed_12_b43e8de8___unnamed_40_7218f704:name;
+const unique T.OriginalFileObject___unnamed_40_7218f704:name;
+const unique T.ListEntry___unnamed_40_c55c9377:name;
+const unique T.Wcb___unnamed_40_c55c9377:name;
+const unique T.InitialPrivilegeSet___unnamed_44_5584090d:name;
+const unique T.PrivilegeSet___unnamed_44_5584090d:name;
+const unique T.Overlay___unnamed_48_cf99b13f:name;
+const unique T.Apc___unnamed_48_cf99b13f:name;
+const unique T.CompletionKey___unnamed_48_cf99b13f:name;
+const unique T.PowerState___unnamed_4_069846fb:name;
+const unique T.IdType___unnamed_4_224c32f4:name;
+const unique T.Capabilities___unnamed_4_2de698da:name;
+const unique T.__unnamed_4_c3479730___unnamed_4_3a2fdc5e:name;
+const unique T.ContextAsUlong___unnamed_4_3a2fdc5e:name;
+const unique T.Length___unnamed_4_3a4c1a13:name;
+const unique T.__unnamed_2_46cc4597___unnamed_4_43913aa5:name;
+const unique T.ClusterCount___unnamed_4_43913aa5:name;
+const unique T.DeleteHandle___unnamed_4_43913aa5:name;
+const unique T.UserApcRoutine___unnamed_4_4e8dd2ba:name;
+const unique T.IssuingProcess___unnamed_4_4e8dd2ba:name;
+const unique T.Srb___unnamed_4_52603077:name;
+const unique T.Address___unnamed_4_52c594f7:name;
+const unique T.CreatorBackTraceIndex___unnamed_4_52c594f7:name;
+const unique T.Type___unnamed_4_5ca00198:name;
+const unique T.__unnamed_1_29794256___unnamed_4_5ca00198:name;
+const unique T.__unnamed_1_2ef8da39___unnamed_4_5ca00198:name;
+const unique T.__unnamed_1_2dc63b48___unnamed_4_5ca00198:name;
+const unique T.MasterIrp___unnamed_4_6ac6463c:name;
+const unique T.IrpCount___unnamed_4_6ac6463c:name;
+const unique T.SystemBuffer___unnamed_4_6ac6463c:name;
+const unique T.OwnerCount___unnamed_4_6f9ac8e1:name;
+const unique T.TableSize___unnamed_4_6f9ac8e1:name;
+const unique T.PowerSequence___unnamed_4_7a02167b:name;
+const unique T.SystemContext___unnamed_4_7d9d0c7e:name;
+const unique T.SystemPowerStateContext___unnamed_4_7d9d0c7e:name;
+const unique T.IoResourceRequirementList___unnamed_4_82f7a864:name;
+const unique T.Length___unnamed_4_9aec220b:name;
+const unique T.__unnamed_4_5ca00198___unnamed_4_a97c65a1:name;
+const unique T.Lock___unnamed_4_a97c65a1:name;
+const unique T.Reserved1___unnamed_4_c3479730:name;
+const unique T.TargetSystemState___unnamed_4_c3479730:name;
+const unique T.EffectiveSystemState___unnamed_4_c3479730:name;
+const unique T.CurrentSystemState___unnamed_4_c3479730:name;
+const unique T.IgnoreHibernationPath___unnamed_4_c3479730:name;
+const unique T.PseudoTransition___unnamed_4_c3479730:name;
+const unique T.Reserved2___unnamed_4_c3479730:name;
+const unique T.Status___unnamed_4_d99b6e2b:name;
+const unique T.Pointer___unnamed_4_d99b6e2b:name;
+const unique T.CurrentStackLocation___unnamed_4_f19b65c1:name;
+const unique T.PacketType___unnamed_4_f19b65c1:name;
+const unique T.Type___unnamed_4_fa10fc16:name;
+const unique T.SecurityInformation___unnamed_8_01efa60d:name;
+const unique T.Length___unnamed_8_01efa60d:name;
+const unique T.MinimumChannel___unnamed_8_08d4cef8:name;
+const unique T.MaximumChannel___unnamed_8_08d4cef8:name;
+const unique T.__unnamed_4_4e8dd2ba___unnamed_8_0a898c0c:name;
+const unique T.UserApcContext___unnamed_8_0a898c0c:name;
+const unique T.SecurityInformation___unnamed_8_1330f93a:name;
+const unique T.SecurityDescriptor___unnamed_8_1330f93a:name;
+const unique T.AsynchronousParameters___unnamed_8_181d0de9:name;
+const unique T.AllocationSize___unnamed_8_181d0de9:name;
+const unique T.Vpb___unnamed_8_4812764d:name;
+const unique T.DeviceObject___unnamed_8_4812764d:name;
+const unique T.Length___unnamed_8_559a91e6:name;
+const unique T.FsInformationClass___unnamed_8_559a91e6:name;
+const unique T.Length___unnamed_8_5845b309:name;
+const unique T.FileInformationClass___unnamed_8_5845b309:name;
+const unique T.LowPart___unnamed_8_58ee4a31:name;
+const unique T.HighPart___unnamed_8_58ee4a31:name;
+const unique T.AllocatedResources___unnamed_8_61acf4ce:name;
+const unique T.AllocatedResourcesTranslated___unnamed_8_61acf4ce:name;
+const unique T.DeviceTextType___unnamed_8_6acfee04:name;
+const unique T.LocaleId___unnamed_8_6acfee04:name;
+const unique T.Length___unnamed_8_7f26a9dd:name;
+const unique T.CompletionFilter___unnamed_8_7f26a9dd:name;
+const unique T.Vpb___unnamed_8_87add0bd:name;
+const unique T.DeviceObject___unnamed_8_87add0bd:name;
+const unique T.InPath___unnamed_8_b2773e4c:name;
+const unique T.Reserved___unnamed_8_b2773e4c:name;
+const unique T.Type___unnamed_8_b2773e4c:name;
+const unique T.Length___unnamed_8_de890d4e:name;
+const unique T.FsInformationClass___unnamed_8_de890d4e:name;
+const unique T.LowPart___unnamed_8_ef9ba0d3:name;
+const unique T.HighPart___unnamed_8_ef9ba0d3:name;
+
+// Type declarations
+
+const unique T.A1_CM_FULL_RESOURCE_DESCRIPTOR:name;
+const unique T.A1_CM_PARTIAL_RESOURCE_DESCRIPTOR:name;
+const unique T.A1_IO_RESOURCE_DESCRIPTOR:name;
+const unique T.A1_IO_RESOURCE_LIST:name;
+const unique T.A1_LUID_AND_ATTRIBUTES:name;
+const unique T.A256UINT2:name;
+const unique T.A28PFDRIVER_DISPATCH:name;
+const unique T.A2UCHAR:name;
+const unique T.A2UINT2:name;
+const unique T.A32UINT2:name;
+const unique T.A37CHAR:name;
+const unique T.A3UCHAR:name;
+const unique T.A3UINT4:name;
+const unique T.A3_LUID_AND_ATTRIBUTES:name;
+const unique T.A40CHAR:name;
+const unique T.A4PVOID:name;
+const unique T.A4UINT4:name;
+const unique T.A5_DEVICE_POWER_STATE:name;
+const unique T.A65CHAR:name;
+const unique T.A75CHAR:name;
+const unique T.A76CHAR:name;
+const unique T.A7UINT2:name;
+const unique T.A7_DEVICE_POWER_STATE:name;
+const unique T.A83CHAR:name;
+const unique T.A8UCHAR:name;
+const unique T.A9UINT2:name;
+const unique T.BUS_QUERY_ID_TYPE:name;
+const unique T.CHAR:name;
+const unique T.DEVICE_TEXT_TYPE:name;
+const unique T.F0:name;
+const unique T.F1:name;
+const unique T.F10:name;
+const unique T.F11:name;
+const unique T.F12:name;
+const unique T.F13:name;
+const unique T.F14:name;
+const unique T.F15:name;
+const unique T.F16:name;
+const unique T.F17:name;
+const unique T.F18:name;
+const unique T.F19:name;
+const unique T.F2:name;
+const unique T.F20:name;
+const unique T.F21:name;
+const unique T.F22:name;
+const unique T.F23:name;
+const unique T.F24:name;
+const unique T.F25:name;
+const unique T.F26:name;
+const unique T.F27:name;
+const unique T.F28:name;
+const unique T.F29:name;
+const unique T.F3:name;
+const unique T.F30:name;
+const unique T.F31:name;
+const unique T.F32:name;
+const unique T.F33:name;
+const unique T.F34:name;
+const unique T.F35:name;
+const unique T.F36:name;
+const unique T.F37:name;
+const unique T.F38:name;
+const unique T.F4:name;
+const unique T.F5:name;
+const unique T.F6:name;
+const unique T.F7:name;
+const unique T.F8:name;
+const unique T.F9:name;
+const unique T.FDRIVER_ADD_DEVICE:name;
+const unique T.FDRIVER_CANCEL:name;
+const unique T.FDRIVER_CONTROL:name;
+const unique T.FDRIVER_DISPATCH:name;
+const unique T.FDRIVER_INITIALIZE:name;
+const unique T.FDRIVER_STARTIO:name;
+const unique T.FDRIVER_UNLOAD:name;
+const unique T.FFAST_IO_ACQUIRE_FILE:name;
+const unique T.FFAST_IO_ACQUIRE_FOR_CCFLUSH:name;
+const unique T.FFAST_IO_ACQUIRE_FOR_MOD_WRITE:name;
+const unique T.FFAST_IO_CHECK_IF_POSSIBLE:name;
+const unique T.FFAST_IO_DETACH_DEVICE:name;
+const unique T.FFAST_IO_DEVICE_CONTROL:name;
+const unique T.FFAST_IO_LOCK:name;
+const unique T.FFAST_IO_MDL_READ:name;
+const unique T.FFAST_IO_MDL_READ_COMPLETE:name;
+const unique T.FFAST_IO_MDL_READ_COMPLETE_COMPRESSED:name;
+const unique T.FFAST_IO_MDL_WRITE_COMPLETE:name;
+const unique T.FFAST_IO_MDL_WRITE_COMPLETE_COMPRESSED:name;
+const unique T.FFAST_IO_PREPARE_MDL_WRITE:name;
+const unique T.FFAST_IO_QUERY_BASIC_INFO:name;
+const unique T.FFAST_IO_QUERY_NETWORK_OPEN_INFO:name;
+const unique T.FFAST_IO_QUERY_OPEN:name;
+const unique T.FFAST_IO_QUERY_STANDARD_INFO:name;
+const unique T.FFAST_IO_READ:name;
+const unique T.FFAST_IO_READ_COMPRESSED:name;
+const unique T.FFAST_IO_RELEASE_FILE:name;
+const unique T.FFAST_IO_RELEASE_FOR_CCFLUSH:name;
+const unique T.FFAST_IO_RELEASE_FOR_MOD_WRITE:name;
+const unique T.FFAST_IO_UNLOCK_ALL:name;
+const unique T.FFAST_IO_UNLOCK_ALL_BY_KEY:name;
+const unique T.FFAST_IO_UNLOCK_SINGLE:name;
+const unique T.FFAST_IO_WRITE:name;
+const unique T.FFAST_IO_WRITE_COMPRESSED:name;
+const unique T.FIO_COMPLETION_ROUTINE:name;
+const unique T.FKDEFERRED_ROUTINE:name;
+const unique T.INT2:name;
+const unique T.INT4:name;
+const unique T.INT8:name;
+const unique T.PA2UINT2:name;
+const unique T.PA37CHAR:name;
+const unique T.PA40CHAR:name;
+const unique T.PA4UINT4:name;
+const unique T.PA65CHAR:name;
+const unique T.PA75CHAR:name;
+const unique T.PA76CHAR:name;
+const unique T.PA7UINT2:name;
+const unique T.PA83CHAR:name;
+const unique T.PA9UINT2:name;
+const unique T.PCHAR:name;
+const unique T.PF19:name;
+const unique T.PF21:name;
+const unique T.PF23:name;
+const unique T.PF24:name;
+const unique T.PF25:name;
+const unique T.PF33:name;
+const unique T.PF34:name;
+const unique T.PF35:name;
+const unique T.PF36:name;
+const unique T.PF37:name;
+const unique T.PF38:name;
+const unique T.PFDRIVER_ADD_DEVICE:name;
+const unique T.PFDRIVER_CANCEL:name;
+const unique T.PFDRIVER_CONTROL:name;
+const unique T.PFDRIVER_DISPATCH:name;
+const unique T.PFDRIVER_INITIALIZE:name;
+const unique T.PFDRIVER_STARTIO:name;
+const unique T.PFDRIVER_UNLOAD:name;
+const unique T.PFFAST_IO_ACQUIRE_FILE:name;
+const unique T.PFFAST_IO_ACQUIRE_FOR_CCFLUSH:name;
+const unique T.PFFAST_IO_ACQUIRE_FOR_MOD_WRITE:name;
+const unique T.PFFAST_IO_CHECK_IF_POSSIBLE:name;
+const unique T.PFFAST_IO_DETACH_DEVICE:name;
+const unique T.PFFAST_IO_DEVICE_CONTROL:name;
+const unique T.PFFAST_IO_LOCK:name;
+const unique T.PFFAST_IO_MDL_READ:name;
+const unique T.PFFAST_IO_MDL_READ_COMPLETE:name;
+const unique T.PFFAST_IO_MDL_READ_COMPLETE_COMPRESSED:name;
+const unique T.PFFAST_IO_MDL_WRITE_COMPLETE:name;
+const unique T.PFFAST_IO_MDL_WRITE_COMPLETE_COMPRESSED:name;
+const unique T.PFFAST_IO_PREPARE_MDL_WRITE:name;
+const unique T.PFFAST_IO_QUERY_BASIC_INFO:name;
+const unique T.PFFAST_IO_QUERY_NETWORK_OPEN_INFO:name;
+const unique T.PFFAST_IO_QUERY_OPEN:name;
+const unique T.PFFAST_IO_QUERY_STANDARD_INFO:name;
+const unique T.PFFAST_IO_READ:name;
+const unique T.PFFAST_IO_READ_COMPRESSED:name;
+const unique T.PFFAST_IO_RELEASE_FILE:name;
+const unique T.PFFAST_IO_RELEASE_FOR_CCFLUSH:name;
+const unique T.PFFAST_IO_RELEASE_FOR_MOD_WRITE:name;
+const unique T.PFFAST_IO_UNLOCK_ALL:name;
+const unique T.PFFAST_IO_UNLOCK_ALL_BY_KEY:name;
+const unique T.PFFAST_IO_UNLOCK_SINGLE:name;
+const unique T.PFFAST_IO_WRITE:name;
+const unique T.PFFAST_IO_WRITE_COMPRESSED:name;
+const unique T.PFIO_COMPLETION_ROUTINE:name;
+const unique T.PFKDEFERRED_ROUTINE:name;
+const unique T.PINT4:name;
+const unique T.POWER_ACTION:name;
+const unique T.PPCHAR:name;
+const unique T.PPF24:name;
+const unique T.PPPUINT2:name;
+const unique T.PPP_DEVICE_OBJECT:name;
+const unique T.PPUINT2:name;
+const unique T.PPUINT4:name;
+const unique T.PPVOID:name;
+const unique T.PP_DEVICE_EXTENSION:name;
+const unique T.PP_DEVICE_OBJECT:name;
+const unique T.PP_DRIVER_OBJECT:name;
+const unique T.PP_ERESOURCE:name;
+const unique T.PP_FAST_MUTEX:name;
+const unique T.PP_IO_REMOVE_LOCK:name;
+const unique T.PP_LIST_ENTRY:name;
+const unique T.PP_MDL:name;
+const unique T.PP_UNICODE_STRING:name;
+const unique T.PUCHAR:name;
+const unique T.PUINT2:name;
+const unique T.PUINT4:name;
+const unique T.PVOID:name;
+const unique T.PWMIGUIDREGINFO:name;
+const unique T.P_ACCESS_STATE:name;
+const unique T.P_CM_RESOURCE_LIST:name;
+const unique T.P_COMPRESSED_DATA_INFO:name;
+const unique T.P_DEVICE_CAPABILITIES:name;
+const unique T.P_DEVICE_EXTENSION:name;
+const unique T.P_DEVICE_OBJECT:name;
+const unique T.P_DEVOBJ_EXTENSION:name;
+const unique T.P_DRIVER_EXTENSION:name;
+const unique T.P_DRIVER_OBJECT:name;
+const unique T.P_EPROCESS:name;
+const unique T.P_ERESOURCE:name;
+const unique T.P_ETHREAD:name;
+const unique T.P_FAST_IO_DISPATCH:name;
+const unique T.P_FAST_MUTEX:name;
+const unique T.P_FILE_BASIC_INFORMATION:name;
+const unique T.P_FILE_GET_QUOTA_INFORMATION:name;
+const unique T.P_FILE_NETWORK_OPEN_INFORMATION:name;
+const unique T.P_FILE_OBJECT:name;
+const unique T.P_FILE_STANDARD_INFORMATION:name;
+const unique T.P_GLOBALS:name;
+const unique T.P_GUID:name;
+const unique T.P_INTERFACE:name;
+const unique T.P_IO_COMPLETION_CONTEXT:name;
+const unique T.P_IO_REMOVE_LOCK:name;
+const unique T.P_IO_REMOVE_LOCK_TRACKING_BLOCK:name;
+const unique T.P_IO_RESOURCE_REQUIREMENTS_LIST:name;
+const unique T.P_IO_SECURITY_CONTEXT:name;
+const unique T.P_IO_STACK_LOCATION:name;
+const unique T.P_IO_STATUS_BLOCK:name;
+const unique T.P_IO_TIMER:name;
+const unique T.P_IRP:name;
+const unique T.P_KAPC:name;
+const unique T.P_KDPC:name;
+const unique T.P_KEVENT:name;
+const unique T.P_KEYBOARD_INPUT_DATA:name;
+const unique T.P_KSEMAPHORE:name;
+const unique T.P_KTHREAD:name;
+const unique T.P_LARGE_INTEGER:name;
+const unique T.P_LIST_ENTRY:name;
+const unique T.P_MDL:name;
+const unique T.P_OWNER_ENTRY:name;
+const unique T.P_POOL_TYPE:name;
+const unique T.P_PORT:name;
+const unique T.P_POWER_SEQUENCE:name;
+const unique T.P_SCSI_REQUEST_BLOCK:name;
+const unique T.P_SECTION_OBJECT_POINTERS:name;
+const unique T.P_SECURITY_QUALITY_OF_SERVICE:name;
+const unique T.P_UNICODE_STRING:name;
+const unique T.P_VPB:name;
+const unique T.UCHAR:name;
+const unique T.UINT2:name;
+const unique T.UINT4:name;
+const unique T.VOID:name;
+const unique T.WMIENABLEDISABLECONTROL:name;
+const unique T.WMIGUIDREGINFO:name;
+const unique T._ACCESS_STATE:name;
+const unique T._CM_FULL_RESOURCE_DESCRIPTOR:name;
+const unique T._CM_PARTIAL_RESOURCE_DESCRIPTOR:name;
+const unique T._CM_PARTIAL_RESOURCE_LIST:name;
+const unique T._CM_RESOURCE_LIST:name;
+const unique T._COMPRESSED_DATA_INFO:name;
+const unique T._DEVICE_CAPABILITIES:name;
+const unique T._DEVICE_EXTENSION:name;
+const unique T._DEVICE_OBJECT:name;
+const unique T._DEVICE_POWER_STATE:name;
+const unique T._DEVICE_RELATION_TYPE:name;
+const unique T._DEVICE_USAGE_NOTIFICATION_TYPE:name;
+const unique T._DEVOBJ_EXTENSION:name;
+const unique T._DISPATCHER_HEADER:name;
+const unique T._DRIVER_EXTENSION:name;
+const unique T._DRIVER_OBJECT:name;
+const unique T._EPROCESS:name;
+const unique T._ERESOURCE:name;
+const unique T._ETHREAD:name;
+const unique T._FAST_IO_DISPATCH:name;
+const unique T._FAST_MUTEX:name;
+const unique T._FILE_BASIC_INFORMATION:name;
+const unique T._FILE_GET_QUOTA_INFORMATION:name;
+const unique T._FILE_INFORMATION_CLASS:name;
+const unique T._FILE_NETWORK_OPEN_INFORMATION:name;
+const unique T._FILE_OBJECT:name;
+const unique T._FILE_STANDARD_INFORMATION:name;
+const unique T._FSINFOCLASS:name;
+const unique T._GLOBALS:name;
+const unique T._GUID:name;
+const unique T._INITIAL_PRIVILEGE_SET:name;
+const unique T._INTERFACE:name;
+const unique T._INTERFACE_TYPE:name;
+const unique T._IO_ALLOCATION_ACTION:name;
+const unique T._IO_COMPLETION_CONTEXT:name;
+const unique T._IO_REMOVE_LOCK:name;
+const unique T._IO_REMOVE_LOCK_COMMON_BLOCK:name;
+const unique T._IO_REMOVE_LOCK_DBG_BLOCK:name;
+const unique T._IO_REMOVE_LOCK_TRACKING_BLOCK:name;
+const unique T._IO_RESOURCE_DESCRIPTOR:name;
+const unique T._IO_RESOURCE_LIST:name;
+const unique T._IO_RESOURCE_REQUIREMENTS_LIST:name;
+const unique T._IO_SECURITY_CONTEXT:name;
+const unique T._IO_STACK_LOCATION:name;
+const unique T._IO_STATUS_BLOCK:name;
+const unique T._IO_TIMER:name;
+const unique T._IRP:name;
+const unique T._IRQ_DEVICE_POLICY:name;
+const unique T._IRQ_PRIORITY:name;
+const unique T._KAPC:name;
+const unique T._KDEVICE_QUEUE:name;
+const unique T._KDEVICE_QUEUE_ENTRY:name;
+const unique T._KDPC:name;
+const unique T._KEVENT:name;
+const unique T._KEYBOARD_ATTRIBUTES:name;
+const unique T._KEYBOARD_ID:name;
+const unique T._KEYBOARD_INDICATOR_PARAMETERS:name;
+const unique T._KEYBOARD_INPUT_DATA:name;
+const unique T._KEYBOARD_TYPEMATIC_PARAMETERS:name;
+const unique T._KSEMAPHORE:name;
+const unique T._KTHREAD:name;
+const unique T._LARGE_INTEGER:name;
+const unique T._LIST_ENTRY:name;
+const unique T._LUID:name;
+const unique T._LUID_AND_ATTRIBUTES:name;
+const unique T._MDL:name;
+const unique T._OWNER_ENTRY:name;
+const unique T._POOL_TYPE:name;
+const unique T._PORT:name;
+const unique T._POWER_SEQUENCE:name;
+const unique T._POWER_STATE:name;
+const unique T._POWER_STATE_TYPE:name;
+const unique T._PRIVILEGE_SET:name;
+const unique T._SCSI_REQUEST_BLOCK:name;
+const unique T._SECTION_OBJECT_POINTERS:name;
+const unique T._SECURITY_IMPERSONATION_LEVEL:name;
+const unique T._SECURITY_QUALITY_OF_SERVICE:name;
+const unique T._SECURITY_SUBJECT_CONTEXT:name;
+const unique T._SYSTEM_POWER_STATE:name;
+const unique T._SYSTEM_POWER_STATE_CONTEXT:name;
+const unique T._UNICODE_STRING:name;
+const unique T._VPB:name;
+const unique T._WAIT_CONTEXT_BLOCK:name;
+const unique T._WMILIB_CONTEXT:name;
+const unique T.__unnamed_12_0d6a30de:name;
+const unique T.__unnamed_12_17f5c211:name;
+const unique T.__unnamed_12_1fb42e39:name;
+const unique T.__unnamed_12_2a1563c6:name;
+const unique T.__unnamed_12_31347272:name;
+const unique T.__unnamed_12_429aadc0:name;
+const unique T.__unnamed_12_4719de1a:name;
+const unique T.__unnamed_12_4be56faa:name;
+const unique T.__unnamed_12_5ce25b92:name;
+const unique T.__unnamed_12_7a698b72:name;
+const unique T.__unnamed_12_87c0de8d:name;
+const unique T.__unnamed_12_98bfc55a:name;
+const unique T.__unnamed_12_ab1bd9d7:name;
+const unique T.__unnamed_12_b0429be9:name;
+const unique T.__unnamed_12_b43e8de8:name;
+const unique T.__unnamed_12_bfdb39ee:name;
+const unique T.__unnamed_12_cd42b3c3:name;
+const unique T.__unnamed_12_e668effc:name;
+const unique T.__unnamed_12_e80d029e:name;
+const unique T.__unnamed_16_07c0bcc5:name;
+const unique T.__unnamed_16_29cb9f2f:name;
+const unique T.__unnamed_16_30f11dbf:name;
+const unique T.__unnamed_16_35034f68:name;
+const unique T.__unnamed_16_487a9498:name;
+const unique T.__unnamed_16_5f6a8844:name;
+const unique T.__unnamed_16_7177b9f3:name;
+const unique T.__unnamed_16_88e91ef6:name;
+const unique T.__unnamed_16_8c506c98:name;
+const unique T.__unnamed_16_9ac2e5f8:name;
+const unique T.__unnamed_16_b93842ad:name;
+const unique T.__unnamed_16_b9c62eab:name;
+const unique T.__unnamed_16_bb584060:name;
+const unique T.__unnamed_16_dba55c7c:name;
+const unique T.__unnamed_16_e70c268b:name;
+const unique T.__unnamed_16_e734d694:name;
+const unique T.__unnamed_16_eac6dbea:name;
+const unique T.__unnamed_16_f6cae4c2:name;
+const unique T.__unnamed_16_fe36e4f4:name;
+const unique T.__unnamed_1_29794256:name;
+const unique T.__unnamed_1_2dc63b48:name;
+const unique T.__unnamed_1_2ef8da39:name;
+const unique T.__unnamed_1_faa7dc71:name;
+const unique T.__unnamed_20_f4d2e6d8:name;
+const unique T.__unnamed_24_41cbc8c0:name;
+const unique T.__unnamed_24_5419c914:name;
+const unique T.__unnamed_24_67a5ff10:name;
+const unique T.__unnamed_24_72c3976e:name;
+const unique T.__unnamed_24_a26050bb:name;
+const unique T.__unnamed_24_b8f476db:name;
+const unique T.__unnamed_24_d09044b4:name;
+const unique T.__unnamed_2_46cc4597:name;
+const unique T.__unnamed_40_7218f704:name;
+const unique T.__unnamed_40_c55c9377:name;
+const unique T.__unnamed_44_5584090d:name;
+const unique T.__unnamed_48_cf99b13f:name;
+const unique T.__unnamed_4_069846fb:name;
+const unique T.__unnamed_4_224c32f4:name;
+const unique T.__unnamed_4_2de698da:name;
+const unique T.__unnamed_4_3a2fdc5e:name;
+const unique T.__unnamed_4_3a4c1a13:name;
+const unique T.__unnamed_4_43913aa5:name;
+const unique T.__unnamed_4_4e8dd2ba:name;
+const unique T.__unnamed_4_52603077:name;
+const unique T.__unnamed_4_52c594f7:name;
+const unique T.__unnamed_4_5ca00198:name;
+const unique T.__unnamed_4_6ac6463c:name;
+const unique T.__unnamed_4_6f9ac8e1:name;
+const unique T.__unnamed_4_7a02167b:name;
+const unique T.__unnamed_4_7d9d0c7e:name;
+const unique T.__unnamed_4_82f7a864:name;
+const unique T.__unnamed_4_9aec220b:name;
+const unique T.__unnamed_4_a97c65a1:name;
+const unique T.__unnamed_4_c3479730:name;
+const unique T.__unnamed_4_d99b6e2b:name;
+const unique T.__unnamed_4_f19b65c1:name;
+const unique T.__unnamed_4_fa10fc16:name;
+const unique T.__unnamed_8_01efa60d:name;
+const unique T.__unnamed_8_08d4cef8:name;
+const unique T.__unnamed_8_0a898c0c:name;
+const unique T.__unnamed_8_1330f93a:name;
+const unique T.__unnamed_8_181d0de9:name;
+const unique T.__unnamed_8_4812764d:name;
+const unique T.__unnamed_8_559a91e6:name;
+const unique T.__unnamed_8_5845b309:name;
+const unique T.__unnamed_8_58ee4a31:name;
+const unique T.__unnamed_8_61acf4ce:name;
+const unique T.__unnamed_8_6acfee04:name;
+const unique T.__unnamed_8_7f26a9dd:name;
+const unique T.__unnamed_8_87add0bd:name;
+const unique T.__unnamed_8_b2773e4c:name;
+const unique T.__unnamed_8_de890d4e:name;
+const unique T.__unnamed_8_ef9ba0d3:name;
+
+function Abandoned___unnamed_1_29794256(int) returns (int);
+function Abandoned___unnamed_1_29794256Inv(int) returns (int);
+function _S_Abandoned___unnamed_1_29794256([int]bool) returns ([int]bool);
+function _S_Abandoned___unnamed_1_29794256Inv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {Abandoned___unnamed_1_29794256Inv(Abandoned___unnamed_1_29794256(x))} Abandoned___unnamed_1_29794256Inv(Abandoned___unnamed_1_29794256(x)) == x);
+axiom (forall x:int :: {Abandoned___unnamed_1_29794256Inv(x)} Abandoned___unnamed_1_29794256(Abandoned___unnamed_1_29794256Inv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_Abandoned___unnamed_1_29794256(S)[x]} _S_Abandoned___unnamed_1_29794256(S)[x] <==> S[Abandoned___unnamed_1_29794256Inv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_Abandoned___unnamed_1_29794256Inv(S)[x]} _S_Abandoned___unnamed_1_29794256Inv(S)[x] <==> S[Abandoned___unnamed_1_29794256(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Abandoned___unnamed_1_29794256(S)} S[x] ==> _S_Abandoned___unnamed_1_29794256(S)[Abandoned___unnamed_1_29794256(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Abandoned___unnamed_1_29794256Inv(S)} S[x] ==> _S_Abandoned___unnamed_1_29794256Inv(S)[Abandoned___unnamed_1_29794256Inv(x)]);
+
+axiom (forall x:int :: {Abandoned___unnamed_1_29794256(x)} Abandoned___unnamed_1_29794256(x) == x + 0);
+axiom (forall x:int :: {Abandoned___unnamed_1_29794256Inv(x)} Abandoned___unnamed_1_29794256Inv(x) == x - 0);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1) == Abandoned___unnamed_1_29794256Inv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 0)} MINUS_LEFT_PTR(x, 1, 0) == Abandoned___unnamed_1_29794256Inv(x));
+function Absolute___unnamed_1_29794256(int) returns (int);
+function Absolute___unnamed_1_29794256Inv(int) returns (int);
+function _S_Absolute___unnamed_1_29794256([int]bool) returns ([int]bool);
+function _S_Absolute___unnamed_1_29794256Inv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {Absolute___unnamed_1_29794256Inv(Absolute___unnamed_1_29794256(x))} Absolute___unnamed_1_29794256Inv(Absolute___unnamed_1_29794256(x)) == x);
+axiom (forall x:int :: {Absolute___unnamed_1_29794256Inv(x)} Absolute___unnamed_1_29794256(Absolute___unnamed_1_29794256Inv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_Absolute___unnamed_1_29794256(S)[x]} _S_Absolute___unnamed_1_29794256(S)[x] <==> S[Absolute___unnamed_1_29794256Inv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_Absolute___unnamed_1_29794256Inv(S)[x]} _S_Absolute___unnamed_1_29794256Inv(S)[x] <==> S[Absolute___unnamed_1_29794256(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Absolute___unnamed_1_29794256(S)} S[x] ==> _S_Absolute___unnamed_1_29794256(S)[Absolute___unnamed_1_29794256(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Absolute___unnamed_1_29794256Inv(S)} S[x] ==> _S_Absolute___unnamed_1_29794256Inv(S)[Absolute___unnamed_1_29794256Inv(x)]);
+
+axiom (forall x:int :: {Absolute___unnamed_1_29794256(x)} Absolute___unnamed_1_29794256(x) == x + 0);
+axiom (forall x:int :: {Absolute___unnamed_1_29794256Inv(x)} Absolute___unnamed_1_29794256Inv(x) == x - 0);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1) == Absolute___unnamed_1_29794256Inv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 0)} MINUS_LEFT_PTR(x, 1, 0) == Absolute___unnamed_1_29794256Inv(x));
+function AllocateTag__IO_REMOVE_LOCK_DBG_BLOCK(int) returns (int);
+function AllocateTag__IO_REMOVE_LOCK_DBG_BLOCKInv(int) returns (int);
+function _S_AllocateTag__IO_REMOVE_LOCK_DBG_BLOCK([int]bool) returns ([int]bool);
+function _S_AllocateTag__IO_REMOVE_LOCK_DBG_BLOCKInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {AllocateTag__IO_REMOVE_LOCK_DBG_BLOCKInv(AllocateTag__IO_REMOVE_LOCK_DBG_BLOCK(x))} AllocateTag__IO_REMOVE_LOCK_DBG_BLOCKInv(AllocateTag__IO_REMOVE_LOCK_DBG_BLOCK(x)) == x);
+axiom (forall x:int :: {AllocateTag__IO_REMOVE_LOCK_DBG_BLOCKInv(x)} AllocateTag__IO_REMOVE_LOCK_DBG_BLOCK(AllocateTag__IO_REMOVE_LOCK_DBG_BLOCKInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_AllocateTag__IO_REMOVE_LOCK_DBG_BLOCK(S)[x]} _S_AllocateTag__IO_REMOVE_LOCK_DBG_BLOCK(S)[x] <==> S[AllocateTag__IO_REMOVE_LOCK_DBG_BLOCKInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_AllocateTag__IO_REMOVE_LOCK_DBG_BLOCKInv(S)[x]} _S_AllocateTag__IO_REMOVE_LOCK_DBG_BLOCKInv(S)[x] <==> S[AllocateTag__IO_REMOVE_LOCK_DBG_BLOCK(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_AllocateTag__IO_REMOVE_LOCK_DBG_BLOCK(S)} S[x] ==> _S_AllocateTag__IO_REMOVE_LOCK_DBG_BLOCK(S)[AllocateTag__IO_REMOVE_LOCK_DBG_BLOCK(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_AllocateTag__IO_REMOVE_LOCK_DBG_BLOCKInv(S)} S[x] ==> _S_AllocateTag__IO_REMOVE_LOCK_DBG_BLOCKInv(S)[AllocateTag__IO_REMOVE_LOCK_DBG_BLOCKInv(x)]);
+
+axiom (forall x:int :: {AllocateTag__IO_REMOVE_LOCK_DBG_BLOCK(x)} AllocateTag__IO_REMOVE_LOCK_DBG_BLOCK(x) == x + 16);
+axiom (forall x:int :: {AllocateTag__IO_REMOVE_LOCK_DBG_BLOCKInv(x)} AllocateTag__IO_REMOVE_LOCK_DBG_BLOCKInv(x) == x - 16);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 16, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 16, 1) == AllocateTag__IO_REMOVE_LOCK_DBG_BLOCKInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 16)} MINUS_LEFT_PTR(x, 1, 16) == AllocateTag__IO_REMOVE_LOCK_DBG_BLOCKInv(x));
+function AllowDisable__DEVICE_EXTENSION(int) returns (int);
+function AllowDisable__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_AllowDisable__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_AllowDisable__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {AllowDisable__DEVICE_EXTENSIONInv(AllowDisable__DEVICE_EXTENSION(x))} AllowDisable__DEVICE_EXTENSIONInv(AllowDisable__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {AllowDisable__DEVICE_EXTENSIONInv(x)} AllowDisable__DEVICE_EXTENSION(AllowDisable__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_AllowDisable__DEVICE_EXTENSION(S)[x]} _S_AllowDisable__DEVICE_EXTENSION(S)[x] <==> S[AllowDisable__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_AllowDisable__DEVICE_EXTENSIONInv(S)[x]} _S_AllowDisable__DEVICE_EXTENSIONInv(S)[x] <==> S[AllowDisable__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_AllowDisable__DEVICE_EXTENSION(S)} S[x] ==> _S_AllowDisable__DEVICE_EXTENSION(S)[AllowDisable__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_AllowDisable__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_AllowDisable__DEVICE_EXTENSIONInv(S)[AllowDisable__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {AllowDisable__DEVICE_EXTENSION(x)} AllowDisable__DEVICE_EXTENSION(x) == x + 106);
+axiom (forall x:int :: {AllowDisable__DEVICE_EXTENSIONInv(x)} AllowDisable__DEVICE_EXTENSIONInv(x) == x - 106);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 106, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 106, 1) == AllowDisable__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 106)} MINUS_LEFT_PTR(x, 1, 106) == AllowDisable__DEVICE_EXTENSIONInv(x));
+function BaseClassName__GLOBALS(int) returns (int);
+function BaseClassName__GLOBALSInv(int) returns (int);
+function _S_BaseClassName__GLOBALS([int]bool) returns ([int]bool);
+function _S_BaseClassName__GLOBALSInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {BaseClassName__GLOBALSInv(BaseClassName__GLOBALS(x))} BaseClassName__GLOBALSInv(BaseClassName__GLOBALS(x)) == x);
+axiom (forall x:int :: {BaseClassName__GLOBALSInv(x)} BaseClassName__GLOBALS(BaseClassName__GLOBALSInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_BaseClassName__GLOBALS(S)[x]} _S_BaseClassName__GLOBALS(S)[x] <==> S[BaseClassName__GLOBALSInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_BaseClassName__GLOBALSInv(S)[x]} _S_BaseClassName__GLOBALSInv(S)[x] <==> S[BaseClassName__GLOBALS(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_BaseClassName__GLOBALS(S)} S[x] ==> _S_BaseClassName__GLOBALS(S)[BaseClassName__GLOBALS(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_BaseClassName__GLOBALSInv(S)} S[x] ==> _S_BaseClassName__GLOBALSInv(S)[BaseClassName__GLOBALSInv(x)]);
+
+axiom (forall x:int :: {BaseClassName__GLOBALS(x)} BaseClassName__GLOBALS(x) == x + 368);
+axiom (forall x:int :: {BaseClassName__GLOBALSInv(x)} BaseClassName__GLOBALSInv(x) == x - 368);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 368, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 368, 1) == BaseClassName__GLOBALSInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 368)} MINUS_LEFT_PTR(x, 1, 368) == BaseClassName__GLOBALSInv(x));
+function Blink__LIST_ENTRY(int) returns (int);
+function Blink__LIST_ENTRYInv(int) returns (int);
+function _S_Blink__LIST_ENTRY([int]bool) returns ([int]bool);
+function _S_Blink__LIST_ENTRYInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {Blink__LIST_ENTRYInv(Blink__LIST_ENTRY(x))} Blink__LIST_ENTRYInv(Blink__LIST_ENTRY(x)) == x);
+axiom (forall x:int :: {Blink__LIST_ENTRYInv(x)} Blink__LIST_ENTRY(Blink__LIST_ENTRYInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_Blink__LIST_ENTRY(S)[x]} _S_Blink__LIST_ENTRY(S)[x] <==> S[Blink__LIST_ENTRYInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_Blink__LIST_ENTRYInv(S)[x]} _S_Blink__LIST_ENTRYInv(S)[x] <==> S[Blink__LIST_ENTRY(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Blink__LIST_ENTRY(S)} S[x] ==> _S_Blink__LIST_ENTRY(S)[Blink__LIST_ENTRY(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Blink__LIST_ENTRYInv(S)} S[x] ==> _S_Blink__LIST_ENTRYInv(S)[Blink__LIST_ENTRYInv(x)]);
+
+axiom (forall x:int :: {Blink__LIST_ENTRY(x)} Blink__LIST_ENTRY(x) == x + 4);
+axiom (forall x:int :: {Blink__LIST_ENTRYInv(x)} Blink__LIST_ENTRYInv(x) == x - 4);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 4, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 4, 1) == Blink__LIST_ENTRYInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 4)} MINUS_LEFT_PTR(x, 1, 4) == Blink__LIST_ENTRYInv(x));
+function Blocks__IO_REMOVE_LOCK_DBG_BLOCK(int) returns (int);
+function Blocks__IO_REMOVE_LOCK_DBG_BLOCKInv(int) returns (int);
+function _S_Blocks__IO_REMOVE_LOCK_DBG_BLOCK([int]bool) returns ([int]bool);
+function _S_Blocks__IO_REMOVE_LOCK_DBG_BLOCKInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {Blocks__IO_REMOVE_LOCK_DBG_BLOCKInv(Blocks__IO_REMOVE_LOCK_DBG_BLOCK(x))} Blocks__IO_REMOVE_LOCK_DBG_BLOCKInv(Blocks__IO_REMOVE_LOCK_DBG_BLOCK(x)) == x);
+axiom (forall x:int :: {Blocks__IO_REMOVE_LOCK_DBG_BLOCKInv(x)} Blocks__IO_REMOVE_LOCK_DBG_BLOCK(Blocks__IO_REMOVE_LOCK_DBG_BLOCKInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_Blocks__IO_REMOVE_LOCK_DBG_BLOCK(S)[x]} _S_Blocks__IO_REMOVE_LOCK_DBG_BLOCK(S)[x] <==> S[Blocks__IO_REMOVE_LOCK_DBG_BLOCKInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_Blocks__IO_REMOVE_LOCK_DBG_BLOCKInv(S)[x]} _S_Blocks__IO_REMOVE_LOCK_DBG_BLOCKInv(S)[x] <==> S[Blocks__IO_REMOVE_LOCK_DBG_BLOCK(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Blocks__IO_REMOVE_LOCK_DBG_BLOCK(S)} S[x] ==> _S_Blocks__IO_REMOVE_LOCK_DBG_BLOCK(S)[Blocks__IO_REMOVE_LOCK_DBG_BLOCK(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Blocks__IO_REMOVE_LOCK_DBG_BLOCKInv(S)} S[x] ==> _S_Blocks__IO_REMOVE_LOCK_DBG_BLOCKInv(S)[Blocks__IO_REMOVE_LOCK_DBG_BLOCKInv(x)]);
+
+axiom (forall x:int :: {Blocks__IO_REMOVE_LOCK_DBG_BLOCK(x)} Blocks__IO_REMOVE_LOCK_DBG_BLOCK(x) == x + 56);
+axiom (forall x:int :: {Blocks__IO_REMOVE_LOCK_DBG_BLOCKInv(x)} Blocks__IO_REMOVE_LOCK_DBG_BLOCKInv(x) == x - 56);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 56, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 56, 1) == Blocks__IO_REMOVE_LOCK_DBG_BLOCKInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 56)} MINUS_LEFT_PTR(x, 1, 56) == Blocks__IO_REMOVE_LOCK_DBG_BLOCKInv(x));
+function Buffer__UNICODE_STRING(int) returns (int);
+function Buffer__UNICODE_STRINGInv(int) returns (int);
+function _S_Buffer__UNICODE_STRING([int]bool) returns ([int]bool);
+function _S_Buffer__UNICODE_STRINGInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {Buffer__UNICODE_STRINGInv(Buffer__UNICODE_STRING(x))} Buffer__UNICODE_STRINGInv(Buffer__UNICODE_STRING(x)) == x);
+axiom (forall x:int :: {Buffer__UNICODE_STRINGInv(x)} Buffer__UNICODE_STRING(Buffer__UNICODE_STRINGInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_Buffer__UNICODE_STRING(S)[x]} _S_Buffer__UNICODE_STRING(S)[x] <==> S[Buffer__UNICODE_STRINGInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_Buffer__UNICODE_STRINGInv(S)[x]} _S_Buffer__UNICODE_STRINGInv(S)[x] <==> S[Buffer__UNICODE_STRING(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Buffer__UNICODE_STRING(S)} S[x] ==> _S_Buffer__UNICODE_STRING(S)[Buffer__UNICODE_STRING(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Buffer__UNICODE_STRINGInv(S)} S[x] ==> _S_Buffer__UNICODE_STRINGInv(S)[Buffer__UNICODE_STRINGInv(x)]);
+
+axiom (forall x:int :: {Buffer__UNICODE_STRING(x)} Buffer__UNICODE_STRING(x) == x + 4);
+axiom (forall x:int :: {Buffer__UNICODE_STRINGInv(x)} Buffer__UNICODE_STRINGInv(x) == x - 4);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 4, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 4, 1) == Buffer__UNICODE_STRINGInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 4)} MINUS_LEFT_PTR(x, 1, 4) == Buffer__UNICODE_STRINGInv(x));
+function Common__IO_REMOVE_LOCK(int) returns (int);
+function Common__IO_REMOVE_LOCKInv(int) returns (int);
+function _S_Common__IO_REMOVE_LOCK([int]bool) returns ([int]bool);
+function _S_Common__IO_REMOVE_LOCKInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {Common__IO_REMOVE_LOCKInv(Common__IO_REMOVE_LOCK(x))} Common__IO_REMOVE_LOCKInv(Common__IO_REMOVE_LOCK(x)) == x);
+axiom (forall x:int :: {Common__IO_REMOVE_LOCKInv(x)} Common__IO_REMOVE_LOCK(Common__IO_REMOVE_LOCKInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_Common__IO_REMOVE_LOCK(S)[x]} _S_Common__IO_REMOVE_LOCK(S)[x] <==> S[Common__IO_REMOVE_LOCKInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_Common__IO_REMOVE_LOCKInv(S)[x]} _S_Common__IO_REMOVE_LOCKInv(S)[x] <==> S[Common__IO_REMOVE_LOCK(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Common__IO_REMOVE_LOCK(S)} S[x] ==> _S_Common__IO_REMOVE_LOCK(S)[Common__IO_REMOVE_LOCK(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Common__IO_REMOVE_LOCKInv(S)} S[x] ==> _S_Common__IO_REMOVE_LOCKInv(S)[Common__IO_REMOVE_LOCKInv(x)]);
+
+axiom (forall x:int :: {Common__IO_REMOVE_LOCK(x)} Common__IO_REMOVE_LOCK(x) == x + 0);
+axiom (forall x:int :: {Common__IO_REMOVE_LOCKInv(x)} Common__IO_REMOVE_LOCKInv(x) == x - 0);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1) == Common__IO_REMOVE_LOCKInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 0)} MINUS_LEFT_PTR(x, 1, 0) == Common__IO_REMOVE_LOCKInv(x));
+function ConnectOneClassToOnePort__GLOBALS(int) returns (int);
+function ConnectOneClassToOnePort__GLOBALSInv(int) returns (int);
+function _S_ConnectOneClassToOnePort__GLOBALS([int]bool) returns ([int]bool);
+function _S_ConnectOneClassToOnePort__GLOBALSInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {ConnectOneClassToOnePort__GLOBALSInv(ConnectOneClassToOnePort__GLOBALS(x))} ConnectOneClassToOnePort__GLOBALSInv(ConnectOneClassToOnePort__GLOBALS(x)) == x);
+axiom (forall x:int :: {ConnectOneClassToOnePort__GLOBALSInv(x)} ConnectOneClassToOnePort__GLOBALS(ConnectOneClassToOnePort__GLOBALSInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_ConnectOneClassToOnePort__GLOBALS(S)[x]} _S_ConnectOneClassToOnePort__GLOBALS(S)[x] <==> S[ConnectOneClassToOnePort__GLOBALSInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_ConnectOneClassToOnePort__GLOBALSInv(S)[x]} _S_ConnectOneClassToOnePort__GLOBALSInv(S)[x] <==> S[ConnectOneClassToOnePort__GLOBALS(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_ConnectOneClassToOnePort__GLOBALS(S)} S[x] ==> _S_ConnectOneClassToOnePort__GLOBALS(S)[ConnectOneClassToOnePort__GLOBALS(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_ConnectOneClassToOnePort__GLOBALSInv(S)} S[x] ==> _S_ConnectOneClassToOnePort__GLOBALSInv(S)[ConnectOneClassToOnePort__GLOBALSInv(x)]);
+
+axiom (forall x:int :: {ConnectOneClassToOnePort__GLOBALS(x)} ConnectOneClassToOnePort__GLOBALS(x) == x + 56);
+axiom (forall x:int :: {ConnectOneClassToOnePort__GLOBALSInv(x)} ConnectOneClassToOnePort__GLOBALSInv(x) == x - 56);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 56, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 56, 1) == ConnectOneClassToOnePort__GLOBALSInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 56)} MINUS_LEFT_PTR(x, 1, 56) == ConnectOneClassToOnePort__GLOBALSInv(x));
+function DataIn__DEVICE_EXTENSION(int) returns (int);
+function DataIn__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_DataIn__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_DataIn__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {DataIn__DEVICE_EXTENSIONInv(DataIn__DEVICE_EXTENSION(x))} DataIn__DEVICE_EXTENSIONInv(DataIn__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {DataIn__DEVICE_EXTENSIONInv(x)} DataIn__DEVICE_EXTENSION(DataIn__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_DataIn__DEVICE_EXTENSION(S)[x]} _S_DataIn__DEVICE_EXTENSION(S)[x] <==> S[DataIn__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_DataIn__DEVICE_EXTENSIONInv(S)[x]} _S_DataIn__DEVICE_EXTENSIONInv(S)[x] <==> S[DataIn__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_DataIn__DEVICE_EXTENSION(S)} S[x] ==> _S_DataIn__DEVICE_EXTENSION(S)[DataIn__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_DataIn__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_DataIn__DEVICE_EXTENSIONInv(S)[DataIn__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {DataIn__DEVICE_EXTENSION(x)} DataIn__DEVICE_EXTENSION(x) == x + 132);
+axiom (forall x:int :: {DataIn__DEVICE_EXTENSIONInv(x)} DataIn__DEVICE_EXTENSIONInv(x) == x - 132);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 132, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 132, 1) == DataIn__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 132)} MINUS_LEFT_PTR(x, 1, 132) == DataIn__DEVICE_EXTENSIONInv(x));
+function DataOut__DEVICE_EXTENSION(int) returns (int);
+function DataOut__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_DataOut__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_DataOut__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {DataOut__DEVICE_EXTENSIONInv(DataOut__DEVICE_EXTENSION(x))} DataOut__DEVICE_EXTENSIONInv(DataOut__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {DataOut__DEVICE_EXTENSIONInv(x)} DataOut__DEVICE_EXTENSION(DataOut__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_DataOut__DEVICE_EXTENSION(S)[x]} _S_DataOut__DEVICE_EXTENSION(S)[x] <==> S[DataOut__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_DataOut__DEVICE_EXTENSIONInv(S)[x]} _S_DataOut__DEVICE_EXTENSIONInv(S)[x] <==> S[DataOut__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_DataOut__DEVICE_EXTENSION(S)} S[x] ==> _S_DataOut__DEVICE_EXTENSION(S)[DataOut__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_DataOut__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_DataOut__DEVICE_EXTENSIONInv(S)[DataOut__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {DataOut__DEVICE_EXTENSION(x)} DataOut__DEVICE_EXTENSION(x) == x + 136);
+axiom (forall x:int :: {DataOut__DEVICE_EXTENSIONInv(x)} DataOut__DEVICE_EXTENSIONInv(x) == x - 136);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 136, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 136, 1) == DataOut__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 136)} MINUS_LEFT_PTR(x, 1, 136) == DataOut__DEVICE_EXTENSIONInv(x));
+function Dbg__IO_REMOVE_LOCK(int) returns (int);
+function Dbg__IO_REMOVE_LOCKInv(int) returns (int);
+function _S_Dbg__IO_REMOVE_LOCK([int]bool) returns ([int]bool);
+function _S_Dbg__IO_REMOVE_LOCKInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {Dbg__IO_REMOVE_LOCKInv(Dbg__IO_REMOVE_LOCK(x))} Dbg__IO_REMOVE_LOCKInv(Dbg__IO_REMOVE_LOCK(x)) == x);
+axiom (forall x:int :: {Dbg__IO_REMOVE_LOCKInv(x)} Dbg__IO_REMOVE_LOCK(Dbg__IO_REMOVE_LOCKInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_Dbg__IO_REMOVE_LOCK(S)[x]} _S_Dbg__IO_REMOVE_LOCK(S)[x] <==> S[Dbg__IO_REMOVE_LOCKInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_Dbg__IO_REMOVE_LOCKInv(S)[x]} _S_Dbg__IO_REMOVE_LOCKInv(S)[x] <==> S[Dbg__IO_REMOVE_LOCK(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Dbg__IO_REMOVE_LOCK(S)} S[x] ==> _S_Dbg__IO_REMOVE_LOCK(S)[Dbg__IO_REMOVE_LOCK(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Dbg__IO_REMOVE_LOCKInv(S)} S[x] ==> _S_Dbg__IO_REMOVE_LOCKInv(S)[Dbg__IO_REMOVE_LOCKInv(x)]);
+
+axiom (forall x:int :: {Dbg__IO_REMOVE_LOCK(x)} Dbg__IO_REMOVE_LOCK(x) == x + 24);
+axiom (forall x:int :: {Dbg__IO_REMOVE_LOCKInv(x)} Dbg__IO_REMOVE_LOCKInv(x) == x - 24);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 24, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 24, 1) == Dbg__IO_REMOVE_LOCKInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 24)} MINUS_LEFT_PTR(x, 1, 24) == Dbg__IO_REMOVE_LOCKInv(x));
+function DebugActive___unnamed_1_2dc63b48(int) returns (int);
+function DebugActive___unnamed_1_2dc63b48Inv(int) returns (int);
+function _S_DebugActive___unnamed_1_2dc63b48([int]bool) returns ([int]bool);
+function _S_DebugActive___unnamed_1_2dc63b48Inv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {DebugActive___unnamed_1_2dc63b48Inv(DebugActive___unnamed_1_2dc63b48(x))} DebugActive___unnamed_1_2dc63b48Inv(DebugActive___unnamed_1_2dc63b48(x)) == x);
+axiom (forall x:int :: {DebugActive___unnamed_1_2dc63b48Inv(x)} DebugActive___unnamed_1_2dc63b48(DebugActive___unnamed_1_2dc63b48Inv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_DebugActive___unnamed_1_2dc63b48(S)[x]} _S_DebugActive___unnamed_1_2dc63b48(S)[x] <==> S[DebugActive___unnamed_1_2dc63b48Inv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_DebugActive___unnamed_1_2dc63b48Inv(S)[x]} _S_DebugActive___unnamed_1_2dc63b48Inv(S)[x] <==> S[DebugActive___unnamed_1_2dc63b48(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_DebugActive___unnamed_1_2dc63b48(S)} S[x] ==> _S_DebugActive___unnamed_1_2dc63b48(S)[DebugActive___unnamed_1_2dc63b48(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_DebugActive___unnamed_1_2dc63b48Inv(S)} S[x] ==> _S_DebugActive___unnamed_1_2dc63b48Inv(S)[DebugActive___unnamed_1_2dc63b48Inv(x)]);
+
+axiom (forall x:int :: {DebugActive___unnamed_1_2dc63b48(x)} DebugActive___unnamed_1_2dc63b48(x) == x + 0);
+axiom (forall x:int :: {DebugActive___unnamed_1_2dc63b48Inv(x)} DebugActive___unnamed_1_2dc63b48Inv(x) == x - 0);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1) == DebugActive___unnamed_1_2dc63b48Inv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 0)} MINUS_LEFT_PTR(x, 1, 0) == DebugActive___unnamed_1_2dc63b48Inv(x));
+function Delay__KEYBOARD_TYPEMATIC_PARAMETERS(int) returns (int);
+function Delay__KEYBOARD_TYPEMATIC_PARAMETERSInv(int) returns (int);
+function _S_Delay__KEYBOARD_TYPEMATIC_PARAMETERS([int]bool) returns ([int]bool);
+function _S_Delay__KEYBOARD_TYPEMATIC_PARAMETERSInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {Delay__KEYBOARD_TYPEMATIC_PARAMETERSInv(Delay__KEYBOARD_TYPEMATIC_PARAMETERS(x))} Delay__KEYBOARD_TYPEMATIC_PARAMETERSInv(Delay__KEYBOARD_TYPEMATIC_PARAMETERS(x)) == x);
+axiom (forall x:int :: {Delay__KEYBOARD_TYPEMATIC_PARAMETERSInv(x)} Delay__KEYBOARD_TYPEMATIC_PARAMETERS(Delay__KEYBOARD_TYPEMATIC_PARAMETERSInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_Delay__KEYBOARD_TYPEMATIC_PARAMETERS(S)[x]} _S_Delay__KEYBOARD_TYPEMATIC_PARAMETERS(S)[x] <==> S[Delay__KEYBOARD_TYPEMATIC_PARAMETERSInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_Delay__KEYBOARD_TYPEMATIC_PARAMETERSInv(S)[x]} _S_Delay__KEYBOARD_TYPEMATIC_PARAMETERSInv(S)[x] <==> S[Delay__KEYBOARD_TYPEMATIC_PARAMETERS(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Delay__KEYBOARD_TYPEMATIC_PARAMETERS(S)} S[x] ==> _S_Delay__KEYBOARD_TYPEMATIC_PARAMETERS(S)[Delay__KEYBOARD_TYPEMATIC_PARAMETERS(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Delay__KEYBOARD_TYPEMATIC_PARAMETERSInv(S)} S[x] ==> _S_Delay__KEYBOARD_TYPEMATIC_PARAMETERSInv(S)[Delay__KEYBOARD_TYPEMATIC_PARAMETERSInv(x)]);
+
+axiom (forall x:int :: {Delay__KEYBOARD_TYPEMATIC_PARAMETERS(x)} Delay__KEYBOARD_TYPEMATIC_PARAMETERS(x) == x + 4);
+axiom (forall x:int :: {Delay__KEYBOARD_TYPEMATIC_PARAMETERSInv(x)} Delay__KEYBOARD_TYPEMATIC_PARAMETERSInv(x) == x - 4);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 4, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 4, 1) == Delay__KEYBOARD_TYPEMATIC_PARAMETERSInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 4)} MINUS_LEFT_PTR(x, 1, 4) == Delay__KEYBOARD_TYPEMATIC_PARAMETERSInv(x));
+function DeviceExtension__DEVICE_OBJECT(int) returns (int);
+function DeviceExtension__DEVICE_OBJECTInv(int) returns (int);
+function _S_DeviceExtension__DEVICE_OBJECT([int]bool) returns ([int]bool);
+function _S_DeviceExtension__DEVICE_OBJECTInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {DeviceExtension__DEVICE_OBJECTInv(DeviceExtension__DEVICE_OBJECT(x))} DeviceExtension__DEVICE_OBJECTInv(DeviceExtension__DEVICE_OBJECT(x)) == x);
+axiom (forall x:int :: {DeviceExtension__DEVICE_OBJECTInv(x)} DeviceExtension__DEVICE_OBJECT(DeviceExtension__DEVICE_OBJECTInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_DeviceExtension__DEVICE_OBJECT(S)[x]} _S_DeviceExtension__DEVICE_OBJECT(S)[x] <==> S[DeviceExtension__DEVICE_OBJECTInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_DeviceExtension__DEVICE_OBJECTInv(S)[x]} _S_DeviceExtension__DEVICE_OBJECTInv(S)[x] <==> S[DeviceExtension__DEVICE_OBJECT(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_DeviceExtension__DEVICE_OBJECT(S)} S[x] ==> _S_DeviceExtension__DEVICE_OBJECT(S)[DeviceExtension__DEVICE_OBJECT(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_DeviceExtension__DEVICE_OBJECTInv(S)} S[x] ==> _S_DeviceExtension__DEVICE_OBJECTInv(S)[DeviceExtension__DEVICE_OBJECTInv(x)]);
+
+axiom (forall x:int :: {DeviceExtension__DEVICE_OBJECT(x)} DeviceExtension__DEVICE_OBJECT(x) == x + 40);
+axiom (forall x:int :: {DeviceExtension__DEVICE_OBJECTInv(x)} DeviceExtension__DEVICE_OBJECTInv(x) == x - 40);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 40, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 40, 1) == DeviceExtension__DEVICE_OBJECTInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 40)} MINUS_LEFT_PTR(x, 1, 40) == DeviceExtension__DEVICE_OBJECTInv(x));
+function DeviceState__DEVICE_EXTENSION(int) returns (int);
+function DeviceState__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_DeviceState__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_DeviceState__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {DeviceState__DEVICE_EXTENSIONInv(DeviceState__DEVICE_EXTENSION(x))} DeviceState__DEVICE_EXTENSIONInv(DeviceState__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {DeviceState__DEVICE_EXTENSIONInv(x)} DeviceState__DEVICE_EXTENSION(DeviceState__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_DeviceState__DEVICE_EXTENSION(S)[x]} _S_DeviceState__DEVICE_EXTENSION(S)[x] <==> S[DeviceState__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_DeviceState__DEVICE_EXTENSIONInv(S)[x]} _S_DeviceState__DEVICE_EXTENSIONInv(S)[x] <==> S[DeviceState__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_DeviceState__DEVICE_EXTENSION(S)} S[x] ==> _S_DeviceState__DEVICE_EXTENSION(S)[DeviceState__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_DeviceState__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_DeviceState__DEVICE_EXTENSIONInv(S)[DeviceState__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {DeviceState__DEVICE_EXTENSION(x)} DeviceState__DEVICE_EXTENSION(x) == x + 188);
+axiom (forall x:int :: {DeviceState__DEVICE_EXTENSIONInv(x)} DeviceState__DEVICE_EXTENSIONInv(x) == x - 188);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 188, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 188, 1) == DeviceState__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 188)} MINUS_LEFT_PTR(x, 1, 188) == DeviceState__DEVICE_EXTENSIONInv(x));
+function DpcActive___unnamed_1_2dc63b48(int) returns (int);
+function DpcActive___unnamed_1_2dc63b48Inv(int) returns (int);
+function _S_DpcActive___unnamed_1_2dc63b48([int]bool) returns ([int]bool);
+function _S_DpcActive___unnamed_1_2dc63b48Inv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {DpcActive___unnamed_1_2dc63b48Inv(DpcActive___unnamed_1_2dc63b48(x))} DpcActive___unnamed_1_2dc63b48Inv(DpcActive___unnamed_1_2dc63b48(x)) == x);
+axiom (forall x:int :: {DpcActive___unnamed_1_2dc63b48Inv(x)} DpcActive___unnamed_1_2dc63b48(DpcActive___unnamed_1_2dc63b48Inv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_DpcActive___unnamed_1_2dc63b48(S)[x]} _S_DpcActive___unnamed_1_2dc63b48(S)[x] <==> S[DpcActive___unnamed_1_2dc63b48Inv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_DpcActive___unnamed_1_2dc63b48Inv(S)[x]} _S_DpcActive___unnamed_1_2dc63b48Inv(S)[x] <==> S[DpcActive___unnamed_1_2dc63b48(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_DpcActive___unnamed_1_2dc63b48(S)} S[x] ==> _S_DpcActive___unnamed_1_2dc63b48(S)[DpcActive___unnamed_1_2dc63b48(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_DpcActive___unnamed_1_2dc63b48Inv(S)} S[x] ==> _S_DpcActive___unnamed_1_2dc63b48Inv(S)[DpcActive___unnamed_1_2dc63b48Inv(x)]);
+
+axiom (forall x:int :: {DpcActive___unnamed_1_2dc63b48(x)} DpcActive___unnamed_1_2dc63b48(x) == x + 0);
+axiom (forall x:int :: {DpcActive___unnamed_1_2dc63b48Inv(x)} DpcActive___unnamed_1_2dc63b48Inv(x) == x - 0);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1) == DpcActive___unnamed_1_2dc63b48Inv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 0)} MINUS_LEFT_PTR(x, 1, 0) == DpcActive___unnamed_1_2dc63b48Inv(x));
+function Enabled__DEVICE_EXTENSION(int) returns (int);
+function Enabled__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_Enabled__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_Enabled__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {Enabled__DEVICE_EXTENSIONInv(Enabled__DEVICE_EXTENSION(x))} Enabled__DEVICE_EXTENSIONInv(Enabled__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {Enabled__DEVICE_EXTENSIONInv(x)} Enabled__DEVICE_EXTENSION(Enabled__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_Enabled__DEVICE_EXTENSION(S)[x]} _S_Enabled__DEVICE_EXTENSION(S)[x] <==> S[Enabled__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_Enabled__DEVICE_EXTENSIONInv(S)[x]} _S_Enabled__DEVICE_EXTENSIONInv(S)[x] <==> S[Enabled__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Enabled__DEVICE_EXTENSION(S)} S[x] ==> _S_Enabled__DEVICE_EXTENSION(S)[Enabled__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Enabled__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_Enabled__DEVICE_EXTENSIONInv(S)[Enabled__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {Enabled__DEVICE_EXTENSION(x)} Enabled__DEVICE_EXTENSION(x) == x + 284);
+axiom (forall x:int :: {Enabled__DEVICE_EXTENSIONInv(x)} Enabled__DEVICE_EXTENSIONInv(x) == x - 284);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 284, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 284, 1) == Enabled__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 284)} MINUS_LEFT_PTR(x, 1, 284) == Enabled__DEVICE_EXTENSIONInv(x));
+function ExecuteWmiMethod__WMILIB_CONTEXT(int) returns (int);
+function ExecuteWmiMethod__WMILIB_CONTEXTInv(int) returns (int);
+function _S_ExecuteWmiMethod__WMILIB_CONTEXT([int]bool) returns ([int]bool);
+function _S_ExecuteWmiMethod__WMILIB_CONTEXTInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {ExecuteWmiMethod__WMILIB_CONTEXTInv(ExecuteWmiMethod__WMILIB_CONTEXT(x))} ExecuteWmiMethod__WMILIB_CONTEXTInv(ExecuteWmiMethod__WMILIB_CONTEXT(x)) == x);
+axiom (forall x:int :: {ExecuteWmiMethod__WMILIB_CONTEXTInv(x)} ExecuteWmiMethod__WMILIB_CONTEXT(ExecuteWmiMethod__WMILIB_CONTEXTInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_ExecuteWmiMethod__WMILIB_CONTEXT(S)[x]} _S_ExecuteWmiMethod__WMILIB_CONTEXT(S)[x] <==> S[ExecuteWmiMethod__WMILIB_CONTEXTInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_ExecuteWmiMethod__WMILIB_CONTEXTInv(S)[x]} _S_ExecuteWmiMethod__WMILIB_CONTEXTInv(S)[x] <==> S[ExecuteWmiMethod__WMILIB_CONTEXT(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_ExecuteWmiMethod__WMILIB_CONTEXT(S)} S[x] ==> _S_ExecuteWmiMethod__WMILIB_CONTEXT(S)[ExecuteWmiMethod__WMILIB_CONTEXT(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_ExecuteWmiMethod__WMILIB_CONTEXTInv(S)} S[x] ==> _S_ExecuteWmiMethod__WMILIB_CONTEXTInv(S)[ExecuteWmiMethod__WMILIB_CONTEXTInv(x)]);
+
+axiom (forall x:int :: {ExecuteWmiMethod__WMILIB_CONTEXT(x)} ExecuteWmiMethod__WMILIB_CONTEXT(x) == x + 24);
+axiom (forall x:int :: {ExecuteWmiMethod__WMILIB_CONTEXTInv(x)} ExecuteWmiMethod__WMILIB_CONTEXTInv(x) == x - 24);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 24, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 24, 1) == ExecuteWmiMethod__WMILIB_CONTEXTInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 24)} MINUS_LEFT_PTR(x, 1, 24) == ExecuteWmiMethod__WMILIB_CONTEXTInv(x));
+function ExtraWaitWakeIrp__DEVICE_EXTENSION(int) returns (int);
+function ExtraWaitWakeIrp__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_ExtraWaitWakeIrp__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_ExtraWaitWakeIrp__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {ExtraWaitWakeIrp__DEVICE_EXTENSIONInv(ExtraWaitWakeIrp__DEVICE_EXTENSION(x))} ExtraWaitWakeIrp__DEVICE_EXTENSIONInv(ExtraWaitWakeIrp__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {ExtraWaitWakeIrp__DEVICE_EXTENSIONInv(x)} ExtraWaitWakeIrp__DEVICE_EXTENSION(ExtraWaitWakeIrp__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_ExtraWaitWakeIrp__DEVICE_EXTENSION(S)[x]} _S_ExtraWaitWakeIrp__DEVICE_EXTENSION(S)[x] <==> S[ExtraWaitWakeIrp__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_ExtraWaitWakeIrp__DEVICE_EXTENSIONInv(S)[x]} _S_ExtraWaitWakeIrp__DEVICE_EXTENSIONInv(S)[x] <==> S[ExtraWaitWakeIrp__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_ExtraWaitWakeIrp__DEVICE_EXTENSION(S)} S[x] ==> _S_ExtraWaitWakeIrp__DEVICE_EXTENSION(S)[ExtraWaitWakeIrp__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_ExtraWaitWakeIrp__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_ExtraWaitWakeIrp__DEVICE_EXTENSIONInv(S)[ExtraWaitWakeIrp__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {ExtraWaitWakeIrp__DEVICE_EXTENSION(x)} ExtraWaitWakeIrp__DEVICE_EXTENSION(x) == x + 264);
+axiom (forall x:int :: {ExtraWaitWakeIrp__DEVICE_EXTENSIONInv(x)} ExtraWaitWakeIrp__DEVICE_EXTENSIONInv(x) == x - 264);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 264, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 264, 1) == ExtraWaitWakeIrp__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 264)} MINUS_LEFT_PTR(x, 1, 264) == ExtraWaitWakeIrp__DEVICE_EXTENSIONInv(x));
+function File__DEVICE_EXTENSION(int) returns (int);
+function File__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_File__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_File__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {File__DEVICE_EXTENSIONInv(File__DEVICE_EXTENSION(x))} File__DEVICE_EXTENSIONInv(File__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {File__DEVICE_EXTENSIONInv(x)} File__DEVICE_EXTENSION(File__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_File__DEVICE_EXTENSION(S)[x]} _S_File__DEVICE_EXTENSION(S)[x] <==> S[File__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_File__DEVICE_EXTENSIONInv(S)[x]} _S_File__DEVICE_EXTENSIONInv(S)[x] <==> S[File__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_File__DEVICE_EXTENSION(S)} S[x] ==> _S_File__DEVICE_EXTENSION(S)[File__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_File__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_File__DEVICE_EXTENSIONInv(S)[File__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {File__DEVICE_EXTENSION(x)} File__DEVICE_EXTENSION(x) == x + 280);
+axiom (forall x:int :: {File__DEVICE_EXTENSIONInv(x)} File__DEVICE_EXTENSIONInv(x) == x - 280);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 280, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 280, 1) == File__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 280)} MINUS_LEFT_PTR(x, 1, 280) == File__DEVICE_EXTENSIONInv(x));
+function Flags__DEVICE_OBJECT(int) returns (int);
+function Flags__DEVICE_OBJECTInv(int) returns (int);
+function _S_Flags__DEVICE_OBJECT([int]bool) returns ([int]bool);
+function _S_Flags__DEVICE_OBJECTInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {Flags__DEVICE_OBJECTInv(Flags__DEVICE_OBJECT(x))} Flags__DEVICE_OBJECTInv(Flags__DEVICE_OBJECT(x)) == x);
+axiom (forall x:int :: {Flags__DEVICE_OBJECTInv(x)} Flags__DEVICE_OBJECT(Flags__DEVICE_OBJECTInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_Flags__DEVICE_OBJECT(S)[x]} _S_Flags__DEVICE_OBJECT(S)[x] <==> S[Flags__DEVICE_OBJECTInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_Flags__DEVICE_OBJECTInv(S)[x]} _S_Flags__DEVICE_OBJECTInv(S)[x] <==> S[Flags__DEVICE_OBJECT(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Flags__DEVICE_OBJECT(S)} S[x] ==> _S_Flags__DEVICE_OBJECT(S)[Flags__DEVICE_OBJECT(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Flags__DEVICE_OBJECTInv(S)} S[x] ==> _S_Flags__DEVICE_OBJECTInv(S)[Flags__DEVICE_OBJECTInv(x)]);
+
+axiom (forall x:int :: {Flags__DEVICE_OBJECT(x)} Flags__DEVICE_OBJECT(x) == x + 28);
+axiom (forall x:int :: {Flags__DEVICE_OBJECTInv(x)} Flags__DEVICE_OBJECTInv(x) == x - 28);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 28, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 28, 1) == Flags__DEVICE_OBJECTInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 28)} MINUS_LEFT_PTR(x, 1, 28) == Flags__DEVICE_OBJECTInv(x));
+function Flink__LIST_ENTRY(int) returns (int);
+function Flink__LIST_ENTRYInv(int) returns (int);
+function _S_Flink__LIST_ENTRY([int]bool) returns ([int]bool);
+function _S_Flink__LIST_ENTRYInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {Flink__LIST_ENTRYInv(Flink__LIST_ENTRY(x))} Flink__LIST_ENTRYInv(Flink__LIST_ENTRY(x)) == x);
+axiom (forall x:int :: {Flink__LIST_ENTRYInv(x)} Flink__LIST_ENTRY(Flink__LIST_ENTRYInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_Flink__LIST_ENTRY(S)[x]} _S_Flink__LIST_ENTRY(S)[x] <==> S[Flink__LIST_ENTRYInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_Flink__LIST_ENTRYInv(S)[x]} _S_Flink__LIST_ENTRYInv(S)[x] <==> S[Flink__LIST_ENTRY(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Flink__LIST_ENTRY(S)} S[x] ==> _S_Flink__LIST_ENTRY(S)[Flink__LIST_ENTRY(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Flink__LIST_ENTRYInv(S)} S[x] ==> _S_Flink__LIST_ENTRYInv(S)[Flink__LIST_ENTRYInv(x)]);
+
+axiom (forall x:int :: {Flink__LIST_ENTRY(x)} Flink__LIST_ENTRY(x) == x + 0);
+axiom (forall x:int :: {Flink__LIST_ENTRYInv(x)} Flink__LIST_ENTRYInv(x) == x - 0);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1) == Flink__LIST_ENTRYInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 0)} MINUS_LEFT_PTR(x, 1, 0) == Flink__LIST_ENTRYInv(x));
+function GrandMaster__GLOBALS(int) returns (int);
+function GrandMaster__GLOBALSInv(int) returns (int);
+function _S_GrandMaster__GLOBALS([int]bool) returns ([int]bool);
+function _S_GrandMaster__GLOBALSInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {GrandMaster__GLOBALSInv(GrandMaster__GLOBALS(x))} GrandMaster__GLOBALSInv(GrandMaster__GLOBALS(x)) == x);
+axiom (forall x:int :: {GrandMaster__GLOBALSInv(x)} GrandMaster__GLOBALS(GrandMaster__GLOBALSInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_GrandMaster__GLOBALS(S)[x]} _S_GrandMaster__GLOBALS(S)[x] <==> S[GrandMaster__GLOBALSInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_GrandMaster__GLOBALSInv(S)[x]} _S_GrandMaster__GLOBALSInv(S)[x] <==> S[GrandMaster__GLOBALS(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_GrandMaster__GLOBALS(S)} S[x] ==> _S_GrandMaster__GLOBALS(S)[GrandMaster__GLOBALS(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_GrandMaster__GLOBALSInv(S)} S[x] ==> _S_GrandMaster__GLOBALSInv(S)[GrandMaster__GLOBALSInv(x)]);
+
+axiom (forall x:int :: {GrandMaster__GLOBALS(x)} GrandMaster__GLOBALS(x) == x + 4);
+axiom (forall x:int :: {GrandMaster__GLOBALSInv(x)} GrandMaster__GLOBALSInv(x) == x - 4);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 4, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 4, 1) == GrandMaster__GLOBALSInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 4)} MINUS_LEFT_PTR(x, 1, 4) == GrandMaster__GLOBALSInv(x));
+function GuidCount__WMILIB_CONTEXT(int) returns (int);
+function GuidCount__WMILIB_CONTEXTInv(int) returns (int);
+function _S_GuidCount__WMILIB_CONTEXT([int]bool) returns ([int]bool);
+function _S_GuidCount__WMILIB_CONTEXTInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {GuidCount__WMILIB_CONTEXTInv(GuidCount__WMILIB_CONTEXT(x))} GuidCount__WMILIB_CONTEXTInv(GuidCount__WMILIB_CONTEXT(x)) == x);
+axiom (forall x:int :: {GuidCount__WMILIB_CONTEXTInv(x)} GuidCount__WMILIB_CONTEXT(GuidCount__WMILIB_CONTEXTInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_GuidCount__WMILIB_CONTEXT(S)[x]} _S_GuidCount__WMILIB_CONTEXT(S)[x] <==> S[GuidCount__WMILIB_CONTEXTInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_GuidCount__WMILIB_CONTEXTInv(S)[x]} _S_GuidCount__WMILIB_CONTEXTInv(S)[x] <==> S[GuidCount__WMILIB_CONTEXT(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_GuidCount__WMILIB_CONTEXT(S)} S[x] ==> _S_GuidCount__WMILIB_CONTEXT(S)[GuidCount__WMILIB_CONTEXT(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_GuidCount__WMILIB_CONTEXTInv(S)} S[x] ==> _S_GuidCount__WMILIB_CONTEXTInv(S)[GuidCount__WMILIB_CONTEXTInv(x)]);
+
+axiom (forall x:int :: {GuidCount__WMILIB_CONTEXT(x)} GuidCount__WMILIB_CONTEXT(x) == x + 0);
+axiom (forall x:int :: {GuidCount__WMILIB_CONTEXTInv(x)} GuidCount__WMILIB_CONTEXTInv(x) == x - 0);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1) == GuidCount__WMILIB_CONTEXTInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 0)} MINUS_LEFT_PTR(x, 1, 0) == GuidCount__WMILIB_CONTEXTInv(x));
+function GuidList__WMILIB_CONTEXT(int) returns (int);
+function GuidList__WMILIB_CONTEXTInv(int) returns (int);
+function _S_GuidList__WMILIB_CONTEXT([int]bool) returns ([int]bool);
+function _S_GuidList__WMILIB_CONTEXTInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {GuidList__WMILIB_CONTEXTInv(GuidList__WMILIB_CONTEXT(x))} GuidList__WMILIB_CONTEXTInv(GuidList__WMILIB_CONTEXT(x)) == x);
+axiom (forall x:int :: {GuidList__WMILIB_CONTEXTInv(x)} GuidList__WMILIB_CONTEXT(GuidList__WMILIB_CONTEXTInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_GuidList__WMILIB_CONTEXT(S)[x]} _S_GuidList__WMILIB_CONTEXT(S)[x] <==> S[GuidList__WMILIB_CONTEXTInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_GuidList__WMILIB_CONTEXTInv(S)[x]} _S_GuidList__WMILIB_CONTEXTInv(S)[x] <==> S[GuidList__WMILIB_CONTEXT(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_GuidList__WMILIB_CONTEXT(S)} S[x] ==> _S_GuidList__WMILIB_CONTEXT(S)[GuidList__WMILIB_CONTEXT(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_GuidList__WMILIB_CONTEXTInv(S)} S[x] ==> _S_GuidList__WMILIB_CONTEXTInv(S)[GuidList__WMILIB_CONTEXTInv(x)]);
+
+axiom (forall x:int :: {GuidList__WMILIB_CONTEXT(x)} GuidList__WMILIB_CONTEXT(x) == x + 4);
+axiom (forall x:int :: {GuidList__WMILIB_CONTEXTInv(x)} GuidList__WMILIB_CONTEXTInv(x) == x - 4);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 4, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 4, 1) == GuidList__WMILIB_CONTEXTInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 4)} MINUS_LEFT_PTR(x, 1, 4) == GuidList__WMILIB_CONTEXTInv(x));
+function Hand___unnamed_1_2ef8da39(int) returns (int);
+function Hand___unnamed_1_2ef8da39Inv(int) returns (int);
+function _S_Hand___unnamed_1_2ef8da39([int]bool) returns ([int]bool);
+function _S_Hand___unnamed_1_2ef8da39Inv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {Hand___unnamed_1_2ef8da39Inv(Hand___unnamed_1_2ef8da39(x))} Hand___unnamed_1_2ef8da39Inv(Hand___unnamed_1_2ef8da39(x)) == x);
+axiom (forall x:int :: {Hand___unnamed_1_2ef8da39Inv(x)} Hand___unnamed_1_2ef8da39(Hand___unnamed_1_2ef8da39Inv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_Hand___unnamed_1_2ef8da39(S)[x]} _S_Hand___unnamed_1_2ef8da39(S)[x] <==> S[Hand___unnamed_1_2ef8da39Inv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_Hand___unnamed_1_2ef8da39Inv(S)[x]} _S_Hand___unnamed_1_2ef8da39Inv(S)[x] <==> S[Hand___unnamed_1_2ef8da39(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Hand___unnamed_1_2ef8da39(S)} S[x] ==> _S_Hand___unnamed_1_2ef8da39(S)[Hand___unnamed_1_2ef8da39(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Hand___unnamed_1_2ef8da39Inv(S)} S[x] ==> _S_Hand___unnamed_1_2ef8da39Inv(S)[Hand___unnamed_1_2ef8da39Inv(x)]);
+
+axiom (forall x:int :: {Hand___unnamed_1_2ef8da39(x)} Hand___unnamed_1_2ef8da39(x) == x + 0);
+axiom (forall x:int :: {Hand___unnamed_1_2ef8da39Inv(x)} Hand___unnamed_1_2ef8da39Inv(x) == x - 0);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1) == Hand___unnamed_1_2ef8da39Inv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 0)} MINUS_LEFT_PTR(x, 1, 0) == Hand___unnamed_1_2ef8da39Inv(x));
+function Header__KEVENT(int) returns (int);
+function Header__KEVENTInv(int) returns (int);
+function _S_Header__KEVENT([int]bool) returns ([int]bool);
+function _S_Header__KEVENTInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {Header__KEVENTInv(Header__KEVENT(x))} Header__KEVENTInv(Header__KEVENT(x)) == x);
+axiom (forall x:int :: {Header__KEVENTInv(x)} Header__KEVENT(Header__KEVENTInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_Header__KEVENT(S)[x]} _S_Header__KEVENT(S)[x] <==> S[Header__KEVENTInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_Header__KEVENTInv(S)[x]} _S_Header__KEVENTInv(S)[x] <==> S[Header__KEVENT(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Header__KEVENT(S)} S[x] ==> _S_Header__KEVENT(S)[Header__KEVENT(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Header__KEVENTInv(S)} S[x] ==> _S_Header__KEVENTInv(S)[Header__KEVENTInv(x)]);
+
+axiom (forall x:int :: {Header__KEVENT(x)} Header__KEVENT(x) == x + 0);
+axiom (forall x:int :: {Header__KEVENTInv(x)} Header__KEVENTInv(x) == x - 0);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1) == Header__KEVENTInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 0)} MINUS_LEFT_PTR(x, 1, 0) == Header__KEVENTInv(x));
+function HighWatermark__IO_REMOVE_LOCK_DBG_BLOCK(int) returns (int);
+function HighWatermark__IO_REMOVE_LOCK_DBG_BLOCKInv(int) returns (int);
+function _S_HighWatermark__IO_REMOVE_LOCK_DBG_BLOCK([int]bool) returns ([int]bool);
+function _S_HighWatermark__IO_REMOVE_LOCK_DBG_BLOCKInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {HighWatermark__IO_REMOVE_LOCK_DBG_BLOCKInv(HighWatermark__IO_REMOVE_LOCK_DBG_BLOCK(x))} HighWatermark__IO_REMOVE_LOCK_DBG_BLOCKInv(HighWatermark__IO_REMOVE_LOCK_DBG_BLOCK(x)) == x);
+axiom (forall x:int :: {HighWatermark__IO_REMOVE_LOCK_DBG_BLOCKInv(x)} HighWatermark__IO_REMOVE_LOCK_DBG_BLOCK(HighWatermark__IO_REMOVE_LOCK_DBG_BLOCKInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_HighWatermark__IO_REMOVE_LOCK_DBG_BLOCK(S)[x]} _S_HighWatermark__IO_REMOVE_LOCK_DBG_BLOCK(S)[x] <==> S[HighWatermark__IO_REMOVE_LOCK_DBG_BLOCKInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_HighWatermark__IO_REMOVE_LOCK_DBG_BLOCKInv(S)[x]} _S_HighWatermark__IO_REMOVE_LOCK_DBG_BLOCKInv(S)[x] <==> S[HighWatermark__IO_REMOVE_LOCK_DBG_BLOCK(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_HighWatermark__IO_REMOVE_LOCK_DBG_BLOCK(S)} S[x] ==> _S_HighWatermark__IO_REMOVE_LOCK_DBG_BLOCK(S)[HighWatermark__IO_REMOVE_LOCK_DBG_BLOCK(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_HighWatermark__IO_REMOVE_LOCK_DBG_BLOCKInv(S)} S[x] ==> _S_HighWatermark__IO_REMOVE_LOCK_DBG_BLOCKInv(S)[HighWatermark__IO_REMOVE_LOCK_DBG_BLOCKInv(x)]);
+
+axiom (forall x:int :: {HighWatermark__IO_REMOVE_LOCK_DBG_BLOCK(x)} HighWatermark__IO_REMOVE_LOCK_DBG_BLOCK(x) == x + 4);
+axiom (forall x:int :: {HighWatermark__IO_REMOVE_LOCK_DBG_BLOCKInv(x)} HighWatermark__IO_REMOVE_LOCK_DBG_BLOCKInv(x) == x - 4);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 4, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 4, 1) == HighWatermark__IO_REMOVE_LOCK_DBG_BLOCKInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 4)} MINUS_LEFT_PTR(x, 1, 4) == HighWatermark__IO_REMOVE_LOCK_DBG_BLOCKInv(x));
+function IndicatorParameters__DEVICE_EXTENSION(int) returns (int);
+function IndicatorParameters__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_IndicatorParameters__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_IndicatorParameters__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {IndicatorParameters__DEVICE_EXTENSIONInv(IndicatorParameters__DEVICE_EXTENSION(x))} IndicatorParameters__DEVICE_EXTENSIONInv(IndicatorParameters__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {IndicatorParameters__DEVICE_EXTENSIONInv(x)} IndicatorParameters__DEVICE_EXTENSION(IndicatorParameters__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_IndicatorParameters__DEVICE_EXTENSION(S)[x]} _S_IndicatorParameters__DEVICE_EXTENSION(S)[x] <==> S[IndicatorParameters__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_IndicatorParameters__DEVICE_EXTENSIONInv(S)[x]} _S_IndicatorParameters__DEVICE_EXTENSIONInv(S)[x] <==> S[IndicatorParameters__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_IndicatorParameters__DEVICE_EXTENSION(S)} S[x] ==> _S_IndicatorParameters__DEVICE_EXTENSION(S)[IndicatorParameters__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_IndicatorParameters__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_IndicatorParameters__DEVICE_EXTENSIONInv(S)[IndicatorParameters__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {IndicatorParameters__DEVICE_EXTENSION(x)} IndicatorParameters__DEVICE_EXTENSION(x) == x + 168);
+axiom (forall x:int :: {IndicatorParameters__DEVICE_EXTENSIONInv(x)} IndicatorParameters__DEVICE_EXTENSIONInv(x) == x - 168);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 168, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 168, 1) == IndicatorParameters__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 168)} MINUS_LEFT_PTR(x, 1, 168) == IndicatorParameters__DEVICE_EXTENSIONInv(x));
+function InputCount__DEVICE_EXTENSION(int) returns (int);
+function InputCount__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_InputCount__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_InputCount__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {InputCount__DEVICE_EXTENSIONInv(InputCount__DEVICE_EXTENSION(x))} InputCount__DEVICE_EXTENSIONInv(InputCount__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {InputCount__DEVICE_EXTENSIONInv(x)} InputCount__DEVICE_EXTENSION(InputCount__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_InputCount__DEVICE_EXTENSION(S)[x]} _S_InputCount__DEVICE_EXTENSION(S)[x] <==> S[InputCount__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_InputCount__DEVICE_EXTENSIONInv(S)[x]} _S_InputCount__DEVICE_EXTENSIONInv(S)[x] <==> S[InputCount__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_InputCount__DEVICE_EXTENSION(S)} S[x] ==> _S_InputCount__DEVICE_EXTENSION(S)[InputCount__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_InputCount__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_InputCount__DEVICE_EXTENSIONInv(S)[InputCount__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {InputCount__DEVICE_EXTENSION(x)} InputCount__DEVICE_EXTENSION(x) == x + 116);
+axiom (forall x:int :: {InputCount__DEVICE_EXTENSIONInv(x)} InputCount__DEVICE_EXTENSIONInv(x) == x - 116);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 116, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 116, 1) == InputCount__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 116)} MINUS_LEFT_PTR(x, 1, 116) == InputCount__DEVICE_EXTENSIONInv(x));
+function InputDataQueueLength__KEYBOARD_ATTRIBUTES(int) returns (int);
+function InputDataQueueLength__KEYBOARD_ATTRIBUTESInv(int) returns (int);
+function _S_InputDataQueueLength__KEYBOARD_ATTRIBUTES([int]bool) returns ([int]bool);
+function _S_InputDataQueueLength__KEYBOARD_ATTRIBUTESInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {InputDataQueueLength__KEYBOARD_ATTRIBUTESInv(InputDataQueueLength__KEYBOARD_ATTRIBUTES(x))} InputDataQueueLength__KEYBOARD_ATTRIBUTESInv(InputDataQueueLength__KEYBOARD_ATTRIBUTES(x)) == x);
+axiom (forall x:int :: {InputDataQueueLength__KEYBOARD_ATTRIBUTESInv(x)} InputDataQueueLength__KEYBOARD_ATTRIBUTES(InputDataQueueLength__KEYBOARD_ATTRIBUTESInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_InputDataQueueLength__KEYBOARD_ATTRIBUTES(S)[x]} _S_InputDataQueueLength__KEYBOARD_ATTRIBUTES(S)[x] <==> S[InputDataQueueLength__KEYBOARD_ATTRIBUTESInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_InputDataQueueLength__KEYBOARD_ATTRIBUTESInv(S)[x]} _S_InputDataQueueLength__KEYBOARD_ATTRIBUTESInv(S)[x] <==> S[InputDataQueueLength__KEYBOARD_ATTRIBUTES(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_InputDataQueueLength__KEYBOARD_ATTRIBUTES(S)} S[x] ==> _S_InputDataQueueLength__KEYBOARD_ATTRIBUTES(S)[InputDataQueueLength__KEYBOARD_ATTRIBUTES(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_InputDataQueueLength__KEYBOARD_ATTRIBUTESInv(S)} S[x] ==> _S_InputDataQueueLength__KEYBOARD_ATTRIBUTESInv(S)[InputDataQueueLength__KEYBOARD_ATTRIBUTESInv(x)]);
+
+axiom (forall x:int :: {InputDataQueueLength__KEYBOARD_ATTRIBUTES(x)} InputDataQueueLength__KEYBOARD_ATTRIBUTES(x) == x + 12);
+axiom (forall x:int :: {InputDataQueueLength__KEYBOARD_ATTRIBUTESInv(x)} InputDataQueueLength__KEYBOARD_ATTRIBUTESInv(x) == x - 12);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 12, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 12, 1) == InputDataQueueLength__KEYBOARD_ATTRIBUTESInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 12)} MINUS_LEFT_PTR(x, 1, 12) == InputDataQueueLength__KEYBOARD_ATTRIBUTESInv(x));
+function InputData__DEVICE_EXTENSION(int) returns (int);
+function InputData__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_InputData__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_InputData__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {InputData__DEVICE_EXTENSIONInv(InputData__DEVICE_EXTENSION(x))} InputData__DEVICE_EXTENSIONInv(InputData__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {InputData__DEVICE_EXTENSIONInv(x)} InputData__DEVICE_EXTENSION(InputData__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_InputData__DEVICE_EXTENSION(S)[x]} _S_InputData__DEVICE_EXTENSION(S)[x] <==> S[InputData__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_InputData__DEVICE_EXTENSIONInv(S)[x]} _S_InputData__DEVICE_EXTENSIONInv(S)[x] <==> S[InputData__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_InputData__DEVICE_EXTENSION(S)} S[x] ==> _S_InputData__DEVICE_EXTENSION(S)[InputData__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_InputData__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_InputData__DEVICE_EXTENSIONInv(S)[InputData__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {InputData__DEVICE_EXTENSION(x)} InputData__DEVICE_EXTENSION(x) == x + 128);
+axiom (forall x:int :: {InputData__DEVICE_EXTENSIONInv(x)} InputData__DEVICE_EXTENSIONInv(x) == x - 128);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 128, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 128, 1) == InputData__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 128)} MINUS_LEFT_PTR(x, 1, 128) == InputData__DEVICE_EXTENSIONInv(x));
+function Inserted___unnamed_1_2dc63b48(int) returns (int);
+function Inserted___unnamed_1_2dc63b48Inv(int) returns (int);
+function _S_Inserted___unnamed_1_2dc63b48([int]bool) returns ([int]bool);
+function _S_Inserted___unnamed_1_2dc63b48Inv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {Inserted___unnamed_1_2dc63b48Inv(Inserted___unnamed_1_2dc63b48(x))} Inserted___unnamed_1_2dc63b48Inv(Inserted___unnamed_1_2dc63b48(x)) == x);
+axiom (forall x:int :: {Inserted___unnamed_1_2dc63b48Inv(x)} Inserted___unnamed_1_2dc63b48(Inserted___unnamed_1_2dc63b48Inv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_Inserted___unnamed_1_2dc63b48(S)[x]} _S_Inserted___unnamed_1_2dc63b48(S)[x] <==> S[Inserted___unnamed_1_2dc63b48Inv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_Inserted___unnamed_1_2dc63b48Inv(S)[x]} _S_Inserted___unnamed_1_2dc63b48Inv(S)[x] <==> S[Inserted___unnamed_1_2dc63b48(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Inserted___unnamed_1_2dc63b48(S)} S[x] ==> _S_Inserted___unnamed_1_2dc63b48(S)[Inserted___unnamed_1_2dc63b48(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Inserted___unnamed_1_2dc63b48Inv(S)} S[x] ==> _S_Inserted___unnamed_1_2dc63b48Inv(S)[Inserted___unnamed_1_2dc63b48Inv(x)]);
+
+axiom (forall x:int :: {Inserted___unnamed_1_2dc63b48(x)} Inserted___unnamed_1_2dc63b48(x) == x + 0);
+axiom (forall x:int :: {Inserted___unnamed_1_2dc63b48Inv(x)} Inserted___unnamed_1_2dc63b48Inv(x) == x - 0);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1) == Inserted___unnamed_1_2dc63b48Inv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 0)} MINUS_LEFT_PTR(x, 1, 0) == Inserted___unnamed_1_2dc63b48Inv(x));
+function IoCount__IO_REMOVE_LOCK_COMMON_BLOCK(int) returns (int);
+function IoCount__IO_REMOVE_LOCK_COMMON_BLOCKInv(int) returns (int);
+function _S_IoCount__IO_REMOVE_LOCK_COMMON_BLOCK([int]bool) returns ([int]bool);
+function _S_IoCount__IO_REMOVE_LOCK_COMMON_BLOCKInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {IoCount__IO_REMOVE_LOCK_COMMON_BLOCKInv(IoCount__IO_REMOVE_LOCK_COMMON_BLOCK(x))} IoCount__IO_REMOVE_LOCK_COMMON_BLOCKInv(IoCount__IO_REMOVE_LOCK_COMMON_BLOCK(x)) == x);
+axiom (forall x:int :: {IoCount__IO_REMOVE_LOCK_COMMON_BLOCKInv(x)} IoCount__IO_REMOVE_LOCK_COMMON_BLOCK(IoCount__IO_REMOVE_LOCK_COMMON_BLOCKInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_IoCount__IO_REMOVE_LOCK_COMMON_BLOCK(S)[x]} _S_IoCount__IO_REMOVE_LOCK_COMMON_BLOCK(S)[x] <==> S[IoCount__IO_REMOVE_LOCK_COMMON_BLOCKInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_IoCount__IO_REMOVE_LOCK_COMMON_BLOCKInv(S)[x]} _S_IoCount__IO_REMOVE_LOCK_COMMON_BLOCKInv(S)[x] <==> S[IoCount__IO_REMOVE_LOCK_COMMON_BLOCK(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_IoCount__IO_REMOVE_LOCK_COMMON_BLOCK(S)} S[x] ==> _S_IoCount__IO_REMOVE_LOCK_COMMON_BLOCK(S)[IoCount__IO_REMOVE_LOCK_COMMON_BLOCK(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_IoCount__IO_REMOVE_LOCK_COMMON_BLOCKInv(S)} S[x] ==> _S_IoCount__IO_REMOVE_LOCK_COMMON_BLOCKInv(S)[IoCount__IO_REMOVE_LOCK_COMMON_BLOCKInv(x)]);
+
+axiom (forall x:int :: {IoCount__IO_REMOVE_LOCK_COMMON_BLOCK(x)} IoCount__IO_REMOVE_LOCK_COMMON_BLOCK(x) == x + 4);
+axiom (forall x:int :: {IoCount__IO_REMOVE_LOCK_COMMON_BLOCKInv(x)} IoCount__IO_REMOVE_LOCK_COMMON_BLOCKInv(x) == x - 4);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 4, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 4, 1) == IoCount__IO_REMOVE_LOCK_COMMON_BLOCKInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 4)} MINUS_LEFT_PTR(x, 1, 4) == IoCount__IO_REMOVE_LOCK_COMMON_BLOCKInv(x));
+function KeyRepeatMaximum__KEYBOARD_ATTRIBUTES(int) returns (int);
+function KeyRepeatMaximum__KEYBOARD_ATTRIBUTESInv(int) returns (int);
+function _S_KeyRepeatMaximum__KEYBOARD_ATTRIBUTES([int]bool) returns ([int]bool);
+function _S_KeyRepeatMaximum__KEYBOARD_ATTRIBUTESInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {KeyRepeatMaximum__KEYBOARD_ATTRIBUTESInv(KeyRepeatMaximum__KEYBOARD_ATTRIBUTES(x))} KeyRepeatMaximum__KEYBOARD_ATTRIBUTESInv(KeyRepeatMaximum__KEYBOARD_ATTRIBUTES(x)) == x);
+axiom (forall x:int :: {KeyRepeatMaximum__KEYBOARD_ATTRIBUTESInv(x)} KeyRepeatMaximum__KEYBOARD_ATTRIBUTES(KeyRepeatMaximum__KEYBOARD_ATTRIBUTESInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_KeyRepeatMaximum__KEYBOARD_ATTRIBUTES(S)[x]} _S_KeyRepeatMaximum__KEYBOARD_ATTRIBUTES(S)[x] <==> S[KeyRepeatMaximum__KEYBOARD_ATTRIBUTESInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_KeyRepeatMaximum__KEYBOARD_ATTRIBUTESInv(S)[x]} _S_KeyRepeatMaximum__KEYBOARD_ATTRIBUTESInv(S)[x] <==> S[KeyRepeatMaximum__KEYBOARD_ATTRIBUTES(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_KeyRepeatMaximum__KEYBOARD_ATTRIBUTES(S)} S[x] ==> _S_KeyRepeatMaximum__KEYBOARD_ATTRIBUTES(S)[KeyRepeatMaximum__KEYBOARD_ATTRIBUTES(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_KeyRepeatMaximum__KEYBOARD_ATTRIBUTESInv(S)} S[x] ==> _S_KeyRepeatMaximum__KEYBOARD_ATTRIBUTESInv(S)[KeyRepeatMaximum__KEYBOARD_ATTRIBUTESInv(x)]);
+
+axiom (forall x:int :: {KeyRepeatMaximum__KEYBOARD_ATTRIBUTES(x)} KeyRepeatMaximum__KEYBOARD_ATTRIBUTES(x) == x + 22);
+axiom (forall x:int :: {KeyRepeatMaximum__KEYBOARD_ATTRIBUTESInv(x)} KeyRepeatMaximum__KEYBOARD_ATTRIBUTESInv(x) == x - 22);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 22, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 22, 1) == KeyRepeatMaximum__KEYBOARD_ATTRIBUTESInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 22)} MINUS_LEFT_PTR(x, 1, 22) == KeyRepeatMaximum__KEYBOARD_ATTRIBUTESInv(x));
+function KeyRepeatMinimum__KEYBOARD_ATTRIBUTES(int) returns (int);
+function KeyRepeatMinimum__KEYBOARD_ATTRIBUTESInv(int) returns (int);
+function _S_KeyRepeatMinimum__KEYBOARD_ATTRIBUTES([int]bool) returns ([int]bool);
+function _S_KeyRepeatMinimum__KEYBOARD_ATTRIBUTESInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {KeyRepeatMinimum__KEYBOARD_ATTRIBUTESInv(KeyRepeatMinimum__KEYBOARD_ATTRIBUTES(x))} KeyRepeatMinimum__KEYBOARD_ATTRIBUTESInv(KeyRepeatMinimum__KEYBOARD_ATTRIBUTES(x)) == x);
+axiom (forall x:int :: {KeyRepeatMinimum__KEYBOARD_ATTRIBUTESInv(x)} KeyRepeatMinimum__KEYBOARD_ATTRIBUTES(KeyRepeatMinimum__KEYBOARD_ATTRIBUTESInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_KeyRepeatMinimum__KEYBOARD_ATTRIBUTES(S)[x]} _S_KeyRepeatMinimum__KEYBOARD_ATTRIBUTES(S)[x] <==> S[KeyRepeatMinimum__KEYBOARD_ATTRIBUTESInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_KeyRepeatMinimum__KEYBOARD_ATTRIBUTESInv(S)[x]} _S_KeyRepeatMinimum__KEYBOARD_ATTRIBUTESInv(S)[x] <==> S[KeyRepeatMinimum__KEYBOARD_ATTRIBUTES(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_KeyRepeatMinimum__KEYBOARD_ATTRIBUTES(S)} S[x] ==> _S_KeyRepeatMinimum__KEYBOARD_ATTRIBUTES(S)[KeyRepeatMinimum__KEYBOARD_ATTRIBUTES(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_KeyRepeatMinimum__KEYBOARD_ATTRIBUTESInv(S)} S[x] ==> _S_KeyRepeatMinimum__KEYBOARD_ATTRIBUTESInv(S)[KeyRepeatMinimum__KEYBOARD_ATTRIBUTESInv(x)]);
+
+axiom (forall x:int :: {KeyRepeatMinimum__KEYBOARD_ATTRIBUTES(x)} KeyRepeatMinimum__KEYBOARD_ATTRIBUTES(x) == x + 16);
+axiom (forall x:int :: {KeyRepeatMinimum__KEYBOARD_ATTRIBUTESInv(x)} KeyRepeatMinimum__KEYBOARD_ATTRIBUTESInv(x) == x - 16);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 16, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 16, 1) == KeyRepeatMinimum__KEYBOARD_ATTRIBUTESInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 16)} MINUS_LEFT_PTR(x, 1, 16) == KeyRepeatMinimum__KEYBOARD_ATTRIBUTESInv(x));
+function KeyboardAttributes__DEVICE_EXTENSION(int) returns (int);
+function KeyboardAttributes__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_KeyboardAttributes__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_KeyboardAttributes__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {KeyboardAttributes__DEVICE_EXTENSIONInv(KeyboardAttributes__DEVICE_EXTENSION(x))} KeyboardAttributes__DEVICE_EXTENSIONInv(KeyboardAttributes__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {KeyboardAttributes__DEVICE_EXTENSIONInv(x)} KeyboardAttributes__DEVICE_EXTENSION(KeyboardAttributes__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_KeyboardAttributes__DEVICE_EXTENSION(S)[x]} _S_KeyboardAttributes__DEVICE_EXTENSION(S)[x] <==> S[KeyboardAttributes__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_KeyboardAttributes__DEVICE_EXTENSIONInv(S)[x]} _S_KeyboardAttributes__DEVICE_EXTENSIONInv(S)[x] <==> S[KeyboardAttributes__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_KeyboardAttributes__DEVICE_EXTENSION(S)} S[x] ==> _S_KeyboardAttributes__DEVICE_EXTENSION(S)[KeyboardAttributes__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_KeyboardAttributes__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_KeyboardAttributes__DEVICE_EXTENSIONInv(S)[KeyboardAttributes__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {KeyboardAttributes__DEVICE_EXTENSION(x)} KeyboardAttributes__DEVICE_EXTENSION(x) == x + 140);
+axiom (forall x:int :: {KeyboardAttributes__DEVICE_EXTENSIONInv(x)} KeyboardAttributes__DEVICE_EXTENSIONInv(x) == x - 140);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 140, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 140, 1) == KeyboardAttributes__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 140)} MINUS_LEFT_PTR(x, 1, 140) == KeyboardAttributes__DEVICE_EXTENSIONInv(x));
+function KeyboardIdentifier__KEYBOARD_ATTRIBUTES(int) returns (int);
+function KeyboardIdentifier__KEYBOARD_ATTRIBUTESInv(int) returns (int);
+function _S_KeyboardIdentifier__KEYBOARD_ATTRIBUTES([int]bool) returns ([int]bool);
+function _S_KeyboardIdentifier__KEYBOARD_ATTRIBUTESInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {KeyboardIdentifier__KEYBOARD_ATTRIBUTESInv(KeyboardIdentifier__KEYBOARD_ATTRIBUTES(x))} KeyboardIdentifier__KEYBOARD_ATTRIBUTESInv(KeyboardIdentifier__KEYBOARD_ATTRIBUTES(x)) == x);
+axiom (forall x:int :: {KeyboardIdentifier__KEYBOARD_ATTRIBUTESInv(x)} KeyboardIdentifier__KEYBOARD_ATTRIBUTES(KeyboardIdentifier__KEYBOARD_ATTRIBUTESInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_KeyboardIdentifier__KEYBOARD_ATTRIBUTES(S)[x]} _S_KeyboardIdentifier__KEYBOARD_ATTRIBUTES(S)[x] <==> S[KeyboardIdentifier__KEYBOARD_ATTRIBUTESInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_KeyboardIdentifier__KEYBOARD_ATTRIBUTESInv(S)[x]} _S_KeyboardIdentifier__KEYBOARD_ATTRIBUTESInv(S)[x] <==> S[KeyboardIdentifier__KEYBOARD_ATTRIBUTES(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_KeyboardIdentifier__KEYBOARD_ATTRIBUTES(S)} S[x] ==> _S_KeyboardIdentifier__KEYBOARD_ATTRIBUTES(S)[KeyboardIdentifier__KEYBOARD_ATTRIBUTES(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_KeyboardIdentifier__KEYBOARD_ATTRIBUTESInv(S)} S[x] ==> _S_KeyboardIdentifier__KEYBOARD_ATTRIBUTESInv(S)[KeyboardIdentifier__KEYBOARD_ATTRIBUTESInv(x)]);
+
+axiom (forall x:int :: {KeyboardIdentifier__KEYBOARD_ATTRIBUTES(x)} KeyboardIdentifier__KEYBOARD_ATTRIBUTES(x) == x + 0);
+axiom (forall x:int :: {KeyboardIdentifier__KEYBOARD_ATTRIBUTESInv(x)} KeyboardIdentifier__KEYBOARD_ATTRIBUTESInv(x) == x - 0);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1) == KeyboardIdentifier__KEYBOARD_ATTRIBUTESInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 0)} MINUS_LEFT_PTR(x, 1, 0) == KeyboardIdentifier__KEYBOARD_ATTRIBUTESInv(x));
+function KeyboardMode__KEYBOARD_ATTRIBUTES(int) returns (int);
+function KeyboardMode__KEYBOARD_ATTRIBUTESInv(int) returns (int);
+function _S_KeyboardMode__KEYBOARD_ATTRIBUTES([int]bool) returns ([int]bool);
+function _S_KeyboardMode__KEYBOARD_ATTRIBUTESInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {KeyboardMode__KEYBOARD_ATTRIBUTESInv(KeyboardMode__KEYBOARD_ATTRIBUTES(x))} KeyboardMode__KEYBOARD_ATTRIBUTESInv(KeyboardMode__KEYBOARD_ATTRIBUTES(x)) == x);
+axiom (forall x:int :: {KeyboardMode__KEYBOARD_ATTRIBUTESInv(x)} KeyboardMode__KEYBOARD_ATTRIBUTES(KeyboardMode__KEYBOARD_ATTRIBUTESInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_KeyboardMode__KEYBOARD_ATTRIBUTES(S)[x]} _S_KeyboardMode__KEYBOARD_ATTRIBUTES(S)[x] <==> S[KeyboardMode__KEYBOARD_ATTRIBUTESInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_KeyboardMode__KEYBOARD_ATTRIBUTESInv(S)[x]} _S_KeyboardMode__KEYBOARD_ATTRIBUTESInv(S)[x] <==> S[KeyboardMode__KEYBOARD_ATTRIBUTES(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_KeyboardMode__KEYBOARD_ATTRIBUTES(S)} S[x] ==> _S_KeyboardMode__KEYBOARD_ATTRIBUTES(S)[KeyboardMode__KEYBOARD_ATTRIBUTES(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_KeyboardMode__KEYBOARD_ATTRIBUTESInv(S)} S[x] ==> _S_KeyboardMode__KEYBOARD_ATTRIBUTESInv(S)[KeyboardMode__KEYBOARD_ATTRIBUTESInv(x)]);
+
+axiom (forall x:int :: {KeyboardMode__KEYBOARD_ATTRIBUTES(x)} KeyboardMode__KEYBOARD_ATTRIBUTES(x) == x + 2);
+axiom (forall x:int :: {KeyboardMode__KEYBOARD_ATTRIBUTESInv(x)} KeyboardMode__KEYBOARD_ATTRIBUTESInv(x) == x - 2);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 2, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 2, 1) == KeyboardMode__KEYBOARD_ATTRIBUTESInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 2)} MINUS_LEFT_PTR(x, 1, 2) == KeyboardMode__KEYBOARD_ATTRIBUTESInv(x));
+function LedFlags__KEYBOARD_INDICATOR_PARAMETERS(int) returns (int);
+function LedFlags__KEYBOARD_INDICATOR_PARAMETERSInv(int) returns (int);
+function _S_LedFlags__KEYBOARD_INDICATOR_PARAMETERS([int]bool) returns ([int]bool);
+function _S_LedFlags__KEYBOARD_INDICATOR_PARAMETERSInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {LedFlags__KEYBOARD_INDICATOR_PARAMETERSInv(LedFlags__KEYBOARD_INDICATOR_PARAMETERS(x))} LedFlags__KEYBOARD_INDICATOR_PARAMETERSInv(LedFlags__KEYBOARD_INDICATOR_PARAMETERS(x)) == x);
+axiom (forall x:int :: {LedFlags__KEYBOARD_INDICATOR_PARAMETERSInv(x)} LedFlags__KEYBOARD_INDICATOR_PARAMETERS(LedFlags__KEYBOARD_INDICATOR_PARAMETERSInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_LedFlags__KEYBOARD_INDICATOR_PARAMETERS(S)[x]} _S_LedFlags__KEYBOARD_INDICATOR_PARAMETERS(S)[x] <==> S[LedFlags__KEYBOARD_INDICATOR_PARAMETERSInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_LedFlags__KEYBOARD_INDICATOR_PARAMETERSInv(S)[x]} _S_LedFlags__KEYBOARD_INDICATOR_PARAMETERSInv(S)[x] <==> S[LedFlags__KEYBOARD_INDICATOR_PARAMETERS(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_LedFlags__KEYBOARD_INDICATOR_PARAMETERS(S)} S[x] ==> _S_LedFlags__KEYBOARD_INDICATOR_PARAMETERS(S)[LedFlags__KEYBOARD_INDICATOR_PARAMETERS(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_LedFlags__KEYBOARD_INDICATOR_PARAMETERSInv(S)} S[x] ==> _S_LedFlags__KEYBOARD_INDICATOR_PARAMETERSInv(S)[LedFlags__KEYBOARD_INDICATOR_PARAMETERSInv(x)]);
+
+axiom (forall x:int :: {LedFlags__KEYBOARD_INDICATOR_PARAMETERS(x)} LedFlags__KEYBOARD_INDICATOR_PARAMETERS(x) == x + 2);
+axiom (forall x:int :: {LedFlags__KEYBOARD_INDICATOR_PARAMETERSInv(x)} LedFlags__KEYBOARD_INDICATOR_PARAMETERSInv(x) == x - 2);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 2, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 2, 1) == LedFlags__KEYBOARD_INDICATOR_PARAMETERSInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 2)} MINUS_LEFT_PTR(x, 1, 2) == LedFlags__KEYBOARD_INDICATOR_PARAMETERSInv(x));
+function LegacyDeviceList__GLOBALS(int) returns (int);
+function LegacyDeviceList__GLOBALSInv(int) returns (int);
+function _S_LegacyDeviceList__GLOBALS([int]bool) returns ([int]bool);
+function _S_LegacyDeviceList__GLOBALSInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {LegacyDeviceList__GLOBALSInv(LegacyDeviceList__GLOBALS(x))} LegacyDeviceList__GLOBALSInv(LegacyDeviceList__GLOBALS(x)) == x);
+axiom (forall x:int :: {LegacyDeviceList__GLOBALSInv(x)} LegacyDeviceList__GLOBALS(LegacyDeviceList__GLOBALSInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_LegacyDeviceList__GLOBALS(S)[x]} _S_LegacyDeviceList__GLOBALS(S)[x] <==> S[LegacyDeviceList__GLOBALSInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_LegacyDeviceList__GLOBALSInv(S)[x]} _S_LegacyDeviceList__GLOBALSInv(S)[x] <==> S[LegacyDeviceList__GLOBALS(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_LegacyDeviceList__GLOBALS(S)} S[x] ==> _S_LegacyDeviceList__GLOBALS(S)[LegacyDeviceList__GLOBALS(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_LegacyDeviceList__GLOBALSInv(S)} S[x] ==> _S_LegacyDeviceList__GLOBALSInv(S)[LegacyDeviceList__GLOBALSInv(x)]);
+
+axiom (forall x:int :: {LegacyDeviceList__GLOBALS(x)} LegacyDeviceList__GLOBALS(x) == x + 888);
+axiom (forall x:int :: {LegacyDeviceList__GLOBALSInv(x)} LegacyDeviceList__GLOBALSInv(x) == x - 888);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 888, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 888, 1) == LegacyDeviceList__GLOBALSInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 888)} MINUS_LEFT_PTR(x, 1, 888) == LegacyDeviceList__GLOBALSInv(x));
+function Length__UNICODE_STRING(int) returns (int);
+function Length__UNICODE_STRINGInv(int) returns (int);
+function _S_Length__UNICODE_STRING([int]bool) returns ([int]bool);
+function _S_Length__UNICODE_STRINGInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {Length__UNICODE_STRINGInv(Length__UNICODE_STRING(x))} Length__UNICODE_STRINGInv(Length__UNICODE_STRING(x)) == x);
+axiom (forall x:int :: {Length__UNICODE_STRINGInv(x)} Length__UNICODE_STRING(Length__UNICODE_STRINGInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_Length__UNICODE_STRING(S)[x]} _S_Length__UNICODE_STRING(S)[x] <==> S[Length__UNICODE_STRINGInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_Length__UNICODE_STRINGInv(S)[x]} _S_Length__UNICODE_STRINGInv(S)[x] <==> S[Length__UNICODE_STRING(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Length__UNICODE_STRING(S)} S[x] ==> _S_Length__UNICODE_STRING(S)[Length__UNICODE_STRING(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Length__UNICODE_STRINGInv(S)} S[x] ==> _S_Length__UNICODE_STRINGInv(S)[Length__UNICODE_STRINGInv(x)]);
+
+axiom (forall x:int :: {Length__UNICODE_STRING(x)} Length__UNICODE_STRING(x) == x + 0);
+axiom (forall x:int :: {Length__UNICODE_STRINGInv(x)} Length__UNICODE_STRINGInv(x) == x - 0);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1) == Length__UNICODE_STRINGInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 0)} MINUS_LEFT_PTR(x, 1, 0) == Length__UNICODE_STRINGInv(x));
+function Link__DEVICE_EXTENSION(int) returns (int);
+function Link__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_Link__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_Link__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {Link__DEVICE_EXTENSIONInv(Link__DEVICE_EXTENSION(x))} Link__DEVICE_EXTENSIONInv(Link__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {Link__DEVICE_EXTENSIONInv(x)} Link__DEVICE_EXTENSION(Link__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_Link__DEVICE_EXTENSION(S)[x]} _S_Link__DEVICE_EXTENSION(S)[x] <==> S[Link__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_Link__DEVICE_EXTENSIONInv(S)[x]} _S_Link__DEVICE_EXTENSIONInv(S)[x] <==> S[Link__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Link__DEVICE_EXTENSION(S)} S[x] ==> _S_Link__DEVICE_EXTENSION(S)[Link__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Link__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_Link__DEVICE_EXTENSIONInv(S)[Link__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {Link__DEVICE_EXTENSION(x)} Link__DEVICE_EXTENSION(x) == x + 272);
+axiom (forall x:int :: {Link__DEVICE_EXTENSIONInv(x)} Link__DEVICE_EXTENSIONInv(x) == x - 272);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 272, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 272, 1) == Link__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 272)} MINUS_LEFT_PTR(x, 1, 272) == Link__DEVICE_EXTENSIONInv(x));
+function LockList__IO_REMOVE_LOCK_DBG_BLOCK(int) returns (int);
+function LockList__IO_REMOVE_LOCK_DBG_BLOCKInv(int) returns (int);
+function _S_LockList__IO_REMOVE_LOCK_DBG_BLOCK([int]bool) returns ([int]bool);
+function _S_LockList__IO_REMOVE_LOCK_DBG_BLOCKInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {LockList__IO_REMOVE_LOCK_DBG_BLOCKInv(LockList__IO_REMOVE_LOCK_DBG_BLOCK(x))} LockList__IO_REMOVE_LOCK_DBG_BLOCKInv(LockList__IO_REMOVE_LOCK_DBG_BLOCK(x)) == x);
+axiom (forall x:int :: {LockList__IO_REMOVE_LOCK_DBG_BLOCKInv(x)} LockList__IO_REMOVE_LOCK_DBG_BLOCK(LockList__IO_REMOVE_LOCK_DBG_BLOCKInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_LockList__IO_REMOVE_LOCK_DBG_BLOCK(S)[x]} _S_LockList__IO_REMOVE_LOCK_DBG_BLOCK(S)[x] <==> S[LockList__IO_REMOVE_LOCK_DBG_BLOCKInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_LockList__IO_REMOVE_LOCK_DBG_BLOCKInv(S)[x]} _S_LockList__IO_REMOVE_LOCK_DBG_BLOCKInv(S)[x] <==> S[LockList__IO_REMOVE_LOCK_DBG_BLOCK(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_LockList__IO_REMOVE_LOCK_DBG_BLOCK(S)} S[x] ==> _S_LockList__IO_REMOVE_LOCK_DBG_BLOCK(S)[LockList__IO_REMOVE_LOCK_DBG_BLOCK(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_LockList__IO_REMOVE_LOCK_DBG_BLOCKInv(S)} S[x] ==> _S_LockList__IO_REMOVE_LOCK_DBG_BLOCKInv(S)[LockList__IO_REMOVE_LOCK_DBG_BLOCKInv(x)]);
+
+axiom (forall x:int :: {LockList__IO_REMOVE_LOCK_DBG_BLOCK(x)} LockList__IO_REMOVE_LOCK_DBG_BLOCK(x) == x + 20);
+axiom (forall x:int :: {LockList__IO_REMOVE_LOCK_DBG_BLOCKInv(x)} LockList__IO_REMOVE_LOCK_DBG_BLOCKInv(x) == x - 20);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 20, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 20, 1) == LockList__IO_REMOVE_LOCK_DBG_BLOCKInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 20)} MINUS_LEFT_PTR(x, 1, 20) == LockList__IO_REMOVE_LOCK_DBG_BLOCKInv(x));
+function Lock___unnamed_4_a97c65a1(int) returns (int);
+function Lock___unnamed_4_a97c65a1Inv(int) returns (int);
+function _S_Lock___unnamed_4_a97c65a1([int]bool) returns ([int]bool);
+function _S_Lock___unnamed_4_a97c65a1Inv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {Lock___unnamed_4_a97c65a1Inv(Lock___unnamed_4_a97c65a1(x))} Lock___unnamed_4_a97c65a1Inv(Lock___unnamed_4_a97c65a1(x)) == x);
+axiom (forall x:int :: {Lock___unnamed_4_a97c65a1Inv(x)} Lock___unnamed_4_a97c65a1(Lock___unnamed_4_a97c65a1Inv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_Lock___unnamed_4_a97c65a1(S)[x]} _S_Lock___unnamed_4_a97c65a1(S)[x] <==> S[Lock___unnamed_4_a97c65a1Inv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_Lock___unnamed_4_a97c65a1Inv(S)[x]} _S_Lock___unnamed_4_a97c65a1Inv(S)[x] <==> S[Lock___unnamed_4_a97c65a1(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Lock___unnamed_4_a97c65a1(S)} S[x] ==> _S_Lock___unnamed_4_a97c65a1(S)[Lock___unnamed_4_a97c65a1(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Lock___unnamed_4_a97c65a1Inv(S)} S[x] ==> _S_Lock___unnamed_4_a97c65a1Inv(S)[Lock___unnamed_4_a97c65a1Inv(x)]);
+
+axiom (forall x:int :: {Lock___unnamed_4_a97c65a1(x)} Lock___unnamed_4_a97c65a1(x) == x + 0);
+axiom (forall x:int :: {Lock___unnamed_4_a97c65a1Inv(x)} Lock___unnamed_4_a97c65a1Inv(x) == x - 0);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1) == Lock___unnamed_4_a97c65a1Inv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 0)} MINUS_LEFT_PTR(x, 1, 0) == Lock___unnamed_4_a97c65a1Inv(x));
+function LowMemoryCount__IO_REMOVE_LOCK_DBG_BLOCK(int) returns (int);
+function LowMemoryCount__IO_REMOVE_LOCK_DBG_BLOCKInv(int) returns (int);
+function _S_LowMemoryCount__IO_REMOVE_LOCK_DBG_BLOCK([int]bool) returns ([int]bool);
+function _S_LowMemoryCount__IO_REMOVE_LOCK_DBG_BLOCKInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {LowMemoryCount__IO_REMOVE_LOCK_DBG_BLOCKInv(LowMemoryCount__IO_REMOVE_LOCK_DBG_BLOCK(x))} LowMemoryCount__IO_REMOVE_LOCK_DBG_BLOCKInv(LowMemoryCount__IO_REMOVE_LOCK_DBG_BLOCK(x)) == x);
+axiom (forall x:int :: {LowMemoryCount__IO_REMOVE_LOCK_DBG_BLOCKInv(x)} LowMemoryCount__IO_REMOVE_LOCK_DBG_BLOCK(LowMemoryCount__IO_REMOVE_LOCK_DBG_BLOCKInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_LowMemoryCount__IO_REMOVE_LOCK_DBG_BLOCK(S)[x]} _S_LowMemoryCount__IO_REMOVE_LOCK_DBG_BLOCK(S)[x] <==> S[LowMemoryCount__IO_REMOVE_LOCK_DBG_BLOCKInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_LowMemoryCount__IO_REMOVE_LOCK_DBG_BLOCKInv(S)[x]} _S_LowMemoryCount__IO_REMOVE_LOCK_DBG_BLOCKInv(S)[x] <==> S[LowMemoryCount__IO_REMOVE_LOCK_DBG_BLOCK(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_LowMemoryCount__IO_REMOVE_LOCK_DBG_BLOCK(S)} S[x] ==> _S_LowMemoryCount__IO_REMOVE_LOCK_DBG_BLOCK(S)[LowMemoryCount__IO_REMOVE_LOCK_DBG_BLOCK(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_LowMemoryCount__IO_REMOVE_LOCK_DBG_BLOCKInv(S)} S[x] ==> _S_LowMemoryCount__IO_REMOVE_LOCK_DBG_BLOCKInv(S)[LowMemoryCount__IO_REMOVE_LOCK_DBG_BLOCKInv(x)]);
+
+axiom (forall x:int :: {LowMemoryCount__IO_REMOVE_LOCK_DBG_BLOCK(x)} LowMemoryCount__IO_REMOVE_LOCK_DBG_BLOCK(x) == x + 32);
+axiom (forall x:int :: {LowMemoryCount__IO_REMOVE_LOCK_DBG_BLOCKInv(x)} LowMemoryCount__IO_REMOVE_LOCK_DBG_BLOCKInv(x) == x - 32);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 32, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 32, 1) == LowMemoryCount__IO_REMOVE_LOCK_DBG_BLOCKInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 32)} MINUS_LEFT_PTR(x, 1, 32) == LowMemoryCount__IO_REMOVE_LOCK_DBG_BLOCKInv(x));
+function MaxLockedTicks__IO_REMOVE_LOCK_DBG_BLOCK(int) returns (int);
+function MaxLockedTicks__IO_REMOVE_LOCK_DBG_BLOCKInv(int) returns (int);
+function _S_MaxLockedTicks__IO_REMOVE_LOCK_DBG_BLOCK([int]bool) returns ([int]bool);
+function _S_MaxLockedTicks__IO_REMOVE_LOCK_DBG_BLOCKInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {MaxLockedTicks__IO_REMOVE_LOCK_DBG_BLOCKInv(MaxLockedTicks__IO_REMOVE_LOCK_DBG_BLOCK(x))} MaxLockedTicks__IO_REMOVE_LOCK_DBG_BLOCKInv(MaxLockedTicks__IO_REMOVE_LOCK_DBG_BLOCK(x)) == x);
+axiom (forall x:int :: {MaxLockedTicks__IO_REMOVE_LOCK_DBG_BLOCKInv(x)} MaxLockedTicks__IO_REMOVE_LOCK_DBG_BLOCK(MaxLockedTicks__IO_REMOVE_LOCK_DBG_BLOCKInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_MaxLockedTicks__IO_REMOVE_LOCK_DBG_BLOCK(S)[x]} _S_MaxLockedTicks__IO_REMOVE_LOCK_DBG_BLOCK(S)[x] <==> S[MaxLockedTicks__IO_REMOVE_LOCK_DBG_BLOCKInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_MaxLockedTicks__IO_REMOVE_LOCK_DBG_BLOCKInv(S)[x]} _S_MaxLockedTicks__IO_REMOVE_LOCK_DBG_BLOCKInv(S)[x] <==> S[MaxLockedTicks__IO_REMOVE_LOCK_DBG_BLOCK(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_MaxLockedTicks__IO_REMOVE_LOCK_DBG_BLOCK(S)} S[x] ==> _S_MaxLockedTicks__IO_REMOVE_LOCK_DBG_BLOCK(S)[MaxLockedTicks__IO_REMOVE_LOCK_DBG_BLOCK(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_MaxLockedTicks__IO_REMOVE_LOCK_DBG_BLOCKInv(S)} S[x] ==> _S_MaxLockedTicks__IO_REMOVE_LOCK_DBG_BLOCKInv(S)[MaxLockedTicks__IO_REMOVE_LOCK_DBG_BLOCKInv(x)]);
+
+axiom (forall x:int :: {MaxLockedTicks__IO_REMOVE_LOCK_DBG_BLOCK(x)} MaxLockedTicks__IO_REMOVE_LOCK_DBG_BLOCK(x) == x + 8);
+axiom (forall x:int :: {MaxLockedTicks__IO_REMOVE_LOCK_DBG_BLOCKInv(x)} MaxLockedTicks__IO_REMOVE_LOCK_DBG_BLOCKInv(x) == x - 8);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 8, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 8, 1) == MaxLockedTicks__IO_REMOVE_LOCK_DBG_BLOCKInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 8)} MINUS_LEFT_PTR(x, 1, 8) == MaxLockedTicks__IO_REMOVE_LOCK_DBG_BLOCKInv(x));
+function MaximumLength__UNICODE_STRING(int) returns (int);
+function MaximumLength__UNICODE_STRINGInv(int) returns (int);
+function _S_MaximumLength__UNICODE_STRING([int]bool) returns ([int]bool);
+function _S_MaximumLength__UNICODE_STRINGInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {MaximumLength__UNICODE_STRINGInv(MaximumLength__UNICODE_STRING(x))} MaximumLength__UNICODE_STRINGInv(MaximumLength__UNICODE_STRING(x)) == x);
+axiom (forall x:int :: {MaximumLength__UNICODE_STRINGInv(x)} MaximumLength__UNICODE_STRING(MaximumLength__UNICODE_STRINGInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_MaximumLength__UNICODE_STRING(S)[x]} _S_MaximumLength__UNICODE_STRING(S)[x] <==> S[MaximumLength__UNICODE_STRINGInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_MaximumLength__UNICODE_STRINGInv(S)[x]} _S_MaximumLength__UNICODE_STRINGInv(S)[x] <==> S[MaximumLength__UNICODE_STRING(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_MaximumLength__UNICODE_STRING(S)} S[x] ==> _S_MaximumLength__UNICODE_STRING(S)[MaximumLength__UNICODE_STRING(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_MaximumLength__UNICODE_STRINGInv(S)} S[x] ==> _S_MaximumLength__UNICODE_STRINGInv(S)[MaximumLength__UNICODE_STRINGInv(x)]);
+
+axiom (forall x:int :: {MaximumLength__UNICODE_STRING(x)} MaximumLength__UNICODE_STRING(x) == x + 2);
+axiom (forall x:int :: {MaximumLength__UNICODE_STRINGInv(x)} MaximumLength__UNICODE_STRINGInv(x) == x - 2);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 2, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 2, 1) == MaximumLength__UNICODE_STRINGInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 2)} MINUS_LEFT_PTR(x, 1, 2) == MaximumLength__UNICODE_STRINGInv(x));
+function MinDeviceWakeState__DEVICE_EXTENSION(int) returns (int);
+function MinDeviceWakeState__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_MinDeviceWakeState__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_MinDeviceWakeState__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {MinDeviceWakeState__DEVICE_EXTENSIONInv(MinDeviceWakeState__DEVICE_EXTENSION(x))} MinDeviceWakeState__DEVICE_EXTENSIONInv(MinDeviceWakeState__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {MinDeviceWakeState__DEVICE_EXTENSIONInv(x)} MinDeviceWakeState__DEVICE_EXTENSION(MinDeviceWakeState__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_MinDeviceWakeState__DEVICE_EXTENSION(S)[x]} _S_MinDeviceWakeState__DEVICE_EXTENSION(S)[x] <==> S[MinDeviceWakeState__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_MinDeviceWakeState__DEVICE_EXTENSIONInv(S)[x]} _S_MinDeviceWakeState__DEVICE_EXTENSIONInv(S)[x] <==> S[MinDeviceWakeState__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_MinDeviceWakeState__DEVICE_EXTENSION(S)} S[x] ==> _S_MinDeviceWakeState__DEVICE_EXTENSION(S)[MinDeviceWakeState__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_MinDeviceWakeState__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_MinDeviceWakeState__DEVICE_EXTENSIONInv(S)[MinDeviceWakeState__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {MinDeviceWakeState__DEVICE_EXTENSION(x)} MinDeviceWakeState__DEVICE_EXTENSION(x) == x + 252);
+axiom (forall x:int :: {MinDeviceWakeState__DEVICE_EXTENSIONInv(x)} MinDeviceWakeState__DEVICE_EXTENSIONInv(x) == x - 252);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 252, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 252, 1) == MinDeviceWakeState__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 252)} MINUS_LEFT_PTR(x, 1, 252) == MinDeviceWakeState__DEVICE_EXTENSIONInv(x));
+function MinSystemWakeState__DEVICE_EXTENSION(int) returns (int);
+function MinSystemWakeState__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_MinSystemWakeState__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_MinSystemWakeState__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {MinSystemWakeState__DEVICE_EXTENSIONInv(MinSystemWakeState__DEVICE_EXTENSION(x))} MinSystemWakeState__DEVICE_EXTENSIONInv(MinSystemWakeState__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {MinSystemWakeState__DEVICE_EXTENSIONInv(x)} MinSystemWakeState__DEVICE_EXTENSION(MinSystemWakeState__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_MinSystemWakeState__DEVICE_EXTENSION(S)[x]} _S_MinSystemWakeState__DEVICE_EXTENSION(S)[x] <==> S[MinSystemWakeState__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_MinSystemWakeState__DEVICE_EXTENSIONInv(S)[x]} _S_MinSystemWakeState__DEVICE_EXTENSIONInv(S)[x] <==> S[MinSystemWakeState__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_MinSystemWakeState__DEVICE_EXTENSION(S)} S[x] ==> _S_MinSystemWakeState__DEVICE_EXTENSION(S)[MinSystemWakeState__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_MinSystemWakeState__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_MinSystemWakeState__DEVICE_EXTENSIONInv(S)[MinSystemWakeState__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {MinSystemWakeState__DEVICE_EXTENSION(x)} MinSystemWakeState__DEVICE_EXTENSION(x) == x + 256);
+axiom (forall x:int :: {MinSystemWakeState__DEVICE_EXTENSIONInv(x)} MinSystemWakeState__DEVICE_EXTENSIONInv(x) == x - 256);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 256, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 256, 1) == MinSystemWakeState__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 256)} MINUS_LEFT_PTR(x, 1, 256) == MinSystemWakeState__DEVICE_EXTENSIONInv(x));
+function Mutex__GLOBALS(int) returns (int);
+function Mutex__GLOBALSInv(int) returns (int);
+function _S_Mutex__GLOBALS([int]bool) returns ([int]bool);
+function _S_Mutex__GLOBALSInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {Mutex__GLOBALSInv(Mutex__GLOBALS(x))} Mutex__GLOBALSInv(Mutex__GLOBALS(x)) == x);
+axiom (forall x:int :: {Mutex__GLOBALSInv(x)} Mutex__GLOBALS(Mutex__GLOBALSInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_Mutex__GLOBALS(S)[x]} _S_Mutex__GLOBALS(S)[x] <==> S[Mutex__GLOBALSInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_Mutex__GLOBALSInv(S)[x]} _S_Mutex__GLOBALSInv(S)[x] <==> S[Mutex__GLOBALS(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Mutex__GLOBALS(S)} S[x] ==> _S_Mutex__GLOBALS(S)[Mutex__GLOBALS(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Mutex__GLOBALSInv(S)} S[x] ==> _S_Mutex__GLOBALSInv(S)[Mutex__GLOBALSInv(x)]);
+
+axiom (forall x:int :: {Mutex__GLOBALS(x)} Mutex__GLOBALS(x) == x + 24);
+axiom (forall x:int :: {Mutex__GLOBALSInv(x)} Mutex__GLOBALSInv(x) == x - 24);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 24, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 24, 1) == Mutex__GLOBALSInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 24)} MINUS_LEFT_PTR(x, 1, 24) == Mutex__GLOBALSInv(x));
+function NpxIrql___unnamed_1_29794256(int) returns (int);
+function NpxIrql___unnamed_1_29794256Inv(int) returns (int);
+function _S_NpxIrql___unnamed_1_29794256([int]bool) returns ([int]bool);
+function _S_NpxIrql___unnamed_1_29794256Inv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {NpxIrql___unnamed_1_29794256Inv(NpxIrql___unnamed_1_29794256(x))} NpxIrql___unnamed_1_29794256Inv(NpxIrql___unnamed_1_29794256(x)) == x);
+axiom (forall x:int :: {NpxIrql___unnamed_1_29794256Inv(x)} NpxIrql___unnamed_1_29794256(NpxIrql___unnamed_1_29794256Inv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_NpxIrql___unnamed_1_29794256(S)[x]} _S_NpxIrql___unnamed_1_29794256(S)[x] <==> S[NpxIrql___unnamed_1_29794256Inv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_NpxIrql___unnamed_1_29794256Inv(S)[x]} _S_NpxIrql___unnamed_1_29794256Inv(S)[x] <==> S[NpxIrql___unnamed_1_29794256(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_NpxIrql___unnamed_1_29794256(S)} S[x] ==> _S_NpxIrql___unnamed_1_29794256(S)[NpxIrql___unnamed_1_29794256(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_NpxIrql___unnamed_1_29794256Inv(S)} S[x] ==> _S_NpxIrql___unnamed_1_29794256Inv(S)[NpxIrql___unnamed_1_29794256Inv(x)]);
+
+axiom (forall x:int :: {NpxIrql___unnamed_1_29794256(x)} NpxIrql___unnamed_1_29794256(x) == x + 0);
+axiom (forall x:int :: {NpxIrql___unnamed_1_29794256Inv(x)} NpxIrql___unnamed_1_29794256Inv(x) == x - 0);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1) == NpxIrql___unnamed_1_29794256Inv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 0)} MINUS_LEFT_PTR(x, 1, 0) == NpxIrql___unnamed_1_29794256Inv(x));
+function NumberOfFunctionKeys__KEYBOARD_ATTRIBUTES(int) returns (int);
+function NumberOfFunctionKeys__KEYBOARD_ATTRIBUTESInv(int) returns (int);
+function _S_NumberOfFunctionKeys__KEYBOARD_ATTRIBUTES([int]bool) returns ([int]bool);
+function _S_NumberOfFunctionKeys__KEYBOARD_ATTRIBUTESInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {NumberOfFunctionKeys__KEYBOARD_ATTRIBUTESInv(NumberOfFunctionKeys__KEYBOARD_ATTRIBUTES(x))} NumberOfFunctionKeys__KEYBOARD_ATTRIBUTESInv(NumberOfFunctionKeys__KEYBOARD_ATTRIBUTES(x)) == x);
+axiom (forall x:int :: {NumberOfFunctionKeys__KEYBOARD_ATTRIBUTESInv(x)} NumberOfFunctionKeys__KEYBOARD_ATTRIBUTES(NumberOfFunctionKeys__KEYBOARD_ATTRIBUTESInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_NumberOfFunctionKeys__KEYBOARD_ATTRIBUTES(S)[x]} _S_NumberOfFunctionKeys__KEYBOARD_ATTRIBUTES(S)[x] <==> S[NumberOfFunctionKeys__KEYBOARD_ATTRIBUTESInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_NumberOfFunctionKeys__KEYBOARD_ATTRIBUTESInv(S)[x]} _S_NumberOfFunctionKeys__KEYBOARD_ATTRIBUTESInv(S)[x] <==> S[NumberOfFunctionKeys__KEYBOARD_ATTRIBUTES(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_NumberOfFunctionKeys__KEYBOARD_ATTRIBUTES(S)} S[x] ==> _S_NumberOfFunctionKeys__KEYBOARD_ATTRIBUTES(S)[NumberOfFunctionKeys__KEYBOARD_ATTRIBUTES(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_NumberOfFunctionKeys__KEYBOARD_ATTRIBUTESInv(S)} S[x] ==> _S_NumberOfFunctionKeys__KEYBOARD_ATTRIBUTESInv(S)[NumberOfFunctionKeys__KEYBOARD_ATTRIBUTESInv(x)]);
+
+axiom (forall x:int :: {NumberOfFunctionKeys__KEYBOARD_ATTRIBUTES(x)} NumberOfFunctionKeys__KEYBOARD_ATTRIBUTES(x) == x + 4);
+axiom (forall x:int :: {NumberOfFunctionKeys__KEYBOARD_ATTRIBUTESInv(x)} NumberOfFunctionKeys__KEYBOARD_ATTRIBUTESInv(x) == x - 4);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 4, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 4, 1) == NumberOfFunctionKeys__KEYBOARD_ATTRIBUTESInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 4)} MINUS_LEFT_PTR(x, 1, 4) == NumberOfFunctionKeys__KEYBOARD_ATTRIBUTESInv(x));
+function NumberOfIndicators__KEYBOARD_ATTRIBUTES(int) returns (int);
+function NumberOfIndicators__KEYBOARD_ATTRIBUTESInv(int) returns (int);
+function _S_NumberOfIndicators__KEYBOARD_ATTRIBUTES([int]bool) returns ([int]bool);
+function _S_NumberOfIndicators__KEYBOARD_ATTRIBUTESInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {NumberOfIndicators__KEYBOARD_ATTRIBUTESInv(NumberOfIndicators__KEYBOARD_ATTRIBUTES(x))} NumberOfIndicators__KEYBOARD_ATTRIBUTESInv(NumberOfIndicators__KEYBOARD_ATTRIBUTES(x)) == x);
+axiom (forall x:int :: {NumberOfIndicators__KEYBOARD_ATTRIBUTESInv(x)} NumberOfIndicators__KEYBOARD_ATTRIBUTES(NumberOfIndicators__KEYBOARD_ATTRIBUTESInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_NumberOfIndicators__KEYBOARD_ATTRIBUTES(S)[x]} _S_NumberOfIndicators__KEYBOARD_ATTRIBUTES(S)[x] <==> S[NumberOfIndicators__KEYBOARD_ATTRIBUTESInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_NumberOfIndicators__KEYBOARD_ATTRIBUTESInv(S)[x]} _S_NumberOfIndicators__KEYBOARD_ATTRIBUTESInv(S)[x] <==> S[NumberOfIndicators__KEYBOARD_ATTRIBUTES(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_NumberOfIndicators__KEYBOARD_ATTRIBUTES(S)} S[x] ==> _S_NumberOfIndicators__KEYBOARD_ATTRIBUTES(S)[NumberOfIndicators__KEYBOARD_ATTRIBUTES(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_NumberOfIndicators__KEYBOARD_ATTRIBUTESInv(S)} S[x] ==> _S_NumberOfIndicators__KEYBOARD_ATTRIBUTESInv(S)[NumberOfIndicators__KEYBOARD_ATTRIBUTESInv(x)]);
+
+axiom (forall x:int :: {NumberOfIndicators__KEYBOARD_ATTRIBUTES(x)} NumberOfIndicators__KEYBOARD_ATTRIBUTES(x) == x + 6);
+axiom (forall x:int :: {NumberOfIndicators__KEYBOARD_ATTRIBUTESInv(x)} NumberOfIndicators__KEYBOARD_ATTRIBUTESInv(x) == x - 6);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 6, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 6, 1) == NumberOfIndicators__KEYBOARD_ATTRIBUTESInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 6)} MINUS_LEFT_PTR(x, 1, 6) == NumberOfIndicators__KEYBOARD_ATTRIBUTESInv(x));
+function NumberOfKeysTotal__KEYBOARD_ATTRIBUTES(int) returns (int);
+function NumberOfKeysTotal__KEYBOARD_ATTRIBUTESInv(int) returns (int);
+function _S_NumberOfKeysTotal__KEYBOARD_ATTRIBUTES([int]bool) returns ([int]bool);
+function _S_NumberOfKeysTotal__KEYBOARD_ATTRIBUTESInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {NumberOfKeysTotal__KEYBOARD_ATTRIBUTESInv(NumberOfKeysTotal__KEYBOARD_ATTRIBUTES(x))} NumberOfKeysTotal__KEYBOARD_ATTRIBUTESInv(NumberOfKeysTotal__KEYBOARD_ATTRIBUTES(x)) == x);
+axiom (forall x:int :: {NumberOfKeysTotal__KEYBOARD_ATTRIBUTESInv(x)} NumberOfKeysTotal__KEYBOARD_ATTRIBUTES(NumberOfKeysTotal__KEYBOARD_ATTRIBUTESInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_NumberOfKeysTotal__KEYBOARD_ATTRIBUTES(S)[x]} _S_NumberOfKeysTotal__KEYBOARD_ATTRIBUTES(S)[x] <==> S[NumberOfKeysTotal__KEYBOARD_ATTRIBUTESInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_NumberOfKeysTotal__KEYBOARD_ATTRIBUTESInv(S)[x]} _S_NumberOfKeysTotal__KEYBOARD_ATTRIBUTESInv(S)[x] <==> S[NumberOfKeysTotal__KEYBOARD_ATTRIBUTES(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_NumberOfKeysTotal__KEYBOARD_ATTRIBUTES(S)} S[x] ==> _S_NumberOfKeysTotal__KEYBOARD_ATTRIBUTES(S)[NumberOfKeysTotal__KEYBOARD_ATTRIBUTES(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_NumberOfKeysTotal__KEYBOARD_ATTRIBUTESInv(S)} S[x] ==> _S_NumberOfKeysTotal__KEYBOARD_ATTRIBUTESInv(S)[NumberOfKeysTotal__KEYBOARD_ATTRIBUTESInv(x)]);
+
+axiom (forall x:int :: {NumberOfKeysTotal__KEYBOARD_ATTRIBUTES(x)} NumberOfKeysTotal__KEYBOARD_ATTRIBUTES(x) == x + 8);
+axiom (forall x:int :: {NumberOfKeysTotal__KEYBOARD_ATTRIBUTESInv(x)} NumberOfKeysTotal__KEYBOARD_ATTRIBUTESInv(x) == x - 8);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 8, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 8, 1) == NumberOfKeysTotal__KEYBOARD_ATTRIBUTESInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 8)} MINUS_LEFT_PTR(x, 1, 8) == NumberOfKeysTotal__KEYBOARD_ATTRIBUTESInv(x));
+function OkayToLogOverflow__DEVICE_EXTENSION(int) returns (int);
+function OkayToLogOverflow__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_OkayToLogOverflow__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_OkayToLogOverflow__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {OkayToLogOverflow__DEVICE_EXTENSIONInv(OkayToLogOverflow__DEVICE_EXTENSION(x))} OkayToLogOverflow__DEVICE_EXTENSIONInv(OkayToLogOverflow__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {OkayToLogOverflow__DEVICE_EXTENSIONInv(x)} OkayToLogOverflow__DEVICE_EXTENSION(OkayToLogOverflow__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_OkayToLogOverflow__DEVICE_EXTENSION(S)[x]} _S_OkayToLogOverflow__DEVICE_EXTENSION(S)[x] <==> S[OkayToLogOverflow__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_OkayToLogOverflow__DEVICE_EXTENSIONInv(S)[x]} _S_OkayToLogOverflow__DEVICE_EXTENSIONInv(S)[x] <==> S[OkayToLogOverflow__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_OkayToLogOverflow__DEVICE_EXTENSION(S)} S[x] ==> _S_OkayToLogOverflow__DEVICE_EXTENSION(S)[OkayToLogOverflow__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_OkayToLogOverflow__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_OkayToLogOverflow__DEVICE_EXTENSIONInv(S)[OkayToLogOverflow__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {OkayToLogOverflow__DEVICE_EXTENSION(x)} OkayToLogOverflow__DEVICE_EXTENSION(x) == x + 285);
+axiom (forall x:int :: {OkayToLogOverflow__DEVICE_EXTENSIONInv(x)} OkayToLogOverflow__DEVICE_EXTENSIONInv(x) == x - 285);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 285, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 285, 1) == OkayToLogOverflow__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 285)} MINUS_LEFT_PTR(x, 1, 285) == OkayToLogOverflow__DEVICE_EXTENSIONInv(x));
+function PDO__DEVICE_EXTENSION(int) returns (int);
+function PDO__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_PDO__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_PDO__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {PDO__DEVICE_EXTENSIONInv(PDO__DEVICE_EXTENSION(x))} PDO__DEVICE_EXTENSIONInv(PDO__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {PDO__DEVICE_EXTENSIONInv(x)} PDO__DEVICE_EXTENSION(PDO__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_PDO__DEVICE_EXTENSION(S)[x]} _S_PDO__DEVICE_EXTENSION(S)[x] <==> S[PDO__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_PDO__DEVICE_EXTENSIONInv(S)[x]} _S_PDO__DEVICE_EXTENSIONInv(S)[x] <==> S[PDO__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_PDO__DEVICE_EXTENSION(S)} S[x] ==> _S_PDO__DEVICE_EXTENSION(S)[PDO__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_PDO__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_PDO__DEVICE_EXTENSIONInv(S)[PDO__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {PDO__DEVICE_EXTENSION(x)} PDO__DEVICE_EXTENSION(x) == x + 12);
+axiom (forall x:int :: {PDO__DEVICE_EXTENSIONInv(x)} PDO__DEVICE_EXTENSIONInv(x) == x - 12);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 12, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 12, 1) == PDO__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 12)} MINUS_LEFT_PTR(x, 1, 12) == PDO__DEVICE_EXTENSIONInv(x));
+function PnP__DEVICE_EXTENSION(int) returns (int);
+function PnP__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_PnP__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_PnP__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {PnP__DEVICE_EXTENSIONInv(PnP__DEVICE_EXTENSION(x))} PnP__DEVICE_EXTENSIONInv(PnP__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {PnP__DEVICE_EXTENSIONInv(x)} PnP__DEVICE_EXTENSION(PnP__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_PnP__DEVICE_EXTENSION(S)[x]} _S_PnP__DEVICE_EXTENSION(S)[x] <==> S[PnP__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_PnP__DEVICE_EXTENSIONInv(S)[x]} _S_PnP__DEVICE_EXTENSIONInv(S)[x] <==> S[PnP__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_PnP__DEVICE_EXTENSION(S)} S[x] ==> _S_PnP__DEVICE_EXTENSION(S)[PnP__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_PnP__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_PnP__DEVICE_EXTENSIONInv(S)[PnP__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {PnP__DEVICE_EXTENSION(x)} PnP__DEVICE_EXTENSION(x) == x + 104);
+axiom (forall x:int :: {PnP__DEVICE_EXTENSIONInv(x)} PnP__DEVICE_EXTENSIONInv(x) == x - 104);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 104, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 104, 1) == PnP__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 104)} MINUS_LEFT_PTR(x, 1, 104) == PnP__DEVICE_EXTENSIONInv(x));
+function QueryWmiDataBlock__WMILIB_CONTEXT(int) returns (int);
+function QueryWmiDataBlock__WMILIB_CONTEXTInv(int) returns (int);
+function _S_QueryWmiDataBlock__WMILIB_CONTEXT([int]bool) returns ([int]bool);
+function _S_QueryWmiDataBlock__WMILIB_CONTEXTInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {QueryWmiDataBlock__WMILIB_CONTEXTInv(QueryWmiDataBlock__WMILIB_CONTEXT(x))} QueryWmiDataBlock__WMILIB_CONTEXTInv(QueryWmiDataBlock__WMILIB_CONTEXT(x)) == x);
+axiom (forall x:int :: {QueryWmiDataBlock__WMILIB_CONTEXTInv(x)} QueryWmiDataBlock__WMILIB_CONTEXT(QueryWmiDataBlock__WMILIB_CONTEXTInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_QueryWmiDataBlock__WMILIB_CONTEXT(S)[x]} _S_QueryWmiDataBlock__WMILIB_CONTEXT(S)[x] <==> S[QueryWmiDataBlock__WMILIB_CONTEXTInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_QueryWmiDataBlock__WMILIB_CONTEXTInv(S)[x]} _S_QueryWmiDataBlock__WMILIB_CONTEXTInv(S)[x] <==> S[QueryWmiDataBlock__WMILIB_CONTEXT(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_QueryWmiDataBlock__WMILIB_CONTEXT(S)} S[x] ==> _S_QueryWmiDataBlock__WMILIB_CONTEXT(S)[QueryWmiDataBlock__WMILIB_CONTEXT(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_QueryWmiDataBlock__WMILIB_CONTEXTInv(S)} S[x] ==> _S_QueryWmiDataBlock__WMILIB_CONTEXTInv(S)[QueryWmiDataBlock__WMILIB_CONTEXTInv(x)]);
+
+axiom (forall x:int :: {QueryWmiDataBlock__WMILIB_CONTEXT(x)} QueryWmiDataBlock__WMILIB_CONTEXT(x) == x + 12);
+axiom (forall x:int :: {QueryWmiDataBlock__WMILIB_CONTEXTInv(x)} QueryWmiDataBlock__WMILIB_CONTEXTInv(x) == x - 12);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 12, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 12, 1) == QueryWmiDataBlock__WMILIB_CONTEXTInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 12)} MINUS_LEFT_PTR(x, 1, 12) == QueryWmiDataBlock__WMILIB_CONTEXTInv(x));
+function QueryWmiRegInfo__WMILIB_CONTEXT(int) returns (int);
+function QueryWmiRegInfo__WMILIB_CONTEXTInv(int) returns (int);
+function _S_QueryWmiRegInfo__WMILIB_CONTEXT([int]bool) returns ([int]bool);
+function _S_QueryWmiRegInfo__WMILIB_CONTEXTInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {QueryWmiRegInfo__WMILIB_CONTEXTInv(QueryWmiRegInfo__WMILIB_CONTEXT(x))} QueryWmiRegInfo__WMILIB_CONTEXTInv(QueryWmiRegInfo__WMILIB_CONTEXT(x)) == x);
+axiom (forall x:int :: {QueryWmiRegInfo__WMILIB_CONTEXTInv(x)} QueryWmiRegInfo__WMILIB_CONTEXT(QueryWmiRegInfo__WMILIB_CONTEXTInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_QueryWmiRegInfo__WMILIB_CONTEXT(S)[x]} _S_QueryWmiRegInfo__WMILIB_CONTEXT(S)[x] <==> S[QueryWmiRegInfo__WMILIB_CONTEXTInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_QueryWmiRegInfo__WMILIB_CONTEXTInv(S)[x]} _S_QueryWmiRegInfo__WMILIB_CONTEXTInv(S)[x] <==> S[QueryWmiRegInfo__WMILIB_CONTEXT(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_QueryWmiRegInfo__WMILIB_CONTEXT(S)} S[x] ==> _S_QueryWmiRegInfo__WMILIB_CONTEXT(S)[QueryWmiRegInfo__WMILIB_CONTEXT(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_QueryWmiRegInfo__WMILIB_CONTEXTInv(S)} S[x] ==> _S_QueryWmiRegInfo__WMILIB_CONTEXTInv(S)[QueryWmiRegInfo__WMILIB_CONTEXTInv(x)]);
+
+axiom (forall x:int :: {QueryWmiRegInfo__WMILIB_CONTEXT(x)} QueryWmiRegInfo__WMILIB_CONTEXT(x) == x + 8);
+axiom (forall x:int :: {QueryWmiRegInfo__WMILIB_CONTEXTInv(x)} QueryWmiRegInfo__WMILIB_CONTEXTInv(x) == x - 8);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 8, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 8, 1) == QueryWmiRegInfo__WMILIB_CONTEXTInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 8)} MINUS_LEFT_PTR(x, 1, 8) == QueryWmiRegInfo__WMILIB_CONTEXTInv(x));
+function Rate__KEYBOARD_TYPEMATIC_PARAMETERS(int) returns (int);
+function Rate__KEYBOARD_TYPEMATIC_PARAMETERSInv(int) returns (int);
+function _S_Rate__KEYBOARD_TYPEMATIC_PARAMETERS([int]bool) returns ([int]bool);
+function _S_Rate__KEYBOARD_TYPEMATIC_PARAMETERSInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {Rate__KEYBOARD_TYPEMATIC_PARAMETERSInv(Rate__KEYBOARD_TYPEMATIC_PARAMETERS(x))} Rate__KEYBOARD_TYPEMATIC_PARAMETERSInv(Rate__KEYBOARD_TYPEMATIC_PARAMETERS(x)) == x);
+axiom (forall x:int :: {Rate__KEYBOARD_TYPEMATIC_PARAMETERSInv(x)} Rate__KEYBOARD_TYPEMATIC_PARAMETERS(Rate__KEYBOARD_TYPEMATIC_PARAMETERSInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_Rate__KEYBOARD_TYPEMATIC_PARAMETERS(S)[x]} _S_Rate__KEYBOARD_TYPEMATIC_PARAMETERS(S)[x] <==> S[Rate__KEYBOARD_TYPEMATIC_PARAMETERSInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_Rate__KEYBOARD_TYPEMATIC_PARAMETERSInv(S)[x]} _S_Rate__KEYBOARD_TYPEMATIC_PARAMETERSInv(S)[x] <==> S[Rate__KEYBOARD_TYPEMATIC_PARAMETERS(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Rate__KEYBOARD_TYPEMATIC_PARAMETERS(S)} S[x] ==> _S_Rate__KEYBOARD_TYPEMATIC_PARAMETERS(S)[Rate__KEYBOARD_TYPEMATIC_PARAMETERS(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Rate__KEYBOARD_TYPEMATIC_PARAMETERSInv(S)} S[x] ==> _S_Rate__KEYBOARD_TYPEMATIC_PARAMETERSInv(S)[Rate__KEYBOARD_TYPEMATIC_PARAMETERSInv(x)]);
+
+axiom (forall x:int :: {Rate__KEYBOARD_TYPEMATIC_PARAMETERS(x)} Rate__KEYBOARD_TYPEMATIC_PARAMETERS(x) == x + 2);
+axiom (forall x:int :: {Rate__KEYBOARD_TYPEMATIC_PARAMETERSInv(x)} Rate__KEYBOARD_TYPEMATIC_PARAMETERSInv(x) == x - 2);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 2, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 2, 1) == Rate__KEYBOARD_TYPEMATIC_PARAMETERSInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 2)} MINUS_LEFT_PTR(x, 1, 2) == Rate__KEYBOARD_TYPEMATIC_PARAMETERSInv(x));
+function ReadQueue__DEVICE_EXTENSION(int) returns (int);
+function ReadQueue__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_ReadQueue__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_ReadQueue__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {ReadQueue__DEVICE_EXTENSIONInv(ReadQueue__DEVICE_EXTENSION(x))} ReadQueue__DEVICE_EXTENSIONInv(ReadQueue__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {ReadQueue__DEVICE_EXTENSIONInv(x)} ReadQueue__DEVICE_EXTENSION(ReadQueue__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_ReadQueue__DEVICE_EXTENSION(S)[x]} _S_ReadQueue__DEVICE_EXTENSION(S)[x] <==> S[ReadQueue__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_ReadQueue__DEVICE_EXTENSIONInv(S)[x]} _S_ReadQueue__DEVICE_EXTENSIONInv(S)[x] <==> S[ReadQueue__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_ReadQueue__DEVICE_EXTENSION(S)} S[x] ==> _S_ReadQueue__DEVICE_EXTENSION(S)[ReadQueue__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_ReadQueue__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_ReadQueue__DEVICE_EXTENSIONInv(S)[ReadQueue__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {ReadQueue__DEVICE_EXTENSION(x)} ReadQueue__DEVICE_EXTENSION(x) == x + 176);
+axiom (forall x:int :: {ReadQueue__DEVICE_EXTENSIONInv(x)} ReadQueue__DEVICE_EXTENSIONInv(x) == x - 176);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 176, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 176, 1) == ReadQueue__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 176)} MINUS_LEFT_PTR(x, 1, 176) == ReadQueue__DEVICE_EXTENSIONInv(x));
+function RemoveEvent__IO_REMOVE_LOCK_COMMON_BLOCK(int) returns (int);
+function RemoveEvent__IO_REMOVE_LOCK_COMMON_BLOCKInv(int) returns (int);
+function _S_RemoveEvent__IO_REMOVE_LOCK_COMMON_BLOCK([int]bool) returns ([int]bool);
+function _S_RemoveEvent__IO_REMOVE_LOCK_COMMON_BLOCKInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {RemoveEvent__IO_REMOVE_LOCK_COMMON_BLOCKInv(RemoveEvent__IO_REMOVE_LOCK_COMMON_BLOCK(x))} RemoveEvent__IO_REMOVE_LOCK_COMMON_BLOCKInv(RemoveEvent__IO_REMOVE_LOCK_COMMON_BLOCK(x)) == x);
+axiom (forall x:int :: {RemoveEvent__IO_REMOVE_LOCK_COMMON_BLOCKInv(x)} RemoveEvent__IO_REMOVE_LOCK_COMMON_BLOCK(RemoveEvent__IO_REMOVE_LOCK_COMMON_BLOCKInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_RemoveEvent__IO_REMOVE_LOCK_COMMON_BLOCK(S)[x]} _S_RemoveEvent__IO_REMOVE_LOCK_COMMON_BLOCK(S)[x] <==> S[RemoveEvent__IO_REMOVE_LOCK_COMMON_BLOCKInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_RemoveEvent__IO_REMOVE_LOCK_COMMON_BLOCKInv(S)[x]} _S_RemoveEvent__IO_REMOVE_LOCK_COMMON_BLOCKInv(S)[x] <==> S[RemoveEvent__IO_REMOVE_LOCK_COMMON_BLOCK(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_RemoveEvent__IO_REMOVE_LOCK_COMMON_BLOCK(S)} S[x] ==> _S_RemoveEvent__IO_REMOVE_LOCK_COMMON_BLOCK(S)[RemoveEvent__IO_REMOVE_LOCK_COMMON_BLOCK(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_RemoveEvent__IO_REMOVE_LOCK_COMMON_BLOCKInv(S)} S[x] ==> _S_RemoveEvent__IO_REMOVE_LOCK_COMMON_BLOCKInv(S)[RemoveEvent__IO_REMOVE_LOCK_COMMON_BLOCKInv(x)]);
+
+axiom (forall x:int :: {RemoveEvent__IO_REMOVE_LOCK_COMMON_BLOCK(x)} RemoveEvent__IO_REMOVE_LOCK_COMMON_BLOCK(x) == x + 8);
+axiom (forall x:int :: {RemoveEvent__IO_REMOVE_LOCK_COMMON_BLOCKInv(x)} RemoveEvent__IO_REMOVE_LOCK_COMMON_BLOCKInv(x) == x - 8);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 8, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 8, 1) == RemoveEvent__IO_REMOVE_LOCK_COMMON_BLOCKInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 8)} MINUS_LEFT_PTR(x, 1, 8) == RemoveEvent__IO_REMOVE_LOCK_COMMON_BLOCKInv(x));
+function RemoveLock__DEVICE_EXTENSION(int) returns (int);
+function RemoveLock__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_RemoveLock__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_RemoveLock__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {RemoveLock__DEVICE_EXTENSIONInv(RemoveLock__DEVICE_EXTENSION(x))} RemoveLock__DEVICE_EXTENSIONInv(RemoveLock__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {RemoveLock__DEVICE_EXTENSIONInv(x)} RemoveLock__DEVICE_EXTENSION(RemoveLock__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_RemoveLock__DEVICE_EXTENSION(S)[x]} _S_RemoveLock__DEVICE_EXTENSION(S)[x] <==> S[RemoveLock__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_RemoveLock__DEVICE_EXTENSIONInv(S)[x]} _S_RemoveLock__DEVICE_EXTENSIONInv(S)[x] <==> S[RemoveLock__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_RemoveLock__DEVICE_EXTENSION(S)} S[x] ==> _S_RemoveLock__DEVICE_EXTENSION(S)[RemoveLock__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_RemoveLock__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_RemoveLock__DEVICE_EXTENSIONInv(S)[RemoveLock__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {RemoveLock__DEVICE_EXTENSION(x)} RemoveLock__DEVICE_EXTENSION(x) == x + 16);
+axiom (forall x:int :: {RemoveLock__DEVICE_EXTENSIONInv(x)} RemoveLock__DEVICE_EXTENSIONInv(x) == x - 16);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 16, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 16, 1) == RemoveLock__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 16)} MINUS_LEFT_PTR(x, 1, 16) == RemoveLock__DEVICE_EXTENSIONInv(x));
+function Removed__IO_REMOVE_LOCK_COMMON_BLOCK(int) returns (int);
+function Removed__IO_REMOVE_LOCK_COMMON_BLOCKInv(int) returns (int);
+function _S_Removed__IO_REMOVE_LOCK_COMMON_BLOCK([int]bool) returns ([int]bool);
+function _S_Removed__IO_REMOVE_LOCK_COMMON_BLOCKInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {Removed__IO_REMOVE_LOCK_COMMON_BLOCKInv(Removed__IO_REMOVE_LOCK_COMMON_BLOCK(x))} Removed__IO_REMOVE_LOCK_COMMON_BLOCKInv(Removed__IO_REMOVE_LOCK_COMMON_BLOCK(x)) == x);
+axiom (forall x:int :: {Removed__IO_REMOVE_LOCK_COMMON_BLOCKInv(x)} Removed__IO_REMOVE_LOCK_COMMON_BLOCK(Removed__IO_REMOVE_LOCK_COMMON_BLOCKInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_Removed__IO_REMOVE_LOCK_COMMON_BLOCK(S)[x]} _S_Removed__IO_REMOVE_LOCK_COMMON_BLOCK(S)[x] <==> S[Removed__IO_REMOVE_LOCK_COMMON_BLOCKInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_Removed__IO_REMOVE_LOCK_COMMON_BLOCKInv(S)[x]} _S_Removed__IO_REMOVE_LOCK_COMMON_BLOCKInv(S)[x] <==> S[Removed__IO_REMOVE_LOCK_COMMON_BLOCK(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Removed__IO_REMOVE_LOCK_COMMON_BLOCK(S)} S[x] ==> _S_Removed__IO_REMOVE_LOCK_COMMON_BLOCK(S)[Removed__IO_REMOVE_LOCK_COMMON_BLOCK(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Removed__IO_REMOVE_LOCK_COMMON_BLOCKInv(S)} S[x] ==> _S_Removed__IO_REMOVE_LOCK_COMMON_BLOCKInv(S)[Removed__IO_REMOVE_LOCK_COMMON_BLOCKInv(x)]);
+
+axiom (forall x:int :: {Removed__IO_REMOVE_LOCK_COMMON_BLOCK(x)} Removed__IO_REMOVE_LOCK_COMMON_BLOCK(x) == x + 0);
+axiom (forall x:int :: {Removed__IO_REMOVE_LOCK_COMMON_BLOCKInv(x)} Removed__IO_REMOVE_LOCK_COMMON_BLOCKInv(x) == x - 0);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1) == Removed__IO_REMOVE_LOCK_COMMON_BLOCKInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 0)} MINUS_LEFT_PTR(x, 1, 0) == Removed__IO_REMOVE_LOCK_COMMON_BLOCKInv(x));
+function Reserved1__IO_REMOVE_LOCK_DBG_BLOCK(int) returns (int);
+function Reserved1__IO_REMOVE_LOCK_DBG_BLOCKInv(int) returns (int);
+function _S_Reserved1__IO_REMOVE_LOCK_DBG_BLOCK([int]bool) returns ([int]bool);
+function _S_Reserved1__IO_REMOVE_LOCK_DBG_BLOCKInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {Reserved1__IO_REMOVE_LOCK_DBG_BLOCKInv(Reserved1__IO_REMOVE_LOCK_DBG_BLOCK(x))} Reserved1__IO_REMOVE_LOCK_DBG_BLOCKInv(Reserved1__IO_REMOVE_LOCK_DBG_BLOCK(x)) == x);
+axiom (forall x:int :: {Reserved1__IO_REMOVE_LOCK_DBG_BLOCKInv(x)} Reserved1__IO_REMOVE_LOCK_DBG_BLOCK(Reserved1__IO_REMOVE_LOCK_DBG_BLOCKInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_Reserved1__IO_REMOVE_LOCK_DBG_BLOCK(S)[x]} _S_Reserved1__IO_REMOVE_LOCK_DBG_BLOCK(S)[x] <==> S[Reserved1__IO_REMOVE_LOCK_DBG_BLOCKInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_Reserved1__IO_REMOVE_LOCK_DBG_BLOCKInv(S)[x]} _S_Reserved1__IO_REMOVE_LOCK_DBG_BLOCKInv(S)[x] <==> S[Reserved1__IO_REMOVE_LOCK_DBG_BLOCK(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Reserved1__IO_REMOVE_LOCK_DBG_BLOCK(S)} S[x] ==> _S_Reserved1__IO_REMOVE_LOCK_DBG_BLOCK(S)[Reserved1__IO_REMOVE_LOCK_DBG_BLOCK(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Reserved1__IO_REMOVE_LOCK_DBG_BLOCKInv(S)} S[x] ==> _S_Reserved1__IO_REMOVE_LOCK_DBG_BLOCKInv(S)[Reserved1__IO_REMOVE_LOCK_DBG_BLOCKInv(x)]);
+
+axiom (forall x:int :: {Reserved1__IO_REMOVE_LOCK_DBG_BLOCK(x)} Reserved1__IO_REMOVE_LOCK_DBG_BLOCK(x) == x + 36);
+axiom (forall x:int :: {Reserved1__IO_REMOVE_LOCK_DBG_BLOCKInv(x)} Reserved1__IO_REMOVE_LOCK_DBG_BLOCKInv(x) == x - 36);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 36, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 36, 1) == Reserved1__IO_REMOVE_LOCK_DBG_BLOCKInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 36)} MINUS_LEFT_PTR(x, 1, 36) == Reserved1__IO_REMOVE_LOCK_DBG_BLOCKInv(x));
+function Reserved2__IO_REMOVE_LOCK_DBG_BLOCK(int) returns (int);
+function Reserved2__IO_REMOVE_LOCK_DBG_BLOCKInv(int) returns (int);
+function _S_Reserved2__IO_REMOVE_LOCK_DBG_BLOCK([int]bool) returns ([int]bool);
+function _S_Reserved2__IO_REMOVE_LOCK_DBG_BLOCKInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {Reserved2__IO_REMOVE_LOCK_DBG_BLOCKInv(Reserved2__IO_REMOVE_LOCK_DBG_BLOCK(x))} Reserved2__IO_REMOVE_LOCK_DBG_BLOCKInv(Reserved2__IO_REMOVE_LOCK_DBG_BLOCK(x)) == x);
+axiom (forall x:int :: {Reserved2__IO_REMOVE_LOCK_DBG_BLOCKInv(x)} Reserved2__IO_REMOVE_LOCK_DBG_BLOCK(Reserved2__IO_REMOVE_LOCK_DBG_BLOCKInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_Reserved2__IO_REMOVE_LOCK_DBG_BLOCK(S)[x]} _S_Reserved2__IO_REMOVE_LOCK_DBG_BLOCK(S)[x] <==> S[Reserved2__IO_REMOVE_LOCK_DBG_BLOCKInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_Reserved2__IO_REMOVE_LOCK_DBG_BLOCKInv(S)[x]} _S_Reserved2__IO_REMOVE_LOCK_DBG_BLOCKInv(S)[x] <==> S[Reserved2__IO_REMOVE_LOCK_DBG_BLOCK(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Reserved2__IO_REMOVE_LOCK_DBG_BLOCK(S)} S[x] ==> _S_Reserved2__IO_REMOVE_LOCK_DBG_BLOCK(S)[Reserved2__IO_REMOVE_LOCK_DBG_BLOCK(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Reserved2__IO_REMOVE_LOCK_DBG_BLOCKInv(S)} S[x] ==> _S_Reserved2__IO_REMOVE_LOCK_DBG_BLOCKInv(S)[Reserved2__IO_REMOVE_LOCK_DBG_BLOCKInv(x)]);
+
+axiom (forall x:int :: {Reserved2__IO_REMOVE_LOCK_DBG_BLOCK(x)} Reserved2__IO_REMOVE_LOCK_DBG_BLOCK(x) == x + 52);
+axiom (forall x:int :: {Reserved2__IO_REMOVE_LOCK_DBG_BLOCKInv(x)} Reserved2__IO_REMOVE_LOCK_DBG_BLOCKInv(x) == x - 52);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 52, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 52, 1) == Reserved2__IO_REMOVE_LOCK_DBG_BLOCKInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 52)} MINUS_LEFT_PTR(x, 1, 52) == Reserved2__IO_REMOVE_LOCK_DBG_BLOCKInv(x));
+function Reserved__IO_REMOVE_LOCK_COMMON_BLOCK(int) returns (int);
+function Reserved__IO_REMOVE_LOCK_COMMON_BLOCKInv(int) returns (int);
+function _S_Reserved__IO_REMOVE_LOCK_COMMON_BLOCK([int]bool) returns ([int]bool);
+function _S_Reserved__IO_REMOVE_LOCK_COMMON_BLOCKInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {Reserved__IO_REMOVE_LOCK_COMMON_BLOCKInv(Reserved__IO_REMOVE_LOCK_COMMON_BLOCK(x))} Reserved__IO_REMOVE_LOCK_COMMON_BLOCKInv(Reserved__IO_REMOVE_LOCK_COMMON_BLOCK(x)) == x);
+axiom (forall x:int :: {Reserved__IO_REMOVE_LOCK_COMMON_BLOCKInv(x)} Reserved__IO_REMOVE_LOCK_COMMON_BLOCK(Reserved__IO_REMOVE_LOCK_COMMON_BLOCKInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_Reserved__IO_REMOVE_LOCK_COMMON_BLOCK(S)[x]} _S_Reserved__IO_REMOVE_LOCK_COMMON_BLOCK(S)[x] <==> S[Reserved__IO_REMOVE_LOCK_COMMON_BLOCKInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_Reserved__IO_REMOVE_LOCK_COMMON_BLOCKInv(S)[x]} _S_Reserved__IO_REMOVE_LOCK_COMMON_BLOCKInv(S)[x] <==> S[Reserved__IO_REMOVE_LOCK_COMMON_BLOCK(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Reserved__IO_REMOVE_LOCK_COMMON_BLOCK(S)} S[x] ==> _S_Reserved__IO_REMOVE_LOCK_COMMON_BLOCK(S)[Reserved__IO_REMOVE_LOCK_COMMON_BLOCK(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Reserved__IO_REMOVE_LOCK_COMMON_BLOCKInv(S)} S[x] ==> _S_Reserved__IO_REMOVE_LOCK_COMMON_BLOCKInv(S)[Reserved__IO_REMOVE_LOCK_COMMON_BLOCKInv(x)]);
+
+axiom (forall x:int :: {Reserved__IO_REMOVE_LOCK_COMMON_BLOCK(x)} Reserved__IO_REMOVE_LOCK_COMMON_BLOCK(x) == x + 1);
+axiom (forall x:int :: {Reserved__IO_REMOVE_LOCK_COMMON_BLOCKInv(x)} Reserved__IO_REMOVE_LOCK_COMMON_BLOCKInv(x) == x - 1);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 1, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 1, 1) == Reserved__IO_REMOVE_LOCK_COMMON_BLOCKInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 1)} MINUS_LEFT_PTR(x, 1, 1) == Reserved__IO_REMOVE_LOCK_COMMON_BLOCKInv(x));
+function Self__DEVICE_EXTENSION(int) returns (int);
+function Self__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_Self__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_Self__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {Self__DEVICE_EXTENSIONInv(Self__DEVICE_EXTENSION(x))} Self__DEVICE_EXTENSIONInv(Self__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {Self__DEVICE_EXTENSIONInv(x)} Self__DEVICE_EXTENSION(Self__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_Self__DEVICE_EXTENSION(S)[x]} _S_Self__DEVICE_EXTENSION(S)[x] <==> S[Self__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_Self__DEVICE_EXTENSIONInv(S)[x]} _S_Self__DEVICE_EXTENSIONInv(S)[x] <==> S[Self__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Self__DEVICE_EXTENSION(S)} S[x] ==> _S_Self__DEVICE_EXTENSION(S)[Self__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Self__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_Self__DEVICE_EXTENSIONInv(S)[Self__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {Self__DEVICE_EXTENSION(x)} Self__DEVICE_EXTENSION(x) == x + 0);
+axiom (forall x:int :: {Self__DEVICE_EXTENSIONInv(x)} Self__DEVICE_EXTENSIONInv(x) == x - 0);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1) == Self__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 0)} MINUS_LEFT_PTR(x, 1, 0) == Self__DEVICE_EXTENSIONInv(x));
+function SequenceNumber__DEVICE_EXTENSION(int) returns (int);
+function SequenceNumber__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_SequenceNumber__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_SequenceNumber__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {SequenceNumber__DEVICE_EXTENSIONInv(SequenceNumber__DEVICE_EXTENSION(x))} SequenceNumber__DEVICE_EXTENSIONInv(SequenceNumber__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {SequenceNumber__DEVICE_EXTENSIONInv(x)} SequenceNumber__DEVICE_EXTENSION(SequenceNumber__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_SequenceNumber__DEVICE_EXTENSION(S)[x]} _S_SequenceNumber__DEVICE_EXTENSION(S)[x] <==> S[SequenceNumber__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_SequenceNumber__DEVICE_EXTENSIONInv(S)[x]} _S_SequenceNumber__DEVICE_EXTENSIONInv(S)[x] <==> S[SequenceNumber__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_SequenceNumber__DEVICE_EXTENSION(S)} S[x] ==> _S_SequenceNumber__DEVICE_EXTENSION(S)[SequenceNumber__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_SequenceNumber__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_SequenceNumber__DEVICE_EXTENSIONInv(S)[SequenceNumber__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {SequenceNumber__DEVICE_EXTENSION(x)} SequenceNumber__DEVICE_EXTENSION(x) == x + 184);
+axiom (forall x:int :: {SequenceNumber__DEVICE_EXTENSIONInv(x)} SequenceNumber__DEVICE_EXTENSIONInv(x) == x - 184);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 184, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 184, 1) == SequenceNumber__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 184)} MINUS_LEFT_PTR(x, 1, 184) == SequenceNumber__DEVICE_EXTENSIONInv(x));
+function SetWmiDataBlock__WMILIB_CONTEXT(int) returns (int);
+function SetWmiDataBlock__WMILIB_CONTEXTInv(int) returns (int);
+function _S_SetWmiDataBlock__WMILIB_CONTEXT([int]bool) returns ([int]bool);
+function _S_SetWmiDataBlock__WMILIB_CONTEXTInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {SetWmiDataBlock__WMILIB_CONTEXTInv(SetWmiDataBlock__WMILIB_CONTEXT(x))} SetWmiDataBlock__WMILIB_CONTEXTInv(SetWmiDataBlock__WMILIB_CONTEXT(x)) == x);
+axiom (forall x:int :: {SetWmiDataBlock__WMILIB_CONTEXTInv(x)} SetWmiDataBlock__WMILIB_CONTEXT(SetWmiDataBlock__WMILIB_CONTEXTInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_SetWmiDataBlock__WMILIB_CONTEXT(S)[x]} _S_SetWmiDataBlock__WMILIB_CONTEXT(S)[x] <==> S[SetWmiDataBlock__WMILIB_CONTEXTInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_SetWmiDataBlock__WMILIB_CONTEXTInv(S)[x]} _S_SetWmiDataBlock__WMILIB_CONTEXTInv(S)[x] <==> S[SetWmiDataBlock__WMILIB_CONTEXT(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_SetWmiDataBlock__WMILIB_CONTEXT(S)} S[x] ==> _S_SetWmiDataBlock__WMILIB_CONTEXT(S)[SetWmiDataBlock__WMILIB_CONTEXT(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_SetWmiDataBlock__WMILIB_CONTEXTInv(S)} S[x] ==> _S_SetWmiDataBlock__WMILIB_CONTEXTInv(S)[SetWmiDataBlock__WMILIB_CONTEXTInv(x)]);
+
+axiom (forall x:int :: {SetWmiDataBlock__WMILIB_CONTEXT(x)} SetWmiDataBlock__WMILIB_CONTEXT(x) == x + 16);
+axiom (forall x:int :: {SetWmiDataBlock__WMILIB_CONTEXTInv(x)} SetWmiDataBlock__WMILIB_CONTEXTInv(x) == x - 16);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 16, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 16, 1) == SetWmiDataBlock__WMILIB_CONTEXTInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 16)} MINUS_LEFT_PTR(x, 1, 16) == SetWmiDataBlock__WMILIB_CONTEXTInv(x));
+function SetWmiDataItem__WMILIB_CONTEXT(int) returns (int);
+function SetWmiDataItem__WMILIB_CONTEXTInv(int) returns (int);
+function _S_SetWmiDataItem__WMILIB_CONTEXT([int]bool) returns ([int]bool);
+function _S_SetWmiDataItem__WMILIB_CONTEXTInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {SetWmiDataItem__WMILIB_CONTEXTInv(SetWmiDataItem__WMILIB_CONTEXT(x))} SetWmiDataItem__WMILIB_CONTEXTInv(SetWmiDataItem__WMILIB_CONTEXT(x)) == x);
+axiom (forall x:int :: {SetWmiDataItem__WMILIB_CONTEXTInv(x)} SetWmiDataItem__WMILIB_CONTEXT(SetWmiDataItem__WMILIB_CONTEXTInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_SetWmiDataItem__WMILIB_CONTEXT(S)[x]} _S_SetWmiDataItem__WMILIB_CONTEXT(S)[x] <==> S[SetWmiDataItem__WMILIB_CONTEXTInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_SetWmiDataItem__WMILIB_CONTEXTInv(S)[x]} _S_SetWmiDataItem__WMILIB_CONTEXTInv(S)[x] <==> S[SetWmiDataItem__WMILIB_CONTEXT(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_SetWmiDataItem__WMILIB_CONTEXT(S)} S[x] ==> _S_SetWmiDataItem__WMILIB_CONTEXT(S)[SetWmiDataItem__WMILIB_CONTEXT(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_SetWmiDataItem__WMILIB_CONTEXTInv(S)} S[x] ==> _S_SetWmiDataItem__WMILIB_CONTEXTInv(S)[SetWmiDataItem__WMILIB_CONTEXTInv(x)]);
+
+axiom (forall x:int :: {SetWmiDataItem__WMILIB_CONTEXT(x)} SetWmiDataItem__WMILIB_CONTEXT(x) == x + 20);
+axiom (forall x:int :: {SetWmiDataItem__WMILIB_CONTEXTInv(x)} SetWmiDataItem__WMILIB_CONTEXTInv(x) == x - 20);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 20, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 20, 1) == SetWmiDataItem__WMILIB_CONTEXTInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 20)} MINUS_LEFT_PTR(x, 1, 20) == SetWmiDataItem__WMILIB_CONTEXTInv(x));
+function SignalState__DISPATCHER_HEADER(int) returns (int);
+function SignalState__DISPATCHER_HEADERInv(int) returns (int);
+function _S_SignalState__DISPATCHER_HEADER([int]bool) returns ([int]bool);
+function _S_SignalState__DISPATCHER_HEADERInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {SignalState__DISPATCHER_HEADERInv(SignalState__DISPATCHER_HEADER(x))} SignalState__DISPATCHER_HEADERInv(SignalState__DISPATCHER_HEADER(x)) == x);
+axiom (forall x:int :: {SignalState__DISPATCHER_HEADERInv(x)} SignalState__DISPATCHER_HEADER(SignalState__DISPATCHER_HEADERInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_SignalState__DISPATCHER_HEADER(S)[x]} _S_SignalState__DISPATCHER_HEADER(S)[x] <==> S[SignalState__DISPATCHER_HEADERInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_SignalState__DISPATCHER_HEADERInv(S)[x]} _S_SignalState__DISPATCHER_HEADERInv(S)[x] <==> S[SignalState__DISPATCHER_HEADER(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_SignalState__DISPATCHER_HEADER(S)} S[x] ==> _S_SignalState__DISPATCHER_HEADER(S)[SignalState__DISPATCHER_HEADER(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_SignalState__DISPATCHER_HEADERInv(S)} S[x] ==> _S_SignalState__DISPATCHER_HEADERInv(S)[SignalState__DISPATCHER_HEADERInv(x)]);
+
+axiom (forall x:int :: {SignalState__DISPATCHER_HEADER(x)} SignalState__DISPATCHER_HEADER(x) == x + 4);
+axiom (forall x:int :: {SignalState__DISPATCHER_HEADERInv(x)} SignalState__DISPATCHER_HEADERInv(x) == x - 4);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 4, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 4, 1) == SignalState__DISPATCHER_HEADERInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 4)} MINUS_LEFT_PTR(x, 1, 4) == SignalState__DISPATCHER_HEADERInv(x));
+function Signalling___unnamed_1_29794256(int) returns (int);
+function Signalling___unnamed_1_29794256Inv(int) returns (int);
+function _S_Signalling___unnamed_1_29794256([int]bool) returns ([int]bool);
+function _S_Signalling___unnamed_1_29794256Inv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {Signalling___unnamed_1_29794256Inv(Signalling___unnamed_1_29794256(x))} Signalling___unnamed_1_29794256Inv(Signalling___unnamed_1_29794256(x)) == x);
+axiom (forall x:int :: {Signalling___unnamed_1_29794256Inv(x)} Signalling___unnamed_1_29794256(Signalling___unnamed_1_29794256Inv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_Signalling___unnamed_1_29794256(S)[x]} _S_Signalling___unnamed_1_29794256(S)[x] <==> S[Signalling___unnamed_1_29794256Inv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_Signalling___unnamed_1_29794256Inv(S)[x]} _S_Signalling___unnamed_1_29794256Inv(S)[x] <==> S[Signalling___unnamed_1_29794256(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Signalling___unnamed_1_29794256(S)} S[x] ==> _S_Signalling___unnamed_1_29794256(S)[Signalling___unnamed_1_29794256(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Signalling___unnamed_1_29794256Inv(S)} S[x] ==> _S_Signalling___unnamed_1_29794256Inv(S)[Signalling___unnamed_1_29794256Inv(x)]);
+
+axiom (forall x:int :: {Signalling___unnamed_1_29794256(x)} Signalling___unnamed_1_29794256(x) == x + 0);
+axiom (forall x:int :: {Signalling___unnamed_1_29794256Inv(x)} Signalling___unnamed_1_29794256Inv(x) == x - 0);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1) == Signalling___unnamed_1_29794256Inv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 0)} MINUS_LEFT_PTR(x, 1, 0) == Signalling___unnamed_1_29794256Inv(x));
+function Signature__IO_REMOVE_LOCK_DBG_BLOCK(int) returns (int);
+function Signature__IO_REMOVE_LOCK_DBG_BLOCKInv(int) returns (int);
+function _S_Signature__IO_REMOVE_LOCK_DBG_BLOCK([int]bool) returns ([int]bool);
+function _S_Signature__IO_REMOVE_LOCK_DBG_BLOCKInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {Signature__IO_REMOVE_LOCK_DBG_BLOCKInv(Signature__IO_REMOVE_LOCK_DBG_BLOCK(x))} Signature__IO_REMOVE_LOCK_DBG_BLOCKInv(Signature__IO_REMOVE_LOCK_DBG_BLOCK(x)) == x);
+axiom (forall x:int :: {Signature__IO_REMOVE_LOCK_DBG_BLOCKInv(x)} Signature__IO_REMOVE_LOCK_DBG_BLOCK(Signature__IO_REMOVE_LOCK_DBG_BLOCKInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_Signature__IO_REMOVE_LOCK_DBG_BLOCK(S)[x]} _S_Signature__IO_REMOVE_LOCK_DBG_BLOCK(S)[x] <==> S[Signature__IO_REMOVE_LOCK_DBG_BLOCKInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_Signature__IO_REMOVE_LOCK_DBG_BLOCKInv(S)[x]} _S_Signature__IO_REMOVE_LOCK_DBG_BLOCKInv(S)[x] <==> S[Signature__IO_REMOVE_LOCK_DBG_BLOCK(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Signature__IO_REMOVE_LOCK_DBG_BLOCK(S)} S[x] ==> _S_Signature__IO_REMOVE_LOCK_DBG_BLOCK(S)[Signature__IO_REMOVE_LOCK_DBG_BLOCK(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Signature__IO_REMOVE_LOCK_DBG_BLOCKInv(S)} S[x] ==> _S_Signature__IO_REMOVE_LOCK_DBG_BLOCKInv(S)[Signature__IO_REMOVE_LOCK_DBG_BLOCKInv(x)]);
+
+axiom (forall x:int :: {Signature__IO_REMOVE_LOCK_DBG_BLOCK(x)} Signature__IO_REMOVE_LOCK_DBG_BLOCK(x) == x + 0);
+axiom (forall x:int :: {Signature__IO_REMOVE_LOCK_DBG_BLOCKInv(x)} Signature__IO_REMOVE_LOCK_DBG_BLOCKInv(x) == x - 0);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1) == Signature__IO_REMOVE_LOCK_DBG_BLOCKInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 0)} MINUS_LEFT_PTR(x, 1, 0) == Signature__IO_REMOVE_LOCK_DBG_BLOCKInv(x));
+function Size___unnamed_1_2ef8da39(int) returns (int);
+function Size___unnamed_1_2ef8da39Inv(int) returns (int);
+function _S_Size___unnamed_1_2ef8da39([int]bool) returns ([int]bool);
+function _S_Size___unnamed_1_2ef8da39Inv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {Size___unnamed_1_2ef8da39Inv(Size___unnamed_1_2ef8da39(x))} Size___unnamed_1_2ef8da39Inv(Size___unnamed_1_2ef8da39(x)) == x);
+axiom (forall x:int :: {Size___unnamed_1_2ef8da39Inv(x)} Size___unnamed_1_2ef8da39(Size___unnamed_1_2ef8da39Inv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_Size___unnamed_1_2ef8da39(S)[x]} _S_Size___unnamed_1_2ef8da39(S)[x] <==> S[Size___unnamed_1_2ef8da39Inv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_Size___unnamed_1_2ef8da39Inv(S)[x]} _S_Size___unnamed_1_2ef8da39Inv(S)[x] <==> S[Size___unnamed_1_2ef8da39(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Size___unnamed_1_2ef8da39(S)} S[x] ==> _S_Size___unnamed_1_2ef8da39(S)[Size___unnamed_1_2ef8da39(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Size___unnamed_1_2ef8da39Inv(S)} S[x] ==> _S_Size___unnamed_1_2ef8da39Inv(S)[Size___unnamed_1_2ef8da39Inv(x)]);
+
+axiom (forall x:int :: {Size___unnamed_1_2ef8da39(x)} Size___unnamed_1_2ef8da39(x) == x + 0);
+axiom (forall x:int :: {Size___unnamed_1_2ef8da39Inv(x)} Size___unnamed_1_2ef8da39Inv(x) == x - 0);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1) == Size___unnamed_1_2ef8da39Inv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 0)} MINUS_LEFT_PTR(x, 1, 0) == Size___unnamed_1_2ef8da39Inv(x));
+function SpinLock__DEVICE_EXTENSION(int) returns (int);
+function SpinLock__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_SpinLock__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_SpinLock__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {SpinLock__DEVICE_EXTENSIONInv(SpinLock__DEVICE_EXTENSION(x))} SpinLock__DEVICE_EXTENSIONInv(SpinLock__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {SpinLock__DEVICE_EXTENSIONInv(x)} SpinLock__DEVICE_EXTENSION(SpinLock__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_SpinLock__DEVICE_EXTENSION(S)[x]} _S_SpinLock__DEVICE_EXTENSION(S)[x] <==> S[SpinLock__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_SpinLock__DEVICE_EXTENSIONInv(S)[x]} _S_SpinLock__DEVICE_EXTENSIONInv(S)[x] <==> S[SpinLock__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_SpinLock__DEVICE_EXTENSION(S)} S[x] ==> _S_SpinLock__DEVICE_EXTENSION(S)[SpinLock__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_SpinLock__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_SpinLock__DEVICE_EXTENSIONInv(S)[SpinLock__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {SpinLock__DEVICE_EXTENSION(x)} SpinLock__DEVICE_EXTENSION(x) == x + 172);
+axiom (forall x:int :: {SpinLock__DEVICE_EXTENSIONInv(x)} SpinLock__DEVICE_EXTENSIONInv(x) == x - 172);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 172, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 172, 1) == SpinLock__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 172)} MINUS_LEFT_PTR(x, 1, 172) == SpinLock__DEVICE_EXTENSIONInv(x));
+function Spin__IO_REMOVE_LOCK_DBG_BLOCK(int) returns (int);
+function Spin__IO_REMOVE_LOCK_DBG_BLOCKInv(int) returns (int);
+function _S_Spin__IO_REMOVE_LOCK_DBG_BLOCK([int]bool) returns ([int]bool);
+function _S_Spin__IO_REMOVE_LOCK_DBG_BLOCKInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {Spin__IO_REMOVE_LOCK_DBG_BLOCKInv(Spin__IO_REMOVE_LOCK_DBG_BLOCK(x))} Spin__IO_REMOVE_LOCK_DBG_BLOCKInv(Spin__IO_REMOVE_LOCK_DBG_BLOCK(x)) == x);
+axiom (forall x:int :: {Spin__IO_REMOVE_LOCK_DBG_BLOCKInv(x)} Spin__IO_REMOVE_LOCK_DBG_BLOCK(Spin__IO_REMOVE_LOCK_DBG_BLOCKInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_Spin__IO_REMOVE_LOCK_DBG_BLOCK(S)[x]} _S_Spin__IO_REMOVE_LOCK_DBG_BLOCK(S)[x] <==> S[Spin__IO_REMOVE_LOCK_DBG_BLOCKInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_Spin__IO_REMOVE_LOCK_DBG_BLOCKInv(S)[x]} _S_Spin__IO_REMOVE_LOCK_DBG_BLOCKInv(S)[x] <==> S[Spin__IO_REMOVE_LOCK_DBG_BLOCK(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Spin__IO_REMOVE_LOCK_DBG_BLOCK(S)} S[x] ==> _S_Spin__IO_REMOVE_LOCK_DBG_BLOCK(S)[Spin__IO_REMOVE_LOCK_DBG_BLOCK(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Spin__IO_REMOVE_LOCK_DBG_BLOCKInv(S)} S[x] ==> _S_Spin__IO_REMOVE_LOCK_DBG_BLOCKInv(S)[Spin__IO_REMOVE_LOCK_DBG_BLOCKInv(x)]);
+
+axiom (forall x:int :: {Spin__IO_REMOVE_LOCK_DBG_BLOCK(x)} Spin__IO_REMOVE_LOCK_DBG_BLOCK(x) == x + 28);
+axiom (forall x:int :: {Spin__IO_REMOVE_LOCK_DBG_BLOCKInv(x)} Spin__IO_REMOVE_LOCK_DBG_BLOCKInv(x) == x - 28);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 28, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 28, 1) == Spin__IO_REMOVE_LOCK_DBG_BLOCKInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 28)} MINUS_LEFT_PTR(x, 1, 28) == Spin__IO_REMOVE_LOCK_DBG_BLOCKInv(x));
+function Started__DEVICE_EXTENSION(int) returns (int);
+function Started__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_Started__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_Started__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {Started__DEVICE_EXTENSIONInv(Started__DEVICE_EXTENSION(x))} Started__DEVICE_EXTENSIONInv(Started__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {Started__DEVICE_EXTENSIONInv(x)} Started__DEVICE_EXTENSION(Started__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_Started__DEVICE_EXTENSION(S)[x]} _S_Started__DEVICE_EXTENSION(S)[x] <==> S[Started__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_Started__DEVICE_EXTENSIONInv(S)[x]} _S_Started__DEVICE_EXTENSIONInv(S)[x] <==> S[Started__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Started__DEVICE_EXTENSION(S)} S[x] ==> _S_Started__DEVICE_EXTENSION(S)[Started__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Started__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_Started__DEVICE_EXTENSIONInv(S)[Started__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {Started__DEVICE_EXTENSION(x)} Started__DEVICE_EXTENSION(x) == x + 105);
+axiom (forall x:int :: {Started__DEVICE_EXTENSIONInv(x)} Started__DEVICE_EXTENSIONInv(x) == x - 105);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 105, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 105, 1) == Started__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 105)} MINUS_LEFT_PTR(x, 1, 105) == Started__DEVICE_EXTENSIONInv(x));
+function Subtype__KEYBOARD_ID(int) returns (int);
+function Subtype__KEYBOARD_IDInv(int) returns (int);
+function _S_Subtype__KEYBOARD_ID([int]bool) returns ([int]bool);
+function _S_Subtype__KEYBOARD_IDInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {Subtype__KEYBOARD_IDInv(Subtype__KEYBOARD_ID(x))} Subtype__KEYBOARD_IDInv(Subtype__KEYBOARD_ID(x)) == x);
+axiom (forall x:int :: {Subtype__KEYBOARD_IDInv(x)} Subtype__KEYBOARD_ID(Subtype__KEYBOARD_IDInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_Subtype__KEYBOARD_ID(S)[x]} _S_Subtype__KEYBOARD_ID(S)[x] <==> S[Subtype__KEYBOARD_IDInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_Subtype__KEYBOARD_IDInv(S)[x]} _S_Subtype__KEYBOARD_IDInv(S)[x] <==> S[Subtype__KEYBOARD_ID(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Subtype__KEYBOARD_ID(S)} S[x] ==> _S_Subtype__KEYBOARD_ID(S)[Subtype__KEYBOARD_ID(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Subtype__KEYBOARD_IDInv(S)} S[x] ==> _S_Subtype__KEYBOARD_IDInv(S)[Subtype__KEYBOARD_IDInv(x)]);
+
+axiom (forall x:int :: {Subtype__KEYBOARD_ID(x)} Subtype__KEYBOARD_ID(x) == x + 1);
+axiom (forall x:int :: {Subtype__KEYBOARD_IDInv(x)} Subtype__KEYBOARD_IDInv(x) == x - 1);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 1, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 1, 1) == Subtype__KEYBOARD_IDInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 1)} MINUS_LEFT_PTR(x, 1, 1) == Subtype__KEYBOARD_IDInv(x));
+function SurpriseRemoved__DEVICE_EXTENSION(int) returns (int);
+function SurpriseRemoved__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_SurpriseRemoved__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_SurpriseRemoved__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {SurpriseRemoved__DEVICE_EXTENSIONInv(SurpriseRemoved__DEVICE_EXTENSION(x))} SurpriseRemoved__DEVICE_EXTENSIONInv(SurpriseRemoved__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {SurpriseRemoved__DEVICE_EXTENSIONInv(x)} SurpriseRemoved__DEVICE_EXTENSION(SurpriseRemoved__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_SurpriseRemoved__DEVICE_EXTENSION(S)[x]} _S_SurpriseRemoved__DEVICE_EXTENSION(S)[x] <==> S[SurpriseRemoved__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_SurpriseRemoved__DEVICE_EXTENSIONInv(S)[x]} _S_SurpriseRemoved__DEVICE_EXTENSIONInv(S)[x] <==> S[SurpriseRemoved__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_SurpriseRemoved__DEVICE_EXTENSION(S)} S[x] ==> _S_SurpriseRemoved__DEVICE_EXTENSION(S)[SurpriseRemoved__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_SurpriseRemoved__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_SurpriseRemoved__DEVICE_EXTENSIONInv(S)[SurpriseRemoved__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {SurpriseRemoved__DEVICE_EXTENSION(x)} SurpriseRemoved__DEVICE_EXTENSION(x) == x + 287);
+axiom (forall x:int :: {SurpriseRemoved__DEVICE_EXTENSIONInv(x)} SurpriseRemoved__DEVICE_EXTENSIONInv(x) == x - 287);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 287, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 287, 1) == SurpriseRemoved__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 287)} MINUS_LEFT_PTR(x, 1, 287) == SurpriseRemoved__DEVICE_EXTENSIONInv(x));
+function SymbolicLinkName__DEVICE_EXTENSION(int) returns (int);
+function SymbolicLinkName__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_SymbolicLinkName__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_SymbolicLinkName__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {SymbolicLinkName__DEVICE_EXTENSIONInv(SymbolicLinkName__DEVICE_EXTENSION(x))} SymbolicLinkName__DEVICE_EXTENSIONInv(SymbolicLinkName__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {SymbolicLinkName__DEVICE_EXTENSIONInv(x)} SymbolicLinkName__DEVICE_EXTENSION(SymbolicLinkName__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_SymbolicLinkName__DEVICE_EXTENSION(S)[x]} _S_SymbolicLinkName__DEVICE_EXTENSION(S)[x] <==> S[SymbolicLinkName__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_SymbolicLinkName__DEVICE_EXTENSIONInv(S)[x]} _S_SymbolicLinkName__DEVICE_EXTENSIONInv(S)[x] <==> S[SymbolicLinkName__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_SymbolicLinkName__DEVICE_EXTENSION(S)} S[x] ==> _S_SymbolicLinkName__DEVICE_EXTENSION(S)[SymbolicLinkName__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_SymbolicLinkName__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_SymbolicLinkName__DEVICE_EXTENSIONInv(S)[SymbolicLinkName__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {SymbolicLinkName__DEVICE_EXTENSION(x)} SymbolicLinkName__DEVICE_EXTENSION(x) == x + 120);
+axiom (forall x:int :: {SymbolicLinkName__DEVICE_EXTENSIONInv(x)} SymbolicLinkName__DEVICE_EXTENSIONInv(x) == x - 120);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 120, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 120, 1) == SymbolicLinkName__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 120)} MINUS_LEFT_PTR(x, 1, 120) == SymbolicLinkName__DEVICE_EXTENSIONInv(x));
+function SystemState__DEVICE_EXTENSION(int) returns (int);
+function SystemState__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_SystemState__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_SystemState__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {SystemState__DEVICE_EXTENSIONInv(SystemState__DEVICE_EXTENSION(x))} SystemState__DEVICE_EXTENSIONInv(SystemState__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {SystemState__DEVICE_EXTENSIONInv(x)} SystemState__DEVICE_EXTENSION(SystemState__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_SystemState__DEVICE_EXTENSION(S)[x]} _S_SystemState__DEVICE_EXTENSION(S)[x] <==> S[SystemState__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_SystemState__DEVICE_EXTENSIONInv(S)[x]} _S_SystemState__DEVICE_EXTENSIONInv(S)[x] <==> S[SystemState__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_SystemState__DEVICE_EXTENSION(S)} S[x] ==> _S_SystemState__DEVICE_EXTENSION(S)[SystemState__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_SystemState__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_SystemState__DEVICE_EXTENSIONInv(S)[SystemState__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {SystemState__DEVICE_EXTENSION(x)} SystemState__DEVICE_EXTENSION(x) == x + 192);
+axiom (forall x:int :: {SystemState__DEVICE_EXTENSIONInv(x)} SystemState__DEVICE_EXTENSIONInv(x) == x - 192);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 192, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 192, 1) == SystemState__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 192)} MINUS_LEFT_PTR(x, 1, 192) == SystemState__DEVICE_EXTENSIONInv(x));
+function SystemToDeviceState__DEVICE_EXTENSION(int) returns (int);
+function SystemToDeviceState__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_SystemToDeviceState__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_SystemToDeviceState__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {SystemToDeviceState__DEVICE_EXTENSIONInv(SystemToDeviceState__DEVICE_EXTENSION(x))} SystemToDeviceState__DEVICE_EXTENSIONInv(SystemToDeviceState__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {SystemToDeviceState__DEVICE_EXTENSIONInv(x)} SystemToDeviceState__DEVICE_EXTENSION(SystemToDeviceState__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_SystemToDeviceState__DEVICE_EXTENSION(S)[x]} _S_SystemToDeviceState__DEVICE_EXTENSION(S)[x] <==> S[SystemToDeviceState__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_SystemToDeviceState__DEVICE_EXTENSIONInv(S)[x]} _S_SystemToDeviceState__DEVICE_EXTENSIONInv(S)[x] <==> S[SystemToDeviceState__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_SystemToDeviceState__DEVICE_EXTENSION(S)} S[x] ==> _S_SystemToDeviceState__DEVICE_EXTENSION(S)[SystemToDeviceState__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_SystemToDeviceState__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_SystemToDeviceState__DEVICE_EXTENSIONInv(S)[SystemToDeviceState__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {SystemToDeviceState__DEVICE_EXTENSION(x)} SystemToDeviceState__DEVICE_EXTENSION(x) == x + 232);
+axiom (forall x:int :: {SystemToDeviceState__DEVICE_EXTENSIONInv(x)} SystemToDeviceState__DEVICE_EXTENSIONInv(x) == x - 232);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 232, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 232, 1) == SystemToDeviceState__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 232)} MINUS_LEFT_PTR(x, 1, 232) == SystemToDeviceState__DEVICE_EXTENSIONInv(x));
+function TargetNotifyHandle__DEVICE_EXTENSION(int) returns (int);
+function TargetNotifyHandle__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_TargetNotifyHandle__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_TargetNotifyHandle__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {TargetNotifyHandle__DEVICE_EXTENSIONInv(TargetNotifyHandle__DEVICE_EXTENSION(x))} TargetNotifyHandle__DEVICE_EXTENSIONInv(TargetNotifyHandle__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {TargetNotifyHandle__DEVICE_EXTENSIONInv(x)} TargetNotifyHandle__DEVICE_EXTENSION(TargetNotifyHandle__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_TargetNotifyHandle__DEVICE_EXTENSION(S)[x]} _S_TargetNotifyHandle__DEVICE_EXTENSION(S)[x] <==> S[TargetNotifyHandle__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_TargetNotifyHandle__DEVICE_EXTENSIONInv(S)[x]} _S_TargetNotifyHandle__DEVICE_EXTENSIONInv(S)[x] <==> S[TargetNotifyHandle__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_TargetNotifyHandle__DEVICE_EXTENSION(S)} S[x] ==> _S_TargetNotifyHandle__DEVICE_EXTENSION(S)[TargetNotifyHandle__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_TargetNotifyHandle__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_TargetNotifyHandle__DEVICE_EXTENSIONInv(S)[TargetNotifyHandle__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {TargetNotifyHandle__DEVICE_EXTENSION(x)} TargetNotifyHandle__DEVICE_EXTENSION(x) == x + 268);
+axiom (forall x:int :: {TargetNotifyHandle__DEVICE_EXTENSIONInv(x)} TargetNotifyHandle__DEVICE_EXTENSIONInv(x) == x - 268);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 268, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 268, 1) == TargetNotifyHandle__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 268)} MINUS_LEFT_PTR(x, 1, 268) == TargetNotifyHandle__DEVICE_EXTENSIONInv(x));
+function TopPort__DEVICE_EXTENSION(int) returns (int);
+function TopPort__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_TopPort__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_TopPort__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {TopPort__DEVICE_EXTENSIONInv(TopPort__DEVICE_EXTENSION(x))} TopPort__DEVICE_EXTENSIONInv(TopPort__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {TopPort__DEVICE_EXTENSIONInv(x)} TopPort__DEVICE_EXTENSION(TopPort__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_TopPort__DEVICE_EXTENSION(S)[x]} _S_TopPort__DEVICE_EXTENSION(S)[x] <==> S[TopPort__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_TopPort__DEVICE_EXTENSIONInv(S)[x]} _S_TopPort__DEVICE_EXTENSIONInv(S)[x] <==> S[TopPort__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_TopPort__DEVICE_EXTENSION(S)} S[x] ==> _S_TopPort__DEVICE_EXTENSION(S)[TopPort__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_TopPort__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_TopPort__DEVICE_EXTENSIONInv(S)[TopPort__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {TopPort__DEVICE_EXTENSION(x)} TopPort__DEVICE_EXTENSION(x) == x + 8);
+axiom (forall x:int :: {TopPort__DEVICE_EXTENSIONInv(x)} TopPort__DEVICE_EXTENSIONInv(x) == x - 8);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 8, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 8, 1) == TopPort__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 8)} MINUS_LEFT_PTR(x, 1, 8) == TopPort__DEVICE_EXTENSIONInv(x));
+function TrueClassDevice__DEVICE_EXTENSION(int) returns (int);
+function TrueClassDevice__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_TrueClassDevice__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_TrueClassDevice__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {TrueClassDevice__DEVICE_EXTENSIONInv(TrueClassDevice__DEVICE_EXTENSION(x))} TrueClassDevice__DEVICE_EXTENSIONInv(TrueClassDevice__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {TrueClassDevice__DEVICE_EXTENSIONInv(x)} TrueClassDevice__DEVICE_EXTENSION(TrueClassDevice__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_TrueClassDevice__DEVICE_EXTENSION(S)[x]} _S_TrueClassDevice__DEVICE_EXTENSION(S)[x] <==> S[TrueClassDevice__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_TrueClassDevice__DEVICE_EXTENSIONInv(S)[x]} _S_TrueClassDevice__DEVICE_EXTENSIONInv(S)[x] <==> S[TrueClassDevice__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_TrueClassDevice__DEVICE_EXTENSION(S)} S[x] ==> _S_TrueClassDevice__DEVICE_EXTENSION(S)[TrueClassDevice__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_TrueClassDevice__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_TrueClassDevice__DEVICE_EXTENSIONInv(S)[TrueClassDevice__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {TrueClassDevice__DEVICE_EXTENSION(x)} TrueClassDevice__DEVICE_EXTENSION(x) == x + 4);
+axiom (forall x:int :: {TrueClassDevice__DEVICE_EXTENSIONInv(x)} TrueClassDevice__DEVICE_EXTENSIONInv(x) == x - 4);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 4, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 4, 1) == TrueClassDevice__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 4)} MINUS_LEFT_PTR(x, 1, 4) == TrueClassDevice__DEVICE_EXTENSIONInv(x));
+function TrustedSubsystemCount__DEVICE_EXTENSION(int) returns (int);
+function TrustedSubsystemCount__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_TrustedSubsystemCount__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_TrustedSubsystemCount__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {TrustedSubsystemCount__DEVICE_EXTENSIONInv(TrustedSubsystemCount__DEVICE_EXTENSION(x))} TrustedSubsystemCount__DEVICE_EXTENSIONInv(TrustedSubsystemCount__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {TrustedSubsystemCount__DEVICE_EXTENSIONInv(x)} TrustedSubsystemCount__DEVICE_EXTENSION(TrustedSubsystemCount__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_TrustedSubsystemCount__DEVICE_EXTENSION(S)[x]} _S_TrustedSubsystemCount__DEVICE_EXTENSION(S)[x] <==> S[TrustedSubsystemCount__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_TrustedSubsystemCount__DEVICE_EXTENSIONInv(S)[x]} _S_TrustedSubsystemCount__DEVICE_EXTENSIONInv(S)[x] <==> S[TrustedSubsystemCount__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_TrustedSubsystemCount__DEVICE_EXTENSION(S)} S[x] ==> _S_TrustedSubsystemCount__DEVICE_EXTENSION(S)[TrustedSubsystemCount__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_TrustedSubsystemCount__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_TrustedSubsystemCount__DEVICE_EXTENSIONInv(S)[TrustedSubsystemCount__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {TrustedSubsystemCount__DEVICE_EXTENSION(x)} TrustedSubsystemCount__DEVICE_EXTENSION(x) == x + 112);
+axiom (forall x:int :: {TrustedSubsystemCount__DEVICE_EXTENSIONInv(x)} TrustedSubsystemCount__DEVICE_EXTENSIONInv(x) == x - 112);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 112, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 112, 1) == TrustedSubsystemCount__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 112)} MINUS_LEFT_PTR(x, 1, 112) == TrustedSubsystemCount__DEVICE_EXTENSIONInv(x));
+function Type__KEYBOARD_ID(int) returns (int);
+function Type__KEYBOARD_IDInv(int) returns (int);
+function _S_Type__KEYBOARD_ID([int]bool) returns ([int]bool);
+function _S_Type__KEYBOARD_IDInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {Type__KEYBOARD_IDInv(Type__KEYBOARD_ID(x))} Type__KEYBOARD_IDInv(Type__KEYBOARD_ID(x)) == x);
+axiom (forall x:int :: {Type__KEYBOARD_IDInv(x)} Type__KEYBOARD_ID(Type__KEYBOARD_IDInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_Type__KEYBOARD_ID(S)[x]} _S_Type__KEYBOARD_ID(S)[x] <==> S[Type__KEYBOARD_IDInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_Type__KEYBOARD_IDInv(S)[x]} _S_Type__KEYBOARD_IDInv(S)[x] <==> S[Type__KEYBOARD_ID(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Type__KEYBOARD_ID(S)} S[x] ==> _S_Type__KEYBOARD_ID(S)[Type__KEYBOARD_ID(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Type__KEYBOARD_IDInv(S)} S[x] ==> _S_Type__KEYBOARD_IDInv(S)[Type__KEYBOARD_IDInv(x)]);
+
+axiom (forall x:int :: {Type__KEYBOARD_ID(x)} Type__KEYBOARD_ID(x) == x + 0);
+axiom (forall x:int :: {Type__KEYBOARD_IDInv(x)} Type__KEYBOARD_IDInv(x) == x - 0);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1) == Type__KEYBOARD_IDInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 0)} MINUS_LEFT_PTR(x, 1, 0) == Type__KEYBOARD_IDInv(x));
+function Type___unnamed_4_5ca00198(int) returns (int);
+function Type___unnamed_4_5ca00198Inv(int) returns (int);
+function _S_Type___unnamed_4_5ca00198([int]bool) returns ([int]bool);
+function _S_Type___unnamed_4_5ca00198Inv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {Type___unnamed_4_5ca00198Inv(Type___unnamed_4_5ca00198(x))} Type___unnamed_4_5ca00198Inv(Type___unnamed_4_5ca00198(x)) == x);
+axiom (forall x:int :: {Type___unnamed_4_5ca00198Inv(x)} Type___unnamed_4_5ca00198(Type___unnamed_4_5ca00198Inv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_Type___unnamed_4_5ca00198(S)[x]} _S_Type___unnamed_4_5ca00198(S)[x] <==> S[Type___unnamed_4_5ca00198Inv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_Type___unnamed_4_5ca00198Inv(S)[x]} _S_Type___unnamed_4_5ca00198Inv(S)[x] <==> S[Type___unnamed_4_5ca00198(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Type___unnamed_4_5ca00198(S)} S[x] ==> _S_Type___unnamed_4_5ca00198(S)[Type___unnamed_4_5ca00198(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Type___unnamed_4_5ca00198Inv(S)} S[x] ==> _S_Type___unnamed_4_5ca00198Inv(S)[Type___unnamed_4_5ca00198Inv(x)]);
+
+axiom (forall x:int :: {Type___unnamed_4_5ca00198(x)} Type___unnamed_4_5ca00198(x) == x + 0);
+axiom (forall x:int :: {Type___unnamed_4_5ca00198Inv(x)} Type___unnamed_4_5ca00198Inv(x) == x - 0);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1) == Type___unnamed_4_5ca00198Inv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 0)} MINUS_LEFT_PTR(x, 1, 0) == Type___unnamed_4_5ca00198Inv(x));
+function UnitId__DEVICE_EXTENSION(int) returns (int);
+function UnitId__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_UnitId__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_UnitId__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {UnitId__DEVICE_EXTENSIONInv(UnitId__DEVICE_EXTENSION(x))} UnitId__DEVICE_EXTENSIONInv(UnitId__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {UnitId__DEVICE_EXTENSIONInv(x)} UnitId__DEVICE_EXTENSION(UnitId__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_UnitId__DEVICE_EXTENSION(S)[x]} _S_UnitId__DEVICE_EXTENSION(S)[x] <==> S[UnitId__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_UnitId__DEVICE_EXTENSIONInv(S)[x]} _S_UnitId__DEVICE_EXTENSIONInv(S)[x] <==> S[UnitId__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_UnitId__DEVICE_EXTENSION(S)} S[x] ==> _S_UnitId__DEVICE_EXTENSION(S)[UnitId__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_UnitId__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_UnitId__DEVICE_EXTENSIONInv(S)[UnitId__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {UnitId__DEVICE_EXTENSION(x)} UnitId__DEVICE_EXTENSION(x) == x + 196);
+axiom (forall x:int :: {UnitId__DEVICE_EXTENSIONInv(x)} UnitId__DEVICE_EXTENSIONInv(x) == x - 196);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 196, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 196, 1) == UnitId__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 196)} MINUS_LEFT_PTR(x, 1, 196) == UnitId__DEVICE_EXTENSIONInv(x));
+function UnitId__KEYBOARD_INDICATOR_PARAMETERS(int) returns (int);
+function UnitId__KEYBOARD_INDICATOR_PARAMETERSInv(int) returns (int);
+function _S_UnitId__KEYBOARD_INDICATOR_PARAMETERS([int]bool) returns ([int]bool);
+function _S_UnitId__KEYBOARD_INDICATOR_PARAMETERSInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {UnitId__KEYBOARD_INDICATOR_PARAMETERSInv(UnitId__KEYBOARD_INDICATOR_PARAMETERS(x))} UnitId__KEYBOARD_INDICATOR_PARAMETERSInv(UnitId__KEYBOARD_INDICATOR_PARAMETERS(x)) == x);
+axiom (forall x:int :: {UnitId__KEYBOARD_INDICATOR_PARAMETERSInv(x)} UnitId__KEYBOARD_INDICATOR_PARAMETERS(UnitId__KEYBOARD_INDICATOR_PARAMETERSInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_UnitId__KEYBOARD_INDICATOR_PARAMETERS(S)[x]} _S_UnitId__KEYBOARD_INDICATOR_PARAMETERS(S)[x] <==> S[UnitId__KEYBOARD_INDICATOR_PARAMETERSInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_UnitId__KEYBOARD_INDICATOR_PARAMETERSInv(S)[x]} _S_UnitId__KEYBOARD_INDICATOR_PARAMETERSInv(S)[x] <==> S[UnitId__KEYBOARD_INDICATOR_PARAMETERS(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_UnitId__KEYBOARD_INDICATOR_PARAMETERS(S)} S[x] ==> _S_UnitId__KEYBOARD_INDICATOR_PARAMETERS(S)[UnitId__KEYBOARD_INDICATOR_PARAMETERS(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_UnitId__KEYBOARD_INDICATOR_PARAMETERSInv(S)} S[x] ==> _S_UnitId__KEYBOARD_INDICATOR_PARAMETERSInv(S)[UnitId__KEYBOARD_INDICATOR_PARAMETERSInv(x)]);
+
+axiom (forall x:int :: {UnitId__KEYBOARD_INDICATOR_PARAMETERS(x)} UnitId__KEYBOARD_INDICATOR_PARAMETERS(x) == x + 0);
+axiom (forall x:int :: {UnitId__KEYBOARD_INDICATOR_PARAMETERSInv(x)} UnitId__KEYBOARD_INDICATOR_PARAMETERSInv(x) == x - 0);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1) == UnitId__KEYBOARD_INDICATOR_PARAMETERSInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 0)} MINUS_LEFT_PTR(x, 1, 0) == UnitId__KEYBOARD_INDICATOR_PARAMETERSInv(x));
+function UnitId__KEYBOARD_TYPEMATIC_PARAMETERS(int) returns (int);
+function UnitId__KEYBOARD_TYPEMATIC_PARAMETERSInv(int) returns (int);
+function _S_UnitId__KEYBOARD_TYPEMATIC_PARAMETERS([int]bool) returns ([int]bool);
+function _S_UnitId__KEYBOARD_TYPEMATIC_PARAMETERSInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {UnitId__KEYBOARD_TYPEMATIC_PARAMETERSInv(UnitId__KEYBOARD_TYPEMATIC_PARAMETERS(x))} UnitId__KEYBOARD_TYPEMATIC_PARAMETERSInv(UnitId__KEYBOARD_TYPEMATIC_PARAMETERS(x)) == x);
+axiom (forall x:int :: {UnitId__KEYBOARD_TYPEMATIC_PARAMETERSInv(x)} UnitId__KEYBOARD_TYPEMATIC_PARAMETERS(UnitId__KEYBOARD_TYPEMATIC_PARAMETERSInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_UnitId__KEYBOARD_TYPEMATIC_PARAMETERS(S)[x]} _S_UnitId__KEYBOARD_TYPEMATIC_PARAMETERS(S)[x] <==> S[UnitId__KEYBOARD_TYPEMATIC_PARAMETERSInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_UnitId__KEYBOARD_TYPEMATIC_PARAMETERSInv(S)[x]} _S_UnitId__KEYBOARD_TYPEMATIC_PARAMETERSInv(S)[x] <==> S[UnitId__KEYBOARD_TYPEMATIC_PARAMETERS(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_UnitId__KEYBOARD_TYPEMATIC_PARAMETERS(S)} S[x] ==> _S_UnitId__KEYBOARD_TYPEMATIC_PARAMETERS(S)[UnitId__KEYBOARD_TYPEMATIC_PARAMETERS(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_UnitId__KEYBOARD_TYPEMATIC_PARAMETERSInv(S)} S[x] ==> _S_UnitId__KEYBOARD_TYPEMATIC_PARAMETERSInv(S)[UnitId__KEYBOARD_TYPEMATIC_PARAMETERSInv(x)]);
+
+axiom (forall x:int :: {UnitId__KEYBOARD_TYPEMATIC_PARAMETERS(x)} UnitId__KEYBOARD_TYPEMATIC_PARAMETERS(x) == x + 0);
+axiom (forall x:int :: {UnitId__KEYBOARD_TYPEMATIC_PARAMETERSInv(x)} UnitId__KEYBOARD_TYPEMATIC_PARAMETERSInv(x) == x - 0);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1) == UnitId__KEYBOARD_TYPEMATIC_PARAMETERSInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 0)} MINUS_LEFT_PTR(x, 1, 0) == UnitId__KEYBOARD_TYPEMATIC_PARAMETERSInv(x));
+function WaitListHead__DISPATCHER_HEADER(int) returns (int);
+function WaitListHead__DISPATCHER_HEADERInv(int) returns (int);
+function _S_WaitListHead__DISPATCHER_HEADER([int]bool) returns ([int]bool);
+function _S_WaitListHead__DISPATCHER_HEADERInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {WaitListHead__DISPATCHER_HEADERInv(WaitListHead__DISPATCHER_HEADER(x))} WaitListHead__DISPATCHER_HEADERInv(WaitListHead__DISPATCHER_HEADER(x)) == x);
+axiom (forall x:int :: {WaitListHead__DISPATCHER_HEADERInv(x)} WaitListHead__DISPATCHER_HEADER(WaitListHead__DISPATCHER_HEADERInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_WaitListHead__DISPATCHER_HEADER(S)[x]} _S_WaitListHead__DISPATCHER_HEADER(S)[x] <==> S[WaitListHead__DISPATCHER_HEADERInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_WaitListHead__DISPATCHER_HEADERInv(S)[x]} _S_WaitListHead__DISPATCHER_HEADERInv(S)[x] <==> S[WaitListHead__DISPATCHER_HEADER(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_WaitListHead__DISPATCHER_HEADER(S)} S[x] ==> _S_WaitListHead__DISPATCHER_HEADER(S)[WaitListHead__DISPATCHER_HEADER(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_WaitListHead__DISPATCHER_HEADERInv(S)} S[x] ==> _S_WaitListHead__DISPATCHER_HEADERInv(S)[WaitListHead__DISPATCHER_HEADERInv(x)]);
+
+axiom (forall x:int :: {WaitListHead__DISPATCHER_HEADER(x)} WaitListHead__DISPATCHER_HEADER(x) == x + 8);
+axiom (forall x:int :: {WaitListHead__DISPATCHER_HEADERInv(x)} WaitListHead__DISPATCHER_HEADERInv(x) == x - 8);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 8, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 8, 1) == WaitListHead__DISPATCHER_HEADERInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 8)} MINUS_LEFT_PTR(x, 1, 8) == WaitListHead__DISPATCHER_HEADERInv(x));
+function WaitWakeEnabled__DEVICE_EXTENSION(int) returns (int);
+function WaitWakeEnabled__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_WaitWakeEnabled__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_WaitWakeEnabled__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {WaitWakeEnabled__DEVICE_EXTENSIONInv(WaitWakeEnabled__DEVICE_EXTENSION(x))} WaitWakeEnabled__DEVICE_EXTENSIONInv(WaitWakeEnabled__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {WaitWakeEnabled__DEVICE_EXTENSIONInv(x)} WaitWakeEnabled__DEVICE_EXTENSION(WaitWakeEnabled__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_WaitWakeEnabled__DEVICE_EXTENSION(S)[x]} _S_WaitWakeEnabled__DEVICE_EXTENSION(S)[x] <==> S[WaitWakeEnabled__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_WaitWakeEnabled__DEVICE_EXTENSIONInv(S)[x]} _S_WaitWakeEnabled__DEVICE_EXTENSIONInv(S)[x] <==> S[WaitWakeEnabled__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_WaitWakeEnabled__DEVICE_EXTENSION(S)} S[x] ==> _S_WaitWakeEnabled__DEVICE_EXTENSION(S)[WaitWakeEnabled__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_WaitWakeEnabled__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_WaitWakeEnabled__DEVICE_EXTENSIONInv(S)[WaitWakeEnabled__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {WaitWakeEnabled__DEVICE_EXTENSION(x)} WaitWakeEnabled__DEVICE_EXTENSION(x) == x + 286);
+axiom (forall x:int :: {WaitWakeEnabled__DEVICE_EXTENSIONInv(x)} WaitWakeEnabled__DEVICE_EXTENSIONInv(x) == x - 286);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 286, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 286, 1) == WaitWakeEnabled__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 286)} MINUS_LEFT_PTR(x, 1, 286) == WaitWakeEnabled__DEVICE_EXTENSIONInv(x));
+function WaitWakeIrp__DEVICE_EXTENSION(int) returns (int);
+function WaitWakeIrp__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_WaitWakeIrp__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_WaitWakeIrp__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {WaitWakeIrp__DEVICE_EXTENSIONInv(WaitWakeIrp__DEVICE_EXTENSION(x))} WaitWakeIrp__DEVICE_EXTENSIONInv(WaitWakeIrp__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {WaitWakeIrp__DEVICE_EXTENSIONInv(x)} WaitWakeIrp__DEVICE_EXTENSION(WaitWakeIrp__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_WaitWakeIrp__DEVICE_EXTENSION(S)[x]} _S_WaitWakeIrp__DEVICE_EXTENSION(S)[x] <==> S[WaitWakeIrp__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_WaitWakeIrp__DEVICE_EXTENSIONInv(S)[x]} _S_WaitWakeIrp__DEVICE_EXTENSIONInv(S)[x] <==> S[WaitWakeIrp__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_WaitWakeIrp__DEVICE_EXTENSION(S)} S[x] ==> _S_WaitWakeIrp__DEVICE_EXTENSION(S)[WaitWakeIrp__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_WaitWakeIrp__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_WaitWakeIrp__DEVICE_EXTENSIONInv(S)[WaitWakeIrp__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {WaitWakeIrp__DEVICE_EXTENSION(x)} WaitWakeIrp__DEVICE_EXTENSION(x) == x + 260);
+axiom (forall x:int :: {WaitWakeIrp__DEVICE_EXTENSIONInv(x)} WaitWakeIrp__DEVICE_EXTENSIONInv(x) == x - 260);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 260, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 260, 1) == WaitWakeIrp__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 260)} MINUS_LEFT_PTR(x, 1, 260) == WaitWakeIrp__DEVICE_EXTENSIONInv(x));
+function WaitWakeSpinLock__DEVICE_EXTENSION(int) returns (int);
+function WaitWakeSpinLock__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_WaitWakeSpinLock__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_WaitWakeSpinLock__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {WaitWakeSpinLock__DEVICE_EXTENSIONInv(WaitWakeSpinLock__DEVICE_EXTENSION(x))} WaitWakeSpinLock__DEVICE_EXTENSIONInv(WaitWakeSpinLock__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {WaitWakeSpinLock__DEVICE_EXTENSIONInv(x)} WaitWakeSpinLock__DEVICE_EXTENSION(WaitWakeSpinLock__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_WaitWakeSpinLock__DEVICE_EXTENSION(S)[x]} _S_WaitWakeSpinLock__DEVICE_EXTENSION(S)[x] <==> S[WaitWakeSpinLock__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_WaitWakeSpinLock__DEVICE_EXTENSIONInv(S)[x]} _S_WaitWakeSpinLock__DEVICE_EXTENSIONInv(S)[x] <==> S[WaitWakeSpinLock__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_WaitWakeSpinLock__DEVICE_EXTENSION(S)} S[x] ==> _S_WaitWakeSpinLock__DEVICE_EXTENSION(S)[WaitWakeSpinLock__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_WaitWakeSpinLock__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_WaitWakeSpinLock__DEVICE_EXTENSIONInv(S)[WaitWakeSpinLock__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {WaitWakeSpinLock__DEVICE_EXTENSION(x)} WaitWakeSpinLock__DEVICE_EXTENSION(x) == x + 108);
+axiom (forall x:int :: {WaitWakeSpinLock__DEVICE_EXTENSIONInv(x)} WaitWakeSpinLock__DEVICE_EXTENSIONInv(x) == x - 108);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 108, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 108, 1) == WaitWakeSpinLock__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 108)} MINUS_LEFT_PTR(x, 1, 108) == WaitWakeSpinLock__DEVICE_EXTENSIONInv(x));
+function WmiFunctionControl__WMILIB_CONTEXT(int) returns (int);
+function WmiFunctionControl__WMILIB_CONTEXTInv(int) returns (int);
+function _S_WmiFunctionControl__WMILIB_CONTEXT([int]bool) returns ([int]bool);
+function _S_WmiFunctionControl__WMILIB_CONTEXTInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {WmiFunctionControl__WMILIB_CONTEXTInv(WmiFunctionControl__WMILIB_CONTEXT(x))} WmiFunctionControl__WMILIB_CONTEXTInv(WmiFunctionControl__WMILIB_CONTEXT(x)) == x);
+axiom (forall x:int :: {WmiFunctionControl__WMILIB_CONTEXTInv(x)} WmiFunctionControl__WMILIB_CONTEXT(WmiFunctionControl__WMILIB_CONTEXTInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_WmiFunctionControl__WMILIB_CONTEXT(S)[x]} _S_WmiFunctionControl__WMILIB_CONTEXT(S)[x] <==> S[WmiFunctionControl__WMILIB_CONTEXTInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_WmiFunctionControl__WMILIB_CONTEXTInv(S)[x]} _S_WmiFunctionControl__WMILIB_CONTEXTInv(S)[x] <==> S[WmiFunctionControl__WMILIB_CONTEXT(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_WmiFunctionControl__WMILIB_CONTEXT(S)} S[x] ==> _S_WmiFunctionControl__WMILIB_CONTEXT(S)[WmiFunctionControl__WMILIB_CONTEXT(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_WmiFunctionControl__WMILIB_CONTEXTInv(S)} S[x] ==> _S_WmiFunctionControl__WMILIB_CONTEXTInv(S)[WmiFunctionControl__WMILIB_CONTEXTInv(x)]);
+
+axiom (forall x:int :: {WmiFunctionControl__WMILIB_CONTEXT(x)} WmiFunctionControl__WMILIB_CONTEXT(x) == x + 28);
+axiom (forall x:int :: {WmiFunctionControl__WMILIB_CONTEXTInv(x)} WmiFunctionControl__WMILIB_CONTEXTInv(x) == x - 28);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 28, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 28, 1) == WmiFunctionControl__WMILIB_CONTEXTInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 28)} MINUS_LEFT_PTR(x, 1, 28) == WmiFunctionControl__WMILIB_CONTEXTInv(x));
+function WmiLibInfo__DEVICE_EXTENSION(int) returns (int);
+function WmiLibInfo__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_WmiLibInfo__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_WmiLibInfo__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {WmiLibInfo__DEVICE_EXTENSIONInv(WmiLibInfo__DEVICE_EXTENSION(x))} WmiLibInfo__DEVICE_EXTENSIONInv(WmiLibInfo__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {WmiLibInfo__DEVICE_EXTENSIONInv(x)} WmiLibInfo__DEVICE_EXTENSION(WmiLibInfo__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_WmiLibInfo__DEVICE_EXTENSION(S)[x]} _S_WmiLibInfo__DEVICE_EXTENSION(S)[x] <==> S[WmiLibInfo__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_WmiLibInfo__DEVICE_EXTENSIONInv(S)[x]} _S_WmiLibInfo__DEVICE_EXTENSIONInv(S)[x] <==> S[WmiLibInfo__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_WmiLibInfo__DEVICE_EXTENSION(S)} S[x] ==> _S_WmiLibInfo__DEVICE_EXTENSION(S)[WmiLibInfo__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_WmiLibInfo__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_WmiLibInfo__DEVICE_EXTENSIONInv(S)[WmiLibInfo__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {WmiLibInfo__DEVICE_EXTENSION(x)} WmiLibInfo__DEVICE_EXTENSION(x) == x + 200);
+axiom (forall x:int :: {WmiLibInfo__DEVICE_EXTENSIONInv(x)} WmiLibInfo__DEVICE_EXTENSIONInv(x) == x - 200);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 200, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 200, 1) == WmiLibInfo__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 200)} MINUS_LEFT_PTR(x, 1, 200) == WmiLibInfo__DEVICE_EXTENSIONInv(x));
+function __unnamed_1_29794256___unnamed_4_5ca00198(int) returns (int);
+function __unnamed_1_29794256___unnamed_4_5ca00198Inv(int) returns (int);
+function _S___unnamed_1_29794256___unnamed_4_5ca00198([int]bool) returns ([int]bool);
+function _S___unnamed_1_29794256___unnamed_4_5ca00198Inv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {__unnamed_1_29794256___unnamed_4_5ca00198Inv(__unnamed_1_29794256___unnamed_4_5ca00198(x))} __unnamed_1_29794256___unnamed_4_5ca00198Inv(__unnamed_1_29794256___unnamed_4_5ca00198(x)) == x);
+axiom (forall x:int :: {__unnamed_1_29794256___unnamed_4_5ca00198Inv(x)} __unnamed_1_29794256___unnamed_4_5ca00198(__unnamed_1_29794256___unnamed_4_5ca00198Inv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S___unnamed_1_29794256___unnamed_4_5ca00198(S)[x]} _S___unnamed_1_29794256___unnamed_4_5ca00198(S)[x] <==> S[__unnamed_1_29794256___unnamed_4_5ca00198Inv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S___unnamed_1_29794256___unnamed_4_5ca00198Inv(S)[x]} _S___unnamed_1_29794256___unnamed_4_5ca00198Inv(S)[x] <==> S[__unnamed_1_29794256___unnamed_4_5ca00198(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S___unnamed_1_29794256___unnamed_4_5ca00198(S)} S[x] ==> _S___unnamed_1_29794256___unnamed_4_5ca00198(S)[__unnamed_1_29794256___unnamed_4_5ca00198(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S___unnamed_1_29794256___unnamed_4_5ca00198Inv(S)} S[x] ==> _S___unnamed_1_29794256___unnamed_4_5ca00198Inv(S)[__unnamed_1_29794256___unnamed_4_5ca00198Inv(x)]);
+
+axiom (forall x:int :: {__unnamed_1_29794256___unnamed_4_5ca00198(x)} __unnamed_1_29794256___unnamed_4_5ca00198(x) == x + 1);
+axiom (forall x:int :: {__unnamed_1_29794256___unnamed_4_5ca00198Inv(x)} __unnamed_1_29794256___unnamed_4_5ca00198Inv(x) == x - 1);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 1, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 1, 1) == __unnamed_1_29794256___unnamed_4_5ca00198Inv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 1)} MINUS_LEFT_PTR(x, 1, 1) == __unnamed_1_29794256___unnamed_4_5ca00198Inv(x));
+function __unnamed_1_2dc63b48___unnamed_4_5ca00198(int) returns (int);
+function __unnamed_1_2dc63b48___unnamed_4_5ca00198Inv(int) returns (int);
+function _S___unnamed_1_2dc63b48___unnamed_4_5ca00198([int]bool) returns ([int]bool);
+function _S___unnamed_1_2dc63b48___unnamed_4_5ca00198Inv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {__unnamed_1_2dc63b48___unnamed_4_5ca00198Inv(__unnamed_1_2dc63b48___unnamed_4_5ca00198(x))} __unnamed_1_2dc63b48___unnamed_4_5ca00198Inv(__unnamed_1_2dc63b48___unnamed_4_5ca00198(x)) == x);
+axiom (forall x:int :: {__unnamed_1_2dc63b48___unnamed_4_5ca00198Inv(x)} __unnamed_1_2dc63b48___unnamed_4_5ca00198(__unnamed_1_2dc63b48___unnamed_4_5ca00198Inv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S___unnamed_1_2dc63b48___unnamed_4_5ca00198(S)[x]} _S___unnamed_1_2dc63b48___unnamed_4_5ca00198(S)[x] <==> S[__unnamed_1_2dc63b48___unnamed_4_5ca00198Inv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S___unnamed_1_2dc63b48___unnamed_4_5ca00198Inv(S)[x]} _S___unnamed_1_2dc63b48___unnamed_4_5ca00198Inv(S)[x] <==> S[__unnamed_1_2dc63b48___unnamed_4_5ca00198(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S___unnamed_1_2dc63b48___unnamed_4_5ca00198(S)} S[x] ==> _S___unnamed_1_2dc63b48___unnamed_4_5ca00198(S)[__unnamed_1_2dc63b48___unnamed_4_5ca00198(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S___unnamed_1_2dc63b48___unnamed_4_5ca00198Inv(S)} S[x] ==> _S___unnamed_1_2dc63b48___unnamed_4_5ca00198Inv(S)[__unnamed_1_2dc63b48___unnamed_4_5ca00198Inv(x)]);
+
+axiom (forall x:int :: {__unnamed_1_2dc63b48___unnamed_4_5ca00198(x)} __unnamed_1_2dc63b48___unnamed_4_5ca00198(x) == x + 3);
+axiom (forall x:int :: {__unnamed_1_2dc63b48___unnamed_4_5ca00198Inv(x)} __unnamed_1_2dc63b48___unnamed_4_5ca00198Inv(x) == x - 3);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 3, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 3, 1) == __unnamed_1_2dc63b48___unnamed_4_5ca00198Inv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 3)} MINUS_LEFT_PTR(x, 1, 3) == __unnamed_1_2dc63b48___unnamed_4_5ca00198Inv(x));
+function __unnamed_1_2ef8da39___unnamed_4_5ca00198(int) returns (int);
+function __unnamed_1_2ef8da39___unnamed_4_5ca00198Inv(int) returns (int);
+function _S___unnamed_1_2ef8da39___unnamed_4_5ca00198([int]bool) returns ([int]bool);
+function _S___unnamed_1_2ef8da39___unnamed_4_5ca00198Inv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {__unnamed_1_2ef8da39___unnamed_4_5ca00198Inv(__unnamed_1_2ef8da39___unnamed_4_5ca00198(x))} __unnamed_1_2ef8da39___unnamed_4_5ca00198Inv(__unnamed_1_2ef8da39___unnamed_4_5ca00198(x)) == x);
+axiom (forall x:int :: {__unnamed_1_2ef8da39___unnamed_4_5ca00198Inv(x)} __unnamed_1_2ef8da39___unnamed_4_5ca00198(__unnamed_1_2ef8da39___unnamed_4_5ca00198Inv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S___unnamed_1_2ef8da39___unnamed_4_5ca00198(S)[x]} _S___unnamed_1_2ef8da39___unnamed_4_5ca00198(S)[x] <==> S[__unnamed_1_2ef8da39___unnamed_4_5ca00198Inv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S___unnamed_1_2ef8da39___unnamed_4_5ca00198Inv(S)[x]} _S___unnamed_1_2ef8da39___unnamed_4_5ca00198Inv(S)[x] <==> S[__unnamed_1_2ef8da39___unnamed_4_5ca00198(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S___unnamed_1_2ef8da39___unnamed_4_5ca00198(S)} S[x] ==> _S___unnamed_1_2ef8da39___unnamed_4_5ca00198(S)[__unnamed_1_2ef8da39___unnamed_4_5ca00198(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S___unnamed_1_2ef8da39___unnamed_4_5ca00198Inv(S)} S[x] ==> _S___unnamed_1_2ef8da39___unnamed_4_5ca00198Inv(S)[__unnamed_1_2ef8da39___unnamed_4_5ca00198Inv(x)]);
+
+axiom (forall x:int :: {__unnamed_1_2ef8da39___unnamed_4_5ca00198(x)} __unnamed_1_2ef8da39___unnamed_4_5ca00198(x) == x + 2);
+axiom (forall x:int :: {__unnamed_1_2ef8da39___unnamed_4_5ca00198Inv(x)} __unnamed_1_2ef8da39___unnamed_4_5ca00198Inv(x) == x - 2);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 2, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 2, 1) == __unnamed_1_2ef8da39___unnamed_4_5ca00198Inv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 2)} MINUS_LEFT_PTR(x, 1, 2) == __unnamed_1_2ef8da39___unnamed_4_5ca00198Inv(x));
+function __unnamed_4_5ca00198___unnamed_4_a97c65a1(int) returns (int);
+function __unnamed_4_5ca00198___unnamed_4_a97c65a1Inv(int) returns (int);
+function _S___unnamed_4_5ca00198___unnamed_4_a97c65a1([int]bool) returns ([int]bool);
+function _S___unnamed_4_5ca00198___unnamed_4_a97c65a1Inv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {__unnamed_4_5ca00198___unnamed_4_a97c65a1Inv(__unnamed_4_5ca00198___unnamed_4_a97c65a1(x))} __unnamed_4_5ca00198___unnamed_4_a97c65a1Inv(__unnamed_4_5ca00198___unnamed_4_a97c65a1(x)) == x);
+axiom (forall x:int :: {__unnamed_4_5ca00198___unnamed_4_a97c65a1Inv(x)} __unnamed_4_5ca00198___unnamed_4_a97c65a1(__unnamed_4_5ca00198___unnamed_4_a97c65a1Inv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S___unnamed_4_5ca00198___unnamed_4_a97c65a1(S)[x]} _S___unnamed_4_5ca00198___unnamed_4_a97c65a1(S)[x] <==> S[__unnamed_4_5ca00198___unnamed_4_a97c65a1Inv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S___unnamed_4_5ca00198___unnamed_4_a97c65a1Inv(S)[x]} _S___unnamed_4_5ca00198___unnamed_4_a97c65a1Inv(S)[x] <==> S[__unnamed_4_5ca00198___unnamed_4_a97c65a1(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S___unnamed_4_5ca00198___unnamed_4_a97c65a1(S)} S[x] ==> _S___unnamed_4_5ca00198___unnamed_4_a97c65a1(S)[__unnamed_4_5ca00198___unnamed_4_a97c65a1(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S___unnamed_4_5ca00198___unnamed_4_a97c65a1Inv(S)} S[x] ==> _S___unnamed_4_5ca00198___unnamed_4_a97c65a1Inv(S)[__unnamed_4_5ca00198___unnamed_4_a97c65a1Inv(x)]);
+
+axiom (forall x:int :: {__unnamed_4_5ca00198___unnamed_4_a97c65a1(x)} __unnamed_4_5ca00198___unnamed_4_a97c65a1(x) == x + 0);
+axiom (forall x:int :: {__unnamed_4_5ca00198___unnamed_4_a97c65a1Inv(x)} __unnamed_4_5ca00198___unnamed_4_a97c65a1Inv(x) == x - 0);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1) == __unnamed_4_5ca00198___unnamed_4_a97c65a1Inv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 0)} MINUS_LEFT_PTR(x, 1, 0) == __unnamed_4_5ca00198___unnamed_4_a97c65a1Inv(x));
+function __unnamed_4_a97c65a1__DISPATCHER_HEADER(int) returns (int);
+function __unnamed_4_a97c65a1__DISPATCHER_HEADERInv(int) returns (int);
+function _S___unnamed_4_a97c65a1__DISPATCHER_HEADER([int]bool) returns ([int]bool);
+function _S___unnamed_4_a97c65a1__DISPATCHER_HEADERInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {__unnamed_4_a97c65a1__DISPATCHER_HEADERInv(__unnamed_4_a97c65a1__DISPATCHER_HEADER(x))} __unnamed_4_a97c65a1__DISPATCHER_HEADERInv(__unnamed_4_a97c65a1__DISPATCHER_HEADER(x)) == x);
+axiom (forall x:int :: {__unnamed_4_a97c65a1__DISPATCHER_HEADERInv(x)} __unnamed_4_a97c65a1__DISPATCHER_HEADER(__unnamed_4_a97c65a1__DISPATCHER_HEADERInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S___unnamed_4_a97c65a1__DISPATCHER_HEADER(S)[x]} _S___unnamed_4_a97c65a1__DISPATCHER_HEADER(S)[x] <==> S[__unnamed_4_a97c65a1__DISPATCHER_HEADERInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S___unnamed_4_a97c65a1__DISPATCHER_HEADERInv(S)[x]} _S___unnamed_4_a97c65a1__DISPATCHER_HEADERInv(S)[x] <==> S[__unnamed_4_a97c65a1__DISPATCHER_HEADER(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S___unnamed_4_a97c65a1__DISPATCHER_HEADER(S)} S[x] ==> _S___unnamed_4_a97c65a1__DISPATCHER_HEADER(S)[__unnamed_4_a97c65a1__DISPATCHER_HEADER(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S___unnamed_4_a97c65a1__DISPATCHER_HEADERInv(S)} S[x] ==> _S___unnamed_4_a97c65a1__DISPATCHER_HEADERInv(S)[__unnamed_4_a97c65a1__DISPATCHER_HEADERInv(x)]);
+
+axiom (forall x:int :: {__unnamed_4_a97c65a1__DISPATCHER_HEADER(x)} __unnamed_4_a97c65a1__DISPATCHER_HEADER(x) == x + 0);
+axiom (forall x:int :: {__unnamed_4_a97c65a1__DISPATCHER_HEADERInv(x)} __unnamed_4_a97c65a1__DISPATCHER_HEADERInv(x) == x - 0);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1) == __unnamed_4_a97c65a1__DISPATCHER_HEADERInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 0)} MINUS_LEFT_PTR(x, 1, 0) == __unnamed_4_a97c65a1__DISPATCHER_HEADERInv(x));
+function MINUS_BOTH_PTR_OR_BOTH_INT(a:int, b:int, size:int) returns (int);
+axiom (forall a:int, b:int, size:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(a,b,size)}
+size * MINUS_BOTH_PTR_OR_BOTH_INT(a,b,size) <= a - b && a - b < size * (MINUS_BOTH_PTR_OR_BOTH_INT(a,b,size) + 1));
+
+function MINUS_LEFT_PTR(a:int, a_size:int, b:int) returns (int);
+axiom(forall a:int, a_size:int, b:int :: {MINUS_LEFT_PTR(a,a_size,b)} MINUS_LEFT_PTR(a,a_size,b) == a - a_size * b);
+
+function PLUS(a:int, a_size:int, b:int) returns (int);
+axiom (forall a:int, a_size:int, b:int :: {PLUS(a,a_size,b)} PLUS(a,a_size,b) == a + a_size * b);
+
+function MULT(a:int, b:int) returns (int); // a*b
+axiom(forall a:int, b:int :: {MULT(a,b)} MULT(a,b) == a * b);
+
+function DIV(a:int, b:int) returns (int); // a/b
+
+axiom(forall a:int, b:int :: {DIV(a,b)}
+a >= 0 && b > 0 ==> b * DIV(a,b) <= a && a < b * (DIV(a,b) + 1)
+);
+
+axiom(forall a:int, b:int :: {DIV(a,b)}
+a >= 0 && b < 0 ==> b * DIV(a,b) <= a && a < b * (DIV(a,b) - 1)
+);
+
+axiom(forall a:int, b:int :: {DIV(a,b)}
+a < 0 && b > 0 ==> b * DIV(a,b) >= a && a > b * (DIV(a,b) - 1)
+);
+
+axiom(forall a:int, b:int :: {DIV(a,b)}
+a < 0 && b < 0 ==> b * DIV(a,b) >= a && a > b * (DIV(a,b) + 1)
+);
+
+function BINARY_BOTH_INT(a:int, b:int) returns (int);
+
+function POW2(a:int) returns (bool);
+axiom POW2(1);
+axiom POW2(2);
+axiom POW2(4);
+axiom POW2(8);
+axiom POW2(16);
+axiom POW2(32);
+axiom POW2(64);
+axiom POW2(128);
+axiom POW2(256);
+axiom POW2(512);
+axiom POW2(1024);
+axiom POW2(2048);
+axiom POW2(4096);
+axiom POW2(8192);
+axiom POW2(16384);
+axiom POW2(32768);
+axiom POW2(65536);
+axiom POW2(131072);
+axiom POW2(262144);
+axiom POW2(524288);
+axiom POW2(1048576);
+axiom POW2(2097152);
+axiom POW2(4194304);
+axiom POW2(8388608);
+axiom POW2(16777216);
+axiom POW2(33554432);
+
+function choose(a:bool, b:int, c:int) returns (x:int);
+axiom(forall a:bool, b:int, c:int :: {choose(a,b,c)} a ==> choose(a,b,c) == b);
+axiom(forall a:bool, b:int, c:int :: {choose(a,b,c)} !a ==> choose(a,b,c) == c);
+
+function BIT_BAND(a:int, b:int) returns (x:int);
+axiom(forall a:int, b:int :: {BIT_BAND(a,b)} a == b ==> BIT_BAND(a,b) == a);
+axiom(forall a:int, b:int :: {BIT_BAND(a,b)} POW2(a) && POW2(b) && a != b ==> BIT_BAND(a,b) == 0);
+axiom(forall a:int, b:int :: {BIT_BAND(a,b)} a == 0 || b == 0 ==> BIT_BAND(a,b) == 0);
+
+function BIT_BOR(a:int, b:int) returns (x:int);
+
+function BIT_BXOR(a:int, b:int) returns (x:int);
+
+function BIT_BNOT(a:int) returns (int);
+
+function LIFT(a:bool) returns (int);
+axiom(forall a:bool :: {LIFT(a)} a <==> LIFT(a) != 0);
+
+function NOT(a:int) returns (int);
+axiom(forall a:int :: {NOT(a)} a == 0 ==> NOT(a) != 0);
+axiom(forall a:int :: {NOT(a)} a != 0 ==> NOT(a) == 0);
+
+function NULL_CHECK(a:int) returns (int);
+axiom(forall a:int :: {NULL_CHECK(a)} a == 0 ==> NULL_CHECK(a) != 0);
+axiom(forall a:int :: {NULL_CHECK(a)} a != 0 ==> NULL_CHECK(a) == 0);
+
+
+
+
+procedure havoc_assert(i:int);
+requires (i != 0);
+
+procedure havoc_assume(i:int);
+ensures (i != 0);
+
+procedure __HAVOC_free(a:int);
+modifies alloc;
+ensures (forall x:int :: {alloc[x]} x == a || old(alloc)[x] == alloc[x]);
+ensures (alloc[a] == FREED);
+// Additional checks guarded by tranlator flags
+// requires alloc[a] == ALLOCATED;
+// requires Base(a) == a;
+
+procedure __HAVOC_malloc(obj_size:int) returns (new:int);
+requires obj_size >= 0;
+modifies alloc;
+ensures (new > 0);
+ensures (forall x:int :: {Base(x)} new <= x && x < new+obj_size ==> Base(x) == new);
+ensures (forall x:int :: {alloc[x]} x == new || old(alloc)[x] == alloc[x]);
+ensures old(alloc)[new] == UNALLOCATED && alloc[new] == ALLOCATED;
+
+procedure nondet_choice() returns (x:int);
+
+procedure _strdup(str:int) returns (new:int);
+
+procedure _xstrcasecmp(a0:int, a1:int) returns (ret:int);
+
+procedure _xstrcmp(a0:int, a1:int) returns (ret:int);
+
+var Res_DEVICE_STACK:[int]int;
+var Res_DEV_EXTN:[int]int;
+var Res_DEV_OBJ_INIT:[int]int;
+var Res_SPIN_LOCK:[int]int;
+
+
+
+////////////////////
+// Between predicate
+////////////////////
+function ReachBetween(f: [int]int, x: int, y: int, z: int) returns (bool);
+function ReachAvoiding(f: [int]int, x: int, y: int, z: int) returns (bool);
+
+
+//////////////////////////
+// Between set constructor
+//////////////////////////
+function ReachBetweenSet(f: [int]int, x: int, z: int) returns ([int]bool);
+
+////////////////////////////////////////////////////
+// axioms relating ReachBetween and ReachBetweenSet
+////////////////////////////////////////////////////
+axiom(forall f: [int]int, x: int, y: int, z: int :: {ReachBetweenSet(f, x, z)[y]} ReachBetweenSet(f, x, z)[y] <==> ReachBetween(f, x, y, z));
+axiom(forall f: [int]int, x: int, y: int, z: int :: {ReachBetween(f, x, y, z), ReachBetweenSet(f, x, z)} ReachBetween(f, x, y, z) ==> ReachBetweenSet(f, x, z)[y]);
+axiom(forall f: [int]int, x: int, z: int :: {ReachBetweenSet(f, x, z)} ReachBetween(f, x, x, x));
+
+
+//////////////////////////
+// Axioms for ReachBetween
+//////////////////////////
+
+// reflexive
+axiom(forall f: [int]int, x: int :: ReachBetween(f, x, x, x));
+
+// step
+//axiom(forall f: [int]int, x: int :: {f[x]} ReachBetween(f, x, f[x], f[x]));
+axiom(forall f: [int]int, x: int, y: int, z: int, w:int :: {ReachBetween(f, y, z, w), f[x]} ReachBetween(f, x, f[x], f[x]));
+
+// reach
+axiom(forall f: [int]int, x: int, y: int :: {f[x], ReachBetween(f, x, y, y)} ReachBetween(f, x, y, y) ==> x == y || ReachBetween(f, x, f[x], y));
+
+// cycle
+axiom(forall f: [int]int, x: int, y:int :: {f[x], ReachBetween(f, x, y, y)} f[x] == x && ReachBetween(f, x, y, y) ==> x == y);
+
+// sandwich
+axiom(forall f: [int]int, x: int, y: int :: {ReachBetween(f, x, y, x)} ReachBetween(f, x, y, x) ==> x == y);
+
+// order1
+axiom(forall f: [int]int, x: int, y: int, z: int :: {ReachBetween(f, x, y, y), ReachBetween(f, x, z, z)} ReachBetween(f, x, y, y) && ReachBetween(f, x, z, z) ==> ReachBetween(f, x, y, z) || ReachBetween(f, x, z, y));
+
+// order2
+axiom(forall f: [int]int, x: int, y: int, z: int :: {ReachBetween(f, x, y, z)} ReachBetween(f, x, y, z) ==> ReachBetween(f, x, y, y) && ReachBetween(f, y, z, z));
+
+// transitive1
+axiom(forall f: [int]int, x: int, y: int, z: int :: {ReachBetween(f, x, y, y), ReachBetween(f, y, z, z)} ReachBetween(f, x, y, y) && ReachBetween(f, y, z, z) ==> ReachBetween(f, x, z, z));
+
+// transitive2
+axiom(forall f: [int]int, x: int, y: int, z: int, w: int :: {ReachBetween(f, x, y, z), ReachBetween(f, y, w, z)} ReachBetween(f, x, y, z) && ReachBetween(f, y, w, z) ==> ReachBetween(f, x, y, w) && ReachBetween(f, x, w, z));
+
+// transitive3
+axiom(forall f: [int]int, x: int, y: int, z: int, w: int :: {ReachBetween(f, x, y, z), ReachBetween(f, x, w, y)} ReachBetween(f, x, y, z) && ReachBetween(f, x, w, y) ==> ReachBetween(f, x, w, z) && ReachBetween(f, w, y, z));
+
+// This axiom is required to deal with the incompleteness of the trigger for the reflexive axiom.
+// It cannot be proved using the rest of the axioms.
+axiom(forall f: [int]int, u:int, x: int :: {ReachBetween(f, u, x, x)} ReachBetween(f, u, x, x) ==> ReachBetween(f, u, u, x));
+
+// relation between ReachAvoiding and ReachBetween
+axiom(forall f: [int]int, x: int, y: int, z: int :: {ReachAvoiding(f, x, y, z)}{ReachBetween(f, x, y, z)} ReachAvoiding(f, x, y, z) <==> (ReachBetween(f, x, y, z) || (ReachBetween(f, x, y, y) && !ReachBetween(f, x, z, z))));
+
+// update
+axiom(forall f: [int]int, u: int, v: int, x: int, p: int, q: int :: {ReachAvoiding(f[p := q], u, v, x)} ReachAvoiding(f[p := q], u, v, x) <==> ((ReachAvoiding(f, u, v, p) && ReachAvoiding(f, u, v, x)) || (ReachAvoiding(f, u, p, x) && p != x && ReachAvoiding(f, q, v, p) && ReachAvoiding(f, q, v, x))));
+ ///////////////////////////////
+ // Shifts for linking fields
+ ///////////////////////////////
+function Shift_Flink__LIST_ENTRY(f: [int]int) returns ([int]int);
+axiom( forall f: [int]int, __x:int :: {f[Flink__LIST_ENTRY(__x)],Shift_Flink__LIST_ENTRY(f)} {Shift_Flink__LIST_ENTRY(f)[__x]} Shift_Flink__LIST_ENTRY(f)[__x] == f[Flink__LIST_ENTRY(__x)]);
+axiom(forall f: [int]int, __x:int, __v:int :: {Shift_Flink__LIST_ENTRY(f[Flink__LIST_ENTRY(__x) := __v])} Shift_Flink__LIST_ENTRY(f[Flink__LIST_ENTRY(__x) := __v]) == Shift_Flink__LIST_ENTRY(f)[__x := __v]);
+
+const unique Globals : int;
+axiom(Globals != 0);
+// the set of constants for 64 bit integers that Boogie doesn't parse
+const unique BOOGIE_LARGE_INT_4294967273:int;
+
+
+
+procedure ExAcquireFastMutex($FastMutex$1$15000.16$ExAcquireFastMutex$41:int);
+
+//TAG: ensures __preserves_mem
+ensures(Mem == old(Mem));
+//TAG: ensures __preserves_resource("DEV_OBJ_INIT") && __preserves_resource("DEV_EXTN")
+ensures((Res_DEV_OBJ_INIT == old(Res_DEV_OBJ_INIT)) && (Res_DEV_EXTN == old(Res_DEV_EXTN)));
+
+modifies Res_DEVICE_STACK;
+
+//TAG: net change in resource DEVICE_STACK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEVICE_STACK[r]} (Empty()[r]) || old(Res_DEVICE_STACK)[r] == Res_DEVICE_STACK[r]));
+modifies Res_DEV_EXTN;
+
+//TAG: net change in resource DEV_EXTN only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_EXTN[r]} (Empty()[r]) || old(Res_DEV_EXTN)[r] == Res_DEV_EXTN[r]));
+modifies Res_DEV_OBJ_INIT;
+
+//TAG: net change in resource DEV_OBJ_INIT only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_OBJ_INIT[r]} (Empty()[r]) || old(Res_DEV_OBJ_INIT)[r] == Res_DEV_OBJ_INIT[r]));
+modifies Res_SPIN_LOCK;
+
+//TAG: net change in resource SPIN_LOCK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_SPIN_LOCK[r]} (Empty()[r]) || old(Res_SPIN_LOCK)[r] == Res_SPIN_LOCK[r]));
+//TAG: updated memory locations at Mem[T.MinorFunction__IO_STACK_LOCATION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.MinorFunction__IO_STACK_LOCATION][_m]} (Empty()[_m]) || Mem[T.MinorFunction__IO_STACK_LOCATION][_m] == old(Mem)[T.MinorFunction__IO_STACK_LOCATION][_m]));
+//TAG: updated memory locations at Mem[T.CurrentStackLocation___unnamed_4_f19b65c1] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.CurrentStackLocation___unnamed_4_f19b65c1][_m]} (Empty()[_m]) || Mem[T.CurrentStackLocation___unnamed_4_f19b65c1][_m] == old(Mem)[T.CurrentStackLocation___unnamed_4_f19b65c1][_m]));
+//TAG: updated memory locations at Mem[T.DeviceExtension__DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.DeviceExtension__DEVICE_OBJECT][_m] == old(Mem)[T.DeviceExtension__DEVICE_OBJECT][_m]));
+//TAG: updated memory locations at Mem[T.Self__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Self__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Self__DEVICE_EXTENSION][_m] == old(Mem)[T.Self__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.Started__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Started__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Started__DEVICE_EXTENSION][_m] == old(Mem)[T.Started__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.GrandMaster__GLOBALS] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.GrandMaster__GLOBALS][_m]} (Empty()[_m]) || Mem[T.GrandMaster__GLOBALS][_m] == old(Mem)[T.GrandMaster__GLOBALS][_m]));
+//TAG: updated memory locations at Mem[T.P_DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.P_DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.P_DEVICE_OBJECT][_m] == old(Mem)[T.P_DEVICE_OBJECT][_m]));
+
+//TAG: havoc memory locations by default
+modifies Mem;
+
+
+procedure ExAllocatePoolWithTag($PoolType$1$14789.57$ExAllocatePoolWithTag$121:int, $NumberOfBytes$2$14790.16$ExAllocatePoolWithTag$121:int, $Tag$3$14791.15$ExAllocatePoolWithTag$121:int) returns ($result.ExAllocatePoolWithTag$14788.0$1$:int);
+
+//TAG: ensures __preserves_mem
+ensures(Mem == old(Mem));
+//TAG: ensures __preserves_resource("DEV_OBJ_INIT") && __preserves_resource("DEV_EXTN")
+ensures((Res_DEV_OBJ_INIT == old(Res_DEV_OBJ_INIT)) && (Res_DEV_EXTN == old(Res_DEV_EXTN)));
+
+modifies Res_DEVICE_STACK;
+
+//TAG: net change in resource DEVICE_STACK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEVICE_STACK[r]} (Empty()[r]) || old(Res_DEVICE_STACK)[r] == Res_DEVICE_STACK[r]));
+modifies Res_DEV_EXTN;
+
+//TAG: net change in resource DEV_EXTN only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_EXTN[r]} (Empty()[r]) || old(Res_DEV_EXTN)[r] == Res_DEV_EXTN[r]));
+modifies Res_DEV_OBJ_INIT;
+
+//TAG: net change in resource DEV_OBJ_INIT only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_OBJ_INIT[r]} (Empty()[r]) || old(Res_DEV_OBJ_INIT)[r] == Res_DEV_OBJ_INIT[r]));
+modifies Res_SPIN_LOCK;
+
+//TAG: net change in resource SPIN_LOCK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_SPIN_LOCK[r]} (Empty()[r]) || old(Res_SPIN_LOCK)[r] == Res_SPIN_LOCK[r]));
+//TAG: updated memory locations at Mem[T.MinorFunction__IO_STACK_LOCATION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.MinorFunction__IO_STACK_LOCATION][_m]} (Empty()[_m]) || Mem[T.MinorFunction__IO_STACK_LOCATION][_m] == old(Mem)[T.MinorFunction__IO_STACK_LOCATION][_m]));
+//TAG: updated memory locations at Mem[T.CurrentStackLocation___unnamed_4_f19b65c1] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.CurrentStackLocation___unnamed_4_f19b65c1][_m]} (Empty()[_m]) || Mem[T.CurrentStackLocation___unnamed_4_f19b65c1][_m] == old(Mem)[T.CurrentStackLocation___unnamed_4_f19b65c1][_m]));
+//TAG: updated memory locations at Mem[T.DeviceExtension__DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.DeviceExtension__DEVICE_OBJECT][_m] == old(Mem)[T.DeviceExtension__DEVICE_OBJECT][_m]));
+//TAG: updated memory locations at Mem[T.Self__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Self__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Self__DEVICE_EXTENSION][_m] == old(Mem)[T.Self__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.Started__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Started__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Started__DEVICE_EXTENSION][_m] == old(Mem)[T.Started__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.GrandMaster__GLOBALS] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.GrandMaster__GLOBALS][_m]} (Empty()[_m]) || Mem[T.GrandMaster__GLOBALS][_m] == old(Mem)[T.GrandMaster__GLOBALS][_m]));
+//TAG: updated memory locations at Mem[T.P_DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.P_DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.P_DEVICE_OBJECT][_m] == old(Mem)[T.P_DEVICE_OBJECT][_m]));
+
+//TAG: havoc memory locations by default
+modifies Mem;
+
+
+procedure ExFreePoolWithTag($P$1$14901.35$ExFreePoolWithTag$81:int, $Tag$2$14902.15$ExFreePoolWithTag$81:int);
+
+//TAG: ensures __preserves_mem
+ensures(Mem == old(Mem));
+//TAG: ensures __preserves_resource("DEV_OBJ_INIT") && __preserves_resource("DEV_EXTN")
+ensures((Res_DEV_OBJ_INIT == old(Res_DEV_OBJ_INIT)) && (Res_DEV_EXTN == old(Res_DEV_EXTN)));
+
+modifies Res_DEVICE_STACK;
+
+//TAG: net change in resource DEVICE_STACK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEVICE_STACK[r]} (Empty()[r]) || old(Res_DEVICE_STACK)[r] == Res_DEVICE_STACK[r]));
+modifies Res_DEV_EXTN;
+
+//TAG: net change in resource DEV_EXTN only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_EXTN[r]} (Empty()[r]) || old(Res_DEV_EXTN)[r] == Res_DEV_EXTN[r]));
+modifies Res_DEV_OBJ_INIT;
+
+//TAG: net change in resource DEV_OBJ_INIT only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_OBJ_INIT[r]} (Empty()[r]) || old(Res_DEV_OBJ_INIT)[r] == Res_DEV_OBJ_INIT[r]));
+modifies Res_SPIN_LOCK;
+
+//TAG: net change in resource SPIN_LOCK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_SPIN_LOCK[r]} (Empty()[r]) || old(Res_SPIN_LOCK)[r] == Res_SPIN_LOCK[r]));
+//TAG: updated memory locations at Mem[T.MinorFunction__IO_STACK_LOCATION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.MinorFunction__IO_STACK_LOCATION][_m]} (Empty()[_m]) || Mem[T.MinorFunction__IO_STACK_LOCATION][_m] == old(Mem)[T.MinorFunction__IO_STACK_LOCATION][_m]));
+//TAG: updated memory locations at Mem[T.CurrentStackLocation___unnamed_4_f19b65c1] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.CurrentStackLocation___unnamed_4_f19b65c1][_m]} (Empty()[_m]) || Mem[T.CurrentStackLocation___unnamed_4_f19b65c1][_m] == old(Mem)[T.CurrentStackLocation___unnamed_4_f19b65c1][_m]));
+//TAG: updated memory locations at Mem[T.DeviceExtension__DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.DeviceExtension__DEVICE_OBJECT][_m] == old(Mem)[T.DeviceExtension__DEVICE_OBJECT][_m]));
+//TAG: updated memory locations at Mem[T.Self__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Self__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Self__DEVICE_EXTENSION][_m] == old(Mem)[T.Self__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.Started__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Started__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Started__DEVICE_EXTENSION][_m] == old(Mem)[T.Started__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.GrandMaster__GLOBALS] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.GrandMaster__GLOBALS][_m]} (Empty()[_m]) || Mem[T.GrandMaster__GLOBALS][_m] == old(Mem)[T.GrandMaster__GLOBALS][_m]));
+//TAG: updated memory locations at Mem[T.P_DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.P_DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.P_DEVICE_OBJECT][_m] == old(Mem)[T.P_DEVICE_OBJECT][_m]));
+
+//TAG: havoc memory locations by default
+modifies Mem;
+
+
+procedure ExReleaseFastMutex($FastMutex$1$15013.16$ExReleaseFastMutex$41:int);
+
+//TAG: ensures __preserves_mem
+ensures(Mem == old(Mem));
+//TAG: ensures __preserves_resource("DEV_OBJ_INIT") && __preserves_resource("DEV_EXTN")
+ensures((Res_DEV_OBJ_INIT == old(Res_DEV_OBJ_INIT)) && (Res_DEV_EXTN == old(Res_DEV_EXTN)));
+
+modifies Res_DEVICE_STACK;
+
+//TAG: net change in resource DEVICE_STACK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEVICE_STACK[r]} (Empty()[r]) || old(Res_DEVICE_STACK)[r] == Res_DEVICE_STACK[r]));
+modifies Res_DEV_EXTN;
+
+//TAG: net change in resource DEV_EXTN only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_EXTN[r]} (Empty()[r]) || old(Res_DEV_EXTN)[r] == Res_DEV_EXTN[r]));
+modifies Res_DEV_OBJ_INIT;
+
+//TAG: net change in resource DEV_OBJ_INIT only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_OBJ_INIT[r]} (Empty()[r]) || old(Res_DEV_OBJ_INIT)[r] == Res_DEV_OBJ_INIT[r]));
+modifies Res_SPIN_LOCK;
+
+//TAG: net change in resource SPIN_LOCK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_SPIN_LOCK[r]} (Empty()[r]) || old(Res_SPIN_LOCK)[r] == Res_SPIN_LOCK[r]));
+//TAG: updated memory locations at Mem[T.MinorFunction__IO_STACK_LOCATION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.MinorFunction__IO_STACK_LOCATION][_m]} (Empty()[_m]) || Mem[T.MinorFunction__IO_STACK_LOCATION][_m] == old(Mem)[T.MinorFunction__IO_STACK_LOCATION][_m]));
+//TAG: updated memory locations at Mem[T.CurrentStackLocation___unnamed_4_f19b65c1] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.CurrentStackLocation___unnamed_4_f19b65c1][_m]} (Empty()[_m]) || Mem[T.CurrentStackLocation___unnamed_4_f19b65c1][_m] == old(Mem)[T.CurrentStackLocation___unnamed_4_f19b65c1][_m]));
+//TAG: updated memory locations at Mem[T.DeviceExtension__DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.DeviceExtension__DEVICE_OBJECT][_m] == old(Mem)[T.DeviceExtension__DEVICE_OBJECT][_m]));
+//TAG: updated memory locations at Mem[T.Self__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Self__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Self__DEVICE_EXTENSION][_m] == old(Mem)[T.Self__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.Started__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Started__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Started__DEVICE_EXTENSION][_m] == old(Mem)[T.Started__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.GrandMaster__GLOBALS] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.GrandMaster__GLOBALS][_m]} (Empty()[_m]) || Mem[T.GrandMaster__GLOBALS][_m] == old(Mem)[T.GrandMaster__GLOBALS][_m]));
+//TAG: updated memory locations at Mem[T.P_DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.P_DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.P_DEVICE_OBJECT][_m] == old(Mem)[T.P_DEVICE_OBJECT][_m]));
+
+//TAG: havoc memory locations by default
+modifies Mem;
+
+
+procedure InitializeListHead_IRP($ListHead$1$12.44$InitializeListHead_IRP$41:int);
+
+//TAG: ensures __preserves_mem
+ensures(Mem == old(Mem));
+//TAG: ensures __preserves_resource("DEV_OBJ_INIT") && __preserves_resource("DEV_EXTN")
+ensures((Res_DEV_OBJ_INIT == old(Res_DEV_OBJ_INIT)) && (Res_DEV_EXTN == old(Res_DEV_EXTN)));
+
+modifies Res_DEVICE_STACK;
+
+//TAG: net change in resource DEVICE_STACK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEVICE_STACK[r]} (Empty()[r]) || old(Res_DEVICE_STACK)[r] == Res_DEVICE_STACK[r]));
+modifies Res_DEV_EXTN;
+
+//TAG: net change in resource DEV_EXTN only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_EXTN[r]} (Empty()[r]) || old(Res_DEV_EXTN)[r] == Res_DEV_EXTN[r]));
+modifies Res_DEV_OBJ_INIT;
+
+//TAG: net change in resource DEV_OBJ_INIT only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_OBJ_INIT[r]} (Empty()[r]) || old(Res_DEV_OBJ_INIT)[r] == Res_DEV_OBJ_INIT[r]));
+modifies Res_SPIN_LOCK;
+
+//TAG: net change in resource SPIN_LOCK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_SPIN_LOCK[r]} (Empty()[r]) || old(Res_SPIN_LOCK)[r] == Res_SPIN_LOCK[r]));
+//TAG: updated memory locations at Mem[T.MinorFunction__IO_STACK_LOCATION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.MinorFunction__IO_STACK_LOCATION][_m]} (Empty()[_m]) || Mem[T.MinorFunction__IO_STACK_LOCATION][_m] == old(Mem)[T.MinorFunction__IO_STACK_LOCATION][_m]));
+//TAG: updated memory locations at Mem[T.CurrentStackLocation___unnamed_4_f19b65c1] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.CurrentStackLocation___unnamed_4_f19b65c1][_m]} (Empty()[_m]) || Mem[T.CurrentStackLocation___unnamed_4_f19b65c1][_m] == old(Mem)[T.CurrentStackLocation___unnamed_4_f19b65c1][_m]));
+//TAG: updated memory locations at Mem[T.DeviceExtension__DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.DeviceExtension__DEVICE_OBJECT][_m] == old(Mem)[T.DeviceExtension__DEVICE_OBJECT][_m]));
+//TAG: updated memory locations at Mem[T.Self__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Self__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Self__DEVICE_EXTENSION][_m] == old(Mem)[T.Self__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.Started__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Started__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Started__DEVICE_EXTENSION][_m] == old(Mem)[T.Started__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.GrandMaster__GLOBALS] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.GrandMaster__GLOBALS][_m]} (Empty()[_m]) || Mem[T.GrandMaster__GLOBALS][_m] == old(Mem)[T.GrandMaster__GLOBALS][_m]));
+//TAG: updated memory locations at Mem[T.P_DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.P_DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.P_DEVICE_OBJECT][_m] == old(Mem)[T.P_DEVICE_OBJECT][_m]));
+
+//TAG: havoc memory locations by default
+modifies Mem;
+
+
+procedure IoCreateDevice($DriverObject$1$21226.25$IoCreateDevice$281:int, $DeviceExtensionSize$2$21227.16$IoCreateDevice$281:int, $DeviceName$3$21228.29$IoCreateDevice$281:int, $DeviceType$4$21229.22$IoCreateDevice$281:int, $DeviceCharacteristics$5$21230.16$IoCreateDevice$281:int, $Exclusive$6$21231.18$IoCreateDevice$281:int, $DeviceObject$7$21237.20$IoCreateDevice$281:int) returns ($result.IoCreateDevice$21225.0$1$:int);
+
+//TAG: ensures (LONG)__return >= 0 ==> *DeviceObject != (void *)0
+ensures(($result.IoCreateDevice$21225.0$1$ >= 0) ==> (Mem[T.P_DEVICE_OBJECT][$DeviceObject$7$21237.20$IoCreateDevice$281] != 0));
+//TAG: ensures (LONG)__return >= 0 ==> (*DeviceObject)->DeviceExtension != (void *)0
+ensures(($result.IoCreateDevice$21225.0$1$ >= 0) ==> (Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.P_DEVICE_OBJECT][$DeviceObject$7$21237.20$IoCreateDevice$281])] != 0));
+//TAG: ensures (LONG)__return >= 0 ==> __resource("DEV_EXTN", (*DeviceObject)->DeviceExtension) == 1
+ensures(($result.IoCreateDevice$21225.0$1$ >= 0) ==> (Res_DEV_EXTN[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.P_DEVICE_OBJECT][$DeviceObject$7$21237.20$IoCreateDevice$281])]] == 1));
+//TAG: ensures (LONG)__return >= 0 ==> __resource("DEV_OBJ_INIT", *DeviceObject) == 1 && __resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)(*DeviceObject))->DeviceExtension)) == 1
+ensures(($result.IoCreateDevice$21225.0$1$ >= 0) ==> ((Res_DEV_OBJ_INIT[Mem[T.P_DEVICE_OBJECT][$DeviceObject$7$21237.20$IoCreateDevice$281]] == 1) && (Res_DEV_EXTN[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.P_DEVICE_OBJECT][$DeviceObject$7$21237.20$IoCreateDevice$281])]] == 1)));
+//TAG: ensures (LONG)__return >= 0 ==> __old_resource("DEV_OBJ_INIT", *DeviceObject) == 0 && __old_resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)(*DeviceObject))->DeviceExtension)) == 0
+ensures(($result.IoCreateDevice$21225.0$1$ >= 0) ==> ((old(Res_DEV_OBJ_INIT)[Mem[T.P_DEVICE_OBJECT][$DeviceObject$7$21237.20$IoCreateDevice$281]] == 0) && (old(Res_DEV_EXTN)[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.P_DEVICE_OBJECT][$DeviceObject$7$21237.20$IoCreateDevice$281])]] == 0)));
+//TAG: ensures (LONG)__return >= 0 ==> __updates_resource("DEV_OBJ_INIT", *DeviceObject, 1) && __updates_resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)(*DeviceObject))->DeviceExtension), 1)
+ensures(($result.IoCreateDevice$21225.0$1$ >= 0) ==> ((Res_DEV_OBJ_INIT == old(Res_DEV_OBJ_INIT)[Mem[T.P_DEVICE_OBJECT][$DeviceObject$7$21237.20$IoCreateDevice$281] := 1]) && (Res_DEV_EXTN == old(Res_DEV_EXTN)[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.P_DEVICE_OBJECT][$DeviceObject$7$21237.20$IoCreateDevice$281])] := 1])));
+//TAG: ensures !((LONG)__return >= 0) ==> __resource("DEV_OBJ_INIT", *DeviceObject) == __old_resource("DEV_OBJ_INIT", *DeviceObject) && __resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)(*DeviceObject))->DeviceExtension)) == __old_resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)(*DeviceObject))->DeviceExtension))
+ensures((!($result.IoCreateDevice$21225.0$1$ >= 0)) ==> ((Res_DEV_OBJ_INIT[Mem[T.P_DEVICE_OBJECT][$DeviceObject$7$21237.20$IoCreateDevice$281]] == old(Res_DEV_OBJ_INIT)[Mem[T.P_DEVICE_OBJECT][$DeviceObject$7$21237.20$IoCreateDevice$281]]) && (Res_DEV_EXTN[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.P_DEVICE_OBJECT][$DeviceObject$7$21237.20$IoCreateDevice$281])]] == old(Res_DEV_EXTN)[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.P_DEVICE_OBJECT][$DeviceObject$7$21237.20$IoCreateDevice$281])]])));
+//TAG: ensures !((LONG)__return >= 0) ==> __preserves_resource("DEV_OBJ_INIT") && __preserves_resource("DEV_EXTN")
+free ensures((!($result.IoCreateDevice$21225.0$1$ >= 0)) ==> ((Res_DEV_OBJ_INIT == old(Res_DEV_OBJ_INIT)) && (Res_DEV_EXTN == old(Res_DEV_EXTN))));
+//TAG: ensures (LONG)__return >= 0 ==> !(__resource("DEV_OBJ_INIT", ((struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)(*DeviceObject))->DeviceExtension))->Self) == 1)
+ensures(($result.IoCreateDevice$21225.0$1$ >= 0) ==> (!(Res_DEV_OBJ_INIT[Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.P_DEVICE_OBJECT][$DeviceObject$7$21237.20$IoCreateDevice$281])])]] == 1)));
+//TAG: ensures !((LONG)__return >= 0) ==> *DeviceObject == __old(*DeviceObject)
+ensures((!($result.IoCreateDevice$21225.0$1$ >= 0)) ==> (Mem[T.P_DEVICE_OBJECT][$DeviceObject$7$21237.20$IoCreateDevice$281] == old(Mem)[T.P_DEVICE_OBJECT][$DeviceObject$7$21237.20$IoCreateDevice$281]));
+//TAG: ensures __preserves_field_map(__offset((*((struct _LIST_ENTRY *)0)).Flink))
+ensures(Mem[T.Flink__LIST_ENTRY] == old(Mem)[T.Flink__LIST_ENTRY]);
+//TAG: ensures (LONG)__return >= 0 ==> __return == 0
+ensures(($result.IoCreateDevice$21225.0$1$ >= 0) ==> ($result.IoCreateDevice$21225.0$1$ == 0));
+
+modifies Res_DEVICE_STACK;
+
+//TAG: net change in resource DEVICE_STACK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEVICE_STACK[r]} (Empty()[r]) || old(Res_DEVICE_STACK)[r] == Res_DEVICE_STACK[r]));
+modifies Res_DEV_EXTN;
+
+//TAG: net change in resource DEV_EXTN only for: __set_empty, (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)(*DeviceObject))->DeviceExtension)
+ensures (Subset(Empty(), Union(Union(Empty(), Empty()), Singleton(Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.P_DEVICE_OBJECT][$DeviceObject$7$21237.20$IoCreateDevice$281])]))) && (forall r:int :: {Res_DEV_EXTN[r]} (Empty()[r]) || (Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.P_DEVICE_OBJECT][$DeviceObject$7$21237.20$IoCreateDevice$281])] == r) || old(Res_DEV_EXTN)[r] == Res_DEV_EXTN[r]));
+modifies Res_DEV_OBJ_INIT;
+
+//TAG: net change in resource DEV_OBJ_INIT only for: __set_empty, *DeviceObject
+ensures (Subset(Empty(), Union(Union(Empty(), Empty()), Singleton(Mem[T.P_DEVICE_OBJECT][$DeviceObject$7$21237.20$IoCreateDevice$281]))) && (forall r:int :: {Res_DEV_OBJ_INIT[r]} (Empty()[r]) || (Mem[T.P_DEVICE_OBJECT][$DeviceObject$7$21237.20$IoCreateDevice$281] == r) || old(Res_DEV_OBJ_INIT)[r] == Res_DEV_OBJ_INIT[r]));
+modifies Res_SPIN_LOCK;
+
+//TAG: net change in resource SPIN_LOCK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_SPIN_LOCK[r]} (Empty()[r]) || old(Res_SPIN_LOCK)[r] == Res_SPIN_LOCK[r]));
+//TAG: updated memory locations at Mem[T.MinorFunction__IO_STACK_LOCATION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.MinorFunction__IO_STACK_LOCATION][_m]} (Empty()[_m]) || Mem[T.MinorFunction__IO_STACK_LOCATION][_m] == old(Mem)[T.MinorFunction__IO_STACK_LOCATION][_m]));
+//TAG: updated memory locations at Mem[T.CurrentStackLocation___unnamed_4_f19b65c1] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.CurrentStackLocation___unnamed_4_f19b65c1][_m]} (Empty()[_m]) || Mem[T.CurrentStackLocation___unnamed_4_f19b65c1][_m] == old(Mem)[T.CurrentStackLocation___unnamed_4_f19b65c1][_m]));
+//TAG: updated memory locations at Mem[T.DeviceExtension__DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.DeviceExtension__DEVICE_OBJECT][_m] == old(Mem)[T.DeviceExtension__DEVICE_OBJECT][_m]));
+//TAG: updated memory locations at Mem[T.Self__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Self__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Self__DEVICE_EXTENSION][_m] == old(Mem)[T.Self__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.Started__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Started__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Started__DEVICE_EXTENSION][_m] == old(Mem)[T.Started__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.GrandMaster__GLOBALS] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.GrandMaster__GLOBALS][_m]} (Empty()[_m]) || Mem[T.GrandMaster__GLOBALS][_m] == old(Mem)[T.GrandMaster__GLOBALS][_m]));
+//TAG: updated memory locations at Mem[T.P_DEVICE_OBJECT] only for: __set_empty, DeviceObject
+ensures (Subset(Empty(), Union(Union(Empty(), Empty()), Singleton($DeviceObject$7$21237.20$IoCreateDevice$281))) && (forall _m:int :: {Mem[T.P_DEVICE_OBJECT][_m]} (Empty()[_m]) || (_m == $DeviceObject$7$21237.20$IoCreateDevice$281) || Mem[T.P_DEVICE_OBJECT][_m] == old(Mem)[T.P_DEVICE_OBJECT][_m]));
+
+//TAG: havoc memory locations by default
+modifies Mem;
+
+
+procedure IoDeleteDevice($DeviceObject$1$21328.67$IoDeleteDevice$41:int);
+
+//TAG: ensures __preserves_mem
+ensures(Mem == old(Mem));
+//TAG: requires 1 ==> __resource("DEV_OBJ_INIT", DeviceObject) == 1 && __resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)DeviceObject)->DeviceExtension)) == 1
+requires((true) ==> ((Res_DEV_OBJ_INIT[$DeviceObject$1$21328.67$IoDeleteDevice$41] == 1) && (Res_DEV_EXTN[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT($DeviceObject$1$21328.67$IoDeleteDevice$41)]] == 1)));
+//TAG: ensures 1 ==> __resource("DEV_OBJ_INIT", DeviceObject) == 0 && __resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)DeviceObject)->DeviceExtension)) == 0
+ensures((true) ==> ((Res_DEV_OBJ_INIT[$DeviceObject$1$21328.67$IoDeleteDevice$41] == 0) && (Res_DEV_EXTN[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT($DeviceObject$1$21328.67$IoDeleteDevice$41)]] == 0)));
+//TAG: ensures 1 ==> __updates_resource("DEV_OBJ_INIT", DeviceObject, 0) && __updates_resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)DeviceObject)->DeviceExtension), 0)
+ensures((true) ==> ((Res_DEV_OBJ_INIT == old(Res_DEV_OBJ_INIT)[$DeviceObject$1$21328.67$IoDeleteDevice$41 := 0]) && (Res_DEV_EXTN == old(Res_DEV_EXTN)[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT($DeviceObject$1$21328.67$IoDeleteDevice$41)] := 0])));
+//TAG: ensures !1 ==> __resource("DEV_OBJ_INIT", DeviceObject) == __old_resource("DEV_OBJ_INIT", DeviceObject) && __resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)DeviceObject)->DeviceExtension)) == __old_resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)DeviceObject)->DeviceExtension))
+ensures((!(true)) ==> ((Res_DEV_OBJ_INIT[$DeviceObject$1$21328.67$IoDeleteDevice$41] == old(Res_DEV_OBJ_INIT)[$DeviceObject$1$21328.67$IoDeleteDevice$41]) && (Res_DEV_EXTN[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT($DeviceObject$1$21328.67$IoDeleteDevice$41)]] == old(Res_DEV_EXTN)[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT($DeviceObject$1$21328.67$IoDeleteDevice$41)]])));
+//TAG: ensures !1 ==> __preserves_resource("DEV_OBJ_INIT") && __preserves_resource("DEV_EXTN")
+free ensures((!(true)) ==> ((Res_DEV_OBJ_INIT == old(Res_DEV_OBJ_INIT)) && (Res_DEV_EXTN == old(Res_DEV_EXTN))));
+
+modifies Res_DEVICE_STACK;
+
+//TAG: net change in resource DEVICE_STACK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEVICE_STACK[r]} (Empty()[r]) || old(Res_DEVICE_STACK)[r] == Res_DEVICE_STACK[r]));
+modifies Res_DEV_EXTN;
+
+//TAG: net change in resource DEV_EXTN only for: __set_empty, (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)DeviceObject)->DeviceExtension)
+ensures (Subset(Empty(), Union(Union(Empty(), Empty()), Singleton(Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT($DeviceObject$1$21328.67$IoDeleteDevice$41)]))) && (forall r:int :: {Res_DEV_EXTN[r]} (Empty()[r]) || (Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT($DeviceObject$1$21328.67$IoDeleteDevice$41)] == r) || old(Res_DEV_EXTN)[r] == Res_DEV_EXTN[r]));
+modifies Res_DEV_OBJ_INIT;
+
+//TAG: net change in resource DEV_OBJ_INIT only for: __set_empty, DeviceObject
+ensures (Subset(Empty(), Union(Union(Empty(), Empty()), Singleton($DeviceObject$1$21328.67$IoDeleteDevice$41))) && (forall r:int :: {Res_DEV_OBJ_INIT[r]} (Empty()[r]) || ($DeviceObject$1$21328.67$IoDeleteDevice$41 == r) || old(Res_DEV_OBJ_INIT)[r] == Res_DEV_OBJ_INIT[r]));
+modifies Res_SPIN_LOCK;
+
+//TAG: net change in resource SPIN_LOCK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_SPIN_LOCK[r]} (Empty()[r]) || old(Res_SPIN_LOCK)[r] == Res_SPIN_LOCK[r]));
+//TAG: updated memory locations at Mem[T.MinorFunction__IO_STACK_LOCATION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.MinorFunction__IO_STACK_LOCATION][_m]} (Empty()[_m]) || Mem[T.MinorFunction__IO_STACK_LOCATION][_m] == old(Mem)[T.MinorFunction__IO_STACK_LOCATION][_m]));
+//TAG: updated memory locations at Mem[T.CurrentStackLocation___unnamed_4_f19b65c1] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.CurrentStackLocation___unnamed_4_f19b65c1][_m]} (Empty()[_m]) || Mem[T.CurrentStackLocation___unnamed_4_f19b65c1][_m] == old(Mem)[T.CurrentStackLocation___unnamed_4_f19b65c1][_m]));
+//TAG: updated memory locations at Mem[T.DeviceExtension__DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.DeviceExtension__DEVICE_OBJECT][_m] == old(Mem)[T.DeviceExtension__DEVICE_OBJECT][_m]));
+//TAG: updated memory locations at Mem[T.Self__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Self__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Self__DEVICE_EXTENSION][_m] == old(Mem)[T.Self__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.Started__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Started__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Started__DEVICE_EXTENSION][_m] == old(Mem)[T.Started__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.GrandMaster__GLOBALS] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.GrandMaster__GLOBALS][_m]} (Empty()[_m]) || Mem[T.GrandMaster__GLOBALS][_m] == old(Mem)[T.GrandMaster__GLOBALS][_m]));
+//TAG: updated memory locations at Mem[T.P_DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.P_DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.P_DEVICE_OBJECT][_m] == old(Mem)[T.P_DEVICE_OBJECT][_m]));
+
+//TAG: havoc memory locations by default
+modifies Mem;
+
+
+procedure IoInitializeRemoveLockEx($Lock$1$22135.25$IoInitializeRemoveLockEx$201:int, $AllocateTag$2$22136.16$IoInitializeRemoveLockEx$201:int, $MaxLockedMinutes$3$22137.16$IoInitializeRemoveLockEx$201:int, $HighWatermark$4$22138.16$IoInitializeRemoveLockEx$201:int, $RemlockSize$5$22139.16$IoInitializeRemoveLockEx$201:int);
+
+//TAG: ensures __preserves_mem
+ensures(Mem == old(Mem));
+//TAG: ensures __preserves_resource("DEV_OBJ_INIT") && __preserves_resource("DEV_EXTN")
+ensures((Res_DEV_OBJ_INIT == old(Res_DEV_OBJ_INIT)) && (Res_DEV_EXTN == old(Res_DEV_EXTN)));
+
+modifies Res_DEVICE_STACK;
+
+//TAG: net change in resource DEVICE_STACK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEVICE_STACK[r]} (Empty()[r]) || old(Res_DEVICE_STACK)[r] == Res_DEVICE_STACK[r]));
+modifies Res_DEV_EXTN;
+
+//TAG: net change in resource DEV_EXTN only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_EXTN[r]} (Empty()[r]) || old(Res_DEV_EXTN)[r] == Res_DEV_EXTN[r]));
+modifies Res_DEV_OBJ_INIT;
+
+//TAG: net change in resource DEV_OBJ_INIT only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_OBJ_INIT[r]} (Empty()[r]) || old(Res_DEV_OBJ_INIT)[r] == Res_DEV_OBJ_INIT[r]));
+modifies Res_SPIN_LOCK;
+
+//TAG: net change in resource SPIN_LOCK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_SPIN_LOCK[r]} (Empty()[r]) || old(Res_SPIN_LOCK)[r] == Res_SPIN_LOCK[r]));
+//TAG: updated memory locations at Mem[T.MinorFunction__IO_STACK_LOCATION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.MinorFunction__IO_STACK_LOCATION][_m]} (Empty()[_m]) || Mem[T.MinorFunction__IO_STACK_LOCATION][_m] == old(Mem)[T.MinorFunction__IO_STACK_LOCATION][_m]));
+//TAG: updated memory locations at Mem[T.CurrentStackLocation___unnamed_4_f19b65c1] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.CurrentStackLocation___unnamed_4_f19b65c1][_m]} (Empty()[_m]) || Mem[T.CurrentStackLocation___unnamed_4_f19b65c1][_m] == old(Mem)[T.CurrentStackLocation___unnamed_4_f19b65c1][_m]));
+//TAG: updated memory locations at Mem[T.DeviceExtension__DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.DeviceExtension__DEVICE_OBJECT][_m] == old(Mem)[T.DeviceExtension__DEVICE_OBJECT][_m]));
+//TAG: updated memory locations at Mem[T.Self__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Self__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Self__DEVICE_EXTENSION][_m] == old(Mem)[T.Self__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.Started__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Started__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Started__DEVICE_EXTENSION][_m] == old(Mem)[T.Started__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.GrandMaster__GLOBALS] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.GrandMaster__GLOBALS][_m]} (Empty()[_m]) || Mem[T.GrandMaster__GLOBALS][_m] == old(Mem)[T.GrandMaster__GLOBALS][_m]));
+//TAG: updated memory locations at Mem[T.P_DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.P_DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.P_DEVICE_OBJECT][_m] == old(Mem)[T.P_DEVICE_OBJECT][_m]));
+
+//TAG: havoc memory locations by default
+modifies Mem;
+
+
+procedure KbdInitializeDataQueue($Context$1$557.13$KbdInitializeDataQueue$41:int);
+
+//TAG: requires __resource("DEV_EXTN", Context) == 1
+requires(Res_DEV_EXTN[$Context$1$557.13$KbdInitializeDataQueue$41] == 1);
+//TAG: requires __pforall(_H_x, (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension), __inv_resource("DEV_OBJ_INIT", 1), ((struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension))->Self == _H_x && __resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension)) == 1)
+requires((forall _H_x:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)]} Inverse(Res_DEV_OBJ_INIT,1)[_H_x] ==> ((Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)])] == _H_x) && (Res_DEV_EXTN[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)]] == 1))));
+//TAG: requires __pforall(_H_z, _H_z->Self, __inv_resource("DEV_EXTN", 1), __resource("DEV_OBJ_INIT", _H_z->Self) == 1 && (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)(_H_z->Self))->DeviceExtension) == _H_z)
+requires((forall _H_z:int :: {Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)]} Inverse(Res_DEV_EXTN,1)[_H_z] ==> ((Res_DEV_OBJ_INIT[Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)]] == 1) && (Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)])] == _H_z))));
+//TAG: requires __forall(_H_z, __inv_resource("DEV_EXTN", 1), 1)
+requires((Subset(Empty(), Inverse(Res_DEV_EXTN,1)) && (forall _H_z : int :: {Inverse(Res_DEV_EXTN,1)[_H_z]} (Inverse(Res_DEV_EXTN,1)[_H_z]) ==> (true))));
+//TAG: requires 1 ==> (Globals.GrandMaster != (void *)0 ==> __resource("DEV_EXTN", Globals.GrandMaster) == 1)
+requires((true) ==> ((Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)] != 0) ==> (Res_DEV_EXTN[Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)]] == 1)));
+//TAG: requires 1 ==> __setin(&Globals.LegacyDeviceList, __btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList))
+requires((true) ==> (ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[LegacyDeviceList__GLOBALS(Globals)]));
+//TAG: requires 1 ==> __forall(_H_y, __btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList), _H_y == &Globals.LegacyDeviceList || __resource("DEV_EXTN", CONTAINING_RECORD(_H_y, struct _DEVICE_EXTENSION , Link)) == 1)
+requires((true) ==> ((Subset(Empty(), ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))) && (forall _H_y : int :: {ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[_H_y]} (ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[_H_y]) ==> ((_H_y == LegacyDeviceList__GLOBALS(Globals)) || (Res_DEV_EXTN[MINUS_LEFT_PTR(_H_y, 1, Link__DEVICE_EXTENSION(0))] == 1))))));
+//TAG: requires 1 ==> !__setin(&Globals.GrandMaster->Link, __setminus(__btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList), __set(&Globals.LegacyDeviceList)))
+requires((true) ==> (!(Difference(ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals)), Singleton(LegacyDeviceList__GLOBALS(Globals)))[Link__DEVICE_EXTENSION(Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)])])));
+//TAG: ensures __resource("DEV_EXTN", Context) == 1
+ensures(Res_DEV_EXTN[$Context$1$557.13$KbdInitializeDataQueue$41] == 1);
+//TAG: ensures __pforall(_H_x, (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension), __inv_resource("DEV_OBJ_INIT", 1), ((struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension))->Self == _H_x && __resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension)) == 1)
+ensures((forall _H_x:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)]} Inverse(Res_DEV_OBJ_INIT,1)[_H_x] ==> ((Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)])] == _H_x) && (Res_DEV_EXTN[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)]] == 1))));
+//TAG: ensures __pforall(_H_z, _H_z->Self, __inv_resource("DEV_EXTN", 1), __resource("DEV_OBJ_INIT", _H_z->Self) == 1 && (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)(_H_z->Self))->DeviceExtension) == _H_z)
+ensures((forall _H_z:int :: {Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)]} Inverse(Res_DEV_EXTN,1)[_H_z] ==> ((Res_DEV_OBJ_INIT[Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)]] == 1) && (Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)])] == _H_z))));
+//TAG: ensures __forall(_H_z, __inv_resource("DEV_EXTN", 1), 1)
+ensures((Subset(Empty(), Inverse(Res_DEV_EXTN,1)) && (forall _H_z : int :: {Inverse(Res_DEV_EXTN,1)[_H_z]} (Inverse(Res_DEV_EXTN,1)[_H_z]) ==> (true))));
+//TAG: ensures 1 ==> (Globals.GrandMaster != (void *)0 ==> __resource("DEV_EXTN", Globals.GrandMaster) == 1)
+ensures((true) ==> ((Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)] != 0) ==> (Res_DEV_EXTN[Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)]] == 1)));
+//TAG: ensures 1 ==> __setin(&Globals.LegacyDeviceList, __btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList))
+ensures((true) ==> (ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[LegacyDeviceList__GLOBALS(Globals)]));
+//TAG: ensures 1 ==> __forall(_H_y, __btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList), _H_y == &Globals.LegacyDeviceList || __resource("DEV_EXTN", CONTAINING_RECORD(_H_y, struct _DEVICE_EXTENSION , Link)) == 1)
+ensures((true) ==> ((Subset(Empty(), ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))) && (forall _H_y : int :: {ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[_H_y]} (ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[_H_y]) ==> ((_H_y == LegacyDeviceList__GLOBALS(Globals)) || (Res_DEV_EXTN[MINUS_LEFT_PTR(_H_y, 1, Link__DEVICE_EXTENSION(0))] == 1))))));
+//TAG: ensures 1 ==> !__setin(&Globals.GrandMaster->Link, __setminus(__btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList), __set(&Globals.LegacyDeviceList)))
+ensures((true) ==> (!(Difference(ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals)), Singleton(LegacyDeviceList__GLOBALS(Globals)))[Link__DEVICE_EXTENSION(Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)])])));
+//TAG: ensures __preserves_field_map(__offset((*((struct _LIST_ENTRY *)0)).Flink))
+ensures(Mem[T.Flink__LIST_ENTRY] == old(Mem)[T.Flink__LIST_ENTRY]);
+//TAG: ensures __preserves_resource("DEV_OBJ_INIT")
+ensures(Res_DEV_OBJ_INIT == old(Res_DEV_OBJ_INIT));
+//TAG: ensures __preserves_resource("DEV_EXTN")
+ensures(Res_DEV_EXTN == old(Res_DEV_EXTN));
+
+modifies Res_DEVICE_STACK;
+
+//TAG: net change in resource DEVICE_STACK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEVICE_STACK[r]} (Empty()[r]) || old(Res_DEVICE_STACK)[r] == Res_DEVICE_STACK[r]));
+modifies Res_DEV_EXTN;
+
+//TAG: net change in resource DEV_EXTN only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_EXTN[r]} (Empty()[r]) || old(Res_DEV_EXTN)[r] == Res_DEV_EXTN[r]));
+modifies Res_DEV_OBJ_INIT;
+
+//TAG: net change in resource DEV_OBJ_INIT only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_OBJ_INIT[r]} (Empty()[r]) || old(Res_DEV_OBJ_INIT)[r] == Res_DEV_OBJ_INIT[r]));
+modifies Res_SPIN_LOCK;
+
+//TAG: net change in resource SPIN_LOCK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_SPIN_LOCK[r]} (Empty()[r]) || old(Res_SPIN_LOCK)[r] == Res_SPIN_LOCK[r]));
+//TAG: updated memory locations at Mem[T.MinorFunction__IO_STACK_LOCATION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.MinorFunction__IO_STACK_LOCATION][_m]} (Empty()[_m]) || Mem[T.MinorFunction__IO_STACK_LOCATION][_m] == old(Mem)[T.MinorFunction__IO_STACK_LOCATION][_m]));
+//TAG: updated memory locations at Mem[T.CurrentStackLocation___unnamed_4_f19b65c1] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.CurrentStackLocation___unnamed_4_f19b65c1][_m]} (Empty()[_m]) || Mem[T.CurrentStackLocation___unnamed_4_f19b65c1][_m] == old(Mem)[T.CurrentStackLocation___unnamed_4_f19b65c1][_m]));
+//TAG: updated memory locations at Mem[T.DeviceExtension__DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.DeviceExtension__DEVICE_OBJECT][_m] == old(Mem)[T.DeviceExtension__DEVICE_OBJECT][_m]));
+//TAG: updated memory locations at Mem[T.Self__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Self__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Self__DEVICE_EXTENSION][_m] == old(Mem)[T.Self__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.Started__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Started__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Started__DEVICE_EXTENSION][_m] == old(Mem)[T.Started__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.GrandMaster__GLOBALS] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.GrandMaster__GLOBALS][_m]} (Empty()[_m]) || Mem[T.GrandMaster__GLOBALS][_m] == old(Mem)[T.GrandMaster__GLOBALS][_m]));
+//TAG: updated memory locations at Mem[T.P_DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.P_DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.P_DEVICE_OBJECT][_m] == old(Mem)[T.P_DEVICE_OBJECT][_m]));
+
+//TAG: havoc memory locations by default
+modifies Mem;
+
+
+procedure KeInitializeSpinLock($SpinLock$1$13860.22$KeInitializeSpinLock$41:int);
+
+//TAG: ensures __preserves_mem
+ensures(Mem == old(Mem));
+//TAG: ensures __preserves_resource("DEV_OBJ_INIT") && __preserves_resource("DEV_EXTN")
+ensures((Res_DEV_OBJ_INIT == old(Res_DEV_OBJ_INIT)) && (Res_DEV_EXTN == old(Res_DEV_EXTN)));
+
+modifies Res_DEVICE_STACK;
+
+//TAG: net change in resource DEVICE_STACK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEVICE_STACK[r]} (Empty()[r]) || old(Res_DEVICE_STACK)[r] == Res_DEVICE_STACK[r]));
+modifies Res_DEV_EXTN;
+
+//TAG: net change in resource DEV_EXTN only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_EXTN[r]} (Empty()[r]) || old(Res_DEV_EXTN)[r] == Res_DEV_EXTN[r]));
+modifies Res_DEV_OBJ_INIT;
+
+//TAG: net change in resource DEV_OBJ_INIT only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_OBJ_INIT[r]} (Empty()[r]) || old(Res_DEV_OBJ_INIT)[r] == Res_DEV_OBJ_INIT[r]));
+modifies Res_SPIN_LOCK;
+
+//TAG: net change in resource SPIN_LOCK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_SPIN_LOCK[r]} (Empty()[r]) || old(Res_SPIN_LOCK)[r] == Res_SPIN_LOCK[r]));
+//TAG: updated memory locations at Mem[T.MinorFunction__IO_STACK_LOCATION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.MinorFunction__IO_STACK_LOCATION][_m]} (Empty()[_m]) || Mem[T.MinorFunction__IO_STACK_LOCATION][_m] == old(Mem)[T.MinorFunction__IO_STACK_LOCATION][_m]));
+//TAG: updated memory locations at Mem[T.CurrentStackLocation___unnamed_4_f19b65c1] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.CurrentStackLocation___unnamed_4_f19b65c1][_m]} (Empty()[_m]) || Mem[T.CurrentStackLocation___unnamed_4_f19b65c1][_m] == old(Mem)[T.CurrentStackLocation___unnamed_4_f19b65c1][_m]));
+//TAG: updated memory locations at Mem[T.DeviceExtension__DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.DeviceExtension__DEVICE_OBJECT][_m] == old(Mem)[T.DeviceExtension__DEVICE_OBJECT][_m]));
+//TAG: updated memory locations at Mem[T.Self__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Self__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Self__DEVICE_EXTENSION][_m] == old(Mem)[T.Self__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.Started__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Started__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Started__DEVICE_EXTENSION][_m] == old(Mem)[T.Started__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.GrandMaster__GLOBALS] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.GrandMaster__GLOBALS][_m]} (Empty()[_m]) || Mem[T.GrandMaster__GLOBALS][_m] == old(Mem)[T.GrandMaster__GLOBALS][_m]));
+//TAG: updated memory locations at Mem[T.P_DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.P_DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.P_DEVICE_OBJECT][_m] == old(Mem)[T.P_DEVICE_OBJECT][_m]));
+
+//TAG: havoc memory locations by default
+modifies Mem;
+
+
+procedure KeyboardClassLogError($Object$1$580.10$KeyboardClassLogError$281:int, $ErrorCode$2$581.10$KeyboardClassLogError$281:int, $UniqueErrorValue$3$582.10$KeyboardClassLogError$281:int, $FinalStatus$4$583.13$KeyboardClassLogError$281:int, $DumpCount$5$584.10$KeyboardClassLogError$281:int, $DumpData$6$585.11$KeyboardClassLogError$281:int, $MajorFunction$7$586.10$KeyboardClassLogError$281:int);
+
+//TAG: requires __pforall(_H_x, (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension), __inv_resource("DEV_OBJ_INIT", 1), ((struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension))->Self == _H_x && __resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension)) == 1)
+requires((forall _H_x:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)]} Inverse(Res_DEV_OBJ_INIT,1)[_H_x] ==> ((Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)])] == _H_x) && (Res_DEV_EXTN[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)]] == 1))));
+//TAG: requires __pforall(_H_z, _H_z->Self, __inv_resource("DEV_EXTN", 1), __resource("DEV_OBJ_INIT", _H_z->Self) == 1 && (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)(_H_z->Self))->DeviceExtension) == _H_z)
+requires((forall _H_z:int :: {Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)]} Inverse(Res_DEV_EXTN,1)[_H_z] ==> ((Res_DEV_OBJ_INIT[Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)]] == 1) && (Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)])] == _H_z))));
+//TAG: requires __forall(_H_z, __inv_resource("DEV_EXTN", 1), 1)
+requires((Subset(Empty(), Inverse(Res_DEV_EXTN,1)) && (forall _H_z : int :: {Inverse(Res_DEV_EXTN,1)[_H_z]} (Inverse(Res_DEV_EXTN,1)[_H_z]) ==> (true))));
+//TAG: requires 1 ==> (Globals.GrandMaster != (void *)0 ==> __resource("DEV_EXTN", Globals.GrandMaster) == 1)
+requires((true) ==> ((Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)] != 0) ==> (Res_DEV_EXTN[Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)]] == 1)));
+//TAG: requires 1 ==> __setin(&Globals.LegacyDeviceList, __btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList))
+requires((true) ==> (ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[LegacyDeviceList__GLOBALS(Globals)]));
+//TAG: requires 1 ==> __forall(_H_y, __btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList), _H_y == &Globals.LegacyDeviceList || __resource("DEV_EXTN", CONTAINING_RECORD(_H_y, struct _DEVICE_EXTENSION , Link)) == 1)
+requires((true) ==> ((Subset(Empty(), ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))) && (forall _H_y : int :: {ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[_H_y]} (ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[_H_y]) ==> ((_H_y == LegacyDeviceList__GLOBALS(Globals)) || (Res_DEV_EXTN[MINUS_LEFT_PTR(_H_y, 1, Link__DEVICE_EXTENSION(0))] == 1))))));
+//TAG: requires 1 ==> !__setin(&Globals.GrandMaster->Link, __setminus(__btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList), __set(&Globals.LegacyDeviceList)))
+requires((true) ==> (!(Difference(ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals)), Singleton(LegacyDeviceList__GLOBALS(Globals)))[Link__DEVICE_EXTENSION(Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)])])));
+//TAG: ensures __pforall(_H_x, (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension), __inv_resource("DEV_OBJ_INIT", 1), ((struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension))->Self == _H_x && __resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension)) == 1)
+ensures((forall _H_x:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)]} Inverse(Res_DEV_OBJ_INIT,1)[_H_x] ==> ((Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)])] == _H_x) && (Res_DEV_EXTN[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)]] == 1))));
+//TAG: ensures __pforall(_H_z, _H_z->Self, __inv_resource("DEV_EXTN", 1), __resource("DEV_OBJ_INIT", _H_z->Self) == 1 && (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)(_H_z->Self))->DeviceExtension) == _H_z)
+ensures((forall _H_z:int :: {Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)]} Inverse(Res_DEV_EXTN,1)[_H_z] ==> ((Res_DEV_OBJ_INIT[Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)]] == 1) && (Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)])] == _H_z))));
+//TAG: ensures __forall(_H_z, __inv_resource("DEV_EXTN", 1), 1)
+ensures((Subset(Empty(), Inverse(Res_DEV_EXTN,1)) && (forall _H_z : int :: {Inverse(Res_DEV_EXTN,1)[_H_z]} (Inverse(Res_DEV_EXTN,1)[_H_z]) ==> (true))));
+//TAG: ensures 1 ==> (Globals.GrandMaster != (void *)0 ==> __resource("DEV_EXTN", Globals.GrandMaster) == 1)
+ensures((true) ==> ((Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)] != 0) ==> (Res_DEV_EXTN[Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)]] == 1)));
+//TAG: ensures 1 ==> __setin(&Globals.LegacyDeviceList, __btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList))
+ensures((true) ==> (ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[LegacyDeviceList__GLOBALS(Globals)]));
+//TAG: ensures 1 ==> __forall(_H_y, __btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList), _H_y == &Globals.LegacyDeviceList || __resource("DEV_EXTN", CONTAINING_RECORD(_H_y, struct _DEVICE_EXTENSION , Link)) == 1)
+ensures((true) ==> ((Subset(Empty(), ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))) && (forall _H_y : int :: {ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[_H_y]} (ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[_H_y]) ==> ((_H_y == LegacyDeviceList__GLOBALS(Globals)) || (Res_DEV_EXTN[MINUS_LEFT_PTR(_H_y, 1, Link__DEVICE_EXTENSION(0))] == 1))))));
+//TAG: ensures 1 ==> !__setin(&Globals.GrandMaster->Link, __setminus(__btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList), __set(&Globals.LegacyDeviceList)))
+ensures((true) ==> (!(Difference(ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals)), Singleton(LegacyDeviceList__GLOBALS(Globals)))[Link__DEVICE_EXTENSION(Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)])])));
+//TAG: ensures __preserves_field_map(__offset((*((struct _LIST_ENTRY *)0)).Flink))
+ensures(Mem[T.Flink__LIST_ENTRY] == old(Mem)[T.Flink__LIST_ENTRY]);
+//TAG: ensures __preserves_resource("DEV_OBJ_INIT")
+ensures(Res_DEV_OBJ_INIT == old(Res_DEV_OBJ_INIT));
+//TAG: ensures __preserves_resource("DEV_EXTN")
+ensures(Res_DEV_EXTN == old(Res_DEV_EXTN));
+
+modifies Res_DEVICE_STACK;
+
+//TAG: net change in resource DEVICE_STACK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEVICE_STACK[r]} (Empty()[r]) || old(Res_DEVICE_STACK)[r] == Res_DEVICE_STACK[r]));
+modifies Res_DEV_EXTN;
+
+//TAG: net change in resource DEV_EXTN only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_EXTN[r]} (Empty()[r]) || old(Res_DEV_EXTN)[r] == Res_DEV_EXTN[r]));
+modifies Res_DEV_OBJ_INIT;
+
+//TAG: net change in resource DEV_OBJ_INIT only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_OBJ_INIT[r]} (Empty()[r]) || old(Res_DEV_OBJ_INIT)[r] == Res_DEV_OBJ_INIT[r]));
+modifies Res_SPIN_LOCK;
+
+//TAG: net change in resource SPIN_LOCK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_SPIN_LOCK[r]} (Empty()[r]) || old(Res_SPIN_LOCK)[r] == Res_SPIN_LOCK[r]));
+//TAG: updated memory locations at Mem[T.MinorFunction__IO_STACK_LOCATION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.MinorFunction__IO_STACK_LOCATION][_m]} (Empty()[_m]) || Mem[T.MinorFunction__IO_STACK_LOCATION][_m] == old(Mem)[T.MinorFunction__IO_STACK_LOCATION][_m]));
+//TAG: updated memory locations at Mem[T.CurrentStackLocation___unnamed_4_f19b65c1] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.CurrentStackLocation___unnamed_4_f19b65c1][_m]} (Empty()[_m]) || Mem[T.CurrentStackLocation___unnamed_4_f19b65c1][_m] == old(Mem)[T.CurrentStackLocation___unnamed_4_f19b65c1][_m]));
+//TAG: updated memory locations at Mem[T.DeviceExtension__DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.DeviceExtension__DEVICE_OBJECT][_m] == old(Mem)[T.DeviceExtension__DEVICE_OBJECT][_m]));
+//TAG: updated memory locations at Mem[T.Self__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Self__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Self__DEVICE_EXTENSION][_m] == old(Mem)[T.Self__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.Started__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Started__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Started__DEVICE_EXTENSION][_m] == old(Mem)[T.Started__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.GrandMaster__GLOBALS] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.GrandMaster__GLOBALS][_m]} (Empty()[_m]) || Mem[T.GrandMaster__GLOBALS][_m] == old(Mem)[T.GrandMaster__GLOBALS][_m]));
+//TAG: updated memory locations at Mem[T.P_DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.P_DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.P_DEVICE_OBJECT][_m] == old(Mem)[T.P_DEVICE_OBJECT][_m]));
+
+//TAG: havoc memory locations by default
+modifies Mem;
+
+
+procedure RtlAppendUnicodeToString($Destination$1$7421.28$RtlAppendUnicodeToString$81:int, $Source$2$7422.20$RtlAppendUnicodeToString$81:int) returns ($result.RtlAppendUnicodeToString$7420.0$1$:int);
+
+//TAG: ensures __preserves_mem
+ensures(Mem == old(Mem));
+//TAG: ensures __preserves_resource("DEV_OBJ_INIT") && __preserves_resource("DEV_EXTN")
+ensures((Res_DEV_OBJ_INIT == old(Res_DEV_OBJ_INIT)) && (Res_DEV_EXTN == old(Res_DEV_EXTN)));
+
+modifies Res_DEVICE_STACK;
+
+//TAG: net change in resource DEVICE_STACK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEVICE_STACK[r]} (Empty()[r]) || old(Res_DEVICE_STACK)[r] == Res_DEVICE_STACK[r]));
+modifies Res_DEV_EXTN;
+
+//TAG: net change in resource DEV_EXTN only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_EXTN[r]} (Empty()[r]) || old(Res_DEV_EXTN)[r] == Res_DEV_EXTN[r]));
+modifies Res_DEV_OBJ_INIT;
+
+//TAG: net change in resource DEV_OBJ_INIT only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_OBJ_INIT[r]} (Empty()[r]) || old(Res_DEV_OBJ_INIT)[r] == Res_DEV_OBJ_INIT[r]));
+modifies Res_SPIN_LOCK;
+
+//TAG: net change in resource SPIN_LOCK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_SPIN_LOCK[r]} (Empty()[r]) || old(Res_SPIN_LOCK)[r] == Res_SPIN_LOCK[r]));
+//TAG: updated memory locations at Mem[T.MinorFunction__IO_STACK_LOCATION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.MinorFunction__IO_STACK_LOCATION][_m]} (Empty()[_m]) || Mem[T.MinorFunction__IO_STACK_LOCATION][_m] == old(Mem)[T.MinorFunction__IO_STACK_LOCATION][_m]));
+//TAG: updated memory locations at Mem[T.CurrentStackLocation___unnamed_4_f19b65c1] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.CurrentStackLocation___unnamed_4_f19b65c1][_m]} (Empty()[_m]) || Mem[T.CurrentStackLocation___unnamed_4_f19b65c1][_m] == old(Mem)[T.CurrentStackLocation___unnamed_4_f19b65c1][_m]));
+//TAG: updated memory locations at Mem[T.DeviceExtension__DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.DeviceExtension__DEVICE_OBJECT][_m] == old(Mem)[T.DeviceExtension__DEVICE_OBJECT][_m]));
+//TAG: updated memory locations at Mem[T.Self__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Self__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Self__DEVICE_EXTENSION][_m] == old(Mem)[T.Self__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.Started__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Started__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Started__DEVICE_EXTENSION][_m] == old(Mem)[T.Started__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.GrandMaster__GLOBALS] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.GrandMaster__GLOBALS][_m]} (Empty()[_m]) || Mem[T.GrandMaster__GLOBALS][_m] == old(Mem)[T.GrandMaster__GLOBALS][_m]));
+//TAG: updated memory locations at Mem[T.P_DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.P_DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.P_DEVICE_OBJECT][_m] == old(Mem)[T.P_DEVICE_OBJECT][_m]));
+
+//TAG: havoc memory locations by default
+modifies Mem;
+
+
+procedure RtlFreeUnicodeString($UnicodeString$1$7452.28$RtlFreeUnicodeString$41:int);
+
+//TAG: ensures __preserves_mem
+ensures(Mem == old(Mem));
+//TAG: ensures __preserves_resource("DEV_OBJ_INIT") && __preserves_resource("DEV_EXTN")
+ensures((Res_DEV_OBJ_INIT == old(Res_DEV_OBJ_INIT)) && (Res_DEV_EXTN == old(Res_DEV_EXTN)));
+
+modifies Res_DEVICE_STACK;
+
+//TAG: net change in resource DEVICE_STACK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEVICE_STACK[r]} (Empty()[r]) || old(Res_DEVICE_STACK)[r] == Res_DEVICE_STACK[r]));
+modifies Res_DEV_EXTN;
+
+//TAG: net change in resource DEV_EXTN only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_EXTN[r]} (Empty()[r]) || old(Res_DEV_EXTN)[r] == Res_DEV_EXTN[r]));
+modifies Res_DEV_OBJ_INIT;
+
+//TAG: net change in resource DEV_OBJ_INIT only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_OBJ_INIT[r]} (Empty()[r]) || old(Res_DEV_OBJ_INIT)[r] == Res_DEV_OBJ_INIT[r]));
+modifies Res_SPIN_LOCK;
+
+//TAG: net change in resource SPIN_LOCK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_SPIN_LOCK[r]} (Empty()[r]) || old(Res_SPIN_LOCK)[r] == Res_SPIN_LOCK[r]));
+//TAG: updated memory locations at Mem[T.MinorFunction__IO_STACK_LOCATION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.MinorFunction__IO_STACK_LOCATION][_m]} (Empty()[_m]) || Mem[T.MinorFunction__IO_STACK_LOCATION][_m] == old(Mem)[T.MinorFunction__IO_STACK_LOCATION][_m]));
+//TAG: updated memory locations at Mem[T.CurrentStackLocation___unnamed_4_f19b65c1] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.CurrentStackLocation___unnamed_4_f19b65c1][_m]} (Empty()[_m]) || Mem[T.CurrentStackLocation___unnamed_4_f19b65c1][_m] == old(Mem)[T.CurrentStackLocation___unnamed_4_f19b65c1][_m]));
+//TAG: updated memory locations at Mem[T.DeviceExtension__DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.DeviceExtension__DEVICE_OBJECT][_m] == old(Mem)[T.DeviceExtension__DEVICE_OBJECT][_m]));
+//TAG: updated memory locations at Mem[T.Self__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Self__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Self__DEVICE_EXTENSION][_m] == old(Mem)[T.Self__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.Started__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Started__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Started__DEVICE_EXTENSION][_m] == old(Mem)[T.Started__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.GrandMaster__GLOBALS] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.GrandMaster__GLOBALS][_m]} (Empty()[_m]) || Mem[T.GrandMaster__GLOBALS][_m] == old(Mem)[T.GrandMaster__GLOBALS][_m]));
+//TAG: updated memory locations at Mem[T.P_DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.P_DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.P_DEVICE_OBJECT][_m] == old(Mem)[T.P_DEVICE_OBJECT][_m]));
+
+//TAG: havoc memory locations by default
+modifies Mem;
+
+
+procedure __PREfastPagedCode();
+
+//TAG: ensures __preserves_mem
+ensures(Mem == old(Mem));
+//TAG: ensures __preserves_resource("DEV_OBJ_INIT") && __preserves_resource("DEV_EXTN")
+ensures((Res_DEV_OBJ_INIT == old(Res_DEV_OBJ_INIT)) && (Res_DEV_EXTN == old(Res_DEV_EXTN)));
+
+modifies Res_DEVICE_STACK;
+
+//TAG: net change in resource DEVICE_STACK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEVICE_STACK[r]} (Empty()[r]) || old(Res_DEVICE_STACK)[r] == Res_DEVICE_STACK[r]));
+modifies Res_DEV_EXTN;
+
+//TAG: net change in resource DEV_EXTN only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_EXTN[r]} (Empty()[r]) || old(Res_DEV_EXTN)[r] == Res_DEV_EXTN[r]));
+modifies Res_DEV_OBJ_INIT;
+
+//TAG: net change in resource DEV_OBJ_INIT only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_OBJ_INIT[r]} (Empty()[r]) || old(Res_DEV_OBJ_INIT)[r] == Res_DEV_OBJ_INIT[r]));
+modifies Res_SPIN_LOCK;
+
+//TAG: net change in resource SPIN_LOCK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_SPIN_LOCK[r]} (Empty()[r]) || old(Res_SPIN_LOCK)[r] == Res_SPIN_LOCK[r]));
+//TAG: updated memory locations at Mem[T.MinorFunction__IO_STACK_LOCATION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.MinorFunction__IO_STACK_LOCATION][_m]} (Empty()[_m]) || Mem[T.MinorFunction__IO_STACK_LOCATION][_m] == old(Mem)[T.MinorFunction__IO_STACK_LOCATION][_m]));
+//TAG: updated memory locations at Mem[T.CurrentStackLocation___unnamed_4_f19b65c1] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.CurrentStackLocation___unnamed_4_f19b65c1][_m]} (Empty()[_m]) || Mem[T.CurrentStackLocation___unnamed_4_f19b65c1][_m] == old(Mem)[T.CurrentStackLocation___unnamed_4_f19b65c1][_m]));
+//TAG: updated memory locations at Mem[T.DeviceExtension__DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.DeviceExtension__DEVICE_OBJECT][_m] == old(Mem)[T.DeviceExtension__DEVICE_OBJECT][_m]));
+//TAG: updated memory locations at Mem[T.Self__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Self__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Self__DEVICE_EXTENSION][_m] == old(Mem)[T.Self__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.Started__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Started__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Started__DEVICE_EXTENSION][_m] == old(Mem)[T.Started__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.GrandMaster__GLOBALS] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.GrandMaster__GLOBALS][_m]} (Empty()[_m]) || Mem[T.GrandMaster__GLOBALS][_m] == old(Mem)[T.GrandMaster__GLOBALS][_m]));
+//TAG: updated memory locations at Mem[T.P_DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.P_DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.P_DEVICE_OBJECT][_m] == old(Mem)[T.P_DEVICE_OBJECT][_m]));
+
+//TAG: havoc memory locations by default
+modifies Mem;
+
+
+procedure KbdCreateClassObject($DriverObject$1$3354.28$KbdCreateClassObject$201:int, $TmpDeviceExtension$2$3355.28$KbdCreateClassObject$201:int, $ClassDeviceObject$3$3356.28$KbdCreateClassObject$201:int, $FullDeviceName$4$3357.35$KbdCreateClassObject$201:int, $Legacy$5$3358.28$KbdCreateClassObject$201:int) returns ($result.KbdCreateClassObject$3353.0$1$:int)
+
+//TAG: requires __pforall(_H_x, (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension), __inv_resource("DEV_OBJ_INIT", 1), ((struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension))->Self == _H_x && __resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension)) == 1)
+requires((forall _H_x:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)]} Inverse(Res_DEV_OBJ_INIT,1)[_H_x] ==> ((Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)])] == _H_x) && (Res_DEV_EXTN[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)]] == 1))));
+//TAG: requires __pforall(_H_z, _H_z->Self, __inv_resource("DEV_EXTN", 1), __resource("DEV_OBJ_INIT", _H_z->Self) == 1 && (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)(_H_z->Self))->DeviceExtension) == _H_z)
+requires((forall _H_z:int :: {Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)]} Inverse(Res_DEV_EXTN,1)[_H_z] ==> ((Res_DEV_OBJ_INIT[Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)]] == 1) && (Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)])] == _H_z))));
+//TAG: requires __forall(_H_z, __inv_resource("DEV_EXTN", 1), 1)
+requires((Subset(Empty(), Inverse(Res_DEV_EXTN,1)) && (forall _H_z : int :: {Inverse(Res_DEV_EXTN,1)[_H_z]} (Inverse(Res_DEV_EXTN,1)[_H_z]) ==> (true))));
+//TAG: requires 1 ==> (Globals.GrandMaster != (void *)0 ==> __resource("DEV_EXTN", Globals.GrandMaster) == 1)
+requires((true) ==> ((Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)] != 0) ==> (Res_DEV_EXTN[Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)]] == 1)));
+//TAG: requires 1 ==> __setin(&Globals.LegacyDeviceList, __btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList))
+requires((true) ==> (ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[LegacyDeviceList__GLOBALS(Globals)]));
+//TAG: requires 1 ==> __forall(_H_y, __btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList), _H_y == &Globals.LegacyDeviceList || __resource("DEV_EXTN", CONTAINING_RECORD(_H_y, struct _DEVICE_EXTENSION , Link)) == 1)
+requires((true) ==> ((Subset(Empty(), ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))) && (forall _H_y : int :: {ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[_H_y]} (ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[_H_y]) ==> ((_H_y == LegacyDeviceList__GLOBALS(Globals)) || (Res_DEV_EXTN[MINUS_LEFT_PTR(_H_y, 1, Link__DEVICE_EXTENSION(0))] == 1))))));
+//TAG: requires 1 ==> !__setin(&Globals.GrandMaster->Link, __setminus(__btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList), __set(&Globals.LegacyDeviceList)))
+requires((true) ==> (!(Difference(ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals)), Singleton(LegacyDeviceList__GLOBALS(Globals)))[Link__DEVICE_EXTENSION(Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)])])));
+//TAG: ensures __pforall(_H_x, (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension), __inv_resource("DEV_OBJ_INIT", 1), ((struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension))->Self == _H_x && __resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension)) == 1)
+ensures((forall _H_x:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)]} Inverse(Res_DEV_OBJ_INIT,1)[_H_x] ==> ((Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)])] == _H_x) && (Res_DEV_EXTN[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)]] == 1))));
+//TAG: ensures __pforall(_H_z, _H_z->Self, __inv_resource("DEV_EXTN", 1), __resource("DEV_OBJ_INIT", _H_z->Self) == 1 && (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)(_H_z->Self))->DeviceExtension) == _H_z)
+ensures((forall _H_z:int :: {Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)]} Inverse(Res_DEV_EXTN,1)[_H_z] ==> ((Res_DEV_OBJ_INIT[Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)]] == 1) && (Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)])] == _H_z))));
+//TAG: ensures __forall(_H_z, __inv_resource("DEV_EXTN", 1), 1)
+ensures((Subset(Empty(), Inverse(Res_DEV_EXTN,1)) && (forall _H_z : int :: {Inverse(Res_DEV_EXTN,1)[_H_z]} (Inverse(Res_DEV_EXTN,1)[_H_z]) ==> (true))));
+//TAG: ensures 1 ==> (Globals.GrandMaster != (void *)0 ==> __resource("DEV_EXTN", Globals.GrandMaster) == 1)
+ensures((true) ==> ((Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)] != 0) ==> (Res_DEV_EXTN[Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)]] == 1)));
+//TAG: ensures 1 ==> __setin(&Globals.LegacyDeviceList, __btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList))
+ensures((true) ==> (ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[LegacyDeviceList__GLOBALS(Globals)]));
+//TAG: ensures 1 ==> __forall(_H_y, __btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList), _H_y == &Globals.LegacyDeviceList || __resource("DEV_EXTN", CONTAINING_RECORD(_H_y, struct _DEVICE_EXTENSION , Link)) == 1)
+ensures((true) ==> ((Subset(Empty(), ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))) && (forall _H_y : int :: {ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[_H_y]} (ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[_H_y]) ==> ((_H_y == LegacyDeviceList__GLOBALS(Globals)) || (Res_DEV_EXTN[MINUS_LEFT_PTR(_H_y, 1, Link__DEVICE_EXTENSION(0))] == 1))))));
+//TAG: ensures 1 ==> !__setin(&Globals.GrandMaster->Link, __setminus(__btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList), __set(&Globals.LegacyDeviceList)))
+ensures((true) ==> (!(Difference(ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals)), Singleton(LegacyDeviceList__GLOBALS(Globals)))[Link__DEVICE_EXTENSION(Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)])])));
+//TAG: ensures __preserves_field_map(__offset((*((struct _LIST_ENTRY *)0)).Flink))
+ensures(Mem[T.Flink__LIST_ENTRY] == old(Mem)[T.Flink__LIST_ENTRY]);
+//TAG: ensures (LONG)__return >= 0 ==> *ClassDeviceObject != (void *)0
+ensures(($result.KbdCreateClassObject$3353.0$1$ >= 0) ==> (Mem[T.P_DEVICE_OBJECT][$ClassDeviceObject$3$3356.28$KbdCreateClassObject$201] != 0));
+//TAG: ensures (LONG)__return >= 0 ==> (*ClassDeviceObject)->DeviceExtension != (void *)0
+ensures(($result.KbdCreateClassObject$3353.0$1$ >= 0) ==> (Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.P_DEVICE_OBJECT][$ClassDeviceObject$3$3356.28$KbdCreateClassObject$201])] != 0));
+//TAG: ensures (LONG)__return >= 0 ==> __resource("DEV_EXTN", (*ClassDeviceObject)->DeviceExtension) == 1
+ensures(($result.KbdCreateClassObject$3353.0$1$ >= 0) ==> (Res_DEV_EXTN[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.P_DEVICE_OBJECT][$ClassDeviceObject$3$3356.28$KbdCreateClassObject$201])]] == 1));
+//TAG: ensures (LONG)__return >= 0 ==> __resource("DEV_OBJ_INIT", *ClassDeviceObject) == 1 && __resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)(*ClassDeviceObject))->DeviceExtension)) == 1
+ensures(($result.KbdCreateClassObject$3353.0$1$ >= 0) ==> ((Res_DEV_OBJ_INIT[Mem[T.P_DEVICE_OBJECT][$ClassDeviceObject$3$3356.28$KbdCreateClassObject$201]] == 1) && (Res_DEV_EXTN[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.P_DEVICE_OBJECT][$ClassDeviceObject$3$3356.28$KbdCreateClassObject$201])]] == 1)));
+//TAG: ensures (LONG)__return >= 0 ==> __old_resource("DEV_OBJ_INIT", *ClassDeviceObject) == 0 && __old_resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)(*ClassDeviceObject))->DeviceExtension)) == 0
+ensures(($result.KbdCreateClassObject$3353.0$1$ >= 0) ==> ((old(Res_DEV_OBJ_INIT)[Mem[T.P_DEVICE_OBJECT][$ClassDeviceObject$3$3356.28$KbdCreateClassObject$201]] == 0) && (old(Res_DEV_EXTN)[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.P_DEVICE_OBJECT][$ClassDeviceObject$3$3356.28$KbdCreateClassObject$201])]] == 0)));
+//TAG: ensures (LONG)__return >= 0 ==> __updates_resource("DEV_OBJ_INIT", *ClassDeviceObject, 1) && __updates_resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)(*ClassDeviceObject))->DeviceExtension), 1)
+ensures(($result.KbdCreateClassObject$3353.0$1$ >= 0) ==> ((Res_DEV_OBJ_INIT == old(Res_DEV_OBJ_INIT)[Mem[T.P_DEVICE_OBJECT][$ClassDeviceObject$3$3356.28$KbdCreateClassObject$201] := 1]) && (Res_DEV_EXTN == old(Res_DEV_EXTN)[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.P_DEVICE_OBJECT][$ClassDeviceObject$3$3356.28$KbdCreateClassObject$201])] := 1])));
+//TAG: ensures !((LONG)__return >= 0) ==> __resource("DEV_OBJ_INIT", *ClassDeviceObject) == __old_resource("DEV_OBJ_INIT", *ClassDeviceObject) && __resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)(*ClassDeviceObject))->DeviceExtension)) == __old_resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)(*ClassDeviceObject))->DeviceExtension))
+ensures((!($result.KbdCreateClassObject$3353.0$1$ >= 0)) ==> ((Res_DEV_OBJ_INIT[Mem[T.P_DEVICE_OBJECT][$ClassDeviceObject$3$3356.28$KbdCreateClassObject$201]] == old(Res_DEV_OBJ_INIT)[Mem[T.P_DEVICE_OBJECT][$ClassDeviceObject$3$3356.28$KbdCreateClassObject$201]]) && (Res_DEV_EXTN[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.P_DEVICE_OBJECT][$ClassDeviceObject$3$3356.28$KbdCreateClassObject$201])]] == old(Res_DEV_EXTN)[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.P_DEVICE_OBJECT][$ClassDeviceObject$3$3356.28$KbdCreateClassObject$201])]])));
+//TAG: ensures !((LONG)__return >= 0) ==> __preserves_resource("DEV_OBJ_INIT") && __preserves_resource("DEV_EXTN")
+free ensures((!($result.KbdCreateClassObject$3353.0$1$ >= 0)) ==> ((Res_DEV_OBJ_INIT == old(Res_DEV_OBJ_INIT)) && (Res_DEV_EXTN == old(Res_DEV_EXTN))));
+modifies alloc;
+free ensures(forall f:int :: {alloc[Base(f)]} old(alloc)[Base(f)] == UNALLOCATED || old(alloc)[Base(f)] == alloc[Base(f)]);
+
+modifies Res_DEVICE_STACK;
+
+//TAG: net change in resource DEVICE_STACK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEVICE_STACK[r]} (Empty()[r]) || old(Res_DEVICE_STACK)[r] == Res_DEVICE_STACK[r]));
+modifies Res_DEV_EXTN;
+
+//TAG: net change in resource DEV_EXTN only for: __set_empty, (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)(*ClassDeviceObject))->DeviceExtension)
+ensures (Subset(Empty(), Union(Union(Empty(), Empty()), Singleton(Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.P_DEVICE_OBJECT][$ClassDeviceObject$3$3356.28$KbdCreateClassObject$201])]))) && (forall r:int :: {Res_DEV_EXTN[r]} (Empty()[r]) || (Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.P_DEVICE_OBJECT][$ClassDeviceObject$3$3356.28$KbdCreateClassObject$201])] == r) || old(Res_DEV_EXTN)[r] == Res_DEV_EXTN[r]));
+modifies Res_DEV_OBJ_INIT;
+
+//TAG: net change in resource DEV_OBJ_INIT only for: __set_empty, *ClassDeviceObject
+ensures (Subset(Empty(), Union(Union(Empty(), Empty()), Singleton(Mem[T.P_DEVICE_OBJECT][$ClassDeviceObject$3$3356.28$KbdCreateClassObject$201]))) && (forall r:int :: {Res_DEV_OBJ_INIT[r]} (Empty()[r]) || (Mem[T.P_DEVICE_OBJECT][$ClassDeviceObject$3$3356.28$KbdCreateClassObject$201] == r) || old(Res_DEV_OBJ_INIT)[r] == Res_DEV_OBJ_INIT[r]));
+modifies Res_SPIN_LOCK;
+
+//TAG: net change in resource SPIN_LOCK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_SPIN_LOCK[r]} (Empty()[r]) || old(Res_SPIN_LOCK)[r] == Res_SPIN_LOCK[r]));
+//TAG: updated memory locations at Mem[T.MinorFunction__IO_STACK_LOCATION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.MinorFunction__IO_STACK_LOCATION][_m]} (Empty()[_m]) || Mem[T.MinorFunction__IO_STACK_LOCATION][_m] == old(Mem)[T.MinorFunction__IO_STACK_LOCATION][_m]));
+//TAG: updated memory locations at Mem[T.CurrentStackLocation___unnamed_4_f19b65c1] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.CurrentStackLocation___unnamed_4_f19b65c1][_m]} (Empty()[_m]) || Mem[T.CurrentStackLocation___unnamed_4_f19b65c1][_m] == old(Mem)[T.CurrentStackLocation___unnamed_4_f19b65c1][_m]));
+//TAG: updated memory locations at Mem[T.DeviceExtension__DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.DeviceExtension__DEVICE_OBJECT][_m] == old(Mem)[T.DeviceExtension__DEVICE_OBJECT][_m]));
+//TAG: updated memory locations at Mem[T.Self__DEVICE_EXTENSION] only for: __set_true
+ensures (Subset(Empty(), Union(Empty(), SetTrue())) && (forall _m:int :: {Mem[T.Self__DEVICE_EXTENSION][_m]} (SetTrue()[_m]) || Mem[T.Self__DEVICE_EXTENSION][_m] == old(Mem)[T.Self__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.Started__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Started__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Started__DEVICE_EXTENSION][_m] == old(Mem)[T.Started__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.GrandMaster__GLOBALS] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.GrandMaster__GLOBALS][_m]} (Empty()[_m]) || Mem[T.GrandMaster__GLOBALS][_m] == old(Mem)[T.GrandMaster__GLOBALS][_m]));
+//TAG: updated memory locations at Mem[T.P_DEVICE_OBJECT] only for: __set_empty, ClassDeviceObject
+ensures (Subset(Empty(), Union(Union(Empty(), Empty()), Singleton($ClassDeviceObject$3$3356.28$KbdCreateClassObject$201))) && (forall _m:int :: {Mem[T.P_DEVICE_OBJECT][_m]} (Empty()[_m]) || (_m == $ClassDeviceObject$3$3356.28$KbdCreateClassObject$201) || Mem[T.P_DEVICE_OBJECT][_m] == old(Mem)[T.P_DEVICE_OBJECT][_m]));
+
+//TAG: havoc memory locations by default
+modifies Mem;
+{
+var havoc_stringTemp:int;
+var condVal:int;
+var $ClassDeviceObject$3$3356.28$KbdCreateClassObject$20 : int;
+var $DriverObject$1$3354.28$KbdCreateClassObject$20 : int;
+var $ExAllocatePoolWithTag.arg.2$4$ : int;
+var $FullDeviceName$4$3357.35$KbdCreateClassObject$20 : int;
+var $KbdDebugPrint.arg.2$15$ : int;
+var $KbdDebugPrint.arg.2$18$ : int;
+var $KbdDebugPrint.arg.2$2$ : int;
+var $KbdDebugPrint.arg.2$20$ : int;
+var $KbdDebugPrint.arg.2$22$ : int;
+var $KbdDebugPrint.arg.2$5$ : int;
+var $Legacy$5$3358.28$KbdCreateClassObject$20 : int;
+var $RtlAppendUnicodeToString.arg.2$12$ : int;
+var $RtlAppendUnicodeToString.arg.2$14$ : int;
+var $RtlAppendUnicodeToString.arg.2$9$ : int;
+var $TmpDeviceExtension$2$3355.28$KbdCreateClassObject$20 : int;
+var $deviceExtension$8$3388.24$KbdCreateClassObject$20 : int;
+var $dumpCount$11$3391.24$KbdCreateClassObject$20 : int;
+var $dumpData$12$3392.24$KbdCreateClassObject$20 : int;
+var $errorCode$9$3389.24$KbdCreateClassObject$20 : int;
+var $fullClassName$10$3390.24$KbdCreateClassObject$20 : int;
+var $i$13$3393.24$KbdCreateClassObject$20 : int;
+var $memset.arg.3$7$ : int;
+var $nameIndex$14$3394.24$KbdCreateClassObject$20 : int;
+var $result.ExAllocatePoolWithTag$3441.0$3$ : int;
+var $result.ExAllocatePoolWithTag$3557.0$19$ : int;
+var $result.IoCreateDevice$3485.35$16$ : int;
+var $result.IoCreateDevice$3499.31$17$ : int;
+var $result.RtlAppendUnicodeToString$3460.32$8$ : int;
+var $result.RtlAppendUnicodeToString$3461.32$10$ : int;
+var $result.RtlAppendUnicodeToString$3464.36$11$ : int;
+var $result.RtlAppendUnicodeToString$3467.32$13$ : int;
+var $result.memset$3459.8$6$ : int;
+var $result.question.21$ : int;
+var $status$6$3386.24$KbdCreateClassObject$20 : int;
+var $uniqueErrorValue$7$3387.24$KbdCreateClassObject$20 : int;
+var tempBoogie0:int;
+var tempBoogie1:int;
+var tempBoogie2:int;
+var tempBoogie3:int;
+var tempBoogie4:int;
+var tempBoogie5:int;
+var tempBoogie6:int;
+var tempBoogie7:int;
+var tempBoogie8:int;
+var tempBoogie9:int;
+var tempBoogie10:int;
+var tempBoogie11:int;
+var tempBoogie12:int;
+var tempBoogie13:int;
+var tempBoogie14:int;
+var tempBoogie15:int;
+var tempBoogie16:int;
+var tempBoogie17:int;
+var tempBoogie18:int;
+var tempBoogie19:int;
+var LOOP_78_alloc:[int]name;
+var LOOP_78_Mem:[name][int]int;
+var LOOP_78_Res_DEVICE_STACK:[int]int;
+var LOOP_78_Res_DEV_EXTN:[int]int;
+var LOOP_78_Res_DEV_OBJ_INIT:[int]int;
+var LOOP_78_Res_SPIN_LOCK:[int]int;
+
+
+start:
+
+assume (alloc[$DriverObject$1$3354.28$KbdCreateClassObject$201] != UNALLOCATED);
+assume (alloc[$TmpDeviceExtension$2$3355.28$KbdCreateClassObject$201] != UNALLOCATED);
+assume (alloc[$ClassDeviceObject$3$3356.28$KbdCreateClassObject$201] != UNALLOCATED);
+assume (alloc[$FullDeviceName$4$3357.35$KbdCreateClassObject$201] != UNALLOCATED);
+call $dumpData$12$3392.24$KbdCreateClassObject$20 := __HAVOC_malloc(16);
+call $fullClassName$10$3390.24$KbdCreateClassObject$20 := __HAVOC_malloc(8);
+$DriverObject$1$3354.28$KbdCreateClassObject$20 := $DriverObject$1$3354.28$KbdCreateClassObject$201;
+$TmpDeviceExtension$2$3355.28$KbdCreateClassObject$20 := $TmpDeviceExtension$2$3355.28$KbdCreateClassObject$201;
+$ClassDeviceObject$3$3356.28$KbdCreateClassObject$20 := $ClassDeviceObject$3$3356.28$KbdCreateClassObject$201;
+$FullDeviceName$4$3357.35$KbdCreateClassObject$20 := $FullDeviceName$4$3357.35$KbdCreateClassObject$201;
+$Legacy$5$3358.28$KbdCreateClassObject$20 := $Legacy$5$3358.28$KbdCreateClassObject$201;
+goto label_3;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3627)
+label_1:
+call __HAVOC_free($dumpData$12$3392.24$KbdCreateClassObject$20);
+call __HAVOC_free($fullClassName$10$3390.24$KbdCreateClassObject$20);
+assume (forall m:int:: {Res_DEVICE_STACK[m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Res_DEVICE_STACK[m] == old(Res_DEVICE_STACK)[m]);
+assume (forall m:int:: {Res_DEV_EXTN[m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Res_DEV_EXTN[m] == old(Res_DEV_EXTN)[m]);
+assume (forall m:int:: {Res_DEV_OBJ_INIT[m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Res_DEV_OBJ_INIT[m] == old(Res_DEV_OBJ_INIT)[m]);
+assume (forall m:int:: {Res_SPIN_LOCK[m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Res_SPIN_LOCK[m] == old(Res_SPIN_LOCK)[m]);
+assume (forall m:int :: {Mem[T.A2UINT2][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.A2UINT2][m] == old(Mem[T.A2UINT2])[m]);
+assume (forall m:int :: {Mem[T.A37CHAR][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.A37CHAR][m] == old(Mem[T.A37CHAR])[m]);
+assume (forall m:int :: {Mem[T.A40CHAR][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.A40CHAR][m] == old(Mem[T.A40CHAR])[m]);
+assume (forall m:int :: {Mem[T.A4UINT4][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.A4UINT4][m] == old(Mem[T.A4UINT4])[m]);
+assume (forall m:int :: {Mem[T.A65CHAR][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.A65CHAR][m] == old(Mem[T.A65CHAR])[m]);
+assume (forall m:int :: {Mem[T.A75CHAR][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.A75CHAR][m] == old(Mem[T.A75CHAR])[m]);
+assume (forall m:int :: {Mem[T.A76CHAR][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.A76CHAR][m] == old(Mem[T.A76CHAR])[m]);
+assume (forall m:int :: {Mem[T.A7UINT2][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.A7UINT2][m] == old(Mem[T.A7UINT2])[m]);
+assume (forall m:int :: {Mem[T.A83CHAR][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.A83CHAR][m] == old(Mem[T.A83CHAR])[m]);
+assume (forall m:int :: {Mem[T.A9UINT2][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.A9UINT2][m] == old(Mem[T.A9UINT2])[m]);
+assume (forall m:int :: {Mem[T.Abandoned___unnamed_1_29794256][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.Abandoned___unnamed_1_29794256][m] == old(Mem[T.Abandoned___unnamed_1_29794256])[m]);
+assume (forall m:int :: {Mem[T.Absolute___unnamed_1_29794256][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.Absolute___unnamed_1_29794256][m] == old(Mem[T.Absolute___unnamed_1_29794256])[m]);
+assume (forall m:int :: {Mem[T.AllocateTag__IO_REMOVE_LOCK_DBG_BLOCK][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.AllocateTag__IO_REMOVE_LOCK_DBG_BLOCK][m] == old(Mem[T.AllocateTag__IO_REMOVE_LOCK_DBG_BLOCK])[m]);
+assume (forall m:int :: {Mem[T.AllowDisable__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.AllowDisable__DEVICE_EXTENSION][m] == old(Mem[T.AllowDisable__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.BaseClassName__GLOBALS][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.BaseClassName__GLOBALS][m] == old(Mem[T.BaseClassName__GLOBALS])[m]);
+assume (forall m:int :: {Mem[T.Blink__LIST_ENTRY][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.Blink__LIST_ENTRY][m] == old(Mem[T.Blink__LIST_ENTRY])[m]);
+assume (forall m:int :: {Mem[T.Blocks__IO_REMOVE_LOCK_DBG_BLOCK][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.Blocks__IO_REMOVE_LOCK_DBG_BLOCK][m] == old(Mem[T.Blocks__IO_REMOVE_LOCK_DBG_BLOCK])[m]);
+assume (forall m:int :: {Mem[T.Buffer__UNICODE_STRING][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.Buffer__UNICODE_STRING][m] == old(Mem[T.Buffer__UNICODE_STRING])[m]);
+assume (forall m:int :: {Mem[T.ConnectOneClassToOnePort__GLOBALS][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.ConnectOneClassToOnePort__GLOBALS][m] == old(Mem[T.ConnectOneClassToOnePort__GLOBALS])[m]);
+assume (forall m:int :: {Mem[T.CurrentStackLocation___unnamed_4_f19b65c1][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.CurrentStackLocation___unnamed_4_f19b65c1][m] == old(Mem[T.CurrentStackLocation___unnamed_4_f19b65c1])[m]);
+assume (forall m:int :: {Mem[T.DataIn__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.DataIn__DEVICE_EXTENSION][m] == old(Mem[T.DataIn__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.DataOut__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.DataOut__DEVICE_EXTENSION][m] == old(Mem[T.DataOut__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.DebugActive___unnamed_1_2dc63b48][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.DebugActive___unnamed_1_2dc63b48][m] == old(Mem[T.DebugActive___unnamed_1_2dc63b48])[m]);
+assume (forall m:int :: {Mem[T.Delay__KEYBOARD_TYPEMATIC_PARAMETERS][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.Delay__KEYBOARD_TYPEMATIC_PARAMETERS][m] == old(Mem[T.Delay__KEYBOARD_TYPEMATIC_PARAMETERS])[m]);
+assume (forall m:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.DeviceExtension__DEVICE_OBJECT][m] == old(Mem[T.DeviceExtension__DEVICE_OBJECT])[m]);
+assume (forall m:int :: {Mem[T.DeviceState__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.DeviceState__DEVICE_EXTENSION][m] == old(Mem[T.DeviceState__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.DpcActive___unnamed_1_2dc63b48][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.DpcActive___unnamed_1_2dc63b48][m] == old(Mem[T.DpcActive___unnamed_1_2dc63b48])[m]);
+assume (forall m:int :: {Mem[T.Enabled__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.Enabled__DEVICE_EXTENSION][m] == old(Mem[T.Enabled__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.ExecuteWmiMethod__WMILIB_CONTEXT][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.ExecuteWmiMethod__WMILIB_CONTEXT][m] == old(Mem[T.ExecuteWmiMethod__WMILIB_CONTEXT])[m]);
+assume (forall m:int :: {Mem[T.ExtraWaitWakeIrp__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.ExtraWaitWakeIrp__DEVICE_EXTENSION][m] == old(Mem[T.ExtraWaitWakeIrp__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.File__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.File__DEVICE_EXTENSION][m] == old(Mem[T.File__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.Flags__DEVICE_OBJECT][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.Flags__DEVICE_OBJECT][m] == old(Mem[T.Flags__DEVICE_OBJECT])[m]);
+assume (forall m:int :: {Mem[T.Flink__LIST_ENTRY][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.Flink__LIST_ENTRY][m] == old(Mem[T.Flink__LIST_ENTRY])[m]);
+assume (forall m:int :: {Mem[T.GrandMaster__GLOBALS][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.GrandMaster__GLOBALS][m] == old(Mem[T.GrandMaster__GLOBALS])[m]);
+assume (forall m:int :: {Mem[T.GuidCount__WMILIB_CONTEXT][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.GuidCount__WMILIB_CONTEXT][m] == old(Mem[T.GuidCount__WMILIB_CONTEXT])[m]);
+assume (forall m:int :: {Mem[T.GuidList__WMILIB_CONTEXT][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.GuidList__WMILIB_CONTEXT][m] == old(Mem[T.GuidList__WMILIB_CONTEXT])[m]);
+assume (forall m:int :: {Mem[T.Hand___unnamed_1_2ef8da39][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.Hand___unnamed_1_2ef8da39][m] == old(Mem[T.Hand___unnamed_1_2ef8da39])[m]);
+assume (forall m:int :: {Mem[T.HighWatermark__IO_REMOVE_LOCK_DBG_BLOCK][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.HighWatermark__IO_REMOVE_LOCK_DBG_BLOCK][m] == old(Mem[T.HighWatermark__IO_REMOVE_LOCK_DBG_BLOCK])[m]);
+assume (forall m:int :: {Mem[T.INT4][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.INT4][m] == old(Mem[T.INT4])[m]);
+assume (forall m:int :: {Mem[T.InputCount__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.InputCount__DEVICE_EXTENSION][m] == old(Mem[T.InputCount__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.InputDataQueueLength__KEYBOARD_ATTRIBUTES][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.InputDataQueueLength__KEYBOARD_ATTRIBUTES][m] == old(Mem[T.InputDataQueueLength__KEYBOARD_ATTRIBUTES])[m]);
+assume (forall m:int :: {Mem[T.InputData__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.InputData__DEVICE_EXTENSION][m] == old(Mem[T.InputData__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.Inserted___unnamed_1_2dc63b48][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.Inserted___unnamed_1_2dc63b48][m] == old(Mem[T.Inserted___unnamed_1_2dc63b48])[m]);
+assume (forall m:int :: {Mem[T.IoCount__IO_REMOVE_LOCK_COMMON_BLOCK][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.IoCount__IO_REMOVE_LOCK_COMMON_BLOCK][m] == old(Mem[T.IoCount__IO_REMOVE_LOCK_COMMON_BLOCK])[m]);
+assume (forall m:int :: {Mem[T.KeyboardAttributes__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.KeyboardAttributes__DEVICE_EXTENSION][m] == old(Mem[T.KeyboardAttributes__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.KeyboardMode__KEYBOARD_ATTRIBUTES][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.KeyboardMode__KEYBOARD_ATTRIBUTES][m] == old(Mem[T.KeyboardMode__KEYBOARD_ATTRIBUTES])[m]);
+assume (forall m:int :: {Mem[T.LedFlags__KEYBOARD_INDICATOR_PARAMETERS][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.LedFlags__KEYBOARD_INDICATOR_PARAMETERS][m] == old(Mem[T.LedFlags__KEYBOARD_INDICATOR_PARAMETERS])[m]);
+assume (forall m:int :: {Mem[T.LegacyDeviceList__GLOBALS][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.LegacyDeviceList__GLOBALS][m] == old(Mem[T.LegacyDeviceList__GLOBALS])[m]);
+assume (forall m:int :: {Mem[T.Length__UNICODE_STRING][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.Length__UNICODE_STRING][m] == old(Mem[T.Length__UNICODE_STRING])[m]);
+assume (forall m:int :: {Mem[T.Link__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.Link__DEVICE_EXTENSION][m] == old(Mem[T.Link__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.Lock___unnamed_4_a97c65a1][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.Lock___unnamed_4_a97c65a1][m] == old(Mem[T.Lock___unnamed_4_a97c65a1])[m]);
+assume (forall m:int :: {Mem[T.LowMemoryCount__IO_REMOVE_LOCK_DBG_BLOCK][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.LowMemoryCount__IO_REMOVE_LOCK_DBG_BLOCK][m] == old(Mem[T.LowMemoryCount__IO_REMOVE_LOCK_DBG_BLOCK])[m]);
+assume (forall m:int :: {Mem[T.MaxLockedTicks__IO_REMOVE_LOCK_DBG_BLOCK][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.MaxLockedTicks__IO_REMOVE_LOCK_DBG_BLOCK][m] == old(Mem[T.MaxLockedTicks__IO_REMOVE_LOCK_DBG_BLOCK])[m]);
+assume (forall m:int :: {Mem[T.MaximumLength__UNICODE_STRING][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.MaximumLength__UNICODE_STRING][m] == old(Mem[T.MaximumLength__UNICODE_STRING])[m]);
+assume (forall m:int :: {Mem[T.MinDeviceWakeState__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.MinDeviceWakeState__DEVICE_EXTENSION][m] == old(Mem[T.MinDeviceWakeState__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.MinSystemWakeState__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.MinSystemWakeState__DEVICE_EXTENSION][m] == old(Mem[T.MinSystemWakeState__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.MinorFunction__IO_STACK_LOCATION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.MinorFunction__IO_STACK_LOCATION][m] == old(Mem[T.MinorFunction__IO_STACK_LOCATION])[m]);
+assume (forall m:int :: {Mem[T.Mutex__GLOBALS][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.Mutex__GLOBALS][m] == old(Mem[T.Mutex__GLOBALS])[m]);
+assume (forall m:int :: {Mem[T.NpxIrql___unnamed_1_29794256][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.NpxIrql___unnamed_1_29794256][m] == old(Mem[T.NpxIrql___unnamed_1_29794256])[m]);
+assume (forall m:int :: {Mem[T.NumberOfFunctionKeys__KEYBOARD_ATTRIBUTES][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.NumberOfFunctionKeys__KEYBOARD_ATTRIBUTES][m] == old(Mem[T.NumberOfFunctionKeys__KEYBOARD_ATTRIBUTES])[m]);
+assume (forall m:int :: {Mem[T.NumberOfIndicators__KEYBOARD_ATTRIBUTES][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.NumberOfIndicators__KEYBOARD_ATTRIBUTES][m] == old(Mem[T.NumberOfIndicators__KEYBOARD_ATTRIBUTES])[m]);
+assume (forall m:int :: {Mem[T.NumberOfKeysTotal__KEYBOARD_ATTRIBUTES][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.NumberOfKeysTotal__KEYBOARD_ATTRIBUTES][m] == old(Mem[T.NumberOfKeysTotal__KEYBOARD_ATTRIBUTES])[m]);
+assume (forall m:int :: {Mem[T.OkayToLogOverflow__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.OkayToLogOverflow__DEVICE_EXTENSION][m] == old(Mem[T.OkayToLogOverflow__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.PCHAR][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.PCHAR][m] == old(Mem[T.PCHAR])[m]);
+assume (forall m:int :: {Mem[T.PDO__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.PDO__DEVICE_EXTENSION][m] == old(Mem[T.PDO__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.PUINT2][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.PUINT2][m] == old(Mem[T.PUINT2])[m]);
+assume (forall m:int :: {Mem[T.PUINT4][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.PUINT4][m] == old(Mem[T.PUINT4])[m]);
+assume (forall m:int :: {Mem[T.PVOID][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.PVOID][m] == old(Mem[T.PVOID])[m]);
+assume (forall m:int :: {Mem[T.P_DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.P_DEVICE_EXTENSION][m] == old(Mem[T.P_DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.P_DEVICE_OBJECT][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.P_DEVICE_OBJECT][m] == old(Mem[T.P_DEVICE_OBJECT])[m]);
+assume (forall m:int :: {Mem[T.P_DRIVER_OBJECT][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.P_DRIVER_OBJECT][m] == old(Mem[T.P_DRIVER_OBJECT])[m]);
+assume (forall m:int :: {Mem[T.P_FAST_MUTEX][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.P_FAST_MUTEX][m] == old(Mem[T.P_FAST_MUTEX])[m]);
+assume (forall m:int :: {Mem[T.P_IO_REMOVE_LOCK][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.P_IO_REMOVE_LOCK][m] == old(Mem[T.P_IO_REMOVE_LOCK])[m]);
+assume (forall m:int :: {Mem[T.P_KEYBOARD_INPUT_DATA][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.P_KEYBOARD_INPUT_DATA][m] == old(Mem[T.P_KEYBOARD_INPUT_DATA])[m]);
+assume (forall m:int :: {Mem[T.P_LIST_ENTRY][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.P_LIST_ENTRY][m] == old(Mem[T.P_LIST_ENTRY])[m]);
+assume (forall m:int :: {Mem[T.P_UNICODE_STRING][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.P_UNICODE_STRING][m] == old(Mem[T.P_UNICODE_STRING])[m]);
+assume (forall m:int :: {Mem[T.PnP__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.PnP__DEVICE_EXTENSION][m] == old(Mem[T.PnP__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.QueryWmiDataBlock__WMILIB_CONTEXT][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.QueryWmiDataBlock__WMILIB_CONTEXT][m] == old(Mem[T.QueryWmiDataBlock__WMILIB_CONTEXT])[m]);
+assume (forall m:int :: {Mem[T.QueryWmiRegInfo__WMILIB_CONTEXT][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.QueryWmiRegInfo__WMILIB_CONTEXT][m] == old(Mem[T.QueryWmiRegInfo__WMILIB_CONTEXT])[m]);
+assume (forall m:int :: {Mem[T.Rate__KEYBOARD_TYPEMATIC_PARAMETERS][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.Rate__KEYBOARD_TYPEMATIC_PARAMETERS][m] == old(Mem[T.Rate__KEYBOARD_TYPEMATIC_PARAMETERS])[m]);
+assume (forall m:int :: {Mem[T.ReadQueue__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.ReadQueue__DEVICE_EXTENSION][m] == old(Mem[T.ReadQueue__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.RemoveLock__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.RemoveLock__DEVICE_EXTENSION][m] == old(Mem[T.RemoveLock__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.Removed__IO_REMOVE_LOCK_COMMON_BLOCK][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.Removed__IO_REMOVE_LOCK_COMMON_BLOCK][m] == old(Mem[T.Removed__IO_REMOVE_LOCK_COMMON_BLOCK])[m]);
+assume (forall m:int :: {Mem[T.Reserved1__IO_REMOVE_LOCK_DBG_BLOCK][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.Reserved1__IO_REMOVE_LOCK_DBG_BLOCK][m] == old(Mem[T.Reserved1__IO_REMOVE_LOCK_DBG_BLOCK])[m]);
+assume (forall m:int :: {Mem[T.Reserved2__IO_REMOVE_LOCK_DBG_BLOCK][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.Reserved2__IO_REMOVE_LOCK_DBG_BLOCK][m] == old(Mem[T.Reserved2__IO_REMOVE_LOCK_DBG_BLOCK])[m]);
+assume (forall m:int :: {Mem[T.Reserved__IO_REMOVE_LOCK_COMMON_BLOCK][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.Reserved__IO_REMOVE_LOCK_COMMON_BLOCK][m] == old(Mem[T.Reserved__IO_REMOVE_LOCK_COMMON_BLOCK])[m]);
+assume (forall m:int :: {Mem[T.Self__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.Self__DEVICE_EXTENSION][m] == old(Mem[T.Self__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.SequenceNumber__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.SequenceNumber__DEVICE_EXTENSION][m] == old(Mem[T.SequenceNumber__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.SetWmiDataBlock__WMILIB_CONTEXT][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.SetWmiDataBlock__WMILIB_CONTEXT][m] == old(Mem[T.SetWmiDataBlock__WMILIB_CONTEXT])[m]);
+assume (forall m:int :: {Mem[T.SetWmiDataItem__WMILIB_CONTEXT][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.SetWmiDataItem__WMILIB_CONTEXT][m] == old(Mem[T.SetWmiDataItem__WMILIB_CONTEXT])[m]);
+assume (forall m:int :: {Mem[T.SignalState__DISPATCHER_HEADER][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.SignalState__DISPATCHER_HEADER][m] == old(Mem[T.SignalState__DISPATCHER_HEADER])[m]);
+assume (forall m:int :: {Mem[T.Signalling___unnamed_1_29794256][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.Signalling___unnamed_1_29794256][m] == old(Mem[T.Signalling___unnamed_1_29794256])[m]);
+assume (forall m:int :: {Mem[T.Signature__IO_REMOVE_LOCK_DBG_BLOCK][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.Signature__IO_REMOVE_LOCK_DBG_BLOCK][m] == old(Mem[T.Signature__IO_REMOVE_LOCK_DBG_BLOCK])[m]);
+assume (forall m:int :: {Mem[T.Size___unnamed_1_2ef8da39][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.Size___unnamed_1_2ef8da39][m] == old(Mem[T.Size___unnamed_1_2ef8da39])[m]);
+assume (forall m:int :: {Mem[T.SpinLock__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.SpinLock__DEVICE_EXTENSION][m] == old(Mem[T.SpinLock__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.Spin__IO_REMOVE_LOCK_DBG_BLOCK][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.Spin__IO_REMOVE_LOCK_DBG_BLOCK][m] == old(Mem[T.Spin__IO_REMOVE_LOCK_DBG_BLOCK])[m]);
+assume (forall m:int :: {Mem[T.Started__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.Started__DEVICE_EXTENSION][m] == old(Mem[T.Started__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.Subtype__KEYBOARD_ID][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.Subtype__KEYBOARD_ID][m] == old(Mem[T.Subtype__KEYBOARD_ID])[m]);
+assume (forall m:int :: {Mem[T.SurpriseRemoved__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.SurpriseRemoved__DEVICE_EXTENSION][m] == old(Mem[T.SurpriseRemoved__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.SystemState__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.SystemState__DEVICE_EXTENSION][m] == old(Mem[T.SystemState__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.SystemToDeviceState__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.SystemToDeviceState__DEVICE_EXTENSION][m] == old(Mem[T.SystemToDeviceState__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.TargetNotifyHandle__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.TargetNotifyHandle__DEVICE_EXTENSION][m] == old(Mem[T.TargetNotifyHandle__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.TopPort__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.TopPort__DEVICE_EXTENSION][m] == old(Mem[T.TopPort__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.TrueClassDevice__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.TrueClassDevice__DEVICE_EXTENSION][m] == old(Mem[T.TrueClassDevice__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.TrustedSubsystemCount__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.TrustedSubsystemCount__DEVICE_EXTENSION][m] == old(Mem[T.TrustedSubsystemCount__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.Type__KEYBOARD_ID][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.Type__KEYBOARD_ID][m] == old(Mem[T.Type__KEYBOARD_ID])[m]);
+assume (forall m:int :: {Mem[T.Type___unnamed_4_5ca00198][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.Type___unnamed_4_5ca00198][m] == old(Mem[T.Type___unnamed_4_5ca00198])[m]);
+assume (forall m:int :: {Mem[T.UCHAR][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.UCHAR][m] == old(Mem[T.UCHAR])[m]);
+assume (forall m:int :: {Mem[T.UINT2][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.UINT2][m] == old(Mem[T.UINT2])[m]);
+assume (forall m:int :: {Mem[T.UINT4][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.UINT4][m] == old(Mem[T.UINT4])[m]);
+assume (forall m:int :: {Mem[T.UnitId__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.UnitId__DEVICE_EXTENSION][m] == old(Mem[T.UnitId__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.UnitId__KEYBOARD_INDICATOR_PARAMETERS][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.UnitId__KEYBOARD_INDICATOR_PARAMETERS][m] == old(Mem[T.UnitId__KEYBOARD_INDICATOR_PARAMETERS])[m]);
+assume (forall m:int :: {Mem[T.UnitId__KEYBOARD_TYPEMATIC_PARAMETERS][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.UnitId__KEYBOARD_TYPEMATIC_PARAMETERS][m] == old(Mem[T.UnitId__KEYBOARD_TYPEMATIC_PARAMETERS])[m]);
+assume (forall m:int :: {Mem[T.WaitWakeEnabled__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.WaitWakeEnabled__DEVICE_EXTENSION][m] == old(Mem[T.WaitWakeEnabled__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.WaitWakeIrp__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.WaitWakeIrp__DEVICE_EXTENSION][m] == old(Mem[T.WaitWakeIrp__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.WaitWakeSpinLock__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.WaitWakeSpinLock__DEVICE_EXTENSION][m] == old(Mem[T.WaitWakeSpinLock__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.WmiFunctionControl__WMILIB_CONTEXT][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.WmiFunctionControl__WMILIB_CONTEXT][m] == old(Mem[T.WmiFunctionControl__WMILIB_CONTEXT])[m]);
+assume (forall m:int :: {Mem[T._POOL_TYPE][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T._POOL_TYPE][m] == old(Mem[T._POOL_TYPE])[m]);
+return;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3627)
+label_2:
+assume false;
+return;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3386)
+label_3:
+goto label_4;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3387)
+label_4:
+goto label_5;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3388)
+label_5:
+goto label_6;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3388)
+label_6:
+$deviceExtension$8$3388.24$KbdCreateClassObject$20 := 0 ;
+goto label_7;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3389)
+label_7:
+goto label_8;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3389)
+label_8:
+$errorCode$9$3389.24$KbdCreateClassObject$20 := 0 ;
+goto label_9;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3390)
+label_9:
+goto label_10;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3390)
+label_10:
+// Skipping Structure assignment due to the flag SkipStructAssignments
+goto label_11;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3391)
+label_11:
+goto label_12;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3391)
+label_12:
+$dumpCount$11$3391.24$KbdCreateClassObject$20 := 0 ;
+goto label_13;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3392)
+label_13:
+goto label_14;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3393)
+label_14:
+goto label_15;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3394)
+label_15:
+goto label_16;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3396)
+label_16:
+call __PREfastPagedCode ();
+goto label_22;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3398)
+label_19:
+// skip KbdDebugPrint
+goto label_23;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3398)
+label_22:
+call havoc_stringTemp := __HAVOC_malloc(1);
+$KbdDebugPrint.arg.2$2$ := havoc_stringTemp ;
+goto label_19;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3404)
+label_23:
+call ExAcquireFastMutex (Mutex__GLOBALS(Globals));
+goto label_26;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3409)
+label_26:
+Mem[T.P_DEVICE_OBJECT] := Mem[T.P_DEVICE_OBJECT][$ClassDeviceObject$3$3356.28$KbdCreateClassObject$20 := 0];
+goto label_27;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3411)
+label_27:
+goto label_27_true , label_27_false ;
+
+
+label_27_true :
+assume (Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)] != 0);
+goto label_89;
+
+
+label_27_false :
+assume (Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)] == 0);
+goto label_28;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3415)
+label_28:
+call ExReleaseFastMutex (Mutex__GLOBALS(Globals));
+goto label_31;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3421)
+label_31:
+goto label_31_true , label_31_false ;
+
+
+label_31_true :
+assume (BOOGIE_LARGE_INT_4294967273 < Mem[T.Length__UNICODE_STRING][Length__UNICODE_STRING(BaseClassName__GLOBALS(Globals))]);
+goto label_32;
+
+
+label_31_false :
+assume !(BOOGIE_LARGE_INT_4294967273 < Mem[T.Length__UNICODE_STRING][Length__UNICODE_STRING(BaseClassName__GLOBALS(Globals))]);
+goto label_37;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3422)
+label_32:
+$status$6$3386.24$KbdCreateClassObject$20 := -1073741823 ;
+goto label_33;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3423)
+label_33:
+$errorCode$9$3389.24$KbdCreateClassObject$20 := -1073414143 ;
+goto label_34;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3424)
+label_34:
+$uniqueErrorValue$7$3387.24$KbdCreateClassObject$20 := 10006 ;
+goto label_35;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3425)
+label_35:
+Mem[T.UINT4] := Mem[T.UINT4][PLUS($dumpData$12$3392.24$KbdCreateClassObject$20, 4, 0) := Mem[T.MaximumLength__UNICODE_STRING][MaximumLength__UNICODE_STRING($fullClassName$10$3390.24$KbdCreateClassObject$20)]];
+goto label_36;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3426)
+label_36:
+$dumpCount$11$3391.24$KbdCreateClassObject$20 := 1 ;
+goto label_136;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3433)
+label_37:
+Mem[T.MaximumLength__UNICODE_STRING] := Mem[T.MaximumLength__UNICODE_STRING][MaximumLength__UNICODE_STRING($fullClassName$10$3390.24$KbdCreateClassObject$20) := PLUS(PLUS(18, 1, Mem[T.Length__UNICODE_STRING][Length__UNICODE_STRING(BaseClassName__GLOBALS(Globals))]), 1, 4)];
+goto label_38;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3437)
+label_38:
+goto label_38_true , label_38_false ;
+
+
+label_38_true :
+assume (Mem[T.ConnectOneClassToOnePort__GLOBALS][ConnectOneClassToOnePort__GLOBALS(Globals)] != 0);
+goto label_39;
+
+
+label_38_false :
+assume (Mem[T.ConnectOneClassToOnePort__GLOBALS][ConnectOneClassToOnePort__GLOBALS(Globals)] == 0);
+goto label_44;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3437)
+label_39:
+goto label_39_true , label_39_false ;
+
+
+label_39_true :
+assume ($Legacy$5$3358.28$KbdCreateClassObject$20 != 0);
+goto label_40;
+
+
+label_39_false :
+assume ($Legacy$5$3358.28$KbdCreateClassObject$20 == 0);
+goto label_44;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3438)
+label_40:
+tempBoogie0 := PLUS(Mem[T.MaximumLength__UNICODE_STRING][MaximumLength__UNICODE_STRING($fullClassName$10$3390.24$KbdCreateClassObject$20)], 1, 14) ;
+Mem[T.MaximumLength__UNICODE_STRING] := Mem[T.MaximumLength__UNICODE_STRING][MaximumLength__UNICODE_STRING($fullClassName$10$3390.24$KbdCreateClassObject$20) := tempBoogie0];
+goto label_44;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3441)
+label_41:
+call $result.ExAllocatePoolWithTag$3441.0$3$ := ExAllocatePoolWithTag (1, $ExAllocatePoolWithTag.arg.2$4$, 1130652235);
+goto label_45;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3441)
+label_44:
+$ExAllocatePoolWithTag.arg.2$4$ := Mem[T.MaximumLength__UNICODE_STRING][MaximumLength__UNICODE_STRING($fullClassName$10$3390.24$KbdCreateClassObject$20)] ;
+goto label_41;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3441)
+label_45:
+Mem[T.Buffer__UNICODE_STRING] := Mem[T.Buffer__UNICODE_STRING][Buffer__UNICODE_STRING($fullClassName$10$3390.24$KbdCreateClassObject$20) := $result.ExAllocatePoolWithTag$3441.0$3$];
+goto label_46;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3444)
+label_46:
+goto label_46_true , label_46_false ;
+
+
+label_46_true :
+assume (Mem[T.Buffer__UNICODE_STRING][Buffer__UNICODE_STRING($fullClassName$10$3390.24$KbdCreateClassObject$20)] != 0);
+goto label_59;
+
+
+label_46_false :
+assume (Mem[T.Buffer__UNICODE_STRING][Buffer__UNICODE_STRING($fullClassName$10$3390.24$KbdCreateClassObject$20)] == 0);
+goto label_50;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3446)
+label_47:
+// skip KbdDebugPrint
+goto label_51;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3446)
+label_50:
+call havoc_stringTemp := __HAVOC_malloc(1);
+$KbdDebugPrint.arg.2$5$ := havoc_stringTemp ;
+goto label_47;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3451)
+label_51:
+$status$6$3386.24$KbdCreateClassObject$20 := -1073741823 ;
+goto label_52;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3452)
+label_52:
+$errorCode$9$3389.24$KbdCreateClassObject$20 := -1073414143 ;
+goto label_53;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3453)
+label_53:
+$uniqueErrorValue$7$3387.24$KbdCreateClassObject$20 := 10006 ;
+goto label_54;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3454)
+label_54:
+Mem[T.UINT4] := Mem[T.UINT4][PLUS($dumpData$12$3392.24$KbdCreateClassObject$20, 4, 0) := Mem[T.MaximumLength__UNICODE_STRING][MaximumLength__UNICODE_STRING($fullClassName$10$3390.24$KbdCreateClassObject$20)]];
+goto label_55;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3455)
+label_55:
+$dumpCount$11$3391.24$KbdCreateClassObject$20 := 1 ;
+goto label_136;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3459)
+label_56:
+// ignoring intrinsic intrinsic.memset
+havoc $result.memset$3459.8$6$;
+goto label_63;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3459)
+label_59:
+$memset.arg.3$7$ := Mem[T.MaximumLength__UNICODE_STRING][MaximumLength__UNICODE_STRING($fullClassName$10$3390.24$KbdCreateClassObject$20)] ;
+goto label_56;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3460)
+label_60:
+call $result.RtlAppendUnicodeToString$3460.32$8$ := RtlAppendUnicodeToString ($fullClassName$10$3390.24$KbdCreateClassObject$20, $RtlAppendUnicodeToString.arg.2$9$);
+goto label_64;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3460)
+label_63:
+call havoc_stringTemp := __HAVOC_malloc(1);
+$RtlAppendUnicodeToString.arg.2$9$ := havoc_stringTemp ;
+goto label_60;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3461)
+label_64:
+call $result.RtlAppendUnicodeToString$3461.32$10$ := RtlAppendUnicodeToString ($fullClassName$10$3390.24$KbdCreateClassObject$20, Mem[T.Buffer__UNICODE_STRING][Buffer__UNICODE_STRING(BaseClassName__GLOBALS(Globals))]);
+goto label_67;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3463)
+label_67:
+goto label_67_true , label_67_false ;
+
+
+label_67_true :
+assume (Mem[T.ConnectOneClassToOnePort__GLOBALS][ConnectOneClassToOnePort__GLOBALS(Globals)] != 0);
+goto label_68;
+
+
+label_67_false :
+assume (Mem[T.ConnectOneClassToOnePort__GLOBALS][ConnectOneClassToOnePort__GLOBALS(Globals)] == 0);
+goto label_76;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3463)
+label_68:
+goto label_68_true , label_68_false ;
+
+
+label_68_true :
+assume ($Legacy$5$3358.28$KbdCreateClassObject$20 != 0);
+goto label_72;
+
+
+label_68_false :
+assume ($Legacy$5$3358.28$KbdCreateClassObject$20 == 0);
+goto label_76;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3464)
+label_69:
+call $result.RtlAppendUnicodeToString$3464.36$11$ := RtlAppendUnicodeToString ($fullClassName$10$3390.24$KbdCreateClassObject$20, $RtlAppendUnicodeToString.arg.2$12$);
+goto label_76;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3464)
+label_72:
+call havoc_stringTemp := __HAVOC_malloc(1);
+$RtlAppendUnicodeToString.arg.2$12$ := havoc_stringTemp ;
+goto label_69;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3467)
+label_73:
+call $result.RtlAppendUnicodeToString$3467.32$13$ := RtlAppendUnicodeToString ($fullClassName$10$3390.24$KbdCreateClassObject$20, $RtlAppendUnicodeToString.arg.2$14$);
+goto label_77;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3467)
+label_76:
+call havoc_stringTemp := __HAVOC_malloc(1);
+$RtlAppendUnicodeToString.arg.2$14$ := havoc_stringTemp ;
+goto label_73;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3473)
+label_77:
+$nameIndex$14$3394.24$KbdCreateClassObject$20 := 0 ;
+goto label_78;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3477)
+label_78:
+// loop entry initialization...
+LOOP_78_alloc := alloc;
+LOOP_78_Mem := Mem;
+LOOP_78_Res_DEVICE_STACK := Res_DEVICE_STACK;
+LOOP_78_Res_DEV_EXTN := Res_DEV_EXTN;
+LOOP_78_Res_DEV_OBJ_INIT := Res_DEV_OBJ_INIT;
+LOOP_78_Res_SPIN_LOCK := Res_SPIN_LOCK;
+goto label_78_head;
+
+
+label_78_head:
+// loop head assertions...
+//TAG: requires __pforall(_H_x, (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension), __inv_resource("DEV_OBJ_INIT", 1), ((struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension))->Self == _H_x && __resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension)) == 1)
+assert((forall _H_x:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)]} Inverse(Res_DEV_OBJ_INIT,1)[_H_x] ==> ((Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)])] == _H_x) && (Res_DEV_EXTN[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)]] == 1))));
+//TAG: requires __pforall(_H_z, _H_z->Self, __inv_resource("DEV_EXTN", 1), __resource("DEV_OBJ_INIT", _H_z->Self) == 1 && (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)(_H_z->Self))->DeviceExtension) == _H_z)
+assert((forall _H_z:int :: {Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)]} Inverse(Res_DEV_EXTN,1)[_H_z] ==> ((Res_DEV_OBJ_INIT[Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)]] == 1) && (Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)])] == _H_z))));
+//TAG: requires __forall(_H_z, __inv_resource("DEV_EXTN", 1), 1)
+assert((Subset(Empty(), Inverse(Res_DEV_EXTN,1)) && (forall _H_z : int :: {Inverse(Res_DEV_EXTN,1)[_H_z]} (Inverse(Res_DEV_EXTN,1)[_H_z]) ==> (true))));
+//TAG: requires 1 ==> (Globals.GrandMaster != (void *)0 ==> __resource("DEV_EXTN", Globals.GrandMaster) == 1)
+assert((true) ==> ((Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)] != 0) ==> (Res_DEV_EXTN[Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)]] == 1)));
+//TAG: requires 1 ==> __setin(&Globals.LegacyDeviceList, __btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList))
+assert((true) ==> (ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[LegacyDeviceList__GLOBALS(Globals)]));
+//TAG: requires 1 ==> __forall(_H_y, __btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList), _H_y == &Globals.LegacyDeviceList || __resource("DEV_EXTN", CONTAINING_RECORD(_H_y, struct _DEVICE_EXTENSION , Link)) == 1)
+assert((true) ==> ((Subset(Empty(), ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))) && (forall _H_y : int :: {ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[_H_y]} (ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[_H_y]) ==> ((_H_y == LegacyDeviceList__GLOBALS(Globals)) || (Res_DEV_EXTN[MINUS_LEFT_PTR(_H_y, 1, Link__DEVICE_EXTENSION(0))] == 1))))));
+//TAG: requires 1 ==> !__setin(&Globals.GrandMaster->Link, __setminus(__btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList), __set(&Globals.LegacyDeviceList)))
+assert((true) ==> (!(Difference(ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals)), Singleton(LegacyDeviceList__GLOBALS(Globals)))[Link__DEVICE_EXTENSION(Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)])])));
+//TAG: requires __preserves_resource("DEV_OBJ_INIT")
+assert(Res_DEV_OBJ_INIT == LOOP_78_Res_DEV_OBJ_INIT);
+//TAG: requires __preserves_resource("DEV_EXTN")
+assert(Res_DEV_EXTN == LOOP_78_Res_DEV_EXTN);
+//TAG: requires __preserves_field_map(__offset((*((struct _LIST_ENTRY *)0)).Flink))
+assert(Mem[T.Flink__LIST_ENTRY] == LOOP_78_Mem[T.Flink__LIST_ENTRY]);
+assume(forall f:int :: {alloc[Base(f)]} LOOP_78_alloc[Base(f)] == UNALLOCATED || LOOP_78_alloc[Base(f)] == alloc[Base(f)]);
+
+
+//TAG: net change in resource DEVICE_STACK only for: __set_empty
+assert (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEVICE_STACK[r]} (Empty()[r]) || LOOP_78_Res_DEVICE_STACK[r] == Res_DEVICE_STACK[r]));
+
+//TAG: net change in resource DEV_EXTN only for: __set_empty
+assert (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_EXTN[r]} (Empty()[r]) || LOOP_78_Res_DEV_EXTN[r] == Res_DEV_EXTN[r]));
+
+//TAG: net change in resource DEV_OBJ_INIT only for: __set_empty
+assert (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_OBJ_INIT[r]} (Empty()[r]) || LOOP_78_Res_DEV_OBJ_INIT[r] == Res_DEV_OBJ_INIT[r]));
+
+//TAG: net change in resource SPIN_LOCK only for: __set_empty
+assert (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_SPIN_LOCK[r]} (Empty()[r]) || LOOP_78_Res_SPIN_LOCK[r] == Res_SPIN_LOCK[r]));
+//TAG: updated memory locations at Mem[T.MinorFunction__IO_STACK_LOCATION] only for: __set_empty
+assert (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.MinorFunction__IO_STACK_LOCATION][_m]} (Empty()[_m]) || Mem[T.MinorFunction__IO_STACK_LOCATION][_m] == LOOP_78_Mem[T.MinorFunction__IO_STACK_LOCATION][_m]));
+//TAG: updated memory locations at Mem[T.CurrentStackLocation___unnamed_4_f19b65c1] only for: __set_empty
+assert (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.CurrentStackLocation___unnamed_4_f19b65c1][_m]} (Empty()[_m]) || Mem[T.CurrentStackLocation___unnamed_4_f19b65c1][_m] == LOOP_78_Mem[T.CurrentStackLocation___unnamed_4_f19b65c1][_m]));
+//TAG: updated memory locations at Mem[T.DeviceExtension__DEVICE_OBJECT] only for: __set_empty
+assert (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.DeviceExtension__DEVICE_OBJECT][_m] == LOOP_78_Mem[T.DeviceExtension__DEVICE_OBJECT][_m]));
+//TAG: updated memory locations at Mem[T.Self__DEVICE_EXTENSION] only for: __set_true, __set_empty
+assert (Subset(Empty(), Union(Union(Empty(), SetTrue()), Empty())) && (forall _m:int :: {Mem[T.Self__DEVICE_EXTENSION][_m]} (SetTrue()[_m]) || (Empty()[_m]) || Mem[T.Self__DEVICE_EXTENSION][_m] == LOOP_78_Mem[T.Self__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.Started__DEVICE_EXTENSION] only for: __set_empty
+assert (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Started__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Started__DEVICE_EXTENSION][_m] == LOOP_78_Mem[T.Started__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.GrandMaster__GLOBALS] only for: __set_empty
+assert (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.GrandMaster__GLOBALS][_m]} (Empty()[_m]) || Mem[T.GrandMaster__GLOBALS][_m] == LOOP_78_Mem[T.GrandMaster__GLOBALS][_m]));
+//TAG: updated memory locations at Mem[T.P_DEVICE_OBJECT] only for: __set_empty
+assert (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.P_DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.P_DEVICE_OBJECT][_m] == LOOP_78_Mem[T.P_DEVICE_OBJECT][_m]));
+
+// end loop head assertions
+
+Mem[T.UINT2] := Mem[T.UINT2][PLUS(Mem[T.Buffer__UNICODE_STRING][Buffer__UNICODE_STRING($fullClassName$10$3390.24$KbdCreateClassObject$20)], 2, MINUS_BOTH_PTR_OR_BOTH_INT( BINARY_BOTH_INT(Mem[T.Length__UNICODE_STRING][Length__UNICODE_STRING($fullClassName$10$3390.24$KbdCreateClassObject$20)], 2), 1, 1)) := PLUS(48, 1, $nameIndex$14$3394.24$KbdCreateClassObject$20)];
+$nameIndex$14$3394.24$KbdCreateClassObject$20 := PLUS($nameIndex$14$3394.24$KbdCreateClassObject$20, 1, 1) ;
+goto label_82;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3479)
+label_79:
+// skip KbdDebugPrint
+goto label_83;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3479)
+label_82:
+call havoc_stringTemp := __HAVOC_malloc(1);
+$KbdDebugPrint.arg.2$15$ := havoc_stringTemp ;
+goto label_79;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3485)
+label_83:
+call $result.IoCreateDevice$3485.35$16$ := IoCreateDevice ($DriverObject$1$3354.28$KbdCreateClassObject$20, 288, $fullClassName$10$3390.24$KbdCreateClassObject$20, 11, 0, 0, $ClassDeviceObject$3$3356.28$KbdCreateClassObject$20);
+goto label_86;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3485)
+label_86:
+$status$6$3386.24$KbdCreateClassObject$20 := $result.IoCreateDevice$3485.35$16$ ;
+goto label_87;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3493)
+label_87:
+goto label_87_true , label_87_false ;
+
+
+label_87_true :
+assume (-1073741771 == $status$6$3386.24$KbdCreateClassObject$20);
+goto label_78_head;
+
+
+label_87_false :
+assume !(-1073741771 == $status$6$3386.24$KbdCreateClassObject$20);
+goto label_88;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3495)
+label_88:
+Mem[T.PUINT2] := Mem[T.PUINT2][$FullDeviceName$4$3357.35$KbdCreateClassObject$20 := Mem[T.Buffer__UNICODE_STRING][Buffer__UNICODE_STRING($fullClassName$10$3390.24$KbdCreateClassObject$20)]];
+goto label_97;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3498)
+label_89:
+call ExReleaseFastMutex (Mutex__GLOBALS(Globals));
+goto label_92;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3499)
+label_92:
+call $result.IoCreateDevice$3499.31$17$ := IoCreateDevice ($DriverObject$1$3354.28$KbdCreateClassObject$20, 288, 0, 11, 0, 0, $ClassDeviceObject$3$3356.28$KbdCreateClassObject$20);
+goto label_95;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3499)
+label_95:
+$status$6$3386.24$KbdCreateClassObject$20 := $result.IoCreateDevice$3499.31$17$ ;
+goto label_96;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3506)
+label_96:
+Mem[T.PUINT2] := Mem[T.PUINT2][$FullDeviceName$4$3357.35$KbdCreateClassObject$20 := 0];
+goto label_97;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3509)
+label_97:
+goto label_97_true , label_97_false ;
+
+
+label_97_true :
+assume (0 <= $status$6$3386.24$KbdCreateClassObject$20);
+goto label_98;
+
+
+label_97_false :
+assume !(0 <= $status$6$3386.24$KbdCreateClassObject$20);
+goto label_102;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3509)
+label_98:
+goto label_98_true , label_98_false ;
+
+
+label_98_true :
+assume (Mem[T.P_DEVICE_OBJECT][$ClassDeviceObject$3$3356.28$KbdCreateClassObject$20] != 0);
+goto label_107;
+
+
+label_98_false :
+assume (Mem[T.P_DEVICE_OBJECT][$ClassDeviceObject$3$3356.28$KbdCreateClassObject$20] == 0);
+goto label_102;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3510)
+label_99:
+// skip KbdDebugPrint
+goto label_103;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3510)
+label_102:
+call havoc_stringTemp := __HAVOC_malloc(1);
+$KbdDebugPrint.arg.2$18$ := havoc_stringTemp ;
+goto label_99;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3516)
+label_103:
+$errorCode$9$3389.24$KbdCreateClassObject$20 := -1073414131 ;
+goto label_104;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3517)
+label_104:
+$uniqueErrorValue$7$3387.24$KbdCreateClassObject$20 := 10006 ;
+goto label_105;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3518)
+label_105:
+Mem[T.UINT4] := Mem[T.UINT4][PLUS($dumpData$12$3392.24$KbdCreateClassObject$20, 4, 0) := Mem[T.MaximumLength__UNICODE_STRING][MaximumLength__UNICODE_STRING($fullClassName$10$3390.24$KbdCreateClassObject$20)]];
+goto label_106;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3519)
+label_106:
+$dumpCount$11$3391.24$KbdCreateClassObject$20 := 1 ;
+goto label_136;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3528)
+label_107:
+assume (forall r:int :: {BIT_BAND(BIT_BOR(Mem[T.Flags__DEVICE_OBJECT][Flags__DEVICE_OBJECT(Mem[T.P_DEVICE_OBJECT][$ClassDeviceObject$3$3356.28$KbdCreateClassObject$20])], 4),r)} BIT_BAND(Mem[T.Flags__DEVICE_OBJECT][Flags__DEVICE_OBJECT(Mem[T.P_DEVICE_OBJECT][$ClassDeviceObject$3$3356.28$KbdCreateClassObject$20])],r)!= 0 || BIT_BAND(4,r)!= 0 <==> BIT_BAND(BIT_BOR(Mem[T.Flags__DEVICE_OBJECT][Flags__DEVICE_OBJECT(Mem[T.P_DEVICE_OBJECT][$ClassDeviceObject$3$3356.28$KbdCreateClassObject$20])], 4),r)!= 0);
+tempBoogie0 := BIT_BOR(Mem[T.Flags__DEVICE_OBJECT][Flags__DEVICE_OBJECT(Mem[T.P_DEVICE_OBJECT][$ClassDeviceObject$3$3356.28$KbdCreateClassObject$20])], 4) ;
+Mem[T.Flags__DEVICE_OBJECT] := Mem[T.Flags__DEVICE_OBJECT][Flags__DEVICE_OBJECT(Mem[T.P_DEVICE_OBJECT][$ClassDeviceObject$3$3356.28$KbdCreateClassObject$20]) := tempBoogie0];
+goto label_108;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3529)
+label_108:
+$deviceExtension$8$3388.24$KbdCreateClassObject$20 := Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.P_DEVICE_OBJECT][$ClassDeviceObject$3$3356.28$KbdCreateClassObject$20])] ;
+goto label_109;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3531)
+label_109:
+// Skipping Structure assignment due to the flag SkipStructAssignments
+goto label_110;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3533)
+label_110:
+Mem[T.Self__DEVICE_EXTENSION] := Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION($deviceExtension$8$3388.24$KbdCreateClassObject$20) := Mem[T.P_DEVICE_OBJECT][$ClassDeviceObject$3$3356.28$KbdCreateClassObject$20]];
+goto label_111;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3534)
+label_111:
+call IoInitializeRemoveLockEx (RemoveLock__DEVICE_EXTENSION($deviceExtension$8$3388.24$KbdCreateClassObject$20), 1130652235, 0, 0, 88);
+goto label_114;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3539)
+label_114:
+assume (Mem[T.SpinLock__DEVICE_EXTENSION][SpinLock__DEVICE_EXTENSION($deviceExtension$8$3388.24$KbdCreateClassObject$20)] == Mem[T.UINT4][SpinLock__DEVICE_EXTENSION($deviceExtension$8$3388.24$KbdCreateClassObject$20)]);
+call KeInitializeSpinLock (SpinLock__DEVICE_EXTENSION($deviceExtension$8$3388.24$KbdCreateClassObject$20));
+Mem[T.SpinLock__DEVICE_EXTENSION] := Mem[T.SpinLock__DEVICE_EXTENSION][SpinLock__DEVICE_EXTENSION($deviceExtension$8$3388.24$KbdCreateClassObject$20) := Mem[T.UINT4][SpinLock__DEVICE_EXTENSION($deviceExtension$8$3388.24$KbdCreateClassObject$20)]];
+goto label_117;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3544)
+label_117:
+call InitializeListHead_IRP (ReadQueue__DEVICE_EXTENSION($deviceExtension$8$3388.24$KbdCreateClassObject$20));
+goto label_120;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3550)
+label_120:
+Mem[T.TrustedSubsystemCount__DEVICE_EXTENSION] := Mem[T.TrustedSubsystemCount__DEVICE_EXTENSION][TrustedSubsystemCount__DEVICE_EXTENSION($deviceExtension$8$3388.24$KbdCreateClassObject$20) := 0];
+goto label_121;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3557)
+label_121:
+call $result.ExAllocatePoolWithTag$3557.0$19$ := ExAllocatePoolWithTag (0, Mem[T.InputDataQueueLength__KEYBOARD_ATTRIBUTES][InputDataQueueLength__KEYBOARD_ATTRIBUTES(KeyboardAttributes__DEVICE_EXTENSION($deviceExtension$8$3388.24$KbdCreateClassObject$20))], 1130652235);
+goto label_124;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3556)
+label_124:
+Mem[T.InputData__DEVICE_EXTENSION] := Mem[T.InputData__DEVICE_EXTENSION][InputData__DEVICE_EXTENSION($deviceExtension$8$3388.24$KbdCreateClassObject$20) := $result.ExAllocatePoolWithTag$3557.0$19$];
+goto label_125;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3562)
+label_125:
+goto label_125_true , label_125_false ;
+
+
+label_125_true :
+assume (Mem[T.InputData__DEVICE_EXTENSION][InputData__DEVICE_EXTENSION($deviceExtension$8$3388.24$KbdCreateClassObject$20)] != 0);
+goto label_133;
+
+
+label_125_false :
+assume (Mem[T.InputData__DEVICE_EXTENSION][InputData__DEVICE_EXTENSION($deviceExtension$8$3388.24$KbdCreateClassObject$20)] == 0);
+goto label_129;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3568)
+label_126:
+// skip KbdDebugPrint
+goto label_130;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3568)
+label_129:
+call havoc_stringTemp := __HAVOC_malloc(1);
+$KbdDebugPrint.arg.2$20$ := havoc_stringTemp ;
+goto label_126;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3574)
+label_130:
+$status$6$3386.24$KbdCreateClassObject$20 := -1073741670 ;
+goto label_131;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3580)
+label_131:
+$errorCode$9$3389.24$KbdCreateClassObject$20 := -1073414142 ;
+goto label_132;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3581)
+label_132:
+$uniqueErrorValue$7$3387.24$KbdCreateClassObject$20 := 10020 ;
+goto label_136;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3589)
+label_133:
+call KbdInitializeDataQueue ($deviceExtension$8$3388.24$KbdCreateClassObject$20);
+goto label_136;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3593)
+label_136:
+goto label_136_true , label_136_false ;
+
+
+label_136_true :
+assume ($status$6$3386.24$KbdCreateClassObject$20 != 0);
+goto label_137;
+
+
+label_136_false :
+assume ($status$6$3386.24$KbdCreateClassObject$20 == 0);
+goto label_162;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3599)
+label_137:
+call RtlFreeUnicodeString ($fullClassName$10$3390.24$KbdCreateClassObject$20);
+goto label_140;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3600)
+label_140:
+Mem[T.PUINT2] := Mem[T.PUINT2][$FullDeviceName$4$3357.35$KbdCreateClassObject$20 := 0];
+goto label_141;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3602)
+label_141:
+goto label_141_true , label_141_false ;
+
+
+label_141_true :
+assume ($errorCode$9$3389.24$KbdCreateClassObject$20 != 0);
+goto label_145;
+
+
+label_141_false :
+assume ($errorCode$9$3389.24$KbdCreateClassObject$20 == 0);
+goto label_148;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3603)
+label_142:
+call KeyboardClassLogError ($result.question.21$, $errorCode$9$3389.24$KbdCreateClassObject$20, $uniqueErrorValue$7$3387.24$KbdCreateClassObject$20, $status$6$3386.24$KbdCreateClassObject$20, $dumpCount$11$3391.24$KbdCreateClassObject$20, $dumpData$12$3392.24$KbdCreateClassObject$20, 0);
+goto label_148;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3604)
+label_145:
+goto label_145_true , label_145_false ;
+
+
+label_145_true :
+assume (Mem[T.P_DEVICE_OBJECT][$ClassDeviceObject$3$3356.28$KbdCreateClassObject$20] != 0);
+goto label_147;
+
+
+label_145_false :
+assume (Mem[T.P_DEVICE_OBJECT][$ClassDeviceObject$3$3356.28$KbdCreateClassObject$20] == 0);
+goto label_146;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3604)
+label_146:
+$result.question.21$ := $DriverObject$1$3354.28$KbdCreateClassObject$20 ;
+goto label_142;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3604)
+label_147:
+$result.question.21$ := Mem[T.P_DEVICE_OBJECT][$ClassDeviceObject$3$3356.28$KbdCreateClassObject$20] ;
+goto label_142;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3614)
+label_148:
+goto label_148_true , label_148_false ;
+
+
+label_148_true :
+assume ($deviceExtension$8$3388.24$KbdCreateClassObject$20 != 0);
+goto label_149;
+
+
+label_148_false :
+assume ($deviceExtension$8$3388.24$KbdCreateClassObject$20 == 0);
+goto label_154;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3614)
+label_149:
+goto label_149_true , label_149_false ;
+
+
+label_149_true :
+assume (Mem[T.InputData__DEVICE_EXTENSION][InputData__DEVICE_EXTENSION($deviceExtension$8$3388.24$KbdCreateClassObject$20)] != 0);
+goto label_150;
+
+
+label_149_false :
+assume (Mem[T.InputData__DEVICE_EXTENSION][InputData__DEVICE_EXTENSION($deviceExtension$8$3388.24$KbdCreateClassObject$20)] == 0);
+goto label_154;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3615)
+label_150:
+call ExFreePoolWithTag (Mem[T.InputData__DEVICE_EXTENSION][InputData__DEVICE_EXTENSION($deviceExtension$8$3388.24$KbdCreateClassObject$20)], 0);
+goto label_153;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3616)
+label_153:
+Mem[T.InputData__DEVICE_EXTENSION] := Mem[T.InputData__DEVICE_EXTENSION][InputData__DEVICE_EXTENSION($deviceExtension$8$3388.24$KbdCreateClassObject$20) := 0];
+goto label_154;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3618)
+label_154:
+goto label_154_true , label_154_false ;
+
+
+label_154_true :
+assume (Mem[T.P_DEVICE_OBJECT][$ClassDeviceObject$3$3356.28$KbdCreateClassObject$20] != 0);
+goto label_155;
+
+
+label_154_false :
+assume (Mem[T.P_DEVICE_OBJECT][$ClassDeviceObject$3$3356.28$KbdCreateClassObject$20] == 0);
+goto label_162;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3619)
+label_155:
+call IoDeleteDevice (Mem[T.P_DEVICE_OBJECT][$ClassDeviceObject$3$3356.28$KbdCreateClassObject$20]);
+goto label_158;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3620)
+label_158:
+Mem[T.P_DEVICE_OBJECT] := Mem[T.P_DEVICE_OBJECT][$ClassDeviceObject$3$3356.28$KbdCreateClassObject$20 := 0];
+goto label_162;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3624)
+label_159:
+// skip KbdDebugPrint
+goto label_163;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3624)
+label_162:
+call havoc_stringTemp := __HAVOC_malloc(1);
+$KbdDebugPrint.arg.2$22$ := havoc_stringTemp ;
+goto label_159;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3626)
+label_163:
+$result.KbdCreateClassObject$3353.0$1$ := $status$6$3386.24$KbdCreateClassObject$20 ;
+goto label_1;
+
+}
+
diff --git a/Test/havoc0/KeyboardClassFindMorePorts.bpl b/Test/havoc0/KeyboardClassFindMorePorts.bpl
new file mode 100644
index 00000000..28e0dd09
--- /dev/null
+++ b/Test/havoc0/KeyboardClassFindMorePorts.bpl
@@ -0,0 +1,3780 @@
+type byte, name;
+function OneByteToInt(byte) returns (int);
+function TwoBytesToInt(byte, byte) returns (int);
+function FourBytesToInt(byte, byte, byte, byte) returns (int);
+axiom(forall b0:byte, c0:byte :: {OneByteToInt(b0), OneByteToInt(c0)} OneByteToInt(b0) == OneByteToInt(c0) ==> b0 == c0);
+axiom(forall b0:byte, b1: byte, c0:byte, c1:byte :: {TwoBytesToInt(b0, b1), TwoBytesToInt(c0, c1)} TwoBytesToInt(b0, b1) == TwoBytesToInt(c0, c1) ==> b0 == c0 && b1 == c1);
+axiom(forall b0:byte, b1: byte, b2:byte, b3:byte, c0:byte, c1:byte, c2:byte, c3:byte :: {FourBytesToInt(b0, b1, b2, b3), FourBytesToInt(c0, c1, c2, c3)} FourBytesToInt(b0, b1, b2, b3) == FourBytesToInt(c0, c1, c2, c3) ==> b0 == c0 && b1 == c1 && b2 == c2 && b3 == c3);
+
+// Mutable
+var Mem_BYTE:[int]byte;
+var alloc:[int]name;
+
+
+function Field(int) returns (name);
+function Base(int) returns (int);
+
+// Constants
+const unique UNALLOCATED:name;
+const unique ALLOCATED: name;
+const unique FREED:name;
+
+const unique BYTE:name;
+
+function Equal([int]bool, [int]bool) returns (bool);
+function Subset([int]bool, [int]bool) returns (bool);
+function Disjoint([int]bool, [int]bool) returns (bool);
+
+function Empty() returns ([int]bool);
+function SetTrue() returns ([int]bool);
+function Singleton(int) returns ([int]bool);
+function Reachable([int,int]bool, int) returns ([int]bool);
+function Union([int]bool, [int]bool) returns ([int]bool);
+function Intersection([int]bool, [int]bool) returns ([int]bool);
+function Difference([int]bool, [int]bool) returns ([int]bool);
+function Dereference([int]bool, [int]int) returns ([int]bool);
+function Inverse(f:[int]int, x:int) returns ([int]bool);
+
+function AtLeast(int, int) returns ([int]bool);
+function Rep(int, int) returns (int);
+axiom(forall n:int, x:int, y:int :: {AtLeast(n,x)[y]} AtLeast(n,x)[y] ==> x <= y && Rep(n,x) == Rep(n,y));
+axiom(forall n:int, x:int, y:int :: {AtLeast(n,x),Rep(n,x),Rep(n,y)} x <= y && Rep(n,x) == Rep(n,y) ==> AtLeast(n,x)[y]);
+axiom(forall n:int, x:int :: {AtLeast(n,x)} AtLeast(n,x)[x]);
+axiom(forall n:int, x:int, z:int :: {PLUS(x,n,z)} Rep(n,x) == Rep(n,PLUS(x,n,z)));
+axiom(forall n:int, x:int :: {Rep(n,x)} (exists k:int :: Rep(n,x) - x == n*k));
+
+/*
+function AtLeast(int, int) returns ([int]bool);
+function ModEqual(int, int, int) returns (bool);
+axiom(forall n:int, x:int :: ModEqual(n,x,x));
+axiom(forall n:int, x:int, y:int :: {ModEqual(n,x,y)} ModEqual(n,x,y) ==> ModEqual(n,y,x));
+axiom(forall n:int, x:int, y:int, z:int :: {ModEqual(n,x,y), ModEqual(n,y,z)} ModEqual(n,x,y) && ModEqual(n,y,z) ==> ModEqual(n,x,z));
+axiom(forall n:int, x:int, z:int :: {PLUS(x,n,z)} ModEqual(n,x,PLUS(x,n,z)));
+axiom(forall n:int, x:int, y:int :: {ModEqual(n,x,y)} ModEqual(n,x,y) ==> (exists k:int :: x - y == n*k));
+axiom(forall x:int, n:int, y:int :: {AtLeast(n,x)[y]}{ModEqual(n,x,y)} AtLeast(n,x)[y] <==> x <= y && ModEqual(n,x,y));
+axiom(forall x:int, n:int :: {AtLeast(n,x)} AtLeast(n,x)[x]);
+*/
+
+function Array(int, int, int) returns ([int]bool);
+axiom(forall x:int, n:int, z:int :: {Array(x,n,z)} z <= 0 ==> Equal(Array(x,n,z), Empty()));
+axiom(forall x:int, n:int, z:int :: {Array(x,n,z)} z > 0 ==> Equal(Array(x,n,z), Difference(AtLeast(n,x),AtLeast(n,PLUS(x,n,z)))));
+
+
+axiom(forall x:int :: !Empty()[x]);
+
+axiom(forall x:int :: SetTrue()[x]);
+
+axiom(forall x:int, y:int :: {Singleton(y)[x]} Singleton(y)[x] <==> x == y);
+axiom(forall y:int :: {Singleton(y)} Singleton(y)[y]);
+
+/* this formulation of Union IS more complete than the earlier one */
+/* (A U B)[e], A[d], A U B = Singleton(c), d != e */
+axiom(forall x:int, S:[int]bool, T:[int]bool :: {Union(S,T)[x]}{Union(S,T),S[x]}{Union(S,T),T[x]} Union(S,T)[x] <==> S[x] || T[x]);
+axiom(forall x:int, S:[int]bool, T:[int]bool :: {Intersection(S,T)[x]}{Intersection(S,T),S[x]}{Intersection(S,T),T[x]} Intersection(S,T)[x] <==> S[x] && T[x]);
+axiom(forall x:int, S:[int]bool, T:[int]bool :: {Difference(S,T)[x]}{Difference(S,T),S[x]}{Difference(S,T),T[x]} Difference(S,T)[x] <==> S[x] && !T[x]);
+
+axiom(forall S:[int]bool, T:[int]bool :: {Equal(S,T)} Equal(S,T) <==> Subset(S,T) && Subset(T,S));
+axiom(forall x:int, S:[int]bool, T:[int]bool :: {S[x],Subset(S,T)}{T[x],Subset(S,T)} S[x] && Subset(S,T) ==> T[x]);
+axiom(forall S:[int]bool, T:[int]bool :: {Subset(S,T)} Subset(S,T) || (exists x:int :: S[x] && !T[x]));
+axiom(forall x:int, S:[int]bool, T:[int]bool :: {S[x],Disjoint(S,T)}{T[x],Disjoint(S,T)} !(S[x] && Disjoint(S,T) && T[x]));
+axiom(forall S:[int]bool, T:[int]bool :: {Disjoint(S,T)} Disjoint(S,T) || (exists x:int :: S[x] && T[x]));
+
+axiom(forall f:[int]int, x:int :: {Inverse(f,f[x])} Inverse(f,f[x])[x]);
+axiom(forall f:[int]int, x:int, y:int :: {Inverse(f,y), f[x]} Inverse(f,y)[x] ==> f[x] == y);
+axiom(forall f:[int]int, x:int, y:int :: {Inverse(f[x := y],y)} Equal(Inverse(f[x := y],y), Union(Inverse(f,y), Singleton(x))));
+axiom(forall f:[int]int, x:int, y:int, z:int :: {Inverse(f[x := y],z)} y == z || Equal(Inverse(f[x := y],z), Difference(Inverse(f,z), Singleton(x))));
+
+
+axiom(forall x:int, S:[int]bool, M:[int]int :: {Dereference(S,M)[x]} Dereference(S,M)[x] ==> (exists y:int :: x == M[y] && S[y]));
+axiom(forall x:int, S:[int]bool, M:[int]int :: {M[x], S[x], Dereference(S,M)} S[x] ==> Dereference(S,M)[M[x]]);
+axiom(forall x:int, y:int, S:[int]bool, M:[int]int :: {Dereference(S,M[x := y])} !S[x] ==> Equal(Dereference(S,M[x := y]), Dereference(S,M)));
+axiom(forall x:int, y:int, S:[int]bool, M:[int]int :: {Dereference(S,M[x := y])}
+ S[x] && Equal(Intersection(Inverse(M,M[x]), S), Singleton(x)) ==> Equal(Dereference(S,M[x := y]), Union(Difference(Dereference(S,M), Singleton(M[x])), Singleton(y))));
+axiom(forall x:int, y:int, S:[int]bool, M:[int]int :: {Dereference(S,M[x := y])}
+ S[x] && !Equal(Intersection(Inverse(M,M[x]), S), Singleton(x)) ==> Equal(Dereference(S,M[x := y]), Union(Dereference(S,M), Singleton(y))));
+
+function Unified([name][int]int) returns ([int]int);
+axiom(forall M:[name][int]int, x:int :: {Unified(M)[x]} Unified(M)[x] == M[Field(x)][x]);
+axiom(forall M:[name][int]int, x:int, y:int :: {Unified(M[Field(x) := M[Field(x)][x := y]])} Unified(M[Field(x) := M[Field(x)][x := y]]) == Unified(M)[x := y]);
+// Memory model
+
+var Mem: [name][int]int;
+
+function Match(a:int, t:name) returns (bool);
+function HasType(v:int, t:name, m:[name][int]int) returns (bool);
+function Values(t:name, m:[name][int]int) returns ([int]bool);
+function T.Ptr(t:name) returns (name);
+
+axiom(forall v:int, t:name, m:[name][int]int :: {Values(t, m)[v]} Values(t, m)[v] ==> HasType(v, t, m));
+axiom(forall v:int, t:name, m:[name][int]int :: {HasType(v, t, m), Values(t, m)} HasType(v, t, m) ==> Values(t, m)[v]);
+
+axiom(forall a:int, t:name :: {Match(a, T.Ptr(t))} Match(a, T.Ptr(t)) <==> Field(a) == T.Ptr(t));
+axiom(forall v:int, t:name, m:[name][int]int :: {HasType(v, T.Ptr(t), m)} HasType(v, T.Ptr(t), m) <==> (v == 0 || (v > 0 && Match(v, t))));
+
+axiom(forall v:int, t:name, m1:[name][int]int, m2:[name][int]int :: {HasType(v, t, m1), HasType(v, t, m2)}
+ (HasType(v, t, m1) <==> HasType(v, t, m2)));
+
+// Field declarations
+
+const unique T.Guid_WMIGUIDREGINFO:name;
+const unique T.InstanceCount_WMIGUIDREGINFO:name;
+const unique T.Flags_WMIGUIDREGINFO:name;
+const unique T.OperationID__ACCESS_STATE:name;
+const unique T.SecurityEvaluated__ACCESS_STATE:name;
+const unique T.GenerateAudit__ACCESS_STATE:name;
+const unique T.GenerateOnClose__ACCESS_STATE:name;
+const unique T.PrivilegesAllocated__ACCESS_STATE:name;
+const unique T.Flags__ACCESS_STATE:name;
+const unique T.RemainingDesiredAccess__ACCESS_STATE:name;
+const unique T.PreviouslyGrantedAccess__ACCESS_STATE:name;
+const unique T.OriginalDesiredAccess__ACCESS_STATE:name;
+const unique T.SubjectSecurityContext__ACCESS_STATE:name;
+const unique T.SecurityDescriptor__ACCESS_STATE:name;
+const unique T.AuxData__ACCESS_STATE:name;
+const unique T.Privileges__ACCESS_STATE:name;
+const unique T.AuditPrivileges__ACCESS_STATE:name;
+const unique T.ObjectName__ACCESS_STATE:name;
+const unique T.ObjectTypeName__ACCESS_STATE:name;
+const unique T.InterfaceType__CM_FULL_RESOURCE_DESCRIPTOR:name;
+const unique T.BusNumber__CM_FULL_RESOURCE_DESCRIPTOR:name;
+const unique T.PartialResourceList__CM_FULL_RESOURCE_DESCRIPTOR:name;
+const unique T.Type__CM_PARTIAL_RESOURCE_DESCRIPTOR:name;
+const unique T.ShareDisposition__CM_PARTIAL_RESOURCE_DESCRIPTOR:name;
+const unique T.Flags__CM_PARTIAL_RESOURCE_DESCRIPTOR:name;
+const unique T.u__CM_PARTIAL_RESOURCE_DESCRIPTOR:name;
+const unique T.Version__CM_PARTIAL_RESOURCE_LIST:name;
+const unique T.Revision__CM_PARTIAL_RESOURCE_LIST:name;
+const unique T.Count__CM_PARTIAL_RESOURCE_LIST:name;
+const unique T.PartialDescriptors__CM_PARTIAL_RESOURCE_LIST:name;
+const unique T.Count__CM_RESOURCE_LIST:name;
+const unique T.List__CM_RESOURCE_LIST:name;
+const unique T.Size__DEVICE_CAPABILITIES:name;
+const unique T.Version__DEVICE_CAPABILITIES:name;
+const unique T.DeviceD1__DEVICE_CAPABILITIES:name;
+const unique T.DeviceD2__DEVICE_CAPABILITIES:name;
+const unique T.LockSupported__DEVICE_CAPABILITIES:name;
+const unique T.EjectSupported__DEVICE_CAPABILITIES:name;
+const unique T.Removable__DEVICE_CAPABILITIES:name;
+const unique T.DockDevice__DEVICE_CAPABILITIES:name;
+const unique T.UniqueID__DEVICE_CAPABILITIES:name;
+const unique T.SilentInstall__DEVICE_CAPABILITIES:name;
+const unique T.RawDeviceOK__DEVICE_CAPABILITIES:name;
+const unique T.SurpriseRemovalOK__DEVICE_CAPABILITIES:name;
+const unique T.WakeFromD0__DEVICE_CAPABILITIES:name;
+const unique T.WakeFromD1__DEVICE_CAPABILITIES:name;
+const unique T.WakeFromD2__DEVICE_CAPABILITIES:name;
+const unique T.WakeFromD3__DEVICE_CAPABILITIES:name;
+const unique T.HardwareDisabled__DEVICE_CAPABILITIES:name;
+const unique T.NonDynamic__DEVICE_CAPABILITIES:name;
+const unique T.WarmEjectSupported__DEVICE_CAPABILITIES:name;
+const unique T.NoDisplayInUI__DEVICE_CAPABILITIES:name;
+const unique T.Reserved__DEVICE_CAPABILITIES:name;
+const unique T.Address__DEVICE_CAPABILITIES:name;
+const unique T.UINumber__DEVICE_CAPABILITIES:name;
+const unique T.DeviceState__DEVICE_CAPABILITIES:name;
+const unique T.SystemWake__DEVICE_CAPABILITIES:name;
+const unique T.DeviceWake__DEVICE_CAPABILITIES:name;
+const unique T.D1Latency__DEVICE_CAPABILITIES:name;
+const unique T.D2Latency__DEVICE_CAPABILITIES:name;
+const unique T.D3Latency__DEVICE_CAPABILITIES:name;
+const unique T.Self__DEVICE_EXTENSION:name;
+const unique T.TrueClassDevice__DEVICE_EXTENSION:name;
+const unique T.TopPort__DEVICE_EXTENSION:name;
+const unique T.PDO__DEVICE_EXTENSION:name;
+const unique T.RemoveLock__DEVICE_EXTENSION:name;
+const unique T.PnP__DEVICE_EXTENSION:name;
+const unique T.Started__DEVICE_EXTENSION:name;
+const unique T.AllowDisable__DEVICE_EXTENSION:name;
+const unique T.WaitWakeSpinLock__DEVICE_EXTENSION:name;
+const unique T.TrustedSubsystemCount__DEVICE_EXTENSION:name;
+const unique T.InputCount__DEVICE_EXTENSION:name;
+const unique T.SymbolicLinkName__DEVICE_EXTENSION:name;
+const unique T.InputData__DEVICE_EXTENSION:name;
+const unique T.DataIn__DEVICE_EXTENSION:name;
+const unique T.DataOut__DEVICE_EXTENSION:name;
+const unique T.KeyboardAttributes__DEVICE_EXTENSION:name;
+const unique T.IndicatorParameters__DEVICE_EXTENSION:name;
+const unique T.SpinLock__DEVICE_EXTENSION:name;
+const unique T.ReadQueue__DEVICE_EXTENSION:name;
+const unique T.SequenceNumber__DEVICE_EXTENSION:name;
+const unique T.DeviceState__DEVICE_EXTENSION:name;
+const unique T.SystemState__DEVICE_EXTENSION:name;
+const unique T.UnitId__DEVICE_EXTENSION:name;
+const unique T.WmiLibInfo__DEVICE_EXTENSION:name;
+const unique T.SystemToDeviceState__DEVICE_EXTENSION:name;
+const unique T.MinDeviceWakeState__DEVICE_EXTENSION:name;
+const unique T.MinSystemWakeState__DEVICE_EXTENSION:name;
+const unique T.WaitWakeIrp__DEVICE_EXTENSION:name;
+const unique T.ExtraWaitWakeIrp__DEVICE_EXTENSION:name;
+const unique T.TargetNotifyHandle__DEVICE_EXTENSION:name;
+const unique T.Link__DEVICE_EXTENSION:name;
+const unique T.File__DEVICE_EXTENSION:name;
+const unique T.Enabled__DEVICE_EXTENSION:name;
+const unique T.OkayToLogOverflow__DEVICE_EXTENSION:name;
+const unique T.WaitWakeEnabled__DEVICE_EXTENSION:name;
+const unique T.SurpriseRemoved__DEVICE_EXTENSION:name;
+const unique T.Type__DEVICE_OBJECT:name;
+const unique T.Size__DEVICE_OBJECT:name;
+const unique T.ReferenceCount__DEVICE_OBJECT:name;
+const unique T.DriverObject__DEVICE_OBJECT:name;
+const unique T.NextDevice__DEVICE_OBJECT:name;
+const unique T.AttachedDevice__DEVICE_OBJECT:name;
+const unique T.CurrentIrp__DEVICE_OBJECT:name;
+const unique T.Timer__DEVICE_OBJECT:name;
+const unique T.Flags__DEVICE_OBJECT:name;
+const unique T.Characteristics__DEVICE_OBJECT:name;
+const unique T.Vpb__DEVICE_OBJECT:name;
+const unique T.DeviceExtension__DEVICE_OBJECT:name;
+const unique T.DeviceType__DEVICE_OBJECT:name;
+const unique T.StackSize__DEVICE_OBJECT:name;
+const unique T.Queue__DEVICE_OBJECT:name;
+const unique T.AlignmentRequirement__DEVICE_OBJECT:name;
+const unique T.DeviceQueue__DEVICE_OBJECT:name;
+const unique T.Dpc__DEVICE_OBJECT:name;
+const unique T.ActiveThreadCount__DEVICE_OBJECT:name;
+const unique T.SecurityDescriptor__DEVICE_OBJECT:name;
+const unique T.DeviceLock__DEVICE_OBJECT:name;
+const unique T.SectorSize__DEVICE_OBJECT:name;
+const unique T.Spare1__DEVICE_OBJECT:name;
+const unique T.DeviceObjectExtension__DEVICE_OBJECT:name;
+const unique T.Reserved__DEVICE_OBJECT:name;
+const unique T.Type__DEVOBJ_EXTENSION:name;
+const unique T.Size__DEVOBJ_EXTENSION:name;
+const unique T.DeviceObject__DEVOBJ_EXTENSION:name;
+const unique T.__unnamed_4_a97c65a1__DISPATCHER_HEADER:name;
+const unique T.SignalState__DISPATCHER_HEADER:name;
+const unique T.WaitListHead__DISPATCHER_HEADER:name;
+const unique T.DriverObject__DRIVER_EXTENSION:name;
+const unique T.AddDevice__DRIVER_EXTENSION:name;
+const unique T.Count__DRIVER_EXTENSION:name;
+const unique T.ServiceKeyName__DRIVER_EXTENSION:name;
+const unique T.Type__DRIVER_OBJECT:name;
+const unique T.Size__DRIVER_OBJECT:name;
+const unique T.DeviceObject__DRIVER_OBJECT:name;
+const unique T.Flags__DRIVER_OBJECT:name;
+const unique T.DriverStart__DRIVER_OBJECT:name;
+const unique T.DriverSize__DRIVER_OBJECT:name;
+const unique T.DriverSection__DRIVER_OBJECT:name;
+const unique T.DriverExtension__DRIVER_OBJECT:name;
+const unique T.DriverName__DRIVER_OBJECT:name;
+const unique T.HardwareDatabase__DRIVER_OBJECT:name;
+const unique T.FastIoDispatch__DRIVER_OBJECT:name;
+const unique T.DriverInit__DRIVER_OBJECT:name;
+const unique T.DriverStartIo__DRIVER_OBJECT:name;
+const unique T.DriverUnload__DRIVER_OBJECT:name;
+const unique T.MajorFunction__DRIVER_OBJECT:name;
+const unique T.SystemResourcesList__ERESOURCE:name;
+const unique T.OwnerTable__ERESOURCE:name;
+const unique T.ActiveCount__ERESOURCE:name;
+const unique T.Flag__ERESOURCE:name;
+const unique T.SharedWaiters__ERESOURCE:name;
+const unique T.ExclusiveWaiters__ERESOURCE:name;
+const unique T.OwnerEntry__ERESOURCE:name;
+const unique T.ActiveEntries__ERESOURCE:name;
+const unique T.ContentionCount__ERESOURCE:name;
+const unique T.NumberOfSharedWaiters__ERESOURCE:name;
+const unique T.NumberOfExclusiveWaiters__ERESOURCE:name;
+const unique T.__unnamed_4_52c594f7__ERESOURCE:name;
+const unique T.SpinLock__ERESOURCE:name;
+const unique T.SizeOfFastIoDispatch__FAST_IO_DISPATCH:name;
+const unique T.FastIoCheckIfPossible__FAST_IO_DISPATCH:name;
+const unique T.FastIoRead__FAST_IO_DISPATCH:name;
+const unique T.FastIoWrite__FAST_IO_DISPATCH:name;
+const unique T.FastIoQueryBasicInfo__FAST_IO_DISPATCH:name;
+const unique T.FastIoQueryStandardInfo__FAST_IO_DISPATCH:name;
+const unique T.FastIoLock__FAST_IO_DISPATCH:name;
+const unique T.FastIoUnlockSingle__FAST_IO_DISPATCH:name;
+const unique T.FastIoUnlockAll__FAST_IO_DISPATCH:name;
+const unique T.FastIoUnlockAllByKey__FAST_IO_DISPATCH:name;
+const unique T.FastIoDeviceControl__FAST_IO_DISPATCH:name;
+const unique T.AcquireFileForNtCreateSection__FAST_IO_DISPATCH:name;
+const unique T.ReleaseFileForNtCreateSection__FAST_IO_DISPATCH:name;
+const unique T.FastIoDetachDevice__FAST_IO_DISPATCH:name;
+const unique T.FastIoQueryNetworkOpenInfo__FAST_IO_DISPATCH:name;
+const unique T.AcquireForModWrite__FAST_IO_DISPATCH:name;
+const unique T.MdlRead__FAST_IO_DISPATCH:name;
+const unique T.MdlReadComplete__FAST_IO_DISPATCH:name;
+const unique T.PrepareMdlWrite__FAST_IO_DISPATCH:name;
+const unique T.MdlWriteComplete__FAST_IO_DISPATCH:name;
+const unique T.FastIoReadCompressed__FAST_IO_DISPATCH:name;
+const unique T.FastIoWriteCompressed__FAST_IO_DISPATCH:name;
+const unique T.MdlReadCompleteCompressed__FAST_IO_DISPATCH:name;
+const unique T.MdlWriteCompleteCompressed__FAST_IO_DISPATCH:name;
+const unique T.FastIoQueryOpen__FAST_IO_DISPATCH:name;
+const unique T.ReleaseForModWrite__FAST_IO_DISPATCH:name;
+const unique T.AcquireForCcFlush__FAST_IO_DISPATCH:name;
+const unique T.ReleaseForCcFlush__FAST_IO_DISPATCH:name;
+const unique T.Count__FAST_MUTEX:name;
+const unique T.Owner__FAST_MUTEX:name;
+const unique T.Contention__FAST_MUTEX:name;
+const unique T.Gate__FAST_MUTEX:name;
+const unique T.OldIrql__FAST_MUTEX:name;
+const unique T.CreationTime__FILE_BASIC_INFORMATION:name;
+const unique T.LastAccessTime__FILE_BASIC_INFORMATION:name;
+const unique T.LastWriteTime__FILE_BASIC_INFORMATION:name;
+const unique T.ChangeTime__FILE_BASIC_INFORMATION:name;
+const unique T.FileAttributes__FILE_BASIC_INFORMATION:name;
+const unique T.CreationTime__FILE_NETWORK_OPEN_INFORMATION:name;
+const unique T.LastAccessTime__FILE_NETWORK_OPEN_INFORMATION:name;
+const unique T.LastWriteTime__FILE_NETWORK_OPEN_INFORMATION:name;
+const unique T.ChangeTime__FILE_NETWORK_OPEN_INFORMATION:name;
+const unique T.AllocationSize__FILE_NETWORK_OPEN_INFORMATION:name;
+const unique T.EndOfFile__FILE_NETWORK_OPEN_INFORMATION:name;
+const unique T.FileAttributes__FILE_NETWORK_OPEN_INFORMATION:name;
+const unique T.Type__FILE_OBJECT:name;
+const unique T.Size__FILE_OBJECT:name;
+const unique T.DeviceObject__FILE_OBJECT:name;
+const unique T.Vpb__FILE_OBJECT:name;
+const unique T.FsContext__FILE_OBJECT:name;
+const unique T.FsContext2__FILE_OBJECT:name;
+const unique T.SectionObjectPointer__FILE_OBJECT:name;
+const unique T.PrivateCacheMap__FILE_OBJECT:name;
+const unique T.FinalStatus__FILE_OBJECT:name;
+const unique T.RelatedFileObject__FILE_OBJECT:name;
+const unique T.LockOperation__FILE_OBJECT:name;
+const unique T.DeletePending__FILE_OBJECT:name;
+const unique T.ReadAccess__FILE_OBJECT:name;
+const unique T.WriteAccess__FILE_OBJECT:name;
+const unique T.DeleteAccess__FILE_OBJECT:name;
+const unique T.SharedRead__FILE_OBJECT:name;
+const unique T.SharedWrite__FILE_OBJECT:name;
+const unique T.SharedDelete__FILE_OBJECT:name;
+const unique T.Flags__FILE_OBJECT:name;
+const unique T.FileName__FILE_OBJECT:name;
+const unique T.CurrentByteOffset__FILE_OBJECT:name;
+const unique T.Waiters__FILE_OBJECT:name;
+const unique T.Busy__FILE_OBJECT:name;
+const unique T.LastLock__FILE_OBJECT:name;
+const unique T.Lock__FILE_OBJECT:name;
+const unique T.Event__FILE_OBJECT:name;
+const unique T.CompletionContext__FILE_OBJECT:name;
+const unique T.IrpListLock__FILE_OBJECT:name;
+const unique T.IrpList__FILE_OBJECT:name;
+const unique T.FileObjectExtension__FILE_OBJECT:name;
+const unique T.AllocationSize__FILE_STANDARD_INFORMATION:name;
+const unique T.EndOfFile__FILE_STANDARD_INFORMATION:name;
+const unique T.NumberOfLinks__FILE_STANDARD_INFORMATION:name;
+const unique T.DeletePending__FILE_STANDARD_INFORMATION:name;
+const unique T.Directory__FILE_STANDARD_INFORMATION:name;
+const unique T.Debug__GLOBALS:name;
+const unique T.GrandMaster__GLOBALS:name;
+const unique T.AssocClassList__GLOBALS:name;
+const unique T.NumAssocClass__GLOBALS:name;
+const unique T.Opens__GLOBALS:name;
+const unique T.NumberLegacyPorts__GLOBALS:name;
+const unique T.Mutex__GLOBALS:name;
+const unique T.ConnectOneClassToOnePort__GLOBALS:name;
+const unique T.SendOutputToAllPorts__GLOBALS:name;
+const unique T.PortsServiced__GLOBALS:name;
+const unique T.InitExtension__GLOBALS:name;
+const unique T.RegistryPath__GLOBALS:name;
+const unique T.BaseClassName__GLOBALS:name;
+const unique T.BaseClassBuffer__GLOBALS:name;
+const unique T.LegacyDeviceList__GLOBALS:name;
+const unique T.Data1__GUID:name;
+const unique T.Data2__GUID:name;
+const unique T.Data3__GUID:name;
+const unique T.Data4__GUID:name;
+const unique T.PrivilegeCount__INITIAL_PRIVILEGE_SET:name;
+const unique T.Control__INITIAL_PRIVILEGE_SET:name;
+const unique T.Privilege__INITIAL_PRIVILEGE_SET:name;
+const unique T.Size__INTERFACE:name;
+const unique T.Version__INTERFACE:name;
+const unique T.Context__INTERFACE:name;
+const unique T.InterfaceReference__INTERFACE:name;
+const unique T.InterfaceDereference__INTERFACE:name;
+const unique T.Port__IO_COMPLETION_CONTEXT:name;
+const unique T.Key__IO_COMPLETION_CONTEXT:name;
+const unique T.Common__IO_REMOVE_LOCK:name;
+const unique T.Dbg__IO_REMOVE_LOCK:name;
+const unique T.Removed__IO_REMOVE_LOCK_COMMON_BLOCK:name;
+const unique T.Reserved__IO_REMOVE_LOCK_COMMON_BLOCK:name;
+const unique T.IoCount__IO_REMOVE_LOCK_COMMON_BLOCK:name;
+const unique T.RemoveEvent__IO_REMOVE_LOCK_COMMON_BLOCK:name;
+const unique T.Signature__IO_REMOVE_LOCK_DBG_BLOCK:name;
+const unique T.HighWatermark__IO_REMOVE_LOCK_DBG_BLOCK:name;
+const unique T.MaxLockedTicks__IO_REMOVE_LOCK_DBG_BLOCK:name;
+const unique T.AllocateTag__IO_REMOVE_LOCK_DBG_BLOCK:name;
+const unique T.LockList__IO_REMOVE_LOCK_DBG_BLOCK:name;
+const unique T.Spin__IO_REMOVE_LOCK_DBG_BLOCK:name;
+const unique T.LowMemoryCount__IO_REMOVE_LOCK_DBG_BLOCK:name;
+const unique T.Reserved1__IO_REMOVE_LOCK_DBG_BLOCK:name;
+const unique T.Reserved2__IO_REMOVE_LOCK_DBG_BLOCK:name;
+const unique T.Blocks__IO_REMOVE_LOCK_DBG_BLOCK:name;
+const unique T.Option__IO_RESOURCE_DESCRIPTOR:name;
+const unique T.Type__IO_RESOURCE_DESCRIPTOR:name;
+const unique T.ShareDisposition__IO_RESOURCE_DESCRIPTOR:name;
+const unique T.Spare1__IO_RESOURCE_DESCRIPTOR:name;
+const unique T.Flags__IO_RESOURCE_DESCRIPTOR:name;
+const unique T.Spare2__IO_RESOURCE_DESCRIPTOR:name;
+const unique T.u__IO_RESOURCE_DESCRIPTOR:name;
+const unique T.Version__IO_RESOURCE_LIST:name;
+const unique T.Revision__IO_RESOURCE_LIST:name;
+const unique T.Count__IO_RESOURCE_LIST:name;
+const unique T.Descriptors__IO_RESOURCE_LIST:name;
+const unique T.ListSize__IO_RESOURCE_REQUIREMENTS_LIST:name;
+const unique T.InterfaceType__IO_RESOURCE_REQUIREMENTS_LIST:name;
+const unique T.BusNumber__IO_RESOURCE_REQUIREMENTS_LIST:name;
+const unique T.SlotNumber__IO_RESOURCE_REQUIREMENTS_LIST:name;
+const unique T.Reserved__IO_RESOURCE_REQUIREMENTS_LIST:name;
+const unique T.AlternativeLists__IO_RESOURCE_REQUIREMENTS_LIST:name;
+const unique T.List__IO_RESOURCE_REQUIREMENTS_LIST:name;
+const unique T.SecurityQos__IO_SECURITY_CONTEXT:name;
+const unique T.AccessState__IO_SECURITY_CONTEXT:name;
+const unique T.DesiredAccess__IO_SECURITY_CONTEXT:name;
+const unique T.FullCreateOptions__IO_SECURITY_CONTEXT:name;
+const unique T.MajorFunction__IO_STACK_LOCATION:name;
+const unique T.MinorFunction__IO_STACK_LOCATION:name;
+const unique T.Flags__IO_STACK_LOCATION:name;
+const unique T.Control__IO_STACK_LOCATION:name;
+const unique T.Parameters__IO_STACK_LOCATION:name;
+const unique T.DeviceObject__IO_STACK_LOCATION:name;
+const unique T.FileObject__IO_STACK_LOCATION:name;
+const unique T.CompletionRoutine__IO_STACK_LOCATION:name;
+const unique T.Context__IO_STACK_LOCATION:name;
+const unique T.__unnamed_4_d99b6e2b__IO_STATUS_BLOCK:name;
+const unique T.Information__IO_STATUS_BLOCK:name;
+const unique T.Type__IRP:name;
+const unique T.Size__IRP:name;
+const unique T.MdlAddress__IRP:name;
+const unique T.Flags__IRP:name;
+const unique T.AssociatedIrp__IRP:name;
+const unique T.ThreadListEntry__IRP:name;
+const unique T.IoStatus__IRP:name;
+const unique T.RequestorMode__IRP:name;
+const unique T.PendingReturned__IRP:name;
+const unique T.StackCount__IRP:name;
+const unique T.CurrentLocation__IRP:name;
+const unique T.Cancel__IRP:name;
+const unique T.CancelIrql__IRP:name;
+const unique T.ApcEnvironment__IRP:name;
+const unique T.AllocationFlags__IRP:name;
+const unique T.UserIosb__IRP:name;
+const unique T.UserEvent__IRP:name;
+const unique T.Overlay__IRP:name;
+const unique T.CancelRoutine__IRP:name;
+const unique T.UserBuffer__IRP:name;
+const unique T.Tail__IRP:name;
+const unique T.Type__KAPC:name;
+const unique T.SpareByte0__KAPC:name;
+const unique T.Size__KAPC:name;
+const unique T.SpareByte1__KAPC:name;
+const unique T.SpareLong0__KAPC:name;
+const unique T.Thread__KAPC:name;
+const unique T.ApcListEntry__KAPC:name;
+const unique T.KernelRoutine__KAPC:name;
+const unique T.RundownRoutine__KAPC:name;
+const unique T.NormalRoutine__KAPC:name;
+const unique T.NormalContext__KAPC:name;
+const unique T.SystemArgument1__KAPC:name;
+const unique T.SystemArgument2__KAPC:name;
+const unique T.ApcStateIndex__KAPC:name;
+const unique T.ApcMode__KAPC:name;
+const unique T.Inserted__KAPC:name;
+const unique T.Type__KDEVICE_QUEUE:name;
+const unique T.Size__KDEVICE_QUEUE:name;
+const unique T.DeviceListHead__KDEVICE_QUEUE:name;
+const unique T.Lock__KDEVICE_QUEUE:name;
+const unique T.Busy__KDEVICE_QUEUE:name;
+const unique T.DeviceListEntry__KDEVICE_QUEUE_ENTRY:name;
+const unique T.SortKey__KDEVICE_QUEUE_ENTRY:name;
+const unique T.Inserted__KDEVICE_QUEUE_ENTRY:name;
+const unique T.Type__KDPC:name;
+const unique T.Importance__KDPC:name;
+const unique T.Number__KDPC:name;
+const unique T.DpcListEntry__KDPC:name;
+const unique T.DeferredRoutine__KDPC:name;
+const unique T.DeferredContext__KDPC:name;
+const unique T.SystemArgument1__KDPC:name;
+const unique T.SystemArgument2__KDPC:name;
+const unique T.DpcData__KDPC:name;
+const unique T.Header__KEVENT:name;
+const unique T.KeyboardIdentifier__KEYBOARD_ATTRIBUTES:name;
+const unique T.KeyboardMode__KEYBOARD_ATTRIBUTES:name;
+const unique T.NumberOfFunctionKeys__KEYBOARD_ATTRIBUTES:name;
+const unique T.NumberOfIndicators__KEYBOARD_ATTRIBUTES:name;
+const unique T.NumberOfKeysTotal__KEYBOARD_ATTRIBUTES:name;
+const unique T.InputDataQueueLength__KEYBOARD_ATTRIBUTES:name;
+const unique T.KeyRepeatMinimum__KEYBOARD_ATTRIBUTES:name;
+const unique T.KeyRepeatMaximum__KEYBOARD_ATTRIBUTES:name;
+const unique T.Type__KEYBOARD_ID:name;
+const unique T.Subtype__KEYBOARD_ID:name;
+const unique T.UnitId__KEYBOARD_INDICATOR_PARAMETERS:name;
+const unique T.LedFlags__KEYBOARD_INDICATOR_PARAMETERS:name;
+const unique T.UnitId__KEYBOARD_INPUT_DATA:name;
+const unique T.MakeCode__KEYBOARD_INPUT_DATA:name;
+const unique T.Flags__KEYBOARD_INPUT_DATA:name;
+const unique T.Reserved__KEYBOARD_INPUT_DATA:name;
+const unique T.ExtraInformation__KEYBOARD_INPUT_DATA:name;
+const unique T.UnitId__KEYBOARD_TYPEMATIC_PARAMETERS:name;
+const unique T.Rate__KEYBOARD_TYPEMATIC_PARAMETERS:name;
+const unique T.Delay__KEYBOARD_TYPEMATIC_PARAMETERS:name;
+const unique T.Header__KSEMAPHORE:name;
+const unique T.Limit__KSEMAPHORE:name;
+const unique T.__unnamed_8_58ee4a31__LARGE_INTEGER:name;
+const unique T.u__LARGE_INTEGER:name;
+const unique T.QuadPart__LARGE_INTEGER:name;
+const unique T.Flink__LIST_ENTRY:name;
+const unique T.Blink__LIST_ENTRY:name;
+const unique T.LowPart__LUID:name;
+const unique T.HighPart__LUID:name;
+const unique T.Luid__LUID_AND_ATTRIBUTES:name;
+const unique T.Attributes__LUID_AND_ATTRIBUTES:name;
+const unique T.Next__MDL:name;
+const unique T.Size__MDL:name;
+const unique T.MdlFlags__MDL:name;
+const unique T.Process__MDL:name;
+const unique T.MappedSystemVa__MDL:name;
+const unique T.StartVa__MDL:name;
+const unique T.ByteCount__MDL:name;
+const unique T.ByteOffset__MDL:name;
+const unique T.OwnerThread__OWNER_ENTRY:name;
+const unique T.__unnamed_4_6f9ac8e1__OWNER_ENTRY:name;
+const unique T.File__PORT:name;
+const unique T.Port__PORT:name;
+const unique T.Enabled__PORT:name;
+const unique T.Reserved__PORT:name;
+const unique T.Free__PORT:name;
+const unique T.SequenceD1__POWER_SEQUENCE:name;
+const unique T.SequenceD2__POWER_SEQUENCE:name;
+const unique T.SequenceD3__POWER_SEQUENCE:name;
+const unique T.SystemState__POWER_STATE:name;
+const unique T.DeviceState__POWER_STATE:name;
+const unique T.PrivilegeCount__PRIVILEGE_SET:name;
+const unique T.Control__PRIVILEGE_SET:name;
+const unique T.Privilege__PRIVILEGE_SET:name;
+const unique T.DataSectionObject__SECTION_OBJECT_POINTERS:name;
+const unique T.SharedCacheMap__SECTION_OBJECT_POINTERS:name;
+const unique T.ImageSectionObject__SECTION_OBJECT_POINTERS:name;
+const unique T.Length__SECURITY_QUALITY_OF_SERVICE:name;
+const unique T.ImpersonationLevel__SECURITY_QUALITY_OF_SERVICE:name;
+const unique T.ContextTrackingMode__SECURITY_QUALITY_OF_SERVICE:name;
+const unique T.EffectiveOnly__SECURITY_QUALITY_OF_SERVICE:name;
+const unique T.ClientToken__SECURITY_SUBJECT_CONTEXT:name;
+const unique T.ImpersonationLevel__SECURITY_SUBJECT_CONTEXT:name;
+const unique T.PrimaryToken__SECURITY_SUBJECT_CONTEXT:name;
+const unique T.ProcessAuditId__SECURITY_SUBJECT_CONTEXT:name;
+const unique T.__unnamed_4_3a2fdc5e__SYSTEM_POWER_STATE_CONTEXT:name;
+const unique T.Length__UNICODE_STRING:name;
+const unique T.MaximumLength__UNICODE_STRING:name;
+const unique T.Buffer__UNICODE_STRING:name;
+const unique T.Type__VPB:name;
+const unique T.Size__VPB:name;
+const unique T.Flags__VPB:name;
+const unique T.VolumeLabelLength__VPB:name;
+const unique T.DeviceObject__VPB:name;
+const unique T.RealDevice__VPB:name;
+const unique T.SerialNumber__VPB:name;
+const unique T.ReferenceCount__VPB:name;
+const unique T.VolumeLabel__VPB:name;
+const unique T.WaitQueueEntry__WAIT_CONTEXT_BLOCK:name;
+const unique T.DeviceRoutine__WAIT_CONTEXT_BLOCK:name;
+const unique T.DeviceContext__WAIT_CONTEXT_BLOCK:name;
+const unique T.NumberOfMapRegisters__WAIT_CONTEXT_BLOCK:name;
+const unique T.DeviceObject__WAIT_CONTEXT_BLOCK:name;
+const unique T.CurrentIrp__WAIT_CONTEXT_BLOCK:name;
+const unique T.BufferChainingDpc__WAIT_CONTEXT_BLOCK:name;
+const unique T.GuidCount__WMILIB_CONTEXT:name;
+const unique T.GuidList__WMILIB_CONTEXT:name;
+const unique T.QueryWmiRegInfo__WMILIB_CONTEXT:name;
+const unique T.QueryWmiDataBlock__WMILIB_CONTEXT:name;
+const unique T.SetWmiDataBlock__WMILIB_CONTEXT:name;
+const unique T.SetWmiDataItem__WMILIB_CONTEXT:name;
+const unique T.ExecuteWmiMethod__WMILIB_CONTEXT:name;
+const unique T.WmiFunctionControl__WMILIB_CONTEXT:name;
+const unique T.Reserved___unnamed_12_0d6a30de:name;
+const unique T.MessageCount___unnamed_12_0d6a30de:name;
+const unique T.Vector___unnamed_12_0d6a30de:name;
+const unique T.Affinity___unnamed_12_0d6a30de:name;
+const unique T.Start___unnamed_12_17f5c211:name;
+const unique T.Length48___unnamed_12_17f5c211:name;
+const unique T.Start___unnamed_12_1fb42e39:name;
+const unique T.Length___unnamed_12_1fb42e39:name;
+const unique T.Reserved___unnamed_12_1fb42e39:name;
+const unique T.Start___unnamed_12_2a1563c6:name;
+const unique T.Length___unnamed_12_2a1563c6:name;
+const unique T.DataSize___unnamed_12_31347272:name;
+const unique T.Reserved1___unnamed_12_31347272:name;
+const unique T.Reserved2___unnamed_12_31347272:name;
+const unique T.Raw___unnamed_12_429aadc0:name;
+const unique T.Translated___unnamed_12_429aadc0:name;
+const unique T.Start___unnamed_12_4719de1a:name;
+const unique T.Length___unnamed_12_4719de1a:name;
+const unique T.Data___unnamed_12_4be56faa:name;
+const unique T.Data___unnamed_12_5ce25b92:name;
+const unique T.Generic___unnamed_12_7a698b72:name;
+const unique T.Port___unnamed_12_7a698b72:name;
+const unique T.Interrupt___unnamed_12_7a698b72:name;
+const unique T.MessageInterrupt___unnamed_12_7a698b72:name;
+const unique T.Memory___unnamed_12_7a698b72:name;
+const unique T.Dma___unnamed_12_7a698b72:name;
+const unique T.DevicePrivate___unnamed_12_7a698b72:name;
+const unique T.BusNumber___unnamed_12_7a698b72:name;
+const unique T.DeviceSpecificData___unnamed_12_7a698b72:name;
+const unique T.Memory40___unnamed_12_7a698b72:name;
+const unique T.Memory48___unnamed_12_7a698b72:name;
+const unique T.Memory64___unnamed_12_7a698b72:name;
+const unique T.Start___unnamed_12_87c0de8d:name;
+const unique T.Length64___unnamed_12_87c0de8d:name;
+const unique T.Start___unnamed_12_98bfc55a:name;
+const unique T.Length40___unnamed_12_98bfc55a:name;
+const unique T.Priority___unnamed_12_ab1bd9d7:name;
+const unique T.Reserved1___unnamed_12_ab1bd9d7:name;
+const unique T.Reserved2___unnamed_12_ab1bd9d7:name;
+const unique T.Level___unnamed_12_b0429be9:name;
+const unique T.Vector___unnamed_12_b0429be9:name;
+const unique T.Affinity___unnamed_12_b0429be9:name;
+const unique T.ListEntry___unnamed_12_b43e8de8:name;
+const unique T.__unnamed_4_f19b65c1___unnamed_12_b43e8de8:name;
+const unique T.Level___unnamed_12_bfdb39ee:name;
+const unique T.Vector___unnamed_12_bfdb39ee:name;
+const unique T.Affinity___unnamed_12_bfdb39ee:name;
+const unique T.Start___unnamed_12_cd42b3c3:name;
+const unique T.Length___unnamed_12_cd42b3c3:name;
+const unique T.__unnamed_12_429aadc0___unnamed_12_e668effc:name;
+const unique T.Channel___unnamed_12_e80d029e:name;
+const unique T.Port___unnamed_12_e80d029e:name;
+const unique T.Reserved1___unnamed_12_e80d029e:name;
+const unique T.Length___unnamed_16_07c0bcc5:name;
+const unique T.MinBusNumber___unnamed_16_07c0bcc5:name;
+const unique T.MaxBusNumber___unnamed_16_07c0bcc5:name;
+const unique T.Reserved___unnamed_16_07c0bcc5:name;
+const unique T.InterfaceType___unnamed_16_29cb9f2f:name;
+const unique T.Size___unnamed_16_29cb9f2f:name;
+const unique T.Version___unnamed_16_29cb9f2f:name;
+const unique T.Interface___unnamed_16_29cb9f2f:name;
+const unique T.InterfaceSpecificData___unnamed_16_29cb9f2f:name;
+const unique T.SecurityContext___unnamed_16_30f11dbf:name;
+const unique T.Options___unnamed_16_30f11dbf:name;
+const unique T.FileAttributes___unnamed_16_30f11dbf:name;
+const unique T.ShareAccess___unnamed_16_30f11dbf:name;
+const unique T.EaLength___unnamed_16_30f11dbf:name;
+const unique T.DriverContext___unnamed_16_35034f68:name;
+const unique T.Length___unnamed_16_487a9498:name;
+const unique T.FileName___unnamed_16_487a9498:name;
+const unique T.FileInformationClass___unnamed_16_487a9498:name;
+const unique T.FileIndex___unnamed_16_487a9498:name;
+const unique T.OutputBufferLength___unnamed_16_5f6a8844:name;
+const unique T.InputBufferLength___unnamed_16_5f6a8844:name;
+const unique T.FsControlCode___unnamed_16_5f6a8844:name;
+const unique T.Type3InputBuffer___unnamed_16_5f6a8844:name;
+const unique T.Length___unnamed_16_7177b9f3:name;
+const unique T.FileInformationClass___unnamed_16_7177b9f3:name;
+const unique T.FileObject___unnamed_16_7177b9f3:name;
+const unique T.__unnamed_4_43913aa5___unnamed_16_7177b9f3:name;
+const unique T.Length___unnamed_16_88e91ef6:name;
+const unique T.Key___unnamed_16_88e91ef6:name;
+const unique T.ByteOffset___unnamed_16_88e91ef6:name;
+const unique T.Length___unnamed_16_8c506c98:name;
+const unique T.Key___unnamed_16_8c506c98:name;
+const unique T.ByteOffset___unnamed_16_8c506c98:name;
+const unique T.WhichSpace___unnamed_16_9ac2e5f8:name;
+const unique T.Buffer___unnamed_16_9ac2e5f8:name;
+const unique T.Offset___unnamed_16_9ac2e5f8:name;
+const unique T.Length___unnamed_16_9ac2e5f8:name;
+const unique T.Create___unnamed_16_b93842ad:name;
+const unique T.Read___unnamed_16_b93842ad:name;
+const unique T.Write___unnamed_16_b93842ad:name;
+const unique T.QueryDirectory___unnamed_16_b93842ad:name;
+const unique T.NotifyDirectory___unnamed_16_b93842ad:name;
+const unique T.QueryFile___unnamed_16_b93842ad:name;
+const unique T.SetFile___unnamed_16_b93842ad:name;
+const unique T.QueryEa___unnamed_16_b93842ad:name;
+const unique T.SetEa___unnamed_16_b93842ad:name;
+const unique T.QueryVolume___unnamed_16_b93842ad:name;
+const unique T.SetVolume___unnamed_16_b93842ad:name;
+const unique T.FileSystemControl___unnamed_16_b93842ad:name;
+const unique T.LockControl___unnamed_16_b93842ad:name;
+const unique T.DeviceIoControl___unnamed_16_b93842ad:name;
+const unique T.QuerySecurity___unnamed_16_b93842ad:name;
+const unique T.SetSecurity___unnamed_16_b93842ad:name;
+const unique T.MountVolume___unnamed_16_b93842ad:name;
+const unique T.VerifyVolume___unnamed_16_b93842ad:name;
+const unique T.Scsi___unnamed_16_b93842ad:name;
+const unique T.QueryQuota___unnamed_16_b93842ad:name;
+const unique T.SetQuota___unnamed_16_b93842ad:name;
+const unique T.QueryDeviceRelations___unnamed_16_b93842ad:name;
+const unique T.QueryInterface___unnamed_16_b93842ad:name;
+const unique T.DeviceCapabilities___unnamed_16_b93842ad:name;
+const unique T.FilterResourceRequirements___unnamed_16_b93842ad:name;
+const unique T.ReadWriteConfig___unnamed_16_b93842ad:name;
+const unique T.SetLock___unnamed_16_b93842ad:name;
+const unique T.QueryId___unnamed_16_b93842ad:name;
+const unique T.QueryDeviceText___unnamed_16_b93842ad:name;
+const unique T.UsageNotification___unnamed_16_b93842ad:name;
+const unique T.WaitWake___unnamed_16_b93842ad:name;
+const unique T.PowerSequence___unnamed_16_b93842ad:name;
+const unique T.Power___unnamed_16_b93842ad:name;
+const unique T.StartDevice___unnamed_16_b93842ad:name;
+const unique T.WMI___unnamed_16_b93842ad:name;
+const unique T.Others___unnamed_16_b93842ad:name;
+const unique T.Length___unnamed_16_b9c62eab:name;
+const unique T.Key___unnamed_16_b9c62eab:name;
+const unique T.ByteOffset___unnamed_16_b9c62eab:name;
+const unique T.__unnamed_4_7d9d0c7e___unnamed_16_bb584060:name;
+const unique T.Type___unnamed_16_bb584060:name;
+const unique T.State___unnamed_16_bb584060:name;
+const unique T.ShutdownType___unnamed_16_bb584060:name;
+const unique T.OutputBufferLength___unnamed_16_dba55c7c:name;
+const unique T.InputBufferLength___unnamed_16_dba55c7c:name;
+const unique T.IoControlCode___unnamed_16_dba55c7c:name;
+const unique T.Type3InputBuffer___unnamed_16_dba55c7c:name;
+const unique T.DeviceQueueEntry___unnamed_16_e70c268b:name;
+const unique T.__unnamed_16_35034f68___unnamed_16_e70c268b:name;
+const unique T.Argument1___unnamed_16_e734d694:name;
+const unique T.Argument2___unnamed_16_e734d694:name;
+const unique T.Argument3___unnamed_16_e734d694:name;
+const unique T.Argument4___unnamed_16_e734d694:name;
+const unique T.ProviderId___unnamed_16_eac6dbea:name;
+const unique T.DataPath___unnamed_16_eac6dbea:name;
+const unique T.BufferSize___unnamed_16_eac6dbea:name;
+const unique T.Buffer___unnamed_16_eac6dbea:name;
+const unique T.Length___unnamed_16_f6cae4c2:name;
+const unique T.EaList___unnamed_16_f6cae4c2:name;
+const unique T.EaListLength___unnamed_16_f6cae4c2:name;
+const unique T.EaIndex___unnamed_16_f6cae4c2:name;
+const unique T.Length___unnamed_16_fe36e4f4:name;
+const unique T.StartSid___unnamed_16_fe36e4f4:name;
+const unique T.SidList___unnamed_16_fe36e4f4:name;
+const unique T.SidListLength___unnamed_16_fe36e4f4:name;
+const unique T.Abandoned___unnamed_1_29794256:name;
+const unique T.Absolute___unnamed_1_29794256:name;
+const unique T.NpxIrql___unnamed_1_29794256:name;
+const unique T.Signalling___unnamed_1_29794256:name;
+const unique T.Inserted___unnamed_1_2dc63b48:name;
+const unique T.DebugActive___unnamed_1_2dc63b48:name;
+const unique T.DpcActive___unnamed_1_2dc63b48:name;
+const unique T.Size___unnamed_1_2ef8da39:name;
+const unique T.Hand___unnamed_1_2ef8da39:name;
+const unique T.Lock___unnamed_1_faa7dc71:name;
+const unique T.MinimumVector___unnamed_20_f4d2e6d8:name;
+const unique T.MaximumVector___unnamed_20_f4d2e6d8:name;
+const unique T.AffinityPolicy___unnamed_20_f4d2e6d8:name;
+const unique T.PriorityPolicy___unnamed_20_f4d2e6d8:name;
+const unique T.TargetedProcessors___unnamed_20_f4d2e6d8:name;
+const unique T.Length___unnamed_24_41cbc8c0:name;
+const unique T.Alignment___unnamed_24_41cbc8c0:name;
+const unique T.MinimumAddress___unnamed_24_41cbc8c0:name;
+const unique T.MaximumAddress___unnamed_24_41cbc8c0:name;
+const unique T.Length48___unnamed_24_5419c914:name;
+const unique T.Alignment48___unnamed_24_5419c914:name;
+const unique T.MinimumAddress___unnamed_24_5419c914:name;
+const unique T.MaximumAddress___unnamed_24_5419c914:name;
+const unique T.Length___unnamed_24_67a5ff10:name;
+const unique T.Alignment___unnamed_24_67a5ff10:name;
+const unique T.MinimumAddress___unnamed_24_67a5ff10:name;
+const unique T.MaximumAddress___unnamed_24_67a5ff10:name;
+const unique T.Port___unnamed_24_72c3976e:name;
+const unique T.Memory___unnamed_24_72c3976e:name;
+const unique T.Interrupt___unnamed_24_72c3976e:name;
+const unique T.Dma___unnamed_24_72c3976e:name;
+const unique T.Generic___unnamed_24_72c3976e:name;
+const unique T.DevicePrivate___unnamed_24_72c3976e:name;
+const unique T.BusNumber___unnamed_24_72c3976e:name;
+const unique T.ConfigData___unnamed_24_72c3976e:name;
+const unique T.Memory40___unnamed_24_72c3976e:name;
+const unique T.Memory48___unnamed_24_72c3976e:name;
+const unique T.Memory64___unnamed_24_72c3976e:name;
+const unique T.Length64___unnamed_24_a26050bb:name;
+const unique T.Alignment64___unnamed_24_a26050bb:name;
+const unique T.MinimumAddress___unnamed_24_a26050bb:name;
+const unique T.MaximumAddress___unnamed_24_a26050bb:name;
+const unique T.Length___unnamed_24_b8f476db:name;
+const unique T.Alignment___unnamed_24_b8f476db:name;
+const unique T.MinimumAddress___unnamed_24_b8f476db:name;
+const unique T.MaximumAddress___unnamed_24_b8f476db:name;
+const unique T.Length40___unnamed_24_d09044b4:name;
+const unique T.Alignment40___unnamed_24_d09044b4:name;
+const unique T.MinimumAddress___unnamed_24_d09044b4:name;
+const unique T.MaximumAddress___unnamed_24_d09044b4:name;
+const unique T.ReplaceIfExists___unnamed_2_46cc4597:name;
+const unique T.AdvanceOnly___unnamed_2_46cc4597:name;
+const unique T.__unnamed_16_e70c268b___unnamed_40_7218f704:name;
+const unique T.Thread___unnamed_40_7218f704:name;
+const unique T.AuxiliaryBuffer___unnamed_40_7218f704:name;
+const unique T.__unnamed_12_b43e8de8___unnamed_40_7218f704:name;
+const unique T.OriginalFileObject___unnamed_40_7218f704:name;
+const unique T.ListEntry___unnamed_40_c55c9377:name;
+const unique T.Wcb___unnamed_40_c55c9377:name;
+const unique T.InitialPrivilegeSet___unnamed_44_5584090d:name;
+const unique T.PrivilegeSet___unnamed_44_5584090d:name;
+const unique T.Overlay___unnamed_48_cf99b13f:name;
+const unique T.Apc___unnamed_48_cf99b13f:name;
+const unique T.CompletionKey___unnamed_48_cf99b13f:name;
+const unique T.PowerState___unnamed_4_069846fb:name;
+const unique T.IdType___unnamed_4_224c32f4:name;
+const unique T.Capabilities___unnamed_4_2de698da:name;
+const unique T.__unnamed_4_c3479730___unnamed_4_3a2fdc5e:name;
+const unique T.ContextAsUlong___unnamed_4_3a2fdc5e:name;
+const unique T.Length___unnamed_4_3a4c1a13:name;
+const unique T.__unnamed_2_46cc4597___unnamed_4_43913aa5:name;
+const unique T.ClusterCount___unnamed_4_43913aa5:name;
+const unique T.DeleteHandle___unnamed_4_43913aa5:name;
+const unique T.UserApcRoutine___unnamed_4_4e8dd2ba:name;
+const unique T.IssuingProcess___unnamed_4_4e8dd2ba:name;
+const unique T.Srb___unnamed_4_52603077:name;
+const unique T.Address___unnamed_4_52c594f7:name;
+const unique T.CreatorBackTraceIndex___unnamed_4_52c594f7:name;
+const unique T.Type___unnamed_4_5ca00198:name;
+const unique T.__unnamed_1_29794256___unnamed_4_5ca00198:name;
+const unique T.__unnamed_1_2ef8da39___unnamed_4_5ca00198:name;
+const unique T.__unnamed_1_2dc63b48___unnamed_4_5ca00198:name;
+const unique T.MasterIrp___unnamed_4_6ac6463c:name;
+const unique T.IrpCount___unnamed_4_6ac6463c:name;
+const unique T.SystemBuffer___unnamed_4_6ac6463c:name;
+const unique T.OwnerCount___unnamed_4_6f9ac8e1:name;
+const unique T.TableSize___unnamed_4_6f9ac8e1:name;
+const unique T.PowerSequence___unnamed_4_7a02167b:name;
+const unique T.SystemContext___unnamed_4_7d9d0c7e:name;
+const unique T.SystemPowerStateContext___unnamed_4_7d9d0c7e:name;
+const unique T.IoResourceRequirementList___unnamed_4_82f7a864:name;
+const unique T.Length___unnamed_4_9aec220b:name;
+const unique T.__unnamed_4_5ca00198___unnamed_4_a97c65a1:name;
+const unique T.Lock___unnamed_4_a97c65a1:name;
+const unique T.Reserved1___unnamed_4_c3479730:name;
+const unique T.TargetSystemState___unnamed_4_c3479730:name;
+const unique T.EffectiveSystemState___unnamed_4_c3479730:name;
+const unique T.CurrentSystemState___unnamed_4_c3479730:name;
+const unique T.IgnoreHibernationPath___unnamed_4_c3479730:name;
+const unique T.PseudoTransition___unnamed_4_c3479730:name;
+const unique T.Reserved2___unnamed_4_c3479730:name;
+const unique T.Status___unnamed_4_d99b6e2b:name;
+const unique T.Pointer___unnamed_4_d99b6e2b:name;
+const unique T.CurrentStackLocation___unnamed_4_f19b65c1:name;
+const unique T.PacketType___unnamed_4_f19b65c1:name;
+const unique T.Type___unnamed_4_fa10fc16:name;
+const unique T.SecurityInformation___unnamed_8_01efa60d:name;
+const unique T.Length___unnamed_8_01efa60d:name;
+const unique T.MinimumChannel___unnamed_8_08d4cef8:name;
+const unique T.MaximumChannel___unnamed_8_08d4cef8:name;
+const unique T.__unnamed_4_4e8dd2ba___unnamed_8_0a898c0c:name;
+const unique T.UserApcContext___unnamed_8_0a898c0c:name;
+const unique T.SecurityInformation___unnamed_8_1330f93a:name;
+const unique T.SecurityDescriptor___unnamed_8_1330f93a:name;
+const unique T.AsynchronousParameters___unnamed_8_181d0de9:name;
+const unique T.AllocationSize___unnamed_8_181d0de9:name;
+const unique T.Vpb___unnamed_8_4812764d:name;
+const unique T.DeviceObject___unnamed_8_4812764d:name;
+const unique T.Length___unnamed_8_559a91e6:name;
+const unique T.FsInformationClass___unnamed_8_559a91e6:name;
+const unique T.Length___unnamed_8_5845b309:name;
+const unique T.FileInformationClass___unnamed_8_5845b309:name;
+const unique T.LowPart___unnamed_8_58ee4a31:name;
+const unique T.HighPart___unnamed_8_58ee4a31:name;
+const unique T.AllocatedResources___unnamed_8_61acf4ce:name;
+const unique T.AllocatedResourcesTranslated___unnamed_8_61acf4ce:name;
+const unique T.DeviceTextType___unnamed_8_6acfee04:name;
+const unique T.LocaleId___unnamed_8_6acfee04:name;
+const unique T.Length___unnamed_8_7f26a9dd:name;
+const unique T.CompletionFilter___unnamed_8_7f26a9dd:name;
+const unique T.Vpb___unnamed_8_87add0bd:name;
+const unique T.DeviceObject___unnamed_8_87add0bd:name;
+const unique T.InPath___unnamed_8_b2773e4c:name;
+const unique T.Reserved___unnamed_8_b2773e4c:name;
+const unique T.Type___unnamed_8_b2773e4c:name;
+const unique T.Length___unnamed_8_de890d4e:name;
+const unique T.FsInformationClass___unnamed_8_de890d4e:name;
+const unique T.LowPart___unnamed_8_ef9ba0d3:name;
+const unique T.HighPart___unnamed_8_ef9ba0d3:name;
+
+// Type declarations
+
+const unique T.A1_CM_FULL_RESOURCE_DESCRIPTOR:name;
+const unique T.A1_CM_PARTIAL_RESOURCE_DESCRIPTOR:name;
+const unique T.A1_IO_RESOURCE_DESCRIPTOR:name;
+const unique T.A1_IO_RESOURCE_LIST:name;
+const unique T.A1_LUID_AND_ATTRIBUTES:name;
+const unique T.A256UINT2:name;
+const unique T.A28PFDRIVER_DISPATCH:name;
+const unique T.A2UCHAR:name;
+const unique T.A2UINT2:name;
+const unique T.A32UINT2:name;
+const unique T.A3UCHAR:name;
+const unique T.A3UINT4:name;
+const unique T.A3_LUID_AND_ATTRIBUTES:name;
+const unique T.A4PVOID:name;
+const unique T.A4UINT4:name;
+const unique T.A5UINT2:name;
+const unique T.A5_DEVICE_POWER_STATE:name;
+const unique T.A7_DEVICE_POWER_STATE:name;
+const unique T.A88CHAR:name;
+const unique T.A8UCHAR:name;
+const unique T.A9UINT2:name;
+const unique T.BUS_QUERY_ID_TYPE:name;
+const unique T.CHAR:name;
+const unique T.DEVICE_TEXT_TYPE:name;
+const unique T.F0:name;
+const unique T.F1:name;
+const unique T.F10:name;
+const unique T.F11:name;
+const unique T.F12:name;
+const unique T.F13:name;
+const unique T.F14:name;
+const unique T.F15:name;
+const unique T.F16:name;
+const unique T.F17:name;
+const unique T.F18:name;
+const unique T.F19:name;
+const unique T.F2:name;
+const unique T.F20:name;
+const unique T.F21:name;
+const unique T.F22:name;
+const unique T.F23:name;
+const unique T.F24:name;
+const unique T.F25:name;
+const unique T.F26:name;
+const unique T.F27:name;
+const unique T.F28:name;
+const unique T.F29:name;
+const unique T.F3:name;
+const unique T.F30:name;
+const unique T.F31:name;
+const unique T.F32:name;
+const unique T.F33:name;
+const unique T.F34:name;
+const unique T.F35:name;
+const unique T.F36:name;
+const unique T.F37:name;
+const unique T.F38:name;
+const unique T.F4:name;
+const unique T.F5:name;
+const unique T.F6:name;
+const unique T.F7:name;
+const unique T.F8:name;
+const unique T.F9:name;
+const unique T.FDRIVER_ADD_DEVICE:name;
+const unique T.FDRIVER_CANCEL:name;
+const unique T.FDRIVER_CONTROL:name;
+const unique T.FDRIVER_DISPATCH:name;
+const unique T.FDRIVER_INITIALIZE:name;
+const unique T.FDRIVER_STARTIO:name;
+const unique T.FDRIVER_UNLOAD:name;
+const unique T.FFAST_IO_ACQUIRE_FILE:name;
+const unique T.FFAST_IO_ACQUIRE_FOR_CCFLUSH:name;
+const unique T.FFAST_IO_ACQUIRE_FOR_MOD_WRITE:name;
+const unique T.FFAST_IO_CHECK_IF_POSSIBLE:name;
+const unique T.FFAST_IO_DETACH_DEVICE:name;
+const unique T.FFAST_IO_DEVICE_CONTROL:name;
+const unique T.FFAST_IO_LOCK:name;
+const unique T.FFAST_IO_MDL_READ:name;
+const unique T.FFAST_IO_MDL_READ_COMPLETE:name;
+const unique T.FFAST_IO_MDL_READ_COMPLETE_COMPRESSED:name;
+const unique T.FFAST_IO_MDL_WRITE_COMPLETE:name;
+const unique T.FFAST_IO_MDL_WRITE_COMPLETE_COMPRESSED:name;
+const unique T.FFAST_IO_PREPARE_MDL_WRITE:name;
+const unique T.FFAST_IO_QUERY_BASIC_INFO:name;
+const unique T.FFAST_IO_QUERY_NETWORK_OPEN_INFO:name;
+const unique T.FFAST_IO_QUERY_OPEN:name;
+const unique T.FFAST_IO_QUERY_STANDARD_INFO:name;
+const unique T.FFAST_IO_READ:name;
+const unique T.FFAST_IO_READ_COMPRESSED:name;
+const unique T.FFAST_IO_RELEASE_FILE:name;
+const unique T.FFAST_IO_RELEASE_FOR_CCFLUSH:name;
+const unique T.FFAST_IO_RELEASE_FOR_MOD_WRITE:name;
+const unique T.FFAST_IO_UNLOCK_ALL:name;
+const unique T.FFAST_IO_UNLOCK_ALL_BY_KEY:name;
+const unique T.FFAST_IO_UNLOCK_SINGLE:name;
+const unique T.FFAST_IO_WRITE:name;
+const unique T.FFAST_IO_WRITE_COMPRESSED:name;
+const unique T.FIO_COMPLETION_ROUTINE:name;
+const unique T.FKDEFERRED_ROUTINE:name;
+const unique T.INT2:name;
+const unique T.INT4:name;
+const unique T.INT8:name;
+const unique T.PA256UINT2:name;
+const unique T.PA2UINT2:name;
+const unique T.PA4UINT4:name;
+const unique T.PA5UINT2:name;
+const unique T.PA88CHAR:name;
+const unique T.PA9UINT2:name;
+const unique T.PCHAR:name;
+const unique T.PF19:name;
+const unique T.PF21:name;
+const unique T.PF23:name;
+const unique T.PF24:name;
+const unique T.PF25:name;
+const unique T.PF33:name;
+const unique T.PF34:name;
+const unique T.PF35:name;
+const unique T.PF36:name;
+const unique T.PF37:name;
+const unique T.PF38:name;
+const unique T.PFDRIVER_ADD_DEVICE:name;
+const unique T.PFDRIVER_CANCEL:name;
+const unique T.PFDRIVER_CONTROL:name;
+const unique T.PFDRIVER_DISPATCH:name;
+const unique T.PFDRIVER_INITIALIZE:name;
+const unique T.PFDRIVER_STARTIO:name;
+const unique T.PFDRIVER_UNLOAD:name;
+const unique T.PFFAST_IO_ACQUIRE_FILE:name;
+const unique T.PFFAST_IO_ACQUIRE_FOR_CCFLUSH:name;
+const unique T.PFFAST_IO_ACQUIRE_FOR_MOD_WRITE:name;
+const unique T.PFFAST_IO_CHECK_IF_POSSIBLE:name;
+const unique T.PFFAST_IO_DETACH_DEVICE:name;
+const unique T.PFFAST_IO_DEVICE_CONTROL:name;
+const unique T.PFFAST_IO_LOCK:name;
+const unique T.PFFAST_IO_MDL_READ:name;
+const unique T.PFFAST_IO_MDL_READ_COMPLETE:name;
+const unique T.PFFAST_IO_MDL_READ_COMPLETE_COMPRESSED:name;
+const unique T.PFFAST_IO_MDL_WRITE_COMPLETE:name;
+const unique T.PFFAST_IO_MDL_WRITE_COMPLETE_COMPRESSED:name;
+const unique T.PFFAST_IO_PREPARE_MDL_WRITE:name;
+const unique T.PFFAST_IO_QUERY_BASIC_INFO:name;
+const unique T.PFFAST_IO_QUERY_NETWORK_OPEN_INFO:name;
+const unique T.PFFAST_IO_QUERY_OPEN:name;
+const unique T.PFFAST_IO_QUERY_STANDARD_INFO:name;
+const unique T.PFFAST_IO_READ:name;
+const unique T.PFFAST_IO_READ_COMPRESSED:name;
+const unique T.PFFAST_IO_RELEASE_FILE:name;
+const unique T.PFFAST_IO_RELEASE_FOR_CCFLUSH:name;
+const unique T.PFFAST_IO_RELEASE_FOR_MOD_WRITE:name;
+const unique T.PFFAST_IO_UNLOCK_ALL:name;
+const unique T.PFFAST_IO_UNLOCK_ALL_BY_KEY:name;
+const unique T.PFFAST_IO_UNLOCK_SINGLE:name;
+const unique T.PFFAST_IO_WRITE:name;
+const unique T.PFFAST_IO_WRITE_COMPRESSED:name;
+const unique T.PFIO_COMPLETION_ROUTINE:name;
+const unique T.PFKDEFERRED_ROUTINE:name;
+const unique T.PINT4:name;
+const unique T.POWER_ACTION:name;
+const unique T.PPCHAR:name;
+const unique T.PPF24:name;
+const unique T.PPPUINT2:name;
+const unique T.PPP_DEVICE_OBJECT:name;
+const unique T.PPP_FILE_OBJECT:name;
+const unique T.PPUINT2:name;
+const unique T.PPUINT4:name;
+const unique T.PPVOID:name;
+const unique T.PP_DEVICE_EXTENSION:name;
+const unique T.PP_DEVICE_OBJECT:name;
+const unique T.PP_DRIVER_OBJECT:name;
+const unique T.PP_ERESOURCE:name;
+const unique T.PP_FAST_MUTEX:name;
+const unique T.PP_FILE_OBJECT:name;
+const unique T.PP_LIST_ENTRY:name;
+const unique T.PP_MDL:name;
+const unique T.PP_PORT:name;
+const unique T.PP_UNICODE_STRING:name;
+const unique T.PUCHAR:name;
+const unique T.PUINT2:name;
+const unique T.PUINT4:name;
+const unique T.PVOID:name;
+const unique T.PWMIGUIDREGINFO:name;
+const unique T.P_ACCESS_STATE:name;
+const unique T.P_CM_RESOURCE_LIST:name;
+const unique T.P_COMPRESSED_DATA_INFO:name;
+const unique T.P_DEVICE_CAPABILITIES:name;
+const unique T.P_DEVICE_EXTENSION:name;
+const unique T.P_DEVICE_OBJECT:name;
+const unique T.P_DEVOBJ_EXTENSION:name;
+const unique T.P_DRIVER_EXTENSION:name;
+const unique T.P_DRIVER_OBJECT:name;
+const unique T.P_EPROCESS:name;
+const unique T.P_ERESOURCE:name;
+const unique T.P_ETHREAD:name;
+const unique T.P_FAST_IO_DISPATCH:name;
+const unique T.P_FAST_MUTEX:name;
+const unique T.P_FILE_BASIC_INFORMATION:name;
+const unique T.P_FILE_GET_QUOTA_INFORMATION:name;
+const unique T.P_FILE_NETWORK_OPEN_INFORMATION:name;
+const unique T.P_FILE_OBJECT:name;
+const unique T.P_FILE_STANDARD_INFORMATION:name;
+const unique T.P_GLOBALS:name;
+const unique T.P_GUID:name;
+const unique T.P_INTERFACE:name;
+const unique T.P_IO_COMPLETION_CONTEXT:name;
+const unique T.P_IO_REMOVE_LOCK_TRACKING_BLOCK:name;
+const unique T.P_IO_RESOURCE_REQUIREMENTS_LIST:name;
+const unique T.P_IO_SECURITY_CONTEXT:name;
+const unique T.P_IO_STACK_LOCATION:name;
+const unique T.P_IO_STATUS_BLOCK:name;
+const unique T.P_IO_TIMER:name;
+const unique T.P_IRP:name;
+const unique T.P_KAPC:name;
+const unique T.P_KDPC:name;
+const unique T.P_KEVENT:name;
+const unique T.P_KEYBOARD_INPUT_DATA:name;
+const unique T.P_KSEMAPHORE:name;
+const unique T.P_KTHREAD:name;
+const unique T.P_LARGE_INTEGER:name;
+const unique T.P_LIST_ENTRY:name;
+const unique T.P_MDL:name;
+const unique T.P_OWNER_ENTRY:name;
+const unique T.P_POOL_TYPE:name;
+const unique T.P_PORT:name;
+const unique T.P_POWER_SEQUENCE:name;
+const unique T.P_SCSI_REQUEST_BLOCK:name;
+const unique T.P_SECTION_OBJECT_POINTERS:name;
+const unique T.P_SECURITY_QUALITY_OF_SERVICE:name;
+const unique T.P_UNICODE_STRING:name;
+const unique T.P_VPB:name;
+const unique T.UCHAR:name;
+const unique T.UINT2:name;
+const unique T.UINT4:name;
+const unique T.VOID:name;
+const unique T.WMIENABLEDISABLECONTROL:name;
+const unique T.WMIGUIDREGINFO:name;
+const unique T._ACCESS_STATE:name;
+const unique T._CM_FULL_RESOURCE_DESCRIPTOR:name;
+const unique T._CM_PARTIAL_RESOURCE_DESCRIPTOR:name;
+const unique T._CM_PARTIAL_RESOURCE_LIST:name;
+const unique T._CM_RESOURCE_LIST:name;
+const unique T._COMPRESSED_DATA_INFO:name;
+const unique T._DEVICE_CAPABILITIES:name;
+const unique T._DEVICE_EXTENSION:name;
+const unique T._DEVICE_OBJECT:name;
+const unique T._DEVICE_POWER_STATE:name;
+const unique T._DEVICE_RELATION_TYPE:name;
+const unique T._DEVICE_USAGE_NOTIFICATION_TYPE:name;
+const unique T._DEVOBJ_EXTENSION:name;
+const unique T._DISPATCHER_HEADER:name;
+const unique T._DRIVER_EXTENSION:name;
+const unique T._DRIVER_OBJECT:name;
+const unique T._EPROCESS:name;
+const unique T._ERESOURCE:name;
+const unique T._ETHREAD:name;
+const unique T._FAST_IO_DISPATCH:name;
+const unique T._FAST_MUTEX:name;
+const unique T._FILE_BASIC_INFORMATION:name;
+const unique T._FILE_GET_QUOTA_INFORMATION:name;
+const unique T._FILE_INFORMATION_CLASS:name;
+const unique T._FILE_NETWORK_OPEN_INFORMATION:name;
+const unique T._FILE_OBJECT:name;
+const unique T._FILE_STANDARD_INFORMATION:name;
+const unique T._FSINFOCLASS:name;
+const unique T._GLOBALS:name;
+const unique T._GUID:name;
+const unique T._INITIAL_PRIVILEGE_SET:name;
+const unique T._INTERFACE:name;
+const unique T._INTERFACE_TYPE:name;
+const unique T._IO_ALLOCATION_ACTION:name;
+const unique T._IO_COMPLETION_CONTEXT:name;
+const unique T._IO_REMOVE_LOCK:name;
+const unique T._IO_REMOVE_LOCK_COMMON_BLOCK:name;
+const unique T._IO_REMOVE_LOCK_DBG_BLOCK:name;
+const unique T._IO_REMOVE_LOCK_TRACKING_BLOCK:name;
+const unique T._IO_RESOURCE_DESCRIPTOR:name;
+const unique T._IO_RESOURCE_LIST:name;
+const unique T._IO_RESOURCE_REQUIREMENTS_LIST:name;
+const unique T._IO_SECURITY_CONTEXT:name;
+const unique T._IO_STACK_LOCATION:name;
+const unique T._IO_STATUS_BLOCK:name;
+const unique T._IO_TIMER:name;
+const unique T._IRP:name;
+const unique T._IRQ_DEVICE_POLICY:name;
+const unique T._IRQ_PRIORITY:name;
+const unique T._KAPC:name;
+const unique T._KDEVICE_QUEUE:name;
+const unique T._KDEVICE_QUEUE_ENTRY:name;
+const unique T._KDPC:name;
+const unique T._KEVENT:name;
+const unique T._KEYBOARD_ATTRIBUTES:name;
+const unique T._KEYBOARD_ID:name;
+const unique T._KEYBOARD_INDICATOR_PARAMETERS:name;
+const unique T._KEYBOARD_INPUT_DATA:name;
+const unique T._KEYBOARD_TYPEMATIC_PARAMETERS:name;
+const unique T._KSEMAPHORE:name;
+const unique T._KTHREAD:name;
+const unique T._LARGE_INTEGER:name;
+const unique T._LIST_ENTRY:name;
+const unique T._LUID:name;
+const unique T._LUID_AND_ATTRIBUTES:name;
+const unique T._MDL:name;
+const unique T._OWNER_ENTRY:name;
+const unique T._POOL_TYPE:name;
+const unique T._PORT:name;
+const unique T._POWER_SEQUENCE:name;
+const unique T._POWER_STATE:name;
+const unique T._POWER_STATE_TYPE:name;
+const unique T._PRIVILEGE_SET:name;
+const unique T._SCSI_REQUEST_BLOCK:name;
+const unique T._SECTION_OBJECT_POINTERS:name;
+const unique T._SECURITY_IMPERSONATION_LEVEL:name;
+const unique T._SECURITY_QUALITY_OF_SERVICE:name;
+const unique T._SECURITY_SUBJECT_CONTEXT:name;
+const unique T._SYSTEM_POWER_STATE:name;
+const unique T._SYSTEM_POWER_STATE_CONTEXT:name;
+const unique T._UNICODE_STRING:name;
+const unique T._VPB:name;
+const unique T._WAIT_CONTEXT_BLOCK:name;
+const unique T._WMILIB_CONTEXT:name;
+const unique T.__unnamed_12_0d6a30de:name;
+const unique T.__unnamed_12_17f5c211:name;
+const unique T.__unnamed_12_1fb42e39:name;
+const unique T.__unnamed_12_2a1563c6:name;
+const unique T.__unnamed_12_31347272:name;
+const unique T.__unnamed_12_429aadc0:name;
+const unique T.__unnamed_12_4719de1a:name;
+const unique T.__unnamed_12_4be56faa:name;
+const unique T.__unnamed_12_5ce25b92:name;
+const unique T.__unnamed_12_7a698b72:name;
+const unique T.__unnamed_12_87c0de8d:name;
+const unique T.__unnamed_12_98bfc55a:name;
+const unique T.__unnamed_12_ab1bd9d7:name;
+const unique T.__unnamed_12_b0429be9:name;
+const unique T.__unnamed_12_b43e8de8:name;
+const unique T.__unnamed_12_bfdb39ee:name;
+const unique T.__unnamed_12_cd42b3c3:name;
+const unique T.__unnamed_12_e668effc:name;
+const unique T.__unnamed_12_e80d029e:name;
+const unique T.__unnamed_16_07c0bcc5:name;
+const unique T.__unnamed_16_29cb9f2f:name;
+const unique T.__unnamed_16_30f11dbf:name;
+const unique T.__unnamed_16_35034f68:name;
+const unique T.__unnamed_16_487a9498:name;
+const unique T.__unnamed_16_5f6a8844:name;
+const unique T.__unnamed_16_7177b9f3:name;
+const unique T.__unnamed_16_88e91ef6:name;
+const unique T.__unnamed_16_8c506c98:name;
+const unique T.__unnamed_16_9ac2e5f8:name;
+const unique T.__unnamed_16_b93842ad:name;
+const unique T.__unnamed_16_b9c62eab:name;
+const unique T.__unnamed_16_bb584060:name;
+const unique T.__unnamed_16_dba55c7c:name;
+const unique T.__unnamed_16_e70c268b:name;
+const unique T.__unnamed_16_e734d694:name;
+const unique T.__unnamed_16_eac6dbea:name;
+const unique T.__unnamed_16_f6cae4c2:name;
+const unique T.__unnamed_16_fe36e4f4:name;
+const unique T.__unnamed_1_29794256:name;
+const unique T.__unnamed_1_2dc63b48:name;
+const unique T.__unnamed_1_2ef8da39:name;
+const unique T.__unnamed_1_faa7dc71:name;
+const unique T.__unnamed_20_f4d2e6d8:name;
+const unique T.__unnamed_24_41cbc8c0:name;
+const unique T.__unnamed_24_5419c914:name;
+const unique T.__unnamed_24_67a5ff10:name;
+const unique T.__unnamed_24_72c3976e:name;
+const unique T.__unnamed_24_a26050bb:name;
+const unique T.__unnamed_24_b8f476db:name;
+const unique T.__unnamed_24_d09044b4:name;
+const unique T.__unnamed_2_46cc4597:name;
+const unique T.__unnamed_40_7218f704:name;
+const unique T.__unnamed_40_c55c9377:name;
+const unique T.__unnamed_44_5584090d:name;
+const unique T.__unnamed_48_cf99b13f:name;
+const unique T.__unnamed_4_069846fb:name;
+const unique T.__unnamed_4_224c32f4:name;
+const unique T.__unnamed_4_2de698da:name;
+const unique T.__unnamed_4_3a2fdc5e:name;
+const unique T.__unnamed_4_3a4c1a13:name;
+const unique T.__unnamed_4_43913aa5:name;
+const unique T.__unnamed_4_4e8dd2ba:name;
+const unique T.__unnamed_4_52603077:name;
+const unique T.__unnamed_4_52c594f7:name;
+const unique T.__unnamed_4_5ca00198:name;
+const unique T.__unnamed_4_6ac6463c:name;
+const unique T.__unnamed_4_6f9ac8e1:name;
+const unique T.__unnamed_4_7a02167b:name;
+const unique T.__unnamed_4_7d9d0c7e:name;
+const unique T.__unnamed_4_82f7a864:name;
+const unique T.__unnamed_4_9aec220b:name;
+const unique T.__unnamed_4_a97c65a1:name;
+const unique T.__unnamed_4_c3479730:name;
+const unique T.__unnamed_4_d99b6e2b:name;
+const unique T.__unnamed_4_f19b65c1:name;
+const unique T.__unnamed_4_fa10fc16:name;
+const unique T.__unnamed_8_01efa60d:name;
+const unique T.__unnamed_8_08d4cef8:name;
+const unique T.__unnamed_8_0a898c0c:name;
+const unique T.__unnamed_8_1330f93a:name;
+const unique T.__unnamed_8_181d0de9:name;
+const unique T.__unnamed_8_4812764d:name;
+const unique T.__unnamed_8_559a91e6:name;
+const unique T.__unnamed_8_5845b309:name;
+const unique T.__unnamed_8_58ee4a31:name;
+const unique T.__unnamed_8_61acf4ce:name;
+const unique T.__unnamed_8_6acfee04:name;
+const unique T.__unnamed_8_7f26a9dd:name;
+const unique T.__unnamed_8_87add0bd:name;
+const unique T.__unnamed_8_b2773e4c:name;
+const unique T.__unnamed_8_de890d4e:name;
+const unique T.__unnamed_8_ef9ba0d3:name;
+
+function AssocClassList__GLOBALS(int) returns (int);
+function AssocClassList__GLOBALSInv(int) returns (int);
+function _S_AssocClassList__GLOBALS([int]bool) returns ([int]bool);
+function _S_AssocClassList__GLOBALSInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {AssocClassList__GLOBALSInv(AssocClassList__GLOBALS(x))} AssocClassList__GLOBALSInv(AssocClassList__GLOBALS(x)) == x);
+axiom (forall x:int :: {AssocClassList__GLOBALSInv(x)} AssocClassList__GLOBALS(AssocClassList__GLOBALSInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_AssocClassList__GLOBALS(S)[x]} _S_AssocClassList__GLOBALS(S)[x] <==> S[AssocClassList__GLOBALSInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_AssocClassList__GLOBALSInv(S)[x]} _S_AssocClassList__GLOBALSInv(S)[x] <==> S[AssocClassList__GLOBALS(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_AssocClassList__GLOBALS(S)} S[x] ==> _S_AssocClassList__GLOBALS(S)[AssocClassList__GLOBALS(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_AssocClassList__GLOBALSInv(S)} S[x] ==> _S_AssocClassList__GLOBALSInv(S)[AssocClassList__GLOBALSInv(x)]);
+
+axiom (forall x:int :: {AssocClassList__GLOBALS(x)} AssocClassList__GLOBALS(x) == x + 8);
+axiom (forall x:int :: {AssocClassList__GLOBALSInv(x)} AssocClassList__GLOBALSInv(x) == x - 8);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 8, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 8, 1) == AssocClassList__GLOBALSInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 8)} MINUS_LEFT_PTR(x, 1, 8) == AssocClassList__GLOBALSInv(x));
+function BaseClassName__GLOBALS(int) returns (int);
+function BaseClassName__GLOBALSInv(int) returns (int);
+function _S_BaseClassName__GLOBALS([int]bool) returns ([int]bool);
+function _S_BaseClassName__GLOBALSInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {BaseClassName__GLOBALSInv(BaseClassName__GLOBALS(x))} BaseClassName__GLOBALSInv(BaseClassName__GLOBALS(x)) == x);
+axiom (forall x:int :: {BaseClassName__GLOBALSInv(x)} BaseClassName__GLOBALS(BaseClassName__GLOBALSInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_BaseClassName__GLOBALS(S)[x]} _S_BaseClassName__GLOBALS(S)[x] <==> S[BaseClassName__GLOBALSInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_BaseClassName__GLOBALSInv(S)[x]} _S_BaseClassName__GLOBALSInv(S)[x] <==> S[BaseClassName__GLOBALS(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_BaseClassName__GLOBALS(S)} S[x] ==> _S_BaseClassName__GLOBALS(S)[BaseClassName__GLOBALS(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_BaseClassName__GLOBALSInv(S)} S[x] ==> _S_BaseClassName__GLOBALSInv(S)[BaseClassName__GLOBALSInv(x)]);
+
+axiom (forall x:int :: {BaseClassName__GLOBALS(x)} BaseClassName__GLOBALS(x) == x + 368);
+axiom (forall x:int :: {BaseClassName__GLOBALSInv(x)} BaseClassName__GLOBALSInv(x) == x - 368);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 368, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 368, 1) == BaseClassName__GLOBALSInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 368)} MINUS_LEFT_PTR(x, 1, 368) == BaseClassName__GLOBALSInv(x));
+function Buffer__UNICODE_STRING(int) returns (int);
+function Buffer__UNICODE_STRINGInv(int) returns (int);
+function _S_Buffer__UNICODE_STRING([int]bool) returns ([int]bool);
+function _S_Buffer__UNICODE_STRINGInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {Buffer__UNICODE_STRINGInv(Buffer__UNICODE_STRING(x))} Buffer__UNICODE_STRINGInv(Buffer__UNICODE_STRING(x)) == x);
+axiom (forall x:int :: {Buffer__UNICODE_STRINGInv(x)} Buffer__UNICODE_STRING(Buffer__UNICODE_STRINGInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_Buffer__UNICODE_STRING(S)[x]} _S_Buffer__UNICODE_STRING(S)[x] <==> S[Buffer__UNICODE_STRINGInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_Buffer__UNICODE_STRINGInv(S)[x]} _S_Buffer__UNICODE_STRINGInv(S)[x] <==> S[Buffer__UNICODE_STRING(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Buffer__UNICODE_STRING(S)} S[x] ==> _S_Buffer__UNICODE_STRING(S)[Buffer__UNICODE_STRING(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Buffer__UNICODE_STRINGInv(S)} S[x] ==> _S_Buffer__UNICODE_STRINGInv(S)[Buffer__UNICODE_STRINGInv(x)]);
+
+axiom (forall x:int :: {Buffer__UNICODE_STRING(x)} Buffer__UNICODE_STRING(x) == x + 4);
+axiom (forall x:int :: {Buffer__UNICODE_STRINGInv(x)} Buffer__UNICODE_STRINGInv(x) == x - 4);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 4, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 4, 1) == Buffer__UNICODE_STRINGInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 4)} MINUS_LEFT_PTR(x, 1, 4) == Buffer__UNICODE_STRINGInv(x));
+function DataIn__DEVICE_EXTENSION(int) returns (int);
+function DataIn__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_DataIn__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_DataIn__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {DataIn__DEVICE_EXTENSIONInv(DataIn__DEVICE_EXTENSION(x))} DataIn__DEVICE_EXTENSIONInv(DataIn__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {DataIn__DEVICE_EXTENSIONInv(x)} DataIn__DEVICE_EXTENSION(DataIn__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_DataIn__DEVICE_EXTENSION(S)[x]} _S_DataIn__DEVICE_EXTENSION(S)[x] <==> S[DataIn__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_DataIn__DEVICE_EXTENSIONInv(S)[x]} _S_DataIn__DEVICE_EXTENSIONInv(S)[x] <==> S[DataIn__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_DataIn__DEVICE_EXTENSION(S)} S[x] ==> _S_DataIn__DEVICE_EXTENSION(S)[DataIn__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_DataIn__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_DataIn__DEVICE_EXTENSIONInv(S)[DataIn__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {DataIn__DEVICE_EXTENSION(x)} DataIn__DEVICE_EXTENSION(x) == x + 132);
+axiom (forall x:int :: {DataIn__DEVICE_EXTENSIONInv(x)} DataIn__DEVICE_EXTENSIONInv(x) == x - 132);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 132, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 132, 1) == DataIn__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 132)} MINUS_LEFT_PTR(x, 1, 132) == DataIn__DEVICE_EXTENSIONInv(x));
+function DataOut__DEVICE_EXTENSION(int) returns (int);
+function DataOut__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_DataOut__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_DataOut__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {DataOut__DEVICE_EXTENSIONInv(DataOut__DEVICE_EXTENSION(x))} DataOut__DEVICE_EXTENSIONInv(DataOut__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {DataOut__DEVICE_EXTENSIONInv(x)} DataOut__DEVICE_EXTENSION(DataOut__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_DataOut__DEVICE_EXTENSION(S)[x]} _S_DataOut__DEVICE_EXTENSION(S)[x] <==> S[DataOut__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_DataOut__DEVICE_EXTENSIONInv(S)[x]} _S_DataOut__DEVICE_EXTENSIONInv(S)[x] <==> S[DataOut__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_DataOut__DEVICE_EXTENSION(S)} S[x] ==> _S_DataOut__DEVICE_EXTENSION(S)[DataOut__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_DataOut__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_DataOut__DEVICE_EXTENSIONInv(S)[DataOut__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {DataOut__DEVICE_EXTENSION(x)} DataOut__DEVICE_EXTENSION(x) == x + 136);
+axiom (forall x:int :: {DataOut__DEVICE_EXTENSIONInv(x)} DataOut__DEVICE_EXTENSIONInv(x) == x - 136);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 136, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 136, 1) == DataOut__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 136)} MINUS_LEFT_PTR(x, 1, 136) == DataOut__DEVICE_EXTENSIONInv(x));
+function DeviceExtension__DEVICE_OBJECT(int) returns (int);
+function DeviceExtension__DEVICE_OBJECTInv(int) returns (int);
+function _S_DeviceExtension__DEVICE_OBJECT([int]bool) returns ([int]bool);
+function _S_DeviceExtension__DEVICE_OBJECTInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {DeviceExtension__DEVICE_OBJECTInv(DeviceExtension__DEVICE_OBJECT(x))} DeviceExtension__DEVICE_OBJECTInv(DeviceExtension__DEVICE_OBJECT(x)) == x);
+axiom (forall x:int :: {DeviceExtension__DEVICE_OBJECTInv(x)} DeviceExtension__DEVICE_OBJECT(DeviceExtension__DEVICE_OBJECTInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_DeviceExtension__DEVICE_OBJECT(S)[x]} _S_DeviceExtension__DEVICE_OBJECT(S)[x] <==> S[DeviceExtension__DEVICE_OBJECTInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_DeviceExtension__DEVICE_OBJECTInv(S)[x]} _S_DeviceExtension__DEVICE_OBJECTInv(S)[x] <==> S[DeviceExtension__DEVICE_OBJECT(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_DeviceExtension__DEVICE_OBJECT(S)} S[x] ==> _S_DeviceExtension__DEVICE_OBJECT(S)[DeviceExtension__DEVICE_OBJECT(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_DeviceExtension__DEVICE_OBJECTInv(S)} S[x] ==> _S_DeviceExtension__DEVICE_OBJECTInv(S)[DeviceExtension__DEVICE_OBJECTInv(x)]);
+
+axiom (forall x:int :: {DeviceExtension__DEVICE_OBJECT(x)} DeviceExtension__DEVICE_OBJECT(x) == x + 40);
+axiom (forall x:int :: {DeviceExtension__DEVICE_OBJECTInv(x)} DeviceExtension__DEVICE_OBJECTInv(x) == x - 40);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 40, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 40, 1) == DeviceExtension__DEVICE_OBJECTInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 40)} MINUS_LEFT_PTR(x, 1, 40) == DeviceExtension__DEVICE_OBJECTInv(x));
+function File__DEVICE_EXTENSION(int) returns (int);
+function File__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_File__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_File__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {File__DEVICE_EXTENSIONInv(File__DEVICE_EXTENSION(x))} File__DEVICE_EXTENSIONInv(File__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {File__DEVICE_EXTENSIONInv(x)} File__DEVICE_EXTENSION(File__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_File__DEVICE_EXTENSION(S)[x]} _S_File__DEVICE_EXTENSION(S)[x] <==> S[File__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_File__DEVICE_EXTENSIONInv(S)[x]} _S_File__DEVICE_EXTENSIONInv(S)[x] <==> S[File__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_File__DEVICE_EXTENSION(S)} S[x] ==> _S_File__DEVICE_EXTENSION(S)[File__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_File__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_File__DEVICE_EXTENSIONInv(S)[File__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {File__DEVICE_EXTENSION(x)} File__DEVICE_EXTENSION(x) == x + 280);
+axiom (forall x:int :: {File__DEVICE_EXTENSIONInv(x)} File__DEVICE_EXTENSIONInv(x) == x - 280);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 280, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 280, 1) == File__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 280)} MINUS_LEFT_PTR(x, 1, 280) == File__DEVICE_EXTENSIONInv(x));
+function File__PORT(int) returns (int);
+function File__PORTInv(int) returns (int);
+function _S_File__PORT([int]bool) returns ([int]bool);
+function _S_File__PORTInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {File__PORTInv(File__PORT(x))} File__PORTInv(File__PORT(x)) == x);
+axiom (forall x:int :: {File__PORTInv(x)} File__PORT(File__PORTInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_File__PORT(S)[x]} _S_File__PORT(S)[x] <==> S[File__PORTInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_File__PORTInv(S)[x]} _S_File__PORTInv(S)[x] <==> S[File__PORT(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_File__PORT(S)} S[x] ==> _S_File__PORT(S)[File__PORT(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_File__PORTInv(S)} S[x] ==> _S_File__PORTInv(S)[File__PORTInv(x)]);
+
+axiom (forall x:int :: {File__PORT(x)} File__PORT(x) == x + 0);
+axiom (forall x:int :: {File__PORTInv(x)} File__PORTInv(x) == x - 0);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1) == File__PORTInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 0)} MINUS_LEFT_PTR(x, 1, 0) == File__PORTInv(x));
+function Flags__DEVICE_OBJECT(int) returns (int);
+function Flags__DEVICE_OBJECTInv(int) returns (int);
+function _S_Flags__DEVICE_OBJECT([int]bool) returns ([int]bool);
+function _S_Flags__DEVICE_OBJECTInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {Flags__DEVICE_OBJECTInv(Flags__DEVICE_OBJECT(x))} Flags__DEVICE_OBJECTInv(Flags__DEVICE_OBJECT(x)) == x);
+axiom (forall x:int :: {Flags__DEVICE_OBJECTInv(x)} Flags__DEVICE_OBJECT(Flags__DEVICE_OBJECTInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_Flags__DEVICE_OBJECT(S)[x]} _S_Flags__DEVICE_OBJECT(S)[x] <==> S[Flags__DEVICE_OBJECTInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_Flags__DEVICE_OBJECTInv(S)[x]} _S_Flags__DEVICE_OBJECTInv(S)[x] <==> S[Flags__DEVICE_OBJECT(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Flags__DEVICE_OBJECT(S)} S[x] ==> _S_Flags__DEVICE_OBJECT(S)[Flags__DEVICE_OBJECT(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Flags__DEVICE_OBJECTInv(S)} S[x] ==> _S_Flags__DEVICE_OBJECTInv(S)[Flags__DEVICE_OBJECTInv(x)]);
+
+axiom (forall x:int :: {Flags__DEVICE_OBJECT(x)} Flags__DEVICE_OBJECT(x) == x + 28);
+axiom (forall x:int :: {Flags__DEVICE_OBJECTInv(x)} Flags__DEVICE_OBJECTInv(x) == x - 28);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 28, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 28, 1) == Flags__DEVICE_OBJECTInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 28)} MINUS_LEFT_PTR(x, 1, 28) == Flags__DEVICE_OBJECTInv(x));
+function Flink__LIST_ENTRY(int) returns (int);
+function Flink__LIST_ENTRYInv(int) returns (int);
+function _S_Flink__LIST_ENTRY([int]bool) returns ([int]bool);
+function _S_Flink__LIST_ENTRYInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {Flink__LIST_ENTRYInv(Flink__LIST_ENTRY(x))} Flink__LIST_ENTRYInv(Flink__LIST_ENTRY(x)) == x);
+axiom (forall x:int :: {Flink__LIST_ENTRYInv(x)} Flink__LIST_ENTRY(Flink__LIST_ENTRYInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_Flink__LIST_ENTRY(S)[x]} _S_Flink__LIST_ENTRY(S)[x] <==> S[Flink__LIST_ENTRYInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_Flink__LIST_ENTRYInv(S)[x]} _S_Flink__LIST_ENTRYInv(S)[x] <==> S[Flink__LIST_ENTRY(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Flink__LIST_ENTRY(S)} S[x] ==> _S_Flink__LIST_ENTRY(S)[Flink__LIST_ENTRY(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Flink__LIST_ENTRYInv(S)} S[x] ==> _S_Flink__LIST_ENTRYInv(S)[Flink__LIST_ENTRYInv(x)]);
+
+axiom (forall x:int :: {Flink__LIST_ENTRY(x)} Flink__LIST_ENTRY(x) == x + 0);
+axiom (forall x:int :: {Flink__LIST_ENTRYInv(x)} Flink__LIST_ENTRYInv(x) == x - 0);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1) == Flink__LIST_ENTRYInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 0)} MINUS_LEFT_PTR(x, 1, 0) == Flink__LIST_ENTRYInv(x));
+function Free__PORT(int) returns (int);
+function Free__PORTInv(int) returns (int);
+function _S_Free__PORT([int]bool) returns ([int]bool);
+function _S_Free__PORTInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {Free__PORTInv(Free__PORT(x))} Free__PORTInv(Free__PORT(x)) == x);
+axiom (forall x:int :: {Free__PORTInv(x)} Free__PORT(Free__PORTInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_Free__PORT(S)[x]} _S_Free__PORT(S)[x] <==> S[Free__PORTInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_Free__PORTInv(S)[x]} _S_Free__PORTInv(S)[x] <==> S[Free__PORT(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Free__PORT(S)} S[x] ==> _S_Free__PORT(S)[Free__PORT(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Free__PORTInv(S)} S[x] ==> _S_Free__PORTInv(S)[Free__PORTInv(x)]);
+
+axiom (forall x:int :: {Free__PORT(x)} Free__PORT(x) == x + 11);
+axiom (forall x:int :: {Free__PORTInv(x)} Free__PORTInv(x) == x - 11);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 11, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 11, 1) == Free__PORTInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 11)} MINUS_LEFT_PTR(x, 1, 11) == Free__PORTInv(x));
+function GrandMaster__GLOBALS(int) returns (int);
+function GrandMaster__GLOBALSInv(int) returns (int);
+function _S_GrandMaster__GLOBALS([int]bool) returns ([int]bool);
+function _S_GrandMaster__GLOBALSInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {GrandMaster__GLOBALSInv(GrandMaster__GLOBALS(x))} GrandMaster__GLOBALSInv(GrandMaster__GLOBALS(x)) == x);
+axiom (forall x:int :: {GrandMaster__GLOBALSInv(x)} GrandMaster__GLOBALS(GrandMaster__GLOBALSInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_GrandMaster__GLOBALS(S)[x]} _S_GrandMaster__GLOBALS(S)[x] <==> S[GrandMaster__GLOBALSInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_GrandMaster__GLOBALSInv(S)[x]} _S_GrandMaster__GLOBALSInv(S)[x] <==> S[GrandMaster__GLOBALS(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_GrandMaster__GLOBALS(S)} S[x] ==> _S_GrandMaster__GLOBALS(S)[GrandMaster__GLOBALS(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_GrandMaster__GLOBALSInv(S)} S[x] ==> _S_GrandMaster__GLOBALSInv(S)[GrandMaster__GLOBALSInv(x)]);
+
+axiom (forall x:int :: {GrandMaster__GLOBALS(x)} GrandMaster__GLOBALS(x) == x + 4);
+axiom (forall x:int :: {GrandMaster__GLOBALSInv(x)} GrandMaster__GLOBALSInv(x) == x - 4);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 4, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 4, 1) == GrandMaster__GLOBALSInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 4)} MINUS_LEFT_PTR(x, 1, 4) == GrandMaster__GLOBALSInv(x));
+function InitExtension__GLOBALS(int) returns (int);
+function InitExtension__GLOBALSInv(int) returns (int);
+function _S_InitExtension__GLOBALS([int]bool) returns ([int]bool);
+function _S_InitExtension__GLOBALSInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {InitExtension__GLOBALSInv(InitExtension__GLOBALS(x))} InitExtension__GLOBALSInv(InitExtension__GLOBALS(x)) == x);
+axiom (forall x:int :: {InitExtension__GLOBALSInv(x)} InitExtension__GLOBALS(InitExtension__GLOBALSInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_InitExtension__GLOBALS(S)[x]} _S_InitExtension__GLOBALS(S)[x] <==> S[InitExtension__GLOBALSInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_InitExtension__GLOBALSInv(S)[x]} _S_InitExtension__GLOBALSInv(S)[x] <==> S[InitExtension__GLOBALS(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_InitExtension__GLOBALS(S)} S[x] ==> _S_InitExtension__GLOBALS(S)[InitExtension__GLOBALS(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_InitExtension__GLOBALSInv(S)} S[x] ==> _S_InitExtension__GLOBALSInv(S)[InitExtension__GLOBALSInv(x)]);
+
+axiom (forall x:int :: {InitExtension__GLOBALS(x)} InitExtension__GLOBALS(x) == x + 72);
+axiom (forall x:int :: {InitExtension__GLOBALSInv(x)} InitExtension__GLOBALSInv(x) == x - 72);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 72, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 72, 1) == InitExtension__GLOBALSInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 72)} MINUS_LEFT_PTR(x, 1, 72) == InitExtension__GLOBALSInv(x));
+function InputData__DEVICE_EXTENSION(int) returns (int);
+function InputData__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_InputData__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_InputData__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {InputData__DEVICE_EXTENSIONInv(InputData__DEVICE_EXTENSION(x))} InputData__DEVICE_EXTENSIONInv(InputData__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {InputData__DEVICE_EXTENSIONInv(x)} InputData__DEVICE_EXTENSION(InputData__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_InputData__DEVICE_EXTENSION(S)[x]} _S_InputData__DEVICE_EXTENSION(S)[x] <==> S[InputData__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_InputData__DEVICE_EXTENSIONInv(S)[x]} _S_InputData__DEVICE_EXTENSIONInv(S)[x] <==> S[InputData__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_InputData__DEVICE_EXTENSION(S)} S[x] ==> _S_InputData__DEVICE_EXTENSION(S)[InputData__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_InputData__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_InputData__DEVICE_EXTENSIONInv(S)[InputData__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {InputData__DEVICE_EXTENSION(x)} InputData__DEVICE_EXTENSION(x) == x + 128);
+axiom (forall x:int :: {InputData__DEVICE_EXTENSIONInv(x)} InputData__DEVICE_EXTENSIONInv(x) == x - 128);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 128, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 128, 1) == InputData__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 128)} MINUS_LEFT_PTR(x, 1, 128) == InputData__DEVICE_EXTENSIONInv(x));
+function LegacyDeviceList__GLOBALS(int) returns (int);
+function LegacyDeviceList__GLOBALSInv(int) returns (int);
+function _S_LegacyDeviceList__GLOBALS([int]bool) returns ([int]bool);
+function _S_LegacyDeviceList__GLOBALSInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {LegacyDeviceList__GLOBALSInv(LegacyDeviceList__GLOBALS(x))} LegacyDeviceList__GLOBALSInv(LegacyDeviceList__GLOBALS(x)) == x);
+axiom (forall x:int :: {LegacyDeviceList__GLOBALSInv(x)} LegacyDeviceList__GLOBALS(LegacyDeviceList__GLOBALSInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_LegacyDeviceList__GLOBALS(S)[x]} _S_LegacyDeviceList__GLOBALS(S)[x] <==> S[LegacyDeviceList__GLOBALSInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_LegacyDeviceList__GLOBALSInv(S)[x]} _S_LegacyDeviceList__GLOBALSInv(S)[x] <==> S[LegacyDeviceList__GLOBALS(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_LegacyDeviceList__GLOBALS(S)} S[x] ==> _S_LegacyDeviceList__GLOBALS(S)[LegacyDeviceList__GLOBALS(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_LegacyDeviceList__GLOBALSInv(S)} S[x] ==> _S_LegacyDeviceList__GLOBALSInv(S)[LegacyDeviceList__GLOBALSInv(x)]);
+
+axiom (forall x:int :: {LegacyDeviceList__GLOBALS(x)} LegacyDeviceList__GLOBALS(x) == x + 888);
+axiom (forall x:int :: {LegacyDeviceList__GLOBALSInv(x)} LegacyDeviceList__GLOBALSInv(x) == x - 888);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 888, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 888, 1) == LegacyDeviceList__GLOBALSInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 888)} MINUS_LEFT_PTR(x, 1, 888) == LegacyDeviceList__GLOBALSInv(x));
+function Length__UNICODE_STRING(int) returns (int);
+function Length__UNICODE_STRINGInv(int) returns (int);
+function _S_Length__UNICODE_STRING([int]bool) returns ([int]bool);
+function _S_Length__UNICODE_STRINGInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {Length__UNICODE_STRINGInv(Length__UNICODE_STRING(x))} Length__UNICODE_STRINGInv(Length__UNICODE_STRING(x)) == x);
+axiom (forall x:int :: {Length__UNICODE_STRINGInv(x)} Length__UNICODE_STRING(Length__UNICODE_STRINGInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_Length__UNICODE_STRING(S)[x]} _S_Length__UNICODE_STRING(S)[x] <==> S[Length__UNICODE_STRINGInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_Length__UNICODE_STRINGInv(S)[x]} _S_Length__UNICODE_STRINGInv(S)[x] <==> S[Length__UNICODE_STRING(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Length__UNICODE_STRING(S)} S[x] ==> _S_Length__UNICODE_STRING(S)[Length__UNICODE_STRING(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Length__UNICODE_STRINGInv(S)} S[x] ==> _S_Length__UNICODE_STRINGInv(S)[Length__UNICODE_STRINGInv(x)]);
+
+axiom (forall x:int :: {Length__UNICODE_STRING(x)} Length__UNICODE_STRING(x) == x + 0);
+axiom (forall x:int :: {Length__UNICODE_STRINGInv(x)} Length__UNICODE_STRINGInv(x) == x - 0);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1) == Length__UNICODE_STRINGInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 0)} MINUS_LEFT_PTR(x, 1, 0) == Length__UNICODE_STRINGInv(x));
+function Link__DEVICE_EXTENSION(int) returns (int);
+function Link__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_Link__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_Link__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {Link__DEVICE_EXTENSIONInv(Link__DEVICE_EXTENSION(x))} Link__DEVICE_EXTENSIONInv(Link__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {Link__DEVICE_EXTENSIONInv(x)} Link__DEVICE_EXTENSION(Link__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_Link__DEVICE_EXTENSION(S)[x]} _S_Link__DEVICE_EXTENSION(S)[x] <==> S[Link__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_Link__DEVICE_EXTENSIONInv(S)[x]} _S_Link__DEVICE_EXTENSIONInv(S)[x] <==> S[Link__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Link__DEVICE_EXTENSION(S)} S[x] ==> _S_Link__DEVICE_EXTENSION(S)[Link__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Link__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_Link__DEVICE_EXTENSIONInv(S)[Link__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {Link__DEVICE_EXTENSION(x)} Link__DEVICE_EXTENSION(x) == x + 272);
+axiom (forall x:int :: {Link__DEVICE_EXTENSIONInv(x)} Link__DEVICE_EXTENSIONInv(x) == x - 272);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 272, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 272, 1) == Link__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 272)} MINUS_LEFT_PTR(x, 1, 272) == Link__DEVICE_EXTENSIONInv(x));
+function MaximumLength__UNICODE_STRING(int) returns (int);
+function MaximumLength__UNICODE_STRINGInv(int) returns (int);
+function _S_MaximumLength__UNICODE_STRING([int]bool) returns ([int]bool);
+function _S_MaximumLength__UNICODE_STRINGInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {MaximumLength__UNICODE_STRINGInv(MaximumLength__UNICODE_STRING(x))} MaximumLength__UNICODE_STRINGInv(MaximumLength__UNICODE_STRING(x)) == x);
+axiom (forall x:int :: {MaximumLength__UNICODE_STRINGInv(x)} MaximumLength__UNICODE_STRING(MaximumLength__UNICODE_STRINGInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_MaximumLength__UNICODE_STRING(S)[x]} _S_MaximumLength__UNICODE_STRING(S)[x] <==> S[MaximumLength__UNICODE_STRINGInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_MaximumLength__UNICODE_STRINGInv(S)[x]} _S_MaximumLength__UNICODE_STRINGInv(S)[x] <==> S[MaximumLength__UNICODE_STRING(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_MaximumLength__UNICODE_STRING(S)} S[x] ==> _S_MaximumLength__UNICODE_STRING(S)[MaximumLength__UNICODE_STRING(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_MaximumLength__UNICODE_STRINGInv(S)} S[x] ==> _S_MaximumLength__UNICODE_STRINGInv(S)[MaximumLength__UNICODE_STRINGInv(x)]);
+
+axiom (forall x:int :: {MaximumLength__UNICODE_STRING(x)} MaximumLength__UNICODE_STRING(x) == x + 2);
+axiom (forall x:int :: {MaximumLength__UNICODE_STRINGInv(x)} MaximumLength__UNICODE_STRINGInv(x) == x - 2);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 2, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 2, 1) == MaximumLength__UNICODE_STRINGInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 2)} MINUS_LEFT_PTR(x, 1, 2) == MaximumLength__UNICODE_STRINGInv(x));
+function Mutex__GLOBALS(int) returns (int);
+function Mutex__GLOBALSInv(int) returns (int);
+function _S_Mutex__GLOBALS([int]bool) returns ([int]bool);
+function _S_Mutex__GLOBALSInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {Mutex__GLOBALSInv(Mutex__GLOBALS(x))} Mutex__GLOBALSInv(Mutex__GLOBALS(x)) == x);
+axiom (forall x:int :: {Mutex__GLOBALSInv(x)} Mutex__GLOBALS(Mutex__GLOBALSInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_Mutex__GLOBALS(S)[x]} _S_Mutex__GLOBALS(S)[x] <==> S[Mutex__GLOBALSInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_Mutex__GLOBALSInv(S)[x]} _S_Mutex__GLOBALSInv(S)[x] <==> S[Mutex__GLOBALS(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Mutex__GLOBALS(S)} S[x] ==> _S_Mutex__GLOBALS(S)[Mutex__GLOBALS(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Mutex__GLOBALSInv(S)} S[x] ==> _S_Mutex__GLOBALSInv(S)[Mutex__GLOBALSInv(x)]);
+
+axiom (forall x:int :: {Mutex__GLOBALS(x)} Mutex__GLOBALS(x) == x + 24);
+axiom (forall x:int :: {Mutex__GLOBALSInv(x)} Mutex__GLOBALSInv(x) == x - 24);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 24, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 24, 1) == Mutex__GLOBALSInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 24)} MINUS_LEFT_PTR(x, 1, 24) == Mutex__GLOBALSInv(x));
+function NumberLegacyPorts__GLOBALS(int) returns (int);
+function NumberLegacyPorts__GLOBALSInv(int) returns (int);
+function _S_NumberLegacyPorts__GLOBALS([int]bool) returns ([int]bool);
+function _S_NumberLegacyPorts__GLOBALSInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {NumberLegacyPorts__GLOBALSInv(NumberLegacyPorts__GLOBALS(x))} NumberLegacyPorts__GLOBALSInv(NumberLegacyPorts__GLOBALS(x)) == x);
+axiom (forall x:int :: {NumberLegacyPorts__GLOBALSInv(x)} NumberLegacyPorts__GLOBALS(NumberLegacyPorts__GLOBALSInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_NumberLegacyPorts__GLOBALS(S)[x]} _S_NumberLegacyPorts__GLOBALS(S)[x] <==> S[NumberLegacyPorts__GLOBALSInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_NumberLegacyPorts__GLOBALSInv(S)[x]} _S_NumberLegacyPorts__GLOBALSInv(S)[x] <==> S[NumberLegacyPorts__GLOBALS(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_NumberLegacyPorts__GLOBALS(S)} S[x] ==> _S_NumberLegacyPorts__GLOBALS(S)[NumberLegacyPorts__GLOBALS(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_NumberLegacyPorts__GLOBALSInv(S)} S[x] ==> _S_NumberLegacyPorts__GLOBALSInv(S)[NumberLegacyPorts__GLOBALSInv(x)]);
+
+axiom (forall x:int :: {NumberLegacyPorts__GLOBALS(x)} NumberLegacyPorts__GLOBALS(x) == x + 20);
+axiom (forall x:int :: {NumberLegacyPorts__GLOBALSInv(x)} NumberLegacyPorts__GLOBALSInv(x) == x - 20);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 20, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 20, 1) == NumberLegacyPorts__GLOBALSInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 20)} MINUS_LEFT_PTR(x, 1, 20) == NumberLegacyPorts__GLOBALSInv(x));
+function PnP__DEVICE_EXTENSION(int) returns (int);
+function PnP__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_PnP__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_PnP__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {PnP__DEVICE_EXTENSIONInv(PnP__DEVICE_EXTENSION(x))} PnP__DEVICE_EXTENSIONInv(PnP__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {PnP__DEVICE_EXTENSIONInv(x)} PnP__DEVICE_EXTENSION(PnP__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_PnP__DEVICE_EXTENSION(S)[x]} _S_PnP__DEVICE_EXTENSION(S)[x] <==> S[PnP__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_PnP__DEVICE_EXTENSIONInv(S)[x]} _S_PnP__DEVICE_EXTENSIONInv(S)[x] <==> S[PnP__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_PnP__DEVICE_EXTENSION(S)} S[x] ==> _S_PnP__DEVICE_EXTENSION(S)[PnP__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_PnP__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_PnP__DEVICE_EXTENSIONInv(S)[PnP__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {PnP__DEVICE_EXTENSION(x)} PnP__DEVICE_EXTENSION(x) == x + 104);
+axiom (forall x:int :: {PnP__DEVICE_EXTENSIONInv(x)} PnP__DEVICE_EXTENSIONInv(x) == x - 104);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 104, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 104, 1) == PnP__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 104)} MINUS_LEFT_PTR(x, 1, 104) == PnP__DEVICE_EXTENSIONInv(x));
+function Port__PORT(int) returns (int);
+function Port__PORTInv(int) returns (int);
+function _S_Port__PORT([int]bool) returns ([int]bool);
+function _S_Port__PORTInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {Port__PORTInv(Port__PORT(x))} Port__PORTInv(Port__PORT(x)) == x);
+axiom (forall x:int :: {Port__PORTInv(x)} Port__PORT(Port__PORTInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_Port__PORT(S)[x]} _S_Port__PORT(S)[x] <==> S[Port__PORTInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_Port__PORTInv(S)[x]} _S_Port__PORTInv(S)[x] <==> S[Port__PORT(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Port__PORT(S)} S[x] ==> _S_Port__PORT(S)[Port__PORT(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Port__PORTInv(S)} S[x] ==> _S_Port__PORTInv(S)[Port__PORTInv(x)]);
+
+axiom (forall x:int :: {Port__PORT(x)} Port__PORT(x) == x + 4);
+axiom (forall x:int :: {Port__PORTInv(x)} Port__PORTInv(x) == x - 4);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 4, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 4, 1) == Port__PORTInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 4)} MINUS_LEFT_PTR(x, 1, 4) == Port__PORTInv(x));
+function PortsServiced__GLOBALS(int) returns (int);
+function PortsServiced__GLOBALSInv(int) returns (int);
+function _S_PortsServiced__GLOBALS([int]bool) returns ([int]bool);
+function _S_PortsServiced__GLOBALSInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {PortsServiced__GLOBALSInv(PortsServiced__GLOBALS(x))} PortsServiced__GLOBALSInv(PortsServiced__GLOBALS(x)) == x);
+axiom (forall x:int :: {PortsServiced__GLOBALSInv(x)} PortsServiced__GLOBALS(PortsServiced__GLOBALSInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_PortsServiced__GLOBALS(S)[x]} _S_PortsServiced__GLOBALS(S)[x] <==> S[PortsServiced__GLOBALSInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_PortsServiced__GLOBALSInv(S)[x]} _S_PortsServiced__GLOBALSInv(S)[x] <==> S[PortsServiced__GLOBALS(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_PortsServiced__GLOBALS(S)} S[x] ==> _S_PortsServiced__GLOBALS(S)[PortsServiced__GLOBALS(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_PortsServiced__GLOBALSInv(S)} S[x] ==> _S_PortsServiced__GLOBALSInv(S)[PortsServiced__GLOBALSInv(x)]);
+
+axiom (forall x:int :: {PortsServiced__GLOBALS(x)} PortsServiced__GLOBALS(x) == x + 64);
+axiom (forall x:int :: {PortsServiced__GLOBALSInv(x)} PortsServiced__GLOBALSInv(x) == x - 64);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 64, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 64, 1) == PortsServiced__GLOBALSInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 64)} MINUS_LEFT_PTR(x, 1, 64) == PortsServiced__GLOBALSInv(x));
+function Self__DEVICE_EXTENSION(int) returns (int);
+function Self__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_Self__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_Self__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {Self__DEVICE_EXTENSIONInv(Self__DEVICE_EXTENSION(x))} Self__DEVICE_EXTENSIONInv(Self__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {Self__DEVICE_EXTENSIONInv(x)} Self__DEVICE_EXTENSION(Self__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_Self__DEVICE_EXTENSION(S)[x]} _S_Self__DEVICE_EXTENSION(S)[x] <==> S[Self__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_Self__DEVICE_EXTENSIONInv(S)[x]} _S_Self__DEVICE_EXTENSIONInv(S)[x] <==> S[Self__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Self__DEVICE_EXTENSION(S)} S[x] ==> _S_Self__DEVICE_EXTENSION(S)[Self__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Self__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_Self__DEVICE_EXTENSIONInv(S)[Self__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {Self__DEVICE_EXTENSION(x)} Self__DEVICE_EXTENSION(x) == x + 0);
+axiom (forall x:int :: {Self__DEVICE_EXTENSIONInv(x)} Self__DEVICE_EXTENSIONInv(x) == x - 0);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1) == Self__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 0)} MINUS_LEFT_PTR(x, 1, 0) == Self__DEVICE_EXTENSIONInv(x));
+function StackSize__DEVICE_OBJECT(int) returns (int);
+function StackSize__DEVICE_OBJECTInv(int) returns (int);
+function _S_StackSize__DEVICE_OBJECT([int]bool) returns ([int]bool);
+function _S_StackSize__DEVICE_OBJECTInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {StackSize__DEVICE_OBJECTInv(StackSize__DEVICE_OBJECT(x))} StackSize__DEVICE_OBJECTInv(StackSize__DEVICE_OBJECT(x)) == x);
+axiom (forall x:int :: {StackSize__DEVICE_OBJECTInv(x)} StackSize__DEVICE_OBJECT(StackSize__DEVICE_OBJECTInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_StackSize__DEVICE_OBJECT(S)[x]} _S_StackSize__DEVICE_OBJECT(S)[x] <==> S[StackSize__DEVICE_OBJECTInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_StackSize__DEVICE_OBJECTInv(S)[x]} _S_StackSize__DEVICE_OBJECTInv(S)[x] <==> S[StackSize__DEVICE_OBJECT(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_StackSize__DEVICE_OBJECT(S)} S[x] ==> _S_StackSize__DEVICE_OBJECT(S)[StackSize__DEVICE_OBJECT(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_StackSize__DEVICE_OBJECTInv(S)} S[x] ==> _S_StackSize__DEVICE_OBJECTInv(S)[StackSize__DEVICE_OBJECTInv(x)]);
+
+axiom (forall x:int :: {StackSize__DEVICE_OBJECT(x)} StackSize__DEVICE_OBJECT(x) == x + 48);
+axiom (forall x:int :: {StackSize__DEVICE_OBJECTInv(x)} StackSize__DEVICE_OBJECTInv(x) == x - 48);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 48, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 48, 1) == StackSize__DEVICE_OBJECTInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 48)} MINUS_LEFT_PTR(x, 1, 48) == StackSize__DEVICE_OBJECTInv(x));
+function Started__DEVICE_EXTENSION(int) returns (int);
+function Started__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_Started__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_Started__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {Started__DEVICE_EXTENSIONInv(Started__DEVICE_EXTENSION(x))} Started__DEVICE_EXTENSIONInv(Started__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {Started__DEVICE_EXTENSIONInv(x)} Started__DEVICE_EXTENSION(Started__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_Started__DEVICE_EXTENSION(S)[x]} _S_Started__DEVICE_EXTENSION(S)[x] <==> S[Started__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_Started__DEVICE_EXTENSIONInv(S)[x]} _S_Started__DEVICE_EXTENSIONInv(S)[x] <==> S[Started__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Started__DEVICE_EXTENSION(S)} S[x] ==> _S_Started__DEVICE_EXTENSION(S)[Started__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Started__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_Started__DEVICE_EXTENSIONInv(S)[Started__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {Started__DEVICE_EXTENSION(x)} Started__DEVICE_EXTENSION(x) == x + 105);
+axiom (forall x:int :: {Started__DEVICE_EXTENSIONInv(x)} Started__DEVICE_EXTENSIONInv(x) == x - 105);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 105, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 105, 1) == Started__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 105)} MINUS_LEFT_PTR(x, 1, 105) == Started__DEVICE_EXTENSIONInv(x));
+function TopPort__DEVICE_EXTENSION(int) returns (int);
+function TopPort__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_TopPort__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_TopPort__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {TopPort__DEVICE_EXTENSIONInv(TopPort__DEVICE_EXTENSION(x))} TopPort__DEVICE_EXTENSIONInv(TopPort__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {TopPort__DEVICE_EXTENSIONInv(x)} TopPort__DEVICE_EXTENSION(TopPort__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_TopPort__DEVICE_EXTENSION(S)[x]} _S_TopPort__DEVICE_EXTENSION(S)[x] <==> S[TopPort__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_TopPort__DEVICE_EXTENSIONInv(S)[x]} _S_TopPort__DEVICE_EXTENSIONInv(S)[x] <==> S[TopPort__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_TopPort__DEVICE_EXTENSION(S)} S[x] ==> _S_TopPort__DEVICE_EXTENSION(S)[TopPort__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_TopPort__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_TopPort__DEVICE_EXTENSIONInv(S)[TopPort__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {TopPort__DEVICE_EXTENSION(x)} TopPort__DEVICE_EXTENSION(x) == x + 8);
+axiom (forall x:int :: {TopPort__DEVICE_EXTENSIONInv(x)} TopPort__DEVICE_EXTENSIONInv(x) == x - 8);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 8, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 8, 1) == TopPort__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 8)} MINUS_LEFT_PTR(x, 1, 8) == TopPort__DEVICE_EXTENSIONInv(x));
+function UnitId__DEVICE_EXTENSION(int) returns (int);
+function UnitId__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_UnitId__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_UnitId__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {UnitId__DEVICE_EXTENSIONInv(UnitId__DEVICE_EXTENSION(x))} UnitId__DEVICE_EXTENSIONInv(UnitId__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {UnitId__DEVICE_EXTENSIONInv(x)} UnitId__DEVICE_EXTENSION(UnitId__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_UnitId__DEVICE_EXTENSION(S)[x]} _S_UnitId__DEVICE_EXTENSION(S)[x] <==> S[UnitId__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_UnitId__DEVICE_EXTENSIONInv(S)[x]} _S_UnitId__DEVICE_EXTENSIONInv(S)[x] <==> S[UnitId__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_UnitId__DEVICE_EXTENSION(S)} S[x] ==> _S_UnitId__DEVICE_EXTENSION(S)[UnitId__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_UnitId__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_UnitId__DEVICE_EXTENSIONInv(S)[UnitId__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {UnitId__DEVICE_EXTENSION(x)} UnitId__DEVICE_EXTENSION(x) == x + 196);
+axiom (forall x:int :: {UnitId__DEVICE_EXTENSIONInv(x)} UnitId__DEVICE_EXTENSIONInv(x) == x - 196);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 196, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 196, 1) == UnitId__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 196)} MINUS_LEFT_PTR(x, 1, 196) == UnitId__DEVICE_EXTENSIONInv(x));
+function MINUS_BOTH_PTR_OR_BOTH_INT(a:int, b:int, size:int) returns (int);
+axiom (forall a:int, b:int, size:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(a,b,size)}
+size * MINUS_BOTH_PTR_OR_BOTH_INT(a,b,size) <= a - b && a - b < size * (MINUS_BOTH_PTR_OR_BOTH_INT(a,b,size) + 1));
+
+function MINUS_LEFT_PTR(a:int, a_size:int, b:int) returns (int);
+axiom(forall a:int, a_size:int, b:int :: {MINUS_LEFT_PTR(a,a_size,b)} MINUS_LEFT_PTR(a,a_size,b) == a - a_size * b);
+
+function PLUS(a:int, a_size:int, b:int) returns (int);
+axiom (forall a:int, a_size:int, b:int :: {PLUS(a,a_size,b)} PLUS(a,a_size,b) == a + a_size * b);
+
+function MULT(a:int, b:int) returns (int); // a*b
+axiom(forall a:int, b:int :: {MULT(a,b)} MULT(a,b) == a * b);
+
+function DIV(a:int, b:int) returns (int); // a/b
+
+axiom(forall a:int, b:int :: {DIV(a,b)}
+a >= 0 && b > 0 ==> b * DIV(a,b) <= a && a < b * (DIV(a,b) + 1)
+);
+
+axiom(forall a:int, b:int :: {DIV(a,b)}
+a >= 0 && b < 0 ==> b * DIV(a,b) <= a && a < b * (DIV(a,b) - 1)
+);
+
+axiom(forall a:int, b:int :: {DIV(a,b)}
+a < 0 && b > 0 ==> b * DIV(a,b) >= a && a > b * (DIV(a,b) - 1)
+);
+
+axiom(forall a:int, b:int :: {DIV(a,b)}
+a < 0 && b < 0 ==> b * DIV(a,b) >= a && a > b * (DIV(a,b) + 1)
+);
+
+function BINARY_BOTH_INT(a:int, b:int) returns (int);
+
+function POW2(a:int) returns (bool);
+axiom POW2(1);
+axiom POW2(2);
+axiom POW2(4);
+axiom POW2(8);
+axiom POW2(16);
+axiom POW2(32);
+axiom POW2(64);
+axiom POW2(128);
+axiom POW2(256);
+axiom POW2(512);
+axiom POW2(1024);
+axiom POW2(2048);
+axiom POW2(4096);
+axiom POW2(8192);
+axiom POW2(16384);
+axiom POW2(32768);
+axiom POW2(65536);
+axiom POW2(131072);
+axiom POW2(262144);
+axiom POW2(524288);
+axiom POW2(1048576);
+axiom POW2(2097152);
+axiom POW2(4194304);
+axiom POW2(8388608);
+axiom POW2(16777216);
+axiom POW2(33554432);
+
+function choose(a:bool, b:int, c:int) returns (x:int);
+axiom(forall a:bool, b:int, c:int :: {choose(a,b,c)} a ==> choose(a,b,c) == b);
+axiom(forall a:bool, b:int, c:int :: {choose(a,b,c)} !a ==> choose(a,b,c) == c);
+
+function BIT_BAND(a:int, b:int) returns (x:int);
+axiom(forall a:int, b:int :: {BIT_BAND(a,b)} a == b ==> BIT_BAND(a,b) == a);
+axiom(forall a:int, b:int :: {BIT_BAND(a,b)} POW2(a) && POW2(b) && a != b ==> BIT_BAND(a,b) == 0);
+axiom(forall a:int, b:int :: {BIT_BAND(a,b)} a == 0 || b == 0 ==> BIT_BAND(a,b) == 0);
+
+function BIT_BOR(a:int, b:int) returns (x:int);
+
+function BIT_BXOR(a:int, b:int) returns (x:int);
+
+function BIT_BNOT(a:int) returns (int);
+
+function LIFT(a:bool) returns (int);
+axiom(forall a:bool :: {LIFT(a)} a <==> LIFT(a) != 0);
+
+function NOT(a:int) returns (int);
+axiom(forall a:int :: {NOT(a)} a == 0 ==> NOT(a) != 0);
+axiom(forall a:int :: {NOT(a)} a != 0 ==> NOT(a) == 0);
+
+function NULL_CHECK(a:int) returns (int);
+axiom(forall a:int :: {NULL_CHECK(a)} a == 0 ==> NULL_CHECK(a) != 0);
+axiom(forall a:int :: {NULL_CHECK(a)} a != 0 ==> NULL_CHECK(a) == 0);
+
+
+
+
+procedure havoc_assert(i:int);
+requires (i != 0);
+
+procedure havoc_assume(i:int);
+ensures (i != 0);
+
+procedure __HAVOC_free(a:int);
+modifies alloc;
+ensures (forall x:int :: {alloc[x]} x == a || old(alloc)[x] == alloc[x]);
+ensures (alloc[a] == FREED);
+// Additional checks guarded by tranlator flags
+// requires alloc[a] == ALLOCATED;
+// requires Base(a) == a;
+
+procedure __HAVOC_malloc(obj_size:int) returns (new:int);
+requires obj_size >= 0;
+modifies alloc;
+ensures (new > 0);
+ensures (forall x:int :: {Base(x)} new <= x && x < new+obj_size ==> Base(x) == new);
+ensures (forall x:int :: {alloc[x]} x == new || old(alloc)[x] == alloc[x]);
+ensures old(alloc)[new] == UNALLOCATED && alloc[new] == ALLOCATED;
+
+procedure nondet_choice() returns (x:int);
+
+procedure _strdup(str:int) returns (new:int);
+
+procedure _xstrcasecmp(a0:int, a1:int) returns (ret:int);
+
+procedure _xstrcmp(a0:int, a1:int) returns (ret:int);
+
+var Res_DEVICE_STACK:[int]int;
+var Res_DEV_EXTN:[int]int;
+var Res_DEV_OBJ_INIT:[int]int;
+var Res_SPIN_LOCK:[int]int;
+
+
+
+////////////////////
+// Between predicate
+////////////////////
+function ReachBetween(f: [int]int, x: int, y: int, z: int) returns (bool);
+function ReachAvoiding(f: [int]int, x: int, y: int, z: int) returns (bool);
+
+
+//////////////////////////
+// Between set constructor
+//////////////////////////
+function ReachBetweenSet(f: [int]int, x: int, z: int) returns ([int]bool);
+
+////////////////////////////////////////////////////
+// axioms relating ReachBetween and ReachBetweenSet
+////////////////////////////////////////////////////
+axiom(forall f: [int]int, x: int, y: int, z: int :: {ReachBetweenSet(f, x, z)[y]} ReachBetweenSet(f, x, z)[y] <==> ReachBetween(f, x, y, z));
+axiom(forall f: [int]int, x: int, y: int, z: int :: {ReachBetween(f, x, y, z), ReachBetweenSet(f, x, z)} ReachBetween(f, x, y, z) ==> ReachBetweenSet(f, x, z)[y]);
+axiom(forall f: [int]int, x: int, z: int :: {ReachBetweenSet(f, x, z)} ReachBetween(f, x, x, x));
+
+
+//////////////////////////
+// Axioms for ReachBetween
+//////////////////////////
+
+// reflexive
+axiom(forall f: [int]int, x: int :: ReachBetween(f, x, x, x));
+
+// step
+//axiom(forall f: [int]int, x: int :: {f[x]} ReachBetween(f, x, f[x], f[x]));
+axiom(forall f: [int]int, x: int, y: int, z: int, w:int :: {ReachBetween(f, y, z, w), f[x]} ReachBetween(f, x, f[x], f[x]));
+
+// reach
+axiom(forall f: [int]int, x: int, y: int :: {f[x], ReachBetween(f, x, y, y)} ReachBetween(f, x, y, y) ==> x == y || ReachBetween(f, x, f[x], y));
+
+// cycle
+axiom(forall f: [int]int, x: int, y:int :: {f[x], ReachBetween(f, x, y, y)} f[x] == x && ReachBetween(f, x, y, y) ==> x == y);
+
+// sandwich
+axiom(forall f: [int]int, x: int, y: int :: {ReachBetween(f, x, y, x)} ReachBetween(f, x, y, x) ==> x == y);
+
+// order1
+axiom(forall f: [int]int, x: int, y: int, z: int :: {ReachBetween(f, x, y, y), ReachBetween(f, x, z, z)} ReachBetween(f, x, y, y) && ReachBetween(f, x, z, z) ==> ReachBetween(f, x, y, z) || ReachBetween(f, x, z, y));
+
+// order2
+axiom(forall f: [int]int, x: int, y: int, z: int :: {ReachBetween(f, x, y, z)} ReachBetween(f, x, y, z) ==> ReachBetween(f, x, y, y) && ReachBetween(f, y, z, z));
+
+// transitive1
+axiom(forall f: [int]int, x: int, y: int, z: int :: {ReachBetween(f, x, y, y), ReachBetween(f, y, z, z)} ReachBetween(f, x, y, y) && ReachBetween(f, y, z, z) ==> ReachBetween(f, x, z, z));
+
+// transitive2
+axiom(forall f: [int]int, x: int, y: int, z: int, w: int :: {ReachBetween(f, x, y, z), ReachBetween(f, y, w, z)} ReachBetween(f, x, y, z) && ReachBetween(f, y, w, z) ==> ReachBetween(f, x, y, w) && ReachBetween(f, x, w, z));
+
+// transitive3
+axiom(forall f: [int]int, x: int, y: int, z: int, w: int :: {ReachBetween(f, x, y, z), ReachBetween(f, x, w, y)} ReachBetween(f, x, y, z) && ReachBetween(f, x, w, y) ==> ReachBetween(f, x, w, z) && ReachBetween(f, w, y, z));
+
+// This axiom is required to deal with the incompleteness of the trigger for the reflexive axiom.
+// It cannot be proved using the rest of the axioms.
+axiom(forall f: [int]int, u:int, x: int :: {ReachBetween(f, u, x, x)} ReachBetween(f, u, x, x) ==> ReachBetween(f, u, u, x));
+
+// relation between ReachAvoiding and ReachBetween
+axiom(forall f: [int]int, x: int, y: int, z: int :: {ReachAvoiding(f, x, y, z)}{ReachBetween(f, x, y, z)} ReachAvoiding(f, x, y, z) <==> (ReachBetween(f, x, y, z) || (ReachBetween(f, x, y, y) && !ReachBetween(f, x, z, z))));
+
+// update
+axiom(forall f: [int]int, u: int, v: int, x: int, p: int, q: int :: {ReachAvoiding(f[p := q], u, v, x)} ReachAvoiding(f[p := q], u, v, x) <==> ((ReachAvoiding(f, u, v, p) && ReachAvoiding(f, u, v, x)) || (ReachAvoiding(f, u, p, x) && p != x && ReachAvoiding(f, q, v, p) && ReachAvoiding(f, q, v, x))));
+ ///////////////////////////////
+ // Shifts for linking fields
+ ///////////////////////////////
+function Shift_Flink__LIST_ENTRY(f: [int]int) returns ([int]int);
+axiom( forall f: [int]int, __x:int :: {f[Flink__LIST_ENTRY(__x)],Shift_Flink__LIST_ENTRY(f)} {Shift_Flink__LIST_ENTRY(f)[__x]} Shift_Flink__LIST_ENTRY(f)[__x] == f[Flink__LIST_ENTRY(__x)]);
+axiom(forall f: [int]int, __x:int, __v:int :: {Shift_Flink__LIST_ENTRY(f[Flink__LIST_ENTRY(__x) := __v])} Shift_Flink__LIST_ENTRY(f[Flink__LIST_ENTRY(__x) := __v]) == Shift_Flink__LIST_ENTRY(f)[__x := __v]);
+
+const unique Globals : int;
+axiom(Globals != 0);
+// the set of constants for 64 bit integers that Boogie doesn't parse
+const unique BOOGIE_LARGE_INT_3221553153:int;
+
+
+
+procedure ExAcquireFastMutex($FastMutex$1$15000.16$ExAcquireFastMutex$41:int);
+
+//TAG: ensures __preserves_mem
+ensures(Mem == old(Mem));
+//TAG: ensures __preserves_resource("DEV_OBJ_INIT") && __preserves_resource("DEV_EXTN")
+ensures((Res_DEV_OBJ_INIT == old(Res_DEV_OBJ_INIT)) && (Res_DEV_EXTN == old(Res_DEV_EXTN)));
+
+modifies Res_DEVICE_STACK;
+
+//TAG: net change in resource DEVICE_STACK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEVICE_STACK[r]} (Empty()[r]) || old(Res_DEVICE_STACK)[r] == Res_DEVICE_STACK[r]));
+modifies Res_DEV_EXTN;
+
+//TAG: net change in resource DEV_EXTN only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_EXTN[r]} (Empty()[r]) || old(Res_DEV_EXTN)[r] == Res_DEV_EXTN[r]));
+modifies Res_DEV_OBJ_INIT;
+
+//TAG: net change in resource DEV_OBJ_INIT only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_OBJ_INIT[r]} (Empty()[r]) || old(Res_DEV_OBJ_INIT)[r] == Res_DEV_OBJ_INIT[r]));
+modifies Res_SPIN_LOCK;
+
+//TAG: net change in resource SPIN_LOCK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_SPIN_LOCK[r]} (Empty()[r]) || old(Res_SPIN_LOCK)[r] == Res_SPIN_LOCK[r]));
+//TAG: updated memory locations at Mem[T.MinorFunction__IO_STACK_LOCATION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.MinorFunction__IO_STACK_LOCATION][_m]} (Empty()[_m]) || Mem[T.MinorFunction__IO_STACK_LOCATION][_m] == old(Mem)[T.MinorFunction__IO_STACK_LOCATION][_m]));
+//TAG: updated memory locations at Mem[T.CurrentStackLocation___unnamed_4_f19b65c1] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.CurrentStackLocation___unnamed_4_f19b65c1][_m]} (Empty()[_m]) || Mem[T.CurrentStackLocation___unnamed_4_f19b65c1][_m] == old(Mem)[T.CurrentStackLocation___unnamed_4_f19b65c1][_m]));
+//TAG: updated memory locations at Mem[T.DeviceExtension__DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.DeviceExtension__DEVICE_OBJECT][_m] == old(Mem)[T.DeviceExtension__DEVICE_OBJECT][_m]));
+//TAG: updated memory locations at Mem[T.Self__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Self__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Self__DEVICE_EXTENSION][_m] == old(Mem)[T.Self__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.Started__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Started__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Started__DEVICE_EXTENSION][_m] == old(Mem)[T.Started__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.GrandMaster__GLOBALS] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.GrandMaster__GLOBALS][_m]} (Empty()[_m]) || Mem[T.GrandMaster__GLOBALS][_m] == old(Mem)[T.GrandMaster__GLOBALS][_m]));
+//TAG: updated memory locations at Mem[T.P_DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.P_DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.P_DEVICE_OBJECT][_m] == old(Mem)[T.P_DEVICE_OBJECT][_m]));
+
+//TAG: havoc memory locations by default
+modifies Mem;
+
+
+procedure ExAllocatePoolWithTag($PoolType$1$14789.57$ExAllocatePoolWithTag$121:int, $NumberOfBytes$2$14790.16$ExAllocatePoolWithTag$121:int, $Tag$3$14791.15$ExAllocatePoolWithTag$121:int) returns ($result.ExAllocatePoolWithTag$14788.0$1$:int);
+
+//TAG: ensures __preserves_mem
+ensures(Mem == old(Mem));
+//TAG: ensures __preserves_resource("DEV_OBJ_INIT") && __preserves_resource("DEV_EXTN")
+ensures((Res_DEV_OBJ_INIT == old(Res_DEV_OBJ_INIT)) && (Res_DEV_EXTN == old(Res_DEV_EXTN)));
+
+modifies Res_DEVICE_STACK;
+
+//TAG: net change in resource DEVICE_STACK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEVICE_STACK[r]} (Empty()[r]) || old(Res_DEVICE_STACK)[r] == Res_DEVICE_STACK[r]));
+modifies Res_DEV_EXTN;
+
+//TAG: net change in resource DEV_EXTN only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_EXTN[r]} (Empty()[r]) || old(Res_DEV_EXTN)[r] == Res_DEV_EXTN[r]));
+modifies Res_DEV_OBJ_INIT;
+
+//TAG: net change in resource DEV_OBJ_INIT only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_OBJ_INIT[r]} (Empty()[r]) || old(Res_DEV_OBJ_INIT)[r] == Res_DEV_OBJ_INIT[r]));
+modifies Res_SPIN_LOCK;
+
+//TAG: net change in resource SPIN_LOCK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_SPIN_LOCK[r]} (Empty()[r]) || old(Res_SPIN_LOCK)[r] == Res_SPIN_LOCK[r]));
+//TAG: updated memory locations at Mem[T.MinorFunction__IO_STACK_LOCATION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.MinorFunction__IO_STACK_LOCATION][_m]} (Empty()[_m]) || Mem[T.MinorFunction__IO_STACK_LOCATION][_m] == old(Mem)[T.MinorFunction__IO_STACK_LOCATION][_m]));
+//TAG: updated memory locations at Mem[T.CurrentStackLocation___unnamed_4_f19b65c1] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.CurrentStackLocation___unnamed_4_f19b65c1][_m]} (Empty()[_m]) || Mem[T.CurrentStackLocation___unnamed_4_f19b65c1][_m] == old(Mem)[T.CurrentStackLocation___unnamed_4_f19b65c1][_m]));
+//TAG: updated memory locations at Mem[T.DeviceExtension__DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.DeviceExtension__DEVICE_OBJECT][_m] == old(Mem)[T.DeviceExtension__DEVICE_OBJECT][_m]));
+//TAG: updated memory locations at Mem[T.Self__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Self__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Self__DEVICE_EXTENSION][_m] == old(Mem)[T.Self__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.Started__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Started__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Started__DEVICE_EXTENSION][_m] == old(Mem)[T.Started__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.GrandMaster__GLOBALS] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.GrandMaster__GLOBALS][_m]} (Empty()[_m]) || Mem[T.GrandMaster__GLOBALS][_m] == old(Mem)[T.GrandMaster__GLOBALS][_m]));
+//TAG: updated memory locations at Mem[T.P_DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.P_DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.P_DEVICE_OBJECT][_m] == old(Mem)[T.P_DEVICE_OBJECT][_m]));
+
+//TAG: havoc memory locations by default
+modifies Mem;
+
+
+procedure ExFreePoolWithTag($P$1$14901.35$ExFreePoolWithTag$81:int, $Tag$2$14902.15$ExFreePoolWithTag$81:int);
+
+//TAG: ensures __preserves_mem
+ensures(Mem == old(Mem));
+//TAG: ensures __preserves_resource("DEV_OBJ_INIT") && __preserves_resource("DEV_EXTN")
+ensures((Res_DEV_OBJ_INIT == old(Res_DEV_OBJ_INIT)) && (Res_DEV_EXTN == old(Res_DEV_EXTN)));
+
+modifies Res_DEVICE_STACK;
+
+//TAG: net change in resource DEVICE_STACK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEVICE_STACK[r]} (Empty()[r]) || old(Res_DEVICE_STACK)[r] == Res_DEVICE_STACK[r]));
+modifies Res_DEV_EXTN;
+
+//TAG: net change in resource DEV_EXTN only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_EXTN[r]} (Empty()[r]) || old(Res_DEV_EXTN)[r] == Res_DEV_EXTN[r]));
+modifies Res_DEV_OBJ_INIT;
+
+//TAG: net change in resource DEV_OBJ_INIT only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_OBJ_INIT[r]} (Empty()[r]) || old(Res_DEV_OBJ_INIT)[r] == Res_DEV_OBJ_INIT[r]));
+modifies Res_SPIN_LOCK;
+
+//TAG: net change in resource SPIN_LOCK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_SPIN_LOCK[r]} (Empty()[r]) || old(Res_SPIN_LOCK)[r] == Res_SPIN_LOCK[r]));
+//TAG: updated memory locations at Mem[T.MinorFunction__IO_STACK_LOCATION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.MinorFunction__IO_STACK_LOCATION][_m]} (Empty()[_m]) || Mem[T.MinorFunction__IO_STACK_LOCATION][_m] == old(Mem)[T.MinorFunction__IO_STACK_LOCATION][_m]));
+//TAG: updated memory locations at Mem[T.CurrentStackLocation___unnamed_4_f19b65c1] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.CurrentStackLocation___unnamed_4_f19b65c1][_m]} (Empty()[_m]) || Mem[T.CurrentStackLocation___unnamed_4_f19b65c1][_m] == old(Mem)[T.CurrentStackLocation___unnamed_4_f19b65c1][_m]));
+//TAG: updated memory locations at Mem[T.DeviceExtension__DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.DeviceExtension__DEVICE_OBJECT][_m] == old(Mem)[T.DeviceExtension__DEVICE_OBJECT][_m]));
+//TAG: updated memory locations at Mem[T.Self__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Self__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Self__DEVICE_EXTENSION][_m] == old(Mem)[T.Self__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.Started__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Started__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Started__DEVICE_EXTENSION][_m] == old(Mem)[T.Started__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.GrandMaster__GLOBALS] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.GrandMaster__GLOBALS][_m]} (Empty()[_m]) || Mem[T.GrandMaster__GLOBALS][_m] == old(Mem)[T.GrandMaster__GLOBALS][_m]));
+//TAG: updated memory locations at Mem[T.P_DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.P_DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.P_DEVICE_OBJECT][_m] == old(Mem)[T.P_DEVICE_OBJECT][_m]));
+
+//TAG: havoc memory locations by default
+modifies Mem;
+
+
+procedure ExReleaseFastMutex($FastMutex$1$15013.16$ExReleaseFastMutex$41:int);
+
+//TAG: ensures __preserves_mem
+ensures(Mem == old(Mem));
+//TAG: ensures __preserves_resource("DEV_OBJ_INIT") && __preserves_resource("DEV_EXTN")
+ensures((Res_DEV_OBJ_INIT == old(Res_DEV_OBJ_INIT)) && (Res_DEV_EXTN == old(Res_DEV_EXTN)));
+
+modifies Res_DEVICE_STACK;
+
+//TAG: net change in resource DEVICE_STACK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEVICE_STACK[r]} (Empty()[r]) || old(Res_DEVICE_STACK)[r] == Res_DEVICE_STACK[r]));
+modifies Res_DEV_EXTN;
+
+//TAG: net change in resource DEV_EXTN only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_EXTN[r]} (Empty()[r]) || old(Res_DEV_EXTN)[r] == Res_DEV_EXTN[r]));
+modifies Res_DEV_OBJ_INIT;
+
+//TAG: net change in resource DEV_OBJ_INIT only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_OBJ_INIT[r]} (Empty()[r]) || old(Res_DEV_OBJ_INIT)[r] == Res_DEV_OBJ_INIT[r]));
+modifies Res_SPIN_LOCK;
+
+//TAG: net change in resource SPIN_LOCK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_SPIN_LOCK[r]} (Empty()[r]) || old(Res_SPIN_LOCK)[r] == Res_SPIN_LOCK[r]));
+//TAG: updated memory locations at Mem[T.MinorFunction__IO_STACK_LOCATION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.MinorFunction__IO_STACK_LOCATION][_m]} (Empty()[_m]) || Mem[T.MinorFunction__IO_STACK_LOCATION][_m] == old(Mem)[T.MinorFunction__IO_STACK_LOCATION][_m]));
+//TAG: updated memory locations at Mem[T.CurrentStackLocation___unnamed_4_f19b65c1] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.CurrentStackLocation___unnamed_4_f19b65c1][_m]} (Empty()[_m]) || Mem[T.CurrentStackLocation___unnamed_4_f19b65c1][_m] == old(Mem)[T.CurrentStackLocation___unnamed_4_f19b65c1][_m]));
+//TAG: updated memory locations at Mem[T.DeviceExtension__DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.DeviceExtension__DEVICE_OBJECT][_m] == old(Mem)[T.DeviceExtension__DEVICE_OBJECT][_m]));
+//TAG: updated memory locations at Mem[T.Self__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Self__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Self__DEVICE_EXTENSION][_m] == old(Mem)[T.Self__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.Started__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Started__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Started__DEVICE_EXTENSION][_m] == old(Mem)[T.Started__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.GrandMaster__GLOBALS] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.GrandMaster__GLOBALS][_m]} (Empty()[_m]) || Mem[T.GrandMaster__GLOBALS][_m] == old(Mem)[T.GrandMaster__GLOBALS][_m]));
+//TAG: updated memory locations at Mem[T.P_DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.P_DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.P_DEVICE_OBJECT][_m] == old(Mem)[T.P_DEVICE_OBJECT][_m]));
+
+//TAG: havoc memory locations by default
+modifies Mem;
+
+
+procedure InsertTailList($ListHead$1$6980.24$InsertTailList$81:int, $Entry$2$6981.41$InsertTailList$81:int);
+
+//TAG: ensures __preserves_resource("DEV_OBJ_INIT") && __preserves_resource("DEV_EXTN")
+ensures((Res_DEV_OBJ_INIT == old(Res_DEV_OBJ_INIT)) && (Res_DEV_EXTN == old(Res_DEV_EXTN)));
+//TAG: ensures __seteq(__btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), ListHead->Flink, ListHead), __setunion(__old(__btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), ListHead->Flink, ListHead)), __set(Entry)))
+ensures((Subset(ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY($ListHead$1$6980.24$InsertTailList$81)], $ListHead$1$6980.24$InsertTailList$81), Union(ReachBetweenSet(Shift_Flink__LIST_ENTRY(old(Mem)[T.Flink__LIST_ENTRY]), old(Mem)[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY($ListHead$1$6980.24$InsertTailList$81)], $ListHead$1$6980.24$InsertTailList$81), Singleton($Entry$2$6981.41$InsertTailList$81))) && Subset(Union(ReachBetweenSet(Shift_Flink__LIST_ENTRY(old(Mem)[T.Flink__LIST_ENTRY]), old(Mem)[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY($ListHead$1$6980.24$InsertTailList$81)], $ListHead$1$6980.24$InsertTailList$81), Singleton($Entry$2$6981.41$InsertTailList$81)), ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY($ListHead$1$6980.24$InsertTailList$81)], $ListHead$1$6980.24$InsertTailList$81))));
+
+modifies Res_DEVICE_STACK;
+
+//TAG: net change in resource DEVICE_STACK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEVICE_STACK[r]} (Empty()[r]) || old(Res_DEVICE_STACK)[r] == Res_DEVICE_STACK[r]));
+modifies Res_DEV_EXTN;
+
+//TAG: net change in resource DEV_EXTN only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_EXTN[r]} (Empty()[r]) || old(Res_DEV_EXTN)[r] == Res_DEV_EXTN[r]));
+modifies Res_DEV_OBJ_INIT;
+
+//TAG: net change in resource DEV_OBJ_INIT only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_OBJ_INIT[r]} (Empty()[r]) || old(Res_DEV_OBJ_INIT)[r] == Res_DEV_OBJ_INIT[r]));
+modifies Res_SPIN_LOCK;
+
+//TAG: net change in resource SPIN_LOCK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_SPIN_LOCK[r]} (Empty()[r]) || old(Res_SPIN_LOCK)[r] == Res_SPIN_LOCK[r]));
+//TAG: updated memory locations at Mem[T.MinorFunction__IO_STACK_LOCATION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.MinorFunction__IO_STACK_LOCATION][_m]} (Empty()[_m]) || Mem[T.MinorFunction__IO_STACK_LOCATION][_m] == old(Mem)[T.MinorFunction__IO_STACK_LOCATION][_m]));
+//TAG: updated memory locations at Mem[T.CurrentStackLocation___unnamed_4_f19b65c1] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.CurrentStackLocation___unnamed_4_f19b65c1][_m]} (Empty()[_m]) || Mem[T.CurrentStackLocation___unnamed_4_f19b65c1][_m] == old(Mem)[T.CurrentStackLocation___unnamed_4_f19b65c1][_m]));
+//TAG: updated memory locations at Mem[T.DeviceExtension__DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.DeviceExtension__DEVICE_OBJECT][_m] == old(Mem)[T.DeviceExtension__DEVICE_OBJECT][_m]));
+//TAG: updated memory locations at Mem[T.Self__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Self__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Self__DEVICE_EXTENSION][_m] == old(Mem)[T.Self__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.Started__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Started__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Started__DEVICE_EXTENSION][_m] == old(Mem)[T.Started__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.GrandMaster__GLOBALS] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.GrandMaster__GLOBALS][_m]} (Empty()[_m]) || Mem[T.GrandMaster__GLOBALS][_m] == old(Mem)[T.GrandMaster__GLOBALS][_m]));
+//TAG: updated memory locations at Mem[T.P_DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.P_DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.P_DEVICE_OBJECT][_m] == old(Mem)[T.P_DEVICE_OBJECT][_m]));
+
+//TAG: havoc memory locations by default
+modifies Mem;
+
+
+procedure IoDeleteDevice($DeviceObject$1$21328.67$IoDeleteDevice$41:int);
+
+//TAG: ensures __preserves_mem
+ensures(Mem == old(Mem));
+//TAG: requires 1 ==> __resource("DEV_OBJ_INIT", DeviceObject) == 1 && __resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)DeviceObject)->DeviceExtension)) == 1
+requires((true) ==> ((Res_DEV_OBJ_INIT[$DeviceObject$1$21328.67$IoDeleteDevice$41] == 1) && (Res_DEV_EXTN[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT($DeviceObject$1$21328.67$IoDeleteDevice$41)]] == 1)));
+//TAG: ensures 1 ==> __resource("DEV_OBJ_INIT", DeviceObject) == 0 && __resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)DeviceObject)->DeviceExtension)) == 0
+ensures((true) ==> ((Res_DEV_OBJ_INIT[$DeviceObject$1$21328.67$IoDeleteDevice$41] == 0) && (Res_DEV_EXTN[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT($DeviceObject$1$21328.67$IoDeleteDevice$41)]] == 0)));
+//TAG: ensures 1 ==> __updates_resource("DEV_OBJ_INIT", DeviceObject, 0) && __updates_resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)DeviceObject)->DeviceExtension), 0)
+ensures((true) ==> ((Res_DEV_OBJ_INIT == old(Res_DEV_OBJ_INIT)[$DeviceObject$1$21328.67$IoDeleteDevice$41 := 0]) && (Res_DEV_EXTN == old(Res_DEV_EXTN)[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT($DeviceObject$1$21328.67$IoDeleteDevice$41)] := 0])));
+//TAG: ensures !1 ==> __resource("DEV_OBJ_INIT", DeviceObject) == __old_resource("DEV_OBJ_INIT", DeviceObject) && __resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)DeviceObject)->DeviceExtension)) == __old_resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)DeviceObject)->DeviceExtension))
+ensures((!(true)) ==> ((Res_DEV_OBJ_INIT[$DeviceObject$1$21328.67$IoDeleteDevice$41] == old(Res_DEV_OBJ_INIT)[$DeviceObject$1$21328.67$IoDeleteDevice$41]) && (Res_DEV_EXTN[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT($DeviceObject$1$21328.67$IoDeleteDevice$41)]] == old(Res_DEV_EXTN)[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT($DeviceObject$1$21328.67$IoDeleteDevice$41)]])));
+//TAG: ensures !1 ==> __preserves_resource("DEV_OBJ_INIT") && __preserves_resource("DEV_EXTN")
+free ensures((!(true)) ==> ((Res_DEV_OBJ_INIT == old(Res_DEV_OBJ_INIT)) && (Res_DEV_EXTN == old(Res_DEV_EXTN))));
+
+modifies Res_DEVICE_STACK;
+
+//TAG: net change in resource DEVICE_STACK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEVICE_STACK[r]} (Empty()[r]) || old(Res_DEVICE_STACK)[r] == Res_DEVICE_STACK[r]));
+modifies Res_DEV_EXTN;
+
+//TAG: net change in resource DEV_EXTN only for: __set_empty, (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)DeviceObject)->DeviceExtension)
+ensures (Subset(Empty(), Union(Union(Empty(), Empty()), Singleton(Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT($DeviceObject$1$21328.67$IoDeleteDevice$41)]))) && (forall r:int :: {Res_DEV_EXTN[r]} (Empty()[r]) || (Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT($DeviceObject$1$21328.67$IoDeleteDevice$41)] == r) || old(Res_DEV_EXTN)[r] == Res_DEV_EXTN[r]));
+modifies Res_DEV_OBJ_INIT;
+
+//TAG: net change in resource DEV_OBJ_INIT only for: __set_empty, DeviceObject
+ensures (Subset(Empty(), Union(Union(Empty(), Empty()), Singleton($DeviceObject$1$21328.67$IoDeleteDevice$41))) && (forall r:int :: {Res_DEV_OBJ_INIT[r]} (Empty()[r]) || ($DeviceObject$1$21328.67$IoDeleteDevice$41 == r) || old(Res_DEV_OBJ_INIT)[r] == Res_DEV_OBJ_INIT[r]));
+modifies Res_SPIN_LOCK;
+
+//TAG: net change in resource SPIN_LOCK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_SPIN_LOCK[r]} (Empty()[r]) || old(Res_SPIN_LOCK)[r] == Res_SPIN_LOCK[r]));
+//TAG: updated memory locations at Mem[T.MinorFunction__IO_STACK_LOCATION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.MinorFunction__IO_STACK_LOCATION][_m]} (Empty()[_m]) || Mem[T.MinorFunction__IO_STACK_LOCATION][_m] == old(Mem)[T.MinorFunction__IO_STACK_LOCATION][_m]));
+//TAG: updated memory locations at Mem[T.CurrentStackLocation___unnamed_4_f19b65c1] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.CurrentStackLocation___unnamed_4_f19b65c1][_m]} (Empty()[_m]) || Mem[T.CurrentStackLocation___unnamed_4_f19b65c1][_m] == old(Mem)[T.CurrentStackLocation___unnamed_4_f19b65c1][_m]));
+//TAG: updated memory locations at Mem[T.DeviceExtension__DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.DeviceExtension__DEVICE_OBJECT][_m] == old(Mem)[T.DeviceExtension__DEVICE_OBJECT][_m]));
+//TAG: updated memory locations at Mem[T.Self__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Self__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Self__DEVICE_EXTENSION][_m] == old(Mem)[T.Self__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.Started__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Started__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Started__DEVICE_EXTENSION][_m] == old(Mem)[T.Started__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.GrandMaster__GLOBALS] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.GrandMaster__GLOBALS][_m]} (Empty()[_m]) || Mem[T.GrandMaster__GLOBALS][_m] == old(Mem)[T.GrandMaster__GLOBALS][_m]));
+//TAG: updated memory locations at Mem[T.P_DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.P_DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.P_DEVICE_OBJECT][_m] == old(Mem)[T.P_DEVICE_OBJECT][_m]));
+
+//TAG: havoc memory locations by default
+modifies Mem;
+
+
+procedure IoGetDeviceObjectPointer($ObjectName$1$21492.26$IoGetDeviceObjectPointer$161:int, $DesiredAccess$2$21493.22$IoGetDeviceObjectPointer$161:int, $FileObject$3$21494.24$IoGetDeviceObjectPointer$161:int, $DeviceObject$4$21495.26$IoGetDeviceObjectPointer$161:int) returns ($result.IoGetDeviceObjectPointer$21491.0$1$:int);
+
+//TAG: ensures __preserves_mem
+ensures(Mem == old(Mem));
+//TAG: ensures __preserves_resource("DEV_OBJ_INIT") && __preserves_resource("DEV_EXTN")
+ensures((Res_DEV_OBJ_INIT == old(Res_DEV_OBJ_INIT)) && (Res_DEV_EXTN == old(Res_DEV_EXTN)));
+
+modifies Res_DEVICE_STACK;
+
+//TAG: net change in resource DEVICE_STACK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEVICE_STACK[r]} (Empty()[r]) || old(Res_DEVICE_STACK)[r] == Res_DEVICE_STACK[r]));
+modifies Res_DEV_EXTN;
+
+//TAG: net change in resource DEV_EXTN only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_EXTN[r]} (Empty()[r]) || old(Res_DEV_EXTN)[r] == Res_DEV_EXTN[r]));
+modifies Res_DEV_OBJ_INIT;
+
+//TAG: net change in resource DEV_OBJ_INIT only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_OBJ_INIT[r]} (Empty()[r]) || old(Res_DEV_OBJ_INIT)[r] == Res_DEV_OBJ_INIT[r]));
+modifies Res_SPIN_LOCK;
+
+//TAG: net change in resource SPIN_LOCK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_SPIN_LOCK[r]} (Empty()[r]) || old(Res_SPIN_LOCK)[r] == Res_SPIN_LOCK[r]));
+//TAG: updated memory locations at Mem[T.MinorFunction__IO_STACK_LOCATION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.MinorFunction__IO_STACK_LOCATION][_m]} (Empty()[_m]) || Mem[T.MinorFunction__IO_STACK_LOCATION][_m] == old(Mem)[T.MinorFunction__IO_STACK_LOCATION][_m]));
+//TAG: updated memory locations at Mem[T.CurrentStackLocation___unnamed_4_f19b65c1] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.CurrentStackLocation___unnamed_4_f19b65c1][_m]} (Empty()[_m]) || Mem[T.CurrentStackLocation___unnamed_4_f19b65c1][_m] == old(Mem)[T.CurrentStackLocation___unnamed_4_f19b65c1][_m]));
+//TAG: updated memory locations at Mem[T.DeviceExtension__DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.DeviceExtension__DEVICE_OBJECT][_m] == old(Mem)[T.DeviceExtension__DEVICE_OBJECT][_m]));
+//TAG: updated memory locations at Mem[T.Self__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Self__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Self__DEVICE_EXTENSION][_m] == old(Mem)[T.Self__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.Started__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Started__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Started__DEVICE_EXTENSION][_m] == old(Mem)[T.Started__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.GrandMaster__GLOBALS] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.GrandMaster__GLOBALS][_m]} (Empty()[_m]) || Mem[T.GrandMaster__GLOBALS][_m] == old(Mem)[T.GrandMaster__GLOBALS][_m]));
+//TAG: updated memory locations at Mem[T.P_DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.P_DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.P_DEVICE_OBJECT][_m] == old(Mem)[T.P_DEVICE_OBJECT][_m]));
+
+//TAG: havoc memory locations by default
+modifies Mem;
+
+
+procedure KbdCreateClassObject($DriverObject$1$3354.28$KbdCreateClassObject$201:int, $TmpDeviceExtension$2$3355.28$KbdCreateClassObject$201:int, $ClassDeviceObject$3$3356.28$KbdCreateClassObject$201:int, $FullDeviceName$4$3357.35$KbdCreateClassObject$201:int, $Legacy$5$3358.28$KbdCreateClassObject$201:int) returns ($result.KbdCreateClassObject$3353.0$1$:int);
+
+//TAG: requires __pforall(_H_x, (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension), __inv_resource("DEV_OBJ_INIT", 1), ((struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension))->Self == _H_x && __resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension)) == 1)
+requires((forall _H_x:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)]} Inverse(Res_DEV_OBJ_INIT,1)[_H_x] ==> ((Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)])] == _H_x) && (Res_DEV_EXTN[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)]] == 1))));
+//TAG: requires __pforall(_H_z, _H_z->Self, __inv_resource("DEV_EXTN", 1), __resource("DEV_OBJ_INIT", _H_z->Self) == 1 && (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)(_H_z->Self))->DeviceExtension) == _H_z)
+requires((forall _H_z:int :: {Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)]} Inverse(Res_DEV_EXTN,1)[_H_z] ==> ((Res_DEV_OBJ_INIT[Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)]] == 1) && (Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)])] == _H_z))));
+//TAG: requires __forall(_H_z, __inv_resource("DEV_EXTN", 1), 1)
+requires((Subset(Empty(), Inverse(Res_DEV_EXTN,1)) && (forall _H_z : int :: {Inverse(Res_DEV_EXTN,1)[_H_z]} (Inverse(Res_DEV_EXTN,1)[_H_z]) ==> (true))));
+//TAG: requires 1 ==> (Globals.GrandMaster != (void *)0 ==> __resource("DEV_EXTN", Globals.GrandMaster) == 1)
+requires((true) ==> ((Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)] != 0) ==> (Res_DEV_EXTN[Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)]] == 1)));
+//TAG: requires 1 ==> __setin(&Globals.LegacyDeviceList, __btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList))
+requires((true) ==> (ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[LegacyDeviceList__GLOBALS(Globals)]));
+//TAG: requires 1 ==> __forall(_H_y, __btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList), _H_y == &Globals.LegacyDeviceList || __resource("DEV_EXTN", CONTAINING_RECORD(_H_y, struct _DEVICE_EXTENSION , Link)) == 1)
+requires((true) ==> ((Subset(Empty(), ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))) && (forall _H_y : int :: {ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[_H_y]} (ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[_H_y]) ==> ((_H_y == LegacyDeviceList__GLOBALS(Globals)) || (Res_DEV_EXTN[MINUS_LEFT_PTR(_H_y, 1, Link__DEVICE_EXTENSION(0))] == 1))))));
+//TAG: requires 1 ==> !__setin(&Globals.GrandMaster->Link, __setminus(__btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList), __set(&Globals.LegacyDeviceList)))
+requires((true) ==> (!(Difference(ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals)), Singleton(LegacyDeviceList__GLOBALS(Globals)))[Link__DEVICE_EXTENSION(Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)])])));
+//TAG: ensures __pforall(_H_x, (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension), __inv_resource("DEV_OBJ_INIT", 1), ((struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension))->Self == _H_x && __resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension)) == 1)
+ensures((forall _H_x:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)]} Inverse(Res_DEV_OBJ_INIT,1)[_H_x] ==> ((Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)])] == _H_x) && (Res_DEV_EXTN[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)]] == 1))));
+//TAG: ensures __pforall(_H_z, _H_z->Self, __inv_resource("DEV_EXTN", 1), __resource("DEV_OBJ_INIT", _H_z->Self) == 1 && (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)(_H_z->Self))->DeviceExtension) == _H_z)
+ensures((forall _H_z:int :: {Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)]} Inverse(Res_DEV_EXTN,1)[_H_z] ==> ((Res_DEV_OBJ_INIT[Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)]] == 1) && (Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)])] == _H_z))));
+//TAG: ensures __forall(_H_z, __inv_resource("DEV_EXTN", 1), 1)
+ensures((Subset(Empty(), Inverse(Res_DEV_EXTN,1)) && (forall _H_z : int :: {Inverse(Res_DEV_EXTN,1)[_H_z]} (Inverse(Res_DEV_EXTN,1)[_H_z]) ==> (true))));
+//TAG: ensures 1 ==> (Globals.GrandMaster != (void *)0 ==> __resource("DEV_EXTN", Globals.GrandMaster) == 1)
+ensures((true) ==> ((Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)] != 0) ==> (Res_DEV_EXTN[Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)]] == 1)));
+//TAG: ensures 1 ==> __setin(&Globals.LegacyDeviceList, __btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList))
+ensures((true) ==> (ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[LegacyDeviceList__GLOBALS(Globals)]));
+//TAG: ensures 1 ==> __forall(_H_y, __btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList), _H_y == &Globals.LegacyDeviceList || __resource("DEV_EXTN", CONTAINING_RECORD(_H_y, struct _DEVICE_EXTENSION , Link)) == 1)
+ensures((true) ==> ((Subset(Empty(), ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))) && (forall _H_y : int :: {ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[_H_y]} (ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[_H_y]) ==> ((_H_y == LegacyDeviceList__GLOBALS(Globals)) || (Res_DEV_EXTN[MINUS_LEFT_PTR(_H_y, 1, Link__DEVICE_EXTENSION(0))] == 1))))));
+//TAG: ensures 1 ==> !__setin(&Globals.GrandMaster->Link, __setminus(__btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList), __set(&Globals.LegacyDeviceList)))
+ensures((true) ==> (!(Difference(ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals)), Singleton(LegacyDeviceList__GLOBALS(Globals)))[Link__DEVICE_EXTENSION(Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)])])));
+//TAG: ensures __preserves_field_map(__offset((*((struct _LIST_ENTRY *)0)).Flink))
+ensures(Mem[T.Flink__LIST_ENTRY] == old(Mem)[T.Flink__LIST_ENTRY]);
+//TAG: ensures (LONG)__return >= 0 ==> *ClassDeviceObject != (void *)0
+ensures(($result.KbdCreateClassObject$3353.0$1$ >= 0) ==> (Mem[T.P_DEVICE_OBJECT][$ClassDeviceObject$3$3356.28$KbdCreateClassObject$201] != 0));
+//TAG: ensures (LONG)__return >= 0 ==> (*ClassDeviceObject)->DeviceExtension != (void *)0
+ensures(($result.KbdCreateClassObject$3353.0$1$ >= 0) ==> (Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.P_DEVICE_OBJECT][$ClassDeviceObject$3$3356.28$KbdCreateClassObject$201])] != 0));
+//TAG: ensures (LONG)__return >= 0 ==> __resource("DEV_EXTN", (*ClassDeviceObject)->DeviceExtension) == 1
+ensures(($result.KbdCreateClassObject$3353.0$1$ >= 0) ==> (Res_DEV_EXTN[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.P_DEVICE_OBJECT][$ClassDeviceObject$3$3356.28$KbdCreateClassObject$201])]] == 1));
+//TAG: ensures (LONG)__return >= 0 ==> __resource("DEV_OBJ_INIT", *ClassDeviceObject) == 1 && __resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)(*ClassDeviceObject))->DeviceExtension)) == 1
+ensures(($result.KbdCreateClassObject$3353.0$1$ >= 0) ==> ((Res_DEV_OBJ_INIT[Mem[T.P_DEVICE_OBJECT][$ClassDeviceObject$3$3356.28$KbdCreateClassObject$201]] == 1) && (Res_DEV_EXTN[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.P_DEVICE_OBJECT][$ClassDeviceObject$3$3356.28$KbdCreateClassObject$201])]] == 1)));
+//TAG: ensures (LONG)__return >= 0 ==> __old_resource("DEV_OBJ_INIT", *ClassDeviceObject) == 0 && __old_resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)(*ClassDeviceObject))->DeviceExtension)) == 0
+ensures(($result.KbdCreateClassObject$3353.0$1$ >= 0) ==> ((old(Res_DEV_OBJ_INIT)[Mem[T.P_DEVICE_OBJECT][$ClassDeviceObject$3$3356.28$KbdCreateClassObject$201]] == 0) && (old(Res_DEV_EXTN)[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.P_DEVICE_OBJECT][$ClassDeviceObject$3$3356.28$KbdCreateClassObject$201])]] == 0)));
+//TAG: ensures (LONG)__return >= 0 ==> __updates_resource("DEV_OBJ_INIT", *ClassDeviceObject, 1) && __updates_resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)(*ClassDeviceObject))->DeviceExtension), 1)
+ensures(($result.KbdCreateClassObject$3353.0$1$ >= 0) ==> ((Res_DEV_OBJ_INIT == old(Res_DEV_OBJ_INIT)[Mem[T.P_DEVICE_OBJECT][$ClassDeviceObject$3$3356.28$KbdCreateClassObject$201] := 1]) && (Res_DEV_EXTN == old(Res_DEV_EXTN)[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.P_DEVICE_OBJECT][$ClassDeviceObject$3$3356.28$KbdCreateClassObject$201])] := 1])));
+//TAG: ensures !((LONG)__return >= 0) ==> __resource("DEV_OBJ_INIT", *ClassDeviceObject) == __old_resource("DEV_OBJ_INIT", *ClassDeviceObject) && __resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)(*ClassDeviceObject))->DeviceExtension)) == __old_resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)(*ClassDeviceObject))->DeviceExtension))
+ensures((!($result.KbdCreateClassObject$3353.0$1$ >= 0)) ==> ((Res_DEV_OBJ_INIT[Mem[T.P_DEVICE_OBJECT][$ClassDeviceObject$3$3356.28$KbdCreateClassObject$201]] == old(Res_DEV_OBJ_INIT)[Mem[T.P_DEVICE_OBJECT][$ClassDeviceObject$3$3356.28$KbdCreateClassObject$201]]) && (Res_DEV_EXTN[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.P_DEVICE_OBJECT][$ClassDeviceObject$3$3356.28$KbdCreateClassObject$201])]] == old(Res_DEV_EXTN)[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.P_DEVICE_OBJECT][$ClassDeviceObject$3$3356.28$KbdCreateClassObject$201])]])));
+//TAG: ensures !((LONG)__return >= 0) ==> __preserves_resource("DEV_OBJ_INIT") && __preserves_resource("DEV_EXTN")
+free ensures((!($result.KbdCreateClassObject$3353.0$1$ >= 0)) ==> ((Res_DEV_OBJ_INIT == old(Res_DEV_OBJ_INIT)) && (Res_DEV_EXTN == old(Res_DEV_EXTN))));
+
+modifies Res_DEVICE_STACK;
+
+//TAG: net change in resource DEVICE_STACK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEVICE_STACK[r]} (Empty()[r]) || old(Res_DEVICE_STACK)[r] == Res_DEVICE_STACK[r]));
+modifies Res_DEV_EXTN;
+
+//TAG: net change in resource DEV_EXTN only for: __set_empty, (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)(*ClassDeviceObject))->DeviceExtension)
+ensures (Subset(Empty(), Union(Union(Empty(), Empty()), Singleton(Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.P_DEVICE_OBJECT][$ClassDeviceObject$3$3356.28$KbdCreateClassObject$201])]))) && (forall r:int :: {Res_DEV_EXTN[r]} (Empty()[r]) || (Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.P_DEVICE_OBJECT][$ClassDeviceObject$3$3356.28$KbdCreateClassObject$201])] == r) || old(Res_DEV_EXTN)[r] == Res_DEV_EXTN[r]));
+modifies Res_DEV_OBJ_INIT;
+
+//TAG: net change in resource DEV_OBJ_INIT only for: __set_empty, *ClassDeviceObject
+ensures (Subset(Empty(), Union(Union(Empty(), Empty()), Singleton(Mem[T.P_DEVICE_OBJECT][$ClassDeviceObject$3$3356.28$KbdCreateClassObject$201]))) && (forall r:int :: {Res_DEV_OBJ_INIT[r]} (Empty()[r]) || (Mem[T.P_DEVICE_OBJECT][$ClassDeviceObject$3$3356.28$KbdCreateClassObject$201] == r) || old(Res_DEV_OBJ_INIT)[r] == Res_DEV_OBJ_INIT[r]));
+modifies Res_SPIN_LOCK;
+
+//TAG: net change in resource SPIN_LOCK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_SPIN_LOCK[r]} (Empty()[r]) || old(Res_SPIN_LOCK)[r] == Res_SPIN_LOCK[r]));
+//TAG: updated memory locations at Mem[T.MinorFunction__IO_STACK_LOCATION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.MinorFunction__IO_STACK_LOCATION][_m]} (Empty()[_m]) || Mem[T.MinorFunction__IO_STACK_LOCATION][_m] == old(Mem)[T.MinorFunction__IO_STACK_LOCATION][_m]));
+//TAG: updated memory locations at Mem[T.CurrentStackLocation___unnamed_4_f19b65c1] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.CurrentStackLocation___unnamed_4_f19b65c1][_m]} (Empty()[_m]) || Mem[T.CurrentStackLocation___unnamed_4_f19b65c1][_m] == old(Mem)[T.CurrentStackLocation___unnamed_4_f19b65c1][_m]));
+//TAG: updated memory locations at Mem[T.DeviceExtension__DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.DeviceExtension__DEVICE_OBJECT][_m] == old(Mem)[T.DeviceExtension__DEVICE_OBJECT][_m]));
+//TAG: updated memory locations at Mem[T.Self__DEVICE_EXTENSION] only for: __set_true
+ensures (Subset(Empty(), Union(Empty(), SetTrue())) && (forall _m:int :: {Mem[T.Self__DEVICE_EXTENSION][_m]} (SetTrue()[_m]) || Mem[T.Self__DEVICE_EXTENSION][_m] == old(Mem)[T.Self__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.Started__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Started__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Started__DEVICE_EXTENSION][_m] == old(Mem)[T.Started__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.GrandMaster__GLOBALS] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.GrandMaster__GLOBALS][_m]} (Empty()[_m]) || Mem[T.GrandMaster__GLOBALS][_m] == old(Mem)[T.GrandMaster__GLOBALS][_m]));
+//TAG: updated memory locations at Mem[T.P_DEVICE_OBJECT] only for: __set_empty, ClassDeviceObject
+ensures (Subset(Empty(), Union(Union(Empty(), Empty()), Singleton($ClassDeviceObject$3$3356.28$KbdCreateClassObject$201))) && (forall _m:int :: {Mem[T.P_DEVICE_OBJECT][_m]} (Empty()[_m]) || (_m == $ClassDeviceObject$3$3356.28$KbdCreateClassObject$201) || Mem[T.P_DEVICE_OBJECT][_m] == old(Mem)[T.P_DEVICE_OBJECT][_m]));
+
+//TAG: havoc memory locations by default
+modifies Mem;
+
+
+procedure KbdDeterminePortsServiced($BasePortName$1$3676.23$KbdDeterminePortsServiced$81:int, $NumberPortsServiced$2$3677.18$KbdDeterminePortsServiced$81:int) returns ($result.KbdDeterminePortsServiced$3675.0$1$:int);
+
+//TAG: requires __pforall(_H_x, (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension), __inv_resource("DEV_OBJ_INIT", 1), ((struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension))->Self == _H_x && __resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension)) == 1)
+requires((forall _H_x:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)]} Inverse(Res_DEV_OBJ_INIT,1)[_H_x] ==> ((Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)])] == _H_x) && (Res_DEV_EXTN[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)]] == 1))));
+//TAG: requires __pforall(_H_z, _H_z->Self, __inv_resource("DEV_EXTN", 1), __resource("DEV_OBJ_INIT", _H_z->Self) == 1 && (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)(_H_z->Self))->DeviceExtension) == _H_z)
+requires((forall _H_z:int :: {Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)]} Inverse(Res_DEV_EXTN,1)[_H_z] ==> ((Res_DEV_OBJ_INIT[Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)]] == 1) && (Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)])] == _H_z))));
+//TAG: requires __forall(_H_z, __inv_resource("DEV_EXTN", 1), 1)
+requires((Subset(Empty(), Inverse(Res_DEV_EXTN,1)) && (forall _H_z : int :: {Inverse(Res_DEV_EXTN,1)[_H_z]} (Inverse(Res_DEV_EXTN,1)[_H_z]) ==> (true))));
+//TAG: requires 1 ==> (Globals.GrandMaster != (void *)0 ==> __resource("DEV_EXTN", Globals.GrandMaster) == 1)
+requires((true) ==> ((Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)] != 0) ==> (Res_DEV_EXTN[Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)]] == 1)));
+//TAG: requires 1 ==> __setin(&Globals.LegacyDeviceList, __btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList))
+requires((true) ==> (ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[LegacyDeviceList__GLOBALS(Globals)]));
+//TAG: requires 1 ==> __forall(_H_y, __btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList), _H_y == &Globals.LegacyDeviceList || __resource("DEV_EXTN", CONTAINING_RECORD(_H_y, struct _DEVICE_EXTENSION , Link)) == 1)
+requires((true) ==> ((Subset(Empty(), ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))) && (forall _H_y : int :: {ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[_H_y]} (ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[_H_y]) ==> ((_H_y == LegacyDeviceList__GLOBALS(Globals)) || (Res_DEV_EXTN[MINUS_LEFT_PTR(_H_y, 1, Link__DEVICE_EXTENSION(0))] == 1))))));
+//TAG: requires 1 ==> !__setin(&Globals.GrandMaster->Link, __setminus(__btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList), __set(&Globals.LegacyDeviceList)))
+requires((true) ==> (!(Difference(ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals)), Singleton(LegacyDeviceList__GLOBALS(Globals)))[Link__DEVICE_EXTENSION(Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)])])));
+//TAG: ensures __pforall(_H_x, (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension), __inv_resource("DEV_OBJ_INIT", 1), ((struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension))->Self == _H_x && __resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension)) == 1)
+ensures((forall _H_x:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)]} Inverse(Res_DEV_OBJ_INIT,1)[_H_x] ==> ((Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)])] == _H_x) && (Res_DEV_EXTN[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)]] == 1))));
+//TAG: ensures __pforall(_H_z, _H_z->Self, __inv_resource("DEV_EXTN", 1), __resource("DEV_OBJ_INIT", _H_z->Self) == 1 && (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)(_H_z->Self))->DeviceExtension) == _H_z)
+ensures((forall _H_z:int :: {Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)]} Inverse(Res_DEV_EXTN,1)[_H_z] ==> ((Res_DEV_OBJ_INIT[Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)]] == 1) && (Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)])] == _H_z))));
+//TAG: ensures __forall(_H_z, __inv_resource("DEV_EXTN", 1), 1)
+ensures((Subset(Empty(), Inverse(Res_DEV_EXTN,1)) && (forall _H_z : int :: {Inverse(Res_DEV_EXTN,1)[_H_z]} (Inverse(Res_DEV_EXTN,1)[_H_z]) ==> (true))));
+//TAG: ensures 1 ==> (Globals.GrandMaster != (void *)0 ==> __resource("DEV_EXTN", Globals.GrandMaster) == 1)
+ensures((true) ==> ((Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)] != 0) ==> (Res_DEV_EXTN[Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)]] == 1)));
+//TAG: ensures 1 ==> __setin(&Globals.LegacyDeviceList, __btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList))
+ensures((true) ==> (ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[LegacyDeviceList__GLOBALS(Globals)]));
+//TAG: ensures 1 ==> __forall(_H_y, __btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList), _H_y == &Globals.LegacyDeviceList || __resource("DEV_EXTN", CONTAINING_RECORD(_H_y, struct _DEVICE_EXTENSION , Link)) == 1)
+ensures((true) ==> ((Subset(Empty(), ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))) && (forall _H_y : int :: {ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[_H_y]} (ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[_H_y]) ==> ((_H_y == LegacyDeviceList__GLOBALS(Globals)) || (Res_DEV_EXTN[MINUS_LEFT_PTR(_H_y, 1, Link__DEVICE_EXTENSION(0))] == 1))))));
+//TAG: ensures 1 ==> !__setin(&Globals.GrandMaster->Link, __setminus(__btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList), __set(&Globals.LegacyDeviceList)))
+ensures((true) ==> (!(Difference(ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals)), Singleton(LegacyDeviceList__GLOBALS(Globals)))[Link__DEVICE_EXTENSION(Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)])])));
+//TAG: ensures __preserves_field_map(__offset((*((struct _LIST_ENTRY *)0)).Flink))
+ensures(Mem[T.Flink__LIST_ENTRY] == old(Mem)[T.Flink__LIST_ENTRY]);
+//TAG: ensures __preserves_resource("DEV_OBJ_INIT")
+ensures(Res_DEV_OBJ_INIT == old(Res_DEV_OBJ_INIT));
+//TAG: ensures __preserves_resource("DEV_EXTN")
+ensures(Res_DEV_EXTN == old(Res_DEV_EXTN));
+
+modifies Res_DEVICE_STACK;
+
+//TAG: net change in resource DEVICE_STACK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEVICE_STACK[r]} (Empty()[r]) || old(Res_DEVICE_STACK)[r] == Res_DEVICE_STACK[r]));
+modifies Res_DEV_EXTN;
+
+//TAG: net change in resource DEV_EXTN only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_EXTN[r]} (Empty()[r]) || old(Res_DEV_EXTN)[r] == Res_DEV_EXTN[r]));
+modifies Res_DEV_OBJ_INIT;
+
+//TAG: net change in resource DEV_OBJ_INIT only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_OBJ_INIT[r]} (Empty()[r]) || old(Res_DEV_OBJ_INIT)[r] == Res_DEV_OBJ_INIT[r]));
+modifies Res_SPIN_LOCK;
+
+//TAG: net change in resource SPIN_LOCK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_SPIN_LOCK[r]} (Empty()[r]) || old(Res_SPIN_LOCK)[r] == Res_SPIN_LOCK[r]));
+//TAG: updated memory locations at Mem[T.MinorFunction__IO_STACK_LOCATION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.MinorFunction__IO_STACK_LOCATION][_m]} (Empty()[_m]) || Mem[T.MinorFunction__IO_STACK_LOCATION][_m] == old(Mem)[T.MinorFunction__IO_STACK_LOCATION][_m]));
+//TAG: updated memory locations at Mem[T.CurrentStackLocation___unnamed_4_f19b65c1] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.CurrentStackLocation___unnamed_4_f19b65c1][_m]} (Empty()[_m]) || Mem[T.CurrentStackLocation___unnamed_4_f19b65c1][_m] == old(Mem)[T.CurrentStackLocation___unnamed_4_f19b65c1][_m]));
+//TAG: updated memory locations at Mem[T.DeviceExtension__DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.DeviceExtension__DEVICE_OBJECT][_m] == old(Mem)[T.DeviceExtension__DEVICE_OBJECT][_m]));
+//TAG: updated memory locations at Mem[T.Self__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Self__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Self__DEVICE_EXTENSION][_m] == old(Mem)[T.Self__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.Started__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Started__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Started__DEVICE_EXTENSION][_m] == old(Mem)[T.Started__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.GrandMaster__GLOBALS] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.GrandMaster__GLOBALS][_m]} (Empty()[_m]) || Mem[T.GrandMaster__GLOBALS][_m] == old(Mem)[T.GrandMaster__GLOBALS][_m]));
+//TAG: updated memory locations at Mem[T.P_DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.P_DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.P_DEVICE_OBJECT][_m] == old(Mem)[T.P_DEVICE_OBJECT][_m]));
+
+//TAG: havoc memory locations by default
+modifies Mem;
+
+
+procedure KeyboardAddDeviceEx($ClassData$1$819.28$KeyboardAddDeviceEx$121:int, $FullClassName$2$820.28$KeyboardAddDeviceEx$121:int, $File$3$821.28$KeyboardAddDeviceEx$121:int) returns ($result.KeyboardAddDeviceEx$818.0$1$:int);
+
+//TAG: requires __resource("DEV_EXTN", ClassData) == 1
+requires(Res_DEV_EXTN[$ClassData$1$819.28$KeyboardAddDeviceEx$121] == 1);
+//TAG: requires __pforall(_H_x, (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension), __inv_resource("DEV_OBJ_INIT", 1), ((struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension))->Self == _H_x && __resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension)) == 1)
+requires((forall _H_x:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)]} Inverse(Res_DEV_OBJ_INIT,1)[_H_x] ==> ((Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)])] == _H_x) && (Res_DEV_EXTN[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)]] == 1))));
+//TAG: requires __pforall(_H_z, _H_z->Self, __inv_resource("DEV_EXTN", 1), __resource("DEV_OBJ_INIT", _H_z->Self) == 1 && (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)(_H_z->Self))->DeviceExtension) == _H_z)
+requires((forall _H_z:int :: {Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)]} Inverse(Res_DEV_EXTN,1)[_H_z] ==> ((Res_DEV_OBJ_INIT[Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)]] == 1) && (Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)])] == _H_z))));
+//TAG: requires __forall(_H_z, __inv_resource("DEV_EXTN", 1), 1)
+requires((Subset(Empty(), Inverse(Res_DEV_EXTN,1)) && (forall _H_z : int :: {Inverse(Res_DEV_EXTN,1)[_H_z]} (Inverse(Res_DEV_EXTN,1)[_H_z]) ==> (true))));
+//TAG: requires 1 ==> (Globals.GrandMaster != (void *)0 ==> __resource("DEV_EXTN", Globals.GrandMaster) == 1)
+requires((true) ==> ((Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)] != 0) ==> (Res_DEV_EXTN[Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)]] == 1)));
+//TAG: requires 1 ==> __setin(&Globals.LegacyDeviceList, __btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList))
+requires((true) ==> (ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[LegacyDeviceList__GLOBALS(Globals)]));
+//TAG: requires 1 ==> __forall(_H_y, __btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList), _H_y == &Globals.LegacyDeviceList || __resource("DEV_EXTN", CONTAINING_RECORD(_H_y, struct _DEVICE_EXTENSION , Link)) == 1)
+requires((true) ==> ((Subset(Empty(), ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))) && (forall _H_y : int :: {ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[_H_y]} (ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[_H_y]) ==> ((_H_y == LegacyDeviceList__GLOBALS(Globals)) || (Res_DEV_EXTN[MINUS_LEFT_PTR(_H_y, 1, Link__DEVICE_EXTENSION(0))] == 1))))));
+//TAG: requires 1 ==> !__setin(&Globals.GrandMaster->Link, __setminus(__btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList), __set(&Globals.LegacyDeviceList)))
+requires((true) ==> (!(Difference(ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals)), Singleton(LegacyDeviceList__GLOBALS(Globals)))[Link__DEVICE_EXTENSION(Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)])])));
+//TAG: ensures __resource("DEV_EXTN", ClassData) == 1
+ensures(Res_DEV_EXTN[$ClassData$1$819.28$KeyboardAddDeviceEx$121] == 1);
+//TAG: ensures __pforall(_H_x, (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension), __inv_resource("DEV_OBJ_INIT", 1), ((struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension))->Self == _H_x && __resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension)) == 1)
+ensures((forall _H_x:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)]} Inverse(Res_DEV_OBJ_INIT,1)[_H_x] ==> ((Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)])] == _H_x) && (Res_DEV_EXTN[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)]] == 1))));
+//TAG: ensures __pforall(_H_z, _H_z->Self, __inv_resource("DEV_EXTN", 1), __resource("DEV_OBJ_INIT", _H_z->Self) == 1 && (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)(_H_z->Self))->DeviceExtension) == _H_z)
+ensures((forall _H_z:int :: {Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)]} Inverse(Res_DEV_EXTN,1)[_H_z] ==> ((Res_DEV_OBJ_INIT[Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)]] == 1) && (Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)])] == _H_z))));
+//TAG: ensures __forall(_H_z, __inv_resource("DEV_EXTN", 1), 1)
+ensures((Subset(Empty(), Inverse(Res_DEV_EXTN,1)) && (forall _H_z : int :: {Inverse(Res_DEV_EXTN,1)[_H_z]} (Inverse(Res_DEV_EXTN,1)[_H_z]) ==> (true))));
+//TAG: ensures 1 ==> (Globals.GrandMaster != (void *)0 ==> __resource("DEV_EXTN", Globals.GrandMaster) == 1)
+ensures((true) ==> ((Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)] != 0) ==> (Res_DEV_EXTN[Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)]] == 1)));
+//TAG: ensures 1 ==> __setin(&Globals.LegacyDeviceList, __btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList))
+ensures((true) ==> (ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[LegacyDeviceList__GLOBALS(Globals)]));
+//TAG: ensures 1 ==> __forall(_H_y, __btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList), _H_y == &Globals.LegacyDeviceList || __resource("DEV_EXTN", CONTAINING_RECORD(_H_y, struct _DEVICE_EXTENSION , Link)) == 1)
+ensures((true) ==> ((Subset(Empty(), ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))) && (forall _H_y : int :: {ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[_H_y]} (ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[_H_y]) ==> ((_H_y == LegacyDeviceList__GLOBALS(Globals)) || (Res_DEV_EXTN[MINUS_LEFT_PTR(_H_y, 1, Link__DEVICE_EXTENSION(0))] == 1))))));
+//TAG: ensures 1 ==> !__setin(&Globals.GrandMaster->Link, __setminus(__btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList), __set(&Globals.LegacyDeviceList)))
+ensures((true) ==> (!(Difference(ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals)), Singleton(LegacyDeviceList__GLOBALS(Globals)))[Link__DEVICE_EXTENSION(Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)])])));
+//TAG: ensures __preserves_field_map(__offset((*((struct _LIST_ENTRY *)0)).Flink))
+ensures(Mem[T.Flink__LIST_ENTRY] == old(Mem)[T.Flink__LIST_ENTRY]);
+//TAG: ensures __preserves_resource("DEV_OBJ_INIT")
+ensures(Res_DEV_OBJ_INIT == old(Res_DEV_OBJ_INIT));
+//TAG: ensures __preserves_resource("DEV_EXTN")
+ensures(Res_DEV_EXTN == old(Res_DEV_EXTN));
+
+modifies Res_DEVICE_STACK;
+
+//TAG: net change in resource DEVICE_STACK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEVICE_STACK[r]} (Empty()[r]) || old(Res_DEVICE_STACK)[r] == Res_DEVICE_STACK[r]));
+modifies Res_DEV_EXTN;
+
+//TAG: net change in resource DEV_EXTN only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_EXTN[r]} (Empty()[r]) || old(Res_DEV_EXTN)[r] == Res_DEV_EXTN[r]));
+modifies Res_DEV_OBJ_INIT;
+
+//TAG: net change in resource DEV_OBJ_INIT only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_OBJ_INIT[r]} (Empty()[r]) || old(Res_DEV_OBJ_INIT)[r] == Res_DEV_OBJ_INIT[r]));
+modifies Res_SPIN_LOCK;
+
+//TAG: net change in resource SPIN_LOCK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_SPIN_LOCK[r]} (Empty()[r]) || old(Res_SPIN_LOCK)[r] == Res_SPIN_LOCK[r]));
+//TAG: updated memory locations at Mem[T.MinorFunction__IO_STACK_LOCATION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.MinorFunction__IO_STACK_LOCATION][_m]} (Empty()[_m]) || Mem[T.MinorFunction__IO_STACK_LOCATION][_m] == old(Mem)[T.MinorFunction__IO_STACK_LOCATION][_m]));
+//TAG: updated memory locations at Mem[T.CurrentStackLocation___unnamed_4_f19b65c1] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.CurrentStackLocation___unnamed_4_f19b65c1][_m]} (Empty()[_m]) || Mem[T.CurrentStackLocation___unnamed_4_f19b65c1][_m] == old(Mem)[T.CurrentStackLocation___unnamed_4_f19b65c1][_m]));
+//TAG: updated memory locations at Mem[T.DeviceExtension__DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.DeviceExtension__DEVICE_OBJECT][_m] == old(Mem)[T.DeviceExtension__DEVICE_OBJECT][_m]));
+//TAG: updated memory locations at Mem[T.Self__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Self__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Self__DEVICE_EXTENSION][_m] == old(Mem)[T.Self__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.Started__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Started__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Started__DEVICE_EXTENSION][_m] == old(Mem)[T.Started__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.GrandMaster__GLOBALS] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.GrandMaster__GLOBALS][_m]} (Empty()[_m]) || Mem[T.GrandMaster__GLOBALS][_m] == old(Mem)[T.GrandMaster__GLOBALS][_m]));
+//TAG: updated memory locations at Mem[T.P_DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.P_DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.P_DEVICE_OBJECT][_m] == old(Mem)[T.P_DEVICE_OBJECT][_m]));
+
+//TAG: havoc memory locations by default
+modifies Mem;
+
+
+procedure KeyboardClassLogError($Object$1$4824.10$KeyboardClassLogError$281:int, $ErrorCode$2$4825.10$KeyboardClassLogError$281:int, $UniqueErrorValue$3$4826.10$KeyboardClassLogError$281:int, $FinalStatus$4$4827.13$KeyboardClassLogError$281:int, $DumpCount$5$4828.10$KeyboardClassLogError$281:int, $DumpData$6$4829.11$KeyboardClassLogError$281:int, $MajorFunction$7$4830.10$KeyboardClassLogError$281:int);
+
+//TAG: requires __pforall(_H_x, (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension), __inv_resource("DEV_OBJ_INIT", 1), ((struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension))->Self == _H_x && __resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension)) == 1)
+requires((forall _H_x:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)]} Inverse(Res_DEV_OBJ_INIT,1)[_H_x] ==> ((Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)])] == _H_x) && (Res_DEV_EXTN[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)]] == 1))));
+//TAG: requires __pforall(_H_z, _H_z->Self, __inv_resource("DEV_EXTN", 1), __resource("DEV_OBJ_INIT", _H_z->Self) == 1 && (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)(_H_z->Self))->DeviceExtension) == _H_z)
+requires((forall _H_z:int :: {Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)]} Inverse(Res_DEV_EXTN,1)[_H_z] ==> ((Res_DEV_OBJ_INIT[Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)]] == 1) && (Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)])] == _H_z))));
+//TAG: requires __forall(_H_z, __inv_resource("DEV_EXTN", 1), 1)
+requires((Subset(Empty(), Inverse(Res_DEV_EXTN,1)) && (forall _H_z : int :: {Inverse(Res_DEV_EXTN,1)[_H_z]} (Inverse(Res_DEV_EXTN,1)[_H_z]) ==> (true))));
+//TAG: requires 1 ==> (Globals.GrandMaster != (void *)0 ==> __resource("DEV_EXTN", Globals.GrandMaster) == 1)
+requires((true) ==> ((Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)] != 0) ==> (Res_DEV_EXTN[Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)]] == 1)));
+//TAG: requires 1 ==> __setin(&Globals.LegacyDeviceList, __btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList))
+requires((true) ==> (ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[LegacyDeviceList__GLOBALS(Globals)]));
+//TAG: requires 1 ==> __forall(_H_y, __btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList), _H_y == &Globals.LegacyDeviceList || __resource("DEV_EXTN", CONTAINING_RECORD(_H_y, struct _DEVICE_EXTENSION , Link)) == 1)
+requires((true) ==> ((Subset(Empty(), ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))) && (forall _H_y : int :: {ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[_H_y]} (ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[_H_y]) ==> ((_H_y == LegacyDeviceList__GLOBALS(Globals)) || (Res_DEV_EXTN[MINUS_LEFT_PTR(_H_y, 1, Link__DEVICE_EXTENSION(0))] == 1))))));
+//TAG: requires 1 ==> !__setin(&Globals.GrandMaster->Link, __setminus(__btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList), __set(&Globals.LegacyDeviceList)))
+requires((true) ==> (!(Difference(ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals)), Singleton(LegacyDeviceList__GLOBALS(Globals)))[Link__DEVICE_EXTENSION(Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)])])));
+//TAG: ensures __pforall(_H_x, (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension), __inv_resource("DEV_OBJ_INIT", 1), ((struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension))->Self == _H_x && __resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension)) == 1)
+ensures((forall _H_x:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)]} Inverse(Res_DEV_OBJ_INIT,1)[_H_x] ==> ((Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)])] == _H_x) && (Res_DEV_EXTN[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)]] == 1))));
+//TAG: ensures __pforall(_H_z, _H_z->Self, __inv_resource("DEV_EXTN", 1), __resource("DEV_OBJ_INIT", _H_z->Self) == 1 && (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)(_H_z->Self))->DeviceExtension) == _H_z)
+ensures((forall _H_z:int :: {Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)]} Inverse(Res_DEV_EXTN,1)[_H_z] ==> ((Res_DEV_OBJ_INIT[Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)]] == 1) && (Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)])] == _H_z))));
+//TAG: ensures __forall(_H_z, __inv_resource("DEV_EXTN", 1), 1)
+ensures((Subset(Empty(), Inverse(Res_DEV_EXTN,1)) && (forall _H_z : int :: {Inverse(Res_DEV_EXTN,1)[_H_z]} (Inverse(Res_DEV_EXTN,1)[_H_z]) ==> (true))));
+//TAG: ensures 1 ==> (Globals.GrandMaster != (void *)0 ==> __resource("DEV_EXTN", Globals.GrandMaster) == 1)
+ensures((true) ==> ((Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)] != 0) ==> (Res_DEV_EXTN[Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)]] == 1)));
+//TAG: ensures 1 ==> __setin(&Globals.LegacyDeviceList, __btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList))
+ensures((true) ==> (ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[LegacyDeviceList__GLOBALS(Globals)]));
+//TAG: ensures 1 ==> __forall(_H_y, __btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList), _H_y == &Globals.LegacyDeviceList || __resource("DEV_EXTN", CONTAINING_RECORD(_H_y, struct _DEVICE_EXTENSION , Link)) == 1)
+ensures((true) ==> ((Subset(Empty(), ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))) && (forall _H_y : int :: {ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[_H_y]} (ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[_H_y]) ==> ((_H_y == LegacyDeviceList__GLOBALS(Globals)) || (Res_DEV_EXTN[MINUS_LEFT_PTR(_H_y, 1, Link__DEVICE_EXTENSION(0))] == 1))))));
+//TAG: ensures 1 ==> !__setin(&Globals.GrandMaster->Link, __setminus(__btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList), __set(&Globals.LegacyDeviceList)))
+ensures((true) ==> (!(Difference(ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals)), Singleton(LegacyDeviceList__GLOBALS(Globals)))[Link__DEVICE_EXTENSION(Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)])])));
+//TAG: ensures __preserves_field_map(__offset((*((struct _LIST_ENTRY *)0)).Flink))
+ensures(Mem[T.Flink__LIST_ENTRY] == old(Mem)[T.Flink__LIST_ENTRY]);
+//TAG: ensures __preserves_resource("DEV_OBJ_INIT")
+ensures(Res_DEV_OBJ_INIT == old(Res_DEV_OBJ_INIT));
+//TAG: ensures __preserves_resource("DEV_EXTN")
+ensures(Res_DEV_EXTN == old(Res_DEV_EXTN));
+
+modifies Res_DEVICE_STACK;
+
+//TAG: net change in resource DEVICE_STACK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEVICE_STACK[r]} (Empty()[r]) || old(Res_DEVICE_STACK)[r] == Res_DEVICE_STACK[r]));
+modifies Res_DEV_EXTN;
+
+//TAG: net change in resource DEV_EXTN only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_EXTN[r]} (Empty()[r]) || old(Res_DEV_EXTN)[r] == Res_DEV_EXTN[r]));
+modifies Res_DEV_OBJ_INIT;
+
+//TAG: net change in resource DEV_OBJ_INIT only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_OBJ_INIT[r]} (Empty()[r]) || old(Res_DEV_OBJ_INIT)[r] == Res_DEV_OBJ_INIT[r]));
+modifies Res_SPIN_LOCK;
+
+//TAG: net change in resource SPIN_LOCK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_SPIN_LOCK[r]} (Empty()[r]) || old(Res_SPIN_LOCK)[r] == Res_SPIN_LOCK[r]));
+//TAG: updated memory locations at Mem[T.MinorFunction__IO_STACK_LOCATION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.MinorFunction__IO_STACK_LOCATION][_m]} (Empty()[_m]) || Mem[T.MinorFunction__IO_STACK_LOCATION][_m] == old(Mem)[T.MinorFunction__IO_STACK_LOCATION][_m]));
+//TAG: updated memory locations at Mem[T.CurrentStackLocation___unnamed_4_f19b65c1] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.CurrentStackLocation___unnamed_4_f19b65c1][_m]} (Empty()[_m]) || Mem[T.CurrentStackLocation___unnamed_4_f19b65c1][_m] == old(Mem)[T.CurrentStackLocation___unnamed_4_f19b65c1][_m]));
+//TAG: updated memory locations at Mem[T.DeviceExtension__DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.DeviceExtension__DEVICE_OBJECT][_m] == old(Mem)[T.DeviceExtension__DEVICE_OBJECT][_m]));
+//TAG: updated memory locations at Mem[T.Self__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Self__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Self__DEVICE_EXTENSION][_m] == old(Mem)[T.Self__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.Started__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Started__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Started__DEVICE_EXTENSION][_m] == old(Mem)[T.Started__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.GrandMaster__GLOBALS] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.GrandMaster__GLOBALS][_m]} (Empty()[_m]) || Mem[T.GrandMaster__GLOBALS][_m] == old(Mem)[T.GrandMaster__GLOBALS][_m]));
+//TAG: updated memory locations at Mem[T.P_DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.P_DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.P_DEVICE_OBJECT][_m] == old(Mem)[T.P_DEVICE_OBJECT][_m]));
+
+//TAG: havoc memory locations by default
+modifies Mem;
+
+
+procedure ObfDereferenceObject($Object$1$24931.15$ObfDereferenceObject$41:int) returns ($result.ObfDereferenceObject$24930.0$1$:int);
+
+//TAG: ensures __preserves_mem
+ensures(Mem == old(Mem));
+//TAG: ensures __preserves_resource("DEV_OBJ_INIT") && __preserves_resource("DEV_EXTN")
+ensures((Res_DEV_OBJ_INIT == old(Res_DEV_OBJ_INIT)) && (Res_DEV_EXTN == old(Res_DEV_EXTN)));
+
+modifies Res_DEVICE_STACK;
+
+//TAG: net change in resource DEVICE_STACK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEVICE_STACK[r]} (Empty()[r]) || old(Res_DEVICE_STACK)[r] == Res_DEVICE_STACK[r]));
+modifies Res_DEV_EXTN;
+
+//TAG: net change in resource DEV_EXTN only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_EXTN[r]} (Empty()[r]) || old(Res_DEV_EXTN)[r] == Res_DEV_EXTN[r]));
+modifies Res_DEV_OBJ_INIT;
+
+//TAG: net change in resource DEV_OBJ_INIT only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_OBJ_INIT[r]} (Empty()[r]) || old(Res_DEV_OBJ_INIT)[r] == Res_DEV_OBJ_INIT[r]));
+modifies Res_SPIN_LOCK;
+
+//TAG: net change in resource SPIN_LOCK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_SPIN_LOCK[r]} (Empty()[r]) || old(Res_SPIN_LOCK)[r] == Res_SPIN_LOCK[r]));
+//TAG: updated memory locations at Mem[T.MinorFunction__IO_STACK_LOCATION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.MinorFunction__IO_STACK_LOCATION][_m]} (Empty()[_m]) || Mem[T.MinorFunction__IO_STACK_LOCATION][_m] == old(Mem)[T.MinorFunction__IO_STACK_LOCATION][_m]));
+//TAG: updated memory locations at Mem[T.CurrentStackLocation___unnamed_4_f19b65c1] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.CurrentStackLocation___unnamed_4_f19b65c1][_m]} (Empty()[_m]) || Mem[T.CurrentStackLocation___unnamed_4_f19b65c1][_m] == old(Mem)[T.CurrentStackLocation___unnamed_4_f19b65c1][_m]));
+//TAG: updated memory locations at Mem[T.DeviceExtension__DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.DeviceExtension__DEVICE_OBJECT][_m] == old(Mem)[T.DeviceExtension__DEVICE_OBJECT][_m]));
+//TAG: updated memory locations at Mem[T.Self__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Self__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Self__DEVICE_EXTENSION][_m] == old(Mem)[T.Self__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.Started__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Started__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Started__DEVICE_EXTENSION][_m] == old(Mem)[T.Started__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.GrandMaster__GLOBALS] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.GrandMaster__GLOBALS][_m]} (Empty()[_m]) || Mem[T.GrandMaster__GLOBALS][_m] == old(Mem)[T.GrandMaster__GLOBALS][_m]));
+//TAG: updated memory locations at Mem[T.P_DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.P_DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.P_DEVICE_OBJECT][_m] == old(Mem)[T.P_DEVICE_OBJECT][_m]));
+
+//TAG: havoc memory locations by default
+modifies Mem;
+
+
+procedure RtlAppendUnicodeToString($Destination$1$7421.28$RtlAppendUnicodeToString$81:int, $Source$2$7422.20$RtlAppendUnicodeToString$81:int) returns ($result.RtlAppendUnicodeToString$7420.0$1$:int);
+
+//TAG: ensures __preserves_mem
+ensures(Mem == old(Mem));
+//TAG: ensures __preserves_resource("DEV_OBJ_INIT") && __preserves_resource("DEV_EXTN")
+ensures((Res_DEV_OBJ_INIT == old(Res_DEV_OBJ_INIT)) && (Res_DEV_EXTN == old(Res_DEV_EXTN)));
+
+modifies Res_DEVICE_STACK;
+
+//TAG: net change in resource DEVICE_STACK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEVICE_STACK[r]} (Empty()[r]) || old(Res_DEVICE_STACK)[r] == Res_DEVICE_STACK[r]));
+modifies Res_DEV_EXTN;
+
+//TAG: net change in resource DEV_EXTN only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_EXTN[r]} (Empty()[r]) || old(Res_DEV_EXTN)[r] == Res_DEV_EXTN[r]));
+modifies Res_DEV_OBJ_INIT;
+
+//TAG: net change in resource DEV_OBJ_INIT only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_OBJ_INIT[r]} (Empty()[r]) || old(Res_DEV_OBJ_INIT)[r] == Res_DEV_OBJ_INIT[r]));
+modifies Res_SPIN_LOCK;
+
+//TAG: net change in resource SPIN_LOCK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_SPIN_LOCK[r]} (Empty()[r]) || old(Res_SPIN_LOCK)[r] == Res_SPIN_LOCK[r]));
+//TAG: updated memory locations at Mem[T.MinorFunction__IO_STACK_LOCATION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.MinorFunction__IO_STACK_LOCATION][_m]} (Empty()[_m]) || Mem[T.MinorFunction__IO_STACK_LOCATION][_m] == old(Mem)[T.MinorFunction__IO_STACK_LOCATION][_m]));
+//TAG: updated memory locations at Mem[T.CurrentStackLocation___unnamed_4_f19b65c1] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.CurrentStackLocation___unnamed_4_f19b65c1][_m]} (Empty()[_m]) || Mem[T.CurrentStackLocation___unnamed_4_f19b65c1][_m] == old(Mem)[T.CurrentStackLocation___unnamed_4_f19b65c1][_m]));
+//TAG: updated memory locations at Mem[T.DeviceExtension__DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.DeviceExtension__DEVICE_OBJECT][_m] == old(Mem)[T.DeviceExtension__DEVICE_OBJECT][_m]));
+//TAG: updated memory locations at Mem[T.Self__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Self__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Self__DEVICE_EXTENSION][_m] == old(Mem)[T.Self__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.Started__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Started__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Started__DEVICE_EXTENSION][_m] == old(Mem)[T.Started__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.GrandMaster__GLOBALS] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.GrandMaster__GLOBALS][_m]} (Empty()[_m]) || Mem[T.GrandMaster__GLOBALS][_m] == old(Mem)[T.GrandMaster__GLOBALS][_m]));
+//TAG: updated memory locations at Mem[T.P_DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.P_DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.P_DEVICE_OBJECT][_m] == old(Mem)[T.P_DEVICE_OBJECT][_m]));
+
+//TAG: havoc memory locations by default
+modifies Mem;
+
+
+procedure RtlCopyUnicodeString($DestinationString$1$7401.28$RtlCopyUnicodeString$81:int, $SourceString$2$7402.30$RtlCopyUnicodeString$81:int);
+
+//TAG: ensures __preserves_mem
+ensures(Mem == old(Mem));
+//TAG: ensures __preserves_resource("DEV_OBJ_INIT") && __preserves_resource("DEV_EXTN")
+ensures((Res_DEV_OBJ_INIT == old(Res_DEV_OBJ_INIT)) && (Res_DEV_EXTN == old(Res_DEV_EXTN)));
+
+modifies Res_DEVICE_STACK;
+
+//TAG: net change in resource DEVICE_STACK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEVICE_STACK[r]} (Empty()[r]) || old(Res_DEVICE_STACK)[r] == Res_DEVICE_STACK[r]));
+modifies Res_DEV_EXTN;
+
+//TAG: net change in resource DEV_EXTN only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_EXTN[r]} (Empty()[r]) || old(Res_DEV_EXTN)[r] == Res_DEV_EXTN[r]));
+modifies Res_DEV_OBJ_INIT;
+
+//TAG: net change in resource DEV_OBJ_INIT only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_OBJ_INIT[r]} (Empty()[r]) || old(Res_DEV_OBJ_INIT)[r] == Res_DEV_OBJ_INIT[r]));
+modifies Res_SPIN_LOCK;
+
+//TAG: net change in resource SPIN_LOCK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_SPIN_LOCK[r]} (Empty()[r]) || old(Res_SPIN_LOCK)[r] == Res_SPIN_LOCK[r]));
+//TAG: updated memory locations at Mem[T.MinorFunction__IO_STACK_LOCATION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.MinorFunction__IO_STACK_LOCATION][_m]} (Empty()[_m]) || Mem[T.MinorFunction__IO_STACK_LOCATION][_m] == old(Mem)[T.MinorFunction__IO_STACK_LOCATION][_m]));
+//TAG: updated memory locations at Mem[T.CurrentStackLocation___unnamed_4_f19b65c1] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.CurrentStackLocation___unnamed_4_f19b65c1][_m]} (Empty()[_m]) || Mem[T.CurrentStackLocation___unnamed_4_f19b65c1][_m] == old(Mem)[T.CurrentStackLocation___unnamed_4_f19b65c1][_m]));
+//TAG: updated memory locations at Mem[T.DeviceExtension__DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.DeviceExtension__DEVICE_OBJECT][_m] == old(Mem)[T.DeviceExtension__DEVICE_OBJECT][_m]));
+//TAG: updated memory locations at Mem[T.Self__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Self__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Self__DEVICE_EXTENSION][_m] == old(Mem)[T.Self__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.Started__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Started__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Started__DEVICE_EXTENSION][_m] == old(Mem)[T.Started__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.GrandMaster__GLOBALS] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.GrandMaster__GLOBALS][_m]} (Empty()[_m]) || Mem[T.GrandMaster__GLOBALS][_m] == old(Mem)[T.GrandMaster__GLOBALS][_m]));
+//TAG: updated memory locations at Mem[T.P_DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.P_DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.P_DEVICE_OBJECT][_m] == old(Mem)[T.P_DEVICE_OBJECT][_m]));
+
+//TAG: havoc memory locations by default
+modifies Mem;
+
+
+procedure RtlInitUnicodeString($DestinationString$1$7281.26$RtlInitUnicodeString$81:int, $SourceString$2$7282.37$RtlInitUnicodeString$81:int);
+
+//TAG: ensures __preserves_mem
+ensures(Mem == old(Mem));
+//TAG: ensures __preserves_resource("DEV_OBJ_INIT") && __preserves_resource("DEV_EXTN")
+ensures((Res_DEV_OBJ_INIT == old(Res_DEV_OBJ_INIT)) && (Res_DEV_EXTN == old(Res_DEV_EXTN)));
+
+modifies Res_DEVICE_STACK;
+
+//TAG: net change in resource DEVICE_STACK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEVICE_STACK[r]} (Empty()[r]) || old(Res_DEVICE_STACK)[r] == Res_DEVICE_STACK[r]));
+modifies Res_DEV_EXTN;
+
+//TAG: net change in resource DEV_EXTN only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_EXTN[r]} (Empty()[r]) || old(Res_DEV_EXTN)[r] == Res_DEV_EXTN[r]));
+modifies Res_DEV_OBJ_INIT;
+
+//TAG: net change in resource DEV_OBJ_INIT only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_OBJ_INIT[r]} (Empty()[r]) || old(Res_DEV_OBJ_INIT)[r] == Res_DEV_OBJ_INIT[r]));
+modifies Res_SPIN_LOCK;
+
+//TAG: net change in resource SPIN_LOCK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_SPIN_LOCK[r]} (Empty()[r]) || old(Res_SPIN_LOCK)[r] == Res_SPIN_LOCK[r]));
+//TAG: updated memory locations at Mem[T.MinorFunction__IO_STACK_LOCATION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.MinorFunction__IO_STACK_LOCATION][_m]} (Empty()[_m]) || Mem[T.MinorFunction__IO_STACK_LOCATION][_m] == old(Mem)[T.MinorFunction__IO_STACK_LOCATION][_m]));
+//TAG: updated memory locations at Mem[T.CurrentStackLocation___unnamed_4_f19b65c1] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.CurrentStackLocation___unnamed_4_f19b65c1][_m]} (Empty()[_m]) || Mem[T.CurrentStackLocation___unnamed_4_f19b65c1][_m] == old(Mem)[T.CurrentStackLocation___unnamed_4_f19b65c1][_m]));
+//TAG: updated memory locations at Mem[T.DeviceExtension__DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.DeviceExtension__DEVICE_OBJECT][_m] == old(Mem)[T.DeviceExtension__DEVICE_OBJECT][_m]));
+//TAG: updated memory locations at Mem[T.Self__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Self__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Self__DEVICE_EXTENSION][_m] == old(Mem)[T.Self__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.Started__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Started__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Started__DEVICE_EXTENSION][_m] == old(Mem)[T.Started__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.GrandMaster__GLOBALS] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.GrandMaster__GLOBALS][_m]} (Empty()[_m]) || Mem[T.GrandMaster__GLOBALS][_m] == old(Mem)[T.GrandMaster__GLOBALS][_m]));
+//TAG: updated memory locations at Mem[T.P_DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.P_DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.P_DEVICE_OBJECT][_m] == old(Mem)[T.P_DEVICE_OBJECT][_m]));
+
+//TAG: havoc memory locations by default
+modifies Mem;
+
+
+procedure __PREfastPagedCode();
+
+//TAG: ensures __preserves_mem
+ensures(Mem == old(Mem));
+//TAG: ensures __preserves_resource("DEV_OBJ_INIT") && __preserves_resource("DEV_EXTN")
+ensures((Res_DEV_OBJ_INIT == old(Res_DEV_OBJ_INIT)) && (Res_DEV_EXTN == old(Res_DEV_EXTN)));
+
+modifies Res_DEVICE_STACK;
+
+//TAG: net change in resource DEVICE_STACK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEVICE_STACK[r]} (Empty()[r]) || old(Res_DEVICE_STACK)[r] == Res_DEVICE_STACK[r]));
+modifies Res_DEV_EXTN;
+
+//TAG: net change in resource DEV_EXTN only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_EXTN[r]} (Empty()[r]) || old(Res_DEV_EXTN)[r] == Res_DEV_EXTN[r]));
+modifies Res_DEV_OBJ_INIT;
+
+//TAG: net change in resource DEV_OBJ_INIT only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_OBJ_INIT[r]} (Empty()[r]) || old(Res_DEV_OBJ_INIT)[r] == Res_DEV_OBJ_INIT[r]));
+modifies Res_SPIN_LOCK;
+
+//TAG: net change in resource SPIN_LOCK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_SPIN_LOCK[r]} (Empty()[r]) || old(Res_SPIN_LOCK)[r] == Res_SPIN_LOCK[r]));
+//TAG: updated memory locations at Mem[T.MinorFunction__IO_STACK_LOCATION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.MinorFunction__IO_STACK_LOCATION][_m]} (Empty()[_m]) || Mem[T.MinorFunction__IO_STACK_LOCATION][_m] == old(Mem)[T.MinorFunction__IO_STACK_LOCATION][_m]));
+//TAG: updated memory locations at Mem[T.CurrentStackLocation___unnamed_4_f19b65c1] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.CurrentStackLocation___unnamed_4_f19b65c1][_m]} (Empty()[_m]) || Mem[T.CurrentStackLocation___unnamed_4_f19b65c1][_m] == old(Mem)[T.CurrentStackLocation___unnamed_4_f19b65c1][_m]));
+//TAG: updated memory locations at Mem[T.DeviceExtension__DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.DeviceExtension__DEVICE_OBJECT][_m] == old(Mem)[T.DeviceExtension__DEVICE_OBJECT][_m]));
+//TAG: updated memory locations at Mem[T.Self__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Self__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Self__DEVICE_EXTENSION][_m] == old(Mem)[T.Self__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.Started__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Started__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Started__DEVICE_EXTENSION][_m] == old(Mem)[T.Started__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.GrandMaster__GLOBALS] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.GrandMaster__GLOBALS][_m]} (Empty()[_m]) || Mem[T.GrandMaster__GLOBALS][_m] == old(Mem)[T.GrandMaster__GLOBALS][_m]));
+//TAG: updated memory locations at Mem[T.P_DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.P_DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.P_DEVICE_OBJECT][_m] == old(Mem)[T.P_DEVICE_OBJECT][_m]));
+
+//TAG: havoc memory locations by default
+modifies Mem;
+
+
+procedure KeyboardClassFindMorePorts($DriverObject$1$4861.20$KeyboardClassFindMorePorts$121:int, $Context$2$4862.20$KeyboardClassFindMorePorts$121:int, $Count$3$4863.20$KeyboardClassFindMorePorts$121:int)
+
+//TAG: requires 1 ==> (Globals.GrandMaster != (void *)0 ==> __resource("DEV_EXTN", Globals.GrandMaster) == 1)
+requires((true) ==> ((Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)] != 0) ==> (Res_DEV_EXTN[Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)]] == 1)));
+//TAG: requires 1 ==> __setin(&Globals.LegacyDeviceList, __btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList))
+requires((true) ==> (ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[LegacyDeviceList__GLOBALS(Globals)]));
+//TAG: requires 1 ==> __forall(_H_y, __btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList), _H_y == &Globals.LegacyDeviceList || __resource("DEV_EXTN", CONTAINING_RECORD(_H_y, struct _DEVICE_EXTENSION , Link)) == 1)
+requires((true) ==> ((Subset(Empty(), ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))) && (forall _H_y : int :: {ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[_H_y]} (ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[_H_y]) ==> ((_H_y == LegacyDeviceList__GLOBALS(Globals)) || (Res_DEV_EXTN[MINUS_LEFT_PTR(_H_y, 1, Link__DEVICE_EXTENSION(0))] == 1))))));
+//TAG: requires 1 ==> !__setin(&Globals.GrandMaster->Link, __setminus(__btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList), __set(&Globals.LegacyDeviceList)))
+requires((true) ==> (!(Difference(ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals)), Singleton(LegacyDeviceList__GLOBALS(Globals)))[Link__DEVICE_EXTENSION(Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)])])));
+//TAG: requires __pforall(_H_x, (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension), __inv_resource("DEV_OBJ_INIT", 1), ((struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension))->Self == _H_x && __resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension)) == 1)
+requires((forall _H_x:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)]} Inverse(Res_DEV_OBJ_INIT,1)[_H_x] ==> ((Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)])] == _H_x) && (Res_DEV_EXTN[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)]] == 1))));
+//TAG: requires __pforall(_H_z, _H_z->Self, __inv_resource("DEV_EXTN", 1), __resource("DEV_OBJ_INIT", _H_z->Self) == 1 && (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)(_H_z->Self))->DeviceExtension) == _H_z) && __forall(_H_z, __inv_resource("DEV_EXTN", 1), 1)
+requires(((forall _H_z:int :: {Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)]} Inverse(Res_DEV_EXTN,1)[_H_z] ==> ((Res_DEV_OBJ_INIT[Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)]] == 1) && (Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)])] == _H_z)))) && ((Subset(Empty(), Inverse(Res_DEV_EXTN,1)) && (forall _H_z : int :: {Inverse(Res_DEV_EXTN,1)[_H_z]} (Inverse(Res_DEV_EXTN,1)[_H_z]) ==> (true)))));
+//TAG: ensures 1 ==> (Globals.GrandMaster != (void *)0 ==> __resource("DEV_EXTN", Globals.GrandMaster) == 1)
+ensures((true) ==> ((Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)] != 0) ==> (Res_DEV_EXTN[Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)]] == 1)));
+//TAG: ensures 1 ==> __setin(&Globals.LegacyDeviceList, __btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList))
+ensures((true) ==> (ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[LegacyDeviceList__GLOBALS(Globals)]));
+//TAG: ensures 1 ==> __forall(_H_y, __btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList), _H_y == &Globals.LegacyDeviceList || __resource("DEV_EXTN", CONTAINING_RECORD(_H_y, struct _DEVICE_EXTENSION , Link)) == 1)
+ensures((true) ==> ((Subset(Empty(), ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))) && (forall _H_y : int :: {ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[_H_y]} (ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[_H_y]) ==> ((_H_y == LegacyDeviceList__GLOBALS(Globals)) || (Res_DEV_EXTN[MINUS_LEFT_PTR(_H_y, 1, Link__DEVICE_EXTENSION(0))] == 1))))));
+//TAG: ensures 1 ==> !__setin(&Globals.GrandMaster->Link, __setminus(__btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList), __set(&Globals.LegacyDeviceList)))
+ensures((true) ==> (!(Difference(ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals)), Singleton(LegacyDeviceList__GLOBALS(Globals)))[Link__DEVICE_EXTENSION(Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)])])));
+//TAG: ensures __pforall(_H_x, (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension), __inv_resource("DEV_OBJ_INIT", 1), ((struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension))->Self == _H_x && __resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension)) == 1)
+ensures((forall _H_x:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)]} Inverse(Res_DEV_OBJ_INIT,1)[_H_x] ==> ((Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)])] == _H_x) && (Res_DEV_EXTN[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)]] == 1))));
+//TAG: ensures __pforall(_H_z, _H_z->Self, __inv_resource("DEV_EXTN", 1), __resource("DEV_OBJ_INIT", _H_z->Self) == 1 && (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)(_H_z->Self))->DeviceExtension) == _H_z) && __forall(_H_z, __inv_resource("DEV_EXTN", 1), 1)
+ensures(((forall _H_z:int :: {Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)]} Inverse(Res_DEV_EXTN,1)[_H_z] ==> ((Res_DEV_OBJ_INIT[Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)]] == 1) && (Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)])] == _H_z)))) && ((Subset(Empty(), Inverse(Res_DEV_EXTN,1)) && (forall _H_z : int :: {Inverse(Res_DEV_EXTN,1)[_H_z]} (Inverse(Res_DEV_EXTN,1)[_H_z]) ==> (true)))));
+modifies alloc;
+free ensures(forall f:int :: {alloc[Base(f)]} old(alloc)[Base(f)] == UNALLOCATED || old(alloc)[Base(f)] == alloc[Base(f)]);
+
+modifies Res_DEVICE_STACK;
+
+//TAG: net change in resource DEVICE_STACK only for:
+modifies Res_DEV_EXTN;
+
+//TAG: net change in resource DEV_EXTN only for:
+modifies Res_DEV_OBJ_INIT;
+
+//TAG: net change in resource DEV_OBJ_INIT only for:
+modifies Res_SPIN_LOCK;
+
+//TAG: net change in resource SPIN_LOCK only for:
+
+//TAG: havoc memory locations by default
+modifies Mem;
+{
+var havoc_stringTemp:int;
+var condVal:int;
+var $Context$2$4862.20$KeyboardClassFindMorePorts$12 : int;
+var $Count$3$4863.20$KeyboardClassFindMorePorts$12 : int;
+var $DriverObject$1$4861.20$KeyboardClassFindMorePorts$12 : int;
+var $ExAllocatePoolWithTag.arg.2$5$ : int;
+var $KbdDebugPrint.arg.2$6$ : int;
+var $RtlAppendUnicodeToString.arg.2$10$ : int;
+var $RtlAppendUnicodeToString.arg.2$13$ : int;
+var $RtlAppendUnicodeToString.arg.2$3$ : int;
+var $basePortBuffer$13$4895.28$KeyboardClassFindMorePorts$12 : int;
+var $basePortName$11$4893.28$KeyboardClassFindMorePorts$12 : int;
+var $classDeviceObject$6$4888.28$KeyboardClassFindMorePorts$12 : int;
+var $deviceExtension$5$4887.28$KeyboardClassFindMorePorts$12 : int;
+var $dumpData$7$4889.28$KeyboardClassFindMorePorts$12 : int;
+var $file$15$4897.28$KeyboardClassFindMorePorts$12 : int;
+var $fullClassName$14$4896.28$KeyboardClassFindMorePorts$12 : int;
+var $fullPortName$12$4894.28$KeyboardClassFindMorePorts$12 : int;
+var $i$8$4890.28$KeyboardClassFindMorePorts$12 : int;
+var $memset.arg.3$8$ : int;
+var $numPorts$9$4891.28$KeyboardClassFindMorePorts$12 : int;
+var $port$16$5029.22$KeyboardClassFindMorePorts$12 : int;
+var $result.ExAllocatePoolWithTag$4926.0$4$ : int;
+var $result.IoGetDeviceObjectPointer$5001.42$16$ : int;
+var $result.KbdCreateClassObject$4978.38$15$ : int;
+var $result.KbdDeterminePortsServiced$4954.29$14$ : int;
+var $result.KeyboardAddDeviceEx$5013.37$17$ : int;
+var $result.ObfDereferenceObject$5042.16$18$ : int;
+var $result.RtlAppendUnicodeToString$4915.28$2$ : int;
+var $result.RtlAppendUnicodeToString$4950.28$9$ : int;
+var $result.RtlAppendUnicodeToString$4951.28$11$ : int;
+var $result.RtlAppendUnicodeToString$4952.28$12$ : int;
+var $result.memset$4903.4$1$ : int;
+var $result.memset$4949.4$7$ : int;
+var $status$4$4886.28$KeyboardClassFindMorePorts$12 : int;
+var $successfulCreates$10$4892.28$KeyboardClassFindMorePorts$12 : int;
+var tempBoogie0:int;
+var tempBoogie1:int;
+var tempBoogie2:int;
+var tempBoogie3:int;
+var tempBoogie4:int;
+var tempBoogie5:int;
+var tempBoogie6:int;
+var tempBoogie7:int;
+var tempBoogie8:int;
+var tempBoogie9:int;
+var tempBoogie10:int;
+var tempBoogie11:int;
+var tempBoogie12:int;
+var tempBoogie13:int;
+var tempBoogie14:int;
+var tempBoogie15:int;
+var tempBoogie16:int;
+var tempBoogie17:int;
+var tempBoogie18:int;
+var tempBoogie19:int;
+var LOOP_74_alloc:[int]name;
+var LOOP_74_Mem:[name][int]int;
+var LOOP_74_Res_DEVICE_STACK:[int]int;
+var LOOP_74_Res_DEV_EXTN:[int]int;
+var LOOP_74_Res_DEV_OBJ_INIT:[int]int;
+var LOOP_74_Res_SPIN_LOCK:[int]int;
+
+
+start:
+
+assume (alloc[$DriverObject$1$4861.20$KeyboardClassFindMorePorts$121] != UNALLOCATED);
+assume (alloc[$Context$2$4862.20$KeyboardClassFindMorePorts$121] != UNALLOCATED);
+call $basePortBuffer$13$4895.28$KeyboardClassFindMorePorts$12 := __HAVOC_malloc(512);
+call $basePortName$11$4893.28$KeyboardClassFindMorePorts$12 := __HAVOC_malloc(8);
+call $classDeviceObject$6$4888.28$KeyboardClassFindMorePorts$12 := __HAVOC_malloc(4);
+call $dumpData$7$4889.28$KeyboardClassFindMorePorts$12 := __HAVOC_malloc(16);
+call $file$15$4897.28$KeyboardClassFindMorePorts$12 := __HAVOC_malloc(4);
+call $fullClassName$14$4896.28$KeyboardClassFindMorePorts$12 := __HAVOC_malloc(4);
+call $fullPortName$12$4894.28$KeyboardClassFindMorePorts$12 := __HAVOC_malloc(8);
+call $numPorts$9$4891.28$KeyboardClassFindMorePorts$12 := __HAVOC_malloc(4);
+$DriverObject$1$4861.20$KeyboardClassFindMorePorts$12 := $DriverObject$1$4861.20$KeyboardClassFindMorePorts$121;
+$Context$2$4862.20$KeyboardClassFindMorePorts$12 := $Context$2$4862.20$KeyboardClassFindMorePorts$121;
+$Count$3$4863.20$KeyboardClassFindMorePorts$12 := $Count$3$4863.20$KeyboardClassFindMorePorts$121;
+goto label_3;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(5070)
+label_1:
+call __HAVOC_free($basePortBuffer$13$4895.28$KeyboardClassFindMorePorts$12);
+call __HAVOC_free($basePortName$11$4893.28$KeyboardClassFindMorePorts$12);
+call __HAVOC_free($classDeviceObject$6$4888.28$KeyboardClassFindMorePorts$12);
+call __HAVOC_free($dumpData$7$4889.28$KeyboardClassFindMorePorts$12);
+call __HAVOC_free($file$15$4897.28$KeyboardClassFindMorePorts$12);
+call __HAVOC_free($fullClassName$14$4896.28$KeyboardClassFindMorePorts$12);
+call __HAVOC_free($fullPortName$12$4894.28$KeyboardClassFindMorePorts$12);
+call __HAVOC_free($numPorts$9$4891.28$KeyboardClassFindMorePorts$12);
+assume (forall m:int:: {Res_DEVICE_STACK[m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Res_DEVICE_STACK[m] == old(Res_DEVICE_STACK)[m]);
+assume (forall m:int:: {Res_DEV_EXTN[m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Res_DEV_EXTN[m] == old(Res_DEV_EXTN)[m]);
+assume (forall m:int:: {Res_DEV_OBJ_INIT[m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Res_DEV_OBJ_INIT[m] == old(Res_DEV_OBJ_INIT)[m]);
+assume (forall m:int:: {Res_SPIN_LOCK[m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Res_SPIN_LOCK[m] == old(Res_SPIN_LOCK)[m]);
+assume (forall m:int :: {Mem[T.A256UINT2][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.A256UINT2][m] == old(Mem[T.A256UINT2])[m]);
+assume (forall m:int :: {Mem[T.A2UINT2][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.A2UINT2][m] == old(Mem[T.A2UINT2])[m]);
+assume (forall m:int :: {Mem[T.A4UINT4][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.A4UINT4][m] == old(Mem[T.A4UINT4])[m]);
+assume (forall m:int :: {Mem[T.A5UINT2][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.A5UINT2][m] == old(Mem[T.A5UINT2])[m]);
+assume (forall m:int :: {Mem[T.A88CHAR][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.A88CHAR][m] == old(Mem[T.A88CHAR])[m]);
+assume (forall m:int :: {Mem[T.A9UINT2][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.A9UINT2][m] == old(Mem[T.A9UINT2])[m]);
+assume (forall m:int :: {Mem[T.AssocClassList__GLOBALS][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.AssocClassList__GLOBALS][m] == old(Mem[T.AssocClassList__GLOBALS])[m]);
+assume (forall m:int :: {Mem[T.BaseClassName__GLOBALS][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.BaseClassName__GLOBALS][m] == old(Mem[T.BaseClassName__GLOBALS])[m]);
+assume (forall m:int :: {Mem[T.Buffer__UNICODE_STRING][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.Buffer__UNICODE_STRING][m] == old(Mem[T.Buffer__UNICODE_STRING])[m]);
+assume (forall m:int :: {Mem[T.CHAR][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.CHAR][m] == old(Mem[T.CHAR])[m]);
+assume (forall m:int :: {Mem[T.CurrentStackLocation___unnamed_4_f19b65c1][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.CurrentStackLocation___unnamed_4_f19b65c1][m] == old(Mem[T.CurrentStackLocation___unnamed_4_f19b65c1])[m]);
+assume (forall m:int :: {Mem[T.DataIn__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.DataIn__DEVICE_EXTENSION][m] == old(Mem[T.DataIn__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.DataOut__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.DataOut__DEVICE_EXTENSION][m] == old(Mem[T.DataOut__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.DeviceExtension__DEVICE_OBJECT][m] == old(Mem[T.DeviceExtension__DEVICE_OBJECT])[m]);
+assume (forall m:int :: {Mem[T.File__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.File__DEVICE_EXTENSION][m] == old(Mem[T.File__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.File__PORT][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.File__PORT][m] == old(Mem[T.File__PORT])[m]);
+assume (forall m:int :: {Mem[T.Flags__DEVICE_OBJECT][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.Flags__DEVICE_OBJECT][m] == old(Mem[T.Flags__DEVICE_OBJECT])[m]);
+assume (forall m:int :: {Mem[T.Flink__LIST_ENTRY][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.Flink__LIST_ENTRY][m] == old(Mem[T.Flink__LIST_ENTRY])[m]);
+assume (forall m:int :: {Mem[T.Free__PORT][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.Free__PORT][m] == old(Mem[T.Free__PORT])[m]);
+assume (forall m:int :: {Mem[T.GrandMaster__GLOBALS][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.GrandMaster__GLOBALS][m] == old(Mem[T.GrandMaster__GLOBALS])[m]);
+assume (forall m:int :: {Mem[T.INT4][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.INT4][m] == old(Mem[T.INT4])[m]);
+assume (forall m:int :: {Mem[T.InitExtension__GLOBALS][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.InitExtension__GLOBALS][m] == old(Mem[T.InitExtension__GLOBALS])[m]);
+assume (forall m:int :: {Mem[T.InputData__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.InputData__DEVICE_EXTENSION][m] == old(Mem[T.InputData__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.LegacyDeviceList__GLOBALS][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.LegacyDeviceList__GLOBALS][m] == old(Mem[T.LegacyDeviceList__GLOBALS])[m]);
+assume (forall m:int :: {Mem[T.Length__UNICODE_STRING][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.Length__UNICODE_STRING][m] == old(Mem[T.Length__UNICODE_STRING])[m]);
+assume (forall m:int :: {Mem[T.Link__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.Link__DEVICE_EXTENSION][m] == old(Mem[T.Link__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.MaximumLength__UNICODE_STRING][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.MaximumLength__UNICODE_STRING][m] == old(Mem[T.MaximumLength__UNICODE_STRING])[m]);
+assume (forall m:int :: {Mem[T.MinorFunction__IO_STACK_LOCATION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.MinorFunction__IO_STACK_LOCATION][m] == old(Mem[T.MinorFunction__IO_STACK_LOCATION])[m]);
+assume (forall m:int :: {Mem[T.Mutex__GLOBALS][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.Mutex__GLOBALS][m] == old(Mem[T.Mutex__GLOBALS])[m]);
+assume (forall m:int :: {Mem[T.NumberLegacyPorts__GLOBALS][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.NumberLegacyPorts__GLOBALS][m] == old(Mem[T.NumberLegacyPorts__GLOBALS])[m]);
+assume (forall m:int :: {Mem[T.PCHAR][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.PCHAR][m] == old(Mem[T.PCHAR])[m]);
+assume (forall m:int :: {Mem[T.PPUINT2][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.PPUINT2][m] == old(Mem[T.PPUINT2])[m]);
+assume (forall m:int :: {Mem[T.PP_DEVICE_OBJECT][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.PP_DEVICE_OBJECT][m] == old(Mem[T.PP_DEVICE_OBJECT])[m]);
+assume (forall m:int :: {Mem[T.PP_FILE_OBJECT][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.PP_FILE_OBJECT][m] == old(Mem[T.PP_FILE_OBJECT])[m]);
+assume (forall m:int :: {Mem[T.PUINT2][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.PUINT2][m] == old(Mem[T.PUINT2])[m]);
+assume (forall m:int :: {Mem[T.PUINT4][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.PUINT4][m] == old(Mem[T.PUINT4])[m]);
+assume (forall m:int :: {Mem[T.PVOID][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.PVOID][m] == old(Mem[T.PVOID])[m]);
+assume (forall m:int :: {Mem[T.P_DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.P_DEVICE_EXTENSION][m] == old(Mem[T.P_DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.P_DEVICE_OBJECT][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.P_DEVICE_OBJECT][m] == old(Mem[T.P_DEVICE_OBJECT])[m]);
+assume (forall m:int :: {Mem[T.P_DRIVER_OBJECT][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.P_DRIVER_OBJECT][m] == old(Mem[T.P_DRIVER_OBJECT])[m]);
+assume (forall m:int :: {Mem[T.P_FAST_MUTEX][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.P_FAST_MUTEX][m] == old(Mem[T.P_FAST_MUTEX])[m]);
+assume (forall m:int :: {Mem[T.P_FILE_OBJECT][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.P_FILE_OBJECT][m] == old(Mem[T.P_FILE_OBJECT])[m]);
+assume (forall m:int :: {Mem[T.P_KEYBOARD_INPUT_DATA][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.P_KEYBOARD_INPUT_DATA][m] == old(Mem[T.P_KEYBOARD_INPUT_DATA])[m]);
+assume (forall m:int :: {Mem[T.P_LIST_ENTRY][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.P_LIST_ENTRY][m] == old(Mem[T.P_LIST_ENTRY])[m]);
+assume (forall m:int :: {Mem[T.P_UNICODE_STRING][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.P_UNICODE_STRING][m] == old(Mem[T.P_UNICODE_STRING])[m]);
+assume (forall m:int :: {Mem[T.PnP__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.PnP__DEVICE_EXTENSION][m] == old(Mem[T.PnP__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.Port__PORT][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.Port__PORT][m] == old(Mem[T.Port__PORT])[m]);
+assume (forall m:int :: {Mem[T.PortsServiced__GLOBALS][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.PortsServiced__GLOBALS][m] == old(Mem[T.PortsServiced__GLOBALS])[m]);
+assume (forall m:int :: {Mem[T.Self__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.Self__DEVICE_EXTENSION][m] == old(Mem[T.Self__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.StackSize__DEVICE_OBJECT][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.StackSize__DEVICE_OBJECT][m] == old(Mem[T.StackSize__DEVICE_OBJECT])[m]);
+assume (forall m:int :: {Mem[T.Started__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.Started__DEVICE_EXTENSION][m] == old(Mem[T.Started__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.TopPort__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.TopPort__DEVICE_EXTENSION][m] == old(Mem[T.TopPort__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.UCHAR][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.UCHAR][m] == old(Mem[T.UCHAR])[m]);
+assume (forall m:int :: {Mem[T.UINT2][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.UINT2][m] == old(Mem[T.UINT2])[m]);
+assume (forall m:int :: {Mem[T.UINT4][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.UINT4][m] == old(Mem[T.UINT4])[m]);
+assume (forall m:int :: {Mem[T.UnitId__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.UnitId__DEVICE_EXTENSION][m] == old(Mem[T.UnitId__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T._POOL_TYPE][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T._POOL_TYPE][m] == old(Mem[T._POOL_TYPE])[m]);
+return;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(5070)
+label_2:
+assume false;
+return;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(4886)
+label_3:
+goto label_4;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(4887)
+label_4:
+goto label_5;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(4887)
+label_5:
+$deviceExtension$5$4887.28$KeyboardClassFindMorePorts$12 := 0 ;
+goto label_6;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(4888)
+label_6:
+goto label_7;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(4888)
+label_7:
+Mem[T.P_DEVICE_OBJECT] := Mem[T.P_DEVICE_OBJECT][$classDeviceObject$6$4888.28$KeyboardClassFindMorePorts$12 := 0];
+goto label_8;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(4889)
+label_8:
+goto label_9;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(4890)
+label_9:
+goto label_10;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(4891)
+label_10:
+goto label_11;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(4892)
+label_11:
+goto label_12;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(4893)
+label_12:
+goto label_13;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(4894)
+label_13:
+goto label_14;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(4895)
+label_14:
+goto label_15;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(4896)
+label_15:
+goto label_16;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(4896)
+label_16:
+Mem[T.PUINT2] := Mem[T.PUINT2][$fullClassName$14$4896.28$KeyboardClassFindMorePorts$12 := 0];
+goto label_17;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(4897)
+label_17:
+goto label_18;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(4899)
+label_18:
+call __PREfastPagedCode ();
+goto label_21;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(4901)
+label_21:
+Mem[T.MaximumLength__UNICODE_STRING] := Mem[T.MaximumLength__UNICODE_STRING][MaximumLength__UNICODE_STRING($fullPortName$12$4894.28$KeyboardClassFindMorePorts$12) := 0];
+goto label_22;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(4903)
+label_22:
+// ignoring intrinsic intrinsic.memset
+havoc $result.memset$4903.4$1$;
+goto label_25;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(4904)
+label_25:
+Mem[T.Buffer__UNICODE_STRING] := Mem[T.Buffer__UNICODE_STRING][Buffer__UNICODE_STRING($basePortName$11$4893.28$KeyboardClassFindMorePorts$12) := $basePortBuffer$13$4895.28$KeyboardClassFindMorePorts$12];
+goto label_26;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(4905)
+label_26:
+Mem[T.Length__UNICODE_STRING] := Mem[T.Length__UNICODE_STRING][Length__UNICODE_STRING($basePortName$11$4893.28$KeyboardClassFindMorePorts$12) := 0];
+goto label_27;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(4906)
+label_27:
+Mem[T.MaximumLength__UNICODE_STRING] := Mem[T.MaximumLength__UNICODE_STRING][MaximumLength__UNICODE_STRING($basePortName$11$4893.28$KeyboardClassFindMorePorts$12) := 512];
+goto label_28;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(4913)
+label_28:
+call RtlCopyUnicodeString ($basePortName$11$4893.28$KeyboardClassFindMorePorts$12, BaseClassName__GLOBALS(Globals));
+goto label_31;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(4914)
+label_31:
+tempBoogie0 := MINUS_BOTH_PTR_OR_BOTH_INT( Mem[T.Length__UNICODE_STRING][Length__UNICODE_STRING($basePortName$11$4893.28$KeyboardClassFindMorePorts$12)], 10, 1) ;
+Mem[T.Length__UNICODE_STRING] := Mem[T.Length__UNICODE_STRING][Length__UNICODE_STRING($basePortName$11$4893.28$KeyboardClassFindMorePorts$12) := tempBoogie0];
+goto label_35;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(4915)
+label_32:
+call $result.RtlAppendUnicodeToString$4915.28$2$ := RtlAppendUnicodeToString ($basePortName$11$4893.28$KeyboardClassFindMorePorts$12, $RtlAppendUnicodeToString.arg.2$3$);
+goto label_36;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(4915)
+label_35:
+call havoc_stringTemp := __HAVOC_malloc(1);
+$RtlAppendUnicodeToString.arg.2$3$ := havoc_stringTemp ;
+goto label_32;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(4920)
+label_36:
+call RtlInitUnicodeString ($fullPortName$12$4894.28$KeyboardClassFindMorePorts$12, 0);
+goto label_39;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(4922)
+label_39:
+Mem[T.MaximumLength__UNICODE_STRING] := Mem[T.MaximumLength__UNICODE_STRING][MaximumLength__UNICODE_STRING($fullPortName$12$4894.28$KeyboardClassFindMorePorts$12) := PLUS(PLUS(18, 1, Mem[T.Length__UNICODE_STRING][Length__UNICODE_STRING($basePortName$11$4893.28$KeyboardClassFindMorePorts$12)]), 1, 2)];
+goto label_43;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(4926)
+label_40:
+call $result.ExAllocatePoolWithTag$4926.0$4$ := ExAllocatePoolWithTag (1, $ExAllocatePoolWithTag.arg.2$5$, 1130652235);
+goto label_44;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(4926)
+label_43:
+$ExAllocatePoolWithTag.arg.2$5$ := Mem[T.MaximumLength__UNICODE_STRING][MaximumLength__UNICODE_STRING($fullPortName$12$4894.28$KeyboardClassFindMorePorts$12)] ;
+goto label_40;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(4926)
+label_44:
+Mem[T.Buffer__UNICODE_STRING] := Mem[T.Buffer__UNICODE_STRING][Buffer__UNICODE_STRING($fullPortName$12$4894.28$KeyboardClassFindMorePorts$12) := $result.ExAllocatePoolWithTag$4926.0$4$];
+goto label_45;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(4929)
+label_45:
+goto label_45_true , label_45_false ;
+
+
+label_45_true :
+assume (Mem[T.Buffer__UNICODE_STRING][Buffer__UNICODE_STRING($fullPortName$12$4894.28$KeyboardClassFindMorePorts$12)] != 0);
+goto label_57;
+
+
+label_45_false :
+assume (Mem[T.Buffer__UNICODE_STRING][Buffer__UNICODE_STRING($fullPortName$12$4894.28$KeyboardClassFindMorePorts$12)] == 0);
+goto label_49;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(4931)
+label_46:
+// skip KbdDebugPrint
+goto label_50;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(4931)
+label_49:
+call havoc_stringTemp := __HAVOC_malloc(1);
+$KbdDebugPrint.arg.2$6$ := havoc_stringTemp ;
+goto label_46;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(4936)
+label_50:
+Mem[T.UINT4] := Mem[T.UINT4][PLUS($dumpData$7$4889.28$KeyboardClassFindMorePorts$12, 4, 0) := Mem[T.MaximumLength__UNICODE_STRING][MaximumLength__UNICODE_STRING($fullPortName$12$4894.28$KeyboardClassFindMorePorts$12)]];
+goto label_51;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(4937)
+label_51:
+call KeyboardClassLogError ($DriverObject$1$4861.20$KeyboardClassFindMorePorts$12, BOOGIE_LARGE_INT_3221553153, 10008, -1073741823, 1, $dumpData$7$4889.28$KeyboardClassFindMorePorts$12, 0);
+goto label_151;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(4949)
+label_54:
+// ignoring intrinsic intrinsic.memset
+havoc $result.memset$4949.4$7$;
+goto label_61;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(4949)
+label_57:
+$memset.arg.3$8$ := Mem[T.MaximumLength__UNICODE_STRING][MaximumLength__UNICODE_STRING($fullPortName$12$4894.28$KeyboardClassFindMorePorts$12)] ;
+goto label_54;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(4950)
+label_58:
+call $result.RtlAppendUnicodeToString$4950.28$9$ := RtlAppendUnicodeToString ($fullPortName$12$4894.28$KeyboardClassFindMorePorts$12, $RtlAppendUnicodeToString.arg.2$10$);
+goto label_62;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(4950)
+label_61:
+call havoc_stringTemp := __HAVOC_malloc(1);
+$RtlAppendUnicodeToString.arg.2$10$ := havoc_stringTemp ;
+goto label_58;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(4951)
+label_62:
+call $result.RtlAppendUnicodeToString$4951.28$11$ := RtlAppendUnicodeToString ($fullPortName$12$4894.28$KeyboardClassFindMorePorts$12, Mem[T.Buffer__UNICODE_STRING][Buffer__UNICODE_STRING($basePortName$11$4893.28$KeyboardClassFindMorePorts$12)]);
+goto label_68;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(4952)
+label_65:
+call $result.RtlAppendUnicodeToString$4952.28$12$ := RtlAppendUnicodeToString ($fullPortName$12$4894.28$KeyboardClassFindMorePorts$12, $RtlAppendUnicodeToString.arg.2$13$);
+goto label_69;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(4952)
+label_68:
+call havoc_stringTemp := __HAVOC_malloc(1);
+$RtlAppendUnicodeToString.arg.2$13$ := havoc_stringTemp ;
+goto label_65;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(4954)
+label_69:
+call $result.KbdDeterminePortsServiced$4954.29$14$ := KbdDeterminePortsServiced ($basePortName$11$4893.28$KeyboardClassFindMorePorts$12, $numPorts$9$4891.28$KeyboardClassFindMorePorts$12);
+goto label_72;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(4961)
+label_72:
+$i$8$4890.28$KeyboardClassFindMorePorts$12 := Mem[T.NumberLegacyPorts__GLOBALS][NumberLegacyPorts__GLOBALS(Globals)] ;
+goto label_73;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(4961)
+label_73:
+$successfulCreates$10$4892.28$KeyboardClassFindMorePorts$12 := 0 ;
+goto label_74;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(4962)
+label_74:
+// loop entry initialization...
+LOOP_74_alloc := alloc;
+LOOP_74_Mem := Mem;
+LOOP_74_Res_DEVICE_STACK := Res_DEVICE_STACK;
+LOOP_74_Res_DEV_EXTN := Res_DEV_EXTN;
+LOOP_74_Res_DEV_OBJ_INIT := Res_DEV_OBJ_INIT;
+LOOP_74_Res_SPIN_LOCK := Res_SPIN_LOCK;
+goto label_74_head;
+
+
+label_74_head:
+// loop head assertions...
+//TAG: requires __pforall(_H_x, (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension), __inv_resource("DEV_OBJ_INIT", 1), ((struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension))->Self == _H_x && __resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension)) == 1)
+assert((forall _H_x:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)]} Inverse(Res_DEV_OBJ_INIT,1)[_H_x] ==> ((Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)])] == _H_x) && (Res_DEV_EXTN[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)]] == 1))));
+//TAG: requires __pforall(_H_z, _H_z->Self, __inv_resource("DEV_EXTN", 1), __resource("DEV_OBJ_INIT", _H_z->Self) == 1 && (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)(_H_z->Self))->DeviceExtension) == _H_z)
+assert((forall _H_z:int :: {Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)]} Inverse(Res_DEV_EXTN,1)[_H_z] ==> ((Res_DEV_OBJ_INIT[Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)]] == 1) && (Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)])] == _H_z))));
+//TAG: requires __forall(_H_z, __inv_resource("DEV_EXTN", 1), 1)
+assert((Subset(Empty(), Inverse(Res_DEV_EXTN,1)) && (forall _H_z : int :: {Inverse(Res_DEV_EXTN,1)[_H_z]} (Inverse(Res_DEV_EXTN,1)[_H_z]) ==> (true))));
+//TAG: requires 1 ==> (Globals.GrandMaster != (void *)0 ==> __resource("DEV_EXTN", Globals.GrandMaster) == 1)
+assert((true) ==> ((Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)] != 0) ==> (Res_DEV_EXTN[Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)]] == 1)));
+//TAG: requires 1 ==> __setin(&Globals.LegacyDeviceList, __btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList))
+assert((true) ==> (ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[LegacyDeviceList__GLOBALS(Globals)]));
+//TAG: requires 1 ==> __forall(_H_y, __btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList), _H_y == &Globals.LegacyDeviceList || __resource("DEV_EXTN", CONTAINING_RECORD(_H_y, struct _DEVICE_EXTENSION , Link)) == 1)
+assert((true) ==> ((Subset(Empty(), ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))) && (forall _H_y : int :: {ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[_H_y]} (ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[_H_y]) ==> ((_H_y == LegacyDeviceList__GLOBALS(Globals)) || (Res_DEV_EXTN[MINUS_LEFT_PTR(_H_y, 1, Link__DEVICE_EXTENSION(0))] == 1))))));
+//TAG: requires 1 ==> !__setin(&Globals.GrandMaster->Link, __setminus(__btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList), __set(&Globals.LegacyDeviceList)))
+assert((true) ==> (!(Difference(ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals)), Singleton(LegacyDeviceList__GLOBALS(Globals)))[Link__DEVICE_EXTENSION(Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)])])));
+assume(forall f:int :: {alloc[Base(f)]} LOOP_74_alloc[Base(f)] == UNALLOCATED || LOOP_74_alloc[Base(f)] == alloc[Base(f)]);
+
+
+//TAG: net change in resource DEVICE_STACK only for: __set_empty
+assert (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEVICE_STACK[r]} (Empty()[r]) || LOOP_74_Res_DEVICE_STACK[r] == Res_DEVICE_STACK[r]));
+
+//TAG: net change in resource DEV_EXTN only for: __set_true
+assert (Subset(Empty(), Union(Empty(), SetTrue())) && (forall r:int :: {Res_DEV_EXTN[r]} (SetTrue()[r]) || LOOP_74_Res_DEV_EXTN[r] == Res_DEV_EXTN[r]));
+
+//TAG: net change in resource DEV_OBJ_INIT only for: __set_true
+assert (Subset(Empty(), Union(Empty(), SetTrue())) && (forall r:int :: {Res_DEV_OBJ_INIT[r]} (SetTrue()[r]) || LOOP_74_Res_DEV_OBJ_INIT[r] == Res_DEV_OBJ_INIT[r]));
+
+//TAG: net change in resource SPIN_LOCK only for: __set_empty
+assert (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_SPIN_LOCK[r]} (Empty()[r]) || LOOP_74_Res_SPIN_LOCK[r] == Res_SPIN_LOCK[r]));
+//TAG: updated memory locations at Mem[T.MinorFunction__IO_STACK_LOCATION] only for: __set_empty
+assert (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.MinorFunction__IO_STACK_LOCATION][_m]} (Empty()[_m]) || Mem[T.MinorFunction__IO_STACK_LOCATION][_m] == LOOP_74_Mem[T.MinorFunction__IO_STACK_LOCATION][_m]));
+//TAG: updated memory locations at Mem[T.CurrentStackLocation___unnamed_4_f19b65c1] only for: __set_empty
+assert (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.CurrentStackLocation___unnamed_4_f19b65c1][_m]} (Empty()[_m]) || Mem[T.CurrentStackLocation___unnamed_4_f19b65c1][_m] == LOOP_74_Mem[T.CurrentStackLocation___unnamed_4_f19b65c1][_m]));
+//TAG: updated memory locations at Mem[T.DeviceExtension__DEVICE_OBJECT] only for: __set_empty
+assert (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.DeviceExtension__DEVICE_OBJECT][_m] == LOOP_74_Mem[T.DeviceExtension__DEVICE_OBJECT][_m]));
+//TAG: updated memory locations at Mem[T.Self__DEVICE_EXTENSION] only for: __set_true
+assert (Subset(Empty(), Union(Empty(), SetTrue())) && (forall _m:int :: {Mem[T.Self__DEVICE_EXTENSION][_m]} (SetTrue()[_m]) || Mem[T.Self__DEVICE_EXTENSION][_m] == LOOP_74_Mem[T.Self__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.Started__DEVICE_EXTENSION] only for: __set_empty
+assert (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Started__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Started__DEVICE_EXTENSION][_m] == LOOP_74_Mem[T.Started__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.GrandMaster__GLOBALS] only for: __set_empty
+assert (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.GrandMaster__GLOBALS][_m]} (Empty()[_m]) || Mem[T.GrandMaster__GLOBALS][_m] == LOOP_74_Mem[T.GrandMaster__GLOBALS][_m]));
+//TAG: updated memory locations at Mem[T.P_DEVICE_OBJECT] only for: __set_true
+assert (Subset(Empty(), Union(Empty(), SetTrue())) && (forall _m:int :: {Mem[T.P_DEVICE_OBJECT][_m]} (SetTrue()[_m]) || Mem[T.P_DEVICE_OBJECT][_m] == LOOP_74_Mem[T.P_DEVICE_OBJECT][_m]));
+
+// end loop head assertions
+
+goto label_74_true , label_74_false ;
+
+
+label_74_true :
+assume ($i$8$4890.28$KeyboardClassFindMorePorts$12 < Mem[T.PortsServiced__GLOBALS][PortsServiced__GLOBALS(Globals)]);
+goto label_75;
+
+
+label_74_false :
+assume !($i$8$4890.28$KeyboardClassFindMorePorts$12 < Mem[T.PortsServiced__GLOBALS][PortsServiced__GLOBALS(Globals)]);
+goto label_150;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(4962)
+label_75:
+goto label_75_true , label_75_false ;
+
+
+label_75_true :
+assume ($i$8$4890.28$KeyboardClassFindMorePorts$12 < Mem[T.UINT4][$numPorts$9$4891.28$KeyboardClassFindMorePorts$12]);
+goto label_76;
+
+
+label_75_false :
+assume !($i$8$4890.28$KeyboardClassFindMorePorts$12 < Mem[T.UINT4][$numPorts$9$4891.28$KeyboardClassFindMorePorts$12]);
+goto label_150;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(4973)
+label_76:
+Mem[T.UINT2] := Mem[T.UINT2][PLUS(Mem[T.Buffer__UNICODE_STRING][Buffer__UNICODE_STRING($fullPortName$12$4894.28$KeyboardClassFindMorePorts$12)], 2, MINUS_BOTH_PTR_OR_BOTH_INT( BINARY_BOTH_INT(Mem[T.Length__UNICODE_STRING][Length__UNICODE_STRING($fullPortName$12$4894.28$KeyboardClassFindMorePorts$12)], 2), 1, 1)) := PLUS(48, 1, $i$8$4890.28$KeyboardClassFindMorePorts$12)];
+goto label_77;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(4978)
+label_77:
+call $result.KbdCreateClassObject$4978.38$15$ := KbdCreateClassObject ($DriverObject$1$4861.20$KeyboardClassFindMorePorts$12, InitExtension__GLOBALS(Globals), $classDeviceObject$6$4888.28$KeyboardClassFindMorePorts$12, $fullClassName$14$4896.28$KeyboardClassFindMorePorts$12, 1);
+goto label_80;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(4978)
+label_80:
+$status$4$4886.28$KeyboardClassFindMorePorts$12 := $result.KbdCreateClassObject$4978.38$15$ ;
+goto label_81;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(4984)
+label_81:
+goto label_81_true , label_81_false ;
+
+
+label_81_true :
+assume (0 <= $status$4$4886.28$KeyboardClassFindMorePorts$12);
+goto label_85;
+
+
+label_81_false :
+assume !(0 <= $status$4$4886.28$KeyboardClassFindMorePorts$12);
+goto label_82;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(4985)
+label_82:
+call KeyboardClassLogError ($DriverObject$1$4861.20$KeyboardClassFindMorePorts$12, BOOGIE_LARGE_INT_3221553153, 10008, $status$4$4886.28$KeyboardClassFindMorePorts$12, 0, 0, 0);
+goto label_149;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(4995)
+label_85:
+$deviceExtension$5$4887.28$KeyboardClassFindMorePorts$12 := Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.P_DEVICE_OBJECT][$classDeviceObject$6$4888.28$KeyboardClassFindMorePorts$12])] ;
+goto label_86;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(4996)
+label_86:
+Mem[T.PnP__DEVICE_EXTENSION] := Mem[T.PnP__DEVICE_EXTENSION][PnP__DEVICE_EXTENSION($deviceExtension$5$4887.28$KeyboardClassFindMorePorts$12) := 0];
+goto label_87;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(5001)
+label_87:
+assume (Mem[T.TopPort__DEVICE_EXTENSION][TopPort__DEVICE_EXTENSION($deviceExtension$5$4887.28$KeyboardClassFindMorePorts$12)] == Mem[T.P_DEVICE_OBJECT][TopPort__DEVICE_EXTENSION($deviceExtension$5$4887.28$KeyboardClassFindMorePorts$12)]);
+call $result.IoGetDeviceObjectPointer$5001.42$16$ := IoGetDeviceObjectPointer ($fullPortName$12$4894.28$KeyboardClassFindMorePorts$12, 128, $file$15$4897.28$KeyboardClassFindMorePorts$12, TopPort__DEVICE_EXTENSION($deviceExtension$5$4887.28$KeyboardClassFindMorePorts$12));
+Mem[T.TopPort__DEVICE_EXTENSION] := Mem[T.TopPort__DEVICE_EXTENSION][TopPort__DEVICE_EXTENSION($deviceExtension$5$4887.28$KeyboardClassFindMorePorts$12) := Mem[T.P_DEVICE_OBJECT][TopPort__DEVICE_EXTENSION($deviceExtension$5$4887.28$KeyboardClassFindMorePorts$12)]];
+goto label_90;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(5001)
+label_90:
+$status$4$4886.28$KeyboardClassFindMorePorts$12 := $result.IoGetDeviceObjectPointer$5001.42$16$ ;
+goto label_91;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(5006)
+label_91:
+goto label_91_true , label_91_false ;
+
+
+label_91_true :
+assume ($status$4$4886.28$KeyboardClassFindMorePorts$12 != 0);
+goto label_92;
+
+
+label_91_false :
+assume ($status$4$4886.28$KeyboardClassFindMorePorts$12 == 0);
+goto label_103;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(5008)
+label_92:
+goto label_92_true , label_92_false ;
+
+
+label_92_true :
+assume (Mem[T.InputData__DEVICE_EXTENSION][InputData__DEVICE_EXTENSION($deviceExtension$5$4887.28$KeyboardClassFindMorePorts$12)] != 0);
+goto label_93;
+
+
+label_92_false :
+assume (Mem[T.InputData__DEVICE_EXTENSION][InputData__DEVICE_EXTENSION($deviceExtension$5$4887.28$KeyboardClassFindMorePorts$12)] == 0);
+goto label_99;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(5008)
+label_93:
+call ExFreePoolWithTag (Mem[T.InputData__DEVICE_EXTENSION][InputData__DEVICE_EXTENSION($deviceExtension$5$4887.28$KeyboardClassFindMorePorts$12)], 0);
+goto label_96;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(5008)
+label_96:
+Mem[T.DataOut__DEVICE_EXTENSION] := Mem[T.DataOut__DEVICE_EXTENSION][DataOut__DEVICE_EXTENSION($deviceExtension$5$4887.28$KeyboardClassFindMorePorts$12) := 0];
+goto label_97;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(5008)
+label_97:
+Mem[T.DataIn__DEVICE_EXTENSION] := Mem[T.DataIn__DEVICE_EXTENSION][DataIn__DEVICE_EXTENSION($deviceExtension$5$4887.28$KeyboardClassFindMorePorts$12) := Mem[T.DataOut__DEVICE_EXTENSION][DataOut__DEVICE_EXTENSION($deviceExtension$5$4887.28$KeyboardClassFindMorePorts$12)]];
+goto label_98;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(5008)
+label_98:
+Mem[T.InputData__DEVICE_EXTENSION] := Mem[T.InputData__DEVICE_EXTENSION][InputData__DEVICE_EXTENSION($deviceExtension$5$4887.28$KeyboardClassFindMorePorts$12) := Mem[T.DataIn__DEVICE_EXTENSION][DataIn__DEVICE_EXTENSION($deviceExtension$5$4887.28$KeyboardClassFindMorePorts$12)]];
+goto label_99;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(5008)
+label_99:
+call IoDeleteDevice (Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION($deviceExtension$5$4887.28$KeyboardClassFindMorePorts$12)]);
+goto label_102;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(5008)
+label_102:
+$deviceExtension$5$4887.28$KeyboardClassFindMorePorts$12 := 0 ;
+goto label_149;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(5012)
+label_103:
+Mem[T.StackSize__DEVICE_OBJECT] := Mem[T.StackSize__DEVICE_OBJECT][StackSize__DEVICE_OBJECT(Mem[T.P_DEVICE_OBJECT][$classDeviceObject$6$4888.28$KeyboardClassFindMorePorts$12]) := PLUS(1, 1, Mem[T.StackSize__DEVICE_OBJECT][StackSize__DEVICE_OBJECT(Mem[T.TopPort__DEVICE_EXTENSION][TopPort__DEVICE_EXTENSION($deviceExtension$5$4887.28$KeyboardClassFindMorePorts$12)])])];
+goto label_104;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(5013)
+label_104:
+call $result.KeyboardAddDeviceEx$5013.37$17$ := KeyboardAddDeviceEx ($deviceExtension$5$4887.28$KeyboardClassFindMorePorts$12, Mem[T.PUINT2][$fullClassName$14$4896.28$KeyboardClassFindMorePorts$12], Mem[T.P_FILE_OBJECT][$file$15$4897.28$KeyboardClassFindMorePorts$12]);
+goto label_107;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(5013)
+label_107:
+$status$4$4886.28$KeyboardClassFindMorePorts$12 := $result.KeyboardAddDeviceEx$5013.37$17$ ;
+goto label_108;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(5014)
+label_108:
+assume (forall r:int :: {BIT_BAND(BIT_BAND(Mem[T.Flags__DEVICE_OBJECT][Flags__DEVICE_OBJECT(Mem[T.P_DEVICE_OBJECT][$classDeviceObject$6$4888.28$KeyboardClassFindMorePorts$12])], BIT_BNOT(128)),r)} (POW2(r) && POW2(128) && r != 128) ==> (BIT_BAND(Mem[T.Flags__DEVICE_OBJECT][Flags__DEVICE_OBJECT(Mem[T.P_DEVICE_OBJECT][$classDeviceObject$6$4888.28$KeyboardClassFindMorePorts$12])],r)!= 0 <==> BIT_BAND(BIT_BAND(Mem[T.Flags__DEVICE_OBJECT][Flags__DEVICE_OBJECT(Mem[T.P_DEVICE_OBJECT][$classDeviceObject$6$4888.28$KeyboardClassFindMorePorts$12])], BIT_BNOT(128)),r)!= 0));
+assume (BIT_BAND(BIT_BAND(Mem[T.Flags__DEVICE_OBJECT][Flags__DEVICE_OBJECT(Mem[T.P_DEVICE_OBJECT][$classDeviceObject$6$4888.28$KeyboardClassFindMorePorts$12])], BIT_BNOT(128)),128) == 0);
+tempBoogie0 := BIT_BAND(Mem[T.Flags__DEVICE_OBJECT][Flags__DEVICE_OBJECT(Mem[T.P_DEVICE_OBJECT][$classDeviceObject$6$4888.28$KeyboardClassFindMorePorts$12])], BIT_BNOT(128)) ;
+Mem[T.Flags__DEVICE_OBJECT] := Mem[T.Flags__DEVICE_OBJECT][Flags__DEVICE_OBJECT(Mem[T.P_DEVICE_OBJECT][$classDeviceObject$6$4888.28$KeyboardClassFindMorePorts$12]) := tempBoogie0];
+goto label_109;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(5016)
+label_109:
+goto label_109_true , label_109_false ;
+
+
+label_109_true :
+assume (Mem[T.PUINT2][$fullClassName$14$4896.28$KeyboardClassFindMorePorts$12] != 0);
+goto label_110;
+
+
+label_109_false :
+assume (Mem[T.PUINT2][$fullClassName$14$4896.28$KeyboardClassFindMorePorts$12] == 0);
+goto label_114;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(5017)
+label_110:
+call ExFreePoolWithTag (Mem[T.PUINT2][$fullClassName$14$4896.28$KeyboardClassFindMorePorts$12], 0);
+goto label_113;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(5018)
+label_113:
+Mem[T.PUINT2] := Mem[T.PUINT2][$fullClassName$14$4896.28$KeyboardClassFindMorePorts$12 := 0];
+goto label_114;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(5021)
+label_114:
+goto label_114_true , label_114_false ;
+
+
+label_114_true :
+assume (0 <= $status$4$4886.28$KeyboardClassFindMorePorts$12);
+goto label_145;
+
+
+label_114_false :
+assume !(0 <= $status$4$4886.28$KeyboardClassFindMorePorts$12);
+goto label_115;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(5022)
+label_115:
+goto label_115_true , label_115_false ;
+
+
+label_115_true :
+assume (Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)] != 0);
+goto label_119;
+
+
+label_115_false :
+assume (Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)] == 0);
+goto label_116;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(5023)
+label_116:
+goto label_116_true , label_116_false ;
+
+
+label_116_true :
+assume (Mem[T.File__DEVICE_EXTENSION][File__DEVICE_EXTENSION($deviceExtension$5$4887.28$KeyboardClassFindMorePorts$12)] != 0);
+goto label_117;
+
+
+label_116_false :
+assume (Mem[T.File__DEVICE_EXTENSION][File__DEVICE_EXTENSION($deviceExtension$5$4887.28$KeyboardClassFindMorePorts$12)] == 0);
+goto label_130;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(5024)
+label_117:
+Mem[T.P_FILE_OBJECT] := Mem[T.P_FILE_OBJECT][$file$15$4897.28$KeyboardClassFindMorePorts$12 := Mem[T.File__DEVICE_EXTENSION][File__DEVICE_EXTENSION($deviceExtension$5$4887.28$KeyboardClassFindMorePorts$12)]];
+goto label_118;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(5025)
+label_118:
+Mem[T.File__DEVICE_EXTENSION] := Mem[T.File__DEVICE_EXTENSION][File__DEVICE_EXTENSION($deviceExtension$5$4887.28$KeyboardClassFindMorePorts$12) := 0];
+goto label_130;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(5029)
+label_119:
+goto label_120;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(5031)
+label_120:
+call ExAcquireFastMutex (Mutex__GLOBALS(Globals));
+goto label_123;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(5033)
+label_123:
+Mem[T.P_FILE_OBJECT] := Mem[T.P_FILE_OBJECT][$file$15$4897.28$KeyboardClassFindMorePorts$12 := Mem[T.File__PORT][File__PORT(PLUS(Mem[T.AssocClassList__GLOBALS][AssocClassList__GLOBALS(Globals)], 12, Mem[T.UnitId__DEVICE_EXTENSION][UnitId__DEVICE_EXTENSION($deviceExtension$5$4887.28$KeyboardClassFindMorePorts$12)]))]];
+goto label_124;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(5034)
+label_124:
+Mem[T.File__PORT] := Mem[T.File__PORT][File__PORT(PLUS(Mem[T.AssocClassList__GLOBALS][AssocClassList__GLOBALS(Globals)], 12, Mem[T.UnitId__DEVICE_EXTENSION][UnitId__DEVICE_EXTENSION($deviceExtension$5$4887.28$KeyboardClassFindMorePorts$12)])) := 0];
+goto label_125;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(5035)
+label_125:
+Mem[T.Free__PORT] := Mem[T.Free__PORT][Free__PORT(PLUS(Mem[T.AssocClassList__GLOBALS][AssocClassList__GLOBALS(Globals)], 12, Mem[T.UnitId__DEVICE_EXTENSION][UnitId__DEVICE_EXTENSION($deviceExtension$5$4887.28$KeyboardClassFindMorePorts$12)])) := 1];
+goto label_126;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(5036)
+label_126:
+Mem[T.Port__PORT] := Mem[T.Port__PORT][Port__PORT(PLUS(Mem[T.AssocClassList__GLOBALS][AssocClassList__GLOBALS(Globals)], 12, Mem[T.UnitId__DEVICE_EXTENSION][UnitId__DEVICE_EXTENSION($deviceExtension$5$4887.28$KeyboardClassFindMorePorts$12)])) := 0];
+goto label_127;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(5038)
+label_127:
+call ExReleaseFastMutex (Mutex__GLOBALS(Globals));
+goto label_130;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(5041)
+label_130:
+goto label_130_true , label_130_false ;
+
+
+label_130_true :
+assume (Mem[T.P_FILE_OBJECT][$file$15$4897.28$KeyboardClassFindMorePorts$12] != 0);
+goto label_131;
+
+
+label_130_false :
+assume (Mem[T.P_FILE_OBJECT][$file$15$4897.28$KeyboardClassFindMorePorts$12] == 0);
+goto label_134;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(5042)
+label_131:
+call $result.ObfDereferenceObject$5042.16$18$ := ObfDereferenceObject (Mem[T.P_FILE_OBJECT][$file$15$4897.28$KeyboardClassFindMorePorts$12]);
+goto label_134;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(5045)
+label_134:
+goto label_134_true , label_134_false ;
+
+
+label_134_true :
+assume (Mem[T.InputData__DEVICE_EXTENSION][InputData__DEVICE_EXTENSION($deviceExtension$5$4887.28$KeyboardClassFindMorePorts$12)] != 0);
+goto label_135;
+
+
+label_134_false :
+assume (Mem[T.InputData__DEVICE_EXTENSION][InputData__DEVICE_EXTENSION($deviceExtension$5$4887.28$KeyboardClassFindMorePorts$12)] == 0);
+goto label_141;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(5045)
+label_135:
+call ExFreePoolWithTag (Mem[T.InputData__DEVICE_EXTENSION][InputData__DEVICE_EXTENSION($deviceExtension$5$4887.28$KeyboardClassFindMorePorts$12)], 0);
+goto label_138;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(5045)
+label_138:
+Mem[T.DataOut__DEVICE_EXTENSION] := Mem[T.DataOut__DEVICE_EXTENSION][DataOut__DEVICE_EXTENSION($deviceExtension$5$4887.28$KeyboardClassFindMorePorts$12) := 0];
+goto label_139;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(5045)
+label_139:
+Mem[T.DataIn__DEVICE_EXTENSION] := Mem[T.DataIn__DEVICE_EXTENSION][DataIn__DEVICE_EXTENSION($deviceExtension$5$4887.28$KeyboardClassFindMorePorts$12) := Mem[T.DataOut__DEVICE_EXTENSION][DataOut__DEVICE_EXTENSION($deviceExtension$5$4887.28$KeyboardClassFindMorePorts$12)]];
+goto label_140;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(5045)
+label_140:
+Mem[T.InputData__DEVICE_EXTENSION] := Mem[T.InputData__DEVICE_EXTENSION][InputData__DEVICE_EXTENSION($deviceExtension$5$4887.28$KeyboardClassFindMorePorts$12) := Mem[T.DataIn__DEVICE_EXTENSION][DataIn__DEVICE_EXTENSION($deviceExtension$5$4887.28$KeyboardClassFindMorePorts$12)]];
+goto label_141;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(5045)
+label_141:
+call IoDeleteDevice (Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION($deviceExtension$5$4887.28$KeyboardClassFindMorePorts$12)]);
+goto label_144;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(5045)
+label_144:
+$deviceExtension$5$4887.28$KeyboardClassFindMorePorts$12 := 0 ;
+goto label_149;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(5052)
+label_145:
+call InsertTailList (LegacyDeviceList__GLOBALS(Globals), Link__DEVICE_EXTENSION($deviceExtension$5$4887.28$KeyboardClassFindMorePorts$12));
+goto label_148;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(5053)
+label_148:
+$successfulCreates$10$4892.28$KeyboardClassFindMorePorts$12 := PLUS($successfulCreates$10$4892.28$KeyboardClassFindMorePorts$12, 1, 1) ;
+goto label_149;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(4963)
+label_149:
+$i$8$4890.28$KeyboardClassFindMorePorts$12 := PLUS($i$8$4890.28$KeyboardClassFindMorePorts$12, 1, 1) ;
+goto label_74_head;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(5055)
+label_150:
+Mem[T.NumberLegacyPorts__GLOBALS] := Mem[T.NumberLegacyPorts__GLOBALS][NumberLegacyPorts__GLOBALS(Globals) := $i$8$4890.28$KeyboardClassFindMorePorts$12];
+goto label_151;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(5063)
+label_151:
+goto label_151_true , label_151_false ;
+
+
+label_151_true :
+assume (Mem[T.Buffer__UNICODE_STRING][Buffer__UNICODE_STRING($fullPortName$12$4894.28$KeyboardClassFindMorePorts$12)] != 0);
+goto label_152;
+
+
+label_151_false :
+assume (Mem[T.Buffer__UNICODE_STRING][Buffer__UNICODE_STRING($fullPortName$12$4894.28$KeyboardClassFindMorePorts$12)] == 0);
+goto label_155;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(5064)
+label_152:
+call ExFreePoolWithTag (Mem[T.Buffer__UNICODE_STRING][Buffer__UNICODE_STRING($fullPortName$12$4894.28$KeyboardClassFindMorePorts$12)], 0);
+goto label_155;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(5067)
+label_155:
+goto label_155_true , label_155_false ;
+
+
+label_155_true :
+assume (Mem[T.PUINT2][$fullClassName$14$4896.28$KeyboardClassFindMorePorts$12] != 0);
+goto label_156;
+
+
+label_155_false :
+assume (Mem[T.PUINT2][$fullClassName$14$4896.28$KeyboardClassFindMorePorts$12] == 0);
+goto label_1;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(5068)
+label_156:
+call ExFreePoolWithTag (Mem[T.PUINT2][$fullClassName$14$4896.28$KeyboardClassFindMorePorts$12], 0);
+goto label_1;
+
+}
+
diff --git a/Test/havoc0/KeyboardClassUnload.bpl b/Test/havoc0/KeyboardClassUnload.bpl
new file mode 100644
index 00000000..3deae4cd
--- /dev/null
+++ b/Test/havoc0/KeyboardClassUnload.bpl
@@ -0,0 +1,3333 @@
+type byte, name;
+function OneByteToInt(byte) returns (int);
+function TwoBytesToInt(byte, byte) returns (int);
+function FourBytesToInt(byte, byte, byte, byte) returns (int);
+axiom(forall b0:byte, c0:byte :: {OneByteToInt(b0), OneByteToInt(c0)} OneByteToInt(b0) == OneByteToInt(c0) ==> b0 == c0);
+axiom(forall b0:byte, b1: byte, c0:byte, c1:byte :: {TwoBytesToInt(b0, b1), TwoBytesToInt(c0, c1)} TwoBytesToInt(b0, b1) == TwoBytesToInt(c0, c1) ==> b0 == c0 && b1 == c1);
+axiom(forall b0:byte, b1: byte, b2:byte, b3:byte, c0:byte, c1:byte, c2:byte, c3:byte :: {FourBytesToInt(b0, b1, b2, b3), FourBytesToInt(c0, c1, c2, c3)} FourBytesToInt(b0, b1, b2, b3) == FourBytesToInt(c0, c1, c2, c3) ==> b0 == c0 && b1 == c1 && b2 == c2 && b3 == c3);
+
+// Mutable
+var Mem_BYTE:[int]byte;
+var alloc:[int]name;
+
+
+function Field(int) returns (name);
+function Base(int) returns (int);
+
+// Constants
+const unique UNALLOCATED:name;
+const unique ALLOCATED: name;
+const unique FREED:name;
+
+const unique BYTE:name;
+
+function Equal([int]bool, [int]bool) returns (bool);
+function Subset([int]bool, [int]bool) returns (bool);
+function Disjoint([int]bool, [int]bool) returns (bool);
+
+function Empty() returns ([int]bool);
+function SetTrue() returns ([int]bool);
+function Singleton(int) returns ([int]bool);
+function Reachable([int,int]bool, int) returns ([int]bool);
+function Union([int]bool, [int]bool) returns ([int]bool);
+function Intersection([int]bool, [int]bool) returns ([int]bool);
+function Difference([int]bool, [int]bool) returns ([int]bool);
+function Dereference([int]bool, [int]int) returns ([int]bool);
+function Inverse(f:[int]int, x:int) returns ([int]bool);
+
+function AtLeast(int, int) returns ([int]bool);
+function Rep(int, int) returns (int);
+axiom(forall n:int, x:int, y:int :: {AtLeast(n,x)[y]} AtLeast(n,x)[y] ==> x <= y && Rep(n,x) == Rep(n,y));
+axiom(forall n:int, x:int, y:int :: {AtLeast(n,x),Rep(n,x),Rep(n,y)} x <= y && Rep(n,x) == Rep(n,y) ==> AtLeast(n,x)[y]);
+axiom(forall n:int, x:int :: {AtLeast(n,x)} AtLeast(n,x)[x]);
+axiom(forall n:int, x:int, z:int :: {PLUS(x,n,z)} Rep(n,x) == Rep(n,PLUS(x,n,z)));
+axiom(forall n:int, x:int :: {Rep(n,x)} (exists k:int :: Rep(n,x) - x == n*k));
+
+/*
+function AtLeast(int, int) returns ([int]bool);
+function ModEqual(int, int, int) returns (bool);
+axiom(forall n:int, x:int :: ModEqual(n,x,x));
+axiom(forall n:int, x:int, y:int :: {ModEqual(n,x,y)} ModEqual(n,x,y) ==> ModEqual(n,y,x));
+axiom(forall n:int, x:int, y:int, z:int :: {ModEqual(n,x,y), ModEqual(n,y,z)} ModEqual(n,x,y) && ModEqual(n,y,z) ==> ModEqual(n,x,z));
+axiom(forall n:int, x:int, z:int :: {PLUS(x,n,z)} ModEqual(n,x,PLUS(x,n,z)));
+axiom(forall n:int, x:int, y:int :: {ModEqual(n,x,y)} ModEqual(n,x,y) ==> (exists k:int :: x - y == n*k));
+axiom(forall x:int, n:int, y:int :: {AtLeast(n,x)[y]}{ModEqual(n,x,y)} AtLeast(n,x)[y] <==> x <= y && ModEqual(n,x,y));
+axiom(forall x:int, n:int :: {AtLeast(n,x)} AtLeast(n,x)[x]);
+*/
+
+function Array(int, int, int) returns ([int]bool);
+axiom(forall x:int, n:int, z:int :: {Array(x,n,z)} z <= 0 ==> Equal(Array(x,n,z), Empty()));
+axiom(forall x:int, n:int, z:int :: {Array(x,n,z)} z > 0 ==> Equal(Array(x,n,z), Difference(AtLeast(n,x),AtLeast(n,PLUS(x,n,z)))));
+
+
+axiom(forall x:int :: !Empty()[x]);
+
+axiom(forall x:int :: SetTrue()[x]);
+
+axiom(forall x:int, y:int :: {Singleton(y)[x]} Singleton(y)[x] <==> x == y);
+axiom(forall y:int :: {Singleton(y)} Singleton(y)[y]);
+
+/* this formulation of Union IS more complete than the earlier one */
+/* (A U B)[e], A[d], A U B = Singleton(c), d != e */
+axiom(forall x:int, S:[int]bool, T:[int]bool :: {Union(S,T)[x]}{Union(S,T),S[x]}{Union(S,T),T[x]} Union(S,T)[x] <==> S[x] || T[x]);
+axiom(forall x:int, S:[int]bool, T:[int]bool :: {Intersection(S,T)[x]}{Intersection(S,T),S[x]}{Intersection(S,T),T[x]} Intersection(S,T)[x] <==> S[x] && T[x]);
+axiom(forall x:int, S:[int]bool, T:[int]bool :: {Difference(S,T)[x]}{Difference(S,T),S[x]}{Difference(S,T),T[x]} Difference(S,T)[x] <==> S[x] && !T[x]);
+
+axiom(forall S:[int]bool, T:[int]bool :: {Equal(S,T)} Equal(S,T) <==> Subset(S,T) && Subset(T,S));
+axiom(forall x:int, S:[int]bool, T:[int]bool :: {S[x],Subset(S,T)}{T[x],Subset(S,T)} S[x] && Subset(S,T) ==> T[x]);
+axiom(forall S:[int]bool, T:[int]bool :: {Subset(S,T)} Subset(S,T) || (exists x:int :: S[x] && !T[x]));
+axiom(forall x:int, S:[int]bool, T:[int]bool :: {S[x],Disjoint(S,T)}{T[x],Disjoint(S,T)} !(S[x] && Disjoint(S,T) && T[x]));
+axiom(forall S:[int]bool, T:[int]bool :: {Disjoint(S,T)} Disjoint(S,T) || (exists x:int :: S[x] && T[x]));
+
+axiom(forall f:[int]int, x:int :: {Inverse(f,f[x])} Inverse(f,f[x])[x]);
+axiom(forall f:[int]int, x:int, y:int :: {Inverse(f,y), f[x]} Inverse(f,y)[x] ==> f[x] == y);
+axiom(forall f:[int]int, x:int, y:int :: {Inverse(f[x := y],y)} Equal(Inverse(f[x := y],y), Union(Inverse(f,y), Singleton(x))));
+axiom(forall f:[int]int, x:int, y:int, z:int :: {Inverse(f[x := y],z)} y == z || Equal(Inverse(f[x := y],z), Difference(Inverse(f,z), Singleton(x))));
+
+
+axiom(forall x:int, S:[int]bool, M:[int]int :: {Dereference(S,M)[x]} Dereference(S,M)[x] ==> (exists y:int :: x == M[y] && S[y]));
+axiom(forall x:int, S:[int]bool, M:[int]int :: {M[x], S[x], Dereference(S,M)} S[x] ==> Dereference(S,M)[M[x]]);
+axiom(forall x:int, y:int, S:[int]bool, M:[int]int :: {Dereference(S,M[x := y])} !S[x] ==> Equal(Dereference(S,M[x := y]), Dereference(S,M)));
+axiom(forall x:int, y:int, S:[int]bool, M:[int]int :: {Dereference(S,M[x := y])}
+ S[x] && Equal(Intersection(Inverse(M,M[x]), S), Singleton(x)) ==> Equal(Dereference(S,M[x := y]), Union(Difference(Dereference(S,M), Singleton(M[x])), Singleton(y))));
+axiom(forall x:int, y:int, S:[int]bool, M:[int]int :: {Dereference(S,M[x := y])}
+ S[x] && !Equal(Intersection(Inverse(M,M[x]), S), Singleton(x)) ==> Equal(Dereference(S,M[x := y]), Union(Dereference(S,M), Singleton(y))));
+
+function Unified([name][int]int) returns ([int]int);
+axiom(forall M:[name][int]int, x:int :: {Unified(M)[x]} Unified(M)[x] == M[Field(x)][x]);
+axiom(forall M:[name][int]int, x:int, y:int :: {Unified(M[Field(x) := M[Field(x)][x := y]])} Unified(M[Field(x) := M[Field(x)][x := y]]) == Unified(M)[x := y]);
+// Memory model
+
+var Mem: [name][int]int;
+
+function Match(a:int, t:name) returns (bool);
+function HasType(v:int, t:name, m:[name][int]int) returns (bool);
+function Values(t:name, m:[name][int]int) returns ([int]bool);
+function T.Ptr(t:name) returns (name);
+
+axiom(forall v:int, t:name, m:[name][int]int :: {Values(t, m)[v]} Values(t, m)[v] ==> HasType(v, t, m));
+axiom(forall v:int, t:name, m:[name][int]int :: {HasType(v, t, m), Values(t, m)} HasType(v, t, m) ==> Values(t, m)[v]);
+
+axiom(forall a:int, t:name :: {Match(a, T.Ptr(t))} Match(a, T.Ptr(t)) <==> Field(a) == T.Ptr(t));
+axiom(forall v:int, t:name, m:[name][int]int :: {HasType(v, T.Ptr(t), m)} HasType(v, T.Ptr(t), m) <==> (v == 0 || (v > 0 && Match(v, t))));
+
+axiom(forall v:int, t:name, m1:[name][int]int, m2:[name][int]int :: {HasType(v, t, m1), HasType(v, t, m2)}
+ (HasType(v, t, m1) <==> HasType(v, t, m2)));
+
+// Field declarations
+
+const unique T.Guid_WMIGUIDREGINFO:name;
+const unique T.InstanceCount_WMIGUIDREGINFO:name;
+const unique T.Flags_WMIGUIDREGINFO:name;
+const unique T.OperationID__ACCESS_STATE:name;
+const unique T.SecurityEvaluated__ACCESS_STATE:name;
+const unique T.GenerateAudit__ACCESS_STATE:name;
+const unique T.GenerateOnClose__ACCESS_STATE:name;
+const unique T.PrivilegesAllocated__ACCESS_STATE:name;
+const unique T.Flags__ACCESS_STATE:name;
+const unique T.RemainingDesiredAccess__ACCESS_STATE:name;
+const unique T.PreviouslyGrantedAccess__ACCESS_STATE:name;
+const unique T.OriginalDesiredAccess__ACCESS_STATE:name;
+const unique T.SubjectSecurityContext__ACCESS_STATE:name;
+const unique T.SecurityDescriptor__ACCESS_STATE:name;
+const unique T.AuxData__ACCESS_STATE:name;
+const unique T.Privileges__ACCESS_STATE:name;
+const unique T.AuditPrivileges__ACCESS_STATE:name;
+const unique T.ObjectName__ACCESS_STATE:name;
+const unique T.ObjectTypeName__ACCESS_STATE:name;
+const unique T.InterfaceType__CM_FULL_RESOURCE_DESCRIPTOR:name;
+const unique T.BusNumber__CM_FULL_RESOURCE_DESCRIPTOR:name;
+const unique T.PartialResourceList__CM_FULL_RESOURCE_DESCRIPTOR:name;
+const unique T.Type__CM_PARTIAL_RESOURCE_DESCRIPTOR:name;
+const unique T.ShareDisposition__CM_PARTIAL_RESOURCE_DESCRIPTOR:name;
+const unique T.Flags__CM_PARTIAL_RESOURCE_DESCRIPTOR:name;
+const unique T.u__CM_PARTIAL_RESOURCE_DESCRIPTOR:name;
+const unique T.Version__CM_PARTIAL_RESOURCE_LIST:name;
+const unique T.Revision__CM_PARTIAL_RESOURCE_LIST:name;
+const unique T.Count__CM_PARTIAL_RESOURCE_LIST:name;
+const unique T.PartialDescriptors__CM_PARTIAL_RESOURCE_LIST:name;
+const unique T.Count__CM_RESOURCE_LIST:name;
+const unique T.List__CM_RESOURCE_LIST:name;
+const unique T.Size__DEVICE_CAPABILITIES:name;
+const unique T.Version__DEVICE_CAPABILITIES:name;
+const unique T.DeviceD1__DEVICE_CAPABILITIES:name;
+const unique T.DeviceD2__DEVICE_CAPABILITIES:name;
+const unique T.LockSupported__DEVICE_CAPABILITIES:name;
+const unique T.EjectSupported__DEVICE_CAPABILITIES:name;
+const unique T.Removable__DEVICE_CAPABILITIES:name;
+const unique T.DockDevice__DEVICE_CAPABILITIES:name;
+const unique T.UniqueID__DEVICE_CAPABILITIES:name;
+const unique T.SilentInstall__DEVICE_CAPABILITIES:name;
+const unique T.RawDeviceOK__DEVICE_CAPABILITIES:name;
+const unique T.SurpriseRemovalOK__DEVICE_CAPABILITIES:name;
+const unique T.WakeFromD0__DEVICE_CAPABILITIES:name;
+const unique T.WakeFromD1__DEVICE_CAPABILITIES:name;
+const unique T.WakeFromD2__DEVICE_CAPABILITIES:name;
+const unique T.WakeFromD3__DEVICE_CAPABILITIES:name;
+const unique T.HardwareDisabled__DEVICE_CAPABILITIES:name;
+const unique T.NonDynamic__DEVICE_CAPABILITIES:name;
+const unique T.WarmEjectSupported__DEVICE_CAPABILITIES:name;
+const unique T.NoDisplayInUI__DEVICE_CAPABILITIES:name;
+const unique T.Reserved__DEVICE_CAPABILITIES:name;
+const unique T.Address__DEVICE_CAPABILITIES:name;
+const unique T.UINumber__DEVICE_CAPABILITIES:name;
+const unique T.DeviceState__DEVICE_CAPABILITIES:name;
+const unique T.SystemWake__DEVICE_CAPABILITIES:name;
+const unique T.DeviceWake__DEVICE_CAPABILITIES:name;
+const unique T.D1Latency__DEVICE_CAPABILITIES:name;
+const unique T.D2Latency__DEVICE_CAPABILITIES:name;
+const unique T.D3Latency__DEVICE_CAPABILITIES:name;
+const unique T.Self__DEVICE_EXTENSION:name;
+const unique T.TrueClassDevice__DEVICE_EXTENSION:name;
+const unique T.TopPort__DEVICE_EXTENSION:name;
+const unique T.PDO__DEVICE_EXTENSION:name;
+const unique T.RemoveLock__DEVICE_EXTENSION:name;
+const unique T.PnP__DEVICE_EXTENSION:name;
+const unique T.Started__DEVICE_EXTENSION:name;
+const unique T.AllowDisable__DEVICE_EXTENSION:name;
+const unique T.WaitWakeSpinLock__DEVICE_EXTENSION:name;
+const unique T.TrustedSubsystemCount__DEVICE_EXTENSION:name;
+const unique T.InputCount__DEVICE_EXTENSION:name;
+const unique T.SymbolicLinkName__DEVICE_EXTENSION:name;
+const unique T.InputData__DEVICE_EXTENSION:name;
+const unique T.DataIn__DEVICE_EXTENSION:name;
+const unique T.DataOut__DEVICE_EXTENSION:name;
+const unique T.KeyboardAttributes__DEVICE_EXTENSION:name;
+const unique T.IndicatorParameters__DEVICE_EXTENSION:name;
+const unique T.SpinLock__DEVICE_EXTENSION:name;
+const unique T.ReadQueue__DEVICE_EXTENSION:name;
+const unique T.SequenceNumber__DEVICE_EXTENSION:name;
+const unique T.DeviceState__DEVICE_EXTENSION:name;
+const unique T.SystemState__DEVICE_EXTENSION:name;
+const unique T.UnitId__DEVICE_EXTENSION:name;
+const unique T.WmiLibInfo__DEVICE_EXTENSION:name;
+const unique T.SystemToDeviceState__DEVICE_EXTENSION:name;
+const unique T.MinDeviceWakeState__DEVICE_EXTENSION:name;
+const unique T.MinSystemWakeState__DEVICE_EXTENSION:name;
+const unique T.WaitWakeIrp__DEVICE_EXTENSION:name;
+const unique T.ExtraWaitWakeIrp__DEVICE_EXTENSION:name;
+const unique T.TargetNotifyHandle__DEVICE_EXTENSION:name;
+const unique T.Link__DEVICE_EXTENSION:name;
+const unique T.File__DEVICE_EXTENSION:name;
+const unique T.Enabled__DEVICE_EXTENSION:name;
+const unique T.OkayToLogOverflow__DEVICE_EXTENSION:name;
+const unique T.WaitWakeEnabled__DEVICE_EXTENSION:name;
+const unique T.SurpriseRemoved__DEVICE_EXTENSION:name;
+const unique T.Type__DEVICE_OBJECT:name;
+const unique T.Size__DEVICE_OBJECT:name;
+const unique T.ReferenceCount__DEVICE_OBJECT:name;
+const unique T.DriverObject__DEVICE_OBJECT:name;
+const unique T.NextDevice__DEVICE_OBJECT:name;
+const unique T.AttachedDevice__DEVICE_OBJECT:name;
+const unique T.CurrentIrp__DEVICE_OBJECT:name;
+const unique T.Timer__DEVICE_OBJECT:name;
+const unique T.Flags__DEVICE_OBJECT:name;
+const unique T.Characteristics__DEVICE_OBJECT:name;
+const unique T.Vpb__DEVICE_OBJECT:name;
+const unique T.DeviceExtension__DEVICE_OBJECT:name;
+const unique T.DeviceType__DEVICE_OBJECT:name;
+const unique T.StackSize__DEVICE_OBJECT:name;
+const unique T.Queue__DEVICE_OBJECT:name;
+const unique T.AlignmentRequirement__DEVICE_OBJECT:name;
+const unique T.DeviceQueue__DEVICE_OBJECT:name;
+const unique T.Dpc__DEVICE_OBJECT:name;
+const unique T.ActiveThreadCount__DEVICE_OBJECT:name;
+const unique T.SecurityDescriptor__DEVICE_OBJECT:name;
+const unique T.DeviceLock__DEVICE_OBJECT:name;
+const unique T.SectorSize__DEVICE_OBJECT:name;
+const unique T.Spare1__DEVICE_OBJECT:name;
+const unique T.DeviceObjectExtension__DEVICE_OBJECT:name;
+const unique T.Reserved__DEVICE_OBJECT:name;
+const unique T.Type__DEVOBJ_EXTENSION:name;
+const unique T.Size__DEVOBJ_EXTENSION:name;
+const unique T.DeviceObject__DEVOBJ_EXTENSION:name;
+const unique T.__unnamed_4_a97c65a1__DISPATCHER_HEADER:name;
+const unique T.SignalState__DISPATCHER_HEADER:name;
+const unique T.WaitListHead__DISPATCHER_HEADER:name;
+const unique T.DriverObject__DRIVER_EXTENSION:name;
+const unique T.AddDevice__DRIVER_EXTENSION:name;
+const unique T.Count__DRIVER_EXTENSION:name;
+const unique T.ServiceKeyName__DRIVER_EXTENSION:name;
+const unique T.Type__DRIVER_OBJECT:name;
+const unique T.Size__DRIVER_OBJECT:name;
+const unique T.DeviceObject__DRIVER_OBJECT:name;
+const unique T.Flags__DRIVER_OBJECT:name;
+const unique T.DriverStart__DRIVER_OBJECT:name;
+const unique T.DriverSize__DRIVER_OBJECT:name;
+const unique T.DriverSection__DRIVER_OBJECT:name;
+const unique T.DriverExtension__DRIVER_OBJECT:name;
+const unique T.DriverName__DRIVER_OBJECT:name;
+const unique T.HardwareDatabase__DRIVER_OBJECT:name;
+const unique T.FastIoDispatch__DRIVER_OBJECT:name;
+const unique T.DriverInit__DRIVER_OBJECT:name;
+const unique T.DriverStartIo__DRIVER_OBJECT:name;
+const unique T.DriverUnload__DRIVER_OBJECT:name;
+const unique T.MajorFunction__DRIVER_OBJECT:name;
+const unique T.SystemResourcesList__ERESOURCE:name;
+const unique T.OwnerTable__ERESOURCE:name;
+const unique T.ActiveCount__ERESOURCE:name;
+const unique T.Flag__ERESOURCE:name;
+const unique T.SharedWaiters__ERESOURCE:name;
+const unique T.ExclusiveWaiters__ERESOURCE:name;
+const unique T.OwnerEntry__ERESOURCE:name;
+const unique T.ActiveEntries__ERESOURCE:name;
+const unique T.ContentionCount__ERESOURCE:name;
+const unique T.NumberOfSharedWaiters__ERESOURCE:name;
+const unique T.NumberOfExclusiveWaiters__ERESOURCE:name;
+const unique T.__unnamed_4_52c594f7__ERESOURCE:name;
+const unique T.SpinLock__ERESOURCE:name;
+const unique T.SizeOfFastIoDispatch__FAST_IO_DISPATCH:name;
+const unique T.FastIoCheckIfPossible__FAST_IO_DISPATCH:name;
+const unique T.FastIoRead__FAST_IO_DISPATCH:name;
+const unique T.FastIoWrite__FAST_IO_DISPATCH:name;
+const unique T.FastIoQueryBasicInfo__FAST_IO_DISPATCH:name;
+const unique T.FastIoQueryStandardInfo__FAST_IO_DISPATCH:name;
+const unique T.FastIoLock__FAST_IO_DISPATCH:name;
+const unique T.FastIoUnlockSingle__FAST_IO_DISPATCH:name;
+const unique T.FastIoUnlockAll__FAST_IO_DISPATCH:name;
+const unique T.FastIoUnlockAllByKey__FAST_IO_DISPATCH:name;
+const unique T.FastIoDeviceControl__FAST_IO_DISPATCH:name;
+const unique T.AcquireFileForNtCreateSection__FAST_IO_DISPATCH:name;
+const unique T.ReleaseFileForNtCreateSection__FAST_IO_DISPATCH:name;
+const unique T.FastIoDetachDevice__FAST_IO_DISPATCH:name;
+const unique T.FastIoQueryNetworkOpenInfo__FAST_IO_DISPATCH:name;
+const unique T.AcquireForModWrite__FAST_IO_DISPATCH:name;
+const unique T.MdlRead__FAST_IO_DISPATCH:name;
+const unique T.MdlReadComplete__FAST_IO_DISPATCH:name;
+const unique T.PrepareMdlWrite__FAST_IO_DISPATCH:name;
+const unique T.MdlWriteComplete__FAST_IO_DISPATCH:name;
+const unique T.FastIoReadCompressed__FAST_IO_DISPATCH:name;
+const unique T.FastIoWriteCompressed__FAST_IO_DISPATCH:name;
+const unique T.MdlReadCompleteCompressed__FAST_IO_DISPATCH:name;
+const unique T.MdlWriteCompleteCompressed__FAST_IO_DISPATCH:name;
+const unique T.FastIoQueryOpen__FAST_IO_DISPATCH:name;
+const unique T.ReleaseForModWrite__FAST_IO_DISPATCH:name;
+const unique T.AcquireForCcFlush__FAST_IO_DISPATCH:name;
+const unique T.ReleaseForCcFlush__FAST_IO_DISPATCH:name;
+const unique T.Count__FAST_MUTEX:name;
+const unique T.Owner__FAST_MUTEX:name;
+const unique T.Contention__FAST_MUTEX:name;
+const unique T.Gate__FAST_MUTEX:name;
+const unique T.OldIrql__FAST_MUTEX:name;
+const unique T.CreationTime__FILE_BASIC_INFORMATION:name;
+const unique T.LastAccessTime__FILE_BASIC_INFORMATION:name;
+const unique T.LastWriteTime__FILE_BASIC_INFORMATION:name;
+const unique T.ChangeTime__FILE_BASIC_INFORMATION:name;
+const unique T.FileAttributes__FILE_BASIC_INFORMATION:name;
+const unique T.CreationTime__FILE_NETWORK_OPEN_INFORMATION:name;
+const unique T.LastAccessTime__FILE_NETWORK_OPEN_INFORMATION:name;
+const unique T.LastWriteTime__FILE_NETWORK_OPEN_INFORMATION:name;
+const unique T.ChangeTime__FILE_NETWORK_OPEN_INFORMATION:name;
+const unique T.AllocationSize__FILE_NETWORK_OPEN_INFORMATION:name;
+const unique T.EndOfFile__FILE_NETWORK_OPEN_INFORMATION:name;
+const unique T.FileAttributes__FILE_NETWORK_OPEN_INFORMATION:name;
+const unique T.Type__FILE_OBJECT:name;
+const unique T.Size__FILE_OBJECT:name;
+const unique T.DeviceObject__FILE_OBJECT:name;
+const unique T.Vpb__FILE_OBJECT:name;
+const unique T.FsContext__FILE_OBJECT:name;
+const unique T.FsContext2__FILE_OBJECT:name;
+const unique T.SectionObjectPointer__FILE_OBJECT:name;
+const unique T.PrivateCacheMap__FILE_OBJECT:name;
+const unique T.FinalStatus__FILE_OBJECT:name;
+const unique T.RelatedFileObject__FILE_OBJECT:name;
+const unique T.LockOperation__FILE_OBJECT:name;
+const unique T.DeletePending__FILE_OBJECT:name;
+const unique T.ReadAccess__FILE_OBJECT:name;
+const unique T.WriteAccess__FILE_OBJECT:name;
+const unique T.DeleteAccess__FILE_OBJECT:name;
+const unique T.SharedRead__FILE_OBJECT:name;
+const unique T.SharedWrite__FILE_OBJECT:name;
+const unique T.SharedDelete__FILE_OBJECT:name;
+const unique T.Flags__FILE_OBJECT:name;
+const unique T.FileName__FILE_OBJECT:name;
+const unique T.CurrentByteOffset__FILE_OBJECT:name;
+const unique T.Waiters__FILE_OBJECT:name;
+const unique T.Busy__FILE_OBJECT:name;
+const unique T.LastLock__FILE_OBJECT:name;
+const unique T.Lock__FILE_OBJECT:name;
+const unique T.Event__FILE_OBJECT:name;
+const unique T.CompletionContext__FILE_OBJECT:name;
+const unique T.IrpListLock__FILE_OBJECT:name;
+const unique T.IrpList__FILE_OBJECT:name;
+const unique T.FileObjectExtension__FILE_OBJECT:name;
+const unique T.AllocationSize__FILE_STANDARD_INFORMATION:name;
+const unique T.EndOfFile__FILE_STANDARD_INFORMATION:name;
+const unique T.NumberOfLinks__FILE_STANDARD_INFORMATION:name;
+const unique T.DeletePending__FILE_STANDARD_INFORMATION:name;
+const unique T.Directory__FILE_STANDARD_INFORMATION:name;
+const unique T.Debug__GLOBALS:name;
+const unique T.GrandMaster__GLOBALS:name;
+const unique T.AssocClassList__GLOBALS:name;
+const unique T.NumAssocClass__GLOBALS:name;
+const unique T.Opens__GLOBALS:name;
+const unique T.NumberLegacyPorts__GLOBALS:name;
+const unique T.Mutex__GLOBALS:name;
+const unique T.ConnectOneClassToOnePort__GLOBALS:name;
+const unique T.SendOutputToAllPorts__GLOBALS:name;
+const unique T.PortsServiced__GLOBALS:name;
+const unique T.InitExtension__GLOBALS:name;
+const unique T.RegistryPath__GLOBALS:name;
+const unique T.BaseClassName__GLOBALS:name;
+const unique T.BaseClassBuffer__GLOBALS:name;
+const unique T.LegacyDeviceList__GLOBALS:name;
+const unique T.Data1__GUID:name;
+const unique T.Data2__GUID:name;
+const unique T.Data3__GUID:name;
+const unique T.Data4__GUID:name;
+const unique T.PrivilegeCount__INITIAL_PRIVILEGE_SET:name;
+const unique T.Control__INITIAL_PRIVILEGE_SET:name;
+const unique T.Privilege__INITIAL_PRIVILEGE_SET:name;
+const unique T.Size__INTERFACE:name;
+const unique T.Version__INTERFACE:name;
+const unique T.Context__INTERFACE:name;
+const unique T.InterfaceReference__INTERFACE:name;
+const unique T.InterfaceDereference__INTERFACE:name;
+const unique T.Port__IO_COMPLETION_CONTEXT:name;
+const unique T.Key__IO_COMPLETION_CONTEXT:name;
+const unique T.Common__IO_REMOVE_LOCK:name;
+const unique T.Dbg__IO_REMOVE_LOCK:name;
+const unique T.Removed__IO_REMOVE_LOCK_COMMON_BLOCK:name;
+const unique T.Reserved__IO_REMOVE_LOCK_COMMON_BLOCK:name;
+const unique T.IoCount__IO_REMOVE_LOCK_COMMON_BLOCK:name;
+const unique T.RemoveEvent__IO_REMOVE_LOCK_COMMON_BLOCK:name;
+const unique T.Signature__IO_REMOVE_LOCK_DBG_BLOCK:name;
+const unique T.HighWatermark__IO_REMOVE_LOCK_DBG_BLOCK:name;
+const unique T.MaxLockedTicks__IO_REMOVE_LOCK_DBG_BLOCK:name;
+const unique T.AllocateTag__IO_REMOVE_LOCK_DBG_BLOCK:name;
+const unique T.LockList__IO_REMOVE_LOCK_DBG_BLOCK:name;
+const unique T.Spin__IO_REMOVE_LOCK_DBG_BLOCK:name;
+const unique T.LowMemoryCount__IO_REMOVE_LOCK_DBG_BLOCK:name;
+const unique T.Reserved1__IO_REMOVE_LOCK_DBG_BLOCK:name;
+const unique T.Reserved2__IO_REMOVE_LOCK_DBG_BLOCK:name;
+const unique T.Blocks__IO_REMOVE_LOCK_DBG_BLOCK:name;
+const unique T.Option__IO_RESOURCE_DESCRIPTOR:name;
+const unique T.Type__IO_RESOURCE_DESCRIPTOR:name;
+const unique T.ShareDisposition__IO_RESOURCE_DESCRIPTOR:name;
+const unique T.Spare1__IO_RESOURCE_DESCRIPTOR:name;
+const unique T.Flags__IO_RESOURCE_DESCRIPTOR:name;
+const unique T.Spare2__IO_RESOURCE_DESCRIPTOR:name;
+const unique T.u__IO_RESOURCE_DESCRIPTOR:name;
+const unique T.Version__IO_RESOURCE_LIST:name;
+const unique T.Revision__IO_RESOURCE_LIST:name;
+const unique T.Count__IO_RESOURCE_LIST:name;
+const unique T.Descriptors__IO_RESOURCE_LIST:name;
+const unique T.ListSize__IO_RESOURCE_REQUIREMENTS_LIST:name;
+const unique T.InterfaceType__IO_RESOURCE_REQUIREMENTS_LIST:name;
+const unique T.BusNumber__IO_RESOURCE_REQUIREMENTS_LIST:name;
+const unique T.SlotNumber__IO_RESOURCE_REQUIREMENTS_LIST:name;
+const unique T.Reserved__IO_RESOURCE_REQUIREMENTS_LIST:name;
+const unique T.AlternativeLists__IO_RESOURCE_REQUIREMENTS_LIST:name;
+const unique T.List__IO_RESOURCE_REQUIREMENTS_LIST:name;
+const unique T.SecurityQos__IO_SECURITY_CONTEXT:name;
+const unique T.AccessState__IO_SECURITY_CONTEXT:name;
+const unique T.DesiredAccess__IO_SECURITY_CONTEXT:name;
+const unique T.FullCreateOptions__IO_SECURITY_CONTEXT:name;
+const unique T.MajorFunction__IO_STACK_LOCATION:name;
+const unique T.MinorFunction__IO_STACK_LOCATION:name;
+const unique T.Flags__IO_STACK_LOCATION:name;
+const unique T.Control__IO_STACK_LOCATION:name;
+const unique T.Parameters__IO_STACK_LOCATION:name;
+const unique T.DeviceObject__IO_STACK_LOCATION:name;
+const unique T.FileObject__IO_STACK_LOCATION:name;
+const unique T.CompletionRoutine__IO_STACK_LOCATION:name;
+const unique T.Context__IO_STACK_LOCATION:name;
+const unique T.__unnamed_4_d99b6e2b__IO_STATUS_BLOCK:name;
+const unique T.Information__IO_STATUS_BLOCK:name;
+const unique T.Type__IRP:name;
+const unique T.Size__IRP:name;
+const unique T.MdlAddress__IRP:name;
+const unique T.Flags__IRP:name;
+const unique T.AssociatedIrp__IRP:name;
+const unique T.ThreadListEntry__IRP:name;
+const unique T.IoStatus__IRP:name;
+const unique T.RequestorMode__IRP:name;
+const unique T.PendingReturned__IRP:name;
+const unique T.StackCount__IRP:name;
+const unique T.CurrentLocation__IRP:name;
+const unique T.Cancel__IRP:name;
+const unique T.CancelIrql__IRP:name;
+const unique T.ApcEnvironment__IRP:name;
+const unique T.AllocationFlags__IRP:name;
+const unique T.UserIosb__IRP:name;
+const unique T.UserEvent__IRP:name;
+const unique T.Overlay__IRP:name;
+const unique T.CancelRoutine__IRP:name;
+const unique T.UserBuffer__IRP:name;
+const unique T.Tail__IRP:name;
+const unique T.Type__KAPC:name;
+const unique T.SpareByte0__KAPC:name;
+const unique T.Size__KAPC:name;
+const unique T.SpareByte1__KAPC:name;
+const unique T.SpareLong0__KAPC:name;
+const unique T.Thread__KAPC:name;
+const unique T.ApcListEntry__KAPC:name;
+const unique T.KernelRoutine__KAPC:name;
+const unique T.RundownRoutine__KAPC:name;
+const unique T.NormalRoutine__KAPC:name;
+const unique T.NormalContext__KAPC:name;
+const unique T.SystemArgument1__KAPC:name;
+const unique T.SystemArgument2__KAPC:name;
+const unique T.ApcStateIndex__KAPC:name;
+const unique T.ApcMode__KAPC:name;
+const unique T.Inserted__KAPC:name;
+const unique T.Type__KDEVICE_QUEUE:name;
+const unique T.Size__KDEVICE_QUEUE:name;
+const unique T.DeviceListHead__KDEVICE_QUEUE:name;
+const unique T.Lock__KDEVICE_QUEUE:name;
+const unique T.Busy__KDEVICE_QUEUE:name;
+const unique T.DeviceListEntry__KDEVICE_QUEUE_ENTRY:name;
+const unique T.SortKey__KDEVICE_QUEUE_ENTRY:name;
+const unique T.Inserted__KDEVICE_QUEUE_ENTRY:name;
+const unique T.Type__KDPC:name;
+const unique T.Importance__KDPC:name;
+const unique T.Number__KDPC:name;
+const unique T.DpcListEntry__KDPC:name;
+const unique T.DeferredRoutine__KDPC:name;
+const unique T.DeferredContext__KDPC:name;
+const unique T.SystemArgument1__KDPC:name;
+const unique T.SystemArgument2__KDPC:name;
+const unique T.DpcData__KDPC:name;
+const unique T.Header__KEVENT:name;
+const unique T.KeyboardIdentifier__KEYBOARD_ATTRIBUTES:name;
+const unique T.KeyboardMode__KEYBOARD_ATTRIBUTES:name;
+const unique T.NumberOfFunctionKeys__KEYBOARD_ATTRIBUTES:name;
+const unique T.NumberOfIndicators__KEYBOARD_ATTRIBUTES:name;
+const unique T.NumberOfKeysTotal__KEYBOARD_ATTRIBUTES:name;
+const unique T.InputDataQueueLength__KEYBOARD_ATTRIBUTES:name;
+const unique T.KeyRepeatMinimum__KEYBOARD_ATTRIBUTES:name;
+const unique T.KeyRepeatMaximum__KEYBOARD_ATTRIBUTES:name;
+const unique T.Type__KEYBOARD_ID:name;
+const unique T.Subtype__KEYBOARD_ID:name;
+const unique T.UnitId__KEYBOARD_INDICATOR_PARAMETERS:name;
+const unique T.LedFlags__KEYBOARD_INDICATOR_PARAMETERS:name;
+const unique T.UnitId__KEYBOARD_INPUT_DATA:name;
+const unique T.MakeCode__KEYBOARD_INPUT_DATA:name;
+const unique T.Flags__KEYBOARD_INPUT_DATA:name;
+const unique T.Reserved__KEYBOARD_INPUT_DATA:name;
+const unique T.ExtraInformation__KEYBOARD_INPUT_DATA:name;
+const unique T.UnitId__KEYBOARD_TYPEMATIC_PARAMETERS:name;
+const unique T.Rate__KEYBOARD_TYPEMATIC_PARAMETERS:name;
+const unique T.Delay__KEYBOARD_TYPEMATIC_PARAMETERS:name;
+const unique T.Header__KSEMAPHORE:name;
+const unique T.Limit__KSEMAPHORE:name;
+const unique T.__unnamed_8_58ee4a31__LARGE_INTEGER:name;
+const unique T.u__LARGE_INTEGER:name;
+const unique T.QuadPart__LARGE_INTEGER:name;
+const unique T.Flink__LIST_ENTRY:name;
+const unique T.Blink__LIST_ENTRY:name;
+const unique T.LowPart__LUID:name;
+const unique T.HighPart__LUID:name;
+const unique T.Luid__LUID_AND_ATTRIBUTES:name;
+const unique T.Attributes__LUID_AND_ATTRIBUTES:name;
+const unique T.Next__MDL:name;
+const unique T.Size__MDL:name;
+const unique T.MdlFlags__MDL:name;
+const unique T.Process__MDL:name;
+const unique T.MappedSystemVa__MDL:name;
+const unique T.StartVa__MDL:name;
+const unique T.ByteCount__MDL:name;
+const unique T.ByteOffset__MDL:name;
+const unique T.OwnerThread__OWNER_ENTRY:name;
+const unique T.__unnamed_4_6f9ac8e1__OWNER_ENTRY:name;
+const unique T.File__PORT:name;
+const unique T.Port__PORT:name;
+const unique T.Enabled__PORT:name;
+const unique T.Reserved__PORT:name;
+const unique T.Free__PORT:name;
+const unique T.SequenceD1__POWER_SEQUENCE:name;
+const unique T.SequenceD2__POWER_SEQUENCE:name;
+const unique T.SequenceD3__POWER_SEQUENCE:name;
+const unique T.SystemState__POWER_STATE:name;
+const unique T.DeviceState__POWER_STATE:name;
+const unique T.PrivilegeCount__PRIVILEGE_SET:name;
+const unique T.Control__PRIVILEGE_SET:name;
+const unique T.Privilege__PRIVILEGE_SET:name;
+const unique T.DataSectionObject__SECTION_OBJECT_POINTERS:name;
+const unique T.SharedCacheMap__SECTION_OBJECT_POINTERS:name;
+const unique T.ImageSectionObject__SECTION_OBJECT_POINTERS:name;
+const unique T.Length__SECURITY_QUALITY_OF_SERVICE:name;
+const unique T.ImpersonationLevel__SECURITY_QUALITY_OF_SERVICE:name;
+const unique T.ContextTrackingMode__SECURITY_QUALITY_OF_SERVICE:name;
+const unique T.EffectiveOnly__SECURITY_QUALITY_OF_SERVICE:name;
+const unique T.ClientToken__SECURITY_SUBJECT_CONTEXT:name;
+const unique T.ImpersonationLevel__SECURITY_SUBJECT_CONTEXT:name;
+const unique T.PrimaryToken__SECURITY_SUBJECT_CONTEXT:name;
+const unique T.ProcessAuditId__SECURITY_SUBJECT_CONTEXT:name;
+const unique T.__unnamed_4_3a2fdc5e__SYSTEM_POWER_STATE_CONTEXT:name;
+const unique T.Length__UNICODE_STRING:name;
+const unique T.MaximumLength__UNICODE_STRING:name;
+const unique T.Buffer__UNICODE_STRING:name;
+const unique T.Type__VPB:name;
+const unique T.Size__VPB:name;
+const unique T.Flags__VPB:name;
+const unique T.VolumeLabelLength__VPB:name;
+const unique T.DeviceObject__VPB:name;
+const unique T.RealDevice__VPB:name;
+const unique T.SerialNumber__VPB:name;
+const unique T.ReferenceCount__VPB:name;
+const unique T.VolumeLabel__VPB:name;
+const unique T.WaitQueueEntry__WAIT_CONTEXT_BLOCK:name;
+const unique T.DeviceRoutine__WAIT_CONTEXT_BLOCK:name;
+const unique T.DeviceContext__WAIT_CONTEXT_BLOCK:name;
+const unique T.NumberOfMapRegisters__WAIT_CONTEXT_BLOCK:name;
+const unique T.DeviceObject__WAIT_CONTEXT_BLOCK:name;
+const unique T.CurrentIrp__WAIT_CONTEXT_BLOCK:name;
+const unique T.BufferChainingDpc__WAIT_CONTEXT_BLOCK:name;
+const unique T.GuidCount__WMILIB_CONTEXT:name;
+const unique T.GuidList__WMILIB_CONTEXT:name;
+const unique T.QueryWmiRegInfo__WMILIB_CONTEXT:name;
+const unique T.QueryWmiDataBlock__WMILIB_CONTEXT:name;
+const unique T.SetWmiDataBlock__WMILIB_CONTEXT:name;
+const unique T.SetWmiDataItem__WMILIB_CONTEXT:name;
+const unique T.ExecuteWmiMethod__WMILIB_CONTEXT:name;
+const unique T.WmiFunctionControl__WMILIB_CONTEXT:name;
+const unique T.Reserved___unnamed_12_0d6a30de:name;
+const unique T.MessageCount___unnamed_12_0d6a30de:name;
+const unique T.Vector___unnamed_12_0d6a30de:name;
+const unique T.Affinity___unnamed_12_0d6a30de:name;
+const unique T.Start___unnamed_12_17f5c211:name;
+const unique T.Length48___unnamed_12_17f5c211:name;
+const unique T.Start___unnamed_12_1fb42e39:name;
+const unique T.Length___unnamed_12_1fb42e39:name;
+const unique T.Reserved___unnamed_12_1fb42e39:name;
+const unique T.Start___unnamed_12_2a1563c6:name;
+const unique T.Length___unnamed_12_2a1563c6:name;
+const unique T.DataSize___unnamed_12_31347272:name;
+const unique T.Reserved1___unnamed_12_31347272:name;
+const unique T.Reserved2___unnamed_12_31347272:name;
+const unique T.Raw___unnamed_12_429aadc0:name;
+const unique T.Translated___unnamed_12_429aadc0:name;
+const unique T.Start___unnamed_12_4719de1a:name;
+const unique T.Length___unnamed_12_4719de1a:name;
+const unique T.Data___unnamed_12_4be56faa:name;
+const unique T.Data___unnamed_12_5ce25b92:name;
+const unique T.Generic___unnamed_12_7a698b72:name;
+const unique T.Port___unnamed_12_7a698b72:name;
+const unique T.Interrupt___unnamed_12_7a698b72:name;
+const unique T.MessageInterrupt___unnamed_12_7a698b72:name;
+const unique T.Memory___unnamed_12_7a698b72:name;
+const unique T.Dma___unnamed_12_7a698b72:name;
+const unique T.DevicePrivate___unnamed_12_7a698b72:name;
+const unique T.BusNumber___unnamed_12_7a698b72:name;
+const unique T.DeviceSpecificData___unnamed_12_7a698b72:name;
+const unique T.Memory40___unnamed_12_7a698b72:name;
+const unique T.Memory48___unnamed_12_7a698b72:name;
+const unique T.Memory64___unnamed_12_7a698b72:name;
+const unique T.Start___unnamed_12_87c0de8d:name;
+const unique T.Length64___unnamed_12_87c0de8d:name;
+const unique T.Start___unnamed_12_98bfc55a:name;
+const unique T.Length40___unnamed_12_98bfc55a:name;
+const unique T.Priority___unnamed_12_ab1bd9d7:name;
+const unique T.Reserved1___unnamed_12_ab1bd9d7:name;
+const unique T.Reserved2___unnamed_12_ab1bd9d7:name;
+const unique T.Level___unnamed_12_b0429be9:name;
+const unique T.Vector___unnamed_12_b0429be9:name;
+const unique T.Affinity___unnamed_12_b0429be9:name;
+const unique T.ListEntry___unnamed_12_b43e8de8:name;
+const unique T.__unnamed_4_f19b65c1___unnamed_12_b43e8de8:name;
+const unique T.Level___unnamed_12_bfdb39ee:name;
+const unique T.Vector___unnamed_12_bfdb39ee:name;
+const unique T.Affinity___unnamed_12_bfdb39ee:name;
+const unique T.Start___unnamed_12_cd42b3c3:name;
+const unique T.Length___unnamed_12_cd42b3c3:name;
+const unique T.__unnamed_12_429aadc0___unnamed_12_e668effc:name;
+const unique T.Channel___unnamed_12_e80d029e:name;
+const unique T.Port___unnamed_12_e80d029e:name;
+const unique T.Reserved1___unnamed_12_e80d029e:name;
+const unique T.Length___unnamed_16_07c0bcc5:name;
+const unique T.MinBusNumber___unnamed_16_07c0bcc5:name;
+const unique T.MaxBusNumber___unnamed_16_07c0bcc5:name;
+const unique T.Reserved___unnamed_16_07c0bcc5:name;
+const unique T.InterfaceType___unnamed_16_29cb9f2f:name;
+const unique T.Size___unnamed_16_29cb9f2f:name;
+const unique T.Version___unnamed_16_29cb9f2f:name;
+const unique T.Interface___unnamed_16_29cb9f2f:name;
+const unique T.InterfaceSpecificData___unnamed_16_29cb9f2f:name;
+const unique T.SecurityContext___unnamed_16_30f11dbf:name;
+const unique T.Options___unnamed_16_30f11dbf:name;
+const unique T.FileAttributes___unnamed_16_30f11dbf:name;
+const unique T.ShareAccess___unnamed_16_30f11dbf:name;
+const unique T.EaLength___unnamed_16_30f11dbf:name;
+const unique T.DriverContext___unnamed_16_35034f68:name;
+const unique T.Length___unnamed_16_487a9498:name;
+const unique T.FileName___unnamed_16_487a9498:name;
+const unique T.FileInformationClass___unnamed_16_487a9498:name;
+const unique T.FileIndex___unnamed_16_487a9498:name;
+const unique T.OutputBufferLength___unnamed_16_5f6a8844:name;
+const unique T.InputBufferLength___unnamed_16_5f6a8844:name;
+const unique T.FsControlCode___unnamed_16_5f6a8844:name;
+const unique T.Type3InputBuffer___unnamed_16_5f6a8844:name;
+const unique T.Length___unnamed_16_7177b9f3:name;
+const unique T.FileInformationClass___unnamed_16_7177b9f3:name;
+const unique T.FileObject___unnamed_16_7177b9f3:name;
+const unique T.__unnamed_4_43913aa5___unnamed_16_7177b9f3:name;
+const unique T.Length___unnamed_16_88e91ef6:name;
+const unique T.Key___unnamed_16_88e91ef6:name;
+const unique T.ByteOffset___unnamed_16_88e91ef6:name;
+const unique T.Length___unnamed_16_8c506c98:name;
+const unique T.Key___unnamed_16_8c506c98:name;
+const unique T.ByteOffset___unnamed_16_8c506c98:name;
+const unique T.WhichSpace___unnamed_16_9ac2e5f8:name;
+const unique T.Buffer___unnamed_16_9ac2e5f8:name;
+const unique T.Offset___unnamed_16_9ac2e5f8:name;
+const unique T.Length___unnamed_16_9ac2e5f8:name;
+const unique T.Create___unnamed_16_b93842ad:name;
+const unique T.Read___unnamed_16_b93842ad:name;
+const unique T.Write___unnamed_16_b93842ad:name;
+const unique T.QueryDirectory___unnamed_16_b93842ad:name;
+const unique T.NotifyDirectory___unnamed_16_b93842ad:name;
+const unique T.QueryFile___unnamed_16_b93842ad:name;
+const unique T.SetFile___unnamed_16_b93842ad:name;
+const unique T.QueryEa___unnamed_16_b93842ad:name;
+const unique T.SetEa___unnamed_16_b93842ad:name;
+const unique T.QueryVolume___unnamed_16_b93842ad:name;
+const unique T.SetVolume___unnamed_16_b93842ad:name;
+const unique T.FileSystemControl___unnamed_16_b93842ad:name;
+const unique T.LockControl___unnamed_16_b93842ad:name;
+const unique T.DeviceIoControl___unnamed_16_b93842ad:name;
+const unique T.QuerySecurity___unnamed_16_b93842ad:name;
+const unique T.SetSecurity___unnamed_16_b93842ad:name;
+const unique T.MountVolume___unnamed_16_b93842ad:name;
+const unique T.VerifyVolume___unnamed_16_b93842ad:name;
+const unique T.Scsi___unnamed_16_b93842ad:name;
+const unique T.QueryQuota___unnamed_16_b93842ad:name;
+const unique T.SetQuota___unnamed_16_b93842ad:name;
+const unique T.QueryDeviceRelations___unnamed_16_b93842ad:name;
+const unique T.QueryInterface___unnamed_16_b93842ad:name;
+const unique T.DeviceCapabilities___unnamed_16_b93842ad:name;
+const unique T.FilterResourceRequirements___unnamed_16_b93842ad:name;
+const unique T.ReadWriteConfig___unnamed_16_b93842ad:name;
+const unique T.SetLock___unnamed_16_b93842ad:name;
+const unique T.QueryId___unnamed_16_b93842ad:name;
+const unique T.QueryDeviceText___unnamed_16_b93842ad:name;
+const unique T.UsageNotification___unnamed_16_b93842ad:name;
+const unique T.WaitWake___unnamed_16_b93842ad:name;
+const unique T.PowerSequence___unnamed_16_b93842ad:name;
+const unique T.Power___unnamed_16_b93842ad:name;
+const unique T.StartDevice___unnamed_16_b93842ad:name;
+const unique T.WMI___unnamed_16_b93842ad:name;
+const unique T.Others___unnamed_16_b93842ad:name;
+const unique T.Length___unnamed_16_b9c62eab:name;
+const unique T.Key___unnamed_16_b9c62eab:name;
+const unique T.ByteOffset___unnamed_16_b9c62eab:name;
+const unique T.__unnamed_4_7d9d0c7e___unnamed_16_bb584060:name;
+const unique T.Type___unnamed_16_bb584060:name;
+const unique T.State___unnamed_16_bb584060:name;
+const unique T.ShutdownType___unnamed_16_bb584060:name;
+const unique T.OutputBufferLength___unnamed_16_dba55c7c:name;
+const unique T.InputBufferLength___unnamed_16_dba55c7c:name;
+const unique T.IoControlCode___unnamed_16_dba55c7c:name;
+const unique T.Type3InputBuffer___unnamed_16_dba55c7c:name;
+const unique T.DeviceQueueEntry___unnamed_16_e70c268b:name;
+const unique T.__unnamed_16_35034f68___unnamed_16_e70c268b:name;
+const unique T.Argument1___unnamed_16_e734d694:name;
+const unique T.Argument2___unnamed_16_e734d694:name;
+const unique T.Argument3___unnamed_16_e734d694:name;
+const unique T.Argument4___unnamed_16_e734d694:name;
+const unique T.ProviderId___unnamed_16_eac6dbea:name;
+const unique T.DataPath___unnamed_16_eac6dbea:name;
+const unique T.BufferSize___unnamed_16_eac6dbea:name;
+const unique T.Buffer___unnamed_16_eac6dbea:name;
+const unique T.Length___unnamed_16_f6cae4c2:name;
+const unique T.EaList___unnamed_16_f6cae4c2:name;
+const unique T.EaListLength___unnamed_16_f6cae4c2:name;
+const unique T.EaIndex___unnamed_16_f6cae4c2:name;
+const unique T.Length___unnamed_16_fe36e4f4:name;
+const unique T.StartSid___unnamed_16_fe36e4f4:name;
+const unique T.SidList___unnamed_16_fe36e4f4:name;
+const unique T.SidListLength___unnamed_16_fe36e4f4:name;
+const unique T.Abandoned___unnamed_1_29794256:name;
+const unique T.Absolute___unnamed_1_29794256:name;
+const unique T.NpxIrql___unnamed_1_29794256:name;
+const unique T.Signalling___unnamed_1_29794256:name;
+const unique T.Inserted___unnamed_1_2dc63b48:name;
+const unique T.DebugActive___unnamed_1_2dc63b48:name;
+const unique T.DpcActive___unnamed_1_2dc63b48:name;
+const unique T.Size___unnamed_1_2ef8da39:name;
+const unique T.Hand___unnamed_1_2ef8da39:name;
+const unique T.Lock___unnamed_1_faa7dc71:name;
+const unique T.MinimumVector___unnamed_20_f4d2e6d8:name;
+const unique T.MaximumVector___unnamed_20_f4d2e6d8:name;
+const unique T.AffinityPolicy___unnamed_20_f4d2e6d8:name;
+const unique T.PriorityPolicy___unnamed_20_f4d2e6d8:name;
+const unique T.TargetedProcessors___unnamed_20_f4d2e6d8:name;
+const unique T.Length___unnamed_24_41cbc8c0:name;
+const unique T.Alignment___unnamed_24_41cbc8c0:name;
+const unique T.MinimumAddress___unnamed_24_41cbc8c0:name;
+const unique T.MaximumAddress___unnamed_24_41cbc8c0:name;
+const unique T.Length48___unnamed_24_5419c914:name;
+const unique T.Alignment48___unnamed_24_5419c914:name;
+const unique T.MinimumAddress___unnamed_24_5419c914:name;
+const unique T.MaximumAddress___unnamed_24_5419c914:name;
+const unique T.Length___unnamed_24_67a5ff10:name;
+const unique T.Alignment___unnamed_24_67a5ff10:name;
+const unique T.MinimumAddress___unnamed_24_67a5ff10:name;
+const unique T.MaximumAddress___unnamed_24_67a5ff10:name;
+const unique T.Port___unnamed_24_72c3976e:name;
+const unique T.Memory___unnamed_24_72c3976e:name;
+const unique T.Interrupt___unnamed_24_72c3976e:name;
+const unique T.Dma___unnamed_24_72c3976e:name;
+const unique T.Generic___unnamed_24_72c3976e:name;
+const unique T.DevicePrivate___unnamed_24_72c3976e:name;
+const unique T.BusNumber___unnamed_24_72c3976e:name;
+const unique T.ConfigData___unnamed_24_72c3976e:name;
+const unique T.Memory40___unnamed_24_72c3976e:name;
+const unique T.Memory48___unnamed_24_72c3976e:name;
+const unique T.Memory64___unnamed_24_72c3976e:name;
+const unique T.Length64___unnamed_24_a26050bb:name;
+const unique T.Alignment64___unnamed_24_a26050bb:name;
+const unique T.MinimumAddress___unnamed_24_a26050bb:name;
+const unique T.MaximumAddress___unnamed_24_a26050bb:name;
+const unique T.Length___unnamed_24_b8f476db:name;
+const unique T.Alignment___unnamed_24_b8f476db:name;
+const unique T.MinimumAddress___unnamed_24_b8f476db:name;
+const unique T.MaximumAddress___unnamed_24_b8f476db:name;
+const unique T.Length40___unnamed_24_d09044b4:name;
+const unique T.Alignment40___unnamed_24_d09044b4:name;
+const unique T.MinimumAddress___unnamed_24_d09044b4:name;
+const unique T.MaximumAddress___unnamed_24_d09044b4:name;
+const unique T.ReplaceIfExists___unnamed_2_46cc4597:name;
+const unique T.AdvanceOnly___unnamed_2_46cc4597:name;
+const unique T.__unnamed_16_e70c268b___unnamed_40_7218f704:name;
+const unique T.Thread___unnamed_40_7218f704:name;
+const unique T.AuxiliaryBuffer___unnamed_40_7218f704:name;
+const unique T.__unnamed_12_b43e8de8___unnamed_40_7218f704:name;
+const unique T.OriginalFileObject___unnamed_40_7218f704:name;
+const unique T.ListEntry___unnamed_40_c55c9377:name;
+const unique T.Wcb___unnamed_40_c55c9377:name;
+const unique T.InitialPrivilegeSet___unnamed_44_5584090d:name;
+const unique T.PrivilegeSet___unnamed_44_5584090d:name;
+const unique T.Overlay___unnamed_48_cf99b13f:name;
+const unique T.Apc___unnamed_48_cf99b13f:name;
+const unique T.CompletionKey___unnamed_48_cf99b13f:name;
+const unique T.PowerState___unnamed_4_069846fb:name;
+const unique T.IdType___unnamed_4_224c32f4:name;
+const unique T.Capabilities___unnamed_4_2de698da:name;
+const unique T.__unnamed_4_c3479730___unnamed_4_3a2fdc5e:name;
+const unique T.ContextAsUlong___unnamed_4_3a2fdc5e:name;
+const unique T.Length___unnamed_4_3a4c1a13:name;
+const unique T.__unnamed_2_46cc4597___unnamed_4_43913aa5:name;
+const unique T.ClusterCount___unnamed_4_43913aa5:name;
+const unique T.DeleteHandle___unnamed_4_43913aa5:name;
+const unique T.UserApcRoutine___unnamed_4_4e8dd2ba:name;
+const unique T.IssuingProcess___unnamed_4_4e8dd2ba:name;
+const unique T.Srb___unnamed_4_52603077:name;
+const unique T.Address___unnamed_4_52c594f7:name;
+const unique T.CreatorBackTraceIndex___unnamed_4_52c594f7:name;
+const unique T.Type___unnamed_4_5ca00198:name;
+const unique T.__unnamed_1_29794256___unnamed_4_5ca00198:name;
+const unique T.__unnamed_1_2ef8da39___unnamed_4_5ca00198:name;
+const unique T.__unnamed_1_2dc63b48___unnamed_4_5ca00198:name;
+const unique T.MasterIrp___unnamed_4_6ac6463c:name;
+const unique T.IrpCount___unnamed_4_6ac6463c:name;
+const unique T.SystemBuffer___unnamed_4_6ac6463c:name;
+const unique T.OwnerCount___unnamed_4_6f9ac8e1:name;
+const unique T.TableSize___unnamed_4_6f9ac8e1:name;
+const unique T.PowerSequence___unnamed_4_7a02167b:name;
+const unique T.SystemContext___unnamed_4_7d9d0c7e:name;
+const unique T.SystemPowerStateContext___unnamed_4_7d9d0c7e:name;
+const unique T.IoResourceRequirementList___unnamed_4_82f7a864:name;
+const unique T.Length___unnamed_4_9aec220b:name;
+const unique T.__unnamed_4_5ca00198___unnamed_4_a97c65a1:name;
+const unique T.Lock___unnamed_4_a97c65a1:name;
+const unique T.Reserved1___unnamed_4_c3479730:name;
+const unique T.TargetSystemState___unnamed_4_c3479730:name;
+const unique T.EffectiveSystemState___unnamed_4_c3479730:name;
+const unique T.CurrentSystemState___unnamed_4_c3479730:name;
+const unique T.IgnoreHibernationPath___unnamed_4_c3479730:name;
+const unique T.PseudoTransition___unnamed_4_c3479730:name;
+const unique T.Reserved2___unnamed_4_c3479730:name;
+const unique T.Status___unnamed_4_d99b6e2b:name;
+const unique T.Pointer___unnamed_4_d99b6e2b:name;
+const unique T.CurrentStackLocation___unnamed_4_f19b65c1:name;
+const unique T.PacketType___unnamed_4_f19b65c1:name;
+const unique T.Type___unnamed_4_fa10fc16:name;
+const unique T.SecurityInformation___unnamed_8_01efa60d:name;
+const unique T.Length___unnamed_8_01efa60d:name;
+const unique T.MinimumChannel___unnamed_8_08d4cef8:name;
+const unique T.MaximumChannel___unnamed_8_08d4cef8:name;
+const unique T.__unnamed_4_4e8dd2ba___unnamed_8_0a898c0c:name;
+const unique T.UserApcContext___unnamed_8_0a898c0c:name;
+const unique T.SecurityInformation___unnamed_8_1330f93a:name;
+const unique T.SecurityDescriptor___unnamed_8_1330f93a:name;
+const unique T.AsynchronousParameters___unnamed_8_181d0de9:name;
+const unique T.AllocationSize___unnamed_8_181d0de9:name;
+const unique T.Vpb___unnamed_8_4812764d:name;
+const unique T.DeviceObject___unnamed_8_4812764d:name;
+const unique T.Length___unnamed_8_559a91e6:name;
+const unique T.FsInformationClass___unnamed_8_559a91e6:name;
+const unique T.Length___unnamed_8_5845b309:name;
+const unique T.FileInformationClass___unnamed_8_5845b309:name;
+const unique T.LowPart___unnamed_8_58ee4a31:name;
+const unique T.HighPart___unnamed_8_58ee4a31:name;
+const unique T.AllocatedResources___unnamed_8_61acf4ce:name;
+const unique T.AllocatedResourcesTranslated___unnamed_8_61acf4ce:name;
+const unique T.DeviceTextType___unnamed_8_6acfee04:name;
+const unique T.LocaleId___unnamed_8_6acfee04:name;
+const unique T.Length___unnamed_8_7f26a9dd:name;
+const unique T.CompletionFilter___unnamed_8_7f26a9dd:name;
+const unique T.Vpb___unnamed_8_87add0bd:name;
+const unique T.DeviceObject___unnamed_8_87add0bd:name;
+const unique T.InPath___unnamed_8_b2773e4c:name;
+const unique T.Reserved___unnamed_8_b2773e4c:name;
+const unique T.Type___unnamed_8_b2773e4c:name;
+const unique T.Length___unnamed_8_de890d4e:name;
+const unique T.FsInformationClass___unnamed_8_de890d4e:name;
+const unique T.LowPart___unnamed_8_ef9ba0d3:name;
+const unique T.HighPart___unnamed_8_ef9ba0d3:name;
+
+// Type declarations
+
+const unique T.A11CHAR:name;
+const unique T.A19CHAR:name;
+const unique T.A1_CM_FULL_RESOURCE_DESCRIPTOR:name;
+const unique T.A1_CM_PARTIAL_RESOURCE_DESCRIPTOR:name;
+const unique T.A1_IO_RESOURCE_DESCRIPTOR:name;
+const unique T.A1_IO_RESOURCE_LIST:name;
+const unique T.A1_LUID_AND_ATTRIBUTES:name;
+const unique T.A256UINT2:name;
+const unique T.A28PFDRIVER_DISPATCH:name;
+const unique T.A2UCHAR:name;
+const unique T.A32UINT2:name;
+const unique T.A36CHAR:name;
+const unique T.A37CHAR:name;
+const unique T.A39CHAR:name;
+const unique T.A3UCHAR:name;
+const unique T.A3UINT4:name;
+const unique T.A3_LUID_AND_ATTRIBUTES:name;
+const unique T.A43CHAR:name;
+const unique T.A4PVOID:name;
+const unique T.A4UINT4:name;
+const unique T.A5_DEVICE_POWER_STATE:name;
+const unique T.A74CHAR:name;
+const unique T.A7_DEVICE_POWER_STATE:name;
+const unique T.A8UCHAR:name;
+const unique T.BUS_QUERY_ID_TYPE:name;
+const unique T.CHAR:name;
+const unique T.DEVICE_TEXT_TYPE:name;
+const unique T.F0:name;
+const unique T.F1:name;
+const unique T.F10:name;
+const unique T.F11:name;
+const unique T.F12:name;
+const unique T.F13:name;
+const unique T.F14:name;
+const unique T.F15:name;
+const unique T.F16:name;
+const unique T.F17:name;
+const unique T.F18:name;
+const unique T.F19:name;
+const unique T.F2:name;
+const unique T.F20:name;
+const unique T.F21:name;
+const unique T.F22:name;
+const unique T.F23:name;
+const unique T.F24:name;
+const unique T.F25:name;
+const unique T.F26:name;
+const unique T.F27:name;
+const unique T.F28:name;
+const unique T.F29:name;
+const unique T.F3:name;
+const unique T.F30:name;
+const unique T.F31:name;
+const unique T.F32:name;
+const unique T.F33:name;
+const unique T.F34:name;
+const unique T.F35:name;
+const unique T.F36:name;
+const unique T.F37:name;
+const unique T.F38:name;
+const unique T.F4:name;
+const unique T.F5:name;
+const unique T.F6:name;
+const unique T.F7:name;
+const unique T.F8:name;
+const unique T.F9:name;
+const unique T.FDRIVER_ADD_DEVICE:name;
+const unique T.FDRIVER_CANCEL:name;
+const unique T.FDRIVER_CONTROL:name;
+const unique T.FDRIVER_DISPATCH:name;
+const unique T.FDRIVER_INITIALIZE:name;
+const unique T.FDRIVER_STARTIO:name;
+const unique T.FDRIVER_UNLOAD:name;
+const unique T.FFAST_IO_ACQUIRE_FILE:name;
+const unique T.FFAST_IO_ACQUIRE_FOR_CCFLUSH:name;
+const unique T.FFAST_IO_ACQUIRE_FOR_MOD_WRITE:name;
+const unique T.FFAST_IO_CHECK_IF_POSSIBLE:name;
+const unique T.FFAST_IO_DETACH_DEVICE:name;
+const unique T.FFAST_IO_DEVICE_CONTROL:name;
+const unique T.FFAST_IO_LOCK:name;
+const unique T.FFAST_IO_MDL_READ:name;
+const unique T.FFAST_IO_MDL_READ_COMPLETE:name;
+const unique T.FFAST_IO_MDL_READ_COMPLETE_COMPRESSED:name;
+const unique T.FFAST_IO_MDL_WRITE_COMPLETE:name;
+const unique T.FFAST_IO_MDL_WRITE_COMPLETE_COMPRESSED:name;
+const unique T.FFAST_IO_PREPARE_MDL_WRITE:name;
+const unique T.FFAST_IO_QUERY_BASIC_INFO:name;
+const unique T.FFAST_IO_QUERY_NETWORK_OPEN_INFO:name;
+const unique T.FFAST_IO_QUERY_OPEN:name;
+const unique T.FFAST_IO_QUERY_STANDARD_INFO:name;
+const unique T.FFAST_IO_READ:name;
+const unique T.FFAST_IO_READ_COMPRESSED:name;
+const unique T.FFAST_IO_RELEASE_FILE:name;
+const unique T.FFAST_IO_RELEASE_FOR_CCFLUSH:name;
+const unique T.FFAST_IO_RELEASE_FOR_MOD_WRITE:name;
+const unique T.FFAST_IO_UNLOCK_ALL:name;
+const unique T.FFAST_IO_UNLOCK_ALL_BY_KEY:name;
+const unique T.FFAST_IO_UNLOCK_SINGLE:name;
+const unique T.FFAST_IO_WRITE:name;
+const unique T.FFAST_IO_WRITE_COMPRESSED:name;
+const unique T.FIO_COMPLETION_ROUTINE:name;
+const unique T.FKDEFERRED_ROUTINE:name;
+const unique T.INT2:name;
+const unique T.INT4:name;
+const unique T.INT8:name;
+const unique T.PA11CHAR:name;
+const unique T.PA19CHAR:name;
+const unique T.PA36CHAR:name;
+const unique T.PA37CHAR:name;
+const unique T.PA39CHAR:name;
+const unique T.PA43CHAR:name;
+const unique T.PA74CHAR:name;
+const unique T.PCHAR:name;
+const unique T.PF19:name;
+const unique T.PF21:name;
+const unique T.PF23:name;
+const unique T.PF24:name;
+const unique T.PF25:name;
+const unique T.PF33:name;
+const unique T.PF34:name;
+const unique T.PF35:name;
+const unique T.PF36:name;
+const unique T.PF37:name;
+const unique T.PF38:name;
+const unique T.PFDRIVER_ADD_DEVICE:name;
+const unique T.PFDRIVER_CANCEL:name;
+const unique T.PFDRIVER_CONTROL:name;
+const unique T.PFDRIVER_DISPATCH:name;
+const unique T.PFDRIVER_INITIALIZE:name;
+const unique T.PFDRIVER_STARTIO:name;
+const unique T.PFDRIVER_UNLOAD:name;
+const unique T.PFFAST_IO_ACQUIRE_FILE:name;
+const unique T.PFFAST_IO_ACQUIRE_FOR_CCFLUSH:name;
+const unique T.PFFAST_IO_ACQUIRE_FOR_MOD_WRITE:name;
+const unique T.PFFAST_IO_CHECK_IF_POSSIBLE:name;
+const unique T.PFFAST_IO_DETACH_DEVICE:name;
+const unique T.PFFAST_IO_DEVICE_CONTROL:name;
+const unique T.PFFAST_IO_LOCK:name;
+const unique T.PFFAST_IO_MDL_READ:name;
+const unique T.PFFAST_IO_MDL_READ_COMPLETE:name;
+const unique T.PFFAST_IO_MDL_READ_COMPLETE_COMPRESSED:name;
+const unique T.PFFAST_IO_MDL_WRITE_COMPLETE:name;
+const unique T.PFFAST_IO_MDL_WRITE_COMPLETE_COMPRESSED:name;
+const unique T.PFFAST_IO_PREPARE_MDL_WRITE:name;
+const unique T.PFFAST_IO_QUERY_BASIC_INFO:name;
+const unique T.PFFAST_IO_QUERY_NETWORK_OPEN_INFO:name;
+const unique T.PFFAST_IO_QUERY_OPEN:name;
+const unique T.PFFAST_IO_QUERY_STANDARD_INFO:name;
+const unique T.PFFAST_IO_READ:name;
+const unique T.PFFAST_IO_READ_COMPRESSED:name;
+const unique T.PFFAST_IO_RELEASE_FILE:name;
+const unique T.PFFAST_IO_RELEASE_FOR_CCFLUSH:name;
+const unique T.PFFAST_IO_RELEASE_FOR_MOD_WRITE:name;
+const unique T.PFFAST_IO_UNLOCK_ALL:name;
+const unique T.PFFAST_IO_UNLOCK_ALL_BY_KEY:name;
+const unique T.PFFAST_IO_UNLOCK_SINGLE:name;
+const unique T.PFFAST_IO_WRITE:name;
+const unique T.PFFAST_IO_WRITE_COMPRESSED:name;
+const unique T.PFIO_COMPLETION_ROUTINE:name;
+const unique T.PFKDEFERRED_ROUTINE:name;
+const unique T.PINT4:name;
+const unique T.POWER_ACTION:name;
+const unique T.PPCHAR:name;
+const unique T.PPF24:name;
+const unique T.PPP_FILE_OBJECT:name;
+const unique T.PPVOID:name;
+const unique T.PP_DEVICE_EXTENSION:name;
+const unique T.PP_DEVICE_OBJECT:name;
+const unique T.PP_DRIVER_OBJECT:name;
+const unique T.PP_ERESOURCE:name;
+const unique T.PP_FILE_OBJECT:name;
+const unique T.PP_IRP:name;
+const unique T.PP_LIST_ENTRY:name;
+const unique T.PP_MDL:name;
+const unique T.PP_PORT:name;
+const unique T.PP_UNICODE_STRING:name;
+const unique T.PUCHAR:name;
+const unique T.PUINT2:name;
+const unique T.PUINT4:name;
+const unique T.PVOID:name;
+const unique T.PWMIGUIDREGINFO:name;
+const unique T.P_ACCESS_STATE:name;
+const unique T.P_CM_RESOURCE_LIST:name;
+const unique T.P_COMPRESSED_DATA_INFO:name;
+const unique T.P_DEVICE_CAPABILITIES:name;
+const unique T.P_DEVICE_EXTENSION:name;
+const unique T.P_DEVICE_OBJECT:name;
+const unique T.P_DEVOBJ_EXTENSION:name;
+const unique T.P_DRIVER_EXTENSION:name;
+const unique T.P_DRIVER_OBJECT:name;
+const unique T.P_EPROCESS:name;
+const unique T.P_ERESOURCE:name;
+const unique T.P_ETHREAD:name;
+const unique T.P_FAST_IO_DISPATCH:name;
+const unique T.P_FILE_BASIC_INFORMATION:name;
+const unique T.P_FILE_GET_QUOTA_INFORMATION:name;
+const unique T.P_FILE_NETWORK_OPEN_INFORMATION:name;
+const unique T.P_FILE_OBJECT:name;
+const unique T.P_FILE_STANDARD_INFORMATION:name;
+const unique T.P_GLOBALS:name;
+const unique T.P_GUID:name;
+const unique T.P_INTERFACE:name;
+const unique T.P_IO_COMPLETION_CONTEXT:name;
+const unique T.P_IO_REMOVE_LOCK_TRACKING_BLOCK:name;
+const unique T.P_IO_RESOURCE_REQUIREMENTS_LIST:name;
+const unique T.P_IO_SECURITY_CONTEXT:name;
+const unique T.P_IO_STACK_LOCATION:name;
+const unique T.P_IO_STATUS_BLOCK:name;
+const unique T.P_IO_TIMER:name;
+const unique T.P_IRP:name;
+const unique T.P_KAPC:name;
+const unique T.P_KDPC:name;
+const unique T.P_KEVENT:name;
+const unique T.P_KEYBOARD_INPUT_DATA:name;
+const unique T.P_KSEMAPHORE:name;
+const unique T.P_KTHREAD:name;
+const unique T.P_LARGE_INTEGER:name;
+const unique T.P_LIST_ENTRY:name;
+const unique T.P_MDL:name;
+const unique T.P_OWNER_ENTRY:name;
+const unique T.P_PORT:name;
+const unique T.P_POWER_SEQUENCE:name;
+const unique T.P_SCSI_REQUEST_BLOCK:name;
+const unique T.P_SECTION_OBJECT_POINTERS:name;
+const unique T.P_SECURITY_QUALITY_OF_SERVICE:name;
+const unique T.P_UNICODE_STRING:name;
+const unique T.P_VPB:name;
+const unique T.UCHAR:name;
+const unique T.UINT2:name;
+const unique T.UINT4:name;
+const unique T.VOID:name;
+const unique T.WMIENABLEDISABLECONTROL:name;
+const unique T.WMIGUIDREGINFO:name;
+const unique T._ACCESS_STATE:name;
+const unique T._CM_FULL_RESOURCE_DESCRIPTOR:name;
+const unique T._CM_PARTIAL_RESOURCE_DESCRIPTOR:name;
+const unique T._CM_PARTIAL_RESOURCE_LIST:name;
+const unique T._CM_RESOURCE_LIST:name;
+const unique T._COMPRESSED_DATA_INFO:name;
+const unique T._DEVICE_CAPABILITIES:name;
+const unique T._DEVICE_EXTENSION:name;
+const unique T._DEVICE_OBJECT:name;
+const unique T._DEVICE_POWER_STATE:name;
+const unique T._DEVICE_RELATION_TYPE:name;
+const unique T._DEVICE_USAGE_NOTIFICATION_TYPE:name;
+const unique T._DEVOBJ_EXTENSION:name;
+const unique T._DISPATCHER_HEADER:name;
+const unique T._DRIVER_EXTENSION:name;
+const unique T._DRIVER_OBJECT:name;
+const unique T._EPROCESS:name;
+const unique T._ERESOURCE:name;
+const unique T._ETHREAD:name;
+const unique T._FAST_IO_DISPATCH:name;
+const unique T._FAST_MUTEX:name;
+const unique T._FILE_BASIC_INFORMATION:name;
+const unique T._FILE_GET_QUOTA_INFORMATION:name;
+const unique T._FILE_INFORMATION_CLASS:name;
+const unique T._FILE_NETWORK_OPEN_INFORMATION:name;
+const unique T._FILE_OBJECT:name;
+const unique T._FILE_STANDARD_INFORMATION:name;
+const unique T._FSINFOCLASS:name;
+const unique T._GLOBALS:name;
+const unique T._GUID:name;
+const unique T._INITIAL_PRIVILEGE_SET:name;
+const unique T._INTERFACE:name;
+const unique T._INTERFACE_TYPE:name;
+const unique T._IO_ALLOCATION_ACTION:name;
+const unique T._IO_COMPLETION_CONTEXT:name;
+const unique T._IO_REMOVE_LOCK:name;
+const unique T._IO_REMOVE_LOCK_COMMON_BLOCK:name;
+const unique T._IO_REMOVE_LOCK_DBG_BLOCK:name;
+const unique T._IO_REMOVE_LOCK_TRACKING_BLOCK:name;
+const unique T._IO_RESOURCE_DESCRIPTOR:name;
+const unique T._IO_RESOURCE_LIST:name;
+const unique T._IO_RESOURCE_REQUIREMENTS_LIST:name;
+const unique T._IO_SECURITY_CONTEXT:name;
+const unique T._IO_STACK_LOCATION:name;
+const unique T._IO_STATUS_BLOCK:name;
+const unique T._IO_TIMER:name;
+const unique T._IRP:name;
+const unique T._IRQ_DEVICE_POLICY:name;
+const unique T._IRQ_PRIORITY:name;
+const unique T._KAPC:name;
+const unique T._KDEVICE_QUEUE:name;
+const unique T._KDEVICE_QUEUE_ENTRY:name;
+const unique T._KDPC:name;
+const unique T._KEVENT:name;
+const unique T._KEYBOARD_ATTRIBUTES:name;
+const unique T._KEYBOARD_ID:name;
+const unique T._KEYBOARD_INDICATOR_PARAMETERS:name;
+const unique T._KEYBOARD_INPUT_DATA:name;
+const unique T._KEYBOARD_TYPEMATIC_PARAMETERS:name;
+const unique T._KSEMAPHORE:name;
+const unique T._KTHREAD:name;
+const unique T._LARGE_INTEGER:name;
+const unique T._LIST_ENTRY:name;
+const unique T._LUID:name;
+const unique T._LUID_AND_ATTRIBUTES:name;
+const unique T._MDL:name;
+const unique T._OWNER_ENTRY:name;
+const unique T._PORT:name;
+const unique T._POWER_SEQUENCE:name;
+const unique T._POWER_STATE:name;
+const unique T._POWER_STATE_TYPE:name;
+const unique T._PRIVILEGE_SET:name;
+const unique T._SCSI_REQUEST_BLOCK:name;
+const unique T._SECTION_OBJECT_POINTERS:name;
+const unique T._SECURITY_IMPERSONATION_LEVEL:name;
+const unique T._SECURITY_QUALITY_OF_SERVICE:name;
+const unique T._SECURITY_SUBJECT_CONTEXT:name;
+const unique T._SYSTEM_POWER_STATE:name;
+const unique T._SYSTEM_POWER_STATE_CONTEXT:name;
+const unique T._UNICODE_STRING:name;
+const unique T._VPB:name;
+const unique T._WAIT_CONTEXT_BLOCK:name;
+const unique T._WMILIB_CONTEXT:name;
+const unique T.__unnamed_12_0d6a30de:name;
+const unique T.__unnamed_12_17f5c211:name;
+const unique T.__unnamed_12_1fb42e39:name;
+const unique T.__unnamed_12_2a1563c6:name;
+const unique T.__unnamed_12_31347272:name;
+const unique T.__unnamed_12_429aadc0:name;
+const unique T.__unnamed_12_4719de1a:name;
+const unique T.__unnamed_12_4be56faa:name;
+const unique T.__unnamed_12_5ce25b92:name;
+const unique T.__unnamed_12_7a698b72:name;
+const unique T.__unnamed_12_87c0de8d:name;
+const unique T.__unnamed_12_98bfc55a:name;
+const unique T.__unnamed_12_ab1bd9d7:name;
+const unique T.__unnamed_12_b0429be9:name;
+const unique T.__unnamed_12_b43e8de8:name;
+const unique T.__unnamed_12_bfdb39ee:name;
+const unique T.__unnamed_12_cd42b3c3:name;
+const unique T.__unnamed_12_e668effc:name;
+const unique T.__unnamed_12_e80d029e:name;
+const unique T.__unnamed_16_07c0bcc5:name;
+const unique T.__unnamed_16_29cb9f2f:name;
+const unique T.__unnamed_16_30f11dbf:name;
+const unique T.__unnamed_16_35034f68:name;
+const unique T.__unnamed_16_487a9498:name;
+const unique T.__unnamed_16_5f6a8844:name;
+const unique T.__unnamed_16_7177b9f3:name;
+const unique T.__unnamed_16_88e91ef6:name;
+const unique T.__unnamed_16_8c506c98:name;
+const unique T.__unnamed_16_9ac2e5f8:name;
+const unique T.__unnamed_16_b93842ad:name;
+const unique T.__unnamed_16_b9c62eab:name;
+const unique T.__unnamed_16_bb584060:name;
+const unique T.__unnamed_16_dba55c7c:name;
+const unique T.__unnamed_16_e70c268b:name;
+const unique T.__unnamed_16_e734d694:name;
+const unique T.__unnamed_16_eac6dbea:name;
+const unique T.__unnamed_16_f6cae4c2:name;
+const unique T.__unnamed_16_fe36e4f4:name;
+const unique T.__unnamed_1_29794256:name;
+const unique T.__unnamed_1_2dc63b48:name;
+const unique T.__unnamed_1_2ef8da39:name;
+const unique T.__unnamed_1_faa7dc71:name;
+const unique T.__unnamed_20_f4d2e6d8:name;
+const unique T.__unnamed_24_41cbc8c0:name;
+const unique T.__unnamed_24_5419c914:name;
+const unique T.__unnamed_24_67a5ff10:name;
+const unique T.__unnamed_24_72c3976e:name;
+const unique T.__unnamed_24_a26050bb:name;
+const unique T.__unnamed_24_b8f476db:name;
+const unique T.__unnamed_24_d09044b4:name;
+const unique T.__unnamed_2_46cc4597:name;
+const unique T.__unnamed_40_7218f704:name;
+const unique T.__unnamed_40_c55c9377:name;
+const unique T.__unnamed_44_5584090d:name;
+const unique T.__unnamed_48_cf99b13f:name;
+const unique T.__unnamed_4_069846fb:name;
+const unique T.__unnamed_4_224c32f4:name;
+const unique T.__unnamed_4_2de698da:name;
+const unique T.__unnamed_4_3a2fdc5e:name;
+const unique T.__unnamed_4_3a4c1a13:name;
+const unique T.__unnamed_4_43913aa5:name;
+const unique T.__unnamed_4_4e8dd2ba:name;
+const unique T.__unnamed_4_52603077:name;
+const unique T.__unnamed_4_52c594f7:name;
+const unique T.__unnamed_4_5ca00198:name;
+const unique T.__unnamed_4_6ac6463c:name;
+const unique T.__unnamed_4_6f9ac8e1:name;
+const unique T.__unnamed_4_7a02167b:name;
+const unique T.__unnamed_4_7d9d0c7e:name;
+const unique T.__unnamed_4_82f7a864:name;
+const unique T.__unnamed_4_9aec220b:name;
+const unique T.__unnamed_4_a97c65a1:name;
+const unique T.__unnamed_4_c3479730:name;
+const unique T.__unnamed_4_d99b6e2b:name;
+const unique T.__unnamed_4_f19b65c1:name;
+const unique T.__unnamed_4_fa10fc16:name;
+const unique T.__unnamed_8_01efa60d:name;
+const unique T.__unnamed_8_08d4cef8:name;
+const unique T.__unnamed_8_0a898c0c:name;
+const unique T.__unnamed_8_1330f93a:name;
+const unique T.__unnamed_8_181d0de9:name;
+const unique T.__unnamed_8_4812764d:name;
+const unique T.__unnamed_8_559a91e6:name;
+const unique T.__unnamed_8_5845b309:name;
+const unique T.__unnamed_8_58ee4a31:name;
+const unique T.__unnamed_8_61acf4ce:name;
+const unique T.__unnamed_8_6acfee04:name;
+const unique T.__unnamed_8_7f26a9dd:name;
+const unique T.__unnamed_8_87add0bd:name;
+const unique T.__unnamed_8_b2773e4c:name;
+const unique T.__unnamed_8_de890d4e:name;
+const unique T.__unnamed_8_ef9ba0d3:name;
+
+function AssocClassList__GLOBALS(int) returns (int);
+function AssocClassList__GLOBALSInv(int) returns (int);
+function _S_AssocClassList__GLOBALS([int]bool) returns ([int]bool);
+function _S_AssocClassList__GLOBALSInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {AssocClassList__GLOBALSInv(AssocClassList__GLOBALS(x))} AssocClassList__GLOBALSInv(AssocClassList__GLOBALS(x)) == x);
+axiom (forall x:int :: {AssocClassList__GLOBALSInv(x)} AssocClassList__GLOBALS(AssocClassList__GLOBALSInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_AssocClassList__GLOBALS(S)[x]} _S_AssocClassList__GLOBALS(S)[x] <==> S[AssocClassList__GLOBALSInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_AssocClassList__GLOBALSInv(S)[x]} _S_AssocClassList__GLOBALSInv(S)[x] <==> S[AssocClassList__GLOBALS(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_AssocClassList__GLOBALS(S)} S[x] ==> _S_AssocClassList__GLOBALS(S)[AssocClassList__GLOBALS(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_AssocClassList__GLOBALSInv(S)} S[x] ==> _S_AssocClassList__GLOBALSInv(S)[AssocClassList__GLOBALSInv(x)]);
+
+axiom (forall x:int :: {AssocClassList__GLOBALS(x)} AssocClassList__GLOBALS(x) == x + 8);
+axiom (forall x:int :: {AssocClassList__GLOBALSInv(x)} AssocClassList__GLOBALSInv(x) == x - 8);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 8, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 8, 1) == AssocClassList__GLOBALSInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 8)} MINUS_LEFT_PTR(x, 1, 8) == AssocClassList__GLOBALSInv(x));
+function Buffer__UNICODE_STRING(int) returns (int);
+function Buffer__UNICODE_STRINGInv(int) returns (int);
+function _S_Buffer__UNICODE_STRING([int]bool) returns ([int]bool);
+function _S_Buffer__UNICODE_STRINGInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {Buffer__UNICODE_STRINGInv(Buffer__UNICODE_STRING(x))} Buffer__UNICODE_STRINGInv(Buffer__UNICODE_STRING(x)) == x);
+axiom (forall x:int :: {Buffer__UNICODE_STRINGInv(x)} Buffer__UNICODE_STRING(Buffer__UNICODE_STRINGInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_Buffer__UNICODE_STRING(S)[x]} _S_Buffer__UNICODE_STRING(S)[x] <==> S[Buffer__UNICODE_STRINGInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_Buffer__UNICODE_STRINGInv(S)[x]} _S_Buffer__UNICODE_STRINGInv(S)[x] <==> S[Buffer__UNICODE_STRING(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Buffer__UNICODE_STRING(S)} S[x] ==> _S_Buffer__UNICODE_STRING(S)[Buffer__UNICODE_STRING(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Buffer__UNICODE_STRINGInv(S)} S[x] ==> _S_Buffer__UNICODE_STRINGInv(S)[Buffer__UNICODE_STRINGInv(x)]);
+
+axiom (forall x:int :: {Buffer__UNICODE_STRING(x)} Buffer__UNICODE_STRING(x) == x + 4);
+axiom (forall x:int :: {Buffer__UNICODE_STRINGInv(x)} Buffer__UNICODE_STRINGInv(x) == x - 4);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 4, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 4, 1) == Buffer__UNICODE_STRINGInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 4)} MINUS_LEFT_PTR(x, 1, 4) == Buffer__UNICODE_STRINGInv(x));
+function DataIn__DEVICE_EXTENSION(int) returns (int);
+function DataIn__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_DataIn__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_DataIn__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {DataIn__DEVICE_EXTENSIONInv(DataIn__DEVICE_EXTENSION(x))} DataIn__DEVICE_EXTENSIONInv(DataIn__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {DataIn__DEVICE_EXTENSIONInv(x)} DataIn__DEVICE_EXTENSION(DataIn__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_DataIn__DEVICE_EXTENSION(S)[x]} _S_DataIn__DEVICE_EXTENSION(S)[x] <==> S[DataIn__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_DataIn__DEVICE_EXTENSIONInv(S)[x]} _S_DataIn__DEVICE_EXTENSIONInv(S)[x] <==> S[DataIn__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_DataIn__DEVICE_EXTENSION(S)} S[x] ==> _S_DataIn__DEVICE_EXTENSION(S)[DataIn__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_DataIn__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_DataIn__DEVICE_EXTENSIONInv(S)[DataIn__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {DataIn__DEVICE_EXTENSION(x)} DataIn__DEVICE_EXTENSION(x) == x + 132);
+axiom (forall x:int :: {DataIn__DEVICE_EXTENSIONInv(x)} DataIn__DEVICE_EXTENSIONInv(x) == x - 132);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 132, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 132, 1) == DataIn__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 132)} MINUS_LEFT_PTR(x, 1, 132) == DataIn__DEVICE_EXTENSIONInv(x));
+function DataOut__DEVICE_EXTENSION(int) returns (int);
+function DataOut__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_DataOut__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_DataOut__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {DataOut__DEVICE_EXTENSIONInv(DataOut__DEVICE_EXTENSION(x))} DataOut__DEVICE_EXTENSIONInv(DataOut__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {DataOut__DEVICE_EXTENSIONInv(x)} DataOut__DEVICE_EXTENSION(DataOut__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_DataOut__DEVICE_EXTENSION(S)[x]} _S_DataOut__DEVICE_EXTENSION(S)[x] <==> S[DataOut__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_DataOut__DEVICE_EXTENSIONInv(S)[x]} _S_DataOut__DEVICE_EXTENSIONInv(S)[x] <==> S[DataOut__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_DataOut__DEVICE_EXTENSION(S)} S[x] ==> _S_DataOut__DEVICE_EXTENSION(S)[DataOut__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_DataOut__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_DataOut__DEVICE_EXTENSIONInv(S)[DataOut__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {DataOut__DEVICE_EXTENSION(x)} DataOut__DEVICE_EXTENSION(x) == x + 136);
+axiom (forall x:int :: {DataOut__DEVICE_EXTENSIONInv(x)} DataOut__DEVICE_EXTENSIONInv(x) == x - 136);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 136, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 136, 1) == DataOut__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 136)} MINUS_LEFT_PTR(x, 1, 136) == DataOut__DEVICE_EXTENSIONInv(x));
+function DeviceExtension__DEVICE_OBJECT(int) returns (int);
+function DeviceExtension__DEVICE_OBJECTInv(int) returns (int);
+function _S_DeviceExtension__DEVICE_OBJECT([int]bool) returns ([int]bool);
+function _S_DeviceExtension__DEVICE_OBJECTInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {DeviceExtension__DEVICE_OBJECTInv(DeviceExtension__DEVICE_OBJECT(x))} DeviceExtension__DEVICE_OBJECTInv(DeviceExtension__DEVICE_OBJECT(x)) == x);
+axiom (forall x:int :: {DeviceExtension__DEVICE_OBJECTInv(x)} DeviceExtension__DEVICE_OBJECT(DeviceExtension__DEVICE_OBJECTInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_DeviceExtension__DEVICE_OBJECT(S)[x]} _S_DeviceExtension__DEVICE_OBJECT(S)[x] <==> S[DeviceExtension__DEVICE_OBJECTInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_DeviceExtension__DEVICE_OBJECTInv(S)[x]} _S_DeviceExtension__DEVICE_OBJECTInv(S)[x] <==> S[DeviceExtension__DEVICE_OBJECT(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_DeviceExtension__DEVICE_OBJECT(S)} S[x] ==> _S_DeviceExtension__DEVICE_OBJECT(S)[DeviceExtension__DEVICE_OBJECT(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_DeviceExtension__DEVICE_OBJECTInv(S)} S[x] ==> _S_DeviceExtension__DEVICE_OBJECTInv(S)[DeviceExtension__DEVICE_OBJECTInv(x)]);
+
+axiom (forall x:int :: {DeviceExtension__DEVICE_OBJECT(x)} DeviceExtension__DEVICE_OBJECT(x) == x + 40);
+axiom (forall x:int :: {DeviceExtension__DEVICE_OBJECTInv(x)} DeviceExtension__DEVICE_OBJECTInv(x) == x - 40);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 40, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 40, 1) == DeviceExtension__DEVICE_OBJECTInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 40)} MINUS_LEFT_PTR(x, 1, 40) == DeviceExtension__DEVICE_OBJECTInv(x));
+function Enabled__DEVICE_EXTENSION(int) returns (int);
+function Enabled__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_Enabled__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_Enabled__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {Enabled__DEVICE_EXTENSIONInv(Enabled__DEVICE_EXTENSION(x))} Enabled__DEVICE_EXTENSIONInv(Enabled__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {Enabled__DEVICE_EXTENSIONInv(x)} Enabled__DEVICE_EXTENSION(Enabled__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_Enabled__DEVICE_EXTENSION(S)[x]} _S_Enabled__DEVICE_EXTENSION(S)[x] <==> S[Enabled__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_Enabled__DEVICE_EXTENSIONInv(S)[x]} _S_Enabled__DEVICE_EXTENSIONInv(S)[x] <==> S[Enabled__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Enabled__DEVICE_EXTENSION(S)} S[x] ==> _S_Enabled__DEVICE_EXTENSION(S)[Enabled__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Enabled__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_Enabled__DEVICE_EXTENSIONInv(S)[Enabled__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {Enabled__DEVICE_EXTENSION(x)} Enabled__DEVICE_EXTENSION(x) == x + 284);
+axiom (forall x:int :: {Enabled__DEVICE_EXTENSIONInv(x)} Enabled__DEVICE_EXTENSIONInv(x) == x - 284);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 284, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 284, 1) == Enabled__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 284)} MINUS_LEFT_PTR(x, 1, 284) == Enabled__DEVICE_EXTENSIONInv(x));
+function Enabled__PORT(int) returns (int);
+function Enabled__PORTInv(int) returns (int);
+function _S_Enabled__PORT([int]bool) returns ([int]bool);
+function _S_Enabled__PORTInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {Enabled__PORTInv(Enabled__PORT(x))} Enabled__PORTInv(Enabled__PORT(x)) == x);
+axiom (forall x:int :: {Enabled__PORTInv(x)} Enabled__PORT(Enabled__PORTInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_Enabled__PORT(S)[x]} _S_Enabled__PORT(S)[x] <==> S[Enabled__PORTInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_Enabled__PORTInv(S)[x]} _S_Enabled__PORTInv(S)[x] <==> S[Enabled__PORT(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Enabled__PORT(S)} S[x] ==> _S_Enabled__PORT(S)[Enabled__PORT(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Enabled__PORTInv(S)} S[x] ==> _S_Enabled__PORTInv(S)[Enabled__PORTInv(x)]);
+
+axiom (forall x:int :: {Enabled__PORT(x)} Enabled__PORT(x) == x + 8);
+axiom (forall x:int :: {Enabled__PORTInv(x)} Enabled__PORTInv(x) == x - 8);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 8, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 8, 1) == Enabled__PORTInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 8)} MINUS_LEFT_PTR(x, 1, 8) == Enabled__PORTInv(x));
+function File__DEVICE_EXTENSION(int) returns (int);
+function File__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_File__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_File__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {File__DEVICE_EXTENSIONInv(File__DEVICE_EXTENSION(x))} File__DEVICE_EXTENSIONInv(File__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {File__DEVICE_EXTENSIONInv(x)} File__DEVICE_EXTENSION(File__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_File__DEVICE_EXTENSION(S)[x]} _S_File__DEVICE_EXTENSION(S)[x] <==> S[File__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_File__DEVICE_EXTENSIONInv(S)[x]} _S_File__DEVICE_EXTENSIONInv(S)[x] <==> S[File__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_File__DEVICE_EXTENSION(S)} S[x] ==> _S_File__DEVICE_EXTENSION(S)[File__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_File__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_File__DEVICE_EXTENSIONInv(S)[File__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {File__DEVICE_EXTENSION(x)} File__DEVICE_EXTENSION(x) == x + 280);
+axiom (forall x:int :: {File__DEVICE_EXTENSIONInv(x)} File__DEVICE_EXTENSIONInv(x) == x - 280);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 280, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 280, 1) == File__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 280)} MINUS_LEFT_PTR(x, 1, 280) == File__DEVICE_EXTENSIONInv(x));
+function File__PORT(int) returns (int);
+function File__PORTInv(int) returns (int);
+function _S_File__PORT([int]bool) returns ([int]bool);
+function _S_File__PORTInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {File__PORTInv(File__PORT(x))} File__PORTInv(File__PORT(x)) == x);
+axiom (forall x:int :: {File__PORTInv(x)} File__PORT(File__PORTInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_File__PORT(S)[x]} _S_File__PORT(S)[x] <==> S[File__PORTInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_File__PORTInv(S)[x]} _S_File__PORTInv(S)[x] <==> S[File__PORT(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_File__PORT(S)} S[x] ==> _S_File__PORT(S)[File__PORT(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_File__PORTInv(S)} S[x] ==> _S_File__PORTInv(S)[File__PORTInv(x)]);
+
+axiom (forall x:int :: {File__PORT(x)} File__PORT(x) == x + 0);
+axiom (forall x:int :: {File__PORTInv(x)} File__PORTInv(x) == x - 0);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1) == File__PORTInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 0)} MINUS_LEFT_PTR(x, 1, 0) == File__PORTInv(x));
+function Flink__LIST_ENTRY(int) returns (int);
+function Flink__LIST_ENTRYInv(int) returns (int);
+function _S_Flink__LIST_ENTRY([int]bool) returns ([int]bool);
+function _S_Flink__LIST_ENTRYInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {Flink__LIST_ENTRYInv(Flink__LIST_ENTRY(x))} Flink__LIST_ENTRYInv(Flink__LIST_ENTRY(x)) == x);
+axiom (forall x:int :: {Flink__LIST_ENTRYInv(x)} Flink__LIST_ENTRY(Flink__LIST_ENTRYInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_Flink__LIST_ENTRY(S)[x]} _S_Flink__LIST_ENTRY(S)[x] <==> S[Flink__LIST_ENTRYInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_Flink__LIST_ENTRYInv(S)[x]} _S_Flink__LIST_ENTRYInv(S)[x] <==> S[Flink__LIST_ENTRY(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Flink__LIST_ENTRY(S)} S[x] ==> _S_Flink__LIST_ENTRY(S)[Flink__LIST_ENTRY(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Flink__LIST_ENTRYInv(S)} S[x] ==> _S_Flink__LIST_ENTRYInv(S)[Flink__LIST_ENTRYInv(x)]);
+
+axiom (forall x:int :: {Flink__LIST_ENTRY(x)} Flink__LIST_ENTRY(x) == x + 0);
+axiom (forall x:int :: {Flink__LIST_ENTRYInv(x)} Flink__LIST_ENTRYInv(x) == x - 0);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1) == Flink__LIST_ENTRYInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 0)} MINUS_LEFT_PTR(x, 1, 0) == Flink__LIST_ENTRYInv(x));
+function Free__PORT(int) returns (int);
+function Free__PORTInv(int) returns (int);
+function _S_Free__PORT([int]bool) returns ([int]bool);
+function _S_Free__PORTInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {Free__PORTInv(Free__PORT(x))} Free__PORTInv(Free__PORT(x)) == x);
+axiom (forall x:int :: {Free__PORTInv(x)} Free__PORT(Free__PORTInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_Free__PORT(S)[x]} _S_Free__PORT(S)[x] <==> S[Free__PORTInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_Free__PORTInv(S)[x]} _S_Free__PORTInv(S)[x] <==> S[Free__PORT(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Free__PORT(S)} S[x] ==> _S_Free__PORT(S)[Free__PORT(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Free__PORTInv(S)} S[x] ==> _S_Free__PORTInv(S)[Free__PORTInv(x)]);
+
+axiom (forall x:int :: {Free__PORT(x)} Free__PORT(x) == x + 11);
+axiom (forall x:int :: {Free__PORTInv(x)} Free__PORTInv(x) == x - 11);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 11, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 11, 1) == Free__PORTInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 11)} MINUS_LEFT_PTR(x, 1, 11) == Free__PORTInv(x));
+function GrandMaster__GLOBALS(int) returns (int);
+function GrandMaster__GLOBALSInv(int) returns (int);
+function _S_GrandMaster__GLOBALS([int]bool) returns ([int]bool);
+function _S_GrandMaster__GLOBALSInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {GrandMaster__GLOBALSInv(GrandMaster__GLOBALS(x))} GrandMaster__GLOBALSInv(GrandMaster__GLOBALS(x)) == x);
+axiom (forall x:int :: {GrandMaster__GLOBALSInv(x)} GrandMaster__GLOBALS(GrandMaster__GLOBALSInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_GrandMaster__GLOBALS(S)[x]} _S_GrandMaster__GLOBALS(S)[x] <==> S[GrandMaster__GLOBALSInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_GrandMaster__GLOBALSInv(S)[x]} _S_GrandMaster__GLOBALSInv(S)[x] <==> S[GrandMaster__GLOBALS(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_GrandMaster__GLOBALS(S)} S[x] ==> _S_GrandMaster__GLOBALS(S)[GrandMaster__GLOBALS(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_GrandMaster__GLOBALSInv(S)} S[x] ==> _S_GrandMaster__GLOBALSInv(S)[GrandMaster__GLOBALSInv(x)]);
+
+axiom (forall x:int :: {GrandMaster__GLOBALS(x)} GrandMaster__GLOBALS(x) == x + 4);
+axiom (forall x:int :: {GrandMaster__GLOBALSInv(x)} GrandMaster__GLOBALSInv(x) == x - 4);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 4, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 4, 1) == GrandMaster__GLOBALSInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 4)} MINUS_LEFT_PTR(x, 1, 4) == GrandMaster__GLOBALSInv(x));
+function InputData__DEVICE_EXTENSION(int) returns (int);
+function InputData__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_InputData__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_InputData__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {InputData__DEVICE_EXTENSIONInv(InputData__DEVICE_EXTENSION(x))} InputData__DEVICE_EXTENSIONInv(InputData__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {InputData__DEVICE_EXTENSIONInv(x)} InputData__DEVICE_EXTENSION(InputData__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_InputData__DEVICE_EXTENSION(S)[x]} _S_InputData__DEVICE_EXTENSION(S)[x] <==> S[InputData__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_InputData__DEVICE_EXTENSIONInv(S)[x]} _S_InputData__DEVICE_EXTENSIONInv(S)[x] <==> S[InputData__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_InputData__DEVICE_EXTENSION(S)} S[x] ==> _S_InputData__DEVICE_EXTENSION(S)[InputData__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_InputData__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_InputData__DEVICE_EXTENSIONInv(S)[InputData__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {InputData__DEVICE_EXTENSION(x)} InputData__DEVICE_EXTENSION(x) == x + 128);
+axiom (forall x:int :: {InputData__DEVICE_EXTENSIONInv(x)} InputData__DEVICE_EXTENSIONInv(x) == x - 128);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 128, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 128, 1) == InputData__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 128)} MINUS_LEFT_PTR(x, 1, 128) == InputData__DEVICE_EXTENSIONInv(x));
+function LegacyDeviceList__GLOBALS(int) returns (int);
+function LegacyDeviceList__GLOBALSInv(int) returns (int);
+function _S_LegacyDeviceList__GLOBALS([int]bool) returns ([int]bool);
+function _S_LegacyDeviceList__GLOBALSInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {LegacyDeviceList__GLOBALSInv(LegacyDeviceList__GLOBALS(x))} LegacyDeviceList__GLOBALSInv(LegacyDeviceList__GLOBALS(x)) == x);
+axiom (forall x:int :: {LegacyDeviceList__GLOBALSInv(x)} LegacyDeviceList__GLOBALS(LegacyDeviceList__GLOBALSInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_LegacyDeviceList__GLOBALS(S)[x]} _S_LegacyDeviceList__GLOBALS(S)[x] <==> S[LegacyDeviceList__GLOBALSInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_LegacyDeviceList__GLOBALSInv(S)[x]} _S_LegacyDeviceList__GLOBALSInv(S)[x] <==> S[LegacyDeviceList__GLOBALS(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_LegacyDeviceList__GLOBALS(S)} S[x] ==> _S_LegacyDeviceList__GLOBALS(S)[LegacyDeviceList__GLOBALS(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_LegacyDeviceList__GLOBALSInv(S)} S[x] ==> _S_LegacyDeviceList__GLOBALSInv(S)[LegacyDeviceList__GLOBALSInv(x)]);
+
+axiom (forall x:int :: {LegacyDeviceList__GLOBALS(x)} LegacyDeviceList__GLOBALS(x) == x + 888);
+axiom (forall x:int :: {LegacyDeviceList__GLOBALSInv(x)} LegacyDeviceList__GLOBALSInv(x) == x - 888);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 888, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 888, 1) == LegacyDeviceList__GLOBALSInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 888)} MINUS_LEFT_PTR(x, 1, 888) == LegacyDeviceList__GLOBALSInv(x));
+function Link__DEVICE_EXTENSION(int) returns (int);
+function Link__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_Link__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_Link__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {Link__DEVICE_EXTENSIONInv(Link__DEVICE_EXTENSION(x))} Link__DEVICE_EXTENSIONInv(Link__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {Link__DEVICE_EXTENSIONInv(x)} Link__DEVICE_EXTENSION(Link__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_Link__DEVICE_EXTENSION(S)[x]} _S_Link__DEVICE_EXTENSION(S)[x] <==> S[Link__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_Link__DEVICE_EXTENSIONInv(S)[x]} _S_Link__DEVICE_EXTENSIONInv(S)[x] <==> S[Link__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Link__DEVICE_EXTENSION(S)} S[x] ==> _S_Link__DEVICE_EXTENSION(S)[Link__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Link__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_Link__DEVICE_EXTENSIONInv(S)[Link__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {Link__DEVICE_EXTENSION(x)} Link__DEVICE_EXTENSION(x) == x + 272);
+axiom (forall x:int :: {Link__DEVICE_EXTENSIONInv(x)} Link__DEVICE_EXTENSIONInv(x) == x - 272);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 272, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 272, 1) == Link__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 272)} MINUS_LEFT_PTR(x, 1, 272) == Link__DEVICE_EXTENSIONInv(x));
+function NumAssocClass__GLOBALS(int) returns (int);
+function NumAssocClass__GLOBALSInv(int) returns (int);
+function _S_NumAssocClass__GLOBALS([int]bool) returns ([int]bool);
+function _S_NumAssocClass__GLOBALSInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {NumAssocClass__GLOBALSInv(NumAssocClass__GLOBALS(x))} NumAssocClass__GLOBALSInv(NumAssocClass__GLOBALS(x)) == x);
+axiom (forall x:int :: {NumAssocClass__GLOBALSInv(x)} NumAssocClass__GLOBALS(NumAssocClass__GLOBALSInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_NumAssocClass__GLOBALS(S)[x]} _S_NumAssocClass__GLOBALS(S)[x] <==> S[NumAssocClass__GLOBALSInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_NumAssocClass__GLOBALSInv(S)[x]} _S_NumAssocClass__GLOBALSInv(S)[x] <==> S[NumAssocClass__GLOBALS(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_NumAssocClass__GLOBALS(S)} S[x] ==> _S_NumAssocClass__GLOBALS(S)[NumAssocClass__GLOBALS(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_NumAssocClass__GLOBALSInv(S)} S[x] ==> _S_NumAssocClass__GLOBALSInv(S)[NumAssocClass__GLOBALSInv(x)]);
+
+axiom (forall x:int :: {NumAssocClass__GLOBALS(x)} NumAssocClass__GLOBALS(x) == x + 12);
+axiom (forall x:int :: {NumAssocClass__GLOBALSInv(x)} NumAssocClass__GLOBALSInv(x) == x - 12);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 12, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 12, 1) == NumAssocClass__GLOBALSInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 12)} MINUS_LEFT_PTR(x, 1, 12) == NumAssocClass__GLOBALSInv(x));
+function PnP__DEVICE_EXTENSION(int) returns (int);
+function PnP__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_PnP__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_PnP__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {PnP__DEVICE_EXTENSIONInv(PnP__DEVICE_EXTENSION(x))} PnP__DEVICE_EXTENSIONInv(PnP__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {PnP__DEVICE_EXTENSIONInv(x)} PnP__DEVICE_EXTENSION(PnP__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_PnP__DEVICE_EXTENSION(S)[x]} _S_PnP__DEVICE_EXTENSION(S)[x] <==> S[PnP__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_PnP__DEVICE_EXTENSIONInv(S)[x]} _S_PnP__DEVICE_EXTENSIONInv(S)[x] <==> S[PnP__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_PnP__DEVICE_EXTENSION(S)} S[x] ==> _S_PnP__DEVICE_EXTENSION(S)[PnP__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_PnP__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_PnP__DEVICE_EXTENSIONInv(S)[PnP__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {PnP__DEVICE_EXTENSION(x)} PnP__DEVICE_EXTENSION(x) == x + 104);
+axiom (forall x:int :: {PnP__DEVICE_EXTENSIONInv(x)} PnP__DEVICE_EXTENSIONInv(x) == x - 104);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 104, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 104, 1) == PnP__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 104)} MINUS_LEFT_PTR(x, 1, 104) == PnP__DEVICE_EXTENSIONInv(x));
+function Port__PORT(int) returns (int);
+function Port__PORTInv(int) returns (int);
+function _S_Port__PORT([int]bool) returns ([int]bool);
+function _S_Port__PORTInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {Port__PORTInv(Port__PORT(x))} Port__PORTInv(Port__PORT(x)) == x);
+axiom (forall x:int :: {Port__PORTInv(x)} Port__PORT(Port__PORTInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_Port__PORT(S)[x]} _S_Port__PORT(S)[x] <==> S[Port__PORTInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_Port__PORTInv(S)[x]} _S_Port__PORTInv(S)[x] <==> S[Port__PORT(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Port__PORT(S)} S[x] ==> _S_Port__PORT(S)[Port__PORT(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Port__PORTInv(S)} S[x] ==> _S_Port__PORTInv(S)[Port__PORTInv(x)]);
+
+axiom (forall x:int :: {Port__PORT(x)} Port__PORT(x) == x + 4);
+axiom (forall x:int :: {Port__PORTInv(x)} Port__PORTInv(x) == x - 4);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 4, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 4, 1) == Port__PORTInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 4)} MINUS_LEFT_PTR(x, 1, 4) == Port__PORTInv(x));
+function RegistryPath__GLOBALS(int) returns (int);
+function RegistryPath__GLOBALSInv(int) returns (int);
+function _S_RegistryPath__GLOBALS([int]bool) returns ([int]bool);
+function _S_RegistryPath__GLOBALSInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {RegistryPath__GLOBALSInv(RegistryPath__GLOBALS(x))} RegistryPath__GLOBALSInv(RegistryPath__GLOBALS(x)) == x);
+axiom (forall x:int :: {RegistryPath__GLOBALSInv(x)} RegistryPath__GLOBALS(RegistryPath__GLOBALSInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_RegistryPath__GLOBALS(S)[x]} _S_RegistryPath__GLOBALS(S)[x] <==> S[RegistryPath__GLOBALSInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_RegistryPath__GLOBALSInv(S)[x]} _S_RegistryPath__GLOBALSInv(S)[x] <==> S[RegistryPath__GLOBALS(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_RegistryPath__GLOBALS(S)} S[x] ==> _S_RegistryPath__GLOBALS(S)[RegistryPath__GLOBALS(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_RegistryPath__GLOBALSInv(S)} S[x] ==> _S_RegistryPath__GLOBALSInv(S)[RegistryPath__GLOBALSInv(x)]);
+
+axiom (forall x:int :: {RegistryPath__GLOBALS(x)} RegistryPath__GLOBALS(x) == x + 360);
+axiom (forall x:int :: {RegistryPath__GLOBALSInv(x)} RegistryPath__GLOBALSInv(x) == x - 360);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 360, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 360, 1) == RegistryPath__GLOBALSInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 360)} MINUS_LEFT_PTR(x, 1, 360) == RegistryPath__GLOBALSInv(x));
+function Self__DEVICE_EXTENSION(int) returns (int);
+function Self__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_Self__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_Self__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {Self__DEVICE_EXTENSIONInv(Self__DEVICE_EXTENSION(x))} Self__DEVICE_EXTENSIONInv(Self__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {Self__DEVICE_EXTENSIONInv(x)} Self__DEVICE_EXTENSION(Self__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_Self__DEVICE_EXTENSION(S)[x]} _S_Self__DEVICE_EXTENSION(S)[x] <==> S[Self__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_Self__DEVICE_EXTENSIONInv(S)[x]} _S_Self__DEVICE_EXTENSIONInv(S)[x] <==> S[Self__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Self__DEVICE_EXTENSION(S)} S[x] ==> _S_Self__DEVICE_EXTENSION(S)[Self__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Self__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_Self__DEVICE_EXTENSIONInv(S)[Self__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {Self__DEVICE_EXTENSION(x)} Self__DEVICE_EXTENSION(x) == x + 0);
+axiom (forall x:int :: {Self__DEVICE_EXTENSIONInv(x)} Self__DEVICE_EXTENSIONInv(x) == x - 0);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1) == Self__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 0)} MINUS_LEFT_PTR(x, 1, 0) == Self__DEVICE_EXTENSIONInv(x));
+function StackSize__DEVICE_OBJECT(int) returns (int);
+function StackSize__DEVICE_OBJECTInv(int) returns (int);
+function _S_StackSize__DEVICE_OBJECT([int]bool) returns ([int]bool);
+function _S_StackSize__DEVICE_OBJECTInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {StackSize__DEVICE_OBJECTInv(StackSize__DEVICE_OBJECT(x))} StackSize__DEVICE_OBJECTInv(StackSize__DEVICE_OBJECT(x)) == x);
+axiom (forall x:int :: {StackSize__DEVICE_OBJECTInv(x)} StackSize__DEVICE_OBJECT(StackSize__DEVICE_OBJECTInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_StackSize__DEVICE_OBJECT(S)[x]} _S_StackSize__DEVICE_OBJECT(S)[x] <==> S[StackSize__DEVICE_OBJECTInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_StackSize__DEVICE_OBJECTInv(S)[x]} _S_StackSize__DEVICE_OBJECTInv(S)[x] <==> S[StackSize__DEVICE_OBJECT(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_StackSize__DEVICE_OBJECT(S)} S[x] ==> _S_StackSize__DEVICE_OBJECT(S)[StackSize__DEVICE_OBJECT(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_StackSize__DEVICE_OBJECTInv(S)} S[x] ==> _S_StackSize__DEVICE_OBJECTInv(S)[StackSize__DEVICE_OBJECTInv(x)]);
+
+axiom (forall x:int :: {StackSize__DEVICE_OBJECT(x)} StackSize__DEVICE_OBJECT(x) == x + 48);
+axiom (forall x:int :: {StackSize__DEVICE_OBJECTInv(x)} StackSize__DEVICE_OBJECTInv(x) == x - 48);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 48, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 48, 1) == StackSize__DEVICE_OBJECTInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 48)} MINUS_LEFT_PTR(x, 1, 48) == StackSize__DEVICE_OBJECTInv(x));
+function Started__DEVICE_EXTENSION(int) returns (int);
+function Started__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_Started__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_Started__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {Started__DEVICE_EXTENSIONInv(Started__DEVICE_EXTENSION(x))} Started__DEVICE_EXTENSIONInv(Started__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {Started__DEVICE_EXTENSIONInv(x)} Started__DEVICE_EXTENSION(Started__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_Started__DEVICE_EXTENSION(S)[x]} _S_Started__DEVICE_EXTENSION(S)[x] <==> S[Started__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_Started__DEVICE_EXTENSIONInv(S)[x]} _S_Started__DEVICE_EXTENSIONInv(S)[x] <==> S[Started__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Started__DEVICE_EXTENSION(S)} S[x] ==> _S_Started__DEVICE_EXTENSION(S)[Started__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Started__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_Started__DEVICE_EXTENSIONInv(S)[Started__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {Started__DEVICE_EXTENSION(x)} Started__DEVICE_EXTENSION(x) == x + 105);
+axiom (forall x:int :: {Started__DEVICE_EXTENSIONInv(x)} Started__DEVICE_EXTENSIONInv(x) == x - 105);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 105, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 105, 1) == Started__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 105)} MINUS_LEFT_PTR(x, 1, 105) == Started__DEVICE_EXTENSIONInv(x));
+function TopPort__DEVICE_EXTENSION(int) returns (int);
+function TopPort__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_TopPort__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_TopPort__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {TopPort__DEVICE_EXTENSIONInv(TopPort__DEVICE_EXTENSION(x))} TopPort__DEVICE_EXTENSIONInv(TopPort__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {TopPort__DEVICE_EXTENSIONInv(x)} TopPort__DEVICE_EXTENSION(TopPort__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_TopPort__DEVICE_EXTENSION(S)[x]} _S_TopPort__DEVICE_EXTENSION(S)[x] <==> S[TopPort__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_TopPort__DEVICE_EXTENSIONInv(S)[x]} _S_TopPort__DEVICE_EXTENSIONInv(S)[x] <==> S[TopPort__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_TopPort__DEVICE_EXTENSION(S)} S[x] ==> _S_TopPort__DEVICE_EXTENSION(S)[TopPort__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_TopPort__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_TopPort__DEVICE_EXTENSIONInv(S)[TopPort__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {TopPort__DEVICE_EXTENSION(x)} TopPort__DEVICE_EXTENSION(x) == x + 8);
+axiom (forall x:int :: {TopPort__DEVICE_EXTENSIONInv(x)} TopPort__DEVICE_EXTENSIONInv(x) == x - 8);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 8, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 8, 1) == TopPort__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 8)} MINUS_LEFT_PTR(x, 1, 8) == TopPort__DEVICE_EXTENSIONInv(x));
+function UnitId__DEVICE_EXTENSION(int) returns (int);
+function UnitId__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_UnitId__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_UnitId__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {UnitId__DEVICE_EXTENSIONInv(UnitId__DEVICE_EXTENSION(x))} UnitId__DEVICE_EXTENSIONInv(UnitId__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {UnitId__DEVICE_EXTENSIONInv(x)} UnitId__DEVICE_EXTENSION(UnitId__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_UnitId__DEVICE_EXTENSION(S)[x]} _S_UnitId__DEVICE_EXTENSION(S)[x] <==> S[UnitId__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_UnitId__DEVICE_EXTENSIONInv(S)[x]} _S_UnitId__DEVICE_EXTENSIONInv(S)[x] <==> S[UnitId__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_UnitId__DEVICE_EXTENSION(S)} S[x] ==> _S_UnitId__DEVICE_EXTENSION(S)[UnitId__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_UnitId__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_UnitId__DEVICE_EXTENSIONInv(S)[UnitId__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {UnitId__DEVICE_EXTENSION(x)} UnitId__DEVICE_EXTENSION(x) == x + 196);
+axiom (forall x:int :: {UnitId__DEVICE_EXTENSIONInv(x)} UnitId__DEVICE_EXTENSIONInv(x) == x - 196);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 196, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 196, 1) == UnitId__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 196)} MINUS_LEFT_PTR(x, 1, 196) == UnitId__DEVICE_EXTENSIONInv(x));
+function MINUS_BOTH_PTR_OR_BOTH_INT(a:int, b:int, size:int) returns (int);
+axiom (forall a:int, b:int, size:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(a,b,size)}
+size * MINUS_BOTH_PTR_OR_BOTH_INT(a,b,size) <= a - b && a - b < size * (MINUS_BOTH_PTR_OR_BOTH_INT(a,b,size) + 1));
+
+function MINUS_LEFT_PTR(a:int, a_size:int, b:int) returns (int);
+axiom(forall a:int, a_size:int, b:int :: {MINUS_LEFT_PTR(a,a_size,b)} MINUS_LEFT_PTR(a,a_size,b) == a - a_size * b);
+
+function PLUS(a:int, a_size:int, b:int) returns (int);
+axiom (forall a:int, a_size:int, b:int :: {PLUS(a,a_size,b)} PLUS(a,a_size,b) == a + a_size * b);
+
+function MULT(a:int, b:int) returns (int); // a*b
+axiom(forall a:int, b:int :: {MULT(a,b)} MULT(a,b) == a * b);
+
+function DIV(a:int, b:int) returns (int); // a/b
+
+axiom(forall a:int, b:int :: {DIV(a,b)}
+a >= 0 && b > 0 ==> b * DIV(a,b) <= a && a < b * (DIV(a,b) + 1)
+);
+
+axiom(forall a:int, b:int :: {DIV(a,b)}
+a >= 0 && b < 0 ==> b * DIV(a,b) <= a && a < b * (DIV(a,b) - 1)
+);
+
+axiom(forall a:int, b:int :: {DIV(a,b)}
+a < 0 && b > 0 ==> b * DIV(a,b) >= a && a > b * (DIV(a,b) - 1)
+);
+
+axiom(forall a:int, b:int :: {DIV(a,b)}
+a < 0 && b < 0 ==> b * DIV(a,b) >= a && a > b * (DIV(a,b) + 1)
+);
+
+function BINARY_BOTH_INT(a:int, b:int) returns (int);
+
+function POW2(a:int) returns (bool);
+axiom POW2(1);
+axiom POW2(2);
+axiom POW2(4);
+axiom POW2(8);
+axiom POW2(16);
+axiom POW2(32);
+axiom POW2(64);
+axiom POW2(128);
+axiom POW2(256);
+axiom POW2(512);
+axiom POW2(1024);
+axiom POW2(2048);
+axiom POW2(4096);
+axiom POW2(8192);
+axiom POW2(16384);
+axiom POW2(32768);
+axiom POW2(65536);
+axiom POW2(131072);
+axiom POW2(262144);
+axiom POW2(524288);
+axiom POW2(1048576);
+axiom POW2(2097152);
+axiom POW2(4194304);
+axiom POW2(8388608);
+axiom POW2(16777216);
+axiom POW2(33554432);
+
+function choose(a:bool, b:int, c:int) returns (x:int);
+axiom(forall a:bool, b:int, c:int :: {choose(a,b,c)} a ==> choose(a,b,c) == b);
+axiom(forall a:bool, b:int, c:int :: {choose(a,b,c)} !a ==> choose(a,b,c) == c);
+
+function BIT_BAND(a:int, b:int) returns (x:int);
+axiom(forall a:int, b:int :: {BIT_BAND(a,b)} a == b ==> BIT_BAND(a,b) == a);
+axiom(forall a:int, b:int :: {BIT_BAND(a,b)} POW2(a) && POW2(b) && a != b ==> BIT_BAND(a,b) == 0);
+axiom(forall a:int, b:int :: {BIT_BAND(a,b)} a == 0 || b == 0 ==> BIT_BAND(a,b) == 0);
+
+function BIT_BOR(a:int, b:int) returns (x:int);
+
+function BIT_BXOR(a:int, b:int) returns (x:int);
+
+function BIT_BNOT(a:int) returns (int);
+
+function LIFT(a:bool) returns (int);
+axiom(forall a:bool :: {LIFT(a)} a <==> LIFT(a) != 0);
+
+function NOT(a:int) returns (int);
+axiom(forall a:int :: {NOT(a)} a == 0 ==> NOT(a) != 0);
+axiom(forall a:int :: {NOT(a)} a != 0 ==> NOT(a) == 0);
+
+function NULL_CHECK(a:int) returns (int);
+axiom(forall a:int :: {NULL_CHECK(a)} a == 0 ==> NULL_CHECK(a) != 0);
+axiom(forall a:int :: {NULL_CHECK(a)} a != 0 ==> NULL_CHECK(a) == 0);
+
+
+
+
+procedure havoc_assert(i:int);
+requires (i != 0);
+
+procedure havoc_assume(i:int);
+ensures (i != 0);
+
+procedure __HAVOC_free(a:int);
+modifies alloc;
+ensures (forall x:int :: {alloc[x]} x == a || old(alloc)[x] == alloc[x]);
+ensures (alloc[a] == FREED);
+// Additional checks guarded by tranlator flags
+// requires alloc[a] == ALLOCATED;
+// requires Base(a) == a;
+
+procedure __HAVOC_malloc(obj_size:int) returns (new:int);
+requires obj_size >= 0;
+modifies alloc;
+ensures (new > 0);
+ensures (forall x:int :: {Base(x)} new <= x && x < new+obj_size ==> Base(x) == new);
+ensures (forall x:int :: {alloc[x]} x == new || old(alloc)[x] == alloc[x]);
+ensures old(alloc)[new] == UNALLOCATED && alloc[new] == ALLOCATED;
+
+procedure nondet_choice() returns (x:int);
+
+procedure _strdup(str:int) returns (new:int);
+
+procedure _xstrcasecmp(a0:int, a1:int) returns (ret:int);
+
+procedure _xstrcmp(a0:int, a1:int) returns (ret:int);
+
+var Res_DEVICE_STACK:[int]int;
+var Res_DEV_EXTN:[int]int;
+var Res_DEV_OBJ_INIT:[int]int;
+var Res_SPIN_LOCK:[int]int;
+
+
+
+////////////////////
+// Between predicate
+////////////////////
+function ReachBetween(f: [int]int, x: int, y: int, z: int) returns (bool);
+function ReachAvoiding(f: [int]int, x: int, y: int, z: int) returns (bool);
+
+
+//////////////////////////
+// Between set constructor
+//////////////////////////
+function ReachBetweenSet(f: [int]int, x: int, z: int) returns ([int]bool);
+
+////////////////////////////////////////////////////
+// axioms relating ReachBetween and ReachBetweenSet
+////////////////////////////////////////////////////
+axiom(forall f: [int]int, x: int, y: int, z: int :: {ReachBetweenSet(f, x, z)[y]} ReachBetweenSet(f, x, z)[y] <==> ReachBetween(f, x, y, z));
+axiom(forall f: [int]int, x: int, y: int, z: int :: {ReachBetween(f, x, y, z), ReachBetweenSet(f, x, z)} ReachBetween(f, x, y, z) ==> ReachBetweenSet(f, x, z)[y]);
+axiom(forall f: [int]int, x: int, z: int :: {ReachBetweenSet(f, x, z)} ReachBetween(f, x, x, x));
+
+
+//////////////////////////
+// Axioms for ReachBetween
+//////////////////////////
+
+// reflexive
+axiom(forall f: [int]int, x: int :: ReachBetween(f, x, x, x));
+
+// step
+//axiom(forall f: [int]int, x: int :: {f[x]} ReachBetween(f, x, f[x], f[x]));
+axiom(forall f: [int]int, x: int, y: int, z: int, w:int :: {ReachBetween(f, y, z, w), f[x]} ReachBetween(f, x, f[x], f[x]));
+
+// reach
+axiom(forall f: [int]int, x: int, y: int :: {f[x], ReachBetween(f, x, y, y)} ReachBetween(f, x, y, y) ==> x == y || ReachBetween(f, x, f[x], y));
+
+// cycle
+axiom(forall f: [int]int, x: int, y:int :: {f[x], ReachBetween(f, x, y, y)} f[x] == x && ReachBetween(f, x, y, y) ==> x == y);
+
+// sandwich
+axiom(forall f: [int]int, x: int, y: int :: {ReachBetween(f, x, y, x)} ReachBetween(f, x, y, x) ==> x == y);
+
+// order1
+axiom(forall f: [int]int, x: int, y: int, z: int :: {ReachBetween(f, x, y, y), ReachBetween(f, x, z, z)} ReachBetween(f, x, y, y) && ReachBetween(f, x, z, z) ==> ReachBetween(f, x, y, z) || ReachBetween(f, x, z, y));
+
+// order2
+axiom(forall f: [int]int, x: int, y: int, z: int :: {ReachBetween(f, x, y, z)} ReachBetween(f, x, y, z) ==> ReachBetween(f, x, y, y) && ReachBetween(f, y, z, z));
+
+// transitive1
+axiom(forall f: [int]int, x: int, y: int, z: int :: {ReachBetween(f, x, y, y), ReachBetween(f, y, z, z)} ReachBetween(f, x, y, y) && ReachBetween(f, y, z, z) ==> ReachBetween(f, x, z, z));
+
+// transitive2
+axiom(forall f: [int]int, x: int, y: int, z: int, w: int :: {ReachBetween(f, x, y, z), ReachBetween(f, y, w, z)} ReachBetween(f, x, y, z) && ReachBetween(f, y, w, z) ==> ReachBetween(f, x, y, w) && ReachBetween(f, x, w, z));
+
+// transitive3
+axiom(forall f: [int]int, x: int, y: int, z: int, w: int :: {ReachBetween(f, x, y, z), ReachBetween(f, x, w, y)} ReachBetween(f, x, y, z) && ReachBetween(f, x, w, y) ==> ReachBetween(f, x, w, z) && ReachBetween(f, w, y, z));
+
+// This axiom is required to deal with the incompleteness of the trigger for the reflexive axiom.
+// It cannot be proved using the rest of the axioms.
+axiom(forall f: [int]int, u:int, x: int :: {ReachBetween(f, u, x, x)} ReachBetween(f, u, x, x) ==> ReachBetween(f, u, u, x));
+
+// relation between ReachAvoiding and ReachBetween
+axiom(forall f: [int]int, x: int, y: int, z: int :: {ReachAvoiding(f, x, y, z)}{ReachBetween(f, x, y, z)} ReachAvoiding(f, x, y, z) <==> (ReachBetween(f, x, y, z) || (ReachBetween(f, x, y, y) && !ReachBetween(f, x, z, z))));
+
+// update
+axiom(forall f: [int]int, u: int, v: int, x: int, p: int, q: int :: {ReachAvoiding(f[p := q], u, v, x)} ReachAvoiding(f[p := q], u, v, x) <==> ((ReachAvoiding(f, u, v, p) && ReachAvoiding(f, u, v, x)) || (ReachAvoiding(f, u, p, x) && p != x && ReachAvoiding(f, q, v, p) && ReachAvoiding(f, q, v, x))));
+ ///////////////////////////////
+ // Shifts for linking fields
+ ///////////////////////////////
+function Shift_Flink__LIST_ENTRY(f: [int]int) returns ([int]int);
+axiom( forall f: [int]int, __x:int :: {f[Flink__LIST_ENTRY(__x)],Shift_Flink__LIST_ENTRY(f)} {Shift_Flink__LIST_ENTRY(f)[__x]} Shift_Flink__LIST_ENTRY(f)[__x] == f[Flink__LIST_ENTRY(__x)]);
+axiom(forall f: [int]int, __x:int, __v:int :: {Shift_Flink__LIST_ENTRY(f[Flink__LIST_ENTRY(__x) := __v])} Shift_Flink__LIST_ENTRY(f[Flink__LIST_ENTRY(__x) := __v]) == Shift_Flink__LIST_ENTRY(f)[__x := __v]);
+
+const unique Globals : int;
+axiom(Globals != 0);
+
+
+procedure ExFreePoolWithTag($P$1$14901.35$ExFreePoolWithTag$81:int, $Tag$2$14902.15$ExFreePoolWithTag$81:int);
+
+//TAG: ensures __preserves_mem
+ensures(Mem == old(Mem));
+//TAG: ensures __preserves_resource("DEV_OBJ_INIT") && __preserves_resource("DEV_EXTN")
+ensures((Res_DEV_OBJ_INIT == old(Res_DEV_OBJ_INIT)) && (Res_DEV_EXTN == old(Res_DEV_EXTN)));
+
+modifies Res_DEVICE_STACK;
+
+//TAG: net change in resource DEVICE_STACK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEVICE_STACK[r]} (Empty()[r]) || old(Res_DEVICE_STACK)[r] == Res_DEVICE_STACK[r]));
+modifies Res_DEV_EXTN;
+
+//TAG: net change in resource DEV_EXTN only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_EXTN[r]} (Empty()[r]) || old(Res_DEV_EXTN)[r] == Res_DEV_EXTN[r]));
+modifies Res_DEV_OBJ_INIT;
+
+//TAG: net change in resource DEV_OBJ_INIT only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_OBJ_INIT[r]} (Empty()[r]) || old(Res_DEV_OBJ_INIT)[r] == Res_DEV_OBJ_INIT[r]));
+modifies Res_SPIN_LOCK;
+
+//TAG: net change in resource SPIN_LOCK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_SPIN_LOCK[r]} (Empty()[r]) || old(Res_SPIN_LOCK)[r] == Res_SPIN_LOCK[r]));
+//TAG: updated memory locations at Mem[T.MinorFunction__IO_STACK_LOCATION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.MinorFunction__IO_STACK_LOCATION][_m]} (Empty()[_m]) || Mem[T.MinorFunction__IO_STACK_LOCATION][_m] == old(Mem)[T.MinorFunction__IO_STACK_LOCATION][_m]));
+//TAG: updated memory locations at Mem[T.CurrentStackLocation___unnamed_4_f19b65c1] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.CurrentStackLocation___unnamed_4_f19b65c1][_m]} (Empty()[_m]) || Mem[T.CurrentStackLocation___unnamed_4_f19b65c1][_m] == old(Mem)[T.CurrentStackLocation___unnamed_4_f19b65c1][_m]));
+//TAG: updated memory locations at Mem[T.DeviceExtension__DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.DeviceExtension__DEVICE_OBJECT][_m] == old(Mem)[T.DeviceExtension__DEVICE_OBJECT][_m]));
+//TAG: updated memory locations at Mem[T.Self__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Self__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Self__DEVICE_EXTENSION][_m] == old(Mem)[T.Self__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.Started__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Started__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Started__DEVICE_EXTENSION][_m] == old(Mem)[T.Started__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.GrandMaster__GLOBALS] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.GrandMaster__GLOBALS][_m]} (Empty()[_m]) || Mem[T.GrandMaster__GLOBALS][_m] == old(Mem)[T.GrandMaster__GLOBALS][_m]));
+//TAG: updated memory locations at Mem[T.P_DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.P_DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.P_DEVICE_OBJECT][_m] == old(Mem)[T.P_DEVICE_OBJECT][_m]));
+
+//TAG: havoc memory locations by default
+modifies Mem;
+
+
+procedure IoAllocateIrp($StackSize$1$20453.15$IoAllocateIrp$81:int, $ChargeQuota$2$20454.17$IoAllocateIrp$81:int) returns ($result.IoAllocateIrp$20452.0$1$:int);
+
+//TAG: ensures __preserves_mem
+ensures(Mem == old(Mem));
+//TAG: ensures __preserves_resource("DEV_OBJ_INIT") && __preserves_resource("DEV_EXTN")
+ensures((Res_DEV_OBJ_INIT == old(Res_DEV_OBJ_INIT)) && (Res_DEV_EXTN == old(Res_DEV_EXTN)));
+
+modifies Res_DEVICE_STACK;
+
+//TAG: net change in resource DEVICE_STACK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEVICE_STACK[r]} (Empty()[r]) || old(Res_DEVICE_STACK)[r] == Res_DEVICE_STACK[r]));
+modifies Res_DEV_EXTN;
+
+//TAG: net change in resource DEV_EXTN only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_EXTN[r]} (Empty()[r]) || old(Res_DEV_EXTN)[r] == Res_DEV_EXTN[r]));
+modifies Res_DEV_OBJ_INIT;
+
+//TAG: net change in resource DEV_OBJ_INIT only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_OBJ_INIT[r]} (Empty()[r]) || old(Res_DEV_OBJ_INIT)[r] == Res_DEV_OBJ_INIT[r]));
+modifies Res_SPIN_LOCK;
+
+//TAG: net change in resource SPIN_LOCK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_SPIN_LOCK[r]} (Empty()[r]) || old(Res_SPIN_LOCK)[r] == Res_SPIN_LOCK[r]));
+//TAG: updated memory locations at Mem[T.MinorFunction__IO_STACK_LOCATION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.MinorFunction__IO_STACK_LOCATION][_m]} (Empty()[_m]) || Mem[T.MinorFunction__IO_STACK_LOCATION][_m] == old(Mem)[T.MinorFunction__IO_STACK_LOCATION][_m]));
+//TAG: updated memory locations at Mem[T.CurrentStackLocation___unnamed_4_f19b65c1] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.CurrentStackLocation___unnamed_4_f19b65c1][_m]} (Empty()[_m]) || Mem[T.CurrentStackLocation___unnamed_4_f19b65c1][_m] == old(Mem)[T.CurrentStackLocation___unnamed_4_f19b65c1][_m]));
+//TAG: updated memory locations at Mem[T.DeviceExtension__DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.DeviceExtension__DEVICE_OBJECT][_m] == old(Mem)[T.DeviceExtension__DEVICE_OBJECT][_m]));
+//TAG: updated memory locations at Mem[T.Self__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Self__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Self__DEVICE_EXTENSION][_m] == old(Mem)[T.Self__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.Started__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Started__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Started__DEVICE_EXTENSION][_m] == old(Mem)[T.Started__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.GrandMaster__GLOBALS] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.GrandMaster__GLOBALS][_m]} (Empty()[_m]) || Mem[T.GrandMaster__GLOBALS][_m] == old(Mem)[T.GrandMaster__GLOBALS][_m]));
+//TAG: updated memory locations at Mem[T.P_DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.P_DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.P_DEVICE_OBJECT][_m] == old(Mem)[T.P_DEVICE_OBJECT][_m]));
+
+//TAG: havoc memory locations by default
+modifies Mem;
+
+
+procedure IoDeleteDevice($DeviceObject$1$21328.67$IoDeleteDevice$41:int);
+
+//TAG: ensures __preserves_mem
+ensures(Mem == old(Mem));
+//TAG: requires 1 ==> __resource("DEV_OBJ_INIT", DeviceObject) == 1 && __resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)DeviceObject)->DeviceExtension)) == 1
+requires((true) ==> ((Res_DEV_OBJ_INIT[$DeviceObject$1$21328.67$IoDeleteDevice$41] == 1) && (Res_DEV_EXTN[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT($DeviceObject$1$21328.67$IoDeleteDevice$41)]] == 1)));
+//TAG: ensures 1 ==> __resource("DEV_OBJ_INIT", DeviceObject) == 0 && __resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)DeviceObject)->DeviceExtension)) == 0
+ensures((true) ==> ((Res_DEV_OBJ_INIT[$DeviceObject$1$21328.67$IoDeleteDevice$41] == 0) && (Res_DEV_EXTN[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT($DeviceObject$1$21328.67$IoDeleteDevice$41)]] == 0)));
+//TAG: ensures 1 ==> __updates_resource("DEV_OBJ_INIT", DeviceObject, 0) && __updates_resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)DeviceObject)->DeviceExtension), 0)
+ensures((true) ==> ((Res_DEV_OBJ_INIT == old(Res_DEV_OBJ_INIT)[$DeviceObject$1$21328.67$IoDeleteDevice$41 := 0]) && (Res_DEV_EXTN == old(Res_DEV_EXTN)[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT($DeviceObject$1$21328.67$IoDeleteDevice$41)] := 0])));
+//TAG: ensures !1 ==> __resource("DEV_OBJ_INIT", DeviceObject) == __old_resource("DEV_OBJ_INIT", DeviceObject) && __resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)DeviceObject)->DeviceExtension)) == __old_resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)DeviceObject)->DeviceExtension))
+ensures((!(true)) ==> ((Res_DEV_OBJ_INIT[$DeviceObject$1$21328.67$IoDeleteDevice$41] == old(Res_DEV_OBJ_INIT)[$DeviceObject$1$21328.67$IoDeleteDevice$41]) && (Res_DEV_EXTN[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT($DeviceObject$1$21328.67$IoDeleteDevice$41)]] == old(Res_DEV_EXTN)[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT($DeviceObject$1$21328.67$IoDeleteDevice$41)]])));
+//TAG: ensures !1 ==> __preserves_resource("DEV_OBJ_INIT") && __preserves_resource("DEV_EXTN")
+free ensures((!(true)) ==> ((Res_DEV_OBJ_INIT == old(Res_DEV_OBJ_INIT)) && (Res_DEV_EXTN == old(Res_DEV_EXTN))));
+
+modifies Res_DEVICE_STACK;
+
+//TAG: net change in resource DEVICE_STACK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEVICE_STACK[r]} (Empty()[r]) || old(Res_DEVICE_STACK)[r] == Res_DEVICE_STACK[r]));
+modifies Res_DEV_EXTN;
+
+//TAG: net change in resource DEV_EXTN only for: __set_empty, (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)DeviceObject)->DeviceExtension)
+ensures (Subset(Empty(), Union(Union(Empty(), Empty()), Singleton(Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT($DeviceObject$1$21328.67$IoDeleteDevice$41)]))) && (forall r:int :: {Res_DEV_EXTN[r]} (Empty()[r]) || (Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT($DeviceObject$1$21328.67$IoDeleteDevice$41)] == r) || old(Res_DEV_EXTN)[r] == Res_DEV_EXTN[r]));
+modifies Res_DEV_OBJ_INIT;
+
+//TAG: net change in resource DEV_OBJ_INIT only for: __set_empty, DeviceObject
+ensures (Subset(Empty(), Union(Union(Empty(), Empty()), Singleton($DeviceObject$1$21328.67$IoDeleteDevice$41))) && (forall r:int :: {Res_DEV_OBJ_INIT[r]} (Empty()[r]) || ($DeviceObject$1$21328.67$IoDeleteDevice$41 == r) || old(Res_DEV_OBJ_INIT)[r] == Res_DEV_OBJ_INIT[r]));
+modifies Res_SPIN_LOCK;
+
+//TAG: net change in resource SPIN_LOCK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_SPIN_LOCK[r]} (Empty()[r]) || old(Res_SPIN_LOCK)[r] == Res_SPIN_LOCK[r]));
+//TAG: updated memory locations at Mem[T.MinorFunction__IO_STACK_LOCATION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.MinorFunction__IO_STACK_LOCATION][_m]} (Empty()[_m]) || Mem[T.MinorFunction__IO_STACK_LOCATION][_m] == old(Mem)[T.MinorFunction__IO_STACK_LOCATION][_m]));
+//TAG: updated memory locations at Mem[T.CurrentStackLocation___unnamed_4_f19b65c1] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.CurrentStackLocation___unnamed_4_f19b65c1][_m]} (Empty()[_m]) || Mem[T.CurrentStackLocation___unnamed_4_f19b65c1][_m] == old(Mem)[T.CurrentStackLocation___unnamed_4_f19b65c1][_m]));
+//TAG: updated memory locations at Mem[T.DeviceExtension__DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.DeviceExtension__DEVICE_OBJECT][_m] == old(Mem)[T.DeviceExtension__DEVICE_OBJECT][_m]));
+//TAG: updated memory locations at Mem[T.Self__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Self__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Self__DEVICE_EXTENSION][_m] == old(Mem)[T.Self__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.Started__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Started__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Started__DEVICE_EXTENSION][_m] == old(Mem)[T.Started__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.GrandMaster__GLOBALS] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.GrandMaster__GLOBALS][_m]} (Empty()[_m]) || Mem[T.GrandMaster__GLOBALS][_m] == old(Mem)[T.GrandMaster__GLOBALS][_m]));
+//TAG: updated memory locations at Mem[T.P_DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.P_DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.P_DEVICE_OBJECT][_m] == old(Mem)[T.P_DEVICE_OBJECT][_m]));
+
+//TAG: havoc memory locations by default
+modifies Mem;
+
+
+procedure IoFreeIrp($Irp$1$21417.14$IoFreeIrp$41:int);
+
+//TAG: ensures __preserves_mem
+ensures(Mem == old(Mem));
+//TAG: ensures __preserves_resource("DEV_OBJ_INIT") && __preserves_resource("DEV_EXTN")
+ensures((Res_DEV_OBJ_INIT == old(Res_DEV_OBJ_INIT)) && (Res_DEV_EXTN == old(Res_DEV_EXTN)));
+
+modifies Res_DEVICE_STACK;
+
+//TAG: net change in resource DEVICE_STACK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEVICE_STACK[r]} (Empty()[r]) || old(Res_DEVICE_STACK)[r] == Res_DEVICE_STACK[r]));
+modifies Res_DEV_EXTN;
+
+//TAG: net change in resource DEV_EXTN only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_EXTN[r]} (Empty()[r]) || old(Res_DEV_EXTN)[r] == Res_DEV_EXTN[r]));
+modifies Res_DEV_OBJ_INIT;
+
+//TAG: net change in resource DEV_OBJ_INIT only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_OBJ_INIT[r]} (Empty()[r]) || old(Res_DEV_OBJ_INIT)[r] == Res_DEV_OBJ_INIT[r]));
+modifies Res_SPIN_LOCK;
+
+//TAG: net change in resource SPIN_LOCK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_SPIN_LOCK[r]} (Empty()[r]) || old(Res_SPIN_LOCK)[r] == Res_SPIN_LOCK[r]));
+//TAG: updated memory locations at Mem[T.MinorFunction__IO_STACK_LOCATION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.MinorFunction__IO_STACK_LOCATION][_m]} (Empty()[_m]) || Mem[T.MinorFunction__IO_STACK_LOCATION][_m] == old(Mem)[T.MinorFunction__IO_STACK_LOCATION][_m]));
+//TAG: updated memory locations at Mem[T.CurrentStackLocation___unnamed_4_f19b65c1] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.CurrentStackLocation___unnamed_4_f19b65c1][_m]} (Empty()[_m]) || Mem[T.CurrentStackLocation___unnamed_4_f19b65c1][_m] == old(Mem)[T.CurrentStackLocation___unnamed_4_f19b65c1][_m]));
+//TAG: updated memory locations at Mem[T.DeviceExtension__DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.DeviceExtension__DEVICE_OBJECT][_m] == old(Mem)[T.DeviceExtension__DEVICE_OBJECT][_m]));
+//TAG: updated memory locations at Mem[T.Self__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Self__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Self__DEVICE_EXTENSION][_m] == old(Mem)[T.Self__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.Started__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Started__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Started__DEVICE_EXTENSION][_m] == old(Mem)[T.Started__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.GrandMaster__GLOBALS] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.GrandMaster__GLOBALS][_m]} (Empty()[_m]) || Mem[T.GrandMaster__GLOBALS][_m] == old(Mem)[T.GrandMaster__GLOBALS][_m]));
+//TAG: updated memory locations at Mem[T.P_DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.P_DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.P_DEVICE_OBJECT][_m] == old(Mem)[T.P_DEVICE_OBJECT][_m]));
+
+//TAG: havoc memory locations by default
+modifies Mem;
+
+
+procedure KbdEnableDisablePort($EnableFlag$1$543.15$KbdEnableDisablePort$161:int, $Irp$2$544.15$KbdEnableDisablePort$161:int, $Port$3$545.25$KbdEnableDisablePort$161:int, $File$4$546.22$KbdEnableDisablePort$161:int) returns ($result.KbdEnableDisablePort$542.0$1$:int);
+
+//TAG: requires __pforall(_H_x, (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension), __inv_resource("DEV_OBJ_INIT", 1), ((struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension))->Self == _H_x && __resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension)) == 1)
+requires((forall _H_x:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)]} Inverse(Res_DEV_OBJ_INIT,1)[_H_x] ==> ((Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)])] == _H_x) && (Res_DEV_EXTN[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)]] == 1))));
+//TAG: requires __pforall(_H_z, _H_z->Self, __inv_resource("DEV_EXTN", 1), __resource("DEV_OBJ_INIT", _H_z->Self) == 1 && (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)(_H_z->Self))->DeviceExtension) == _H_z)
+requires((forall _H_z:int :: {Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)]} Inverse(Res_DEV_EXTN,1)[_H_z] ==> ((Res_DEV_OBJ_INIT[Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)]] == 1) && (Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)])] == _H_z))));
+//TAG: requires __forall(_H_z, __inv_resource("DEV_EXTN", 1), 1)
+requires((Subset(Empty(), Inverse(Res_DEV_EXTN,1)) && (forall _H_z : int :: {Inverse(Res_DEV_EXTN,1)[_H_z]} (Inverse(Res_DEV_EXTN,1)[_H_z]) ==> (true))));
+//TAG: requires 1 ==> (Globals.GrandMaster != (void *)0 ==> __resource("DEV_EXTN", Globals.GrandMaster) == 1)
+requires((true) ==> ((Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)] != 0) ==> (Res_DEV_EXTN[Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)]] == 1)));
+//TAG: requires 1 ==> __setin(&Globals.LegacyDeviceList, __btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList))
+requires((true) ==> (ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[LegacyDeviceList__GLOBALS(Globals)]));
+//TAG: requires 1 ==> __forall(_H_y, __btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList), _H_y == &Globals.LegacyDeviceList || __resource("DEV_EXTN", CONTAINING_RECORD(_H_y, struct _DEVICE_EXTENSION , Link)) == 1)
+requires((true) ==> ((Subset(Empty(), ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))) && (forall _H_y : int :: {ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[_H_y]} (ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[_H_y]) ==> ((_H_y == LegacyDeviceList__GLOBALS(Globals)) || (Res_DEV_EXTN[MINUS_LEFT_PTR(_H_y, 1, Link__DEVICE_EXTENSION(0))] == 1))))));
+//TAG: requires 1 ==> !__setin(&Globals.GrandMaster->Link, __setminus(__btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList), __set(&Globals.LegacyDeviceList)))
+requires((true) ==> (!(Difference(ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals)), Singleton(LegacyDeviceList__GLOBALS(Globals)))[Link__DEVICE_EXTENSION(Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)])])));
+//TAG: ensures __pforall(_H_x, (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension), __inv_resource("DEV_OBJ_INIT", 1), ((struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension))->Self == _H_x && __resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension)) == 1)
+ensures((forall _H_x:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)]} Inverse(Res_DEV_OBJ_INIT,1)[_H_x] ==> ((Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)])] == _H_x) && (Res_DEV_EXTN[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)]] == 1))));
+//TAG: ensures __pforall(_H_z, _H_z->Self, __inv_resource("DEV_EXTN", 1), __resource("DEV_OBJ_INIT", _H_z->Self) == 1 && (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)(_H_z->Self))->DeviceExtension) == _H_z)
+ensures((forall _H_z:int :: {Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)]} Inverse(Res_DEV_EXTN,1)[_H_z] ==> ((Res_DEV_OBJ_INIT[Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)]] == 1) && (Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)])] == _H_z))));
+//TAG: ensures __forall(_H_z, __inv_resource("DEV_EXTN", 1), 1)
+ensures((Subset(Empty(), Inverse(Res_DEV_EXTN,1)) && (forall _H_z : int :: {Inverse(Res_DEV_EXTN,1)[_H_z]} (Inverse(Res_DEV_EXTN,1)[_H_z]) ==> (true))));
+//TAG: ensures 1 ==> (Globals.GrandMaster != (void *)0 ==> __resource("DEV_EXTN", Globals.GrandMaster) == 1)
+ensures((true) ==> ((Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)] != 0) ==> (Res_DEV_EXTN[Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)]] == 1)));
+//TAG: ensures 1 ==> __setin(&Globals.LegacyDeviceList, __btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList))
+ensures((true) ==> (ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[LegacyDeviceList__GLOBALS(Globals)]));
+//TAG: ensures 1 ==> __forall(_H_y, __btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList), _H_y == &Globals.LegacyDeviceList || __resource("DEV_EXTN", CONTAINING_RECORD(_H_y, struct _DEVICE_EXTENSION , Link)) == 1)
+ensures((true) ==> ((Subset(Empty(), ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))) && (forall _H_y : int :: {ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[_H_y]} (ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[_H_y]) ==> ((_H_y == LegacyDeviceList__GLOBALS(Globals)) || (Res_DEV_EXTN[MINUS_LEFT_PTR(_H_y, 1, Link__DEVICE_EXTENSION(0))] == 1))))));
+//TAG: ensures 1 ==> !__setin(&Globals.GrandMaster->Link, __setminus(__btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList), __set(&Globals.LegacyDeviceList)))
+ensures((true) ==> (!(Difference(ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals)), Singleton(LegacyDeviceList__GLOBALS(Globals)))[Link__DEVICE_EXTENSION(Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)])])));
+//TAG: ensures __preserves_field_map(__offset((*((struct _LIST_ENTRY *)0)).Flink))
+ensures(Mem[T.Flink__LIST_ENTRY] == old(Mem)[T.Flink__LIST_ENTRY]);
+//TAG: ensures __preserves_resource("DEV_OBJ_INIT")
+ensures(Res_DEV_OBJ_INIT == old(Res_DEV_OBJ_INIT));
+//TAG: ensures __preserves_resource("DEV_EXTN")
+ensures(Res_DEV_EXTN == old(Res_DEV_EXTN));
+
+modifies Res_DEVICE_STACK;
+
+//TAG: net change in resource DEVICE_STACK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEVICE_STACK[r]} (Empty()[r]) || old(Res_DEVICE_STACK)[r] == Res_DEVICE_STACK[r]));
+modifies Res_DEV_EXTN;
+
+//TAG: net change in resource DEV_EXTN only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_EXTN[r]} (Empty()[r]) || old(Res_DEV_EXTN)[r] == Res_DEV_EXTN[r]));
+modifies Res_DEV_OBJ_INIT;
+
+//TAG: net change in resource DEV_OBJ_INIT only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_OBJ_INIT[r]} (Empty()[r]) || old(Res_DEV_OBJ_INIT)[r] == Res_DEV_OBJ_INIT[r]));
+modifies Res_SPIN_LOCK;
+
+//TAG: net change in resource SPIN_LOCK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_SPIN_LOCK[r]} (Empty()[r]) || old(Res_SPIN_LOCK)[r] == Res_SPIN_LOCK[r]));
+//TAG: updated memory locations at Mem[T.MinorFunction__IO_STACK_LOCATION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.MinorFunction__IO_STACK_LOCATION][_m]} (Empty()[_m]) || Mem[T.MinorFunction__IO_STACK_LOCATION][_m] == old(Mem)[T.MinorFunction__IO_STACK_LOCATION][_m]));
+//TAG: updated memory locations at Mem[T.CurrentStackLocation___unnamed_4_f19b65c1] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.CurrentStackLocation___unnamed_4_f19b65c1][_m]} (Empty()[_m]) || Mem[T.CurrentStackLocation___unnamed_4_f19b65c1][_m] == old(Mem)[T.CurrentStackLocation___unnamed_4_f19b65c1][_m]));
+//TAG: updated memory locations at Mem[T.DeviceExtension__DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.DeviceExtension__DEVICE_OBJECT][_m] == old(Mem)[T.DeviceExtension__DEVICE_OBJECT][_m]));
+//TAG: updated memory locations at Mem[T.Self__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Self__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Self__DEVICE_EXTENSION][_m] == old(Mem)[T.Self__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.Started__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Started__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Started__DEVICE_EXTENSION][_m] == old(Mem)[T.Started__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.GrandMaster__GLOBALS] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.GrandMaster__GLOBALS][_m]} (Empty()[_m]) || Mem[T.GrandMaster__GLOBALS][_m] == old(Mem)[T.GrandMaster__GLOBALS][_m]));
+//TAG: updated memory locations at Mem[T.P_DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.P_DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.P_DEVICE_OBJECT][_m] == old(Mem)[T.P_DEVICE_OBJECT][_m]));
+
+//TAG: havoc memory locations by default
+modifies Mem;
+
+
+procedure KeyboardClassCleanupQueue($DeviceObject$1$1080.28$KeyboardClassCleanupQueue$121:int, $DeviceExtension$2$1081.28$KeyboardClassCleanupQueue$121:int, $FileObject$3$1082.28$KeyboardClassCleanupQueue$121:int);
+
+//TAG: requires __resource("DEV_EXTN", DeviceExtension) == 1
+requires(Res_DEV_EXTN[$DeviceExtension$2$1081.28$KeyboardClassCleanupQueue$121] == 1);
+//TAG: requires __pforall(_H_x, (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension), __inv_resource("DEV_OBJ_INIT", 1), ((struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension))->Self == _H_x && __resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension)) == 1)
+requires((forall _H_x:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)]} Inverse(Res_DEV_OBJ_INIT,1)[_H_x] ==> ((Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)])] == _H_x) && (Res_DEV_EXTN[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)]] == 1))));
+//TAG: requires __pforall(_H_z, _H_z->Self, __inv_resource("DEV_EXTN", 1), __resource("DEV_OBJ_INIT", _H_z->Self) == 1 && (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)(_H_z->Self))->DeviceExtension) == _H_z)
+requires((forall _H_z:int :: {Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)]} Inverse(Res_DEV_EXTN,1)[_H_z] ==> ((Res_DEV_OBJ_INIT[Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)]] == 1) && (Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)])] == _H_z))));
+//TAG: requires __forall(_H_z, __inv_resource("DEV_EXTN", 1), 1)
+requires((Subset(Empty(), Inverse(Res_DEV_EXTN,1)) && (forall _H_z : int :: {Inverse(Res_DEV_EXTN,1)[_H_z]} (Inverse(Res_DEV_EXTN,1)[_H_z]) ==> (true))));
+//TAG: requires 1 ==> (Globals.GrandMaster != (void *)0 ==> __resource("DEV_EXTN", Globals.GrandMaster) == 1)
+requires((true) ==> ((Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)] != 0) ==> (Res_DEV_EXTN[Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)]] == 1)));
+//TAG: requires 1 ==> __setin(&Globals.LegacyDeviceList, __btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList))
+requires((true) ==> (ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[LegacyDeviceList__GLOBALS(Globals)]));
+//TAG: requires 1 ==> __forall(_H_y, __btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList), _H_y == &Globals.LegacyDeviceList || __resource("DEV_EXTN", CONTAINING_RECORD(_H_y, struct _DEVICE_EXTENSION , Link)) == 1)
+requires((true) ==> ((Subset(Empty(), ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))) && (forall _H_y : int :: {ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[_H_y]} (ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[_H_y]) ==> ((_H_y == LegacyDeviceList__GLOBALS(Globals)) || (Res_DEV_EXTN[MINUS_LEFT_PTR(_H_y, 1, Link__DEVICE_EXTENSION(0))] == 1))))));
+//TAG: requires __resource("DEV_OBJ_INIT", DeviceObject) == 1
+requires(Res_DEV_OBJ_INIT[$DeviceObject$1$1080.28$KeyboardClassCleanupQueue$121] == 1);
+//TAG: ensures __resource("DEV_EXTN", DeviceExtension) == 1
+ensures(Res_DEV_EXTN[$DeviceExtension$2$1081.28$KeyboardClassCleanupQueue$121] == 1);
+//TAG: ensures __pforall(_H_x, (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension), __inv_resource("DEV_OBJ_INIT", 1), ((struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension))->Self == _H_x && __resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension)) == 1)
+ensures((forall _H_x:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)]} Inverse(Res_DEV_OBJ_INIT,1)[_H_x] ==> ((Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)])] == _H_x) && (Res_DEV_EXTN[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)]] == 1))));
+//TAG: ensures __pforall(_H_z, _H_z->Self, __inv_resource("DEV_EXTN", 1), __resource("DEV_OBJ_INIT", _H_z->Self) == 1 && (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)(_H_z->Self))->DeviceExtension) == _H_z)
+ensures((forall _H_z:int :: {Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)]} Inverse(Res_DEV_EXTN,1)[_H_z] ==> ((Res_DEV_OBJ_INIT[Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)]] == 1) && (Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)])] == _H_z))));
+//TAG: ensures __forall(_H_z, __inv_resource("DEV_EXTN", 1), 1)
+ensures((Subset(Empty(), Inverse(Res_DEV_EXTN,1)) && (forall _H_z : int :: {Inverse(Res_DEV_EXTN,1)[_H_z]} (Inverse(Res_DEV_EXTN,1)[_H_z]) ==> (true))));
+//TAG: ensures 1 ==> (Globals.GrandMaster != (void *)0 ==> __resource("DEV_EXTN", Globals.GrandMaster) == 1)
+ensures((true) ==> ((Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)] != 0) ==> (Res_DEV_EXTN[Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)]] == 1)));
+//TAG: ensures 1 ==> __setin(&Globals.LegacyDeviceList, __btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList))
+ensures((true) ==> (ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[LegacyDeviceList__GLOBALS(Globals)]));
+//TAG: ensures 1 ==> __forall(_H_y, __btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList), _H_y == &Globals.LegacyDeviceList || __resource("DEV_EXTN", CONTAINING_RECORD(_H_y, struct _DEVICE_EXTENSION , Link)) == 1)
+ensures((true) ==> ((Subset(Empty(), ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))) && (forall _H_y : int :: {ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[_H_y]} (ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[_H_y]) ==> ((_H_y == LegacyDeviceList__GLOBALS(Globals)) || (Res_DEV_EXTN[MINUS_LEFT_PTR(_H_y, 1, Link__DEVICE_EXTENSION(0))] == 1))))));
+//TAG: ensures __preserves_field_map(__offset((*((struct _LIST_ENTRY *)0)).Flink))
+ensures(Mem[T.Flink__LIST_ENTRY] == old(Mem)[T.Flink__LIST_ENTRY]);
+//TAG: ensures __preserves_resource("DEV_OBJ_INIT")
+ensures(Res_DEV_OBJ_INIT == old(Res_DEV_OBJ_INIT));
+//TAG: ensures __preserves_resource("DEV_EXTN")
+ensures(Res_DEV_EXTN == old(Res_DEV_EXTN));
+//TAG: ensures __resource("DEV_OBJ_INIT", DeviceObject) == 1
+ensures(Res_DEV_OBJ_INIT[$DeviceObject$1$1080.28$KeyboardClassCleanupQueue$121] == 1);
+
+modifies Res_DEVICE_STACK;
+
+//TAG: net change in resource DEVICE_STACK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEVICE_STACK[r]} (Empty()[r]) || old(Res_DEVICE_STACK)[r] == Res_DEVICE_STACK[r]));
+modifies Res_DEV_EXTN;
+
+//TAG: net change in resource DEV_EXTN only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_EXTN[r]} (Empty()[r]) || old(Res_DEV_EXTN)[r] == Res_DEV_EXTN[r]));
+modifies Res_DEV_OBJ_INIT;
+
+//TAG: net change in resource DEV_OBJ_INIT only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_OBJ_INIT[r]} (Empty()[r]) || old(Res_DEV_OBJ_INIT)[r] == Res_DEV_OBJ_INIT[r]));
+modifies Res_SPIN_LOCK;
+
+//TAG: net change in resource SPIN_LOCK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_SPIN_LOCK[r]} (Empty()[r]) || old(Res_SPIN_LOCK)[r] == Res_SPIN_LOCK[r]));
+//TAG: updated memory locations at Mem[T.MinorFunction__IO_STACK_LOCATION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.MinorFunction__IO_STACK_LOCATION][_m]} (Empty()[_m]) || Mem[T.MinorFunction__IO_STACK_LOCATION][_m] == old(Mem)[T.MinorFunction__IO_STACK_LOCATION][_m]));
+//TAG: updated memory locations at Mem[T.CurrentStackLocation___unnamed_4_f19b65c1] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.CurrentStackLocation___unnamed_4_f19b65c1][_m]} (Empty()[_m]) || Mem[T.CurrentStackLocation___unnamed_4_f19b65c1][_m] == old(Mem)[T.CurrentStackLocation___unnamed_4_f19b65c1][_m]));
+//TAG: updated memory locations at Mem[T.DeviceExtension__DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.DeviceExtension__DEVICE_OBJECT][_m] == old(Mem)[T.DeviceExtension__DEVICE_OBJECT][_m]));
+//TAG: updated memory locations at Mem[T.Self__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Self__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Self__DEVICE_EXTENSION][_m] == old(Mem)[T.Self__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.Started__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Started__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Started__DEVICE_EXTENSION][_m] == old(Mem)[T.Started__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.GrandMaster__GLOBALS] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.GrandMaster__GLOBALS][_m]} (Empty()[_m]) || Mem[T.GrandMaster__GLOBALS][_m] == old(Mem)[T.GrandMaster__GLOBALS][_m]));
+//TAG: updated memory locations at Mem[T.P_DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.P_DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.P_DEVICE_OBJECT][_m] == old(Mem)[T.P_DEVICE_OBJECT][_m]));
+
+//TAG: havoc memory locations by default
+modifies Mem;
+
+
+procedure ObfDereferenceObject($Object$1$24931.15$ObfDereferenceObject$41:int) returns ($result.ObfDereferenceObject$24930.0$1$:int);
+
+//TAG: ensures __preserves_mem
+ensures(Mem == old(Mem));
+//TAG: ensures __preserves_resource("DEV_OBJ_INIT") && __preserves_resource("DEV_EXTN")
+ensures((Res_DEV_OBJ_INIT == old(Res_DEV_OBJ_INIT)) && (Res_DEV_EXTN == old(Res_DEV_EXTN)));
+
+modifies Res_DEVICE_STACK;
+
+//TAG: net change in resource DEVICE_STACK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEVICE_STACK[r]} (Empty()[r]) || old(Res_DEVICE_STACK)[r] == Res_DEVICE_STACK[r]));
+modifies Res_DEV_EXTN;
+
+//TAG: net change in resource DEV_EXTN only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_EXTN[r]} (Empty()[r]) || old(Res_DEV_EXTN)[r] == Res_DEV_EXTN[r]));
+modifies Res_DEV_OBJ_INIT;
+
+//TAG: net change in resource DEV_OBJ_INIT only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_OBJ_INIT[r]} (Empty()[r]) || old(Res_DEV_OBJ_INIT)[r] == Res_DEV_OBJ_INIT[r]));
+modifies Res_SPIN_LOCK;
+
+//TAG: net change in resource SPIN_LOCK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_SPIN_LOCK[r]} (Empty()[r]) || old(Res_SPIN_LOCK)[r] == Res_SPIN_LOCK[r]));
+//TAG: updated memory locations at Mem[T.MinorFunction__IO_STACK_LOCATION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.MinorFunction__IO_STACK_LOCATION][_m]} (Empty()[_m]) || Mem[T.MinorFunction__IO_STACK_LOCATION][_m] == old(Mem)[T.MinorFunction__IO_STACK_LOCATION][_m]));
+//TAG: updated memory locations at Mem[T.CurrentStackLocation___unnamed_4_f19b65c1] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.CurrentStackLocation___unnamed_4_f19b65c1][_m]} (Empty()[_m]) || Mem[T.CurrentStackLocation___unnamed_4_f19b65c1][_m] == old(Mem)[T.CurrentStackLocation___unnamed_4_f19b65c1][_m]));
+//TAG: updated memory locations at Mem[T.DeviceExtension__DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.DeviceExtension__DEVICE_OBJECT][_m] == old(Mem)[T.DeviceExtension__DEVICE_OBJECT][_m]));
+//TAG: updated memory locations at Mem[T.Self__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Self__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Self__DEVICE_EXTENSION][_m] == old(Mem)[T.Self__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.Started__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Started__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Started__DEVICE_EXTENSION][_m] == old(Mem)[T.Started__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.GrandMaster__GLOBALS] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.GrandMaster__GLOBALS][_m]} (Empty()[_m]) || Mem[T.GrandMaster__GLOBALS][_m] == old(Mem)[T.GrandMaster__GLOBALS][_m]));
+//TAG: updated memory locations at Mem[T.P_DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.P_DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.P_DEVICE_OBJECT][_m] == old(Mem)[T.P_DEVICE_OBJECT][_m]));
+
+//TAG: havoc memory locations by default
+modifies Mem;
+
+
+procedure RemoveEntryList($Entry$1$6929.19$RemoveEntryList$41:int) returns ($result.RemoveEntryList$6928.0$1$:int);
+
+//TAG: ensures __preserves_resource("DEV_OBJ_INIT") && __preserves_resource("DEV_EXTN")
+ensures((Res_DEV_OBJ_INIT == old(Res_DEV_OBJ_INIT)) && (Res_DEV_EXTN == old(Res_DEV_EXTN)));
+//TAG: ensures __preserves_resource("DEV_OBJ_INIT") && __preserves_resource("DEV_EXTN")
+ensures((Res_DEV_OBJ_INIT == old(Res_DEV_OBJ_INIT)) && (Res_DEV_EXTN == old(Res_DEV_EXTN)));
+//TAG: ensures __seteq(__btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList), __setminus(__old(__btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList)), __set(Entry)))
+ensures((Subset(ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals)), Difference(ReachBetweenSet(Shift_Flink__LIST_ENTRY(old(Mem)[T.Flink__LIST_ENTRY]), old(Mem)[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(old(Globals)))], LegacyDeviceList__GLOBALS(old(Globals))), Singleton($Entry$1$6929.19$RemoveEntryList$41))) && Subset(Difference(ReachBetweenSet(Shift_Flink__LIST_ENTRY(old(Mem)[T.Flink__LIST_ENTRY]), old(Mem)[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(old(Globals)))], LegacyDeviceList__GLOBALS(old(Globals))), Singleton($Entry$1$6929.19$RemoveEntryList$41)), ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals)))));
+//TAG: ensures Entry->Flink == __old(Entry->Flink)
+ensures(Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY($Entry$1$6929.19$RemoveEntryList$41)] == old(Mem)[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY($Entry$1$6929.19$RemoveEntryList$41)]);
+
+modifies Res_DEVICE_STACK;
+
+//TAG: net change in resource DEVICE_STACK only for: __set_empty, __set_empty
+ensures (Subset(Empty(), Union(Union(Empty(), Empty()), Empty())) && (forall r:int :: {Res_DEVICE_STACK[r]} (Empty()[r]) || (Empty()[r]) || old(Res_DEVICE_STACK)[r] == Res_DEVICE_STACK[r]));
+modifies Res_DEV_EXTN;
+
+//TAG: net change in resource DEV_EXTN only for: __set_empty, __set_empty
+ensures (Subset(Empty(), Union(Union(Empty(), Empty()), Empty())) && (forall r:int :: {Res_DEV_EXTN[r]} (Empty()[r]) || (Empty()[r]) || old(Res_DEV_EXTN)[r] == Res_DEV_EXTN[r]));
+modifies Res_DEV_OBJ_INIT;
+
+//TAG: net change in resource DEV_OBJ_INIT only for: __set_empty, __set_empty
+ensures (Subset(Empty(), Union(Union(Empty(), Empty()), Empty())) && (forall r:int :: {Res_DEV_OBJ_INIT[r]} (Empty()[r]) || (Empty()[r]) || old(Res_DEV_OBJ_INIT)[r] == Res_DEV_OBJ_INIT[r]));
+modifies Res_SPIN_LOCK;
+
+//TAG: net change in resource SPIN_LOCK only for: __set_empty, __set_empty
+ensures (Subset(Empty(), Union(Union(Empty(), Empty()), Empty())) && (forall r:int :: {Res_SPIN_LOCK[r]} (Empty()[r]) || (Empty()[r]) || old(Res_SPIN_LOCK)[r] == Res_SPIN_LOCK[r]));
+//TAG: updated memory locations at Mem[T.MinorFunction__IO_STACK_LOCATION] only for: __set_empty, __set_empty
+ensures (Subset(Empty(), Union(Union(Empty(), Empty()), Empty())) && (forall _m:int :: {Mem[T.MinorFunction__IO_STACK_LOCATION][_m]} (Empty()[_m]) || (Empty()[_m]) || Mem[T.MinorFunction__IO_STACK_LOCATION][_m] == old(Mem)[T.MinorFunction__IO_STACK_LOCATION][_m]));
+//TAG: updated memory locations at Mem[T.CurrentStackLocation___unnamed_4_f19b65c1] only for: __set_empty, __set_empty
+ensures (Subset(Empty(), Union(Union(Empty(), Empty()), Empty())) && (forall _m:int :: {Mem[T.CurrentStackLocation___unnamed_4_f19b65c1][_m]} (Empty()[_m]) || (Empty()[_m]) || Mem[T.CurrentStackLocation___unnamed_4_f19b65c1][_m] == old(Mem)[T.CurrentStackLocation___unnamed_4_f19b65c1][_m]));
+//TAG: updated memory locations at Mem[T.DeviceExtension__DEVICE_OBJECT] only for: __set_empty, __set_empty
+ensures (Subset(Empty(), Union(Union(Empty(), Empty()), Empty())) && (forall _m:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][_m]} (Empty()[_m]) || (Empty()[_m]) || Mem[T.DeviceExtension__DEVICE_OBJECT][_m] == old(Mem)[T.DeviceExtension__DEVICE_OBJECT][_m]));
+//TAG: updated memory locations at Mem[T.Self__DEVICE_EXTENSION] only for: __set_empty, __set_empty
+ensures (Subset(Empty(), Union(Union(Empty(), Empty()), Empty())) && (forall _m:int :: {Mem[T.Self__DEVICE_EXTENSION][_m]} (Empty()[_m]) || (Empty()[_m]) || Mem[T.Self__DEVICE_EXTENSION][_m] == old(Mem)[T.Self__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.Started__DEVICE_EXTENSION] only for: __set_empty, __set_empty
+ensures (Subset(Empty(), Union(Union(Empty(), Empty()), Empty())) && (forall _m:int :: {Mem[T.Started__DEVICE_EXTENSION][_m]} (Empty()[_m]) || (Empty()[_m]) || Mem[T.Started__DEVICE_EXTENSION][_m] == old(Mem)[T.Started__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.GrandMaster__GLOBALS] only for: __set_empty, __set_empty
+ensures (Subset(Empty(), Union(Union(Empty(), Empty()), Empty())) && (forall _m:int :: {Mem[T.GrandMaster__GLOBALS][_m]} (Empty()[_m]) || (Empty()[_m]) || Mem[T.GrandMaster__GLOBALS][_m] == old(Mem)[T.GrandMaster__GLOBALS][_m]));
+//TAG: updated memory locations at Mem[T.P_DEVICE_OBJECT] only for: __set_empty, __set_empty
+ensures (Subset(Empty(), Union(Union(Empty(), Empty()), Empty())) && (forall _m:int :: {Mem[T.P_DEVICE_OBJECT][_m]} (Empty()[_m]) || (Empty()[_m]) || Mem[T.P_DEVICE_OBJECT][_m] == old(Mem)[T.P_DEVICE_OBJECT][_m]));
+
+//TAG: havoc memory locations by default
+modifies Mem;
+
+
+procedure __PREfastPagedCode();
+
+//TAG: ensures __preserves_mem
+ensures(Mem == old(Mem));
+//TAG: ensures __preserves_resource("DEV_OBJ_INIT") && __preserves_resource("DEV_EXTN")
+ensures((Res_DEV_OBJ_INIT == old(Res_DEV_OBJ_INIT)) && (Res_DEV_EXTN == old(Res_DEV_EXTN)));
+
+modifies Res_DEVICE_STACK;
+
+//TAG: net change in resource DEVICE_STACK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEVICE_STACK[r]} (Empty()[r]) || old(Res_DEVICE_STACK)[r] == Res_DEVICE_STACK[r]));
+modifies Res_DEV_EXTN;
+
+//TAG: net change in resource DEV_EXTN only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_EXTN[r]} (Empty()[r]) || old(Res_DEV_EXTN)[r] == Res_DEV_EXTN[r]));
+modifies Res_DEV_OBJ_INIT;
+
+//TAG: net change in resource DEV_OBJ_INIT only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_OBJ_INIT[r]} (Empty()[r]) || old(Res_DEV_OBJ_INIT)[r] == Res_DEV_OBJ_INIT[r]));
+modifies Res_SPIN_LOCK;
+
+//TAG: net change in resource SPIN_LOCK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_SPIN_LOCK[r]} (Empty()[r]) || old(Res_SPIN_LOCK)[r] == Res_SPIN_LOCK[r]));
+//TAG: updated memory locations at Mem[T.MinorFunction__IO_STACK_LOCATION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.MinorFunction__IO_STACK_LOCATION][_m]} (Empty()[_m]) || Mem[T.MinorFunction__IO_STACK_LOCATION][_m] == old(Mem)[T.MinorFunction__IO_STACK_LOCATION][_m]));
+//TAG: updated memory locations at Mem[T.CurrentStackLocation___unnamed_4_f19b65c1] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.CurrentStackLocation___unnamed_4_f19b65c1][_m]} (Empty()[_m]) || Mem[T.CurrentStackLocation___unnamed_4_f19b65c1][_m] == old(Mem)[T.CurrentStackLocation___unnamed_4_f19b65c1][_m]));
+//TAG: updated memory locations at Mem[T.DeviceExtension__DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.DeviceExtension__DEVICE_OBJECT][_m] == old(Mem)[T.DeviceExtension__DEVICE_OBJECT][_m]));
+//TAG: updated memory locations at Mem[T.Self__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Self__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Self__DEVICE_EXTENSION][_m] == old(Mem)[T.Self__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.Started__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Started__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Started__DEVICE_EXTENSION][_m] == old(Mem)[T.Started__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.GrandMaster__GLOBALS] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.GrandMaster__GLOBALS][_m]} (Empty()[_m]) || Mem[T.GrandMaster__GLOBALS][_m] == old(Mem)[T.GrandMaster__GLOBALS][_m]));
+//TAG: updated memory locations at Mem[T.P_DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.P_DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.P_DEVICE_OBJECT][_m] == old(Mem)[T.P_DEVICE_OBJECT][_m]));
+
+//TAG: havoc memory locations by default
+modifies Mem;
+
+
+procedure KeyboardClassUnload($DriverObject$1$2966.24$KeyboardClassUnload$41:int)
+
+//TAG: requires __pforall(_H_x, (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension), __inv_resource("DEV_OBJ_INIT", 1), ((struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension))->Self == _H_x && __resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension)) == 1)
+requires((forall _H_x:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)]} Inverse(Res_DEV_OBJ_INIT,1)[_H_x] ==> ((Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)])] == _H_x) && (Res_DEV_EXTN[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)]] == 1))));
+//TAG: requires __pforall(_H_z, _H_z->Self, __inv_resource("DEV_EXTN", 1), __resource("DEV_OBJ_INIT", _H_z->Self) == 1 && (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)(_H_z->Self))->DeviceExtension) == _H_z) && __forall(_H_z, __inv_resource("DEV_EXTN", 1), 1)
+requires(((forall _H_z:int :: {Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)]} Inverse(Res_DEV_EXTN,1)[_H_z] ==> ((Res_DEV_OBJ_INIT[Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)]] == 1) && (Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)])] == _H_z)))) && ((Subset(Empty(), Inverse(Res_DEV_EXTN,1)) && (forall _H_z : int :: {Inverse(Res_DEV_EXTN,1)[_H_z]} (Inverse(Res_DEV_EXTN,1)[_H_z]) ==> (true)))));
+//TAG: ensures __pforall(_H_x, (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension), __inv_resource("DEV_OBJ_INIT", 1), ((struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension))->Self == _H_x && __resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension)) == 1)
+ensures((forall _H_x:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)]} Inverse(Res_DEV_OBJ_INIT,1)[_H_x] ==> ((Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)])] == _H_x) && (Res_DEV_EXTN[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)]] == 1))));
+//TAG: ensures __pforall(_H_z, _H_z->Self, __inv_resource("DEV_EXTN", 1), __resource("DEV_OBJ_INIT", _H_z->Self) == 1 && (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)(_H_z->Self))->DeviceExtension) == _H_z) && __forall(_H_z, __inv_resource("DEV_EXTN", 1), 1)
+ensures(((forall _H_z:int :: {Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)]} Inverse(Res_DEV_EXTN,1)[_H_z] ==> ((Res_DEV_OBJ_INIT[Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)]] == 1) && (Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)])] == _H_z)))) && ((Subset(Empty(), Inverse(Res_DEV_EXTN,1)) && (forall _H_z : int :: {Inverse(Res_DEV_EXTN,1)[_H_z]} (Inverse(Res_DEV_EXTN,1)[_H_z]) ==> (true)))));
+//TAG: requires 1 ==> (Globals.GrandMaster != (void *)0 ==> __resource("DEV_EXTN", Globals.GrandMaster) == 1)
+requires((true) ==> ((Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)] != 0) ==> (Res_DEV_EXTN[Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)]] == 1)));
+//TAG: requires 1 ==> __setin(&Globals.LegacyDeviceList, __btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList))
+requires((true) ==> (ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[LegacyDeviceList__GLOBALS(Globals)]));
+//TAG: requires 1 ==> __forall(_H_y, __btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList), _H_y == &Globals.LegacyDeviceList || __resource("DEV_EXTN", CONTAINING_RECORD(_H_y, struct _DEVICE_EXTENSION , Link)) == 1)
+requires((true) ==> ((Subset(Empty(), ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))) && (forall _H_y : int :: {ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[_H_y]} (ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[_H_y]) ==> ((_H_y == LegacyDeviceList__GLOBALS(Globals)) || (Res_DEV_EXTN[MINUS_LEFT_PTR(_H_y, 1, Link__DEVICE_EXTENSION(0))] == 1))))));
+//TAG: requires 1 ==> !__setin(&Globals.GrandMaster->Link, __setminus(__btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList), __set(&Globals.LegacyDeviceList)))
+requires((true) ==> (!(Difference(ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals)), Singleton(LegacyDeviceList__GLOBALS(Globals)))[Link__DEVICE_EXTENSION(Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)])])));
+modifies alloc;
+free ensures(forall f:int :: {alloc[Base(f)]} old(alloc)[Base(f)] == UNALLOCATED || old(alloc)[Base(f)] == alloc[Base(f)]);
+
+modifies Res_DEVICE_STACK;
+
+//TAG: net change in resource DEVICE_STACK only for:
+modifies Res_DEV_EXTN;
+
+//TAG: net change in resource DEV_EXTN only for:
+modifies Res_DEV_OBJ_INIT;
+
+//TAG: net change in resource DEV_OBJ_INIT only for:
+modifies Res_SPIN_LOCK;
+
+//TAG: net change in resource SPIN_LOCK only for:
+
+//TAG: havoc memory locations by default
+modifies Mem;
+{
+var havoc_stringTemp:int;
+var condVal:int;
+var $DriverObject$1$2966.24$KeyboardClassUnload$4 : int;
+var $IoAllocateIrp.arg.1$9$ : int;
+var $KbdDebugPrint.arg.2$1$ : int;
+var $KbdDebugPrint.arg.2$19$ : int;
+var $RtlAssert.arg.1$14$ : int;
+var $RtlAssert.arg.1$16$ : int;
+var $RtlAssert.arg.1$18$ : int;
+var $RtlAssert.arg.1$3$ : int;
+var $RtlAssert.arg.1$5$ : int;
+var $RtlAssert.arg.1$7$ : int;
+var $RtlAssert.arg.2$13$ : int;
+var $RtlAssert.arg.2$15$ : int;
+var $RtlAssert.arg.2$17$ : int;
+var $RtlAssert.arg.2$2$ : int;
+var $RtlAssert.arg.2$4$ : int;
+var $RtlAssert.arg.2$6$ : int;
+var $data$3$2989.22$KeyboardClassUnload$4 : int;
+var $enabled$6$3006.16$KeyboardClassUnload$4 : int;
+var $entry$2$2988.16$KeyboardClassUnload$4 : int;
+var $file$7$3007.21$KeyboardClassUnload$4 : int;
+var $i$8$3075.14$KeyboardClassUnload$4 : int;
+var $irp$5$2991.9$KeyboardClassUnload$4 : int;
+var $port$4$2990.10$KeyboardClassUnload$4 : int;
+var $result.IoAllocateIrp$3031.31$8$ : int;
+var $result.KbdEnableDisablePort$3033.37$10$ : int;
+var $result.ObfDereferenceObject$3044.12$11$ : int;
+var $result.RemoveEntryList$3055.24$12$ : int;
+var tempBoogie0:int;
+var tempBoogie1:int;
+var tempBoogie2:int;
+var tempBoogie3:int;
+var tempBoogie4:int;
+var tempBoogie5:int;
+var tempBoogie6:int;
+var tempBoogie7:int;
+var tempBoogie8:int;
+var tempBoogie9:int;
+var tempBoogie10:int;
+var tempBoogie11:int;
+var tempBoogie12:int;
+var tempBoogie13:int;
+var tempBoogie14:int;
+var tempBoogie15:int;
+var tempBoogie16:int;
+var tempBoogie17:int;
+var tempBoogie18:int;
+var tempBoogie19:int;
+var LOOP_15_alloc:[int]name;
+var LOOP_15_Mem:[name][int]int;
+var LOOP_15_Res_DEVICE_STACK:[int]int;
+var LOOP_15_Res_DEV_EXTN:[int]int;
+var LOOP_15_Res_DEV_OBJ_INIT:[int]int;
+var LOOP_15_Res_SPIN_LOCK:[int]int;
+var LOOP_108_alloc:[int]name;
+var LOOP_108_Mem:[name][int]int;
+var LOOP_108_Res_DEVICE_STACK:[int]int;
+var LOOP_108_Res_DEV_EXTN:[int]int;
+var LOOP_108_Res_DEV_OBJ_INIT:[int]int;
+var LOOP_108_Res_SPIN_LOCK:[int]int;
+
+
+start:
+
+assume (alloc[$DriverObject$1$2966.24$KeyboardClassUnload$41] != UNALLOCATED);
+call $file$7$3007.21$KeyboardClassUnload$4 := __HAVOC_malloc(4);
+$DriverObject$1$2966.24$KeyboardClassUnload$4 := $DriverObject$1$2966.24$KeyboardClassUnload$41;
+goto label_3;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3088)
+label_1:
+call __HAVOC_free($file$7$3007.21$KeyboardClassUnload$4);
+assume (forall m:int:: {Res_DEVICE_STACK[m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Res_DEVICE_STACK[m] == old(Res_DEVICE_STACK)[m]);
+assume (forall m:int:: {Res_DEV_EXTN[m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Res_DEV_EXTN[m] == old(Res_DEV_EXTN)[m]);
+assume (forall m:int:: {Res_DEV_OBJ_INIT[m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Res_DEV_OBJ_INIT[m] == old(Res_DEV_OBJ_INIT)[m]);
+assume (forall m:int:: {Res_SPIN_LOCK[m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Res_SPIN_LOCK[m] == old(Res_SPIN_LOCK)[m]);
+assume (forall m:int :: {Mem[T.A11CHAR][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.A11CHAR][m] == old(Mem[T.A11CHAR])[m]);
+assume (forall m:int :: {Mem[T.A19CHAR][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.A19CHAR][m] == old(Mem[T.A19CHAR])[m]);
+assume (forall m:int :: {Mem[T.A36CHAR][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.A36CHAR][m] == old(Mem[T.A36CHAR])[m]);
+assume (forall m:int :: {Mem[T.A37CHAR][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.A37CHAR][m] == old(Mem[T.A37CHAR])[m]);
+assume (forall m:int :: {Mem[T.A39CHAR][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.A39CHAR][m] == old(Mem[T.A39CHAR])[m]);
+assume (forall m:int :: {Mem[T.A43CHAR][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.A43CHAR][m] == old(Mem[T.A43CHAR])[m]);
+assume (forall m:int :: {Mem[T.A74CHAR][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.A74CHAR][m] == old(Mem[T.A74CHAR])[m]);
+assume (forall m:int :: {Mem[T.AssocClassList__GLOBALS][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.AssocClassList__GLOBALS][m] == old(Mem[T.AssocClassList__GLOBALS])[m]);
+assume (forall m:int :: {Mem[T.Buffer__UNICODE_STRING][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.Buffer__UNICODE_STRING][m] == old(Mem[T.Buffer__UNICODE_STRING])[m]);
+assume (forall m:int :: {Mem[T.CurrentStackLocation___unnamed_4_f19b65c1][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.CurrentStackLocation___unnamed_4_f19b65c1][m] == old(Mem[T.CurrentStackLocation___unnamed_4_f19b65c1])[m]);
+assume (forall m:int :: {Mem[T.DataIn__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.DataIn__DEVICE_EXTENSION][m] == old(Mem[T.DataIn__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.DataOut__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.DataOut__DEVICE_EXTENSION][m] == old(Mem[T.DataOut__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.DeviceExtension__DEVICE_OBJECT][m] == old(Mem[T.DeviceExtension__DEVICE_OBJECT])[m]);
+assume (forall m:int :: {Mem[T.Enabled__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.Enabled__DEVICE_EXTENSION][m] == old(Mem[T.Enabled__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.Enabled__PORT][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.Enabled__PORT][m] == old(Mem[T.Enabled__PORT])[m]);
+assume (forall m:int :: {Mem[T.File__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.File__DEVICE_EXTENSION][m] == old(Mem[T.File__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.File__PORT][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.File__PORT][m] == old(Mem[T.File__PORT])[m]);
+assume (forall m:int :: {Mem[T.Flink__LIST_ENTRY][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.Flink__LIST_ENTRY][m] == old(Mem[T.Flink__LIST_ENTRY])[m]);
+assume (forall m:int :: {Mem[T.Free__PORT][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.Free__PORT][m] == old(Mem[T.Free__PORT])[m]);
+assume (forall m:int :: {Mem[T.GrandMaster__GLOBALS][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.GrandMaster__GLOBALS][m] == old(Mem[T.GrandMaster__GLOBALS])[m]);
+assume (forall m:int :: {Mem[T.INT4][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.INT4][m] == old(Mem[T.INT4])[m]);
+assume (forall m:int :: {Mem[T.InputData__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.InputData__DEVICE_EXTENSION][m] == old(Mem[T.InputData__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.LegacyDeviceList__GLOBALS][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.LegacyDeviceList__GLOBALS][m] == old(Mem[T.LegacyDeviceList__GLOBALS])[m]);
+assume (forall m:int :: {Mem[T.Link__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.Link__DEVICE_EXTENSION][m] == old(Mem[T.Link__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.MinorFunction__IO_STACK_LOCATION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.MinorFunction__IO_STACK_LOCATION][m] == old(Mem[T.MinorFunction__IO_STACK_LOCATION])[m]);
+assume (forall m:int :: {Mem[T.NumAssocClass__GLOBALS][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.NumAssocClass__GLOBALS][m] == old(Mem[T.NumAssocClass__GLOBALS])[m]);
+assume (forall m:int :: {Mem[T.PCHAR][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.PCHAR][m] == old(Mem[T.PCHAR])[m]);
+assume (forall m:int :: {Mem[T.PP_FILE_OBJECT][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.PP_FILE_OBJECT][m] == old(Mem[T.PP_FILE_OBJECT])[m]);
+assume (forall m:int :: {Mem[T.PVOID][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.PVOID][m] == old(Mem[T.PVOID])[m]);
+assume (forall m:int :: {Mem[T.P_DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.P_DEVICE_EXTENSION][m] == old(Mem[T.P_DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.P_DEVICE_OBJECT][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.P_DEVICE_OBJECT][m] == old(Mem[T.P_DEVICE_OBJECT])[m]);
+assume (forall m:int :: {Mem[T.P_FILE_OBJECT][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.P_FILE_OBJECT][m] == old(Mem[T.P_FILE_OBJECT])[m]);
+assume (forall m:int :: {Mem[T.P_IRP][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.P_IRP][m] == old(Mem[T.P_IRP])[m]);
+assume (forall m:int :: {Mem[T.P_KEYBOARD_INPUT_DATA][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.P_KEYBOARD_INPUT_DATA][m] == old(Mem[T.P_KEYBOARD_INPUT_DATA])[m]);
+assume (forall m:int :: {Mem[T.P_LIST_ENTRY][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.P_LIST_ENTRY][m] == old(Mem[T.P_LIST_ENTRY])[m]);
+assume (forall m:int :: {Mem[T.P_PORT][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.P_PORT][m] == old(Mem[T.P_PORT])[m]);
+assume (forall m:int :: {Mem[T.PnP__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.PnP__DEVICE_EXTENSION][m] == old(Mem[T.PnP__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.Port__PORT][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.Port__PORT][m] == old(Mem[T.Port__PORT])[m]);
+assume (forall m:int :: {Mem[T.RegistryPath__GLOBALS][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.RegistryPath__GLOBALS][m] == old(Mem[T.RegistryPath__GLOBALS])[m]);
+assume (forall m:int :: {Mem[T.Self__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.Self__DEVICE_EXTENSION][m] == old(Mem[T.Self__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.StackSize__DEVICE_OBJECT][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.StackSize__DEVICE_OBJECT][m] == old(Mem[T.StackSize__DEVICE_OBJECT])[m]);
+assume (forall m:int :: {Mem[T.Started__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.Started__DEVICE_EXTENSION][m] == old(Mem[T.Started__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.TopPort__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.TopPort__DEVICE_EXTENSION][m] == old(Mem[T.TopPort__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.UCHAR][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.UCHAR][m] == old(Mem[T.UCHAR])[m]);
+assume (forall m:int :: {Mem[T.UINT4][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.UINT4][m] == old(Mem[T.UINT4])[m]);
+assume (forall m:int :: {Mem[T.UnitId__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.UnitId__DEVICE_EXTENSION][m] == old(Mem[T.UnitId__DEVICE_EXTENSION])[m]);
+return;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3088)
+label_2:
+assume false;
+return;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(2988)
+label_3:
+goto label_4;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(2989)
+label_4:
+goto label_5;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(2990)
+label_5:
+goto label_6;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(2991)
+label_6:
+goto label_7;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(2995)
+label_7:
+call __PREfastPagedCode ();
+goto label_13;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(2997)
+label_10:
+// skip KbdDebugPrint
+goto label_14;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(2997)
+label_13:
+call havoc_stringTemp := __HAVOC_malloc(1);
+$KbdDebugPrint.arg.2$1$ := havoc_stringTemp ;
+goto label_10;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3002)
+label_14:
+$entry$2$2988.16$KeyboardClassUnload$4 := Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))] ;
+goto label_15;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3003)
+label_15:
+// loop entry initialization...
+LOOP_15_alloc := alloc;
+LOOP_15_Mem := Mem;
+LOOP_15_Res_DEVICE_STACK := Res_DEVICE_STACK;
+LOOP_15_Res_DEV_EXTN := Res_DEV_EXTN;
+LOOP_15_Res_DEV_OBJ_INIT := Res_DEV_OBJ_INIT;
+LOOP_15_Res_SPIN_LOCK := Res_SPIN_LOCK;
+goto label_15_head;
+
+
+label_15_head:
+// loop head assertions...
+//TAG: requires __pforall(_H_x, (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension), __inv_resource("DEV_OBJ_INIT", 1), ((struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension))->Self == _H_x && __resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension)) == 1)
+assert((forall _H_x:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)]} Inverse(Res_DEV_OBJ_INIT,1)[_H_x] ==> ((Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)])] == _H_x) && (Res_DEV_EXTN[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)]] == 1))));
+//TAG: requires __pforall(_H_z, _H_z->Self, __inv_resource("DEV_EXTN", 1), __resource("DEV_OBJ_INIT", _H_z->Self) == 1 && (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)(_H_z->Self))->DeviceExtension) == _H_z)
+assert((forall _H_z:int :: {Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)]} Inverse(Res_DEV_EXTN,1)[_H_z] ==> ((Res_DEV_OBJ_INIT[Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)]] == 1) && (Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)])] == _H_z))));
+//TAG: requires __forall(_H_z, __inv_resource("DEV_EXTN", 1), 1)
+assert((Subset(Empty(), Inverse(Res_DEV_EXTN,1)) && (forall _H_z : int :: {Inverse(Res_DEV_EXTN,1)[_H_z]} (Inverse(Res_DEV_EXTN,1)[_H_z]) ==> (true))));
+//TAG: requires 1 ==> (Globals.GrandMaster != (void *)0 ==> __resource("DEV_EXTN", Globals.GrandMaster) == 1)
+assert((true) ==> ((Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)] != 0) ==> (Res_DEV_EXTN[Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)]] == 1)));
+//TAG: requires 1 ==> __setin(&Globals.LegacyDeviceList, __btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList))
+assert((true) ==> (ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[LegacyDeviceList__GLOBALS(Globals)]));
+//TAG: requires 1 ==> __forall(_H_y, __btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList), _H_y == &Globals.LegacyDeviceList || __resource("DEV_EXTN", CONTAINING_RECORD(_H_y, struct _DEVICE_EXTENSION , Link)) == 1)
+assert((true) ==> ((Subset(Empty(), ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))) && (forall _H_y : int :: {ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[_H_y]} (ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[_H_y]) ==> ((_H_y == LegacyDeviceList__GLOBALS(Globals)) || (Res_DEV_EXTN[MINUS_LEFT_PTR(_H_y, 1, Link__DEVICE_EXTENSION(0))] == 1))))));
+//TAG: requires 1 ==> !__setin(&Globals.GrandMaster->Link, __setminus(__btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList), __set(&Globals.LegacyDeviceList)))
+assert((true) ==> (!(Difference(ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals)), Singleton(LegacyDeviceList__GLOBALS(Globals)))[Link__DEVICE_EXTENSION(Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)])])));
+//TAG: requires __setin(entry, __btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList))
+assert(ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[$entry$2$2988.16$KeyboardClassUnload$4]);
+assume(forall f:int :: {alloc[Base(f)]} LOOP_15_alloc[Base(f)] == UNALLOCATED || LOOP_15_alloc[Base(f)] == alloc[Base(f)]);
+
+
+//TAG: net change in resource DEVICE_STACK only for: __set_empty
+assert (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEVICE_STACK[r]} (Empty()[r]) || LOOP_15_Res_DEVICE_STACK[r] == Res_DEVICE_STACK[r]));
+
+//TAG: net change in resource DEV_EXTN only for: __set_true
+assert (Subset(Empty(), Union(Empty(), SetTrue())) && (forall r:int :: {Res_DEV_EXTN[r]} (SetTrue()[r]) || LOOP_15_Res_DEV_EXTN[r] == Res_DEV_EXTN[r]));
+
+//TAG: net change in resource DEV_OBJ_INIT only for: __set_true
+assert (Subset(Empty(), Union(Empty(), SetTrue())) && (forall r:int :: {Res_DEV_OBJ_INIT[r]} (SetTrue()[r]) || LOOP_15_Res_DEV_OBJ_INIT[r] == Res_DEV_OBJ_INIT[r]));
+
+//TAG: net change in resource SPIN_LOCK only for: __set_empty
+assert (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_SPIN_LOCK[r]} (Empty()[r]) || LOOP_15_Res_SPIN_LOCK[r] == Res_SPIN_LOCK[r]));
+//TAG: updated memory locations at Mem[T.MinorFunction__IO_STACK_LOCATION] only for: __set_empty
+assert (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.MinorFunction__IO_STACK_LOCATION][_m]} (Empty()[_m]) || Mem[T.MinorFunction__IO_STACK_LOCATION][_m] == LOOP_15_Mem[T.MinorFunction__IO_STACK_LOCATION][_m]));
+//TAG: updated memory locations at Mem[T.CurrentStackLocation___unnamed_4_f19b65c1] only for: __set_empty
+assert (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.CurrentStackLocation___unnamed_4_f19b65c1][_m]} (Empty()[_m]) || Mem[T.CurrentStackLocation___unnamed_4_f19b65c1][_m] == LOOP_15_Mem[T.CurrentStackLocation___unnamed_4_f19b65c1][_m]));
+//TAG: updated memory locations at Mem[T.DeviceExtension__DEVICE_OBJECT] only for: __set_empty
+assert (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.DeviceExtension__DEVICE_OBJECT][_m] == LOOP_15_Mem[T.DeviceExtension__DEVICE_OBJECT][_m]));
+//TAG: updated memory locations at Mem[T.Self__DEVICE_EXTENSION] only for: __set_empty
+assert (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Self__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Self__DEVICE_EXTENSION][_m] == LOOP_15_Mem[T.Self__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.Started__DEVICE_EXTENSION] only for: __set_empty
+assert (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Started__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Started__DEVICE_EXTENSION][_m] == LOOP_15_Mem[T.Started__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.GrandMaster__GLOBALS] only for: __set_empty
+assert (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.GrandMaster__GLOBALS][_m]} (Empty()[_m]) || Mem[T.GrandMaster__GLOBALS][_m] == LOOP_15_Mem[T.GrandMaster__GLOBALS][_m]));
+//TAG: updated memory locations at Mem[T.P_DEVICE_OBJECT] only for: __set_empty
+assert (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.P_DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.P_DEVICE_OBJECT][_m] == LOOP_15_Mem[T.P_DEVICE_OBJECT][_m]));
+
+// end loop head assertions
+
+goto label_15_true , label_15_false ;
+
+
+label_15_true :
+assume ($entry$2$2988.16$KeyboardClassUnload$4 != LegacyDeviceList__GLOBALS(Globals));
+goto label_16;
+
+
+label_15_false :
+assume !($entry$2$2988.16$KeyboardClassUnload$4 != LegacyDeviceList__GLOBALS(Globals));
+goto label_85;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3006)
+label_16:
+goto label_17;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3006)
+label_17:
+$enabled$6$3006.16$KeyboardClassUnload$4 := 0 ;
+goto label_18;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3007)
+label_18:
+goto label_19;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3007)
+label_19:
+Mem[T.P_FILE_OBJECT] := Mem[T.P_FILE_OBJECT][$file$7$3007.21$KeyboardClassUnload$4 := 0];
+goto label_20;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3009)
+label_20:
+$data$3$2989.22$KeyboardClassUnload$4 := MINUS_LEFT_PTR($entry$2$2988.16$KeyboardClassUnload$4, 1, 272) ;
+goto label_21;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3010)
+label_21:
+goto label_21_true , label_21_false ;
+
+
+label_21_true :
+assume (Mem[T.PnP__DEVICE_EXTENSION][PnP__DEVICE_EXTENSION($data$3$2989.22$KeyboardClassUnload$4)] != 0);
+goto label_25;
+
+
+label_21_false :
+assume (Mem[T.PnP__DEVICE_EXTENSION][PnP__DEVICE_EXTENSION($data$3$2989.22$KeyboardClassUnload$4)] == 0);
+goto label_27;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3010)
+label_22:
+// skip RtlAssert
+goto label_27;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3010)
+label_25:
+call havoc_stringTemp := __HAVOC_malloc(1);
+$RtlAssert.arg.2$2$ := havoc_stringTemp ;
+goto label_26;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3010)
+label_26:
+call havoc_stringTemp := __HAVOC_malloc(1);
+$RtlAssert.arg.1$3$ := havoc_stringTemp ;
+goto label_22;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3012)
+label_27:
+goto label_27_true , label_27_false ;
+
+
+label_27_true :
+assume (Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)] != 0);
+goto label_28;
+
+
+label_27_false :
+assume (Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)] == 0);
+goto label_40;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3013)
+label_28:
+$port$4$2990.10$KeyboardClassUnload$4 := PLUS(Mem[T.AssocClassList__GLOBALS][AssocClassList__GLOBALS(Globals)], 12, Mem[T.UnitId__DEVICE_EXTENSION][UnitId__DEVICE_EXTENSION($data$3$2989.22$KeyboardClassUnload$4)]) ;
+goto label_29;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3014)
+label_29:
+goto label_29_true , label_29_false ;
+
+
+label_29_true :
+assume (Mem[T.Port__PORT][Port__PORT($port$4$2990.10$KeyboardClassUnload$4)] == $data$3$2989.22$KeyboardClassUnload$4);
+goto label_35;
+
+
+label_29_false :
+assume !(Mem[T.Port__PORT][Port__PORT($port$4$2990.10$KeyboardClassUnload$4)] == $data$3$2989.22$KeyboardClassUnload$4);
+goto label_33;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3014)
+label_30:
+// skip RtlAssert
+goto label_35;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3014)
+label_33:
+call havoc_stringTemp := __HAVOC_malloc(1);
+$RtlAssert.arg.2$4$ := havoc_stringTemp ;
+goto label_34;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3014)
+label_34:
+call havoc_stringTemp := __HAVOC_malloc(1);
+$RtlAssert.arg.1$5$ := havoc_stringTemp ;
+goto label_30;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3016)
+label_35:
+$enabled$6$3006.16$KeyboardClassUnload$4 := Mem[T.Enabled__PORT][Enabled__PORT($port$4$2990.10$KeyboardClassUnload$4)] ;
+goto label_36;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3017)
+label_36:
+Mem[T.P_FILE_OBJECT] := Mem[T.P_FILE_OBJECT][$file$7$3007.21$KeyboardClassUnload$4 := Mem[T.File__PORT][File__PORT($port$4$2990.10$KeyboardClassUnload$4)]];
+goto label_37;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3019)
+label_37:
+Mem[T.Enabled__PORT] := Mem[T.Enabled__PORT][Enabled__PORT($port$4$2990.10$KeyboardClassUnload$4) := 0];
+goto label_38;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3020)
+label_38:
+Mem[T.File__PORT] := Mem[T.File__PORT][File__PORT($port$4$2990.10$KeyboardClassUnload$4) := 0];
+goto label_39;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3021)
+label_39:
+Mem[T.Free__PORT] := Mem[T.Free__PORT][Free__PORT($port$4$2990.10$KeyboardClassUnload$4) := 1];
+goto label_49;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3024)
+label_40:
+$enabled$6$3006.16$KeyboardClassUnload$4 := Mem[T.Enabled__DEVICE_EXTENSION][Enabled__DEVICE_EXTENSION($data$3$2989.22$KeyboardClassUnload$4)] ;
+goto label_41;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3025)
+label_41:
+Mem[T.P_FILE_OBJECT] := Mem[T.P_FILE_OBJECT][$file$7$3007.21$KeyboardClassUnload$4 := Mem[T.File__DEVICE_EXTENSION][File__DEVICE_EXTENSION($data$3$2989.22$KeyboardClassUnload$4)]];
+goto label_42;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3026)
+label_42:
+goto label_42_true , label_42_false ;
+
+
+label_42_true :
+assume (Mem[T.File__DEVICE_EXTENSION][File__DEVICE_EXTENSION($data$3$2989.22$KeyboardClassUnload$4)] != 0);
+goto label_48;
+
+
+label_42_false :
+assume (Mem[T.File__DEVICE_EXTENSION][File__DEVICE_EXTENSION($data$3$2989.22$KeyboardClassUnload$4)] == 0);
+goto label_46;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3026)
+label_43:
+// skip RtlAssert
+goto label_48;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3026)
+label_46:
+call havoc_stringTemp := __HAVOC_malloc(1);
+$RtlAssert.arg.2$6$ := havoc_stringTemp ;
+goto label_47;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3026)
+label_47:
+call havoc_stringTemp := __HAVOC_malloc(1);
+$RtlAssert.arg.1$7$ := havoc_stringTemp ;
+goto label_43;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3027)
+label_48:
+Mem[T.Enabled__DEVICE_EXTENSION] := Mem[T.Enabled__DEVICE_EXTENSION][Enabled__DEVICE_EXTENSION($data$3$2989.22$KeyboardClassUnload$4) := 0];
+goto label_49;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3030)
+label_49:
+goto label_49_true , label_49_false ;
+
+
+label_49_true :
+assume ($enabled$6$3006.16$KeyboardClassUnload$4 != 0);
+goto label_53;
+
+
+label_49_false :
+assume ($enabled$6$3006.16$KeyboardClassUnload$4 == 0);
+goto label_62;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3031)
+label_50:
+call $result.IoAllocateIrp$3031.31$8$ := IoAllocateIrp ($IoAllocateIrp.arg.1$9$, 0);
+goto label_54;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3031)
+label_53:
+$IoAllocateIrp.arg.1$9$ := PLUS(Mem[T.StackSize__DEVICE_OBJECT][StackSize__DEVICE_OBJECT(Mem[T.TopPort__DEVICE_EXTENSION][TopPort__DEVICE_EXTENSION($data$3$2989.22$KeyboardClassUnload$4)])], 1, 1) ;
+goto label_50;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3031)
+label_54:
+$irp$5$2991.9$KeyboardClassUnload$4 := $result.IoAllocateIrp$3031.31$8$ ;
+goto label_55;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3032)
+label_55:
+goto label_55_true , label_55_false ;
+
+
+label_55_true :
+assume ($irp$5$2991.9$KeyboardClassUnload$4 != 0);
+goto label_56;
+
+
+label_55_false :
+assume ($irp$5$2991.9$KeyboardClassUnload$4 == 0);
+goto label_62;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3033)
+label_56:
+call $result.KbdEnableDisablePort$3033.37$10$ := KbdEnableDisablePort (0, $irp$5$2991.9$KeyboardClassUnload$4, $data$3$2989.22$KeyboardClassUnload$4, $file$7$3007.21$KeyboardClassUnload$4);
+goto label_59;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3034)
+label_59:
+call IoFreeIrp ($irp$5$2991.9$KeyboardClassUnload$4);
+goto label_62;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3043)
+label_62:
+goto label_62_true , label_62_false ;
+
+
+label_62_true :
+assume (Mem[T.P_FILE_OBJECT][$file$7$3007.21$KeyboardClassUnload$4] != 0);
+goto label_63;
+
+
+label_62_false :
+assume (Mem[T.P_FILE_OBJECT][$file$7$3007.21$KeyboardClassUnload$4] == 0);
+goto label_66;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3044)
+label_63:
+call $result.ObfDereferenceObject$3044.12$11$ := ObfDereferenceObject (Mem[T.P_FILE_OBJECT][$file$7$3007.21$KeyboardClassUnload$4]);
+goto label_66;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3051)
+label_66:
+goto label_66_true , label_66_false ;
+
+
+label_66_true :
+assume (Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)] != 0);
+goto label_70;
+
+
+label_66_false :
+assume (Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)] == 0);
+goto label_67;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3052)
+label_67:
+call KeyboardClassCleanupQueue (Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION($data$3$2989.22$KeyboardClassUnload$4)], $data$3$2989.22$KeyboardClassUnload$4, 0);
+goto label_70;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3055)
+label_70:
+call $result.RemoveEntryList$3055.24$12$ := RemoveEntryList (Link__DEVICE_EXTENSION($data$3$2989.22$KeyboardClassUnload$4));
+goto label_73;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3056)
+label_73:
+$entry$2$2988.16$KeyboardClassUnload$4 := Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY($entry$2$2988.16$KeyboardClassUnload$4)] ;
+goto label_74;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3058)
+label_74:
+goto label_74_true , label_74_false ;
+
+
+label_74_true :
+assume (Mem[T.InputData__DEVICE_EXTENSION][InputData__DEVICE_EXTENSION($data$3$2989.22$KeyboardClassUnload$4)] != 0);
+goto label_75;
+
+
+label_74_false :
+assume (Mem[T.InputData__DEVICE_EXTENSION][InputData__DEVICE_EXTENSION($data$3$2989.22$KeyboardClassUnload$4)] == 0);
+goto label_81;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3058)
+label_75:
+call ExFreePoolWithTag (Mem[T.InputData__DEVICE_EXTENSION][InputData__DEVICE_EXTENSION($data$3$2989.22$KeyboardClassUnload$4)], 0);
+goto label_78;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3058)
+label_78:
+Mem[T.DataOut__DEVICE_EXTENSION] := Mem[T.DataOut__DEVICE_EXTENSION][DataOut__DEVICE_EXTENSION($data$3$2989.22$KeyboardClassUnload$4) := 0];
+goto label_79;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3058)
+label_79:
+Mem[T.DataIn__DEVICE_EXTENSION] := Mem[T.DataIn__DEVICE_EXTENSION][DataIn__DEVICE_EXTENSION($data$3$2989.22$KeyboardClassUnload$4) := Mem[T.DataOut__DEVICE_EXTENSION][DataOut__DEVICE_EXTENSION($data$3$2989.22$KeyboardClassUnload$4)]];
+goto label_80;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3058)
+label_80:
+Mem[T.InputData__DEVICE_EXTENSION] := Mem[T.InputData__DEVICE_EXTENSION][InputData__DEVICE_EXTENSION($data$3$2989.22$KeyboardClassUnload$4) := Mem[T.DataIn__DEVICE_EXTENSION][DataIn__DEVICE_EXTENSION($data$3$2989.22$KeyboardClassUnload$4)]];
+goto label_81;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3058)
+label_81:
+call IoDeleteDevice (Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION($data$3$2989.22$KeyboardClassUnload$4)]);
+goto label_84;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3058)
+label_84:
+$data$3$2989.22$KeyboardClassUnload$4 := 0 ;
+goto label_15_head;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3064)
+label_85:
+goto label_85_true , label_85_false ;
+
+
+label_85_true :
+assume (Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)] != 0);
+goto label_86;
+
+
+label_85_false :
+assume (Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)] == 0);
+goto label_102;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3065)
+label_86:
+$data$3$2989.22$KeyboardClassUnload$4 := Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)] ;
+goto label_87;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3066)
+label_87:
+Mem[T.GrandMaster__GLOBALS] := Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals) := 0];
+goto label_88;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3068)
+label_88:
+call KeyboardClassCleanupQueue (Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION($data$3$2989.22$KeyboardClassUnload$4)], $data$3$2989.22$KeyboardClassUnload$4, 0);
+goto label_91;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3069)
+label_91:
+goto label_91_true , label_91_false ;
+
+
+label_91_true :
+assume (Mem[T.InputData__DEVICE_EXTENSION][InputData__DEVICE_EXTENSION($data$3$2989.22$KeyboardClassUnload$4)] != 0);
+goto label_92;
+
+
+label_91_false :
+assume (Mem[T.InputData__DEVICE_EXTENSION][InputData__DEVICE_EXTENSION($data$3$2989.22$KeyboardClassUnload$4)] == 0);
+goto label_98;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3069)
+label_92:
+call ExFreePoolWithTag (Mem[T.InputData__DEVICE_EXTENSION][InputData__DEVICE_EXTENSION($data$3$2989.22$KeyboardClassUnload$4)], 0);
+goto label_95;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3069)
+label_95:
+Mem[T.DataOut__DEVICE_EXTENSION] := Mem[T.DataOut__DEVICE_EXTENSION][DataOut__DEVICE_EXTENSION($data$3$2989.22$KeyboardClassUnload$4) := 0];
+goto label_96;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3069)
+label_96:
+Mem[T.DataIn__DEVICE_EXTENSION] := Mem[T.DataIn__DEVICE_EXTENSION][DataIn__DEVICE_EXTENSION($data$3$2989.22$KeyboardClassUnload$4) := Mem[T.DataOut__DEVICE_EXTENSION][DataOut__DEVICE_EXTENSION($data$3$2989.22$KeyboardClassUnload$4)]];
+goto label_97;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3069)
+label_97:
+Mem[T.InputData__DEVICE_EXTENSION] := Mem[T.InputData__DEVICE_EXTENSION][InputData__DEVICE_EXTENSION($data$3$2989.22$KeyboardClassUnload$4) := Mem[T.DataIn__DEVICE_EXTENSION][DataIn__DEVICE_EXTENSION($data$3$2989.22$KeyboardClassUnload$4)]];
+goto label_98;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3069)
+label_98:
+call IoDeleteDevice (Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION($data$3$2989.22$KeyboardClassUnload$4)]);
+goto label_101;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3069)
+label_101:
+$data$3$2989.22$KeyboardClassUnload$4 := 0 ;
+goto label_102;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3072)
+label_102:
+call ExFreePoolWithTag (Mem[T.Buffer__UNICODE_STRING][Buffer__UNICODE_STRING(RegistryPath__GLOBALS(Globals))], 0);
+goto label_105;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3073)
+label_105:
+goto label_105_true , label_105_false ;
+
+
+label_105_true :
+assume (Mem[T.AssocClassList__GLOBALS][AssocClassList__GLOBALS(Globals)] != 0);
+goto label_106;
+
+
+label_105_false :
+assume (Mem[T.AssocClassList__GLOBALS][AssocClassList__GLOBALS(Globals)] == 0);
+goto label_134;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3075)
+label_106:
+goto label_107;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3077)
+label_107:
+$i$8$3075.14$KeyboardClassUnload$4 := 0 ;
+goto label_108;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3077)
+label_108:
+// loop entry initialization...
+LOOP_108_alloc := alloc;
+LOOP_108_Mem := Mem;
+LOOP_108_Res_DEVICE_STACK := Res_DEVICE_STACK;
+LOOP_108_Res_DEV_EXTN := Res_DEV_EXTN;
+LOOP_108_Res_DEV_OBJ_INIT := Res_DEV_OBJ_INIT;
+LOOP_108_Res_SPIN_LOCK := Res_SPIN_LOCK;
+goto label_108_head;
+
+
+label_108_head:
+// loop head assertions...
+//TAG: requires __pforall(_H_x, (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension), __inv_resource("DEV_OBJ_INIT", 1), ((struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension))->Self == _H_x && __resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension)) == 1)
+assert((forall _H_x:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)]} Inverse(Res_DEV_OBJ_INIT,1)[_H_x] ==> ((Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)])] == _H_x) && (Res_DEV_EXTN[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)]] == 1))));
+//TAG: requires __pforall(_H_z, _H_z->Self, __inv_resource("DEV_EXTN", 1), __resource("DEV_OBJ_INIT", _H_z->Self) == 1 && (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)(_H_z->Self))->DeviceExtension) == _H_z)
+assert((forall _H_z:int :: {Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)]} Inverse(Res_DEV_EXTN,1)[_H_z] ==> ((Res_DEV_OBJ_INIT[Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)]] == 1) && (Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)])] == _H_z))));
+//TAG: requires __forall(_H_z, __inv_resource("DEV_EXTN", 1), 1)
+assert((Subset(Empty(), Inverse(Res_DEV_EXTN,1)) && (forall _H_z : int :: {Inverse(Res_DEV_EXTN,1)[_H_z]} (Inverse(Res_DEV_EXTN,1)[_H_z]) ==> (true))));
+//TAG: requires 1 ==> (Globals.GrandMaster != (void *)0 ==> __resource("DEV_EXTN", Globals.GrandMaster) == 1)
+assert((true) ==> ((Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)] != 0) ==> (Res_DEV_EXTN[Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)]] == 1)));
+//TAG: requires 1 ==> __setin(&Globals.LegacyDeviceList, __btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList))
+assert((true) ==> (ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[LegacyDeviceList__GLOBALS(Globals)]));
+//TAG: requires 1 ==> __forall(_H_y, __btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList), _H_y == &Globals.LegacyDeviceList || __resource("DEV_EXTN", CONTAINING_RECORD(_H_y, struct _DEVICE_EXTENSION , Link)) == 1)
+assert((true) ==> ((Subset(Empty(), ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))) && (forall _H_y : int :: {ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[_H_y]} (ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[_H_y]) ==> ((_H_y == LegacyDeviceList__GLOBALS(Globals)) || (Res_DEV_EXTN[MINUS_LEFT_PTR(_H_y, 1, Link__DEVICE_EXTENSION(0))] == 1))))));
+//TAG: requires __preserves_resource("DEV_OBJ_INIT")
+assert(Res_DEV_OBJ_INIT == LOOP_108_Res_DEV_OBJ_INIT);
+//TAG: requires __preserves_resource("DEV_EXTN")
+assert(Res_DEV_EXTN == LOOP_108_Res_DEV_EXTN);
+//TAG: requires __preserves_field_map(__offset((*((struct _LIST_ENTRY *)0)).Flink))
+assert(Mem[T.Flink__LIST_ENTRY] == LOOP_108_Mem[T.Flink__LIST_ENTRY]);
+assume(forall f:int :: {alloc[Base(f)]} LOOP_108_alloc[Base(f)] == UNALLOCATED || LOOP_108_alloc[Base(f)] == alloc[Base(f)]);
+
+
+//TAG: net change in resource DEVICE_STACK only for: __set_empty
+assert (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEVICE_STACK[r]} (Empty()[r]) || LOOP_108_Res_DEVICE_STACK[r] == Res_DEVICE_STACK[r]));
+
+//TAG: net change in resource DEV_EXTN only for: __set_empty
+assert (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_EXTN[r]} (Empty()[r]) || LOOP_108_Res_DEV_EXTN[r] == Res_DEV_EXTN[r]));
+
+//TAG: net change in resource DEV_OBJ_INIT only for: __set_empty
+assert (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_OBJ_INIT[r]} (Empty()[r]) || LOOP_108_Res_DEV_OBJ_INIT[r] == Res_DEV_OBJ_INIT[r]));
+
+//TAG: net change in resource SPIN_LOCK only for: __set_empty
+assert (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_SPIN_LOCK[r]} (Empty()[r]) || LOOP_108_Res_SPIN_LOCK[r] == Res_SPIN_LOCK[r]));
+//TAG: updated memory locations at Mem[T.MinorFunction__IO_STACK_LOCATION] only for: __set_empty
+assert (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.MinorFunction__IO_STACK_LOCATION][_m]} (Empty()[_m]) || Mem[T.MinorFunction__IO_STACK_LOCATION][_m] == LOOP_108_Mem[T.MinorFunction__IO_STACK_LOCATION][_m]));
+//TAG: updated memory locations at Mem[T.CurrentStackLocation___unnamed_4_f19b65c1] only for: __set_empty
+assert (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.CurrentStackLocation___unnamed_4_f19b65c1][_m]} (Empty()[_m]) || Mem[T.CurrentStackLocation___unnamed_4_f19b65c1][_m] == LOOP_108_Mem[T.CurrentStackLocation___unnamed_4_f19b65c1][_m]));
+//TAG: updated memory locations at Mem[T.DeviceExtension__DEVICE_OBJECT] only for: __set_empty
+assert (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.DeviceExtension__DEVICE_OBJECT][_m] == LOOP_108_Mem[T.DeviceExtension__DEVICE_OBJECT][_m]));
+//TAG: updated memory locations at Mem[T.Self__DEVICE_EXTENSION] only for: __set_empty
+assert (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Self__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Self__DEVICE_EXTENSION][_m] == LOOP_108_Mem[T.Self__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.Started__DEVICE_EXTENSION] only for: __set_empty
+assert (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Started__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Started__DEVICE_EXTENSION][_m] == LOOP_108_Mem[T.Started__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.GrandMaster__GLOBALS] only for: __set_empty
+assert (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.GrandMaster__GLOBALS][_m]} (Empty()[_m]) || Mem[T.GrandMaster__GLOBALS][_m] == LOOP_108_Mem[T.GrandMaster__GLOBALS][_m]));
+//TAG: updated memory locations at Mem[T.P_DEVICE_OBJECT] only for: __set_empty
+assert (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.P_DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.P_DEVICE_OBJECT][_m] == LOOP_108_Mem[T.P_DEVICE_OBJECT][_m]));
+
+// end loop head assertions
+
+goto label_108_true , label_108_false ;
+
+
+label_108_true :
+assume ($i$8$3075.14$KeyboardClassUnload$4 < Mem[T.NumAssocClass__GLOBALS][NumAssocClass__GLOBALS(Globals)]);
+goto label_109;
+
+
+label_108_false :
+assume !($i$8$3075.14$KeyboardClassUnload$4 < Mem[T.NumAssocClass__GLOBALS][NumAssocClass__GLOBALS(Globals)]);
+goto label_128;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3078)
+label_109:
+goto label_109_true , label_109_false ;
+
+
+label_109_true :
+assume (Mem[T.Free__PORT][Free__PORT(PLUS(Mem[T.AssocClassList__GLOBALS][AssocClassList__GLOBALS(Globals)], 12, $i$8$3075.14$KeyboardClassUnload$4))] == 1);
+goto label_115;
+
+
+label_109_false :
+assume !(Mem[T.Free__PORT][Free__PORT(PLUS(Mem[T.AssocClassList__GLOBALS][AssocClassList__GLOBALS(Globals)], 12, $i$8$3075.14$KeyboardClassUnload$4))] == 1);
+goto label_113;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3078)
+label_110:
+// skip RtlAssert
+goto label_115;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3078)
+label_113:
+call havoc_stringTemp := __HAVOC_malloc(1);
+$RtlAssert.arg.2$13$ := havoc_stringTemp ;
+goto label_114;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3078)
+label_114:
+call havoc_stringTemp := __HAVOC_malloc(1);
+$RtlAssert.arg.1$14$ := havoc_stringTemp ;
+goto label_110;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3079)
+label_115:
+goto label_115_true , label_115_false ;
+
+
+label_115_true :
+assume (Mem[T.Enabled__PORT][Enabled__PORT(PLUS(Mem[T.AssocClassList__GLOBALS][AssocClassList__GLOBALS(Globals)], 12, $i$8$3075.14$KeyboardClassUnload$4))] != 0);
+goto label_119;
+
+
+label_115_false :
+assume (Mem[T.Enabled__PORT][Enabled__PORT(PLUS(Mem[T.AssocClassList__GLOBALS][AssocClassList__GLOBALS(Globals)], 12, $i$8$3075.14$KeyboardClassUnload$4))] == 0);
+goto label_121;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3079)
+label_116:
+// skip RtlAssert
+goto label_121;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3079)
+label_119:
+call havoc_stringTemp := __HAVOC_malloc(1);
+$RtlAssert.arg.2$15$ := havoc_stringTemp ;
+goto label_120;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3079)
+label_120:
+call havoc_stringTemp := __HAVOC_malloc(1);
+$RtlAssert.arg.1$16$ := havoc_stringTemp ;
+goto label_116;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3080)
+label_121:
+goto label_121_true , label_121_false ;
+
+
+label_121_true :
+assume (Mem[T.File__PORT][File__PORT(PLUS(Mem[T.AssocClassList__GLOBALS][AssocClassList__GLOBALS(Globals)], 12, $i$8$3075.14$KeyboardClassUnload$4))] != 0);
+goto label_125;
+
+
+label_121_false :
+assume (Mem[T.File__PORT][File__PORT(PLUS(Mem[T.AssocClassList__GLOBALS][AssocClassList__GLOBALS(Globals)], 12, $i$8$3075.14$KeyboardClassUnload$4))] == 0);
+goto label_127;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3080)
+label_122:
+// skip RtlAssert
+goto label_127;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3080)
+label_125:
+call havoc_stringTemp := __HAVOC_malloc(1);
+$RtlAssert.arg.2$17$ := havoc_stringTemp ;
+goto label_126;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3080)
+label_126:
+call havoc_stringTemp := __HAVOC_malloc(1);
+$RtlAssert.arg.1$18$ := havoc_stringTemp ;
+goto label_122;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3077)
+label_127:
+$i$8$3075.14$KeyboardClassUnload$4 := PLUS($i$8$3075.14$KeyboardClassUnload$4, 1, 1) ;
+goto label_108_head;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3084)
+label_128:
+call ExFreePoolWithTag (Mem[T.AssocClassList__GLOBALS][AssocClassList__GLOBALS(Globals)], 0);
+goto label_134;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3087)
+label_131:
+// skip KbdDebugPrint
+goto label_1;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\kbdclass_fbl_fbs_dev2_ntfs\kbdclass.c(3087)
+label_134:
+call havoc_stringTemp := __HAVOC_malloc(1);
+$KbdDebugPrint.arg.2$19$ := havoc_stringTemp ;
+goto label_131;
+
+}
+
diff --git a/Test/havoc0/MouCreateClassObject.bpl b/Test/havoc0/MouCreateClassObject.bpl
new file mode 100644
index 00000000..d988dfbd
--- /dev/null
+++ b/Test/havoc0/MouCreateClassObject.bpl
@@ -0,0 +1,4918 @@
+type byte, name;
+function OneByteToInt(byte) returns (int);
+function TwoBytesToInt(byte, byte) returns (int);
+function FourBytesToInt(byte, byte, byte, byte) returns (int);
+axiom(forall b0:byte, c0:byte :: {OneByteToInt(b0), OneByteToInt(c0)} OneByteToInt(b0) == OneByteToInt(c0) ==> b0 == c0);
+axiom(forall b0:byte, b1: byte, c0:byte, c1:byte :: {TwoBytesToInt(b0, b1), TwoBytesToInt(c0, c1)} TwoBytesToInt(b0, b1) == TwoBytesToInt(c0, c1) ==> b0 == c0 && b1 == c1);
+axiom(forall b0:byte, b1: byte, b2:byte, b3:byte, c0:byte, c1:byte, c2:byte, c3:byte :: {FourBytesToInt(b0, b1, b2, b3), FourBytesToInt(c0, c1, c2, c3)} FourBytesToInt(b0, b1, b2, b3) == FourBytesToInt(c0, c1, c2, c3) ==> b0 == c0 && b1 == c1 && b2 == c2 && b3 == c3);
+
+// Mutable
+var Mem_BYTE:[int]byte;
+var alloc:[int]name;
+
+
+function Field(int) returns (name);
+function Base(int) returns (int);
+
+// Constants
+const unique UNALLOCATED:name;
+const unique ALLOCATED: name;
+const unique FREED:name;
+
+const unique BYTE:name;
+
+function Equal([int]bool, [int]bool) returns (bool);
+function Subset([int]bool, [int]bool) returns (bool);
+function Disjoint([int]bool, [int]bool) returns (bool);
+
+function Empty() returns ([int]bool);
+function SetTrue() returns ([int]bool);
+function Singleton(int) returns ([int]bool);
+function Reachable([int,int]bool, int) returns ([int]bool);
+function Union([int]bool, [int]bool) returns ([int]bool);
+function Intersection([int]bool, [int]bool) returns ([int]bool);
+function Difference([int]bool, [int]bool) returns ([int]bool);
+function Dereference([int]bool, [int]int) returns ([int]bool);
+function Inverse(f:[int]int, x:int) returns ([int]bool);
+
+function AtLeast(int, int) returns ([int]bool);
+function Rep(int, int) returns (int);
+axiom(forall n:int, x:int, y:int :: {AtLeast(n,x)[y]} AtLeast(n,x)[y] ==> x <= y && Rep(n,x) == Rep(n,y));
+axiom(forall n:int, x:int, y:int :: {AtLeast(n,x),Rep(n,x),Rep(n,y)} x <= y && Rep(n,x) == Rep(n,y) ==> AtLeast(n,x)[y]);
+axiom(forall n:int, x:int :: {AtLeast(n,x)} AtLeast(n,x)[x]);
+axiom(forall n:int, x:int, z:int :: {PLUS(x,n,z)} Rep(n,x) == Rep(n,PLUS(x,n,z)));
+axiom(forall n:int, x:int :: {Rep(n,x)} (exists k:int :: Rep(n,x) - x == n*k));
+
+/*
+function AtLeast(int, int) returns ([int]bool);
+function ModEqual(int, int, int) returns (bool);
+axiom(forall n:int, x:int :: ModEqual(n,x,x));
+axiom(forall n:int, x:int, y:int :: {ModEqual(n,x,y)} ModEqual(n,x,y) ==> ModEqual(n,y,x));
+axiom(forall n:int, x:int, y:int, z:int :: {ModEqual(n,x,y), ModEqual(n,y,z)} ModEqual(n,x,y) && ModEqual(n,y,z) ==> ModEqual(n,x,z));
+axiom(forall n:int, x:int, z:int :: {PLUS(x,n,z)} ModEqual(n,x,PLUS(x,n,z)));
+axiom(forall n:int, x:int, y:int :: {ModEqual(n,x,y)} ModEqual(n,x,y) ==> (exists k:int :: x - y == n*k));
+axiom(forall x:int, n:int, y:int :: {AtLeast(n,x)[y]}{ModEqual(n,x,y)} AtLeast(n,x)[y] <==> x <= y && ModEqual(n,x,y));
+axiom(forall x:int, n:int :: {AtLeast(n,x)} AtLeast(n,x)[x]);
+*/
+
+function Array(int, int, int) returns ([int]bool);
+axiom(forall x:int, n:int, z:int :: {Array(x,n,z)} z <= 0 ==> Equal(Array(x,n,z), Empty()));
+axiom(forall x:int, n:int, z:int :: {Array(x,n,z)} z > 0 ==> Equal(Array(x,n,z), Difference(AtLeast(n,x),AtLeast(n,PLUS(x,n,z)))));
+
+
+axiom(forall x:int :: !Empty()[x]);
+
+axiom(forall x:int :: SetTrue()[x]);
+
+axiom(forall x:int, y:int :: {Singleton(y)[x]} Singleton(y)[x] <==> x == y);
+axiom(forall y:int :: {Singleton(y)} Singleton(y)[y]);
+
+/* this formulation of Union IS more complete than the earlier one */
+/* (A U B)[e], A[d], A U B = Singleton(c), d != e */
+axiom(forall x:int, S:[int]bool, T:[int]bool :: {Union(S,T)[x]}{Union(S,T),S[x]}{Union(S,T),T[x]} Union(S,T)[x] <==> S[x] || T[x]);
+axiom(forall x:int, S:[int]bool, T:[int]bool :: {Intersection(S,T)[x]}{Intersection(S,T),S[x]}{Intersection(S,T),T[x]} Intersection(S,T)[x] <==> S[x] && T[x]);
+axiom(forall x:int, S:[int]bool, T:[int]bool :: {Difference(S,T)[x]}{Difference(S,T),S[x]}{Difference(S,T),T[x]} Difference(S,T)[x] <==> S[x] && !T[x]);
+
+axiom(forall S:[int]bool, T:[int]bool :: {Equal(S,T)} Equal(S,T) <==> Subset(S,T) && Subset(T,S));
+axiom(forall x:int, S:[int]bool, T:[int]bool :: {S[x],Subset(S,T)}{T[x],Subset(S,T)} S[x] && Subset(S,T) ==> T[x]);
+axiom(forall S:[int]bool, T:[int]bool :: {Subset(S,T)} Subset(S,T) || (exists x:int :: S[x] && !T[x]));
+axiom(forall x:int, S:[int]bool, T:[int]bool :: {S[x],Disjoint(S,T)}{T[x],Disjoint(S,T)} !(S[x] && Disjoint(S,T) && T[x]));
+axiom(forall S:[int]bool, T:[int]bool :: {Disjoint(S,T)} Disjoint(S,T) || (exists x:int :: S[x] && T[x]));
+
+axiom(forall f:[int]int, x:int :: {Inverse(f,f[x])} Inverse(f,f[x])[x]);
+axiom(forall f:[int]int, x:int, y:int :: {Inverse(f,y), f[x]} Inverse(f,y)[x] ==> f[x] == y);
+axiom(forall f:[int]int, x:int, y:int :: {Inverse(f[x := y],y)} Equal(Inverse(f[x := y],y), Union(Inverse(f,y), Singleton(x))));
+axiom(forall f:[int]int, x:int, y:int, z:int :: {Inverse(f[x := y],z)} y == z || Equal(Inverse(f[x := y],z), Difference(Inverse(f,z), Singleton(x))));
+
+
+axiom(forall x:int, S:[int]bool, M:[int]int :: {Dereference(S,M)[x]} Dereference(S,M)[x] ==> (exists y:int :: x == M[y] && S[y]));
+axiom(forall x:int, S:[int]bool, M:[int]int :: {M[x], S[x], Dereference(S,M)} S[x] ==> Dereference(S,M)[M[x]]);
+axiom(forall x:int, y:int, S:[int]bool, M:[int]int :: {Dereference(S,M[x := y])} !S[x] ==> Equal(Dereference(S,M[x := y]), Dereference(S,M)));
+axiom(forall x:int, y:int, S:[int]bool, M:[int]int :: {Dereference(S,M[x := y])}
+ S[x] && Equal(Intersection(Inverse(M,M[x]), S), Singleton(x)) ==> Equal(Dereference(S,M[x := y]), Union(Difference(Dereference(S,M), Singleton(M[x])), Singleton(y))));
+axiom(forall x:int, y:int, S:[int]bool, M:[int]int :: {Dereference(S,M[x := y])}
+ S[x] && !Equal(Intersection(Inverse(M,M[x]), S), Singleton(x)) ==> Equal(Dereference(S,M[x := y]), Union(Dereference(S,M), Singleton(y))));
+
+function Unified([name][int]int) returns ([int]int);
+axiom(forall M:[name][int]int, x:int :: {Unified(M)[x]} Unified(M)[x] == M[Field(x)][x]);
+axiom(forall M:[name][int]int, x:int, y:int :: {Unified(M[Field(x) := M[Field(x)][x := y]])} Unified(M[Field(x) := M[Field(x)][x := y]]) == Unified(M)[x := y]);
+// Memory model
+
+var Mem: [name][int]int;
+
+function Match(a:int, t:name) returns (bool);
+function HasType(v:int, t:name, m:[name][int]int) returns (bool);
+function Values(t:name, m:[name][int]int) returns ([int]bool);
+function T.Ptr(t:name) returns (name);
+
+axiom(forall v:int, t:name, m:[name][int]int :: {Values(t, m)[v]} Values(t, m)[v] ==> HasType(v, t, m));
+axiom(forall v:int, t:name, m:[name][int]int :: {HasType(v, t, m), Values(t, m)} HasType(v, t, m) ==> Values(t, m)[v]);
+
+axiom(forall a:int, t:name :: {Match(a, T.Ptr(t))} Match(a, T.Ptr(t)) <==> Field(a) == T.Ptr(t));
+axiom(forall v:int, t:name, m:[name][int]int :: {HasType(v, T.Ptr(t), m)} HasType(v, T.Ptr(t), m) <==> (v == 0 || (v > 0 && Match(v, t))));
+
+axiom(forall v:int, t:name, m1:[name][int]int, m2:[name][int]int :: {HasType(v, t, m1), HasType(v, t, m2)}
+ (HasType(v, t, m1) <==> HasType(v, t, m2)));
+
+// Field declarations
+
+const unique T.Guid_WMIGUIDREGINFO:name;
+const unique T.InstanceCount_WMIGUIDREGINFO:name;
+const unique T.Flags_WMIGUIDREGINFO:name;
+const unique T.OperationID__ACCESS_STATE:name;
+const unique T.SecurityEvaluated__ACCESS_STATE:name;
+const unique T.GenerateAudit__ACCESS_STATE:name;
+const unique T.GenerateOnClose__ACCESS_STATE:name;
+const unique T.PrivilegesAllocated__ACCESS_STATE:name;
+const unique T.Flags__ACCESS_STATE:name;
+const unique T.RemainingDesiredAccess__ACCESS_STATE:name;
+const unique T.PreviouslyGrantedAccess__ACCESS_STATE:name;
+const unique T.OriginalDesiredAccess__ACCESS_STATE:name;
+const unique T.SubjectSecurityContext__ACCESS_STATE:name;
+const unique T.SecurityDescriptor__ACCESS_STATE:name;
+const unique T.AuxData__ACCESS_STATE:name;
+const unique T.Privileges__ACCESS_STATE:name;
+const unique T.AuditPrivileges__ACCESS_STATE:name;
+const unique T.ObjectName__ACCESS_STATE:name;
+const unique T.ObjectTypeName__ACCESS_STATE:name;
+const unique T.InterfaceType__CM_FULL_RESOURCE_DESCRIPTOR:name;
+const unique T.BusNumber__CM_FULL_RESOURCE_DESCRIPTOR:name;
+const unique T.PartialResourceList__CM_FULL_RESOURCE_DESCRIPTOR:name;
+const unique T.Type__CM_PARTIAL_RESOURCE_DESCRIPTOR:name;
+const unique T.ShareDisposition__CM_PARTIAL_RESOURCE_DESCRIPTOR:name;
+const unique T.Flags__CM_PARTIAL_RESOURCE_DESCRIPTOR:name;
+const unique T.u__CM_PARTIAL_RESOURCE_DESCRIPTOR:name;
+const unique T.Version__CM_PARTIAL_RESOURCE_LIST:name;
+const unique T.Revision__CM_PARTIAL_RESOURCE_LIST:name;
+const unique T.Count__CM_PARTIAL_RESOURCE_LIST:name;
+const unique T.PartialDescriptors__CM_PARTIAL_RESOURCE_LIST:name;
+const unique T.Count__CM_RESOURCE_LIST:name;
+const unique T.List__CM_RESOURCE_LIST:name;
+const unique T.Size__DEVICE_CAPABILITIES:name;
+const unique T.Version__DEVICE_CAPABILITIES:name;
+const unique T.DeviceD1__DEVICE_CAPABILITIES:name;
+const unique T.DeviceD2__DEVICE_CAPABILITIES:name;
+const unique T.LockSupported__DEVICE_CAPABILITIES:name;
+const unique T.EjectSupported__DEVICE_CAPABILITIES:name;
+const unique T.Removable__DEVICE_CAPABILITIES:name;
+const unique T.DockDevice__DEVICE_CAPABILITIES:name;
+const unique T.UniqueID__DEVICE_CAPABILITIES:name;
+const unique T.SilentInstall__DEVICE_CAPABILITIES:name;
+const unique T.RawDeviceOK__DEVICE_CAPABILITIES:name;
+const unique T.SurpriseRemovalOK__DEVICE_CAPABILITIES:name;
+const unique T.WakeFromD0__DEVICE_CAPABILITIES:name;
+const unique T.WakeFromD1__DEVICE_CAPABILITIES:name;
+const unique T.WakeFromD2__DEVICE_CAPABILITIES:name;
+const unique T.WakeFromD3__DEVICE_CAPABILITIES:name;
+const unique T.HardwareDisabled__DEVICE_CAPABILITIES:name;
+const unique T.NonDynamic__DEVICE_CAPABILITIES:name;
+const unique T.WarmEjectSupported__DEVICE_CAPABILITIES:name;
+const unique T.NoDisplayInUI__DEVICE_CAPABILITIES:name;
+const unique T.Reserved__DEVICE_CAPABILITIES:name;
+const unique T.Address__DEVICE_CAPABILITIES:name;
+const unique T.UINumber__DEVICE_CAPABILITIES:name;
+const unique T.DeviceState__DEVICE_CAPABILITIES:name;
+const unique T.SystemWake__DEVICE_CAPABILITIES:name;
+const unique T.DeviceWake__DEVICE_CAPABILITIES:name;
+const unique T.D1Latency__DEVICE_CAPABILITIES:name;
+const unique T.D2Latency__DEVICE_CAPABILITIES:name;
+const unique T.D3Latency__DEVICE_CAPABILITIES:name;
+const unique T.Self__DEVICE_EXTENSION:name;
+const unique T.TrueClassDevice__DEVICE_EXTENSION:name;
+const unique T.TopPort__DEVICE_EXTENSION:name;
+const unique T.PDO__DEVICE_EXTENSION:name;
+const unique T.RemoveLock__DEVICE_EXTENSION:name;
+const unique T.PnP__DEVICE_EXTENSION:name;
+const unique T.Started__DEVICE_EXTENSION:name;
+const unique T.OkayToLogOverflow__DEVICE_EXTENSION:name;
+const unique T.WaitWakeSpinLock__DEVICE_EXTENSION:name;
+const unique T.TrustedSubsystemCount__DEVICE_EXTENSION:name;
+const unique T.InputCount__DEVICE_EXTENSION:name;
+const unique T.SymbolicLinkName__DEVICE_EXTENSION:name;
+const unique T.InputData__DEVICE_EXTENSION:name;
+const unique T.DataIn__DEVICE_EXTENSION:name;
+const unique T.DataOut__DEVICE_EXTENSION:name;
+const unique T.MouseAttributes__DEVICE_EXTENSION:name;
+const unique T.SpinLock__DEVICE_EXTENSION:name;
+const unique T.ReadQueue__DEVICE_EXTENSION:name;
+const unique T.SequenceNumber__DEVICE_EXTENSION:name;
+const unique T.DeviceState__DEVICE_EXTENSION:name;
+const unique T.SystemState__DEVICE_EXTENSION:name;
+const unique T.UnitId__DEVICE_EXTENSION:name;
+const unique T.WmiLibInfo__DEVICE_EXTENSION:name;
+const unique T.SystemToDeviceState__DEVICE_EXTENSION:name;
+const unique T.MinDeviceWakeState__DEVICE_EXTENSION:name;
+const unique T.MinSystemWakeState__DEVICE_EXTENSION:name;
+const unique T.WaitWakeIrp__DEVICE_EXTENSION:name;
+const unique T.ExtraWaitWakeIrp__DEVICE_EXTENSION:name;
+const unique T.TargetNotifyHandle__DEVICE_EXTENSION:name;
+const unique T.Link__DEVICE_EXTENSION:name;
+const unique T.File__DEVICE_EXTENSION:name;
+const unique T.Enabled__DEVICE_EXTENSION:name;
+const unique T.WaitWakeEnabled__DEVICE_EXTENSION:name;
+const unique T.SurpriseRemoved__DEVICE_EXTENSION:name;
+const unique T.Type__DEVICE_OBJECT:name;
+const unique T.Size__DEVICE_OBJECT:name;
+const unique T.ReferenceCount__DEVICE_OBJECT:name;
+const unique T.DriverObject__DEVICE_OBJECT:name;
+const unique T.NextDevice__DEVICE_OBJECT:name;
+const unique T.AttachedDevice__DEVICE_OBJECT:name;
+const unique T.CurrentIrp__DEVICE_OBJECT:name;
+const unique T.Timer__DEVICE_OBJECT:name;
+const unique T.Flags__DEVICE_OBJECT:name;
+const unique T.Characteristics__DEVICE_OBJECT:name;
+const unique T.Vpb__DEVICE_OBJECT:name;
+const unique T.DeviceExtension__DEVICE_OBJECT:name;
+const unique T.DeviceType__DEVICE_OBJECT:name;
+const unique T.StackSize__DEVICE_OBJECT:name;
+const unique T.Queue__DEVICE_OBJECT:name;
+const unique T.AlignmentRequirement__DEVICE_OBJECT:name;
+const unique T.DeviceQueue__DEVICE_OBJECT:name;
+const unique T.Dpc__DEVICE_OBJECT:name;
+const unique T.ActiveThreadCount__DEVICE_OBJECT:name;
+const unique T.SecurityDescriptor__DEVICE_OBJECT:name;
+const unique T.DeviceLock__DEVICE_OBJECT:name;
+const unique T.SectorSize__DEVICE_OBJECT:name;
+const unique T.Spare1__DEVICE_OBJECT:name;
+const unique T.DeviceObjectExtension__DEVICE_OBJECT:name;
+const unique T.Reserved__DEVICE_OBJECT:name;
+const unique T.Type__DEVOBJ_EXTENSION:name;
+const unique T.Size__DEVOBJ_EXTENSION:name;
+const unique T.DeviceObject__DEVOBJ_EXTENSION:name;
+const unique T.__unnamed_4_c9b2e921__DISPATCHER_HEADER:name;
+const unique T.SignalState__DISPATCHER_HEADER:name;
+const unique T.WaitListHead__DISPATCHER_HEADER:name;
+const unique T.DriverObject__DRIVER_EXTENSION:name;
+const unique T.AddDevice__DRIVER_EXTENSION:name;
+const unique T.Count__DRIVER_EXTENSION:name;
+const unique T.ServiceKeyName__DRIVER_EXTENSION:name;
+const unique T.Type__DRIVER_OBJECT:name;
+const unique T.Size__DRIVER_OBJECT:name;
+const unique T.DeviceObject__DRIVER_OBJECT:name;
+const unique T.Flags__DRIVER_OBJECT:name;
+const unique T.DriverStart__DRIVER_OBJECT:name;
+const unique T.DriverSize__DRIVER_OBJECT:name;
+const unique T.DriverSection__DRIVER_OBJECT:name;
+const unique T.DriverExtension__DRIVER_OBJECT:name;
+const unique T.DriverName__DRIVER_OBJECT:name;
+const unique T.HardwareDatabase__DRIVER_OBJECT:name;
+const unique T.FastIoDispatch__DRIVER_OBJECT:name;
+const unique T.DriverInit__DRIVER_OBJECT:name;
+const unique T.DriverStartIo__DRIVER_OBJECT:name;
+const unique T.DriverUnload__DRIVER_OBJECT:name;
+const unique T.MajorFunction__DRIVER_OBJECT:name;
+const unique T.SystemResourcesList__ERESOURCE:name;
+const unique T.OwnerTable__ERESOURCE:name;
+const unique T.ActiveCount__ERESOURCE:name;
+const unique T.Flag__ERESOURCE:name;
+const unique T.SharedWaiters__ERESOURCE:name;
+const unique T.ExclusiveWaiters__ERESOURCE:name;
+const unique T.OwnerEntry__ERESOURCE:name;
+const unique T.ActiveEntries__ERESOURCE:name;
+const unique T.ContentionCount__ERESOURCE:name;
+const unique T.NumberOfSharedWaiters__ERESOURCE:name;
+const unique T.NumberOfExclusiveWaiters__ERESOURCE:name;
+const unique T.__unnamed_4_46b62f69__ERESOURCE:name;
+const unique T.SpinLock__ERESOURCE:name;
+const unique T.SizeOfFastIoDispatch__FAST_IO_DISPATCH:name;
+const unique T.FastIoCheckIfPossible__FAST_IO_DISPATCH:name;
+const unique T.FastIoRead__FAST_IO_DISPATCH:name;
+const unique T.FastIoWrite__FAST_IO_DISPATCH:name;
+const unique T.FastIoQueryBasicInfo__FAST_IO_DISPATCH:name;
+const unique T.FastIoQueryStandardInfo__FAST_IO_DISPATCH:name;
+const unique T.FastIoLock__FAST_IO_DISPATCH:name;
+const unique T.FastIoUnlockSingle__FAST_IO_DISPATCH:name;
+const unique T.FastIoUnlockAll__FAST_IO_DISPATCH:name;
+const unique T.FastIoUnlockAllByKey__FAST_IO_DISPATCH:name;
+const unique T.FastIoDeviceControl__FAST_IO_DISPATCH:name;
+const unique T.AcquireFileForNtCreateSection__FAST_IO_DISPATCH:name;
+const unique T.ReleaseFileForNtCreateSection__FAST_IO_DISPATCH:name;
+const unique T.FastIoDetachDevice__FAST_IO_DISPATCH:name;
+const unique T.FastIoQueryNetworkOpenInfo__FAST_IO_DISPATCH:name;
+const unique T.AcquireForModWrite__FAST_IO_DISPATCH:name;
+const unique T.MdlRead__FAST_IO_DISPATCH:name;
+const unique T.MdlReadComplete__FAST_IO_DISPATCH:name;
+const unique T.PrepareMdlWrite__FAST_IO_DISPATCH:name;
+const unique T.MdlWriteComplete__FAST_IO_DISPATCH:name;
+const unique T.FastIoReadCompressed__FAST_IO_DISPATCH:name;
+const unique T.FastIoWriteCompressed__FAST_IO_DISPATCH:name;
+const unique T.MdlReadCompleteCompressed__FAST_IO_DISPATCH:name;
+const unique T.MdlWriteCompleteCompressed__FAST_IO_DISPATCH:name;
+const unique T.FastIoQueryOpen__FAST_IO_DISPATCH:name;
+const unique T.ReleaseForModWrite__FAST_IO_DISPATCH:name;
+const unique T.AcquireForCcFlush__FAST_IO_DISPATCH:name;
+const unique T.ReleaseForCcFlush__FAST_IO_DISPATCH:name;
+const unique T.Count__FAST_MUTEX:name;
+const unique T.Owner__FAST_MUTEX:name;
+const unique T.Contention__FAST_MUTEX:name;
+const unique T.Gate__FAST_MUTEX:name;
+const unique T.OldIrql__FAST_MUTEX:name;
+const unique T.CreationTime__FILE_BASIC_INFORMATION:name;
+const unique T.LastAccessTime__FILE_BASIC_INFORMATION:name;
+const unique T.LastWriteTime__FILE_BASIC_INFORMATION:name;
+const unique T.ChangeTime__FILE_BASIC_INFORMATION:name;
+const unique T.FileAttributes__FILE_BASIC_INFORMATION:name;
+const unique T.CreationTime__FILE_NETWORK_OPEN_INFORMATION:name;
+const unique T.LastAccessTime__FILE_NETWORK_OPEN_INFORMATION:name;
+const unique T.LastWriteTime__FILE_NETWORK_OPEN_INFORMATION:name;
+const unique T.ChangeTime__FILE_NETWORK_OPEN_INFORMATION:name;
+const unique T.AllocationSize__FILE_NETWORK_OPEN_INFORMATION:name;
+const unique T.EndOfFile__FILE_NETWORK_OPEN_INFORMATION:name;
+const unique T.FileAttributes__FILE_NETWORK_OPEN_INFORMATION:name;
+const unique T.Type__FILE_OBJECT:name;
+const unique T.Size__FILE_OBJECT:name;
+const unique T.DeviceObject__FILE_OBJECT:name;
+const unique T.Vpb__FILE_OBJECT:name;
+const unique T.FsContext__FILE_OBJECT:name;
+const unique T.FsContext2__FILE_OBJECT:name;
+const unique T.SectionObjectPointer__FILE_OBJECT:name;
+const unique T.PrivateCacheMap__FILE_OBJECT:name;
+const unique T.FinalStatus__FILE_OBJECT:name;
+const unique T.RelatedFileObject__FILE_OBJECT:name;
+const unique T.LockOperation__FILE_OBJECT:name;
+const unique T.DeletePending__FILE_OBJECT:name;
+const unique T.ReadAccess__FILE_OBJECT:name;
+const unique T.WriteAccess__FILE_OBJECT:name;
+const unique T.DeleteAccess__FILE_OBJECT:name;
+const unique T.SharedRead__FILE_OBJECT:name;
+const unique T.SharedWrite__FILE_OBJECT:name;
+const unique T.SharedDelete__FILE_OBJECT:name;
+const unique T.Flags__FILE_OBJECT:name;
+const unique T.FileName__FILE_OBJECT:name;
+const unique T.CurrentByteOffset__FILE_OBJECT:name;
+const unique T.Waiters__FILE_OBJECT:name;
+const unique T.Busy__FILE_OBJECT:name;
+const unique T.LastLock__FILE_OBJECT:name;
+const unique T.Lock__FILE_OBJECT:name;
+const unique T.Event__FILE_OBJECT:name;
+const unique T.CompletionContext__FILE_OBJECT:name;
+const unique T.IrpListLock__FILE_OBJECT:name;
+const unique T.IrpList__FILE_OBJECT:name;
+const unique T.FileObjectExtension__FILE_OBJECT:name;
+const unique T.AllocationSize__FILE_STANDARD_INFORMATION:name;
+const unique T.EndOfFile__FILE_STANDARD_INFORMATION:name;
+const unique T.NumberOfLinks__FILE_STANDARD_INFORMATION:name;
+const unique T.DeletePending__FILE_STANDARD_INFORMATION:name;
+const unique T.Directory__FILE_STANDARD_INFORMATION:name;
+const unique T.Debug__GLOBALS:name;
+const unique T.GrandMaster__GLOBALS:name;
+const unique T.AssocClassList__GLOBALS:name;
+const unique T.NumAssocClass__GLOBALS:name;
+const unique T.Opens__GLOBALS:name;
+const unique T.NumberLegacyPorts__GLOBALS:name;
+const unique T.Mutex__GLOBALS:name;
+const unique T.ConnectOneClassToOnePort__GLOBALS:name;
+const unique T.PortsServiced__GLOBALS:name;
+const unique T.InitExtension__GLOBALS:name;
+const unique T.RegistryPath__GLOBALS:name;
+const unique T.BaseClassName__GLOBALS:name;
+const unique T.BaseClassBuffer__GLOBALS:name;
+const unique T.LegacyDeviceList__GLOBALS:name;
+const unique T.Data1__GUID:name;
+const unique T.Data2__GUID:name;
+const unique T.Data3__GUID:name;
+const unique T.Data4__GUID:name;
+const unique T.PrivilegeCount__INITIAL_PRIVILEGE_SET:name;
+const unique T.Control__INITIAL_PRIVILEGE_SET:name;
+const unique T.Privilege__INITIAL_PRIVILEGE_SET:name;
+const unique T.Size__INTERFACE:name;
+const unique T.Version__INTERFACE:name;
+const unique T.Context__INTERFACE:name;
+const unique T.InterfaceReference__INTERFACE:name;
+const unique T.InterfaceDereference__INTERFACE:name;
+const unique T.Port__IO_COMPLETION_CONTEXT:name;
+const unique T.Key__IO_COMPLETION_CONTEXT:name;
+const unique T.Common__IO_REMOVE_LOCK:name;
+const unique T.Dbg__IO_REMOVE_LOCK:name;
+const unique T.Removed__IO_REMOVE_LOCK_COMMON_BLOCK:name;
+const unique T.Reserved__IO_REMOVE_LOCK_COMMON_BLOCK:name;
+const unique T.IoCount__IO_REMOVE_LOCK_COMMON_BLOCK:name;
+const unique T.RemoveEvent__IO_REMOVE_LOCK_COMMON_BLOCK:name;
+const unique T.Signature__IO_REMOVE_LOCK_DBG_BLOCK:name;
+const unique T.HighWatermark__IO_REMOVE_LOCK_DBG_BLOCK:name;
+const unique T.MaxLockedTicks__IO_REMOVE_LOCK_DBG_BLOCK:name;
+const unique T.AllocateTag__IO_REMOVE_LOCK_DBG_BLOCK:name;
+const unique T.LockList__IO_REMOVE_LOCK_DBG_BLOCK:name;
+const unique T.Spin__IO_REMOVE_LOCK_DBG_BLOCK:name;
+const unique T.LowMemoryCount__IO_REMOVE_LOCK_DBG_BLOCK:name;
+const unique T.Reserved1__IO_REMOVE_LOCK_DBG_BLOCK:name;
+const unique T.Reserved2__IO_REMOVE_LOCK_DBG_BLOCK:name;
+const unique T.Blocks__IO_REMOVE_LOCK_DBG_BLOCK:name;
+const unique T.Option__IO_RESOURCE_DESCRIPTOR:name;
+const unique T.Type__IO_RESOURCE_DESCRIPTOR:name;
+const unique T.ShareDisposition__IO_RESOURCE_DESCRIPTOR:name;
+const unique T.Spare1__IO_RESOURCE_DESCRIPTOR:name;
+const unique T.Flags__IO_RESOURCE_DESCRIPTOR:name;
+const unique T.Spare2__IO_RESOURCE_DESCRIPTOR:name;
+const unique T.u__IO_RESOURCE_DESCRIPTOR:name;
+const unique T.Version__IO_RESOURCE_LIST:name;
+const unique T.Revision__IO_RESOURCE_LIST:name;
+const unique T.Count__IO_RESOURCE_LIST:name;
+const unique T.Descriptors__IO_RESOURCE_LIST:name;
+const unique T.ListSize__IO_RESOURCE_REQUIREMENTS_LIST:name;
+const unique T.InterfaceType__IO_RESOURCE_REQUIREMENTS_LIST:name;
+const unique T.BusNumber__IO_RESOURCE_REQUIREMENTS_LIST:name;
+const unique T.SlotNumber__IO_RESOURCE_REQUIREMENTS_LIST:name;
+const unique T.Reserved__IO_RESOURCE_REQUIREMENTS_LIST:name;
+const unique T.AlternativeLists__IO_RESOURCE_REQUIREMENTS_LIST:name;
+const unique T.List__IO_RESOURCE_REQUIREMENTS_LIST:name;
+const unique T.SecurityQos__IO_SECURITY_CONTEXT:name;
+const unique T.AccessState__IO_SECURITY_CONTEXT:name;
+const unique T.DesiredAccess__IO_SECURITY_CONTEXT:name;
+const unique T.FullCreateOptions__IO_SECURITY_CONTEXT:name;
+const unique T.MajorFunction__IO_STACK_LOCATION:name;
+const unique T.MinorFunction__IO_STACK_LOCATION:name;
+const unique T.Flags__IO_STACK_LOCATION:name;
+const unique T.Control__IO_STACK_LOCATION:name;
+const unique T.Parameters__IO_STACK_LOCATION:name;
+const unique T.DeviceObject__IO_STACK_LOCATION:name;
+const unique T.FileObject__IO_STACK_LOCATION:name;
+const unique T.CompletionRoutine__IO_STACK_LOCATION:name;
+const unique T.Context__IO_STACK_LOCATION:name;
+const unique T.__unnamed_4_16aff58e__IO_STATUS_BLOCK:name;
+const unique T.Information__IO_STATUS_BLOCK:name;
+const unique T.Type__IRP:name;
+const unique T.Size__IRP:name;
+const unique T.MdlAddress__IRP:name;
+const unique T.Flags__IRP:name;
+const unique T.AssociatedIrp__IRP:name;
+const unique T.ThreadListEntry__IRP:name;
+const unique T.IoStatus__IRP:name;
+const unique T.RequestorMode__IRP:name;
+const unique T.PendingReturned__IRP:name;
+const unique T.StackCount__IRP:name;
+const unique T.CurrentLocation__IRP:name;
+const unique T.Cancel__IRP:name;
+const unique T.CancelIrql__IRP:name;
+const unique T.ApcEnvironment__IRP:name;
+const unique T.AllocationFlags__IRP:name;
+const unique T.UserIosb__IRP:name;
+const unique T.UserEvent__IRP:name;
+const unique T.Overlay__IRP:name;
+const unique T.CancelRoutine__IRP:name;
+const unique T.UserBuffer__IRP:name;
+const unique T.Tail__IRP:name;
+const unique T.Type__KAPC:name;
+const unique T.SpareByte0__KAPC:name;
+const unique T.Size__KAPC:name;
+const unique T.SpareByte1__KAPC:name;
+const unique T.SpareLong0__KAPC:name;
+const unique T.Thread__KAPC:name;
+const unique T.ApcListEntry__KAPC:name;
+const unique T.KernelRoutine__KAPC:name;
+const unique T.RundownRoutine__KAPC:name;
+const unique T.NormalRoutine__KAPC:name;
+const unique T.NormalContext__KAPC:name;
+const unique T.SystemArgument1__KAPC:name;
+const unique T.SystemArgument2__KAPC:name;
+const unique T.ApcStateIndex__KAPC:name;
+const unique T.ApcMode__KAPC:name;
+const unique T.Inserted__KAPC:name;
+const unique T.Type__KDEVICE_QUEUE:name;
+const unique T.Size__KDEVICE_QUEUE:name;
+const unique T.DeviceListHead__KDEVICE_QUEUE:name;
+const unique T.Lock__KDEVICE_QUEUE:name;
+const unique T.Busy__KDEVICE_QUEUE:name;
+const unique T.DeviceListEntry__KDEVICE_QUEUE_ENTRY:name;
+const unique T.SortKey__KDEVICE_QUEUE_ENTRY:name;
+const unique T.Inserted__KDEVICE_QUEUE_ENTRY:name;
+const unique T.Type__KDPC:name;
+const unique T.Importance__KDPC:name;
+const unique T.Number__KDPC:name;
+const unique T.DpcListEntry__KDPC:name;
+const unique T.DeferredRoutine__KDPC:name;
+const unique T.DeferredContext__KDPC:name;
+const unique T.SystemArgument1__KDPC:name;
+const unique T.SystemArgument2__KDPC:name;
+const unique T.DpcData__KDPC:name;
+const unique T.Header__KEVENT:name;
+const unique T.Header__KSEMAPHORE:name;
+const unique T.Limit__KSEMAPHORE:name;
+const unique T.__unnamed_8_8684a3e7__LARGE_INTEGER:name;
+const unique T.u__LARGE_INTEGER:name;
+const unique T.QuadPart__LARGE_INTEGER:name;
+const unique T.Flink__LIST_ENTRY:name;
+const unique T.Blink__LIST_ENTRY:name;
+const unique T.LowPart__LUID:name;
+const unique T.HighPart__LUID:name;
+const unique T.Luid__LUID_AND_ATTRIBUTES:name;
+const unique T.Attributes__LUID_AND_ATTRIBUTES:name;
+const unique T.Next__MDL:name;
+const unique T.Size__MDL:name;
+const unique T.MdlFlags__MDL:name;
+const unique T.Process__MDL:name;
+const unique T.MappedSystemVa__MDL:name;
+const unique T.StartVa__MDL:name;
+const unique T.ByteCount__MDL:name;
+const unique T.ByteOffset__MDL:name;
+const unique T.MouseIdentifier__MOUSE_ATTRIBUTES:name;
+const unique T.NumberOfButtons__MOUSE_ATTRIBUTES:name;
+const unique T.SampleRate__MOUSE_ATTRIBUTES:name;
+const unique T.InputDataQueueLength__MOUSE_ATTRIBUTES:name;
+const unique T.UnitId__MOUSE_INPUT_DATA:name;
+const unique T.Flags__MOUSE_INPUT_DATA:name;
+const unique T.__unnamed_4_9c11ed91__MOUSE_INPUT_DATA:name;
+const unique T.RawButtons__MOUSE_INPUT_DATA:name;
+const unique T.LastX__MOUSE_INPUT_DATA:name;
+const unique T.LastY__MOUSE_INPUT_DATA:name;
+const unique T.ExtraInformation__MOUSE_INPUT_DATA:name;
+const unique T.OwnerThread__OWNER_ENTRY:name;
+const unique T.__unnamed_4_c1e23b02__OWNER_ENTRY:name;
+const unique T.File__PORT:name;
+const unique T.Port__PORT:name;
+const unique T.Enabled__PORT:name;
+const unique T.Reserved__PORT:name;
+const unique T.Free__PORT:name;
+const unique T.SequenceD1__POWER_SEQUENCE:name;
+const unique T.SequenceD2__POWER_SEQUENCE:name;
+const unique T.SequenceD3__POWER_SEQUENCE:name;
+const unique T.SystemState__POWER_STATE:name;
+const unique T.DeviceState__POWER_STATE:name;
+const unique T.PrivilegeCount__PRIVILEGE_SET:name;
+const unique T.Control__PRIVILEGE_SET:name;
+const unique T.Privilege__PRIVILEGE_SET:name;
+const unique T.DataSectionObject__SECTION_OBJECT_POINTERS:name;
+const unique T.SharedCacheMap__SECTION_OBJECT_POINTERS:name;
+const unique T.ImageSectionObject__SECTION_OBJECT_POINTERS:name;
+const unique T.Length__SECURITY_QUALITY_OF_SERVICE:name;
+const unique T.ImpersonationLevel__SECURITY_QUALITY_OF_SERVICE:name;
+const unique T.ContextTrackingMode__SECURITY_QUALITY_OF_SERVICE:name;
+const unique T.EffectiveOnly__SECURITY_QUALITY_OF_SERVICE:name;
+const unique T.ClientToken__SECURITY_SUBJECT_CONTEXT:name;
+const unique T.ImpersonationLevel__SECURITY_SUBJECT_CONTEXT:name;
+const unique T.PrimaryToken__SECURITY_SUBJECT_CONTEXT:name;
+const unique T.ProcessAuditId__SECURITY_SUBJECT_CONTEXT:name;
+const unique T.__unnamed_4_b4f5a780__SYSTEM_POWER_STATE_CONTEXT:name;
+const unique T.Length__UNICODE_STRING:name;
+const unique T.MaximumLength__UNICODE_STRING:name;
+const unique T.Buffer__UNICODE_STRING:name;
+const unique T.Type__VPB:name;
+const unique T.Size__VPB:name;
+const unique T.Flags__VPB:name;
+const unique T.VolumeLabelLength__VPB:name;
+const unique T.DeviceObject__VPB:name;
+const unique T.RealDevice__VPB:name;
+const unique T.SerialNumber__VPB:name;
+const unique T.ReferenceCount__VPB:name;
+const unique T.VolumeLabel__VPB:name;
+const unique T.WaitQueueEntry__WAIT_CONTEXT_BLOCK:name;
+const unique T.DeviceRoutine__WAIT_CONTEXT_BLOCK:name;
+const unique T.DeviceContext__WAIT_CONTEXT_BLOCK:name;
+const unique T.NumberOfMapRegisters__WAIT_CONTEXT_BLOCK:name;
+const unique T.DeviceObject__WAIT_CONTEXT_BLOCK:name;
+const unique T.CurrentIrp__WAIT_CONTEXT_BLOCK:name;
+const unique T.BufferChainingDpc__WAIT_CONTEXT_BLOCK:name;
+const unique T.GuidCount__WMILIB_CONTEXT:name;
+const unique T.GuidList__WMILIB_CONTEXT:name;
+const unique T.QueryWmiRegInfo__WMILIB_CONTEXT:name;
+const unique T.QueryWmiDataBlock__WMILIB_CONTEXT:name;
+const unique T.SetWmiDataBlock__WMILIB_CONTEXT:name;
+const unique T.SetWmiDataItem__WMILIB_CONTEXT:name;
+const unique T.ExecuteWmiMethod__WMILIB_CONTEXT:name;
+const unique T.WmiFunctionControl__WMILIB_CONTEXT:name;
+const unique T.Start___unnamed_12_06b9ee6e:name;
+const unique T.Length48___unnamed_12_06b9ee6e:name;
+const unique T.Start___unnamed_12_0882bd02:name;
+const unique T.Length64___unnamed_12_0882bd02:name;
+const unique T.__unnamed_12_2e80217b___unnamed_12_264d0dab:name;
+const unique T.Raw___unnamed_12_2e80217b:name;
+const unique T.Translated___unnamed_12_2e80217b:name;
+const unique T.Data___unnamed_12_5cc7ace2:name;
+const unique T.Channel___unnamed_12_6374506e:name;
+const unique T.Port___unnamed_12_6374506e:name;
+const unique T.Reserved1___unnamed_12_6374506e:name;
+const unique T.Priority___unnamed_12_68a4278e:name;
+const unique T.Reserved1___unnamed_12_68a4278e:name;
+const unique T.Reserved2___unnamed_12_68a4278e:name;
+const unique T.Generic___unnamed_12_79ed2653:name;
+const unique T.Port___unnamed_12_79ed2653:name;
+const unique T.Interrupt___unnamed_12_79ed2653:name;
+const unique T.MessageInterrupt___unnamed_12_79ed2653:name;
+const unique T.Memory___unnamed_12_79ed2653:name;
+const unique T.Dma___unnamed_12_79ed2653:name;
+const unique T.DevicePrivate___unnamed_12_79ed2653:name;
+const unique T.BusNumber___unnamed_12_79ed2653:name;
+const unique T.DeviceSpecificData___unnamed_12_79ed2653:name;
+const unique T.Memory40___unnamed_12_79ed2653:name;
+const unique T.Memory48___unnamed_12_79ed2653:name;
+const unique T.Memory64___unnamed_12_79ed2653:name;
+const unique T.Start___unnamed_12_7da594c0:name;
+const unique T.Length40___unnamed_12_7da594c0:name;
+const unique T.Start___unnamed_12_9873e05d:name;
+const unique T.Length___unnamed_12_9873e05d:name;
+const unique T.DataSize___unnamed_12_9cc8cebc:name;
+const unique T.Reserved1___unnamed_12_9cc8cebc:name;
+const unique T.Reserved2___unnamed_12_9cc8cebc:name;
+const unique T.Start___unnamed_12_b98da82e:name;
+const unique T.Length___unnamed_12_b98da82e:name;
+const unique T.Level___unnamed_12_c2880e88:name;
+const unique T.Vector___unnamed_12_c2880e88:name;
+const unique T.Affinity___unnamed_12_c2880e88:name;
+const unique T.Start___unnamed_12_c49ab31a:name;
+const unique T.Length___unnamed_12_c49ab31a:name;
+const unique T.ListEntry___unnamed_12_c6ed93f3:name;
+const unique T.__unnamed_4_a7aa989c___unnamed_12_c6ed93f3:name;
+const unique T.Data___unnamed_12_ced61554:name;
+const unique T.Reserved___unnamed_12_d9c44df5:name;
+const unique T.MessageCount___unnamed_12_d9c44df5:name;
+const unique T.Vector___unnamed_12_d9c44df5:name;
+const unique T.Affinity___unnamed_12_d9c44df5:name;
+const unique T.Start___unnamed_12_db3dcbfc:name;
+const unique T.Length___unnamed_12_db3dcbfc:name;
+const unique T.Reserved___unnamed_12_db3dcbfc:name;
+const unique T.Level___unnamed_12_fb26b3fc:name;
+const unique T.Vector___unnamed_12_fb26b3fc:name;
+const unique T.Affinity___unnamed_12_fb26b3fc:name;
+const unique T.OutputBufferLength___unnamed_16_22e4d054:name;
+const unique T.InputBufferLength___unnamed_16_22e4d054:name;
+const unique T.IoControlCode___unnamed_16_22e4d054:name;
+const unique T.Type3InputBuffer___unnamed_16_22e4d054:name;
+const unique T.Create___unnamed_16_39b626ad:name;
+const unique T.Read___unnamed_16_39b626ad:name;
+const unique T.Write___unnamed_16_39b626ad:name;
+const unique T.QueryDirectory___unnamed_16_39b626ad:name;
+const unique T.NotifyDirectory___unnamed_16_39b626ad:name;
+const unique T.QueryFile___unnamed_16_39b626ad:name;
+const unique T.SetFile___unnamed_16_39b626ad:name;
+const unique T.QueryEa___unnamed_16_39b626ad:name;
+const unique T.SetEa___unnamed_16_39b626ad:name;
+const unique T.QueryVolume___unnamed_16_39b626ad:name;
+const unique T.SetVolume___unnamed_16_39b626ad:name;
+const unique T.FileSystemControl___unnamed_16_39b626ad:name;
+const unique T.LockControl___unnamed_16_39b626ad:name;
+const unique T.DeviceIoControl___unnamed_16_39b626ad:name;
+const unique T.QuerySecurity___unnamed_16_39b626ad:name;
+const unique T.SetSecurity___unnamed_16_39b626ad:name;
+const unique T.MountVolume___unnamed_16_39b626ad:name;
+const unique T.VerifyVolume___unnamed_16_39b626ad:name;
+const unique T.Scsi___unnamed_16_39b626ad:name;
+const unique T.QueryQuota___unnamed_16_39b626ad:name;
+const unique T.SetQuota___unnamed_16_39b626ad:name;
+const unique T.QueryDeviceRelations___unnamed_16_39b626ad:name;
+const unique T.QueryInterface___unnamed_16_39b626ad:name;
+const unique T.DeviceCapabilities___unnamed_16_39b626ad:name;
+const unique T.FilterResourceRequirements___unnamed_16_39b626ad:name;
+const unique T.ReadWriteConfig___unnamed_16_39b626ad:name;
+const unique T.SetLock___unnamed_16_39b626ad:name;
+const unique T.QueryId___unnamed_16_39b626ad:name;
+const unique T.QueryDeviceText___unnamed_16_39b626ad:name;
+const unique T.UsageNotification___unnamed_16_39b626ad:name;
+const unique T.WaitWake___unnamed_16_39b626ad:name;
+const unique T.PowerSequence___unnamed_16_39b626ad:name;
+const unique T.Power___unnamed_16_39b626ad:name;
+const unique T.StartDevice___unnamed_16_39b626ad:name;
+const unique T.WMI___unnamed_16_39b626ad:name;
+const unique T.Others___unnamed_16_39b626ad:name;
+const unique T.WhichSpace___unnamed_16_56c011d7:name;
+const unique T.Buffer___unnamed_16_56c011d7:name;
+const unique T.Offset___unnamed_16_56c011d7:name;
+const unique T.Length___unnamed_16_56c011d7:name;
+const unique T.DeviceQueueEntry___unnamed_16_5fed8f23:name;
+const unique T.__unnamed_16_ae643f17___unnamed_16_5fed8f23:name;
+const unique T.Length___unnamed_16_6be9abe0:name;
+const unique T.FileName___unnamed_16_6be9abe0:name;
+const unique T.FileInformationClass___unnamed_16_6be9abe0:name;
+const unique T.FileIndex___unnamed_16_6be9abe0:name;
+const unique T.InterfaceType___unnamed_16_78879a38:name;
+const unique T.Size___unnamed_16_78879a38:name;
+const unique T.Version___unnamed_16_78879a38:name;
+const unique T.Interface___unnamed_16_78879a38:name;
+const unique T.InterfaceSpecificData___unnamed_16_78879a38:name;
+const unique T.Length___unnamed_16_804a2f24:name;
+const unique T.StartSid___unnamed_16_804a2f24:name;
+const unique T.SidList___unnamed_16_804a2f24:name;
+const unique T.SidListLength___unnamed_16_804a2f24:name;
+const unique T.Argument1___unnamed_16_8586693f:name;
+const unique T.Argument2___unnamed_16_8586693f:name;
+const unique T.Argument3___unnamed_16_8586693f:name;
+const unique T.Argument4___unnamed_16_8586693f:name;
+const unique T.Length___unnamed_16_8831e65f:name;
+const unique T.Key___unnamed_16_8831e65f:name;
+const unique T.ByteOffset___unnamed_16_8831e65f:name;
+const unique T.SecurityContext___unnamed_16_8c2d663a:name;
+const unique T.Options___unnamed_16_8c2d663a:name;
+const unique T.FileAttributes___unnamed_16_8c2d663a:name;
+const unique T.ShareAccess___unnamed_16_8c2d663a:name;
+const unique T.EaLength___unnamed_16_8c2d663a:name;
+const unique T.Length___unnamed_16_913b9a7a:name;
+const unique T.Key___unnamed_16_913b9a7a:name;
+const unique T.ByteOffset___unnamed_16_913b9a7a:name;
+const unique T.OutputBufferLength___unnamed_16_94d1d1c7:name;
+const unique T.InputBufferLength___unnamed_16_94d1d1c7:name;
+const unique T.FsControlCode___unnamed_16_94d1d1c7:name;
+const unique T.Type3InputBuffer___unnamed_16_94d1d1c7:name;
+const unique T.Length___unnamed_16_a2fab4da:name;
+const unique T.FileInformationClass___unnamed_16_a2fab4da:name;
+const unique T.FileObject___unnamed_16_a2fab4da:name;
+const unique T.__unnamed_4_a7d0864c___unnamed_16_a2fab4da:name;
+const unique T.DriverContext___unnamed_16_ae643f17:name;
+const unique T.Length___unnamed_16_c1b29316:name;
+const unique T.Key___unnamed_16_c1b29316:name;
+const unique T.ByteOffset___unnamed_16_c1b29316:name;
+const unique T.ProviderId___unnamed_16_cbd53ed4:name;
+const unique T.DataPath___unnamed_16_cbd53ed4:name;
+const unique T.BufferSize___unnamed_16_cbd53ed4:name;
+const unique T.Buffer___unnamed_16_cbd53ed4:name;
+const unique T.Length___unnamed_16_db70db6e:name;
+const unique T.MinBusNumber___unnamed_16_db70db6e:name;
+const unique T.MaxBusNumber___unnamed_16_db70db6e:name;
+const unique T.Reserved___unnamed_16_db70db6e:name;
+const unique T.Length___unnamed_16_ef4b6307:name;
+const unique T.EaList___unnamed_16_ef4b6307:name;
+const unique T.EaListLength___unnamed_16_ef4b6307:name;
+const unique T.EaIndex___unnamed_16_ef4b6307:name;
+const unique T.__unnamed_4_b060dea6___unnamed_16_fdda1f62:name;
+const unique T.Type___unnamed_16_fdda1f62:name;
+const unique T.State___unnamed_16_fdda1f62:name;
+const unique T.ShutdownType___unnamed_16_fdda1f62:name;
+const unique T.Lock___unnamed_1_1394de4b:name;
+const unique T.Abandoned___unnamed_1_2bb39c56:name;
+const unique T.Absolute___unnamed_1_2bb39c56:name;
+const unique T.NpxIrql___unnamed_1_2bb39c56:name;
+const unique T.Signalling___unnamed_1_2bb39c56:name;
+const unique T.Inserted___unnamed_1_9fa0583a:name;
+const unique T.DebugActive___unnamed_1_9fa0583a:name;
+const unique T.DpcActive___unnamed_1_9fa0583a:name;
+const unique T.Size___unnamed_1_e30779f5:name;
+const unique T.Hand___unnamed_1_e30779f5:name;
+const unique T.MinimumVector___unnamed_20_83d468e4:name;
+const unique T.MaximumVector___unnamed_20_83d468e4:name;
+const unique T.AffinityPolicy___unnamed_20_83d468e4:name;
+const unique T.PriorityPolicy___unnamed_20_83d468e4:name;
+const unique T.TargetedProcessors___unnamed_20_83d468e4:name;
+const unique T.Length40___unnamed_24_035931da:name;
+const unique T.Alignment40___unnamed_24_035931da:name;
+const unique T.MinimumAddress___unnamed_24_035931da:name;
+const unique T.MaximumAddress___unnamed_24_035931da:name;
+const unique T.Length___unnamed_24_38e128db:name;
+const unique T.Alignment___unnamed_24_38e128db:name;
+const unique T.MinimumAddress___unnamed_24_38e128db:name;
+const unique T.MaximumAddress___unnamed_24_38e128db:name;
+const unique T.Length___unnamed_24_9500ea34:name;
+const unique T.Alignment___unnamed_24_9500ea34:name;
+const unique T.MinimumAddress___unnamed_24_9500ea34:name;
+const unique T.MaximumAddress___unnamed_24_9500ea34:name;
+const unique T.Length___unnamed_24_9734802c:name;
+const unique T.Alignment___unnamed_24_9734802c:name;
+const unique T.MinimumAddress___unnamed_24_9734802c:name;
+const unique T.MaximumAddress___unnamed_24_9734802c:name;
+const unique T.Length64___unnamed_24_af62813f:name;
+const unique T.Alignment64___unnamed_24_af62813f:name;
+const unique T.MinimumAddress___unnamed_24_af62813f:name;
+const unique T.MaximumAddress___unnamed_24_af62813f:name;
+const unique T.Length48___unnamed_24_c0555099:name;
+const unique T.Alignment48___unnamed_24_c0555099:name;
+const unique T.MinimumAddress___unnamed_24_c0555099:name;
+const unique T.MaximumAddress___unnamed_24_c0555099:name;
+const unique T.Port___unnamed_24_d7c4ec3a:name;
+const unique T.Memory___unnamed_24_d7c4ec3a:name;
+const unique T.Interrupt___unnamed_24_d7c4ec3a:name;
+const unique T.Dma___unnamed_24_d7c4ec3a:name;
+const unique T.Generic___unnamed_24_d7c4ec3a:name;
+const unique T.DevicePrivate___unnamed_24_d7c4ec3a:name;
+const unique T.BusNumber___unnamed_24_d7c4ec3a:name;
+const unique T.ConfigData___unnamed_24_d7c4ec3a:name;
+const unique T.Memory40___unnamed_24_d7c4ec3a:name;
+const unique T.Memory48___unnamed_24_d7c4ec3a:name;
+const unique T.Memory64___unnamed_24_d7c4ec3a:name;
+const unique T.ReplaceIfExists___unnamed_2_196a7f56:name;
+const unique T.AdvanceOnly___unnamed_2_196a7f56:name;
+const unique T.__unnamed_16_5fed8f23___unnamed_40_a0414182:name;
+const unique T.Thread___unnamed_40_a0414182:name;
+const unique T.AuxiliaryBuffer___unnamed_40_a0414182:name;
+const unique T.__unnamed_12_c6ed93f3___unnamed_40_a0414182:name;
+const unique T.OriginalFileObject___unnamed_40_a0414182:name;
+const unique T.ListEntry___unnamed_40_d90496f4:name;
+const unique T.Wcb___unnamed_40_d90496f4:name;
+const unique T.InitialPrivilegeSet___unnamed_44_a7026dca:name;
+const unique T.PrivilegeSet___unnamed_44_a7026dca:name;
+const unique T.Overlay___unnamed_48_c1da9fa5:name;
+const unique T.Apc___unnamed_48_c1da9fa5:name;
+const unique T.CompletionKey___unnamed_48_c1da9fa5:name;
+const unique T.PowerSequence___unnamed_4_0510b147:name;
+const unique T.Length___unnamed_4_0a569078:name;
+const unique T.Status___unnamed_4_16aff58e:name;
+const unique T.Pointer___unnamed_4_16aff58e:name;
+const unique T.IdType___unnamed_4_40bf8e34:name;
+const unique T.Address___unnamed_4_46b62f69:name;
+const unique T.CreatorBackTraceIndex___unnamed_4_46b62f69:name;
+const unique T.Capabilities___unnamed_4_73d46255:name;
+const unique T.Srb___unnamed_4_765e3037:name;
+const unique T.Type___unnamed_4_846adf3f:name;
+const unique T.__unnamed_1_2bb39c56___unnamed_4_846adf3f:name;
+const unique T.__unnamed_1_e30779f5___unnamed_4_846adf3f:name;
+const unique T.__unnamed_1_9fa0583a___unnamed_4_846adf3f:name;
+const unique T.PowerState___unnamed_4_8dd73d30:name;
+const unique T.Type___unnamed_4_957e0d74:name;
+const unique T.Buttons___unnamed_4_9c11ed91:name;
+const unique T.__unnamed_4_b5247f10___unnamed_4_9c11ed91:name;
+const unique T.IoResourceRequirementList___unnamed_4_a58d40c8:name;
+const unique T.CurrentStackLocation___unnamed_4_a7aa989c:name;
+const unique T.PacketType___unnamed_4_a7aa989c:name;
+const unique T.__unnamed_2_196a7f56___unnamed_4_a7d0864c:name;
+const unique T.ClusterCount___unnamed_4_a7d0864c:name;
+const unique T.DeleteHandle___unnamed_4_a7d0864c:name;
+const unique T.Length___unnamed_4_aa20b426:name;
+const unique T.UserApcRoutine___unnamed_4_ab87ddfd:name;
+const unique T.IssuingProcess___unnamed_4_ab87ddfd:name;
+const unique T.Reserved1___unnamed_4_b016b1e1:name;
+const unique T.TargetSystemState___unnamed_4_b016b1e1:name;
+const unique T.EffectiveSystemState___unnamed_4_b016b1e1:name;
+const unique T.CurrentSystemState___unnamed_4_b016b1e1:name;
+const unique T.IgnoreHibernationPath___unnamed_4_b016b1e1:name;
+const unique T.PseudoTransition___unnamed_4_b016b1e1:name;
+const unique T.Reserved2___unnamed_4_b016b1e1:name;
+const unique T.SystemContext___unnamed_4_b060dea6:name;
+const unique T.SystemPowerStateContext___unnamed_4_b060dea6:name;
+const unique T.__unnamed_4_b016b1e1___unnamed_4_b4f5a780:name;
+const unique T.ContextAsUlong___unnamed_4_b4f5a780:name;
+const unique T.ButtonFlags___unnamed_4_b5247f10:name;
+const unique T.ButtonData___unnamed_4_b5247f10:name;
+const unique T.OwnerCount___unnamed_4_c1e23b02:name;
+const unique T.TableSize___unnamed_4_c1e23b02:name;
+const unique T.__unnamed_4_846adf3f___unnamed_4_c9b2e921:name;
+const unique T.Lock___unnamed_4_c9b2e921:name;
+const unique T.MasterIrp___unnamed_4_fa7b96a7:name;
+const unique T.IrpCount___unnamed_4_fa7b96a7:name;
+const unique T.SystemBuffer___unnamed_4_fa7b96a7:name;
+const unique T.Vpb___unnamed_8_09ad2712:name;
+const unique T.DeviceObject___unnamed_8_09ad2712:name;
+const unique T.Length___unnamed_8_21ac1dba:name;
+const unique T.CompletionFilter___unnamed_8_21ac1dba:name;
+const unique T.Length___unnamed_8_27d3ab76:name;
+const unique T.FsInformationClass___unnamed_8_27d3ab76:name;
+const unique T.Vpb___unnamed_8_4289df81:name;
+const unique T.DeviceObject___unnamed_8_4289df81:name;
+const unique T.Length___unnamed_8_47b72724:name;
+const unique T.FileInformationClass___unnamed_8_47b72724:name;
+const unique T.DeviceTextType___unnamed_8_4b3e3ba3:name;
+const unique T.LocaleId___unnamed_8_4b3e3ba3:name;
+const unique T.__unnamed_4_ab87ddfd___unnamed_8_4f695993:name;
+const unique T.UserApcContext___unnamed_8_4f695993:name;
+const unique T.AllocatedResources___unnamed_8_5cfb6ca4:name;
+const unique T.AllocatedResourcesTranslated___unnamed_8_5cfb6ca4:name;
+const unique T.SecurityInformation___unnamed_8_606438c5:name;
+const unique T.Length___unnamed_8_606438c5:name;
+const unique T.MinimumChannel___unnamed_8_6ad774c0:name;
+const unique T.MaximumChannel___unnamed_8_6ad774c0:name;
+const unique T.Length___unnamed_8_805045cb:name;
+const unique T.FsInformationClass___unnamed_8_805045cb:name;
+const unique T.LowPart___unnamed_8_8684a3e7:name;
+const unique T.HighPart___unnamed_8_8684a3e7:name;
+const unique T.SecurityInformation___unnamed_8_8cc410da:name;
+const unique T.SecurityDescriptor___unnamed_8_8cc410da:name;
+const unique T.InPath___unnamed_8_a47253e0:name;
+const unique T.Reserved___unnamed_8_a47253e0:name;
+const unique T.Type___unnamed_8_a47253e0:name;
+const unique T.AsynchronousParameters___unnamed_8_bbd07f6c:name;
+const unique T.AllocationSize___unnamed_8_bbd07f6c:name;
+const unique T.LowPart___unnamed_8_c9ca8234:name;
+const unique T.HighPart___unnamed_8_c9ca8234:name;
+
+// Type declarations
+
+const unique T.A1_CM_FULL_RESOURCE_DESCRIPTOR:name;
+const unique T.A1_CM_PARTIAL_RESOURCE_DESCRIPTOR:name;
+const unique T.A1_IO_RESOURCE_DESCRIPTOR:name;
+const unique T.A1_IO_RESOURCE_LIST:name;
+const unique T.A1_LUID_AND_ATTRIBUTES:name;
+const unique T.A256UINT2:name;
+const unique T.A28PFDRIVER_DISPATCH:name;
+const unique T.A2UCHAR:name;
+const unique T.A2UINT2:name;
+const unique T.A32UINT2:name;
+const unique T.A37CHAR:name;
+const unique T.A3UCHAR:name;
+const unique T.A3UINT4:name;
+const unique T.A3_LUID_AND_ATTRIBUTES:name;
+const unique T.A40CHAR:name;
+const unique T.A4PVOID:name;
+const unique T.A4UINT4:name;
+const unique T.A5_DEVICE_POWER_STATE:name;
+const unique T.A65CHAR:name;
+const unique T.A75CHAR:name;
+const unique T.A76CHAR:name;
+const unique T.A7UINT2:name;
+const unique T.A7_DEVICE_POWER_STATE:name;
+const unique T.A80CHAR:name;
+const unique T.A8UCHAR:name;
+const unique T.A9UINT2:name;
+const unique T.BUS_QUERY_ID_TYPE:name;
+const unique T.CHAR:name;
+const unique T.DEVICE_TEXT_TYPE:name;
+const unique T.F0:name;
+const unique T.F1:name;
+const unique T.F10:name;
+const unique T.F11:name;
+const unique T.F12:name;
+const unique T.F13:name;
+const unique T.F14:name;
+const unique T.F15:name;
+const unique T.F16:name;
+const unique T.F17:name;
+const unique T.F18:name;
+const unique T.F19:name;
+const unique T.F2:name;
+const unique T.F20:name;
+const unique T.F21:name;
+const unique T.F22:name;
+const unique T.F23:name;
+const unique T.F24:name;
+const unique T.F25:name;
+const unique T.F26:name;
+const unique T.F27:name;
+const unique T.F28:name;
+const unique T.F29:name;
+const unique T.F3:name;
+const unique T.F30:name;
+const unique T.F31:name;
+const unique T.F32:name;
+const unique T.F33:name;
+const unique T.F34:name;
+const unique T.F35:name;
+const unique T.F36:name;
+const unique T.F37:name;
+const unique T.F38:name;
+const unique T.F4:name;
+const unique T.F5:name;
+const unique T.F6:name;
+const unique T.F7:name;
+const unique T.F8:name;
+const unique T.F9:name;
+const unique T.FDRIVER_ADD_DEVICE:name;
+const unique T.FDRIVER_CANCEL:name;
+const unique T.FDRIVER_CONTROL:name;
+const unique T.FDRIVER_DISPATCH:name;
+const unique T.FDRIVER_INITIALIZE:name;
+const unique T.FDRIVER_STARTIO:name;
+const unique T.FDRIVER_UNLOAD:name;
+const unique T.FFAST_IO_ACQUIRE_FILE:name;
+const unique T.FFAST_IO_ACQUIRE_FOR_CCFLUSH:name;
+const unique T.FFAST_IO_ACQUIRE_FOR_MOD_WRITE:name;
+const unique T.FFAST_IO_CHECK_IF_POSSIBLE:name;
+const unique T.FFAST_IO_DETACH_DEVICE:name;
+const unique T.FFAST_IO_DEVICE_CONTROL:name;
+const unique T.FFAST_IO_LOCK:name;
+const unique T.FFAST_IO_MDL_READ:name;
+const unique T.FFAST_IO_MDL_READ_COMPLETE:name;
+const unique T.FFAST_IO_MDL_READ_COMPLETE_COMPRESSED:name;
+const unique T.FFAST_IO_MDL_WRITE_COMPLETE:name;
+const unique T.FFAST_IO_MDL_WRITE_COMPLETE_COMPRESSED:name;
+const unique T.FFAST_IO_PREPARE_MDL_WRITE:name;
+const unique T.FFAST_IO_QUERY_BASIC_INFO:name;
+const unique T.FFAST_IO_QUERY_NETWORK_OPEN_INFO:name;
+const unique T.FFAST_IO_QUERY_OPEN:name;
+const unique T.FFAST_IO_QUERY_STANDARD_INFO:name;
+const unique T.FFAST_IO_READ:name;
+const unique T.FFAST_IO_READ_COMPRESSED:name;
+const unique T.FFAST_IO_RELEASE_FILE:name;
+const unique T.FFAST_IO_RELEASE_FOR_CCFLUSH:name;
+const unique T.FFAST_IO_RELEASE_FOR_MOD_WRITE:name;
+const unique T.FFAST_IO_UNLOCK_ALL:name;
+const unique T.FFAST_IO_UNLOCK_ALL_BY_KEY:name;
+const unique T.FFAST_IO_UNLOCK_SINGLE:name;
+const unique T.FFAST_IO_WRITE:name;
+const unique T.FFAST_IO_WRITE_COMPRESSED:name;
+const unique T.FIO_COMPLETION_ROUTINE:name;
+const unique T.FKDEFERRED_ROUTINE:name;
+const unique T.INT2:name;
+const unique T.INT4:name;
+const unique T.INT8:name;
+const unique T.PA2UINT2:name;
+const unique T.PA37CHAR:name;
+const unique T.PA40CHAR:name;
+const unique T.PA4UINT4:name;
+const unique T.PA65CHAR:name;
+const unique T.PA75CHAR:name;
+const unique T.PA76CHAR:name;
+const unique T.PA7UINT2:name;
+const unique T.PA80CHAR:name;
+const unique T.PA9UINT2:name;
+const unique T.PCHAR:name;
+const unique T.PF19:name;
+const unique T.PF21:name;
+const unique T.PF23:name;
+const unique T.PF24:name;
+const unique T.PF25:name;
+const unique T.PF33:name;
+const unique T.PF34:name;
+const unique T.PF35:name;
+const unique T.PF36:name;
+const unique T.PF37:name;
+const unique T.PF38:name;
+const unique T.PFDRIVER_ADD_DEVICE:name;
+const unique T.PFDRIVER_CANCEL:name;
+const unique T.PFDRIVER_CONTROL:name;
+const unique T.PFDRIVER_DISPATCH:name;
+const unique T.PFDRIVER_INITIALIZE:name;
+const unique T.PFDRIVER_STARTIO:name;
+const unique T.PFDRIVER_UNLOAD:name;
+const unique T.PFFAST_IO_ACQUIRE_FILE:name;
+const unique T.PFFAST_IO_ACQUIRE_FOR_CCFLUSH:name;
+const unique T.PFFAST_IO_ACQUIRE_FOR_MOD_WRITE:name;
+const unique T.PFFAST_IO_CHECK_IF_POSSIBLE:name;
+const unique T.PFFAST_IO_DETACH_DEVICE:name;
+const unique T.PFFAST_IO_DEVICE_CONTROL:name;
+const unique T.PFFAST_IO_LOCK:name;
+const unique T.PFFAST_IO_MDL_READ:name;
+const unique T.PFFAST_IO_MDL_READ_COMPLETE:name;
+const unique T.PFFAST_IO_MDL_READ_COMPLETE_COMPRESSED:name;
+const unique T.PFFAST_IO_MDL_WRITE_COMPLETE:name;
+const unique T.PFFAST_IO_MDL_WRITE_COMPLETE_COMPRESSED:name;
+const unique T.PFFAST_IO_PREPARE_MDL_WRITE:name;
+const unique T.PFFAST_IO_QUERY_BASIC_INFO:name;
+const unique T.PFFAST_IO_QUERY_NETWORK_OPEN_INFO:name;
+const unique T.PFFAST_IO_QUERY_OPEN:name;
+const unique T.PFFAST_IO_QUERY_STANDARD_INFO:name;
+const unique T.PFFAST_IO_READ:name;
+const unique T.PFFAST_IO_READ_COMPRESSED:name;
+const unique T.PFFAST_IO_RELEASE_FILE:name;
+const unique T.PFFAST_IO_RELEASE_FOR_CCFLUSH:name;
+const unique T.PFFAST_IO_RELEASE_FOR_MOD_WRITE:name;
+const unique T.PFFAST_IO_UNLOCK_ALL:name;
+const unique T.PFFAST_IO_UNLOCK_ALL_BY_KEY:name;
+const unique T.PFFAST_IO_UNLOCK_SINGLE:name;
+const unique T.PFFAST_IO_WRITE:name;
+const unique T.PFFAST_IO_WRITE_COMPRESSED:name;
+const unique T.PFIO_COMPLETION_ROUTINE:name;
+const unique T.PFKDEFERRED_ROUTINE:name;
+const unique T.PINT4:name;
+const unique T.POWER_ACTION:name;
+const unique T.PPCHAR:name;
+const unique T.PPF24:name;
+const unique T.PPPUINT2:name;
+const unique T.PPP_DEVICE_OBJECT:name;
+const unique T.PPUINT2:name;
+const unique T.PPUINT4:name;
+const unique T.PPVOID:name;
+const unique T.PP_DEVICE_EXTENSION:name;
+const unique T.PP_DEVICE_OBJECT:name;
+const unique T.PP_DRIVER_OBJECT:name;
+const unique T.PP_ERESOURCE:name;
+const unique T.PP_FAST_MUTEX:name;
+const unique T.PP_IO_REMOVE_LOCK:name;
+const unique T.PP_LIST_ENTRY:name;
+const unique T.PP_MDL:name;
+const unique T.PP_UNICODE_STRING:name;
+const unique T.PUCHAR:name;
+const unique T.PUINT2:name;
+const unique T.PUINT4:name;
+const unique T.PVOID:name;
+const unique T.PWMIGUIDREGINFO:name;
+const unique T.P_ACCESS_STATE:name;
+const unique T.P_CM_RESOURCE_LIST:name;
+const unique T.P_COMPRESSED_DATA_INFO:name;
+const unique T.P_DEVICE_CAPABILITIES:name;
+const unique T.P_DEVICE_EXTENSION:name;
+const unique T.P_DEVICE_OBJECT:name;
+const unique T.P_DEVOBJ_EXTENSION:name;
+const unique T.P_DRIVER_EXTENSION:name;
+const unique T.P_DRIVER_OBJECT:name;
+const unique T.P_EPROCESS:name;
+const unique T.P_ERESOURCE:name;
+const unique T.P_ETHREAD:name;
+const unique T.P_FAST_IO_DISPATCH:name;
+const unique T.P_FAST_MUTEX:name;
+const unique T.P_FILE_BASIC_INFORMATION:name;
+const unique T.P_FILE_GET_QUOTA_INFORMATION:name;
+const unique T.P_FILE_NETWORK_OPEN_INFORMATION:name;
+const unique T.P_FILE_OBJECT:name;
+const unique T.P_FILE_STANDARD_INFORMATION:name;
+const unique T.P_GLOBALS:name;
+const unique T.P_GUID:name;
+const unique T.P_INTERFACE:name;
+const unique T.P_IO_COMPLETION_CONTEXT:name;
+const unique T.P_IO_REMOVE_LOCK:name;
+const unique T.P_IO_REMOVE_LOCK_TRACKING_BLOCK:name;
+const unique T.P_IO_RESOURCE_REQUIREMENTS_LIST:name;
+const unique T.P_IO_SECURITY_CONTEXT:name;
+const unique T.P_IO_STACK_LOCATION:name;
+const unique T.P_IO_STATUS_BLOCK:name;
+const unique T.P_IO_TIMER:name;
+const unique T.P_IRP:name;
+const unique T.P_KAPC:name;
+const unique T.P_KDPC:name;
+const unique T.P_KEVENT:name;
+const unique T.P_KSEMAPHORE:name;
+const unique T.P_KTHREAD:name;
+const unique T.P_LARGE_INTEGER:name;
+const unique T.P_LIST_ENTRY:name;
+const unique T.P_MDL:name;
+const unique T.P_MOUSE_INPUT_DATA:name;
+const unique T.P_OWNER_ENTRY:name;
+const unique T.P_POOL_TYPE:name;
+const unique T.P_PORT:name;
+const unique T.P_POWER_SEQUENCE:name;
+const unique T.P_SCSI_REQUEST_BLOCK:name;
+const unique T.P_SECTION_OBJECT_POINTERS:name;
+const unique T.P_SECURITY_QUALITY_OF_SERVICE:name;
+const unique T.P_UNICODE_STRING:name;
+const unique T.P_VPB:name;
+const unique T.UCHAR:name;
+const unique T.UINT2:name;
+const unique T.UINT4:name;
+const unique T.VOID:name;
+const unique T.WMIENABLEDISABLECONTROL:name;
+const unique T.WMIGUIDREGINFO:name;
+const unique T._ACCESS_STATE:name;
+const unique T._CM_FULL_RESOURCE_DESCRIPTOR:name;
+const unique T._CM_PARTIAL_RESOURCE_DESCRIPTOR:name;
+const unique T._CM_PARTIAL_RESOURCE_LIST:name;
+const unique T._CM_RESOURCE_LIST:name;
+const unique T._COMPRESSED_DATA_INFO:name;
+const unique T._DEVICE_CAPABILITIES:name;
+const unique T._DEVICE_EXTENSION:name;
+const unique T._DEVICE_OBJECT:name;
+const unique T._DEVICE_POWER_STATE:name;
+const unique T._DEVICE_RELATION_TYPE:name;
+const unique T._DEVICE_USAGE_NOTIFICATION_TYPE:name;
+const unique T._DEVOBJ_EXTENSION:name;
+const unique T._DISPATCHER_HEADER:name;
+const unique T._DRIVER_EXTENSION:name;
+const unique T._DRIVER_OBJECT:name;
+const unique T._EPROCESS:name;
+const unique T._ERESOURCE:name;
+const unique T._ETHREAD:name;
+const unique T._FAST_IO_DISPATCH:name;
+const unique T._FAST_MUTEX:name;
+const unique T._FILE_BASIC_INFORMATION:name;
+const unique T._FILE_GET_QUOTA_INFORMATION:name;
+const unique T._FILE_INFORMATION_CLASS:name;
+const unique T._FILE_NETWORK_OPEN_INFORMATION:name;
+const unique T._FILE_OBJECT:name;
+const unique T._FILE_STANDARD_INFORMATION:name;
+const unique T._FSINFOCLASS:name;
+const unique T._GLOBALS:name;
+const unique T._GUID:name;
+const unique T._INITIAL_PRIVILEGE_SET:name;
+const unique T._INTERFACE:name;
+const unique T._INTERFACE_TYPE:name;
+const unique T._IO_ALLOCATION_ACTION:name;
+const unique T._IO_COMPLETION_CONTEXT:name;
+const unique T._IO_REMOVE_LOCK:name;
+const unique T._IO_REMOVE_LOCK_COMMON_BLOCK:name;
+const unique T._IO_REMOVE_LOCK_DBG_BLOCK:name;
+const unique T._IO_REMOVE_LOCK_TRACKING_BLOCK:name;
+const unique T._IO_RESOURCE_DESCRIPTOR:name;
+const unique T._IO_RESOURCE_LIST:name;
+const unique T._IO_RESOURCE_REQUIREMENTS_LIST:name;
+const unique T._IO_SECURITY_CONTEXT:name;
+const unique T._IO_STACK_LOCATION:name;
+const unique T._IO_STATUS_BLOCK:name;
+const unique T._IO_TIMER:name;
+const unique T._IRP:name;
+const unique T._IRQ_DEVICE_POLICY:name;
+const unique T._IRQ_PRIORITY:name;
+const unique T._KAPC:name;
+const unique T._KDEVICE_QUEUE:name;
+const unique T._KDEVICE_QUEUE_ENTRY:name;
+const unique T._KDPC:name;
+const unique T._KEVENT:name;
+const unique T._KSEMAPHORE:name;
+const unique T._KTHREAD:name;
+const unique T._LARGE_INTEGER:name;
+const unique T._LIST_ENTRY:name;
+const unique T._LUID:name;
+const unique T._LUID_AND_ATTRIBUTES:name;
+const unique T._MDL:name;
+const unique T._MOUSE_ATTRIBUTES:name;
+const unique T._MOUSE_INPUT_DATA:name;
+const unique T._OWNER_ENTRY:name;
+const unique T._POOL_TYPE:name;
+const unique T._PORT:name;
+const unique T._POWER_SEQUENCE:name;
+const unique T._POWER_STATE:name;
+const unique T._POWER_STATE_TYPE:name;
+const unique T._PRIVILEGE_SET:name;
+const unique T._SCSI_REQUEST_BLOCK:name;
+const unique T._SECTION_OBJECT_POINTERS:name;
+const unique T._SECURITY_IMPERSONATION_LEVEL:name;
+const unique T._SECURITY_QUALITY_OF_SERVICE:name;
+const unique T._SECURITY_SUBJECT_CONTEXT:name;
+const unique T._SYSTEM_POWER_STATE:name;
+const unique T._SYSTEM_POWER_STATE_CONTEXT:name;
+const unique T._UNICODE_STRING:name;
+const unique T._VPB:name;
+const unique T._WAIT_CONTEXT_BLOCK:name;
+const unique T._WMILIB_CONTEXT:name;
+const unique T.__unnamed_12_06b9ee6e:name;
+const unique T.__unnamed_12_0882bd02:name;
+const unique T.__unnamed_12_264d0dab:name;
+const unique T.__unnamed_12_2e80217b:name;
+const unique T.__unnamed_12_5cc7ace2:name;
+const unique T.__unnamed_12_6374506e:name;
+const unique T.__unnamed_12_68a4278e:name;
+const unique T.__unnamed_12_79ed2653:name;
+const unique T.__unnamed_12_7da594c0:name;
+const unique T.__unnamed_12_9873e05d:name;
+const unique T.__unnamed_12_9cc8cebc:name;
+const unique T.__unnamed_12_b98da82e:name;
+const unique T.__unnamed_12_c2880e88:name;
+const unique T.__unnamed_12_c49ab31a:name;
+const unique T.__unnamed_12_c6ed93f3:name;
+const unique T.__unnamed_12_ced61554:name;
+const unique T.__unnamed_12_d9c44df5:name;
+const unique T.__unnamed_12_db3dcbfc:name;
+const unique T.__unnamed_12_fb26b3fc:name;
+const unique T.__unnamed_16_22e4d054:name;
+const unique T.__unnamed_16_39b626ad:name;
+const unique T.__unnamed_16_56c011d7:name;
+const unique T.__unnamed_16_5fed8f23:name;
+const unique T.__unnamed_16_6be9abe0:name;
+const unique T.__unnamed_16_78879a38:name;
+const unique T.__unnamed_16_804a2f24:name;
+const unique T.__unnamed_16_8586693f:name;
+const unique T.__unnamed_16_8831e65f:name;
+const unique T.__unnamed_16_8c2d663a:name;
+const unique T.__unnamed_16_913b9a7a:name;
+const unique T.__unnamed_16_94d1d1c7:name;
+const unique T.__unnamed_16_a2fab4da:name;
+const unique T.__unnamed_16_ae643f17:name;
+const unique T.__unnamed_16_c1b29316:name;
+const unique T.__unnamed_16_cbd53ed4:name;
+const unique T.__unnamed_16_db70db6e:name;
+const unique T.__unnamed_16_ef4b6307:name;
+const unique T.__unnamed_16_fdda1f62:name;
+const unique T.__unnamed_1_1394de4b:name;
+const unique T.__unnamed_1_2bb39c56:name;
+const unique T.__unnamed_1_9fa0583a:name;
+const unique T.__unnamed_1_e30779f5:name;
+const unique T.__unnamed_20_83d468e4:name;
+const unique T.__unnamed_24_035931da:name;
+const unique T.__unnamed_24_38e128db:name;
+const unique T.__unnamed_24_9500ea34:name;
+const unique T.__unnamed_24_9734802c:name;
+const unique T.__unnamed_24_af62813f:name;
+const unique T.__unnamed_24_c0555099:name;
+const unique T.__unnamed_24_d7c4ec3a:name;
+const unique T.__unnamed_2_196a7f56:name;
+const unique T.__unnamed_40_a0414182:name;
+const unique T.__unnamed_40_d90496f4:name;
+const unique T.__unnamed_44_a7026dca:name;
+const unique T.__unnamed_48_c1da9fa5:name;
+const unique T.__unnamed_4_0510b147:name;
+const unique T.__unnamed_4_0a569078:name;
+const unique T.__unnamed_4_16aff58e:name;
+const unique T.__unnamed_4_40bf8e34:name;
+const unique T.__unnamed_4_46b62f69:name;
+const unique T.__unnamed_4_73d46255:name;
+const unique T.__unnamed_4_765e3037:name;
+const unique T.__unnamed_4_846adf3f:name;
+const unique T.__unnamed_4_8dd73d30:name;
+const unique T.__unnamed_4_957e0d74:name;
+const unique T.__unnamed_4_9c11ed91:name;
+const unique T.__unnamed_4_a58d40c8:name;
+const unique T.__unnamed_4_a7aa989c:name;
+const unique T.__unnamed_4_a7d0864c:name;
+const unique T.__unnamed_4_aa20b426:name;
+const unique T.__unnamed_4_ab87ddfd:name;
+const unique T.__unnamed_4_b016b1e1:name;
+const unique T.__unnamed_4_b060dea6:name;
+const unique T.__unnamed_4_b4f5a780:name;
+const unique T.__unnamed_4_b5247f10:name;
+const unique T.__unnamed_4_c1e23b02:name;
+const unique T.__unnamed_4_c9b2e921:name;
+const unique T.__unnamed_4_fa7b96a7:name;
+const unique T.__unnamed_8_09ad2712:name;
+const unique T.__unnamed_8_21ac1dba:name;
+const unique T.__unnamed_8_27d3ab76:name;
+const unique T.__unnamed_8_4289df81:name;
+const unique T.__unnamed_8_47b72724:name;
+const unique T.__unnamed_8_4b3e3ba3:name;
+const unique T.__unnamed_8_4f695993:name;
+const unique T.__unnamed_8_5cfb6ca4:name;
+const unique T.__unnamed_8_606438c5:name;
+const unique T.__unnamed_8_6ad774c0:name;
+const unique T.__unnamed_8_805045cb:name;
+const unique T.__unnamed_8_8684a3e7:name;
+const unique T.__unnamed_8_8cc410da:name;
+const unique T.__unnamed_8_a47253e0:name;
+const unique T.__unnamed_8_bbd07f6c:name;
+const unique T.__unnamed_8_c9ca8234:name;
+
+function Abandoned___unnamed_1_2bb39c56(int) returns (int);
+function Abandoned___unnamed_1_2bb39c56Inv(int) returns (int);
+function _S_Abandoned___unnamed_1_2bb39c56([int]bool) returns ([int]bool);
+function _S_Abandoned___unnamed_1_2bb39c56Inv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {Abandoned___unnamed_1_2bb39c56Inv(Abandoned___unnamed_1_2bb39c56(x))} Abandoned___unnamed_1_2bb39c56Inv(Abandoned___unnamed_1_2bb39c56(x)) == x);
+axiom (forall x:int :: {Abandoned___unnamed_1_2bb39c56Inv(x)} Abandoned___unnamed_1_2bb39c56(Abandoned___unnamed_1_2bb39c56Inv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_Abandoned___unnamed_1_2bb39c56(S)[x]} _S_Abandoned___unnamed_1_2bb39c56(S)[x] <==> S[Abandoned___unnamed_1_2bb39c56Inv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_Abandoned___unnamed_1_2bb39c56Inv(S)[x]} _S_Abandoned___unnamed_1_2bb39c56Inv(S)[x] <==> S[Abandoned___unnamed_1_2bb39c56(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Abandoned___unnamed_1_2bb39c56(S)} S[x] ==> _S_Abandoned___unnamed_1_2bb39c56(S)[Abandoned___unnamed_1_2bb39c56(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Abandoned___unnamed_1_2bb39c56Inv(S)} S[x] ==> _S_Abandoned___unnamed_1_2bb39c56Inv(S)[Abandoned___unnamed_1_2bb39c56Inv(x)]);
+
+axiom (forall x:int :: {Abandoned___unnamed_1_2bb39c56(x)} Abandoned___unnamed_1_2bb39c56(x) == x + 0);
+axiom (forall x:int :: {Abandoned___unnamed_1_2bb39c56Inv(x)} Abandoned___unnamed_1_2bb39c56Inv(x) == x - 0);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1) == Abandoned___unnamed_1_2bb39c56Inv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 0)} MINUS_LEFT_PTR(x, 1, 0) == Abandoned___unnamed_1_2bb39c56Inv(x));
+function Absolute___unnamed_1_2bb39c56(int) returns (int);
+function Absolute___unnamed_1_2bb39c56Inv(int) returns (int);
+function _S_Absolute___unnamed_1_2bb39c56([int]bool) returns ([int]bool);
+function _S_Absolute___unnamed_1_2bb39c56Inv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {Absolute___unnamed_1_2bb39c56Inv(Absolute___unnamed_1_2bb39c56(x))} Absolute___unnamed_1_2bb39c56Inv(Absolute___unnamed_1_2bb39c56(x)) == x);
+axiom (forall x:int :: {Absolute___unnamed_1_2bb39c56Inv(x)} Absolute___unnamed_1_2bb39c56(Absolute___unnamed_1_2bb39c56Inv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_Absolute___unnamed_1_2bb39c56(S)[x]} _S_Absolute___unnamed_1_2bb39c56(S)[x] <==> S[Absolute___unnamed_1_2bb39c56Inv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_Absolute___unnamed_1_2bb39c56Inv(S)[x]} _S_Absolute___unnamed_1_2bb39c56Inv(S)[x] <==> S[Absolute___unnamed_1_2bb39c56(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Absolute___unnamed_1_2bb39c56(S)} S[x] ==> _S_Absolute___unnamed_1_2bb39c56(S)[Absolute___unnamed_1_2bb39c56(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Absolute___unnamed_1_2bb39c56Inv(S)} S[x] ==> _S_Absolute___unnamed_1_2bb39c56Inv(S)[Absolute___unnamed_1_2bb39c56Inv(x)]);
+
+axiom (forall x:int :: {Absolute___unnamed_1_2bb39c56(x)} Absolute___unnamed_1_2bb39c56(x) == x + 0);
+axiom (forall x:int :: {Absolute___unnamed_1_2bb39c56Inv(x)} Absolute___unnamed_1_2bb39c56Inv(x) == x - 0);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1) == Absolute___unnamed_1_2bb39c56Inv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 0)} MINUS_LEFT_PTR(x, 1, 0) == Absolute___unnamed_1_2bb39c56Inv(x));
+function AllocateTag__IO_REMOVE_LOCK_DBG_BLOCK(int) returns (int);
+function AllocateTag__IO_REMOVE_LOCK_DBG_BLOCKInv(int) returns (int);
+function _S_AllocateTag__IO_REMOVE_LOCK_DBG_BLOCK([int]bool) returns ([int]bool);
+function _S_AllocateTag__IO_REMOVE_LOCK_DBG_BLOCKInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {AllocateTag__IO_REMOVE_LOCK_DBG_BLOCKInv(AllocateTag__IO_REMOVE_LOCK_DBG_BLOCK(x))} AllocateTag__IO_REMOVE_LOCK_DBG_BLOCKInv(AllocateTag__IO_REMOVE_LOCK_DBG_BLOCK(x)) == x);
+axiom (forall x:int :: {AllocateTag__IO_REMOVE_LOCK_DBG_BLOCKInv(x)} AllocateTag__IO_REMOVE_LOCK_DBG_BLOCK(AllocateTag__IO_REMOVE_LOCK_DBG_BLOCKInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_AllocateTag__IO_REMOVE_LOCK_DBG_BLOCK(S)[x]} _S_AllocateTag__IO_REMOVE_LOCK_DBG_BLOCK(S)[x] <==> S[AllocateTag__IO_REMOVE_LOCK_DBG_BLOCKInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_AllocateTag__IO_REMOVE_LOCK_DBG_BLOCKInv(S)[x]} _S_AllocateTag__IO_REMOVE_LOCK_DBG_BLOCKInv(S)[x] <==> S[AllocateTag__IO_REMOVE_LOCK_DBG_BLOCK(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_AllocateTag__IO_REMOVE_LOCK_DBG_BLOCK(S)} S[x] ==> _S_AllocateTag__IO_REMOVE_LOCK_DBG_BLOCK(S)[AllocateTag__IO_REMOVE_LOCK_DBG_BLOCK(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_AllocateTag__IO_REMOVE_LOCK_DBG_BLOCKInv(S)} S[x] ==> _S_AllocateTag__IO_REMOVE_LOCK_DBG_BLOCKInv(S)[AllocateTag__IO_REMOVE_LOCK_DBG_BLOCKInv(x)]);
+
+axiom (forall x:int :: {AllocateTag__IO_REMOVE_LOCK_DBG_BLOCK(x)} AllocateTag__IO_REMOVE_LOCK_DBG_BLOCK(x) == x + 16);
+axiom (forall x:int :: {AllocateTag__IO_REMOVE_LOCK_DBG_BLOCKInv(x)} AllocateTag__IO_REMOVE_LOCK_DBG_BLOCKInv(x) == x - 16);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 16, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 16, 1) == AllocateTag__IO_REMOVE_LOCK_DBG_BLOCKInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 16)} MINUS_LEFT_PTR(x, 1, 16) == AllocateTag__IO_REMOVE_LOCK_DBG_BLOCKInv(x));
+function BaseClassName__GLOBALS(int) returns (int);
+function BaseClassName__GLOBALSInv(int) returns (int);
+function _S_BaseClassName__GLOBALS([int]bool) returns ([int]bool);
+function _S_BaseClassName__GLOBALSInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {BaseClassName__GLOBALSInv(BaseClassName__GLOBALS(x))} BaseClassName__GLOBALSInv(BaseClassName__GLOBALS(x)) == x);
+axiom (forall x:int :: {BaseClassName__GLOBALSInv(x)} BaseClassName__GLOBALS(BaseClassName__GLOBALSInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_BaseClassName__GLOBALS(S)[x]} _S_BaseClassName__GLOBALS(S)[x] <==> S[BaseClassName__GLOBALSInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_BaseClassName__GLOBALSInv(S)[x]} _S_BaseClassName__GLOBALSInv(S)[x] <==> S[BaseClassName__GLOBALS(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_BaseClassName__GLOBALS(S)} S[x] ==> _S_BaseClassName__GLOBALS(S)[BaseClassName__GLOBALS(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_BaseClassName__GLOBALSInv(S)} S[x] ==> _S_BaseClassName__GLOBALSInv(S)[BaseClassName__GLOBALSInv(x)]);
+
+axiom (forall x:int :: {BaseClassName__GLOBALS(x)} BaseClassName__GLOBALS(x) == x + 344);
+axiom (forall x:int :: {BaseClassName__GLOBALSInv(x)} BaseClassName__GLOBALSInv(x) == x - 344);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 344, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 344, 1) == BaseClassName__GLOBALSInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 344)} MINUS_LEFT_PTR(x, 1, 344) == BaseClassName__GLOBALSInv(x));
+function Blink__LIST_ENTRY(int) returns (int);
+function Blink__LIST_ENTRYInv(int) returns (int);
+function _S_Blink__LIST_ENTRY([int]bool) returns ([int]bool);
+function _S_Blink__LIST_ENTRYInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {Blink__LIST_ENTRYInv(Blink__LIST_ENTRY(x))} Blink__LIST_ENTRYInv(Blink__LIST_ENTRY(x)) == x);
+axiom (forall x:int :: {Blink__LIST_ENTRYInv(x)} Blink__LIST_ENTRY(Blink__LIST_ENTRYInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_Blink__LIST_ENTRY(S)[x]} _S_Blink__LIST_ENTRY(S)[x] <==> S[Blink__LIST_ENTRYInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_Blink__LIST_ENTRYInv(S)[x]} _S_Blink__LIST_ENTRYInv(S)[x] <==> S[Blink__LIST_ENTRY(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Blink__LIST_ENTRY(S)} S[x] ==> _S_Blink__LIST_ENTRY(S)[Blink__LIST_ENTRY(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Blink__LIST_ENTRYInv(S)} S[x] ==> _S_Blink__LIST_ENTRYInv(S)[Blink__LIST_ENTRYInv(x)]);
+
+axiom (forall x:int :: {Blink__LIST_ENTRY(x)} Blink__LIST_ENTRY(x) == x + 4);
+axiom (forall x:int :: {Blink__LIST_ENTRYInv(x)} Blink__LIST_ENTRYInv(x) == x - 4);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 4, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 4, 1) == Blink__LIST_ENTRYInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 4)} MINUS_LEFT_PTR(x, 1, 4) == Blink__LIST_ENTRYInv(x));
+function Blocks__IO_REMOVE_LOCK_DBG_BLOCK(int) returns (int);
+function Blocks__IO_REMOVE_LOCK_DBG_BLOCKInv(int) returns (int);
+function _S_Blocks__IO_REMOVE_LOCK_DBG_BLOCK([int]bool) returns ([int]bool);
+function _S_Blocks__IO_REMOVE_LOCK_DBG_BLOCKInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {Blocks__IO_REMOVE_LOCK_DBG_BLOCKInv(Blocks__IO_REMOVE_LOCK_DBG_BLOCK(x))} Blocks__IO_REMOVE_LOCK_DBG_BLOCKInv(Blocks__IO_REMOVE_LOCK_DBG_BLOCK(x)) == x);
+axiom (forall x:int :: {Blocks__IO_REMOVE_LOCK_DBG_BLOCKInv(x)} Blocks__IO_REMOVE_LOCK_DBG_BLOCK(Blocks__IO_REMOVE_LOCK_DBG_BLOCKInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_Blocks__IO_REMOVE_LOCK_DBG_BLOCK(S)[x]} _S_Blocks__IO_REMOVE_LOCK_DBG_BLOCK(S)[x] <==> S[Blocks__IO_REMOVE_LOCK_DBG_BLOCKInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_Blocks__IO_REMOVE_LOCK_DBG_BLOCKInv(S)[x]} _S_Blocks__IO_REMOVE_LOCK_DBG_BLOCKInv(S)[x] <==> S[Blocks__IO_REMOVE_LOCK_DBG_BLOCK(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Blocks__IO_REMOVE_LOCK_DBG_BLOCK(S)} S[x] ==> _S_Blocks__IO_REMOVE_LOCK_DBG_BLOCK(S)[Blocks__IO_REMOVE_LOCK_DBG_BLOCK(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Blocks__IO_REMOVE_LOCK_DBG_BLOCKInv(S)} S[x] ==> _S_Blocks__IO_REMOVE_LOCK_DBG_BLOCKInv(S)[Blocks__IO_REMOVE_LOCK_DBG_BLOCKInv(x)]);
+
+axiom (forall x:int :: {Blocks__IO_REMOVE_LOCK_DBG_BLOCK(x)} Blocks__IO_REMOVE_LOCK_DBG_BLOCK(x) == x + 56);
+axiom (forall x:int :: {Blocks__IO_REMOVE_LOCK_DBG_BLOCKInv(x)} Blocks__IO_REMOVE_LOCK_DBG_BLOCKInv(x) == x - 56);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 56, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 56, 1) == Blocks__IO_REMOVE_LOCK_DBG_BLOCKInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 56)} MINUS_LEFT_PTR(x, 1, 56) == Blocks__IO_REMOVE_LOCK_DBG_BLOCKInv(x));
+function Buffer__UNICODE_STRING(int) returns (int);
+function Buffer__UNICODE_STRINGInv(int) returns (int);
+function _S_Buffer__UNICODE_STRING([int]bool) returns ([int]bool);
+function _S_Buffer__UNICODE_STRINGInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {Buffer__UNICODE_STRINGInv(Buffer__UNICODE_STRING(x))} Buffer__UNICODE_STRINGInv(Buffer__UNICODE_STRING(x)) == x);
+axiom (forall x:int :: {Buffer__UNICODE_STRINGInv(x)} Buffer__UNICODE_STRING(Buffer__UNICODE_STRINGInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_Buffer__UNICODE_STRING(S)[x]} _S_Buffer__UNICODE_STRING(S)[x] <==> S[Buffer__UNICODE_STRINGInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_Buffer__UNICODE_STRINGInv(S)[x]} _S_Buffer__UNICODE_STRINGInv(S)[x] <==> S[Buffer__UNICODE_STRING(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Buffer__UNICODE_STRING(S)} S[x] ==> _S_Buffer__UNICODE_STRING(S)[Buffer__UNICODE_STRING(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Buffer__UNICODE_STRINGInv(S)} S[x] ==> _S_Buffer__UNICODE_STRINGInv(S)[Buffer__UNICODE_STRINGInv(x)]);
+
+axiom (forall x:int :: {Buffer__UNICODE_STRING(x)} Buffer__UNICODE_STRING(x) == x + 4);
+axiom (forall x:int :: {Buffer__UNICODE_STRINGInv(x)} Buffer__UNICODE_STRINGInv(x) == x - 4);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 4, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 4, 1) == Buffer__UNICODE_STRINGInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 4)} MINUS_LEFT_PTR(x, 1, 4) == Buffer__UNICODE_STRINGInv(x));
+function Common__IO_REMOVE_LOCK(int) returns (int);
+function Common__IO_REMOVE_LOCKInv(int) returns (int);
+function _S_Common__IO_REMOVE_LOCK([int]bool) returns ([int]bool);
+function _S_Common__IO_REMOVE_LOCKInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {Common__IO_REMOVE_LOCKInv(Common__IO_REMOVE_LOCK(x))} Common__IO_REMOVE_LOCKInv(Common__IO_REMOVE_LOCK(x)) == x);
+axiom (forall x:int :: {Common__IO_REMOVE_LOCKInv(x)} Common__IO_REMOVE_LOCK(Common__IO_REMOVE_LOCKInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_Common__IO_REMOVE_LOCK(S)[x]} _S_Common__IO_REMOVE_LOCK(S)[x] <==> S[Common__IO_REMOVE_LOCKInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_Common__IO_REMOVE_LOCKInv(S)[x]} _S_Common__IO_REMOVE_LOCKInv(S)[x] <==> S[Common__IO_REMOVE_LOCK(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Common__IO_REMOVE_LOCK(S)} S[x] ==> _S_Common__IO_REMOVE_LOCK(S)[Common__IO_REMOVE_LOCK(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Common__IO_REMOVE_LOCKInv(S)} S[x] ==> _S_Common__IO_REMOVE_LOCKInv(S)[Common__IO_REMOVE_LOCKInv(x)]);
+
+axiom (forall x:int :: {Common__IO_REMOVE_LOCK(x)} Common__IO_REMOVE_LOCK(x) == x + 0);
+axiom (forall x:int :: {Common__IO_REMOVE_LOCKInv(x)} Common__IO_REMOVE_LOCKInv(x) == x - 0);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1) == Common__IO_REMOVE_LOCKInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 0)} MINUS_LEFT_PTR(x, 1, 0) == Common__IO_REMOVE_LOCKInv(x));
+function ConnectOneClassToOnePort__GLOBALS(int) returns (int);
+function ConnectOneClassToOnePort__GLOBALSInv(int) returns (int);
+function _S_ConnectOneClassToOnePort__GLOBALS([int]bool) returns ([int]bool);
+function _S_ConnectOneClassToOnePort__GLOBALSInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {ConnectOneClassToOnePort__GLOBALSInv(ConnectOneClassToOnePort__GLOBALS(x))} ConnectOneClassToOnePort__GLOBALSInv(ConnectOneClassToOnePort__GLOBALS(x)) == x);
+axiom (forall x:int :: {ConnectOneClassToOnePort__GLOBALSInv(x)} ConnectOneClassToOnePort__GLOBALS(ConnectOneClassToOnePort__GLOBALSInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_ConnectOneClassToOnePort__GLOBALS(S)[x]} _S_ConnectOneClassToOnePort__GLOBALS(S)[x] <==> S[ConnectOneClassToOnePort__GLOBALSInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_ConnectOneClassToOnePort__GLOBALSInv(S)[x]} _S_ConnectOneClassToOnePort__GLOBALSInv(S)[x] <==> S[ConnectOneClassToOnePort__GLOBALS(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_ConnectOneClassToOnePort__GLOBALS(S)} S[x] ==> _S_ConnectOneClassToOnePort__GLOBALS(S)[ConnectOneClassToOnePort__GLOBALS(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_ConnectOneClassToOnePort__GLOBALSInv(S)} S[x] ==> _S_ConnectOneClassToOnePort__GLOBALSInv(S)[ConnectOneClassToOnePort__GLOBALSInv(x)]);
+
+axiom (forall x:int :: {ConnectOneClassToOnePort__GLOBALS(x)} ConnectOneClassToOnePort__GLOBALS(x) == x + 56);
+axiom (forall x:int :: {ConnectOneClassToOnePort__GLOBALSInv(x)} ConnectOneClassToOnePort__GLOBALSInv(x) == x - 56);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 56, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 56, 1) == ConnectOneClassToOnePort__GLOBALSInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 56)} MINUS_LEFT_PTR(x, 1, 56) == ConnectOneClassToOnePort__GLOBALSInv(x));
+function DataIn__DEVICE_EXTENSION(int) returns (int);
+function DataIn__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_DataIn__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_DataIn__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {DataIn__DEVICE_EXTENSIONInv(DataIn__DEVICE_EXTENSION(x))} DataIn__DEVICE_EXTENSIONInv(DataIn__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {DataIn__DEVICE_EXTENSIONInv(x)} DataIn__DEVICE_EXTENSION(DataIn__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_DataIn__DEVICE_EXTENSION(S)[x]} _S_DataIn__DEVICE_EXTENSION(S)[x] <==> S[DataIn__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_DataIn__DEVICE_EXTENSIONInv(S)[x]} _S_DataIn__DEVICE_EXTENSIONInv(S)[x] <==> S[DataIn__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_DataIn__DEVICE_EXTENSION(S)} S[x] ==> _S_DataIn__DEVICE_EXTENSION(S)[DataIn__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_DataIn__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_DataIn__DEVICE_EXTENSIONInv(S)[DataIn__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {DataIn__DEVICE_EXTENSION(x)} DataIn__DEVICE_EXTENSION(x) == x + 132);
+axiom (forall x:int :: {DataIn__DEVICE_EXTENSIONInv(x)} DataIn__DEVICE_EXTENSIONInv(x) == x - 132);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 132, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 132, 1) == DataIn__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 132)} MINUS_LEFT_PTR(x, 1, 132) == DataIn__DEVICE_EXTENSIONInv(x));
+function DataOut__DEVICE_EXTENSION(int) returns (int);
+function DataOut__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_DataOut__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_DataOut__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {DataOut__DEVICE_EXTENSIONInv(DataOut__DEVICE_EXTENSION(x))} DataOut__DEVICE_EXTENSIONInv(DataOut__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {DataOut__DEVICE_EXTENSIONInv(x)} DataOut__DEVICE_EXTENSION(DataOut__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_DataOut__DEVICE_EXTENSION(S)[x]} _S_DataOut__DEVICE_EXTENSION(S)[x] <==> S[DataOut__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_DataOut__DEVICE_EXTENSIONInv(S)[x]} _S_DataOut__DEVICE_EXTENSIONInv(S)[x] <==> S[DataOut__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_DataOut__DEVICE_EXTENSION(S)} S[x] ==> _S_DataOut__DEVICE_EXTENSION(S)[DataOut__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_DataOut__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_DataOut__DEVICE_EXTENSIONInv(S)[DataOut__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {DataOut__DEVICE_EXTENSION(x)} DataOut__DEVICE_EXTENSION(x) == x + 136);
+axiom (forall x:int :: {DataOut__DEVICE_EXTENSIONInv(x)} DataOut__DEVICE_EXTENSIONInv(x) == x - 136);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 136, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 136, 1) == DataOut__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 136)} MINUS_LEFT_PTR(x, 1, 136) == DataOut__DEVICE_EXTENSIONInv(x));
+function Dbg__IO_REMOVE_LOCK(int) returns (int);
+function Dbg__IO_REMOVE_LOCKInv(int) returns (int);
+function _S_Dbg__IO_REMOVE_LOCK([int]bool) returns ([int]bool);
+function _S_Dbg__IO_REMOVE_LOCKInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {Dbg__IO_REMOVE_LOCKInv(Dbg__IO_REMOVE_LOCK(x))} Dbg__IO_REMOVE_LOCKInv(Dbg__IO_REMOVE_LOCK(x)) == x);
+axiom (forall x:int :: {Dbg__IO_REMOVE_LOCKInv(x)} Dbg__IO_REMOVE_LOCK(Dbg__IO_REMOVE_LOCKInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_Dbg__IO_REMOVE_LOCK(S)[x]} _S_Dbg__IO_REMOVE_LOCK(S)[x] <==> S[Dbg__IO_REMOVE_LOCKInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_Dbg__IO_REMOVE_LOCKInv(S)[x]} _S_Dbg__IO_REMOVE_LOCKInv(S)[x] <==> S[Dbg__IO_REMOVE_LOCK(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Dbg__IO_REMOVE_LOCK(S)} S[x] ==> _S_Dbg__IO_REMOVE_LOCK(S)[Dbg__IO_REMOVE_LOCK(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Dbg__IO_REMOVE_LOCKInv(S)} S[x] ==> _S_Dbg__IO_REMOVE_LOCKInv(S)[Dbg__IO_REMOVE_LOCKInv(x)]);
+
+axiom (forall x:int :: {Dbg__IO_REMOVE_LOCK(x)} Dbg__IO_REMOVE_LOCK(x) == x + 24);
+axiom (forall x:int :: {Dbg__IO_REMOVE_LOCKInv(x)} Dbg__IO_REMOVE_LOCKInv(x) == x - 24);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 24, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 24, 1) == Dbg__IO_REMOVE_LOCKInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 24)} MINUS_LEFT_PTR(x, 1, 24) == Dbg__IO_REMOVE_LOCKInv(x));
+function DebugActive___unnamed_1_9fa0583a(int) returns (int);
+function DebugActive___unnamed_1_9fa0583aInv(int) returns (int);
+function _S_DebugActive___unnamed_1_9fa0583a([int]bool) returns ([int]bool);
+function _S_DebugActive___unnamed_1_9fa0583aInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {DebugActive___unnamed_1_9fa0583aInv(DebugActive___unnamed_1_9fa0583a(x))} DebugActive___unnamed_1_9fa0583aInv(DebugActive___unnamed_1_9fa0583a(x)) == x);
+axiom (forall x:int :: {DebugActive___unnamed_1_9fa0583aInv(x)} DebugActive___unnamed_1_9fa0583a(DebugActive___unnamed_1_9fa0583aInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_DebugActive___unnamed_1_9fa0583a(S)[x]} _S_DebugActive___unnamed_1_9fa0583a(S)[x] <==> S[DebugActive___unnamed_1_9fa0583aInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_DebugActive___unnamed_1_9fa0583aInv(S)[x]} _S_DebugActive___unnamed_1_9fa0583aInv(S)[x] <==> S[DebugActive___unnamed_1_9fa0583a(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_DebugActive___unnamed_1_9fa0583a(S)} S[x] ==> _S_DebugActive___unnamed_1_9fa0583a(S)[DebugActive___unnamed_1_9fa0583a(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_DebugActive___unnamed_1_9fa0583aInv(S)} S[x] ==> _S_DebugActive___unnamed_1_9fa0583aInv(S)[DebugActive___unnamed_1_9fa0583aInv(x)]);
+
+axiom (forall x:int :: {DebugActive___unnamed_1_9fa0583a(x)} DebugActive___unnamed_1_9fa0583a(x) == x + 0);
+axiom (forall x:int :: {DebugActive___unnamed_1_9fa0583aInv(x)} DebugActive___unnamed_1_9fa0583aInv(x) == x - 0);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1) == DebugActive___unnamed_1_9fa0583aInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 0)} MINUS_LEFT_PTR(x, 1, 0) == DebugActive___unnamed_1_9fa0583aInv(x));
+function DeviceExtension__DEVICE_OBJECT(int) returns (int);
+function DeviceExtension__DEVICE_OBJECTInv(int) returns (int);
+function _S_DeviceExtension__DEVICE_OBJECT([int]bool) returns ([int]bool);
+function _S_DeviceExtension__DEVICE_OBJECTInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {DeviceExtension__DEVICE_OBJECTInv(DeviceExtension__DEVICE_OBJECT(x))} DeviceExtension__DEVICE_OBJECTInv(DeviceExtension__DEVICE_OBJECT(x)) == x);
+axiom (forall x:int :: {DeviceExtension__DEVICE_OBJECTInv(x)} DeviceExtension__DEVICE_OBJECT(DeviceExtension__DEVICE_OBJECTInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_DeviceExtension__DEVICE_OBJECT(S)[x]} _S_DeviceExtension__DEVICE_OBJECT(S)[x] <==> S[DeviceExtension__DEVICE_OBJECTInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_DeviceExtension__DEVICE_OBJECTInv(S)[x]} _S_DeviceExtension__DEVICE_OBJECTInv(S)[x] <==> S[DeviceExtension__DEVICE_OBJECT(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_DeviceExtension__DEVICE_OBJECT(S)} S[x] ==> _S_DeviceExtension__DEVICE_OBJECT(S)[DeviceExtension__DEVICE_OBJECT(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_DeviceExtension__DEVICE_OBJECTInv(S)} S[x] ==> _S_DeviceExtension__DEVICE_OBJECTInv(S)[DeviceExtension__DEVICE_OBJECTInv(x)]);
+
+axiom (forall x:int :: {DeviceExtension__DEVICE_OBJECT(x)} DeviceExtension__DEVICE_OBJECT(x) == x + 40);
+axiom (forall x:int :: {DeviceExtension__DEVICE_OBJECTInv(x)} DeviceExtension__DEVICE_OBJECTInv(x) == x - 40);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 40, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 40, 1) == DeviceExtension__DEVICE_OBJECTInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 40)} MINUS_LEFT_PTR(x, 1, 40) == DeviceExtension__DEVICE_OBJECTInv(x));
+function DeviceState__DEVICE_EXTENSION(int) returns (int);
+function DeviceState__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_DeviceState__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_DeviceState__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {DeviceState__DEVICE_EXTENSIONInv(DeviceState__DEVICE_EXTENSION(x))} DeviceState__DEVICE_EXTENSIONInv(DeviceState__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {DeviceState__DEVICE_EXTENSIONInv(x)} DeviceState__DEVICE_EXTENSION(DeviceState__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_DeviceState__DEVICE_EXTENSION(S)[x]} _S_DeviceState__DEVICE_EXTENSION(S)[x] <==> S[DeviceState__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_DeviceState__DEVICE_EXTENSIONInv(S)[x]} _S_DeviceState__DEVICE_EXTENSIONInv(S)[x] <==> S[DeviceState__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_DeviceState__DEVICE_EXTENSION(S)} S[x] ==> _S_DeviceState__DEVICE_EXTENSION(S)[DeviceState__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_DeviceState__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_DeviceState__DEVICE_EXTENSIONInv(S)[DeviceState__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {DeviceState__DEVICE_EXTENSION(x)} DeviceState__DEVICE_EXTENSION(x) == x + 168);
+axiom (forall x:int :: {DeviceState__DEVICE_EXTENSIONInv(x)} DeviceState__DEVICE_EXTENSIONInv(x) == x - 168);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 168, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 168, 1) == DeviceState__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 168)} MINUS_LEFT_PTR(x, 1, 168) == DeviceState__DEVICE_EXTENSIONInv(x));
+function DpcActive___unnamed_1_9fa0583a(int) returns (int);
+function DpcActive___unnamed_1_9fa0583aInv(int) returns (int);
+function _S_DpcActive___unnamed_1_9fa0583a([int]bool) returns ([int]bool);
+function _S_DpcActive___unnamed_1_9fa0583aInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {DpcActive___unnamed_1_9fa0583aInv(DpcActive___unnamed_1_9fa0583a(x))} DpcActive___unnamed_1_9fa0583aInv(DpcActive___unnamed_1_9fa0583a(x)) == x);
+axiom (forall x:int :: {DpcActive___unnamed_1_9fa0583aInv(x)} DpcActive___unnamed_1_9fa0583a(DpcActive___unnamed_1_9fa0583aInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_DpcActive___unnamed_1_9fa0583a(S)[x]} _S_DpcActive___unnamed_1_9fa0583a(S)[x] <==> S[DpcActive___unnamed_1_9fa0583aInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_DpcActive___unnamed_1_9fa0583aInv(S)[x]} _S_DpcActive___unnamed_1_9fa0583aInv(S)[x] <==> S[DpcActive___unnamed_1_9fa0583a(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_DpcActive___unnamed_1_9fa0583a(S)} S[x] ==> _S_DpcActive___unnamed_1_9fa0583a(S)[DpcActive___unnamed_1_9fa0583a(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_DpcActive___unnamed_1_9fa0583aInv(S)} S[x] ==> _S_DpcActive___unnamed_1_9fa0583aInv(S)[DpcActive___unnamed_1_9fa0583aInv(x)]);
+
+axiom (forall x:int :: {DpcActive___unnamed_1_9fa0583a(x)} DpcActive___unnamed_1_9fa0583a(x) == x + 0);
+axiom (forall x:int :: {DpcActive___unnamed_1_9fa0583aInv(x)} DpcActive___unnamed_1_9fa0583aInv(x) == x - 0);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1) == DpcActive___unnamed_1_9fa0583aInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 0)} MINUS_LEFT_PTR(x, 1, 0) == DpcActive___unnamed_1_9fa0583aInv(x));
+function Enabled__DEVICE_EXTENSION(int) returns (int);
+function Enabled__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_Enabled__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_Enabled__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {Enabled__DEVICE_EXTENSIONInv(Enabled__DEVICE_EXTENSION(x))} Enabled__DEVICE_EXTENSIONInv(Enabled__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {Enabled__DEVICE_EXTENSIONInv(x)} Enabled__DEVICE_EXTENSION(Enabled__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_Enabled__DEVICE_EXTENSION(S)[x]} _S_Enabled__DEVICE_EXTENSION(S)[x] <==> S[Enabled__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_Enabled__DEVICE_EXTENSIONInv(S)[x]} _S_Enabled__DEVICE_EXTENSIONInv(S)[x] <==> S[Enabled__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Enabled__DEVICE_EXTENSION(S)} S[x] ==> _S_Enabled__DEVICE_EXTENSION(S)[Enabled__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Enabled__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_Enabled__DEVICE_EXTENSIONInv(S)[Enabled__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {Enabled__DEVICE_EXTENSION(x)} Enabled__DEVICE_EXTENSION(x) == x + 264);
+axiom (forall x:int :: {Enabled__DEVICE_EXTENSIONInv(x)} Enabled__DEVICE_EXTENSIONInv(x) == x - 264);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 264, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 264, 1) == Enabled__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 264)} MINUS_LEFT_PTR(x, 1, 264) == Enabled__DEVICE_EXTENSIONInv(x));
+function ExecuteWmiMethod__WMILIB_CONTEXT(int) returns (int);
+function ExecuteWmiMethod__WMILIB_CONTEXTInv(int) returns (int);
+function _S_ExecuteWmiMethod__WMILIB_CONTEXT([int]bool) returns ([int]bool);
+function _S_ExecuteWmiMethod__WMILIB_CONTEXTInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {ExecuteWmiMethod__WMILIB_CONTEXTInv(ExecuteWmiMethod__WMILIB_CONTEXT(x))} ExecuteWmiMethod__WMILIB_CONTEXTInv(ExecuteWmiMethod__WMILIB_CONTEXT(x)) == x);
+axiom (forall x:int :: {ExecuteWmiMethod__WMILIB_CONTEXTInv(x)} ExecuteWmiMethod__WMILIB_CONTEXT(ExecuteWmiMethod__WMILIB_CONTEXTInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_ExecuteWmiMethod__WMILIB_CONTEXT(S)[x]} _S_ExecuteWmiMethod__WMILIB_CONTEXT(S)[x] <==> S[ExecuteWmiMethod__WMILIB_CONTEXTInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_ExecuteWmiMethod__WMILIB_CONTEXTInv(S)[x]} _S_ExecuteWmiMethod__WMILIB_CONTEXTInv(S)[x] <==> S[ExecuteWmiMethod__WMILIB_CONTEXT(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_ExecuteWmiMethod__WMILIB_CONTEXT(S)} S[x] ==> _S_ExecuteWmiMethod__WMILIB_CONTEXT(S)[ExecuteWmiMethod__WMILIB_CONTEXT(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_ExecuteWmiMethod__WMILIB_CONTEXTInv(S)} S[x] ==> _S_ExecuteWmiMethod__WMILIB_CONTEXTInv(S)[ExecuteWmiMethod__WMILIB_CONTEXTInv(x)]);
+
+axiom (forall x:int :: {ExecuteWmiMethod__WMILIB_CONTEXT(x)} ExecuteWmiMethod__WMILIB_CONTEXT(x) == x + 24);
+axiom (forall x:int :: {ExecuteWmiMethod__WMILIB_CONTEXTInv(x)} ExecuteWmiMethod__WMILIB_CONTEXTInv(x) == x - 24);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 24, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 24, 1) == ExecuteWmiMethod__WMILIB_CONTEXTInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 24)} MINUS_LEFT_PTR(x, 1, 24) == ExecuteWmiMethod__WMILIB_CONTEXTInv(x));
+function ExtraWaitWakeIrp__DEVICE_EXTENSION(int) returns (int);
+function ExtraWaitWakeIrp__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_ExtraWaitWakeIrp__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_ExtraWaitWakeIrp__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {ExtraWaitWakeIrp__DEVICE_EXTENSIONInv(ExtraWaitWakeIrp__DEVICE_EXTENSION(x))} ExtraWaitWakeIrp__DEVICE_EXTENSIONInv(ExtraWaitWakeIrp__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {ExtraWaitWakeIrp__DEVICE_EXTENSIONInv(x)} ExtraWaitWakeIrp__DEVICE_EXTENSION(ExtraWaitWakeIrp__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_ExtraWaitWakeIrp__DEVICE_EXTENSION(S)[x]} _S_ExtraWaitWakeIrp__DEVICE_EXTENSION(S)[x] <==> S[ExtraWaitWakeIrp__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_ExtraWaitWakeIrp__DEVICE_EXTENSIONInv(S)[x]} _S_ExtraWaitWakeIrp__DEVICE_EXTENSIONInv(S)[x] <==> S[ExtraWaitWakeIrp__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_ExtraWaitWakeIrp__DEVICE_EXTENSION(S)} S[x] ==> _S_ExtraWaitWakeIrp__DEVICE_EXTENSION(S)[ExtraWaitWakeIrp__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_ExtraWaitWakeIrp__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_ExtraWaitWakeIrp__DEVICE_EXTENSIONInv(S)[ExtraWaitWakeIrp__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {ExtraWaitWakeIrp__DEVICE_EXTENSION(x)} ExtraWaitWakeIrp__DEVICE_EXTENSION(x) == x + 244);
+axiom (forall x:int :: {ExtraWaitWakeIrp__DEVICE_EXTENSIONInv(x)} ExtraWaitWakeIrp__DEVICE_EXTENSIONInv(x) == x - 244);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 244, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 244, 1) == ExtraWaitWakeIrp__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 244)} MINUS_LEFT_PTR(x, 1, 244) == ExtraWaitWakeIrp__DEVICE_EXTENSIONInv(x));
+function File__DEVICE_EXTENSION(int) returns (int);
+function File__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_File__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_File__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {File__DEVICE_EXTENSIONInv(File__DEVICE_EXTENSION(x))} File__DEVICE_EXTENSIONInv(File__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {File__DEVICE_EXTENSIONInv(x)} File__DEVICE_EXTENSION(File__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_File__DEVICE_EXTENSION(S)[x]} _S_File__DEVICE_EXTENSION(S)[x] <==> S[File__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_File__DEVICE_EXTENSIONInv(S)[x]} _S_File__DEVICE_EXTENSIONInv(S)[x] <==> S[File__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_File__DEVICE_EXTENSION(S)} S[x] ==> _S_File__DEVICE_EXTENSION(S)[File__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_File__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_File__DEVICE_EXTENSIONInv(S)[File__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {File__DEVICE_EXTENSION(x)} File__DEVICE_EXTENSION(x) == x + 260);
+axiom (forall x:int :: {File__DEVICE_EXTENSIONInv(x)} File__DEVICE_EXTENSIONInv(x) == x - 260);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 260, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 260, 1) == File__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 260)} MINUS_LEFT_PTR(x, 1, 260) == File__DEVICE_EXTENSIONInv(x));
+function Flags__DEVICE_OBJECT(int) returns (int);
+function Flags__DEVICE_OBJECTInv(int) returns (int);
+function _S_Flags__DEVICE_OBJECT([int]bool) returns ([int]bool);
+function _S_Flags__DEVICE_OBJECTInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {Flags__DEVICE_OBJECTInv(Flags__DEVICE_OBJECT(x))} Flags__DEVICE_OBJECTInv(Flags__DEVICE_OBJECT(x)) == x);
+axiom (forall x:int :: {Flags__DEVICE_OBJECTInv(x)} Flags__DEVICE_OBJECT(Flags__DEVICE_OBJECTInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_Flags__DEVICE_OBJECT(S)[x]} _S_Flags__DEVICE_OBJECT(S)[x] <==> S[Flags__DEVICE_OBJECTInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_Flags__DEVICE_OBJECTInv(S)[x]} _S_Flags__DEVICE_OBJECTInv(S)[x] <==> S[Flags__DEVICE_OBJECT(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Flags__DEVICE_OBJECT(S)} S[x] ==> _S_Flags__DEVICE_OBJECT(S)[Flags__DEVICE_OBJECT(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Flags__DEVICE_OBJECTInv(S)} S[x] ==> _S_Flags__DEVICE_OBJECTInv(S)[Flags__DEVICE_OBJECTInv(x)]);
+
+axiom (forall x:int :: {Flags__DEVICE_OBJECT(x)} Flags__DEVICE_OBJECT(x) == x + 28);
+axiom (forall x:int :: {Flags__DEVICE_OBJECTInv(x)} Flags__DEVICE_OBJECTInv(x) == x - 28);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 28, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 28, 1) == Flags__DEVICE_OBJECTInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 28)} MINUS_LEFT_PTR(x, 1, 28) == Flags__DEVICE_OBJECTInv(x));
+function Flink__LIST_ENTRY(int) returns (int);
+function Flink__LIST_ENTRYInv(int) returns (int);
+function _S_Flink__LIST_ENTRY([int]bool) returns ([int]bool);
+function _S_Flink__LIST_ENTRYInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {Flink__LIST_ENTRYInv(Flink__LIST_ENTRY(x))} Flink__LIST_ENTRYInv(Flink__LIST_ENTRY(x)) == x);
+axiom (forall x:int :: {Flink__LIST_ENTRYInv(x)} Flink__LIST_ENTRY(Flink__LIST_ENTRYInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_Flink__LIST_ENTRY(S)[x]} _S_Flink__LIST_ENTRY(S)[x] <==> S[Flink__LIST_ENTRYInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_Flink__LIST_ENTRYInv(S)[x]} _S_Flink__LIST_ENTRYInv(S)[x] <==> S[Flink__LIST_ENTRY(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Flink__LIST_ENTRY(S)} S[x] ==> _S_Flink__LIST_ENTRY(S)[Flink__LIST_ENTRY(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Flink__LIST_ENTRYInv(S)} S[x] ==> _S_Flink__LIST_ENTRYInv(S)[Flink__LIST_ENTRYInv(x)]);
+
+axiom (forall x:int :: {Flink__LIST_ENTRY(x)} Flink__LIST_ENTRY(x) == x + 0);
+axiom (forall x:int :: {Flink__LIST_ENTRYInv(x)} Flink__LIST_ENTRYInv(x) == x - 0);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1) == Flink__LIST_ENTRYInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 0)} MINUS_LEFT_PTR(x, 1, 0) == Flink__LIST_ENTRYInv(x));
+function GrandMaster__GLOBALS(int) returns (int);
+function GrandMaster__GLOBALSInv(int) returns (int);
+function _S_GrandMaster__GLOBALS([int]bool) returns ([int]bool);
+function _S_GrandMaster__GLOBALSInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {GrandMaster__GLOBALSInv(GrandMaster__GLOBALS(x))} GrandMaster__GLOBALSInv(GrandMaster__GLOBALS(x)) == x);
+axiom (forall x:int :: {GrandMaster__GLOBALSInv(x)} GrandMaster__GLOBALS(GrandMaster__GLOBALSInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_GrandMaster__GLOBALS(S)[x]} _S_GrandMaster__GLOBALS(S)[x] <==> S[GrandMaster__GLOBALSInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_GrandMaster__GLOBALSInv(S)[x]} _S_GrandMaster__GLOBALSInv(S)[x] <==> S[GrandMaster__GLOBALS(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_GrandMaster__GLOBALS(S)} S[x] ==> _S_GrandMaster__GLOBALS(S)[GrandMaster__GLOBALS(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_GrandMaster__GLOBALSInv(S)} S[x] ==> _S_GrandMaster__GLOBALSInv(S)[GrandMaster__GLOBALSInv(x)]);
+
+axiom (forall x:int :: {GrandMaster__GLOBALS(x)} GrandMaster__GLOBALS(x) == x + 4);
+axiom (forall x:int :: {GrandMaster__GLOBALSInv(x)} GrandMaster__GLOBALSInv(x) == x - 4);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 4, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 4, 1) == GrandMaster__GLOBALSInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 4)} MINUS_LEFT_PTR(x, 1, 4) == GrandMaster__GLOBALSInv(x));
+function GuidCount__WMILIB_CONTEXT(int) returns (int);
+function GuidCount__WMILIB_CONTEXTInv(int) returns (int);
+function _S_GuidCount__WMILIB_CONTEXT([int]bool) returns ([int]bool);
+function _S_GuidCount__WMILIB_CONTEXTInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {GuidCount__WMILIB_CONTEXTInv(GuidCount__WMILIB_CONTEXT(x))} GuidCount__WMILIB_CONTEXTInv(GuidCount__WMILIB_CONTEXT(x)) == x);
+axiom (forall x:int :: {GuidCount__WMILIB_CONTEXTInv(x)} GuidCount__WMILIB_CONTEXT(GuidCount__WMILIB_CONTEXTInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_GuidCount__WMILIB_CONTEXT(S)[x]} _S_GuidCount__WMILIB_CONTEXT(S)[x] <==> S[GuidCount__WMILIB_CONTEXTInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_GuidCount__WMILIB_CONTEXTInv(S)[x]} _S_GuidCount__WMILIB_CONTEXTInv(S)[x] <==> S[GuidCount__WMILIB_CONTEXT(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_GuidCount__WMILIB_CONTEXT(S)} S[x] ==> _S_GuidCount__WMILIB_CONTEXT(S)[GuidCount__WMILIB_CONTEXT(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_GuidCount__WMILIB_CONTEXTInv(S)} S[x] ==> _S_GuidCount__WMILIB_CONTEXTInv(S)[GuidCount__WMILIB_CONTEXTInv(x)]);
+
+axiom (forall x:int :: {GuidCount__WMILIB_CONTEXT(x)} GuidCount__WMILIB_CONTEXT(x) == x + 0);
+axiom (forall x:int :: {GuidCount__WMILIB_CONTEXTInv(x)} GuidCount__WMILIB_CONTEXTInv(x) == x - 0);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1) == GuidCount__WMILIB_CONTEXTInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 0)} MINUS_LEFT_PTR(x, 1, 0) == GuidCount__WMILIB_CONTEXTInv(x));
+function GuidList__WMILIB_CONTEXT(int) returns (int);
+function GuidList__WMILIB_CONTEXTInv(int) returns (int);
+function _S_GuidList__WMILIB_CONTEXT([int]bool) returns ([int]bool);
+function _S_GuidList__WMILIB_CONTEXTInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {GuidList__WMILIB_CONTEXTInv(GuidList__WMILIB_CONTEXT(x))} GuidList__WMILIB_CONTEXTInv(GuidList__WMILIB_CONTEXT(x)) == x);
+axiom (forall x:int :: {GuidList__WMILIB_CONTEXTInv(x)} GuidList__WMILIB_CONTEXT(GuidList__WMILIB_CONTEXTInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_GuidList__WMILIB_CONTEXT(S)[x]} _S_GuidList__WMILIB_CONTEXT(S)[x] <==> S[GuidList__WMILIB_CONTEXTInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_GuidList__WMILIB_CONTEXTInv(S)[x]} _S_GuidList__WMILIB_CONTEXTInv(S)[x] <==> S[GuidList__WMILIB_CONTEXT(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_GuidList__WMILIB_CONTEXT(S)} S[x] ==> _S_GuidList__WMILIB_CONTEXT(S)[GuidList__WMILIB_CONTEXT(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_GuidList__WMILIB_CONTEXTInv(S)} S[x] ==> _S_GuidList__WMILIB_CONTEXTInv(S)[GuidList__WMILIB_CONTEXTInv(x)]);
+
+axiom (forall x:int :: {GuidList__WMILIB_CONTEXT(x)} GuidList__WMILIB_CONTEXT(x) == x + 4);
+axiom (forall x:int :: {GuidList__WMILIB_CONTEXTInv(x)} GuidList__WMILIB_CONTEXTInv(x) == x - 4);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 4, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 4, 1) == GuidList__WMILIB_CONTEXTInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 4)} MINUS_LEFT_PTR(x, 1, 4) == GuidList__WMILIB_CONTEXTInv(x));
+function Hand___unnamed_1_e30779f5(int) returns (int);
+function Hand___unnamed_1_e30779f5Inv(int) returns (int);
+function _S_Hand___unnamed_1_e30779f5([int]bool) returns ([int]bool);
+function _S_Hand___unnamed_1_e30779f5Inv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {Hand___unnamed_1_e30779f5Inv(Hand___unnamed_1_e30779f5(x))} Hand___unnamed_1_e30779f5Inv(Hand___unnamed_1_e30779f5(x)) == x);
+axiom (forall x:int :: {Hand___unnamed_1_e30779f5Inv(x)} Hand___unnamed_1_e30779f5(Hand___unnamed_1_e30779f5Inv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_Hand___unnamed_1_e30779f5(S)[x]} _S_Hand___unnamed_1_e30779f5(S)[x] <==> S[Hand___unnamed_1_e30779f5Inv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_Hand___unnamed_1_e30779f5Inv(S)[x]} _S_Hand___unnamed_1_e30779f5Inv(S)[x] <==> S[Hand___unnamed_1_e30779f5(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Hand___unnamed_1_e30779f5(S)} S[x] ==> _S_Hand___unnamed_1_e30779f5(S)[Hand___unnamed_1_e30779f5(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Hand___unnamed_1_e30779f5Inv(S)} S[x] ==> _S_Hand___unnamed_1_e30779f5Inv(S)[Hand___unnamed_1_e30779f5Inv(x)]);
+
+axiom (forall x:int :: {Hand___unnamed_1_e30779f5(x)} Hand___unnamed_1_e30779f5(x) == x + 0);
+axiom (forall x:int :: {Hand___unnamed_1_e30779f5Inv(x)} Hand___unnamed_1_e30779f5Inv(x) == x - 0);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1) == Hand___unnamed_1_e30779f5Inv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 0)} MINUS_LEFT_PTR(x, 1, 0) == Hand___unnamed_1_e30779f5Inv(x));
+function Header__KEVENT(int) returns (int);
+function Header__KEVENTInv(int) returns (int);
+function _S_Header__KEVENT([int]bool) returns ([int]bool);
+function _S_Header__KEVENTInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {Header__KEVENTInv(Header__KEVENT(x))} Header__KEVENTInv(Header__KEVENT(x)) == x);
+axiom (forall x:int :: {Header__KEVENTInv(x)} Header__KEVENT(Header__KEVENTInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_Header__KEVENT(S)[x]} _S_Header__KEVENT(S)[x] <==> S[Header__KEVENTInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_Header__KEVENTInv(S)[x]} _S_Header__KEVENTInv(S)[x] <==> S[Header__KEVENT(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Header__KEVENT(S)} S[x] ==> _S_Header__KEVENT(S)[Header__KEVENT(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Header__KEVENTInv(S)} S[x] ==> _S_Header__KEVENTInv(S)[Header__KEVENTInv(x)]);
+
+axiom (forall x:int :: {Header__KEVENT(x)} Header__KEVENT(x) == x + 0);
+axiom (forall x:int :: {Header__KEVENTInv(x)} Header__KEVENTInv(x) == x - 0);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1) == Header__KEVENTInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 0)} MINUS_LEFT_PTR(x, 1, 0) == Header__KEVENTInv(x));
+function HighWatermark__IO_REMOVE_LOCK_DBG_BLOCK(int) returns (int);
+function HighWatermark__IO_REMOVE_LOCK_DBG_BLOCKInv(int) returns (int);
+function _S_HighWatermark__IO_REMOVE_LOCK_DBG_BLOCK([int]bool) returns ([int]bool);
+function _S_HighWatermark__IO_REMOVE_LOCK_DBG_BLOCKInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {HighWatermark__IO_REMOVE_LOCK_DBG_BLOCKInv(HighWatermark__IO_REMOVE_LOCK_DBG_BLOCK(x))} HighWatermark__IO_REMOVE_LOCK_DBG_BLOCKInv(HighWatermark__IO_REMOVE_LOCK_DBG_BLOCK(x)) == x);
+axiom (forall x:int :: {HighWatermark__IO_REMOVE_LOCK_DBG_BLOCKInv(x)} HighWatermark__IO_REMOVE_LOCK_DBG_BLOCK(HighWatermark__IO_REMOVE_LOCK_DBG_BLOCKInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_HighWatermark__IO_REMOVE_LOCK_DBG_BLOCK(S)[x]} _S_HighWatermark__IO_REMOVE_LOCK_DBG_BLOCK(S)[x] <==> S[HighWatermark__IO_REMOVE_LOCK_DBG_BLOCKInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_HighWatermark__IO_REMOVE_LOCK_DBG_BLOCKInv(S)[x]} _S_HighWatermark__IO_REMOVE_LOCK_DBG_BLOCKInv(S)[x] <==> S[HighWatermark__IO_REMOVE_LOCK_DBG_BLOCK(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_HighWatermark__IO_REMOVE_LOCK_DBG_BLOCK(S)} S[x] ==> _S_HighWatermark__IO_REMOVE_LOCK_DBG_BLOCK(S)[HighWatermark__IO_REMOVE_LOCK_DBG_BLOCK(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_HighWatermark__IO_REMOVE_LOCK_DBG_BLOCKInv(S)} S[x] ==> _S_HighWatermark__IO_REMOVE_LOCK_DBG_BLOCKInv(S)[HighWatermark__IO_REMOVE_LOCK_DBG_BLOCKInv(x)]);
+
+axiom (forall x:int :: {HighWatermark__IO_REMOVE_LOCK_DBG_BLOCK(x)} HighWatermark__IO_REMOVE_LOCK_DBG_BLOCK(x) == x + 4);
+axiom (forall x:int :: {HighWatermark__IO_REMOVE_LOCK_DBG_BLOCKInv(x)} HighWatermark__IO_REMOVE_LOCK_DBG_BLOCKInv(x) == x - 4);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 4, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 4, 1) == HighWatermark__IO_REMOVE_LOCK_DBG_BLOCKInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 4)} MINUS_LEFT_PTR(x, 1, 4) == HighWatermark__IO_REMOVE_LOCK_DBG_BLOCKInv(x));
+function InputCount__DEVICE_EXTENSION(int) returns (int);
+function InputCount__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_InputCount__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_InputCount__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {InputCount__DEVICE_EXTENSIONInv(InputCount__DEVICE_EXTENSION(x))} InputCount__DEVICE_EXTENSIONInv(InputCount__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {InputCount__DEVICE_EXTENSIONInv(x)} InputCount__DEVICE_EXTENSION(InputCount__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_InputCount__DEVICE_EXTENSION(S)[x]} _S_InputCount__DEVICE_EXTENSION(S)[x] <==> S[InputCount__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_InputCount__DEVICE_EXTENSIONInv(S)[x]} _S_InputCount__DEVICE_EXTENSIONInv(S)[x] <==> S[InputCount__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_InputCount__DEVICE_EXTENSION(S)} S[x] ==> _S_InputCount__DEVICE_EXTENSION(S)[InputCount__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_InputCount__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_InputCount__DEVICE_EXTENSIONInv(S)[InputCount__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {InputCount__DEVICE_EXTENSION(x)} InputCount__DEVICE_EXTENSION(x) == x + 116);
+axiom (forall x:int :: {InputCount__DEVICE_EXTENSIONInv(x)} InputCount__DEVICE_EXTENSIONInv(x) == x - 116);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 116, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 116, 1) == InputCount__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 116)} MINUS_LEFT_PTR(x, 1, 116) == InputCount__DEVICE_EXTENSIONInv(x));
+function InputDataQueueLength__MOUSE_ATTRIBUTES(int) returns (int);
+function InputDataQueueLength__MOUSE_ATTRIBUTESInv(int) returns (int);
+function _S_InputDataQueueLength__MOUSE_ATTRIBUTES([int]bool) returns ([int]bool);
+function _S_InputDataQueueLength__MOUSE_ATTRIBUTESInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {InputDataQueueLength__MOUSE_ATTRIBUTESInv(InputDataQueueLength__MOUSE_ATTRIBUTES(x))} InputDataQueueLength__MOUSE_ATTRIBUTESInv(InputDataQueueLength__MOUSE_ATTRIBUTES(x)) == x);
+axiom (forall x:int :: {InputDataQueueLength__MOUSE_ATTRIBUTESInv(x)} InputDataQueueLength__MOUSE_ATTRIBUTES(InputDataQueueLength__MOUSE_ATTRIBUTESInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_InputDataQueueLength__MOUSE_ATTRIBUTES(S)[x]} _S_InputDataQueueLength__MOUSE_ATTRIBUTES(S)[x] <==> S[InputDataQueueLength__MOUSE_ATTRIBUTESInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_InputDataQueueLength__MOUSE_ATTRIBUTESInv(S)[x]} _S_InputDataQueueLength__MOUSE_ATTRIBUTESInv(S)[x] <==> S[InputDataQueueLength__MOUSE_ATTRIBUTES(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_InputDataQueueLength__MOUSE_ATTRIBUTES(S)} S[x] ==> _S_InputDataQueueLength__MOUSE_ATTRIBUTES(S)[InputDataQueueLength__MOUSE_ATTRIBUTES(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_InputDataQueueLength__MOUSE_ATTRIBUTESInv(S)} S[x] ==> _S_InputDataQueueLength__MOUSE_ATTRIBUTESInv(S)[InputDataQueueLength__MOUSE_ATTRIBUTESInv(x)]);
+
+axiom (forall x:int :: {InputDataQueueLength__MOUSE_ATTRIBUTES(x)} InputDataQueueLength__MOUSE_ATTRIBUTES(x) == x + 8);
+axiom (forall x:int :: {InputDataQueueLength__MOUSE_ATTRIBUTESInv(x)} InputDataQueueLength__MOUSE_ATTRIBUTESInv(x) == x - 8);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 8, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 8, 1) == InputDataQueueLength__MOUSE_ATTRIBUTESInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 8)} MINUS_LEFT_PTR(x, 1, 8) == InputDataQueueLength__MOUSE_ATTRIBUTESInv(x));
+function InputData__DEVICE_EXTENSION(int) returns (int);
+function InputData__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_InputData__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_InputData__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {InputData__DEVICE_EXTENSIONInv(InputData__DEVICE_EXTENSION(x))} InputData__DEVICE_EXTENSIONInv(InputData__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {InputData__DEVICE_EXTENSIONInv(x)} InputData__DEVICE_EXTENSION(InputData__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_InputData__DEVICE_EXTENSION(S)[x]} _S_InputData__DEVICE_EXTENSION(S)[x] <==> S[InputData__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_InputData__DEVICE_EXTENSIONInv(S)[x]} _S_InputData__DEVICE_EXTENSIONInv(S)[x] <==> S[InputData__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_InputData__DEVICE_EXTENSION(S)} S[x] ==> _S_InputData__DEVICE_EXTENSION(S)[InputData__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_InputData__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_InputData__DEVICE_EXTENSIONInv(S)[InputData__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {InputData__DEVICE_EXTENSION(x)} InputData__DEVICE_EXTENSION(x) == x + 128);
+axiom (forall x:int :: {InputData__DEVICE_EXTENSIONInv(x)} InputData__DEVICE_EXTENSIONInv(x) == x - 128);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 128, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 128, 1) == InputData__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 128)} MINUS_LEFT_PTR(x, 1, 128) == InputData__DEVICE_EXTENSIONInv(x));
+function Inserted___unnamed_1_9fa0583a(int) returns (int);
+function Inserted___unnamed_1_9fa0583aInv(int) returns (int);
+function _S_Inserted___unnamed_1_9fa0583a([int]bool) returns ([int]bool);
+function _S_Inserted___unnamed_1_9fa0583aInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {Inserted___unnamed_1_9fa0583aInv(Inserted___unnamed_1_9fa0583a(x))} Inserted___unnamed_1_9fa0583aInv(Inserted___unnamed_1_9fa0583a(x)) == x);
+axiom (forall x:int :: {Inserted___unnamed_1_9fa0583aInv(x)} Inserted___unnamed_1_9fa0583a(Inserted___unnamed_1_9fa0583aInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_Inserted___unnamed_1_9fa0583a(S)[x]} _S_Inserted___unnamed_1_9fa0583a(S)[x] <==> S[Inserted___unnamed_1_9fa0583aInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_Inserted___unnamed_1_9fa0583aInv(S)[x]} _S_Inserted___unnamed_1_9fa0583aInv(S)[x] <==> S[Inserted___unnamed_1_9fa0583a(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Inserted___unnamed_1_9fa0583a(S)} S[x] ==> _S_Inserted___unnamed_1_9fa0583a(S)[Inserted___unnamed_1_9fa0583a(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Inserted___unnamed_1_9fa0583aInv(S)} S[x] ==> _S_Inserted___unnamed_1_9fa0583aInv(S)[Inserted___unnamed_1_9fa0583aInv(x)]);
+
+axiom (forall x:int :: {Inserted___unnamed_1_9fa0583a(x)} Inserted___unnamed_1_9fa0583a(x) == x + 0);
+axiom (forall x:int :: {Inserted___unnamed_1_9fa0583aInv(x)} Inserted___unnamed_1_9fa0583aInv(x) == x - 0);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1) == Inserted___unnamed_1_9fa0583aInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 0)} MINUS_LEFT_PTR(x, 1, 0) == Inserted___unnamed_1_9fa0583aInv(x));
+function IoCount__IO_REMOVE_LOCK_COMMON_BLOCK(int) returns (int);
+function IoCount__IO_REMOVE_LOCK_COMMON_BLOCKInv(int) returns (int);
+function _S_IoCount__IO_REMOVE_LOCK_COMMON_BLOCK([int]bool) returns ([int]bool);
+function _S_IoCount__IO_REMOVE_LOCK_COMMON_BLOCKInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {IoCount__IO_REMOVE_LOCK_COMMON_BLOCKInv(IoCount__IO_REMOVE_LOCK_COMMON_BLOCK(x))} IoCount__IO_REMOVE_LOCK_COMMON_BLOCKInv(IoCount__IO_REMOVE_LOCK_COMMON_BLOCK(x)) == x);
+axiom (forall x:int :: {IoCount__IO_REMOVE_LOCK_COMMON_BLOCKInv(x)} IoCount__IO_REMOVE_LOCK_COMMON_BLOCK(IoCount__IO_REMOVE_LOCK_COMMON_BLOCKInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_IoCount__IO_REMOVE_LOCK_COMMON_BLOCK(S)[x]} _S_IoCount__IO_REMOVE_LOCK_COMMON_BLOCK(S)[x] <==> S[IoCount__IO_REMOVE_LOCK_COMMON_BLOCKInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_IoCount__IO_REMOVE_LOCK_COMMON_BLOCKInv(S)[x]} _S_IoCount__IO_REMOVE_LOCK_COMMON_BLOCKInv(S)[x] <==> S[IoCount__IO_REMOVE_LOCK_COMMON_BLOCK(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_IoCount__IO_REMOVE_LOCK_COMMON_BLOCK(S)} S[x] ==> _S_IoCount__IO_REMOVE_LOCK_COMMON_BLOCK(S)[IoCount__IO_REMOVE_LOCK_COMMON_BLOCK(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_IoCount__IO_REMOVE_LOCK_COMMON_BLOCKInv(S)} S[x] ==> _S_IoCount__IO_REMOVE_LOCK_COMMON_BLOCKInv(S)[IoCount__IO_REMOVE_LOCK_COMMON_BLOCKInv(x)]);
+
+axiom (forall x:int :: {IoCount__IO_REMOVE_LOCK_COMMON_BLOCK(x)} IoCount__IO_REMOVE_LOCK_COMMON_BLOCK(x) == x + 4);
+axiom (forall x:int :: {IoCount__IO_REMOVE_LOCK_COMMON_BLOCKInv(x)} IoCount__IO_REMOVE_LOCK_COMMON_BLOCKInv(x) == x - 4);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 4, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 4, 1) == IoCount__IO_REMOVE_LOCK_COMMON_BLOCKInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 4)} MINUS_LEFT_PTR(x, 1, 4) == IoCount__IO_REMOVE_LOCK_COMMON_BLOCKInv(x));
+function LegacyDeviceList__GLOBALS(int) returns (int);
+function LegacyDeviceList__GLOBALSInv(int) returns (int);
+function _S_LegacyDeviceList__GLOBALS([int]bool) returns ([int]bool);
+function _S_LegacyDeviceList__GLOBALSInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {LegacyDeviceList__GLOBALSInv(LegacyDeviceList__GLOBALS(x))} LegacyDeviceList__GLOBALSInv(LegacyDeviceList__GLOBALS(x)) == x);
+axiom (forall x:int :: {LegacyDeviceList__GLOBALSInv(x)} LegacyDeviceList__GLOBALS(LegacyDeviceList__GLOBALSInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_LegacyDeviceList__GLOBALS(S)[x]} _S_LegacyDeviceList__GLOBALS(S)[x] <==> S[LegacyDeviceList__GLOBALSInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_LegacyDeviceList__GLOBALSInv(S)[x]} _S_LegacyDeviceList__GLOBALSInv(S)[x] <==> S[LegacyDeviceList__GLOBALS(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_LegacyDeviceList__GLOBALS(S)} S[x] ==> _S_LegacyDeviceList__GLOBALS(S)[LegacyDeviceList__GLOBALS(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_LegacyDeviceList__GLOBALSInv(S)} S[x] ==> _S_LegacyDeviceList__GLOBALSInv(S)[LegacyDeviceList__GLOBALSInv(x)]);
+
+axiom (forall x:int :: {LegacyDeviceList__GLOBALS(x)} LegacyDeviceList__GLOBALS(x) == x + 864);
+axiom (forall x:int :: {LegacyDeviceList__GLOBALSInv(x)} LegacyDeviceList__GLOBALSInv(x) == x - 864);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 864, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 864, 1) == LegacyDeviceList__GLOBALSInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 864)} MINUS_LEFT_PTR(x, 1, 864) == LegacyDeviceList__GLOBALSInv(x));
+function Length__UNICODE_STRING(int) returns (int);
+function Length__UNICODE_STRINGInv(int) returns (int);
+function _S_Length__UNICODE_STRING([int]bool) returns ([int]bool);
+function _S_Length__UNICODE_STRINGInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {Length__UNICODE_STRINGInv(Length__UNICODE_STRING(x))} Length__UNICODE_STRINGInv(Length__UNICODE_STRING(x)) == x);
+axiom (forall x:int :: {Length__UNICODE_STRINGInv(x)} Length__UNICODE_STRING(Length__UNICODE_STRINGInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_Length__UNICODE_STRING(S)[x]} _S_Length__UNICODE_STRING(S)[x] <==> S[Length__UNICODE_STRINGInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_Length__UNICODE_STRINGInv(S)[x]} _S_Length__UNICODE_STRINGInv(S)[x] <==> S[Length__UNICODE_STRING(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Length__UNICODE_STRING(S)} S[x] ==> _S_Length__UNICODE_STRING(S)[Length__UNICODE_STRING(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Length__UNICODE_STRINGInv(S)} S[x] ==> _S_Length__UNICODE_STRINGInv(S)[Length__UNICODE_STRINGInv(x)]);
+
+axiom (forall x:int :: {Length__UNICODE_STRING(x)} Length__UNICODE_STRING(x) == x + 0);
+axiom (forall x:int :: {Length__UNICODE_STRINGInv(x)} Length__UNICODE_STRINGInv(x) == x - 0);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1) == Length__UNICODE_STRINGInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 0)} MINUS_LEFT_PTR(x, 1, 0) == Length__UNICODE_STRINGInv(x));
+function Link__DEVICE_EXTENSION(int) returns (int);
+function Link__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_Link__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_Link__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {Link__DEVICE_EXTENSIONInv(Link__DEVICE_EXTENSION(x))} Link__DEVICE_EXTENSIONInv(Link__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {Link__DEVICE_EXTENSIONInv(x)} Link__DEVICE_EXTENSION(Link__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_Link__DEVICE_EXTENSION(S)[x]} _S_Link__DEVICE_EXTENSION(S)[x] <==> S[Link__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_Link__DEVICE_EXTENSIONInv(S)[x]} _S_Link__DEVICE_EXTENSIONInv(S)[x] <==> S[Link__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Link__DEVICE_EXTENSION(S)} S[x] ==> _S_Link__DEVICE_EXTENSION(S)[Link__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Link__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_Link__DEVICE_EXTENSIONInv(S)[Link__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {Link__DEVICE_EXTENSION(x)} Link__DEVICE_EXTENSION(x) == x + 252);
+axiom (forall x:int :: {Link__DEVICE_EXTENSIONInv(x)} Link__DEVICE_EXTENSIONInv(x) == x - 252);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 252, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 252, 1) == Link__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 252)} MINUS_LEFT_PTR(x, 1, 252) == Link__DEVICE_EXTENSIONInv(x));
+function LockList__IO_REMOVE_LOCK_DBG_BLOCK(int) returns (int);
+function LockList__IO_REMOVE_LOCK_DBG_BLOCKInv(int) returns (int);
+function _S_LockList__IO_REMOVE_LOCK_DBG_BLOCK([int]bool) returns ([int]bool);
+function _S_LockList__IO_REMOVE_LOCK_DBG_BLOCKInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {LockList__IO_REMOVE_LOCK_DBG_BLOCKInv(LockList__IO_REMOVE_LOCK_DBG_BLOCK(x))} LockList__IO_REMOVE_LOCK_DBG_BLOCKInv(LockList__IO_REMOVE_LOCK_DBG_BLOCK(x)) == x);
+axiom (forall x:int :: {LockList__IO_REMOVE_LOCK_DBG_BLOCKInv(x)} LockList__IO_REMOVE_LOCK_DBG_BLOCK(LockList__IO_REMOVE_LOCK_DBG_BLOCKInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_LockList__IO_REMOVE_LOCK_DBG_BLOCK(S)[x]} _S_LockList__IO_REMOVE_LOCK_DBG_BLOCK(S)[x] <==> S[LockList__IO_REMOVE_LOCK_DBG_BLOCKInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_LockList__IO_REMOVE_LOCK_DBG_BLOCKInv(S)[x]} _S_LockList__IO_REMOVE_LOCK_DBG_BLOCKInv(S)[x] <==> S[LockList__IO_REMOVE_LOCK_DBG_BLOCK(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_LockList__IO_REMOVE_LOCK_DBG_BLOCK(S)} S[x] ==> _S_LockList__IO_REMOVE_LOCK_DBG_BLOCK(S)[LockList__IO_REMOVE_LOCK_DBG_BLOCK(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_LockList__IO_REMOVE_LOCK_DBG_BLOCKInv(S)} S[x] ==> _S_LockList__IO_REMOVE_LOCK_DBG_BLOCKInv(S)[LockList__IO_REMOVE_LOCK_DBG_BLOCKInv(x)]);
+
+axiom (forall x:int :: {LockList__IO_REMOVE_LOCK_DBG_BLOCK(x)} LockList__IO_REMOVE_LOCK_DBG_BLOCK(x) == x + 20);
+axiom (forall x:int :: {LockList__IO_REMOVE_LOCK_DBG_BLOCKInv(x)} LockList__IO_REMOVE_LOCK_DBG_BLOCKInv(x) == x - 20);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 20, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 20, 1) == LockList__IO_REMOVE_LOCK_DBG_BLOCKInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 20)} MINUS_LEFT_PTR(x, 1, 20) == LockList__IO_REMOVE_LOCK_DBG_BLOCKInv(x));
+function Lock___unnamed_4_c9b2e921(int) returns (int);
+function Lock___unnamed_4_c9b2e921Inv(int) returns (int);
+function _S_Lock___unnamed_4_c9b2e921([int]bool) returns ([int]bool);
+function _S_Lock___unnamed_4_c9b2e921Inv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {Lock___unnamed_4_c9b2e921Inv(Lock___unnamed_4_c9b2e921(x))} Lock___unnamed_4_c9b2e921Inv(Lock___unnamed_4_c9b2e921(x)) == x);
+axiom (forall x:int :: {Lock___unnamed_4_c9b2e921Inv(x)} Lock___unnamed_4_c9b2e921(Lock___unnamed_4_c9b2e921Inv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_Lock___unnamed_4_c9b2e921(S)[x]} _S_Lock___unnamed_4_c9b2e921(S)[x] <==> S[Lock___unnamed_4_c9b2e921Inv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_Lock___unnamed_4_c9b2e921Inv(S)[x]} _S_Lock___unnamed_4_c9b2e921Inv(S)[x] <==> S[Lock___unnamed_4_c9b2e921(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Lock___unnamed_4_c9b2e921(S)} S[x] ==> _S_Lock___unnamed_4_c9b2e921(S)[Lock___unnamed_4_c9b2e921(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Lock___unnamed_4_c9b2e921Inv(S)} S[x] ==> _S_Lock___unnamed_4_c9b2e921Inv(S)[Lock___unnamed_4_c9b2e921Inv(x)]);
+
+axiom (forall x:int :: {Lock___unnamed_4_c9b2e921(x)} Lock___unnamed_4_c9b2e921(x) == x + 0);
+axiom (forall x:int :: {Lock___unnamed_4_c9b2e921Inv(x)} Lock___unnamed_4_c9b2e921Inv(x) == x - 0);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1) == Lock___unnamed_4_c9b2e921Inv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 0)} MINUS_LEFT_PTR(x, 1, 0) == Lock___unnamed_4_c9b2e921Inv(x));
+function LowMemoryCount__IO_REMOVE_LOCK_DBG_BLOCK(int) returns (int);
+function LowMemoryCount__IO_REMOVE_LOCK_DBG_BLOCKInv(int) returns (int);
+function _S_LowMemoryCount__IO_REMOVE_LOCK_DBG_BLOCK([int]bool) returns ([int]bool);
+function _S_LowMemoryCount__IO_REMOVE_LOCK_DBG_BLOCKInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {LowMemoryCount__IO_REMOVE_LOCK_DBG_BLOCKInv(LowMemoryCount__IO_REMOVE_LOCK_DBG_BLOCK(x))} LowMemoryCount__IO_REMOVE_LOCK_DBG_BLOCKInv(LowMemoryCount__IO_REMOVE_LOCK_DBG_BLOCK(x)) == x);
+axiom (forall x:int :: {LowMemoryCount__IO_REMOVE_LOCK_DBG_BLOCKInv(x)} LowMemoryCount__IO_REMOVE_LOCK_DBG_BLOCK(LowMemoryCount__IO_REMOVE_LOCK_DBG_BLOCKInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_LowMemoryCount__IO_REMOVE_LOCK_DBG_BLOCK(S)[x]} _S_LowMemoryCount__IO_REMOVE_LOCK_DBG_BLOCK(S)[x] <==> S[LowMemoryCount__IO_REMOVE_LOCK_DBG_BLOCKInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_LowMemoryCount__IO_REMOVE_LOCK_DBG_BLOCKInv(S)[x]} _S_LowMemoryCount__IO_REMOVE_LOCK_DBG_BLOCKInv(S)[x] <==> S[LowMemoryCount__IO_REMOVE_LOCK_DBG_BLOCK(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_LowMemoryCount__IO_REMOVE_LOCK_DBG_BLOCK(S)} S[x] ==> _S_LowMemoryCount__IO_REMOVE_LOCK_DBG_BLOCK(S)[LowMemoryCount__IO_REMOVE_LOCK_DBG_BLOCK(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_LowMemoryCount__IO_REMOVE_LOCK_DBG_BLOCKInv(S)} S[x] ==> _S_LowMemoryCount__IO_REMOVE_LOCK_DBG_BLOCKInv(S)[LowMemoryCount__IO_REMOVE_LOCK_DBG_BLOCKInv(x)]);
+
+axiom (forall x:int :: {LowMemoryCount__IO_REMOVE_LOCK_DBG_BLOCK(x)} LowMemoryCount__IO_REMOVE_LOCK_DBG_BLOCK(x) == x + 32);
+axiom (forall x:int :: {LowMemoryCount__IO_REMOVE_LOCK_DBG_BLOCKInv(x)} LowMemoryCount__IO_REMOVE_LOCK_DBG_BLOCKInv(x) == x - 32);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 32, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 32, 1) == LowMemoryCount__IO_REMOVE_LOCK_DBG_BLOCKInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 32)} MINUS_LEFT_PTR(x, 1, 32) == LowMemoryCount__IO_REMOVE_LOCK_DBG_BLOCKInv(x));
+function MaxLockedTicks__IO_REMOVE_LOCK_DBG_BLOCK(int) returns (int);
+function MaxLockedTicks__IO_REMOVE_LOCK_DBG_BLOCKInv(int) returns (int);
+function _S_MaxLockedTicks__IO_REMOVE_LOCK_DBG_BLOCK([int]bool) returns ([int]bool);
+function _S_MaxLockedTicks__IO_REMOVE_LOCK_DBG_BLOCKInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {MaxLockedTicks__IO_REMOVE_LOCK_DBG_BLOCKInv(MaxLockedTicks__IO_REMOVE_LOCK_DBG_BLOCK(x))} MaxLockedTicks__IO_REMOVE_LOCK_DBG_BLOCKInv(MaxLockedTicks__IO_REMOVE_LOCK_DBG_BLOCK(x)) == x);
+axiom (forall x:int :: {MaxLockedTicks__IO_REMOVE_LOCK_DBG_BLOCKInv(x)} MaxLockedTicks__IO_REMOVE_LOCK_DBG_BLOCK(MaxLockedTicks__IO_REMOVE_LOCK_DBG_BLOCKInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_MaxLockedTicks__IO_REMOVE_LOCK_DBG_BLOCK(S)[x]} _S_MaxLockedTicks__IO_REMOVE_LOCK_DBG_BLOCK(S)[x] <==> S[MaxLockedTicks__IO_REMOVE_LOCK_DBG_BLOCKInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_MaxLockedTicks__IO_REMOVE_LOCK_DBG_BLOCKInv(S)[x]} _S_MaxLockedTicks__IO_REMOVE_LOCK_DBG_BLOCKInv(S)[x] <==> S[MaxLockedTicks__IO_REMOVE_LOCK_DBG_BLOCK(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_MaxLockedTicks__IO_REMOVE_LOCK_DBG_BLOCK(S)} S[x] ==> _S_MaxLockedTicks__IO_REMOVE_LOCK_DBG_BLOCK(S)[MaxLockedTicks__IO_REMOVE_LOCK_DBG_BLOCK(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_MaxLockedTicks__IO_REMOVE_LOCK_DBG_BLOCKInv(S)} S[x] ==> _S_MaxLockedTicks__IO_REMOVE_LOCK_DBG_BLOCKInv(S)[MaxLockedTicks__IO_REMOVE_LOCK_DBG_BLOCKInv(x)]);
+
+axiom (forall x:int :: {MaxLockedTicks__IO_REMOVE_LOCK_DBG_BLOCK(x)} MaxLockedTicks__IO_REMOVE_LOCK_DBG_BLOCK(x) == x + 8);
+axiom (forall x:int :: {MaxLockedTicks__IO_REMOVE_LOCK_DBG_BLOCKInv(x)} MaxLockedTicks__IO_REMOVE_LOCK_DBG_BLOCKInv(x) == x - 8);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 8, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 8, 1) == MaxLockedTicks__IO_REMOVE_LOCK_DBG_BLOCKInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 8)} MINUS_LEFT_PTR(x, 1, 8) == MaxLockedTicks__IO_REMOVE_LOCK_DBG_BLOCKInv(x));
+function MaximumLength__UNICODE_STRING(int) returns (int);
+function MaximumLength__UNICODE_STRINGInv(int) returns (int);
+function _S_MaximumLength__UNICODE_STRING([int]bool) returns ([int]bool);
+function _S_MaximumLength__UNICODE_STRINGInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {MaximumLength__UNICODE_STRINGInv(MaximumLength__UNICODE_STRING(x))} MaximumLength__UNICODE_STRINGInv(MaximumLength__UNICODE_STRING(x)) == x);
+axiom (forall x:int :: {MaximumLength__UNICODE_STRINGInv(x)} MaximumLength__UNICODE_STRING(MaximumLength__UNICODE_STRINGInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_MaximumLength__UNICODE_STRING(S)[x]} _S_MaximumLength__UNICODE_STRING(S)[x] <==> S[MaximumLength__UNICODE_STRINGInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_MaximumLength__UNICODE_STRINGInv(S)[x]} _S_MaximumLength__UNICODE_STRINGInv(S)[x] <==> S[MaximumLength__UNICODE_STRING(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_MaximumLength__UNICODE_STRING(S)} S[x] ==> _S_MaximumLength__UNICODE_STRING(S)[MaximumLength__UNICODE_STRING(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_MaximumLength__UNICODE_STRINGInv(S)} S[x] ==> _S_MaximumLength__UNICODE_STRINGInv(S)[MaximumLength__UNICODE_STRINGInv(x)]);
+
+axiom (forall x:int :: {MaximumLength__UNICODE_STRING(x)} MaximumLength__UNICODE_STRING(x) == x + 2);
+axiom (forall x:int :: {MaximumLength__UNICODE_STRINGInv(x)} MaximumLength__UNICODE_STRINGInv(x) == x - 2);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 2, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 2, 1) == MaximumLength__UNICODE_STRINGInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 2)} MINUS_LEFT_PTR(x, 1, 2) == MaximumLength__UNICODE_STRINGInv(x));
+function MinDeviceWakeState__DEVICE_EXTENSION(int) returns (int);
+function MinDeviceWakeState__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_MinDeviceWakeState__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_MinDeviceWakeState__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {MinDeviceWakeState__DEVICE_EXTENSIONInv(MinDeviceWakeState__DEVICE_EXTENSION(x))} MinDeviceWakeState__DEVICE_EXTENSIONInv(MinDeviceWakeState__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {MinDeviceWakeState__DEVICE_EXTENSIONInv(x)} MinDeviceWakeState__DEVICE_EXTENSION(MinDeviceWakeState__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_MinDeviceWakeState__DEVICE_EXTENSION(S)[x]} _S_MinDeviceWakeState__DEVICE_EXTENSION(S)[x] <==> S[MinDeviceWakeState__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_MinDeviceWakeState__DEVICE_EXTENSIONInv(S)[x]} _S_MinDeviceWakeState__DEVICE_EXTENSIONInv(S)[x] <==> S[MinDeviceWakeState__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_MinDeviceWakeState__DEVICE_EXTENSION(S)} S[x] ==> _S_MinDeviceWakeState__DEVICE_EXTENSION(S)[MinDeviceWakeState__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_MinDeviceWakeState__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_MinDeviceWakeState__DEVICE_EXTENSIONInv(S)[MinDeviceWakeState__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {MinDeviceWakeState__DEVICE_EXTENSION(x)} MinDeviceWakeState__DEVICE_EXTENSION(x) == x + 232);
+axiom (forall x:int :: {MinDeviceWakeState__DEVICE_EXTENSIONInv(x)} MinDeviceWakeState__DEVICE_EXTENSIONInv(x) == x - 232);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 232, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 232, 1) == MinDeviceWakeState__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 232)} MINUS_LEFT_PTR(x, 1, 232) == MinDeviceWakeState__DEVICE_EXTENSIONInv(x));
+function MinSystemWakeState__DEVICE_EXTENSION(int) returns (int);
+function MinSystemWakeState__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_MinSystemWakeState__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_MinSystemWakeState__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {MinSystemWakeState__DEVICE_EXTENSIONInv(MinSystemWakeState__DEVICE_EXTENSION(x))} MinSystemWakeState__DEVICE_EXTENSIONInv(MinSystemWakeState__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {MinSystemWakeState__DEVICE_EXTENSIONInv(x)} MinSystemWakeState__DEVICE_EXTENSION(MinSystemWakeState__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_MinSystemWakeState__DEVICE_EXTENSION(S)[x]} _S_MinSystemWakeState__DEVICE_EXTENSION(S)[x] <==> S[MinSystemWakeState__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_MinSystemWakeState__DEVICE_EXTENSIONInv(S)[x]} _S_MinSystemWakeState__DEVICE_EXTENSIONInv(S)[x] <==> S[MinSystemWakeState__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_MinSystemWakeState__DEVICE_EXTENSION(S)} S[x] ==> _S_MinSystemWakeState__DEVICE_EXTENSION(S)[MinSystemWakeState__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_MinSystemWakeState__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_MinSystemWakeState__DEVICE_EXTENSIONInv(S)[MinSystemWakeState__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {MinSystemWakeState__DEVICE_EXTENSION(x)} MinSystemWakeState__DEVICE_EXTENSION(x) == x + 236);
+axiom (forall x:int :: {MinSystemWakeState__DEVICE_EXTENSIONInv(x)} MinSystemWakeState__DEVICE_EXTENSIONInv(x) == x - 236);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 236, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 236, 1) == MinSystemWakeState__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 236)} MINUS_LEFT_PTR(x, 1, 236) == MinSystemWakeState__DEVICE_EXTENSIONInv(x));
+function MouseAttributes__DEVICE_EXTENSION(int) returns (int);
+function MouseAttributes__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_MouseAttributes__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_MouseAttributes__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {MouseAttributes__DEVICE_EXTENSIONInv(MouseAttributes__DEVICE_EXTENSION(x))} MouseAttributes__DEVICE_EXTENSIONInv(MouseAttributes__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {MouseAttributes__DEVICE_EXTENSIONInv(x)} MouseAttributes__DEVICE_EXTENSION(MouseAttributes__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_MouseAttributes__DEVICE_EXTENSION(S)[x]} _S_MouseAttributes__DEVICE_EXTENSION(S)[x] <==> S[MouseAttributes__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_MouseAttributes__DEVICE_EXTENSIONInv(S)[x]} _S_MouseAttributes__DEVICE_EXTENSIONInv(S)[x] <==> S[MouseAttributes__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_MouseAttributes__DEVICE_EXTENSION(S)} S[x] ==> _S_MouseAttributes__DEVICE_EXTENSION(S)[MouseAttributes__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_MouseAttributes__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_MouseAttributes__DEVICE_EXTENSIONInv(S)[MouseAttributes__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {MouseAttributes__DEVICE_EXTENSION(x)} MouseAttributes__DEVICE_EXTENSION(x) == x + 140);
+axiom (forall x:int :: {MouseAttributes__DEVICE_EXTENSIONInv(x)} MouseAttributes__DEVICE_EXTENSIONInv(x) == x - 140);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 140, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 140, 1) == MouseAttributes__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 140)} MINUS_LEFT_PTR(x, 1, 140) == MouseAttributes__DEVICE_EXTENSIONInv(x));
+function MouseIdentifier__MOUSE_ATTRIBUTES(int) returns (int);
+function MouseIdentifier__MOUSE_ATTRIBUTESInv(int) returns (int);
+function _S_MouseIdentifier__MOUSE_ATTRIBUTES([int]bool) returns ([int]bool);
+function _S_MouseIdentifier__MOUSE_ATTRIBUTESInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {MouseIdentifier__MOUSE_ATTRIBUTESInv(MouseIdentifier__MOUSE_ATTRIBUTES(x))} MouseIdentifier__MOUSE_ATTRIBUTESInv(MouseIdentifier__MOUSE_ATTRIBUTES(x)) == x);
+axiom (forall x:int :: {MouseIdentifier__MOUSE_ATTRIBUTESInv(x)} MouseIdentifier__MOUSE_ATTRIBUTES(MouseIdentifier__MOUSE_ATTRIBUTESInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_MouseIdentifier__MOUSE_ATTRIBUTES(S)[x]} _S_MouseIdentifier__MOUSE_ATTRIBUTES(S)[x] <==> S[MouseIdentifier__MOUSE_ATTRIBUTESInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_MouseIdentifier__MOUSE_ATTRIBUTESInv(S)[x]} _S_MouseIdentifier__MOUSE_ATTRIBUTESInv(S)[x] <==> S[MouseIdentifier__MOUSE_ATTRIBUTES(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_MouseIdentifier__MOUSE_ATTRIBUTES(S)} S[x] ==> _S_MouseIdentifier__MOUSE_ATTRIBUTES(S)[MouseIdentifier__MOUSE_ATTRIBUTES(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_MouseIdentifier__MOUSE_ATTRIBUTESInv(S)} S[x] ==> _S_MouseIdentifier__MOUSE_ATTRIBUTESInv(S)[MouseIdentifier__MOUSE_ATTRIBUTESInv(x)]);
+
+axiom (forall x:int :: {MouseIdentifier__MOUSE_ATTRIBUTES(x)} MouseIdentifier__MOUSE_ATTRIBUTES(x) == x + 0);
+axiom (forall x:int :: {MouseIdentifier__MOUSE_ATTRIBUTESInv(x)} MouseIdentifier__MOUSE_ATTRIBUTESInv(x) == x - 0);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1) == MouseIdentifier__MOUSE_ATTRIBUTESInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 0)} MINUS_LEFT_PTR(x, 1, 0) == MouseIdentifier__MOUSE_ATTRIBUTESInv(x));
+function Mutex__GLOBALS(int) returns (int);
+function Mutex__GLOBALSInv(int) returns (int);
+function _S_Mutex__GLOBALS([int]bool) returns ([int]bool);
+function _S_Mutex__GLOBALSInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {Mutex__GLOBALSInv(Mutex__GLOBALS(x))} Mutex__GLOBALSInv(Mutex__GLOBALS(x)) == x);
+axiom (forall x:int :: {Mutex__GLOBALSInv(x)} Mutex__GLOBALS(Mutex__GLOBALSInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_Mutex__GLOBALS(S)[x]} _S_Mutex__GLOBALS(S)[x] <==> S[Mutex__GLOBALSInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_Mutex__GLOBALSInv(S)[x]} _S_Mutex__GLOBALSInv(S)[x] <==> S[Mutex__GLOBALS(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Mutex__GLOBALS(S)} S[x] ==> _S_Mutex__GLOBALS(S)[Mutex__GLOBALS(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Mutex__GLOBALSInv(S)} S[x] ==> _S_Mutex__GLOBALSInv(S)[Mutex__GLOBALSInv(x)]);
+
+axiom (forall x:int :: {Mutex__GLOBALS(x)} Mutex__GLOBALS(x) == x + 24);
+axiom (forall x:int :: {Mutex__GLOBALSInv(x)} Mutex__GLOBALSInv(x) == x - 24);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 24, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 24, 1) == Mutex__GLOBALSInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 24)} MINUS_LEFT_PTR(x, 1, 24) == Mutex__GLOBALSInv(x));
+function NpxIrql___unnamed_1_2bb39c56(int) returns (int);
+function NpxIrql___unnamed_1_2bb39c56Inv(int) returns (int);
+function _S_NpxIrql___unnamed_1_2bb39c56([int]bool) returns ([int]bool);
+function _S_NpxIrql___unnamed_1_2bb39c56Inv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {NpxIrql___unnamed_1_2bb39c56Inv(NpxIrql___unnamed_1_2bb39c56(x))} NpxIrql___unnamed_1_2bb39c56Inv(NpxIrql___unnamed_1_2bb39c56(x)) == x);
+axiom (forall x:int :: {NpxIrql___unnamed_1_2bb39c56Inv(x)} NpxIrql___unnamed_1_2bb39c56(NpxIrql___unnamed_1_2bb39c56Inv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_NpxIrql___unnamed_1_2bb39c56(S)[x]} _S_NpxIrql___unnamed_1_2bb39c56(S)[x] <==> S[NpxIrql___unnamed_1_2bb39c56Inv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_NpxIrql___unnamed_1_2bb39c56Inv(S)[x]} _S_NpxIrql___unnamed_1_2bb39c56Inv(S)[x] <==> S[NpxIrql___unnamed_1_2bb39c56(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_NpxIrql___unnamed_1_2bb39c56(S)} S[x] ==> _S_NpxIrql___unnamed_1_2bb39c56(S)[NpxIrql___unnamed_1_2bb39c56(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_NpxIrql___unnamed_1_2bb39c56Inv(S)} S[x] ==> _S_NpxIrql___unnamed_1_2bb39c56Inv(S)[NpxIrql___unnamed_1_2bb39c56Inv(x)]);
+
+axiom (forall x:int :: {NpxIrql___unnamed_1_2bb39c56(x)} NpxIrql___unnamed_1_2bb39c56(x) == x + 0);
+axiom (forall x:int :: {NpxIrql___unnamed_1_2bb39c56Inv(x)} NpxIrql___unnamed_1_2bb39c56Inv(x) == x - 0);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1) == NpxIrql___unnamed_1_2bb39c56Inv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 0)} MINUS_LEFT_PTR(x, 1, 0) == NpxIrql___unnamed_1_2bb39c56Inv(x));
+function NumberOfButtons__MOUSE_ATTRIBUTES(int) returns (int);
+function NumberOfButtons__MOUSE_ATTRIBUTESInv(int) returns (int);
+function _S_NumberOfButtons__MOUSE_ATTRIBUTES([int]bool) returns ([int]bool);
+function _S_NumberOfButtons__MOUSE_ATTRIBUTESInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {NumberOfButtons__MOUSE_ATTRIBUTESInv(NumberOfButtons__MOUSE_ATTRIBUTES(x))} NumberOfButtons__MOUSE_ATTRIBUTESInv(NumberOfButtons__MOUSE_ATTRIBUTES(x)) == x);
+axiom (forall x:int :: {NumberOfButtons__MOUSE_ATTRIBUTESInv(x)} NumberOfButtons__MOUSE_ATTRIBUTES(NumberOfButtons__MOUSE_ATTRIBUTESInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_NumberOfButtons__MOUSE_ATTRIBUTES(S)[x]} _S_NumberOfButtons__MOUSE_ATTRIBUTES(S)[x] <==> S[NumberOfButtons__MOUSE_ATTRIBUTESInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_NumberOfButtons__MOUSE_ATTRIBUTESInv(S)[x]} _S_NumberOfButtons__MOUSE_ATTRIBUTESInv(S)[x] <==> S[NumberOfButtons__MOUSE_ATTRIBUTES(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_NumberOfButtons__MOUSE_ATTRIBUTES(S)} S[x] ==> _S_NumberOfButtons__MOUSE_ATTRIBUTES(S)[NumberOfButtons__MOUSE_ATTRIBUTES(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_NumberOfButtons__MOUSE_ATTRIBUTESInv(S)} S[x] ==> _S_NumberOfButtons__MOUSE_ATTRIBUTESInv(S)[NumberOfButtons__MOUSE_ATTRIBUTESInv(x)]);
+
+axiom (forall x:int :: {NumberOfButtons__MOUSE_ATTRIBUTES(x)} NumberOfButtons__MOUSE_ATTRIBUTES(x) == x + 2);
+axiom (forall x:int :: {NumberOfButtons__MOUSE_ATTRIBUTESInv(x)} NumberOfButtons__MOUSE_ATTRIBUTESInv(x) == x - 2);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 2, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 2, 1) == NumberOfButtons__MOUSE_ATTRIBUTESInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 2)} MINUS_LEFT_PTR(x, 1, 2) == NumberOfButtons__MOUSE_ATTRIBUTESInv(x));
+function OkayToLogOverflow__DEVICE_EXTENSION(int) returns (int);
+function OkayToLogOverflow__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_OkayToLogOverflow__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_OkayToLogOverflow__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {OkayToLogOverflow__DEVICE_EXTENSIONInv(OkayToLogOverflow__DEVICE_EXTENSION(x))} OkayToLogOverflow__DEVICE_EXTENSIONInv(OkayToLogOverflow__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {OkayToLogOverflow__DEVICE_EXTENSIONInv(x)} OkayToLogOverflow__DEVICE_EXTENSION(OkayToLogOverflow__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_OkayToLogOverflow__DEVICE_EXTENSION(S)[x]} _S_OkayToLogOverflow__DEVICE_EXTENSION(S)[x] <==> S[OkayToLogOverflow__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_OkayToLogOverflow__DEVICE_EXTENSIONInv(S)[x]} _S_OkayToLogOverflow__DEVICE_EXTENSIONInv(S)[x] <==> S[OkayToLogOverflow__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_OkayToLogOverflow__DEVICE_EXTENSION(S)} S[x] ==> _S_OkayToLogOverflow__DEVICE_EXTENSION(S)[OkayToLogOverflow__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_OkayToLogOverflow__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_OkayToLogOverflow__DEVICE_EXTENSIONInv(S)[OkayToLogOverflow__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {OkayToLogOverflow__DEVICE_EXTENSION(x)} OkayToLogOverflow__DEVICE_EXTENSION(x) == x + 106);
+axiom (forall x:int :: {OkayToLogOverflow__DEVICE_EXTENSIONInv(x)} OkayToLogOverflow__DEVICE_EXTENSIONInv(x) == x - 106);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 106, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 106, 1) == OkayToLogOverflow__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 106)} MINUS_LEFT_PTR(x, 1, 106) == OkayToLogOverflow__DEVICE_EXTENSIONInv(x));
+function PDO__DEVICE_EXTENSION(int) returns (int);
+function PDO__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_PDO__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_PDO__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {PDO__DEVICE_EXTENSIONInv(PDO__DEVICE_EXTENSION(x))} PDO__DEVICE_EXTENSIONInv(PDO__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {PDO__DEVICE_EXTENSIONInv(x)} PDO__DEVICE_EXTENSION(PDO__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_PDO__DEVICE_EXTENSION(S)[x]} _S_PDO__DEVICE_EXTENSION(S)[x] <==> S[PDO__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_PDO__DEVICE_EXTENSIONInv(S)[x]} _S_PDO__DEVICE_EXTENSIONInv(S)[x] <==> S[PDO__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_PDO__DEVICE_EXTENSION(S)} S[x] ==> _S_PDO__DEVICE_EXTENSION(S)[PDO__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_PDO__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_PDO__DEVICE_EXTENSIONInv(S)[PDO__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {PDO__DEVICE_EXTENSION(x)} PDO__DEVICE_EXTENSION(x) == x + 12);
+axiom (forall x:int :: {PDO__DEVICE_EXTENSIONInv(x)} PDO__DEVICE_EXTENSIONInv(x) == x - 12);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 12, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 12, 1) == PDO__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 12)} MINUS_LEFT_PTR(x, 1, 12) == PDO__DEVICE_EXTENSIONInv(x));
+function PnP__DEVICE_EXTENSION(int) returns (int);
+function PnP__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_PnP__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_PnP__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {PnP__DEVICE_EXTENSIONInv(PnP__DEVICE_EXTENSION(x))} PnP__DEVICE_EXTENSIONInv(PnP__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {PnP__DEVICE_EXTENSIONInv(x)} PnP__DEVICE_EXTENSION(PnP__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_PnP__DEVICE_EXTENSION(S)[x]} _S_PnP__DEVICE_EXTENSION(S)[x] <==> S[PnP__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_PnP__DEVICE_EXTENSIONInv(S)[x]} _S_PnP__DEVICE_EXTENSIONInv(S)[x] <==> S[PnP__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_PnP__DEVICE_EXTENSION(S)} S[x] ==> _S_PnP__DEVICE_EXTENSION(S)[PnP__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_PnP__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_PnP__DEVICE_EXTENSIONInv(S)[PnP__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {PnP__DEVICE_EXTENSION(x)} PnP__DEVICE_EXTENSION(x) == x + 104);
+axiom (forall x:int :: {PnP__DEVICE_EXTENSIONInv(x)} PnP__DEVICE_EXTENSIONInv(x) == x - 104);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 104, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 104, 1) == PnP__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 104)} MINUS_LEFT_PTR(x, 1, 104) == PnP__DEVICE_EXTENSIONInv(x));
+function QueryWmiDataBlock__WMILIB_CONTEXT(int) returns (int);
+function QueryWmiDataBlock__WMILIB_CONTEXTInv(int) returns (int);
+function _S_QueryWmiDataBlock__WMILIB_CONTEXT([int]bool) returns ([int]bool);
+function _S_QueryWmiDataBlock__WMILIB_CONTEXTInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {QueryWmiDataBlock__WMILIB_CONTEXTInv(QueryWmiDataBlock__WMILIB_CONTEXT(x))} QueryWmiDataBlock__WMILIB_CONTEXTInv(QueryWmiDataBlock__WMILIB_CONTEXT(x)) == x);
+axiom (forall x:int :: {QueryWmiDataBlock__WMILIB_CONTEXTInv(x)} QueryWmiDataBlock__WMILIB_CONTEXT(QueryWmiDataBlock__WMILIB_CONTEXTInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_QueryWmiDataBlock__WMILIB_CONTEXT(S)[x]} _S_QueryWmiDataBlock__WMILIB_CONTEXT(S)[x] <==> S[QueryWmiDataBlock__WMILIB_CONTEXTInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_QueryWmiDataBlock__WMILIB_CONTEXTInv(S)[x]} _S_QueryWmiDataBlock__WMILIB_CONTEXTInv(S)[x] <==> S[QueryWmiDataBlock__WMILIB_CONTEXT(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_QueryWmiDataBlock__WMILIB_CONTEXT(S)} S[x] ==> _S_QueryWmiDataBlock__WMILIB_CONTEXT(S)[QueryWmiDataBlock__WMILIB_CONTEXT(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_QueryWmiDataBlock__WMILIB_CONTEXTInv(S)} S[x] ==> _S_QueryWmiDataBlock__WMILIB_CONTEXTInv(S)[QueryWmiDataBlock__WMILIB_CONTEXTInv(x)]);
+
+axiom (forall x:int :: {QueryWmiDataBlock__WMILIB_CONTEXT(x)} QueryWmiDataBlock__WMILIB_CONTEXT(x) == x + 12);
+axiom (forall x:int :: {QueryWmiDataBlock__WMILIB_CONTEXTInv(x)} QueryWmiDataBlock__WMILIB_CONTEXTInv(x) == x - 12);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 12, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 12, 1) == QueryWmiDataBlock__WMILIB_CONTEXTInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 12)} MINUS_LEFT_PTR(x, 1, 12) == QueryWmiDataBlock__WMILIB_CONTEXTInv(x));
+function QueryWmiRegInfo__WMILIB_CONTEXT(int) returns (int);
+function QueryWmiRegInfo__WMILIB_CONTEXTInv(int) returns (int);
+function _S_QueryWmiRegInfo__WMILIB_CONTEXT([int]bool) returns ([int]bool);
+function _S_QueryWmiRegInfo__WMILIB_CONTEXTInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {QueryWmiRegInfo__WMILIB_CONTEXTInv(QueryWmiRegInfo__WMILIB_CONTEXT(x))} QueryWmiRegInfo__WMILIB_CONTEXTInv(QueryWmiRegInfo__WMILIB_CONTEXT(x)) == x);
+axiom (forall x:int :: {QueryWmiRegInfo__WMILIB_CONTEXTInv(x)} QueryWmiRegInfo__WMILIB_CONTEXT(QueryWmiRegInfo__WMILIB_CONTEXTInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_QueryWmiRegInfo__WMILIB_CONTEXT(S)[x]} _S_QueryWmiRegInfo__WMILIB_CONTEXT(S)[x] <==> S[QueryWmiRegInfo__WMILIB_CONTEXTInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_QueryWmiRegInfo__WMILIB_CONTEXTInv(S)[x]} _S_QueryWmiRegInfo__WMILIB_CONTEXTInv(S)[x] <==> S[QueryWmiRegInfo__WMILIB_CONTEXT(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_QueryWmiRegInfo__WMILIB_CONTEXT(S)} S[x] ==> _S_QueryWmiRegInfo__WMILIB_CONTEXT(S)[QueryWmiRegInfo__WMILIB_CONTEXT(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_QueryWmiRegInfo__WMILIB_CONTEXTInv(S)} S[x] ==> _S_QueryWmiRegInfo__WMILIB_CONTEXTInv(S)[QueryWmiRegInfo__WMILIB_CONTEXTInv(x)]);
+
+axiom (forall x:int :: {QueryWmiRegInfo__WMILIB_CONTEXT(x)} QueryWmiRegInfo__WMILIB_CONTEXT(x) == x + 8);
+axiom (forall x:int :: {QueryWmiRegInfo__WMILIB_CONTEXTInv(x)} QueryWmiRegInfo__WMILIB_CONTEXTInv(x) == x - 8);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 8, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 8, 1) == QueryWmiRegInfo__WMILIB_CONTEXTInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 8)} MINUS_LEFT_PTR(x, 1, 8) == QueryWmiRegInfo__WMILIB_CONTEXTInv(x));
+function ReadQueue__DEVICE_EXTENSION(int) returns (int);
+function ReadQueue__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_ReadQueue__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_ReadQueue__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {ReadQueue__DEVICE_EXTENSIONInv(ReadQueue__DEVICE_EXTENSION(x))} ReadQueue__DEVICE_EXTENSIONInv(ReadQueue__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {ReadQueue__DEVICE_EXTENSIONInv(x)} ReadQueue__DEVICE_EXTENSION(ReadQueue__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_ReadQueue__DEVICE_EXTENSION(S)[x]} _S_ReadQueue__DEVICE_EXTENSION(S)[x] <==> S[ReadQueue__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_ReadQueue__DEVICE_EXTENSIONInv(S)[x]} _S_ReadQueue__DEVICE_EXTENSIONInv(S)[x] <==> S[ReadQueue__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_ReadQueue__DEVICE_EXTENSION(S)} S[x] ==> _S_ReadQueue__DEVICE_EXTENSION(S)[ReadQueue__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_ReadQueue__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_ReadQueue__DEVICE_EXTENSIONInv(S)[ReadQueue__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {ReadQueue__DEVICE_EXTENSION(x)} ReadQueue__DEVICE_EXTENSION(x) == x + 156);
+axiom (forall x:int :: {ReadQueue__DEVICE_EXTENSIONInv(x)} ReadQueue__DEVICE_EXTENSIONInv(x) == x - 156);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 156, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 156, 1) == ReadQueue__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 156)} MINUS_LEFT_PTR(x, 1, 156) == ReadQueue__DEVICE_EXTENSIONInv(x));
+function RemoveEvent__IO_REMOVE_LOCK_COMMON_BLOCK(int) returns (int);
+function RemoveEvent__IO_REMOVE_LOCK_COMMON_BLOCKInv(int) returns (int);
+function _S_RemoveEvent__IO_REMOVE_LOCK_COMMON_BLOCK([int]bool) returns ([int]bool);
+function _S_RemoveEvent__IO_REMOVE_LOCK_COMMON_BLOCKInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {RemoveEvent__IO_REMOVE_LOCK_COMMON_BLOCKInv(RemoveEvent__IO_REMOVE_LOCK_COMMON_BLOCK(x))} RemoveEvent__IO_REMOVE_LOCK_COMMON_BLOCKInv(RemoveEvent__IO_REMOVE_LOCK_COMMON_BLOCK(x)) == x);
+axiom (forall x:int :: {RemoveEvent__IO_REMOVE_LOCK_COMMON_BLOCKInv(x)} RemoveEvent__IO_REMOVE_LOCK_COMMON_BLOCK(RemoveEvent__IO_REMOVE_LOCK_COMMON_BLOCKInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_RemoveEvent__IO_REMOVE_LOCK_COMMON_BLOCK(S)[x]} _S_RemoveEvent__IO_REMOVE_LOCK_COMMON_BLOCK(S)[x] <==> S[RemoveEvent__IO_REMOVE_LOCK_COMMON_BLOCKInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_RemoveEvent__IO_REMOVE_LOCK_COMMON_BLOCKInv(S)[x]} _S_RemoveEvent__IO_REMOVE_LOCK_COMMON_BLOCKInv(S)[x] <==> S[RemoveEvent__IO_REMOVE_LOCK_COMMON_BLOCK(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_RemoveEvent__IO_REMOVE_LOCK_COMMON_BLOCK(S)} S[x] ==> _S_RemoveEvent__IO_REMOVE_LOCK_COMMON_BLOCK(S)[RemoveEvent__IO_REMOVE_LOCK_COMMON_BLOCK(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_RemoveEvent__IO_REMOVE_LOCK_COMMON_BLOCKInv(S)} S[x] ==> _S_RemoveEvent__IO_REMOVE_LOCK_COMMON_BLOCKInv(S)[RemoveEvent__IO_REMOVE_LOCK_COMMON_BLOCKInv(x)]);
+
+axiom (forall x:int :: {RemoveEvent__IO_REMOVE_LOCK_COMMON_BLOCK(x)} RemoveEvent__IO_REMOVE_LOCK_COMMON_BLOCK(x) == x + 8);
+axiom (forall x:int :: {RemoveEvent__IO_REMOVE_LOCK_COMMON_BLOCKInv(x)} RemoveEvent__IO_REMOVE_LOCK_COMMON_BLOCKInv(x) == x - 8);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 8, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 8, 1) == RemoveEvent__IO_REMOVE_LOCK_COMMON_BLOCKInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 8)} MINUS_LEFT_PTR(x, 1, 8) == RemoveEvent__IO_REMOVE_LOCK_COMMON_BLOCKInv(x));
+function RemoveLock__DEVICE_EXTENSION(int) returns (int);
+function RemoveLock__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_RemoveLock__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_RemoveLock__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {RemoveLock__DEVICE_EXTENSIONInv(RemoveLock__DEVICE_EXTENSION(x))} RemoveLock__DEVICE_EXTENSIONInv(RemoveLock__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {RemoveLock__DEVICE_EXTENSIONInv(x)} RemoveLock__DEVICE_EXTENSION(RemoveLock__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_RemoveLock__DEVICE_EXTENSION(S)[x]} _S_RemoveLock__DEVICE_EXTENSION(S)[x] <==> S[RemoveLock__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_RemoveLock__DEVICE_EXTENSIONInv(S)[x]} _S_RemoveLock__DEVICE_EXTENSIONInv(S)[x] <==> S[RemoveLock__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_RemoveLock__DEVICE_EXTENSION(S)} S[x] ==> _S_RemoveLock__DEVICE_EXTENSION(S)[RemoveLock__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_RemoveLock__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_RemoveLock__DEVICE_EXTENSIONInv(S)[RemoveLock__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {RemoveLock__DEVICE_EXTENSION(x)} RemoveLock__DEVICE_EXTENSION(x) == x + 16);
+axiom (forall x:int :: {RemoveLock__DEVICE_EXTENSIONInv(x)} RemoveLock__DEVICE_EXTENSIONInv(x) == x - 16);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 16, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 16, 1) == RemoveLock__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 16)} MINUS_LEFT_PTR(x, 1, 16) == RemoveLock__DEVICE_EXTENSIONInv(x));
+function Removed__IO_REMOVE_LOCK_COMMON_BLOCK(int) returns (int);
+function Removed__IO_REMOVE_LOCK_COMMON_BLOCKInv(int) returns (int);
+function _S_Removed__IO_REMOVE_LOCK_COMMON_BLOCK([int]bool) returns ([int]bool);
+function _S_Removed__IO_REMOVE_LOCK_COMMON_BLOCKInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {Removed__IO_REMOVE_LOCK_COMMON_BLOCKInv(Removed__IO_REMOVE_LOCK_COMMON_BLOCK(x))} Removed__IO_REMOVE_LOCK_COMMON_BLOCKInv(Removed__IO_REMOVE_LOCK_COMMON_BLOCK(x)) == x);
+axiom (forall x:int :: {Removed__IO_REMOVE_LOCK_COMMON_BLOCKInv(x)} Removed__IO_REMOVE_LOCK_COMMON_BLOCK(Removed__IO_REMOVE_LOCK_COMMON_BLOCKInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_Removed__IO_REMOVE_LOCK_COMMON_BLOCK(S)[x]} _S_Removed__IO_REMOVE_LOCK_COMMON_BLOCK(S)[x] <==> S[Removed__IO_REMOVE_LOCK_COMMON_BLOCKInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_Removed__IO_REMOVE_LOCK_COMMON_BLOCKInv(S)[x]} _S_Removed__IO_REMOVE_LOCK_COMMON_BLOCKInv(S)[x] <==> S[Removed__IO_REMOVE_LOCK_COMMON_BLOCK(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Removed__IO_REMOVE_LOCK_COMMON_BLOCK(S)} S[x] ==> _S_Removed__IO_REMOVE_LOCK_COMMON_BLOCK(S)[Removed__IO_REMOVE_LOCK_COMMON_BLOCK(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Removed__IO_REMOVE_LOCK_COMMON_BLOCKInv(S)} S[x] ==> _S_Removed__IO_REMOVE_LOCK_COMMON_BLOCKInv(S)[Removed__IO_REMOVE_LOCK_COMMON_BLOCKInv(x)]);
+
+axiom (forall x:int :: {Removed__IO_REMOVE_LOCK_COMMON_BLOCK(x)} Removed__IO_REMOVE_LOCK_COMMON_BLOCK(x) == x + 0);
+axiom (forall x:int :: {Removed__IO_REMOVE_LOCK_COMMON_BLOCKInv(x)} Removed__IO_REMOVE_LOCK_COMMON_BLOCKInv(x) == x - 0);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1) == Removed__IO_REMOVE_LOCK_COMMON_BLOCKInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 0)} MINUS_LEFT_PTR(x, 1, 0) == Removed__IO_REMOVE_LOCK_COMMON_BLOCKInv(x));
+function Reserved1__IO_REMOVE_LOCK_DBG_BLOCK(int) returns (int);
+function Reserved1__IO_REMOVE_LOCK_DBG_BLOCKInv(int) returns (int);
+function _S_Reserved1__IO_REMOVE_LOCK_DBG_BLOCK([int]bool) returns ([int]bool);
+function _S_Reserved1__IO_REMOVE_LOCK_DBG_BLOCKInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {Reserved1__IO_REMOVE_LOCK_DBG_BLOCKInv(Reserved1__IO_REMOVE_LOCK_DBG_BLOCK(x))} Reserved1__IO_REMOVE_LOCK_DBG_BLOCKInv(Reserved1__IO_REMOVE_LOCK_DBG_BLOCK(x)) == x);
+axiom (forall x:int :: {Reserved1__IO_REMOVE_LOCK_DBG_BLOCKInv(x)} Reserved1__IO_REMOVE_LOCK_DBG_BLOCK(Reserved1__IO_REMOVE_LOCK_DBG_BLOCKInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_Reserved1__IO_REMOVE_LOCK_DBG_BLOCK(S)[x]} _S_Reserved1__IO_REMOVE_LOCK_DBG_BLOCK(S)[x] <==> S[Reserved1__IO_REMOVE_LOCK_DBG_BLOCKInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_Reserved1__IO_REMOVE_LOCK_DBG_BLOCKInv(S)[x]} _S_Reserved1__IO_REMOVE_LOCK_DBG_BLOCKInv(S)[x] <==> S[Reserved1__IO_REMOVE_LOCK_DBG_BLOCK(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Reserved1__IO_REMOVE_LOCK_DBG_BLOCK(S)} S[x] ==> _S_Reserved1__IO_REMOVE_LOCK_DBG_BLOCK(S)[Reserved1__IO_REMOVE_LOCK_DBG_BLOCK(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Reserved1__IO_REMOVE_LOCK_DBG_BLOCKInv(S)} S[x] ==> _S_Reserved1__IO_REMOVE_LOCK_DBG_BLOCKInv(S)[Reserved1__IO_REMOVE_LOCK_DBG_BLOCKInv(x)]);
+
+axiom (forall x:int :: {Reserved1__IO_REMOVE_LOCK_DBG_BLOCK(x)} Reserved1__IO_REMOVE_LOCK_DBG_BLOCK(x) == x + 36);
+axiom (forall x:int :: {Reserved1__IO_REMOVE_LOCK_DBG_BLOCKInv(x)} Reserved1__IO_REMOVE_LOCK_DBG_BLOCKInv(x) == x - 36);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 36, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 36, 1) == Reserved1__IO_REMOVE_LOCK_DBG_BLOCKInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 36)} MINUS_LEFT_PTR(x, 1, 36) == Reserved1__IO_REMOVE_LOCK_DBG_BLOCKInv(x));
+function Reserved2__IO_REMOVE_LOCK_DBG_BLOCK(int) returns (int);
+function Reserved2__IO_REMOVE_LOCK_DBG_BLOCKInv(int) returns (int);
+function _S_Reserved2__IO_REMOVE_LOCK_DBG_BLOCK([int]bool) returns ([int]bool);
+function _S_Reserved2__IO_REMOVE_LOCK_DBG_BLOCKInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {Reserved2__IO_REMOVE_LOCK_DBG_BLOCKInv(Reserved2__IO_REMOVE_LOCK_DBG_BLOCK(x))} Reserved2__IO_REMOVE_LOCK_DBG_BLOCKInv(Reserved2__IO_REMOVE_LOCK_DBG_BLOCK(x)) == x);
+axiom (forall x:int :: {Reserved2__IO_REMOVE_LOCK_DBG_BLOCKInv(x)} Reserved2__IO_REMOVE_LOCK_DBG_BLOCK(Reserved2__IO_REMOVE_LOCK_DBG_BLOCKInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_Reserved2__IO_REMOVE_LOCK_DBG_BLOCK(S)[x]} _S_Reserved2__IO_REMOVE_LOCK_DBG_BLOCK(S)[x] <==> S[Reserved2__IO_REMOVE_LOCK_DBG_BLOCKInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_Reserved2__IO_REMOVE_LOCK_DBG_BLOCKInv(S)[x]} _S_Reserved2__IO_REMOVE_LOCK_DBG_BLOCKInv(S)[x] <==> S[Reserved2__IO_REMOVE_LOCK_DBG_BLOCK(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Reserved2__IO_REMOVE_LOCK_DBG_BLOCK(S)} S[x] ==> _S_Reserved2__IO_REMOVE_LOCK_DBG_BLOCK(S)[Reserved2__IO_REMOVE_LOCK_DBG_BLOCK(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Reserved2__IO_REMOVE_LOCK_DBG_BLOCKInv(S)} S[x] ==> _S_Reserved2__IO_REMOVE_LOCK_DBG_BLOCKInv(S)[Reserved2__IO_REMOVE_LOCK_DBG_BLOCKInv(x)]);
+
+axiom (forall x:int :: {Reserved2__IO_REMOVE_LOCK_DBG_BLOCK(x)} Reserved2__IO_REMOVE_LOCK_DBG_BLOCK(x) == x + 52);
+axiom (forall x:int :: {Reserved2__IO_REMOVE_LOCK_DBG_BLOCKInv(x)} Reserved2__IO_REMOVE_LOCK_DBG_BLOCKInv(x) == x - 52);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 52, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 52, 1) == Reserved2__IO_REMOVE_LOCK_DBG_BLOCKInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 52)} MINUS_LEFT_PTR(x, 1, 52) == Reserved2__IO_REMOVE_LOCK_DBG_BLOCKInv(x));
+function Reserved__IO_REMOVE_LOCK_COMMON_BLOCK(int) returns (int);
+function Reserved__IO_REMOVE_LOCK_COMMON_BLOCKInv(int) returns (int);
+function _S_Reserved__IO_REMOVE_LOCK_COMMON_BLOCK([int]bool) returns ([int]bool);
+function _S_Reserved__IO_REMOVE_LOCK_COMMON_BLOCKInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {Reserved__IO_REMOVE_LOCK_COMMON_BLOCKInv(Reserved__IO_REMOVE_LOCK_COMMON_BLOCK(x))} Reserved__IO_REMOVE_LOCK_COMMON_BLOCKInv(Reserved__IO_REMOVE_LOCK_COMMON_BLOCK(x)) == x);
+axiom (forall x:int :: {Reserved__IO_REMOVE_LOCK_COMMON_BLOCKInv(x)} Reserved__IO_REMOVE_LOCK_COMMON_BLOCK(Reserved__IO_REMOVE_LOCK_COMMON_BLOCKInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_Reserved__IO_REMOVE_LOCK_COMMON_BLOCK(S)[x]} _S_Reserved__IO_REMOVE_LOCK_COMMON_BLOCK(S)[x] <==> S[Reserved__IO_REMOVE_LOCK_COMMON_BLOCKInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_Reserved__IO_REMOVE_LOCK_COMMON_BLOCKInv(S)[x]} _S_Reserved__IO_REMOVE_LOCK_COMMON_BLOCKInv(S)[x] <==> S[Reserved__IO_REMOVE_LOCK_COMMON_BLOCK(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Reserved__IO_REMOVE_LOCK_COMMON_BLOCK(S)} S[x] ==> _S_Reserved__IO_REMOVE_LOCK_COMMON_BLOCK(S)[Reserved__IO_REMOVE_LOCK_COMMON_BLOCK(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Reserved__IO_REMOVE_LOCK_COMMON_BLOCKInv(S)} S[x] ==> _S_Reserved__IO_REMOVE_LOCK_COMMON_BLOCKInv(S)[Reserved__IO_REMOVE_LOCK_COMMON_BLOCKInv(x)]);
+
+axiom (forall x:int :: {Reserved__IO_REMOVE_LOCK_COMMON_BLOCK(x)} Reserved__IO_REMOVE_LOCK_COMMON_BLOCK(x) == x + 1);
+axiom (forall x:int :: {Reserved__IO_REMOVE_LOCK_COMMON_BLOCKInv(x)} Reserved__IO_REMOVE_LOCK_COMMON_BLOCKInv(x) == x - 1);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 1, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 1, 1) == Reserved__IO_REMOVE_LOCK_COMMON_BLOCKInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 1)} MINUS_LEFT_PTR(x, 1, 1) == Reserved__IO_REMOVE_LOCK_COMMON_BLOCKInv(x));
+function SampleRate__MOUSE_ATTRIBUTES(int) returns (int);
+function SampleRate__MOUSE_ATTRIBUTESInv(int) returns (int);
+function _S_SampleRate__MOUSE_ATTRIBUTES([int]bool) returns ([int]bool);
+function _S_SampleRate__MOUSE_ATTRIBUTESInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {SampleRate__MOUSE_ATTRIBUTESInv(SampleRate__MOUSE_ATTRIBUTES(x))} SampleRate__MOUSE_ATTRIBUTESInv(SampleRate__MOUSE_ATTRIBUTES(x)) == x);
+axiom (forall x:int :: {SampleRate__MOUSE_ATTRIBUTESInv(x)} SampleRate__MOUSE_ATTRIBUTES(SampleRate__MOUSE_ATTRIBUTESInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_SampleRate__MOUSE_ATTRIBUTES(S)[x]} _S_SampleRate__MOUSE_ATTRIBUTES(S)[x] <==> S[SampleRate__MOUSE_ATTRIBUTESInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_SampleRate__MOUSE_ATTRIBUTESInv(S)[x]} _S_SampleRate__MOUSE_ATTRIBUTESInv(S)[x] <==> S[SampleRate__MOUSE_ATTRIBUTES(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_SampleRate__MOUSE_ATTRIBUTES(S)} S[x] ==> _S_SampleRate__MOUSE_ATTRIBUTES(S)[SampleRate__MOUSE_ATTRIBUTES(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_SampleRate__MOUSE_ATTRIBUTESInv(S)} S[x] ==> _S_SampleRate__MOUSE_ATTRIBUTESInv(S)[SampleRate__MOUSE_ATTRIBUTESInv(x)]);
+
+axiom (forall x:int :: {SampleRate__MOUSE_ATTRIBUTES(x)} SampleRate__MOUSE_ATTRIBUTES(x) == x + 4);
+axiom (forall x:int :: {SampleRate__MOUSE_ATTRIBUTESInv(x)} SampleRate__MOUSE_ATTRIBUTESInv(x) == x - 4);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 4, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 4, 1) == SampleRate__MOUSE_ATTRIBUTESInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 4)} MINUS_LEFT_PTR(x, 1, 4) == SampleRate__MOUSE_ATTRIBUTESInv(x));
+function Self__DEVICE_EXTENSION(int) returns (int);
+function Self__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_Self__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_Self__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {Self__DEVICE_EXTENSIONInv(Self__DEVICE_EXTENSION(x))} Self__DEVICE_EXTENSIONInv(Self__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {Self__DEVICE_EXTENSIONInv(x)} Self__DEVICE_EXTENSION(Self__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_Self__DEVICE_EXTENSION(S)[x]} _S_Self__DEVICE_EXTENSION(S)[x] <==> S[Self__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_Self__DEVICE_EXTENSIONInv(S)[x]} _S_Self__DEVICE_EXTENSIONInv(S)[x] <==> S[Self__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Self__DEVICE_EXTENSION(S)} S[x] ==> _S_Self__DEVICE_EXTENSION(S)[Self__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Self__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_Self__DEVICE_EXTENSIONInv(S)[Self__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {Self__DEVICE_EXTENSION(x)} Self__DEVICE_EXTENSION(x) == x + 0);
+axiom (forall x:int :: {Self__DEVICE_EXTENSIONInv(x)} Self__DEVICE_EXTENSIONInv(x) == x - 0);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1) == Self__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 0)} MINUS_LEFT_PTR(x, 1, 0) == Self__DEVICE_EXTENSIONInv(x));
+function SequenceNumber__DEVICE_EXTENSION(int) returns (int);
+function SequenceNumber__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_SequenceNumber__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_SequenceNumber__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {SequenceNumber__DEVICE_EXTENSIONInv(SequenceNumber__DEVICE_EXTENSION(x))} SequenceNumber__DEVICE_EXTENSIONInv(SequenceNumber__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {SequenceNumber__DEVICE_EXTENSIONInv(x)} SequenceNumber__DEVICE_EXTENSION(SequenceNumber__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_SequenceNumber__DEVICE_EXTENSION(S)[x]} _S_SequenceNumber__DEVICE_EXTENSION(S)[x] <==> S[SequenceNumber__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_SequenceNumber__DEVICE_EXTENSIONInv(S)[x]} _S_SequenceNumber__DEVICE_EXTENSIONInv(S)[x] <==> S[SequenceNumber__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_SequenceNumber__DEVICE_EXTENSION(S)} S[x] ==> _S_SequenceNumber__DEVICE_EXTENSION(S)[SequenceNumber__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_SequenceNumber__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_SequenceNumber__DEVICE_EXTENSIONInv(S)[SequenceNumber__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {SequenceNumber__DEVICE_EXTENSION(x)} SequenceNumber__DEVICE_EXTENSION(x) == x + 164);
+axiom (forall x:int :: {SequenceNumber__DEVICE_EXTENSIONInv(x)} SequenceNumber__DEVICE_EXTENSIONInv(x) == x - 164);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 164, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 164, 1) == SequenceNumber__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 164)} MINUS_LEFT_PTR(x, 1, 164) == SequenceNumber__DEVICE_EXTENSIONInv(x));
+function SetWmiDataBlock__WMILIB_CONTEXT(int) returns (int);
+function SetWmiDataBlock__WMILIB_CONTEXTInv(int) returns (int);
+function _S_SetWmiDataBlock__WMILIB_CONTEXT([int]bool) returns ([int]bool);
+function _S_SetWmiDataBlock__WMILIB_CONTEXTInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {SetWmiDataBlock__WMILIB_CONTEXTInv(SetWmiDataBlock__WMILIB_CONTEXT(x))} SetWmiDataBlock__WMILIB_CONTEXTInv(SetWmiDataBlock__WMILIB_CONTEXT(x)) == x);
+axiom (forall x:int :: {SetWmiDataBlock__WMILIB_CONTEXTInv(x)} SetWmiDataBlock__WMILIB_CONTEXT(SetWmiDataBlock__WMILIB_CONTEXTInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_SetWmiDataBlock__WMILIB_CONTEXT(S)[x]} _S_SetWmiDataBlock__WMILIB_CONTEXT(S)[x] <==> S[SetWmiDataBlock__WMILIB_CONTEXTInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_SetWmiDataBlock__WMILIB_CONTEXTInv(S)[x]} _S_SetWmiDataBlock__WMILIB_CONTEXTInv(S)[x] <==> S[SetWmiDataBlock__WMILIB_CONTEXT(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_SetWmiDataBlock__WMILIB_CONTEXT(S)} S[x] ==> _S_SetWmiDataBlock__WMILIB_CONTEXT(S)[SetWmiDataBlock__WMILIB_CONTEXT(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_SetWmiDataBlock__WMILIB_CONTEXTInv(S)} S[x] ==> _S_SetWmiDataBlock__WMILIB_CONTEXTInv(S)[SetWmiDataBlock__WMILIB_CONTEXTInv(x)]);
+
+axiom (forall x:int :: {SetWmiDataBlock__WMILIB_CONTEXT(x)} SetWmiDataBlock__WMILIB_CONTEXT(x) == x + 16);
+axiom (forall x:int :: {SetWmiDataBlock__WMILIB_CONTEXTInv(x)} SetWmiDataBlock__WMILIB_CONTEXTInv(x) == x - 16);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 16, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 16, 1) == SetWmiDataBlock__WMILIB_CONTEXTInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 16)} MINUS_LEFT_PTR(x, 1, 16) == SetWmiDataBlock__WMILIB_CONTEXTInv(x));
+function SetWmiDataItem__WMILIB_CONTEXT(int) returns (int);
+function SetWmiDataItem__WMILIB_CONTEXTInv(int) returns (int);
+function _S_SetWmiDataItem__WMILIB_CONTEXT([int]bool) returns ([int]bool);
+function _S_SetWmiDataItem__WMILIB_CONTEXTInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {SetWmiDataItem__WMILIB_CONTEXTInv(SetWmiDataItem__WMILIB_CONTEXT(x))} SetWmiDataItem__WMILIB_CONTEXTInv(SetWmiDataItem__WMILIB_CONTEXT(x)) == x);
+axiom (forall x:int :: {SetWmiDataItem__WMILIB_CONTEXTInv(x)} SetWmiDataItem__WMILIB_CONTEXT(SetWmiDataItem__WMILIB_CONTEXTInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_SetWmiDataItem__WMILIB_CONTEXT(S)[x]} _S_SetWmiDataItem__WMILIB_CONTEXT(S)[x] <==> S[SetWmiDataItem__WMILIB_CONTEXTInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_SetWmiDataItem__WMILIB_CONTEXTInv(S)[x]} _S_SetWmiDataItem__WMILIB_CONTEXTInv(S)[x] <==> S[SetWmiDataItem__WMILIB_CONTEXT(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_SetWmiDataItem__WMILIB_CONTEXT(S)} S[x] ==> _S_SetWmiDataItem__WMILIB_CONTEXT(S)[SetWmiDataItem__WMILIB_CONTEXT(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_SetWmiDataItem__WMILIB_CONTEXTInv(S)} S[x] ==> _S_SetWmiDataItem__WMILIB_CONTEXTInv(S)[SetWmiDataItem__WMILIB_CONTEXTInv(x)]);
+
+axiom (forall x:int :: {SetWmiDataItem__WMILIB_CONTEXT(x)} SetWmiDataItem__WMILIB_CONTEXT(x) == x + 20);
+axiom (forall x:int :: {SetWmiDataItem__WMILIB_CONTEXTInv(x)} SetWmiDataItem__WMILIB_CONTEXTInv(x) == x - 20);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 20, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 20, 1) == SetWmiDataItem__WMILIB_CONTEXTInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 20)} MINUS_LEFT_PTR(x, 1, 20) == SetWmiDataItem__WMILIB_CONTEXTInv(x));
+function SignalState__DISPATCHER_HEADER(int) returns (int);
+function SignalState__DISPATCHER_HEADERInv(int) returns (int);
+function _S_SignalState__DISPATCHER_HEADER([int]bool) returns ([int]bool);
+function _S_SignalState__DISPATCHER_HEADERInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {SignalState__DISPATCHER_HEADERInv(SignalState__DISPATCHER_HEADER(x))} SignalState__DISPATCHER_HEADERInv(SignalState__DISPATCHER_HEADER(x)) == x);
+axiom (forall x:int :: {SignalState__DISPATCHER_HEADERInv(x)} SignalState__DISPATCHER_HEADER(SignalState__DISPATCHER_HEADERInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_SignalState__DISPATCHER_HEADER(S)[x]} _S_SignalState__DISPATCHER_HEADER(S)[x] <==> S[SignalState__DISPATCHER_HEADERInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_SignalState__DISPATCHER_HEADERInv(S)[x]} _S_SignalState__DISPATCHER_HEADERInv(S)[x] <==> S[SignalState__DISPATCHER_HEADER(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_SignalState__DISPATCHER_HEADER(S)} S[x] ==> _S_SignalState__DISPATCHER_HEADER(S)[SignalState__DISPATCHER_HEADER(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_SignalState__DISPATCHER_HEADERInv(S)} S[x] ==> _S_SignalState__DISPATCHER_HEADERInv(S)[SignalState__DISPATCHER_HEADERInv(x)]);
+
+axiom (forall x:int :: {SignalState__DISPATCHER_HEADER(x)} SignalState__DISPATCHER_HEADER(x) == x + 4);
+axiom (forall x:int :: {SignalState__DISPATCHER_HEADERInv(x)} SignalState__DISPATCHER_HEADERInv(x) == x - 4);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 4, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 4, 1) == SignalState__DISPATCHER_HEADERInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 4)} MINUS_LEFT_PTR(x, 1, 4) == SignalState__DISPATCHER_HEADERInv(x));
+function Signalling___unnamed_1_2bb39c56(int) returns (int);
+function Signalling___unnamed_1_2bb39c56Inv(int) returns (int);
+function _S_Signalling___unnamed_1_2bb39c56([int]bool) returns ([int]bool);
+function _S_Signalling___unnamed_1_2bb39c56Inv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {Signalling___unnamed_1_2bb39c56Inv(Signalling___unnamed_1_2bb39c56(x))} Signalling___unnamed_1_2bb39c56Inv(Signalling___unnamed_1_2bb39c56(x)) == x);
+axiom (forall x:int :: {Signalling___unnamed_1_2bb39c56Inv(x)} Signalling___unnamed_1_2bb39c56(Signalling___unnamed_1_2bb39c56Inv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_Signalling___unnamed_1_2bb39c56(S)[x]} _S_Signalling___unnamed_1_2bb39c56(S)[x] <==> S[Signalling___unnamed_1_2bb39c56Inv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_Signalling___unnamed_1_2bb39c56Inv(S)[x]} _S_Signalling___unnamed_1_2bb39c56Inv(S)[x] <==> S[Signalling___unnamed_1_2bb39c56(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Signalling___unnamed_1_2bb39c56(S)} S[x] ==> _S_Signalling___unnamed_1_2bb39c56(S)[Signalling___unnamed_1_2bb39c56(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Signalling___unnamed_1_2bb39c56Inv(S)} S[x] ==> _S_Signalling___unnamed_1_2bb39c56Inv(S)[Signalling___unnamed_1_2bb39c56Inv(x)]);
+
+axiom (forall x:int :: {Signalling___unnamed_1_2bb39c56(x)} Signalling___unnamed_1_2bb39c56(x) == x + 0);
+axiom (forall x:int :: {Signalling___unnamed_1_2bb39c56Inv(x)} Signalling___unnamed_1_2bb39c56Inv(x) == x - 0);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1) == Signalling___unnamed_1_2bb39c56Inv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 0)} MINUS_LEFT_PTR(x, 1, 0) == Signalling___unnamed_1_2bb39c56Inv(x));
+function Signature__IO_REMOVE_LOCK_DBG_BLOCK(int) returns (int);
+function Signature__IO_REMOVE_LOCK_DBG_BLOCKInv(int) returns (int);
+function _S_Signature__IO_REMOVE_LOCK_DBG_BLOCK([int]bool) returns ([int]bool);
+function _S_Signature__IO_REMOVE_LOCK_DBG_BLOCKInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {Signature__IO_REMOVE_LOCK_DBG_BLOCKInv(Signature__IO_REMOVE_LOCK_DBG_BLOCK(x))} Signature__IO_REMOVE_LOCK_DBG_BLOCKInv(Signature__IO_REMOVE_LOCK_DBG_BLOCK(x)) == x);
+axiom (forall x:int :: {Signature__IO_REMOVE_LOCK_DBG_BLOCKInv(x)} Signature__IO_REMOVE_LOCK_DBG_BLOCK(Signature__IO_REMOVE_LOCK_DBG_BLOCKInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_Signature__IO_REMOVE_LOCK_DBG_BLOCK(S)[x]} _S_Signature__IO_REMOVE_LOCK_DBG_BLOCK(S)[x] <==> S[Signature__IO_REMOVE_LOCK_DBG_BLOCKInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_Signature__IO_REMOVE_LOCK_DBG_BLOCKInv(S)[x]} _S_Signature__IO_REMOVE_LOCK_DBG_BLOCKInv(S)[x] <==> S[Signature__IO_REMOVE_LOCK_DBG_BLOCK(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Signature__IO_REMOVE_LOCK_DBG_BLOCK(S)} S[x] ==> _S_Signature__IO_REMOVE_LOCK_DBG_BLOCK(S)[Signature__IO_REMOVE_LOCK_DBG_BLOCK(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Signature__IO_REMOVE_LOCK_DBG_BLOCKInv(S)} S[x] ==> _S_Signature__IO_REMOVE_LOCK_DBG_BLOCKInv(S)[Signature__IO_REMOVE_LOCK_DBG_BLOCKInv(x)]);
+
+axiom (forall x:int :: {Signature__IO_REMOVE_LOCK_DBG_BLOCK(x)} Signature__IO_REMOVE_LOCK_DBG_BLOCK(x) == x + 0);
+axiom (forall x:int :: {Signature__IO_REMOVE_LOCK_DBG_BLOCKInv(x)} Signature__IO_REMOVE_LOCK_DBG_BLOCKInv(x) == x - 0);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1) == Signature__IO_REMOVE_LOCK_DBG_BLOCKInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 0)} MINUS_LEFT_PTR(x, 1, 0) == Signature__IO_REMOVE_LOCK_DBG_BLOCKInv(x));
+function Size___unnamed_1_e30779f5(int) returns (int);
+function Size___unnamed_1_e30779f5Inv(int) returns (int);
+function _S_Size___unnamed_1_e30779f5([int]bool) returns ([int]bool);
+function _S_Size___unnamed_1_e30779f5Inv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {Size___unnamed_1_e30779f5Inv(Size___unnamed_1_e30779f5(x))} Size___unnamed_1_e30779f5Inv(Size___unnamed_1_e30779f5(x)) == x);
+axiom (forall x:int :: {Size___unnamed_1_e30779f5Inv(x)} Size___unnamed_1_e30779f5(Size___unnamed_1_e30779f5Inv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_Size___unnamed_1_e30779f5(S)[x]} _S_Size___unnamed_1_e30779f5(S)[x] <==> S[Size___unnamed_1_e30779f5Inv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_Size___unnamed_1_e30779f5Inv(S)[x]} _S_Size___unnamed_1_e30779f5Inv(S)[x] <==> S[Size___unnamed_1_e30779f5(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Size___unnamed_1_e30779f5(S)} S[x] ==> _S_Size___unnamed_1_e30779f5(S)[Size___unnamed_1_e30779f5(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Size___unnamed_1_e30779f5Inv(S)} S[x] ==> _S_Size___unnamed_1_e30779f5Inv(S)[Size___unnamed_1_e30779f5Inv(x)]);
+
+axiom (forall x:int :: {Size___unnamed_1_e30779f5(x)} Size___unnamed_1_e30779f5(x) == x + 0);
+axiom (forall x:int :: {Size___unnamed_1_e30779f5Inv(x)} Size___unnamed_1_e30779f5Inv(x) == x - 0);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1) == Size___unnamed_1_e30779f5Inv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 0)} MINUS_LEFT_PTR(x, 1, 0) == Size___unnamed_1_e30779f5Inv(x));
+function SpinLock__DEVICE_EXTENSION(int) returns (int);
+function SpinLock__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_SpinLock__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_SpinLock__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {SpinLock__DEVICE_EXTENSIONInv(SpinLock__DEVICE_EXTENSION(x))} SpinLock__DEVICE_EXTENSIONInv(SpinLock__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {SpinLock__DEVICE_EXTENSIONInv(x)} SpinLock__DEVICE_EXTENSION(SpinLock__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_SpinLock__DEVICE_EXTENSION(S)[x]} _S_SpinLock__DEVICE_EXTENSION(S)[x] <==> S[SpinLock__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_SpinLock__DEVICE_EXTENSIONInv(S)[x]} _S_SpinLock__DEVICE_EXTENSIONInv(S)[x] <==> S[SpinLock__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_SpinLock__DEVICE_EXTENSION(S)} S[x] ==> _S_SpinLock__DEVICE_EXTENSION(S)[SpinLock__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_SpinLock__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_SpinLock__DEVICE_EXTENSIONInv(S)[SpinLock__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {SpinLock__DEVICE_EXTENSION(x)} SpinLock__DEVICE_EXTENSION(x) == x + 152);
+axiom (forall x:int :: {SpinLock__DEVICE_EXTENSIONInv(x)} SpinLock__DEVICE_EXTENSIONInv(x) == x - 152);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 152, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 152, 1) == SpinLock__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 152)} MINUS_LEFT_PTR(x, 1, 152) == SpinLock__DEVICE_EXTENSIONInv(x));
+function Spin__IO_REMOVE_LOCK_DBG_BLOCK(int) returns (int);
+function Spin__IO_REMOVE_LOCK_DBG_BLOCKInv(int) returns (int);
+function _S_Spin__IO_REMOVE_LOCK_DBG_BLOCK([int]bool) returns ([int]bool);
+function _S_Spin__IO_REMOVE_LOCK_DBG_BLOCKInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {Spin__IO_REMOVE_LOCK_DBG_BLOCKInv(Spin__IO_REMOVE_LOCK_DBG_BLOCK(x))} Spin__IO_REMOVE_LOCK_DBG_BLOCKInv(Spin__IO_REMOVE_LOCK_DBG_BLOCK(x)) == x);
+axiom (forall x:int :: {Spin__IO_REMOVE_LOCK_DBG_BLOCKInv(x)} Spin__IO_REMOVE_LOCK_DBG_BLOCK(Spin__IO_REMOVE_LOCK_DBG_BLOCKInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_Spin__IO_REMOVE_LOCK_DBG_BLOCK(S)[x]} _S_Spin__IO_REMOVE_LOCK_DBG_BLOCK(S)[x] <==> S[Spin__IO_REMOVE_LOCK_DBG_BLOCKInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_Spin__IO_REMOVE_LOCK_DBG_BLOCKInv(S)[x]} _S_Spin__IO_REMOVE_LOCK_DBG_BLOCKInv(S)[x] <==> S[Spin__IO_REMOVE_LOCK_DBG_BLOCK(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Spin__IO_REMOVE_LOCK_DBG_BLOCK(S)} S[x] ==> _S_Spin__IO_REMOVE_LOCK_DBG_BLOCK(S)[Spin__IO_REMOVE_LOCK_DBG_BLOCK(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Spin__IO_REMOVE_LOCK_DBG_BLOCKInv(S)} S[x] ==> _S_Spin__IO_REMOVE_LOCK_DBG_BLOCKInv(S)[Spin__IO_REMOVE_LOCK_DBG_BLOCKInv(x)]);
+
+axiom (forall x:int :: {Spin__IO_REMOVE_LOCK_DBG_BLOCK(x)} Spin__IO_REMOVE_LOCK_DBG_BLOCK(x) == x + 28);
+axiom (forall x:int :: {Spin__IO_REMOVE_LOCK_DBG_BLOCKInv(x)} Spin__IO_REMOVE_LOCK_DBG_BLOCKInv(x) == x - 28);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 28, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 28, 1) == Spin__IO_REMOVE_LOCK_DBG_BLOCKInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 28)} MINUS_LEFT_PTR(x, 1, 28) == Spin__IO_REMOVE_LOCK_DBG_BLOCKInv(x));
+function Started__DEVICE_EXTENSION(int) returns (int);
+function Started__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_Started__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_Started__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {Started__DEVICE_EXTENSIONInv(Started__DEVICE_EXTENSION(x))} Started__DEVICE_EXTENSIONInv(Started__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {Started__DEVICE_EXTENSIONInv(x)} Started__DEVICE_EXTENSION(Started__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_Started__DEVICE_EXTENSION(S)[x]} _S_Started__DEVICE_EXTENSION(S)[x] <==> S[Started__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_Started__DEVICE_EXTENSIONInv(S)[x]} _S_Started__DEVICE_EXTENSIONInv(S)[x] <==> S[Started__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Started__DEVICE_EXTENSION(S)} S[x] ==> _S_Started__DEVICE_EXTENSION(S)[Started__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Started__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_Started__DEVICE_EXTENSIONInv(S)[Started__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {Started__DEVICE_EXTENSION(x)} Started__DEVICE_EXTENSION(x) == x + 105);
+axiom (forall x:int :: {Started__DEVICE_EXTENSIONInv(x)} Started__DEVICE_EXTENSIONInv(x) == x - 105);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 105, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 105, 1) == Started__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 105)} MINUS_LEFT_PTR(x, 1, 105) == Started__DEVICE_EXTENSIONInv(x));
+function SurpriseRemoved__DEVICE_EXTENSION(int) returns (int);
+function SurpriseRemoved__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_SurpriseRemoved__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_SurpriseRemoved__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {SurpriseRemoved__DEVICE_EXTENSIONInv(SurpriseRemoved__DEVICE_EXTENSION(x))} SurpriseRemoved__DEVICE_EXTENSIONInv(SurpriseRemoved__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {SurpriseRemoved__DEVICE_EXTENSIONInv(x)} SurpriseRemoved__DEVICE_EXTENSION(SurpriseRemoved__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_SurpriseRemoved__DEVICE_EXTENSION(S)[x]} _S_SurpriseRemoved__DEVICE_EXTENSION(S)[x] <==> S[SurpriseRemoved__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_SurpriseRemoved__DEVICE_EXTENSIONInv(S)[x]} _S_SurpriseRemoved__DEVICE_EXTENSIONInv(S)[x] <==> S[SurpriseRemoved__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_SurpriseRemoved__DEVICE_EXTENSION(S)} S[x] ==> _S_SurpriseRemoved__DEVICE_EXTENSION(S)[SurpriseRemoved__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_SurpriseRemoved__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_SurpriseRemoved__DEVICE_EXTENSIONInv(S)[SurpriseRemoved__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {SurpriseRemoved__DEVICE_EXTENSION(x)} SurpriseRemoved__DEVICE_EXTENSION(x) == x + 266);
+axiom (forall x:int :: {SurpriseRemoved__DEVICE_EXTENSIONInv(x)} SurpriseRemoved__DEVICE_EXTENSIONInv(x) == x - 266);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 266, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 266, 1) == SurpriseRemoved__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 266)} MINUS_LEFT_PTR(x, 1, 266) == SurpriseRemoved__DEVICE_EXTENSIONInv(x));
+function SymbolicLinkName__DEVICE_EXTENSION(int) returns (int);
+function SymbolicLinkName__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_SymbolicLinkName__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_SymbolicLinkName__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {SymbolicLinkName__DEVICE_EXTENSIONInv(SymbolicLinkName__DEVICE_EXTENSION(x))} SymbolicLinkName__DEVICE_EXTENSIONInv(SymbolicLinkName__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {SymbolicLinkName__DEVICE_EXTENSIONInv(x)} SymbolicLinkName__DEVICE_EXTENSION(SymbolicLinkName__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_SymbolicLinkName__DEVICE_EXTENSION(S)[x]} _S_SymbolicLinkName__DEVICE_EXTENSION(S)[x] <==> S[SymbolicLinkName__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_SymbolicLinkName__DEVICE_EXTENSIONInv(S)[x]} _S_SymbolicLinkName__DEVICE_EXTENSIONInv(S)[x] <==> S[SymbolicLinkName__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_SymbolicLinkName__DEVICE_EXTENSION(S)} S[x] ==> _S_SymbolicLinkName__DEVICE_EXTENSION(S)[SymbolicLinkName__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_SymbolicLinkName__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_SymbolicLinkName__DEVICE_EXTENSIONInv(S)[SymbolicLinkName__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {SymbolicLinkName__DEVICE_EXTENSION(x)} SymbolicLinkName__DEVICE_EXTENSION(x) == x + 120);
+axiom (forall x:int :: {SymbolicLinkName__DEVICE_EXTENSIONInv(x)} SymbolicLinkName__DEVICE_EXTENSIONInv(x) == x - 120);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 120, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 120, 1) == SymbolicLinkName__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 120)} MINUS_LEFT_PTR(x, 1, 120) == SymbolicLinkName__DEVICE_EXTENSIONInv(x));
+function SystemState__DEVICE_EXTENSION(int) returns (int);
+function SystemState__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_SystemState__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_SystemState__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {SystemState__DEVICE_EXTENSIONInv(SystemState__DEVICE_EXTENSION(x))} SystemState__DEVICE_EXTENSIONInv(SystemState__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {SystemState__DEVICE_EXTENSIONInv(x)} SystemState__DEVICE_EXTENSION(SystemState__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_SystemState__DEVICE_EXTENSION(S)[x]} _S_SystemState__DEVICE_EXTENSION(S)[x] <==> S[SystemState__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_SystemState__DEVICE_EXTENSIONInv(S)[x]} _S_SystemState__DEVICE_EXTENSIONInv(S)[x] <==> S[SystemState__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_SystemState__DEVICE_EXTENSION(S)} S[x] ==> _S_SystemState__DEVICE_EXTENSION(S)[SystemState__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_SystemState__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_SystemState__DEVICE_EXTENSIONInv(S)[SystemState__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {SystemState__DEVICE_EXTENSION(x)} SystemState__DEVICE_EXTENSION(x) == x + 172);
+axiom (forall x:int :: {SystemState__DEVICE_EXTENSIONInv(x)} SystemState__DEVICE_EXTENSIONInv(x) == x - 172);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 172, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 172, 1) == SystemState__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 172)} MINUS_LEFT_PTR(x, 1, 172) == SystemState__DEVICE_EXTENSIONInv(x));
+function SystemToDeviceState__DEVICE_EXTENSION(int) returns (int);
+function SystemToDeviceState__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_SystemToDeviceState__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_SystemToDeviceState__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {SystemToDeviceState__DEVICE_EXTENSIONInv(SystemToDeviceState__DEVICE_EXTENSION(x))} SystemToDeviceState__DEVICE_EXTENSIONInv(SystemToDeviceState__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {SystemToDeviceState__DEVICE_EXTENSIONInv(x)} SystemToDeviceState__DEVICE_EXTENSION(SystemToDeviceState__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_SystemToDeviceState__DEVICE_EXTENSION(S)[x]} _S_SystemToDeviceState__DEVICE_EXTENSION(S)[x] <==> S[SystemToDeviceState__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_SystemToDeviceState__DEVICE_EXTENSIONInv(S)[x]} _S_SystemToDeviceState__DEVICE_EXTENSIONInv(S)[x] <==> S[SystemToDeviceState__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_SystemToDeviceState__DEVICE_EXTENSION(S)} S[x] ==> _S_SystemToDeviceState__DEVICE_EXTENSION(S)[SystemToDeviceState__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_SystemToDeviceState__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_SystemToDeviceState__DEVICE_EXTENSIONInv(S)[SystemToDeviceState__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {SystemToDeviceState__DEVICE_EXTENSION(x)} SystemToDeviceState__DEVICE_EXTENSION(x) == x + 212);
+axiom (forall x:int :: {SystemToDeviceState__DEVICE_EXTENSIONInv(x)} SystemToDeviceState__DEVICE_EXTENSIONInv(x) == x - 212);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 212, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 212, 1) == SystemToDeviceState__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 212)} MINUS_LEFT_PTR(x, 1, 212) == SystemToDeviceState__DEVICE_EXTENSIONInv(x));
+function TargetNotifyHandle__DEVICE_EXTENSION(int) returns (int);
+function TargetNotifyHandle__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_TargetNotifyHandle__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_TargetNotifyHandle__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {TargetNotifyHandle__DEVICE_EXTENSIONInv(TargetNotifyHandle__DEVICE_EXTENSION(x))} TargetNotifyHandle__DEVICE_EXTENSIONInv(TargetNotifyHandle__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {TargetNotifyHandle__DEVICE_EXTENSIONInv(x)} TargetNotifyHandle__DEVICE_EXTENSION(TargetNotifyHandle__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_TargetNotifyHandle__DEVICE_EXTENSION(S)[x]} _S_TargetNotifyHandle__DEVICE_EXTENSION(S)[x] <==> S[TargetNotifyHandle__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_TargetNotifyHandle__DEVICE_EXTENSIONInv(S)[x]} _S_TargetNotifyHandle__DEVICE_EXTENSIONInv(S)[x] <==> S[TargetNotifyHandle__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_TargetNotifyHandle__DEVICE_EXTENSION(S)} S[x] ==> _S_TargetNotifyHandle__DEVICE_EXTENSION(S)[TargetNotifyHandle__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_TargetNotifyHandle__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_TargetNotifyHandle__DEVICE_EXTENSIONInv(S)[TargetNotifyHandle__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {TargetNotifyHandle__DEVICE_EXTENSION(x)} TargetNotifyHandle__DEVICE_EXTENSION(x) == x + 248);
+axiom (forall x:int :: {TargetNotifyHandle__DEVICE_EXTENSIONInv(x)} TargetNotifyHandle__DEVICE_EXTENSIONInv(x) == x - 248);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 248, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 248, 1) == TargetNotifyHandle__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 248)} MINUS_LEFT_PTR(x, 1, 248) == TargetNotifyHandle__DEVICE_EXTENSIONInv(x));
+function TopPort__DEVICE_EXTENSION(int) returns (int);
+function TopPort__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_TopPort__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_TopPort__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {TopPort__DEVICE_EXTENSIONInv(TopPort__DEVICE_EXTENSION(x))} TopPort__DEVICE_EXTENSIONInv(TopPort__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {TopPort__DEVICE_EXTENSIONInv(x)} TopPort__DEVICE_EXTENSION(TopPort__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_TopPort__DEVICE_EXTENSION(S)[x]} _S_TopPort__DEVICE_EXTENSION(S)[x] <==> S[TopPort__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_TopPort__DEVICE_EXTENSIONInv(S)[x]} _S_TopPort__DEVICE_EXTENSIONInv(S)[x] <==> S[TopPort__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_TopPort__DEVICE_EXTENSION(S)} S[x] ==> _S_TopPort__DEVICE_EXTENSION(S)[TopPort__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_TopPort__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_TopPort__DEVICE_EXTENSIONInv(S)[TopPort__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {TopPort__DEVICE_EXTENSION(x)} TopPort__DEVICE_EXTENSION(x) == x + 8);
+axiom (forall x:int :: {TopPort__DEVICE_EXTENSIONInv(x)} TopPort__DEVICE_EXTENSIONInv(x) == x - 8);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 8, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 8, 1) == TopPort__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 8)} MINUS_LEFT_PTR(x, 1, 8) == TopPort__DEVICE_EXTENSIONInv(x));
+function TrueClassDevice__DEVICE_EXTENSION(int) returns (int);
+function TrueClassDevice__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_TrueClassDevice__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_TrueClassDevice__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {TrueClassDevice__DEVICE_EXTENSIONInv(TrueClassDevice__DEVICE_EXTENSION(x))} TrueClassDevice__DEVICE_EXTENSIONInv(TrueClassDevice__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {TrueClassDevice__DEVICE_EXTENSIONInv(x)} TrueClassDevice__DEVICE_EXTENSION(TrueClassDevice__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_TrueClassDevice__DEVICE_EXTENSION(S)[x]} _S_TrueClassDevice__DEVICE_EXTENSION(S)[x] <==> S[TrueClassDevice__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_TrueClassDevice__DEVICE_EXTENSIONInv(S)[x]} _S_TrueClassDevice__DEVICE_EXTENSIONInv(S)[x] <==> S[TrueClassDevice__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_TrueClassDevice__DEVICE_EXTENSION(S)} S[x] ==> _S_TrueClassDevice__DEVICE_EXTENSION(S)[TrueClassDevice__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_TrueClassDevice__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_TrueClassDevice__DEVICE_EXTENSIONInv(S)[TrueClassDevice__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {TrueClassDevice__DEVICE_EXTENSION(x)} TrueClassDevice__DEVICE_EXTENSION(x) == x + 4);
+axiom (forall x:int :: {TrueClassDevice__DEVICE_EXTENSIONInv(x)} TrueClassDevice__DEVICE_EXTENSIONInv(x) == x - 4);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 4, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 4, 1) == TrueClassDevice__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 4)} MINUS_LEFT_PTR(x, 1, 4) == TrueClassDevice__DEVICE_EXTENSIONInv(x));
+function TrustedSubsystemCount__DEVICE_EXTENSION(int) returns (int);
+function TrustedSubsystemCount__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_TrustedSubsystemCount__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_TrustedSubsystemCount__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {TrustedSubsystemCount__DEVICE_EXTENSIONInv(TrustedSubsystemCount__DEVICE_EXTENSION(x))} TrustedSubsystemCount__DEVICE_EXTENSIONInv(TrustedSubsystemCount__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {TrustedSubsystemCount__DEVICE_EXTENSIONInv(x)} TrustedSubsystemCount__DEVICE_EXTENSION(TrustedSubsystemCount__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_TrustedSubsystemCount__DEVICE_EXTENSION(S)[x]} _S_TrustedSubsystemCount__DEVICE_EXTENSION(S)[x] <==> S[TrustedSubsystemCount__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_TrustedSubsystemCount__DEVICE_EXTENSIONInv(S)[x]} _S_TrustedSubsystemCount__DEVICE_EXTENSIONInv(S)[x] <==> S[TrustedSubsystemCount__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_TrustedSubsystemCount__DEVICE_EXTENSION(S)} S[x] ==> _S_TrustedSubsystemCount__DEVICE_EXTENSION(S)[TrustedSubsystemCount__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_TrustedSubsystemCount__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_TrustedSubsystemCount__DEVICE_EXTENSIONInv(S)[TrustedSubsystemCount__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {TrustedSubsystemCount__DEVICE_EXTENSION(x)} TrustedSubsystemCount__DEVICE_EXTENSION(x) == x + 112);
+axiom (forall x:int :: {TrustedSubsystemCount__DEVICE_EXTENSIONInv(x)} TrustedSubsystemCount__DEVICE_EXTENSIONInv(x) == x - 112);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 112, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 112, 1) == TrustedSubsystemCount__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 112)} MINUS_LEFT_PTR(x, 1, 112) == TrustedSubsystemCount__DEVICE_EXTENSIONInv(x));
+function Type___unnamed_4_846adf3f(int) returns (int);
+function Type___unnamed_4_846adf3fInv(int) returns (int);
+function _S_Type___unnamed_4_846adf3f([int]bool) returns ([int]bool);
+function _S_Type___unnamed_4_846adf3fInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {Type___unnamed_4_846adf3fInv(Type___unnamed_4_846adf3f(x))} Type___unnamed_4_846adf3fInv(Type___unnamed_4_846adf3f(x)) == x);
+axiom (forall x:int :: {Type___unnamed_4_846adf3fInv(x)} Type___unnamed_4_846adf3f(Type___unnamed_4_846adf3fInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_Type___unnamed_4_846adf3f(S)[x]} _S_Type___unnamed_4_846adf3f(S)[x] <==> S[Type___unnamed_4_846adf3fInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_Type___unnamed_4_846adf3fInv(S)[x]} _S_Type___unnamed_4_846adf3fInv(S)[x] <==> S[Type___unnamed_4_846adf3f(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Type___unnamed_4_846adf3f(S)} S[x] ==> _S_Type___unnamed_4_846adf3f(S)[Type___unnamed_4_846adf3f(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Type___unnamed_4_846adf3fInv(S)} S[x] ==> _S_Type___unnamed_4_846adf3fInv(S)[Type___unnamed_4_846adf3fInv(x)]);
+
+axiom (forall x:int :: {Type___unnamed_4_846adf3f(x)} Type___unnamed_4_846adf3f(x) == x + 0);
+axiom (forall x:int :: {Type___unnamed_4_846adf3fInv(x)} Type___unnamed_4_846adf3fInv(x) == x - 0);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1) == Type___unnamed_4_846adf3fInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 0)} MINUS_LEFT_PTR(x, 1, 0) == Type___unnamed_4_846adf3fInv(x));
+function UnitId__DEVICE_EXTENSION(int) returns (int);
+function UnitId__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_UnitId__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_UnitId__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {UnitId__DEVICE_EXTENSIONInv(UnitId__DEVICE_EXTENSION(x))} UnitId__DEVICE_EXTENSIONInv(UnitId__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {UnitId__DEVICE_EXTENSIONInv(x)} UnitId__DEVICE_EXTENSION(UnitId__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_UnitId__DEVICE_EXTENSION(S)[x]} _S_UnitId__DEVICE_EXTENSION(S)[x] <==> S[UnitId__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_UnitId__DEVICE_EXTENSIONInv(S)[x]} _S_UnitId__DEVICE_EXTENSIONInv(S)[x] <==> S[UnitId__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_UnitId__DEVICE_EXTENSION(S)} S[x] ==> _S_UnitId__DEVICE_EXTENSION(S)[UnitId__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_UnitId__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_UnitId__DEVICE_EXTENSIONInv(S)[UnitId__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {UnitId__DEVICE_EXTENSION(x)} UnitId__DEVICE_EXTENSION(x) == x + 176);
+axiom (forall x:int :: {UnitId__DEVICE_EXTENSIONInv(x)} UnitId__DEVICE_EXTENSIONInv(x) == x - 176);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 176, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 176, 1) == UnitId__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 176)} MINUS_LEFT_PTR(x, 1, 176) == UnitId__DEVICE_EXTENSIONInv(x));
+function WaitListHead__DISPATCHER_HEADER(int) returns (int);
+function WaitListHead__DISPATCHER_HEADERInv(int) returns (int);
+function _S_WaitListHead__DISPATCHER_HEADER([int]bool) returns ([int]bool);
+function _S_WaitListHead__DISPATCHER_HEADERInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {WaitListHead__DISPATCHER_HEADERInv(WaitListHead__DISPATCHER_HEADER(x))} WaitListHead__DISPATCHER_HEADERInv(WaitListHead__DISPATCHER_HEADER(x)) == x);
+axiom (forall x:int :: {WaitListHead__DISPATCHER_HEADERInv(x)} WaitListHead__DISPATCHER_HEADER(WaitListHead__DISPATCHER_HEADERInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_WaitListHead__DISPATCHER_HEADER(S)[x]} _S_WaitListHead__DISPATCHER_HEADER(S)[x] <==> S[WaitListHead__DISPATCHER_HEADERInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_WaitListHead__DISPATCHER_HEADERInv(S)[x]} _S_WaitListHead__DISPATCHER_HEADERInv(S)[x] <==> S[WaitListHead__DISPATCHER_HEADER(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_WaitListHead__DISPATCHER_HEADER(S)} S[x] ==> _S_WaitListHead__DISPATCHER_HEADER(S)[WaitListHead__DISPATCHER_HEADER(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_WaitListHead__DISPATCHER_HEADERInv(S)} S[x] ==> _S_WaitListHead__DISPATCHER_HEADERInv(S)[WaitListHead__DISPATCHER_HEADERInv(x)]);
+
+axiom (forall x:int :: {WaitListHead__DISPATCHER_HEADER(x)} WaitListHead__DISPATCHER_HEADER(x) == x + 8);
+axiom (forall x:int :: {WaitListHead__DISPATCHER_HEADERInv(x)} WaitListHead__DISPATCHER_HEADERInv(x) == x - 8);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 8, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 8, 1) == WaitListHead__DISPATCHER_HEADERInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 8)} MINUS_LEFT_PTR(x, 1, 8) == WaitListHead__DISPATCHER_HEADERInv(x));
+function WaitWakeEnabled__DEVICE_EXTENSION(int) returns (int);
+function WaitWakeEnabled__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_WaitWakeEnabled__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_WaitWakeEnabled__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {WaitWakeEnabled__DEVICE_EXTENSIONInv(WaitWakeEnabled__DEVICE_EXTENSION(x))} WaitWakeEnabled__DEVICE_EXTENSIONInv(WaitWakeEnabled__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {WaitWakeEnabled__DEVICE_EXTENSIONInv(x)} WaitWakeEnabled__DEVICE_EXTENSION(WaitWakeEnabled__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_WaitWakeEnabled__DEVICE_EXTENSION(S)[x]} _S_WaitWakeEnabled__DEVICE_EXTENSION(S)[x] <==> S[WaitWakeEnabled__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_WaitWakeEnabled__DEVICE_EXTENSIONInv(S)[x]} _S_WaitWakeEnabled__DEVICE_EXTENSIONInv(S)[x] <==> S[WaitWakeEnabled__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_WaitWakeEnabled__DEVICE_EXTENSION(S)} S[x] ==> _S_WaitWakeEnabled__DEVICE_EXTENSION(S)[WaitWakeEnabled__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_WaitWakeEnabled__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_WaitWakeEnabled__DEVICE_EXTENSIONInv(S)[WaitWakeEnabled__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {WaitWakeEnabled__DEVICE_EXTENSION(x)} WaitWakeEnabled__DEVICE_EXTENSION(x) == x + 265);
+axiom (forall x:int :: {WaitWakeEnabled__DEVICE_EXTENSIONInv(x)} WaitWakeEnabled__DEVICE_EXTENSIONInv(x) == x - 265);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 265, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 265, 1) == WaitWakeEnabled__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 265)} MINUS_LEFT_PTR(x, 1, 265) == WaitWakeEnabled__DEVICE_EXTENSIONInv(x));
+function WaitWakeIrp__DEVICE_EXTENSION(int) returns (int);
+function WaitWakeIrp__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_WaitWakeIrp__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_WaitWakeIrp__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {WaitWakeIrp__DEVICE_EXTENSIONInv(WaitWakeIrp__DEVICE_EXTENSION(x))} WaitWakeIrp__DEVICE_EXTENSIONInv(WaitWakeIrp__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {WaitWakeIrp__DEVICE_EXTENSIONInv(x)} WaitWakeIrp__DEVICE_EXTENSION(WaitWakeIrp__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_WaitWakeIrp__DEVICE_EXTENSION(S)[x]} _S_WaitWakeIrp__DEVICE_EXTENSION(S)[x] <==> S[WaitWakeIrp__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_WaitWakeIrp__DEVICE_EXTENSIONInv(S)[x]} _S_WaitWakeIrp__DEVICE_EXTENSIONInv(S)[x] <==> S[WaitWakeIrp__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_WaitWakeIrp__DEVICE_EXTENSION(S)} S[x] ==> _S_WaitWakeIrp__DEVICE_EXTENSION(S)[WaitWakeIrp__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_WaitWakeIrp__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_WaitWakeIrp__DEVICE_EXTENSIONInv(S)[WaitWakeIrp__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {WaitWakeIrp__DEVICE_EXTENSION(x)} WaitWakeIrp__DEVICE_EXTENSION(x) == x + 240);
+axiom (forall x:int :: {WaitWakeIrp__DEVICE_EXTENSIONInv(x)} WaitWakeIrp__DEVICE_EXTENSIONInv(x) == x - 240);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 240, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 240, 1) == WaitWakeIrp__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 240)} MINUS_LEFT_PTR(x, 1, 240) == WaitWakeIrp__DEVICE_EXTENSIONInv(x));
+function WaitWakeSpinLock__DEVICE_EXTENSION(int) returns (int);
+function WaitWakeSpinLock__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_WaitWakeSpinLock__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_WaitWakeSpinLock__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {WaitWakeSpinLock__DEVICE_EXTENSIONInv(WaitWakeSpinLock__DEVICE_EXTENSION(x))} WaitWakeSpinLock__DEVICE_EXTENSIONInv(WaitWakeSpinLock__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {WaitWakeSpinLock__DEVICE_EXTENSIONInv(x)} WaitWakeSpinLock__DEVICE_EXTENSION(WaitWakeSpinLock__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_WaitWakeSpinLock__DEVICE_EXTENSION(S)[x]} _S_WaitWakeSpinLock__DEVICE_EXTENSION(S)[x] <==> S[WaitWakeSpinLock__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_WaitWakeSpinLock__DEVICE_EXTENSIONInv(S)[x]} _S_WaitWakeSpinLock__DEVICE_EXTENSIONInv(S)[x] <==> S[WaitWakeSpinLock__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_WaitWakeSpinLock__DEVICE_EXTENSION(S)} S[x] ==> _S_WaitWakeSpinLock__DEVICE_EXTENSION(S)[WaitWakeSpinLock__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_WaitWakeSpinLock__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_WaitWakeSpinLock__DEVICE_EXTENSIONInv(S)[WaitWakeSpinLock__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {WaitWakeSpinLock__DEVICE_EXTENSION(x)} WaitWakeSpinLock__DEVICE_EXTENSION(x) == x + 108);
+axiom (forall x:int :: {WaitWakeSpinLock__DEVICE_EXTENSIONInv(x)} WaitWakeSpinLock__DEVICE_EXTENSIONInv(x) == x - 108);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 108, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 108, 1) == WaitWakeSpinLock__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 108)} MINUS_LEFT_PTR(x, 1, 108) == WaitWakeSpinLock__DEVICE_EXTENSIONInv(x));
+function WmiFunctionControl__WMILIB_CONTEXT(int) returns (int);
+function WmiFunctionControl__WMILIB_CONTEXTInv(int) returns (int);
+function _S_WmiFunctionControl__WMILIB_CONTEXT([int]bool) returns ([int]bool);
+function _S_WmiFunctionControl__WMILIB_CONTEXTInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {WmiFunctionControl__WMILIB_CONTEXTInv(WmiFunctionControl__WMILIB_CONTEXT(x))} WmiFunctionControl__WMILIB_CONTEXTInv(WmiFunctionControl__WMILIB_CONTEXT(x)) == x);
+axiom (forall x:int :: {WmiFunctionControl__WMILIB_CONTEXTInv(x)} WmiFunctionControl__WMILIB_CONTEXT(WmiFunctionControl__WMILIB_CONTEXTInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_WmiFunctionControl__WMILIB_CONTEXT(S)[x]} _S_WmiFunctionControl__WMILIB_CONTEXT(S)[x] <==> S[WmiFunctionControl__WMILIB_CONTEXTInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_WmiFunctionControl__WMILIB_CONTEXTInv(S)[x]} _S_WmiFunctionControl__WMILIB_CONTEXTInv(S)[x] <==> S[WmiFunctionControl__WMILIB_CONTEXT(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_WmiFunctionControl__WMILIB_CONTEXT(S)} S[x] ==> _S_WmiFunctionControl__WMILIB_CONTEXT(S)[WmiFunctionControl__WMILIB_CONTEXT(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_WmiFunctionControl__WMILIB_CONTEXTInv(S)} S[x] ==> _S_WmiFunctionControl__WMILIB_CONTEXTInv(S)[WmiFunctionControl__WMILIB_CONTEXTInv(x)]);
+
+axiom (forall x:int :: {WmiFunctionControl__WMILIB_CONTEXT(x)} WmiFunctionControl__WMILIB_CONTEXT(x) == x + 28);
+axiom (forall x:int :: {WmiFunctionControl__WMILIB_CONTEXTInv(x)} WmiFunctionControl__WMILIB_CONTEXTInv(x) == x - 28);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 28, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 28, 1) == WmiFunctionControl__WMILIB_CONTEXTInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 28)} MINUS_LEFT_PTR(x, 1, 28) == WmiFunctionControl__WMILIB_CONTEXTInv(x));
+function WmiLibInfo__DEVICE_EXTENSION(int) returns (int);
+function WmiLibInfo__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_WmiLibInfo__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_WmiLibInfo__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {WmiLibInfo__DEVICE_EXTENSIONInv(WmiLibInfo__DEVICE_EXTENSION(x))} WmiLibInfo__DEVICE_EXTENSIONInv(WmiLibInfo__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {WmiLibInfo__DEVICE_EXTENSIONInv(x)} WmiLibInfo__DEVICE_EXTENSION(WmiLibInfo__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_WmiLibInfo__DEVICE_EXTENSION(S)[x]} _S_WmiLibInfo__DEVICE_EXTENSION(S)[x] <==> S[WmiLibInfo__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_WmiLibInfo__DEVICE_EXTENSIONInv(S)[x]} _S_WmiLibInfo__DEVICE_EXTENSIONInv(S)[x] <==> S[WmiLibInfo__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_WmiLibInfo__DEVICE_EXTENSION(S)} S[x] ==> _S_WmiLibInfo__DEVICE_EXTENSION(S)[WmiLibInfo__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_WmiLibInfo__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_WmiLibInfo__DEVICE_EXTENSIONInv(S)[WmiLibInfo__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {WmiLibInfo__DEVICE_EXTENSION(x)} WmiLibInfo__DEVICE_EXTENSION(x) == x + 180);
+axiom (forall x:int :: {WmiLibInfo__DEVICE_EXTENSIONInv(x)} WmiLibInfo__DEVICE_EXTENSIONInv(x) == x - 180);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 180, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 180, 1) == WmiLibInfo__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 180)} MINUS_LEFT_PTR(x, 1, 180) == WmiLibInfo__DEVICE_EXTENSIONInv(x));
+function __unnamed_1_2bb39c56___unnamed_4_846adf3f(int) returns (int);
+function __unnamed_1_2bb39c56___unnamed_4_846adf3fInv(int) returns (int);
+function _S___unnamed_1_2bb39c56___unnamed_4_846adf3f([int]bool) returns ([int]bool);
+function _S___unnamed_1_2bb39c56___unnamed_4_846adf3fInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {__unnamed_1_2bb39c56___unnamed_4_846adf3fInv(__unnamed_1_2bb39c56___unnamed_4_846adf3f(x))} __unnamed_1_2bb39c56___unnamed_4_846adf3fInv(__unnamed_1_2bb39c56___unnamed_4_846adf3f(x)) == x);
+axiom (forall x:int :: {__unnamed_1_2bb39c56___unnamed_4_846adf3fInv(x)} __unnamed_1_2bb39c56___unnamed_4_846adf3f(__unnamed_1_2bb39c56___unnamed_4_846adf3fInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S___unnamed_1_2bb39c56___unnamed_4_846adf3f(S)[x]} _S___unnamed_1_2bb39c56___unnamed_4_846adf3f(S)[x] <==> S[__unnamed_1_2bb39c56___unnamed_4_846adf3fInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S___unnamed_1_2bb39c56___unnamed_4_846adf3fInv(S)[x]} _S___unnamed_1_2bb39c56___unnamed_4_846adf3fInv(S)[x] <==> S[__unnamed_1_2bb39c56___unnamed_4_846adf3f(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S___unnamed_1_2bb39c56___unnamed_4_846adf3f(S)} S[x] ==> _S___unnamed_1_2bb39c56___unnamed_4_846adf3f(S)[__unnamed_1_2bb39c56___unnamed_4_846adf3f(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S___unnamed_1_2bb39c56___unnamed_4_846adf3fInv(S)} S[x] ==> _S___unnamed_1_2bb39c56___unnamed_4_846adf3fInv(S)[__unnamed_1_2bb39c56___unnamed_4_846adf3fInv(x)]);
+
+axiom (forall x:int :: {__unnamed_1_2bb39c56___unnamed_4_846adf3f(x)} __unnamed_1_2bb39c56___unnamed_4_846adf3f(x) == x + 1);
+axiom (forall x:int :: {__unnamed_1_2bb39c56___unnamed_4_846adf3fInv(x)} __unnamed_1_2bb39c56___unnamed_4_846adf3fInv(x) == x - 1);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 1, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 1, 1) == __unnamed_1_2bb39c56___unnamed_4_846adf3fInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 1)} MINUS_LEFT_PTR(x, 1, 1) == __unnamed_1_2bb39c56___unnamed_4_846adf3fInv(x));
+function __unnamed_1_9fa0583a___unnamed_4_846adf3f(int) returns (int);
+function __unnamed_1_9fa0583a___unnamed_4_846adf3fInv(int) returns (int);
+function _S___unnamed_1_9fa0583a___unnamed_4_846adf3f([int]bool) returns ([int]bool);
+function _S___unnamed_1_9fa0583a___unnamed_4_846adf3fInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {__unnamed_1_9fa0583a___unnamed_4_846adf3fInv(__unnamed_1_9fa0583a___unnamed_4_846adf3f(x))} __unnamed_1_9fa0583a___unnamed_4_846adf3fInv(__unnamed_1_9fa0583a___unnamed_4_846adf3f(x)) == x);
+axiom (forall x:int :: {__unnamed_1_9fa0583a___unnamed_4_846adf3fInv(x)} __unnamed_1_9fa0583a___unnamed_4_846adf3f(__unnamed_1_9fa0583a___unnamed_4_846adf3fInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S___unnamed_1_9fa0583a___unnamed_4_846adf3f(S)[x]} _S___unnamed_1_9fa0583a___unnamed_4_846adf3f(S)[x] <==> S[__unnamed_1_9fa0583a___unnamed_4_846adf3fInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S___unnamed_1_9fa0583a___unnamed_4_846adf3fInv(S)[x]} _S___unnamed_1_9fa0583a___unnamed_4_846adf3fInv(S)[x] <==> S[__unnamed_1_9fa0583a___unnamed_4_846adf3f(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S___unnamed_1_9fa0583a___unnamed_4_846adf3f(S)} S[x] ==> _S___unnamed_1_9fa0583a___unnamed_4_846adf3f(S)[__unnamed_1_9fa0583a___unnamed_4_846adf3f(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S___unnamed_1_9fa0583a___unnamed_4_846adf3fInv(S)} S[x] ==> _S___unnamed_1_9fa0583a___unnamed_4_846adf3fInv(S)[__unnamed_1_9fa0583a___unnamed_4_846adf3fInv(x)]);
+
+axiom (forall x:int :: {__unnamed_1_9fa0583a___unnamed_4_846adf3f(x)} __unnamed_1_9fa0583a___unnamed_4_846adf3f(x) == x + 3);
+axiom (forall x:int :: {__unnamed_1_9fa0583a___unnamed_4_846adf3fInv(x)} __unnamed_1_9fa0583a___unnamed_4_846adf3fInv(x) == x - 3);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 3, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 3, 1) == __unnamed_1_9fa0583a___unnamed_4_846adf3fInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 3)} MINUS_LEFT_PTR(x, 1, 3) == __unnamed_1_9fa0583a___unnamed_4_846adf3fInv(x));
+function __unnamed_1_e30779f5___unnamed_4_846adf3f(int) returns (int);
+function __unnamed_1_e30779f5___unnamed_4_846adf3fInv(int) returns (int);
+function _S___unnamed_1_e30779f5___unnamed_4_846adf3f([int]bool) returns ([int]bool);
+function _S___unnamed_1_e30779f5___unnamed_4_846adf3fInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {__unnamed_1_e30779f5___unnamed_4_846adf3fInv(__unnamed_1_e30779f5___unnamed_4_846adf3f(x))} __unnamed_1_e30779f5___unnamed_4_846adf3fInv(__unnamed_1_e30779f5___unnamed_4_846adf3f(x)) == x);
+axiom (forall x:int :: {__unnamed_1_e30779f5___unnamed_4_846adf3fInv(x)} __unnamed_1_e30779f5___unnamed_4_846adf3f(__unnamed_1_e30779f5___unnamed_4_846adf3fInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S___unnamed_1_e30779f5___unnamed_4_846adf3f(S)[x]} _S___unnamed_1_e30779f5___unnamed_4_846adf3f(S)[x] <==> S[__unnamed_1_e30779f5___unnamed_4_846adf3fInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S___unnamed_1_e30779f5___unnamed_4_846adf3fInv(S)[x]} _S___unnamed_1_e30779f5___unnamed_4_846adf3fInv(S)[x] <==> S[__unnamed_1_e30779f5___unnamed_4_846adf3f(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S___unnamed_1_e30779f5___unnamed_4_846adf3f(S)} S[x] ==> _S___unnamed_1_e30779f5___unnamed_4_846adf3f(S)[__unnamed_1_e30779f5___unnamed_4_846adf3f(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S___unnamed_1_e30779f5___unnamed_4_846adf3fInv(S)} S[x] ==> _S___unnamed_1_e30779f5___unnamed_4_846adf3fInv(S)[__unnamed_1_e30779f5___unnamed_4_846adf3fInv(x)]);
+
+axiom (forall x:int :: {__unnamed_1_e30779f5___unnamed_4_846adf3f(x)} __unnamed_1_e30779f5___unnamed_4_846adf3f(x) == x + 2);
+axiom (forall x:int :: {__unnamed_1_e30779f5___unnamed_4_846adf3fInv(x)} __unnamed_1_e30779f5___unnamed_4_846adf3fInv(x) == x - 2);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 2, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 2, 1) == __unnamed_1_e30779f5___unnamed_4_846adf3fInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 2)} MINUS_LEFT_PTR(x, 1, 2) == __unnamed_1_e30779f5___unnamed_4_846adf3fInv(x));
+function __unnamed_4_846adf3f___unnamed_4_c9b2e921(int) returns (int);
+function __unnamed_4_846adf3f___unnamed_4_c9b2e921Inv(int) returns (int);
+function _S___unnamed_4_846adf3f___unnamed_4_c9b2e921([int]bool) returns ([int]bool);
+function _S___unnamed_4_846adf3f___unnamed_4_c9b2e921Inv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {__unnamed_4_846adf3f___unnamed_4_c9b2e921Inv(__unnamed_4_846adf3f___unnamed_4_c9b2e921(x))} __unnamed_4_846adf3f___unnamed_4_c9b2e921Inv(__unnamed_4_846adf3f___unnamed_4_c9b2e921(x)) == x);
+axiom (forall x:int :: {__unnamed_4_846adf3f___unnamed_4_c9b2e921Inv(x)} __unnamed_4_846adf3f___unnamed_4_c9b2e921(__unnamed_4_846adf3f___unnamed_4_c9b2e921Inv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S___unnamed_4_846adf3f___unnamed_4_c9b2e921(S)[x]} _S___unnamed_4_846adf3f___unnamed_4_c9b2e921(S)[x] <==> S[__unnamed_4_846adf3f___unnamed_4_c9b2e921Inv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S___unnamed_4_846adf3f___unnamed_4_c9b2e921Inv(S)[x]} _S___unnamed_4_846adf3f___unnamed_4_c9b2e921Inv(S)[x] <==> S[__unnamed_4_846adf3f___unnamed_4_c9b2e921(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S___unnamed_4_846adf3f___unnamed_4_c9b2e921(S)} S[x] ==> _S___unnamed_4_846adf3f___unnamed_4_c9b2e921(S)[__unnamed_4_846adf3f___unnamed_4_c9b2e921(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S___unnamed_4_846adf3f___unnamed_4_c9b2e921Inv(S)} S[x] ==> _S___unnamed_4_846adf3f___unnamed_4_c9b2e921Inv(S)[__unnamed_4_846adf3f___unnamed_4_c9b2e921Inv(x)]);
+
+axiom (forall x:int :: {__unnamed_4_846adf3f___unnamed_4_c9b2e921(x)} __unnamed_4_846adf3f___unnamed_4_c9b2e921(x) == x + 0);
+axiom (forall x:int :: {__unnamed_4_846adf3f___unnamed_4_c9b2e921Inv(x)} __unnamed_4_846adf3f___unnamed_4_c9b2e921Inv(x) == x - 0);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1) == __unnamed_4_846adf3f___unnamed_4_c9b2e921Inv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 0)} MINUS_LEFT_PTR(x, 1, 0) == __unnamed_4_846adf3f___unnamed_4_c9b2e921Inv(x));
+function __unnamed_4_c9b2e921__DISPATCHER_HEADER(int) returns (int);
+function __unnamed_4_c9b2e921__DISPATCHER_HEADERInv(int) returns (int);
+function _S___unnamed_4_c9b2e921__DISPATCHER_HEADER([int]bool) returns ([int]bool);
+function _S___unnamed_4_c9b2e921__DISPATCHER_HEADERInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {__unnamed_4_c9b2e921__DISPATCHER_HEADERInv(__unnamed_4_c9b2e921__DISPATCHER_HEADER(x))} __unnamed_4_c9b2e921__DISPATCHER_HEADERInv(__unnamed_4_c9b2e921__DISPATCHER_HEADER(x)) == x);
+axiom (forall x:int :: {__unnamed_4_c9b2e921__DISPATCHER_HEADERInv(x)} __unnamed_4_c9b2e921__DISPATCHER_HEADER(__unnamed_4_c9b2e921__DISPATCHER_HEADERInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S___unnamed_4_c9b2e921__DISPATCHER_HEADER(S)[x]} _S___unnamed_4_c9b2e921__DISPATCHER_HEADER(S)[x] <==> S[__unnamed_4_c9b2e921__DISPATCHER_HEADERInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S___unnamed_4_c9b2e921__DISPATCHER_HEADERInv(S)[x]} _S___unnamed_4_c9b2e921__DISPATCHER_HEADERInv(S)[x] <==> S[__unnamed_4_c9b2e921__DISPATCHER_HEADER(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S___unnamed_4_c9b2e921__DISPATCHER_HEADER(S)} S[x] ==> _S___unnamed_4_c9b2e921__DISPATCHER_HEADER(S)[__unnamed_4_c9b2e921__DISPATCHER_HEADER(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S___unnamed_4_c9b2e921__DISPATCHER_HEADERInv(S)} S[x] ==> _S___unnamed_4_c9b2e921__DISPATCHER_HEADERInv(S)[__unnamed_4_c9b2e921__DISPATCHER_HEADERInv(x)]);
+
+axiom (forall x:int :: {__unnamed_4_c9b2e921__DISPATCHER_HEADER(x)} __unnamed_4_c9b2e921__DISPATCHER_HEADER(x) == x + 0);
+axiom (forall x:int :: {__unnamed_4_c9b2e921__DISPATCHER_HEADERInv(x)} __unnamed_4_c9b2e921__DISPATCHER_HEADERInv(x) == x - 0);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1) == __unnamed_4_c9b2e921__DISPATCHER_HEADERInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 0)} MINUS_LEFT_PTR(x, 1, 0) == __unnamed_4_c9b2e921__DISPATCHER_HEADERInv(x));
+function MINUS_BOTH_PTR_OR_BOTH_INT(a:int, b:int, size:int) returns (int);
+axiom (forall a:int, b:int, size:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(a,b,size)}
+size * MINUS_BOTH_PTR_OR_BOTH_INT(a,b,size) <= a - b && a - b < size * (MINUS_BOTH_PTR_OR_BOTH_INT(a,b,size) + 1));
+
+function MINUS_LEFT_PTR(a:int, a_size:int, b:int) returns (int);
+axiom(forall a:int, a_size:int, b:int :: {MINUS_LEFT_PTR(a,a_size,b)} MINUS_LEFT_PTR(a,a_size,b) == a - a_size * b);
+
+function PLUS(a:int, a_size:int, b:int) returns (int);
+axiom (forall a:int, a_size:int, b:int :: {PLUS(a,a_size,b)} PLUS(a,a_size,b) == a + a_size * b);
+
+function MULT(a:int, b:int) returns (int); // a*b
+axiom(forall a:int, b:int :: {MULT(a,b)} MULT(a,b) == a * b);
+
+function DIV(a:int, b:int) returns (int); // a/b
+
+axiom(forall a:int, b:int :: {DIV(a,b)}
+a >= 0 && b > 0 ==> b * DIV(a,b) <= a && a < b * (DIV(a,b) + 1)
+);
+
+axiom(forall a:int, b:int :: {DIV(a,b)}
+a >= 0 && b < 0 ==> b * DIV(a,b) <= a && a < b * (DIV(a,b) - 1)
+);
+
+axiom(forall a:int, b:int :: {DIV(a,b)}
+a < 0 && b > 0 ==> b * DIV(a,b) >= a && a > b * (DIV(a,b) - 1)
+);
+
+axiom(forall a:int, b:int :: {DIV(a,b)}
+a < 0 && b < 0 ==> b * DIV(a,b) >= a && a > b * (DIV(a,b) + 1)
+);
+
+function BINARY_BOTH_INT(a:int, b:int) returns (int);
+
+function POW2(a:int) returns (bool);
+axiom POW2(1);
+axiom POW2(2);
+axiom POW2(4);
+axiom POW2(8);
+axiom POW2(16);
+axiom POW2(32);
+axiom POW2(64);
+axiom POW2(128);
+axiom POW2(256);
+axiom POW2(512);
+axiom POW2(1024);
+axiom POW2(2048);
+axiom POW2(4096);
+axiom POW2(8192);
+axiom POW2(16384);
+axiom POW2(32768);
+axiom POW2(65536);
+axiom POW2(131072);
+axiom POW2(262144);
+axiom POW2(524288);
+axiom POW2(1048576);
+axiom POW2(2097152);
+axiom POW2(4194304);
+axiom POW2(8388608);
+axiom POW2(16777216);
+axiom POW2(33554432);
+
+function choose(a:bool, b:int, c:int) returns (x:int);
+axiom(forall a:bool, b:int, c:int :: {choose(a,b,c)} a ==> choose(a,b,c) == b);
+axiom(forall a:bool, b:int, c:int :: {choose(a,b,c)} !a ==> choose(a,b,c) == c);
+
+function BIT_BAND(a:int, b:int) returns (x:int);
+axiom(forall a:int, b:int :: {BIT_BAND(a,b)} a == b ==> BIT_BAND(a,b) == a);
+axiom(forall a:int, b:int :: {BIT_BAND(a,b)} POW2(a) && POW2(b) && a != b ==> BIT_BAND(a,b) == 0);
+axiom(forall a:int, b:int :: {BIT_BAND(a,b)} a == 0 || b == 0 ==> BIT_BAND(a,b) == 0);
+
+function BIT_BOR(a:int, b:int) returns (x:int);
+
+function BIT_BXOR(a:int, b:int) returns (x:int);
+
+function BIT_BNOT(a:int) returns (int);
+
+function LIFT(a:bool) returns (int);
+axiom(forall a:bool :: {LIFT(a)} a <==> LIFT(a) != 0);
+
+function NOT(a:int) returns (int);
+axiom(forall a:int :: {NOT(a)} a == 0 ==> NOT(a) != 0);
+axiom(forall a:int :: {NOT(a)} a != 0 ==> NOT(a) == 0);
+
+function NULL_CHECK(a:int) returns (int);
+axiom(forall a:int :: {NULL_CHECK(a)} a == 0 ==> NULL_CHECK(a) != 0);
+axiom(forall a:int :: {NULL_CHECK(a)} a != 0 ==> NULL_CHECK(a) == 0);
+
+
+
+
+procedure havoc_assert(i:int);
+requires (i != 0);
+
+procedure havoc_assume(i:int);
+ensures (i != 0);
+
+procedure __HAVOC_free(a:int);
+modifies alloc;
+ensures (forall x:int :: {alloc[x]} x == a || old(alloc)[x] == alloc[x]);
+ensures (alloc[a] == FREED);
+// Additional checks guarded by tranlator flags
+// requires alloc[a] == ALLOCATED;
+// requires Base(a) == a;
+
+procedure __HAVOC_malloc(obj_size:int) returns (new:int);
+requires obj_size >= 0;
+modifies alloc;
+ensures (new > 0);
+ensures (forall x:int :: {Base(x)} new <= x && x < new+obj_size ==> Base(x) == new);
+ensures (forall x:int :: {alloc[x]} x == new || old(alloc)[x] == alloc[x]);
+ensures old(alloc)[new] == UNALLOCATED && alloc[new] == ALLOCATED;
+
+procedure nondet_choice() returns (x:int);
+
+procedure _strdup(str:int) returns (new:int);
+
+procedure _xstrcasecmp(a0:int, a1:int) returns (ret:int);
+
+procedure _xstrcmp(a0:int, a1:int) returns (ret:int);
+
+var Res_DEVICE_STACK:[int]int;
+var Res_DEV_EXTN:[int]int;
+var Res_DEV_OBJ_INIT:[int]int;
+var Res_SPIN_LOCK:[int]int;
+
+
+
+////////////////////
+// Between predicate
+////////////////////
+function ReachBetween(f: [int]int, x: int, y: int, z: int) returns (bool);
+function ReachAvoiding(f: [int]int, x: int, y: int, z: int) returns (bool);
+
+
+//////////////////////////
+// Between set constructor
+//////////////////////////
+function ReachBetweenSet(f: [int]int, x: int, z: int) returns ([int]bool);
+
+////////////////////////////////////////////////////
+// axioms relating ReachBetween and ReachBetweenSet
+////////////////////////////////////////////////////
+axiom(forall f: [int]int, x: int, y: int, z: int :: {ReachBetweenSet(f, x, z)[y]} ReachBetweenSet(f, x, z)[y] <==> ReachBetween(f, x, y, z));
+axiom(forall f: [int]int, x: int, y: int, z: int :: {ReachBetween(f, x, y, z), ReachBetweenSet(f, x, z)} ReachBetween(f, x, y, z) ==> ReachBetweenSet(f, x, z)[y]);
+axiom(forall f: [int]int, x: int, z: int :: {ReachBetweenSet(f, x, z)} ReachBetween(f, x, x, x));
+
+
+//////////////////////////
+// Axioms for ReachBetween
+//////////////////////////
+
+// reflexive
+axiom(forall f: [int]int, x: int :: ReachBetween(f, x, x, x));
+
+// step
+//axiom(forall f: [int]int, x: int :: {f[x]} ReachBetween(f, x, f[x], f[x]));
+axiom(forall f: [int]int, x: int, y: int, z: int, w:int :: {ReachBetween(f, y, z, w), f[x]} ReachBetween(f, x, f[x], f[x]));
+
+// reach
+axiom(forall f: [int]int, x: int, y: int :: {f[x], ReachBetween(f, x, y, y)} ReachBetween(f, x, y, y) ==> x == y || ReachBetween(f, x, f[x], y));
+
+// cycle
+axiom(forall f: [int]int, x: int, y:int :: {f[x], ReachBetween(f, x, y, y)} f[x] == x && ReachBetween(f, x, y, y) ==> x == y);
+
+// sandwich
+axiom(forall f: [int]int, x: int, y: int :: {ReachBetween(f, x, y, x)} ReachBetween(f, x, y, x) ==> x == y);
+
+// order1
+axiom(forall f: [int]int, x: int, y: int, z: int :: {ReachBetween(f, x, y, y), ReachBetween(f, x, z, z)} ReachBetween(f, x, y, y) && ReachBetween(f, x, z, z) ==> ReachBetween(f, x, y, z) || ReachBetween(f, x, z, y));
+
+// order2
+axiom(forall f: [int]int, x: int, y: int, z: int :: {ReachBetween(f, x, y, z)} ReachBetween(f, x, y, z) ==> ReachBetween(f, x, y, y) && ReachBetween(f, y, z, z));
+
+// transitive1
+axiom(forall f: [int]int, x: int, y: int, z: int :: {ReachBetween(f, x, y, y), ReachBetween(f, y, z, z)} ReachBetween(f, x, y, y) && ReachBetween(f, y, z, z) ==> ReachBetween(f, x, z, z));
+
+// transitive2
+axiom(forall f: [int]int, x: int, y: int, z: int, w: int :: {ReachBetween(f, x, y, z), ReachBetween(f, y, w, z)} ReachBetween(f, x, y, z) && ReachBetween(f, y, w, z) ==> ReachBetween(f, x, y, w) && ReachBetween(f, x, w, z));
+
+// transitive3
+axiom(forall f: [int]int, x: int, y: int, z: int, w: int :: {ReachBetween(f, x, y, z), ReachBetween(f, x, w, y)} ReachBetween(f, x, y, z) && ReachBetween(f, x, w, y) ==> ReachBetween(f, x, w, z) && ReachBetween(f, w, y, z));
+
+// This axiom is required to deal with the incompleteness of the trigger for the reflexive axiom.
+// It cannot be proved using the rest of the axioms.
+axiom(forall f: [int]int, u:int, x: int :: {ReachBetween(f, u, x, x)} ReachBetween(f, u, x, x) ==> ReachBetween(f, u, u, x));
+
+// relation between ReachAvoiding and ReachBetween
+axiom(forall f: [int]int, x: int, y: int, z: int :: {ReachAvoiding(f, x, y, z)}{ReachBetween(f, x, y, z)} ReachAvoiding(f, x, y, z) <==> (ReachBetween(f, x, y, z) || (ReachBetween(f, x, y, y) && !ReachBetween(f, x, z, z))));
+
+// update
+axiom(forall f: [int]int, u: int, v: int, x: int, p: int, q: int :: {ReachAvoiding(f[p := q], u, v, x)} ReachAvoiding(f[p := q], u, v, x) <==> ((ReachAvoiding(f, u, v, p) && ReachAvoiding(f, u, v, x)) || (ReachAvoiding(f, u, p, x) && p != x && ReachAvoiding(f, q, v, p) && ReachAvoiding(f, q, v, x))));
+ ///////////////////////////////
+ // Shifts for linking fields
+ ///////////////////////////////
+function Shift_Flink__LIST_ENTRY(f: [int]int) returns ([int]int);
+axiom( forall f: [int]int, __x:int :: {f[Flink__LIST_ENTRY(__x)],Shift_Flink__LIST_ENTRY(f)} {Shift_Flink__LIST_ENTRY(f)[__x]} Shift_Flink__LIST_ENTRY(f)[__x] == f[Flink__LIST_ENTRY(__x)]);
+axiom(forall f: [int]int, __x:int, __v:int :: {Shift_Flink__LIST_ENTRY(f[Flink__LIST_ENTRY(__x) := __v])} Shift_Flink__LIST_ENTRY(f[Flink__LIST_ENTRY(__x) := __v]) == Shift_Flink__LIST_ENTRY(f)[__x := __v]);
+
+const unique Globals : int;
+axiom(Globals != 0);
+// the set of constants for 64 bit integers that Boogie doesn't parse
+const unique BOOGIE_LARGE_INT_4294967273:int;
+
+
+
+procedure ExAcquireFastMutex($FastMutex$1$15000.16$ExAcquireFastMutex$41:int);
+
+//TAG: ensures __preserves_mem
+ensures(Mem == old(Mem));
+//TAG: ensures __preserves_resource("DEV_OBJ_INIT") && __preserves_resource("DEV_EXTN")
+ensures((Res_DEV_OBJ_INIT == old(Res_DEV_OBJ_INIT)) && (Res_DEV_EXTN == old(Res_DEV_EXTN)));
+
+modifies Res_DEVICE_STACK;
+
+//TAG: net change in resource DEVICE_STACK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEVICE_STACK[r]} (Empty()[r]) || old(Res_DEVICE_STACK)[r] == Res_DEVICE_STACK[r]));
+modifies Res_DEV_EXTN;
+
+//TAG: net change in resource DEV_EXTN only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_EXTN[r]} (Empty()[r]) || old(Res_DEV_EXTN)[r] == Res_DEV_EXTN[r]));
+modifies Res_DEV_OBJ_INIT;
+
+//TAG: net change in resource DEV_OBJ_INIT only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_OBJ_INIT[r]} (Empty()[r]) || old(Res_DEV_OBJ_INIT)[r] == Res_DEV_OBJ_INIT[r]));
+modifies Res_SPIN_LOCK;
+
+//TAG: net change in resource SPIN_LOCK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_SPIN_LOCK[r]} (Empty()[r]) || old(Res_SPIN_LOCK)[r] == Res_SPIN_LOCK[r]));
+//TAG: updated memory locations at Mem[T.MinorFunction__IO_STACK_LOCATION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.MinorFunction__IO_STACK_LOCATION][_m]} (Empty()[_m]) || Mem[T.MinorFunction__IO_STACK_LOCATION][_m] == old(Mem)[T.MinorFunction__IO_STACK_LOCATION][_m]));
+//TAG: updated memory locations at Mem[T.CurrentStackLocation___unnamed_4_a7aa989c] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.CurrentStackLocation___unnamed_4_a7aa989c][_m]} (Empty()[_m]) || Mem[T.CurrentStackLocation___unnamed_4_a7aa989c][_m] == old(Mem)[T.CurrentStackLocation___unnamed_4_a7aa989c][_m]));
+//TAG: updated memory locations at Mem[T.DeviceExtension__DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.DeviceExtension__DEVICE_OBJECT][_m] == old(Mem)[T.DeviceExtension__DEVICE_OBJECT][_m]));
+//TAG: updated memory locations at Mem[T.Self__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Self__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Self__DEVICE_EXTENSION][_m] == old(Mem)[T.Self__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.Started__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Started__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Started__DEVICE_EXTENSION][_m] == old(Mem)[T.Started__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.GrandMaster__GLOBALS] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.GrandMaster__GLOBALS][_m]} (Empty()[_m]) || Mem[T.GrandMaster__GLOBALS][_m] == old(Mem)[T.GrandMaster__GLOBALS][_m]));
+//TAG: updated memory locations at Mem[T.P_DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.P_DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.P_DEVICE_OBJECT][_m] == old(Mem)[T.P_DEVICE_OBJECT][_m]));
+
+//TAG: havoc memory locations by default
+modifies Mem;
+
+
+procedure ExAllocatePoolWithTag($PoolType$1$14789.57$ExAllocatePoolWithTag$121:int, $NumberOfBytes$2$14790.16$ExAllocatePoolWithTag$121:int, $Tag$3$14791.15$ExAllocatePoolWithTag$121:int) returns ($result.ExAllocatePoolWithTag$14788.0$1$:int);
+
+//TAG: ensures __preserves_mem
+ensures(Mem == old(Mem));
+//TAG: ensures __preserves_resource("DEV_OBJ_INIT") && __preserves_resource("DEV_EXTN")
+ensures((Res_DEV_OBJ_INIT == old(Res_DEV_OBJ_INIT)) && (Res_DEV_EXTN == old(Res_DEV_EXTN)));
+
+modifies Res_DEVICE_STACK;
+
+//TAG: net change in resource DEVICE_STACK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEVICE_STACK[r]} (Empty()[r]) || old(Res_DEVICE_STACK)[r] == Res_DEVICE_STACK[r]));
+modifies Res_DEV_EXTN;
+
+//TAG: net change in resource DEV_EXTN only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_EXTN[r]} (Empty()[r]) || old(Res_DEV_EXTN)[r] == Res_DEV_EXTN[r]));
+modifies Res_DEV_OBJ_INIT;
+
+//TAG: net change in resource DEV_OBJ_INIT only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_OBJ_INIT[r]} (Empty()[r]) || old(Res_DEV_OBJ_INIT)[r] == Res_DEV_OBJ_INIT[r]));
+modifies Res_SPIN_LOCK;
+
+//TAG: net change in resource SPIN_LOCK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_SPIN_LOCK[r]} (Empty()[r]) || old(Res_SPIN_LOCK)[r] == Res_SPIN_LOCK[r]));
+//TAG: updated memory locations at Mem[T.MinorFunction__IO_STACK_LOCATION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.MinorFunction__IO_STACK_LOCATION][_m]} (Empty()[_m]) || Mem[T.MinorFunction__IO_STACK_LOCATION][_m] == old(Mem)[T.MinorFunction__IO_STACK_LOCATION][_m]));
+//TAG: updated memory locations at Mem[T.CurrentStackLocation___unnamed_4_a7aa989c] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.CurrentStackLocation___unnamed_4_a7aa989c][_m]} (Empty()[_m]) || Mem[T.CurrentStackLocation___unnamed_4_a7aa989c][_m] == old(Mem)[T.CurrentStackLocation___unnamed_4_a7aa989c][_m]));
+//TAG: updated memory locations at Mem[T.DeviceExtension__DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.DeviceExtension__DEVICE_OBJECT][_m] == old(Mem)[T.DeviceExtension__DEVICE_OBJECT][_m]));
+//TAG: updated memory locations at Mem[T.Self__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Self__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Self__DEVICE_EXTENSION][_m] == old(Mem)[T.Self__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.Started__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Started__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Started__DEVICE_EXTENSION][_m] == old(Mem)[T.Started__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.GrandMaster__GLOBALS] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.GrandMaster__GLOBALS][_m]} (Empty()[_m]) || Mem[T.GrandMaster__GLOBALS][_m] == old(Mem)[T.GrandMaster__GLOBALS][_m]));
+//TAG: updated memory locations at Mem[T.P_DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.P_DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.P_DEVICE_OBJECT][_m] == old(Mem)[T.P_DEVICE_OBJECT][_m]));
+
+//TAG: havoc memory locations by default
+modifies Mem;
+
+
+procedure ExFreePoolWithTag($P$1$14901.35$ExFreePoolWithTag$81:int, $Tag$2$14902.15$ExFreePoolWithTag$81:int);
+
+//TAG: ensures __preserves_mem
+ensures(Mem == old(Mem));
+//TAG: ensures __preserves_resource("DEV_OBJ_INIT") && __preserves_resource("DEV_EXTN")
+ensures((Res_DEV_OBJ_INIT == old(Res_DEV_OBJ_INIT)) && (Res_DEV_EXTN == old(Res_DEV_EXTN)));
+
+modifies Res_DEVICE_STACK;
+
+//TAG: net change in resource DEVICE_STACK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEVICE_STACK[r]} (Empty()[r]) || old(Res_DEVICE_STACK)[r] == Res_DEVICE_STACK[r]));
+modifies Res_DEV_EXTN;
+
+//TAG: net change in resource DEV_EXTN only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_EXTN[r]} (Empty()[r]) || old(Res_DEV_EXTN)[r] == Res_DEV_EXTN[r]));
+modifies Res_DEV_OBJ_INIT;
+
+//TAG: net change in resource DEV_OBJ_INIT only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_OBJ_INIT[r]} (Empty()[r]) || old(Res_DEV_OBJ_INIT)[r] == Res_DEV_OBJ_INIT[r]));
+modifies Res_SPIN_LOCK;
+
+//TAG: net change in resource SPIN_LOCK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_SPIN_LOCK[r]} (Empty()[r]) || old(Res_SPIN_LOCK)[r] == Res_SPIN_LOCK[r]));
+//TAG: updated memory locations at Mem[T.MinorFunction__IO_STACK_LOCATION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.MinorFunction__IO_STACK_LOCATION][_m]} (Empty()[_m]) || Mem[T.MinorFunction__IO_STACK_LOCATION][_m] == old(Mem)[T.MinorFunction__IO_STACK_LOCATION][_m]));
+//TAG: updated memory locations at Mem[T.CurrentStackLocation___unnamed_4_a7aa989c] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.CurrentStackLocation___unnamed_4_a7aa989c][_m]} (Empty()[_m]) || Mem[T.CurrentStackLocation___unnamed_4_a7aa989c][_m] == old(Mem)[T.CurrentStackLocation___unnamed_4_a7aa989c][_m]));
+//TAG: updated memory locations at Mem[T.DeviceExtension__DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.DeviceExtension__DEVICE_OBJECT][_m] == old(Mem)[T.DeviceExtension__DEVICE_OBJECT][_m]));
+//TAG: updated memory locations at Mem[T.Self__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Self__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Self__DEVICE_EXTENSION][_m] == old(Mem)[T.Self__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.Started__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Started__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Started__DEVICE_EXTENSION][_m] == old(Mem)[T.Started__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.GrandMaster__GLOBALS] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.GrandMaster__GLOBALS][_m]} (Empty()[_m]) || Mem[T.GrandMaster__GLOBALS][_m] == old(Mem)[T.GrandMaster__GLOBALS][_m]));
+//TAG: updated memory locations at Mem[T.P_DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.P_DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.P_DEVICE_OBJECT][_m] == old(Mem)[T.P_DEVICE_OBJECT][_m]));
+
+//TAG: havoc memory locations by default
+modifies Mem;
+
+
+procedure ExReleaseFastMutex($FastMutex$1$15013.16$ExReleaseFastMutex$41:int);
+
+//TAG: ensures __preserves_mem
+ensures(Mem == old(Mem));
+//TAG: ensures __preserves_resource("DEV_OBJ_INIT") && __preserves_resource("DEV_EXTN")
+ensures((Res_DEV_OBJ_INIT == old(Res_DEV_OBJ_INIT)) && (Res_DEV_EXTN == old(Res_DEV_EXTN)));
+
+modifies Res_DEVICE_STACK;
+
+//TAG: net change in resource DEVICE_STACK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEVICE_STACK[r]} (Empty()[r]) || old(Res_DEVICE_STACK)[r] == Res_DEVICE_STACK[r]));
+modifies Res_DEV_EXTN;
+
+//TAG: net change in resource DEV_EXTN only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_EXTN[r]} (Empty()[r]) || old(Res_DEV_EXTN)[r] == Res_DEV_EXTN[r]));
+modifies Res_DEV_OBJ_INIT;
+
+//TAG: net change in resource DEV_OBJ_INIT only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_OBJ_INIT[r]} (Empty()[r]) || old(Res_DEV_OBJ_INIT)[r] == Res_DEV_OBJ_INIT[r]));
+modifies Res_SPIN_LOCK;
+
+//TAG: net change in resource SPIN_LOCK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_SPIN_LOCK[r]} (Empty()[r]) || old(Res_SPIN_LOCK)[r] == Res_SPIN_LOCK[r]));
+//TAG: updated memory locations at Mem[T.MinorFunction__IO_STACK_LOCATION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.MinorFunction__IO_STACK_LOCATION][_m]} (Empty()[_m]) || Mem[T.MinorFunction__IO_STACK_LOCATION][_m] == old(Mem)[T.MinorFunction__IO_STACK_LOCATION][_m]));
+//TAG: updated memory locations at Mem[T.CurrentStackLocation___unnamed_4_a7aa989c] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.CurrentStackLocation___unnamed_4_a7aa989c][_m]} (Empty()[_m]) || Mem[T.CurrentStackLocation___unnamed_4_a7aa989c][_m] == old(Mem)[T.CurrentStackLocation___unnamed_4_a7aa989c][_m]));
+//TAG: updated memory locations at Mem[T.DeviceExtension__DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.DeviceExtension__DEVICE_OBJECT][_m] == old(Mem)[T.DeviceExtension__DEVICE_OBJECT][_m]));
+//TAG: updated memory locations at Mem[T.Self__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Self__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Self__DEVICE_EXTENSION][_m] == old(Mem)[T.Self__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.Started__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Started__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Started__DEVICE_EXTENSION][_m] == old(Mem)[T.Started__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.GrandMaster__GLOBALS] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.GrandMaster__GLOBALS][_m]} (Empty()[_m]) || Mem[T.GrandMaster__GLOBALS][_m] == old(Mem)[T.GrandMaster__GLOBALS][_m]));
+//TAG: updated memory locations at Mem[T.P_DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.P_DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.P_DEVICE_OBJECT][_m] == old(Mem)[T.P_DEVICE_OBJECT][_m]));
+
+//TAG: havoc memory locations by default
+modifies Mem;
+
+
+procedure InitializeListHead_IRP($ListHead$1$12.44$InitializeListHead_IRP$41:int);
+
+//TAG: ensures __preserves_mem
+ensures(Mem == old(Mem));
+//TAG: ensures __preserves_resource("DEV_OBJ_INIT") && __preserves_resource("DEV_EXTN")
+ensures((Res_DEV_OBJ_INIT == old(Res_DEV_OBJ_INIT)) && (Res_DEV_EXTN == old(Res_DEV_EXTN)));
+
+modifies Res_DEVICE_STACK;
+
+//TAG: net change in resource DEVICE_STACK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEVICE_STACK[r]} (Empty()[r]) || old(Res_DEVICE_STACK)[r] == Res_DEVICE_STACK[r]));
+modifies Res_DEV_EXTN;
+
+//TAG: net change in resource DEV_EXTN only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_EXTN[r]} (Empty()[r]) || old(Res_DEV_EXTN)[r] == Res_DEV_EXTN[r]));
+modifies Res_DEV_OBJ_INIT;
+
+//TAG: net change in resource DEV_OBJ_INIT only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_OBJ_INIT[r]} (Empty()[r]) || old(Res_DEV_OBJ_INIT)[r] == Res_DEV_OBJ_INIT[r]));
+modifies Res_SPIN_LOCK;
+
+//TAG: net change in resource SPIN_LOCK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_SPIN_LOCK[r]} (Empty()[r]) || old(Res_SPIN_LOCK)[r] == Res_SPIN_LOCK[r]));
+//TAG: updated memory locations at Mem[T.MinorFunction__IO_STACK_LOCATION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.MinorFunction__IO_STACK_LOCATION][_m]} (Empty()[_m]) || Mem[T.MinorFunction__IO_STACK_LOCATION][_m] == old(Mem)[T.MinorFunction__IO_STACK_LOCATION][_m]));
+//TAG: updated memory locations at Mem[T.CurrentStackLocation___unnamed_4_a7aa989c] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.CurrentStackLocation___unnamed_4_a7aa989c][_m]} (Empty()[_m]) || Mem[T.CurrentStackLocation___unnamed_4_a7aa989c][_m] == old(Mem)[T.CurrentStackLocation___unnamed_4_a7aa989c][_m]));
+//TAG: updated memory locations at Mem[T.DeviceExtension__DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.DeviceExtension__DEVICE_OBJECT][_m] == old(Mem)[T.DeviceExtension__DEVICE_OBJECT][_m]));
+//TAG: updated memory locations at Mem[T.Self__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Self__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Self__DEVICE_EXTENSION][_m] == old(Mem)[T.Self__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.Started__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Started__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Started__DEVICE_EXTENSION][_m] == old(Mem)[T.Started__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.GrandMaster__GLOBALS] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.GrandMaster__GLOBALS][_m]} (Empty()[_m]) || Mem[T.GrandMaster__GLOBALS][_m] == old(Mem)[T.GrandMaster__GLOBALS][_m]));
+//TAG: updated memory locations at Mem[T.P_DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.P_DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.P_DEVICE_OBJECT][_m] == old(Mem)[T.P_DEVICE_OBJECT][_m]));
+
+//TAG: havoc memory locations by default
+modifies Mem;
+
+
+procedure IoCreateDevice($DriverObject$1$21226.25$IoCreateDevice$281:int, $DeviceExtensionSize$2$21227.16$IoCreateDevice$281:int, $DeviceName$3$21228.29$IoCreateDevice$281:int, $DeviceType$4$21229.22$IoCreateDevice$281:int, $DeviceCharacteristics$5$21230.16$IoCreateDevice$281:int, $Exclusive$6$21231.18$IoCreateDevice$281:int, $DeviceObject$7$21237.20$IoCreateDevice$281:int) returns ($result.IoCreateDevice$21225.0$1$:int);
+
+//TAG: ensures (LONG)__return >= 0 ==> *DeviceObject != (void *)0
+ensures(($result.IoCreateDevice$21225.0$1$ >= 0) ==> (Mem[T.P_DEVICE_OBJECT][$DeviceObject$7$21237.20$IoCreateDevice$281] != 0));
+//TAG: ensures (LONG)__return >= 0 ==> (*DeviceObject)->DeviceExtension != (void *)0
+ensures(($result.IoCreateDevice$21225.0$1$ >= 0) ==> (Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.P_DEVICE_OBJECT][$DeviceObject$7$21237.20$IoCreateDevice$281])] != 0));
+//TAG: ensures (LONG)__return >= 0 ==> __resource("DEV_EXTN", (*DeviceObject)->DeviceExtension) == 1
+ensures(($result.IoCreateDevice$21225.0$1$ >= 0) ==> (Res_DEV_EXTN[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.P_DEVICE_OBJECT][$DeviceObject$7$21237.20$IoCreateDevice$281])]] == 1));
+//TAG: ensures (LONG)__return >= 0 ==> __resource("DEV_OBJ_INIT", *DeviceObject) == 1 && __resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)(*DeviceObject))->DeviceExtension)) == 1
+ensures(($result.IoCreateDevice$21225.0$1$ >= 0) ==> ((Res_DEV_OBJ_INIT[Mem[T.P_DEVICE_OBJECT][$DeviceObject$7$21237.20$IoCreateDevice$281]] == 1) && (Res_DEV_EXTN[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.P_DEVICE_OBJECT][$DeviceObject$7$21237.20$IoCreateDevice$281])]] == 1)));
+//TAG: ensures (LONG)__return >= 0 ==> __old_resource("DEV_OBJ_INIT", *DeviceObject) == 0 && __old_resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)(*DeviceObject))->DeviceExtension)) == 0
+ensures(($result.IoCreateDevice$21225.0$1$ >= 0) ==> ((old(Res_DEV_OBJ_INIT)[Mem[T.P_DEVICE_OBJECT][$DeviceObject$7$21237.20$IoCreateDevice$281]] == 0) && (old(Res_DEV_EXTN)[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.P_DEVICE_OBJECT][$DeviceObject$7$21237.20$IoCreateDevice$281])]] == 0)));
+//TAG: ensures (LONG)__return >= 0 ==> __updates_resource("DEV_OBJ_INIT", *DeviceObject, 1) && __updates_resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)(*DeviceObject))->DeviceExtension), 1)
+ensures(($result.IoCreateDevice$21225.0$1$ >= 0) ==> ((Res_DEV_OBJ_INIT == old(Res_DEV_OBJ_INIT)[Mem[T.P_DEVICE_OBJECT][$DeviceObject$7$21237.20$IoCreateDevice$281] := 1]) && (Res_DEV_EXTN == old(Res_DEV_EXTN)[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.P_DEVICE_OBJECT][$DeviceObject$7$21237.20$IoCreateDevice$281])] := 1])));
+//TAG: ensures !((LONG)__return >= 0) ==> __resource("DEV_OBJ_INIT", *DeviceObject) == __old_resource("DEV_OBJ_INIT", *DeviceObject) && __resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)(*DeviceObject))->DeviceExtension)) == __old_resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)(*DeviceObject))->DeviceExtension))
+ensures((!($result.IoCreateDevice$21225.0$1$ >= 0)) ==> ((Res_DEV_OBJ_INIT[Mem[T.P_DEVICE_OBJECT][$DeviceObject$7$21237.20$IoCreateDevice$281]] == old(Res_DEV_OBJ_INIT)[Mem[T.P_DEVICE_OBJECT][$DeviceObject$7$21237.20$IoCreateDevice$281]]) && (Res_DEV_EXTN[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.P_DEVICE_OBJECT][$DeviceObject$7$21237.20$IoCreateDevice$281])]] == old(Res_DEV_EXTN)[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.P_DEVICE_OBJECT][$DeviceObject$7$21237.20$IoCreateDevice$281])]])));
+//TAG: ensures !((LONG)__return >= 0) ==> __preserves_resource("DEV_OBJ_INIT") && __preserves_resource("DEV_EXTN")
+free ensures((!($result.IoCreateDevice$21225.0$1$ >= 0)) ==> ((Res_DEV_OBJ_INIT == old(Res_DEV_OBJ_INIT)) && (Res_DEV_EXTN == old(Res_DEV_EXTN))));
+//TAG: ensures (LONG)__return >= 0 ==> !(__resource("DEV_OBJ_INIT", ((struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)(*DeviceObject))->DeviceExtension))->Self) == 1)
+ensures(($result.IoCreateDevice$21225.0$1$ >= 0) ==> (!(Res_DEV_OBJ_INIT[Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.P_DEVICE_OBJECT][$DeviceObject$7$21237.20$IoCreateDevice$281])])]] == 1)));
+//TAG: ensures !((LONG)__return >= 0) ==> *DeviceObject == __old(*DeviceObject)
+ensures((!($result.IoCreateDevice$21225.0$1$ >= 0)) ==> (Mem[T.P_DEVICE_OBJECT][$DeviceObject$7$21237.20$IoCreateDevice$281] == old(Mem)[T.P_DEVICE_OBJECT][$DeviceObject$7$21237.20$IoCreateDevice$281]));
+//TAG: ensures __preserves_field_map(__offset((*((struct _LIST_ENTRY *)0)).Flink))
+ensures(Mem[T.Flink__LIST_ENTRY] == old(Mem)[T.Flink__LIST_ENTRY]);
+//TAG: ensures (LONG)__return >= 0 ==> __return == 0
+ensures(($result.IoCreateDevice$21225.0$1$ >= 0) ==> ($result.IoCreateDevice$21225.0$1$ == 0));
+
+modifies Res_DEVICE_STACK;
+
+//TAG: net change in resource DEVICE_STACK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEVICE_STACK[r]} (Empty()[r]) || old(Res_DEVICE_STACK)[r] == Res_DEVICE_STACK[r]));
+modifies Res_DEV_EXTN;
+
+//TAG: net change in resource DEV_EXTN only for: __set_empty, (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)(*DeviceObject))->DeviceExtension)
+ensures (Subset(Empty(), Union(Union(Empty(), Empty()), Singleton(Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.P_DEVICE_OBJECT][$DeviceObject$7$21237.20$IoCreateDevice$281])]))) && (forall r:int :: {Res_DEV_EXTN[r]} (Empty()[r]) || (Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.P_DEVICE_OBJECT][$DeviceObject$7$21237.20$IoCreateDevice$281])] == r) || old(Res_DEV_EXTN)[r] == Res_DEV_EXTN[r]));
+modifies Res_DEV_OBJ_INIT;
+
+//TAG: net change in resource DEV_OBJ_INIT only for: __set_empty, *DeviceObject
+ensures (Subset(Empty(), Union(Union(Empty(), Empty()), Singleton(Mem[T.P_DEVICE_OBJECT][$DeviceObject$7$21237.20$IoCreateDevice$281]))) && (forall r:int :: {Res_DEV_OBJ_INIT[r]} (Empty()[r]) || (Mem[T.P_DEVICE_OBJECT][$DeviceObject$7$21237.20$IoCreateDevice$281] == r) || old(Res_DEV_OBJ_INIT)[r] == Res_DEV_OBJ_INIT[r]));
+modifies Res_SPIN_LOCK;
+
+//TAG: net change in resource SPIN_LOCK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_SPIN_LOCK[r]} (Empty()[r]) || old(Res_SPIN_LOCK)[r] == Res_SPIN_LOCK[r]));
+//TAG: updated memory locations at Mem[T.MinorFunction__IO_STACK_LOCATION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.MinorFunction__IO_STACK_LOCATION][_m]} (Empty()[_m]) || Mem[T.MinorFunction__IO_STACK_LOCATION][_m] == old(Mem)[T.MinorFunction__IO_STACK_LOCATION][_m]));
+//TAG: updated memory locations at Mem[T.CurrentStackLocation___unnamed_4_a7aa989c] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.CurrentStackLocation___unnamed_4_a7aa989c][_m]} (Empty()[_m]) || Mem[T.CurrentStackLocation___unnamed_4_a7aa989c][_m] == old(Mem)[T.CurrentStackLocation___unnamed_4_a7aa989c][_m]));
+//TAG: updated memory locations at Mem[T.DeviceExtension__DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.DeviceExtension__DEVICE_OBJECT][_m] == old(Mem)[T.DeviceExtension__DEVICE_OBJECT][_m]));
+//TAG: updated memory locations at Mem[T.Self__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Self__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Self__DEVICE_EXTENSION][_m] == old(Mem)[T.Self__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.Started__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Started__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Started__DEVICE_EXTENSION][_m] == old(Mem)[T.Started__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.GrandMaster__GLOBALS] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.GrandMaster__GLOBALS][_m]} (Empty()[_m]) || Mem[T.GrandMaster__GLOBALS][_m] == old(Mem)[T.GrandMaster__GLOBALS][_m]));
+//TAG: updated memory locations at Mem[T.P_DEVICE_OBJECT] only for: __set_empty, DeviceObject
+ensures (Subset(Empty(), Union(Union(Empty(), Empty()), Singleton($DeviceObject$7$21237.20$IoCreateDevice$281))) && (forall _m:int :: {Mem[T.P_DEVICE_OBJECT][_m]} (Empty()[_m]) || (_m == $DeviceObject$7$21237.20$IoCreateDevice$281) || Mem[T.P_DEVICE_OBJECT][_m] == old(Mem)[T.P_DEVICE_OBJECT][_m]));
+
+//TAG: havoc memory locations by default
+modifies Mem;
+
+
+procedure IoDeleteDevice($DeviceObject$1$21328.67$IoDeleteDevice$41:int);
+
+//TAG: ensures __preserves_mem
+ensures(Mem == old(Mem));
+//TAG: requires 1 ==> __resource("DEV_OBJ_INIT", DeviceObject) == 1 && __resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)DeviceObject)->DeviceExtension)) == 1
+requires((true) ==> ((Res_DEV_OBJ_INIT[$DeviceObject$1$21328.67$IoDeleteDevice$41] == 1) && (Res_DEV_EXTN[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT($DeviceObject$1$21328.67$IoDeleteDevice$41)]] == 1)));
+//TAG: ensures 1 ==> __resource("DEV_OBJ_INIT", DeviceObject) == 0 && __resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)DeviceObject)->DeviceExtension)) == 0
+ensures((true) ==> ((Res_DEV_OBJ_INIT[$DeviceObject$1$21328.67$IoDeleteDevice$41] == 0) && (Res_DEV_EXTN[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT($DeviceObject$1$21328.67$IoDeleteDevice$41)]] == 0)));
+//TAG: ensures 1 ==> __updates_resource("DEV_OBJ_INIT", DeviceObject, 0) && __updates_resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)DeviceObject)->DeviceExtension), 0)
+ensures((true) ==> ((Res_DEV_OBJ_INIT == old(Res_DEV_OBJ_INIT)[$DeviceObject$1$21328.67$IoDeleteDevice$41 := 0]) && (Res_DEV_EXTN == old(Res_DEV_EXTN)[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT($DeviceObject$1$21328.67$IoDeleteDevice$41)] := 0])));
+//TAG: ensures !1 ==> __resource("DEV_OBJ_INIT", DeviceObject) == __old_resource("DEV_OBJ_INIT", DeviceObject) && __resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)DeviceObject)->DeviceExtension)) == __old_resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)DeviceObject)->DeviceExtension))
+ensures((!(true)) ==> ((Res_DEV_OBJ_INIT[$DeviceObject$1$21328.67$IoDeleteDevice$41] == old(Res_DEV_OBJ_INIT)[$DeviceObject$1$21328.67$IoDeleteDevice$41]) && (Res_DEV_EXTN[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT($DeviceObject$1$21328.67$IoDeleteDevice$41)]] == old(Res_DEV_EXTN)[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT($DeviceObject$1$21328.67$IoDeleteDevice$41)]])));
+//TAG: ensures !1 ==> __preserves_resource("DEV_OBJ_INIT") && __preserves_resource("DEV_EXTN")
+free ensures((!(true)) ==> ((Res_DEV_OBJ_INIT == old(Res_DEV_OBJ_INIT)) && (Res_DEV_EXTN == old(Res_DEV_EXTN))));
+
+modifies Res_DEVICE_STACK;
+
+//TAG: net change in resource DEVICE_STACK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEVICE_STACK[r]} (Empty()[r]) || old(Res_DEVICE_STACK)[r] == Res_DEVICE_STACK[r]));
+modifies Res_DEV_EXTN;
+
+//TAG: net change in resource DEV_EXTN only for: __set_empty, (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)DeviceObject)->DeviceExtension)
+ensures (Subset(Empty(), Union(Union(Empty(), Empty()), Singleton(Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT($DeviceObject$1$21328.67$IoDeleteDevice$41)]))) && (forall r:int :: {Res_DEV_EXTN[r]} (Empty()[r]) || (Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT($DeviceObject$1$21328.67$IoDeleteDevice$41)] == r) || old(Res_DEV_EXTN)[r] == Res_DEV_EXTN[r]));
+modifies Res_DEV_OBJ_INIT;
+
+//TAG: net change in resource DEV_OBJ_INIT only for: __set_empty, DeviceObject
+ensures (Subset(Empty(), Union(Union(Empty(), Empty()), Singleton($DeviceObject$1$21328.67$IoDeleteDevice$41))) && (forall r:int :: {Res_DEV_OBJ_INIT[r]} (Empty()[r]) || ($DeviceObject$1$21328.67$IoDeleteDevice$41 == r) || old(Res_DEV_OBJ_INIT)[r] == Res_DEV_OBJ_INIT[r]));
+modifies Res_SPIN_LOCK;
+
+//TAG: net change in resource SPIN_LOCK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_SPIN_LOCK[r]} (Empty()[r]) || old(Res_SPIN_LOCK)[r] == Res_SPIN_LOCK[r]));
+//TAG: updated memory locations at Mem[T.MinorFunction__IO_STACK_LOCATION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.MinorFunction__IO_STACK_LOCATION][_m]} (Empty()[_m]) || Mem[T.MinorFunction__IO_STACK_LOCATION][_m] == old(Mem)[T.MinorFunction__IO_STACK_LOCATION][_m]));
+//TAG: updated memory locations at Mem[T.CurrentStackLocation___unnamed_4_a7aa989c] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.CurrentStackLocation___unnamed_4_a7aa989c][_m]} (Empty()[_m]) || Mem[T.CurrentStackLocation___unnamed_4_a7aa989c][_m] == old(Mem)[T.CurrentStackLocation___unnamed_4_a7aa989c][_m]));
+//TAG: updated memory locations at Mem[T.DeviceExtension__DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.DeviceExtension__DEVICE_OBJECT][_m] == old(Mem)[T.DeviceExtension__DEVICE_OBJECT][_m]));
+//TAG: updated memory locations at Mem[T.Self__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Self__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Self__DEVICE_EXTENSION][_m] == old(Mem)[T.Self__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.Started__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Started__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Started__DEVICE_EXTENSION][_m] == old(Mem)[T.Started__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.GrandMaster__GLOBALS] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.GrandMaster__GLOBALS][_m]} (Empty()[_m]) || Mem[T.GrandMaster__GLOBALS][_m] == old(Mem)[T.GrandMaster__GLOBALS][_m]));
+//TAG: updated memory locations at Mem[T.P_DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.P_DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.P_DEVICE_OBJECT][_m] == old(Mem)[T.P_DEVICE_OBJECT][_m]));
+
+//TAG: havoc memory locations by default
+modifies Mem;
+
+
+procedure IoInitializeRemoveLockEx($Lock$1$22135.25$IoInitializeRemoveLockEx$201:int, $AllocateTag$2$22136.16$IoInitializeRemoveLockEx$201:int, $MaxLockedMinutes$3$22137.16$IoInitializeRemoveLockEx$201:int, $HighWatermark$4$22138.16$IoInitializeRemoveLockEx$201:int, $RemlockSize$5$22139.16$IoInitializeRemoveLockEx$201:int);
+
+//TAG: ensures __preserves_mem
+ensures(Mem == old(Mem));
+//TAG: ensures __preserves_resource("DEV_OBJ_INIT") && __preserves_resource("DEV_EXTN")
+ensures((Res_DEV_OBJ_INIT == old(Res_DEV_OBJ_INIT)) && (Res_DEV_EXTN == old(Res_DEV_EXTN)));
+
+modifies Res_DEVICE_STACK;
+
+//TAG: net change in resource DEVICE_STACK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEVICE_STACK[r]} (Empty()[r]) || old(Res_DEVICE_STACK)[r] == Res_DEVICE_STACK[r]));
+modifies Res_DEV_EXTN;
+
+//TAG: net change in resource DEV_EXTN only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_EXTN[r]} (Empty()[r]) || old(Res_DEV_EXTN)[r] == Res_DEV_EXTN[r]));
+modifies Res_DEV_OBJ_INIT;
+
+//TAG: net change in resource DEV_OBJ_INIT only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_OBJ_INIT[r]} (Empty()[r]) || old(Res_DEV_OBJ_INIT)[r] == Res_DEV_OBJ_INIT[r]));
+modifies Res_SPIN_LOCK;
+
+//TAG: net change in resource SPIN_LOCK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_SPIN_LOCK[r]} (Empty()[r]) || old(Res_SPIN_LOCK)[r] == Res_SPIN_LOCK[r]));
+//TAG: updated memory locations at Mem[T.MinorFunction__IO_STACK_LOCATION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.MinorFunction__IO_STACK_LOCATION][_m]} (Empty()[_m]) || Mem[T.MinorFunction__IO_STACK_LOCATION][_m] == old(Mem)[T.MinorFunction__IO_STACK_LOCATION][_m]));
+//TAG: updated memory locations at Mem[T.CurrentStackLocation___unnamed_4_a7aa989c] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.CurrentStackLocation___unnamed_4_a7aa989c][_m]} (Empty()[_m]) || Mem[T.CurrentStackLocation___unnamed_4_a7aa989c][_m] == old(Mem)[T.CurrentStackLocation___unnamed_4_a7aa989c][_m]));
+//TAG: updated memory locations at Mem[T.DeviceExtension__DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.DeviceExtension__DEVICE_OBJECT][_m] == old(Mem)[T.DeviceExtension__DEVICE_OBJECT][_m]));
+//TAG: updated memory locations at Mem[T.Self__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Self__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Self__DEVICE_EXTENSION][_m] == old(Mem)[T.Self__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.Started__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Started__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Started__DEVICE_EXTENSION][_m] == old(Mem)[T.Started__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.GrandMaster__GLOBALS] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.GrandMaster__GLOBALS][_m]} (Empty()[_m]) || Mem[T.GrandMaster__GLOBALS][_m] == old(Mem)[T.GrandMaster__GLOBALS][_m]));
+//TAG: updated memory locations at Mem[T.P_DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.P_DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.P_DEVICE_OBJECT][_m] == old(Mem)[T.P_DEVICE_OBJECT][_m]));
+
+//TAG: havoc memory locations by default
+modifies Mem;
+
+
+procedure KeInitializeSpinLock($SpinLock$1$13860.22$KeInitializeSpinLock$41:int);
+
+//TAG: ensures __preserves_mem
+ensures(Mem == old(Mem));
+//TAG: ensures __preserves_resource("DEV_OBJ_INIT") && __preserves_resource("DEV_EXTN")
+ensures((Res_DEV_OBJ_INIT == old(Res_DEV_OBJ_INIT)) && (Res_DEV_EXTN == old(Res_DEV_EXTN)));
+//TAG: ensures 1 ==> __resource("SPIN_LOCK", SpinLock) == 0
+ensures((true) ==> (Res_SPIN_LOCK[$SpinLock$1$13860.22$KeInitializeSpinLock$41] == 0));
+
+modifies Res_DEVICE_STACK;
+
+//TAG: net change in resource DEVICE_STACK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEVICE_STACK[r]} (Empty()[r]) || old(Res_DEVICE_STACK)[r] == Res_DEVICE_STACK[r]));
+modifies Res_DEV_EXTN;
+
+//TAG: net change in resource DEV_EXTN only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_EXTN[r]} (Empty()[r]) || old(Res_DEV_EXTN)[r] == Res_DEV_EXTN[r]));
+modifies Res_DEV_OBJ_INIT;
+
+//TAG: net change in resource DEV_OBJ_INIT only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_OBJ_INIT[r]} (Empty()[r]) || old(Res_DEV_OBJ_INIT)[r] == Res_DEV_OBJ_INIT[r]));
+modifies Res_SPIN_LOCK;
+
+//TAG: net change in resource SPIN_LOCK only for: __set_empty, SpinLock
+ensures (Subset(Empty(), Union(Union(Empty(), Empty()), Singleton($SpinLock$1$13860.22$KeInitializeSpinLock$41))) && (forall r:int :: {Res_SPIN_LOCK[r]} (Empty()[r]) || ($SpinLock$1$13860.22$KeInitializeSpinLock$41 == r) || old(Res_SPIN_LOCK)[r] == Res_SPIN_LOCK[r]));
+//TAG: updated memory locations at Mem[T.MinorFunction__IO_STACK_LOCATION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.MinorFunction__IO_STACK_LOCATION][_m]} (Empty()[_m]) || Mem[T.MinorFunction__IO_STACK_LOCATION][_m] == old(Mem)[T.MinorFunction__IO_STACK_LOCATION][_m]));
+//TAG: updated memory locations at Mem[T.CurrentStackLocation___unnamed_4_a7aa989c] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.CurrentStackLocation___unnamed_4_a7aa989c][_m]} (Empty()[_m]) || Mem[T.CurrentStackLocation___unnamed_4_a7aa989c][_m] == old(Mem)[T.CurrentStackLocation___unnamed_4_a7aa989c][_m]));
+//TAG: updated memory locations at Mem[T.DeviceExtension__DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.DeviceExtension__DEVICE_OBJECT][_m] == old(Mem)[T.DeviceExtension__DEVICE_OBJECT][_m]));
+//TAG: updated memory locations at Mem[T.Self__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Self__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Self__DEVICE_EXTENSION][_m] == old(Mem)[T.Self__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.Started__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Started__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Started__DEVICE_EXTENSION][_m] == old(Mem)[T.Started__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.GrandMaster__GLOBALS] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.GrandMaster__GLOBALS][_m]} (Empty()[_m]) || Mem[T.GrandMaster__GLOBALS][_m] == old(Mem)[T.GrandMaster__GLOBALS][_m]));
+//TAG: updated memory locations at Mem[T.P_DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.P_DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.P_DEVICE_OBJECT][_m] == old(Mem)[T.P_DEVICE_OBJECT][_m]));
+
+//TAG: havoc memory locations by default
+modifies Mem;
+
+
+procedure MouInitializeDataQueue($Context$1$518.13$MouInitializeDataQueue$41:int);
+
+//TAG: requires __resource("DEV_EXTN", Context) == 1
+requires(Res_DEV_EXTN[$Context$1$518.13$MouInitializeDataQueue$41] == 1);
+//TAG: requires __resource("SPIN_LOCK", &((struct _DEVICE_EXTENSION *)Context)->SpinLock) == 0
+requires(Res_SPIN_LOCK[SpinLock__DEVICE_EXTENSION($Context$1$518.13$MouInitializeDataQueue$41)] == 0);
+//TAG: requires __pforall(_H_x, (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension), __inv_resource("DEV_OBJ_INIT", 1), ((struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension))->Self == _H_x && __resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension)) == 1)
+requires((forall _H_x:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)]} Inverse(Res_DEV_OBJ_INIT,1)[_H_x] ==> ((Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)])] == _H_x) && (Res_DEV_EXTN[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)]] == 1))));
+//TAG: requires __pforall(_H_z, _H_z->Self, __inv_resource("DEV_EXTN", 1), __resource("DEV_OBJ_INIT", _H_z->Self) == 1 && (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)(_H_z->Self))->DeviceExtension) == _H_z)
+requires((forall _H_z:int :: {Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)]} Inverse(Res_DEV_EXTN,1)[_H_z] ==> ((Res_DEV_OBJ_INIT[Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)]] == 1) && (Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)])] == _H_z))));
+//TAG: requires 1 ==> (Globals.GrandMaster != (void *)0 ==> __resource("DEV_EXTN", Globals.GrandMaster) == 1)
+requires((true) ==> ((Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)] != 0) ==> (Res_DEV_EXTN[Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)]] == 1)));
+//TAG: requires 1 ==> __setin(&Globals.LegacyDeviceList, __btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList))
+requires((true) ==> (ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[LegacyDeviceList__GLOBALS(Globals)]));
+//TAG: requires 1 ==> __forall(_H_y, __btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList), _H_y == &Globals.LegacyDeviceList || __resource("DEV_EXTN", CONTAINING_RECORD(_H_y, struct _DEVICE_EXTENSION , Link)) == 1)
+requires((true) ==> ((Subset(Empty(), ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))) && (forall _H_y : int :: {ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[_H_y]} (ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[_H_y]) ==> ((_H_y == LegacyDeviceList__GLOBALS(Globals)) || (Res_DEV_EXTN[MINUS_LEFT_PTR(_H_y, 1, Link__DEVICE_EXTENSION(0))] == 1))))));
+//TAG: requires 1 ==> !__setin(&Globals.GrandMaster->Link, __setminus(__btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList), __set(&Globals.LegacyDeviceList)))
+requires((true) ==> (!(Difference(ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals)), Singleton(LegacyDeviceList__GLOBALS(Globals)))[Link__DEVICE_EXTENSION(Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)])])));
+//TAG: ensures __resource("DEV_EXTN", Context) == 1
+ensures(Res_DEV_EXTN[$Context$1$518.13$MouInitializeDataQueue$41] == 1);
+//TAG: ensures __resource("SPIN_LOCK", &((struct _DEVICE_EXTENSION *)Context)->SpinLock) == 0
+ensures(Res_SPIN_LOCK[SpinLock__DEVICE_EXTENSION($Context$1$518.13$MouInitializeDataQueue$41)] == 0);
+//TAG: ensures __pforall(_H_x, (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension), __inv_resource("DEV_OBJ_INIT", 1), ((struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension))->Self == _H_x && __resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension)) == 1)
+ensures((forall _H_x:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)]} Inverse(Res_DEV_OBJ_INIT,1)[_H_x] ==> ((Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)])] == _H_x) && (Res_DEV_EXTN[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)]] == 1))));
+//TAG: ensures __pforall(_H_z, _H_z->Self, __inv_resource("DEV_EXTN", 1), __resource("DEV_OBJ_INIT", _H_z->Self) == 1 && (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)(_H_z->Self))->DeviceExtension) == _H_z)
+ensures((forall _H_z:int :: {Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)]} Inverse(Res_DEV_EXTN,1)[_H_z] ==> ((Res_DEV_OBJ_INIT[Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)]] == 1) && (Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)])] == _H_z))));
+//TAG: ensures 1 ==> (Globals.GrandMaster != (void *)0 ==> __resource("DEV_EXTN", Globals.GrandMaster) == 1)
+ensures((true) ==> ((Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)] != 0) ==> (Res_DEV_EXTN[Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)]] == 1)));
+//TAG: ensures 1 ==> __setin(&Globals.LegacyDeviceList, __btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList))
+ensures((true) ==> (ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[LegacyDeviceList__GLOBALS(Globals)]));
+//TAG: ensures 1 ==> __forall(_H_y, __btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList), _H_y == &Globals.LegacyDeviceList || __resource("DEV_EXTN", CONTAINING_RECORD(_H_y, struct _DEVICE_EXTENSION , Link)) == 1)
+ensures((true) ==> ((Subset(Empty(), ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))) && (forall _H_y : int :: {ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[_H_y]} (ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[_H_y]) ==> ((_H_y == LegacyDeviceList__GLOBALS(Globals)) || (Res_DEV_EXTN[MINUS_LEFT_PTR(_H_y, 1, Link__DEVICE_EXTENSION(0))] == 1))))));
+//TAG: ensures 1 ==> !__setin(&Globals.GrandMaster->Link, __setminus(__btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList), __set(&Globals.LegacyDeviceList)))
+ensures((true) ==> (!(Difference(ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals)), Singleton(LegacyDeviceList__GLOBALS(Globals)))[Link__DEVICE_EXTENSION(Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)])])));
+//TAG: ensures __preserves_field_map(__offset((*((struct _LIST_ENTRY *)0)).Flink))
+ensures(Mem[T.Flink__LIST_ENTRY] == old(Mem)[T.Flink__LIST_ENTRY]);
+//TAG: ensures __preserves_resource("DEV_OBJ_INIT")
+ensures(Res_DEV_OBJ_INIT == old(Res_DEV_OBJ_INIT));
+//TAG: ensures __preserves_resource("DEV_EXTN")
+ensures(Res_DEV_EXTN == old(Res_DEV_EXTN));
+
+modifies Res_DEVICE_STACK;
+
+//TAG: net change in resource DEVICE_STACK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEVICE_STACK[r]} (Empty()[r]) || old(Res_DEVICE_STACK)[r] == Res_DEVICE_STACK[r]));
+modifies Res_DEV_EXTN;
+
+//TAG: net change in resource DEV_EXTN only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_EXTN[r]} (Empty()[r]) || old(Res_DEV_EXTN)[r] == Res_DEV_EXTN[r]));
+modifies Res_DEV_OBJ_INIT;
+
+//TAG: net change in resource DEV_OBJ_INIT only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_OBJ_INIT[r]} (Empty()[r]) || old(Res_DEV_OBJ_INIT)[r] == Res_DEV_OBJ_INIT[r]));
+modifies Res_SPIN_LOCK;
+
+//TAG: net change in resource SPIN_LOCK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_SPIN_LOCK[r]} (Empty()[r]) || old(Res_SPIN_LOCK)[r] == Res_SPIN_LOCK[r]));
+//TAG: updated memory locations at Mem[T.MinorFunction__IO_STACK_LOCATION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.MinorFunction__IO_STACK_LOCATION][_m]} (Empty()[_m]) || Mem[T.MinorFunction__IO_STACK_LOCATION][_m] == old(Mem)[T.MinorFunction__IO_STACK_LOCATION][_m]));
+//TAG: updated memory locations at Mem[T.CurrentStackLocation___unnamed_4_a7aa989c] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.CurrentStackLocation___unnamed_4_a7aa989c][_m]} (Empty()[_m]) || Mem[T.CurrentStackLocation___unnamed_4_a7aa989c][_m] == old(Mem)[T.CurrentStackLocation___unnamed_4_a7aa989c][_m]));
+//TAG: updated memory locations at Mem[T.DeviceExtension__DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.DeviceExtension__DEVICE_OBJECT][_m] == old(Mem)[T.DeviceExtension__DEVICE_OBJECT][_m]));
+//TAG: updated memory locations at Mem[T.Self__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Self__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Self__DEVICE_EXTENSION][_m] == old(Mem)[T.Self__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.Started__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Started__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Started__DEVICE_EXTENSION][_m] == old(Mem)[T.Started__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.GrandMaster__GLOBALS] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.GrandMaster__GLOBALS][_m]} (Empty()[_m]) || Mem[T.GrandMaster__GLOBALS][_m] == old(Mem)[T.GrandMaster__GLOBALS][_m]));
+//TAG: updated memory locations at Mem[T.P_DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.P_DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.P_DEVICE_OBJECT][_m] == old(Mem)[T.P_DEVICE_OBJECT][_m]));
+
+//TAG: havoc memory locations by default
+modifies Mem;
+
+
+procedure MouseClassLogError($Object$1$542.10$MouseClassLogError$281:int, $ErrorCode$2$543.10$MouseClassLogError$281:int, $UniqueErrorValue$3$544.10$MouseClassLogError$281:int, $FinalStatus$4$545.13$MouseClassLogError$281:int, $DumpCount$5$546.10$MouseClassLogError$281:int, $DumpData$6$547.11$MouseClassLogError$281:int, $MajorFunction$7$548.10$MouseClassLogError$281:int);
+
+//TAG: requires __pforall(_H_x, (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension), __inv_resource("DEV_OBJ_INIT", 1), ((struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension))->Self == _H_x && __resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension)) == 1)
+requires((forall _H_x:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)]} Inverse(Res_DEV_OBJ_INIT,1)[_H_x] ==> ((Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)])] == _H_x) && (Res_DEV_EXTN[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)]] == 1))));
+//TAG: requires __pforall(_H_z, _H_z->Self, __inv_resource("DEV_EXTN", 1), __resource("DEV_OBJ_INIT", _H_z->Self) == 1 && (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)(_H_z->Self))->DeviceExtension) == _H_z)
+requires((forall _H_z:int :: {Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)]} Inverse(Res_DEV_EXTN,1)[_H_z] ==> ((Res_DEV_OBJ_INIT[Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)]] == 1) && (Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)])] == _H_z))));
+//TAG: requires 1 ==> (Globals.GrandMaster != (void *)0 ==> __resource("DEV_EXTN", Globals.GrandMaster) == 1)
+requires((true) ==> ((Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)] != 0) ==> (Res_DEV_EXTN[Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)]] == 1)));
+//TAG: requires 1 ==> __setin(&Globals.LegacyDeviceList, __btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList))
+requires((true) ==> (ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[LegacyDeviceList__GLOBALS(Globals)]));
+//TAG: requires 1 ==> __forall(_H_y, __btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList), _H_y == &Globals.LegacyDeviceList || __resource("DEV_EXTN", CONTAINING_RECORD(_H_y, struct _DEVICE_EXTENSION , Link)) == 1)
+requires((true) ==> ((Subset(Empty(), ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))) && (forall _H_y : int :: {ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[_H_y]} (ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[_H_y]) ==> ((_H_y == LegacyDeviceList__GLOBALS(Globals)) || (Res_DEV_EXTN[MINUS_LEFT_PTR(_H_y, 1, Link__DEVICE_EXTENSION(0))] == 1))))));
+//TAG: requires 1 ==> !__setin(&Globals.GrandMaster->Link, __setminus(__btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList), __set(&Globals.LegacyDeviceList)))
+requires((true) ==> (!(Difference(ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals)), Singleton(LegacyDeviceList__GLOBALS(Globals)))[Link__DEVICE_EXTENSION(Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)])])));
+//TAG: ensures __pforall(_H_x, (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension), __inv_resource("DEV_OBJ_INIT", 1), ((struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension))->Self == _H_x && __resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension)) == 1)
+ensures((forall _H_x:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)]} Inverse(Res_DEV_OBJ_INIT,1)[_H_x] ==> ((Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)])] == _H_x) && (Res_DEV_EXTN[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)]] == 1))));
+//TAG: ensures __pforall(_H_z, _H_z->Self, __inv_resource("DEV_EXTN", 1), __resource("DEV_OBJ_INIT", _H_z->Self) == 1 && (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)(_H_z->Self))->DeviceExtension) == _H_z)
+ensures((forall _H_z:int :: {Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)]} Inverse(Res_DEV_EXTN,1)[_H_z] ==> ((Res_DEV_OBJ_INIT[Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)]] == 1) && (Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)])] == _H_z))));
+//TAG: ensures 1 ==> (Globals.GrandMaster != (void *)0 ==> __resource("DEV_EXTN", Globals.GrandMaster) == 1)
+ensures((true) ==> ((Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)] != 0) ==> (Res_DEV_EXTN[Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)]] == 1)));
+//TAG: ensures 1 ==> __setin(&Globals.LegacyDeviceList, __btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList))
+ensures((true) ==> (ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[LegacyDeviceList__GLOBALS(Globals)]));
+//TAG: ensures 1 ==> __forall(_H_y, __btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList), _H_y == &Globals.LegacyDeviceList || __resource("DEV_EXTN", CONTAINING_RECORD(_H_y, struct _DEVICE_EXTENSION , Link)) == 1)
+ensures((true) ==> ((Subset(Empty(), ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))) && (forall _H_y : int :: {ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[_H_y]} (ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[_H_y]) ==> ((_H_y == LegacyDeviceList__GLOBALS(Globals)) || (Res_DEV_EXTN[MINUS_LEFT_PTR(_H_y, 1, Link__DEVICE_EXTENSION(0))] == 1))))));
+//TAG: ensures 1 ==> !__setin(&Globals.GrandMaster->Link, __setminus(__btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList), __set(&Globals.LegacyDeviceList)))
+ensures((true) ==> (!(Difference(ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals)), Singleton(LegacyDeviceList__GLOBALS(Globals)))[Link__DEVICE_EXTENSION(Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)])])));
+//TAG: ensures __preserves_field_map(__offset((*((struct _LIST_ENTRY *)0)).Flink))
+ensures(Mem[T.Flink__LIST_ENTRY] == old(Mem)[T.Flink__LIST_ENTRY]);
+//TAG: ensures __preserves_resource("DEV_OBJ_INIT")
+ensures(Res_DEV_OBJ_INIT == old(Res_DEV_OBJ_INIT));
+//TAG: ensures __preserves_resource("DEV_EXTN")
+ensures(Res_DEV_EXTN == old(Res_DEV_EXTN));
+
+modifies Res_DEVICE_STACK;
+
+//TAG: net change in resource DEVICE_STACK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEVICE_STACK[r]} (Empty()[r]) || old(Res_DEVICE_STACK)[r] == Res_DEVICE_STACK[r]));
+modifies Res_DEV_EXTN;
+
+//TAG: net change in resource DEV_EXTN only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_EXTN[r]} (Empty()[r]) || old(Res_DEV_EXTN)[r] == Res_DEV_EXTN[r]));
+modifies Res_DEV_OBJ_INIT;
+
+//TAG: net change in resource DEV_OBJ_INIT only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_OBJ_INIT[r]} (Empty()[r]) || old(Res_DEV_OBJ_INIT)[r] == Res_DEV_OBJ_INIT[r]));
+modifies Res_SPIN_LOCK;
+
+//TAG: net change in resource SPIN_LOCK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_SPIN_LOCK[r]} (Empty()[r]) || old(Res_SPIN_LOCK)[r] == Res_SPIN_LOCK[r]));
+//TAG: updated memory locations at Mem[T.MinorFunction__IO_STACK_LOCATION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.MinorFunction__IO_STACK_LOCATION][_m]} (Empty()[_m]) || Mem[T.MinorFunction__IO_STACK_LOCATION][_m] == old(Mem)[T.MinorFunction__IO_STACK_LOCATION][_m]));
+//TAG: updated memory locations at Mem[T.CurrentStackLocation___unnamed_4_a7aa989c] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.CurrentStackLocation___unnamed_4_a7aa989c][_m]} (Empty()[_m]) || Mem[T.CurrentStackLocation___unnamed_4_a7aa989c][_m] == old(Mem)[T.CurrentStackLocation___unnamed_4_a7aa989c][_m]));
+//TAG: updated memory locations at Mem[T.DeviceExtension__DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.DeviceExtension__DEVICE_OBJECT][_m] == old(Mem)[T.DeviceExtension__DEVICE_OBJECT][_m]));
+//TAG: updated memory locations at Mem[T.Self__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Self__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Self__DEVICE_EXTENSION][_m] == old(Mem)[T.Self__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.Started__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Started__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Started__DEVICE_EXTENSION][_m] == old(Mem)[T.Started__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.GrandMaster__GLOBALS] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.GrandMaster__GLOBALS][_m]} (Empty()[_m]) || Mem[T.GrandMaster__GLOBALS][_m] == old(Mem)[T.GrandMaster__GLOBALS][_m]));
+//TAG: updated memory locations at Mem[T.P_DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.P_DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.P_DEVICE_OBJECT][_m] == old(Mem)[T.P_DEVICE_OBJECT][_m]));
+
+//TAG: havoc memory locations by default
+modifies Mem;
+
+
+procedure RtlAppendUnicodeToString($Destination$1$7421.28$RtlAppendUnicodeToString$81:int, $Source$2$7422.20$RtlAppendUnicodeToString$81:int) returns ($result.RtlAppendUnicodeToString$7420.0$1$:int);
+
+//TAG: ensures __preserves_mem
+ensures(Mem == old(Mem));
+//TAG: ensures __preserves_resource("DEV_OBJ_INIT") && __preserves_resource("DEV_EXTN")
+ensures((Res_DEV_OBJ_INIT == old(Res_DEV_OBJ_INIT)) && (Res_DEV_EXTN == old(Res_DEV_EXTN)));
+
+modifies Res_DEVICE_STACK;
+
+//TAG: net change in resource DEVICE_STACK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEVICE_STACK[r]} (Empty()[r]) || old(Res_DEVICE_STACK)[r] == Res_DEVICE_STACK[r]));
+modifies Res_DEV_EXTN;
+
+//TAG: net change in resource DEV_EXTN only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_EXTN[r]} (Empty()[r]) || old(Res_DEV_EXTN)[r] == Res_DEV_EXTN[r]));
+modifies Res_DEV_OBJ_INIT;
+
+//TAG: net change in resource DEV_OBJ_INIT only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_OBJ_INIT[r]} (Empty()[r]) || old(Res_DEV_OBJ_INIT)[r] == Res_DEV_OBJ_INIT[r]));
+modifies Res_SPIN_LOCK;
+
+//TAG: net change in resource SPIN_LOCK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_SPIN_LOCK[r]} (Empty()[r]) || old(Res_SPIN_LOCK)[r] == Res_SPIN_LOCK[r]));
+//TAG: updated memory locations at Mem[T.MinorFunction__IO_STACK_LOCATION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.MinorFunction__IO_STACK_LOCATION][_m]} (Empty()[_m]) || Mem[T.MinorFunction__IO_STACK_LOCATION][_m] == old(Mem)[T.MinorFunction__IO_STACK_LOCATION][_m]));
+//TAG: updated memory locations at Mem[T.CurrentStackLocation___unnamed_4_a7aa989c] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.CurrentStackLocation___unnamed_4_a7aa989c][_m]} (Empty()[_m]) || Mem[T.CurrentStackLocation___unnamed_4_a7aa989c][_m] == old(Mem)[T.CurrentStackLocation___unnamed_4_a7aa989c][_m]));
+//TAG: updated memory locations at Mem[T.DeviceExtension__DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.DeviceExtension__DEVICE_OBJECT][_m] == old(Mem)[T.DeviceExtension__DEVICE_OBJECT][_m]));
+//TAG: updated memory locations at Mem[T.Self__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Self__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Self__DEVICE_EXTENSION][_m] == old(Mem)[T.Self__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.Started__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Started__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Started__DEVICE_EXTENSION][_m] == old(Mem)[T.Started__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.GrandMaster__GLOBALS] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.GrandMaster__GLOBALS][_m]} (Empty()[_m]) || Mem[T.GrandMaster__GLOBALS][_m] == old(Mem)[T.GrandMaster__GLOBALS][_m]));
+//TAG: updated memory locations at Mem[T.P_DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.P_DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.P_DEVICE_OBJECT][_m] == old(Mem)[T.P_DEVICE_OBJECT][_m]));
+
+//TAG: havoc memory locations by default
+modifies Mem;
+
+
+procedure RtlFreeUnicodeString($UnicodeString$1$7452.28$RtlFreeUnicodeString$41:int);
+
+//TAG: ensures __preserves_mem
+ensures(Mem == old(Mem));
+//TAG: ensures __preserves_resource("DEV_OBJ_INIT") && __preserves_resource("DEV_EXTN")
+ensures((Res_DEV_OBJ_INIT == old(Res_DEV_OBJ_INIT)) && (Res_DEV_EXTN == old(Res_DEV_EXTN)));
+
+modifies Res_DEVICE_STACK;
+
+//TAG: net change in resource DEVICE_STACK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEVICE_STACK[r]} (Empty()[r]) || old(Res_DEVICE_STACK)[r] == Res_DEVICE_STACK[r]));
+modifies Res_DEV_EXTN;
+
+//TAG: net change in resource DEV_EXTN only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_EXTN[r]} (Empty()[r]) || old(Res_DEV_EXTN)[r] == Res_DEV_EXTN[r]));
+modifies Res_DEV_OBJ_INIT;
+
+//TAG: net change in resource DEV_OBJ_INIT only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_OBJ_INIT[r]} (Empty()[r]) || old(Res_DEV_OBJ_INIT)[r] == Res_DEV_OBJ_INIT[r]));
+modifies Res_SPIN_LOCK;
+
+//TAG: net change in resource SPIN_LOCK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_SPIN_LOCK[r]} (Empty()[r]) || old(Res_SPIN_LOCK)[r] == Res_SPIN_LOCK[r]));
+//TAG: updated memory locations at Mem[T.MinorFunction__IO_STACK_LOCATION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.MinorFunction__IO_STACK_LOCATION][_m]} (Empty()[_m]) || Mem[T.MinorFunction__IO_STACK_LOCATION][_m] == old(Mem)[T.MinorFunction__IO_STACK_LOCATION][_m]));
+//TAG: updated memory locations at Mem[T.CurrentStackLocation___unnamed_4_a7aa989c] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.CurrentStackLocation___unnamed_4_a7aa989c][_m]} (Empty()[_m]) || Mem[T.CurrentStackLocation___unnamed_4_a7aa989c][_m] == old(Mem)[T.CurrentStackLocation___unnamed_4_a7aa989c][_m]));
+//TAG: updated memory locations at Mem[T.DeviceExtension__DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.DeviceExtension__DEVICE_OBJECT][_m] == old(Mem)[T.DeviceExtension__DEVICE_OBJECT][_m]));
+//TAG: updated memory locations at Mem[T.Self__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Self__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Self__DEVICE_EXTENSION][_m] == old(Mem)[T.Self__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.Started__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Started__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Started__DEVICE_EXTENSION][_m] == old(Mem)[T.Started__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.GrandMaster__GLOBALS] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.GrandMaster__GLOBALS][_m]} (Empty()[_m]) || Mem[T.GrandMaster__GLOBALS][_m] == old(Mem)[T.GrandMaster__GLOBALS][_m]));
+//TAG: updated memory locations at Mem[T.P_DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.P_DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.P_DEVICE_OBJECT][_m] == old(Mem)[T.P_DEVICE_OBJECT][_m]));
+
+//TAG: havoc memory locations by default
+modifies Mem;
+
+
+procedure __PREfastPagedCode();
+
+//TAG: ensures __preserves_mem
+ensures(Mem == old(Mem));
+//TAG: ensures __preserves_resource("DEV_OBJ_INIT") && __preserves_resource("DEV_EXTN")
+ensures((Res_DEV_OBJ_INIT == old(Res_DEV_OBJ_INIT)) && (Res_DEV_EXTN == old(Res_DEV_EXTN)));
+
+modifies Res_DEVICE_STACK;
+
+//TAG: net change in resource DEVICE_STACK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEVICE_STACK[r]} (Empty()[r]) || old(Res_DEVICE_STACK)[r] == Res_DEVICE_STACK[r]));
+modifies Res_DEV_EXTN;
+
+//TAG: net change in resource DEV_EXTN only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_EXTN[r]} (Empty()[r]) || old(Res_DEV_EXTN)[r] == Res_DEV_EXTN[r]));
+modifies Res_DEV_OBJ_INIT;
+
+//TAG: net change in resource DEV_OBJ_INIT only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_OBJ_INIT[r]} (Empty()[r]) || old(Res_DEV_OBJ_INIT)[r] == Res_DEV_OBJ_INIT[r]));
+modifies Res_SPIN_LOCK;
+
+//TAG: net change in resource SPIN_LOCK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_SPIN_LOCK[r]} (Empty()[r]) || old(Res_SPIN_LOCK)[r] == Res_SPIN_LOCK[r]));
+//TAG: updated memory locations at Mem[T.MinorFunction__IO_STACK_LOCATION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.MinorFunction__IO_STACK_LOCATION][_m]} (Empty()[_m]) || Mem[T.MinorFunction__IO_STACK_LOCATION][_m] == old(Mem)[T.MinorFunction__IO_STACK_LOCATION][_m]));
+//TAG: updated memory locations at Mem[T.CurrentStackLocation___unnamed_4_a7aa989c] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.CurrentStackLocation___unnamed_4_a7aa989c][_m]} (Empty()[_m]) || Mem[T.CurrentStackLocation___unnamed_4_a7aa989c][_m] == old(Mem)[T.CurrentStackLocation___unnamed_4_a7aa989c][_m]));
+//TAG: updated memory locations at Mem[T.DeviceExtension__DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.DeviceExtension__DEVICE_OBJECT][_m] == old(Mem)[T.DeviceExtension__DEVICE_OBJECT][_m]));
+//TAG: updated memory locations at Mem[T.Self__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Self__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Self__DEVICE_EXTENSION][_m] == old(Mem)[T.Self__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.Started__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Started__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Started__DEVICE_EXTENSION][_m] == old(Mem)[T.Started__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.GrandMaster__GLOBALS] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.GrandMaster__GLOBALS][_m]} (Empty()[_m]) || Mem[T.GrandMaster__GLOBALS][_m] == old(Mem)[T.GrandMaster__GLOBALS][_m]));
+//TAG: updated memory locations at Mem[T.P_DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.P_DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.P_DEVICE_OBJECT][_m] == old(Mem)[T.P_DEVICE_OBJECT][_m]));
+
+//TAG: havoc memory locations by default
+modifies Mem;
+
+
+procedure MouCreateClassObject($DriverObject$1$3165.28$MouCreateClassObject$201:int, $TmpDeviceExtension$2$3166.28$MouCreateClassObject$201:int, $ClassDeviceObject$3$3167.28$MouCreateClassObject$201:int, $FullDeviceName$4$3168.35$MouCreateClassObject$201:int, $Legacy$5$3169.28$MouCreateClassObject$201:int) returns ($result.MouCreateClassObject$3164.0$1$:int)
+
+//TAG: requires __pforall(_H_x, (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension), __inv_resource("DEV_OBJ_INIT", 1), ((struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension))->Self == _H_x && __resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension)) == 1)
+requires((forall _H_x:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)]} Inverse(Res_DEV_OBJ_INIT,1)[_H_x] ==> ((Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)])] == _H_x) && (Res_DEV_EXTN[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)]] == 1))));
+//TAG: requires __pforall(_H_z, _H_z->Self, __inv_resource("DEV_EXTN", 1), __resource("DEV_OBJ_INIT", _H_z->Self) == 1 && (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)(_H_z->Self))->DeviceExtension) == _H_z)
+requires((forall _H_z:int :: {Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)]} Inverse(Res_DEV_EXTN,1)[_H_z] ==> ((Res_DEV_OBJ_INIT[Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)]] == 1) && (Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)])] == _H_z))));
+//TAG: requires __forall(_H_z, __inv_resource("DEV_EXTN", 1), __resource("SPIN_LOCK", &_H_z->SpinLock) == 0 && __resource("SPIN_LOCK", &_H_z->WaitWakeSpinLock) == 0)
+requires((Subset(Empty(), Inverse(Res_DEV_EXTN,1)) && (forall _H_z : int :: {Inverse(Res_DEV_EXTN,1)[_H_z]} (Inverse(Res_DEV_EXTN,1)[_H_z]) ==> ((Res_SPIN_LOCK[SpinLock__DEVICE_EXTENSION(_H_z)] == 0) && (Res_SPIN_LOCK[WaitWakeSpinLock__DEVICE_EXTENSION(_H_z)] == 0)))));
+//TAG: requires 1 ==> (Globals.GrandMaster != (void *)0 ==> __resource("DEV_EXTN", Globals.GrandMaster) == 1)
+requires((true) ==> ((Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)] != 0) ==> (Res_DEV_EXTN[Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)]] == 1)));
+//TAG: requires 1 ==> __setin(&Globals.LegacyDeviceList, __btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList))
+requires((true) ==> (ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[LegacyDeviceList__GLOBALS(Globals)]));
+//TAG: requires 1 ==> __forall(_H_y, __btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList), _H_y == &Globals.LegacyDeviceList || __resource("DEV_EXTN", CONTAINING_RECORD(_H_y, struct _DEVICE_EXTENSION , Link)) == 1)
+requires((true) ==> ((Subset(Empty(), ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))) && (forall _H_y : int :: {ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[_H_y]} (ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[_H_y]) ==> ((_H_y == LegacyDeviceList__GLOBALS(Globals)) || (Res_DEV_EXTN[MINUS_LEFT_PTR(_H_y, 1, Link__DEVICE_EXTENSION(0))] == 1))))));
+//TAG: requires 1 ==> !__setin(&Globals.GrandMaster->Link, __setminus(__btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList), __set(&Globals.LegacyDeviceList)))
+requires((true) ==> (!(Difference(ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals)), Singleton(LegacyDeviceList__GLOBALS(Globals)))[Link__DEVICE_EXTENSION(Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)])])));
+//TAG: ensures __pforall(_H_x, (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension), __inv_resource("DEV_OBJ_INIT", 1), ((struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension))->Self == _H_x && __resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension)) == 1)
+ensures((forall _H_x:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)]} Inverse(Res_DEV_OBJ_INIT,1)[_H_x] ==> ((Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)])] == _H_x) && (Res_DEV_EXTN[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)]] == 1))));
+//TAG: ensures __pforall(_H_z, _H_z->Self, __inv_resource("DEV_EXTN", 1), __resource("DEV_OBJ_INIT", _H_z->Self) == 1 && (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)(_H_z->Self))->DeviceExtension) == _H_z)
+ensures((forall _H_z:int :: {Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)]} Inverse(Res_DEV_EXTN,1)[_H_z] ==> ((Res_DEV_OBJ_INIT[Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)]] == 1) && (Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)])] == _H_z))));
+//TAG: ensures 1 ==> (Globals.GrandMaster != (void *)0 ==> __resource("DEV_EXTN", Globals.GrandMaster) == 1)
+ensures((true) ==> ((Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)] != 0) ==> (Res_DEV_EXTN[Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)]] == 1)));
+//TAG: ensures 1 ==> __setin(&Globals.LegacyDeviceList, __btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList))
+ensures((true) ==> (ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[LegacyDeviceList__GLOBALS(Globals)]));
+//TAG: ensures 1 ==> __forall(_H_y, __btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList), _H_y == &Globals.LegacyDeviceList || __resource("DEV_EXTN", CONTAINING_RECORD(_H_y, struct _DEVICE_EXTENSION , Link)) == 1)
+ensures((true) ==> ((Subset(Empty(), ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))) && (forall _H_y : int :: {ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[_H_y]} (ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[_H_y]) ==> ((_H_y == LegacyDeviceList__GLOBALS(Globals)) || (Res_DEV_EXTN[MINUS_LEFT_PTR(_H_y, 1, Link__DEVICE_EXTENSION(0))] == 1))))));
+//TAG: ensures 1 ==> !__setin(&Globals.GrandMaster->Link, __setminus(__btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList), __set(&Globals.LegacyDeviceList)))
+ensures((true) ==> (!(Difference(ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals)), Singleton(LegacyDeviceList__GLOBALS(Globals)))[Link__DEVICE_EXTENSION(Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)])])));
+//TAG: ensures __preserves_field_map(__offset((*((struct _LIST_ENTRY *)0)).Flink))
+ensures(Mem[T.Flink__LIST_ENTRY] == old(Mem)[T.Flink__LIST_ENTRY]);
+//TAG: ensures (LONG)__return >= 0 ==> *ClassDeviceObject != (void *)0
+ensures(($result.MouCreateClassObject$3164.0$1$ >= 0) ==> (Mem[T.P_DEVICE_OBJECT][$ClassDeviceObject$3$3167.28$MouCreateClassObject$201] != 0));
+//TAG: ensures (LONG)__return >= 0 ==> (*ClassDeviceObject)->DeviceExtension != (void *)0
+ensures(($result.MouCreateClassObject$3164.0$1$ >= 0) ==> (Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.P_DEVICE_OBJECT][$ClassDeviceObject$3$3167.28$MouCreateClassObject$201])] != 0));
+//TAG: ensures (LONG)__return >= 0 ==> __resource("DEV_EXTN", (*ClassDeviceObject)->DeviceExtension) == 1
+ensures(($result.MouCreateClassObject$3164.0$1$ >= 0) ==> (Res_DEV_EXTN[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.P_DEVICE_OBJECT][$ClassDeviceObject$3$3167.28$MouCreateClassObject$201])]] == 1));
+//TAG: ensures (LONG)__return >= 0 ==> __resource("DEV_OBJ_INIT", *ClassDeviceObject) == 1 && __resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)(*ClassDeviceObject))->DeviceExtension)) == 1
+ensures(($result.MouCreateClassObject$3164.0$1$ >= 0) ==> ((Res_DEV_OBJ_INIT[Mem[T.P_DEVICE_OBJECT][$ClassDeviceObject$3$3167.28$MouCreateClassObject$201]] == 1) && (Res_DEV_EXTN[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.P_DEVICE_OBJECT][$ClassDeviceObject$3$3167.28$MouCreateClassObject$201])]] == 1)));
+//TAG: ensures (LONG)__return >= 0 ==> __old_resource("DEV_OBJ_INIT", *ClassDeviceObject) == 0 && __old_resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)(*ClassDeviceObject))->DeviceExtension)) == 0
+ensures(($result.MouCreateClassObject$3164.0$1$ >= 0) ==> ((old(Res_DEV_OBJ_INIT)[Mem[T.P_DEVICE_OBJECT][$ClassDeviceObject$3$3167.28$MouCreateClassObject$201]] == 0) && (old(Res_DEV_EXTN)[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.P_DEVICE_OBJECT][$ClassDeviceObject$3$3167.28$MouCreateClassObject$201])]] == 0)));
+//TAG: ensures (LONG)__return >= 0 ==> __updates_resource("DEV_OBJ_INIT", *ClassDeviceObject, 1) && __updates_resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)(*ClassDeviceObject))->DeviceExtension), 1)
+ensures(($result.MouCreateClassObject$3164.0$1$ >= 0) ==> ((Res_DEV_OBJ_INIT == old(Res_DEV_OBJ_INIT)[Mem[T.P_DEVICE_OBJECT][$ClassDeviceObject$3$3167.28$MouCreateClassObject$201] := 1]) && (Res_DEV_EXTN == old(Res_DEV_EXTN)[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.P_DEVICE_OBJECT][$ClassDeviceObject$3$3167.28$MouCreateClassObject$201])] := 1])));
+//TAG: ensures !((LONG)__return >= 0) ==> __resource("DEV_OBJ_INIT", *ClassDeviceObject) == __old_resource("DEV_OBJ_INIT", *ClassDeviceObject) && __resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)(*ClassDeviceObject))->DeviceExtension)) == __old_resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)(*ClassDeviceObject))->DeviceExtension))
+ensures((!($result.MouCreateClassObject$3164.0$1$ >= 0)) ==> ((Res_DEV_OBJ_INIT[Mem[T.P_DEVICE_OBJECT][$ClassDeviceObject$3$3167.28$MouCreateClassObject$201]] == old(Res_DEV_OBJ_INIT)[Mem[T.P_DEVICE_OBJECT][$ClassDeviceObject$3$3167.28$MouCreateClassObject$201]]) && (Res_DEV_EXTN[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.P_DEVICE_OBJECT][$ClassDeviceObject$3$3167.28$MouCreateClassObject$201])]] == old(Res_DEV_EXTN)[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.P_DEVICE_OBJECT][$ClassDeviceObject$3$3167.28$MouCreateClassObject$201])]])));
+//TAG: ensures !((LONG)__return >= 0) ==> __preserves_resource("DEV_OBJ_INIT") && __preserves_resource("DEV_EXTN")
+free ensures((!($result.MouCreateClassObject$3164.0$1$ >= 0)) ==> ((Res_DEV_OBJ_INIT == old(Res_DEV_OBJ_INIT)) && (Res_DEV_EXTN == old(Res_DEV_EXTN))));
+//TAG: ensures __forall(_H_z, __inv_resource("DEV_EXTN", 1), __setin(_H_z, __set((struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)(*ClassDeviceObject))->DeviceExtension))) || __resource("SPIN_LOCK", &_H_z->SpinLock) == 0 && __resource("SPIN_LOCK", &_H_z->WaitWakeSpinLock) == 0)
+ensures((Subset(Empty(), Inverse(Res_DEV_EXTN,1)) && (forall _H_z : int :: {Inverse(Res_DEV_EXTN,1)[_H_z]} (Inverse(Res_DEV_EXTN,1)[_H_z]) ==> ((Singleton(Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.P_DEVICE_OBJECT][$ClassDeviceObject$3$3167.28$MouCreateClassObject$201])])[_H_z]) || ((Res_SPIN_LOCK[SpinLock__DEVICE_EXTENSION(_H_z)] == 0) && (Res_SPIN_LOCK[WaitWakeSpinLock__DEVICE_EXTENSION(_H_z)] == 0))))));
+//TAG: ensures !((LONG)__return >= 0) ==> __forall(_H_z, __inv_resource("DEV_EXTN", 1), __resource("SPIN_LOCK", &_H_z->SpinLock) == 0 && __resource("SPIN_LOCK", &_H_z->WaitWakeSpinLock) == 0)
+ensures((!($result.MouCreateClassObject$3164.0$1$ >= 0)) ==> ((Subset(Empty(), Inverse(Res_DEV_EXTN,1)) && (forall _H_z : int :: {Inverse(Res_DEV_EXTN,1)[_H_z]} (Inverse(Res_DEV_EXTN,1)[_H_z]) ==> ((Res_SPIN_LOCK[SpinLock__DEVICE_EXTENSION(_H_z)] == 0) && (Res_SPIN_LOCK[WaitWakeSpinLock__DEVICE_EXTENSION(_H_z)] == 0))))));
+//TAG: ensures (LONG)__return >= 0 ==> __resource("SPIN_LOCK", &((struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)(*ClassDeviceObject))->DeviceExtension))->SpinLock) == 0
+ensures(($result.MouCreateClassObject$3164.0$1$ >= 0) ==> (Res_SPIN_LOCK[SpinLock__DEVICE_EXTENSION(Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.P_DEVICE_OBJECT][$ClassDeviceObject$3$3167.28$MouCreateClassObject$201])])] == 0));
+modifies alloc;
+free ensures(forall f:int :: {alloc[Base(f)]} old(alloc)[Base(f)] == UNALLOCATED || old(alloc)[Base(f)] == alloc[Base(f)]);
+
+modifies Res_DEVICE_STACK;
+
+//TAG: net change in resource DEVICE_STACK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEVICE_STACK[r]} (Empty()[r]) || old(Res_DEVICE_STACK)[r] == Res_DEVICE_STACK[r]));
+modifies Res_DEV_EXTN;
+
+//TAG: net change in resource DEV_EXTN only for: __set_empty, (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)(*ClassDeviceObject))->DeviceExtension)
+ensures (Subset(Empty(), Union(Union(Empty(), Empty()), Singleton(Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.P_DEVICE_OBJECT][$ClassDeviceObject$3$3167.28$MouCreateClassObject$201])]))) && (forall r:int :: {Res_DEV_EXTN[r]} (Empty()[r]) || (Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.P_DEVICE_OBJECT][$ClassDeviceObject$3$3167.28$MouCreateClassObject$201])] == r) || old(Res_DEV_EXTN)[r] == Res_DEV_EXTN[r]));
+modifies Res_DEV_OBJ_INIT;
+
+//TAG: net change in resource DEV_OBJ_INIT only for: __set_empty, *ClassDeviceObject
+ensures (Subset(Empty(), Union(Union(Empty(), Empty()), Singleton(Mem[T.P_DEVICE_OBJECT][$ClassDeviceObject$3$3167.28$MouCreateClassObject$201]))) && (forall r:int :: {Res_DEV_OBJ_INIT[r]} (Empty()[r]) || (Mem[T.P_DEVICE_OBJECT][$ClassDeviceObject$3$3167.28$MouCreateClassObject$201] == r) || old(Res_DEV_OBJ_INIT)[r] == Res_DEV_OBJ_INIT[r]));
+modifies Res_SPIN_LOCK;
+
+//TAG: net change in resource SPIN_LOCK only for: &TmpDeviceExtension->WaitWakeSpinLock, &((struct _DEVICE_EXTENSION *)TmpDeviceExtension)->SpinLock, __set_true
+ensures (Subset(Empty(), Union(Union(Union(Empty(), Singleton(WaitWakeSpinLock__DEVICE_EXTENSION($TmpDeviceExtension$2$3166.28$MouCreateClassObject$201))), Singleton(SpinLock__DEVICE_EXTENSION($TmpDeviceExtension$2$3166.28$MouCreateClassObject$201))), SetTrue())) && (forall r:int :: {Res_SPIN_LOCK[r]} (WaitWakeSpinLock__DEVICE_EXTENSION($TmpDeviceExtension$2$3166.28$MouCreateClassObject$201) == r) || (SpinLock__DEVICE_EXTENSION($TmpDeviceExtension$2$3166.28$MouCreateClassObject$201) == r) || (SetTrue()[r]) || old(Res_SPIN_LOCK)[r] == Res_SPIN_LOCK[r]));
+//TAG: updated memory locations at Mem[T.MinorFunction__IO_STACK_LOCATION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.MinorFunction__IO_STACK_LOCATION][_m]} (Empty()[_m]) || Mem[T.MinorFunction__IO_STACK_LOCATION][_m] == old(Mem)[T.MinorFunction__IO_STACK_LOCATION][_m]));
+//TAG: updated memory locations at Mem[T.CurrentStackLocation___unnamed_4_a7aa989c] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.CurrentStackLocation___unnamed_4_a7aa989c][_m]} (Empty()[_m]) || Mem[T.CurrentStackLocation___unnamed_4_a7aa989c][_m] == old(Mem)[T.CurrentStackLocation___unnamed_4_a7aa989c][_m]));
+//TAG: updated memory locations at Mem[T.DeviceExtension__DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.DeviceExtension__DEVICE_OBJECT][_m] == old(Mem)[T.DeviceExtension__DEVICE_OBJECT][_m]));
+//TAG: updated memory locations at Mem[T.Self__DEVICE_EXTENSION] only for: __set_true
+ensures (Subset(Empty(), Union(Empty(), SetTrue())) && (forall _m:int :: {Mem[T.Self__DEVICE_EXTENSION][_m]} (SetTrue()[_m]) || Mem[T.Self__DEVICE_EXTENSION][_m] == old(Mem)[T.Self__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.Started__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Started__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Started__DEVICE_EXTENSION][_m] == old(Mem)[T.Started__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.GrandMaster__GLOBALS] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.GrandMaster__GLOBALS][_m]} (Empty()[_m]) || Mem[T.GrandMaster__GLOBALS][_m] == old(Mem)[T.GrandMaster__GLOBALS][_m]));
+//TAG: updated memory locations at Mem[T.P_DEVICE_OBJECT] only for: __set_empty, ClassDeviceObject
+ensures (Subset(Empty(), Union(Union(Empty(), Empty()), Singleton($ClassDeviceObject$3$3167.28$MouCreateClassObject$201))) && (forall _m:int :: {Mem[T.P_DEVICE_OBJECT][_m]} (Empty()[_m]) || (_m == $ClassDeviceObject$3$3167.28$MouCreateClassObject$201) || Mem[T.P_DEVICE_OBJECT][_m] == old(Mem)[T.P_DEVICE_OBJECT][_m]));
+
+//TAG: havoc memory locations by default
+modifies Mem;
+{
+var havoc_stringTemp:int;
+var condVal:int;
+var $ClassDeviceObject$3$3167.28$MouCreateClassObject$20 : int;
+var $DriverObject$1$3165.28$MouCreateClassObject$20 : int;
+var $ExAllocatePoolWithTag.arg.2$4$ : int;
+var $FullDeviceName$4$3168.35$MouCreateClassObject$20 : int;
+var $Legacy$5$3169.28$MouCreateClassObject$20 : int;
+var $MouDebugPrint.arg.2$15$ : int;
+var $MouDebugPrint.arg.2$18$ : int;
+var $MouDebugPrint.arg.2$2$ : int;
+var $MouDebugPrint.arg.2$20$ : int;
+var $MouDebugPrint.arg.2$22$ : int;
+var $MouDebugPrint.arg.2$5$ : int;
+var $RtlAppendUnicodeToString.arg.2$12$ : int;
+var $RtlAppendUnicodeToString.arg.2$14$ : int;
+var $RtlAppendUnicodeToString.arg.2$9$ : int;
+var $TmpDeviceExtension$2$3166.28$MouCreateClassObject$20 : int;
+var $deviceExtension$8$3199.24$MouCreateClassObject$20 : int;
+var $dumpCount$11$3202.24$MouCreateClassObject$20 : int;
+var $dumpData$12$3203.24$MouCreateClassObject$20 : int;
+var $errorCode$9$3200.24$MouCreateClassObject$20 : int;
+var $fullClassName$10$3201.24$MouCreateClassObject$20 : int;
+var $i$13$3204.24$MouCreateClassObject$20 : int;
+var $memset.arg.3$7$ : int;
+var $nameIndex$14$3205.24$MouCreateClassObject$20 : int;
+var $result.ExAllocatePoolWithTag$3252.0$3$ : int;
+var $result.ExAllocatePoolWithTag$3370.0$19$ : int;
+var $result.IoCreateDevice$3296.35$16$ : int;
+var $result.IoCreateDevice$3310.31$17$ : int;
+var $result.RtlAppendUnicodeToString$3271.32$8$ : int;
+var $result.RtlAppendUnicodeToString$3272.32$10$ : int;
+var $result.RtlAppendUnicodeToString$3275.36$11$ : int;
+var $result.RtlAppendUnicodeToString$3278.32$13$ : int;
+var $result.memset$3270.8$6$ : int;
+var $result.question.21$ : int;
+var $status$6$3197.24$MouCreateClassObject$20 : int;
+var $uniqueErrorValue$7$3198.24$MouCreateClassObject$20 : int;
+var tempBoogie0:int;
+var tempBoogie1:int;
+var tempBoogie2:int;
+var tempBoogie3:int;
+var tempBoogie4:int;
+var tempBoogie5:int;
+var tempBoogie6:int;
+var tempBoogie7:int;
+var tempBoogie8:int;
+var tempBoogie9:int;
+var tempBoogie10:int;
+var tempBoogie11:int;
+var tempBoogie12:int;
+var tempBoogie13:int;
+var tempBoogie14:int;
+var tempBoogie15:int;
+var tempBoogie16:int;
+var tempBoogie17:int;
+var tempBoogie18:int;
+var tempBoogie19:int;
+var LOOP_78_alloc:[int]name;
+var LOOP_78_Mem:[name][int]int;
+var LOOP_78_Res_DEVICE_STACK:[int]int;
+var LOOP_78_Res_DEV_EXTN:[int]int;
+var LOOP_78_Res_DEV_OBJ_INIT:[int]int;
+var LOOP_78_Res_SPIN_LOCK:[int]int;
+
+
+start:
+
+assume (alloc[$DriverObject$1$3165.28$MouCreateClassObject$201] != UNALLOCATED);
+assume (alloc[$TmpDeviceExtension$2$3166.28$MouCreateClassObject$201] != UNALLOCATED);
+assume (alloc[$ClassDeviceObject$3$3167.28$MouCreateClassObject$201] != UNALLOCATED);
+assume (alloc[$FullDeviceName$4$3168.35$MouCreateClassObject$201] != UNALLOCATED);
+call $dumpData$12$3203.24$MouCreateClassObject$20 := __HAVOC_malloc(16);
+call $fullClassName$10$3201.24$MouCreateClassObject$20 := __HAVOC_malloc(8);
+$DriverObject$1$3165.28$MouCreateClassObject$20 := $DriverObject$1$3165.28$MouCreateClassObject$201;
+$TmpDeviceExtension$2$3166.28$MouCreateClassObject$20 := $TmpDeviceExtension$2$3166.28$MouCreateClassObject$201;
+$ClassDeviceObject$3$3167.28$MouCreateClassObject$20 := $ClassDeviceObject$3$3167.28$MouCreateClassObject$201;
+$FullDeviceName$4$3168.35$MouCreateClassObject$20 := $FullDeviceName$4$3168.35$MouCreateClassObject$201;
+$Legacy$5$3169.28$MouCreateClassObject$20 := $Legacy$5$3169.28$MouCreateClassObject$201;
+goto label_3;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3440)
+label_1:
+call __HAVOC_free($dumpData$12$3203.24$MouCreateClassObject$20);
+call __HAVOC_free($fullClassName$10$3201.24$MouCreateClassObject$20);
+assume (forall m:int:: {Res_DEVICE_STACK[m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Res_DEVICE_STACK[m] == old(Res_DEVICE_STACK)[m]);
+assume (forall m:int:: {Res_DEV_EXTN[m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Res_DEV_EXTN[m] == old(Res_DEV_EXTN)[m]);
+assume (forall m:int:: {Res_DEV_OBJ_INIT[m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Res_DEV_OBJ_INIT[m] == old(Res_DEV_OBJ_INIT)[m]);
+assume (forall m:int:: {Res_SPIN_LOCK[m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Res_SPIN_LOCK[m] == old(Res_SPIN_LOCK)[m]);
+assume (forall m:int :: {Mem[T.A2UINT2][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.A2UINT2][m] == old(Mem[T.A2UINT2])[m]);
+assume (forall m:int :: {Mem[T.A37CHAR][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.A37CHAR][m] == old(Mem[T.A37CHAR])[m]);
+assume (forall m:int :: {Mem[T.A40CHAR][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.A40CHAR][m] == old(Mem[T.A40CHAR])[m]);
+assume (forall m:int :: {Mem[T.A4UINT4][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.A4UINT4][m] == old(Mem[T.A4UINT4])[m]);
+assume (forall m:int :: {Mem[T.A65CHAR][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.A65CHAR][m] == old(Mem[T.A65CHAR])[m]);
+assume (forall m:int :: {Mem[T.A75CHAR][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.A75CHAR][m] == old(Mem[T.A75CHAR])[m]);
+assume (forall m:int :: {Mem[T.A76CHAR][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.A76CHAR][m] == old(Mem[T.A76CHAR])[m]);
+assume (forall m:int :: {Mem[T.A7UINT2][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.A7UINT2][m] == old(Mem[T.A7UINT2])[m]);
+assume (forall m:int :: {Mem[T.A80CHAR][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.A80CHAR][m] == old(Mem[T.A80CHAR])[m]);
+assume (forall m:int :: {Mem[T.A9UINT2][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.A9UINT2][m] == old(Mem[T.A9UINT2])[m]);
+assume (forall m:int :: {Mem[T.Abandoned___unnamed_1_2bb39c56][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.Abandoned___unnamed_1_2bb39c56][m] == old(Mem[T.Abandoned___unnamed_1_2bb39c56])[m]);
+assume (forall m:int :: {Mem[T.Absolute___unnamed_1_2bb39c56][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.Absolute___unnamed_1_2bb39c56][m] == old(Mem[T.Absolute___unnamed_1_2bb39c56])[m]);
+assume (forall m:int :: {Mem[T.AllocateTag__IO_REMOVE_LOCK_DBG_BLOCK][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.AllocateTag__IO_REMOVE_LOCK_DBG_BLOCK][m] == old(Mem[T.AllocateTag__IO_REMOVE_LOCK_DBG_BLOCK])[m]);
+assume (forall m:int :: {Mem[T.BaseClassName__GLOBALS][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.BaseClassName__GLOBALS][m] == old(Mem[T.BaseClassName__GLOBALS])[m]);
+assume (forall m:int :: {Mem[T.Blink__LIST_ENTRY][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.Blink__LIST_ENTRY][m] == old(Mem[T.Blink__LIST_ENTRY])[m]);
+assume (forall m:int :: {Mem[T.Blocks__IO_REMOVE_LOCK_DBG_BLOCK][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.Blocks__IO_REMOVE_LOCK_DBG_BLOCK][m] == old(Mem[T.Blocks__IO_REMOVE_LOCK_DBG_BLOCK])[m]);
+assume (forall m:int :: {Mem[T.Buffer__UNICODE_STRING][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.Buffer__UNICODE_STRING][m] == old(Mem[T.Buffer__UNICODE_STRING])[m]);
+assume (forall m:int :: {Mem[T.ConnectOneClassToOnePort__GLOBALS][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.ConnectOneClassToOnePort__GLOBALS][m] == old(Mem[T.ConnectOneClassToOnePort__GLOBALS])[m]);
+assume (forall m:int :: {Mem[T.CurrentStackLocation___unnamed_4_a7aa989c][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.CurrentStackLocation___unnamed_4_a7aa989c][m] == old(Mem[T.CurrentStackLocation___unnamed_4_a7aa989c])[m]);
+assume (forall m:int :: {Mem[T.DataIn__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.DataIn__DEVICE_EXTENSION][m] == old(Mem[T.DataIn__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.DataOut__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.DataOut__DEVICE_EXTENSION][m] == old(Mem[T.DataOut__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.DebugActive___unnamed_1_9fa0583a][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.DebugActive___unnamed_1_9fa0583a][m] == old(Mem[T.DebugActive___unnamed_1_9fa0583a])[m]);
+assume (forall m:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.DeviceExtension__DEVICE_OBJECT][m] == old(Mem[T.DeviceExtension__DEVICE_OBJECT])[m]);
+assume (forall m:int :: {Mem[T.DeviceState__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.DeviceState__DEVICE_EXTENSION][m] == old(Mem[T.DeviceState__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.DpcActive___unnamed_1_9fa0583a][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.DpcActive___unnamed_1_9fa0583a][m] == old(Mem[T.DpcActive___unnamed_1_9fa0583a])[m]);
+assume (forall m:int :: {Mem[T.Enabled__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.Enabled__DEVICE_EXTENSION][m] == old(Mem[T.Enabled__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.ExecuteWmiMethod__WMILIB_CONTEXT][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.ExecuteWmiMethod__WMILIB_CONTEXT][m] == old(Mem[T.ExecuteWmiMethod__WMILIB_CONTEXT])[m]);
+assume (forall m:int :: {Mem[T.ExtraWaitWakeIrp__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.ExtraWaitWakeIrp__DEVICE_EXTENSION][m] == old(Mem[T.ExtraWaitWakeIrp__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.File__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.File__DEVICE_EXTENSION][m] == old(Mem[T.File__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.Flags__DEVICE_OBJECT][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.Flags__DEVICE_OBJECT][m] == old(Mem[T.Flags__DEVICE_OBJECT])[m]);
+assume (forall m:int :: {Mem[T.Flink__LIST_ENTRY][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.Flink__LIST_ENTRY][m] == old(Mem[T.Flink__LIST_ENTRY])[m]);
+assume (forall m:int :: {Mem[T.GrandMaster__GLOBALS][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.GrandMaster__GLOBALS][m] == old(Mem[T.GrandMaster__GLOBALS])[m]);
+assume (forall m:int :: {Mem[T.GuidCount__WMILIB_CONTEXT][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.GuidCount__WMILIB_CONTEXT][m] == old(Mem[T.GuidCount__WMILIB_CONTEXT])[m]);
+assume (forall m:int :: {Mem[T.GuidList__WMILIB_CONTEXT][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.GuidList__WMILIB_CONTEXT][m] == old(Mem[T.GuidList__WMILIB_CONTEXT])[m]);
+assume (forall m:int :: {Mem[T.Hand___unnamed_1_e30779f5][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.Hand___unnamed_1_e30779f5][m] == old(Mem[T.Hand___unnamed_1_e30779f5])[m]);
+assume (forall m:int :: {Mem[T.HighWatermark__IO_REMOVE_LOCK_DBG_BLOCK][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.HighWatermark__IO_REMOVE_LOCK_DBG_BLOCK][m] == old(Mem[T.HighWatermark__IO_REMOVE_LOCK_DBG_BLOCK])[m]);
+assume (forall m:int :: {Mem[T.INT4][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.INT4][m] == old(Mem[T.INT4])[m]);
+assume (forall m:int :: {Mem[T.InputCount__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.InputCount__DEVICE_EXTENSION][m] == old(Mem[T.InputCount__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.InputDataQueueLength__MOUSE_ATTRIBUTES][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.InputDataQueueLength__MOUSE_ATTRIBUTES][m] == old(Mem[T.InputDataQueueLength__MOUSE_ATTRIBUTES])[m]);
+assume (forall m:int :: {Mem[T.InputData__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.InputData__DEVICE_EXTENSION][m] == old(Mem[T.InputData__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.Inserted___unnamed_1_9fa0583a][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.Inserted___unnamed_1_9fa0583a][m] == old(Mem[T.Inserted___unnamed_1_9fa0583a])[m]);
+assume (forall m:int :: {Mem[T.IoCount__IO_REMOVE_LOCK_COMMON_BLOCK][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.IoCount__IO_REMOVE_LOCK_COMMON_BLOCK][m] == old(Mem[T.IoCount__IO_REMOVE_LOCK_COMMON_BLOCK])[m]);
+assume (forall m:int :: {Mem[T.LegacyDeviceList__GLOBALS][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.LegacyDeviceList__GLOBALS][m] == old(Mem[T.LegacyDeviceList__GLOBALS])[m]);
+assume (forall m:int :: {Mem[T.Length__UNICODE_STRING][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.Length__UNICODE_STRING][m] == old(Mem[T.Length__UNICODE_STRING])[m]);
+assume (forall m:int :: {Mem[T.Link__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.Link__DEVICE_EXTENSION][m] == old(Mem[T.Link__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.Lock___unnamed_4_c9b2e921][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.Lock___unnamed_4_c9b2e921][m] == old(Mem[T.Lock___unnamed_4_c9b2e921])[m]);
+assume (forall m:int :: {Mem[T.LowMemoryCount__IO_REMOVE_LOCK_DBG_BLOCK][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.LowMemoryCount__IO_REMOVE_LOCK_DBG_BLOCK][m] == old(Mem[T.LowMemoryCount__IO_REMOVE_LOCK_DBG_BLOCK])[m]);
+assume (forall m:int :: {Mem[T.MaxLockedTicks__IO_REMOVE_LOCK_DBG_BLOCK][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.MaxLockedTicks__IO_REMOVE_LOCK_DBG_BLOCK][m] == old(Mem[T.MaxLockedTicks__IO_REMOVE_LOCK_DBG_BLOCK])[m]);
+assume (forall m:int :: {Mem[T.MaximumLength__UNICODE_STRING][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.MaximumLength__UNICODE_STRING][m] == old(Mem[T.MaximumLength__UNICODE_STRING])[m]);
+assume (forall m:int :: {Mem[T.MinDeviceWakeState__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.MinDeviceWakeState__DEVICE_EXTENSION][m] == old(Mem[T.MinDeviceWakeState__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.MinSystemWakeState__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.MinSystemWakeState__DEVICE_EXTENSION][m] == old(Mem[T.MinSystemWakeState__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.MinorFunction__IO_STACK_LOCATION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.MinorFunction__IO_STACK_LOCATION][m] == old(Mem[T.MinorFunction__IO_STACK_LOCATION])[m]);
+assume (forall m:int :: {Mem[T.MouseAttributes__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.MouseAttributes__DEVICE_EXTENSION][m] == old(Mem[T.MouseAttributes__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.MouseIdentifier__MOUSE_ATTRIBUTES][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.MouseIdentifier__MOUSE_ATTRIBUTES][m] == old(Mem[T.MouseIdentifier__MOUSE_ATTRIBUTES])[m]);
+assume (forall m:int :: {Mem[T.Mutex__GLOBALS][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.Mutex__GLOBALS][m] == old(Mem[T.Mutex__GLOBALS])[m]);
+assume (forall m:int :: {Mem[T.NpxIrql___unnamed_1_2bb39c56][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.NpxIrql___unnamed_1_2bb39c56][m] == old(Mem[T.NpxIrql___unnamed_1_2bb39c56])[m]);
+assume (forall m:int :: {Mem[T.NumberOfButtons__MOUSE_ATTRIBUTES][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.NumberOfButtons__MOUSE_ATTRIBUTES][m] == old(Mem[T.NumberOfButtons__MOUSE_ATTRIBUTES])[m]);
+assume (forall m:int :: {Mem[T.OkayToLogOverflow__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.OkayToLogOverflow__DEVICE_EXTENSION][m] == old(Mem[T.OkayToLogOverflow__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.PCHAR][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.PCHAR][m] == old(Mem[T.PCHAR])[m]);
+assume (forall m:int :: {Mem[T.PDO__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.PDO__DEVICE_EXTENSION][m] == old(Mem[T.PDO__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.PUINT2][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.PUINT2][m] == old(Mem[T.PUINT2])[m]);
+assume (forall m:int :: {Mem[T.PUINT4][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.PUINT4][m] == old(Mem[T.PUINT4])[m]);
+assume (forall m:int :: {Mem[T.PVOID][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.PVOID][m] == old(Mem[T.PVOID])[m]);
+assume (forall m:int :: {Mem[T.P_DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.P_DEVICE_EXTENSION][m] == old(Mem[T.P_DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.P_DEVICE_OBJECT][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.P_DEVICE_OBJECT][m] == old(Mem[T.P_DEVICE_OBJECT])[m]);
+assume (forall m:int :: {Mem[T.P_DRIVER_OBJECT][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.P_DRIVER_OBJECT][m] == old(Mem[T.P_DRIVER_OBJECT])[m]);
+assume (forall m:int :: {Mem[T.P_FAST_MUTEX][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.P_FAST_MUTEX][m] == old(Mem[T.P_FAST_MUTEX])[m]);
+assume (forall m:int :: {Mem[T.P_IO_REMOVE_LOCK][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.P_IO_REMOVE_LOCK][m] == old(Mem[T.P_IO_REMOVE_LOCK])[m]);
+assume (forall m:int :: {Mem[T.P_LIST_ENTRY][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.P_LIST_ENTRY][m] == old(Mem[T.P_LIST_ENTRY])[m]);
+assume (forall m:int :: {Mem[T.P_MOUSE_INPUT_DATA][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.P_MOUSE_INPUT_DATA][m] == old(Mem[T.P_MOUSE_INPUT_DATA])[m]);
+assume (forall m:int :: {Mem[T.P_UNICODE_STRING][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.P_UNICODE_STRING][m] == old(Mem[T.P_UNICODE_STRING])[m]);
+assume (forall m:int :: {Mem[T.PnP__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.PnP__DEVICE_EXTENSION][m] == old(Mem[T.PnP__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.QueryWmiDataBlock__WMILIB_CONTEXT][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.QueryWmiDataBlock__WMILIB_CONTEXT][m] == old(Mem[T.QueryWmiDataBlock__WMILIB_CONTEXT])[m]);
+assume (forall m:int :: {Mem[T.QueryWmiRegInfo__WMILIB_CONTEXT][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.QueryWmiRegInfo__WMILIB_CONTEXT][m] == old(Mem[T.QueryWmiRegInfo__WMILIB_CONTEXT])[m]);
+assume (forall m:int :: {Mem[T.ReadQueue__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.ReadQueue__DEVICE_EXTENSION][m] == old(Mem[T.ReadQueue__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.RemoveLock__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.RemoveLock__DEVICE_EXTENSION][m] == old(Mem[T.RemoveLock__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.Removed__IO_REMOVE_LOCK_COMMON_BLOCK][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.Removed__IO_REMOVE_LOCK_COMMON_BLOCK][m] == old(Mem[T.Removed__IO_REMOVE_LOCK_COMMON_BLOCK])[m]);
+assume (forall m:int :: {Mem[T.Reserved1__IO_REMOVE_LOCK_DBG_BLOCK][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.Reserved1__IO_REMOVE_LOCK_DBG_BLOCK][m] == old(Mem[T.Reserved1__IO_REMOVE_LOCK_DBG_BLOCK])[m]);
+assume (forall m:int :: {Mem[T.Reserved2__IO_REMOVE_LOCK_DBG_BLOCK][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.Reserved2__IO_REMOVE_LOCK_DBG_BLOCK][m] == old(Mem[T.Reserved2__IO_REMOVE_LOCK_DBG_BLOCK])[m]);
+assume (forall m:int :: {Mem[T.Reserved__IO_REMOVE_LOCK_COMMON_BLOCK][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.Reserved__IO_REMOVE_LOCK_COMMON_BLOCK][m] == old(Mem[T.Reserved__IO_REMOVE_LOCK_COMMON_BLOCK])[m]);
+assume (forall m:int :: {Mem[T.SampleRate__MOUSE_ATTRIBUTES][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.SampleRate__MOUSE_ATTRIBUTES][m] == old(Mem[T.SampleRate__MOUSE_ATTRIBUTES])[m]);
+assume (forall m:int :: {Mem[T.Self__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.Self__DEVICE_EXTENSION][m] == old(Mem[T.Self__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.SequenceNumber__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.SequenceNumber__DEVICE_EXTENSION][m] == old(Mem[T.SequenceNumber__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.SetWmiDataBlock__WMILIB_CONTEXT][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.SetWmiDataBlock__WMILIB_CONTEXT][m] == old(Mem[T.SetWmiDataBlock__WMILIB_CONTEXT])[m]);
+assume (forall m:int :: {Mem[T.SetWmiDataItem__WMILIB_CONTEXT][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.SetWmiDataItem__WMILIB_CONTEXT][m] == old(Mem[T.SetWmiDataItem__WMILIB_CONTEXT])[m]);
+assume (forall m:int :: {Mem[T.SignalState__DISPATCHER_HEADER][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.SignalState__DISPATCHER_HEADER][m] == old(Mem[T.SignalState__DISPATCHER_HEADER])[m]);
+assume (forall m:int :: {Mem[T.Signalling___unnamed_1_2bb39c56][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.Signalling___unnamed_1_2bb39c56][m] == old(Mem[T.Signalling___unnamed_1_2bb39c56])[m]);
+assume (forall m:int :: {Mem[T.Signature__IO_REMOVE_LOCK_DBG_BLOCK][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.Signature__IO_REMOVE_LOCK_DBG_BLOCK][m] == old(Mem[T.Signature__IO_REMOVE_LOCK_DBG_BLOCK])[m]);
+assume (forall m:int :: {Mem[T.Size___unnamed_1_e30779f5][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.Size___unnamed_1_e30779f5][m] == old(Mem[T.Size___unnamed_1_e30779f5])[m]);
+assume (forall m:int :: {Mem[T.SpinLock__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.SpinLock__DEVICE_EXTENSION][m] == old(Mem[T.SpinLock__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.Spin__IO_REMOVE_LOCK_DBG_BLOCK][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.Spin__IO_REMOVE_LOCK_DBG_BLOCK][m] == old(Mem[T.Spin__IO_REMOVE_LOCK_DBG_BLOCK])[m]);
+assume (forall m:int :: {Mem[T.Started__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.Started__DEVICE_EXTENSION][m] == old(Mem[T.Started__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.SurpriseRemoved__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.SurpriseRemoved__DEVICE_EXTENSION][m] == old(Mem[T.SurpriseRemoved__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.SystemState__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.SystemState__DEVICE_EXTENSION][m] == old(Mem[T.SystemState__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.SystemToDeviceState__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.SystemToDeviceState__DEVICE_EXTENSION][m] == old(Mem[T.SystemToDeviceState__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.TargetNotifyHandle__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.TargetNotifyHandle__DEVICE_EXTENSION][m] == old(Mem[T.TargetNotifyHandle__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.TopPort__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.TopPort__DEVICE_EXTENSION][m] == old(Mem[T.TopPort__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.TrueClassDevice__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.TrueClassDevice__DEVICE_EXTENSION][m] == old(Mem[T.TrueClassDevice__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.TrustedSubsystemCount__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.TrustedSubsystemCount__DEVICE_EXTENSION][m] == old(Mem[T.TrustedSubsystemCount__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.Type___unnamed_4_846adf3f][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.Type___unnamed_4_846adf3f][m] == old(Mem[T.Type___unnamed_4_846adf3f])[m]);
+assume (forall m:int :: {Mem[T.UCHAR][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.UCHAR][m] == old(Mem[T.UCHAR])[m]);
+assume (forall m:int :: {Mem[T.UINT2][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.UINT2][m] == old(Mem[T.UINT2])[m]);
+assume (forall m:int :: {Mem[T.UINT4][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.UINT4][m] == old(Mem[T.UINT4])[m]);
+assume (forall m:int :: {Mem[T.UnitId__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.UnitId__DEVICE_EXTENSION][m] == old(Mem[T.UnitId__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.WaitWakeEnabled__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.WaitWakeEnabled__DEVICE_EXTENSION][m] == old(Mem[T.WaitWakeEnabled__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.WaitWakeIrp__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.WaitWakeIrp__DEVICE_EXTENSION][m] == old(Mem[T.WaitWakeIrp__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.WaitWakeSpinLock__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.WaitWakeSpinLock__DEVICE_EXTENSION][m] == old(Mem[T.WaitWakeSpinLock__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.WmiFunctionControl__WMILIB_CONTEXT][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.WmiFunctionControl__WMILIB_CONTEXT][m] == old(Mem[T.WmiFunctionControl__WMILIB_CONTEXT])[m]);
+assume (forall m:int :: {Mem[T._POOL_TYPE][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T._POOL_TYPE][m] == old(Mem[T._POOL_TYPE])[m]);
+return;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3440)
+label_2:
+assume false;
+return;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3197)
+label_3:
+goto label_4;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3198)
+label_4:
+goto label_5;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3199)
+label_5:
+goto label_6;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3199)
+label_6:
+$deviceExtension$8$3199.24$MouCreateClassObject$20 := 0 ;
+goto label_7;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3200)
+label_7:
+goto label_8;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3200)
+label_8:
+$errorCode$9$3200.24$MouCreateClassObject$20 := 0 ;
+goto label_9;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3201)
+label_9:
+goto label_10;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3201)
+label_10:
+// Skipping Structure assignment due to the flag SkipStructAssignments
+goto label_11;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3202)
+label_11:
+goto label_12;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3202)
+label_12:
+$dumpCount$11$3202.24$MouCreateClassObject$20 := 0 ;
+goto label_13;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3203)
+label_13:
+goto label_14;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3204)
+label_14:
+goto label_15;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3205)
+label_15:
+goto label_16;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3207)
+label_16:
+call __PREfastPagedCode ();
+goto label_22;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3209)
+label_19:
+// skip MouDebugPrint
+goto label_23;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3209)
+label_22:
+call havoc_stringTemp := __HAVOC_malloc(1);
+$MouDebugPrint.arg.2$2$ := havoc_stringTemp ;
+goto label_19;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3215)
+label_23:
+call ExAcquireFastMutex (Mutex__GLOBALS(Globals));
+goto label_26;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3220)
+label_26:
+Mem[T.P_DEVICE_OBJECT] := Mem[T.P_DEVICE_OBJECT][$ClassDeviceObject$3$3167.28$MouCreateClassObject$20 := 0];
+goto label_27;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3222)
+label_27:
+goto label_27_true , label_27_false ;
+
+
+label_27_true :
+assume (Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)] != 0);
+goto label_89;
+
+
+label_27_false :
+assume (Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)] == 0);
+goto label_28;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3226)
+label_28:
+call ExReleaseFastMutex (Mutex__GLOBALS(Globals));
+goto label_31;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3232)
+label_31:
+goto label_31_true , label_31_false ;
+
+
+label_31_true :
+assume (BOOGIE_LARGE_INT_4294967273 < Mem[T.Length__UNICODE_STRING][Length__UNICODE_STRING(BaseClassName__GLOBALS(Globals))]);
+goto label_32;
+
+
+label_31_false :
+assume !(BOOGIE_LARGE_INT_4294967273 < Mem[T.Length__UNICODE_STRING][Length__UNICODE_STRING(BaseClassName__GLOBALS(Globals))]);
+goto label_37;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3233)
+label_32:
+$status$6$3197.24$MouCreateClassObject$20 := -1073741823 ;
+goto label_33;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3234)
+label_33:
+$errorCode$9$3200.24$MouCreateClassObject$20 := -1073414143 ;
+goto label_34;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3235)
+label_34:
+$uniqueErrorValue$7$3198.24$MouCreateClassObject$20 := 20006 ;
+goto label_35;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3236)
+label_35:
+Mem[T.UINT4] := Mem[T.UINT4][PLUS($dumpData$12$3203.24$MouCreateClassObject$20, 4, 0) := Mem[T.MaximumLength__UNICODE_STRING][MaximumLength__UNICODE_STRING($fullClassName$10$3201.24$MouCreateClassObject$20)]];
+goto label_36;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3237)
+label_36:
+$dumpCount$11$3202.24$MouCreateClassObject$20 := 1 ;
+goto label_136;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3244)
+label_37:
+Mem[T.MaximumLength__UNICODE_STRING] := Mem[T.MaximumLength__UNICODE_STRING][MaximumLength__UNICODE_STRING($fullClassName$10$3201.24$MouCreateClassObject$20) := PLUS(PLUS(18, 1, Mem[T.Length__UNICODE_STRING][Length__UNICODE_STRING(BaseClassName__GLOBALS(Globals))]), 1, 4)];
+goto label_38;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3248)
+label_38:
+goto label_38_true , label_38_false ;
+
+
+label_38_true :
+assume (Mem[T.ConnectOneClassToOnePort__GLOBALS][ConnectOneClassToOnePort__GLOBALS(Globals)] != 0);
+goto label_39;
+
+
+label_38_false :
+assume (Mem[T.ConnectOneClassToOnePort__GLOBALS][ConnectOneClassToOnePort__GLOBALS(Globals)] == 0);
+goto label_44;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3248)
+label_39:
+goto label_39_true , label_39_false ;
+
+
+label_39_true :
+assume ($Legacy$5$3169.28$MouCreateClassObject$20 != 0);
+goto label_40;
+
+
+label_39_false :
+assume ($Legacy$5$3169.28$MouCreateClassObject$20 == 0);
+goto label_44;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3249)
+label_40:
+tempBoogie0 := PLUS(Mem[T.MaximumLength__UNICODE_STRING][MaximumLength__UNICODE_STRING($fullClassName$10$3201.24$MouCreateClassObject$20)], 1, 14) ;
+Mem[T.MaximumLength__UNICODE_STRING] := Mem[T.MaximumLength__UNICODE_STRING][MaximumLength__UNICODE_STRING($fullClassName$10$3201.24$MouCreateClassObject$20) := tempBoogie0];
+goto label_44;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3252)
+label_41:
+call $result.ExAllocatePoolWithTag$3252.0$3$ := ExAllocatePoolWithTag (1, $ExAllocatePoolWithTag.arg.2$4$, 1131377997);
+goto label_45;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3252)
+label_44:
+$ExAllocatePoolWithTag.arg.2$4$ := Mem[T.MaximumLength__UNICODE_STRING][MaximumLength__UNICODE_STRING($fullClassName$10$3201.24$MouCreateClassObject$20)] ;
+goto label_41;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3252)
+label_45:
+Mem[T.Buffer__UNICODE_STRING] := Mem[T.Buffer__UNICODE_STRING][Buffer__UNICODE_STRING($fullClassName$10$3201.24$MouCreateClassObject$20) := $result.ExAllocatePoolWithTag$3252.0$3$];
+goto label_46;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3255)
+label_46:
+goto label_46_true , label_46_false ;
+
+
+label_46_true :
+assume (Mem[T.Buffer__UNICODE_STRING][Buffer__UNICODE_STRING($fullClassName$10$3201.24$MouCreateClassObject$20)] != 0);
+goto label_59;
+
+
+label_46_false :
+assume (Mem[T.Buffer__UNICODE_STRING][Buffer__UNICODE_STRING($fullClassName$10$3201.24$MouCreateClassObject$20)] == 0);
+goto label_50;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3257)
+label_47:
+// skip MouDebugPrint
+goto label_51;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3257)
+label_50:
+call havoc_stringTemp := __HAVOC_malloc(1);
+$MouDebugPrint.arg.2$5$ := havoc_stringTemp ;
+goto label_47;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3262)
+label_51:
+$status$6$3197.24$MouCreateClassObject$20 := -1073741823 ;
+goto label_52;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3263)
+label_52:
+$errorCode$9$3200.24$MouCreateClassObject$20 := -1073414143 ;
+goto label_53;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3264)
+label_53:
+$uniqueErrorValue$7$3198.24$MouCreateClassObject$20 := 20006 ;
+goto label_54;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3265)
+label_54:
+Mem[T.UINT4] := Mem[T.UINT4][PLUS($dumpData$12$3203.24$MouCreateClassObject$20, 4, 0) := Mem[T.MaximumLength__UNICODE_STRING][MaximumLength__UNICODE_STRING($fullClassName$10$3201.24$MouCreateClassObject$20)]];
+goto label_55;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3266)
+label_55:
+$dumpCount$11$3202.24$MouCreateClassObject$20 := 1 ;
+goto label_136;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3270)
+label_56:
+// ignoring intrinsic intrinsic.memset
+havoc $result.memset$3270.8$6$;
+goto label_63;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3270)
+label_59:
+$memset.arg.3$7$ := Mem[T.MaximumLength__UNICODE_STRING][MaximumLength__UNICODE_STRING($fullClassName$10$3201.24$MouCreateClassObject$20)] ;
+goto label_56;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3271)
+label_60:
+call $result.RtlAppendUnicodeToString$3271.32$8$ := RtlAppendUnicodeToString ($fullClassName$10$3201.24$MouCreateClassObject$20, $RtlAppendUnicodeToString.arg.2$9$);
+goto label_64;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3271)
+label_63:
+call havoc_stringTemp := __HAVOC_malloc(1);
+$RtlAppendUnicodeToString.arg.2$9$ := havoc_stringTemp ;
+goto label_60;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3272)
+label_64:
+call $result.RtlAppendUnicodeToString$3272.32$10$ := RtlAppendUnicodeToString ($fullClassName$10$3201.24$MouCreateClassObject$20, Mem[T.Buffer__UNICODE_STRING][Buffer__UNICODE_STRING(BaseClassName__GLOBALS(Globals))]);
+goto label_67;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3274)
+label_67:
+goto label_67_true , label_67_false ;
+
+
+label_67_true :
+assume (Mem[T.ConnectOneClassToOnePort__GLOBALS][ConnectOneClassToOnePort__GLOBALS(Globals)] != 0);
+goto label_68;
+
+
+label_67_false :
+assume (Mem[T.ConnectOneClassToOnePort__GLOBALS][ConnectOneClassToOnePort__GLOBALS(Globals)] == 0);
+goto label_76;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3274)
+label_68:
+goto label_68_true , label_68_false ;
+
+
+label_68_true :
+assume ($Legacy$5$3169.28$MouCreateClassObject$20 != 0);
+goto label_72;
+
+
+label_68_false :
+assume ($Legacy$5$3169.28$MouCreateClassObject$20 == 0);
+goto label_76;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3275)
+label_69:
+call $result.RtlAppendUnicodeToString$3275.36$11$ := RtlAppendUnicodeToString ($fullClassName$10$3201.24$MouCreateClassObject$20, $RtlAppendUnicodeToString.arg.2$12$);
+goto label_76;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3275)
+label_72:
+call havoc_stringTemp := __HAVOC_malloc(1);
+$RtlAppendUnicodeToString.arg.2$12$ := havoc_stringTemp ;
+goto label_69;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3278)
+label_73:
+call $result.RtlAppendUnicodeToString$3278.32$13$ := RtlAppendUnicodeToString ($fullClassName$10$3201.24$MouCreateClassObject$20, $RtlAppendUnicodeToString.arg.2$14$);
+goto label_77;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3278)
+label_76:
+call havoc_stringTemp := __HAVOC_malloc(1);
+$RtlAppendUnicodeToString.arg.2$14$ := havoc_stringTemp ;
+goto label_73;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3284)
+label_77:
+$nameIndex$14$3205.24$MouCreateClassObject$20 := 0 ;
+goto label_78;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3288)
+label_78:
+// loop entry initialization...
+LOOP_78_alloc := alloc;
+LOOP_78_Mem := Mem;
+LOOP_78_Res_DEVICE_STACK := Res_DEVICE_STACK;
+LOOP_78_Res_DEV_EXTN := Res_DEV_EXTN;
+LOOP_78_Res_DEV_OBJ_INIT := Res_DEV_OBJ_INIT;
+LOOP_78_Res_SPIN_LOCK := Res_SPIN_LOCK;
+goto label_78_head;
+
+
+label_78_head:
+// loop head assertions...
+//TAG: requires __pforall(_H_x, (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension), __inv_resource("DEV_OBJ_INIT", 1), ((struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension))->Self == _H_x && __resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension)) == 1)
+assert((forall _H_x:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)]} Inverse(Res_DEV_OBJ_INIT,1)[_H_x] ==> ((Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)])] == _H_x) && (Res_DEV_EXTN[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)]] == 1))));
+//TAG: requires __pforall(_H_z, _H_z->Self, __inv_resource("DEV_EXTN", 1), __resource("DEV_OBJ_INIT", _H_z->Self) == 1 && (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)(_H_z->Self))->DeviceExtension) == _H_z)
+assert((forall _H_z:int :: {Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)]} Inverse(Res_DEV_EXTN,1)[_H_z] ==> ((Res_DEV_OBJ_INIT[Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)]] == 1) && (Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)])] == _H_z))));
+//TAG: requires __forall(_H_z, __inv_resource("DEV_EXTN", 1), __resource("SPIN_LOCK", &_H_z->SpinLock) == 0 && __resource("SPIN_LOCK", &_H_z->WaitWakeSpinLock) == 0)
+assert((Subset(Empty(), Inverse(Res_DEV_EXTN,1)) && (forall _H_z : int :: {Inverse(Res_DEV_EXTN,1)[_H_z]} (Inverse(Res_DEV_EXTN,1)[_H_z]) ==> ((Res_SPIN_LOCK[SpinLock__DEVICE_EXTENSION(_H_z)] == 0) && (Res_SPIN_LOCK[WaitWakeSpinLock__DEVICE_EXTENSION(_H_z)] == 0)))));
+//TAG: requires 1 ==> (Globals.GrandMaster != (void *)0 ==> __resource("DEV_EXTN", Globals.GrandMaster) == 1)
+assert((true) ==> ((Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)] != 0) ==> (Res_DEV_EXTN[Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)]] == 1)));
+//TAG: requires 1 ==> __setin(&Globals.LegacyDeviceList, __btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList))
+assert((true) ==> (ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[LegacyDeviceList__GLOBALS(Globals)]));
+//TAG: requires 1 ==> __forall(_H_y, __btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList), _H_y == &Globals.LegacyDeviceList || __resource("DEV_EXTN", CONTAINING_RECORD(_H_y, struct _DEVICE_EXTENSION , Link)) == 1)
+assert((true) ==> ((Subset(Empty(), ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))) && (forall _H_y : int :: {ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[_H_y]} (ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[_H_y]) ==> ((_H_y == LegacyDeviceList__GLOBALS(Globals)) || (Res_DEV_EXTN[MINUS_LEFT_PTR(_H_y, 1, Link__DEVICE_EXTENSION(0))] == 1))))));
+//TAG: requires 1 ==> !__setin(&Globals.GrandMaster->Link, __setminus(__btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList), __set(&Globals.LegacyDeviceList)))
+assert((true) ==> (!(Difference(ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals)), Singleton(LegacyDeviceList__GLOBALS(Globals)))[Link__DEVICE_EXTENSION(Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)])])));
+//TAG: requires __preserves_resource("DEV_OBJ_INIT")
+assert(Res_DEV_OBJ_INIT == LOOP_78_Res_DEV_OBJ_INIT);
+//TAG: requires __preserves_resource("DEV_EXTN")
+assert(Res_DEV_EXTN == LOOP_78_Res_DEV_EXTN);
+//TAG: requires __preserves_field_map(__offset((*((struct _LIST_ENTRY *)0)).Flink))
+assert(Mem[T.Flink__LIST_ENTRY] == LOOP_78_Mem[T.Flink__LIST_ENTRY]);
+assume(forall f:int :: {alloc[Base(f)]} LOOP_78_alloc[Base(f)] == UNALLOCATED || LOOP_78_alloc[Base(f)] == alloc[Base(f)]);
+
+
+//TAG: net change in resource DEVICE_STACK only for: __set_empty
+assert (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEVICE_STACK[r]} (Empty()[r]) || LOOP_78_Res_DEVICE_STACK[r] == Res_DEVICE_STACK[r]));
+
+//TAG: net change in resource DEV_EXTN only for: __set_empty
+assert (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_EXTN[r]} (Empty()[r]) || LOOP_78_Res_DEV_EXTN[r] == Res_DEV_EXTN[r]));
+
+//TAG: net change in resource DEV_OBJ_INIT only for: __set_empty
+assert (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_OBJ_INIT[r]} (Empty()[r]) || LOOP_78_Res_DEV_OBJ_INIT[r] == Res_DEV_OBJ_INIT[r]));
+
+//TAG: net change in resource SPIN_LOCK only for: __set_true, __set_empty
+assert (Subset(Empty(), Union(Union(Empty(), SetTrue()), Empty())) && (forall r:int :: {Res_SPIN_LOCK[r]} (SetTrue()[r]) || (Empty()[r]) || LOOP_78_Res_SPIN_LOCK[r] == Res_SPIN_LOCK[r]));
+//TAG: updated memory locations at Mem[T.MinorFunction__IO_STACK_LOCATION] only for: __set_empty
+assert (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.MinorFunction__IO_STACK_LOCATION][_m]} (Empty()[_m]) || Mem[T.MinorFunction__IO_STACK_LOCATION][_m] == LOOP_78_Mem[T.MinorFunction__IO_STACK_LOCATION][_m]));
+//TAG: updated memory locations at Mem[T.CurrentStackLocation___unnamed_4_a7aa989c] only for: __set_empty
+assert (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.CurrentStackLocation___unnamed_4_a7aa989c][_m]} (Empty()[_m]) || Mem[T.CurrentStackLocation___unnamed_4_a7aa989c][_m] == LOOP_78_Mem[T.CurrentStackLocation___unnamed_4_a7aa989c][_m]));
+//TAG: updated memory locations at Mem[T.DeviceExtension__DEVICE_OBJECT] only for: __set_empty
+assert (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.DeviceExtension__DEVICE_OBJECT][_m] == LOOP_78_Mem[T.DeviceExtension__DEVICE_OBJECT][_m]));
+//TAG: updated memory locations at Mem[T.Self__DEVICE_EXTENSION] only for: __set_true, __set_empty
+assert (Subset(Empty(), Union(Union(Empty(), SetTrue()), Empty())) && (forall _m:int :: {Mem[T.Self__DEVICE_EXTENSION][_m]} (SetTrue()[_m]) || (Empty()[_m]) || Mem[T.Self__DEVICE_EXTENSION][_m] == LOOP_78_Mem[T.Self__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.Started__DEVICE_EXTENSION] only for: __set_empty
+assert (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Started__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Started__DEVICE_EXTENSION][_m] == LOOP_78_Mem[T.Started__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.GrandMaster__GLOBALS] only for: __set_empty
+assert (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.GrandMaster__GLOBALS][_m]} (Empty()[_m]) || Mem[T.GrandMaster__GLOBALS][_m] == LOOP_78_Mem[T.GrandMaster__GLOBALS][_m]));
+//TAG: updated memory locations at Mem[T.P_DEVICE_OBJECT] only for: __set_empty
+assert (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.P_DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.P_DEVICE_OBJECT][_m] == LOOP_78_Mem[T.P_DEVICE_OBJECT][_m]));
+
+// end loop head assertions
+
+Mem[T.UINT2] := Mem[T.UINT2][PLUS(Mem[T.Buffer__UNICODE_STRING][Buffer__UNICODE_STRING($fullClassName$10$3201.24$MouCreateClassObject$20)], 2, MINUS_BOTH_PTR_OR_BOTH_INT( BINARY_BOTH_INT(Mem[T.Length__UNICODE_STRING][Length__UNICODE_STRING($fullClassName$10$3201.24$MouCreateClassObject$20)], 2), 1, 1)) := PLUS(48, 1, $nameIndex$14$3205.24$MouCreateClassObject$20)];
+$nameIndex$14$3205.24$MouCreateClassObject$20 := PLUS($nameIndex$14$3205.24$MouCreateClassObject$20, 1, 1) ;
+goto label_82;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3290)
+label_79:
+// skip MouDebugPrint
+goto label_83;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3290)
+label_82:
+call havoc_stringTemp := __HAVOC_malloc(1);
+$MouDebugPrint.arg.2$15$ := havoc_stringTemp ;
+goto label_79;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3296)
+label_83:
+call $result.IoCreateDevice$3296.35$16$ := IoCreateDevice ($DriverObject$1$3165.28$MouCreateClassObject$20, 272, $fullClassName$10$3201.24$MouCreateClassObject$20, 15, 0, 0, $ClassDeviceObject$3$3167.28$MouCreateClassObject$20);
+goto label_86;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3296)
+label_86:
+$status$6$3197.24$MouCreateClassObject$20 := $result.IoCreateDevice$3296.35$16$ ;
+goto label_87;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3304)
+label_87:
+goto label_87_true , label_87_false ;
+
+
+label_87_true :
+assume (-1073741771 == $status$6$3197.24$MouCreateClassObject$20);
+goto label_78_head;
+
+
+label_87_false :
+assume !(-1073741771 == $status$6$3197.24$MouCreateClassObject$20);
+goto label_88;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3306)
+label_88:
+Mem[T.PUINT2] := Mem[T.PUINT2][$FullDeviceName$4$3168.35$MouCreateClassObject$20 := Mem[T.Buffer__UNICODE_STRING][Buffer__UNICODE_STRING($fullClassName$10$3201.24$MouCreateClassObject$20)]];
+goto label_97;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3309)
+label_89:
+call ExReleaseFastMutex (Mutex__GLOBALS(Globals));
+goto label_92;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3310)
+label_92:
+call $result.IoCreateDevice$3310.31$17$ := IoCreateDevice ($DriverObject$1$3165.28$MouCreateClassObject$20, 272, 0, 15, 0, 0, $ClassDeviceObject$3$3167.28$MouCreateClassObject$20);
+goto label_95;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3310)
+label_95:
+$status$6$3197.24$MouCreateClassObject$20 := $result.IoCreateDevice$3310.31$17$ ;
+goto label_96;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3317)
+label_96:
+Mem[T.PUINT2] := Mem[T.PUINT2][$FullDeviceName$4$3168.35$MouCreateClassObject$20 := 0];
+goto label_97;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3320)
+label_97:
+goto label_97_true , label_97_false ;
+
+
+label_97_true :
+assume (0 <= $status$6$3197.24$MouCreateClassObject$20);
+goto label_98;
+
+
+label_97_false :
+assume !(0 <= $status$6$3197.24$MouCreateClassObject$20);
+goto label_102;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3320)
+label_98:
+goto label_98_true , label_98_false ;
+
+
+label_98_true :
+assume (Mem[T.P_DEVICE_OBJECT][$ClassDeviceObject$3$3167.28$MouCreateClassObject$20] != 0);
+goto label_107;
+
+
+label_98_false :
+assume (Mem[T.P_DEVICE_OBJECT][$ClassDeviceObject$3$3167.28$MouCreateClassObject$20] == 0);
+goto label_102;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3321)
+label_99:
+// skip MouDebugPrint
+goto label_103;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3321)
+label_102:
+call havoc_stringTemp := __HAVOC_malloc(1);
+$MouDebugPrint.arg.2$18$ := havoc_stringTemp ;
+goto label_99;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3327)
+label_103:
+$errorCode$9$3200.24$MouCreateClassObject$20 := -1073414131 ;
+goto label_104;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3328)
+label_104:
+$uniqueErrorValue$7$3198.24$MouCreateClassObject$20 := 20006 ;
+goto label_105;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3329)
+label_105:
+Mem[T.UINT4] := Mem[T.UINT4][PLUS($dumpData$12$3203.24$MouCreateClassObject$20, 4, 0) := Mem[T.MaximumLength__UNICODE_STRING][MaximumLength__UNICODE_STRING($fullClassName$10$3201.24$MouCreateClassObject$20)]];
+goto label_106;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3330)
+label_106:
+$dumpCount$11$3202.24$MouCreateClassObject$20 := 1 ;
+goto label_136;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3339)
+label_107:
+assume (forall r:int :: {BIT_BAND(BIT_BOR(Mem[T.Flags__DEVICE_OBJECT][Flags__DEVICE_OBJECT(Mem[T.P_DEVICE_OBJECT][$ClassDeviceObject$3$3167.28$MouCreateClassObject$20])], 4),r)} BIT_BAND(Mem[T.Flags__DEVICE_OBJECT][Flags__DEVICE_OBJECT(Mem[T.P_DEVICE_OBJECT][$ClassDeviceObject$3$3167.28$MouCreateClassObject$20])],r)!= 0 || BIT_BAND(4,r)!= 0 <==> BIT_BAND(BIT_BOR(Mem[T.Flags__DEVICE_OBJECT][Flags__DEVICE_OBJECT(Mem[T.P_DEVICE_OBJECT][$ClassDeviceObject$3$3167.28$MouCreateClassObject$20])], 4),r)!= 0);
+tempBoogie0 := BIT_BOR(Mem[T.Flags__DEVICE_OBJECT][Flags__DEVICE_OBJECT(Mem[T.P_DEVICE_OBJECT][$ClassDeviceObject$3$3167.28$MouCreateClassObject$20])], 4) ;
+Mem[T.Flags__DEVICE_OBJECT] := Mem[T.Flags__DEVICE_OBJECT][Flags__DEVICE_OBJECT(Mem[T.P_DEVICE_OBJECT][$ClassDeviceObject$3$3167.28$MouCreateClassObject$20]) := tempBoogie0];
+goto label_108;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3340)
+label_108:
+$deviceExtension$8$3199.24$MouCreateClassObject$20 := Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.P_DEVICE_OBJECT][$ClassDeviceObject$3$3167.28$MouCreateClassObject$20])] ;
+goto label_109;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3342)
+label_109:
+// Skipping Structure assignment due to the flag SkipStructAssignments
+goto label_110;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3344)
+label_110:
+Mem[T.Self__DEVICE_EXTENSION] := Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION($deviceExtension$8$3199.24$MouCreateClassObject$20) := Mem[T.P_DEVICE_OBJECT][$ClassDeviceObject$3$3167.28$MouCreateClassObject$20]];
+goto label_111;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3345)
+label_111:
+call IoInitializeRemoveLockEx (RemoveLock__DEVICE_EXTENSION($deviceExtension$8$3199.24$MouCreateClassObject$20), 1131377997, 0, 0, 88);
+goto label_114;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3351)
+label_114:
+assume (Mem[T.SpinLock__DEVICE_EXTENSION][SpinLock__DEVICE_EXTENSION($deviceExtension$8$3199.24$MouCreateClassObject$20)] == Mem[T.UINT4][SpinLock__DEVICE_EXTENSION($deviceExtension$8$3199.24$MouCreateClassObject$20)]);
+call KeInitializeSpinLock (SpinLock__DEVICE_EXTENSION($deviceExtension$8$3199.24$MouCreateClassObject$20));
+Mem[T.SpinLock__DEVICE_EXTENSION] := Mem[T.SpinLock__DEVICE_EXTENSION][SpinLock__DEVICE_EXTENSION($deviceExtension$8$3199.24$MouCreateClassObject$20) := Mem[T.UINT4][SpinLock__DEVICE_EXTENSION($deviceExtension$8$3199.24$MouCreateClassObject$20)]];
+goto label_117;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3357)
+label_117:
+call InitializeListHead_IRP (ReadQueue__DEVICE_EXTENSION($deviceExtension$8$3199.24$MouCreateClassObject$20));
+goto label_120;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3363)
+label_120:
+Mem[T.TrustedSubsystemCount__DEVICE_EXTENSION] := Mem[T.TrustedSubsystemCount__DEVICE_EXTENSION][TrustedSubsystemCount__DEVICE_EXTENSION($deviceExtension$8$3199.24$MouCreateClassObject$20) := 0];
+goto label_121;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3370)
+label_121:
+call $result.ExAllocatePoolWithTag$3370.0$19$ := ExAllocatePoolWithTag (0, Mem[T.InputDataQueueLength__MOUSE_ATTRIBUTES][InputDataQueueLength__MOUSE_ATTRIBUTES(MouseAttributes__DEVICE_EXTENSION($deviceExtension$8$3199.24$MouCreateClassObject$20))], 1131377997);
+goto label_124;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3369)
+label_124:
+Mem[T.InputData__DEVICE_EXTENSION] := Mem[T.InputData__DEVICE_EXTENSION][InputData__DEVICE_EXTENSION($deviceExtension$8$3199.24$MouCreateClassObject$20) := $result.ExAllocatePoolWithTag$3370.0$19$];
+goto label_125;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3375)
+label_125:
+goto label_125_true , label_125_false ;
+
+
+label_125_true :
+assume (Mem[T.InputData__DEVICE_EXTENSION][InputData__DEVICE_EXTENSION($deviceExtension$8$3199.24$MouCreateClassObject$20)] != 0);
+goto label_133;
+
+
+label_125_false :
+assume (Mem[T.InputData__DEVICE_EXTENSION][InputData__DEVICE_EXTENSION($deviceExtension$8$3199.24$MouCreateClassObject$20)] == 0);
+goto label_129;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3381)
+label_126:
+// skip MouDebugPrint
+goto label_130;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3381)
+label_129:
+call havoc_stringTemp := __HAVOC_malloc(1);
+$MouDebugPrint.arg.2$20$ := havoc_stringTemp ;
+goto label_126;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3387)
+label_130:
+$status$6$3197.24$MouCreateClassObject$20 := -1073741670 ;
+goto label_131;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3393)
+label_131:
+$errorCode$9$3200.24$MouCreateClassObject$20 := -1073414142 ;
+goto label_132;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3394)
+label_132:
+$uniqueErrorValue$7$3198.24$MouCreateClassObject$20 := 20020 ;
+goto label_136;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3402)
+label_133:
+call MouInitializeDataQueue ($deviceExtension$8$3199.24$MouCreateClassObject$20);
+goto label_136;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3406)
+label_136:
+goto label_136_true , label_136_false ;
+
+
+label_136_true :
+assume ($status$6$3197.24$MouCreateClassObject$20 != 0);
+goto label_137;
+
+
+label_136_false :
+assume ($status$6$3197.24$MouCreateClassObject$20 == 0);
+goto label_162;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3412)
+label_137:
+call RtlFreeUnicodeString ($fullClassName$10$3201.24$MouCreateClassObject$20);
+goto label_140;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3413)
+label_140:
+Mem[T.PUINT2] := Mem[T.PUINT2][$FullDeviceName$4$3168.35$MouCreateClassObject$20 := 0];
+goto label_141;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3415)
+label_141:
+goto label_141_true , label_141_false ;
+
+
+label_141_true :
+assume ($errorCode$9$3200.24$MouCreateClassObject$20 != 0);
+goto label_145;
+
+
+label_141_false :
+assume ($errorCode$9$3200.24$MouCreateClassObject$20 == 0);
+goto label_148;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3416)
+label_142:
+call MouseClassLogError ($result.question.21$, $errorCode$9$3200.24$MouCreateClassObject$20, $uniqueErrorValue$7$3198.24$MouCreateClassObject$20, $status$6$3197.24$MouCreateClassObject$20, $dumpCount$11$3202.24$MouCreateClassObject$20, $dumpData$12$3203.24$MouCreateClassObject$20, 0);
+goto label_148;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3417)
+label_145:
+goto label_145_true , label_145_false ;
+
+
+label_145_true :
+assume (Mem[T.P_DEVICE_OBJECT][$ClassDeviceObject$3$3167.28$MouCreateClassObject$20] != 0);
+goto label_147;
+
+
+label_145_false :
+assume (Mem[T.P_DEVICE_OBJECT][$ClassDeviceObject$3$3167.28$MouCreateClassObject$20] == 0);
+goto label_146;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3417)
+label_146:
+$result.question.21$ := $DriverObject$1$3165.28$MouCreateClassObject$20 ;
+goto label_142;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3417)
+label_147:
+$result.question.21$ := Mem[T.P_DEVICE_OBJECT][$ClassDeviceObject$3$3167.28$MouCreateClassObject$20] ;
+goto label_142;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3427)
+label_148:
+goto label_148_true , label_148_false ;
+
+
+label_148_true :
+assume ($deviceExtension$8$3199.24$MouCreateClassObject$20 != 0);
+goto label_149;
+
+
+label_148_false :
+assume ($deviceExtension$8$3199.24$MouCreateClassObject$20 == 0);
+goto label_154;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3427)
+label_149:
+goto label_149_true , label_149_false ;
+
+
+label_149_true :
+assume (Mem[T.InputData__DEVICE_EXTENSION][InputData__DEVICE_EXTENSION($deviceExtension$8$3199.24$MouCreateClassObject$20)] != 0);
+goto label_150;
+
+
+label_149_false :
+assume (Mem[T.InputData__DEVICE_EXTENSION][InputData__DEVICE_EXTENSION($deviceExtension$8$3199.24$MouCreateClassObject$20)] == 0);
+goto label_154;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3428)
+label_150:
+call ExFreePoolWithTag (Mem[T.InputData__DEVICE_EXTENSION][InputData__DEVICE_EXTENSION($deviceExtension$8$3199.24$MouCreateClassObject$20)], 0);
+goto label_153;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3429)
+label_153:
+Mem[T.InputData__DEVICE_EXTENSION] := Mem[T.InputData__DEVICE_EXTENSION][InputData__DEVICE_EXTENSION($deviceExtension$8$3199.24$MouCreateClassObject$20) := 0];
+goto label_154;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3431)
+label_154:
+goto label_154_true , label_154_false ;
+
+
+label_154_true :
+assume (Mem[T.P_DEVICE_OBJECT][$ClassDeviceObject$3$3167.28$MouCreateClassObject$20] != 0);
+goto label_155;
+
+
+label_154_false :
+assume (Mem[T.P_DEVICE_OBJECT][$ClassDeviceObject$3$3167.28$MouCreateClassObject$20] == 0);
+goto label_162;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3432)
+label_155:
+call IoDeleteDevice (Mem[T.P_DEVICE_OBJECT][$ClassDeviceObject$3$3167.28$MouCreateClassObject$20]);
+goto label_158;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3433)
+label_158:
+Mem[T.P_DEVICE_OBJECT] := Mem[T.P_DEVICE_OBJECT][$ClassDeviceObject$3$3167.28$MouCreateClassObject$20 := 0];
+goto label_162;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3437)
+label_159:
+// skip MouDebugPrint
+goto label_163;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3437)
+label_162:
+call havoc_stringTemp := __HAVOC_malloc(1);
+$MouDebugPrint.arg.2$22$ := havoc_stringTemp ;
+goto label_159;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(3439)
+label_163:
+$result.MouCreateClassObject$3164.0$1$ := $status$6$3197.24$MouCreateClassObject$20 ;
+goto label_1;
+
+}
+
diff --git a/Test/havoc0/MouseClassFindMorePorts.bpl b/Test/havoc0/MouseClassFindMorePorts.bpl
new file mode 100644
index 00000000..627d8502
--- /dev/null
+++ b/Test/havoc0/MouseClassFindMorePorts.bpl
@@ -0,0 +1,3837 @@
+type byte, name;
+function OneByteToInt(byte) returns (int);
+function TwoBytesToInt(byte, byte) returns (int);
+function FourBytesToInt(byte, byte, byte, byte) returns (int);
+axiom(forall b0:byte, c0:byte :: {OneByteToInt(b0), OneByteToInt(c0)} OneByteToInt(b0) == OneByteToInt(c0) ==> b0 == c0);
+axiom(forall b0:byte, b1: byte, c0:byte, c1:byte :: {TwoBytesToInt(b0, b1), TwoBytesToInt(c0, c1)} TwoBytesToInt(b0, b1) == TwoBytesToInt(c0, c1) ==> b0 == c0 && b1 == c1);
+axiom(forall b0:byte, b1: byte, b2:byte, b3:byte, c0:byte, c1:byte, c2:byte, c3:byte :: {FourBytesToInt(b0, b1, b2, b3), FourBytesToInt(c0, c1, c2, c3)} FourBytesToInt(b0, b1, b2, b3) == FourBytesToInt(c0, c1, c2, c3) ==> b0 == c0 && b1 == c1 && b2 == c2 && b3 == c3);
+
+// Mutable
+var Mem_BYTE:[int]byte;
+var alloc:[int]name;
+
+
+function Field(int) returns (name);
+function Base(int) returns (int);
+
+// Constants
+const unique UNALLOCATED:name;
+const unique ALLOCATED: name;
+const unique FREED:name;
+
+const unique BYTE:name;
+
+function Equal([int]bool, [int]bool) returns (bool);
+function Subset([int]bool, [int]bool) returns (bool);
+function Disjoint([int]bool, [int]bool) returns (bool);
+
+function Empty() returns ([int]bool);
+function SetTrue() returns ([int]bool);
+function Singleton(int) returns ([int]bool);
+function Reachable([int,int]bool, int) returns ([int]bool);
+function Union([int]bool, [int]bool) returns ([int]bool);
+function Intersection([int]bool, [int]bool) returns ([int]bool);
+function Difference([int]bool, [int]bool) returns ([int]bool);
+function Dereference([int]bool, [int]int) returns ([int]bool);
+function Inverse(f:[int]int, x:int) returns ([int]bool);
+
+function AtLeast(int, int) returns ([int]bool);
+function Rep(int, int) returns (int);
+axiom(forall n:int, x:int, y:int :: {AtLeast(n,x)[y]} AtLeast(n,x)[y] ==> x <= y && Rep(n,x) == Rep(n,y));
+axiom(forall n:int, x:int, y:int :: {AtLeast(n,x),Rep(n,x),Rep(n,y)} x <= y && Rep(n,x) == Rep(n,y) ==> AtLeast(n,x)[y]);
+axiom(forall n:int, x:int :: {AtLeast(n,x)} AtLeast(n,x)[x]);
+axiom(forall n:int, x:int, z:int :: {PLUS(x,n,z)} Rep(n,x) == Rep(n,PLUS(x,n,z)));
+axiom(forall n:int, x:int :: {Rep(n,x)} (exists k:int :: Rep(n,x) - x == n*k));
+
+/*
+function AtLeast(int, int) returns ([int]bool);
+function ModEqual(int, int, int) returns (bool);
+axiom(forall n:int, x:int :: ModEqual(n,x,x));
+axiom(forall n:int, x:int, y:int :: {ModEqual(n,x,y)} ModEqual(n,x,y) ==> ModEqual(n,y,x));
+axiom(forall n:int, x:int, y:int, z:int :: {ModEqual(n,x,y), ModEqual(n,y,z)} ModEqual(n,x,y) && ModEqual(n,y,z) ==> ModEqual(n,x,z));
+axiom(forall n:int, x:int, z:int :: {PLUS(x,n,z)} ModEqual(n,x,PLUS(x,n,z)));
+axiom(forall n:int, x:int, y:int :: {ModEqual(n,x,y)} ModEqual(n,x,y) ==> (exists k:int :: x - y == n*k));
+axiom(forall x:int, n:int, y:int :: {AtLeast(n,x)[y]}{ModEqual(n,x,y)} AtLeast(n,x)[y] <==> x <= y && ModEqual(n,x,y));
+axiom(forall x:int, n:int :: {AtLeast(n,x)} AtLeast(n,x)[x]);
+*/
+
+function Array(int, int, int) returns ([int]bool);
+axiom(forall x:int, n:int, z:int :: {Array(x,n,z)} z <= 0 ==> Equal(Array(x,n,z), Empty()));
+axiom(forall x:int, n:int, z:int :: {Array(x,n,z)} z > 0 ==> Equal(Array(x,n,z), Difference(AtLeast(n,x),AtLeast(n,PLUS(x,n,z)))));
+
+
+axiom(forall x:int :: !Empty()[x]);
+
+axiom(forall x:int :: SetTrue()[x]);
+
+axiom(forall x:int, y:int :: {Singleton(y)[x]} Singleton(y)[x] <==> x == y);
+axiom(forall y:int :: {Singleton(y)} Singleton(y)[y]);
+
+/* this formulation of Union IS more complete than the earlier one */
+/* (A U B)[e], A[d], A U B = Singleton(c), d != e */
+axiom(forall x:int, S:[int]bool, T:[int]bool :: {Union(S,T)[x]}{Union(S,T),S[x]}{Union(S,T),T[x]} Union(S,T)[x] <==> S[x] || T[x]);
+axiom(forall x:int, S:[int]bool, T:[int]bool :: {Intersection(S,T)[x]}{Intersection(S,T),S[x]}{Intersection(S,T),T[x]} Intersection(S,T)[x] <==> S[x] && T[x]);
+axiom(forall x:int, S:[int]bool, T:[int]bool :: {Difference(S,T)[x]}{Difference(S,T),S[x]}{Difference(S,T),T[x]} Difference(S,T)[x] <==> S[x] && !T[x]);
+
+axiom(forall S:[int]bool, T:[int]bool :: {Equal(S,T)} Equal(S,T) <==> Subset(S,T) && Subset(T,S));
+axiom(forall x:int, S:[int]bool, T:[int]bool :: {S[x],Subset(S,T)}{T[x],Subset(S,T)} S[x] && Subset(S,T) ==> T[x]);
+axiom(forall S:[int]bool, T:[int]bool :: {Subset(S,T)} Subset(S,T) || (exists x:int :: S[x] && !T[x]));
+axiom(forall x:int, S:[int]bool, T:[int]bool :: {S[x],Disjoint(S,T)}{T[x],Disjoint(S,T)} !(S[x] && Disjoint(S,T) && T[x]));
+axiom(forall S:[int]bool, T:[int]bool :: {Disjoint(S,T)} Disjoint(S,T) || (exists x:int :: S[x] && T[x]));
+
+axiom(forall f:[int]int, x:int :: {Inverse(f,f[x])} Inverse(f,f[x])[x]);
+axiom(forall f:[int]int, x:int, y:int :: {Inverse(f,y), f[x]} Inverse(f,y)[x] ==> f[x] == y);
+axiom(forall f:[int]int, x:int, y:int :: {Inverse(f[x := y],y)} Equal(Inverse(f[x := y],y), Union(Inverse(f,y), Singleton(x))));
+axiom(forall f:[int]int, x:int, y:int, z:int :: {Inverse(f[x := y],z)} y == z || Equal(Inverse(f[x := y],z), Difference(Inverse(f,z), Singleton(x))));
+
+
+axiom(forall x:int, S:[int]bool, M:[int]int :: {Dereference(S,M)[x]} Dereference(S,M)[x] ==> (exists y:int :: x == M[y] && S[y]));
+axiom(forall x:int, S:[int]bool, M:[int]int :: {M[x], S[x], Dereference(S,M)} S[x] ==> Dereference(S,M)[M[x]]);
+axiom(forall x:int, y:int, S:[int]bool, M:[int]int :: {Dereference(S,M[x := y])} !S[x] ==> Equal(Dereference(S,M[x := y]), Dereference(S,M)));
+axiom(forall x:int, y:int, S:[int]bool, M:[int]int :: {Dereference(S,M[x := y])}
+ S[x] && Equal(Intersection(Inverse(M,M[x]), S), Singleton(x)) ==> Equal(Dereference(S,M[x := y]), Union(Difference(Dereference(S,M), Singleton(M[x])), Singleton(y))));
+axiom(forall x:int, y:int, S:[int]bool, M:[int]int :: {Dereference(S,M[x := y])}
+ S[x] && !Equal(Intersection(Inverse(M,M[x]), S), Singleton(x)) ==> Equal(Dereference(S,M[x := y]), Union(Dereference(S,M), Singleton(y))));
+
+function Unified([name][int]int) returns ([int]int);
+axiom(forall M:[name][int]int, x:int :: {Unified(M)[x]} Unified(M)[x] == M[Field(x)][x]);
+axiom(forall M:[name][int]int, x:int, y:int :: {Unified(M[Field(x) := M[Field(x)][x := y]])} Unified(M[Field(x) := M[Field(x)][x := y]]) == Unified(M)[x := y]);
+// Memory model
+
+var Mem: [name][int]int;
+
+function Match(a:int, t:name) returns (bool);
+function HasType(v:int, t:name, m:[name][int]int) returns (bool);
+function Values(t:name, m:[name][int]int) returns ([int]bool);
+function T.Ptr(t:name) returns (name);
+
+axiom(forall v:int, t:name, m:[name][int]int :: {Values(t, m)[v]} Values(t, m)[v] ==> HasType(v, t, m));
+axiom(forall v:int, t:name, m:[name][int]int :: {HasType(v, t, m), Values(t, m)} HasType(v, t, m) ==> Values(t, m)[v]);
+
+axiom(forall a:int, t:name :: {Match(a, T.Ptr(t))} Match(a, T.Ptr(t)) <==> Field(a) == T.Ptr(t));
+axiom(forall v:int, t:name, m:[name][int]int :: {HasType(v, T.Ptr(t), m)} HasType(v, T.Ptr(t), m) <==> (v == 0 || (v > 0 && Match(v, t))));
+
+axiom(forall v:int, t:name, m1:[name][int]int, m2:[name][int]int :: {HasType(v, t, m1), HasType(v, t, m2)}
+ (HasType(v, t, m1) <==> HasType(v, t, m2)));
+
+// Field declarations
+
+const unique T.Guid_WMIGUIDREGINFO:name;
+const unique T.InstanceCount_WMIGUIDREGINFO:name;
+const unique T.Flags_WMIGUIDREGINFO:name;
+const unique T.OperationID__ACCESS_STATE:name;
+const unique T.SecurityEvaluated__ACCESS_STATE:name;
+const unique T.GenerateAudit__ACCESS_STATE:name;
+const unique T.GenerateOnClose__ACCESS_STATE:name;
+const unique T.PrivilegesAllocated__ACCESS_STATE:name;
+const unique T.Flags__ACCESS_STATE:name;
+const unique T.RemainingDesiredAccess__ACCESS_STATE:name;
+const unique T.PreviouslyGrantedAccess__ACCESS_STATE:name;
+const unique T.OriginalDesiredAccess__ACCESS_STATE:name;
+const unique T.SubjectSecurityContext__ACCESS_STATE:name;
+const unique T.SecurityDescriptor__ACCESS_STATE:name;
+const unique T.AuxData__ACCESS_STATE:name;
+const unique T.Privileges__ACCESS_STATE:name;
+const unique T.AuditPrivileges__ACCESS_STATE:name;
+const unique T.ObjectName__ACCESS_STATE:name;
+const unique T.ObjectTypeName__ACCESS_STATE:name;
+const unique T.InterfaceType__CM_FULL_RESOURCE_DESCRIPTOR:name;
+const unique T.BusNumber__CM_FULL_RESOURCE_DESCRIPTOR:name;
+const unique T.PartialResourceList__CM_FULL_RESOURCE_DESCRIPTOR:name;
+const unique T.Type__CM_PARTIAL_RESOURCE_DESCRIPTOR:name;
+const unique T.ShareDisposition__CM_PARTIAL_RESOURCE_DESCRIPTOR:name;
+const unique T.Flags__CM_PARTIAL_RESOURCE_DESCRIPTOR:name;
+const unique T.u__CM_PARTIAL_RESOURCE_DESCRIPTOR:name;
+const unique T.Version__CM_PARTIAL_RESOURCE_LIST:name;
+const unique T.Revision__CM_PARTIAL_RESOURCE_LIST:name;
+const unique T.Count__CM_PARTIAL_RESOURCE_LIST:name;
+const unique T.PartialDescriptors__CM_PARTIAL_RESOURCE_LIST:name;
+const unique T.Count__CM_RESOURCE_LIST:name;
+const unique T.List__CM_RESOURCE_LIST:name;
+const unique T.Size__DEVICE_CAPABILITIES:name;
+const unique T.Version__DEVICE_CAPABILITIES:name;
+const unique T.DeviceD1__DEVICE_CAPABILITIES:name;
+const unique T.DeviceD2__DEVICE_CAPABILITIES:name;
+const unique T.LockSupported__DEVICE_CAPABILITIES:name;
+const unique T.EjectSupported__DEVICE_CAPABILITIES:name;
+const unique T.Removable__DEVICE_CAPABILITIES:name;
+const unique T.DockDevice__DEVICE_CAPABILITIES:name;
+const unique T.UniqueID__DEVICE_CAPABILITIES:name;
+const unique T.SilentInstall__DEVICE_CAPABILITIES:name;
+const unique T.RawDeviceOK__DEVICE_CAPABILITIES:name;
+const unique T.SurpriseRemovalOK__DEVICE_CAPABILITIES:name;
+const unique T.WakeFromD0__DEVICE_CAPABILITIES:name;
+const unique T.WakeFromD1__DEVICE_CAPABILITIES:name;
+const unique T.WakeFromD2__DEVICE_CAPABILITIES:name;
+const unique T.WakeFromD3__DEVICE_CAPABILITIES:name;
+const unique T.HardwareDisabled__DEVICE_CAPABILITIES:name;
+const unique T.NonDynamic__DEVICE_CAPABILITIES:name;
+const unique T.WarmEjectSupported__DEVICE_CAPABILITIES:name;
+const unique T.NoDisplayInUI__DEVICE_CAPABILITIES:name;
+const unique T.Reserved__DEVICE_CAPABILITIES:name;
+const unique T.Address__DEVICE_CAPABILITIES:name;
+const unique T.UINumber__DEVICE_CAPABILITIES:name;
+const unique T.DeviceState__DEVICE_CAPABILITIES:name;
+const unique T.SystemWake__DEVICE_CAPABILITIES:name;
+const unique T.DeviceWake__DEVICE_CAPABILITIES:name;
+const unique T.D1Latency__DEVICE_CAPABILITIES:name;
+const unique T.D2Latency__DEVICE_CAPABILITIES:name;
+const unique T.D3Latency__DEVICE_CAPABILITIES:name;
+const unique T.Self__DEVICE_EXTENSION:name;
+const unique T.TrueClassDevice__DEVICE_EXTENSION:name;
+const unique T.TopPort__DEVICE_EXTENSION:name;
+const unique T.PDO__DEVICE_EXTENSION:name;
+const unique T.RemoveLock__DEVICE_EXTENSION:name;
+const unique T.PnP__DEVICE_EXTENSION:name;
+const unique T.Started__DEVICE_EXTENSION:name;
+const unique T.OkayToLogOverflow__DEVICE_EXTENSION:name;
+const unique T.WaitWakeSpinLock__DEVICE_EXTENSION:name;
+const unique T.TrustedSubsystemCount__DEVICE_EXTENSION:name;
+const unique T.InputCount__DEVICE_EXTENSION:name;
+const unique T.SymbolicLinkName__DEVICE_EXTENSION:name;
+const unique T.InputData__DEVICE_EXTENSION:name;
+const unique T.DataIn__DEVICE_EXTENSION:name;
+const unique T.DataOut__DEVICE_EXTENSION:name;
+const unique T.MouseAttributes__DEVICE_EXTENSION:name;
+const unique T.SpinLock__DEVICE_EXTENSION:name;
+const unique T.ReadQueue__DEVICE_EXTENSION:name;
+const unique T.SequenceNumber__DEVICE_EXTENSION:name;
+const unique T.DeviceState__DEVICE_EXTENSION:name;
+const unique T.SystemState__DEVICE_EXTENSION:name;
+const unique T.UnitId__DEVICE_EXTENSION:name;
+const unique T.WmiLibInfo__DEVICE_EXTENSION:name;
+const unique T.SystemToDeviceState__DEVICE_EXTENSION:name;
+const unique T.MinDeviceWakeState__DEVICE_EXTENSION:name;
+const unique T.MinSystemWakeState__DEVICE_EXTENSION:name;
+const unique T.WaitWakeIrp__DEVICE_EXTENSION:name;
+const unique T.ExtraWaitWakeIrp__DEVICE_EXTENSION:name;
+const unique T.TargetNotifyHandle__DEVICE_EXTENSION:name;
+const unique T.Link__DEVICE_EXTENSION:name;
+const unique T.File__DEVICE_EXTENSION:name;
+const unique T.Enabled__DEVICE_EXTENSION:name;
+const unique T.WaitWakeEnabled__DEVICE_EXTENSION:name;
+const unique T.SurpriseRemoved__DEVICE_EXTENSION:name;
+const unique T.Type__DEVICE_OBJECT:name;
+const unique T.Size__DEVICE_OBJECT:name;
+const unique T.ReferenceCount__DEVICE_OBJECT:name;
+const unique T.DriverObject__DEVICE_OBJECT:name;
+const unique T.NextDevice__DEVICE_OBJECT:name;
+const unique T.AttachedDevice__DEVICE_OBJECT:name;
+const unique T.CurrentIrp__DEVICE_OBJECT:name;
+const unique T.Timer__DEVICE_OBJECT:name;
+const unique T.Flags__DEVICE_OBJECT:name;
+const unique T.Characteristics__DEVICE_OBJECT:name;
+const unique T.Vpb__DEVICE_OBJECT:name;
+const unique T.DeviceExtension__DEVICE_OBJECT:name;
+const unique T.DeviceType__DEVICE_OBJECT:name;
+const unique T.StackSize__DEVICE_OBJECT:name;
+const unique T.Queue__DEVICE_OBJECT:name;
+const unique T.AlignmentRequirement__DEVICE_OBJECT:name;
+const unique T.DeviceQueue__DEVICE_OBJECT:name;
+const unique T.Dpc__DEVICE_OBJECT:name;
+const unique T.ActiveThreadCount__DEVICE_OBJECT:name;
+const unique T.SecurityDescriptor__DEVICE_OBJECT:name;
+const unique T.DeviceLock__DEVICE_OBJECT:name;
+const unique T.SectorSize__DEVICE_OBJECT:name;
+const unique T.Spare1__DEVICE_OBJECT:name;
+const unique T.DeviceObjectExtension__DEVICE_OBJECT:name;
+const unique T.Reserved__DEVICE_OBJECT:name;
+const unique T.Type__DEVOBJ_EXTENSION:name;
+const unique T.Size__DEVOBJ_EXTENSION:name;
+const unique T.DeviceObject__DEVOBJ_EXTENSION:name;
+const unique T.__unnamed_4_c9b2e921__DISPATCHER_HEADER:name;
+const unique T.SignalState__DISPATCHER_HEADER:name;
+const unique T.WaitListHead__DISPATCHER_HEADER:name;
+const unique T.DriverObject__DRIVER_EXTENSION:name;
+const unique T.AddDevice__DRIVER_EXTENSION:name;
+const unique T.Count__DRIVER_EXTENSION:name;
+const unique T.ServiceKeyName__DRIVER_EXTENSION:name;
+const unique T.Type__DRIVER_OBJECT:name;
+const unique T.Size__DRIVER_OBJECT:name;
+const unique T.DeviceObject__DRIVER_OBJECT:name;
+const unique T.Flags__DRIVER_OBJECT:name;
+const unique T.DriverStart__DRIVER_OBJECT:name;
+const unique T.DriverSize__DRIVER_OBJECT:name;
+const unique T.DriverSection__DRIVER_OBJECT:name;
+const unique T.DriverExtension__DRIVER_OBJECT:name;
+const unique T.DriverName__DRIVER_OBJECT:name;
+const unique T.HardwareDatabase__DRIVER_OBJECT:name;
+const unique T.FastIoDispatch__DRIVER_OBJECT:name;
+const unique T.DriverInit__DRIVER_OBJECT:name;
+const unique T.DriverStartIo__DRIVER_OBJECT:name;
+const unique T.DriverUnload__DRIVER_OBJECT:name;
+const unique T.MajorFunction__DRIVER_OBJECT:name;
+const unique T.SystemResourcesList__ERESOURCE:name;
+const unique T.OwnerTable__ERESOURCE:name;
+const unique T.ActiveCount__ERESOURCE:name;
+const unique T.Flag__ERESOURCE:name;
+const unique T.SharedWaiters__ERESOURCE:name;
+const unique T.ExclusiveWaiters__ERESOURCE:name;
+const unique T.OwnerEntry__ERESOURCE:name;
+const unique T.ActiveEntries__ERESOURCE:name;
+const unique T.ContentionCount__ERESOURCE:name;
+const unique T.NumberOfSharedWaiters__ERESOURCE:name;
+const unique T.NumberOfExclusiveWaiters__ERESOURCE:name;
+const unique T.__unnamed_4_46b62f69__ERESOURCE:name;
+const unique T.SpinLock__ERESOURCE:name;
+const unique T.SizeOfFastIoDispatch__FAST_IO_DISPATCH:name;
+const unique T.FastIoCheckIfPossible__FAST_IO_DISPATCH:name;
+const unique T.FastIoRead__FAST_IO_DISPATCH:name;
+const unique T.FastIoWrite__FAST_IO_DISPATCH:name;
+const unique T.FastIoQueryBasicInfo__FAST_IO_DISPATCH:name;
+const unique T.FastIoQueryStandardInfo__FAST_IO_DISPATCH:name;
+const unique T.FastIoLock__FAST_IO_DISPATCH:name;
+const unique T.FastIoUnlockSingle__FAST_IO_DISPATCH:name;
+const unique T.FastIoUnlockAll__FAST_IO_DISPATCH:name;
+const unique T.FastIoUnlockAllByKey__FAST_IO_DISPATCH:name;
+const unique T.FastIoDeviceControl__FAST_IO_DISPATCH:name;
+const unique T.AcquireFileForNtCreateSection__FAST_IO_DISPATCH:name;
+const unique T.ReleaseFileForNtCreateSection__FAST_IO_DISPATCH:name;
+const unique T.FastIoDetachDevice__FAST_IO_DISPATCH:name;
+const unique T.FastIoQueryNetworkOpenInfo__FAST_IO_DISPATCH:name;
+const unique T.AcquireForModWrite__FAST_IO_DISPATCH:name;
+const unique T.MdlRead__FAST_IO_DISPATCH:name;
+const unique T.MdlReadComplete__FAST_IO_DISPATCH:name;
+const unique T.PrepareMdlWrite__FAST_IO_DISPATCH:name;
+const unique T.MdlWriteComplete__FAST_IO_DISPATCH:name;
+const unique T.FastIoReadCompressed__FAST_IO_DISPATCH:name;
+const unique T.FastIoWriteCompressed__FAST_IO_DISPATCH:name;
+const unique T.MdlReadCompleteCompressed__FAST_IO_DISPATCH:name;
+const unique T.MdlWriteCompleteCompressed__FAST_IO_DISPATCH:name;
+const unique T.FastIoQueryOpen__FAST_IO_DISPATCH:name;
+const unique T.ReleaseForModWrite__FAST_IO_DISPATCH:name;
+const unique T.AcquireForCcFlush__FAST_IO_DISPATCH:name;
+const unique T.ReleaseForCcFlush__FAST_IO_DISPATCH:name;
+const unique T.Count__FAST_MUTEX:name;
+const unique T.Owner__FAST_MUTEX:name;
+const unique T.Contention__FAST_MUTEX:name;
+const unique T.Gate__FAST_MUTEX:name;
+const unique T.OldIrql__FAST_MUTEX:name;
+const unique T.CreationTime__FILE_BASIC_INFORMATION:name;
+const unique T.LastAccessTime__FILE_BASIC_INFORMATION:name;
+const unique T.LastWriteTime__FILE_BASIC_INFORMATION:name;
+const unique T.ChangeTime__FILE_BASIC_INFORMATION:name;
+const unique T.FileAttributes__FILE_BASIC_INFORMATION:name;
+const unique T.CreationTime__FILE_NETWORK_OPEN_INFORMATION:name;
+const unique T.LastAccessTime__FILE_NETWORK_OPEN_INFORMATION:name;
+const unique T.LastWriteTime__FILE_NETWORK_OPEN_INFORMATION:name;
+const unique T.ChangeTime__FILE_NETWORK_OPEN_INFORMATION:name;
+const unique T.AllocationSize__FILE_NETWORK_OPEN_INFORMATION:name;
+const unique T.EndOfFile__FILE_NETWORK_OPEN_INFORMATION:name;
+const unique T.FileAttributes__FILE_NETWORK_OPEN_INFORMATION:name;
+const unique T.Type__FILE_OBJECT:name;
+const unique T.Size__FILE_OBJECT:name;
+const unique T.DeviceObject__FILE_OBJECT:name;
+const unique T.Vpb__FILE_OBJECT:name;
+const unique T.FsContext__FILE_OBJECT:name;
+const unique T.FsContext2__FILE_OBJECT:name;
+const unique T.SectionObjectPointer__FILE_OBJECT:name;
+const unique T.PrivateCacheMap__FILE_OBJECT:name;
+const unique T.FinalStatus__FILE_OBJECT:name;
+const unique T.RelatedFileObject__FILE_OBJECT:name;
+const unique T.LockOperation__FILE_OBJECT:name;
+const unique T.DeletePending__FILE_OBJECT:name;
+const unique T.ReadAccess__FILE_OBJECT:name;
+const unique T.WriteAccess__FILE_OBJECT:name;
+const unique T.DeleteAccess__FILE_OBJECT:name;
+const unique T.SharedRead__FILE_OBJECT:name;
+const unique T.SharedWrite__FILE_OBJECT:name;
+const unique T.SharedDelete__FILE_OBJECT:name;
+const unique T.Flags__FILE_OBJECT:name;
+const unique T.FileName__FILE_OBJECT:name;
+const unique T.CurrentByteOffset__FILE_OBJECT:name;
+const unique T.Waiters__FILE_OBJECT:name;
+const unique T.Busy__FILE_OBJECT:name;
+const unique T.LastLock__FILE_OBJECT:name;
+const unique T.Lock__FILE_OBJECT:name;
+const unique T.Event__FILE_OBJECT:name;
+const unique T.CompletionContext__FILE_OBJECT:name;
+const unique T.IrpListLock__FILE_OBJECT:name;
+const unique T.IrpList__FILE_OBJECT:name;
+const unique T.FileObjectExtension__FILE_OBJECT:name;
+const unique T.AllocationSize__FILE_STANDARD_INFORMATION:name;
+const unique T.EndOfFile__FILE_STANDARD_INFORMATION:name;
+const unique T.NumberOfLinks__FILE_STANDARD_INFORMATION:name;
+const unique T.DeletePending__FILE_STANDARD_INFORMATION:name;
+const unique T.Directory__FILE_STANDARD_INFORMATION:name;
+const unique T.Debug__GLOBALS:name;
+const unique T.GrandMaster__GLOBALS:name;
+const unique T.AssocClassList__GLOBALS:name;
+const unique T.NumAssocClass__GLOBALS:name;
+const unique T.Opens__GLOBALS:name;
+const unique T.NumberLegacyPorts__GLOBALS:name;
+const unique T.Mutex__GLOBALS:name;
+const unique T.ConnectOneClassToOnePort__GLOBALS:name;
+const unique T.PortsServiced__GLOBALS:name;
+const unique T.InitExtension__GLOBALS:name;
+const unique T.RegistryPath__GLOBALS:name;
+const unique T.BaseClassName__GLOBALS:name;
+const unique T.BaseClassBuffer__GLOBALS:name;
+const unique T.LegacyDeviceList__GLOBALS:name;
+const unique T.Data1__GUID:name;
+const unique T.Data2__GUID:name;
+const unique T.Data3__GUID:name;
+const unique T.Data4__GUID:name;
+const unique T.PrivilegeCount__INITIAL_PRIVILEGE_SET:name;
+const unique T.Control__INITIAL_PRIVILEGE_SET:name;
+const unique T.Privilege__INITIAL_PRIVILEGE_SET:name;
+const unique T.Size__INTERFACE:name;
+const unique T.Version__INTERFACE:name;
+const unique T.Context__INTERFACE:name;
+const unique T.InterfaceReference__INTERFACE:name;
+const unique T.InterfaceDereference__INTERFACE:name;
+const unique T.Port__IO_COMPLETION_CONTEXT:name;
+const unique T.Key__IO_COMPLETION_CONTEXT:name;
+const unique T.Common__IO_REMOVE_LOCK:name;
+const unique T.Dbg__IO_REMOVE_LOCK:name;
+const unique T.Removed__IO_REMOVE_LOCK_COMMON_BLOCK:name;
+const unique T.Reserved__IO_REMOVE_LOCK_COMMON_BLOCK:name;
+const unique T.IoCount__IO_REMOVE_LOCK_COMMON_BLOCK:name;
+const unique T.RemoveEvent__IO_REMOVE_LOCK_COMMON_BLOCK:name;
+const unique T.Signature__IO_REMOVE_LOCK_DBG_BLOCK:name;
+const unique T.HighWatermark__IO_REMOVE_LOCK_DBG_BLOCK:name;
+const unique T.MaxLockedTicks__IO_REMOVE_LOCK_DBG_BLOCK:name;
+const unique T.AllocateTag__IO_REMOVE_LOCK_DBG_BLOCK:name;
+const unique T.LockList__IO_REMOVE_LOCK_DBG_BLOCK:name;
+const unique T.Spin__IO_REMOVE_LOCK_DBG_BLOCK:name;
+const unique T.LowMemoryCount__IO_REMOVE_LOCK_DBG_BLOCK:name;
+const unique T.Reserved1__IO_REMOVE_LOCK_DBG_BLOCK:name;
+const unique T.Reserved2__IO_REMOVE_LOCK_DBG_BLOCK:name;
+const unique T.Blocks__IO_REMOVE_LOCK_DBG_BLOCK:name;
+const unique T.Option__IO_RESOURCE_DESCRIPTOR:name;
+const unique T.Type__IO_RESOURCE_DESCRIPTOR:name;
+const unique T.ShareDisposition__IO_RESOURCE_DESCRIPTOR:name;
+const unique T.Spare1__IO_RESOURCE_DESCRIPTOR:name;
+const unique T.Flags__IO_RESOURCE_DESCRIPTOR:name;
+const unique T.Spare2__IO_RESOURCE_DESCRIPTOR:name;
+const unique T.u__IO_RESOURCE_DESCRIPTOR:name;
+const unique T.Version__IO_RESOURCE_LIST:name;
+const unique T.Revision__IO_RESOURCE_LIST:name;
+const unique T.Count__IO_RESOURCE_LIST:name;
+const unique T.Descriptors__IO_RESOURCE_LIST:name;
+const unique T.ListSize__IO_RESOURCE_REQUIREMENTS_LIST:name;
+const unique T.InterfaceType__IO_RESOURCE_REQUIREMENTS_LIST:name;
+const unique T.BusNumber__IO_RESOURCE_REQUIREMENTS_LIST:name;
+const unique T.SlotNumber__IO_RESOURCE_REQUIREMENTS_LIST:name;
+const unique T.Reserved__IO_RESOURCE_REQUIREMENTS_LIST:name;
+const unique T.AlternativeLists__IO_RESOURCE_REQUIREMENTS_LIST:name;
+const unique T.List__IO_RESOURCE_REQUIREMENTS_LIST:name;
+const unique T.SecurityQos__IO_SECURITY_CONTEXT:name;
+const unique T.AccessState__IO_SECURITY_CONTEXT:name;
+const unique T.DesiredAccess__IO_SECURITY_CONTEXT:name;
+const unique T.FullCreateOptions__IO_SECURITY_CONTEXT:name;
+const unique T.MajorFunction__IO_STACK_LOCATION:name;
+const unique T.MinorFunction__IO_STACK_LOCATION:name;
+const unique T.Flags__IO_STACK_LOCATION:name;
+const unique T.Control__IO_STACK_LOCATION:name;
+const unique T.Parameters__IO_STACK_LOCATION:name;
+const unique T.DeviceObject__IO_STACK_LOCATION:name;
+const unique T.FileObject__IO_STACK_LOCATION:name;
+const unique T.CompletionRoutine__IO_STACK_LOCATION:name;
+const unique T.Context__IO_STACK_LOCATION:name;
+const unique T.__unnamed_4_16aff58e__IO_STATUS_BLOCK:name;
+const unique T.Information__IO_STATUS_BLOCK:name;
+const unique T.Type__IRP:name;
+const unique T.Size__IRP:name;
+const unique T.MdlAddress__IRP:name;
+const unique T.Flags__IRP:name;
+const unique T.AssociatedIrp__IRP:name;
+const unique T.ThreadListEntry__IRP:name;
+const unique T.IoStatus__IRP:name;
+const unique T.RequestorMode__IRP:name;
+const unique T.PendingReturned__IRP:name;
+const unique T.StackCount__IRP:name;
+const unique T.CurrentLocation__IRP:name;
+const unique T.Cancel__IRP:name;
+const unique T.CancelIrql__IRP:name;
+const unique T.ApcEnvironment__IRP:name;
+const unique T.AllocationFlags__IRP:name;
+const unique T.UserIosb__IRP:name;
+const unique T.UserEvent__IRP:name;
+const unique T.Overlay__IRP:name;
+const unique T.CancelRoutine__IRP:name;
+const unique T.UserBuffer__IRP:name;
+const unique T.Tail__IRP:name;
+const unique T.Type__KAPC:name;
+const unique T.SpareByte0__KAPC:name;
+const unique T.Size__KAPC:name;
+const unique T.SpareByte1__KAPC:name;
+const unique T.SpareLong0__KAPC:name;
+const unique T.Thread__KAPC:name;
+const unique T.ApcListEntry__KAPC:name;
+const unique T.KernelRoutine__KAPC:name;
+const unique T.RundownRoutine__KAPC:name;
+const unique T.NormalRoutine__KAPC:name;
+const unique T.NormalContext__KAPC:name;
+const unique T.SystemArgument1__KAPC:name;
+const unique T.SystemArgument2__KAPC:name;
+const unique T.ApcStateIndex__KAPC:name;
+const unique T.ApcMode__KAPC:name;
+const unique T.Inserted__KAPC:name;
+const unique T.Type__KDEVICE_QUEUE:name;
+const unique T.Size__KDEVICE_QUEUE:name;
+const unique T.DeviceListHead__KDEVICE_QUEUE:name;
+const unique T.Lock__KDEVICE_QUEUE:name;
+const unique T.Busy__KDEVICE_QUEUE:name;
+const unique T.DeviceListEntry__KDEVICE_QUEUE_ENTRY:name;
+const unique T.SortKey__KDEVICE_QUEUE_ENTRY:name;
+const unique T.Inserted__KDEVICE_QUEUE_ENTRY:name;
+const unique T.Type__KDPC:name;
+const unique T.Importance__KDPC:name;
+const unique T.Number__KDPC:name;
+const unique T.DpcListEntry__KDPC:name;
+const unique T.DeferredRoutine__KDPC:name;
+const unique T.DeferredContext__KDPC:name;
+const unique T.SystemArgument1__KDPC:name;
+const unique T.SystemArgument2__KDPC:name;
+const unique T.DpcData__KDPC:name;
+const unique T.Header__KEVENT:name;
+const unique T.Header__KSEMAPHORE:name;
+const unique T.Limit__KSEMAPHORE:name;
+const unique T.__unnamed_8_8684a3e7__LARGE_INTEGER:name;
+const unique T.u__LARGE_INTEGER:name;
+const unique T.QuadPart__LARGE_INTEGER:name;
+const unique T.Flink__LIST_ENTRY:name;
+const unique T.Blink__LIST_ENTRY:name;
+const unique T.LowPart__LUID:name;
+const unique T.HighPart__LUID:name;
+const unique T.Luid__LUID_AND_ATTRIBUTES:name;
+const unique T.Attributes__LUID_AND_ATTRIBUTES:name;
+const unique T.Next__MDL:name;
+const unique T.Size__MDL:name;
+const unique T.MdlFlags__MDL:name;
+const unique T.Process__MDL:name;
+const unique T.MappedSystemVa__MDL:name;
+const unique T.StartVa__MDL:name;
+const unique T.ByteCount__MDL:name;
+const unique T.ByteOffset__MDL:name;
+const unique T.MouseIdentifier__MOUSE_ATTRIBUTES:name;
+const unique T.NumberOfButtons__MOUSE_ATTRIBUTES:name;
+const unique T.SampleRate__MOUSE_ATTRIBUTES:name;
+const unique T.InputDataQueueLength__MOUSE_ATTRIBUTES:name;
+const unique T.UnitId__MOUSE_INPUT_DATA:name;
+const unique T.Flags__MOUSE_INPUT_DATA:name;
+const unique T.__unnamed_4_9c11ed91__MOUSE_INPUT_DATA:name;
+const unique T.RawButtons__MOUSE_INPUT_DATA:name;
+const unique T.LastX__MOUSE_INPUT_DATA:name;
+const unique T.LastY__MOUSE_INPUT_DATA:name;
+const unique T.ExtraInformation__MOUSE_INPUT_DATA:name;
+const unique T.OwnerThread__OWNER_ENTRY:name;
+const unique T.__unnamed_4_c1e23b02__OWNER_ENTRY:name;
+const unique T.File__PORT:name;
+const unique T.Port__PORT:name;
+const unique T.Enabled__PORT:name;
+const unique T.Reserved__PORT:name;
+const unique T.Free__PORT:name;
+const unique T.SequenceD1__POWER_SEQUENCE:name;
+const unique T.SequenceD2__POWER_SEQUENCE:name;
+const unique T.SequenceD3__POWER_SEQUENCE:name;
+const unique T.SystemState__POWER_STATE:name;
+const unique T.DeviceState__POWER_STATE:name;
+const unique T.PrivilegeCount__PRIVILEGE_SET:name;
+const unique T.Control__PRIVILEGE_SET:name;
+const unique T.Privilege__PRIVILEGE_SET:name;
+const unique T.DataSectionObject__SECTION_OBJECT_POINTERS:name;
+const unique T.SharedCacheMap__SECTION_OBJECT_POINTERS:name;
+const unique T.ImageSectionObject__SECTION_OBJECT_POINTERS:name;
+const unique T.Length__SECURITY_QUALITY_OF_SERVICE:name;
+const unique T.ImpersonationLevel__SECURITY_QUALITY_OF_SERVICE:name;
+const unique T.ContextTrackingMode__SECURITY_QUALITY_OF_SERVICE:name;
+const unique T.EffectiveOnly__SECURITY_QUALITY_OF_SERVICE:name;
+const unique T.ClientToken__SECURITY_SUBJECT_CONTEXT:name;
+const unique T.ImpersonationLevel__SECURITY_SUBJECT_CONTEXT:name;
+const unique T.PrimaryToken__SECURITY_SUBJECT_CONTEXT:name;
+const unique T.ProcessAuditId__SECURITY_SUBJECT_CONTEXT:name;
+const unique T.__unnamed_4_b4f5a780__SYSTEM_POWER_STATE_CONTEXT:name;
+const unique T.Length__UNICODE_STRING:name;
+const unique T.MaximumLength__UNICODE_STRING:name;
+const unique T.Buffer__UNICODE_STRING:name;
+const unique T.Type__VPB:name;
+const unique T.Size__VPB:name;
+const unique T.Flags__VPB:name;
+const unique T.VolumeLabelLength__VPB:name;
+const unique T.DeviceObject__VPB:name;
+const unique T.RealDevice__VPB:name;
+const unique T.SerialNumber__VPB:name;
+const unique T.ReferenceCount__VPB:name;
+const unique T.VolumeLabel__VPB:name;
+const unique T.WaitQueueEntry__WAIT_CONTEXT_BLOCK:name;
+const unique T.DeviceRoutine__WAIT_CONTEXT_BLOCK:name;
+const unique T.DeviceContext__WAIT_CONTEXT_BLOCK:name;
+const unique T.NumberOfMapRegisters__WAIT_CONTEXT_BLOCK:name;
+const unique T.DeviceObject__WAIT_CONTEXT_BLOCK:name;
+const unique T.CurrentIrp__WAIT_CONTEXT_BLOCK:name;
+const unique T.BufferChainingDpc__WAIT_CONTEXT_BLOCK:name;
+const unique T.GuidCount__WMILIB_CONTEXT:name;
+const unique T.GuidList__WMILIB_CONTEXT:name;
+const unique T.QueryWmiRegInfo__WMILIB_CONTEXT:name;
+const unique T.QueryWmiDataBlock__WMILIB_CONTEXT:name;
+const unique T.SetWmiDataBlock__WMILIB_CONTEXT:name;
+const unique T.SetWmiDataItem__WMILIB_CONTEXT:name;
+const unique T.ExecuteWmiMethod__WMILIB_CONTEXT:name;
+const unique T.WmiFunctionControl__WMILIB_CONTEXT:name;
+const unique T.Start___unnamed_12_06b9ee6e:name;
+const unique T.Length48___unnamed_12_06b9ee6e:name;
+const unique T.Start___unnamed_12_0882bd02:name;
+const unique T.Length64___unnamed_12_0882bd02:name;
+const unique T.__unnamed_12_2e80217b___unnamed_12_264d0dab:name;
+const unique T.Raw___unnamed_12_2e80217b:name;
+const unique T.Translated___unnamed_12_2e80217b:name;
+const unique T.Data___unnamed_12_5cc7ace2:name;
+const unique T.Channel___unnamed_12_6374506e:name;
+const unique T.Port___unnamed_12_6374506e:name;
+const unique T.Reserved1___unnamed_12_6374506e:name;
+const unique T.Priority___unnamed_12_68a4278e:name;
+const unique T.Reserved1___unnamed_12_68a4278e:name;
+const unique T.Reserved2___unnamed_12_68a4278e:name;
+const unique T.Generic___unnamed_12_79ed2653:name;
+const unique T.Port___unnamed_12_79ed2653:name;
+const unique T.Interrupt___unnamed_12_79ed2653:name;
+const unique T.MessageInterrupt___unnamed_12_79ed2653:name;
+const unique T.Memory___unnamed_12_79ed2653:name;
+const unique T.Dma___unnamed_12_79ed2653:name;
+const unique T.DevicePrivate___unnamed_12_79ed2653:name;
+const unique T.BusNumber___unnamed_12_79ed2653:name;
+const unique T.DeviceSpecificData___unnamed_12_79ed2653:name;
+const unique T.Memory40___unnamed_12_79ed2653:name;
+const unique T.Memory48___unnamed_12_79ed2653:name;
+const unique T.Memory64___unnamed_12_79ed2653:name;
+const unique T.Start___unnamed_12_7da594c0:name;
+const unique T.Length40___unnamed_12_7da594c0:name;
+const unique T.Start___unnamed_12_9873e05d:name;
+const unique T.Length___unnamed_12_9873e05d:name;
+const unique T.DataSize___unnamed_12_9cc8cebc:name;
+const unique T.Reserved1___unnamed_12_9cc8cebc:name;
+const unique T.Reserved2___unnamed_12_9cc8cebc:name;
+const unique T.Start___unnamed_12_b98da82e:name;
+const unique T.Length___unnamed_12_b98da82e:name;
+const unique T.Level___unnamed_12_c2880e88:name;
+const unique T.Vector___unnamed_12_c2880e88:name;
+const unique T.Affinity___unnamed_12_c2880e88:name;
+const unique T.Start___unnamed_12_c49ab31a:name;
+const unique T.Length___unnamed_12_c49ab31a:name;
+const unique T.ListEntry___unnamed_12_c6ed93f3:name;
+const unique T.__unnamed_4_a7aa989c___unnamed_12_c6ed93f3:name;
+const unique T.Data___unnamed_12_ced61554:name;
+const unique T.Reserved___unnamed_12_d9c44df5:name;
+const unique T.MessageCount___unnamed_12_d9c44df5:name;
+const unique T.Vector___unnamed_12_d9c44df5:name;
+const unique T.Affinity___unnamed_12_d9c44df5:name;
+const unique T.Start___unnamed_12_db3dcbfc:name;
+const unique T.Length___unnamed_12_db3dcbfc:name;
+const unique T.Reserved___unnamed_12_db3dcbfc:name;
+const unique T.Level___unnamed_12_fb26b3fc:name;
+const unique T.Vector___unnamed_12_fb26b3fc:name;
+const unique T.Affinity___unnamed_12_fb26b3fc:name;
+const unique T.OutputBufferLength___unnamed_16_22e4d054:name;
+const unique T.InputBufferLength___unnamed_16_22e4d054:name;
+const unique T.IoControlCode___unnamed_16_22e4d054:name;
+const unique T.Type3InputBuffer___unnamed_16_22e4d054:name;
+const unique T.Create___unnamed_16_39b626ad:name;
+const unique T.Read___unnamed_16_39b626ad:name;
+const unique T.Write___unnamed_16_39b626ad:name;
+const unique T.QueryDirectory___unnamed_16_39b626ad:name;
+const unique T.NotifyDirectory___unnamed_16_39b626ad:name;
+const unique T.QueryFile___unnamed_16_39b626ad:name;
+const unique T.SetFile___unnamed_16_39b626ad:name;
+const unique T.QueryEa___unnamed_16_39b626ad:name;
+const unique T.SetEa___unnamed_16_39b626ad:name;
+const unique T.QueryVolume___unnamed_16_39b626ad:name;
+const unique T.SetVolume___unnamed_16_39b626ad:name;
+const unique T.FileSystemControl___unnamed_16_39b626ad:name;
+const unique T.LockControl___unnamed_16_39b626ad:name;
+const unique T.DeviceIoControl___unnamed_16_39b626ad:name;
+const unique T.QuerySecurity___unnamed_16_39b626ad:name;
+const unique T.SetSecurity___unnamed_16_39b626ad:name;
+const unique T.MountVolume___unnamed_16_39b626ad:name;
+const unique T.VerifyVolume___unnamed_16_39b626ad:name;
+const unique T.Scsi___unnamed_16_39b626ad:name;
+const unique T.QueryQuota___unnamed_16_39b626ad:name;
+const unique T.SetQuota___unnamed_16_39b626ad:name;
+const unique T.QueryDeviceRelations___unnamed_16_39b626ad:name;
+const unique T.QueryInterface___unnamed_16_39b626ad:name;
+const unique T.DeviceCapabilities___unnamed_16_39b626ad:name;
+const unique T.FilterResourceRequirements___unnamed_16_39b626ad:name;
+const unique T.ReadWriteConfig___unnamed_16_39b626ad:name;
+const unique T.SetLock___unnamed_16_39b626ad:name;
+const unique T.QueryId___unnamed_16_39b626ad:name;
+const unique T.QueryDeviceText___unnamed_16_39b626ad:name;
+const unique T.UsageNotification___unnamed_16_39b626ad:name;
+const unique T.WaitWake___unnamed_16_39b626ad:name;
+const unique T.PowerSequence___unnamed_16_39b626ad:name;
+const unique T.Power___unnamed_16_39b626ad:name;
+const unique T.StartDevice___unnamed_16_39b626ad:name;
+const unique T.WMI___unnamed_16_39b626ad:name;
+const unique T.Others___unnamed_16_39b626ad:name;
+const unique T.WhichSpace___unnamed_16_56c011d7:name;
+const unique T.Buffer___unnamed_16_56c011d7:name;
+const unique T.Offset___unnamed_16_56c011d7:name;
+const unique T.Length___unnamed_16_56c011d7:name;
+const unique T.DeviceQueueEntry___unnamed_16_5fed8f23:name;
+const unique T.__unnamed_16_ae643f17___unnamed_16_5fed8f23:name;
+const unique T.Length___unnamed_16_6be9abe0:name;
+const unique T.FileName___unnamed_16_6be9abe0:name;
+const unique T.FileInformationClass___unnamed_16_6be9abe0:name;
+const unique T.FileIndex___unnamed_16_6be9abe0:name;
+const unique T.InterfaceType___unnamed_16_78879a38:name;
+const unique T.Size___unnamed_16_78879a38:name;
+const unique T.Version___unnamed_16_78879a38:name;
+const unique T.Interface___unnamed_16_78879a38:name;
+const unique T.InterfaceSpecificData___unnamed_16_78879a38:name;
+const unique T.Length___unnamed_16_804a2f24:name;
+const unique T.StartSid___unnamed_16_804a2f24:name;
+const unique T.SidList___unnamed_16_804a2f24:name;
+const unique T.SidListLength___unnamed_16_804a2f24:name;
+const unique T.Argument1___unnamed_16_8586693f:name;
+const unique T.Argument2___unnamed_16_8586693f:name;
+const unique T.Argument3___unnamed_16_8586693f:name;
+const unique T.Argument4___unnamed_16_8586693f:name;
+const unique T.Length___unnamed_16_8831e65f:name;
+const unique T.Key___unnamed_16_8831e65f:name;
+const unique T.ByteOffset___unnamed_16_8831e65f:name;
+const unique T.SecurityContext___unnamed_16_8c2d663a:name;
+const unique T.Options___unnamed_16_8c2d663a:name;
+const unique T.FileAttributes___unnamed_16_8c2d663a:name;
+const unique T.ShareAccess___unnamed_16_8c2d663a:name;
+const unique T.EaLength___unnamed_16_8c2d663a:name;
+const unique T.Length___unnamed_16_913b9a7a:name;
+const unique T.Key___unnamed_16_913b9a7a:name;
+const unique T.ByteOffset___unnamed_16_913b9a7a:name;
+const unique T.OutputBufferLength___unnamed_16_94d1d1c7:name;
+const unique T.InputBufferLength___unnamed_16_94d1d1c7:name;
+const unique T.FsControlCode___unnamed_16_94d1d1c7:name;
+const unique T.Type3InputBuffer___unnamed_16_94d1d1c7:name;
+const unique T.Length___unnamed_16_a2fab4da:name;
+const unique T.FileInformationClass___unnamed_16_a2fab4da:name;
+const unique T.FileObject___unnamed_16_a2fab4da:name;
+const unique T.__unnamed_4_a7d0864c___unnamed_16_a2fab4da:name;
+const unique T.DriverContext___unnamed_16_ae643f17:name;
+const unique T.Length___unnamed_16_c1b29316:name;
+const unique T.Key___unnamed_16_c1b29316:name;
+const unique T.ByteOffset___unnamed_16_c1b29316:name;
+const unique T.ProviderId___unnamed_16_cbd53ed4:name;
+const unique T.DataPath___unnamed_16_cbd53ed4:name;
+const unique T.BufferSize___unnamed_16_cbd53ed4:name;
+const unique T.Buffer___unnamed_16_cbd53ed4:name;
+const unique T.Length___unnamed_16_db70db6e:name;
+const unique T.MinBusNumber___unnamed_16_db70db6e:name;
+const unique T.MaxBusNumber___unnamed_16_db70db6e:name;
+const unique T.Reserved___unnamed_16_db70db6e:name;
+const unique T.Length___unnamed_16_ef4b6307:name;
+const unique T.EaList___unnamed_16_ef4b6307:name;
+const unique T.EaListLength___unnamed_16_ef4b6307:name;
+const unique T.EaIndex___unnamed_16_ef4b6307:name;
+const unique T.__unnamed_4_b060dea6___unnamed_16_fdda1f62:name;
+const unique T.Type___unnamed_16_fdda1f62:name;
+const unique T.State___unnamed_16_fdda1f62:name;
+const unique T.ShutdownType___unnamed_16_fdda1f62:name;
+const unique T.Lock___unnamed_1_1394de4b:name;
+const unique T.Abandoned___unnamed_1_2bb39c56:name;
+const unique T.Absolute___unnamed_1_2bb39c56:name;
+const unique T.NpxIrql___unnamed_1_2bb39c56:name;
+const unique T.Signalling___unnamed_1_2bb39c56:name;
+const unique T.Inserted___unnamed_1_9fa0583a:name;
+const unique T.DebugActive___unnamed_1_9fa0583a:name;
+const unique T.DpcActive___unnamed_1_9fa0583a:name;
+const unique T.Size___unnamed_1_e30779f5:name;
+const unique T.Hand___unnamed_1_e30779f5:name;
+const unique T.MinimumVector___unnamed_20_83d468e4:name;
+const unique T.MaximumVector___unnamed_20_83d468e4:name;
+const unique T.AffinityPolicy___unnamed_20_83d468e4:name;
+const unique T.PriorityPolicy___unnamed_20_83d468e4:name;
+const unique T.TargetedProcessors___unnamed_20_83d468e4:name;
+const unique T.Length40___unnamed_24_035931da:name;
+const unique T.Alignment40___unnamed_24_035931da:name;
+const unique T.MinimumAddress___unnamed_24_035931da:name;
+const unique T.MaximumAddress___unnamed_24_035931da:name;
+const unique T.Length___unnamed_24_38e128db:name;
+const unique T.Alignment___unnamed_24_38e128db:name;
+const unique T.MinimumAddress___unnamed_24_38e128db:name;
+const unique T.MaximumAddress___unnamed_24_38e128db:name;
+const unique T.Length___unnamed_24_9500ea34:name;
+const unique T.Alignment___unnamed_24_9500ea34:name;
+const unique T.MinimumAddress___unnamed_24_9500ea34:name;
+const unique T.MaximumAddress___unnamed_24_9500ea34:name;
+const unique T.Length___unnamed_24_9734802c:name;
+const unique T.Alignment___unnamed_24_9734802c:name;
+const unique T.MinimumAddress___unnamed_24_9734802c:name;
+const unique T.MaximumAddress___unnamed_24_9734802c:name;
+const unique T.Length64___unnamed_24_af62813f:name;
+const unique T.Alignment64___unnamed_24_af62813f:name;
+const unique T.MinimumAddress___unnamed_24_af62813f:name;
+const unique T.MaximumAddress___unnamed_24_af62813f:name;
+const unique T.Length48___unnamed_24_c0555099:name;
+const unique T.Alignment48___unnamed_24_c0555099:name;
+const unique T.MinimumAddress___unnamed_24_c0555099:name;
+const unique T.MaximumAddress___unnamed_24_c0555099:name;
+const unique T.Port___unnamed_24_d7c4ec3a:name;
+const unique T.Memory___unnamed_24_d7c4ec3a:name;
+const unique T.Interrupt___unnamed_24_d7c4ec3a:name;
+const unique T.Dma___unnamed_24_d7c4ec3a:name;
+const unique T.Generic___unnamed_24_d7c4ec3a:name;
+const unique T.DevicePrivate___unnamed_24_d7c4ec3a:name;
+const unique T.BusNumber___unnamed_24_d7c4ec3a:name;
+const unique T.ConfigData___unnamed_24_d7c4ec3a:name;
+const unique T.Memory40___unnamed_24_d7c4ec3a:name;
+const unique T.Memory48___unnamed_24_d7c4ec3a:name;
+const unique T.Memory64___unnamed_24_d7c4ec3a:name;
+const unique T.ReplaceIfExists___unnamed_2_196a7f56:name;
+const unique T.AdvanceOnly___unnamed_2_196a7f56:name;
+const unique T.__unnamed_16_5fed8f23___unnamed_40_a0414182:name;
+const unique T.Thread___unnamed_40_a0414182:name;
+const unique T.AuxiliaryBuffer___unnamed_40_a0414182:name;
+const unique T.__unnamed_12_c6ed93f3___unnamed_40_a0414182:name;
+const unique T.OriginalFileObject___unnamed_40_a0414182:name;
+const unique T.ListEntry___unnamed_40_d90496f4:name;
+const unique T.Wcb___unnamed_40_d90496f4:name;
+const unique T.InitialPrivilegeSet___unnamed_44_a7026dca:name;
+const unique T.PrivilegeSet___unnamed_44_a7026dca:name;
+const unique T.Overlay___unnamed_48_c1da9fa5:name;
+const unique T.Apc___unnamed_48_c1da9fa5:name;
+const unique T.CompletionKey___unnamed_48_c1da9fa5:name;
+const unique T.PowerSequence___unnamed_4_0510b147:name;
+const unique T.Length___unnamed_4_0a569078:name;
+const unique T.Status___unnamed_4_16aff58e:name;
+const unique T.Pointer___unnamed_4_16aff58e:name;
+const unique T.IdType___unnamed_4_40bf8e34:name;
+const unique T.Address___unnamed_4_46b62f69:name;
+const unique T.CreatorBackTraceIndex___unnamed_4_46b62f69:name;
+const unique T.Capabilities___unnamed_4_73d46255:name;
+const unique T.Srb___unnamed_4_765e3037:name;
+const unique T.Type___unnamed_4_846adf3f:name;
+const unique T.__unnamed_1_2bb39c56___unnamed_4_846adf3f:name;
+const unique T.__unnamed_1_e30779f5___unnamed_4_846adf3f:name;
+const unique T.__unnamed_1_9fa0583a___unnamed_4_846adf3f:name;
+const unique T.PowerState___unnamed_4_8dd73d30:name;
+const unique T.Type___unnamed_4_957e0d74:name;
+const unique T.Buttons___unnamed_4_9c11ed91:name;
+const unique T.__unnamed_4_b5247f10___unnamed_4_9c11ed91:name;
+const unique T.IoResourceRequirementList___unnamed_4_a58d40c8:name;
+const unique T.CurrentStackLocation___unnamed_4_a7aa989c:name;
+const unique T.PacketType___unnamed_4_a7aa989c:name;
+const unique T.__unnamed_2_196a7f56___unnamed_4_a7d0864c:name;
+const unique T.ClusterCount___unnamed_4_a7d0864c:name;
+const unique T.DeleteHandle___unnamed_4_a7d0864c:name;
+const unique T.Length___unnamed_4_aa20b426:name;
+const unique T.UserApcRoutine___unnamed_4_ab87ddfd:name;
+const unique T.IssuingProcess___unnamed_4_ab87ddfd:name;
+const unique T.Reserved1___unnamed_4_b016b1e1:name;
+const unique T.TargetSystemState___unnamed_4_b016b1e1:name;
+const unique T.EffectiveSystemState___unnamed_4_b016b1e1:name;
+const unique T.CurrentSystemState___unnamed_4_b016b1e1:name;
+const unique T.IgnoreHibernationPath___unnamed_4_b016b1e1:name;
+const unique T.PseudoTransition___unnamed_4_b016b1e1:name;
+const unique T.Reserved2___unnamed_4_b016b1e1:name;
+const unique T.SystemContext___unnamed_4_b060dea6:name;
+const unique T.SystemPowerStateContext___unnamed_4_b060dea6:name;
+const unique T.__unnamed_4_b016b1e1___unnamed_4_b4f5a780:name;
+const unique T.ContextAsUlong___unnamed_4_b4f5a780:name;
+const unique T.ButtonFlags___unnamed_4_b5247f10:name;
+const unique T.ButtonData___unnamed_4_b5247f10:name;
+const unique T.OwnerCount___unnamed_4_c1e23b02:name;
+const unique T.TableSize___unnamed_4_c1e23b02:name;
+const unique T.__unnamed_4_846adf3f___unnamed_4_c9b2e921:name;
+const unique T.Lock___unnamed_4_c9b2e921:name;
+const unique T.MasterIrp___unnamed_4_fa7b96a7:name;
+const unique T.IrpCount___unnamed_4_fa7b96a7:name;
+const unique T.SystemBuffer___unnamed_4_fa7b96a7:name;
+const unique T.Vpb___unnamed_8_09ad2712:name;
+const unique T.DeviceObject___unnamed_8_09ad2712:name;
+const unique T.Length___unnamed_8_21ac1dba:name;
+const unique T.CompletionFilter___unnamed_8_21ac1dba:name;
+const unique T.Length___unnamed_8_27d3ab76:name;
+const unique T.FsInformationClass___unnamed_8_27d3ab76:name;
+const unique T.Vpb___unnamed_8_4289df81:name;
+const unique T.DeviceObject___unnamed_8_4289df81:name;
+const unique T.Length___unnamed_8_47b72724:name;
+const unique T.FileInformationClass___unnamed_8_47b72724:name;
+const unique T.DeviceTextType___unnamed_8_4b3e3ba3:name;
+const unique T.LocaleId___unnamed_8_4b3e3ba3:name;
+const unique T.__unnamed_4_ab87ddfd___unnamed_8_4f695993:name;
+const unique T.UserApcContext___unnamed_8_4f695993:name;
+const unique T.AllocatedResources___unnamed_8_5cfb6ca4:name;
+const unique T.AllocatedResourcesTranslated___unnamed_8_5cfb6ca4:name;
+const unique T.SecurityInformation___unnamed_8_606438c5:name;
+const unique T.Length___unnamed_8_606438c5:name;
+const unique T.MinimumChannel___unnamed_8_6ad774c0:name;
+const unique T.MaximumChannel___unnamed_8_6ad774c0:name;
+const unique T.Length___unnamed_8_805045cb:name;
+const unique T.FsInformationClass___unnamed_8_805045cb:name;
+const unique T.LowPart___unnamed_8_8684a3e7:name;
+const unique T.HighPart___unnamed_8_8684a3e7:name;
+const unique T.SecurityInformation___unnamed_8_8cc410da:name;
+const unique T.SecurityDescriptor___unnamed_8_8cc410da:name;
+const unique T.InPath___unnamed_8_a47253e0:name;
+const unique T.Reserved___unnamed_8_a47253e0:name;
+const unique T.Type___unnamed_8_a47253e0:name;
+const unique T.AsynchronousParameters___unnamed_8_bbd07f6c:name;
+const unique T.AllocationSize___unnamed_8_bbd07f6c:name;
+const unique T.LowPart___unnamed_8_c9ca8234:name;
+const unique T.HighPart___unnamed_8_c9ca8234:name;
+
+// Type declarations
+
+const unique T.A1_CM_FULL_RESOURCE_DESCRIPTOR:name;
+const unique T.A1_CM_PARTIAL_RESOURCE_DESCRIPTOR:name;
+const unique T.A1_IO_RESOURCE_DESCRIPTOR:name;
+const unique T.A1_IO_RESOURCE_LIST:name;
+const unique T.A1_LUID_AND_ATTRIBUTES:name;
+const unique T.A256UINT2:name;
+const unique T.A28PFDRIVER_DISPATCH:name;
+const unique T.A2UCHAR:name;
+const unique T.A2UINT2:name;
+const unique T.A32UINT2:name;
+const unique T.A3UCHAR:name;
+const unique T.A3UINT4:name;
+const unique T.A3_LUID_AND_ATTRIBUTES:name;
+const unique T.A4PVOID:name;
+const unique T.A4UINT4:name;
+const unique T.A5UINT2:name;
+const unique T.A5_DEVICE_POWER_STATE:name;
+const unique T.A7_DEVICE_POWER_STATE:name;
+const unique T.A85CHAR:name;
+const unique T.A8UCHAR:name;
+const unique T.A9UINT2:name;
+const unique T.BUS_QUERY_ID_TYPE:name;
+const unique T.CHAR:name;
+const unique T.DEVICE_TEXT_TYPE:name;
+const unique T.F0:name;
+const unique T.F1:name;
+const unique T.F10:name;
+const unique T.F11:name;
+const unique T.F12:name;
+const unique T.F13:name;
+const unique T.F14:name;
+const unique T.F15:name;
+const unique T.F16:name;
+const unique T.F17:name;
+const unique T.F18:name;
+const unique T.F19:name;
+const unique T.F2:name;
+const unique T.F20:name;
+const unique T.F21:name;
+const unique T.F22:name;
+const unique T.F23:name;
+const unique T.F24:name;
+const unique T.F25:name;
+const unique T.F26:name;
+const unique T.F27:name;
+const unique T.F28:name;
+const unique T.F29:name;
+const unique T.F3:name;
+const unique T.F30:name;
+const unique T.F31:name;
+const unique T.F32:name;
+const unique T.F33:name;
+const unique T.F34:name;
+const unique T.F35:name;
+const unique T.F36:name;
+const unique T.F37:name;
+const unique T.F38:name;
+const unique T.F4:name;
+const unique T.F5:name;
+const unique T.F6:name;
+const unique T.F7:name;
+const unique T.F8:name;
+const unique T.F9:name;
+const unique T.FDRIVER_ADD_DEVICE:name;
+const unique T.FDRIVER_CANCEL:name;
+const unique T.FDRIVER_CONTROL:name;
+const unique T.FDRIVER_DISPATCH:name;
+const unique T.FDRIVER_INITIALIZE:name;
+const unique T.FDRIVER_STARTIO:name;
+const unique T.FDRIVER_UNLOAD:name;
+const unique T.FFAST_IO_ACQUIRE_FILE:name;
+const unique T.FFAST_IO_ACQUIRE_FOR_CCFLUSH:name;
+const unique T.FFAST_IO_ACQUIRE_FOR_MOD_WRITE:name;
+const unique T.FFAST_IO_CHECK_IF_POSSIBLE:name;
+const unique T.FFAST_IO_DETACH_DEVICE:name;
+const unique T.FFAST_IO_DEVICE_CONTROL:name;
+const unique T.FFAST_IO_LOCK:name;
+const unique T.FFAST_IO_MDL_READ:name;
+const unique T.FFAST_IO_MDL_READ_COMPLETE:name;
+const unique T.FFAST_IO_MDL_READ_COMPLETE_COMPRESSED:name;
+const unique T.FFAST_IO_MDL_WRITE_COMPLETE:name;
+const unique T.FFAST_IO_MDL_WRITE_COMPLETE_COMPRESSED:name;
+const unique T.FFAST_IO_PREPARE_MDL_WRITE:name;
+const unique T.FFAST_IO_QUERY_BASIC_INFO:name;
+const unique T.FFAST_IO_QUERY_NETWORK_OPEN_INFO:name;
+const unique T.FFAST_IO_QUERY_OPEN:name;
+const unique T.FFAST_IO_QUERY_STANDARD_INFO:name;
+const unique T.FFAST_IO_READ:name;
+const unique T.FFAST_IO_READ_COMPRESSED:name;
+const unique T.FFAST_IO_RELEASE_FILE:name;
+const unique T.FFAST_IO_RELEASE_FOR_CCFLUSH:name;
+const unique T.FFAST_IO_RELEASE_FOR_MOD_WRITE:name;
+const unique T.FFAST_IO_UNLOCK_ALL:name;
+const unique T.FFAST_IO_UNLOCK_ALL_BY_KEY:name;
+const unique T.FFAST_IO_UNLOCK_SINGLE:name;
+const unique T.FFAST_IO_WRITE:name;
+const unique T.FFAST_IO_WRITE_COMPRESSED:name;
+const unique T.FIO_COMPLETION_ROUTINE:name;
+const unique T.FKDEFERRED_ROUTINE:name;
+const unique T.INT2:name;
+const unique T.INT4:name;
+const unique T.INT8:name;
+const unique T.PA256UINT2:name;
+const unique T.PA2UINT2:name;
+const unique T.PA4UINT4:name;
+const unique T.PA5UINT2:name;
+const unique T.PA85CHAR:name;
+const unique T.PA9UINT2:name;
+const unique T.PCHAR:name;
+const unique T.PF19:name;
+const unique T.PF21:name;
+const unique T.PF23:name;
+const unique T.PF24:name;
+const unique T.PF25:name;
+const unique T.PF33:name;
+const unique T.PF34:name;
+const unique T.PF35:name;
+const unique T.PF36:name;
+const unique T.PF37:name;
+const unique T.PF38:name;
+const unique T.PFDRIVER_ADD_DEVICE:name;
+const unique T.PFDRIVER_CANCEL:name;
+const unique T.PFDRIVER_CONTROL:name;
+const unique T.PFDRIVER_DISPATCH:name;
+const unique T.PFDRIVER_INITIALIZE:name;
+const unique T.PFDRIVER_STARTIO:name;
+const unique T.PFDRIVER_UNLOAD:name;
+const unique T.PFFAST_IO_ACQUIRE_FILE:name;
+const unique T.PFFAST_IO_ACQUIRE_FOR_CCFLUSH:name;
+const unique T.PFFAST_IO_ACQUIRE_FOR_MOD_WRITE:name;
+const unique T.PFFAST_IO_CHECK_IF_POSSIBLE:name;
+const unique T.PFFAST_IO_DETACH_DEVICE:name;
+const unique T.PFFAST_IO_DEVICE_CONTROL:name;
+const unique T.PFFAST_IO_LOCK:name;
+const unique T.PFFAST_IO_MDL_READ:name;
+const unique T.PFFAST_IO_MDL_READ_COMPLETE:name;
+const unique T.PFFAST_IO_MDL_READ_COMPLETE_COMPRESSED:name;
+const unique T.PFFAST_IO_MDL_WRITE_COMPLETE:name;
+const unique T.PFFAST_IO_MDL_WRITE_COMPLETE_COMPRESSED:name;
+const unique T.PFFAST_IO_PREPARE_MDL_WRITE:name;
+const unique T.PFFAST_IO_QUERY_BASIC_INFO:name;
+const unique T.PFFAST_IO_QUERY_NETWORK_OPEN_INFO:name;
+const unique T.PFFAST_IO_QUERY_OPEN:name;
+const unique T.PFFAST_IO_QUERY_STANDARD_INFO:name;
+const unique T.PFFAST_IO_READ:name;
+const unique T.PFFAST_IO_READ_COMPRESSED:name;
+const unique T.PFFAST_IO_RELEASE_FILE:name;
+const unique T.PFFAST_IO_RELEASE_FOR_CCFLUSH:name;
+const unique T.PFFAST_IO_RELEASE_FOR_MOD_WRITE:name;
+const unique T.PFFAST_IO_UNLOCK_ALL:name;
+const unique T.PFFAST_IO_UNLOCK_ALL_BY_KEY:name;
+const unique T.PFFAST_IO_UNLOCK_SINGLE:name;
+const unique T.PFFAST_IO_WRITE:name;
+const unique T.PFFAST_IO_WRITE_COMPRESSED:name;
+const unique T.PFIO_COMPLETION_ROUTINE:name;
+const unique T.PFKDEFERRED_ROUTINE:name;
+const unique T.PINT4:name;
+const unique T.POWER_ACTION:name;
+const unique T.PPCHAR:name;
+const unique T.PPF24:name;
+const unique T.PPPUINT2:name;
+const unique T.PPP_DEVICE_OBJECT:name;
+const unique T.PPP_FILE_OBJECT:name;
+const unique T.PPUINT2:name;
+const unique T.PPUINT4:name;
+const unique T.PPVOID:name;
+const unique T.PP_DEVICE_EXTENSION:name;
+const unique T.PP_DEVICE_OBJECT:name;
+const unique T.PP_DRIVER_OBJECT:name;
+const unique T.PP_ERESOURCE:name;
+const unique T.PP_FAST_MUTEX:name;
+const unique T.PP_FILE_OBJECT:name;
+const unique T.PP_LIST_ENTRY:name;
+const unique T.PP_MDL:name;
+const unique T.PP_PORT:name;
+const unique T.PP_UNICODE_STRING:name;
+const unique T.PUCHAR:name;
+const unique T.PUINT2:name;
+const unique T.PUINT4:name;
+const unique T.PVOID:name;
+const unique T.PWMIGUIDREGINFO:name;
+const unique T.P_ACCESS_STATE:name;
+const unique T.P_CM_RESOURCE_LIST:name;
+const unique T.P_COMPRESSED_DATA_INFO:name;
+const unique T.P_DEVICE_CAPABILITIES:name;
+const unique T.P_DEVICE_EXTENSION:name;
+const unique T.P_DEVICE_OBJECT:name;
+const unique T.P_DEVOBJ_EXTENSION:name;
+const unique T.P_DRIVER_EXTENSION:name;
+const unique T.P_DRIVER_OBJECT:name;
+const unique T.P_EPROCESS:name;
+const unique T.P_ERESOURCE:name;
+const unique T.P_ETHREAD:name;
+const unique T.P_FAST_IO_DISPATCH:name;
+const unique T.P_FAST_MUTEX:name;
+const unique T.P_FILE_BASIC_INFORMATION:name;
+const unique T.P_FILE_GET_QUOTA_INFORMATION:name;
+const unique T.P_FILE_NETWORK_OPEN_INFORMATION:name;
+const unique T.P_FILE_OBJECT:name;
+const unique T.P_FILE_STANDARD_INFORMATION:name;
+const unique T.P_GLOBALS:name;
+const unique T.P_GUID:name;
+const unique T.P_INTERFACE:name;
+const unique T.P_IO_COMPLETION_CONTEXT:name;
+const unique T.P_IO_REMOVE_LOCK_TRACKING_BLOCK:name;
+const unique T.P_IO_RESOURCE_REQUIREMENTS_LIST:name;
+const unique T.P_IO_SECURITY_CONTEXT:name;
+const unique T.P_IO_STACK_LOCATION:name;
+const unique T.P_IO_STATUS_BLOCK:name;
+const unique T.P_IO_TIMER:name;
+const unique T.P_IRP:name;
+const unique T.P_KAPC:name;
+const unique T.P_KDPC:name;
+const unique T.P_KEVENT:name;
+const unique T.P_KSEMAPHORE:name;
+const unique T.P_KTHREAD:name;
+const unique T.P_LARGE_INTEGER:name;
+const unique T.P_LIST_ENTRY:name;
+const unique T.P_MDL:name;
+const unique T.P_MOUSE_INPUT_DATA:name;
+const unique T.P_OWNER_ENTRY:name;
+const unique T.P_POOL_TYPE:name;
+const unique T.P_PORT:name;
+const unique T.P_POWER_SEQUENCE:name;
+const unique T.P_SCSI_REQUEST_BLOCK:name;
+const unique T.P_SECTION_OBJECT_POINTERS:name;
+const unique T.P_SECURITY_QUALITY_OF_SERVICE:name;
+const unique T.P_UNICODE_STRING:name;
+const unique T.P_VPB:name;
+const unique T.UCHAR:name;
+const unique T.UINT2:name;
+const unique T.UINT4:name;
+const unique T.VOID:name;
+const unique T.WMIENABLEDISABLECONTROL:name;
+const unique T.WMIGUIDREGINFO:name;
+const unique T._ACCESS_STATE:name;
+const unique T._CM_FULL_RESOURCE_DESCRIPTOR:name;
+const unique T._CM_PARTIAL_RESOURCE_DESCRIPTOR:name;
+const unique T._CM_PARTIAL_RESOURCE_LIST:name;
+const unique T._CM_RESOURCE_LIST:name;
+const unique T._COMPRESSED_DATA_INFO:name;
+const unique T._DEVICE_CAPABILITIES:name;
+const unique T._DEVICE_EXTENSION:name;
+const unique T._DEVICE_OBJECT:name;
+const unique T._DEVICE_POWER_STATE:name;
+const unique T._DEVICE_RELATION_TYPE:name;
+const unique T._DEVICE_USAGE_NOTIFICATION_TYPE:name;
+const unique T._DEVOBJ_EXTENSION:name;
+const unique T._DISPATCHER_HEADER:name;
+const unique T._DRIVER_EXTENSION:name;
+const unique T._DRIVER_OBJECT:name;
+const unique T._EPROCESS:name;
+const unique T._ERESOURCE:name;
+const unique T._ETHREAD:name;
+const unique T._FAST_IO_DISPATCH:name;
+const unique T._FAST_MUTEX:name;
+const unique T._FILE_BASIC_INFORMATION:name;
+const unique T._FILE_GET_QUOTA_INFORMATION:name;
+const unique T._FILE_INFORMATION_CLASS:name;
+const unique T._FILE_NETWORK_OPEN_INFORMATION:name;
+const unique T._FILE_OBJECT:name;
+const unique T._FILE_STANDARD_INFORMATION:name;
+const unique T._FSINFOCLASS:name;
+const unique T._GLOBALS:name;
+const unique T._GUID:name;
+const unique T._INITIAL_PRIVILEGE_SET:name;
+const unique T._INTERFACE:name;
+const unique T._INTERFACE_TYPE:name;
+const unique T._IO_ALLOCATION_ACTION:name;
+const unique T._IO_COMPLETION_CONTEXT:name;
+const unique T._IO_REMOVE_LOCK:name;
+const unique T._IO_REMOVE_LOCK_COMMON_BLOCK:name;
+const unique T._IO_REMOVE_LOCK_DBG_BLOCK:name;
+const unique T._IO_REMOVE_LOCK_TRACKING_BLOCK:name;
+const unique T._IO_RESOURCE_DESCRIPTOR:name;
+const unique T._IO_RESOURCE_LIST:name;
+const unique T._IO_RESOURCE_REQUIREMENTS_LIST:name;
+const unique T._IO_SECURITY_CONTEXT:name;
+const unique T._IO_STACK_LOCATION:name;
+const unique T._IO_STATUS_BLOCK:name;
+const unique T._IO_TIMER:name;
+const unique T._IRP:name;
+const unique T._IRQ_DEVICE_POLICY:name;
+const unique T._IRQ_PRIORITY:name;
+const unique T._KAPC:name;
+const unique T._KDEVICE_QUEUE:name;
+const unique T._KDEVICE_QUEUE_ENTRY:name;
+const unique T._KDPC:name;
+const unique T._KEVENT:name;
+const unique T._KSEMAPHORE:name;
+const unique T._KTHREAD:name;
+const unique T._LARGE_INTEGER:name;
+const unique T._LIST_ENTRY:name;
+const unique T._LUID:name;
+const unique T._LUID_AND_ATTRIBUTES:name;
+const unique T._MDL:name;
+const unique T._MOUSE_ATTRIBUTES:name;
+const unique T._MOUSE_INPUT_DATA:name;
+const unique T._OWNER_ENTRY:name;
+const unique T._POOL_TYPE:name;
+const unique T._PORT:name;
+const unique T._POWER_SEQUENCE:name;
+const unique T._POWER_STATE:name;
+const unique T._POWER_STATE_TYPE:name;
+const unique T._PRIVILEGE_SET:name;
+const unique T._SCSI_REQUEST_BLOCK:name;
+const unique T._SECTION_OBJECT_POINTERS:name;
+const unique T._SECURITY_IMPERSONATION_LEVEL:name;
+const unique T._SECURITY_QUALITY_OF_SERVICE:name;
+const unique T._SECURITY_SUBJECT_CONTEXT:name;
+const unique T._SYSTEM_POWER_STATE:name;
+const unique T._SYSTEM_POWER_STATE_CONTEXT:name;
+const unique T._UNICODE_STRING:name;
+const unique T._VPB:name;
+const unique T._WAIT_CONTEXT_BLOCK:name;
+const unique T._WMILIB_CONTEXT:name;
+const unique T.__unnamed_12_06b9ee6e:name;
+const unique T.__unnamed_12_0882bd02:name;
+const unique T.__unnamed_12_264d0dab:name;
+const unique T.__unnamed_12_2e80217b:name;
+const unique T.__unnamed_12_5cc7ace2:name;
+const unique T.__unnamed_12_6374506e:name;
+const unique T.__unnamed_12_68a4278e:name;
+const unique T.__unnamed_12_79ed2653:name;
+const unique T.__unnamed_12_7da594c0:name;
+const unique T.__unnamed_12_9873e05d:name;
+const unique T.__unnamed_12_9cc8cebc:name;
+const unique T.__unnamed_12_b98da82e:name;
+const unique T.__unnamed_12_c2880e88:name;
+const unique T.__unnamed_12_c49ab31a:name;
+const unique T.__unnamed_12_c6ed93f3:name;
+const unique T.__unnamed_12_ced61554:name;
+const unique T.__unnamed_12_d9c44df5:name;
+const unique T.__unnamed_12_db3dcbfc:name;
+const unique T.__unnamed_12_fb26b3fc:name;
+const unique T.__unnamed_16_22e4d054:name;
+const unique T.__unnamed_16_39b626ad:name;
+const unique T.__unnamed_16_56c011d7:name;
+const unique T.__unnamed_16_5fed8f23:name;
+const unique T.__unnamed_16_6be9abe0:name;
+const unique T.__unnamed_16_78879a38:name;
+const unique T.__unnamed_16_804a2f24:name;
+const unique T.__unnamed_16_8586693f:name;
+const unique T.__unnamed_16_8831e65f:name;
+const unique T.__unnamed_16_8c2d663a:name;
+const unique T.__unnamed_16_913b9a7a:name;
+const unique T.__unnamed_16_94d1d1c7:name;
+const unique T.__unnamed_16_a2fab4da:name;
+const unique T.__unnamed_16_ae643f17:name;
+const unique T.__unnamed_16_c1b29316:name;
+const unique T.__unnamed_16_cbd53ed4:name;
+const unique T.__unnamed_16_db70db6e:name;
+const unique T.__unnamed_16_ef4b6307:name;
+const unique T.__unnamed_16_fdda1f62:name;
+const unique T.__unnamed_1_1394de4b:name;
+const unique T.__unnamed_1_2bb39c56:name;
+const unique T.__unnamed_1_9fa0583a:name;
+const unique T.__unnamed_1_e30779f5:name;
+const unique T.__unnamed_20_83d468e4:name;
+const unique T.__unnamed_24_035931da:name;
+const unique T.__unnamed_24_38e128db:name;
+const unique T.__unnamed_24_9500ea34:name;
+const unique T.__unnamed_24_9734802c:name;
+const unique T.__unnamed_24_af62813f:name;
+const unique T.__unnamed_24_c0555099:name;
+const unique T.__unnamed_24_d7c4ec3a:name;
+const unique T.__unnamed_2_196a7f56:name;
+const unique T.__unnamed_40_a0414182:name;
+const unique T.__unnamed_40_d90496f4:name;
+const unique T.__unnamed_44_a7026dca:name;
+const unique T.__unnamed_48_c1da9fa5:name;
+const unique T.__unnamed_4_0510b147:name;
+const unique T.__unnamed_4_0a569078:name;
+const unique T.__unnamed_4_16aff58e:name;
+const unique T.__unnamed_4_40bf8e34:name;
+const unique T.__unnamed_4_46b62f69:name;
+const unique T.__unnamed_4_73d46255:name;
+const unique T.__unnamed_4_765e3037:name;
+const unique T.__unnamed_4_846adf3f:name;
+const unique T.__unnamed_4_8dd73d30:name;
+const unique T.__unnamed_4_957e0d74:name;
+const unique T.__unnamed_4_9c11ed91:name;
+const unique T.__unnamed_4_a58d40c8:name;
+const unique T.__unnamed_4_a7aa989c:name;
+const unique T.__unnamed_4_a7d0864c:name;
+const unique T.__unnamed_4_aa20b426:name;
+const unique T.__unnamed_4_ab87ddfd:name;
+const unique T.__unnamed_4_b016b1e1:name;
+const unique T.__unnamed_4_b060dea6:name;
+const unique T.__unnamed_4_b4f5a780:name;
+const unique T.__unnamed_4_b5247f10:name;
+const unique T.__unnamed_4_c1e23b02:name;
+const unique T.__unnamed_4_c9b2e921:name;
+const unique T.__unnamed_4_fa7b96a7:name;
+const unique T.__unnamed_8_09ad2712:name;
+const unique T.__unnamed_8_21ac1dba:name;
+const unique T.__unnamed_8_27d3ab76:name;
+const unique T.__unnamed_8_4289df81:name;
+const unique T.__unnamed_8_47b72724:name;
+const unique T.__unnamed_8_4b3e3ba3:name;
+const unique T.__unnamed_8_4f695993:name;
+const unique T.__unnamed_8_5cfb6ca4:name;
+const unique T.__unnamed_8_606438c5:name;
+const unique T.__unnamed_8_6ad774c0:name;
+const unique T.__unnamed_8_805045cb:name;
+const unique T.__unnamed_8_8684a3e7:name;
+const unique T.__unnamed_8_8cc410da:name;
+const unique T.__unnamed_8_a47253e0:name;
+const unique T.__unnamed_8_bbd07f6c:name;
+const unique T.__unnamed_8_c9ca8234:name;
+
+function AssocClassList__GLOBALS(int) returns (int);
+function AssocClassList__GLOBALSInv(int) returns (int);
+function _S_AssocClassList__GLOBALS([int]bool) returns ([int]bool);
+function _S_AssocClassList__GLOBALSInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {AssocClassList__GLOBALSInv(AssocClassList__GLOBALS(x))} AssocClassList__GLOBALSInv(AssocClassList__GLOBALS(x)) == x);
+axiom (forall x:int :: {AssocClassList__GLOBALSInv(x)} AssocClassList__GLOBALS(AssocClassList__GLOBALSInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_AssocClassList__GLOBALS(S)[x]} _S_AssocClassList__GLOBALS(S)[x] <==> S[AssocClassList__GLOBALSInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_AssocClassList__GLOBALSInv(S)[x]} _S_AssocClassList__GLOBALSInv(S)[x] <==> S[AssocClassList__GLOBALS(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_AssocClassList__GLOBALS(S)} S[x] ==> _S_AssocClassList__GLOBALS(S)[AssocClassList__GLOBALS(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_AssocClassList__GLOBALSInv(S)} S[x] ==> _S_AssocClassList__GLOBALSInv(S)[AssocClassList__GLOBALSInv(x)]);
+
+axiom (forall x:int :: {AssocClassList__GLOBALS(x)} AssocClassList__GLOBALS(x) == x + 8);
+axiom (forall x:int :: {AssocClassList__GLOBALSInv(x)} AssocClassList__GLOBALSInv(x) == x - 8);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 8, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 8, 1) == AssocClassList__GLOBALSInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 8)} MINUS_LEFT_PTR(x, 1, 8) == AssocClassList__GLOBALSInv(x));
+function BaseClassName__GLOBALS(int) returns (int);
+function BaseClassName__GLOBALSInv(int) returns (int);
+function _S_BaseClassName__GLOBALS([int]bool) returns ([int]bool);
+function _S_BaseClassName__GLOBALSInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {BaseClassName__GLOBALSInv(BaseClassName__GLOBALS(x))} BaseClassName__GLOBALSInv(BaseClassName__GLOBALS(x)) == x);
+axiom (forall x:int :: {BaseClassName__GLOBALSInv(x)} BaseClassName__GLOBALS(BaseClassName__GLOBALSInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_BaseClassName__GLOBALS(S)[x]} _S_BaseClassName__GLOBALS(S)[x] <==> S[BaseClassName__GLOBALSInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_BaseClassName__GLOBALSInv(S)[x]} _S_BaseClassName__GLOBALSInv(S)[x] <==> S[BaseClassName__GLOBALS(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_BaseClassName__GLOBALS(S)} S[x] ==> _S_BaseClassName__GLOBALS(S)[BaseClassName__GLOBALS(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_BaseClassName__GLOBALSInv(S)} S[x] ==> _S_BaseClassName__GLOBALSInv(S)[BaseClassName__GLOBALSInv(x)]);
+
+axiom (forall x:int :: {BaseClassName__GLOBALS(x)} BaseClassName__GLOBALS(x) == x + 344);
+axiom (forall x:int :: {BaseClassName__GLOBALSInv(x)} BaseClassName__GLOBALSInv(x) == x - 344);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 344, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 344, 1) == BaseClassName__GLOBALSInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 344)} MINUS_LEFT_PTR(x, 1, 344) == BaseClassName__GLOBALSInv(x));
+function Buffer__UNICODE_STRING(int) returns (int);
+function Buffer__UNICODE_STRINGInv(int) returns (int);
+function _S_Buffer__UNICODE_STRING([int]bool) returns ([int]bool);
+function _S_Buffer__UNICODE_STRINGInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {Buffer__UNICODE_STRINGInv(Buffer__UNICODE_STRING(x))} Buffer__UNICODE_STRINGInv(Buffer__UNICODE_STRING(x)) == x);
+axiom (forall x:int :: {Buffer__UNICODE_STRINGInv(x)} Buffer__UNICODE_STRING(Buffer__UNICODE_STRINGInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_Buffer__UNICODE_STRING(S)[x]} _S_Buffer__UNICODE_STRING(S)[x] <==> S[Buffer__UNICODE_STRINGInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_Buffer__UNICODE_STRINGInv(S)[x]} _S_Buffer__UNICODE_STRINGInv(S)[x] <==> S[Buffer__UNICODE_STRING(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Buffer__UNICODE_STRING(S)} S[x] ==> _S_Buffer__UNICODE_STRING(S)[Buffer__UNICODE_STRING(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Buffer__UNICODE_STRINGInv(S)} S[x] ==> _S_Buffer__UNICODE_STRINGInv(S)[Buffer__UNICODE_STRINGInv(x)]);
+
+axiom (forall x:int :: {Buffer__UNICODE_STRING(x)} Buffer__UNICODE_STRING(x) == x + 4);
+axiom (forall x:int :: {Buffer__UNICODE_STRINGInv(x)} Buffer__UNICODE_STRINGInv(x) == x - 4);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 4, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 4, 1) == Buffer__UNICODE_STRINGInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 4)} MINUS_LEFT_PTR(x, 1, 4) == Buffer__UNICODE_STRINGInv(x));
+function DataIn__DEVICE_EXTENSION(int) returns (int);
+function DataIn__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_DataIn__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_DataIn__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {DataIn__DEVICE_EXTENSIONInv(DataIn__DEVICE_EXTENSION(x))} DataIn__DEVICE_EXTENSIONInv(DataIn__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {DataIn__DEVICE_EXTENSIONInv(x)} DataIn__DEVICE_EXTENSION(DataIn__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_DataIn__DEVICE_EXTENSION(S)[x]} _S_DataIn__DEVICE_EXTENSION(S)[x] <==> S[DataIn__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_DataIn__DEVICE_EXTENSIONInv(S)[x]} _S_DataIn__DEVICE_EXTENSIONInv(S)[x] <==> S[DataIn__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_DataIn__DEVICE_EXTENSION(S)} S[x] ==> _S_DataIn__DEVICE_EXTENSION(S)[DataIn__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_DataIn__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_DataIn__DEVICE_EXTENSIONInv(S)[DataIn__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {DataIn__DEVICE_EXTENSION(x)} DataIn__DEVICE_EXTENSION(x) == x + 132);
+axiom (forall x:int :: {DataIn__DEVICE_EXTENSIONInv(x)} DataIn__DEVICE_EXTENSIONInv(x) == x - 132);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 132, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 132, 1) == DataIn__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 132)} MINUS_LEFT_PTR(x, 1, 132) == DataIn__DEVICE_EXTENSIONInv(x));
+function DataOut__DEVICE_EXTENSION(int) returns (int);
+function DataOut__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_DataOut__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_DataOut__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {DataOut__DEVICE_EXTENSIONInv(DataOut__DEVICE_EXTENSION(x))} DataOut__DEVICE_EXTENSIONInv(DataOut__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {DataOut__DEVICE_EXTENSIONInv(x)} DataOut__DEVICE_EXTENSION(DataOut__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_DataOut__DEVICE_EXTENSION(S)[x]} _S_DataOut__DEVICE_EXTENSION(S)[x] <==> S[DataOut__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_DataOut__DEVICE_EXTENSIONInv(S)[x]} _S_DataOut__DEVICE_EXTENSIONInv(S)[x] <==> S[DataOut__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_DataOut__DEVICE_EXTENSION(S)} S[x] ==> _S_DataOut__DEVICE_EXTENSION(S)[DataOut__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_DataOut__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_DataOut__DEVICE_EXTENSIONInv(S)[DataOut__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {DataOut__DEVICE_EXTENSION(x)} DataOut__DEVICE_EXTENSION(x) == x + 136);
+axiom (forall x:int :: {DataOut__DEVICE_EXTENSIONInv(x)} DataOut__DEVICE_EXTENSIONInv(x) == x - 136);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 136, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 136, 1) == DataOut__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 136)} MINUS_LEFT_PTR(x, 1, 136) == DataOut__DEVICE_EXTENSIONInv(x));
+function DeviceExtension__DEVICE_OBJECT(int) returns (int);
+function DeviceExtension__DEVICE_OBJECTInv(int) returns (int);
+function _S_DeviceExtension__DEVICE_OBJECT([int]bool) returns ([int]bool);
+function _S_DeviceExtension__DEVICE_OBJECTInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {DeviceExtension__DEVICE_OBJECTInv(DeviceExtension__DEVICE_OBJECT(x))} DeviceExtension__DEVICE_OBJECTInv(DeviceExtension__DEVICE_OBJECT(x)) == x);
+axiom (forall x:int :: {DeviceExtension__DEVICE_OBJECTInv(x)} DeviceExtension__DEVICE_OBJECT(DeviceExtension__DEVICE_OBJECTInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_DeviceExtension__DEVICE_OBJECT(S)[x]} _S_DeviceExtension__DEVICE_OBJECT(S)[x] <==> S[DeviceExtension__DEVICE_OBJECTInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_DeviceExtension__DEVICE_OBJECTInv(S)[x]} _S_DeviceExtension__DEVICE_OBJECTInv(S)[x] <==> S[DeviceExtension__DEVICE_OBJECT(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_DeviceExtension__DEVICE_OBJECT(S)} S[x] ==> _S_DeviceExtension__DEVICE_OBJECT(S)[DeviceExtension__DEVICE_OBJECT(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_DeviceExtension__DEVICE_OBJECTInv(S)} S[x] ==> _S_DeviceExtension__DEVICE_OBJECTInv(S)[DeviceExtension__DEVICE_OBJECTInv(x)]);
+
+axiom (forall x:int :: {DeviceExtension__DEVICE_OBJECT(x)} DeviceExtension__DEVICE_OBJECT(x) == x + 40);
+axiom (forall x:int :: {DeviceExtension__DEVICE_OBJECTInv(x)} DeviceExtension__DEVICE_OBJECTInv(x) == x - 40);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 40, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 40, 1) == DeviceExtension__DEVICE_OBJECTInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 40)} MINUS_LEFT_PTR(x, 1, 40) == DeviceExtension__DEVICE_OBJECTInv(x));
+function File__DEVICE_EXTENSION(int) returns (int);
+function File__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_File__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_File__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {File__DEVICE_EXTENSIONInv(File__DEVICE_EXTENSION(x))} File__DEVICE_EXTENSIONInv(File__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {File__DEVICE_EXTENSIONInv(x)} File__DEVICE_EXTENSION(File__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_File__DEVICE_EXTENSION(S)[x]} _S_File__DEVICE_EXTENSION(S)[x] <==> S[File__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_File__DEVICE_EXTENSIONInv(S)[x]} _S_File__DEVICE_EXTENSIONInv(S)[x] <==> S[File__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_File__DEVICE_EXTENSION(S)} S[x] ==> _S_File__DEVICE_EXTENSION(S)[File__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_File__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_File__DEVICE_EXTENSIONInv(S)[File__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {File__DEVICE_EXTENSION(x)} File__DEVICE_EXTENSION(x) == x + 260);
+axiom (forall x:int :: {File__DEVICE_EXTENSIONInv(x)} File__DEVICE_EXTENSIONInv(x) == x - 260);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 260, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 260, 1) == File__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 260)} MINUS_LEFT_PTR(x, 1, 260) == File__DEVICE_EXTENSIONInv(x));
+function File__PORT(int) returns (int);
+function File__PORTInv(int) returns (int);
+function _S_File__PORT([int]bool) returns ([int]bool);
+function _S_File__PORTInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {File__PORTInv(File__PORT(x))} File__PORTInv(File__PORT(x)) == x);
+axiom (forall x:int :: {File__PORTInv(x)} File__PORT(File__PORTInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_File__PORT(S)[x]} _S_File__PORT(S)[x] <==> S[File__PORTInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_File__PORTInv(S)[x]} _S_File__PORTInv(S)[x] <==> S[File__PORT(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_File__PORT(S)} S[x] ==> _S_File__PORT(S)[File__PORT(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_File__PORTInv(S)} S[x] ==> _S_File__PORTInv(S)[File__PORTInv(x)]);
+
+axiom (forall x:int :: {File__PORT(x)} File__PORT(x) == x + 0);
+axiom (forall x:int :: {File__PORTInv(x)} File__PORTInv(x) == x - 0);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1) == File__PORTInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 0)} MINUS_LEFT_PTR(x, 1, 0) == File__PORTInv(x));
+function Flags__DEVICE_OBJECT(int) returns (int);
+function Flags__DEVICE_OBJECTInv(int) returns (int);
+function _S_Flags__DEVICE_OBJECT([int]bool) returns ([int]bool);
+function _S_Flags__DEVICE_OBJECTInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {Flags__DEVICE_OBJECTInv(Flags__DEVICE_OBJECT(x))} Flags__DEVICE_OBJECTInv(Flags__DEVICE_OBJECT(x)) == x);
+axiom (forall x:int :: {Flags__DEVICE_OBJECTInv(x)} Flags__DEVICE_OBJECT(Flags__DEVICE_OBJECTInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_Flags__DEVICE_OBJECT(S)[x]} _S_Flags__DEVICE_OBJECT(S)[x] <==> S[Flags__DEVICE_OBJECTInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_Flags__DEVICE_OBJECTInv(S)[x]} _S_Flags__DEVICE_OBJECTInv(S)[x] <==> S[Flags__DEVICE_OBJECT(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Flags__DEVICE_OBJECT(S)} S[x] ==> _S_Flags__DEVICE_OBJECT(S)[Flags__DEVICE_OBJECT(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Flags__DEVICE_OBJECTInv(S)} S[x] ==> _S_Flags__DEVICE_OBJECTInv(S)[Flags__DEVICE_OBJECTInv(x)]);
+
+axiom (forall x:int :: {Flags__DEVICE_OBJECT(x)} Flags__DEVICE_OBJECT(x) == x + 28);
+axiom (forall x:int :: {Flags__DEVICE_OBJECTInv(x)} Flags__DEVICE_OBJECTInv(x) == x - 28);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 28, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 28, 1) == Flags__DEVICE_OBJECTInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 28)} MINUS_LEFT_PTR(x, 1, 28) == Flags__DEVICE_OBJECTInv(x));
+function Flink__LIST_ENTRY(int) returns (int);
+function Flink__LIST_ENTRYInv(int) returns (int);
+function _S_Flink__LIST_ENTRY([int]bool) returns ([int]bool);
+function _S_Flink__LIST_ENTRYInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {Flink__LIST_ENTRYInv(Flink__LIST_ENTRY(x))} Flink__LIST_ENTRYInv(Flink__LIST_ENTRY(x)) == x);
+axiom (forall x:int :: {Flink__LIST_ENTRYInv(x)} Flink__LIST_ENTRY(Flink__LIST_ENTRYInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_Flink__LIST_ENTRY(S)[x]} _S_Flink__LIST_ENTRY(S)[x] <==> S[Flink__LIST_ENTRYInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_Flink__LIST_ENTRYInv(S)[x]} _S_Flink__LIST_ENTRYInv(S)[x] <==> S[Flink__LIST_ENTRY(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Flink__LIST_ENTRY(S)} S[x] ==> _S_Flink__LIST_ENTRY(S)[Flink__LIST_ENTRY(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Flink__LIST_ENTRYInv(S)} S[x] ==> _S_Flink__LIST_ENTRYInv(S)[Flink__LIST_ENTRYInv(x)]);
+
+axiom (forall x:int :: {Flink__LIST_ENTRY(x)} Flink__LIST_ENTRY(x) == x + 0);
+axiom (forall x:int :: {Flink__LIST_ENTRYInv(x)} Flink__LIST_ENTRYInv(x) == x - 0);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1) == Flink__LIST_ENTRYInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 0)} MINUS_LEFT_PTR(x, 1, 0) == Flink__LIST_ENTRYInv(x));
+function Free__PORT(int) returns (int);
+function Free__PORTInv(int) returns (int);
+function _S_Free__PORT([int]bool) returns ([int]bool);
+function _S_Free__PORTInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {Free__PORTInv(Free__PORT(x))} Free__PORTInv(Free__PORT(x)) == x);
+axiom (forall x:int :: {Free__PORTInv(x)} Free__PORT(Free__PORTInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_Free__PORT(S)[x]} _S_Free__PORT(S)[x] <==> S[Free__PORTInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_Free__PORTInv(S)[x]} _S_Free__PORTInv(S)[x] <==> S[Free__PORT(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Free__PORT(S)} S[x] ==> _S_Free__PORT(S)[Free__PORT(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Free__PORTInv(S)} S[x] ==> _S_Free__PORTInv(S)[Free__PORTInv(x)]);
+
+axiom (forall x:int :: {Free__PORT(x)} Free__PORT(x) == x + 11);
+axiom (forall x:int :: {Free__PORTInv(x)} Free__PORTInv(x) == x - 11);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 11, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 11, 1) == Free__PORTInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 11)} MINUS_LEFT_PTR(x, 1, 11) == Free__PORTInv(x));
+function GrandMaster__GLOBALS(int) returns (int);
+function GrandMaster__GLOBALSInv(int) returns (int);
+function _S_GrandMaster__GLOBALS([int]bool) returns ([int]bool);
+function _S_GrandMaster__GLOBALSInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {GrandMaster__GLOBALSInv(GrandMaster__GLOBALS(x))} GrandMaster__GLOBALSInv(GrandMaster__GLOBALS(x)) == x);
+axiom (forall x:int :: {GrandMaster__GLOBALSInv(x)} GrandMaster__GLOBALS(GrandMaster__GLOBALSInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_GrandMaster__GLOBALS(S)[x]} _S_GrandMaster__GLOBALS(S)[x] <==> S[GrandMaster__GLOBALSInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_GrandMaster__GLOBALSInv(S)[x]} _S_GrandMaster__GLOBALSInv(S)[x] <==> S[GrandMaster__GLOBALS(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_GrandMaster__GLOBALS(S)} S[x] ==> _S_GrandMaster__GLOBALS(S)[GrandMaster__GLOBALS(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_GrandMaster__GLOBALSInv(S)} S[x] ==> _S_GrandMaster__GLOBALSInv(S)[GrandMaster__GLOBALSInv(x)]);
+
+axiom (forall x:int :: {GrandMaster__GLOBALS(x)} GrandMaster__GLOBALS(x) == x + 4);
+axiom (forall x:int :: {GrandMaster__GLOBALSInv(x)} GrandMaster__GLOBALSInv(x) == x - 4);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 4, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 4, 1) == GrandMaster__GLOBALSInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 4)} MINUS_LEFT_PTR(x, 1, 4) == GrandMaster__GLOBALSInv(x));
+function InitExtension__GLOBALS(int) returns (int);
+function InitExtension__GLOBALSInv(int) returns (int);
+function _S_InitExtension__GLOBALS([int]bool) returns ([int]bool);
+function _S_InitExtension__GLOBALSInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {InitExtension__GLOBALSInv(InitExtension__GLOBALS(x))} InitExtension__GLOBALSInv(InitExtension__GLOBALS(x)) == x);
+axiom (forall x:int :: {InitExtension__GLOBALSInv(x)} InitExtension__GLOBALS(InitExtension__GLOBALSInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_InitExtension__GLOBALS(S)[x]} _S_InitExtension__GLOBALS(S)[x] <==> S[InitExtension__GLOBALSInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_InitExtension__GLOBALSInv(S)[x]} _S_InitExtension__GLOBALSInv(S)[x] <==> S[InitExtension__GLOBALS(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_InitExtension__GLOBALS(S)} S[x] ==> _S_InitExtension__GLOBALS(S)[InitExtension__GLOBALS(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_InitExtension__GLOBALSInv(S)} S[x] ==> _S_InitExtension__GLOBALSInv(S)[InitExtension__GLOBALSInv(x)]);
+
+axiom (forall x:int :: {InitExtension__GLOBALS(x)} InitExtension__GLOBALS(x) == x + 64);
+axiom (forall x:int :: {InitExtension__GLOBALSInv(x)} InitExtension__GLOBALSInv(x) == x - 64);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 64, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 64, 1) == InitExtension__GLOBALSInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 64)} MINUS_LEFT_PTR(x, 1, 64) == InitExtension__GLOBALSInv(x));
+function InputData__DEVICE_EXTENSION(int) returns (int);
+function InputData__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_InputData__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_InputData__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {InputData__DEVICE_EXTENSIONInv(InputData__DEVICE_EXTENSION(x))} InputData__DEVICE_EXTENSIONInv(InputData__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {InputData__DEVICE_EXTENSIONInv(x)} InputData__DEVICE_EXTENSION(InputData__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_InputData__DEVICE_EXTENSION(S)[x]} _S_InputData__DEVICE_EXTENSION(S)[x] <==> S[InputData__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_InputData__DEVICE_EXTENSIONInv(S)[x]} _S_InputData__DEVICE_EXTENSIONInv(S)[x] <==> S[InputData__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_InputData__DEVICE_EXTENSION(S)} S[x] ==> _S_InputData__DEVICE_EXTENSION(S)[InputData__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_InputData__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_InputData__DEVICE_EXTENSIONInv(S)[InputData__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {InputData__DEVICE_EXTENSION(x)} InputData__DEVICE_EXTENSION(x) == x + 128);
+axiom (forall x:int :: {InputData__DEVICE_EXTENSIONInv(x)} InputData__DEVICE_EXTENSIONInv(x) == x - 128);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 128, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 128, 1) == InputData__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 128)} MINUS_LEFT_PTR(x, 1, 128) == InputData__DEVICE_EXTENSIONInv(x));
+function LegacyDeviceList__GLOBALS(int) returns (int);
+function LegacyDeviceList__GLOBALSInv(int) returns (int);
+function _S_LegacyDeviceList__GLOBALS([int]bool) returns ([int]bool);
+function _S_LegacyDeviceList__GLOBALSInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {LegacyDeviceList__GLOBALSInv(LegacyDeviceList__GLOBALS(x))} LegacyDeviceList__GLOBALSInv(LegacyDeviceList__GLOBALS(x)) == x);
+axiom (forall x:int :: {LegacyDeviceList__GLOBALSInv(x)} LegacyDeviceList__GLOBALS(LegacyDeviceList__GLOBALSInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_LegacyDeviceList__GLOBALS(S)[x]} _S_LegacyDeviceList__GLOBALS(S)[x] <==> S[LegacyDeviceList__GLOBALSInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_LegacyDeviceList__GLOBALSInv(S)[x]} _S_LegacyDeviceList__GLOBALSInv(S)[x] <==> S[LegacyDeviceList__GLOBALS(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_LegacyDeviceList__GLOBALS(S)} S[x] ==> _S_LegacyDeviceList__GLOBALS(S)[LegacyDeviceList__GLOBALS(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_LegacyDeviceList__GLOBALSInv(S)} S[x] ==> _S_LegacyDeviceList__GLOBALSInv(S)[LegacyDeviceList__GLOBALSInv(x)]);
+
+axiom (forall x:int :: {LegacyDeviceList__GLOBALS(x)} LegacyDeviceList__GLOBALS(x) == x + 864);
+axiom (forall x:int :: {LegacyDeviceList__GLOBALSInv(x)} LegacyDeviceList__GLOBALSInv(x) == x - 864);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 864, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 864, 1) == LegacyDeviceList__GLOBALSInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 864)} MINUS_LEFT_PTR(x, 1, 864) == LegacyDeviceList__GLOBALSInv(x));
+function Length__UNICODE_STRING(int) returns (int);
+function Length__UNICODE_STRINGInv(int) returns (int);
+function _S_Length__UNICODE_STRING([int]bool) returns ([int]bool);
+function _S_Length__UNICODE_STRINGInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {Length__UNICODE_STRINGInv(Length__UNICODE_STRING(x))} Length__UNICODE_STRINGInv(Length__UNICODE_STRING(x)) == x);
+axiom (forall x:int :: {Length__UNICODE_STRINGInv(x)} Length__UNICODE_STRING(Length__UNICODE_STRINGInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_Length__UNICODE_STRING(S)[x]} _S_Length__UNICODE_STRING(S)[x] <==> S[Length__UNICODE_STRINGInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_Length__UNICODE_STRINGInv(S)[x]} _S_Length__UNICODE_STRINGInv(S)[x] <==> S[Length__UNICODE_STRING(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Length__UNICODE_STRING(S)} S[x] ==> _S_Length__UNICODE_STRING(S)[Length__UNICODE_STRING(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Length__UNICODE_STRINGInv(S)} S[x] ==> _S_Length__UNICODE_STRINGInv(S)[Length__UNICODE_STRINGInv(x)]);
+
+axiom (forall x:int :: {Length__UNICODE_STRING(x)} Length__UNICODE_STRING(x) == x + 0);
+axiom (forall x:int :: {Length__UNICODE_STRINGInv(x)} Length__UNICODE_STRINGInv(x) == x - 0);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1) == Length__UNICODE_STRINGInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 0)} MINUS_LEFT_PTR(x, 1, 0) == Length__UNICODE_STRINGInv(x));
+function Link__DEVICE_EXTENSION(int) returns (int);
+function Link__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_Link__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_Link__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {Link__DEVICE_EXTENSIONInv(Link__DEVICE_EXTENSION(x))} Link__DEVICE_EXTENSIONInv(Link__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {Link__DEVICE_EXTENSIONInv(x)} Link__DEVICE_EXTENSION(Link__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_Link__DEVICE_EXTENSION(S)[x]} _S_Link__DEVICE_EXTENSION(S)[x] <==> S[Link__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_Link__DEVICE_EXTENSIONInv(S)[x]} _S_Link__DEVICE_EXTENSIONInv(S)[x] <==> S[Link__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Link__DEVICE_EXTENSION(S)} S[x] ==> _S_Link__DEVICE_EXTENSION(S)[Link__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Link__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_Link__DEVICE_EXTENSIONInv(S)[Link__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {Link__DEVICE_EXTENSION(x)} Link__DEVICE_EXTENSION(x) == x + 252);
+axiom (forall x:int :: {Link__DEVICE_EXTENSIONInv(x)} Link__DEVICE_EXTENSIONInv(x) == x - 252);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 252, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 252, 1) == Link__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 252)} MINUS_LEFT_PTR(x, 1, 252) == Link__DEVICE_EXTENSIONInv(x));
+function MaximumLength__UNICODE_STRING(int) returns (int);
+function MaximumLength__UNICODE_STRINGInv(int) returns (int);
+function _S_MaximumLength__UNICODE_STRING([int]bool) returns ([int]bool);
+function _S_MaximumLength__UNICODE_STRINGInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {MaximumLength__UNICODE_STRINGInv(MaximumLength__UNICODE_STRING(x))} MaximumLength__UNICODE_STRINGInv(MaximumLength__UNICODE_STRING(x)) == x);
+axiom (forall x:int :: {MaximumLength__UNICODE_STRINGInv(x)} MaximumLength__UNICODE_STRING(MaximumLength__UNICODE_STRINGInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_MaximumLength__UNICODE_STRING(S)[x]} _S_MaximumLength__UNICODE_STRING(S)[x] <==> S[MaximumLength__UNICODE_STRINGInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_MaximumLength__UNICODE_STRINGInv(S)[x]} _S_MaximumLength__UNICODE_STRINGInv(S)[x] <==> S[MaximumLength__UNICODE_STRING(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_MaximumLength__UNICODE_STRING(S)} S[x] ==> _S_MaximumLength__UNICODE_STRING(S)[MaximumLength__UNICODE_STRING(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_MaximumLength__UNICODE_STRINGInv(S)} S[x] ==> _S_MaximumLength__UNICODE_STRINGInv(S)[MaximumLength__UNICODE_STRINGInv(x)]);
+
+axiom (forall x:int :: {MaximumLength__UNICODE_STRING(x)} MaximumLength__UNICODE_STRING(x) == x + 2);
+axiom (forall x:int :: {MaximumLength__UNICODE_STRINGInv(x)} MaximumLength__UNICODE_STRINGInv(x) == x - 2);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 2, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 2, 1) == MaximumLength__UNICODE_STRINGInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 2)} MINUS_LEFT_PTR(x, 1, 2) == MaximumLength__UNICODE_STRINGInv(x));
+function Mutex__GLOBALS(int) returns (int);
+function Mutex__GLOBALSInv(int) returns (int);
+function _S_Mutex__GLOBALS([int]bool) returns ([int]bool);
+function _S_Mutex__GLOBALSInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {Mutex__GLOBALSInv(Mutex__GLOBALS(x))} Mutex__GLOBALSInv(Mutex__GLOBALS(x)) == x);
+axiom (forall x:int :: {Mutex__GLOBALSInv(x)} Mutex__GLOBALS(Mutex__GLOBALSInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_Mutex__GLOBALS(S)[x]} _S_Mutex__GLOBALS(S)[x] <==> S[Mutex__GLOBALSInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_Mutex__GLOBALSInv(S)[x]} _S_Mutex__GLOBALSInv(S)[x] <==> S[Mutex__GLOBALS(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Mutex__GLOBALS(S)} S[x] ==> _S_Mutex__GLOBALS(S)[Mutex__GLOBALS(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Mutex__GLOBALSInv(S)} S[x] ==> _S_Mutex__GLOBALSInv(S)[Mutex__GLOBALSInv(x)]);
+
+axiom (forall x:int :: {Mutex__GLOBALS(x)} Mutex__GLOBALS(x) == x + 24);
+axiom (forall x:int :: {Mutex__GLOBALSInv(x)} Mutex__GLOBALSInv(x) == x - 24);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 24, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 24, 1) == Mutex__GLOBALSInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 24)} MINUS_LEFT_PTR(x, 1, 24) == Mutex__GLOBALSInv(x));
+function NumberLegacyPorts__GLOBALS(int) returns (int);
+function NumberLegacyPorts__GLOBALSInv(int) returns (int);
+function _S_NumberLegacyPorts__GLOBALS([int]bool) returns ([int]bool);
+function _S_NumberLegacyPorts__GLOBALSInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {NumberLegacyPorts__GLOBALSInv(NumberLegacyPorts__GLOBALS(x))} NumberLegacyPorts__GLOBALSInv(NumberLegacyPorts__GLOBALS(x)) == x);
+axiom (forall x:int :: {NumberLegacyPorts__GLOBALSInv(x)} NumberLegacyPorts__GLOBALS(NumberLegacyPorts__GLOBALSInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_NumberLegacyPorts__GLOBALS(S)[x]} _S_NumberLegacyPorts__GLOBALS(S)[x] <==> S[NumberLegacyPorts__GLOBALSInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_NumberLegacyPorts__GLOBALSInv(S)[x]} _S_NumberLegacyPorts__GLOBALSInv(S)[x] <==> S[NumberLegacyPorts__GLOBALS(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_NumberLegacyPorts__GLOBALS(S)} S[x] ==> _S_NumberLegacyPorts__GLOBALS(S)[NumberLegacyPorts__GLOBALS(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_NumberLegacyPorts__GLOBALSInv(S)} S[x] ==> _S_NumberLegacyPorts__GLOBALSInv(S)[NumberLegacyPorts__GLOBALSInv(x)]);
+
+axiom (forall x:int :: {NumberLegacyPorts__GLOBALS(x)} NumberLegacyPorts__GLOBALS(x) == x + 20);
+axiom (forall x:int :: {NumberLegacyPorts__GLOBALSInv(x)} NumberLegacyPorts__GLOBALSInv(x) == x - 20);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 20, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 20, 1) == NumberLegacyPorts__GLOBALSInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 20)} MINUS_LEFT_PTR(x, 1, 20) == NumberLegacyPorts__GLOBALSInv(x));
+function PnP__DEVICE_EXTENSION(int) returns (int);
+function PnP__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_PnP__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_PnP__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {PnP__DEVICE_EXTENSIONInv(PnP__DEVICE_EXTENSION(x))} PnP__DEVICE_EXTENSIONInv(PnP__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {PnP__DEVICE_EXTENSIONInv(x)} PnP__DEVICE_EXTENSION(PnP__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_PnP__DEVICE_EXTENSION(S)[x]} _S_PnP__DEVICE_EXTENSION(S)[x] <==> S[PnP__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_PnP__DEVICE_EXTENSIONInv(S)[x]} _S_PnP__DEVICE_EXTENSIONInv(S)[x] <==> S[PnP__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_PnP__DEVICE_EXTENSION(S)} S[x] ==> _S_PnP__DEVICE_EXTENSION(S)[PnP__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_PnP__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_PnP__DEVICE_EXTENSIONInv(S)[PnP__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {PnP__DEVICE_EXTENSION(x)} PnP__DEVICE_EXTENSION(x) == x + 104);
+axiom (forall x:int :: {PnP__DEVICE_EXTENSIONInv(x)} PnP__DEVICE_EXTENSIONInv(x) == x - 104);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 104, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 104, 1) == PnP__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 104)} MINUS_LEFT_PTR(x, 1, 104) == PnP__DEVICE_EXTENSIONInv(x));
+function Port__PORT(int) returns (int);
+function Port__PORTInv(int) returns (int);
+function _S_Port__PORT([int]bool) returns ([int]bool);
+function _S_Port__PORTInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {Port__PORTInv(Port__PORT(x))} Port__PORTInv(Port__PORT(x)) == x);
+axiom (forall x:int :: {Port__PORTInv(x)} Port__PORT(Port__PORTInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_Port__PORT(S)[x]} _S_Port__PORT(S)[x] <==> S[Port__PORTInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_Port__PORTInv(S)[x]} _S_Port__PORTInv(S)[x] <==> S[Port__PORT(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Port__PORT(S)} S[x] ==> _S_Port__PORT(S)[Port__PORT(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Port__PORTInv(S)} S[x] ==> _S_Port__PORTInv(S)[Port__PORTInv(x)]);
+
+axiom (forall x:int :: {Port__PORT(x)} Port__PORT(x) == x + 4);
+axiom (forall x:int :: {Port__PORTInv(x)} Port__PORTInv(x) == x - 4);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 4, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 4, 1) == Port__PORTInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 4)} MINUS_LEFT_PTR(x, 1, 4) == Port__PORTInv(x));
+function PortsServiced__GLOBALS(int) returns (int);
+function PortsServiced__GLOBALSInv(int) returns (int);
+function _S_PortsServiced__GLOBALS([int]bool) returns ([int]bool);
+function _S_PortsServiced__GLOBALSInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {PortsServiced__GLOBALSInv(PortsServiced__GLOBALS(x))} PortsServiced__GLOBALSInv(PortsServiced__GLOBALS(x)) == x);
+axiom (forall x:int :: {PortsServiced__GLOBALSInv(x)} PortsServiced__GLOBALS(PortsServiced__GLOBALSInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_PortsServiced__GLOBALS(S)[x]} _S_PortsServiced__GLOBALS(S)[x] <==> S[PortsServiced__GLOBALSInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_PortsServiced__GLOBALSInv(S)[x]} _S_PortsServiced__GLOBALSInv(S)[x] <==> S[PortsServiced__GLOBALS(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_PortsServiced__GLOBALS(S)} S[x] ==> _S_PortsServiced__GLOBALS(S)[PortsServiced__GLOBALS(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_PortsServiced__GLOBALSInv(S)} S[x] ==> _S_PortsServiced__GLOBALSInv(S)[PortsServiced__GLOBALSInv(x)]);
+
+axiom (forall x:int :: {PortsServiced__GLOBALS(x)} PortsServiced__GLOBALS(x) == x + 60);
+axiom (forall x:int :: {PortsServiced__GLOBALSInv(x)} PortsServiced__GLOBALSInv(x) == x - 60);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 60, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 60, 1) == PortsServiced__GLOBALSInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 60)} MINUS_LEFT_PTR(x, 1, 60) == PortsServiced__GLOBALSInv(x));
+function Self__DEVICE_EXTENSION(int) returns (int);
+function Self__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_Self__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_Self__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {Self__DEVICE_EXTENSIONInv(Self__DEVICE_EXTENSION(x))} Self__DEVICE_EXTENSIONInv(Self__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {Self__DEVICE_EXTENSIONInv(x)} Self__DEVICE_EXTENSION(Self__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_Self__DEVICE_EXTENSION(S)[x]} _S_Self__DEVICE_EXTENSION(S)[x] <==> S[Self__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_Self__DEVICE_EXTENSIONInv(S)[x]} _S_Self__DEVICE_EXTENSIONInv(S)[x] <==> S[Self__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Self__DEVICE_EXTENSION(S)} S[x] ==> _S_Self__DEVICE_EXTENSION(S)[Self__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Self__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_Self__DEVICE_EXTENSIONInv(S)[Self__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {Self__DEVICE_EXTENSION(x)} Self__DEVICE_EXTENSION(x) == x + 0);
+axiom (forall x:int :: {Self__DEVICE_EXTENSIONInv(x)} Self__DEVICE_EXTENSIONInv(x) == x - 0);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1) == Self__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 0)} MINUS_LEFT_PTR(x, 1, 0) == Self__DEVICE_EXTENSIONInv(x));
+function SpinLock__DEVICE_EXTENSION(int) returns (int);
+function SpinLock__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_SpinLock__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_SpinLock__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {SpinLock__DEVICE_EXTENSIONInv(SpinLock__DEVICE_EXTENSION(x))} SpinLock__DEVICE_EXTENSIONInv(SpinLock__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {SpinLock__DEVICE_EXTENSIONInv(x)} SpinLock__DEVICE_EXTENSION(SpinLock__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_SpinLock__DEVICE_EXTENSION(S)[x]} _S_SpinLock__DEVICE_EXTENSION(S)[x] <==> S[SpinLock__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_SpinLock__DEVICE_EXTENSIONInv(S)[x]} _S_SpinLock__DEVICE_EXTENSIONInv(S)[x] <==> S[SpinLock__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_SpinLock__DEVICE_EXTENSION(S)} S[x] ==> _S_SpinLock__DEVICE_EXTENSION(S)[SpinLock__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_SpinLock__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_SpinLock__DEVICE_EXTENSIONInv(S)[SpinLock__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {SpinLock__DEVICE_EXTENSION(x)} SpinLock__DEVICE_EXTENSION(x) == x + 152);
+axiom (forall x:int :: {SpinLock__DEVICE_EXTENSIONInv(x)} SpinLock__DEVICE_EXTENSIONInv(x) == x - 152);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 152, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 152, 1) == SpinLock__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 152)} MINUS_LEFT_PTR(x, 1, 152) == SpinLock__DEVICE_EXTENSIONInv(x));
+function StackSize__DEVICE_OBJECT(int) returns (int);
+function StackSize__DEVICE_OBJECTInv(int) returns (int);
+function _S_StackSize__DEVICE_OBJECT([int]bool) returns ([int]bool);
+function _S_StackSize__DEVICE_OBJECTInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {StackSize__DEVICE_OBJECTInv(StackSize__DEVICE_OBJECT(x))} StackSize__DEVICE_OBJECTInv(StackSize__DEVICE_OBJECT(x)) == x);
+axiom (forall x:int :: {StackSize__DEVICE_OBJECTInv(x)} StackSize__DEVICE_OBJECT(StackSize__DEVICE_OBJECTInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_StackSize__DEVICE_OBJECT(S)[x]} _S_StackSize__DEVICE_OBJECT(S)[x] <==> S[StackSize__DEVICE_OBJECTInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_StackSize__DEVICE_OBJECTInv(S)[x]} _S_StackSize__DEVICE_OBJECTInv(S)[x] <==> S[StackSize__DEVICE_OBJECT(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_StackSize__DEVICE_OBJECT(S)} S[x] ==> _S_StackSize__DEVICE_OBJECT(S)[StackSize__DEVICE_OBJECT(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_StackSize__DEVICE_OBJECTInv(S)} S[x] ==> _S_StackSize__DEVICE_OBJECTInv(S)[StackSize__DEVICE_OBJECTInv(x)]);
+
+axiom (forall x:int :: {StackSize__DEVICE_OBJECT(x)} StackSize__DEVICE_OBJECT(x) == x + 48);
+axiom (forall x:int :: {StackSize__DEVICE_OBJECTInv(x)} StackSize__DEVICE_OBJECTInv(x) == x - 48);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 48, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 48, 1) == StackSize__DEVICE_OBJECTInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 48)} MINUS_LEFT_PTR(x, 1, 48) == StackSize__DEVICE_OBJECTInv(x));
+function Started__DEVICE_EXTENSION(int) returns (int);
+function Started__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_Started__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_Started__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {Started__DEVICE_EXTENSIONInv(Started__DEVICE_EXTENSION(x))} Started__DEVICE_EXTENSIONInv(Started__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {Started__DEVICE_EXTENSIONInv(x)} Started__DEVICE_EXTENSION(Started__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_Started__DEVICE_EXTENSION(S)[x]} _S_Started__DEVICE_EXTENSION(S)[x] <==> S[Started__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_Started__DEVICE_EXTENSIONInv(S)[x]} _S_Started__DEVICE_EXTENSIONInv(S)[x] <==> S[Started__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Started__DEVICE_EXTENSION(S)} S[x] ==> _S_Started__DEVICE_EXTENSION(S)[Started__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Started__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_Started__DEVICE_EXTENSIONInv(S)[Started__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {Started__DEVICE_EXTENSION(x)} Started__DEVICE_EXTENSION(x) == x + 105);
+axiom (forall x:int :: {Started__DEVICE_EXTENSIONInv(x)} Started__DEVICE_EXTENSIONInv(x) == x - 105);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 105, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 105, 1) == Started__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 105)} MINUS_LEFT_PTR(x, 1, 105) == Started__DEVICE_EXTENSIONInv(x));
+function TopPort__DEVICE_EXTENSION(int) returns (int);
+function TopPort__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_TopPort__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_TopPort__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {TopPort__DEVICE_EXTENSIONInv(TopPort__DEVICE_EXTENSION(x))} TopPort__DEVICE_EXTENSIONInv(TopPort__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {TopPort__DEVICE_EXTENSIONInv(x)} TopPort__DEVICE_EXTENSION(TopPort__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_TopPort__DEVICE_EXTENSION(S)[x]} _S_TopPort__DEVICE_EXTENSION(S)[x] <==> S[TopPort__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_TopPort__DEVICE_EXTENSIONInv(S)[x]} _S_TopPort__DEVICE_EXTENSIONInv(S)[x] <==> S[TopPort__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_TopPort__DEVICE_EXTENSION(S)} S[x] ==> _S_TopPort__DEVICE_EXTENSION(S)[TopPort__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_TopPort__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_TopPort__DEVICE_EXTENSIONInv(S)[TopPort__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {TopPort__DEVICE_EXTENSION(x)} TopPort__DEVICE_EXTENSION(x) == x + 8);
+axiom (forall x:int :: {TopPort__DEVICE_EXTENSIONInv(x)} TopPort__DEVICE_EXTENSIONInv(x) == x - 8);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 8, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 8, 1) == TopPort__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 8)} MINUS_LEFT_PTR(x, 1, 8) == TopPort__DEVICE_EXTENSIONInv(x));
+function UnitId__DEVICE_EXTENSION(int) returns (int);
+function UnitId__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_UnitId__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_UnitId__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {UnitId__DEVICE_EXTENSIONInv(UnitId__DEVICE_EXTENSION(x))} UnitId__DEVICE_EXTENSIONInv(UnitId__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {UnitId__DEVICE_EXTENSIONInv(x)} UnitId__DEVICE_EXTENSION(UnitId__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_UnitId__DEVICE_EXTENSION(S)[x]} _S_UnitId__DEVICE_EXTENSION(S)[x] <==> S[UnitId__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_UnitId__DEVICE_EXTENSIONInv(S)[x]} _S_UnitId__DEVICE_EXTENSIONInv(S)[x] <==> S[UnitId__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_UnitId__DEVICE_EXTENSION(S)} S[x] ==> _S_UnitId__DEVICE_EXTENSION(S)[UnitId__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_UnitId__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_UnitId__DEVICE_EXTENSIONInv(S)[UnitId__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {UnitId__DEVICE_EXTENSION(x)} UnitId__DEVICE_EXTENSION(x) == x + 176);
+axiom (forall x:int :: {UnitId__DEVICE_EXTENSIONInv(x)} UnitId__DEVICE_EXTENSIONInv(x) == x - 176);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 176, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 176, 1) == UnitId__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 176)} MINUS_LEFT_PTR(x, 1, 176) == UnitId__DEVICE_EXTENSIONInv(x));
+function WaitWakeSpinLock__DEVICE_EXTENSION(int) returns (int);
+function WaitWakeSpinLock__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_WaitWakeSpinLock__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_WaitWakeSpinLock__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {WaitWakeSpinLock__DEVICE_EXTENSIONInv(WaitWakeSpinLock__DEVICE_EXTENSION(x))} WaitWakeSpinLock__DEVICE_EXTENSIONInv(WaitWakeSpinLock__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {WaitWakeSpinLock__DEVICE_EXTENSIONInv(x)} WaitWakeSpinLock__DEVICE_EXTENSION(WaitWakeSpinLock__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_WaitWakeSpinLock__DEVICE_EXTENSION(S)[x]} _S_WaitWakeSpinLock__DEVICE_EXTENSION(S)[x] <==> S[WaitWakeSpinLock__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_WaitWakeSpinLock__DEVICE_EXTENSIONInv(S)[x]} _S_WaitWakeSpinLock__DEVICE_EXTENSIONInv(S)[x] <==> S[WaitWakeSpinLock__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_WaitWakeSpinLock__DEVICE_EXTENSION(S)} S[x] ==> _S_WaitWakeSpinLock__DEVICE_EXTENSION(S)[WaitWakeSpinLock__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_WaitWakeSpinLock__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_WaitWakeSpinLock__DEVICE_EXTENSIONInv(S)[WaitWakeSpinLock__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {WaitWakeSpinLock__DEVICE_EXTENSION(x)} WaitWakeSpinLock__DEVICE_EXTENSION(x) == x + 108);
+axiom (forall x:int :: {WaitWakeSpinLock__DEVICE_EXTENSIONInv(x)} WaitWakeSpinLock__DEVICE_EXTENSIONInv(x) == x - 108);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 108, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 108, 1) == WaitWakeSpinLock__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 108)} MINUS_LEFT_PTR(x, 1, 108) == WaitWakeSpinLock__DEVICE_EXTENSIONInv(x));
+function MINUS_BOTH_PTR_OR_BOTH_INT(a:int, b:int, size:int) returns (int);
+axiom (forall a:int, b:int, size:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(a,b,size)}
+size * MINUS_BOTH_PTR_OR_BOTH_INT(a,b,size) <= a - b && a - b < size * (MINUS_BOTH_PTR_OR_BOTH_INT(a,b,size) + 1));
+
+function MINUS_LEFT_PTR(a:int, a_size:int, b:int) returns (int);
+axiom(forall a:int, a_size:int, b:int :: {MINUS_LEFT_PTR(a,a_size,b)} MINUS_LEFT_PTR(a,a_size,b) == a - a_size * b);
+
+function PLUS(a:int, a_size:int, b:int) returns (int);
+axiom (forall a:int, a_size:int, b:int :: {PLUS(a,a_size,b)} PLUS(a,a_size,b) == a + a_size * b);
+
+function MULT(a:int, b:int) returns (int); // a*b
+axiom(forall a:int, b:int :: {MULT(a,b)} MULT(a,b) == a * b);
+
+function DIV(a:int, b:int) returns (int); // a/b
+
+axiom(forall a:int, b:int :: {DIV(a,b)}
+a >= 0 && b > 0 ==> b * DIV(a,b) <= a && a < b * (DIV(a,b) + 1)
+);
+
+axiom(forall a:int, b:int :: {DIV(a,b)}
+a >= 0 && b < 0 ==> b * DIV(a,b) <= a && a < b * (DIV(a,b) - 1)
+);
+
+axiom(forall a:int, b:int :: {DIV(a,b)}
+a < 0 && b > 0 ==> b * DIV(a,b) >= a && a > b * (DIV(a,b) - 1)
+);
+
+axiom(forall a:int, b:int :: {DIV(a,b)}
+a < 0 && b < 0 ==> b * DIV(a,b) >= a && a > b * (DIV(a,b) + 1)
+);
+
+function BINARY_BOTH_INT(a:int, b:int) returns (int);
+
+function POW2(a:int) returns (bool);
+axiom POW2(1);
+axiom POW2(2);
+axiom POW2(4);
+axiom POW2(8);
+axiom POW2(16);
+axiom POW2(32);
+axiom POW2(64);
+axiom POW2(128);
+axiom POW2(256);
+axiom POW2(512);
+axiom POW2(1024);
+axiom POW2(2048);
+axiom POW2(4096);
+axiom POW2(8192);
+axiom POW2(16384);
+axiom POW2(32768);
+axiom POW2(65536);
+axiom POW2(131072);
+axiom POW2(262144);
+axiom POW2(524288);
+axiom POW2(1048576);
+axiom POW2(2097152);
+axiom POW2(4194304);
+axiom POW2(8388608);
+axiom POW2(16777216);
+axiom POW2(33554432);
+
+function choose(a:bool, b:int, c:int) returns (x:int);
+axiom(forall a:bool, b:int, c:int :: {choose(a,b,c)} a ==> choose(a,b,c) == b);
+axiom(forall a:bool, b:int, c:int :: {choose(a,b,c)} !a ==> choose(a,b,c) == c);
+
+function BIT_BAND(a:int, b:int) returns (x:int);
+axiom(forall a:int, b:int :: {BIT_BAND(a,b)} a == b ==> BIT_BAND(a,b) == a);
+axiom(forall a:int, b:int :: {BIT_BAND(a,b)} POW2(a) && POW2(b) && a != b ==> BIT_BAND(a,b) == 0);
+axiom(forall a:int, b:int :: {BIT_BAND(a,b)} a == 0 || b == 0 ==> BIT_BAND(a,b) == 0);
+
+function BIT_BOR(a:int, b:int) returns (x:int);
+
+function BIT_BXOR(a:int, b:int) returns (x:int);
+
+function BIT_BNOT(a:int) returns (int);
+
+function LIFT(a:bool) returns (int);
+axiom(forall a:bool :: {LIFT(a)} a <==> LIFT(a) != 0);
+
+function NOT(a:int) returns (int);
+axiom(forall a:int :: {NOT(a)} a == 0 ==> NOT(a) != 0);
+axiom(forall a:int :: {NOT(a)} a != 0 ==> NOT(a) == 0);
+
+function NULL_CHECK(a:int) returns (int);
+axiom(forall a:int :: {NULL_CHECK(a)} a == 0 ==> NULL_CHECK(a) != 0);
+axiom(forall a:int :: {NULL_CHECK(a)} a != 0 ==> NULL_CHECK(a) == 0);
+
+
+
+
+procedure havoc_assert(i:int);
+requires (i != 0);
+
+procedure havoc_assume(i:int);
+ensures (i != 0);
+
+procedure __HAVOC_free(a:int);
+modifies alloc;
+ensures (forall x:int :: {alloc[x]} x == a || old(alloc)[x] == alloc[x]);
+ensures (alloc[a] == FREED);
+// Additional checks guarded by tranlator flags
+// requires alloc[a] == ALLOCATED;
+// requires Base(a) == a;
+
+procedure __HAVOC_malloc(obj_size:int) returns (new:int);
+requires obj_size >= 0;
+modifies alloc;
+ensures (new > 0);
+ensures (forall x:int :: {Base(x)} new <= x && x < new+obj_size ==> Base(x) == new);
+ensures (forall x:int :: {alloc[x]} x == new || old(alloc)[x] == alloc[x]);
+ensures old(alloc)[new] == UNALLOCATED && alloc[new] == ALLOCATED;
+
+procedure nondet_choice() returns (x:int);
+
+procedure _strdup(str:int) returns (new:int);
+
+procedure _xstrcasecmp(a0:int, a1:int) returns (ret:int);
+
+procedure _xstrcmp(a0:int, a1:int) returns (ret:int);
+
+var Res_DEVICE_STACK:[int]int;
+var Res_DEV_EXTN:[int]int;
+var Res_DEV_OBJ_INIT:[int]int;
+var Res_SPIN_LOCK:[int]int;
+
+
+
+////////////////////
+// Between predicate
+////////////////////
+function ReachBetween(f: [int]int, x: int, y: int, z: int) returns (bool);
+function ReachAvoiding(f: [int]int, x: int, y: int, z: int) returns (bool);
+
+
+//////////////////////////
+// Between set constructor
+//////////////////////////
+function ReachBetweenSet(f: [int]int, x: int, z: int) returns ([int]bool);
+
+////////////////////////////////////////////////////
+// axioms relating ReachBetween and ReachBetweenSet
+////////////////////////////////////////////////////
+axiom(forall f: [int]int, x: int, y: int, z: int :: {ReachBetweenSet(f, x, z)[y]} ReachBetweenSet(f, x, z)[y] <==> ReachBetween(f, x, y, z));
+axiom(forall f: [int]int, x: int, y: int, z: int :: {ReachBetween(f, x, y, z), ReachBetweenSet(f, x, z)} ReachBetween(f, x, y, z) ==> ReachBetweenSet(f, x, z)[y]);
+axiom(forall f: [int]int, x: int, z: int :: {ReachBetweenSet(f, x, z)} ReachBetween(f, x, x, x));
+
+
+//////////////////////////
+// Axioms for ReachBetween
+//////////////////////////
+
+// reflexive
+axiom(forall f: [int]int, x: int :: ReachBetween(f, x, x, x));
+
+// step
+//axiom(forall f: [int]int, x: int :: {f[x]} ReachBetween(f, x, f[x], f[x]));
+axiom(forall f: [int]int, x: int, y: int, z: int, w:int :: {ReachBetween(f, y, z, w), f[x]} ReachBetween(f, x, f[x], f[x]));
+
+// reach
+axiom(forall f: [int]int, x: int, y: int :: {f[x], ReachBetween(f, x, y, y)} ReachBetween(f, x, y, y) ==> x == y || ReachBetween(f, x, f[x], y));
+
+// cycle
+axiom(forall f: [int]int, x: int, y:int :: {f[x], ReachBetween(f, x, y, y)} f[x] == x && ReachBetween(f, x, y, y) ==> x == y);
+
+// sandwich
+axiom(forall f: [int]int, x: int, y: int :: {ReachBetween(f, x, y, x)} ReachBetween(f, x, y, x) ==> x == y);
+
+// order1
+axiom(forall f: [int]int, x: int, y: int, z: int :: {ReachBetween(f, x, y, y), ReachBetween(f, x, z, z)} ReachBetween(f, x, y, y) && ReachBetween(f, x, z, z) ==> ReachBetween(f, x, y, z) || ReachBetween(f, x, z, y));
+
+// order2
+axiom(forall f: [int]int, x: int, y: int, z: int :: {ReachBetween(f, x, y, z)} ReachBetween(f, x, y, z) ==> ReachBetween(f, x, y, y) && ReachBetween(f, y, z, z));
+
+// transitive1
+axiom(forall f: [int]int, x: int, y: int, z: int :: {ReachBetween(f, x, y, y), ReachBetween(f, y, z, z)} ReachBetween(f, x, y, y) && ReachBetween(f, y, z, z) ==> ReachBetween(f, x, z, z));
+
+// transitive2
+axiom(forall f: [int]int, x: int, y: int, z: int, w: int :: {ReachBetween(f, x, y, z), ReachBetween(f, y, w, z)} ReachBetween(f, x, y, z) && ReachBetween(f, y, w, z) ==> ReachBetween(f, x, y, w) && ReachBetween(f, x, w, z));
+
+// transitive3
+axiom(forall f: [int]int, x: int, y: int, z: int, w: int :: {ReachBetween(f, x, y, z), ReachBetween(f, x, w, y)} ReachBetween(f, x, y, z) && ReachBetween(f, x, w, y) ==> ReachBetween(f, x, w, z) && ReachBetween(f, w, y, z));
+
+// This axiom is required to deal with the incompleteness of the trigger for the reflexive axiom.
+// It cannot be proved using the rest of the axioms.
+axiom(forall f: [int]int, u:int, x: int :: {ReachBetween(f, u, x, x)} ReachBetween(f, u, x, x) ==> ReachBetween(f, u, u, x));
+
+// relation between ReachAvoiding and ReachBetween
+axiom(forall f: [int]int, x: int, y: int, z: int :: {ReachAvoiding(f, x, y, z)}{ReachBetween(f, x, y, z)} ReachAvoiding(f, x, y, z) <==> (ReachBetween(f, x, y, z) || (ReachBetween(f, x, y, y) && !ReachBetween(f, x, z, z))));
+
+// update
+axiom(forall f: [int]int, u: int, v: int, x: int, p: int, q: int :: {ReachAvoiding(f[p := q], u, v, x)} ReachAvoiding(f[p := q], u, v, x) <==> ((ReachAvoiding(f, u, v, p) && ReachAvoiding(f, u, v, x)) || (ReachAvoiding(f, u, p, x) && p != x && ReachAvoiding(f, q, v, p) && ReachAvoiding(f, q, v, x))));
+ ///////////////////////////////
+ // Shifts for linking fields
+ ///////////////////////////////
+function Shift_Flink__LIST_ENTRY(f: [int]int) returns ([int]int);
+axiom( forall f: [int]int, __x:int :: {f[Flink__LIST_ENTRY(__x)],Shift_Flink__LIST_ENTRY(f)} {Shift_Flink__LIST_ENTRY(f)[__x]} Shift_Flink__LIST_ENTRY(f)[__x] == f[Flink__LIST_ENTRY(__x)]);
+axiom(forall f: [int]int, __x:int, __v:int :: {Shift_Flink__LIST_ENTRY(f[Flink__LIST_ENTRY(__x) := __v])} Shift_Flink__LIST_ENTRY(f[Flink__LIST_ENTRY(__x) := __v]) == Shift_Flink__LIST_ENTRY(f)[__x := __v]);
+
+const unique Globals : int;
+axiom(Globals != 0);
+// the set of constants for 64 bit integers that Boogie doesn't parse
+const unique BOOGIE_LARGE_INT_3221553153:int;
+
+
+
+procedure ExAcquireFastMutex($FastMutex$1$15000.16$ExAcquireFastMutex$41:int);
+
+//TAG: ensures __preserves_mem
+ensures(Mem == old(Mem));
+//TAG: ensures __preserves_resource("DEV_OBJ_INIT") && __preserves_resource("DEV_EXTN")
+ensures((Res_DEV_OBJ_INIT == old(Res_DEV_OBJ_INIT)) && (Res_DEV_EXTN == old(Res_DEV_EXTN)));
+
+modifies Res_DEVICE_STACK;
+
+//TAG: net change in resource DEVICE_STACK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEVICE_STACK[r]} (Empty()[r]) || old(Res_DEVICE_STACK)[r] == Res_DEVICE_STACK[r]));
+modifies Res_DEV_EXTN;
+
+//TAG: net change in resource DEV_EXTN only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_EXTN[r]} (Empty()[r]) || old(Res_DEV_EXTN)[r] == Res_DEV_EXTN[r]));
+modifies Res_DEV_OBJ_INIT;
+
+//TAG: net change in resource DEV_OBJ_INIT only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_OBJ_INIT[r]} (Empty()[r]) || old(Res_DEV_OBJ_INIT)[r] == Res_DEV_OBJ_INIT[r]));
+modifies Res_SPIN_LOCK;
+
+//TAG: net change in resource SPIN_LOCK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_SPIN_LOCK[r]} (Empty()[r]) || old(Res_SPIN_LOCK)[r] == Res_SPIN_LOCK[r]));
+//TAG: updated memory locations at Mem[T.MinorFunction__IO_STACK_LOCATION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.MinorFunction__IO_STACK_LOCATION][_m]} (Empty()[_m]) || Mem[T.MinorFunction__IO_STACK_LOCATION][_m] == old(Mem)[T.MinorFunction__IO_STACK_LOCATION][_m]));
+//TAG: updated memory locations at Mem[T.CurrentStackLocation___unnamed_4_a7aa989c] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.CurrentStackLocation___unnamed_4_a7aa989c][_m]} (Empty()[_m]) || Mem[T.CurrentStackLocation___unnamed_4_a7aa989c][_m] == old(Mem)[T.CurrentStackLocation___unnamed_4_a7aa989c][_m]));
+//TAG: updated memory locations at Mem[T.DeviceExtension__DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.DeviceExtension__DEVICE_OBJECT][_m] == old(Mem)[T.DeviceExtension__DEVICE_OBJECT][_m]));
+//TAG: updated memory locations at Mem[T.Self__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Self__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Self__DEVICE_EXTENSION][_m] == old(Mem)[T.Self__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.Started__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Started__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Started__DEVICE_EXTENSION][_m] == old(Mem)[T.Started__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.GrandMaster__GLOBALS] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.GrandMaster__GLOBALS][_m]} (Empty()[_m]) || Mem[T.GrandMaster__GLOBALS][_m] == old(Mem)[T.GrandMaster__GLOBALS][_m]));
+//TAG: updated memory locations at Mem[T.P_DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.P_DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.P_DEVICE_OBJECT][_m] == old(Mem)[T.P_DEVICE_OBJECT][_m]));
+
+//TAG: havoc memory locations by default
+modifies Mem;
+
+
+procedure ExAllocatePoolWithTag($PoolType$1$14789.57$ExAllocatePoolWithTag$121:int, $NumberOfBytes$2$14790.16$ExAllocatePoolWithTag$121:int, $Tag$3$14791.15$ExAllocatePoolWithTag$121:int) returns ($result.ExAllocatePoolWithTag$14788.0$1$:int);
+
+//TAG: ensures __preserves_mem
+ensures(Mem == old(Mem));
+//TAG: ensures __preserves_resource("DEV_OBJ_INIT") && __preserves_resource("DEV_EXTN")
+ensures((Res_DEV_OBJ_INIT == old(Res_DEV_OBJ_INIT)) && (Res_DEV_EXTN == old(Res_DEV_EXTN)));
+
+modifies Res_DEVICE_STACK;
+
+//TAG: net change in resource DEVICE_STACK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEVICE_STACK[r]} (Empty()[r]) || old(Res_DEVICE_STACK)[r] == Res_DEVICE_STACK[r]));
+modifies Res_DEV_EXTN;
+
+//TAG: net change in resource DEV_EXTN only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_EXTN[r]} (Empty()[r]) || old(Res_DEV_EXTN)[r] == Res_DEV_EXTN[r]));
+modifies Res_DEV_OBJ_INIT;
+
+//TAG: net change in resource DEV_OBJ_INIT only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_OBJ_INIT[r]} (Empty()[r]) || old(Res_DEV_OBJ_INIT)[r] == Res_DEV_OBJ_INIT[r]));
+modifies Res_SPIN_LOCK;
+
+//TAG: net change in resource SPIN_LOCK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_SPIN_LOCK[r]} (Empty()[r]) || old(Res_SPIN_LOCK)[r] == Res_SPIN_LOCK[r]));
+//TAG: updated memory locations at Mem[T.MinorFunction__IO_STACK_LOCATION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.MinorFunction__IO_STACK_LOCATION][_m]} (Empty()[_m]) || Mem[T.MinorFunction__IO_STACK_LOCATION][_m] == old(Mem)[T.MinorFunction__IO_STACK_LOCATION][_m]));
+//TAG: updated memory locations at Mem[T.CurrentStackLocation___unnamed_4_a7aa989c] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.CurrentStackLocation___unnamed_4_a7aa989c][_m]} (Empty()[_m]) || Mem[T.CurrentStackLocation___unnamed_4_a7aa989c][_m] == old(Mem)[T.CurrentStackLocation___unnamed_4_a7aa989c][_m]));
+//TAG: updated memory locations at Mem[T.DeviceExtension__DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.DeviceExtension__DEVICE_OBJECT][_m] == old(Mem)[T.DeviceExtension__DEVICE_OBJECT][_m]));
+//TAG: updated memory locations at Mem[T.Self__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Self__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Self__DEVICE_EXTENSION][_m] == old(Mem)[T.Self__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.Started__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Started__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Started__DEVICE_EXTENSION][_m] == old(Mem)[T.Started__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.GrandMaster__GLOBALS] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.GrandMaster__GLOBALS][_m]} (Empty()[_m]) || Mem[T.GrandMaster__GLOBALS][_m] == old(Mem)[T.GrandMaster__GLOBALS][_m]));
+//TAG: updated memory locations at Mem[T.P_DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.P_DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.P_DEVICE_OBJECT][_m] == old(Mem)[T.P_DEVICE_OBJECT][_m]));
+
+//TAG: havoc memory locations by default
+modifies Mem;
+
+
+procedure ExFreePoolWithTag($P$1$14901.35$ExFreePoolWithTag$81:int, $Tag$2$14902.15$ExFreePoolWithTag$81:int);
+
+//TAG: ensures __preserves_mem
+ensures(Mem == old(Mem));
+//TAG: ensures __preserves_resource("DEV_OBJ_INIT") && __preserves_resource("DEV_EXTN")
+ensures((Res_DEV_OBJ_INIT == old(Res_DEV_OBJ_INIT)) && (Res_DEV_EXTN == old(Res_DEV_EXTN)));
+
+modifies Res_DEVICE_STACK;
+
+//TAG: net change in resource DEVICE_STACK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEVICE_STACK[r]} (Empty()[r]) || old(Res_DEVICE_STACK)[r] == Res_DEVICE_STACK[r]));
+modifies Res_DEV_EXTN;
+
+//TAG: net change in resource DEV_EXTN only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_EXTN[r]} (Empty()[r]) || old(Res_DEV_EXTN)[r] == Res_DEV_EXTN[r]));
+modifies Res_DEV_OBJ_INIT;
+
+//TAG: net change in resource DEV_OBJ_INIT only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_OBJ_INIT[r]} (Empty()[r]) || old(Res_DEV_OBJ_INIT)[r] == Res_DEV_OBJ_INIT[r]));
+modifies Res_SPIN_LOCK;
+
+//TAG: net change in resource SPIN_LOCK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_SPIN_LOCK[r]} (Empty()[r]) || old(Res_SPIN_LOCK)[r] == Res_SPIN_LOCK[r]));
+//TAG: updated memory locations at Mem[T.MinorFunction__IO_STACK_LOCATION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.MinorFunction__IO_STACK_LOCATION][_m]} (Empty()[_m]) || Mem[T.MinorFunction__IO_STACK_LOCATION][_m] == old(Mem)[T.MinorFunction__IO_STACK_LOCATION][_m]));
+//TAG: updated memory locations at Mem[T.CurrentStackLocation___unnamed_4_a7aa989c] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.CurrentStackLocation___unnamed_4_a7aa989c][_m]} (Empty()[_m]) || Mem[T.CurrentStackLocation___unnamed_4_a7aa989c][_m] == old(Mem)[T.CurrentStackLocation___unnamed_4_a7aa989c][_m]));
+//TAG: updated memory locations at Mem[T.DeviceExtension__DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.DeviceExtension__DEVICE_OBJECT][_m] == old(Mem)[T.DeviceExtension__DEVICE_OBJECT][_m]));
+//TAG: updated memory locations at Mem[T.Self__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Self__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Self__DEVICE_EXTENSION][_m] == old(Mem)[T.Self__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.Started__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Started__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Started__DEVICE_EXTENSION][_m] == old(Mem)[T.Started__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.GrandMaster__GLOBALS] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.GrandMaster__GLOBALS][_m]} (Empty()[_m]) || Mem[T.GrandMaster__GLOBALS][_m] == old(Mem)[T.GrandMaster__GLOBALS][_m]));
+//TAG: updated memory locations at Mem[T.P_DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.P_DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.P_DEVICE_OBJECT][_m] == old(Mem)[T.P_DEVICE_OBJECT][_m]));
+
+//TAG: havoc memory locations by default
+modifies Mem;
+
+
+procedure ExReleaseFastMutex($FastMutex$1$15013.16$ExReleaseFastMutex$41:int);
+
+//TAG: ensures __preserves_mem
+ensures(Mem == old(Mem));
+//TAG: ensures __preserves_resource("DEV_OBJ_INIT") && __preserves_resource("DEV_EXTN")
+ensures((Res_DEV_OBJ_INIT == old(Res_DEV_OBJ_INIT)) && (Res_DEV_EXTN == old(Res_DEV_EXTN)));
+
+modifies Res_DEVICE_STACK;
+
+//TAG: net change in resource DEVICE_STACK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEVICE_STACK[r]} (Empty()[r]) || old(Res_DEVICE_STACK)[r] == Res_DEVICE_STACK[r]));
+modifies Res_DEV_EXTN;
+
+//TAG: net change in resource DEV_EXTN only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_EXTN[r]} (Empty()[r]) || old(Res_DEV_EXTN)[r] == Res_DEV_EXTN[r]));
+modifies Res_DEV_OBJ_INIT;
+
+//TAG: net change in resource DEV_OBJ_INIT only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_OBJ_INIT[r]} (Empty()[r]) || old(Res_DEV_OBJ_INIT)[r] == Res_DEV_OBJ_INIT[r]));
+modifies Res_SPIN_LOCK;
+
+//TAG: net change in resource SPIN_LOCK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_SPIN_LOCK[r]} (Empty()[r]) || old(Res_SPIN_LOCK)[r] == Res_SPIN_LOCK[r]));
+//TAG: updated memory locations at Mem[T.MinorFunction__IO_STACK_LOCATION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.MinorFunction__IO_STACK_LOCATION][_m]} (Empty()[_m]) || Mem[T.MinorFunction__IO_STACK_LOCATION][_m] == old(Mem)[T.MinorFunction__IO_STACK_LOCATION][_m]));
+//TAG: updated memory locations at Mem[T.CurrentStackLocation___unnamed_4_a7aa989c] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.CurrentStackLocation___unnamed_4_a7aa989c][_m]} (Empty()[_m]) || Mem[T.CurrentStackLocation___unnamed_4_a7aa989c][_m] == old(Mem)[T.CurrentStackLocation___unnamed_4_a7aa989c][_m]));
+//TAG: updated memory locations at Mem[T.DeviceExtension__DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.DeviceExtension__DEVICE_OBJECT][_m] == old(Mem)[T.DeviceExtension__DEVICE_OBJECT][_m]));
+//TAG: updated memory locations at Mem[T.Self__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Self__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Self__DEVICE_EXTENSION][_m] == old(Mem)[T.Self__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.Started__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Started__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Started__DEVICE_EXTENSION][_m] == old(Mem)[T.Started__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.GrandMaster__GLOBALS] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.GrandMaster__GLOBALS][_m]} (Empty()[_m]) || Mem[T.GrandMaster__GLOBALS][_m] == old(Mem)[T.GrandMaster__GLOBALS][_m]));
+//TAG: updated memory locations at Mem[T.P_DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.P_DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.P_DEVICE_OBJECT][_m] == old(Mem)[T.P_DEVICE_OBJECT][_m]));
+
+//TAG: havoc memory locations by default
+modifies Mem;
+
+
+procedure InsertTailList($ListHead$1$6980.24$InsertTailList$81:int, $Entry$2$6981.41$InsertTailList$81:int);
+
+//TAG: ensures __preserves_resource("DEV_OBJ_INIT") && __preserves_resource("DEV_EXTN")
+ensures((Res_DEV_OBJ_INIT == old(Res_DEV_OBJ_INIT)) && (Res_DEV_EXTN == old(Res_DEV_EXTN)));
+//TAG: ensures __seteq(__btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), ListHead->Flink, ListHead), __setunion(__old(__btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), ListHead->Flink, ListHead)), __set(Entry)))
+ensures((Subset(ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY($ListHead$1$6980.24$InsertTailList$81)], $ListHead$1$6980.24$InsertTailList$81), Union(ReachBetweenSet(Shift_Flink__LIST_ENTRY(old(Mem)[T.Flink__LIST_ENTRY]), old(Mem)[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY($ListHead$1$6980.24$InsertTailList$81)], $ListHead$1$6980.24$InsertTailList$81), Singleton($Entry$2$6981.41$InsertTailList$81))) && Subset(Union(ReachBetweenSet(Shift_Flink__LIST_ENTRY(old(Mem)[T.Flink__LIST_ENTRY]), old(Mem)[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY($ListHead$1$6980.24$InsertTailList$81)], $ListHead$1$6980.24$InsertTailList$81), Singleton($Entry$2$6981.41$InsertTailList$81)), ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY($ListHead$1$6980.24$InsertTailList$81)], $ListHead$1$6980.24$InsertTailList$81))));
+
+modifies Res_DEVICE_STACK;
+
+//TAG: net change in resource DEVICE_STACK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEVICE_STACK[r]} (Empty()[r]) || old(Res_DEVICE_STACK)[r] == Res_DEVICE_STACK[r]));
+modifies Res_DEV_EXTN;
+
+//TAG: net change in resource DEV_EXTN only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_EXTN[r]} (Empty()[r]) || old(Res_DEV_EXTN)[r] == Res_DEV_EXTN[r]));
+modifies Res_DEV_OBJ_INIT;
+
+//TAG: net change in resource DEV_OBJ_INIT only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_OBJ_INIT[r]} (Empty()[r]) || old(Res_DEV_OBJ_INIT)[r] == Res_DEV_OBJ_INIT[r]));
+modifies Res_SPIN_LOCK;
+
+//TAG: net change in resource SPIN_LOCK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_SPIN_LOCK[r]} (Empty()[r]) || old(Res_SPIN_LOCK)[r] == Res_SPIN_LOCK[r]));
+//TAG: updated memory locations at Mem[T.MinorFunction__IO_STACK_LOCATION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.MinorFunction__IO_STACK_LOCATION][_m]} (Empty()[_m]) || Mem[T.MinorFunction__IO_STACK_LOCATION][_m] == old(Mem)[T.MinorFunction__IO_STACK_LOCATION][_m]));
+//TAG: updated memory locations at Mem[T.CurrentStackLocation___unnamed_4_a7aa989c] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.CurrentStackLocation___unnamed_4_a7aa989c][_m]} (Empty()[_m]) || Mem[T.CurrentStackLocation___unnamed_4_a7aa989c][_m] == old(Mem)[T.CurrentStackLocation___unnamed_4_a7aa989c][_m]));
+//TAG: updated memory locations at Mem[T.DeviceExtension__DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.DeviceExtension__DEVICE_OBJECT][_m] == old(Mem)[T.DeviceExtension__DEVICE_OBJECT][_m]));
+//TAG: updated memory locations at Mem[T.Self__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Self__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Self__DEVICE_EXTENSION][_m] == old(Mem)[T.Self__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.Started__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Started__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Started__DEVICE_EXTENSION][_m] == old(Mem)[T.Started__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.GrandMaster__GLOBALS] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.GrandMaster__GLOBALS][_m]} (Empty()[_m]) || Mem[T.GrandMaster__GLOBALS][_m] == old(Mem)[T.GrandMaster__GLOBALS][_m]));
+//TAG: updated memory locations at Mem[T.P_DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.P_DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.P_DEVICE_OBJECT][_m] == old(Mem)[T.P_DEVICE_OBJECT][_m]));
+
+//TAG: havoc memory locations by default
+modifies Mem;
+
+
+procedure IoDeleteDevice($DeviceObject$1$21328.67$IoDeleteDevice$41:int);
+
+//TAG: ensures __preserves_mem
+ensures(Mem == old(Mem));
+//TAG: requires 1 ==> __resource("DEV_OBJ_INIT", DeviceObject) == 1 && __resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)DeviceObject)->DeviceExtension)) == 1
+requires((true) ==> ((Res_DEV_OBJ_INIT[$DeviceObject$1$21328.67$IoDeleteDevice$41] == 1) && (Res_DEV_EXTN[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT($DeviceObject$1$21328.67$IoDeleteDevice$41)]] == 1)));
+//TAG: ensures 1 ==> __resource("DEV_OBJ_INIT", DeviceObject) == 0 && __resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)DeviceObject)->DeviceExtension)) == 0
+ensures((true) ==> ((Res_DEV_OBJ_INIT[$DeviceObject$1$21328.67$IoDeleteDevice$41] == 0) && (Res_DEV_EXTN[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT($DeviceObject$1$21328.67$IoDeleteDevice$41)]] == 0)));
+//TAG: ensures 1 ==> __updates_resource("DEV_OBJ_INIT", DeviceObject, 0) && __updates_resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)DeviceObject)->DeviceExtension), 0)
+ensures((true) ==> ((Res_DEV_OBJ_INIT == old(Res_DEV_OBJ_INIT)[$DeviceObject$1$21328.67$IoDeleteDevice$41 := 0]) && (Res_DEV_EXTN == old(Res_DEV_EXTN)[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT($DeviceObject$1$21328.67$IoDeleteDevice$41)] := 0])));
+//TAG: ensures !1 ==> __resource("DEV_OBJ_INIT", DeviceObject) == __old_resource("DEV_OBJ_INIT", DeviceObject) && __resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)DeviceObject)->DeviceExtension)) == __old_resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)DeviceObject)->DeviceExtension))
+ensures((!(true)) ==> ((Res_DEV_OBJ_INIT[$DeviceObject$1$21328.67$IoDeleteDevice$41] == old(Res_DEV_OBJ_INIT)[$DeviceObject$1$21328.67$IoDeleteDevice$41]) && (Res_DEV_EXTN[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT($DeviceObject$1$21328.67$IoDeleteDevice$41)]] == old(Res_DEV_EXTN)[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT($DeviceObject$1$21328.67$IoDeleteDevice$41)]])));
+//TAG: ensures !1 ==> __preserves_resource("DEV_OBJ_INIT") && __preserves_resource("DEV_EXTN")
+free ensures((!(true)) ==> ((Res_DEV_OBJ_INIT == old(Res_DEV_OBJ_INIT)) && (Res_DEV_EXTN == old(Res_DEV_EXTN))));
+
+modifies Res_DEVICE_STACK;
+
+//TAG: net change in resource DEVICE_STACK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEVICE_STACK[r]} (Empty()[r]) || old(Res_DEVICE_STACK)[r] == Res_DEVICE_STACK[r]));
+modifies Res_DEV_EXTN;
+
+//TAG: net change in resource DEV_EXTN only for: __set_empty, (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)DeviceObject)->DeviceExtension)
+ensures (Subset(Empty(), Union(Union(Empty(), Empty()), Singleton(Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT($DeviceObject$1$21328.67$IoDeleteDevice$41)]))) && (forall r:int :: {Res_DEV_EXTN[r]} (Empty()[r]) || (Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT($DeviceObject$1$21328.67$IoDeleteDevice$41)] == r) || old(Res_DEV_EXTN)[r] == Res_DEV_EXTN[r]));
+modifies Res_DEV_OBJ_INIT;
+
+//TAG: net change in resource DEV_OBJ_INIT only for: __set_empty, DeviceObject
+ensures (Subset(Empty(), Union(Union(Empty(), Empty()), Singleton($DeviceObject$1$21328.67$IoDeleteDevice$41))) && (forall r:int :: {Res_DEV_OBJ_INIT[r]} (Empty()[r]) || ($DeviceObject$1$21328.67$IoDeleteDevice$41 == r) || old(Res_DEV_OBJ_INIT)[r] == Res_DEV_OBJ_INIT[r]));
+modifies Res_SPIN_LOCK;
+
+//TAG: net change in resource SPIN_LOCK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_SPIN_LOCK[r]} (Empty()[r]) || old(Res_SPIN_LOCK)[r] == Res_SPIN_LOCK[r]));
+//TAG: updated memory locations at Mem[T.MinorFunction__IO_STACK_LOCATION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.MinorFunction__IO_STACK_LOCATION][_m]} (Empty()[_m]) || Mem[T.MinorFunction__IO_STACK_LOCATION][_m] == old(Mem)[T.MinorFunction__IO_STACK_LOCATION][_m]));
+//TAG: updated memory locations at Mem[T.CurrentStackLocation___unnamed_4_a7aa989c] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.CurrentStackLocation___unnamed_4_a7aa989c][_m]} (Empty()[_m]) || Mem[T.CurrentStackLocation___unnamed_4_a7aa989c][_m] == old(Mem)[T.CurrentStackLocation___unnamed_4_a7aa989c][_m]));
+//TAG: updated memory locations at Mem[T.DeviceExtension__DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.DeviceExtension__DEVICE_OBJECT][_m] == old(Mem)[T.DeviceExtension__DEVICE_OBJECT][_m]));
+//TAG: updated memory locations at Mem[T.Self__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Self__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Self__DEVICE_EXTENSION][_m] == old(Mem)[T.Self__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.Started__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Started__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Started__DEVICE_EXTENSION][_m] == old(Mem)[T.Started__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.GrandMaster__GLOBALS] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.GrandMaster__GLOBALS][_m]} (Empty()[_m]) || Mem[T.GrandMaster__GLOBALS][_m] == old(Mem)[T.GrandMaster__GLOBALS][_m]));
+//TAG: updated memory locations at Mem[T.P_DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.P_DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.P_DEVICE_OBJECT][_m] == old(Mem)[T.P_DEVICE_OBJECT][_m]));
+
+//TAG: havoc memory locations by default
+modifies Mem;
+
+
+procedure IoGetDeviceObjectPointer($ObjectName$1$21492.26$IoGetDeviceObjectPointer$161:int, $DesiredAccess$2$21493.22$IoGetDeviceObjectPointer$161:int, $FileObject$3$21494.24$IoGetDeviceObjectPointer$161:int, $DeviceObject$4$21495.26$IoGetDeviceObjectPointer$161:int) returns ($result.IoGetDeviceObjectPointer$21491.0$1$:int);
+
+//TAG: ensures __preserves_mem
+ensures(Mem == old(Mem));
+//TAG: ensures __preserves_resource("DEV_OBJ_INIT") && __preserves_resource("DEV_EXTN")
+ensures((Res_DEV_OBJ_INIT == old(Res_DEV_OBJ_INIT)) && (Res_DEV_EXTN == old(Res_DEV_EXTN)));
+
+modifies Res_DEVICE_STACK;
+
+//TAG: net change in resource DEVICE_STACK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEVICE_STACK[r]} (Empty()[r]) || old(Res_DEVICE_STACK)[r] == Res_DEVICE_STACK[r]));
+modifies Res_DEV_EXTN;
+
+//TAG: net change in resource DEV_EXTN only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_EXTN[r]} (Empty()[r]) || old(Res_DEV_EXTN)[r] == Res_DEV_EXTN[r]));
+modifies Res_DEV_OBJ_INIT;
+
+//TAG: net change in resource DEV_OBJ_INIT only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_OBJ_INIT[r]} (Empty()[r]) || old(Res_DEV_OBJ_INIT)[r] == Res_DEV_OBJ_INIT[r]));
+modifies Res_SPIN_LOCK;
+
+//TAG: net change in resource SPIN_LOCK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_SPIN_LOCK[r]} (Empty()[r]) || old(Res_SPIN_LOCK)[r] == Res_SPIN_LOCK[r]));
+//TAG: updated memory locations at Mem[T.MinorFunction__IO_STACK_LOCATION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.MinorFunction__IO_STACK_LOCATION][_m]} (Empty()[_m]) || Mem[T.MinorFunction__IO_STACK_LOCATION][_m] == old(Mem)[T.MinorFunction__IO_STACK_LOCATION][_m]));
+//TAG: updated memory locations at Mem[T.CurrentStackLocation___unnamed_4_a7aa989c] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.CurrentStackLocation___unnamed_4_a7aa989c][_m]} (Empty()[_m]) || Mem[T.CurrentStackLocation___unnamed_4_a7aa989c][_m] == old(Mem)[T.CurrentStackLocation___unnamed_4_a7aa989c][_m]));
+//TAG: updated memory locations at Mem[T.DeviceExtension__DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.DeviceExtension__DEVICE_OBJECT][_m] == old(Mem)[T.DeviceExtension__DEVICE_OBJECT][_m]));
+//TAG: updated memory locations at Mem[T.Self__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Self__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Self__DEVICE_EXTENSION][_m] == old(Mem)[T.Self__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.Started__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Started__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Started__DEVICE_EXTENSION][_m] == old(Mem)[T.Started__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.GrandMaster__GLOBALS] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.GrandMaster__GLOBALS][_m]} (Empty()[_m]) || Mem[T.GrandMaster__GLOBALS][_m] == old(Mem)[T.GrandMaster__GLOBALS][_m]));
+//TAG: updated memory locations at Mem[T.P_DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.P_DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.P_DEVICE_OBJECT][_m] == old(Mem)[T.P_DEVICE_OBJECT][_m]));
+
+//TAG: havoc memory locations by default
+modifies Mem;
+
+
+procedure MouCreateClassObject($DriverObject$1$3165.28$MouCreateClassObject$201:int, $TmpDeviceExtension$2$3166.28$MouCreateClassObject$201:int, $ClassDeviceObject$3$3167.28$MouCreateClassObject$201:int, $FullDeviceName$4$3168.35$MouCreateClassObject$201:int, $Legacy$5$3169.28$MouCreateClassObject$201:int) returns ($result.MouCreateClassObject$3164.0$1$:int);
+
+//TAG: requires __pforall(_H_x, (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension), __inv_resource("DEV_OBJ_INIT", 1), ((struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension))->Self == _H_x && __resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension)) == 1)
+requires((forall _H_x:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)]} Inverse(Res_DEV_OBJ_INIT,1)[_H_x] ==> ((Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)])] == _H_x) && (Res_DEV_EXTN[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)]] == 1))));
+//TAG: requires __pforall(_H_z, _H_z->Self, __inv_resource("DEV_EXTN", 1), __resource("DEV_OBJ_INIT", _H_z->Self) == 1 && (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)(_H_z->Self))->DeviceExtension) == _H_z)
+requires((forall _H_z:int :: {Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)]} Inverse(Res_DEV_EXTN,1)[_H_z] ==> ((Res_DEV_OBJ_INIT[Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)]] == 1) && (Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)])] == _H_z))));
+//TAG: requires __forall(_H_z, __inv_resource("DEV_EXTN", 1), __resource("SPIN_LOCK", &_H_z->SpinLock) == 0 && __resource("SPIN_LOCK", &_H_z->WaitWakeSpinLock) == 0)
+requires((Subset(Empty(), Inverse(Res_DEV_EXTN,1)) && (forall _H_z : int :: {Inverse(Res_DEV_EXTN,1)[_H_z]} (Inverse(Res_DEV_EXTN,1)[_H_z]) ==> ((Res_SPIN_LOCK[SpinLock__DEVICE_EXTENSION(_H_z)] == 0) && (Res_SPIN_LOCK[WaitWakeSpinLock__DEVICE_EXTENSION(_H_z)] == 0)))));
+//TAG: requires 1 ==> (Globals.GrandMaster != (void *)0 ==> __resource("DEV_EXTN", Globals.GrandMaster) == 1)
+requires((true) ==> ((Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)] != 0) ==> (Res_DEV_EXTN[Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)]] == 1)));
+//TAG: requires 1 ==> __setin(&Globals.LegacyDeviceList, __btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList))
+requires((true) ==> (ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[LegacyDeviceList__GLOBALS(Globals)]));
+//TAG: requires 1 ==> __forall(_H_y, __btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList), _H_y == &Globals.LegacyDeviceList || __resource("DEV_EXTN", CONTAINING_RECORD(_H_y, struct _DEVICE_EXTENSION , Link)) == 1)
+requires((true) ==> ((Subset(Empty(), ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))) && (forall _H_y : int :: {ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[_H_y]} (ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[_H_y]) ==> ((_H_y == LegacyDeviceList__GLOBALS(Globals)) || (Res_DEV_EXTN[MINUS_LEFT_PTR(_H_y, 1, Link__DEVICE_EXTENSION(0))] == 1))))));
+//TAG: requires 1 ==> !__setin(&Globals.GrandMaster->Link, __setminus(__btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList), __set(&Globals.LegacyDeviceList)))
+requires((true) ==> (!(Difference(ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals)), Singleton(LegacyDeviceList__GLOBALS(Globals)))[Link__DEVICE_EXTENSION(Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)])])));
+//TAG: ensures __pforall(_H_x, (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension), __inv_resource("DEV_OBJ_INIT", 1), ((struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension))->Self == _H_x && __resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension)) == 1)
+ensures((forall _H_x:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)]} Inverse(Res_DEV_OBJ_INIT,1)[_H_x] ==> ((Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)])] == _H_x) && (Res_DEV_EXTN[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)]] == 1))));
+//TAG: ensures __pforall(_H_z, _H_z->Self, __inv_resource("DEV_EXTN", 1), __resource("DEV_OBJ_INIT", _H_z->Self) == 1 && (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)(_H_z->Self))->DeviceExtension) == _H_z)
+ensures((forall _H_z:int :: {Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)]} Inverse(Res_DEV_EXTN,1)[_H_z] ==> ((Res_DEV_OBJ_INIT[Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)]] == 1) && (Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)])] == _H_z))));
+//TAG: ensures 1 ==> (Globals.GrandMaster != (void *)0 ==> __resource("DEV_EXTN", Globals.GrandMaster) == 1)
+ensures((true) ==> ((Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)] != 0) ==> (Res_DEV_EXTN[Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)]] == 1)));
+//TAG: ensures 1 ==> __setin(&Globals.LegacyDeviceList, __btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList))
+ensures((true) ==> (ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[LegacyDeviceList__GLOBALS(Globals)]));
+//TAG: ensures 1 ==> __forall(_H_y, __btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList), _H_y == &Globals.LegacyDeviceList || __resource("DEV_EXTN", CONTAINING_RECORD(_H_y, struct _DEVICE_EXTENSION , Link)) == 1)
+ensures((true) ==> ((Subset(Empty(), ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))) && (forall _H_y : int :: {ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[_H_y]} (ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[_H_y]) ==> ((_H_y == LegacyDeviceList__GLOBALS(Globals)) || (Res_DEV_EXTN[MINUS_LEFT_PTR(_H_y, 1, Link__DEVICE_EXTENSION(0))] == 1))))));
+//TAG: ensures 1 ==> !__setin(&Globals.GrandMaster->Link, __setminus(__btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList), __set(&Globals.LegacyDeviceList)))
+ensures((true) ==> (!(Difference(ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals)), Singleton(LegacyDeviceList__GLOBALS(Globals)))[Link__DEVICE_EXTENSION(Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)])])));
+//TAG: ensures __preserves_field_map(__offset((*((struct _LIST_ENTRY *)0)).Flink))
+ensures(Mem[T.Flink__LIST_ENTRY] == old(Mem)[T.Flink__LIST_ENTRY]);
+//TAG: ensures (LONG)__return >= 0 ==> *ClassDeviceObject != (void *)0
+ensures(($result.MouCreateClassObject$3164.0$1$ >= 0) ==> (Mem[T.P_DEVICE_OBJECT][$ClassDeviceObject$3$3167.28$MouCreateClassObject$201] != 0));
+//TAG: ensures (LONG)__return >= 0 ==> (*ClassDeviceObject)->DeviceExtension != (void *)0
+ensures(($result.MouCreateClassObject$3164.0$1$ >= 0) ==> (Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.P_DEVICE_OBJECT][$ClassDeviceObject$3$3167.28$MouCreateClassObject$201])] != 0));
+//TAG: ensures (LONG)__return >= 0 ==> __resource("DEV_EXTN", (*ClassDeviceObject)->DeviceExtension) == 1
+ensures(($result.MouCreateClassObject$3164.0$1$ >= 0) ==> (Res_DEV_EXTN[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.P_DEVICE_OBJECT][$ClassDeviceObject$3$3167.28$MouCreateClassObject$201])]] == 1));
+//TAG: ensures (LONG)__return >= 0 ==> __resource("DEV_OBJ_INIT", *ClassDeviceObject) == 1 && __resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)(*ClassDeviceObject))->DeviceExtension)) == 1
+ensures(($result.MouCreateClassObject$3164.0$1$ >= 0) ==> ((Res_DEV_OBJ_INIT[Mem[T.P_DEVICE_OBJECT][$ClassDeviceObject$3$3167.28$MouCreateClassObject$201]] == 1) && (Res_DEV_EXTN[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.P_DEVICE_OBJECT][$ClassDeviceObject$3$3167.28$MouCreateClassObject$201])]] == 1)));
+//TAG: ensures (LONG)__return >= 0 ==> __old_resource("DEV_OBJ_INIT", *ClassDeviceObject) == 0 && __old_resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)(*ClassDeviceObject))->DeviceExtension)) == 0
+ensures(($result.MouCreateClassObject$3164.0$1$ >= 0) ==> ((old(Res_DEV_OBJ_INIT)[Mem[T.P_DEVICE_OBJECT][$ClassDeviceObject$3$3167.28$MouCreateClassObject$201]] == 0) && (old(Res_DEV_EXTN)[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.P_DEVICE_OBJECT][$ClassDeviceObject$3$3167.28$MouCreateClassObject$201])]] == 0)));
+//TAG: ensures (LONG)__return >= 0 ==> __updates_resource("DEV_OBJ_INIT", *ClassDeviceObject, 1) && __updates_resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)(*ClassDeviceObject))->DeviceExtension), 1)
+ensures(($result.MouCreateClassObject$3164.0$1$ >= 0) ==> ((Res_DEV_OBJ_INIT == old(Res_DEV_OBJ_INIT)[Mem[T.P_DEVICE_OBJECT][$ClassDeviceObject$3$3167.28$MouCreateClassObject$201] := 1]) && (Res_DEV_EXTN == old(Res_DEV_EXTN)[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.P_DEVICE_OBJECT][$ClassDeviceObject$3$3167.28$MouCreateClassObject$201])] := 1])));
+//TAG: ensures !((LONG)__return >= 0) ==> __resource("DEV_OBJ_INIT", *ClassDeviceObject) == __old_resource("DEV_OBJ_INIT", *ClassDeviceObject) && __resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)(*ClassDeviceObject))->DeviceExtension)) == __old_resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)(*ClassDeviceObject))->DeviceExtension))
+ensures((!($result.MouCreateClassObject$3164.0$1$ >= 0)) ==> ((Res_DEV_OBJ_INIT[Mem[T.P_DEVICE_OBJECT][$ClassDeviceObject$3$3167.28$MouCreateClassObject$201]] == old(Res_DEV_OBJ_INIT)[Mem[T.P_DEVICE_OBJECT][$ClassDeviceObject$3$3167.28$MouCreateClassObject$201]]) && (Res_DEV_EXTN[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.P_DEVICE_OBJECT][$ClassDeviceObject$3$3167.28$MouCreateClassObject$201])]] == old(Res_DEV_EXTN)[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.P_DEVICE_OBJECT][$ClassDeviceObject$3$3167.28$MouCreateClassObject$201])]])));
+//TAG: ensures !((LONG)__return >= 0) ==> __preserves_resource("DEV_OBJ_INIT") && __preserves_resource("DEV_EXTN")
+free ensures((!($result.MouCreateClassObject$3164.0$1$ >= 0)) ==> ((Res_DEV_OBJ_INIT == old(Res_DEV_OBJ_INIT)) && (Res_DEV_EXTN == old(Res_DEV_EXTN))));
+//TAG: ensures __forall(_H_z, __inv_resource("DEV_EXTN", 1), __setin(_H_z, __set((struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)(*ClassDeviceObject))->DeviceExtension))) || __resource("SPIN_LOCK", &_H_z->SpinLock) == 0 && __resource("SPIN_LOCK", &_H_z->WaitWakeSpinLock) == 0)
+ensures((Subset(Empty(), Inverse(Res_DEV_EXTN,1)) && (forall _H_z : int :: {Inverse(Res_DEV_EXTN,1)[_H_z]} (Inverse(Res_DEV_EXTN,1)[_H_z]) ==> ((Singleton(Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.P_DEVICE_OBJECT][$ClassDeviceObject$3$3167.28$MouCreateClassObject$201])])[_H_z]) || ((Res_SPIN_LOCK[SpinLock__DEVICE_EXTENSION(_H_z)] == 0) && (Res_SPIN_LOCK[WaitWakeSpinLock__DEVICE_EXTENSION(_H_z)] == 0))))));
+//TAG: ensures !((LONG)__return >= 0) ==> __forall(_H_z, __inv_resource("DEV_EXTN", 1), __resource("SPIN_LOCK", &_H_z->SpinLock) == 0 && __resource("SPIN_LOCK", &_H_z->WaitWakeSpinLock) == 0)
+ensures((!($result.MouCreateClassObject$3164.0$1$ >= 0)) ==> ((Subset(Empty(), Inverse(Res_DEV_EXTN,1)) && (forall _H_z : int :: {Inverse(Res_DEV_EXTN,1)[_H_z]} (Inverse(Res_DEV_EXTN,1)[_H_z]) ==> ((Res_SPIN_LOCK[SpinLock__DEVICE_EXTENSION(_H_z)] == 0) && (Res_SPIN_LOCK[WaitWakeSpinLock__DEVICE_EXTENSION(_H_z)] == 0))))));
+//TAG: ensures (LONG)__return >= 0 ==> __resource("SPIN_LOCK", &((struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)(*ClassDeviceObject))->DeviceExtension))->SpinLock) == 0
+ensures(($result.MouCreateClassObject$3164.0$1$ >= 0) ==> (Res_SPIN_LOCK[SpinLock__DEVICE_EXTENSION(Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.P_DEVICE_OBJECT][$ClassDeviceObject$3$3167.28$MouCreateClassObject$201])])] == 0));
+
+modifies Res_DEVICE_STACK;
+
+//TAG: net change in resource DEVICE_STACK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEVICE_STACK[r]} (Empty()[r]) || old(Res_DEVICE_STACK)[r] == Res_DEVICE_STACK[r]));
+modifies Res_DEV_EXTN;
+
+//TAG: net change in resource DEV_EXTN only for: __set_empty, (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)(*ClassDeviceObject))->DeviceExtension)
+ensures (Subset(Empty(), Union(Union(Empty(), Empty()), Singleton(Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.P_DEVICE_OBJECT][$ClassDeviceObject$3$3167.28$MouCreateClassObject$201])]))) && (forall r:int :: {Res_DEV_EXTN[r]} (Empty()[r]) || (Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.P_DEVICE_OBJECT][$ClassDeviceObject$3$3167.28$MouCreateClassObject$201])] == r) || old(Res_DEV_EXTN)[r] == Res_DEV_EXTN[r]));
+modifies Res_DEV_OBJ_INIT;
+
+//TAG: net change in resource DEV_OBJ_INIT only for: __set_empty, *ClassDeviceObject
+ensures (Subset(Empty(), Union(Union(Empty(), Empty()), Singleton(Mem[T.P_DEVICE_OBJECT][$ClassDeviceObject$3$3167.28$MouCreateClassObject$201]))) && (forall r:int :: {Res_DEV_OBJ_INIT[r]} (Empty()[r]) || (Mem[T.P_DEVICE_OBJECT][$ClassDeviceObject$3$3167.28$MouCreateClassObject$201] == r) || old(Res_DEV_OBJ_INIT)[r] == Res_DEV_OBJ_INIT[r]));
+modifies Res_SPIN_LOCK;
+
+//TAG: net change in resource SPIN_LOCK only for: &TmpDeviceExtension->WaitWakeSpinLock, &((struct _DEVICE_EXTENSION *)TmpDeviceExtension)->SpinLock, __set_true
+ensures (Subset(Empty(), Union(Union(Union(Empty(), Singleton(WaitWakeSpinLock__DEVICE_EXTENSION($TmpDeviceExtension$2$3166.28$MouCreateClassObject$201))), Singleton(SpinLock__DEVICE_EXTENSION($TmpDeviceExtension$2$3166.28$MouCreateClassObject$201))), SetTrue())) && (forall r:int :: {Res_SPIN_LOCK[r]} (WaitWakeSpinLock__DEVICE_EXTENSION($TmpDeviceExtension$2$3166.28$MouCreateClassObject$201) == r) || (SpinLock__DEVICE_EXTENSION($TmpDeviceExtension$2$3166.28$MouCreateClassObject$201) == r) || (SetTrue()[r]) || old(Res_SPIN_LOCK)[r] == Res_SPIN_LOCK[r]));
+//TAG: updated memory locations at Mem[T.MinorFunction__IO_STACK_LOCATION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.MinorFunction__IO_STACK_LOCATION][_m]} (Empty()[_m]) || Mem[T.MinorFunction__IO_STACK_LOCATION][_m] == old(Mem)[T.MinorFunction__IO_STACK_LOCATION][_m]));
+//TAG: updated memory locations at Mem[T.CurrentStackLocation___unnamed_4_a7aa989c] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.CurrentStackLocation___unnamed_4_a7aa989c][_m]} (Empty()[_m]) || Mem[T.CurrentStackLocation___unnamed_4_a7aa989c][_m] == old(Mem)[T.CurrentStackLocation___unnamed_4_a7aa989c][_m]));
+//TAG: updated memory locations at Mem[T.DeviceExtension__DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.DeviceExtension__DEVICE_OBJECT][_m] == old(Mem)[T.DeviceExtension__DEVICE_OBJECT][_m]));
+//TAG: updated memory locations at Mem[T.Self__DEVICE_EXTENSION] only for: __set_true
+ensures (Subset(Empty(), Union(Empty(), SetTrue())) && (forall _m:int :: {Mem[T.Self__DEVICE_EXTENSION][_m]} (SetTrue()[_m]) || Mem[T.Self__DEVICE_EXTENSION][_m] == old(Mem)[T.Self__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.Started__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Started__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Started__DEVICE_EXTENSION][_m] == old(Mem)[T.Started__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.GrandMaster__GLOBALS] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.GrandMaster__GLOBALS][_m]} (Empty()[_m]) || Mem[T.GrandMaster__GLOBALS][_m] == old(Mem)[T.GrandMaster__GLOBALS][_m]));
+//TAG: updated memory locations at Mem[T.P_DEVICE_OBJECT] only for: __set_empty, ClassDeviceObject
+ensures (Subset(Empty(), Union(Union(Empty(), Empty()), Singleton($ClassDeviceObject$3$3167.28$MouCreateClassObject$201))) && (forall _m:int :: {Mem[T.P_DEVICE_OBJECT][_m]} (Empty()[_m]) || (_m == $ClassDeviceObject$3$3167.28$MouCreateClassObject$201) || Mem[T.P_DEVICE_OBJECT][_m] == old(Mem)[T.P_DEVICE_OBJECT][_m]));
+
+//TAG: havoc memory locations by default
+modifies Mem;
+
+
+procedure MouDeterminePortsServiced($BasePortName$1$3491.23$MouDeterminePortsServiced$81:int, $NumberPortsServiced$2$3492.18$MouDeterminePortsServiced$81:int) returns ($result.MouDeterminePortsServiced$3490.0$1$:int);
+
+//TAG: requires __pforall(_H_x, (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension), __inv_resource("DEV_OBJ_INIT", 1), ((struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension))->Self == _H_x && __resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension)) == 1)
+requires((forall _H_x:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)]} Inverse(Res_DEV_OBJ_INIT,1)[_H_x] ==> ((Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)])] == _H_x) && (Res_DEV_EXTN[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)]] == 1))));
+//TAG: requires __pforall(_H_z, _H_z->Self, __inv_resource("DEV_EXTN", 1), __resource("DEV_OBJ_INIT", _H_z->Self) == 1 && (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)(_H_z->Self))->DeviceExtension) == _H_z)
+requires((forall _H_z:int :: {Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)]} Inverse(Res_DEV_EXTN,1)[_H_z] ==> ((Res_DEV_OBJ_INIT[Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)]] == 1) && (Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)])] == _H_z))));
+//TAG: requires __forall(_H_z, __inv_resource("DEV_EXTN", 1), __resource("SPIN_LOCK", &_H_z->SpinLock) == 0 && __resource("SPIN_LOCK", &_H_z->WaitWakeSpinLock) == 0)
+requires((Subset(Empty(), Inverse(Res_DEV_EXTN,1)) && (forall _H_z : int :: {Inverse(Res_DEV_EXTN,1)[_H_z]} (Inverse(Res_DEV_EXTN,1)[_H_z]) ==> ((Res_SPIN_LOCK[SpinLock__DEVICE_EXTENSION(_H_z)] == 0) && (Res_SPIN_LOCK[WaitWakeSpinLock__DEVICE_EXTENSION(_H_z)] == 0)))));
+//TAG: requires 1 ==> (Globals.GrandMaster != (void *)0 ==> __resource("DEV_EXTN", Globals.GrandMaster) == 1)
+requires((true) ==> ((Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)] != 0) ==> (Res_DEV_EXTN[Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)]] == 1)));
+//TAG: requires 1 ==> __setin(&Globals.LegacyDeviceList, __btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList))
+requires((true) ==> (ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[LegacyDeviceList__GLOBALS(Globals)]));
+//TAG: requires 1 ==> __forall(_H_y, __btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList), _H_y == &Globals.LegacyDeviceList || __resource("DEV_EXTN", CONTAINING_RECORD(_H_y, struct _DEVICE_EXTENSION , Link)) == 1)
+requires((true) ==> ((Subset(Empty(), ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))) && (forall _H_y : int :: {ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[_H_y]} (ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[_H_y]) ==> ((_H_y == LegacyDeviceList__GLOBALS(Globals)) || (Res_DEV_EXTN[MINUS_LEFT_PTR(_H_y, 1, Link__DEVICE_EXTENSION(0))] == 1))))));
+//TAG: requires 1 ==> !__setin(&Globals.GrandMaster->Link, __setminus(__btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList), __set(&Globals.LegacyDeviceList)))
+requires((true) ==> (!(Difference(ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals)), Singleton(LegacyDeviceList__GLOBALS(Globals)))[Link__DEVICE_EXTENSION(Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)])])));
+//TAG: ensures __pforall(_H_x, (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension), __inv_resource("DEV_OBJ_INIT", 1), ((struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension))->Self == _H_x && __resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension)) == 1)
+ensures((forall _H_x:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)]} Inverse(Res_DEV_OBJ_INIT,1)[_H_x] ==> ((Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)])] == _H_x) && (Res_DEV_EXTN[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)]] == 1))));
+//TAG: ensures __pforall(_H_z, _H_z->Self, __inv_resource("DEV_EXTN", 1), __resource("DEV_OBJ_INIT", _H_z->Self) == 1 && (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)(_H_z->Self))->DeviceExtension) == _H_z)
+ensures((forall _H_z:int :: {Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)]} Inverse(Res_DEV_EXTN,1)[_H_z] ==> ((Res_DEV_OBJ_INIT[Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)]] == 1) && (Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)])] == _H_z))));
+//TAG: ensures __forall(_H_z, __inv_resource("DEV_EXTN", 1), __resource("SPIN_LOCK", &_H_z->SpinLock) == 0 && __resource("SPIN_LOCK", &_H_z->WaitWakeSpinLock) == 0)
+ensures((Subset(Empty(), Inverse(Res_DEV_EXTN,1)) && (forall _H_z : int :: {Inverse(Res_DEV_EXTN,1)[_H_z]} (Inverse(Res_DEV_EXTN,1)[_H_z]) ==> ((Res_SPIN_LOCK[SpinLock__DEVICE_EXTENSION(_H_z)] == 0) && (Res_SPIN_LOCK[WaitWakeSpinLock__DEVICE_EXTENSION(_H_z)] == 0)))));
+//TAG: ensures 1 ==> (Globals.GrandMaster != (void *)0 ==> __resource("DEV_EXTN", Globals.GrandMaster) == 1)
+ensures((true) ==> ((Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)] != 0) ==> (Res_DEV_EXTN[Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)]] == 1)));
+//TAG: ensures 1 ==> __setin(&Globals.LegacyDeviceList, __btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList))
+ensures((true) ==> (ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[LegacyDeviceList__GLOBALS(Globals)]));
+//TAG: ensures 1 ==> __forall(_H_y, __btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList), _H_y == &Globals.LegacyDeviceList || __resource("DEV_EXTN", CONTAINING_RECORD(_H_y, struct _DEVICE_EXTENSION , Link)) == 1)
+ensures((true) ==> ((Subset(Empty(), ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))) && (forall _H_y : int :: {ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[_H_y]} (ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[_H_y]) ==> ((_H_y == LegacyDeviceList__GLOBALS(Globals)) || (Res_DEV_EXTN[MINUS_LEFT_PTR(_H_y, 1, Link__DEVICE_EXTENSION(0))] == 1))))));
+//TAG: ensures 1 ==> !__setin(&Globals.GrandMaster->Link, __setminus(__btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList), __set(&Globals.LegacyDeviceList)))
+ensures((true) ==> (!(Difference(ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals)), Singleton(LegacyDeviceList__GLOBALS(Globals)))[Link__DEVICE_EXTENSION(Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)])])));
+//TAG: ensures __preserves_field_map(__offset((*((struct _LIST_ENTRY *)0)).Flink))
+ensures(Mem[T.Flink__LIST_ENTRY] == old(Mem)[T.Flink__LIST_ENTRY]);
+//TAG: ensures __preserves_resource("DEV_OBJ_INIT")
+ensures(Res_DEV_OBJ_INIT == old(Res_DEV_OBJ_INIT));
+//TAG: ensures __preserves_resource("DEV_EXTN")
+ensures(Res_DEV_EXTN == old(Res_DEV_EXTN));
+
+modifies Res_DEVICE_STACK;
+
+//TAG: net change in resource DEVICE_STACK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEVICE_STACK[r]} (Empty()[r]) || old(Res_DEVICE_STACK)[r] == Res_DEVICE_STACK[r]));
+modifies Res_DEV_EXTN;
+
+//TAG: net change in resource DEV_EXTN only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_EXTN[r]} (Empty()[r]) || old(Res_DEV_EXTN)[r] == Res_DEV_EXTN[r]));
+modifies Res_DEV_OBJ_INIT;
+
+//TAG: net change in resource DEV_OBJ_INIT only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_OBJ_INIT[r]} (Empty()[r]) || old(Res_DEV_OBJ_INIT)[r] == Res_DEV_OBJ_INIT[r]));
+modifies Res_SPIN_LOCK;
+
+//TAG: net change in resource SPIN_LOCK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_SPIN_LOCK[r]} (Empty()[r]) || old(Res_SPIN_LOCK)[r] == Res_SPIN_LOCK[r]));
+//TAG: updated memory locations at Mem[T.MinorFunction__IO_STACK_LOCATION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.MinorFunction__IO_STACK_LOCATION][_m]} (Empty()[_m]) || Mem[T.MinorFunction__IO_STACK_LOCATION][_m] == old(Mem)[T.MinorFunction__IO_STACK_LOCATION][_m]));
+//TAG: updated memory locations at Mem[T.CurrentStackLocation___unnamed_4_a7aa989c] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.CurrentStackLocation___unnamed_4_a7aa989c][_m]} (Empty()[_m]) || Mem[T.CurrentStackLocation___unnamed_4_a7aa989c][_m] == old(Mem)[T.CurrentStackLocation___unnamed_4_a7aa989c][_m]));
+//TAG: updated memory locations at Mem[T.DeviceExtension__DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.DeviceExtension__DEVICE_OBJECT][_m] == old(Mem)[T.DeviceExtension__DEVICE_OBJECT][_m]));
+//TAG: updated memory locations at Mem[T.Self__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Self__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Self__DEVICE_EXTENSION][_m] == old(Mem)[T.Self__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.Started__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Started__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Started__DEVICE_EXTENSION][_m] == old(Mem)[T.Started__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.GrandMaster__GLOBALS] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.GrandMaster__GLOBALS][_m]} (Empty()[_m]) || Mem[T.GrandMaster__GLOBALS][_m] == old(Mem)[T.GrandMaster__GLOBALS][_m]));
+//TAG: updated memory locations at Mem[T.P_DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.P_DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.P_DEVICE_OBJECT][_m] == old(Mem)[T.P_DEVICE_OBJECT][_m]));
+
+//TAG: havoc memory locations by default
+modifies Mem;
+
+
+procedure MouseAddDeviceEx($ClassData$1$792.28$MouseAddDeviceEx$121:int, $FullClassName$2$793.29$MouseAddDeviceEx$121:int, $File$3$794.28$MouseAddDeviceEx$121:int) returns ($result.MouseAddDeviceEx$791.0$1$:int);
+
+//TAG: requires __resource("DEV_EXTN", ClassData) == 1
+requires(Res_DEV_EXTN[$ClassData$1$792.28$MouseAddDeviceEx$121] == 1);
+//TAG: requires __resource("SPIN_LOCK", &((struct _DEVICE_EXTENSION *)ClassData)->SpinLock) == 0
+requires(Res_SPIN_LOCK[SpinLock__DEVICE_EXTENSION($ClassData$1$792.28$MouseAddDeviceEx$121)] == 0);
+//TAG: requires __pforall(_H_x, (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension), __inv_resource("DEV_OBJ_INIT", 1), ((struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension))->Self == _H_x && __resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension)) == 1)
+requires((forall _H_x:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)]} Inverse(Res_DEV_OBJ_INIT,1)[_H_x] ==> ((Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)])] == _H_x) && (Res_DEV_EXTN[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)]] == 1))));
+//TAG: requires __pforall(_H_z, _H_z->Self, __inv_resource("DEV_EXTN", 1), __resource("DEV_OBJ_INIT", _H_z->Self) == 1 && (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)(_H_z->Self))->DeviceExtension) == _H_z)
+requires((forall _H_z:int :: {Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)]} Inverse(Res_DEV_EXTN,1)[_H_z] ==> ((Res_DEV_OBJ_INIT[Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)]] == 1) && (Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)])] == _H_z))));
+//TAG: requires 1 ==> (Globals.GrandMaster != (void *)0 ==> __resource("DEV_EXTN", Globals.GrandMaster) == 1)
+requires((true) ==> ((Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)] != 0) ==> (Res_DEV_EXTN[Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)]] == 1)));
+//TAG: requires 1 ==> __setin(&Globals.LegacyDeviceList, __btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList))
+requires((true) ==> (ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[LegacyDeviceList__GLOBALS(Globals)]));
+//TAG: requires 1 ==> __forall(_H_y, __btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList), _H_y == &Globals.LegacyDeviceList || __resource("DEV_EXTN", CONTAINING_RECORD(_H_y, struct _DEVICE_EXTENSION , Link)) == 1)
+requires((true) ==> ((Subset(Empty(), ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))) && (forall _H_y : int :: {ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[_H_y]} (ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[_H_y]) ==> ((_H_y == LegacyDeviceList__GLOBALS(Globals)) || (Res_DEV_EXTN[MINUS_LEFT_PTR(_H_y, 1, Link__DEVICE_EXTENSION(0))] == 1))))));
+//TAG: requires 1 ==> !__setin(&Globals.GrandMaster->Link, __setminus(__btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList), __set(&Globals.LegacyDeviceList)))
+requires((true) ==> (!(Difference(ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals)), Singleton(LegacyDeviceList__GLOBALS(Globals)))[Link__DEVICE_EXTENSION(Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)])])));
+//TAG: ensures __resource("DEV_EXTN", ClassData) == 1
+ensures(Res_DEV_EXTN[$ClassData$1$792.28$MouseAddDeviceEx$121] == 1);
+//TAG: ensures __resource("SPIN_LOCK", &((struct _DEVICE_EXTENSION *)ClassData)->WaitWakeSpinLock) == 0
+ensures(Res_SPIN_LOCK[WaitWakeSpinLock__DEVICE_EXTENSION($ClassData$1$792.28$MouseAddDeviceEx$121)] == 0);
+//TAG: ensures __resource("SPIN_LOCK", &((struct _DEVICE_EXTENSION *)ClassData)->SpinLock) == 0
+ensures(Res_SPIN_LOCK[SpinLock__DEVICE_EXTENSION($ClassData$1$792.28$MouseAddDeviceEx$121)] == 0);
+//TAG: ensures __pforall(_H_x, (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension), __inv_resource("DEV_OBJ_INIT", 1), ((struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension))->Self == _H_x && __resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension)) == 1)
+ensures((forall _H_x:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)]} Inverse(Res_DEV_OBJ_INIT,1)[_H_x] ==> ((Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)])] == _H_x) && (Res_DEV_EXTN[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)]] == 1))));
+//TAG: ensures __pforall(_H_z, _H_z->Self, __inv_resource("DEV_EXTN", 1), __resource("DEV_OBJ_INIT", _H_z->Self) == 1 && (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)(_H_z->Self))->DeviceExtension) == _H_z)
+ensures((forall _H_z:int :: {Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)]} Inverse(Res_DEV_EXTN,1)[_H_z] ==> ((Res_DEV_OBJ_INIT[Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)]] == 1) && (Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)])] == _H_z))));
+//TAG: ensures 1 ==> (Globals.GrandMaster != (void *)0 ==> __resource("DEV_EXTN", Globals.GrandMaster) == 1)
+ensures((true) ==> ((Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)] != 0) ==> (Res_DEV_EXTN[Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)]] == 1)));
+//TAG: ensures 1 ==> __setin(&Globals.LegacyDeviceList, __btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList))
+ensures((true) ==> (ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[LegacyDeviceList__GLOBALS(Globals)]));
+//TAG: ensures 1 ==> __forall(_H_y, __btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList), _H_y == &Globals.LegacyDeviceList || __resource("DEV_EXTN", CONTAINING_RECORD(_H_y, struct _DEVICE_EXTENSION , Link)) == 1)
+ensures((true) ==> ((Subset(Empty(), ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))) && (forall _H_y : int :: {ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[_H_y]} (ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[_H_y]) ==> ((_H_y == LegacyDeviceList__GLOBALS(Globals)) || (Res_DEV_EXTN[MINUS_LEFT_PTR(_H_y, 1, Link__DEVICE_EXTENSION(0))] == 1))))));
+//TAG: ensures 1 ==> !__setin(&Globals.GrandMaster->Link, __setminus(__btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList), __set(&Globals.LegacyDeviceList)))
+ensures((true) ==> (!(Difference(ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals)), Singleton(LegacyDeviceList__GLOBALS(Globals)))[Link__DEVICE_EXTENSION(Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)])])));
+//TAG: ensures __preserves_field_map(__offset((*((struct _LIST_ENTRY *)0)).Flink))
+ensures(Mem[T.Flink__LIST_ENTRY] == old(Mem)[T.Flink__LIST_ENTRY]);
+//TAG: ensures __preserves_resource("DEV_OBJ_INIT")
+ensures(Res_DEV_OBJ_INIT == old(Res_DEV_OBJ_INIT));
+//TAG: ensures __preserves_resource("DEV_EXTN")
+ensures(Res_DEV_EXTN == old(Res_DEV_EXTN));
+
+modifies Res_DEVICE_STACK;
+
+//TAG: net change in resource DEVICE_STACK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEVICE_STACK[r]} (Empty()[r]) || old(Res_DEVICE_STACK)[r] == Res_DEVICE_STACK[r]));
+modifies Res_DEV_EXTN;
+
+//TAG: net change in resource DEV_EXTN only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_EXTN[r]} (Empty()[r]) || old(Res_DEV_EXTN)[r] == Res_DEV_EXTN[r]));
+modifies Res_DEV_OBJ_INIT;
+
+//TAG: net change in resource DEV_OBJ_INIT only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_OBJ_INIT[r]} (Empty()[r]) || old(Res_DEV_OBJ_INIT)[r] == Res_DEV_OBJ_INIT[r]));
+modifies Res_SPIN_LOCK;
+
+//TAG: net change in resource SPIN_LOCK only for: &ClassData->WaitWakeSpinLock, __set_empty
+ensures (Subset(Empty(), Union(Union(Empty(), Singleton(WaitWakeSpinLock__DEVICE_EXTENSION($ClassData$1$792.28$MouseAddDeviceEx$121))), Empty())) && (forall r:int :: {Res_SPIN_LOCK[r]} (WaitWakeSpinLock__DEVICE_EXTENSION($ClassData$1$792.28$MouseAddDeviceEx$121) == r) || (Empty()[r]) || old(Res_SPIN_LOCK)[r] == Res_SPIN_LOCK[r]));
+//TAG: updated memory locations at Mem[T.MinorFunction__IO_STACK_LOCATION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.MinorFunction__IO_STACK_LOCATION][_m]} (Empty()[_m]) || Mem[T.MinorFunction__IO_STACK_LOCATION][_m] == old(Mem)[T.MinorFunction__IO_STACK_LOCATION][_m]));
+//TAG: updated memory locations at Mem[T.CurrentStackLocation___unnamed_4_a7aa989c] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.CurrentStackLocation___unnamed_4_a7aa989c][_m]} (Empty()[_m]) || Mem[T.CurrentStackLocation___unnamed_4_a7aa989c][_m] == old(Mem)[T.CurrentStackLocation___unnamed_4_a7aa989c][_m]));
+//TAG: updated memory locations at Mem[T.DeviceExtension__DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.DeviceExtension__DEVICE_OBJECT][_m] == old(Mem)[T.DeviceExtension__DEVICE_OBJECT][_m]));
+//TAG: updated memory locations at Mem[T.Self__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Self__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Self__DEVICE_EXTENSION][_m] == old(Mem)[T.Self__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.Started__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Started__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Started__DEVICE_EXTENSION][_m] == old(Mem)[T.Started__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.GrandMaster__GLOBALS] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.GrandMaster__GLOBALS][_m]} (Empty()[_m]) || Mem[T.GrandMaster__GLOBALS][_m] == old(Mem)[T.GrandMaster__GLOBALS][_m]));
+//TAG: updated memory locations at Mem[T.P_DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.P_DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.P_DEVICE_OBJECT][_m] == old(Mem)[T.P_DEVICE_OBJECT][_m]));
+
+//TAG: havoc memory locations by default
+modifies Mem;
+
+
+procedure MouseClassLogError($Object$1$4550.10$MouseClassLogError$281:int, $ErrorCode$2$4551.10$MouseClassLogError$281:int, $UniqueErrorValue$3$4552.10$MouseClassLogError$281:int, $FinalStatus$4$4553.13$MouseClassLogError$281:int, $DumpCount$5$4554.10$MouseClassLogError$281:int, $DumpData$6$4555.11$MouseClassLogError$281:int, $MajorFunction$7$4556.10$MouseClassLogError$281:int);
+
+//TAG: requires __pforall(_H_x, (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension), __inv_resource("DEV_OBJ_INIT", 1), ((struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension))->Self == _H_x && __resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension)) == 1)
+requires((forall _H_x:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)]} Inverse(Res_DEV_OBJ_INIT,1)[_H_x] ==> ((Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)])] == _H_x) && (Res_DEV_EXTN[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)]] == 1))));
+//TAG: requires __pforall(_H_z, _H_z->Self, __inv_resource("DEV_EXTN", 1), __resource("DEV_OBJ_INIT", _H_z->Self) == 1 && (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)(_H_z->Self))->DeviceExtension) == _H_z)
+requires((forall _H_z:int :: {Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)]} Inverse(Res_DEV_EXTN,1)[_H_z] ==> ((Res_DEV_OBJ_INIT[Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)]] == 1) && (Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)])] == _H_z))));
+//TAG: requires 1 ==> (Globals.GrandMaster != (void *)0 ==> __resource("DEV_EXTN", Globals.GrandMaster) == 1)
+requires((true) ==> ((Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)] != 0) ==> (Res_DEV_EXTN[Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)]] == 1)));
+//TAG: requires 1 ==> __setin(&Globals.LegacyDeviceList, __btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList))
+requires((true) ==> (ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[LegacyDeviceList__GLOBALS(Globals)]));
+//TAG: requires 1 ==> __forall(_H_y, __btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList), _H_y == &Globals.LegacyDeviceList || __resource("DEV_EXTN", CONTAINING_RECORD(_H_y, struct _DEVICE_EXTENSION , Link)) == 1)
+requires((true) ==> ((Subset(Empty(), ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))) && (forall _H_y : int :: {ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[_H_y]} (ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[_H_y]) ==> ((_H_y == LegacyDeviceList__GLOBALS(Globals)) || (Res_DEV_EXTN[MINUS_LEFT_PTR(_H_y, 1, Link__DEVICE_EXTENSION(0))] == 1))))));
+//TAG: requires 1 ==> !__setin(&Globals.GrandMaster->Link, __setminus(__btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList), __set(&Globals.LegacyDeviceList)))
+requires((true) ==> (!(Difference(ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals)), Singleton(LegacyDeviceList__GLOBALS(Globals)))[Link__DEVICE_EXTENSION(Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)])])));
+//TAG: ensures __pforall(_H_x, (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension), __inv_resource("DEV_OBJ_INIT", 1), ((struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension))->Self == _H_x && __resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension)) == 1)
+ensures((forall _H_x:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)]} Inverse(Res_DEV_OBJ_INIT,1)[_H_x] ==> ((Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)])] == _H_x) && (Res_DEV_EXTN[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)]] == 1))));
+//TAG: ensures __pforall(_H_z, _H_z->Self, __inv_resource("DEV_EXTN", 1), __resource("DEV_OBJ_INIT", _H_z->Self) == 1 && (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)(_H_z->Self))->DeviceExtension) == _H_z)
+ensures((forall _H_z:int :: {Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)]} Inverse(Res_DEV_EXTN,1)[_H_z] ==> ((Res_DEV_OBJ_INIT[Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)]] == 1) && (Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)])] == _H_z))));
+//TAG: ensures 1 ==> (Globals.GrandMaster != (void *)0 ==> __resource("DEV_EXTN", Globals.GrandMaster) == 1)
+ensures((true) ==> ((Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)] != 0) ==> (Res_DEV_EXTN[Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)]] == 1)));
+//TAG: ensures 1 ==> __setin(&Globals.LegacyDeviceList, __btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList))
+ensures((true) ==> (ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[LegacyDeviceList__GLOBALS(Globals)]));
+//TAG: ensures 1 ==> __forall(_H_y, __btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList), _H_y == &Globals.LegacyDeviceList || __resource("DEV_EXTN", CONTAINING_RECORD(_H_y, struct _DEVICE_EXTENSION , Link)) == 1)
+ensures((true) ==> ((Subset(Empty(), ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))) && (forall _H_y : int :: {ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[_H_y]} (ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[_H_y]) ==> ((_H_y == LegacyDeviceList__GLOBALS(Globals)) || (Res_DEV_EXTN[MINUS_LEFT_PTR(_H_y, 1, Link__DEVICE_EXTENSION(0))] == 1))))));
+//TAG: ensures 1 ==> !__setin(&Globals.GrandMaster->Link, __setminus(__btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList), __set(&Globals.LegacyDeviceList)))
+ensures((true) ==> (!(Difference(ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals)), Singleton(LegacyDeviceList__GLOBALS(Globals)))[Link__DEVICE_EXTENSION(Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)])])));
+//TAG: ensures __preserves_field_map(__offset((*((struct _LIST_ENTRY *)0)).Flink))
+ensures(Mem[T.Flink__LIST_ENTRY] == old(Mem)[T.Flink__LIST_ENTRY]);
+//TAG: ensures __preserves_resource("DEV_OBJ_INIT")
+ensures(Res_DEV_OBJ_INIT == old(Res_DEV_OBJ_INIT));
+//TAG: ensures __preserves_resource("DEV_EXTN")
+ensures(Res_DEV_EXTN == old(Res_DEV_EXTN));
+
+modifies Res_DEVICE_STACK;
+
+//TAG: net change in resource DEVICE_STACK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEVICE_STACK[r]} (Empty()[r]) || old(Res_DEVICE_STACK)[r] == Res_DEVICE_STACK[r]));
+modifies Res_DEV_EXTN;
+
+//TAG: net change in resource DEV_EXTN only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_EXTN[r]} (Empty()[r]) || old(Res_DEV_EXTN)[r] == Res_DEV_EXTN[r]));
+modifies Res_DEV_OBJ_INIT;
+
+//TAG: net change in resource DEV_OBJ_INIT only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_OBJ_INIT[r]} (Empty()[r]) || old(Res_DEV_OBJ_INIT)[r] == Res_DEV_OBJ_INIT[r]));
+modifies Res_SPIN_LOCK;
+
+//TAG: net change in resource SPIN_LOCK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_SPIN_LOCK[r]} (Empty()[r]) || old(Res_SPIN_LOCK)[r] == Res_SPIN_LOCK[r]));
+//TAG: updated memory locations at Mem[T.MinorFunction__IO_STACK_LOCATION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.MinorFunction__IO_STACK_LOCATION][_m]} (Empty()[_m]) || Mem[T.MinorFunction__IO_STACK_LOCATION][_m] == old(Mem)[T.MinorFunction__IO_STACK_LOCATION][_m]));
+//TAG: updated memory locations at Mem[T.CurrentStackLocation___unnamed_4_a7aa989c] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.CurrentStackLocation___unnamed_4_a7aa989c][_m]} (Empty()[_m]) || Mem[T.CurrentStackLocation___unnamed_4_a7aa989c][_m] == old(Mem)[T.CurrentStackLocation___unnamed_4_a7aa989c][_m]));
+//TAG: updated memory locations at Mem[T.DeviceExtension__DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.DeviceExtension__DEVICE_OBJECT][_m] == old(Mem)[T.DeviceExtension__DEVICE_OBJECT][_m]));
+//TAG: updated memory locations at Mem[T.Self__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Self__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Self__DEVICE_EXTENSION][_m] == old(Mem)[T.Self__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.Started__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Started__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Started__DEVICE_EXTENSION][_m] == old(Mem)[T.Started__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.GrandMaster__GLOBALS] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.GrandMaster__GLOBALS][_m]} (Empty()[_m]) || Mem[T.GrandMaster__GLOBALS][_m] == old(Mem)[T.GrandMaster__GLOBALS][_m]));
+//TAG: updated memory locations at Mem[T.P_DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.P_DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.P_DEVICE_OBJECT][_m] == old(Mem)[T.P_DEVICE_OBJECT][_m]));
+
+//TAG: havoc memory locations by default
+modifies Mem;
+
+
+procedure ObfDereferenceObject($Object$1$24931.15$ObfDereferenceObject$41:int) returns ($result.ObfDereferenceObject$24930.0$1$:int);
+
+//TAG: ensures __preserves_mem
+ensures(Mem == old(Mem));
+//TAG: ensures __preserves_resource("DEV_OBJ_INIT") && __preserves_resource("DEV_EXTN")
+ensures((Res_DEV_OBJ_INIT == old(Res_DEV_OBJ_INIT)) && (Res_DEV_EXTN == old(Res_DEV_EXTN)));
+
+modifies Res_DEVICE_STACK;
+
+//TAG: net change in resource DEVICE_STACK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEVICE_STACK[r]} (Empty()[r]) || old(Res_DEVICE_STACK)[r] == Res_DEVICE_STACK[r]));
+modifies Res_DEV_EXTN;
+
+//TAG: net change in resource DEV_EXTN only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_EXTN[r]} (Empty()[r]) || old(Res_DEV_EXTN)[r] == Res_DEV_EXTN[r]));
+modifies Res_DEV_OBJ_INIT;
+
+//TAG: net change in resource DEV_OBJ_INIT only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_OBJ_INIT[r]} (Empty()[r]) || old(Res_DEV_OBJ_INIT)[r] == Res_DEV_OBJ_INIT[r]));
+modifies Res_SPIN_LOCK;
+
+//TAG: net change in resource SPIN_LOCK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_SPIN_LOCK[r]} (Empty()[r]) || old(Res_SPIN_LOCK)[r] == Res_SPIN_LOCK[r]));
+//TAG: updated memory locations at Mem[T.MinorFunction__IO_STACK_LOCATION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.MinorFunction__IO_STACK_LOCATION][_m]} (Empty()[_m]) || Mem[T.MinorFunction__IO_STACK_LOCATION][_m] == old(Mem)[T.MinorFunction__IO_STACK_LOCATION][_m]));
+//TAG: updated memory locations at Mem[T.CurrentStackLocation___unnamed_4_a7aa989c] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.CurrentStackLocation___unnamed_4_a7aa989c][_m]} (Empty()[_m]) || Mem[T.CurrentStackLocation___unnamed_4_a7aa989c][_m] == old(Mem)[T.CurrentStackLocation___unnamed_4_a7aa989c][_m]));
+//TAG: updated memory locations at Mem[T.DeviceExtension__DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.DeviceExtension__DEVICE_OBJECT][_m] == old(Mem)[T.DeviceExtension__DEVICE_OBJECT][_m]));
+//TAG: updated memory locations at Mem[T.Self__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Self__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Self__DEVICE_EXTENSION][_m] == old(Mem)[T.Self__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.Started__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Started__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Started__DEVICE_EXTENSION][_m] == old(Mem)[T.Started__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.GrandMaster__GLOBALS] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.GrandMaster__GLOBALS][_m]} (Empty()[_m]) || Mem[T.GrandMaster__GLOBALS][_m] == old(Mem)[T.GrandMaster__GLOBALS][_m]));
+//TAG: updated memory locations at Mem[T.P_DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.P_DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.P_DEVICE_OBJECT][_m] == old(Mem)[T.P_DEVICE_OBJECT][_m]));
+
+//TAG: havoc memory locations by default
+modifies Mem;
+
+
+procedure RtlAppendUnicodeToString($Destination$1$7421.28$RtlAppendUnicodeToString$81:int, $Source$2$7422.20$RtlAppendUnicodeToString$81:int) returns ($result.RtlAppendUnicodeToString$7420.0$1$:int);
+
+//TAG: ensures __preserves_mem
+ensures(Mem == old(Mem));
+//TAG: ensures __preserves_resource("DEV_OBJ_INIT") && __preserves_resource("DEV_EXTN")
+ensures((Res_DEV_OBJ_INIT == old(Res_DEV_OBJ_INIT)) && (Res_DEV_EXTN == old(Res_DEV_EXTN)));
+
+modifies Res_DEVICE_STACK;
+
+//TAG: net change in resource DEVICE_STACK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEVICE_STACK[r]} (Empty()[r]) || old(Res_DEVICE_STACK)[r] == Res_DEVICE_STACK[r]));
+modifies Res_DEV_EXTN;
+
+//TAG: net change in resource DEV_EXTN only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_EXTN[r]} (Empty()[r]) || old(Res_DEV_EXTN)[r] == Res_DEV_EXTN[r]));
+modifies Res_DEV_OBJ_INIT;
+
+//TAG: net change in resource DEV_OBJ_INIT only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_OBJ_INIT[r]} (Empty()[r]) || old(Res_DEV_OBJ_INIT)[r] == Res_DEV_OBJ_INIT[r]));
+modifies Res_SPIN_LOCK;
+
+//TAG: net change in resource SPIN_LOCK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_SPIN_LOCK[r]} (Empty()[r]) || old(Res_SPIN_LOCK)[r] == Res_SPIN_LOCK[r]));
+//TAG: updated memory locations at Mem[T.MinorFunction__IO_STACK_LOCATION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.MinorFunction__IO_STACK_LOCATION][_m]} (Empty()[_m]) || Mem[T.MinorFunction__IO_STACK_LOCATION][_m] == old(Mem)[T.MinorFunction__IO_STACK_LOCATION][_m]));
+//TAG: updated memory locations at Mem[T.CurrentStackLocation___unnamed_4_a7aa989c] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.CurrentStackLocation___unnamed_4_a7aa989c][_m]} (Empty()[_m]) || Mem[T.CurrentStackLocation___unnamed_4_a7aa989c][_m] == old(Mem)[T.CurrentStackLocation___unnamed_4_a7aa989c][_m]));
+//TAG: updated memory locations at Mem[T.DeviceExtension__DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.DeviceExtension__DEVICE_OBJECT][_m] == old(Mem)[T.DeviceExtension__DEVICE_OBJECT][_m]));
+//TAG: updated memory locations at Mem[T.Self__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Self__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Self__DEVICE_EXTENSION][_m] == old(Mem)[T.Self__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.Started__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Started__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Started__DEVICE_EXTENSION][_m] == old(Mem)[T.Started__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.GrandMaster__GLOBALS] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.GrandMaster__GLOBALS][_m]} (Empty()[_m]) || Mem[T.GrandMaster__GLOBALS][_m] == old(Mem)[T.GrandMaster__GLOBALS][_m]));
+//TAG: updated memory locations at Mem[T.P_DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.P_DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.P_DEVICE_OBJECT][_m] == old(Mem)[T.P_DEVICE_OBJECT][_m]));
+
+//TAG: havoc memory locations by default
+modifies Mem;
+
+
+procedure RtlCopyUnicodeString($DestinationString$1$7401.28$RtlCopyUnicodeString$81:int, $SourceString$2$7402.30$RtlCopyUnicodeString$81:int);
+
+//TAG: ensures __preserves_mem
+ensures(Mem == old(Mem));
+//TAG: ensures __preserves_resource("DEV_OBJ_INIT") && __preserves_resource("DEV_EXTN")
+ensures((Res_DEV_OBJ_INIT == old(Res_DEV_OBJ_INIT)) && (Res_DEV_EXTN == old(Res_DEV_EXTN)));
+
+modifies Res_DEVICE_STACK;
+
+//TAG: net change in resource DEVICE_STACK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEVICE_STACK[r]} (Empty()[r]) || old(Res_DEVICE_STACK)[r] == Res_DEVICE_STACK[r]));
+modifies Res_DEV_EXTN;
+
+//TAG: net change in resource DEV_EXTN only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_EXTN[r]} (Empty()[r]) || old(Res_DEV_EXTN)[r] == Res_DEV_EXTN[r]));
+modifies Res_DEV_OBJ_INIT;
+
+//TAG: net change in resource DEV_OBJ_INIT only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_OBJ_INIT[r]} (Empty()[r]) || old(Res_DEV_OBJ_INIT)[r] == Res_DEV_OBJ_INIT[r]));
+modifies Res_SPIN_LOCK;
+
+//TAG: net change in resource SPIN_LOCK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_SPIN_LOCK[r]} (Empty()[r]) || old(Res_SPIN_LOCK)[r] == Res_SPIN_LOCK[r]));
+//TAG: updated memory locations at Mem[T.MinorFunction__IO_STACK_LOCATION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.MinorFunction__IO_STACK_LOCATION][_m]} (Empty()[_m]) || Mem[T.MinorFunction__IO_STACK_LOCATION][_m] == old(Mem)[T.MinorFunction__IO_STACK_LOCATION][_m]));
+//TAG: updated memory locations at Mem[T.CurrentStackLocation___unnamed_4_a7aa989c] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.CurrentStackLocation___unnamed_4_a7aa989c][_m]} (Empty()[_m]) || Mem[T.CurrentStackLocation___unnamed_4_a7aa989c][_m] == old(Mem)[T.CurrentStackLocation___unnamed_4_a7aa989c][_m]));
+//TAG: updated memory locations at Mem[T.DeviceExtension__DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.DeviceExtension__DEVICE_OBJECT][_m] == old(Mem)[T.DeviceExtension__DEVICE_OBJECT][_m]));
+//TAG: updated memory locations at Mem[T.Self__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Self__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Self__DEVICE_EXTENSION][_m] == old(Mem)[T.Self__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.Started__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Started__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Started__DEVICE_EXTENSION][_m] == old(Mem)[T.Started__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.GrandMaster__GLOBALS] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.GrandMaster__GLOBALS][_m]} (Empty()[_m]) || Mem[T.GrandMaster__GLOBALS][_m] == old(Mem)[T.GrandMaster__GLOBALS][_m]));
+//TAG: updated memory locations at Mem[T.P_DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.P_DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.P_DEVICE_OBJECT][_m] == old(Mem)[T.P_DEVICE_OBJECT][_m]));
+
+//TAG: havoc memory locations by default
+modifies Mem;
+
+
+procedure RtlInitUnicodeString($DestinationString$1$7281.26$RtlInitUnicodeString$81:int, $SourceString$2$7282.37$RtlInitUnicodeString$81:int);
+
+//TAG: ensures __preserves_mem
+ensures(Mem == old(Mem));
+//TAG: ensures __preserves_resource("DEV_OBJ_INIT") && __preserves_resource("DEV_EXTN")
+ensures((Res_DEV_OBJ_INIT == old(Res_DEV_OBJ_INIT)) && (Res_DEV_EXTN == old(Res_DEV_EXTN)));
+
+modifies Res_DEVICE_STACK;
+
+//TAG: net change in resource DEVICE_STACK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEVICE_STACK[r]} (Empty()[r]) || old(Res_DEVICE_STACK)[r] == Res_DEVICE_STACK[r]));
+modifies Res_DEV_EXTN;
+
+//TAG: net change in resource DEV_EXTN only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_EXTN[r]} (Empty()[r]) || old(Res_DEV_EXTN)[r] == Res_DEV_EXTN[r]));
+modifies Res_DEV_OBJ_INIT;
+
+//TAG: net change in resource DEV_OBJ_INIT only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_OBJ_INIT[r]} (Empty()[r]) || old(Res_DEV_OBJ_INIT)[r] == Res_DEV_OBJ_INIT[r]));
+modifies Res_SPIN_LOCK;
+
+//TAG: net change in resource SPIN_LOCK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_SPIN_LOCK[r]} (Empty()[r]) || old(Res_SPIN_LOCK)[r] == Res_SPIN_LOCK[r]));
+//TAG: updated memory locations at Mem[T.MinorFunction__IO_STACK_LOCATION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.MinorFunction__IO_STACK_LOCATION][_m]} (Empty()[_m]) || Mem[T.MinorFunction__IO_STACK_LOCATION][_m] == old(Mem)[T.MinorFunction__IO_STACK_LOCATION][_m]));
+//TAG: updated memory locations at Mem[T.CurrentStackLocation___unnamed_4_a7aa989c] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.CurrentStackLocation___unnamed_4_a7aa989c][_m]} (Empty()[_m]) || Mem[T.CurrentStackLocation___unnamed_4_a7aa989c][_m] == old(Mem)[T.CurrentStackLocation___unnamed_4_a7aa989c][_m]));
+//TAG: updated memory locations at Mem[T.DeviceExtension__DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.DeviceExtension__DEVICE_OBJECT][_m] == old(Mem)[T.DeviceExtension__DEVICE_OBJECT][_m]));
+//TAG: updated memory locations at Mem[T.Self__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Self__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Self__DEVICE_EXTENSION][_m] == old(Mem)[T.Self__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.Started__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Started__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Started__DEVICE_EXTENSION][_m] == old(Mem)[T.Started__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.GrandMaster__GLOBALS] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.GrandMaster__GLOBALS][_m]} (Empty()[_m]) || Mem[T.GrandMaster__GLOBALS][_m] == old(Mem)[T.GrandMaster__GLOBALS][_m]));
+//TAG: updated memory locations at Mem[T.P_DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.P_DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.P_DEVICE_OBJECT][_m] == old(Mem)[T.P_DEVICE_OBJECT][_m]));
+
+//TAG: havoc memory locations by default
+modifies Mem;
+
+
+procedure __PREfastPagedCode();
+
+//TAG: ensures __preserves_mem
+ensures(Mem == old(Mem));
+//TAG: ensures __preserves_resource("DEV_OBJ_INIT") && __preserves_resource("DEV_EXTN")
+ensures((Res_DEV_OBJ_INIT == old(Res_DEV_OBJ_INIT)) && (Res_DEV_EXTN == old(Res_DEV_EXTN)));
+
+modifies Res_DEVICE_STACK;
+
+//TAG: net change in resource DEVICE_STACK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEVICE_STACK[r]} (Empty()[r]) || old(Res_DEVICE_STACK)[r] == Res_DEVICE_STACK[r]));
+modifies Res_DEV_EXTN;
+
+//TAG: net change in resource DEV_EXTN only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_EXTN[r]} (Empty()[r]) || old(Res_DEV_EXTN)[r] == Res_DEV_EXTN[r]));
+modifies Res_DEV_OBJ_INIT;
+
+//TAG: net change in resource DEV_OBJ_INIT only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_OBJ_INIT[r]} (Empty()[r]) || old(Res_DEV_OBJ_INIT)[r] == Res_DEV_OBJ_INIT[r]));
+modifies Res_SPIN_LOCK;
+
+//TAG: net change in resource SPIN_LOCK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_SPIN_LOCK[r]} (Empty()[r]) || old(Res_SPIN_LOCK)[r] == Res_SPIN_LOCK[r]));
+//TAG: updated memory locations at Mem[T.MinorFunction__IO_STACK_LOCATION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.MinorFunction__IO_STACK_LOCATION][_m]} (Empty()[_m]) || Mem[T.MinorFunction__IO_STACK_LOCATION][_m] == old(Mem)[T.MinorFunction__IO_STACK_LOCATION][_m]));
+//TAG: updated memory locations at Mem[T.CurrentStackLocation___unnamed_4_a7aa989c] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.CurrentStackLocation___unnamed_4_a7aa989c][_m]} (Empty()[_m]) || Mem[T.CurrentStackLocation___unnamed_4_a7aa989c][_m] == old(Mem)[T.CurrentStackLocation___unnamed_4_a7aa989c][_m]));
+//TAG: updated memory locations at Mem[T.DeviceExtension__DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.DeviceExtension__DEVICE_OBJECT][_m] == old(Mem)[T.DeviceExtension__DEVICE_OBJECT][_m]));
+//TAG: updated memory locations at Mem[T.Self__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Self__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Self__DEVICE_EXTENSION][_m] == old(Mem)[T.Self__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.Started__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Started__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Started__DEVICE_EXTENSION][_m] == old(Mem)[T.Started__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.GrandMaster__GLOBALS] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.GrandMaster__GLOBALS][_m]} (Empty()[_m]) || Mem[T.GrandMaster__GLOBALS][_m] == old(Mem)[T.GrandMaster__GLOBALS][_m]));
+//TAG: updated memory locations at Mem[T.P_DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.P_DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.P_DEVICE_OBJECT][_m] == old(Mem)[T.P_DEVICE_OBJECT][_m]));
+
+//TAG: havoc memory locations by default
+modifies Mem;
+
+
+procedure MouseClassFindMorePorts($DriverObject$1$4588.20$MouseClassFindMorePorts$121:int, $Context$2$4589.20$MouseClassFindMorePorts$121:int, $Count$3$4590.20$MouseClassFindMorePorts$121:int)
+
+//TAG: requires 1 ==> (Globals.GrandMaster != (void *)0 ==> __resource("DEV_EXTN", Globals.GrandMaster) == 1)
+requires((true) ==> ((Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)] != 0) ==> (Res_DEV_EXTN[Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)]] == 1)));
+//TAG: requires 1 ==> __setin(&Globals.LegacyDeviceList, __btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList))
+requires((true) ==> (ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[LegacyDeviceList__GLOBALS(Globals)]));
+//TAG: requires 1 ==> __forall(_H_y, __btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList), _H_y == &Globals.LegacyDeviceList || __resource("DEV_EXTN", CONTAINING_RECORD(_H_y, struct _DEVICE_EXTENSION , Link)) == 1)
+requires((true) ==> ((Subset(Empty(), ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))) && (forall _H_y : int :: {ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[_H_y]} (ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[_H_y]) ==> ((_H_y == LegacyDeviceList__GLOBALS(Globals)) || (Res_DEV_EXTN[MINUS_LEFT_PTR(_H_y, 1, Link__DEVICE_EXTENSION(0))] == 1))))));
+//TAG: requires 1 ==> !__setin(&Globals.GrandMaster->Link, __setminus(__btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList), __set(&Globals.LegacyDeviceList)))
+requires((true) ==> (!(Difference(ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals)), Singleton(LegacyDeviceList__GLOBALS(Globals)))[Link__DEVICE_EXTENSION(Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)])])));
+//TAG: requires __pforall(_H_x, (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension), __inv_resource("DEV_OBJ_INIT", 1), ((struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension))->Self == _H_x && __resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension)) == 1)
+requires((forall _H_x:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)]} Inverse(Res_DEV_OBJ_INIT,1)[_H_x] ==> ((Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)])] == _H_x) && (Res_DEV_EXTN[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)]] == 1))));
+//TAG: requires __pforall(_H_z, _H_z->Self, __inv_resource("DEV_EXTN", 1), __resource("DEV_OBJ_INIT", _H_z->Self) == 1 && (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)(_H_z->Self))->DeviceExtension) == _H_z) && __forall(_H_z, __inv_resource("DEV_EXTN", 1), __resource("SPIN_LOCK", &_H_z->SpinLock) == 0 && __resource("SPIN_LOCK", &_H_z->WaitWakeSpinLock) == 0)
+requires(((forall _H_z:int :: {Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)]} Inverse(Res_DEV_EXTN,1)[_H_z] ==> ((Res_DEV_OBJ_INIT[Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)]] == 1) && (Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)])] == _H_z)))) && ((Subset(Empty(), Inverse(Res_DEV_EXTN,1)) && (forall _H_z : int :: {Inverse(Res_DEV_EXTN,1)[_H_z]} (Inverse(Res_DEV_EXTN,1)[_H_z]) ==> ((Res_SPIN_LOCK[SpinLock__DEVICE_EXTENSION(_H_z)] == 0) && (Res_SPIN_LOCK[WaitWakeSpinLock__DEVICE_EXTENSION(_H_z)] == 0))))));
+//TAG: ensures 1 ==> (Globals.GrandMaster != (void *)0 ==> __resource("DEV_EXTN", Globals.GrandMaster) == 1)
+ensures((true) ==> ((Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)] != 0) ==> (Res_DEV_EXTN[Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)]] == 1)));
+//TAG: ensures 1 ==> __setin(&Globals.LegacyDeviceList, __btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList))
+ensures((true) ==> (ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[LegacyDeviceList__GLOBALS(Globals)]));
+//TAG: ensures 1 ==> __forall(_H_y, __btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList), _H_y == &Globals.LegacyDeviceList || __resource("DEV_EXTN", CONTAINING_RECORD(_H_y, struct _DEVICE_EXTENSION , Link)) == 1)
+ensures((true) ==> ((Subset(Empty(), ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))) && (forall _H_y : int :: {ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[_H_y]} (ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[_H_y]) ==> ((_H_y == LegacyDeviceList__GLOBALS(Globals)) || (Res_DEV_EXTN[MINUS_LEFT_PTR(_H_y, 1, Link__DEVICE_EXTENSION(0))] == 1))))));
+//TAG: ensures 1 ==> !__setin(&Globals.GrandMaster->Link, __setminus(__btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList), __set(&Globals.LegacyDeviceList)))
+ensures((true) ==> (!(Difference(ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals)), Singleton(LegacyDeviceList__GLOBALS(Globals)))[Link__DEVICE_EXTENSION(Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)])])));
+//TAG: ensures __pforall(_H_x, (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension), __inv_resource("DEV_OBJ_INIT", 1), ((struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension))->Self == _H_x && __resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension)) == 1)
+ensures((forall _H_x:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)]} Inverse(Res_DEV_OBJ_INIT,1)[_H_x] ==> ((Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)])] == _H_x) && (Res_DEV_EXTN[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)]] == 1))));
+//TAG: ensures __pforall(_H_z, _H_z->Self, __inv_resource("DEV_EXTN", 1), __resource("DEV_OBJ_INIT", _H_z->Self) == 1 && (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)(_H_z->Self))->DeviceExtension) == _H_z) && __forall(_H_z, __inv_resource("DEV_EXTN", 1), __resource("SPIN_LOCK", &_H_z->SpinLock) == 0 && __resource("SPIN_LOCK", &_H_z->WaitWakeSpinLock) == 0)
+ensures(((forall _H_z:int :: {Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)]} Inverse(Res_DEV_EXTN,1)[_H_z] ==> ((Res_DEV_OBJ_INIT[Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)]] == 1) && (Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)])] == _H_z)))) && ((Subset(Empty(), Inverse(Res_DEV_EXTN,1)) && (forall _H_z : int :: {Inverse(Res_DEV_EXTN,1)[_H_z]} (Inverse(Res_DEV_EXTN,1)[_H_z]) ==> ((Res_SPIN_LOCK[SpinLock__DEVICE_EXTENSION(_H_z)] == 0) && (Res_SPIN_LOCK[WaitWakeSpinLock__DEVICE_EXTENSION(_H_z)] == 0))))));
+modifies alloc;
+free ensures(forall f:int :: {alloc[Base(f)]} old(alloc)[Base(f)] == UNALLOCATED || old(alloc)[Base(f)] == alloc[Base(f)]);
+
+modifies Res_DEVICE_STACK;
+
+//TAG: net change in resource DEVICE_STACK only for:
+modifies Res_DEV_EXTN;
+
+//TAG: net change in resource DEV_EXTN only for:
+modifies Res_DEV_OBJ_INIT;
+
+//TAG: net change in resource DEV_OBJ_INIT only for:
+modifies Res_SPIN_LOCK;
+
+//TAG: net change in resource SPIN_LOCK only for:
+
+//TAG: havoc memory locations by default
+modifies Mem;
+{
+var havoc_stringTemp:int;
+var condVal:int;
+var $Context$2$4589.20$MouseClassFindMorePorts$12 : int;
+var $Count$3$4590.20$MouseClassFindMorePorts$12 : int;
+var $DriverObject$1$4588.20$MouseClassFindMorePorts$12 : int;
+var $ExAllocatePoolWithTag.arg.2$5$ : int;
+var $MouDebugPrint.arg.2$6$ : int;
+var $RtlAppendUnicodeToString.arg.2$10$ : int;
+var $RtlAppendUnicodeToString.arg.2$13$ : int;
+var $RtlAppendUnicodeToString.arg.2$3$ : int;
+var $basePortBuffer$13$4622.28$MouseClassFindMorePorts$12 : int;
+var $basePortName$11$4620.28$MouseClassFindMorePorts$12 : int;
+var $classDeviceObject$6$4615.28$MouseClassFindMorePorts$12 : int;
+var $deviceExtension$5$4614.28$MouseClassFindMorePorts$12 : int;
+var $dumpData$7$4616.28$MouseClassFindMorePorts$12 : int;
+var $file$15$4624.28$MouseClassFindMorePorts$12 : int;
+var $fullClassName$14$4623.28$MouseClassFindMorePorts$12 : int;
+var $fullPortName$12$4621.28$MouseClassFindMorePorts$12 : int;
+var $i$8$4617.28$MouseClassFindMorePorts$12 : int;
+var $memset.arg.3$8$ : int;
+var $numPorts$9$4618.28$MouseClassFindMorePorts$12 : int;
+var $port$16$4759.22$MouseClassFindMorePorts$12 : int;
+var $result.ExAllocatePoolWithTag$4653.0$4$ : int;
+var $result.IoGetDeviceObjectPointer$4731.42$16$ : int;
+var $result.MouCreateClassObject$4708.37$15$ : int;
+var $result.MouDeterminePortsServiced$4680.29$14$ : int;
+var $result.MouseAddDeviceEx$4743.34$17$ : int;
+var $result.ObfDereferenceObject$4772.16$18$ : int;
+var $result.RtlAppendUnicodeToString$4642.28$2$ : int;
+var $result.RtlAppendUnicodeToString$4676.28$9$ : int;
+var $result.RtlAppendUnicodeToString$4677.28$11$ : int;
+var $result.RtlAppendUnicodeToString$4678.28$12$ : int;
+var $result.memset$4630.4$1$ : int;
+var $result.memset$4675.4$7$ : int;
+var $status$4$4613.28$MouseClassFindMorePorts$12 : int;
+var $successfulCreates$10$4619.28$MouseClassFindMorePorts$12 : int;
+var tempBoogie0:int;
+var tempBoogie1:int;
+var tempBoogie2:int;
+var tempBoogie3:int;
+var tempBoogie4:int;
+var tempBoogie5:int;
+var tempBoogie6:int;
+var tempBoogie7:int;
+var tempBoogie8:int;
+var tempBoogie9:int;
+var tempBoogie10:int;
+var tempBoogie11:int;
+var tempBoogie12:int;
+var tempBoogie13:int;
+var tempBoogie14:int;
+var tempBoogie15:int;
+var tempBoogie16:int;
+var tempBoogie17:int;
+var tempBoogie18:int;
+var tempBoogie19:int;
+var LOOP_74_alloc:[int]name;
+var LOOP_74_Mem:[name][int]int;
+var LOOP_74_Res_DEVICE_STACK:[int]int;
+var LOOP_74_Res_DEV_EXTN:[int]int;
+var LOOP_74_Res_DEV_OBJ_INIT:[int]int;
+var LOOP_74_Res_SPIN_LOCK:[int]int;
+
+
+start:
+
+assume (alloc[$DriverObject$1$4588.20$MouseClassFindMorePorts$121] != UNALLOCATED);
+assume (alloc[$Context$2$4589.20$MouseClassFindMorePorts$121] != UNALLOCATED);
+call $basePortBuffer$13$4622.28$MouseClassFindMorePorts$12 := __HAVOC_malloc(512);
+call $basePortName$11$4620.28$MouseClassFindMorePorts$12 := __HAVOC_malloc(8);
+call $classDeviceObject$6$4615.28$MouseClassFindMorePorts$12 := __HAVOC_malloc(4);
+call $dumpData$7$4616.28$MouseClassFindMorePorts$12 := __HAVOC_malloc(16);
+call $file$15$4624.28$MouseClassFindMorePorts$12 := __HAVOC_malloc(4);
+call $fullClassName$14$4623.28$MouseClassFindMorePorts$12 := __HAVOC_malloc(4);
+call $fullPortName$12$4621.28$MouseClassFindMorePorts$12 := __HAVOC_malloc(8);
+call $numPorts$9$4618.28$MouseClassFindMorePorts$12 := __HAVOC_malloc(4);
+$DriverObject$1$4588.20$MouseClassFindMorePorts$12 := $DriverObject$1$4588.20$MouseClassFindMorePorts$121;
+$Context$2$4589.20$MouseClassFindMorePorts$12 := $Context$2$4589.20$MouseClassFindMorePorts$121;
+$Count$3$4590.20$MouseClassFindMorePorts$12 := $Count$3$4590.20$MouseClassFindMorePorts$121;
+goto label_3;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(4799)
+label_1:
+call __HAVOC_free($basePortBuffer$13$4622.28$MouseClassFindMorePorts$12);
+call __HAVOC_free($basePortName$11$4620.28$MouseClassFindMorePorts$12);
+call __HAVOC_free($classDeviceObject$6$4615.28$MouseClassFindMorePorts$12);
+call __HAVOC_free($dumpData$7$4616.28$MouseClassFindMorePorts$12);
+call __HAVOC_free($file$15$4624.28$MouseClassFindMorePorts$12);
+call __HAVOC_free($fullClassName$14$4623.28$MouseClassFindMorePorts$12);
+call __HAVOC_free($fullPortName$12$4621.28$MouseClassFindMorePorts$12);
+call __HAVOC_free($numPorts$9$4618.28$MouseClassFindMorePorts$12);
+assume (forall m:int:: {Res_DEVICE_STACK[m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Res_DEVICE_STACK[m] == old(Res_DEVICE_STACK)[m]);
+assume (forall m:int:: {Res_DEV_EXTN[m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Res_DEV_EXTN[m] == old(Res_DEV_EXTN)[m]);
+assume (forall m:int:: {Res_DEV_OBJ_INIT[m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Res_DEV_OBJ_INIT[m] == old(Res_DEV_OBJ_INIT)[m]);
+assume (forall m:int:: {Res_SPIN_LOCK[m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Res_SPIN_LOCK[m] == old(Res_SPIN_LOCK)[m]);
+assume (forall m:int :: {Mem[T.A256UINT2][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.A256UINT2][m] == old(Mem[T.A256UINT2])[m]);
+assume (forall m:int :: {Mem[T.A2UINT2][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.A2UINT2][m] == old(Mem[T.A2UINT2])[m]);
+assume (forall m:int :: {Mem[T.A4UINT4][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.A4UINT4][m] == old(Mem[T.A4UINT4])[m]);
+assume (forall m:int :: {Mem[T.A5UINT2][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.A5UINT2][m] == old(Mem[T.A5UINT2])[m]);
+assume (forall m:int :: {Mem[T.A85CHAR][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.A85CHAR][m] == old(Mem[T.A85CHAR])[m]);
+assume (forall m:int :: {Mem[T.A9UINT2][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.A9UINT2][m] == old(Mem[T.A9UINT2])[m]);
+assume (forall m:int :: {Mem[T.AssocClassList__GLOBALS][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.AssocClassList__GLOBALS][m] == old(Mem[T.AssocClassList__GLOBALS])[m]);
+assume (forall m:int :: {Mem[T.BaseClassName__GLOBALS][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.BaseClassName__GLOBALS][m] == old(Mem[T.BaseClassName__GLOBALS])[m]);
+assume (forall m:int :: {Mem[T.Buffer__UNICODE_STRING][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.Buffer__UNICODE_STRING][m] == old(Mem[T.Buffer__UNICODE_STRING])[m]);
+assume (forall m:int :: {Mem[T.CHAR][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.CHAR][m] == old(Mem[T.CHAR])[m]);
+assume (forall m:int :: {Mem[T.CurrentStackLocation___unnamed_4_a7aa989c][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.CurrentStackLocation___unnamed_4_a7aa989c][m] == old(Mem[T.CurrentStackLocation___unnamed_4_a7aa989c])[m]);
+assume (forall m:int :: {Mem[T.DataIn__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.DataIn__DEVICE_EXTENSION][m] == old(Mem[T.DataIn__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.DataOut__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.DataOut__DEVICE_EXTENSION][m] == old(Mem[T.DataOut__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.DeviceExtension__DEVICE_OBJECT][m] == old(Mem[T.DeviceExtension__DEVICE_OBJECT])[m]);
+assume (forall m:int :: {Mem[T.File__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.File__DEVICE_EXTENSION][m] == old(Mem[T.File__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.File__PORT][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.File__PORT][m] == old(Mem[T.File__PORT])[m]);
+assume (forall m:int :: {Mem[T.Flags__DEVICE_OBJECT][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.Flags__DEVICE_OBJECT][m] == old(Mem[T.Flags__DEVICE_OBJECT])[m]);
+assume (forall m:int :: {Mem[T.Flink__LIST_ENTRY][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.Flink__LIST_ENTRY][m] == old(Mem[T.Flink__LIST_ENTRY])[m]);
+assume (forall m:int :: {Mem[T.Free__PORT][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.Free__PORT][m] == old(Mem[T.Free__PORT])[m]);
+assume (forall m:int :: {Mem[T.GrandMaster__GLOBALS][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.GrandMaster__GLOBALS][m] == old(Mem[T.GrandMaster__GLOBALS])[m]);
+assume (forall m:int :: {Mem[T.INT4][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.INT4][m] == old(Mem[T.INT4])[m]);
+assume (forall m:int :: {Mem[T.InitExtension__GLOBALS][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.InitExtension__GLOBALS][m] == old(Mem[T.InitExtension__GLOBALS])[m]);
+assume (forall m:int :: {Mem[T.InputData__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.InputData__DEVICE_EXTENSION][m] == old(Mem[T.InputData__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.LegacyDeviceList__GLOBALS][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.LegacyDeviceList__GLOBALS][m] == old(Mem[T.LegacyDeviceList__GLOBALS])[m]);
+assume (forall m:int :: {Mem[T.Length__UNICODE_STRING][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.Length__UNICODE_STRING][m] == old(Mem[T.Length__UNICODE_STRING])[m]);
+assume (forall m:int :: {Mem[T.Link__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.Link__DEVICE_EXTENSION][m] == old(Mem[T.Link__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.MaximumLength__UNICODE_STRING][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.MaximumLength__UNICODE_STRING][m] == old(Mem[T.MaximumLength__UNICODE_STRING])[m]);
+assume (forall m:int :: {Mem[T.MinorFunction__IO_STACK_LOCATION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.MinorFunction__IO_STACK_LOCATION][m] == old(Mem[T.MinorFunction__IO_STACK_LOCATION])[m]);
+assume (forall m:int :: {Mem[T.Mutex__GLOBALS][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.Mutex__GLOBALS][m] == old(Mem[T.Mutex__GLOBALS])[m]);
+assume (forall m:int :: {Mem[T.NumberLegacyPorts__GLOBALS][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.NumberLegacyPorts__GLOBALS][m] == old(Mem[T.NumberLegacyPorts__GLOBALS])[m]);
+assume (forall m:int :: {Mem[T.PCHAR][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.PCHAR][m] == old(Mem[T.PCHAR])[m]);
+assume (forall m:int :: {Mem[T.PPUINT2][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.PPUINT2][m] == old(Mem[T.PPUINT2])[m]);
+assume (forall m:int :: {Mem[T.PP_DEVICE_OBJECT][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.PP_DEVICE_OBJECT][m] == old(Mem[T.PP_DEVICE_OBJECT])[m]);
+assume (forall m:int :: {Mem[T.PP_FILE_OBJECT][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.PP_FILE_OBJECT][m] == old(Mem[T.PP_FILE_OBJECT])[m]);
+assume (forall m:int :: {Mem[T.PUINT2][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.PUINT2][m] == old(Mem[T.PUINT2])[m]);
+assume (forall m:int :: {Mem[T.PUINT4][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.PUINT4][m] == old(Mem[T.PUINT4])[m]);
+assume (forall m:int :: {Mem[T.PVOID][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.PVOID][m] == old(Mem[T.PVOID])[m]);
+assume (forall m:int :: {Mem[T.P_DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.P_DEVICE_EXTENSION][m] == old(Mem[T.P_DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.P_DEVICE_OBJECT][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.P_DEVICE_OBJECT][m] == old(Mem[T.P_DEVICE_OBJECT])[m]);
+assume (forall m:int :: {Mem[T.P_DRIVER_OBJECT][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.P_DRIVER_OBJECT][m] == old(Mem[T.P_DRIVER_OBJECT])[m]);
+assume (forall m:int :: {Mem[T.P_FAST_MUTEX][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.P_FAST_MUTEX][m] == old(Mem[T.P_FAST_MUTEX])[m]);
+assume (forall m:int :: {Mem[T.P_FILE_OBJECT][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.P_FILE_OBJECT][m] == old(Mem[T.P_FILE_OBJECT])[m]);
+assume (forall m:int :: {Mem[T.P_LIST_ENTRY][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.P_LIST_ENTRY][m] == old(Mem[T.P_LIST_ENTRY])[m]);
+assume (forall m:int :: {Mem[T.P_MOUSE_INPUT_DATA][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.P_MOUSE_INPUT_DATA][m] == old(Mem[T.P_MOUSE_INPUT_DATA])[m]);
+assume (forall m:int :: {Mem[T.P_UNICODE_STRING][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.P_UNICODE_STRING][m] == old(Mem[T.P_UNICODE_STRING])[m]);
+assume (forall m:int :: {Mem[T.PnP__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.PnP__DEVICE_EXTENSION][m] == old(Mem[T.PnP__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.Port__PORT][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.Port__PORT][m] == old(Mem[T.Port__PORT])[m]);
+assume (forall m:int :: {Mem[T.PortsServiced__GLOBALS][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.PortsServiced__GLOBALS][m] == old(Mem[T.PortsServiced__GLOBALS])[m]);
+assume (forall m:int :: {Mem[T.Self__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.Self__DEVICE_EXTENSION][m] == old(Mem[T.Self__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.SpinLock__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.SpinLock__DEVICE_EXTENSION][m] == old(Mem[T.SpinLock__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.StackSize__DEVICE_OBJECT][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.StackSize__DEVICE_OBJECT][m] == old(Mem[T.StackSize__DEVICE_OBJECT])[m]);
+assume (forall m:int :: {Mem[T.Started__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.Started__DEVICE_EXTENSION][m] == old(Mem[T.Started__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.TopPort__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.TopPort__DEVICE_EXTENSION][m] == old(Mem[T.TopPort__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.UCHAR][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.UCHAR][m] == old(Mem[T.UCHAR])[m]);
+assume (forall m:int :: {Mem[T.UINT2][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.UINT2][m] == old(Mem[T.UINT2])[m]);
+assume (forall m:int :: {Mem[T.UINT4][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.UINT4][m] == old(Mem[T.UINT4])[m]);
+assume (forall m:int :: {Mem[T.UnitId__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.UnitId__DEVICE_EXTENSION][m] == old(Mem[T.UnitId__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.WaitWakeSpinLock__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.WaitWakeSpinLock__DEVICE_EXTENSION][m] == old(Mem[T.WaitWakeSpinLock__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T._POOL_TYPE][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T._POOL_TYPE][m] == old(Mem[T._POOL_TYPE])[m]);
+return;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(4799)
+label_2:
+assume false;
+return;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(4613)
+label_3:
+goto label_4;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(4614)
+label_4:
+goto label_5;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(4614)
+label_5:
+$deviceExtension$5$4614.28$MouseClassFindMorePorts$12 := 0 ;
+goto label_6;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(4615)
+label_6:
+goto label_7;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(4615)
+label_7:
+Mem[T.P_DEVICE_OBJECT] := Mem[T.P_DEVICE_OBJECT][$classDeviceObject$6$4615.28$MouseClassFindMorePorts$12 := 0];
+goto label_8;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(4616)
+label_8:
+goto label_9;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(4617)
+label_9:
+goto label_10;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(4618)
+label_10:
+goto label_11;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(4619)
+label_11:
+goto label_12;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(4620)
+label_12:
+goto label_13;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(4621)
+label_13:
+goto label_14;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(4622)
+label_14:
+goto label_15;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(4623)
+label_15:
+goto label_16;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(4623)
+label_16:
+Mem[T.PUINT2] := Mem[T.PUINT2][$fullClassName$14$4623.28$MouseClassFindMorePorts$12 := 0];
+goto label_17;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(4624)
+label_17:
+goto label_18;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(4626)
+label_18:
+call __PREfastPagedCode ();
+goto label_21;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(4628)
+label_21:
+Mem[T.MaximumLength__UNICODE_STRING] := Mem[T.MaximumLength__UNICODE_STRING][MaximumLength__UNICODE_STRING($fullPortName$12$4621.28$MouseClassFindMorePorts$12) := 0];
+goto label_22;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(4630)
+label_22:
+// ignoring intrinsic intrinsic.memset
+havoc $result.memset$4630.4$1$;
+goto label_25;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(4631)
+label_25:
+Mem[T.Buffer__UNICODE_STRING] := Mem[T.Buffer__UNICODE_STRING][Buffer__UNICODE_STRING($basePortName$11$4620.28$MouseClassFindMorePorts$12) := $basePortBuffer$13$4622.28$MouseClassFindMorePorts$12];
+goto label_26;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(4632)
+label_26:
+Mem[T.Length__UNICODE_STRING] := Mem[T.Length__UNICODE_STRING][Length__UNICODE_STRING($basePortName$11$4620.28$MouseClassFindMorePorts$12) := 0];
+goto label_27;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(4633)
+label_27:
+Mem[T.MaximumLength__UNICODE_STRING] := Mem[T.MaximumLength__UNICODE_STRING][MaximumLength__UNICODE_STRING($basePortName$11$4620.28$MouseClassFindMorePorts$12) := 512];
+goto label_28;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(4640)
+label_28:
+call RtlCopyUnicodeString ($basePortName$11$4620.28$MouseClassFindMorePorts$12, BaseClassName__GLOBALS(Globals));
+goto label_31;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(4641)
+label_31:
+tempBoogie0 := MINUS_BOTH_PTR_OR_BOTH_INT( Mem[T.Length__UNICODE_STRING][Length__UNICODE_STRING($basePortName$11$4620.28$MouseClassFindMorePorts$12)], 10, 1) ;
+Mem[T.Length__UNICODE_STRING] := Mem[T.Length__UNICODE_STRING][Length__UNICODE_STRING($basePortName$11$4620.28$MouseClassFindMorePorts$12) := tempBoogie0];
+goto label_35;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(4642)
+label_32:
+call $result.RtlAppendUnicodeToString$4642.28$2$ := RtlAppendUnicodeToString ($basePortName$11$4620.28$MouseClassFindMorePorts$12, $RtlAppendUnicodeToString.arg.2$3$);
+goto label_36;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(4642)
+label_35:
+call havoc_stringTemp := __HAVOC_malloc(1);
+$RtlAppendUnicodeToString.arg.2$3$ := havoc_stringTemp ;
+goto label_32;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(4647)
+label_36:
+call RtlInitUnicodeString ($fullPortName$12$4621.28$MouseClassFindMorePorts$12, 0);
+goto label_39;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(4649)
+label_39:
+Mem[T.MaximumLength__UNICODE_STRING] := Mem[T.MaximumLength__UNICODE_STRING][MaximumLength__UNICODE_STRING($fullPortName$12$4621.28$MouseClassFindMorePorts$12) := PLUS(PLUS(18, 1, Mem[T.Length__UNICODE_STRING][Length__UNICODE_STRING($basePortName$11$4620.28$MouseClassFindMorePorts$12)]), 1, 2)];
+goto label_43;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(4653)
+label_40:
+call $result.ExAllocatePoolWithTag$4653.0$4$ := ExAllocatePoolWithTag (1, $ExAllocatePoolWithTag.arg.2$5$, 1131377997);
+goto label_44;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(4653)
+label_43:
+$ExAllocatePoolWithTag.arg.2$5$ := Mem[T.MaximumLength__UNICODE_STRING][MaximumLength__UNICODE_STRING($fullPortName$12$4621.28$MouseClassFindMorePorts$12)] ;
+goto label_40;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(4653)
+label_44:
+Mem[T.Buffer__UNICODE_STRING] := Mem[T.Buffer__UNICODE_STRING][Buffer__UNICODE_STRING($fullPortName$12$4621.28$MouseClassFindMorePorts$12) := $result.ExAllocatePoolWithTag$4653.0$4$];
+goto label_45;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(4656)
+label_45:
+goto label_45_true , label_45_false ;
+
+
+label_45_true :
+assume (Mem[T.Buffer__UNICODE_STRING][Buffer__UNICODE_STRING($fullPortName$12$4621.28$MouseClassFindMorePorts$12)] != 0);
+goto label_57;
+
+
+label_45_false :
+assume (Mem[T.Buffer__UNICODE_STRING][Buffer__UNICODE_STRING($fullPortName$12$4621.28$MouseClassFindMorePorts$12)] == 0);
+goto label_49;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(4658)
+label_46:
+// skip MouDebugPrint
+goto label_50;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(4658)
+label_49:
+call havoc_stringTemp := __HAVOC_malloc(1);
+$MouDebugPrint.arg.2$6$ := havoc_stringTemp ;
+goto label_46;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(4663)
+label_50:
+Mem[T.UINT4] := Mem[T.UINT4][PLUS($dumpData$7$4616.28$MouseClassFindMorePorts$12, 4, 0) := Mem[T.MaximumLength__UNICODE_STRING][MaximumLength__UNICODE_STRING($fullPortName$12$4621.28$MouseClassFindMorePorts$12)]];
+goto label_51;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(4664)
+label_51:
+call MouseClassLogError ($DriverObject$1$4588.20$MouseClassFindMorePorts$12, BOOGIE_LARGE_INT_3221553153, 20008, -1073741823, 1, $dumpData$7$4616.28$MouseClassFindMorePorts$12, 0);
+goto label_156;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(4675)
+label_54:
+// ignoring intrinsic intrinsic.memset
+havoc $result.memset$4675.4$7$;
+goto label_61;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(4675)
+label_57:
+$memset.arg.3$8$ := Mem[T.MaximumLength__UNICODE_STRING][MaximumLength__UNICODE_STRING($fullPortName$12$4621.28$MouseClassFindMorePorts$12)] ;
+goto label_54;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(4676)
+label_58:
+call $result.RtlAppendUnicodeToString$4676.28$9$ := RtlAppendUnicodeToString ($fullPortName$12$4621.28$MouseClassFindMorePorts$12, $RtlAppendUnicodeToString.arg.2$10$);
+goto label_62;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(4676)
+label_61:
+call havoc_stringTemp := __HAVOC_malloc(1);
+$RtlAppendUnicodeToString.arg.2$10$ := havoc_stringTemp ;
+goto label_58;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(4677)
+label_62:
+call $result.RtlAppendUnicodeToString$4677.28$11$ := RtlAppendUnicodeToString ($fullPortName$12$4621.28$MouseClassFindMorePorts$12, Mem[T.Buffer__UNICODE_STRING][Buffer__UNICODE_STRING($basePortName$11$4620.28$MouseClassFindMorePorts$12)]);
+goto label_68;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(4678)
+label_65:
+call $result.RtlAppendUnicodeToString$4678.28$12$ := RtlAppendUnicodeToString ($fullPortName$12$4621.28$MouseClassFindMorePorts$12, $RtlAppendUnicodeToString.arg.2$13$);
+goto label_69;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(4678)
+label_68:
+call havoc_stringTemp := __HAVOC_malloc(1);
+$RtlAppendUnicodeToString.arg.2$13$ := havoc_stringTemp ;
+goto label_65;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(4680)
+label_69:
+call $result.MouDeterminePortsServiced$4680.29$14$ := MouDeterminePortsServiced ($basePortName$11$4620.28$MouseClassFindMorePorts$12, $numPorts$9$4618.28$MouseClassFindMorePorts$12);
+goto label_72;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(4687)
+label_72:
+$i$8$4617.28$MouseClassFindMorePorts$12 := Mem[T.NumberLegacyPorts__GLOBALS][NumberLegacyPorts__GLOBALS(Globals)] ;
+goto label_73;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(4687)
+label_73:
+$successfulCreates$10$4619.28$MouseClassFindMorePorts$12 := 0 ;
+goto label_74;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(4688)
+label_74:
+// loop entry initialization...
+LOOP_74_alloc := alloc;
+LOOP_74_Mem := Mem;
+LOOP_74_Res_DEVICE_STACK := Res_DEVICE_STACK;
+LOOP_74_Res_DEV_EXTN := Res_DEV_EXTN;
+LOOP_74_Res_DEV_OBJ_INIT := Res_DEV_OBJ_INIT;
+LOOP_74_Res_SPIN_LOCK := Res_SPIN_LOCK;
+goto label_74_head;
+
+
+label_74_head:
+// loop head assertions...
+//TAG: requires __pforall(_H_x, (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension), __inv_resource("DEV_OBJ_INIT", 1), ((struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension))->Self == _H_x && __resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension)) == 1)
+assert((forall _H_x:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)]} Inverse(Res_DEV_OBJ_INIT,1)[_H_x] ==> ((Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)])] == _H_x) && (Res_DEV_EXTN[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)]] == 1))));
+//TAG: requires __pforall(_H_z, _H_z->Self, __inv_resource("DEV_EXTN", 1), __resource("DEV_OBJ_INIT", _H_z->Self) == 1 && (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)(_H_z->Self))->DeviceExtension) == _H_z)
+assert((forall _H_z:int :: {Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)]} Inverse(Res_DEV_EXTN,1)[_H_z] ==> ((Res_DEV_OBJ_INIT[Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)]] == 1) && (Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)])] == _H_z))));
+//TAG: requires __forall(_H_z, __inv_resource("DEV_EXTN", 1), __resource("SPIN_LOCK", &_H_z->SpinLock) == 0 && __resource("SPIN_LOCK", &_H_z->WaitWakeSpinLock) == 0)
+assert((Subset(Empty(), Inverse(Res_DEV_EXTN,1)) && (forall _H_z : int :: {Inverse(Res_DEV_EXTN,1)[_H_z]} (Inverse(Res_DEV_EXTN,1)[_H_z]) ==> ((Res_SPIN_LOCK[SpinLock__DEVICE_EXTENSION(_H_z)] == 0) && (Res_SPIN_LOCK[WaitWakeSpinLock__DEVICE_EXTENSION(_H_z)] == 0)))));
+//TAG: requires 1 ==> (Globals.GrandMaster != (void *)0 ==> __resource("DEV_EXTN", Globals.GrandMaster) == 1)
+assert((true) ==> ((Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)] != 0) ==> (Res_DEV_EXTN[Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)]] == 1)));
+//TAG: requires 1 ==> __setin(&Globals.LegacyDeviceList, __btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList))
+assert((true) ==> (ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[LegacyDeviceList__GLOBALS(Globals)]));
+//TAG: requires 1 ==> __forall(_H_y, __btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList), _H_y == &Globals.LegacyDeviceList || __resource("DEV_EXTN", CONTAINING_RECORD(_H_y, struct _DEVICE_EXTENSION , Link)) == 1)
+assert((true) ==> ((Subset(Empty(), ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))) && (forall _H_y : int :: {ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[_H_y]} (ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[_H_y]) ==> ((_H_y == LegacyDeviceList__GLOBALS(Globals)) || (Res_DEV_EXTN[MINUS_LEFT_PTR(_H_y, 1, Link__DEVICE_EXTENSION(0))] == 1))))));
+//TAG: requires 1 ==> !__setin(&Globals.GrandMaster->Link, __setminus(__btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList), __set(&Globals.LegacyDeviceList)))
+assert((true) ==> (!(Difference(ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals)), Singleton(LegacyDeviceList__GLOBALS(Globals)))[Link__DEVICE_EXTENSION(Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)])])));
+assume(forall f:int :: {alloc[Base(f)]} LOOP_74_alloc[Base(f)] == UNALLOCATED || LOOP_74_alloc[Base(f)] == alloc[Base(f)]);
+
+
+//TAG: net change in resource DEVICE_STACK only for: __set_empty
+assert (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEVICE_STACK[r]} (Empty()[r]) || LOOP_74_Res_DEVICE_STACK[r] == Res_DEVICE_STACK[r]));
+
+//TAG: net change in resource DEV_EXTN only for: __set_true
+assert (Subset(Empty(), Union(Empty(), SetTrue())) && (forall r:int :: {Res_DEV_EXTN[r]} (SetTrue()[r]) || LOOP_74_Res_DEV_EXTN[r] == Res_DEV_EXTN[r]));
+
+//TAG: net change in resource DEV_OBJ_INIT only for: __set_true
+assert (Subset(Empty(), Union(Empty(), SetTrue())) && (forall r:int :: {Res_DEV_OBJ_INIT[r]} (SetTrue()[r]) || LOOP_74_Res_DEV_OBJ_INIT[r] == Res_DEV_OBJ_INIT[r]));
+
+//TAG: net change in resource SPIN_LOCK only for: __set_true
+assert (Subset(Empty(), Union(Empty(), SetTrue())) && (forall r:int :: {Res_SPIN_LOCK[r]} (SetTrue()[r]) || LOOP_74_Res_SPIN_LOCK[r] == Res_SPIN_LOCK[r]));
+//TAG: updated memory locations at Mem[T.MinorFunction__IO_STACK_LOCATION] only for: __set_empty
+assert (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.MinorFunction__IO_STACK_LOCATION][_m]} (Empty()[_m]) || Mem[T.MinorFunction__IO_STACK_LOCATION][_m] == LOOP_74_Mem[T.MinorFunction__IO_STACK_LOCATION][_m]));
+//TAG: updated memory locations at Mem[T.CurrentStackLocation___unnamed_4_a7aa989c] only for: __set_empty
+assert (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.CurrentStackLocation___unnamed_4_a7aa989c][_m]} (Empty()[_m]) || Mem[T.CurrentStackLocation___unnamed_4_a7aa989c][_m] == LOOP_74_Mem[T.CurrentStackLocation___unnamed_4_a7aa989c][_m]));
+//TAG: updated memory locations at Mem[T.DeviceExtension__DEVICE_OBJECT] only for: __set_empty
+assert (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.DeviceExtension__DEVICE_OBJECT][_m] == LOOP_74_Mem[T.DeviceExtension__DEVICE_OBJECT][_m]));
+//TAG: updated memory locations at Mem[T.Self__DEVICE_EXTENSION] only for: __set_true
+assert (Subset(Empty(), Union(Empty(), SetTrue())) && (forall _m:int :: {Mem[T.Self__DEVICE_EXTENSION][_m]} (SetTrue()[_m]) || Mem[T.Self__DEVICE_EXTENSION][_m] == LOOP_74_Mem[T.Self__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.Started__DEVICE_EXTENSION] only for: __set_empty
+assert (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Started__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Started__DEVICE_EXTENSION][_m] == LOOP_74_Mem[T.Started__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.GrandMaster__GLOBALS] only for: __set_empty
+assert (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.GrandMaster__GLOBALS][_m]} (Empty()[_m]) || Mem[T.GrandMaster__GLOBALS][_m] == LOOP_74_Mem[T.GrandMaster__GLOBALS][_m]));
+//TAG: updated memory locations at Mem[T.P_DEVICE_OBJECT] only for: __set_true
+assert (Subset(Empty(), Union(Empty(), SetTrue())) && (forall _m:int :: {Mem[T.P_DEVICE_OBJECT][_m]} (SetTrue()[_m]) || Mem[T.P_DEVICE_OBJECT][_m] == LOOP_74_Mem[T.P_DEVICE_OBJECT][_m]));
+
+// end loop head assertions
+
+goto label_74_true , label_74_false ;
+
+
+label_74_true :
+assume ($i$8$4617.28$MouseClassFindMorePorts$12 < Mem[T.PortsServiced__GLOBALS][PortsServiced__GLOBALS(Globals)]);
+goto label_75;
+
+
+label_74_false :
+assume !($i$8$4617.28$MouseClassFindMorePorts$12 < Mem[T.PortsServiced__GLOBALS][PortsServiced__GLOBALS(Globals)]);
+goto label_155;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(4688)
+label_75:
+goto label_75_true , label_75_false ;
+
+
+label_75_true :
+assume ($i$8$4617.28$MouseClassFindMorePorts$12 < Mem[T.UINT4][$numPorts$9$4618.28$MouseClassFindMorePorts$12]);
+goto label_76;
+
+
+label_75_false :
+assume !($i$8$4617.28$MouseClassFindMorePorts$12 < Mem[T.UINT4][$numPorts$9$4618.28$MouseClassFindMorePorts$12]);
+goto label_155;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(4698)
+label_76:
+Mem[T.UINT2] := Mem[T.UINT2][PLUS(Mem[T.Buffer__UNICODE_STRING][Buffer__UNICODE_STRING($fullPortName$12$4621.28$MouseClassFindMorePorts$12)], 2, MINUS_BOTH_PTR_OR_BOTH_INT( BINARY_BOTH_INT(Mem[T.Length__UNICODE_STRING][Length__UNICODE_STRING($fullPortName$12$4621.28$MouseClassFindMorePorts$12)], 2), 1, 1)) := PLUS(48, 1, $i$8$4617.28$MouseClassFindMorePorts$12)];
+goto label_77;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(4700)
+label_77:
+goto label_77_true , label_77_false ;
+
+
+label_77_true :
+assume (Mem[T.PUINT2][$fullClassName$14$4623.28$MouseClassFindMorePorts$12] != 0);
+goto label_78;
+
+
+label_77_false :
+assume (Mem[T.PUINT2][$fullClassName$14$4623.28$MouseClassFindMorePorts$12] == 0);
+goto label_82;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(4701)
+label_78:
+call ExFreePoolWithTag (Mem[T.PUINT2][$fullClassName$14$4623.28$MouseClassFindMorePorts$12], 0);
+goto label_81;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(4702)
+label_81:
+Mem[T.PUINT2] := Mem[T.PUINT2][$fullClassName$14$4623.28$MouseClassFindMorePorts$12 := 0];
+goto label_82;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(4708)
+label_82:
+call $result.MouCreateClassObject$4708.37$15$ := MouCreateClassObject ($DriverObject$1$4588.20$MouseClassFindMorePorts$12, InitExtension__GLOBALS(Globals), $classDeviceObject$6$4615.28$MouseClassFindMorePorts$12, $fullClassName$14$4623.28$MouseClassFindMorePorts$12, 1);
+goto label_85;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(4708)
+label_85:
+$status$4$4613.28$MouseClassFindMorePorts$12 := $result.MouCreateClassObject$4708.37$15$ ;
+goto label_86;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(4714)
+label_86:
+goto label_86_true , label_86_false ;
+
+
+label_86_true :
+assume (0 <= $status$4$4613.28$MouseClassFindMorePorts$12);
+goto label_90;
+
+
+label_86_false :
+assume !(0 <= $status$4$4613.28$MouseClassFindMorePorts$12);
+goto label_87;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(4715)
+label_87:
+call MouseClassLogError ($DriverObject$1$4588.20$MouseClassFindMorePorts$12, BOOGIE_LARGE_INT_3221553153, 20008, $status$4$4613.28$MouseClassFindMorePorts$12, 0, 0, 0);
+goto label_154;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(4725)
+label_90:
+$deviceExtension$5$4614.28$MouseClassFindMorePorts$12 := Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.P_DEVICE_OBJECT][$classDeviceObject$6$4615.28$MouseClassFindMorePorts$12])] ;
+goto label_91;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(4726)
+label_91:
+Mem[T.PnP__DEVICE_EXTENSION] := Mem[T.PnP__DEVICE_EXTENSION][PnP__DEVICE_EXTENSION($deviceExtension$5$4614.28$MouseClassFindMorePorts$12) := 0];
+goto label_92;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(4731)
+label_92:
+assume (Mem[T.TopPort__DEVICE_EXTENSION][TopPort__DEVICE_EXTENSION($deviceExtension$5$4614.28$MouseClassFindMorePorts$12)] == Mem[T.P_DEVICE_OBJECT][TopPort__DEVICE_EXTENSION($deviceExtension$5$4614.28$MouseClassFindMorePorts$12)]);
+call $result.IoGetDeviceObjectPointer$4731.42$16$ := IoGetDeviceObjectPointer ($fullPortName$12$4621.28$MouseClassFindMorePorts$12, 128, $file$15$4624.28$MouseClassFindMorePorts$12, TopPort__DEVICE_EXTENSION($deviceExtension$5$4614.28$MouseClassFindMorePorts$12));
+Mem[T.TopPort__DEVICE_EXTENSION] := Mem[T.TopPort__DEVICE_EXTENSION][TopPort__DEVICE_EXTENSION($deviceExtension$5$4614.28$MouseClassFindMorePorts$12) := Mem[T.P_DEVICE_OBJECT][TopPort__DEVICE_EXTENSION($deviceExtension$5$4614.28$MouseClassFindMorePorts$12)]];
+goto label_95;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(4731)
+label_95:
+$status$4$4613.28$MouseClassFindMorePorts$12 := $result.IoGetDeviceObjectPointer$4731.42$16$ ;
+goto label_96;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(4736)
+label_96:
+goto label_96_true , label_96_false ;
+
+
+label_96_true :
+assume ($status$4$4613.28$MouseClassFindMorePorts$12 != 0);
+goto label_97;
+
+
+label_96_false :
+assume ($status$4$4613.28$MouseClassFindMorePorts$12 == 0);
+goto label_108;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(4738)
+label_97:
+goto label_97_true , label_97_false ;
+
+
+label_97_true :
+assume (Mem[T.InputData__DEVICE_EXTENSION][InputData__DEVICE_EXTENSION($deviceExtension$5$4614.28$MouseClassFindMorePorts$12)] != 0);
+goto label_98;
+
+
+label_97_false :
+assume (Mem[T.InputData__DEVICE_EXTENSION][InputData__DEVICE_EXTENSION($deviceExtension$5$4614.28$MouseClassFindMorePorts$12)] == 0);
+goto label_104;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(4738)
+label_98:
+call ExFreePoolWithTag (Mem[T.InputData__DEVICE_EXTENSION][InputData__DEVICE_EXTENSION($deviceExtension$5$4614.28$MouseClassFindMorePorts$12)], 0);
+goto label_101;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(4738)
+label_101:
+Mem[T.DataOut__DEVICE_EXTENSION] := Mem[T.DataOut__DEVICE_EXTENSION][DataOut__DEVICE_EXTENSION($deviceExtension$5$4614.28$MouseClassFindMorePorts$12) := 0];
+goto label_102;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(4738)
+label_102:
+Mem[T.DataIn__DEVICE_EXTENSION] := Mem[T.DataIn__DEVICE_EXTENSION][DataIn__DEVICE_EXTENSION($deviceExtension$5$4614.28$MouseClassFindMorePorts$12) := Mem[T.DataOut__DEVICE_EXTENSION][DataOut__DEVICE_EXTENSION($deviceExtension$5$4614.28$MouseClassFindMorePorts$12)]];
+goto label_103;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(4738)
+label_103:
+Mem[T.InputData__DEVICE_EXTENSION] := Mem[T.InputData__DEVICE_EXTENSION][InputData__DEVICE_EXTENSION($deviceExtension$5$4614.28$MouseClassFindMorePorts$12) := Mem[T.DataIn__DEVICE_EXTENSION][DataIn__DEVICE_EXTENSION($deviceExtension$5$4614.28$MouseClassFindMorePorts$12)]];
+goto label_104;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(4738)
+label_104:
+call IoDeleteDevice (Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION($deviceExtension$5$4614.28$MouseClassFindMorePorts$12)]);
+goto label_107;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(4738)
+label_107:
+$deviceExtension$5$4614.28$MouseClassFindMorePorts$12 := 0 ;
+goto label_154;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(4742)
+label_108:
+Mem[T.StackSize__DEVICE_OBJECT] := Mem[T.StackSize__DEVICE_OBJECT][StackSize__DEVICE_OBJECT(Mem[T.P_DEVICE_OBJECT][$classDeviceObject$6$4615.28$MouseClassFindMorePorts$12]) := PLUS(1, 1, Mem[T.StackSize__DEVICE_OBJECT][StackSize__DEVICE_OBJECT(Mem[T.TopPort__DEVICE_EXTENSION][TopPort__DEVICE_EXTENSION($deviceExtension$5$4614.28$MouseClassFindMorePorts$12)])])];
+goto label_109;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(4743)
+label_109:
+call $result.MouseAddDeviceEx$4743.34$17$ := MouseAddDeviceEx ($deviceExtension$5$4614.28$MouseClassFindMorePorts$12, Mem[T.PUINT2][$fullClassName$14$4623.28$MouseClassFindMorePorts$12], Mem[T.P_FILE_OBJECT][$file$15$4624.28$MouseClassFindMorePorts$12]);
+goto label_112;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(4743)
+label_112:
+$status$4$4613.28$MouseClassFindMorePorts$12 := $result.MouseAddDeviceEx$4743.34$17$ ;
+goto label_113;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(4744)
+label_113:
+assume (forall r:int :: {BIT_BAND(BIT_BAND(Mem[T.Flags__DEVICE_OBJECT][Flags__DEVICE_OBJECT(Mem[T.P_DEVICE_OBJECT][$classDeviceObject$6$4615.28$MouseClassFindMorePorts$12])], BIT_BNOT(128)),r)} (POW2(r) && POW2(128) && r != 128) ==> (BIT_BAND(Mem[T.Flags__DEVICE_OBJECT][Flags__DEVICE_OBJECT(Mem[T.P_DEVICE_OBJECT][$classDeviceObject$6$4615.28$MouseClassFindMorePorts$12])],r)!= 0 <==> BIT_BAND(BIT_BAND(Mem[T.Flags__DEVICE_OBJECT][Flags__DEVICE_OBJECT(Mem[T.P_DEVICE_OBJECT][$classDeviceObject$6$4615.28$MouseClassFindMorePorts$12])], BIT_BNOT(128)),r)!= 0));
+assume (BIT_BAND(BIT_BAND(Mem[T.Flags__DEVICE_OBJECT][Flags__DEVICE_OBJECT(Mem[T.P_DEVICE_OBJECT][$classDeviceObject$6$4615.28$MouseClassFindMorePorts$12])], BIT_BNOT(128)),128) == 0);
+tempBoogie0 := BIT_BAND(Mem[T.Flags__DEVICE_OBJECT][Flags__DEVICE_OBJECT(Mem[T.P_DEVICE_OBJECT][$classDeviceObject$6$4615.28$MouseClassFindMorePorts$12])], BIT_BNOT(128)) ;
+Mem[T.Flags__DEVICE_OBJECT] := Mem[T.Flags__DEVICE_OBJECT][Flags__DEVICE_OBJECT(Mem[T.P_DEVICE_OBJECT][$classDeviceObject$6$4615.28$MouseClassFindMorePorts$12]) := tempBoogie0];
+goto label_114;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(4746)
+label_114:
+goto label_114_true , label_114_false ;
+
+
+label_114_true :
+assume (Mem[T.PUINT2][$fullClassName$14$4623.28$MouseClassFindMorePorts$12] != 0);
+goto label_115;
+
+
+label_114_false :
+assume (Mem[T.PUINT2][$fullClassName$14$4623.28$MouseClassFindMorePorts$12] == 0);
+goto label_119;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(4747)
+label_115:
+call ExFreePoolWithTag (Mem[T.PUINT2][$fullClassName$14$4623.28$MouseClassFindMorePorts$12], 0);
+goto label_118;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(4748)
+label_118:
+Mem[T.PUINT2] := Mem[T.PUINT2][$fullClassName$14$4623.28$MouseClassFindMorePorts$12 := 0];
+goto label_119;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(4751)
+label_119:
+goto label_119_true , label_119_false ;
+
+
+label_119_true :
+assume (0 <= $status$4$4613.28$MouseClassFindMorePorts$12);
+goto label_150;
+
+
+label_119_false :
+assume !(0 <= $status$4$4613.28$MouseClassFindMorePorts$12);
+goto label_120;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(4752)
+label_120:
+goto label_120_true , label_120_false ;
+
+
+label_120_true :
+assume (Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)] != 0);
+goto label_124;
+
+
+label_120_false :
+assume (Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)] == 0);
+goto label_121;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(4753)
+label_121:
+goto label_121_true , label_121_false ;
+
+
+label_121_true :
+assume (Mem[T.File__DEVICE_EXTENSION][File__DEVICE_EXTENSION($deviceExtension$5$4614.28$MouseClassFindMorePorts$12)] != 0);
+goto label_122;
+
+
+label_121_false :
+assume (Mem[T.File__DEVICE_EXTENSION][File__DEVICE_EXTENSION($deviceExtension$5$4614.28$MouseClassFindMorePorts$12)] == 0);
+goto label_135;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(4754)
+label_122:
+Mem[T.P_FILE_OBJECT] := Mem[T.P_FILE_OBJECT][$file$15$4624.28$MouseClassFindMorePorts$12 := Mem[T.File__DEVICE_EXTENSION][File__DEVICE_EXTENSION($deviceExtension$5$4614.28$MouseClassFindMorePorts$12)]];
+goto label_123;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(4755)
+label_123:
+Mem[T.File__DEVICE_EXTENSION] := Mem[T.File__DEVICE_EXTENSION][File__DEVICE_EXTENSION($deviceExtension$5$4614.28$MouseClassFindMorePorts$12) := 0];
+goto label_135;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(4759)
+label_124:
+goto label_125;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(4761)
+label_125:
+call ExAcquireFastMutex (Mutex__GLOBALS(Globals));
+goto label_128;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(4763)
+label_128:
+Mem[T.P_FILE_OBJECT] := Mem[T.P_FILE_OBJECT][$file$15$4624.28$MouseClassFindMorePorts$12 := Mem[T.File__PORT][File__PORT(PLUS(Mem[T.AssocClassList__GLOBALS][AssocClassList__GLOBALS(Globals)], 12, Mem[T.UnitId__DEVICE_EXTENSION][UnitId__DEVICE_EXTENSION($deviceExtension$5$4614.28$MouseClassFindMorePorts$12)]))]];
+goto label_129;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(4764)
+label_129:
+Mem[T.File__PORT] := Mem[T.File__PORT][File__PORT(PLUS(Mem[T.AssocClassList__GLOBALS][AssocClassList__GLOBALS(Globals)], 12, Mem[T.UnitId__DEVICE_EXTENSION][UnitId__DEVICE_EXTENSION($deviceExtension$5$4614.28$MouseClassFindMorePorts$12)])) := 0];
+goto label_130;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(4765)
+label_130:
+Mem[T.Free__PORT] := Mem[T.Free__PORT][Free__PORT(PLUS(Mem[T.AssocClassList__GLOBALS][AssocClassList__GLOBALS(Globals)], 12, Mem[T.UnitId__DEVICE_EXTENSION][UnitId__DEVICE_EXTENSION($deviceExtension$5$4614.28$MouseClassFindMorePorts$12)])) := 1];
+goto label_131;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(4766)
+label_131:
+Mem[T.Port__PORT] := Mem[T.Port__PORT][Port__PORT(PLUS(Mem[T.AssocClassList__GLOBALS][AssocClassList__GLOBALS(Globals)], 12, Mem[T.UnitId__DEVICE_EXTENSION][UnitId__DEVICE_EXTENSION($deviceExtension$5$4614.28$MouseClassFindMorePorts$12)])) := 0];
+goto label_132;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(4768)
+label_132:
+call ExReleaseFastMutex (Mutex__GLOBALS(Globals));
+goto label_135;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(4771)
+label_135:
+goto label_135_true , label_135_false ;
+
+
+label_135_true :
+assume (Mem[T.P_FILE_OBJECT][$file$15$4624.28$MouseClassFindMorePorts$12] != 0);
+goto label_136;
+
+
+label_135_false :
+assume (Mem[T.P_FILE_OBJECT][$file$15$4624.28$MouseClassFindMorePorts$12] == 0);
+goto label_139;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(4772)
+label_136:
+call $result.ObfDereferenceObject$4772.16$18$ := ObfDereferenceObject (Mem[T.P_FILE_OBJECT][$file$15$4624.28$MouseClassFindMorePorts$12]);
+goto label_139;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(4775)
+label_139:
+goto label_139_true , label_139_false ;
+
+
+label_139_true :
+assume (Mem[T.InputData__DEVICE_EXTENSION][InputData__DEVICE_EXTENSION($deviceExtension$5$4614.28$MouseClassFindMorePorts$12)] != 0);
+goto label_140;
+
+
+label_139_false :
+assume (Mem[T.InputData__DEVICE_EXTENSION][InputData__DEVICE_EXTENSION($deviceExtension$5$4614.28$MouseClassFindMorePorts$12)] == 0);
+goto label_146;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(4775)
+label_140:
+call ExFreePoolWithTag (Mem[T.InputData__DEVICE_EXTENSION][InputData__DEVICE_EXTENSION($deviceExtension$5$4614.28$MouseClassFindMorePorts$12)], 0);
+goto label_143;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(4775)
+label_143:
+Mem[T.DataOut__DEVICE_EXTENSION] := Mem[T.DataOut__DEVICE_EXTENSION][DataOut__DEVICE_EXTENSION($deviceExtension$5$4614.28$MouseClassFindMorePorts$12) := 0];
+goto label_144;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(4775)
+label_144:
+Mem[T.DataIn__DEVICE_EXTENSION] := Mem[T.DataIn__DEVICE_EXTENSION][DataIn__DEVICE_EXTENSION($deviceExtension$5$4614.28$MouseClassFindMorePorts$12) := Mem[T.DataOut__DEVICE_EXTENSION][DataOut__DEVICE_EXTENSION($deviceExtension$5$4614.28$MouseClassFindMorePorts$12)]];
+goto label_145;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(4775)
+label_145:
+Mem[T.InputData__DEVICE_EXTENSION] := Mem[T.InputData__DEVICE_EXTENSION][InputData__DEVICE_EXTENSION($deviceExtension$5$4614.28$MouseClassFindMorePorts$12) := Mem[T.DataIn__DEVICE_EXTENSION][DataIn__DEVICE_EXTENSION($deviceExtension$5$4614.28$MouseClassFindMorePorts$12)]];
+goto label_146;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(4775)
+label_146:
+call IoDeleteDevice (Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION($deviceExtension$5$4614.28$MouseClassFindMorePorts$12)]);
+goto label_149;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(4775)
+label_149:
+$deviceExtension$5$4614.28$MouseClassFindMorePorts$12 := 0 ;
+goto label_154;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(4782)
+label_150:
+call InsertTailList (LegacyDeviceList__GLOBALS(Globals), Link__DEVICE_EXTENSION($deviceExtension$5$4614.28$MouseClassFindMorePorts$12));
+goto label_153;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(4783)
+label_153:
+$successfulCreates$10$4619.28$MouseClassFindMorePorts$12 := PLUS($successfulCreates$10$4619.28$MouseClassFindMorePorts$12, 1, 1) ;
+goto label_154;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(4689)
+label_154:
+$i$8$4617.28$MouseClassFindMorePorts$12 := PLUS($i$8$4617.28$MouseClassFindMorePorts$12, 1, 1) ;
+goto label_74_head;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(4786)
+label_155:
+tempBoogie0 := PLUS(Mem[T.NumberLegacyPorts__GLOBALS][NumberLegacyPorts__GLOBALS(Globals)], 1, $successfulCreates$10$4619.28$MouseClassFindMorePorts$12) ;
+Mem[T.NumberLegacyPorts__GLOBALS] := Mem[T.NumberLegacyPorts__GLOBALS][NumberLegacyPorts__GLOBALS(Globals) := tempBoogie0];
+goto label_156;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(4792)
+label_156:
+goto label_156_true , label_156_false ;
+
+
+label_156_true :
+assume (Mem[T.Buffer__UNICODE_STRING][Buffer__UNICODE_STRING($fullPortName$12$4621.28$MouseClassFindMorePorts$12)] != 0);
+goto label_157;
+
+
+label_156_false :
+assume (Mem[T.Buffer__UNICODE_STRING][Buffer__UNICODE_STRING($fullPortName$12$4621.28$MouseClassFindMorePorts$12)] == 0);
+goto label_160;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(4793)
+label_157:
+call ExFreePoolWithTag (Mem[T.Buffer__UNICODE_STRING][Buffer__UNICODE_STRING($fullPortName$12$4621.28$MouseClassFindMorePorts$12)], 0);
+goto label_160;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(4796)
+label_160:
+goto label_160_true , label_160_false ;
+
+
+label_160_true :
+assume (Mem[T.PUINT2][$fullClassName$14$4623.28$MouseClassFindMorePorts$12] != 0);
+goto label_161;
+
+
+label_160_false :
+assume (Mem[T.PUINT2][$fullClassName$14$4623.28$MouseClassFindMorePorts$12] == 0);
+goto label_1;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(4797)
+label_161:
+call ExFreePoolWithTag (Mem[T.PUINT2][$fullClassName$14$4623.28$MouseClassFindMorePorts$12], 0);
+goto label_1;
+
+}
+
diff --git a/Test/havoc0/MouseClassUnload.bpl b/Test/havoc0/MouseClassUnload.bpl
new file mode 100644
index 00000000..87e31029
--- /dev/null
+++ b/Test/havoc0/MouseClassUnload.bpl
@@ -0,0 +1,3369 @@
+type byte, name;
+function OneByteToInt(byte) returns (int);
+function TwoBytesToInt(byte, byte) returns (int);
+function FourBytesToInt(byte, byte, byte, byte) returns (int);
+axiom(forall b0:byte, c0:byte :: {OneByteToInt(b0), OneByteToInt(c0)} OneByteToInt(b0) == OneByteToInt(c0) ==> b0 == c0);
+axiom(forall b0:byte, b1: byte, c0:byte, c1:byte :: {TwoBytesToInt(b0, b1), TwoBytesToInt(c0, c1)} TwoBytesToInt(b0, b1) == TwoBytesToInt(c0, c1) ==> b0 == c0 && b1 == c1);
+axiom(forall b0:byte, b1: byte, b2:byte, b3:byte, c0:byte, c1:byte, c2:byte, c3:byte :: {FourBytesToInt(b0, b1, b2, b3), FourBytesToInt(c0, c1, c2, c3)} FourBytesToInt(b0, b1, b2, b3) == FourBytesToInt(c0, c1, c2, c3) ==> b0 == c0 && b1 == c1 && b2 == c2 && b3 == c3);
+
+// Mutable
+var Mem_BYTE:[int]byte;
+var alloc:[int]name;
+
+
+function Field(int) returns (name);
+function Base(int) returns (int);
+
+// Constants
+const unique UNALLOCATED:name;
+const unique ALLOCATED: name;
+const unique FREED:name;
+
+const unique BYTE:name;
+
+function Equal([int]bool, [int]bool) returns (bool);
+function Subset([int]bool, [int]bool) returns (bool);
+function Disjoint([int]bool, [int]bool) returns (bool);
+
+function Empty() returns ([int]bool);
+function SetTrue() returns ([int]bool);
+function Singleton(int) returns ([int]bool);
+function Reachable([int,int]bool, int) returns ([int]bool);
+function Union([int]bool, [int]bool) returns ([int]bool);
+function Intersection([int]bool, [int]bool) returns ([int]bool);
+function Difference([int]bool, [int]bool) returns ([int]bool);
+function Dereference([int]bool, [int]int) returns ([int]bool);
+function Inverse(f:[int]int, x:int) returns ([int]bool);
+
+function AtLeast(int, int) returns ([int]bool);
+function Rep(int, int) returns (int);
+axiom(forall n:int, x:int, y:int :: {AtLeast(n,x)[y]} AtLeast(n,x)[y] ==> x <= y && Rep(n,x) == Rep(n,y));
+axiom(forall n:int, x:int, y:int :: {AtLeast(n,x),Rep(n,x),Rep(n,y)} x <= y && Rep(n,x) == Rep(n,y) ==> AtLeast(n,x)[y]);
+axiom(forall n:int, x:int :: {AtLeast(n,x)} AtLeast(n,x)[x]);
+axiom(forall n:int, x:int, z:int :: {PLUS(x,n,z)} Rep(n,x) == Rep(n,PLUS(x,n,z)));
+axiom(forall n:int, x:int :: {Rep(n,x)} (exists k:int :: Rep(n,x) - x == n*k));
+
+/*
+function AtLeast(int, int) returns ([int]bool);
+function ModEqual(int, int, int) returns (bool);
+axiom(forall n:int, x:int :: ModEqual(n,x,x));
+axiom(forall n:int, x:int, y:int :: {ModEqual(n,x,y)} ModEqual(n,x,y) ==> ModEqual(n,y,x));
+axiom(forall n:int, x:int, y:int, z:int :: {ModEqual(n,x,y), ModEqual(n,y,z)} ModEqual(n,x,y) && ModEqual(n,y,z) ==> ModEqual(n,x,z));
+axiom(forall n:int, x:int, z:int :: {PLUS(x,n,z)} ModEqual(n,x,PLUS(x,n,z)));
+axiom(forall n:int, x:int, y:int :: {ModEqual(n,x,y)} ModEqual(n,x,y) ==> (exists k:int :: x - y == n*k));
+axiom(forall x:int, n:int, y:int :: {AtLeast(n,x)[y]}{ModEqual(n,x,y)} AtLeast(n,x)[y] <==> x <= y && ModEqual(n,x,y));
+axiom(forall x:int, n:int :: {AtLeast(n,x)} AtLeast(n,x)[x]);
+*/
+
+function Array(int, int, int) returns ([int]bool);
+axiom(forall x:int, n:int, z:int :: {Array(x,n,z)} z <= 0 ==> Equal(Array(x,n,z), Empty()));
+axiom(forall x:int, n:int, z:int :: {Array(x,n,z)} z > 0 ==> Equal(Array(x,n,z), Difference(AtLeast(n,x),AtLeast(n,PLUS(x,n,z)))));
+
+
+axiom(forall x:int :: !Empty()[x]);
+
+axiom(forall x:int :: SetTrue()[x]);
+
+axiom(forall x:int, y:int :: {Singleton(y)[x]} Singleton(y)[x] <==> x == y);
+axiom(forall y:int :: {Singleton(y)} Singleton(y)[y]);
+
+/* this formulation of Union IS more complete than the earlier one */
+/* (A U B)[e], A[d], A U B = Singleton(c), d != e */
+axiom(forall x:int, S:[int]bool, T:[int]bool :: {Union(S,T)[x]}{Union(S,T),S[x]}{Union(S,T),T[x]} Union(S,T)[x] <==> S[x] || T[x]);
+axiom(forall x:int, S:[int]bool, T:[int]bool :: {Intersection(S,T)[x]}{Intersection(S,T),S[x]}{Intersection(S,T),T[x]} Intersection(S,T)[x] <==> S[x] && T[x]);
+axiom(forall x:int, S:[int]bool, T:[int]bool :: {Difference(S,T)[x]}{Difference(S,T),S[x]}{Difference(S,T),T[x]} Difference(S,T)[x] <==> S[x] && !T[x]);
+
+axiom(forall S:[int]bool, T:[int]bool :: {Equal(S,T)} Equal(S,T) <==> Subset(S,T) && Subset(T,S));
+axiom(forall x:int, S:[int]bool, T:[int]bool :: {S[x],Subset(S,T)}{T[x],Subset(S,T)} S[x] && Subset(S,T) ==> T[x]);
+axiom(forall S:[int]bool, T:[int]bool :: {Subset(S,T)} Subset(S,T) || (exists x:int :: S[x] && !T[x]));
+axiom(forall x:int, S:[int]bool, T:[int]bool :: {S[x],Disjoint(S,T)}{T[x],Disjoint(S,T)} !(S[x] && Disjoint(S,T) && T[x]));
+axiom(forall S:[int]bool, T:[int]bool :: {Disjoint(S,T)} Disjoint(S,T) || (exists x:int :: S[x] && T[x]));
+
+axiom(forall f:[int]int, x:int :: {Inverse(f,f[x])} Inverse(f,f[x])[x]);
+axiom(forall f:[int]int, x:int, y:int :: {Inverse(f,y), f[x]} Inverse(f,y)[x] ==> f[x] == y);
+axiom(forall f:[int]int, x:int, y:int :: {Inverse(f[x := y],y)} Equal(Inverse(f[x := y],y), Union(Inverse(f,y), Singleton(x))));
+axiom(forall f:[int]int, x:int, y:int, z:int :: {Inverse(f[x := y],z)} y == z || Equal(Inverse(f[x := y],z), Difference(Inverse(f,z), Singleton(x))));
+
+
+axiom(forall x:int, S:[int]bool, M:[int]int :: {Dereference(S,M)[x]} Dereference(S,M)[x] ==> (exists y:int :: x == M[y] && S[y]));
+axiom(forall x:int, S:[int]bool, M:[int]int :: {M[x], S[x], Dereference(S,M)} S[x] ==> Dereference(S,M)[M[x]]);
+axiom(forall x:int, y:int, S:[int]bool, M:[int]int :: {Dereference(S,M[x := y])} !S[x] ==> Equal(Dereference(S,M[x := y]), Dereference(S,M)));
+axiom(forall x:int, y:int, S:[int]bool, M:[int]int :: {Dereference(S,M[x := y])}
+ S[x] && Equal(Intersection(Inverse(M,M[x]), S), Singleton(x)) ==> Equal(Dereference(S,M[x := y]), Union(Difference(Dereference(S,M), Singleton(M[x])), Singleton(y))));
+axiom(forall x:int, y:int, S:[int]bool, M:[int]int :: {Dereference(S,M[x := y])}
+ S[x] && !Equal(Intersection(Inverse(M,M[x]), S), Singleton(x)) ==> Equal(Dereference(S,M[x := y]), Union(Dereference(S,M), Singleton(y))));
+
+function Unified([name][int]int) returns ([int]int);
+axiom(forall M:[name][int]int, x:int :: {Unified(M)[x]} Unified(M)[x] == M[Field(x)][x]);
+axiom(forall M:[name][int]int, x:int, y:int :: {Unified(M[Field(x) := M[Field(x)][x := y]])} Unified(M[Field(x) := M[Field(x)][x := y]]) == Unified(M)[x := y]);
+// Memory model
+
+var Mem: [name][int]int;
+
+function Match(a:int, t:name) returns (bool);
+function HasType(v:int, t:name, m:[name][int]int) returns (bool);
+function Values(t:name, m:[name][int]int) returns ([int]bool);
+function T.Ptr(t:name) returns (name);
+
+axiom(forall v:int, t:name, m:[name][int]int :: {Values(t, m)[v]} Values(t, m)[v] ==> HasType(v, t, m));
+axiom(forall v:int, t:name, m:[name][int]int :: {HasType(v, t, m), Values(t, m)} HasType(v, t, m) ==> Values(t, m)[v]);
+
+axiom(forall a:int, t:name :: {Match(a, T.Ptr(t))} Match(a, T.Ptr(t)) <==> Field(a) == T.Ptr(t));
+axiom(forall v:int, t:name, m:[name][int]int :: {HasType(v, T.Ptr(t), m)} HasType(v, T.Ptr(t), m) <==> (v == 0 || (v > 0 && Match(v, t))));
+
+axiom(forall v:int, t:name, m1:[name][int]int, m2:[name][int]int :: {HasType(v, t, m1), HasType(v, t, m2)}
+ (HasType(v, t, m1) <==> HasType(v, t, m2)));
+
+// Field declarations
+
+const unique T.Guid_WMIGUIDREGINFO:name;
+const unique T.InstanceCount_WMIGUIDREGINFO:name;
+const unique T.Flags_WMIGUIDREGINFO:name;
+const unique T.OperationID__ACCESS_STATE:name;
+const unique T.SecurityEvaluated__ACCESS_STATE:name;
+const unique T.GenerateAudit__ACCESS_STATE:name;
+const unique T.GenerateOnClose__ACCESS_STATE:name;
+const unique T.PrivilegesAllocated__ACCESS_STATE:name;
+const unique T.Flags__ACCESS_STATE:name;
+const unique T.RemainingDesiredAccess__ACCESS_STATE:name;
+const unique T.PreviouslyGrantedAccess__ACCESS_STATE:name;
+const unique T.OriginalDesiredAccess__ACCESS_STATE:name;
+const unique T.SubjectSecurityContext__ACCESS_STATE:name;
+const unique T.SecurityDescriptor__ACCESS_STATE:name;
+const unique T.AuxData__ACCESS_STATE:name;
+const unique T.Privileges__ACCESS_STATE:name;
+const unique T.AuditPrivileges__ACCESS_STATE:name;
+const unique T.ObjectName__ACCESS_STATE:name;
+const unique T.ObjectTypeName__ACCESS_STATE:name;
+const unique T.InterfaceType__CM_FULL_RESOURCE_DESCRIPTOR:name;
+const unique T.BusNumber__CM_FULL_RESOURCE_DESCRIPTOR:name;
+const unique T.PartialResourceList__CM_FULL_RESOURCE_DESCRIPTOR:name;
+const unique T.Type__CM_PARTIAL_RESOURCE_DESCRIPTOR:name;
+const unique T.ShareDisposition__CM_PARTIAL_RESOURCE_DESCRIPTOR:name;
+const unique T.Flags__CM_PARTIAL_RESOURCE_DESCRIPTOR:name;
+const unique T.u__CM_PARTIAL_RESOURCE_DESCRIPTOR:name;
+const unique T.Version__CM_PARTIAL_RESOURCE_LIST:name;
+const unique T.Revision__CM_PARTIAL_RESOURCE_LIST:name;
+const unique T.Count__CM_PARTIAL_RESOURCE_LIST:name;
+const unique T.PartialDescriptors__CM_PARTIAL_RESOURCE_LIST:name;
+const unique T.Count__CM_RESOURCE_LIST:name;
+const unique T.List__CM_RESOURCE_LIST:name;
+const unique T.Size__DEVICE_CAPABILITIES:name;
+const unique T.Version__DEVICE_CAPABILITIES:name;
+const unique T.DeviceD1__DEVICE_CAPABILITIES:name;
+const unique T.DeviceD2__DEVICE_CAPABILITIES:name;
+const unique T.LockSupported__DEVICE_CAPABILITIES:name;
+const unique T.EjectSupported__DEVICE_CAPABILITIES:name;
+const unique T.Removable__DEVICE_CAPABILITIES:name;
+const unique T.DockDevice__DEVICE_CAPABILITIES:name;
+const unique T.UniqueID__DEVICE_CAPABILITIES:name;
+const unique T.SilentInstall__DEVICE_CAPABILITIES:name;
+const unique T.RawDeviceOK__DEVICE_CAPABILITIES:name;
+const unique T.SurpriseRemovalOK__DEVICE_CAPABILITIES:name;
+const unique T.WakeFromD0__DEVICE_CAPABILITIES:name;
+const unique T.WakeFromD1__DEVICE_CAPABILITIES:name;
+const unique T.WakeFromD2__DEVICE_CAPABILITIES:name;
+const unique T.WakeFromD3__DEVICE_CAPABILITIES:name;
+const unique T.HardwareDisabled__DEVICE_CAPABILITIES:name;
+const unique T.NonDynamic__DEVICE_CAPABILITIES:name;
+const unique T.WarmEjectSupported__DEVICE_CAPABILITIES:name;
+const unique T.NoDisplayInUI__DEVICE_CAPABILITIES:name;
+const unique T.Reserved__DEVICE_CAPABILITIES:name;
+const unique T.Address__DEVICE_CAPABILITIES:name;
+const unique T.UINumber__DEVICE_CAPABILITIES:name;
+const unique T.DeviceState__DEVICE_CAPABILITIES:name;
+const unique T.SystemWake__DEVICE_CAPABILITIES:name;
+const unique T.DeviceWake__DEVICE_CAPABILITIES:name;
+const unique T.D1Latency__DEVICE_CAPABILITIES:name;
+const unique T.D2Latency__DEVICE_CAPABILITIES:name;
+const unique T.D3Latency__DEVICE_CAPABILITIES:name;
+const unique T.Self__DEVICE_EXTENSION:name;
+const unique T.TrueClassDevice__DEVICE_EXTENSION:name;
+const unique T.TopPort__DEVICE_EXTENSION:name;
+const unique T.PDO__DEVICE_EXTENSION:name;
+const unique T.RemoveLock__DEVICE_EXTENSION:name;
+const unique T.PnP__DEVICE_EXTENSION:name;
+const unique T.Started__DEVICE_EXTENSION:name;
+const unique T.OkayToLogOverflow__DEVICE_EXTENSION:name;
+const unique T.WaitWakeSpinLock__DEVICE_EXTENSION:name;
+const unique T.TrustedSubsystemCount__DEVICE_EXTENSION:name;
+const unique T.InputCount__DEVICE_EXTENSION:name;
+const unique T.SymbolicLinkName__DEVICE_EXTENSION:name;
+const unique T.InputData__DEVICE_EXTENSION:name;
+const unique T.DataIn__DEVICE_EXTENSION:name;
+const unique T.DataOut__DEVICE_EXTENSION:name;
+const unique T.MouseAttributes__DEVICE_EXTENSION:name;
+const unique T.SpinLock__DEVICE_EXTENSION:name;
+const unique T.ReadQueue__DEVICE_EXTENSION:name;
+const unique T.SequenceNumber__DEVICE_EXTENSION:name;
+const unique T.DeviceState__DEVICE_EXTENSION:name;
+const unique T.SystemState__DEVICE_EXTENSION:name;
+const unique T.UnitId__DEVICE_EXTENSION:name;
+const unique T.WmiLibInfo__DEVICE_EXTENSION:name;
+const unique T.SystemToDeviceState__DEVICE_EXTENSION:name;
+const unique T.MinDeviceWakeState__DEVICE_EXTENSION:name;
+const unique T.MinSystemWakeState__DEVICE_EXTENSION:name;
+const unique T.WaitWakeIrp__DEVICE_EXTENSION:name;
+const unique T.ExtraWaitWakeIrp__DEVICE_EXTENSION:name;
+const unique T.TargetNotifyHandle__DEVICE_EXTENSION:name;
+const unique T.Link__DEVICE_EXTENSION:name;
+const unique T.File__DEVICE_EXTENSION:name;
+const unique T.Enabled__DEVICE_EXTENSION:name;
+const unique T.WaitWakeEnabled__DEVICE_EXTENSION:name;
+const unique T.SurpriseRemoved__DEVICE_EXTENSION:name;
+const unique T.Type__DEVICE_OBJECT:name;
+const unique T.Size__DEVICE_OBJECT:name;
+const unique T.ReferenceCount__DEVICE_OBJECT:name;
+const unique T.DriverObject__DEVICE_OBJECT:name;
+const unique T.NextDevice__DEVICE_OBJECT:name;
+const unique T.AttachedDevice__DEVICE_OBJECT:name;
+const unique T.CurrentIrp__DEVICE_OBJECT:name;
+const unique T.Timer__DEVICE_OBJECT:name;
+const unique T.Flags__DEVICE_OBJECT:name;
+const unique T.Characteristics__DEVICE_OBJECT:name;
+const unique T.Vpb__DEVICE_OBJECT:name;
+const unique T.DeviceExtension__DEVICE_OBJECT:name;
+const unique T.DeviceType__DEVICE_OBJECT:name;
+const unique T.StackSize__DEVICE_OBJECT:name;
+const unique T.Queue__DEVICE_OBJECT:name;
+const unique T.AlignmentRequirement__DEVICE_OBJECT:name;
+const unique T.DeviceQueue__DEVICE_OBJECT:name;
+const unique T.Dpc__DEVICE_OBJECT:name;
+const unique T.ActiveThreadCount__DEVICE_OBJECT:name;
+const unique T.SecurityDescriptor__DEVICE_OBJECT:name;
+const unique T.DeviceLock__DEVICE_OBJECT:name;
+const unique T.SectorSize__DEVICE_OBJECT:name;
+const unique T.Spare1__DEVICE_OBJECT:name;
+const unique T.DeviceObjectExtension__DEVICE_OBJECT:name;
+const unique T.Reserved__DEVICE_OBJECT:name;
+const unique T.Type__DEVOBJ_EXTENSION:name;
+const unique T.Size__DEVOBJ_EXTENSION:name;
+const unique T.DeviceObject__DEVOBJ_EXTENSION:name;
+const unique T.__unnamed_4_c9b2e921__DISPATCHER_HEADER:name;
+const unique T.SignalState__DISPATCHER_HEADER:name;
+const unique T.WaitListHead__DISPATCHER_HEADER:name;
+const unique T.DriverObject__DRIVER_EXTENSION:name;
+const unique T.AddDevice__DRIVER_EXTENSION:name;
+const unique T.Count__DRIVER_EXTENSION:name;
+const unique T.ServiceKeyName__DRIVER_EXTENSION:name;
+const unique T.Type__DRIVER_OBJECT:name;
+const unique T.Size__DRIVER_OBJECT:name;
+const unique T.DeviceObject__DRIVER_OBJECT:name;
+const unique T.Flags__DRIVER_OBJECT:name;
+const unique T.DriverStart__DRIVER_OBJECT:name;
+const unique T.DriverSize__DRIVER_OBJECT:name;
+const unique T.DriverSection__DRIVER_OBJECT:name;
+const unique T.DriverExtension__DRIVER_OBJECT:name;
+const unique T.DriverName__DRIVER_OBJECT:name;
+const unique T.HardwareDatabase__DRIVER_OBJECT:name;
+const unique T.FastIoDispatch__DRIVER_OBJECT:name;
+const unique T.DriverInit__DRIVER_OBJECT:name;
+const unique T.DriverStartIo__DRIVER_OBJECT:name;
+const unique T.DriverUnload__DRIVER_OBJECT:name;
+const unique T.MajorFunction__DRIVER_OBJECT:name;
+const unique T.SystemResourcesList__ERESOURCE:name;
+const unique T.OwnerTable__ERESOURCE:name;
+const unique T.ActiveCount__ERESOURCE:name;
+const unique T.Flag__ERESOURCE:name;
+const unique T.SharedWaiters__ERESOURCE:name;
+const unique T.ExclusiveWaiters__ERESOURCE:name;
+const unique T.OwnerEntry__ERESOURCE:name;
+const unique T.ActiveEntries__ERESOURCE:name;
+const unique T.ContentionCount__ERESOURCE:name;
+const unique T.NumberOfSharedWaiters__ERESOURCE:name;
+const unique T.NumberOfExclusiveWaiters__ERESOURCE:name;
+const unique T.__unnamed_4_46b62f69__ERESOURCE:name;
+const unique T.SpinLock__ERESOURCE:name;
+const unique T.SizeOfFastIoDispatch__FAST_IO_DISPATCH:name;
+const unique T.FastIoCheckIfPossible__FAST_IO_DISPATCH:name;
+const unique T.FastIoRead__FAST_IO_DISPATCH:name;
+const unique T.FastIoWrite__FAST_IO_DISPATCH:name;
+const unique T.FastIoQueryBasicInfo__FAST_IO_DISPATCH:name;
+const unique T.FastIoQueryStandardInfo__FAST_IO_DISPATCH:name;
+const unique T.FastIoLock__FAST_IO_DISPATCH:name;
+const unique T.FastIoUnlockSingle__FAST_IO_DISPATCH:name;
+const unique T.FastIoUnlockAll__FAST_IO_DISPATCH:name;
+const unique T.FastIoUnlockAllByKey__FAST_IO_DISPATCH:name;
+const unique T.FastIoDeviceControl__FAST_IO_DISPATCH:name;
+const unique T.AcquireFileForNtCreateSection__FAST_IO_DISPATCH:name;
+const unique T.ReleaseFileForNtCreateSection__FAST_IO_DISPATCH:name;
+const unique T.FastIoDetachDevice__FAST_IO_DISPATCH:name;
+const unique T.FastIoQueryNetworkOpenInfo__FAST_IO_DISPATCH:name;
+const unique T.AcquireForModWrite__FAST_IO_DISPATCH:name;
+const unique T.MdlRead__FAST_IO_DISPATCH:name;
+const unique T.MdlReadComplete__FAST_IO_DISPATCH:name;
+const unique T.PrepareMdlWrite__FAST_IO_DISPATCH:name;
+const unique T.MdlWriteComplete__FAST_IO_DISPATCH:name;
+const unique T.FastIoReadCompressed__FAST_IO_DISPATCH:name;
+const unique T.FastIoWriteCompressed__FAST_IO_DISPATCH:name;
+const unique T.MdlReadCompleteCompressed__FAST_IO_DISPATCH:name;
+const unique T.MdlWriteCompleteCompressed__FAST_IO_DISPATCH:name;
+const unique T.FastIoQueryOpen__FAST_IO_DISPATCH:name;
+const unique T.ReleaseForModWrite__FAST_IO_DISPATCH:name;
+const unique T.AcquireForCcFlush__FAST_IO_DISPATCH:name;
+const unique T.ReleaseForCcFlush__FAST_IO_DISPATCH:name;
+const unique T.Count__FAST_MUTEX:name;
+const unique T.Owner__FAST_MUTEX:name;
+const unique T.Contention__FAST_MUTEX:name;
+const unique T.Gate__FAST_MUTEX:name;
+const unique T.OldIrql__FAST_MUTEX:name;
+const unique T.CreationTime__FILE_BASIC_INFORMATION:name;
+const unique T.LastAccessTime__FILE_BASIC_INFORMATION:name;
+const unique T.LastWriteTime__FILE_BASIC_INFORMATION:name;
+const unique T.ChangeTime__FILE_BASIC_INFORMATION:name;
+const unique T.FileAttributes__FILE_BASIC_INFORMATION:name;
+const unique T.CreationTime__FILE_NETWORK_OPEN_INFORMATION:name;
+const unique T.LastAccessTime__FILE_NETWORK_OPEN_INFORMATION:name;
+const unique T.LastWriteTime__FILE_NETWORK_OPEN_INFORMATION:name;
+const unique T.ChangeTime__FILE_NETWORK_OPEN_INFORMATION:name;
+const unique T.AllocationSize__FILE_NETWORK_OPEN_INFORMATION:name;
+const unique T.EndOfFile__FILE_NETWORK_OPEN_INFORMATION:name;
+const unique T.FileAttributes__FILE_NETWORK_OPEN_INFORMATION:name;
+const unique T.Type__FILE_OBJECT:name;
+const unique T.Size__FILE_OBJECT:name;
+const unique T.DeviceObject__FILE_OBJECT:name;
+const unique T.Vpb__FILE_OBJECT:name;
+const unique T.FsContext__FILE_OBJECT:name;
+const unique T.FsContext2__FILE_OBJECT:name;
+const unique T.SectionObjectPointer__FILE_OBJECT:name;
+const unique T.PrivateCacheMap__FILE_OBJECT:name;
+const unique T.FinalStatus__FILE_OBJECT:name;
+const unique T.RelatedFileObject__FILE_OBJECT:name;
+const unique T.LockOperation__FILE_OBJECT:name;
+const unique T.DeletePending__FILE_OBJECT:name;
+const unique T.ReadAccess__FILE_OBJECT:name;
+const unique T.WriteAccess__FILE_OBJECT:name;
+const unique T.DeleteAccess__FILE_OBJECT:name;
+const unique T.SharedRead__FILE_OBJECT:name;
+const unique T.SharedWrite__FILE_OBJECT:name;
+const unique T.SharedDelete__FILE_OBJECT:name;
+const unique T.Flags__FILE_OBJECT:name;
+const unique T.FileName__FILE_OBJECT:name;
+const unique T.CurrentByteOffset__FILE_OBJECT:name;
+const unique T.Waiters__FILE_OBJECT:name;
+const unique T.Busy__FILE_OBJECT:name;
+const unique T.LastLock__FILE_OBJECT:name;
+const unique T.Lock__FILE_OBJECT:name;
+const unique T.Event__FILE_OBJECT:name;
+const unique T.CompletionContext__FILE_OBJECT:name;
+const unique T.IrpListLock__FILE_OBJECT:name;
+const unique T.IrpList__FILE_OBJECT:name;
+const unique T.FileObjectExtension__FILE_OBJECT:name;
+const unique T.AllocationSize__FILE_STANDARD_INFORMATION:name;
+const unique T.EndOfFile__FILE_STANDARD_INFORMATION:name;
+const unique T.NumberOfLinks__FILE_STANDARD_INFORMATION:name;
+const unique T.DeletePending__FILE_STANDARD_INFORMATION:name;
+const unique T.Directory__FILE_STANDARD_INFORMATION:name;
+const unique T.Debug__GLOBALS:name;
+const unique T.GrandMaster__GLOBALS:name;
+const unique T.AssocClassList__GLOBALS:name;
+const unique T.NumAssocClass__GLOBALS:name;
+const unique T.Opens__GLOBALS:name;
+const unique T.NumberLegacyPorts__GLOBALS:name;
+const unique T.Mutex__GLOBALS:name;
+const unique T.ConnectOneClassToOnePort__GLOBALS:name;
+const unique T.PortsServiced__GLOBALS:name;
+const unique T.InitExtension__GLOBALS:name;
+const unique T.RegistryPath__GLOBALS:name;
+const unique T.BaseClassName__GLOBALS:name;
+const unique T.BaseClassBuffer__GLOBALS:name;
+const unique T.LegacyDeviceList__GLOBALS:name;
+const unique T.Data1__GUID:name;
+const unique T.Data2__GUID:name;
+const unique T.Data3__GUID:name;
+const unique T.Data4__GUID:name;
+const unique T.PrivilegeCount__INITIAL_PRIVILEGE_SET:name;
+const unique T.Control__INITIAL_PRIVILEGE_SET:name;
+const unique T.Privilege__INITIAL_PRIVILEGE_SET:name;
+const unique T.Size__INTERFACE:name;
+const unique T.Version__INTERFACE:name;
+const unique T.Context__INTERFACE:name;
+const unique T.InterfaceReference__INTERFACE:name;
+const unique T.InterfaceDereference__INTERFACE:name;
+const unique T.Port__IO_COMPLETION_CONTEXT:name;
+const unique T.Key__IO_COMPLETION_CONTEXT:name;
+const unique T.Common__IO_REMOVE_LOCK:name;
+const unique T.Dbg__IO_REMOVE_LOCK:name;
+const unique T.Removed__IO_REMOVE_LOCK_COMMON_BLOCK:name;
+const unique T.Reserved__IO_REMOVE_LOCK_COMMON_BLOCK:name;
+const unique T.IoCount__IO_REMOVE_LOCK_COMMON_BLOCK:name;
+const unique T.RemoveEvent__IO_REMOVE_LOCK_COMMON_BLOCK:name;
+const unique T.Signature__IO_REMOVE_LOCK_DBG_BLOCK:name;
+const unique T.HighWatermark__IO_REMOVE_LOCK_DBG_BLOCK:name;
+const unique T.MaxLockedTicks__IO_REMOVE_LOCK_DBG_BLOCK:name;
+const unique T.AllocateTag__IO_REMOVE_LOCK_DBG_BLOCK:name;
+const unique T.LockList__IO_REMOVE_LOCK_DBG_BLOCK:name;
+const unique T.Spin__IO_REMOVE_LOCK_DBG_BLOCK:name;
+const unique T.LowMemoryCount__IO_REMOVE_LOCK_DBG_BLOCK:name;
+const unique T.Reserved1__IO_REMOVE_LOCK_DBG_BLOCK:name;
+const unique T.Reserved2__IO_REMOVE_LOCK_DBG_BLOCK:name;
+const unique T.Blocks__IO_REMOVE_LOCK_DBG_BLOCK:name;
+const unique T.Option__IO_RESOURCE_DESCRIPTOR:name;
+const unique T.Type__IO_RESOURCE_DESCRIPTOR:name;
+const unique T.ShareDisposition__IO_RESOURCE_DESCRIPTOR:name;
+const unique T.Spare1__IO_RESOURCE_DESCRIPTOR:name;
+const unique T.Flags__IO_RESOURCE_DESCRIPTOR:name;
+const unique T.Spare2__IO_RESOURCE_DESCRIPTOR:name;
+const unique T.u__IO_RESOURCE_DESCRIPTOR:name;
+const unique T.Version__IO_RESOURCE_LIST:name;
+const unique T.Revision__IO_RESOURCE_LIST:name;
+const unique T.Count__IO_RESOURCE_LIST:name;
+const unique T.Descriptors__IO_RESOURCE_LIST:name;
+const unique T.ListSize__IO_RESOURCE_REQUIREMENTS_LIST:name;
+const unique T.InterfaceType__IO_RESOURCE_REQUIREMENTS_LIST:name;
+const unique T.BusNumber__IO_RESOURCE_REQUIREMENTS_LIST:name;
+const unique T.SlotNumber__IO_RESOURCE_REQUIREMENTS_LIST:name;
+const unique T.Reserved__IO_RESOURCE_REQUIREMENTS_LIST:name;
+const unique T.AlternativeLists__IO_RESOURCE_REQUIREMENTS_LIST:name;
+const unique T.List__IO_RESOURCE_REQUIREMENTS_LIST:name;
+const unique T.SecurityQos__IO_SECURITY_CONTEXT:name;
+const unique T.AccessState__IO_SECURITY_CONTEXT:name;
+const unique T.DesiredAccess__IO_SECURITY_CONTEXT:name;
+const unique T.FullCreateOptions__IO_SECURITY_CONTEXT:name;
+const unique T.MajorFunction__IO_STACK_LOCATION:name;
+const unique T.MinorFunction__IO_STACK_LOCATION:name;
+const unique T.Flags__IO_STACK_LOCATION:name;
+const unique T.Control__IO_STACK_LOCATION:name;
+const unique T.Parameters__IO_STACK_LOCATION:name;
+const unique T.DeviceObject__IO_STACK_LOCATION:name;
+const unique T.FileObject__IO_STACK_LOCATION:name;
+const unique T.CompletionRoutine__IO_STACK_LOCATION:name;
+const unique T.Context__IO_STACK_LOCATION:name;
+const unique T.__unnamed_4_16aff58e__IO_STATUS_BLOCK:name;
+const unique T.Information__IO_STATUS_BLOCK:name;
+const unique T.Type__IRP:name;
+const unique T.Size__IRP:name;
+const unique T.MdlAddress__IRP:name;
+const unique T.Flags__IRP:name;
+const unique T.AssociatedIrp__IRP:name;
+const unique T.ThreadListEntry__IRP:name;
+const unique T.IoStatus__IRP:name;
+const unique T.RequestorMode__IRP:name;
+const unique T.PendingReturned__IRP:name;
+const unique T.StackCount__IRP:name;
+const unique T.CurrentLocation__IRP:name;
+const unique T.Cancel__IRP:name;
+const unique T.CancelIrql__IRP:name;
+const unique T.ApcEnvironment__IRP:name;
+const unique T.AllocationFlags__IRP:name;
+const unique T.UserIosb__IRP:name;
+const unique T.UserEvent__IRP:name;
+const unique T.Overlay__IRP:name;
+const unique T.CancelRoutine__IRP:name;
+const unique T.UserBuffer__IRP:name;
+const unique T.Tail__IRP:name;
+const unique T.Type__KAPC:name;
+const unique T.SpareByte0__KAPC:name;
+const unique T.Size__KAPC:name;
+const unique T.SpareByte1__KAPC:name;
+const unique T.SpareLong0__KAPC:name;
+const unique T.Thread__KAPC:name;
+const unique T.ApcListEntry__KAPC:name;
+const unique T.KernelRoutine__KAPC:name;
+const unique T.RundownRoutine__KAPC:name;
+const unique T.NormalRoutine__KAPC:name;
+const unique T.NormalContext__KAPC:name;
+const unique T.SystemArgument1__KAPC:name;
+const unique T.SystemArgument2__KAPC:name;
+const unique T.ApcStateIndex__KAPC:name;
+const unique T.ApcMode__KAPC:name;
+const unique T.Inserted__KAPC:name;
+const unique T.Type__KDEVICE_QUEUE:name;
+const unique T.Size__KDEVICE_QUEUE:name;
+const unique T.DeviceListHead__KDEVICE_QUEUE:name;
+const unique T.Lock__KDEVICE_QUEUE:name;
+const unique T.Busy__KDEVICE_QUEUE:name;
+const unique T.DeviceListEntry__KDEVICE_QUEUE_ENTRY:name;
+const unique T.SortKey__KDEVICE_QUEUE_ENTRY:name;
+const unique T.Inserted__KDEVICE_QUEUE_ENTRY:name;
+const unique T.Type__KDPC:name;
+const unique T.Importance__KDPC:name;
+const unique T.Number__KDPC:name;
+const unique T.DpcListEntry__KDPC:name;
+const unique T.DeferredRoutine__KDPC:name;
+const unique T.DeferredContext__KDPC:name;
+const unique T.SystemArgument1__KDPC:name;
+const unique T.SystemArgument2__KDPC:name;
+const unique T.DpcData__KDPC:name;
+const unique T.Header__KEVENT:name;
+const unique T.Header__KSEMAPHORE:name;
+const unique T.Limit__KSEMAPHORE:name;
+const unique T.__unnamed_8_8684a3e7__LARGE_INTEGER:name;
+const unique T.u__LARGE_INTEGER:name;
+const unique T.QuadPart__LARGE_INTEGER:name;
+const unique T.Flink__LIST_ENTRY:name;
+const unique T.Blink__LIST_ENTRY:name;
+const unique T.LowPart__LUID:name;
+const unique T.HighPart__LUID:name;
+const unique T.Luid__LUID_AND_ATTRIBUTES:name;
+const unique T.Attributes__LUID_AND_ATTRIBUTES:name;
+const unique T.Next__MDL:name;
+const unique T.Size__MDL:name;
+const unique T.MdlFlags__MDL:name;
+const unique T.Process__MDL:name;
+const unique T.MappedSystemVa__MDL:name;
+const unique T.StartVa__MDL:name;
+const unique T.ByteCount__MDL:name;
+const unique T.ByteOffset__MDL:name;
+const unique T.MouseIdentifier__MOUSE_ATTRIBUTES:name;
+const unique T.NumberOfButtons__MOUSE_ATTRIBUTES:name;
+const unique T.SampleRate__MOUSE_ATTRIBUTES:name;
+const unique T.InputDataQueueLength__MOUSE_ATTRIBUTES:name;
+const unique T.UnitId__MOUSE_INPUT_DATA:name;
+const unique T.Flags__MOUSE_INPUT_DATA:name;
+const unique T.__unnamed_4_9c11ed91__MOUSE_INPUT_DATA:name;
+const unique T.RawButtons__MOUSE_INPUT_DATA:name;
+const unique T.LastX__MOUSE_INPUT_DATA:name;
+const unique T.LastY__MOUSE_INPUT_DATA:name;
+const unique T.ExtraInformation__MOUSE_INPUT_DATA:name;
+const unique T.OwnerThread__OWNER_ENTRY:name;
+const unique T.__unnamed_4_c1e23b02__OWNER_ENTRY:name;
+const unique T.File__PORT:name;
+const unique T.Port__PORT:name;
+const unique T.Enabled__PORT:name;
+const unique T.Reserved__PORT:name;
+const unique T.Free__PORT:name;
+const unique T.SequenceD1__POWER_SEQUENCE:name;
+const unique T.SequenceD2__POWER_SEQUENCE:name;
+const unique T.SequenceD3__POWER_SEQUENCE:name;
+const unique T.SystemState__POWER_STATE:name;
+const unique T.DeviceState__POWER_STATE:name;
+const unique T.PrivilegeCount__PRIVILEGE_SET:name;
+const unique T.Control__PRIVILEGE_SET:name;
+const unique T.Privilege__PRIVILEGE_SET:name;
+const unique T.DataSectionObject__SECTION_OBJECT_POINTERS:name;
+const unique T.SharedCacheMap__SECTION_OBJECT_POINTERS:name;
+const unique T.ImageSectionObject__SECTION_OBJECT_POINTERS:name;
+const unique T.Length__SECURITY_QUALITY_OF_SERVICE:name;
+const unique T.ImpersonationLevel__SECURITY_QUALITY_OF_SERVICE:name;
+const unique T.ContextTrackingMode__SECURITY_QUALITY_OF_SERVICE:name;
+const unique T.EffectiveOnly__SECURITY_QUALITY_OF_SERVICE:name;
+const unique T.ClientToken__SECURITY_SUBJECT_CONTEXT:name;
+const unique T.ImpersonationLevel__SECURITY_SUBJECT_CONTEXT:name;
+const unique T.PrimaryToken__SECURITY_SUBJECT_CONTEXT:name;
+const unique T.ProcessAuditId__SECURITY_SUBJECT_CONTEXT:name;
+const unique T.__unnamed_4_b4f5a780__SYSTEM_POWER_STATE_CONTEXT:name;
+const unique T.Length__UNICODE_STRING:name;
+const unique T.MaximumLength__UNICODE_STRING:name;
+const unique T.Buffer__UNICODE_STRING:name;
+const unique T.Type__VPB:name;
+const unique T.Size__VPB:name;
+const unique T.Flags__VPB:name;
+const unique T.VolumeLabelLength__VPB:name;
+const unique T.DeviceObject__VPB:name;
+const unique T.RealDevice__VPB:name;
+const unique T.SerialNumber__VPB:name;
+const unique T.ReferenceCount__VPB:name;
+const unique T.VolumeLabel__VPB:name;
+const unique T.WaitQueueEntry__WAIT_CONTEXT_BLOCK:name;
+const unique T.DeviceRoutine__WAIT_CONTEXT_BLOCK:name;
+const unique T.DeviceContext__WAIT_CONTEXT_BLOCK:name;
+const unique T.NumberOfMapRegisters__WAIT_CONTEXT_BLOCK:name;
+const unique T.DeviceObject__WAIT_CONTEXT_BLOCK:name;
+const unique T.CurrentIrp__WAIT_CONTEXT_BLOCK:name;
+const unique T.BufferChainingDpc__WAIT_CONTEXT_BLOCK:name;
+const unique T.GuidCount__WMILIB_CONTEXT:name;
+const unique T.GuidList__WMILIB_CONTEXT:name;
+const unique T.QueryWmiRegInfo__WMILIB_CONTEXT:name;
+const unique T.QueryWmiDataBlock__WMILIB_CONTEXT:name;
+const unique T.SetWmiDataBlock__WMILIB_CONTEXT:name;
+const unique T.SetWmiDataItem__WMILIB_CONTEXT:name;
+const unique T.ExecuteWmiMethod__WMILIB_CONTEXT:name;
+const unique T.WmiFunctionControl__WMILIB_CONTEXT:name;
+const unique T.Start___unnamed_12_06b9ee6e:name;
+const unique T.Length48___unnamed_12_06b9ee6e:name;
+const unique T.Start___unnamed_12_0882bd02:name;
+const unique T.Length64___unnamed_12_0882bd02:name;
+const unique T.__unnamed_12_2e80217b___unnamed_12_264d0dab:name;
+const unique T.Raw___unnamed_12_2e80217b:name;
+const unique T.Translated___unnamed_12_2e80217b:name;
+const unique T.Data___unnamed_12_5cc7ace2:name;
+const unique T.Channel___unnamed_12_6374506e:name;
+const unique T.Port___unnamed_12_6374506e:name;
+const unique T.Reserved1___unnamed_12_6374506e:name;
+const unique T.Priority___unnamed_12_68a4278e:name;
+const unique T.Reserved1___unnamed_12_68a4278e:name;
+const unique T.Reserved2___unnamed_12_68a4278e:name;
+const unique T.Generic___unnamed_12_79ed2653:name;
+const unique T.Port___unnamed_12_79ed2653:name;
+const unique T.Interrupt___unnamed_12_79ed2653:name;
+const unique T.MessageInterrupt___unnamed_12_79ed2653:name;
+const unique T.Memory___unnamed_12_79ed2653:name;
+const unique T.Dma___unnamed_12_79ed2653:name;
+const unique T.DevicePrivate___unnamed_12_79ed2653:name;
+const unique T.BusNumber___unnamed_12_79ed2653:name;
+const unique T.DeviceSpecificData___unnamed_12_79ed2653:name;
+const unique T.Memory40___unnamed_12_79ed2653:name;
+const unique T.Memory48___unnamed_12_79ed2653:name;
+const unique T.Memory64___unnamed_12_79ed2653:name;
+const unique T.Start___unnamed_12_7da594c0:name;
+const unique T.Length40___unnamed_12_7da594c0:name;
+const unique T.Start___unnamed_12_9873e05d:name;
+const unique T.Length___unnamed_12_9873e05d:name;
+const unique T.DataSize___unnamed_12_9cc8cebc:name;
+const unique T.Reserved1___unnamed_12_9cc8cebc:name;
+const unique T.Reserved2___unnamed_12_9cc8cebc:name;
+const unique T.Start___unnamed_12_b98da82e:name;
+const unique T.Length___unnamed_12_b98da82e:name;
+const unique T.Level___unnamed_12_c2880e88:name;
+const unique T.Vector___unnamed_12_c2880e88:name;
+const unique T.Affinity___unnamed_12_c2880e88:name;
+const unique T.Start___unnamed_12_c49ab31a:name;
+const unique T.Length___unnamed_12_c49ab31a:name;
+const unique T.ListEntry___unnamed_12_c6ed93f3:name;
+const unique T.__unnamed_4_a7aa989c___unnamed_12_c6ed93f3:name;
+const unique T.Data___unnamed_12_ced61554:name;
+const unique T.Reserved___unnamed_12_d9c44df5:name;
+const unique T.MessageCount___unnamed_12_d9c44df5:name;
+const unique T.Vector___unnamed_12_d9c44df5:name;
+const unique T.Affinity___unnamed_12_d9c44df5:name;
+const unique T.Start___unnamed_12_db3dcbfc:name;
+const unique T.Length___unnamed_12_db3dcbfc:name;
+const unique T.Reserved___unnamed_12_db3dcbfc:name;
+const unique T.Level___unnamed_12_fb26b3fc:name;
+const unique T.Vector___unnamed_12_fb26b3fc:name;
+const unique T.Affinity___unnamed_12_fb26b3fc:name;
+const unique T.OutputBufferLength___unnamed_16_22e4d054:name;
+const unique T.InputBufferLength___unnamed_16_22e4d054:name;
+const unique T.IoControlCode___unnamed_16_22e4d054:name;
+const unique T.Type3InputBuffer___unnamed_16_22e4d054:name;
+const unique T.Create___unnamed_16_39b626ad:name;
+const unique T.Read___unnamed_16_39b626ad:name;
+const unique T.Write___unnamed_16_39b626ad:name;
+const unique T.QueryDirectory___unnamed_16_39b626ad:name;
+const unique T.NotifyDirectory___unnamed_16_39b626ad:name;
+const unique T.QueryFile___unnamed_16_39b626ad:name;
+const unique T.SetFile___unnamed_16_39b626ad:name;
+const unique T.QueryEa___unnamed_16_39b626ad:name;
+const unique T.SetEa___unnamed_16_39b626ad:name;
+const unique T.QueryVolume___unnamed_16_39b626ad:name;
+const unique T.SetVolume___unnamed_16_39b626ad:name;
+const unique T.FileSystemControl___unnamed_16_39b626ad:name;
+const unique T.LockControl___unnamed_16_39b626ad:name;
+const unique T.DeviceIoControl___unnamed_16_39b626ad:name;
+const unique T.QuerySecurity___unnamed_16_39b626ad:name;
+const unique T.SetSecurity___unnamed_16_39b626ad:name;
+const unique T.MountVolume___unnamed_16_39b626ad:name;
+const unique T.VerifyVolume___unnamed_16_39b626ad:name;
+const unique T.Scsi___unnamed_16_39b626ad:name;
+const unique T.QueryQuota___unnamed_16_39b626ad:name;
+const unique T.SetQuota___unnamed_16_39b626ad:name;
+const unique T.QueryDeviceRelations___unnamed_16_39b626ad:name;
+const unique T.QueryInterface___unnamed_16_39b626ad:name;
+const unique T.DeviceCapabilities___unnamed_16_39b626ad:name;
+const unique T.FilterResourceRequirements___unnamed_16_39b626ad:name;
+const unique T.ReadWriteConfig___unnamed_16_39b626ad:name;
+const unique T.SetLock___unnamed_16_39b626ad:name;
+const unique T.QueryId___unnamed_16_39b626ad:name;
+const unique T.QueryDeviceText___unnamed_16_39b626ad:name;
+const unique T.UsageNotification___unnamed_16_39b626ad:name;
+const unique T.WaitWake___unnamed_16_39b626ad:name;
+const unique T.PowerSequence___unnamed_16_39b626ad:name;
+const unique T.Power___unnamed_16_39b626ad:name;
+const unique T.StartDevice___unnamed_16_39b626ad:name;
+const unique T.WMI___unnamed_16_39b626ad:name;
+const unique T.Others___unnamed_16_39b626ad:name;
+const unique T.WhichSpace___unnamed_16_56c011d7:name;
+const unique T.Buffer___unnamed_16_56c011d7:name;
+const unique T.Offset___unnamed_16_56c011d7:name;
+const unique T.Length___unnamed_16_56c011d7:name;
+const unique T.DeviceQueueEntry___unnamed_16_5fed8f23:name;
+const unique T.__unnamed_16_ae643f17___unnamed_16_5fed8f23:name;
+const unique T.Length___unnamed_16_6be9abe0:name;
+const unique T.FileName___unnamed_16_6be9abe0:name;
+const unique T.FileInformationClass___unnamed_16_6be9abe0:name;
+const unique T.FileIndex___unnamed_16_6be9abe0:name;
+const unique T.InterfaceType___unnamed_16_78879a38:name;
+const unique T.Size___unnamed_16_78879a38:name;
+const unique T.Version___unnamed_16_78879a38:name;
+const unique T.Interface___unnamed_16_78879a38:name;
+const unique T.InterfaceSpecificData___unnamed_16_78879a38:name;
+const unique T.Length___unnamed_16_804a2f24:name;
+const unique T.StartSid___unnamed_16_804a2f24:name;
+const unique T.SidList___unnamed_16_804a2f24:name;
+const unique T.SidListLength___unnamed_16_804a2f24:name;
+const unique T.Argument1___unnamed_16_8586693f:name;
+const unique T.Argument2___unnamed_16_8586693f:name;
+const unique T.Argument3___unnamed_16_8586693f:name;
+const unique T.Argument4___unnamed_16_8586693f:name;
+const unique T.Length___unnamed_16_8831e65f:name;
+const unique T.Key___unnamed_16_8831e65f:name;
+const unique T.ByteOffset___unnamed_16_8831e65f:name;
+const unique T.SecurityContext___unnamed_16_8c2d663a:name;
+const unique T.Options___unnamed_16_8c2d663a:name;
+const unique T.FileAttributes___unnamed_16_8c2d663a:name;
+const unique T.ShareAccess___unnamed_16_8c2d663a:name;
+const unique T.EaLength___unnamed_16_8c2d663a:name;
+const unique T.Length___unnamed_16_913b9a7a:name;
+const unique T.Key___unnamed_16_913b9a7a:name;
+const unique T.ByteOffset___unnamed_16_913b9a7a:name;
+const unique T.OutputBufferLength___unnamed_16_94d1d1c7:name;
+const unique T.InputBufferLength___unnamed_16_94d1d1c7:name;
+const unique T.FsControlCode___unnamed_16_94d1d1c7:name;
+const unique T.Type3InputBuffer___unnamed_16_94d1d1c7:name;
+const unique T.Length___unnamed_16_a2fab4da:name;
+const unique T.FileInformationClass___unnamed_16_a2fab4da:name;
+const unique T.FileObject___unnamed_16_a2fab4da:name;
+const unique T.__unnamed_4_a7d0864c___unnamed_16_a2fab4da:name;
+const unique T.DriverContext___unnamed_16_ae643f17:name;
+const unique T.Length___unnamed_16_c1b29316:name;
+const unique T.Key___unnamed_16_c1b29316:name;
+const unique T.ByteOffset___unnamed_16_c1b29316:name;
+const unique T.ProviderId___unnamed_16_cbd53ed4:name;
+const unique T.DataPath___unnamed_16_cbd53ed4:name;
+const unique T.BufferSize___unnamed_16_cbd53ed4:name;
+const unique T.Buffer___unnamed_16_cbd53ed4:name;
+const unique T.Length___unnamed_16_db70db6e:name;
+const unique T.MinBusNumber___unnamed_16_db70db6e:name;
+const unique T.MaxBusNumber___unnamed_16_db70db6e:name;
+const unique T.Reserved___unnamed_16_db70db6e:name;
+const unique T.Length___unnamed_16_ef4b6307:name;
+const unique T.EaList___unnamed_16_ef4b6307:name;
+const unique T.EaListLength___unnamed_16_ef4b6307:name;
+const unique T.EaIndex___unnamed_16_ef4b6307:name;
+const unique T.__unnamed_4_b060dea6___unnamed_16_fdda1f62:name;
+const unique T.Type___unnamed_16_fdda1f62:name;
+const unique T.State___unnamed_16_fdda1f62:name;
+const unique T.ShutdownType___unnamed_16_fdda1f62:name;
+const unique T.Lock___unnamed_1_1394de4b:name;
+const unique T.Abandoned___unnamed_1_2bb39c56:name;
+const unique T.Absolute___unnamed_1_2bb39c56:name;
+const unique T.NpxIrql___unnamed_1_2bb39c56:name;
+const unique T.Signalling___unnamed_1_2bb39c56:name;
+const unique T.Inserted___unnamed_1_9fa0583a:name;
+const unique T.DebugActive___unnamed_1_9fa0583a:name;
+const unique T.DpcActive___unnamed_1_9fa0583a:name;
+const unique T.Size___unnamed_1_e30779f5:name;
+const unique T.Hand___unnamed_1_e30779f5:name;
+const unique T.MinimumVector___unnamed_20_83d468e4:name;
+const unique T.MaximumVector___unnamed_20_83d468e4:name;
+const unique T.AffinityPolicy___unnamed_20_83d468e4:name;
+const unique T.PriorityPolicy___unnamed_20_83d468e4:name;
+const unique T.TargetedProcessors___unnamed_20_83d468e4:name;
+const unique T.Length40___unnamed_24_035931da:name;
+const unique T.Alignment40___unnamed_24_035931da:name;
+const unique T.MinimumAddress___unnamed_24_035931da:name;
+const unique T.MaximumAddress___unnamed_24_035931da:name;
+const unique T.Length___unnamed_24_38e128db:name;
+const unique T.Alignment___unnamed_24_38e128db:name;
+const unique T.MinimumAddress___unnamed_24_38e128db:name;
+const unique T.MaximumAddress___unnamed_24_38e128db:name;
+const unique T.Length___unnamed_24_9500ea34:name;
+const unique T.Alignment___unnamed_24_9500ea34:name;
+const unique T.MinimumAddress___unnamed_24_9500ea34:name;
+const unique T.MaximumAddress___unnamed_24_9500ea34:name;
+const unique T.Length___unnamed_24_9734802c:name;
+const unique T.Alignment___unnamed_24_9734802c:name;
+const unique T.MinimumAddress___unnamed_24_9734802c:name;
+const unique T.MaximumAddress___unnamed_24_9734802c:name;
+const unique T.Length64___unnamed_24_af62813f:name;
+const unique T.Alignment64___unnamed_24_af62813f:name;
+const unique T.MinimumAddress___unnamed_24_af62813f:name;
+const unique T.MaximumAddress___unnamed_24_af62813f:name;
+const unique T.Length48___unnamed_24_c0555099:name;
+const unique T.Alignment48___unnamed_24_c0555099:name;
+const unique T.MinimumAddress___unnamed_24_c0555099:name;
+const unique T.MaximumAddress___unnamed_24_c0555099:name;
+const unique T.Port___unnamed_24_d7c4ec3a:name;
+const unique T.Memory___unnamed_24_d7c4ec3a:name;
+const unique T.Interrupt___unnamed_24_d7c4ec3a:name;
+const unique T.Dma___unnamed_24_d7c4ec3a:name;
+const unique T.Generic___unnamed_24_d7c4ec3a:name;
+const unique T.DevicePrivate___unnamed_24_d7c4ec3a:name;
+const unique T.BusNumber___unnamed_24_d7c4ec3a:name;
+const unique T.ConfigData___unnamed_24_d7c4ec3a:name;
+const unique T.Memory40___unnamed_24_d7c4ec3a:name;
+const unique T.Memory48___unnamed_24_d7c4ec3a:name;
+const unique T.Memory64___unnamed_24_d7c4ec3a:name;
+const unique T.ReplaceIfExists___unnamed_2_196a7f56:name;
+const unique T.AdvanceOnly___unnamed_2_196a7f56:name;
+const unique T.__unnamed_16_5fed8f23___unnamed_40_a0414182:name;
+const unique T.Thread___unnamed_40_a0414182:name;
+const unique T.AuxiliaryBuffer___unnamed_40_a0414182:name;
+const unique T.__unnamed_12_c6ed93f3___unnamed_40_a0414182:name;
+const unique T.OriginalFileObject___unnamed_40_a0414182:name;
+const unique T.ListEntry___unnamed_40_d90496f4:name;
+const unique T.Wcb___unnamed_40_d90496f4:name;
+const unique T.InitialPrivilegeSet___unnamed_44_a7026dca:name;
+const unique T.PrivilegeSet___unnamed_44_a7026dca:name;
+const unique T.Overlay___unnamed_48_c1da9fa5:name;
+const unique T.Apc___unnamed_48_c1da9fa5:name;
+const unique T.CompletionKey___unnamed_48_c1da9fa5:name;
+const unique T.PowerSequence___unnamed_4_0510b147:name;
+const unique T.Length___unnamed_4_0a569078:name;
+const unique T.Status___unnamed_4_16aff58e:name;
+const unique T.Pointer___unnamed_4_16aff58e:name;
+const unique T.IdType___unnamed_4_40bf8e34:name;
+const unique T.Address___unnamed_4_46b62f69:name;
+const unique T.CreatorBackTraceIndex___unnamed_4_46b62f69:name;
+const unique T.Capabilities___unnamed_4_73d46255:name;
+const unique T.Srb___unnamed_4_765e3037:name;
+const unique T.Type___unnamed_4_846adf3f:name;
+const unique T.__unnamed_1_2bb39c56___unnamed_4_846adf3f:name;
+const unique T.__unnamed_1_e30779f5___unnamed_4_846adf3f:name;
+const unique T.__unnamed_1_9fa0583a___unnamed_4_846adf3f:name;
+const unique T.PowerState___unnamed_4_8dd73d30:name;
+const unique T.Type___unnamed_4_957e0d74:name;
+const unique T.Buttons___unnamed_4_9c11ed91:name;
+const unique T.__unnamed_4_b5247f10___unnamed_4_9c11ed91:name;
+const unique T.IoResourceRequirementList___unnamed_4_a58d40c8:name;
+const unique T.CurrentStackLocation___unnamed_4_a7aa989c:name;
+const unique T.PacketType___unnamed_4_a7aa989c:name;
+const unique T.__unnamed_2_196a7f56___unnamed_4_a7d0864c:name;
+const unique T.ClusterCount___unnamed_4_a7d0864c:name;
+const unique T.DeleteHandle___unnamed_4_a7d0864c:name;
+const unique T.Length___unnamed_4_aa20b426:name;
+const unique T.UserApcRoutine___unnamed_4_ab87ddfd:name;
+const unique T.IssuingProcess___unnamed_4_ab87ddfd:name;
+const unique T.Reserved1___unnamed_4_b016b1e1:name;
+const unique T.TargetSystemState___unnamed_4_b016b1e1:name;
+const unique T.EffectiveSystemState___unnamed_4_b016b1e1:name;
+const unique T.CurrentSystemState___unnamed_4_b016b1e1:name;
+const unique T.IgnoreHibernationPath___unnamed_4_b016b1e1:name;
+const unique T.PseudoTransition___unnamed_4_b016b1e1:name;
+const unique T.Reserved2___unnamed_4_b016b1e1:name;
+const unique T.SystemContext___unnamed_4_b060dea6:name;
+const unique T.SystemPowerStateContext___unnamed_4_b060dea6:name;
+const unique T.__unnamed_4_b016b1e1___unnamed_4_b4f5a780:name;
+const unique T.ContextAsUlong___unnamed_4_b4f5a780:name;
+const unique T.ButtonFlags___unnamed_4_b5247f10:name;
+const unique T.ButtonData___unnamed_4_b5247f10:name;
+const unique T.OwnerCount___unnamed_4_c1e23b02:name;
+const unique T.TableSize___unnamed_4_c1e23b02:name;
+const unique T.__unnamed_4_846adf3f___unnamed_4_c9b2e921:name;
+const unique T.Lock___unnamed_4_c9b2e921:name;
+const unique T.MasterIrp___unnamed_4_fa7b96a7:name;
+const unique T.IrpCount___unnamed_4_fa7b96a7:name;
+const unique T.SystemBuffer___unnamed_4_fa7b96a7:name;
+const unique T.Vpb___unnamed_8_09ad2712:name;
+const unique T.DeviceObject___unnamed_8_09ad2712:name;
+const unique T.Length___unnamed_8_21ac1dba:name;
+const unique T.CompletionFilter___unnamed_8_21ac1dba:name;
+const unique T.Length___unnamed_8_27d3ab76:name;
+const unique T.FsInformationClass___unnamed_8_27d3ab76:name;
+const unique T.Vpb___unnamed_8_4289df81:name;
+const unique T.DeviceObject___unnamed_8_4289df81:name;
+const unique T.Length___unnamed_8_47b72724:name;
+const unique T.FileInformationClass___unnamed_8_47b72724:name;
+const unique T.DeviceTextType___unnamed_8_4b3e3ba3:name;
+const unique T.LocaleId___unnamed_8_4b3e3ba3:name;
+const unique T.__unnamed_4_ab87ddfd___unnamed_8_4f695993:name;
+const unique T.UserApcContext___unnamed_8_4f695993:name;
+const unique T.AllocatedResources___unnamed_8_5cfb6ca4:name;
+const unique T.AllocatedResourcesTranslated___unnamed_8_5cfb6ca4:name;
+const unique T.SecurityInformation___unnamed_8_606438c5:name;
+const unique T.Length___unnamed_8_606438c5:name;
+const unique T.MinimumChannel___unnamed_8_6ad774c0:name;
+const unique T.MaximumChannel___unnamed_8_6ad774c0:name;
+const unique T.Length___unnamed_8_805045cb:name;
+const unique T.FsInformationClass___unnamed_8_805045cb:name;
+const unique T.LowPart___unnamed_8_8684a3e7:name;
+const unique T.HighPart___unnamed_8_8684a3e7:name;
+const unique T.SecurityInformation___unnamed_8_8cc410da:name;
+const unique T.SecurityDescriptor___unnamed_8_8cc410da:name;
+const unique T.InPath___unnamed_8_a47253e0:name;
+const unique T.Reserved___unnamed_8_a47253e0:name;
+const unique T.Type___unnamed_8_a47253e0:name;
+const unique T.AsynchronousParameters___unnamed_8_bbd07f6c:name;
+const unique T.AllocationSize___unnamed_8_bbd07f6c:name;
+const unique T.LowPart___unnamed_8_c9ca8234:name;
+const unique T.HighPart___unnamed_8_c9ca8234:name;
+
+// Type declarations
+
+const unique T.A11CHAR:name;
+const unique T.A19CHAR:name;
+const unique T.A1_CM_FULL_RESOURCE_DESCRIPTOR:name;
+const unique T.A1_CM_PARTIAL_RESOURCE_DESCRIPTOR:name;
+const unique T.A1_IO_RESOURCE_DESCRIPTOR:name;
+const unique T.A1_IO_RESOURCE_LIST:name;
+const unique T.A1_LUID_AND_ATTRIBUTES:name;
+const unique T.A256UINT2:name;
+const unique T.A28PFDRIVER_DISPATCH:name;
+const unique T.A2UCHAR:name;
+const unique T.A32UINT2:name;
+const unique T.A33CHAR:name;
+const unique T.A34CHAR:name;
+const unique T.A39CHAR:name;
+const unique T.A3UCHAR:name;
+const unique T.A3UINT4:name;
+const unique T.A3_LUID_AND_ATTRIBUTES:name;
+const unique T.A43CHAR:name;
+const unique T.A4PVOID:name;
+const unique T.A4UINT4:name;
+const unique T.A5_DEVICE_POWER_STATE:name;
+const unique T.A74CHAR:name;
+const unique T.A7_DEVICE_POWER_STATE:name;
+const unique T.A8UCHAR:name;
+const unique T.BUS_QUERY_ID_TYPE:name;
+const unique T.CHAR:name;
+const unique T.DEVICE_TEXT_TYPE:name;
+const unique T.F0:name;
+const unique T.F1:name;
+const unique T.F10:name;
+const unique T.F11:name;
+const unique T.F12:name;
+const unique T.F13:name;
+const unique T.F14:name;
+const unique T.F15:name;
+const unique T.F16:name;
+const unique T.F17:name;
+const unique T.F18:name;
+const unique T.F19:name;
+const unique T.F2:name;
+const unique T.F20:name;
+const unique T.F21:name;
+const unique T.F22:name;
+const unique T.F23:name;
+const unique T.F24:name;
+const unique T.F25:name;
+const unique T.F26:name;
+const unique T.F27:name;
+const unique T.F28:name;
+const unique T.F29:name;
+const unique T.F3:name;
+const unique T.F30:name;
+const unique T.F31:name;
+const unique T.F32:name;
+const unique T.F33:name;
+const unique T.F34:name;
+const unique T.F35:name;
+const unique T.F36:name;
+const unique T.F37:name;
+const unique T.F38:name;
+const unique T.F4:name;
+const unique T.F5:name;
+const unique T.F6:name;
+const unique T.F7:name;
+const unique T.F8:name;
+const unique T.F9:name;
+const unique T.FDRIVER_ADD_DEVICE:name;
+const unique T.FDRIVER_CANCEL:name;
+const unique T.FDRIVER_CONTROL:name;
+const unique T.FDRIVER_DISPATCH:name;
+const unique T.FDRIVER_INITIALIZE:name;
+const unique T.FDRIVER_STARTIO:name;
+const unique T.FDRIVER_UNLOAD:name;
+const unique T.FFAST_IO_ACQUIRE_FILE:name;
+const unique T.FFAST_IO_ACQUIRE_FOR_CCFLUSH:name;
+const unique T.FFAST_IO_ACQUIRE_FOR_MOD_WRITE:name;
+const unique T.FFAST_IO_CHECK_IF_POSSIBLE:name;
+const unique T.FFAST_IO_DETACH_DEVICE:name;
+const unique T.FFAST_IO_DEVICE_CONTROL:name;
+const unique T.FFAST_IO_LOCK:name;
+const unique T.FFAST_IO_MDL_READ:name;
+const unique T.FFAST_IO_MDL_READ_COMPLETE:name;
+const unique T.FFAST_IO_MDL_READ_COMPLETE_COMPRESSED:name;
+const unique T.FFAST_IO_MDL_WRITE_COMPLETE:name;
+const unique T.FFAST_IO_MDL_WRITE_COMPLETE_COMPRESSED:name;
+const unique T.FFAST_IO_PREPARE_MDL_WRITE:name;
+const unique T.FFAST_IO_QUERY_BASIC_INFO:name;
+const unique T.FFAST_IO_QUERY_NETWORK_OPEN_INFO:name;
+const unique T.FFAST_IO_QUERY_OPEN:name;
+const unique T.FFAST_IO_QUERY_STANDARD_INFO:name;
+const unique T.FFAST_IO_READ:name;
+const unique T.FFAST_IO_READ_COMPRESSED:name;
+const unique T.FFAST_IO_RELEASE_FILE:name;
+const unique T.FFAST_IO_RELEASE_FOR_CCFLUSH:name;
+const unique T.FFAST_IO_RELEASE_FOR_MOD_WRITE:name;
+const unique T.FFAST_IO_UNLOCK_ALL:name;
+const unique T.FFAST_IO_UNLOCK_ALL_BY_KEY:name;
+const unique T.FFAST_IO_UNLOCK_SINGLE:name;
+const unique T.FFAST_IO_WRITE:name;
+const unique T.FFAST_IO_WRITE_COMPRESSED:name;
+const unique T.FIO_COMPLETION_ROUTINE:name;
+const unique T.FKDEFERRED_ROUTINE:name;
+const unique T.INT2:name;
+const unique T.INT4:name;
+const unique T.INT8:name;
+const unique T.PA11CHAR:name;
+const unique T.PA19CHAR:name;
+const unique T.PA33CHAR:name;
+const unique T.PA34CHAR:name;
+const unique T.PA39CHAR:name;
+const unique T.PA43CHAR:name;
+const unique T.PA74CHAR:name;
+const unique T.PCHAR:name;
+const unique T.PF19:name;
+const unique T.PF21:name;
+const unique T.PF23:name;
+const unique T.PF24:name;
+const unique T.PF25:name;
+const unique T.PF33:name;
+const unique T.PF34:name;
+const unique T.PF35:name;
+const unique T.PF36:name;
+const unique T.PF37:name;
+const unique T.PF38:name;
+const unique T.PFDRIVER_ADD_DEVICE:name;
+const unique T.PFDRIVER_CANCEL:name;
+const unique T.PFDRIVER_CONTROL:name;
+const unique T.PFDRIVER_DISPATCH:name;
+const unique T.PFDRIVER_INITIALIZE:name;
+const unique T.PFDRIVER_STARTIO:name;
+const unique T.PFDRIVER_UNLOAD:name;
+const unique T.PFFAST_IO_ACQUIRE_FILE:name;
+const unique T.PFFAST_IO_ACQUIRE_FOR_CCFLUSH:name;
+const unique T.PFFAST_IO_ACQUIRE_FOR_MOD_WRITE:name;
+const unique T.PFFAST_IO_CHECK_IF_POSSIBLE:name;
+const unique T.PFFAST_IO_DETACH_DEVICE:name;
+const unique T.PFFAST_IO_DEVICE_CONTROL:name;
+const unique T.PFFAST_IO_LOCK:name;
+const unique T.PFFAST_IO_MDL_READ:name;
+const unique T.PFFAST_IO_MDL_READ_COMPLETE:name;
+const unique T.PFFAST_IO_MDL_READ_COMPLETE_COMPRESSED:name;
+const unique T.PFFAST_IO_MDL_WRITE_COMPLETE:name;
+const unique T.PFFAST_IO_MDL_WRITE_COMPLETE_COMPRESSED:name;
+const unique T.PFFAST_IO_PREPARE_MDL_WRITE:name;
+const unique T.PFFAST_IO_QUERY_BASIC_INFO:name;
+const unique T.PFFAST_IO_QUERY_NETWORK_OPEN_INFO:name;
+const unique T.PFFAST_IO_QUERY_OPEN:name;
+const unique T.PFFAST_IO_QUERY_STANDARD_INFO:name;
+const unique T.PFFAST_IO_READ:name;
+const unique T.PFFAST_IO_READ_COMPRESSED:name;
+const unique T.PFFAST_IO_RELEASE_FILE:name;
+const unique T.PFFAST_IO_RELEASE_FOR_CCFLUSH:name;
+const unique T.PFFAST_IO_RELEASE_FOR_MOD_WRITE:name;
+const unique T.PFFAST_IO_UNLOCK_ALL:name;
+const unique T.PFFAST_IO_UNLOCK_ALL_BY_KEY:name;
+const unique T.PFFAST_IO_UNLOCK_SINGLE:name;
+const unique T.PFFAST_IO_WRITE:name;
+const unique T.PFFAST_IO_WRITE_COMPRESSED:name;
+const unique T.PFIO_COMPLETION_ROUTINE:name;
+const unique T.PFKDEFERRED_ROUTINE:name;
+const unique T.PINT4:name;
+const unique T.POWER_ACTION:name;
+const unique T.PPCHAR:name;
+const unique T.PPF24:name;
+const unique T.PPP_FILE_OBJECT:name;
+const unique T.PPVOID:name;
+const unique T.PP_DEVICE_EXTENSION:name;
+const unique T.PP_DEVICE_OBJECT:name;
+const unique T.PP_DRIVER_OBJECT:name;
+const unique T.PP_ERESOURCE:name;
+const unique T.PP_FILE_OBJECT:name;
+const unique T.PP_IRP:name;
+const unique T.PP_LIST_ENTRY:name;
+const unique T.PP_MDL:name;
+const unique T.PP_PORT:name;
+const unique T.PP_UNICODE_STRING:name;
+const unique T.PUCHAR:name;
+const unique T.PUINT2:name;
+const unique T.PUINT4:name;
+const unique T.PVOID:name;
+const unique T.PWMIGUIDREGINFO:name;
+const unique T.P_ACCESS_STATE:name;
+const unique T.P_CM_RESOURCE_LIST:name;
+const unique T.P_COMPRESSED_DATA_INFO:name;
+const unique T.P_DEVICE_CAPABILITIES:name;
+const unique T.P_DEVICE_EXTENSION:name;
+const unique T.P_DEVICE_OBJECT:name;
+const unique T.P_DEVOBJ_EXTENSION:name;
+const unique T.P_DRIVER_EXTENSION:name;
+const unique T.P_DRIVER_OBJECT:name;
+const unique T.P_EPROCESS:name;
+const unique T.P_ERESOURCE:name;
+const unique T.P_ETHREAD:name;
+const unique T.P_FAST_IO_DISPATCH:name;
+const unique T.P_FILE_BASIC_INFORMATION:name;
+const unique T.P_FILE_GET_QUOTA_INFORMATION:name;
+const unique T.P_FILE_NETWORK_OPEN_INFORMATION:name;
+const unique T.P_FILE_OBJECT:name;
+const unique T.P_FILE_STANDARD_INFORMATION:name;
+const unique T.P_GLOBALS:name;
+const unique T.P_GUID:name;
+const unique T.P_INTERFACE:name;
+const unique T.P_IO_COMPLETION_CONTEXT:name;
+const unique T.P_IO_REMOVE_LOCK_TRACKING_BLOCK:name;
+const unique T.P_IO_RESOURCE_REQUIREMENTS_LIST:name;
+const unique T.P_IO_SECURITY_CONTEXT:name;
+const unique T.P_IO_STACK_LOCATION:name;
+const unique T.P_IO_STATUS_BLOCK:name;
+const unique T.P_IO_TIMER:name;
+const unique T.P_IRP:name;
+const unique T.P_KAPC:name;
+const unique T.P_KDPC:name;
+const unique T.P_KEVENT:name;
+const unique T.P_KSEMAPHORE:name;
+const unique T.P_KTHREAD:name;
+const unique T.P_LARGE_INTEGER:name;
+const unique T.P_LIST_ENTRY:name;
+const unique T.P_MDL:name;
+const unique T.P_MOUSE_INPUT_DATA:name;
+const unique T.P_OWNER_ENTRY:name;
+const unique T.P_PORT:name;
+const unique T.P_POWER_SEQUENCE:name;
+const unique T.P_SCSI_REQUEST_BLOCK:name;
+const unique T.P_SECTION_OBJECT_POINTERS:name;
+const unique T.P_SECURITY_QUALITY_OF_SERVICE:name;
+const unique T.P_UNICODE_STRING:name;
+const unique T.P_VPB:name;
+const unique T.UCHAR:name;
+const unique T.UINT2:name;
+const unique T.UINT4:name;
+const unique T.VOID:name;
+const unique T.WMIENABLEDISABLECONTROL:name;
+const unique T.WMIGUIDREGINFO:name;
+const unique T._ACCESS_STATE:name;
+const unique T._CM_FULL_RESOURCE_DESCRIPTOR:name;
+const unique T._CM_PARTIAL_RESOURCE_DESCRIPTOR:name;
+const unique T._CM_PARTIAL_RESOURCE_LIST:name;
+const unique T._CM_RESOURCE_LIST:name;
+const unique T._COMPRESSED_DATA_INFO:name;
+const unique T._DEVICE_CAPABILITIES:name;
+const unique T._DEVICE_EXTENSION:name;
+const unique T._DEVICE_OBJECT:name;
+const unique T._DEVICE_POWER_STATE:name;
+const unique T._DEVICE_RELATION_TYPE:name;
+const unique T._DEVICE_USAGE_NOTIFICATION_TYPE:name;
+const unique T._DEVOBJ_EXTENSION:name;
+const unique T._DISPATCHER_HEADER:name;
+const unique T._DRIVER_EXTENSION:name;
+const unique T._DRIVER_OBJECT:name;
+const unique T._EPROCESS:name;
+const unique T._ERESOURCE:name;
+const unique T._ETHREAD:name;
+const unique T._FAST_IO_DISPATCH:name;
+const unique T._FAST_MUTEX:name;
+const unique T._FILE_BASIC_INFORMATION:name;
+const unique T._FILE_GET_QUOTA_INFORMATION:name;
+const unique T._FILE_INFORMATION_CLASS:name;
+const unique T._FILE_NETWORK_OPEN_INFORMATION:name;
+const unique T._FILE_OBJECT:name;
+const unique T._FILE_STANDARD_INFORMATION:name;
+const unique T._FSINFOCLASS:name;
+const unique T._GLOBALS:name;
+const unique T._GUID:name;
+const unique T._INITIAL_PRIVILEGE_SET:name;
+const unique T._INTERFACE:name;
+const unique T._INTERFACE_TYPE:name;
+const unique T._IO_ALLOCATION_ACTION:name;
+const unique T._IO_COMPLETION_CONTEXT:name;
+const unique T._IO_REMOVE_LOCK:name;
+const unique T._IO_REMOVE_LOCK_COMMON_BLOCK:name;
+const unique T._IO_REMOVE_LOCK_DBG_BLOCK:name;
+const unique T._IO_REMOVE_LOCK_TRACKING_BLOCK:name;
+const unique T._IO_RESOURCE_DESCRIPTOR:name;
+const unique T._IO_RESOURCE_LIST:name;
+const unique T._IO_RESOURCE_REQUIREMENTS_LIST:name;
+const unique T._IO_SECURITY_CONTEXT:name;
+const unique T._IO_STACK_LOCATION:name;
+const unique T._IO_STATUS_BLOCK:name;
+const unique T._IO_TIMER:name;
+const unique T._IRP:name;
+const unique T._IRQ_DEVICE_POLICY:name;
+const unique T._IRQ_PRIORITY:name;
+const unique T._KAPC:name;
+const unique T._KDEVICE_QUEUE:name;
+const unique T._KDEVICE_QUEUE_ENTRY:name;
+const unique T._KDPC:name;
+const unique T._KEVENT:name;
+const unique T._KSEMAPHORE:name;
+const unique T._KTHREAD:name;
+const unique T._LARGE_INTEGER:name;
+const unique T._LIST_ENTRY:name;
+const unique T._LUID:name;
+const unique T._LUID_AND_ATTRIBUTES:name;
+const unique T._MDL:name;
+const unique T._MOUSE_ATTRIBUTES:name;
+const unique T._MOUSE_INPUT_DATA:name;
+const unique T._OWNER_ENTRY:name;
+const unique T._PORT:name;
+const unique T._POWER_SEQUENCE:name;
+const unique T._POWER_STATE:name;
+const unique T._POWER_STATE_TYPE:name;
+const unique T._PRIVILEGE_SET:name;
+const unique T._SCSI_REQUEST_BLOCK:name;
+const unique T._SECTION_OBJECT_POINTERS:name;
+const unique T._SECURITY_IMPERSONATION_LEVEL:name;
+const unique T._SECURITY_QUALITY_OF_SERVICE:name;
+const unique T._SECURITY_SUBJECT_CONTEXT:name;
+const unique T._SYSTEM_POWER_STATE:name;
+const unique T._SYSTEM_POWER_STATE_CONTEXT:name;
+const unique T._UNICODE_STRING:name;
+const unique T._VPB:name;
+const unique T._WAIT_CONTEXT_BLOCK:name;
+const unique T._WMILIB_CONTEXT:name;
+const unique T.__unnamed_12_06b9ee6e:name;
+const unique T.__unnamed_12_0882bd02:name;
+const unique T.__unnamed_12_264d0dab:name;
+const unique T.__unnamed_12_2e80217b:name;
+const unique T.__unnamed_12_5cc7ace2:name;
+const unique T.__unnamed_12_6374506e:name;
+const unique T.__unnamed_12_68a4278e:name;
+const unique T.__unnamed_12_79ed2653:name;
+const unique T.__unnamed_12_7da594c0:name;
+const unique T.__unnamed_12_9873e05d:name;
+const unique T.__unnamed_12_9cc8cebc:name;
+const unique T.__unnamed_12_b98da82e:name;
+const unique T.__unnamed_12_c2880e88:name;
+const unique T.__unnamed_12_c49ab31a:name;
+const unique T.__unnamed_12_c6ed93f3:name;
+const unique T.__unnamed_12_ced61554:name;
+const unique T.__unnamed_12_d9c44df5:name;
+const unique T.__unnamed_12_db3dcbfc:name;
+const unique T.__unnamed_12_fb26b3fc:name;
+const unique T.__unnamed_16_22e4d054:name;
+const unique T.__unnamed_16_39b626ad:name;
+const unique T.__unnamed_16_56c011d7:name;
+const unique T.__unnamed_16_5fed8f23:name;
+const unique T.__unnamed_16_6be9abe0:name;
+const unique T.__unnamed_16_78879a38:name;
+const unique T.__unnamed_16_804a2f24:name;
+const unique T.__unnamed_16_8586693f:name;
+const unique T.__unnamed_16_8831e65f:name;
+const unique T.__unnamed_16_8c2d663a:name;
+const unique T.__unnamed_16_913b9a7a:name;
+const unique T.__unnamed_16_94d1d1c7:name;
+const unique T.__unnamed_16_a2fab4da:name;
+const unique T.__unnamed_16_ae643f17:name;
+const unique T.__unnamed_16_c1b29316:name;
+const unique T.__unnamed_16_cbd53ed4:name;
+const unique T.__unnamed_16_db70db6e:name;
+const unique T.__unnamed_16_ef4b6307:name;
+const unique T.__unnamed_16_fdda1f62:name;
+const unique T.__unnamed_1_1394de4b:name;
+const unique T.__unnamed_1_2bb39c56:name;
+const unique T.__unnamed_1_9fa0583a:name;
+const unique T.__unnamed_1_e30779f5:name;
+const unique T.__unnamed_20_83d468e4:name;
+const unique T.__unnamed_24_035931da:name;
+const unique T.__unnamed_24_38e128db:name;
+const unique T.__unnamed_24_9500ea34:name;
+const unique T.__unnamed_24_9734802c:name;
+const unique T.__unnamed_24_af62813f:name;
+const unique T.__unnamed_24_c0555099:name;
+const unique T.__unnamed_24_d7c4ec3a:name;
+const unique T.__unnamed_2_196a7f56:name;
+const unique T.__unnamed_40_a0414182:name;
+const unique T.__unnamed_40_d90496f4:name;
+const unique T.__unnamed_44_a7026dca:name;
+const unique T.__unnamed_48_c1da9fa5:name;
+const unique T.__unnamed_4_0510b147:name;
+const unique T.__unnamed_4_0a569078:name;
+const unique T.__unnamed_4_16aff58e:name;
+const unique T.__unnamed_4_40bf8e34:name;
+const unique T.__unnamed_4_46b62f69:name;
+const unique T.__unnamed_4_73d46255:name;
+const unique T.__unnamed_4_765e3037:name;
+const unique T.__unnamed_4_846adf3f:name;
+const unique T.__unnamed_4_8dd73d30:name;
+const unique T.__unnamed_4_957e0d74:name;
+const unique T.__unnamed_4_9c11ed91:name;
+const unique T.__unnamed_4_a58d40c8:name;
+const unique T.__unnamed_4_a7aa989c:name;
+const unique T.__unnamed_4_a7d0864c:name;
+const unique T.__unnamed_4_aa20b426:name;
+const unique T.__unnamed_4_ab87ddfd:name;
+const unique T.__unnamed_4_b016b1e1:name;
+const unique T.__unnamed_4_b060dea6:name;
+const unique T.__unnamed_4_b4f5a780:name;
+const unique T.__unnamed_4_b5247f10:name;
+const unique T.__unnamed_4_c1e23b02:name;
+const unique T.__unnamed_4_c9b2e921:name;
+const unique T.__unnamed_4_fa7b96a7:name;
+const unique T.__unnamed_8_09ad2712:name;
+const unique T.__unnamed_8_21ac1dba:name;
+const unique T.__unnamed_8_27d3ab76:name;
+const unique T.__unnamed_8_4289df81:name;
+const unique T.__unnamed_8_47b72724:name;
+const unique T.__unnamed_8_4b3e3ba3:name;
+const unique T.__unnamed_8_4f695993:name;
+const unique T.__unnamed_8_5cfb6ca4:name;
+const unique T.__unnamed_8_606438c5:name;
+const unique T.__unnamed_8_6ad774c0:name;
+const unique T.__unnamed_8_805045cb:name;
+const unique T.__unnamed_8_8684a3e7:name;
+const unique T.__unnamed_8_8cc410da:name;
+const unique T.__unnamed_8_a47253e0:name;
+const unique T.__unnamed_8_bbd07f6c:name;
+const unique T.__unnamed_8_c9ca8234:name;
+
+function AssocClassList__GLOBALS(int) returns (int);
+function AssocClassList__GLOBALSInv(int) returns (int);
+function _S_AssocClassList__GLOBALS([int]bool) returns ([int]bool);
+function _S_AssocClassList__GLOBALSInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {AssocClassList__GLOBALSInv(AssocClassList__GLOBALS(x))} AssocClassList__GLOBALSInv(AssocClassList__GLOBALS(x)) == x);
+axiom (forall x:int :: {AssocClassList__GLOBALSInv(x)} AssocClassList__GLOBALS(AssocClassList__GLOBALSInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_AssocClassList__GLOBALS(S)[x]} _S_AssocClassList__GLOBALS(S)[x] <==> S[AssocClassList__GLOBALSInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_AssocClassList__GLOBALSInv(S)[x]} _S_AssocClassList__GLOBALSInv(S)[x] <==> S[AssocClassList__GLOBALS(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_AssocClassList__GLOBALS(S)} S[x] ==> _S_AssocClassList__GLOBALS(S)[AssocClassList__GLOBALS(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_AssocClassList__GLOBALSInv(S)} S[x] ==> _S_AssocClassList__GLOBALSInv(S)[AssocClassList__GLOBALSInv(x)]);
+
+axiom (forall x:int :: {AssocClassList__GLOBALS(x)} AssocClassList__GLOBALS(x) == x + 8);
+axiom (forall x:int :: {AssocClassList__GLOBALSInv(x)} AssocClassList__GLOBALSInv(x) == x - 8);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 8, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 8, 1) == AssocClassList__GLOBALSInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 8)} MINUS_LEFT_PTR(x, 1, 8) == AssocClassList__GLOBALSInv(x));
+function Buffer__UNICODE_STRING(int) returns (int);
+function Buffer__UNICODE_STRINGInv(int) returns (int);
+function _S_Buffer__UNICODE_STRING([int]bool) returns ([int]bool);
+function _S_Buffer__UNICODE_STRINGInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {Buffer__UNICODE_STRINGInv(Buffer__UNICODE_STRING(x))} Buffer__UNICODE_STRINGInv(Buffer__UNICODE_STRING(x)) == x);
+axiom (forall x:int :: {Buffer__UNICODE_STRINGInv(x)} Buffer__UNICODE_STRING(Buffer__UNICODE_STRINGInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_Buffer__UNICODE_STRING(S)[x]} _S_Buffer__UNICODE_STRING(S)[x] <==> S[Buffer__UNICODE_STRINGInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_Buffer__UNICODE_STRINGInv(S)[x]} _S_Buffer__UNICODE_STRINGInv(S)[x] <==> S[Buffer__UNICODE_STRING(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Buffer__UNICODE_STRING(S)} S[x] ==> _S_Buffer__UNICODE_STRING(S)[Buffer__UNICODE_STRING(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Buffer__UNICODE_STRINGInv(S)} S[x] ==> _S_Buffer__UNICODE_STRINGInv(S)[Buffer__UNICODE_STRINGInv(x)]);
+
+axiom (forall x:int :: {Buffer__UNICODE_STRING(x)} Buffer__UNICODE_STRING(x) == x + 4);
+axiom (forall x:int :: {Buffer__UNICODE_STRINGInv(x)} Buffer__UNICODE_STRINGInv(x) == x - 4);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 4, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 4, 1) == Buffer__UNICODE_STRINGInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 4)} MINUS_LEFT_PTR(x, 1, 4) == Buffer__UNICODE_STRINGInv(x));
+function DataIn__DEVICE_EXTENSION(int) returns (int);
+function DataIn__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_DataIn__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_DataIn__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {DataIn__DEVICE_EXTENSIONInv(DataIn__DEVICE_EXTENSION(x))} DataIn__DEVICE_EXTENSIONInv(DataIn__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {DataIn__DEVICE_EXTENSIONInv(x)} DataIn__DEVICE_EXTENSION(DataIn__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_DataIn__DEVICE_EXTENSION(S)[x]} _S_DataIn__DEVICE_EXTENSION(S)[x] <==> S[DataIn__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_DataIn__DEVICE_EXTENSIONInv(S)[x]} _S_DataIn__DEVICE_EXTENSIONInv(S)[x] <==> S[DataIn__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_DataIn__DEVICE_EXTENSION(S)} S[x] ==> _S_DataIn__DEVICE_EXTENSION(S)[DataIn__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_DataIn__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_DataIn__DEVICE_EXTENSIONInv(S)[DataIn__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {DataIn__DEVICE_EXTENSION(x)} DataIn__DEVICE_EXTENSION(x) == x + 132);
+axiom (forall x:int :: {DataIn__DEVICE_EXTENSIONInv(x)} DataIn__DEVICE_EXTENSIONInv(x) == x - 132);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 132, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 132, 1) == DataIn__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 132)} MINUS_LEFT_PTR(x, 1, 132) == DataIn__DEVICE_EXTENSIONInv(x));
+function DataOut__DEVICE_EXTENSION(int) returns (int);
+function DataOut__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_DataOut__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_DataOut__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {DataOut__DEVICE_EXTENSIONInv(DataOut__DEVICE_EXTENSION(x))} DataOut__DEVICE_EXTENSIONInv(DataOut__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {DataOut__DEVICE_EXTENSIONInv(x)} DataOut__DEVICE_EXTENSION(DataOut__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_DataOut__DEVICE_EXTENSION(S)[x]} _S_DataOut__DEVICE_EXTENSION(S)[x] <==> S[DataOut__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_DataOut__DEVICE_EXTENSIONInv(S)[x]} _S_DataOut__DEVICE_EXTENSIONInv(S)[x] <==> S[DataOut__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_DataOut__DEVICE_EXTENSION(S)} S[x] ==> _S_DataOut__DEVICE_EXTENSION(S)[DataOut__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_DataOut__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_DataOut__DEVICE_EXTENSIONInv(S)[DataOut__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {DataOut__DEVICE_EXTENSION(x)} DataOut__DEVICE_EXTENSION(x) == x + 136);
+axiom (forall x:int :: {DataOut__DEVICE_EXTENSIONInv(x)} DataOut__DEVICE_EXTENSIONInv(x) == x - 136);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 136, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 136, 1) == DataOut__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 136)} MINUS_LEFT_PTR(x, 1, 136) == DataOut__DEVICE_EXTENSIONInv(x));
+function DeviceExtension__DEVICE_OBJECT(int) returns (int);
+function DeviceExtension__DEVICE_OBJECTInv(int) returns (int);
+function _S_DeviceExtension__DEVICE_OBJECT([int]bool) returns ([int]bool);
+function _S_DeviceExtension__DEVICE_OBJECTInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {DeviceExtension__DEVICE_OBJECTInv(DeviceExtension__DEVICE_OBJECT(x))} DeviceExtension__DEVICE_OBJECTInv(DeviceExtension__DEVICE_OBJECT(x)) == x);
+axiom (forall x:int :: {DeviceExtension__DEVICE_OBJECTInv(x)} DeviceExtension__DEVICE_OBJECT(DeviceExtension__DEVICE_OBJECTInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_DeviceExtension__DEVICE_OBJECT(S)[x]} _S_DeviceExtension__DEVICE_OBJECT(S)[x] <==> S[DeviceExtension__DEVICE_OBJECTInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_DeviceExtension__DEVICE_OBJECTInv(S)[x]} _S_DeviceExtension__DEVICE_OBJECTInv(S)[x] <==> S[DeviceExtension__DEVICE_OBJECT(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_DeviceExtension__DEVICE_OBJECT(S)} S[x] ==> _S_DeviceExtension__DEVICE_OBJECT(S)[DeviceExtension__DEVICE_OBJECT(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_DeviceExtension__DEVICE_OBJECTInv(S)} S[x] ==> _S_DeviceExtension__DEVICE_OBJECTInv(S)[DeviceExtension__DEVICE_OBJECTInv(x)]);
+
+axiom (forall x:int :: {DeviceExtension__DEVICE_OBJECT(x)} DeviceExtension__DEVICE_OBJECT(x) == x + 40);
+axiom (forall x:int :: {DeviceExtension__DEVICE_OBJECTInv(x)} DeviceExtension__DEVICE_OBJECTInv(x) == x - 40);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 40, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 40, 1) == DeviceExtension__DEVICE_OBJECTInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 40)} MINUS_LEFT_PTR(x, 1, 40) == DeviceExtension__DEVICE_OBJECTInv(x));
+function Enabled__DEVICE_EXTENSION(int) returns (int);
+function Enabled__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_Enabled__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_Enabled__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {Enabled__DEVICE_EXTENSIONInv(Enabled__DEVICE_EXTENSION(x))} Enabled__DEVICE_EXTENSIONInv(Enabled__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {Enabled__DEVICE_EXTENSIONInv(x)} Enabled__DEVICE_EXTENSION(Enabled__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_Enabled__DEVICE_EXTENSION(S)[x]} _S_Enabled__DEVICE_EXTENSION(S)[x] <==> S[Enabled__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_Enabled__DEVICE_EXTENSIONInv(S)[x]} _S_Enabled__DEVICE_EXTENSIONInv(S)[x] <==> S[Enabled__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Enabled__DEVICE_EXTENSION(S)} S[x] ==> _S_Enabled__DEVICE_EXTENSION(S)[Enabled__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Enabled__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_Enabled__DEVICE_EXTENSIONInv(S)[Enabled__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {Enabled__DEVICE_EXTENSION(x)} Enabled__DEVICE_EXTENSION(x) == x + 264);
+axiom (forall x:int :: {Enabled__DEVICE_EXTENSIONInv(x)} Enabled__DEVICE_EXTENSIONInv(x) == x - 264);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 264, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 264, 1) == Enabled__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 264)} MINUS_LEFT_PTR(x, 1, 264) == Enabled__DEVICE_EXTENSIONInv(x));
+function Enabled__PORT(int) returns (int);
+function Enabled__PORTInv(int) returns (int);
+function _S_Enabled__PORT([int]bool) returns ([int]bool);
+function _S_Enabled__PORTInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {Enabled__PORTInv(Enabled__PORT(x))} Enabled__PORTInv(Enabled__PORT(x)) == x);
+axiom (forall x:int :: {Enabled__PORTInv(x)} Enabled__PORT(Enabled__PORTInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_Enabled__PORT(S)[x]} _S_Enabled__PORT(S)[x] <==> S[Enabled__PORTInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_Enabled__PORTInv(S)[x]} _S_Enabled__PORTInv(S)[x] <==> S[Enabled__PORT(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Enabled__PORT(S)} S[x] ==> _S_Enabled__PORT(S)[Enabled__PORT(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Enabled__PORTInv(S)} S[x] ==> _S_Enabled__PORTInv(S)[Enabled__PORTInv(x)]);
+
+axiom (forall x:int :: {Enabled__PORT(x)} Enabled__PORT(x) == x + 8);
+axiom (forall x:int :: {Enabled__PORTInv(x)} Enabled__PORTInv(x) == x - 8);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 8, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 8, 1) == Enabled__PORTInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 8)} MINUS_LEFT_PTR(x, 1, 8) == Enabled__PORTInv(x));
+function File__DEVICE_EXTENSION(int) returns (int);
+function File__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_File__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_File__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {File__DEVICE_EXTENSIONInv(File__DEVICE_EXTENSION(x))} File__DEVICE_EXTENSIONInv(File__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {File__DEVICE_EXTENSIONInv(x)} File__DEVICE_EXTENSION(File__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_File__DEVICE_EXTENSION(S)[x]} _S_File__DEVICE_EXTENSION(S)[x] <==> S[File__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_File__DEVICE_EXTENSIONInv(S)[x]} _S_File__DEVICE_EXTENSIONInv(S)[x] <==> S[File__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_File__DEVICE_EXTENSION(S)} S[x] ==> _S_File__DEVICE_EXTENSION(S)[File__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_File__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_File__DEVICE_EXTENSIONInv(S)[File__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {File__DEVICE_EXTENSION(x)} File__DEVICE_EXTENSION(x) == x + 260);
+axiom (forall x:int :: {File__DEVICE_EXTENSIONInv(x)} File__DEVICE_EXTENSIONInv(x) == x - 260);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 260, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 260, 1) == File__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 260)} MINUS_LEFT_PTR(x, 1, 260) == File__DEVICE_EXTENSIONInv(x));
+function File__PORT(int) returns (int);
+function File__PORTInv(int) returns (int);
+function _S_File__PORT([int]bool) returns ([int]bool);
+function _S_File__PORTInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {File__PORTInv(File__PORT(x))} File__PORTInv(File__PORT(x)) == x);
+axiom (forall x:int :: {File__PORTInv(x)} File__PORT(File__PORTInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_File__PORT(S)[x]} _S_File__PORT(S)[x] <==> S[File__PORTInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_File__PORTInv(S)[x]} _S_File__PORTInv(S)[x] <==> S[File__PORT(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_File__PORT(S)} S[x] ==> _S_File__PORT(S)[File__PORT(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_File__PORTInv(S)} S[x] ==> _S_File__PORTInv(S)[File__PORTInv(x)]);
+
+axiom (forall x:int :: {File__PORT(x)} File__PORT(x) == x + 0);
+axiom (forall x:int :: {File__PORTInv(x)} File__PORTInv(x) == x - 0);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1) == File__PORTInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 0)} MINUS_LEFT_PTR(x, 1, 0) == File__PORTInv(x));
+function Flink__LIST_ENTRY(int) returns (int);
+function Flink__LIST_ENTRYInv(int) returns (int);
+function _S_Flink__LIST_ENTRY([int]bool) returns ([int]bool);
+function _S_Flink__LIST_ENTRYInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {Flink__LIST_ENTRYInv(Flink__LIST_ENTRY(x))} Flink__LIST_ENTRYInv(Flink__LIST_ENTRY(x)) == x);
+axiom (forall x:int :: {Flink__LIST_ENTRYInv(x)} Flink__LIST_ENTRY(Flink__LIST_ENTRYInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_Flink__LIST_ENTRY(S)[x]} _S_Flink__LIST_ENTRY(S)[x] <==> S[Flink__LIST_ENTRYInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_Flink__LIST_ENTRYInv(S)[x]} _S_Flink__LIST_ENTRYInv(S)[x] <==> S[Flink__LIST_ENTRY(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Flink__LIST_ENTRY(S)} S[x] ==> _S_Flink__LIST_ENTRY(S)[Flink__LIST_ENTRY(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Flink__LIST_ENTRYInv(S)} S[x] ==> _S_Flink__LIST_ENTRYInv(S)[Flink__LIST_ENTRYInv(x)]);
+
+axiom (forall x:int :: {Flink__LIST_ENTRY(x)} Flink__LIST_ENTRY(x) == x + 0);
+axiom (forall x:int :: {Flink__LIST_ENTRYInv(x)} Flink__LIST_ENTRYInv(x) == x - 0);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1) == Flink__LIST_ENTRYInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 0)} MINUS_LEFT_PTR(x, 1, 0) == Flink__LIST_ENTRYInv(x));
+function Free__PORT(int) returns (int);
+function Free__PORTInv(int) returns (int);
+function _S_Free__PORT([int]bool) returns ([int]bool);
+function _S_Free__PORTInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {Free__PORTInv(Free__PORT(x))} Free__PORTInv(Free__PORT(x)) == x);
+axiom (forall x:int :: {Free__PORTInv(x)} Free__PORT(Free__PORTInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_Free__PORT(S)[x]} _S_Free__PORT(S)[x] <==> S[Free__PORTInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_Free__PORTInv(S)[x]} _S_Free__PORTInv(S)[x] <==> S[Free__PORT(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Free__PORT(S)} S[x] ==> _S_Free__PORT(S)[Free__PORT(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Free__PORTInv(S)} S[x] ==> _S_Free__PORTInv(S)[Free__PORTInv(x)]);
+
+axiom (forall x:int :: {Free__PORT(x)} Free__PORT(x) == x + 11);
+axiom (forall x:int :: {Free__PORTInv(x)} Free__PORTInv(x) == x - 11);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 11, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 11, 1) == Free__PORTInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 11)} MINUS_LEFT_PTR(x, 1, 11) == Free__PORTInv(x));
+function GrandMaster__GLOBALS(int) returns (int);
+function GrandMaster__GLOBALSInv(int) returns (int);
+function _S_GrandMaster__GLOBALS([int]bool) returns ([int]bool);
+function _S_GrandMaster__GLOBALSInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {GrandMaster__GLOBALSInv(GrandMaster__GLOBALS(x))} GrandMaster__GLOBALSInv(GrandMaster__GLOBALS(x)) == x);
+axiom (forall x:int :: {GrandMaster__GLOBALSInv(x)} GrandMaster__GLOBALS(GrandMaster__GLOBALSInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_GrandMaster__GLOBALS(S)[x]} _S_GrandMaster__GLOBALS(S)[x] <==> S[GrandMaster__GLOBALSInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_GrandMaster__GLOBALSInv(S)[x]} _S_GrandMaster__GLOBALSInv(S)[x] <==> S[GrandMaster__GLOBALS(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_GrandMaster__GLOBALS(S)} S[x] ==> _S_GrandMaster__GLOBALS(S)[GrandMaster__GLOBALS(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_GrandMaster__GLOBALSInv(S)} S[x] ==> _S_GrandMaster__GLOBALSInv(S)[GrandMaster__GLOBALSInv(x)]);
+
+axiom (forall x:int :: {GrandMaster__GLOBALS(x)} GrandMaster__GLOBALS(x) == x + 4);
+axiom (forall x:int :: {GrandMaster__GLOBALSInv(x)} GrandMaster__GLOBALSInv(x) == x - 4);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 4, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 4, 1) == GrandMaster__GLOBALSInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 4)} MINUS_LEFT_PTR(x, 1, 4) == GrandMaster__GLOBALSInv(x));
+function InputData__DEVICE_EXTENSION(int) returns (int);
+function InputData__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_InputData__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_InputData__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {InputData__DEVICE_EXTENSIONInv(InputData__DEVICE_EXTENSION(x))} InputData__DEVICE_EXTENSIONInv(InputData__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {InputData__DEVICE_EXTENSIONInv(x)} InputData__DEVICE_EXTENSION(InputData__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_InputData__DEVICE_EXTENSION(S)[x]} _S_InputData__DEVICE_EXTENSION(S)[x] <==> S[InputData__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_InputData__DEVICE_EXTENSIONInv(S)[x]} _S_InputData__DEVICE_EXTENSIONInv(S)[x] <==> S[InputData__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_InputData__DEVICE_EXTENSION(S)} S[x] ==> _S_InputData__DEVICE_EXTENSION(S)[InputData__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_InputData__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_InputData__DEVICE_EXTENSIONInv(S)[InputData__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {InputData__DEVICE_EXTENSION(x)} InputData__DEVICE_EXTENSION(x) == x + 128);
+axiom (forall x:int :: {InputData__DEVICE_EXTENSIONInv(x)} InputData__DEVICE_EXTENSIONInv(x) == x - 128);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 128, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 128, 1) == InputData__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 128)} MINUS_LEFT_PTR(x, 1, 128) == InputData__DEVICE_EXTENSIONInv(x));
+function LegacyDeviceList__GLOBALS(int) returns (int);
+function LegacyDeviceList__GLOBALSInv(int) returns (int);
+function _S_LegacyDeviceList__GLOBALS([int]bool) returns ([int]bool);
+function _S_LegacyDeviceList__GLOBALSInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {LegacyDeviceList__GLOBALSInv(LegacyDeviceList__GLOBALS(x))} LegacyDeviceList__GLOBALSInv(LegacyDeviceList__GLOBALS(x)) == x);
+axiom (forall x:int :: {LegacyDeviceList__GLOBALSInv(x)} LegacyDeviceList__GLOBALS(LegacyDeviceList__GLOBALSInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_LegacyDeviceList__GLOBALS(S)[x]} _S_LegacyDeviceList__GLOBALS(S)[x] <==> S[LegacyDeviceList__GLOBALSInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_LegacyDeviceList__GLOBALSInv(S)[x]} _S_LegacyDeviceList__GLOBALSInv(S)[x] <==> S[LegacyDeviceList__GLOBALS(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_LegacyDeviceList__GLOBALS(S)} S[x] ==> _S_LegacyDeviceList__GLOBALS(S)[LegacyDeviceList__GLOBALS(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_LegacyDeviceList__GLOBALSInv(S)} S[x] ==> _S_LegacyDeviceList__GLOBALSInv(S)[LegacyDeviceList__GLOBALSInv(x)]);
+
+axiom (forall x:int :: {LegacyDeviceList__GLOBALS(x)} LegacyDeviceList__GLOBALS(x) == x + 864);
+axiom (forall x:int :: {LegacyDeviceList__GLOBALSInv(x)} LegacyDeviceList__GLOBALSInv(x) == x - 864);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 864, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 864, 1) == LegacyDeviceList__GLOBALSInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 864)} MINUS_LEFT_PTR(x, 1, 864) == LegacyDeviceList__GLOBALSInv(x));
+function Link__DEVICE_EXTENSION(int) returns (int);
+function Link__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_Link__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_Link__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {Link__DEVICE_EXTENSIONInv(Link__DEVICE_EXTENSION(x))} Link__DEVICE_EXTENSIONInv(Link__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {Link__DEVICE_EXTENSIONInv(x)} Link__DEVICE_EXTENSION(Link__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_Link__DEVICE_EXTENSION(S)[x]} _S_Link__DEVICE_EXTENSION(S)[x] <==> S[Link__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_Link__DEVICE_EXTENSIONInv(S)[x]} _S_Link__DEVICE_EXTENSIONInv(S)[x] <==> S[Link__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Link__DEVICE_EXTENSION(S)} S[x] ==> _S_Link__DEVICE_EXTENSION(S)[Link__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Link__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_Link__DEVICE_EXTENSIONInv(S)[Link__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {Link__DEVICE_EXTENSION(x)} Link__DEVICE_EXTENSION(x) == x + 252);
+axiom (forall x:int :: {Link__DEVICE_EXTENSIONInv(x)} Link__DEVICE_EXTENSIONInv(x) == x - 252);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 252, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 252, 1) == Link__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 252)} MINUS_LEFT_PTR(x, 1, 252) == Link__DEVICE_EXTENSIONInv(x));
+function NumAssocClass__GLOBALS(int) returns (int);
+function NumAssocClass__GLOBALSInv(int) returns (int);
+function _S_NumAssocClass__GLOBALS([int]bool) returns ([int]bool);
+function _S_NumAssocClass__GLOBALSInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {NumAssocClass__GLOBALSInv(NumAssocClass__GLOBALS(x))} NumAssocClass__GLOBALSInv(NumAssocClass__GLOBALS(x)) == x);
+axiom (forall x:int :: {NumAssocClass__GLOBALSInv(x)} NumAssocClass__GLOBALS(NumAssocClass__GLOBALSInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_NumAssocClass__GLOBALS(S)[x]} _S_NumAssocClass__GLOBALS(S)[x] <==> S[NumAssocClass__GLOBALSInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_NumAssocClass__GLOBALSInv(S)[x]} _S_NumAssocClass__GLOBALSInv(S)[x] <==> S[NumAssocClass__GLOBALS(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_NumAssocClass__GLOBALS(S)} S[x] ==> _S_NumAssocClass__GLOBALS(S)[NumAssocClass__GLOBALS(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_NumAssocClass__GLOBALSInv(S)} S[x] ==> _S_NumAssocClass__GLOBALSInv(S)[NumAssocClass__GLOBALSInv(x)]);
+
+axiom (forall x:int :: {NumAssocClass__GLOBALS(x)} NumAssocClass__GLOBALS(x) == x + 12);
+axiom (forall x:int :: {NumAssocClass__GLOBALSInv(x)} NumAssocClass__GLOBALSInv(x) == x - 12);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 12, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 12, 1) == NumAssocClass__GLOBALSInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 12)} MINUS_LEFT_PTR(x, 1, 12) == NumAssocClass__GLOBALSInv(x));
+function PnP__DEVICE_EXTENSION(int) returns (int);
+function PnP__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_PnP__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_PnP__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {PnP__DEVICE_EXTENSIONInv(PnP__DEVICE_EXTENSION(x))} PnP__DEVICE_EXTENSIONInv(PnP__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {PnP__DEVICE_EXTENSIONInv(x)} PnP__DEVICE_EXTENSION(PnP__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_PnP__DEVICE_EXTENSION(S)[x]} _S_PnP__DEVICE_EXTENSION(S)[x] <==> S[PnP__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_PnP__DEVICE_EXTENSIONInv(S)[x]} _S_PnP__DEVICE_EXTENSIONInv(S)[x] <==> S[PnP__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_PnP__DEVICE_EXTENSION(S)} S[x] ==> _S_PnP__DEVICE_EXTENSION(S)[PnP__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_PnP__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_PnP__DEVICE_EXTENSIONInv(S)[PnP__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {PnP__DEVICE_EXTENSION(x)} PnP__DEVICE_EXTENSION(x) == x + 104);
+axiom (forall x:int :: {PnP__DEVICE_EXTENSIONInv(x)} PnP__DEVICE_EXTENSIONInv(x) == x - 104);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 104, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 104, 1) == PnP__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 104)} MINUS_LEFT_PTR(x, 1, 104) == PnP__DEVICE_EXTENSIONInv(x));
+function Port__PORT(int) returns (int);
+function Port__PORTInv(int) returns (int);
+function _S_Port__PORT([int]bool) returns ([int]bool);
+function _S_Port__PORTInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {Port__PORTInv(Port__PORT(x))} Port__PORTInv(Port__PORT(x)) == x);
+axiom (forall x:int :: {Port__PORTInv(x)} Port__PORT(Port__PORTInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_Port__PORT(S)[x]} _S_Port__PORT(S)[x] <==> S[Port__PORTInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_Port__PORTInv(S)[x]} _S_Port__PORTInv(S)[x] <==> S[Port__PORT(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Port__PORT(S)} S[x] ==> _S_Port__PORT(S)[Port__PORT(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Port__PORTInv(S)} S[x] ==> _S_Port__PORTInv(S)[Port__PORTInv(x)]);
+
+axiom (forall x:int :: {Port__PORT(x)} Port__PORT(x) == x + 4);
+axiom (forall x:int :: {Port__PORTInv(x)} Port__PORTInv(x) == x - 4);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 4, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 4, 1) == Port__PORTInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 4)} MINUS_LEFT_PTR(x, 1, 4) == Port__PORTInv(x));
+function RegistryPath__GLOBALS(int) returns (int);
+function RegistryPath__GLOBALSInv(int) returns (int);
+function _S_RegistryPath__GLOBALS([int]bool) returns ([int]bool);
+function _S_RegistryPath__GLOBALSInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {RegistryPath__GLOBALSInv(RegistryPath__GLOBALS(x))} RegistryPath__GLOBALSInv(RegistryPath__GLOBALS(x)) == x);
+axiom (forall x:int :: {RegistryPath__GLOBALSInv(x)} RegistryPath__GLOBALS(RegistryPath__GLOBALSInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_RegistryPath__GLOBALS(S)[x]} _S_RegistryPath__GLOBALS(S)[x] <==> S[RegistryPath__GLOBALSInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_RegistryPath__GLOBALSInv(S)[x]} _S_RegistryPath__GLOBALSInv(S)[x] <==> S[RegistryPath__GLOBALS(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_RegistryPath__GLOBALS(S)} S[x] ==> _S_RegistryPath__GLOBALS(S)[RegistryPath__GLOBALS(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_RegistryPath__GLOBALSInv(S)} S[x] ==> _S_RegistryPath__GLOBALSInv(S)[RegistryPath__GLOBALSInv(x)]);
+
+axiom (forall x:int :: {RegistryPath__GLOBALS(x)} RegistryPath__GLOBALS(x) == x + 336);
+axiom (forall x:int :: {RegistryPath__GLOBALSInv(x)} RegistryPath__GLOBALSInv(x) == x - 336);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 336, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 336, 1) == RegistryPath__GLOBALSInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 336)} MINUS_LEFT_PTR(x, 1, 336) == RegistryPath__GLOBALSInv(x));
+function Self__DEVICE_EXTENSION(int) returns (int);
+function Self__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_Self__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_Self__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {Self__DEVICE_EXTENSIONInv(Self__DEVICE_EXTENSION(x))} Self__DEVICE_EXTENSIONInv(Self__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {Self__DEVICE_EXTENSIONInv(x)} Self__DEVICE_EXTENSION(Self__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_Self__DEVICE_EXTENSION(S)[x]} _S_Self__DEVICE_EXTENSION(S)[x] <==> S[Self__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_Self__DEVICE_EXTENSIONInv(S)[x]} _S_Self__DEVICE_EXTENSIONInv(S)[x] <==> S[Self__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Self__DEVICE_EXTENSION(S)} S[x] ==> _S_Self__DEVICE_EXTENSION(S)[Self__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Self__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_Self__DEVICE_EXTENSIONInv(S)[Self__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {Self__DEVICE_EXTENSION(x)} Self__DEVICE_EXTENSION(x) == x + 0);
+axiom (forall x:int :: {Self__DEVICE_EXTENSIONInv(x)} Self__DEVICE_EXTENSIONInv(x) == x - 0);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 0, 1) == Self__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 0)} MINUS_LEFT_PTR(x, 1, 0) == Self__DEVICE_EXTENSIONInv(x));
+function SpinLock__DEVICE_EXTENSION(int) returns (int);
+function SpinLock__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_SpinLock__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_SpinLock__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {SpinLock__DEVICE_EXTENSIONInv(SpinLock__DEVICE_EXTENSION(x))} SpinLock__DEVICE_EXTENSIONInv(SpinLock__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {SpinLock__DEVICE_EXTENSIONInv(x)} SpinLock__DEVICE_EXTENSION(SpinLock__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_SpinLock__DEVICE_EXTENSION(S)[x]} _S_SpinLock__DEVICE_EXTENSION(S)[x] <==> S[SpinLock__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_SpinLock__DEVICE_EXTENSIONInv(S)[x]} _S_SpinLock__DEVICE_EXTENSIONInv(S)[x] <==> S[SpinLock__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_SpinLock__DEVICE_EXTENSION(S)} S[x] ==> _S_SpinLock__DEVICE_EXTENSION(S)[SpinLock__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_SpinLock__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_SpinLock__DEVICE_EXTENSIONInv(S)[SpinLock__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {SpinLock__DEVICE_EXTENSION(x)} SpinLock__DEVICE_EXTENSION(x) == x + 152);
+axiom (forall x:int :: {SpinLock__DEVICE_EXTENSIONInv(x)} SpinLock__DEVICE_EXTENSIONInv(x) == x - 152);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 152, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 152, 1) == SpinLock__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 152)} MINUS_LEFT_PTR(x, 1, 152) == SpinLock__DEVICE_EXTENSIONInv(x));
+function StackSize__DEVICE_OBJECT(int) returns (int);
+function StackSize__DEVICE_OBJECTInv(int) returns (int);
+function _S_StackSize__DEVICE_OBJECT([int]bool) returns ([int]bool);
+function _S_StackSize__DEVICE_OBJECTInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {StackSize__DEVICE_OBJECTInv(StackSize__DEVICE_OBJECT(x))} StackSize__DEVICE_OBJECTInv(StackSize__DEVICE_OBJECT(x)) == x);
+axiom (forall x:int :: {StackSize__DEVICE_OBJECTInv(x)} StackSize__DEVICE_OBJECT(StackSize__DEVICE_OBJECTInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_StackSize__DEVICE_OBJECT(S)[x]} _S_StackSize__DEVICE_OBJECT(S)[x] <==> S[StackSize__DEVICE_OBJECTInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_StackSize__DEVICE_OBJECTInv(S)[x]} _S_StackSize__DEVICE_OBJECTInv(S)[x] <==> S[StackSize__DEVICE_OBJECT(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_StackSize__DEVICE_OBJECT(S)} S[x] ==> _S_StackSize__DEVICE_OBJECT(S)[StackSize__DEVICE_OBJECT(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_StackSize__DEVICE_OBJECTInv(S)} S[x] ==> _S_StackSize__DEVICE_OBJECTInv(S)[StackSize__DEVICE_OBJECTInv(x)]);
+
+axiom (forall x:int :: {StackSize__DEVICE_OBJECT(x)} StackSize__DEVICE_OBJECT(x) == x + 48);
+axiom (forall x:int :: {StackSize__DEVICE_OBJECTInv(x)} StackSize__DEVICE_OBJECTInv(x) == x - 48);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 48, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 48, 1) == StackSize__DEVICE_OBJECTInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 48)} MINUS_LEFT_PTR(x, 1, 48) == StackSize__DEVICE_OBJECTInv(x));
+function Started__DEVICE_EXTENSION(int) returns (int);
+function Started__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_Started__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_Started__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {Started__DEVICE_EXTENSIONInv(Started__DEVICE_EXTENSION(x))} Started__DEVICE_EXTENSIONInv(Started__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {Started__DEVICE_EXTENSIONInv(x)} Started__DEVICE_EXTENSION(Started__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_Started__DEVICE_EXTENSION(S)[x]} _S_Started__DEVICE_EXTENSION(S)[x] <==> S[Started__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_Started__DEVICE_EXTENSIONInv(S)[x]} _S_Started__DEVICE_EXTENSIONInv(S)[x] <==> S[Started__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Started__DEVICE_EXTENSION(S)} S[x] ==> _S_Started__DEVICE_EXTENSION(S)[Started__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_Started__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_Started__DEVICE_EXTENSIONInv(S)[Started__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {Started__DEVICE_EXTENSION(x)} Started__DEVICE_EXTENSION(x) == x + 105);
+axiom (forall x:int :: {Started__DEVICE_EXTENSIONInv(x)} Started__DEVICE_EXTENSIONInv(x) == x - 105);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 105, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 105, 1) == Started__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 105)} MINUS_LEFT_PTR(x, 1, 105) == Started__DEVICE_EXTENSIONInv(x));
+function TopPort__DEVICE_EXTENSION(int) returns (int);
+function TopPort__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_TopPort__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_TopPort__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {TopPort__DEVICE_EXTENSIONInv(TopPort__DEVICE_EXTENSION(x))} TopPort__DEVICE_EXTENSIONInv(TopPort__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {TopPort__DEVICE_EXTENSIONInv(x)} TopPort__DEVICE_EXTENSION(TopPort__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_TopPort__DEVICE_EXTENSION(S)[x]} _S_TopPort__DEVICE_EXTENSION(S)[x] <==> S[TopPort__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_TopPort__DEVICE_EXTENSIONInv(S)[x]} _S_TopPort__DEVICE_EXTENSIONInv(S)[x] <==> S[TopPort__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_TopPort__DEVICE_EXTENSION(S)} S[x] ==> _S_TopPort__DEVICE_EXTENSION(S)[TopPort__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_TopPort__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_TopPort__DEVICE_EXTENSIONInv(S)[TopPort__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {TopPort__DEVICE_EXTENSION(x)} TopPort__DEVICE_EXTENSION(x) == x + 8);
+axiom (forall x:int :: {TopPort__DEVICE_EXTENSIONInv(x)} TopPort__DEVICE_EXTENSIONInv(x) == x - 8);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 8, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 8, 1) == TopPort__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 8)} MINUS_LEFT_PTR(x, 1, 8) == TopPort__DEVICE_EXTENSIONInv(x));
+function UnitId__DEVICE_EXTENSION(int) returns (int);
+function UnitId__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_UnitId__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_UnitId__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {UnitId__DEVICE_EXTENSIONInv(UnitId__DEVICE_EXTENSION(x))} UnitId__DEVICE_EXTENSIONInv(UnitId__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {UnitId__DEVICE_EXTENSIONInv(x)} UnitId__DEVICE_EXTENSION(UnitId__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_UnitId__DEVICE_EXTENSION(S)[x]} _S_UnitId__DEVICE_EXTENSION(S)[x] <==> S[UnitId__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_UnitId__DEVICE_EXTENSIONInv(S)[x]} _S_UnitId__DEVICE_EXTENSIONInv(S)[x] <==> S[UnitId__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_UnitId__DEVICE_EXTENSION(S)} S[x] ==> _S_UnitId__DEVICE_EXTENSION(S)[UnitId__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_UnitId__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_UnitId__DEVICE_EXTENSIONInv(S)[UnitId__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {UnitId__DEVICE_EXTENSION(x)} UnitId__DEVICE_EXTENSION(x) == x + 176);
+axiom (forall x:int :: {UnitId__DEVICE_EXTENSIONInv(x)} UnitId__DEVICE_EXTENSIONInv(x) == x - 176);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 176, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 176, 1) == UnitId__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 176)} MINUS_LEFT_PTR(x, 1, 176) == UnitId__DEVICE_EXTENSIONInv(x));
+function WaitWakeSpinLock__DEVICE_EXTENSION(int) returns (int);
+function WaitWakeSpinLock__DEVICE_EXTENSIONInv(int) returns (int);
+function _S_WaitWakeSpinLock__DEVICE_EXTENSION([int]bool) returns ([int]bool);
+function _S_WaitWakeSpinLock__DEVICE_EXTENSIONInv([int]bool) returns ([int]bool);
+
+axiom (forall x:int :: {WaitWakeSpinLock__DEVICE_EXTENSIONInv(WaitWakeSpinLock__DEVICE_EXTENSION(x))} WaitWakeSpinLock__DEVICE_EXTENSIONInv(WaitWakeSpinLock__DEVICE_EXTENSION(x)) == x);
+axiom (forall x:int :: {WaitWakeSpinLock__DEVICE_EXTENSIONInv(x)} WaitWakeSpinLock__DEVICE_EXTENSION(WaitWakeSpinLock__DEVICE_EXTENSIONInv(x)) == x);
+
+axiom (forall x:int, S:[int]bool :: {_S_WaitWakeSpinLock__DEVICE_EXTENSION(S)[x]} _S_WaitWakeSpinLock__DEVICE_EXTENSION(S)[x] <==> S[WaitWakeSpinLock__DEVICE_EXTENSIONInv(x)]);
+axiom (forall x:int, S:[int]bool :: {_S_WaitWakeSpinLock__DEVICE_EXTENSIONInv(S)[x]} _S_WaitWakeSpinLock__DEVICE_EXTENSIONInv(S)[x] <==> S[WaitWakeSpinLock__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_WaitWakeSpinLock__DEVICE_EXTENSION(S)} S[x] ==> _S_WaitWakeSpinLock__DEVICE_EXTENSION(S)[WaitWakeSpinLock__DEVICE_EXTENSION(x)]);
+axiom (forall x:int, S:[int]bool :: {S[x], _S_WaitWakeSpinLock__DEVICE_EXTENSIONInv(S)} S[x] ==> _S_WaitWakeSpinLock__DEVICE_EXTENSIONInv(S)[WaitWakeSpinLock__DEVICE_EXTENSIONInv(x)]);
+
+axiom (forall x:int :: {WaitWakeSpinLock__DEVICE_EXTENSION(x)} WaitWakeSpinLock__DEVICE_EXTENSION(x) == x + 108);
+axiom (forall x:int :: {WaitWakeSpinLock__DEVICE_EXTENSIONInv(x)} WaitWakeSpinLock__DEVICE_EXTENSIONInv(x) == x - 108);
+axiom (forall x:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, 108, 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, 108, 1) == WaitWakeSpinLock__DEVICE_EXTENSIONInv(x));
+axiom (forall x:int :: {MINUS_LEFT_PTR(x, 1, 108)} MINUS_LEFT_PTR(x, 1, 108) == WaitWakeSpinLock__DEVICE_EXTENSIONInv(x));
+function MINUS_BOTH_PTR_OR_BOTH_INT(a:int, b:int, size:int) returns (int);
+axiom (forall a:int, b:int, size:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(a,b,size)}
+size * MINUS_BOTH_PTR_OR_BOTH_INT(a,b,size) <= a - b && a - b < size * (MINUS_BOTH_PTR_OR_BOTH_INT(a,b,size) + 1));
+
+function MINUS_LEFT_PTR(a:int, a_size:int, b:int) returns (int);
+axiom(forall a:int, a_size:int, b:int :: {MINUS_LEFT_PTR(a,a_size,b)} MINUS_LEFT_PTR(a,a_size,b) == a - a_size * b);
+
+function PLUS(a:int, a_size:int, b:int) returns (int);
+axiom (forall a:int, a_size:int, b:int :: {PLUS(a,a_size,b)} PLUS(a,a_size,b) == a + a_size * b);
+
+function MULT(a:int, b:int) returns (int); // a*b
+axiom(forall a:int, b:int :: {MULT(a,b)} MULT(a,b) == a * b);
+
+function DIV(a:int, b:int) returns (int); // a/b
+
+axiom(forall a:int, b:int :: {DIV(a,b)}
+a >= 0 && b > 0 ==> b * DIV(a,b) <= a && a < b * (DIV(a,b) + 1)
+);
+
+axiom(forall a:int, b:int :: {DIV(a,b)}
+a >= 0 && b < 0 ==> b * DIV(a,b) <= a && a < b * (DIV(a,b) - 1)
+);
+
+axiom(forall a:int, b:int :: {DIV(a,b)}
+a < 0 && b > 0 ==> b * DIV(a,b) >= a && a > b * (DIV(a,b) - 1)
+);
+
+axiom(forall a:int, b:int :: {DIV(a,b)}
+a < 0 && b < 0 ==> b * DIV(a,b) >= a && a > b * (DIV(a,b) + 1)
+);
+
+function BINARY_BOTH_INT(a:int, b:int) returns (int);
+
+function POW2(a:int) returns (bool);
+axiom POW2(1);
+axiom POW2(2);
+axiom POW2(4);
+axiom POW2(8);
+axiom POW2(16);
+axiom POW2(32);
+axiom POW2(64);
+axiom POW2(128);
+axiom POW2(256);
+axiom POW2(512);
+axiom POW2(1024);
+axiom POW2(2048);
+axiom POW2(4096);
+axiom POW2(8192);
+axiom POW2(16384);
+axiom POW2(32768);
+axiom POW2(65536);
+axiom POW2(131072);
+axiom POW2(262144);
+axiom POW2(524288);
+axiom POW2(1048576);
+axiom POW2(2097152);
+axiom POW2(4194304);
+axiom POW2(8388608);
+axiom POW2(16777216);
+axiom POW2(33554432);
+
+function choose(a:bool, b:int, c:int) returns (x:int);
+axiom(forall a:bool, b:int, c:int :: {choose(a,b,c)} a ==> choose(a,b,c) == b);
+axiom(forall a:bool, b:int, c:int :: {choose(a,b,c)} !a ==> choose(a,b,c) == c);
+
+function BIT_BAND(a:int, b:int) returns (x:int);
+axiom(forall a:int, b:int :: {BIT_BAND(a,b)} a == b ==> BIT_BAND(a,b) == a);
+axiom(forall a:int, b:int :: {BIT_BAND(a,b)} POW2(a) && POW2(b) && a != b ==> BIT_BAND(a,b) == 0);
+axiom(forall a:int, b:int :: {BIT_BAND(a,b)} a == 0 || b == 0 ==> BIT_BAND(a,b) == 0);
+
+function BIT_BOR(a:int, b:int) returns (x:int);
+
+function BIT_BXOR(a:int, b:int) returns (x:int);
+
+function BIT_BNOT(a:int) returns (int);
+
+function LIFT(a:bool) returns (int);
+axiom(forall a:bool :: {LIFT(a)} a <==> LIFT(a) != 0);
+
+function NOT(a:int) returns (int);
+axiom(forall a:int :: {NOT(a)} a == 0 ==> NOT(a) != 0);
+axiom(forall a:int :: {NOT(a)} a != 0 ==> NOT(a) == 0);
+
+function NULL_CHECK(a:int) returns (int);
+axiom(forall a:int :: {NULL_CHECK(a)} a == 0 ==> NULL_CHECK(a) != 0);
+axiom(forall a:int :: {NULL_CHECK(a)} a != 0 ==> NULL_CHECK(a) == 0);
+
+
+
+
+procedure havoc_assert(i:int);
+requires (i != 0);
+
+procedure havoc_assume(i:int);
+ensures (i != 0);
+
+procedure __HAVOC_free(a:int);
+modifies alloc;
+ensures (forall x:int :: {alloc[x]} x == a || old(alloc)[x] == alloc[x]);
+ensures (alloc[a] == FREED);
+// Additional checks guarded by tranlator flags
+// requires alloc[a] == ALLOCATED;
+// requires Base(a) == a;
+
+procedure __HAVOC_malloc(obj_size:int) returns (new:int);
+requires obj_size >= 0;
+modifies alloc;
+ensures (new > 0);
+ensures (forall x:int :: {Base(x)} new <= x && x < new+obj_size ==> Base(x) == new);
+ensures (forall x:int :: {alloc[x]} x == new || old(alloc)[x] == alloc[x]);
+ensures old(alloc)[new] == UNALLOCATED && alloc[new] == ALLOCATED;
+
+procedure nondet_choice() returns (x:int);
+
+procedure _strdup(str:int) returns (new:int);
+
+procedure _xstrcasecmp(a0:int, a1:int) returns (ret:int);
+
+procedure _xstrcmp(a0:int, a1:int) returns (ret:int);
+
+var Res_DEVICE_STACK:[int]int;
+var Res_DEV_EXTN:[int]int;
+var Res_DEV_OBJ_INIT:[int]int;
+var Res_SPIN_LOCK:[int]int;
+
+
+
+////////////////////
+// Between predicate
+////////////////////
+function ReachBetween(f: [int]int, x: int, y: int, z: int) returns (bool);
+function ReachAvoiding(f: [int]int, x: int, y: int, z: int) returns (bool);
+
+
+//////////////////////////
+// Between set constructor
+//////////////////////////
+function ReachBetweenSet(f: [int]int, x: int, z: int) returns ([int]bool);
+
+////////////////////////////////////////////////////
+// axioms relating ReachBetween and ReachBetweenSet
+////////////////////////////////////////////////////
+axiom(forall f: [int]int, x: int, y: int, z: int :: {ReachBetweenSet(f, x, z)[y]} ReachBetweenSet(f, x, z)[y] <==> ReachBetween(f, x, y, z));
+axiom(forall f: [int]int, x: int, y: int, z: int :: {ReachBetween(f, x, y, z), ReachBetweenSet(f, x, z)} ReachBetween(f, x, y, z) ==> ReachBetweenSet(f, x, z)[y]);
+axiom(forall f: [int]int, x: int, z: int :: {ReachBetweenSet(f, x, z)} ReachBetween(f, x, x, x));
+
+
+//////////////////////////
+// Axioms for ReachBetween
+//////////////////////////
+
+// reflexive
+axiom(forall f: [int]int, x: int :: ReachBetween(f, x, x, x));
+
+// step
+//axiom(forall f: [int]int, x: int :: {f[x]} ReachBetween(f, x, f[x], f[x]));
+axiom(forall f: [int]int, x: int, y: int, z: int, w:int :: {ReachBetween(f, y, z, w), f[x]} ReachBetween(f, x, f[x], f[x]));
+
+// reach
+axiom(forall f: [int]int, x: int, y: int :: {f[x], ReachBetween(f, x, y, y)} ReachBetween(f, x, y, y) ==> x == y || ReachBetween(f, x, f[x], y));
+
+// cycle
+axiom(forall f: [int]int, x: int, y:int :: {f[x], ReachBetween(f, x, y, y)} f[x] == x && ReachBetween(f, x, y, y) ==> x == y);
+
+// sandwich
+axiom(forall f: [int]int, x: int, y: int :: {ReachBetween(f, x, y, x)} ReachBetween(f, x, y, x) ==> x == y);
+
+// order1
+axiom(forall f: [int]int, x: int, y: int, z: int :: {ReachBetween(f, x, y, y), ReachBetween(f, x, z, z)} ReachBetween(f, x, y, y) && ReachBetween(f, x, z, z) ==> ReachBetween(f, x, y, z) || ReachBetween(f, x, z, y));
+
+// order2
+axiom(forall f: [int]int, x: int, y: int, z: int :: {ReachBetween(f, x, y, z)} ReachBetween(f, x, y, z) ==> ReachBetween(f, x, y, y) && ReachBetween(f, y, z, z));
+
+// transitive1
+axiom(forall f: [int]int, x: int, y: int, z: int :: {ReachBetween(f, x, y, y), ReachBetween(f, y, z, z)} ReachBetween(f, x, y, y) && ReachBetween(f, y, z, z) ==> ReachBetween(f, x, z, z));
+
+// transitive2
+axiom(forall f: [int]int, x: int, y: int, z: int, w: int :: {ReachBetween(f, x, y, z), ReachBetween(f, y, w, z)} ReachBetween(f, x, y, z) && ReachBetween(f, y, w, z) ==> ReachBetween(f, x, y, w) && ReachBetween(f, x, w, z));
+
+// transitive3
+axiom(forall f: [int]int, x: int, y: int, z: int, w: int :: {ReachBetween(f, x, y, z), ReachBetween(f, x, w, y)} ReachBetween(f, x, y, z) && ReachBetween(f, x, w, y) ==> ReachBetween(f, x, w, z) && ReachBetween(f, w, y, z));
+
+// This axiom is required to deal with the incompleteness of the trigger for the reflexive axiom.
+// It cannot be proved using the rest of the axioms.
+axiom(forall f: [int]int, u:int, x: int :: {ReachBetween(f, u, x, x)} ReachBetween(f, u, x, x) ==> ReachBetween(f, u, u, x));
+
+// relation between ReachAvoiding and ReachBetween
+axiom(forall f: [int]int, x: int, y: int, z: int :: {ReachAvoiding(f, x, y, z)}{ReachBetween(f, x, y, z)} ReachAvoiding(f, x, y, z) <==> (ReachBetween(f, x, y, z) || (ReachBetween(f, x, y, y) && !ReachBetween(f, x, z, z))));
+
+// update
+axiom(forall f: [int]int, u: int, v: int, x: int, p: int, q: int :: {ReachAvoiding(f[p := q], u, v, x)} ReachAvoiding(f[p := q], u, v, x) <==> ((ReachAvoiding(f, u, v, p) && ReachAvoiding(f, u, v, x)) || (ReachAvoiding(f, u, p, x) && p != x && ReachAvoiding(f, q, v, p) && ReachAvoiding(f, q, v, x))));
+ ///////////////////////////////
+ // Shifts for linking fields
+ ///////////////////////////////
+function Shift_Flink__LIST_ENTRY(f: [int]int) returns ([int]int);
+axiom( forall f: [int]int, __x:int :: {f[Flink__LIST_ENTRY(__x)],Shift_Flink__LIST_ENTRY(f)} {Shift_Flink__LIST_ENTRY(f)[__x]} Shift_Flink__LIST_ENTRY(f)[__x] == f[Flink__LIST_ENTRY(__x)]);
+axiom(forall f: [int]int, __x:int, __v:int :: {Shift_Flink__LIST_ENTRY(f[Flink__LIST_ENTRY(__x) := __v])} Shift_Flink__LIST_ENTRY(f[Flink__LIST_ENTRY(__x) := __v]) == Shift_Flink__LIST_ENTRY(f)[__x := __v]);
+
+const unique Globals : int;
+axiom(Globals != 0);
+
+
+procedure ExFreePoolWithTag($P$1$14901.35$ExFreePoolWithTag$81:int, $Tag$2$14902.15$ExFreePoolWithTag$81:int);
+
+//TAG: ensures __preserves_mem
+ensures(Mem == old(Mem));
+//TAG: ensures __preserves_resource("DEV_OBJ_INIT") && __preserves_resource("DEV_EXTN")
+ensures((Res_DEV_OBJ_INIT == old(Res_DEV_OBJ_INIT)) && (Res_DEV_EXTN == old(Res_DEV_EXTN)));
+
+modifies Res_DEVICE_STACK;
+
+//TAG: net change in resource DEVICE_STACK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEVICE_STACK[r]} (Empty()[r]) || old(Res_DEVICE_STACK)[r] == Res_DEVICE_STACK[r]));
+modifies Res_DEV_EXTN;
+
+//TAG: net change in resource DEV_EXTN only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_EXTN[r]} (Empty()[r]) || old(Res_DEV_EXTN)[r] == Res_DEV_EXTN[r]));
+modifies Res_DEV_OBJ_INIT;
+
+//TAG: net change in resource DEV_OBJ_INIT only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_OBJ_INIT[r]} (Empty()[r]) || old(Res_DEV_OBJ_INIT)[r] == Res_DEV_OBJ_INIT[r]));
+modifies Res_SPIN_LOCK;
+
+//TAG: net change in resource SPIN_LOCK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_SPIN_LOCK[r]} (Empty()[r]) || old(Res_SPIN_LOCK)[r] == Res_SPIN_LOCK[r]));
+//TAG: updated memory locations at Mem[T.MinorFunction__IO_STACK_LOCATION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.MinorFunction__IO_STACK_LOCATION][_m]} (Empty()[_m]) || Mem[T.MinorFunction__IO_STACK_LOCATION][_m] == old(Mem)[T.MinorFunction__IO_STACK_LOCATION][_m]));
+//TAG: updated memory locations at Mem[T.CurrentStackLocation___unnamed_4_a7aa989c] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.CurrentStackLocation___unnamed_4_a7aa989c][_m]} (Empty()[_m]) || Mem[T.CurrentStackLocation___unnamed_4_a7aa989c][_m] == old(Mem)[T.CurrentStackLocation___unnamed_4_a7aa989c][_m]));
+//TAG: updated memory locations at Mem[T.DeviceExtension__DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.DeviceExtension__DEVICE_OBJECT][_m] == old(Mem)[T.DeviceExtension__DEVICE_OBJECT][_m]));
+//TAG: updated memory locations at Mem[T.Self__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Self__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Self__DEVICE_EXTENSION][_m] == old(Mem)[T.Self__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.Started__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Started__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Started__DEVICE_EXTENSION][_m] == old(Mem)[T.Started__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.GrandMaster__GLOBALS] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.GrandMaster__GLOBALS][_m]} (Empty()[_m]) || Mem[T.GrandMaster__GLOBALS][_m] == old(Mem)[T.GrandMaster__GLOBALS][_m]));
+//TAG: updated memory locations at Mem[T.P_DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.P_DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.P_DEVICE_OBJECT][_m] == old(Mem)[T.P_DEVICE_OBJECT][_m]));
+
+//TAG: havoc memory locations by default
+modifies Mem;
+
+
+procedure IoAllocateIrp($StackSize$1$20453.15$IoAllocateIrp$81:int, $ChargeQuota$2$20454.17$IoAllocateIrp$81:int) returns ($result.IoAllocateIrp$20452.0$1$:int);
+
+//TAG: ensures __preserves_mem
+ensures(Mem == old(Mem));
+//TAG: ensures __preserves_resource("DEV_OBJ_INIT") && __preserves_resource("DEV_EXTN")
+ensures((Res_DEV_OBJ_INIT == old(Res_DEV_OBJ_INIT)) && (Res_DEV_EXTN == old(Res_DEV_EXTN)));
+
+modifies Res_DEVICE_STACK;
+
+//TAG: net change in resource DEVICE_STACK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEVICE_STACK[r]} (Empty()[r]) || old(Res_DEVICE_STACK)[r] == Res_DEVICE_STACK[r]));
+modifies Res_DEV_EXTN;
+
+//TAG: net change in resource DEV_EXTN only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_EXTN[r]} (Empty()[r]) || old(Res_DEV_EXTN)[r] == Res_DEV_EXTN[r]));
+modifies Res_DEV_OBJ_INIT;
+
+//TAG: net change in resource DEV_OBJ_INIT only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_OBJ_INIT[r]} (Empty()[r]) || old(Res_DEV_OBJ_INIT)[r] == Res_DEV_OBJ_INIT[r]));
+modifies Res_SPIN_LOCK;
+
+//TAG: net change in resource SPIN_LOCK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_SPIN_LOCK[r]} (Empty()[r]) || old(Res_SPIN_LOCK)[r] == Res_SPIN_LOCK[r]));
+//TAG: updated memory locations at Mem[T.MinorFunction__IO_STACK_LOCATION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.MinorFunction__IO_STACK_LOCATION][_m]} (Empty()[_m]) || Mem[T.MinorFunction__IO_STACK_LOCATION][_m] == old(Mem)[T.MinorFunction__IO_STACK_LOCATION][_m]));
+//TAG: updated memory locations at Mem[T.CurrentStackLocation___unnamed_4_a7aa989c] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.CurrentStackLocation___unnamed_4_a7aa989c][_m]} (Empty()[_m]) || Mem[T.CurrentStackLocation___unnamed_4_a7aa989c][_m] == old(Mem)[T.CurrentStackLocation___unnamed_4_a7aa989c][_m]));
+//TAG: updated memory locations at Mem[T.DeviceExtension__DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.DeviceExtension__DEVICE_OBJECT][_m] == old(Mem)[T.DeviceExtension__DEVICE_OBJECT][_m]));
+//TAG: updated memory locations at Mem[T.Self__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Self__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Self__DEVICE_EXTENSION][_m] == old(Mem)[T.Self__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.Started__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Started__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Started__DEVICE_EXTENSION][_m] == old(Mem)[T.Started__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.GrandMaster__GLOBALS] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.GrandMaster__GLOBALS][_m]} (Empty()[_m]) || Mem[T.GrandMaster__GLOBALS][_m] == old(Mem)[T.GrandMaster__GLOBALS][_m]));
+//TAG: updated memory locations at Mem[T.P_DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.P_DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.P_DEVICE_OBJECT][_m] == old(Mem)[T.P_DEVICE_OBJECT][_m]));
+
+//TAG: havoc memory locations by default
+modifies Mem;
+
+
+procedure IoDeleteDevice($DeviceObject$1$21328.67$IoDeleteDevice$41:int);
+
+//TAG: ensures __preserves_mem
+ensures(Mem == old(Mem));
+//TAG: requires 1 ==> __resource("DEV_OBJ_INIT", DeviceObject) == 1 && __resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)DeviceObject)->DeviceExtension)) == 1
+requires((true) ==> ((Res_DEV_OBJ_INIT[$DeviceObject$1$21328.67$IoDeleteDevice$41] == 1) && (Res_DEV_EXTN[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT($DeviceObject$1$21328.67$IoDeleteDevice$41)]] == 1)));
+//TAG: ensures 1 ==> __resource("DEV_OBJ_INIT", DeviceObject) == 0 && __resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)DeviceObject)->DeviceExtension)) == 0
+ensures((true) ==> ((Res_DEV_OBJ_INIT[$DeviceObject$1$21328.67$IoDeleteDevice$41] == 0) && (Res_DEV_EXTN[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT($DeviceObject$1$21328.67$IoDeleteDevice$41)]] == 0)));
+//TAG: ensures 1 ==> __updates_resource("DEV_OBJ_INIT", DeviceObject, 0) && __updates_resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)DeviceObject)->DeviceExtension), 0)
+ensures((true) ==> ((Res_DEV_OBJ_INIT == old(Res_DEV_OBJ_INIT)[$DeviceObject$1$21328.67$IoDeleteDevice$41 := 0]) && (Res_DEV_EXTN == old(Res_DEV_EXTN)[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT($DeviceObject$1$21328.67$IoDeleteDevice$41)] := 0])));
+//TAG: ensures !1 ==> __resource("DEV_OBJ_INIT", DeviceObject) == __old_resource("DEV_OBJ_INIT", DeviceObject) && __resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)DeviceObject)->DeviceExtension)) == __old_resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)DeviceObject)->DeviceExtension))
+ensures((!(true)) ==> ((Res_DEV_OBJ_INIT[$DeviceObject$1$21328.67$IoDeleteDevice$41] == old(Res_DEV_OBJ_INIT)[$DeviceObject$1$21328.67$IoDeleteDevice$41]) && (Res_DEV_EXTN[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT($DeviceObject$1$21328.67$IoDeleteDevice$41)]] == old(Res_DEV_EXTN)[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT($DeviceObject$1$21328.67$IoDeleteDevice$41)]])));
+//TAG: ensures !1 ==> __preserves_resource("DEV_OBJ_INIT") && __preserves_resource("DEV_EXTN")
+free ensures((!(true)) ==> ((Res_DEV_OBJ_INIT == old(Res_DEV_OBJ_INIT)) && (Res_DEV_EXTN == old(Res_DEV_EXTN))));
+
+modifies Res_DEVICE_STACK;
+
+//TAG: net change in resource DEVICE_STACK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEVICE_STACK[r]} (Empty()[r]) || old(Res_DEVICE_STACK)[r] == Res_DEVICE_STACK[r]));
+modifies Res_DEV_EXTN;
+
+//TAG: net change in resource DEV_EXTN only for: __set_empty, (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)DeviceObject)->DeviceExtension)
+ensures (Subset(Empty(), Union(Union(Empty(), Empty()), Singleton(Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT($DeviceObject$1$21328.67$IoDeleteDevice$41)]))) && (forall r:int :: {Res_DEV_EXTN[r]} (Empty()[r]) || (Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT($DeviceObject$1$21328.67$IoDeleteDevice$41)] == r) || old(Res_DEV_EXTN)[r] == Res_DEV_EXTN[r]));
+modifies Res_DEV_OBJ_INIT;
+
+//TAG: net change in resource DEV_OBJ_INIT only for: __set_empty, DeviceObject
+ensures (Subset(Empty(), Union(Union(Empty(), Empty()), Singleton($DeviceObject$1$21328.67$IoDeleteDevice$41))) && (forall r:int :: {Res_DEV_OBJ_INIT[r]} (Empty()[r]) || ($DeviceObject$1$21328.67$IoDeleteDevice$41 == r) || old(Res_DEV_OBJ_INIT)[r] == Res_DEV_OBJ_INIT[r]));
+modifies Res_SPIN_LOCK;
+
+//TAG: net change in resource SPIN_LOCK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_SPIN_LOCK[r]} (Empty()[r]) || old(Res_SPIN_LOCK)[r] == Res_SPIN_LOCK[r]));
+//TAG: updated memory locations at Mem[T.MinorFunction__IO_STACK_LOCATION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.MinorFunction__IO_STACK_LOCATION][_m]} (Empty()[_m]) || Mem[T.MinorFunction__IO_STACK_LOCATION][_m] == old(Mem)[T.MinorFunction__IO_STACK_LOCATION][_m]));
+//TAG: updated memory locations at Mem[T.CurrentStackLocation___unnamed_4_a7aa989c] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.CurrentStackLocation___unnamed_4_a7aa989c][_m]} (Empty()[_m]) || Mem[T.CurrentStackLocation___unnamed_4_a7aa989c][_m] == old(Mem)[T.CurrentStackLocation___unnamed_4_a7aa989c][_m]));
+//TAG: updated memory locations at Mem[T.DeviceExtension__DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.DeviceExtension__DEVICE_OBJECT][_m] == old(Mem)[T.DeviceExtension__DEVICE_OBJECT][_m]));
+//TAG: updated memory locations at Mem[T.Self__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Self__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Self__DEVICE_EXTENSION][_m] == old(Mem)[T.Self__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.Started__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Started__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Started__DEVICE_EXTENSION][_m] == old(Mem)[T.Started__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.GrandMaster__GLOBALS] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.GrandMaster__GLOBALS][_m]} (Empty()[_m]) || Mem[T.GrandMaster__GLOBALS][_m] == old(Mem)[T.GrandMaster__GLOBALS][_m]));
+//TAG: updated memory locations at Mem[T.P_DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.P_DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.P_DEVICE_OBJECT][_m] == old(Mem)[T.P_DEVICE_OBJECT][_m]));
+
+//TAG: havoc memory locations by default
+modifies Mem;
+
+
+procedure IoFreeIrp($Irp$1$21417.14$IoFreeIrp$41:int);
+
+//TAG: ensures __preserves_mem
+ensures(Mem == old(Mem));
+//TAG: ensures __preserves_resource("DEV_OBJ_INIT") && __preserves_resource("DEV_EXTN")
+ensures((Res_DEV_OBJ_INIT == old(Res_DEV_OBJ_INIT)) && (Res_DEV_EXTN == old(Res_DEV_EXTN)));
+
+modifies Res_DEVICE_STACK;
+
+//TAG: net change in resource DEVICE_STACK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEVICE_STACK[r]} (Empty()[r]) || old(Res_DEVICE_STACK)[r] == Res_DEVICE_STACK[r]));
+modifies Res_DEV_EXTN;
+
+//TAG: net change in resource DEV_EXTN only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_EXTN[r]} (Empty()[r]) || old(Res_DEV_EXTN)[r] == Res_DEV_EXTN[r]));
+modifies Res_DEV_OBJ_INIT;
+
+//TAG: net change in resource DEV_OBJ_INIT only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_OBJ_INIT[r]} (Empty()[r]) || old(Res_DEV_OBJ_INIT)[r] == Res_DEV_OBJ_INIT[r]));
+modifies Res_SPIN_LOCK;
+
+//TAG: net change in resource SPIN_LOCK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_SPIN_LOCK[r]} (Empty()[r]) || old(Res_SPIN_LOCK)[r] == Res_SPIN_LOCK[r]));
+//TAG: updated memory locations at Mem[T.MinorFunction__IO_STACK_LOCATION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.MinorFunction__IO_STACK_LOCATION][_m]} (Empty()[_m]) || Mem[T.MinorFunction__IO_STACK_LOCATION][_m] == old(Mem)[T.MinorFunction__IO_STACK_LOCATION][_m]));
+//TAG: updated memory locations at Mem[T.CurrentStackLocation___unnamed_4_a7aa989c] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.CurrentStackLocation___unnamed_4_a7aa989c][_m]} (Empty()[_m]) || Mem[T.CurrentStackLocation___unnamed_4_a7aa989c][_m] == old(Mem)[T.CurrentStackLocation___unnamed_4_a7aa989c][_m]));
+//TAG: updated memory locations at Mem[T.DeviceExtension__DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.DeviceExtension__DEVICE_OBJECT][_m] == old(Mem)[T.DeviceExtension__DEVICE_OBJECT][_m]));
+//TAG: updated memory locations at Mem[T.Self__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Self__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Self__DEVICE_EXTENSION][_m] == old(Mem)[T.Self__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.Started__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Started__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Started__DEVICE_EXTENSION][_m] == old(Mem)[T.Started__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.GrandMaster__GLOBALS] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.GrandMaster__GLOBALS][_m]} (Empty()[_m]) || Mem[T.GrandMaster__GLOBALS][_m] == old(Mem)[T.GrandMaster__GLOBALS][_m]));
+//TAG: updated memory locations at Mem[T.P_DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.P_DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.P_DEVICE_OBJECT][_m] == old(Mem)[T.P_DEVICE_OBJECT][_m]));
+
+//TAG: havoc memory locations by default
+modifies Mem;
+
+
+procedure MouEnableDisablePort($EnableFlag$1$504.15$MouEnableDisablePort$161:int, $Irp$2$505.15$MouEnableDisablePort$161:int, $Port$3$506.25$MouEnableDisablePort$161:int, $File$4$507.22$MouEnableDisablePort$161:int) returns ($result.MouEnableDisablePort$503.0$1$:int);
+
+//TAG: requires __pforall(_H_x, (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension), __inv_resource("DEV_OBJ_INIT", 1), ((struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension))->Self == _H_x && __resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension)) == 1)
+requires((forall _H_x:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)]} Inverse(Res_DEV_OBJ_INIT,1)[_H_x] ==> ((Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)])] == _H_x) && (Res_DEV_EXTN[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)]] == 1))));
+//TAG: requires __pforall(_H_z, _H_z->Self, __inv_resource("DEV_EXTN", 1), __resource("DEV_OBJ_INIT", _H_z->Self) == 1 && (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)(_H_z->Self))->DeviceExtension) == _H_z)
+requires((forall _H_z:int :: {Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)]} Inverse(Res_DEV_EXTN,1)[_H_z] ==> ((Res_DEV_OBJ_INIT[Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)]] == 1) && (Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)])] == _H_z))));
+//TAG: requires __forall(_H_z, __inv_resource("DEV_EXTN", 1), __resource("SPIN_LOCK", &_H_z->SpinLock) == 0 && __resource("SPIN_LOCK", &_H_z->WaitWakeSpinLock) == 0)
+requires((Subset(Empty(), Inverse(Res_DEV_EXTN,1)) && (forall _H_z : int :: {Inverse(Res_DEV_EXTN,1)[_H_z]} (Inverse(Res_DEV_EXTN,1)[_H_z]) ==> ((Res_SPIN_LOCK[SpinLock__DEVICE_EXTENSION(_H_z)] == 0) && (Res_SPIN_LOCK[WaitWakeSpinLock__DEVICE_EXTENSION(_H_z)] == 0)))));
+//TAG: requires 1 ==> (Globals.GrandMaster != (void *)0 ==> __resource("DEV_EXTN", Globals.GrandMaster) == 1)
+requires((true) ==> ((Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)] != 0) ==> (Res_DEV_EXTN[Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)]] == 1)));
+//TAG: requires 1 ==> __setin(&Globals.LegacyDeviceList, __btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList))
+requires((true) ==> (ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[LegacyDeviceList__GLOBALS(Globals)]));
+//TAG: requires 1 ==> __forall(_H_y, __btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList), _H_y == &Globals.LegacyDeviceList || __resource("DEV_EXTN", CONTAINING_RECORD(_H_y, struct _DEVICE_EXTENSION , Link)) == 1)
+requires((true) ==> ((Subset(Empty(), ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))) && (forall _H_y : int :: {ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[_H_y]} (ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[_H_y]) ==> ((_H_y == LegacyDeviceList__GLOBALS(Globals)) || (Res_DEV_EXTN[MINUS_LEFT_PTR(_H_y, 1, Link__DEVICE_EXTENSION(0))] == 1))))));
+//TAG: requires 1 ==> !__setin(&Globals.GrandMaster->Link, __setminus(__btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList), __set(&Globals.LegacyDeviceList)))
+requires((true) ==> (!(Difference(ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals)), Singleton(LegacyDeviceList__GLOBALS(Globals)))[Link__DEVICE_EXTENSION(Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)])])));
+//TAG: ensures __pforall(_H_x, (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension), __inv_resource("DEV_OBJ_INIT", 1), ((struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension))->Self == _H_x && __resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension)) == 1)
+ensures((forall _H_x:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)]} Inverse(Res_DEV_OBJ_INIT,1)[_H_x] ==> ((Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)])] == _H_x) && (Res_DEV_EXTN[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)]] == 1))));
+//TAG: ensures __pforall(_H_z, _H_z->Self, __inv_resource("DEV_EXTN", 1), __resource("DEV_OBJ_INIT", _H_z->Self) == 1 && (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)(_H_z->Self))->DeviceExtension) == _H_z)
+ensures((forall _H_z:int :: {Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)]} Inverse(Res_DEV_EXTN,1)[_H_z] ==> ((Res_DEV_OBJ_INIT[Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)]] == 1) && (Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)])] == _H_z))));
+//TAG: ensures __forall(_H_z, __inv_resource("DEV_EXTN", 1), __resource("SPIN_LOCK", &_H_z->SpinLock) == 0 && __resource("SPIN_LOCK", &_H_z->WaitWakeSpinLock) == 0)
+ensures((Subset(Empty(), Inverse(Res_DEV_EXTN,1)) && (forall _H_z : int :: {Inverse(Res_DEV_EXTN,1)[_H_z]} (Inverse(Res_DEV_EXTN,1)[_H_z]) ==> ((Res_SPIN_LOCK[SpinLock__DEVICE_EXTENSION(_H_z)] == 0) && (Res_SPIN_LOCK[WaitWakeSpinLock__DEVICE_EXTENSION(_H_z)] == 0)))));
+//TAG: ensures 1 ==> (Globals.GrandMaster != (void *)0 ==> __resource("DEV_EXTN", Globals.GrandMaster) == 1)
+ensures((true) ==> ((Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)] != 0) ==> (Res_DEV_EXTN[Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)]] == 1)));
+//TAG: ensures 1 ==> __setin(&Globals.LegacyDeviceList, __btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList))
+ensures((true) ==> (ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[LegacyDeviceList__GLOBALS(Globals)]));
+//TAG: ensures 1 ==> __forall(_H_y, __btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList), _H_y == &Globals.LegacyDeviceList || __resource("DEV_EXTN", CONTAINING_RECORD(_H_y, struct _DEVICE_EXTENSION , Link)) == 1)
+ensures((true) ==> ((Subset(Empty(), ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))) && (forall _H_y : int :: {ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[_H_y]} (ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[_H_y]) ==> ((_H_y == LegacyDeviceList__GLOBALS(Globals)) || (Res_DEV_EXTN[MINUS_LEFT_PTR(_H_y, 1, Link__DEVICE_EXTENSION(0))] == 1))))));
+//TAG: ensures 1 ==> !__setin(&Globals.GrandMaster->Link, __setminus(__btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList), __set(&Globals.LegacyDeviceList)))
+ensures((true) ==> (!(Difference(ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals)), Singleton(LegacyDeviceList__GLOBALS(Globals)))[Link__DEVICE_EXTENSION(Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)])])));
+//TAG: ensures __preserves_field_map(__offset((*((struct _LIST_ENTRY *)0)).Flink))
+ensures(Mem[T.Flink__LIST_ENTRY] == old(Mem)[T.Flink__LIST_ENTRY]);
+//TAG: ensures __preserves_resource("DEV_OBJ_INIT")
+ensures(Res_DEV_OBJ_INIT == old(Res_DEV_OBJ_INIT));
+//TAG: ensures __preserves_resource("DEV_EXTN")
+ensures(Res_DEV_EXTN == old(Res_DEV_EXTN));
+
+modifies Res_DEVICE_STACK;
+
+//TAG: net change in resource DEVICE_STACK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEVICE_STACK[r]} (Empty()[r]) || old(Res_DEVICE_STACK)[r] == Res_DEVICE_STACK[r]));
+modifies Res_DEV_EXTN;
+
+//TAG: net change in resource DEV_EXTN only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_EXTN[r]} (Empty()[r]) || old(Res_DEV_EXTN)[r] == Res_DEV_EXTN[r]));
+modifies Res_DEV_OBJ_INIT;
+
+//TAG: net change in resource DEV_OBJ_INIT only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_OBJ_INIT[r]} (Empty()[r]) || old(Res_DEV_OBJ_INIT)[r] == Res_DEV_OBJ_INIT[r]));
+modifies Res_SPIN_LOCK;
+
+//TAG: net change in resource SPIN_LOCK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_SPIN_LOCK[r]} (Empty()[r]) || old(Res_SPIN_LOCK)[r] == Res_SPIN_LOCK[r]));
+//TAG: updated memory locations at Mem[T.MinorFunction__IO_STACK_LOCATION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.MinorFunction__IO_STACK_LOCATION][_m]} (Empty()[_m]) || Mem[T.MinorFunction__IO_STACK_LOCATION][_m] == old(Mem)[T.MinorFunction__IO_STACK_LOCATION][_m]));
+//TAG: updated memory locations at Mem[T.CurrentStackLocation___unnamed_4_a7aa989c] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.CurrentStackLocation___unnamed_4_a7aa989c][_m]} (Empty()[_m]) || Mem[T.CurrentStackLocation___unnamed_4_a7aa989c][_m] == old(Mem)[T.CurrentStackLocation___unnamed_4_a7aa989c][_m]));
+//TAG: updated memory locations at Mem[T.DeviceExtension__DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.DeviceExtension__DEVICE_OBJECT][_m] == old(Mem)[T.DeviceExtension__DEVICE_OBJECT][_m]));
+//TAG: updated memory locations at Mem[T.Self__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Self__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Self__DEVICE_EXTENSION][_m] == old(Mem)[T.Self__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.Started__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Started__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Started__DEVICE_EXTENSION][_m] == old(Mem)[T.Started__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.GrandMaster__GLOBALS] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.GrandMaster__GLOBALS][_m]} (Empty()[_m]) || Mem[T.GrandMaster__GLOBALS][_m] == old(Mem)[T.GrandMaster__GLOBALS][_m]));
+//TAG: updated memory locations at Mem[T.P_DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.P_DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.P_DEVICE_OBJECT][_m] == old(Mem)[T.P_DEVICE_OBJECT][_m]));
+
+//TAG: havoc memory locations by default
+modifies Mem;
+
+
+procedure MouseClassCleanupQueue($DeviceObject$1$1052.28$MouseClassCleanupQueue$121:int, $DeviceExtension$2$1053.28$MouseClassCleanupQueue$121:int, $FileObject$3$1054.28$MouseClassCleanupQueue$121:int);
+
+//TAG: requires __resource("DEV_EXTN", DeviceExtension) == 1
+requires(Res_DEV_EXTN[$DeviceExtension$2$1053.28$MouseClassCleanupQueue$121] == 1);
+//TAG: requires __resource("SPIN_LOCK", &((struct _DEVICE_EXTENSION *)DeviceExtension)->WaitWakeSpinLock) == 0
+requires(Res_SPIN_LOCK[WaitWakeSpinLock__DEVICE_EXTENSION($DeviceExtension$2$1053.28$MouseClassCleanupQueue$121)] == 0);
+//TAG: requires __resource("SPIN_LOCK", &((struct _DEVICE_EXTENSION *)DeviceExtension)->SpinLock) == 0
+requires(Res_SPIN_LOCK[SpinLock__DEVICE_EXTENSION($DeviceExtension$2$1053.28$MouseClassCleanupQueue$121)] == 0);
+//TAG: requires __pforall(_H_x, (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension), __inv_resource("DEV_OBJ_INIT", 1), ((struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension))->Self == _H_x && __resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension)) == 1)
+requires((forall _H_x:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)]} Inverse(Res_DEV_OBJ_INIT,1)[_H_x] ==> ((Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)])] == _H_x) && (Res_DEV_EXTN[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)]] == 1))));
+//TAG: requires __pforall(_H_z, _H_z->Self, __inv_resource("DEV_EXTN", 1), __resource("DEV_OBJ_INIT", _H_z->Self) == 1 && (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)(_H_z->Self))->DeviceExtension) == _H_z)
+requires((forall _H_z:int :: {Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)]} Inverse(Res_DEV_EXTN,1)[_H_z] ==> ((Res_DEV_OBJ_INIT[Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)]] == 1) && (Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)])] == _H_z))));
+//TAG: requires __forall(_H_z, __inv_resource("DEV_EXTN", 1), __resource("SPIN_LOCK", &_H_z->SpinLock) == 0 && __resource("SPIN_LOCK", &_H_z->WaitWakeSpinLock) == 0)
+requires((Subset(Empty(), Inverse(Res_DEV_EXTN,1)) && (forall _H_z : int :: {Inverse(Res_DEV_EXTN,1)[_H_z]} (Inverse(Res_DEV_EXTN,1)[_H_z]) ==> ((Res_SPIN_LOCK[SpinLock__DEVICE_EXTENSION(_H_z)] == 0) && (Res_SPIN_LOCK[WaitWakeSpinLock__DEVICE_EXTENSION(_H_z)] == 0)))));
+//TAG: requires 1 ==> (Globals.GrandMaster != (void *)0 ==> __resource("DEV_EXTN", Globals.GrandMaster) == 1)
+requires((true) ==> ((Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)] != 0) ==> (Res_DEV_EXTN[Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)]] == 1)));
+//TAG: requires 1 ==> __setin(&Globals.LegacyDeviceList, __btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList))
+requires((true) ==> (ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[LegacyDeviceList__GLOBALS(Globals)]));
+//TAG: requires 1 ==> __forall(_H_y, __btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList), _H_y == &Globals.LegacyDeviceList || __resource("DEV_EXTN", CONTAINING_RECORD(_H_y, struct _DEVICE_EXTENSION , Link)) == 1)
+requires((true) ==> ((Subset(Empty(), ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))) && (forall _H_y : int :: {ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[_H_y]} (ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[_H_y]) ==> ((_H_y == LegacyDeviceList__GLOBALS(Globals)) || (Res_DEV_EXTN[MINUS_LEFT_PTR(_H_y, 1, Link__DEVICE_EXTENSION(0))] == 1))))));
+//TAG: requires __resource("DEV_OBJ_INIT", DeviceObject) == 1
+requires(Res_DEV_OBJ_INIT[$DeviceObject$1$1052.28$MouseClassCleanupQueue$121] == 1);
+//TAG: ensures __resource("DEV_EXTN", DeviceExtension) == 1
+ensures(Res_DEV_EXTN[$DeviceExtension$2$1053.28$MouseClassCleanupQueue$121] == 1);
+//TAG: ensures __resource("SPIN_LOCK", &((struct _DEVICE_EXTENSION *)DeviceExtension)->WaitWakeSpinLock) == 0
+ensures(Res_SPIN_LOCK[WaitWakeSpinLock__DEVICE_EXTENSION($DeviceExtension$2$1053.28$MouseClassCleanupQueue$121)] == 0);
+//TAG: ensures __resource("SPIN_LOCK", &((struct _DEVICE_EXTENSION *)DeviceExtension)->SpinLock) == 0
+ensures(Res_SPIN_LOCK[SpinLock__DEVICE_EXTENSION($DeviceExtension$2$1053.28$MouseClassCleanupQueue$121)] == 0);
+//TAG: ensures __pforall(_H_x, (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension), __inv_resource("DEV_OBJ_INIT", 1), ((struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension))->Self == _H_x && __resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension)) == 1)
+ensures((forall _H_x:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)]} Inverse(Res_DEV_OBJ_INIT,1)[_H_x] ==> ((Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)])] == _H_x) && (Res_DEV_EXTN[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)]] == 1))));
+//TAG: ensures __pforall(_H_z, _H_z->Self, __inv_resource("DEV_EXTN", 1), __resource("DEV_OBJ_INIT", _H_z->Self) == 1 && (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)(_H_z->Self))->DeviceExtension) == _H_z)
+ensures((forall _H_z:int :: {Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)]} Inverse(Res_DEV_EXTN,1)[_H_z] ==> ((Res_DEV_OBJ_INIT[Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)]] == 1) && (Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)])] == _H_z))));
+//TAG: ensures __forall(_H_z, __inv_resource("DEV_EXTN", 1), __resource("SPIN_LOCK", &_H_z->SpinLock) == 0 && __resource("SPIN_LOCK", &_H_z->WaitWakeSpinLock) == 0)
+ensures((Subset(Empty(), Inverse(Res_DEV_EXTN,1)) && (forall _H_z : int :: {Inverse(Res_DEV_EXTN,1)[_H_z]} (Inverse(Res_DEV_EXTN,1)[_H_z]) ==> ((Res_SPIN_LOCK[SpinLock__DEVICE_EXTENSION(_H_z)] == 0) && (Res_SPIN_LOCK[WaitWakeSpinLock__DEVICE_EXTENSION(_H_z)] == 0)))));
+//TAG: ensures 1 ==> (Globals.GrandMaster != (void *)0 ==> __resource("DEV_EXTN", Globals.GrandMaster) == 1)
+ensures((true) ==> ((Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)] != 0) ==> (Res_DEV_EXTN[Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)]] == 1)));
+//TAG: ensures 1 ==> __setin(&Globals.LegacyDeviceList, __btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList))
+ensures((true) ==> (ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[LegacyDeviceList__GLOBALS(Globals)]));
+//TAG: ensures 1 ==> __forall(_H_y, __btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList), _H_y == &Globals.LegacyDeviceList || __resource("DEV_EXTN", CONTAINING_RECORD(_H_y, struct _DEVICE_EXTENSION , Link)) == 1)
+ensures((true) ==> ((Subset(Empty(), ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))) && (forall _H_y : int :: {ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[_H_y]} (ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[_H_y]) ==> ((_H_y == LegacyDeviceList__GLOBALS(Globals)) || (Res_DEV_EXTN[MINUS_LEFT_PTR(_H_y, 1, Link__DEVICE_EXTENSION(0))] == 1))))));
+//TAG: ensures __preserves_field_map(__offset((*((struct _LIST_ENTRY *)0)).Flink))
+ensures(Mem[T.Flink__LIST_ENTRY] == old(Mem)[T.Flink__LIST_ENTRY]);
+//TAG: ensures __preserves_resource("DEV_OBJ_INIT")
+ensures(Res_DEV_OBJ_INIT == old(Res_DEV_OBJ_INIT));
+//TAG: ensures __preserves_resource("DEV_EXTN")
+ensures(Res_DEV_EXTN == old(Res_DEV_EXTN));
+//TAG: ensures __resource("DEV_OBJ_INIT", DeviceObject) == 1
+ensures(Res_DEV_OBJ_INIT[$DeviceObject$1$1052.28$MouseClassCleanupQueue$121] == 1);
+
+modifies Res_DEVICE_STACK;
+
+//TAG: net change in resource DEVICE_STACK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEVICE_STACK[r]} (Empty()[r]) || old(Res_DEVICE_STACK)[r] == Res_DEVICE_STACK[r]));
+modifies Res_DEV_EXTN;
+
+//TAG: net change in resource DEV_EXTN only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_EXTN[r]} (Empty()[r]) || old(Res_DEV_EXTN)[r] == Res_DEV_EXTN[r]));
+modifies Res_DEV_OBJ_INIT;
+
+//TAG: net change in resource DEV_OBJ_INIT only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_OBJ_INIT[r]} (Empty()[r]) || old(Res_DEV_OBJ_INIT)[r] == Res_DEV_OBJ_INIT[r]));
+modifies Res_SPIN_LOCK;
+
+//TAG: net change in resource SPIN_LOCK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_SPIN_LOCK[r]} (Empty()[r]) || old(Res_SPIN_LOCK)[r] == Res_SPIN_LOCK[r]));
+//TAG: updated memory locations at Mem[T.MinorFunction__IO_STACK_LOCATION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.MinorFunction__IO_STACK_LOCATION][_m]} (Empty()[_m]) || Mem[T.MinorFunction__IO_STACK_LOCATION][_m] == old(Mem)[T.MinorFunction__IO_STACK_LOCATION][_m]));
+//TAG: updated memory locations at Mem[T.CurrentStackLocation___unnamed_4_a7aa989c] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.CurrentStackLocation___unnamed_4_a7aa989c][_m]} (Empty()[_m]) || Mem[T.CurrentStackLocation___unnamed_4_a7aa989c][_m] == old(Mem)[T.CurrentStackLocation___unnamed_4_a7aa989c][_m]));
+//TAG: updated memory locations at Mem[T.DeviceExtension__DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.DeviceExtension__DEVICE_OBJECT][_m] == old(Mem)[T.DeviceExtension__DEVICE_OBJECT][_m]));
+//TAG: updated memory locations at Mem[T.Self__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Self__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Self__DEVICE_EXTENSION][_m] == old(Mem)[T.Self__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.Started__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Started__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Started__DEVICE_EXTENSION][_m] == old(Mem)[T.Started__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.GrandMaster__GLOBALS] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.GrandMaster__GLOBALS][_m]} (Empty()[_m]) || Mem[T.GrandMaster__GLOBALS][_m] == old(Mem)[T.GrandMaster__GLOBALS][_m]));
+//TAG: updated memory locations at Mem[T.P_DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.P_DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.P_DEVICE_OBJECT][_m] == old(Mem)[T.P_DEVICE_OBJECT][_m]));
+
+//TAG: havoc memory locations by default
+modifies Mem;
+
+
+procedure ObfDereferenceObject($Object$1$24931.15$ObfDereferenceObject$41:int) returns ($result.ObfDereferenceObject$24930.0$1$:int);
+
+//TAG: ensures __preserves_mem
+ensures(Mem == old(Mem));
+//TAG: ensures __preserves_resource("DEV_OBJ_INIT") && __preserves_resource("DEV_EXTN")
+ensures((Res_DEV_OBJ_INIT == old(Res_DEV_OBJ_INIT)) && (Res_DEV_EXTN == old(Res_DEV_EXTN)));
+
+modifies Res_DEVICE_STACK;
+
+//TAG: net change in resource DEVICE_STACK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEVICE_STACK[r]} (Empty()[r]) || old(Res_DEVICE_STACK)[r] == Res_DEVICE_STACK[r]));
+modifies Res_DEV_EXTN;
+
+//TAG: net change in resource DEV_EXTN only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_EXTN[r]} (Empty()[r]) || old(Res_DEV_EXTN)[r] == Res_DEV_EXTN[r]));
+modifies Res_DEV_OBJ_INIT;
+
+//TAG: net change in resource DEV_OBJ_INIT only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_OBJ_INIT[r]} (Empty()[r]) || old(Res_DEV_OBJ_INIT)[r] == Res_DEV_OBJ_INIT[r]));
+modifies Res_SPIN_LOCK;
+
+//TAG: net change in resource SPIN_LOCK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_SPIN_LOCK[r]} (Empty()[r]) || old(Res_SPIN_LOCK)[r] == Res_SPIN_LOCK[r]));
+//TAG: updated memory locations at Mem[T.MinorFunction__IO_STACK_LOCATION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.MinorFunction__IO_STACK_LOCATION][_m]} (Empty()[_m]) || Mem[T.MinorFunction__IO_STACK_LOCATION][_m] == old(Mem)[T.MinorFunction__IO_STACK_LOCATION][_m]));
+//TAG: updated memory locations at Mem[T.CurrentStackLocation___unnamed_4_a7aa989c] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.CurrentStackLocation___unnamed_4_a7aa989c][_m]} (Empty()[_m]) || Mem[T.CurrentStackLocation___unnamed_4_a7aa989c][_m] == old(Mem)[T.CurrentStackLocation___unnamed_4_a7aa989c][_m]));
+//TAG: updated memory locations at Mem[T.DeviceExtension__DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.DeviceExtension__DEVICE_OBJECT][_m] == old(Mem)[T.DeviceExtension__DEVICE_OBJECT][_m]));
+//TAG: updated memory locations at Mem[T.Self__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Self__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Self__DEVICE_EXTENSION][_m] == old(Mem)[T.Self__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.Started__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Started__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Started__DEVICE_EXTENSION][_m] == old(Mem)[T.Started__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.GrandMaster__GLOBALS] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.GrandMaster__GLOBALS][_m]} (Empty()[_m]) || Mem[T.GrandMaster__GLOBALS][_m] == old(Mem)[T.GrandMaster__GLOBALS][_m]));
+//TAG: updated memory locations at Mem[T.P_DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.P_DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.P_DEVICE_OBJECT][_m] == old(Mem)[T.P_DEVICE_OBJECT][_m]));
+
+//TAG: havoc memory locations by default
+modifies Mem;
+
+
+procedure RemoveEntryList($Entry$1$6929.19$RemoveEntryList$41:int) returns ($result.RemoveEntryList$6928.0$1$:int);
+
+//TAG: ensures __preserves_resource("DEV_OBJ_INIT") && __preserves_resource("DEV_EXTN")
+ensures((Res_DEV_OBJ_INIT == old(Res_DEV_OBJ_INIT)) && (Res_DEV_EXTN == old(Res_DEV_EXTN)));
+//TAG: ensures __preserves_resource("DEV_OBJ_INIT") && __preserves_resource("DEV_EXTN")
+ensures((Res_DEV_OBJ_INIT == old(Res_DEV_OBJ_INIT)) && (Res_DEV_EXTN == old(Res_DEV_EXTN)));
+//TAG: ensures __seteq(__btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList), __setminus(__old(__btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList)), __set(Entry)))
+ensures((Subset(ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals)), Difference(ReachBetweenSet(Shift_Flink__LIST_ENTRY(old(Mem)[T.Flink__LIST_ENTRY]), old(Mem)[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(old(Globals)))], LegacyDeviceList__GLOBALS(old(Globals))), Singleton($Entry$1$6929.19$RemoveEntryList$41))) && Subset(Difference(ReachBetweenSet(Shift_Flink__LIST_ENTRY(old(Mem)[T.Flink__LIST_ENTRY]), old(Mem)[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(old(Globals)))], LegacyDeviceList__GLOBALS(old(Globals))), Singleton($Entry$1$6929.19$RemoveEntryList$41)), ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals)))));
+//TAG: ensures Entry->Flink == __old(Entry->Flink)
+ensures(Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY($Entry$1$6929.19$RemoveEntryList$41)] == old(Mem)[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY($Entry$1$6929.19$RemoveEntryList$41)]);
+
+modifies Res_DEVICE_STACK;
+
+//TAG: net change in resource DEVICE_STACK only for: __set_empty, __set_empty
+ensures (Subset(Empty(), Union(Union(Empty(), Empty()), Empty())) && (forall r:int :: {Res_DEVICE_STACK[r]} (Empty()[r]) || (Empty()[r]) || old(Res_DEVICE_STACK)[r] == Res_DEVICE_STACK[r]));
+modifies Res_DEV_EXTN;
+
+//TAG: net change in resource DEV_EXTN only for: __set_empty, __set_empty
+ensures (Subset(Empty(), Union(Union(Empty(), Empty()), Empty())) && (forall r:int :: {Res_DEV_EXTN[r]} (Empty()[r]) || (Empty()[r]) || old(Res_DEV_EXTN)[r] == Res_DEV_EXTN[r]));
+modifies Res_DEV_OBJ_INIT;
+
+//TAG: net change in resource DEV_OBJ_INIT only for: __set_empty, __set_empty
+ensures (Subset(Empty(), Union(Union(Empty(), Empty()), Empty())) && (forall r:int :: {Res_DEV_OBJ_INIT[r]} (Empty()[r]) || (Empty()[r]) || old(Res_DEV_OBJ_INIT)[r] == Res_DEV_OBJ_INIT[r]));
+modifies Res_SPIN_LOCK;
+
+//TAG: net change in resource SPIN_LOCK only for: __set_empty, __set_empty
+ensures (Subset(Empty(), Union(Union(Empty(), Empty()), Empty())) && (forall r:int :: {Res_SPIN_LOCK[r]} (Empty()[r]) || (Empty()[r]) || old(Res_SPIN_LOCK)[r] == Res_SPIN_LOCK[r]));
+//TAG: updated memory locations at Mem[T.MinorFunction__IO_STACK_LOCATION] only for: __set_empty, __set_empty
+ensures (Subset(Empty(), Union(Union(Empty(), Empty()), Empty())) && (forall _m:int :: {Mem[T.MinorFunction__IO_STACK_LOCATION][_m]} (Empty()[_m]) || (Empty()[_m]) || Mem[T.MinorFunction__IO_STACK_LOCATION][_m] == old(Mem)[T.MinorFunction__IO_STACK_LOCATION][_m]));
+//TAG: updated memory locations at Mem[T.CurrentStackLocation___unnamed_4_a7aa989c] only for: __set_empty, __set_empty
+ensures (Subset(Empty(), Union(Union(Empty(), Empty()), Empty())) && (forall _m:int :: {Mem[T.CurrentStackLocation___unnamed_4_a7aa989c][_m]} (Empty()[_m]) || (Empty()[_m]) || Mem[T.CurrentStackLocation___unnamed_4_a7aa989c][_m] == old(Mem)[T.CurrentStackLocation___unnamed_4_a7aa989c][_m]));
+//TAG: updated memory locations at Mem[T.DeviceExtension__DEVICE_OBJECT] only for: __set_empty, __set_empty
+ensures (Subset(Empty(), Union(Union(Empty(), Empty()), Empty())) && (forall _m:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][_m]} (Empty()[_m]) || (Empty()[_m]) || Mem[T.DeviceExtension__DEVICE_OBJECT][_m] == old(Mem)[T.DeviceExtension__DEVICE_OBJECT][_m]));
+//TAG: updated memory locations at Mem[T.Self__DEVICE_EXTENSION] only for: __set_empty, __set_empty
+ensures (Subset(Empty(), Union(Union(Empty(), Empty()), Empty())) && (forall _m:int :: {Mem[T.Self__DEVICE_EXTENSION][_m]} (Empty()[_m]) || (Empty()[_m]) || Mem[T.Self__DEVICE_EXTENSION][_m] == old(Mem)[T.Self__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.Started__DEVICE_EXTENSION] only for: __set_empty, __set_empty
+ensures (Subset(Empty(), Union(Union(Empty(), Empty()), Empty())) && (forall _m:int :: {Mem[T.Started__DEVICE_EXTENSION][_m]} (Empty()[_m]) || (Empty()[_m]) || Mem[T.Started__DEVICE_EXTENSION][_m] == old(Mem)[T.Started__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.GrandMaster__GLOBALS] only for: __set_empty, __set_empty
+ensures (Subset(Empty(), Union(Union(Empty(), Empty()), Empty())) && (forall _m:int :: {Mem[T.GrandMaster__GLOBALS][_m]} (Empty()[_m]) || (Empty()[_m]) || Mem[T.GrandMaster__GLOBALS][_m] == old(Mem)[T.GrandMaster__GLOBALS][_m]));
+//TAG: updated memory locations at Mem[T.P_DEVICE_OBJECT] only for: __set_empty, __set_empty
+ensures (Subset(Empty(), Union(Union(Empty(), Empty()), Empty())) && (forall _m:int :: {Mem[T.P_DEVICE_OBJECT][_m]} (Empty()[_m]) || (Empty()[_m]) || Mem[T.P_DEVICE_OBJECT][_m] == old(Mem)[T.P_DEVICE_OBJECT][_m]));
+
+//TAG: havoc memory locations by default
+modifies Mem;
+
+
+procedure __PREfastPagedCode();
+
+//TAG: ensures __preserves_mem
+ensures(Mem == old(Mem));
+//TAG: ensures __preserves_resource("DEV_OBJ_INIT") && __preserves_resource("DEV_EXTN")
+ensures((Res_DEV_OBJ_INIT == old(Res_DEV_OBJ_INIT)) && (Res_DEV_EXTN == old(Res_DEV_EXTN)));
+
+modifies Res_DEVICE_STACK;
+
+//TAG: net change in resource DEVICE_STACK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEVICE_STACK[r]} (Empty()[r]) || old(Res_DEVICE_STACK)[r] == Res_DEVICE_STACK[r]));
+modifies Res_DEV_EXTN;
+
+//TAG: net change in resource DEV_EXTN only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_EXTN[r]} (Empty()[r]) || old(Res_DEV_EXTN)[r] == Res_DEV_EXTN[r]));
+modifies Res_DEV_OBJ_INIT;
+
+//TAG: net change in resource DEV_OBJ_INIT only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_OBJ_INIT[r]} (Empty()[r]) || old(Res_DEV_OBJ_INIT)[r] == Res_DEV_OBJ_INIT[r]));
+modifies Res_SPIN_LOCK;
+
+//TAG: net change in resource SPIN_LOCK only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_SPIN_LOCK[r]} (Empty()[r]) || old(Res_SPIN_LOCK)[r] == Res_SPIN_LOCK[r]));
+//TAG: updated memory locations at Mem[T.MinorFunction__IO_STACK_LOCATION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.MinorFunction__IO_STACK_LOCATION][_m]} (Empty()[_m]) || Mem[T.MinorFunction__IO_STACK_LOCATION][_m] == old(Mem)[T.MinorFunction__IO_STACK_LOCATION][_m]));
+//TAG: updated memory locations at Mem[T.CurrentStackLocation___unnamed_4_a7aa989c] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.CurrentStackLocation___unnamed_4_a7aa989c][_m]} (Empty()[_m]) || Mem[T.CurrentStackLocation___unnamed_4_a7aa989c][_m] == old(Mem)[T.CurrentStackLocation___unnamed_4_a7aa989c][_m]));
+//TAG: updated memory locations at Mem[T.DeviceExtension__DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.DeviceExtension__DEVICE_OBJECT][_m] == old(Mem)[T.DeviceExtension__DEVICE_OBJECT][_m]));
+//TAG: updated memory locations at Mem[T.Self__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Self__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Self__DEVICE_EXTENSION][_m] == old(Mem)[T.Self__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.Started__DEVICE_EXTENSION] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Started__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Started__DEVICE_EXTENSION][_m] == old(Mem)[T.Started__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.GrandMaster__GLOBALS] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.GrandMaster__GLOBALS][_m]} (Empty()[_m]) || Mem[T.GrandMaster__GLOBALS][_m] == old(Mem)[T.GrandMaster__GLOBALS][_m]));
+//TAG: updated memory locations at Mem[T.P_DEVICE_OBJECT] only for: __set_empty
+ensures (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.P_DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.P_DEVICE_OBJECT][_m] == old(Mem)[T.P_DEVICE_OBJECT][_m]));
+
+//TAG: havoc memory locations by default
+modifies Mem;
+
+
+procedure MouseClassUnload($DriverObject$1$2789.24$MouseClassUnload$41:int)
+
+//TAG: requires __pforall(_H_x, (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension), __inv_resource("DEV_OBJ_INIT", 1), ((struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension))->Self == _H_x && __resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension)) == 1)
+requires((forall _H_x:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)]} Inverse(Res_DEV_OBJ_INIT,1)[_H_x] ==> ((Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)])] == _H_x) && (Res_DEV_EXTN[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)]] == 1))));
+//TAG: requires __pforall(_H_z, _H_z->Self, __inv_resource("DEV_EXTN", 1), __resource("DEV_OBJ_INIT", _H_z->Self) == 1 && (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)(_H_z->Self))->DeviceExtension) == _H_z) && __forall(_H_z, __inv_resource("DEV_EXTN", 1), __resource("SPIN_LOCK", &_H_z->SpinLock) == 0 && __resource("SPIN_LOCK", &_H_z->WaitWakeSpinLock) == 0)
+requires(((forall _H_z:int :: {Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)]} Inverse(Res_DEV_EXTN,1)[_H_z] ==> ((Res_DEV_OBJ_INIT[Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)]] == 1) && (Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)])] == _H_z)))) && ((Subset(Empty(), Inverse(Res_DEV_EXTN,1)) && (forall _H_z : int :: {Inverse(Res_DEV_EXTN,1)[_H_z]} (Inverse(Res_DEV_EXTN,1)[_H_z]) ==> ((Res_SPIN_LOCK[SpinLock__DEVICE_EXTENSION(_H_z)] == 0) && (Res_SPIN_LOCK[WaitWakeSpinLock__DEVICE_EXTENSION(_H_z)] == 0))))));
+//TAG: ensures __pforall(_H_x, (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension), __inv_resource("DEV_OBJ_INIT", 1), ((struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension))->Self == _H_x && __resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension)) == 1)
+ensures((forall _H_x:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)]} Inverse(Res_DEV_OBJ_INIT,1)[_H_x] ==> ((Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)])] == _H_x) && (Res_DEV_EXTN[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)]] == 1))));
+//TAG: ensures __pforall(_H_z, _H_z->Self, __inv_resource("DEV_EXTN", 1), __resource("DEV_OBJ_INIT", _H_z->Self) == 1 && (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)(_H_z->Self))->DeviceExtension) == _H_z) && __forall(_H_z, __inv_resource("DEV_EXTN", 1), __resource("SPIN_LOCK", &_H_z->SpinLock) == 0 && __resource("SPIN_LOCK", &_H_z->WaitWakeSpinLock) == 0)
+ensures(((forall _H_z:int :: {Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)]} Inverse(Res_DEV_EXTN,1)[_H_z] ==> ((Res_DEV_OBJ_INIT[Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)]] == 1) && (Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)])] == _H_z)))) && ((Subset(Empty(), Inverse(Res_DEV_EXTN,1)) && (forall _H_z : int :: {Inverse(Res_DEV_EXTN,1)[_H_z]} (Inverse(Res_DEV_EXTN,1)[_H_z]) ==> ((Res_SPIN_LOCK[SpinLock__DEVICE_EXTENSION(_H_z)] == 0) && (Res_SPIN_LOCK[WaitWakeSpinLock__DEVICE_EXTENSION(_H_z)] == 0))))));
+//TAG: requires 1 ==> (Globals.GrandMaster != (void *)0 ==> __resource("DEV_EXTN", Globals.GrandMaster) == 1)
+requires((true) ==> ((Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)] != 0) ==> (Res_DEV_EXTN[Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)]] == 1)));
+//TAG: requires 1 ==> __setin(&Globals.LegacyDeviceList, __btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList))
+requires((true) ==> (ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[LegacyDeviceList__GLOBALS(Globals)]));
+//TAG: requires 1 ==> __forall(_H_y, __btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList), _H_y == &Globals.LegacyDeviceList || __resource("DEV_EXTN", CONTAINING_RECORD(_H_y, struct _DEVICE_EXTENSION , Link)) == 1)
+requires((true) ==> ((Subset(Empty(), ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))) && (forall _H_y : int :: {ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[_H_y]} (ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[_H_y]) ==> ((_H_y == LegacyDeviceList__GLOBALS(Globals)) || (Res_DEV_EXTN[MINUS_LEFT_PTR(_H_y, 1, Link__DEVICE_EXTENSION(0))] == 1))))));
+//TAG: requires 1 ==> !__setin(&Globals.GrandMaster->Link, __setminus(__btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList), __set(&Globals.LegacyDeviceList)))
+requires((true) ==> (!(Difference(ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals)), Singleton(LegacyDeviceList__GLOBALS(Globals)))[Link__DEVICE_EXTENSION(Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)])])));
+modifies alloc;
+free ensures(forall f:int :: {alloc[Base(f)]} old(alloc)[Base(f)] == UNALLOCATED || old(alloc)[Base(f)] == alloc[Base(f)]);
+
+modifies Res_DEVICE_STACK;
+
+//TAG: net change in resource DEVICE_STACK only for:
+modifies Res_DEV_EXTN;
+
+//TAG: net change in resource DEV_EXTN only for:
+modifies Res_DEV_OBJ_INIT;
+
+//TAG: net change in resource DEV_OBJ_INIT only for:
+modifies Res_SPIN_LOCK;
+
+//TAG: net change in resource SPIN_LOCK only for:
+
+//TAG: havoc memory locations by default
+modifies Mem;
+{
+var havoc_stringTemp:int;
+var condVal:int;
+var $DriverObject$1$2789.24$MouseClassUnload$4 : int;
+var $IoAllocateIrp.arg.1$9$ : int;
+var $MouDebugPrint.arg.2$1$ : int;
+var $MouDebugPrint.arg.2$19$ : int;
+var $RtlAssert.arg.1$14$ : int;
+var $RtlAssert.arg.1$16$ : int;
+var $RtlAssert.arg.1$18$ : int;
+var $RtlAssert.arg.1$3$ : int;
+var $RtlAssert.arg.1$5$ : int;
+var $RtlAssert.arg.1$7$ : int;
+var $RtlAssert.arg.2$13$ : int;
+var $RtlAssert.arg.2$15$ : int;
+var $RtlAssert.arg.2$17$ : int;
+var $RtlAssert.arg.2$2$ : int;
+var $RtlAssert.arg.2$4$ : int;
+var $RtlAssert.arg.2$6$ : int;
+var $data$3$2812.22$MouseClassUnload$4 : int;
+var $enabled$6$2829.16$MouseClassUnload$4 : int;
+var $entry$2$2811.16$MouseClassUnload$4 : int;
+var $file$7$2830.21$MouseClassUnload$4 : int;
+var $i$8$2898.14$MouseClassUnload$4 : int;
+var $irp$5$2814.9$MouseClassUnload$4 : int;
+var $port$4$2813.10$MouseClassUnload$4 : int;
+var $result.IoAllocateIrp$2854.31$8$ : int;
+var $result.MouEnableDisablePort$2856.37$10$ : int;
+var $result.ObfDereferenceObject$2867.12$11$ : int;
+var $result.RemoveEntryList$2878.24$12$ : int;
+var tempBoogie0:int;
+var tempBoogie1:int;
+var tempBoogie2:int;
+var tempBoogie3:int;
+var tempBoogie4:int;
+var tempBoogie5:int;
+var tempBoogie6:int;
+var tempBoogie7:int;
+var tempBoogie8:int;
+var tempBoogie9:int;
+var tempBoogie10:int;
+var tempBoogie11:int;
+var tempBoogie12:int;
+var tempBoogie13:int;
+var tempBoogie14:int;
+var tempBoogie15:int;
+var tempBoogie16:int;
+var tempBoogie17:int;
+var tempBoogie18:int;
+var tempBoogie19:int;
+var LOOP_15_alloc:[int]name;
+var LOOP_15_Mem:[name][int]int;
+var LOOP_15_Res_DEVICE_STACK:[int]int;
+var LOOP_15_Res_DEV_EXTN:[int]int;
+var LOOP_15_Res_DEV_OBJ_INIT:[int]int;
+var LOOP_15_Res_SPIN_LOCK:[int]int;
+var LOOP_108_alloc:[int]name;
+var LOOP_108_Mem:[name][int]int;
+var LOOP_108_Res_DEVICE_STACK:[int]int;
+var LOOP_108_Res_DEV_EXTN:[int]int;
+var LOOP_108_Res_DEV_OBJ_INIT:[int]int;
+var LOOP_108_Res_SPIN_LOCK:[int]int;
+
+
+start:
+
+assume (alloc[$DriverObject$1$2789.24$MouseClassUnload$41] != UNALLOCATED);
+call $file$7$2830.21$MouseClassUnload$4 := __HAVOC_malloc(4);
+$DriverObject$1$2789.24$MouseClassUnload$4 := $DriverObject$1$2789.24$MouseClassUnload$41;
+goto label_3;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(2911)
+label_1:
+call __HAVOC_free($file$7$2830.21$MouseClassUnload$4);
+assume (forall m:int:: {Res_DEVICE_STACK[m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Res_DEVICE_STACK[m] == old(Res_DEVICE_STACK)[m]);
+assume (forall m:int:: {Res_DEV_EXTN[m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Res_DEV_EXTN[m] == old(Res_DEV_EXTN)[m]);
+assume (forall m:int:: {Res_DEV_OBJ_INIT[m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Res_DEV_OBJ_INIT[m] == old(Res_DEV_OBJ_INIT)[m]);
+assume (forall m:int:: {Res_SPIN_LOCK[m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Res_SPIN_LOCK[m] == old(Res_SPIN_LOCK)[m]);
+assume (forall m:int :: {Mem[T.A11CHAR][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.A11CHAR][m] == old(Mem[T.A11CHAR])[m]);
+assume (forall m:int :: {Mem[T.A19CHAR][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.A19CHAR][m] == old(Mem[T.A19CHAR])[m]);
+assume (forall m:int :: {Mem[T.A33CHAR][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.A33CHAR][m] == old(Mem[T.A33CHAR])[m]);
+assume (forall m:int :: {Mem[T.A34CHAR][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.A34CHAR][m] == old(Mem[T.A34CHAR])[m]);
+assume (forall m:int :: {Mem[T.A39CHAR][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.A39CHAR][m] == old(Mem[T.A39CHAR])[m]);
+assume (forall m:int :: {Mem[T.A43CHAR][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.A43CHAR][m] == old(Mem[T.A43CHAR])[m]);
+assume (forall m:int :: {Mem[T.A74CHAR][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.A74CHAR][m] == old(Mem[T.A74CHAR])[m]);
+assume (forall m:int :: {Mem[T.AssocClassList__GLOBALS][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.AssocClassList__GLOBALS][m] == old(Mem[T.AssocClassList__GLOBALS])[m]);
+assume (forall m:int :: {Mem[T.Buffer__UNICODE_STRING][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.Buffer__UNICODE_STRING][m] == old(Mem[T.Buffer__UNICODE_STRING])[m]);
+assume (forall m:int :: {Mem[T.CurrentStackLocation___unnamed_4_a7aa989c][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.CurrentStackLocation___unnamed_4_a7aa989c][m] == old(Mem[T.CurrentStackLocation___unnamed_4_a7aa989c])[m]);
+assume (forall m:int :: {Mem[T.DataIn__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.DataIn__DEVICE_EXTENSION][m] == old(Mem[T.DataIn__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.DataOut__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.DataOut__DEVICE_EXTENSION][m] == old(Mem[T.DataOut__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.DeviceExtension__DEVICE_OBJECT][m] == old(Mem[T.DeviceExtension__DEVICE_OBJECT])[m]);
+assume (forall m:int :: {Mem[T.Enabled__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.Enabled__DEVICE_EXTENSION][m] == old(Mem[T.Enabled__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.Enabled__PORT][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.Enabled__PORT][m] == old(Mem[T.Enabled__PORT])[m]);
+assume (forall m:int :: {Mem[T.File__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.File__DEVICE_EXTENSION][m] == old(Mem[T.File__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.File__PORT][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.File__PORT][m] == old(Mem[T.File__PORT])[m]);
+assume (forall m:int :: {Mem[T.Flink__LIST_ENTRY][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.Flink__LIST_ENTRY][m] == old(Mem[T.Flink__LIST_ENTRY])[m]);
+assume (forall m:int :: {Mem[T.Free__PORT][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.Free__PORT][m] == old(Mem[T.Free__PORT])[m]);
+assume (forall m:int :: {Mem[T.GrandMaster__GLOBALS][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.GrandMaster__GLOBALS][m] == old(Mem[T.GrandMaster__GLOBALS])[m]);
+assume (forall m:int :: {Mem[T.INT4][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.INT4][m] == old(Mem[T.INT4])[m]);
+assume (forall m:int :: {Mem[T.InputData__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.InputData__DEVICE_EXTENSION][m] == old(Mem[T.InputData__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.LegacyDeviceList__GLOBALS][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.LegacyDeviceList__GLOBALS][m] == old(Mem[T.LegacyDeviceList__GLOBALS])[m]);
+assume (forall m:int :: {Mem[T.Link__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.Link__DEVICE_EXTENSION][m] == old(Mem[T.Link__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.MinorFunction__IO_STACK_LOCATION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.MinorFunction__IO_STACK_LOCATION][m] == old(Mem[T.MinorFunction__IO_STACK_LOCATION])[m]);
+assume (forall m:int :: {Mem[T.NumAssocClass__GLOBALS][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.NumAssocClass__GLOBALS][m] == old(Mem[T.NumAssocClass__GLOBALS])[m]);
+assume (forall m:int :: {Mem[T.PCHAR][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.PCHAR][m] == old(Mem[T.PCHAR])[m]);
+assume (forall m:int :: {Mem[T.PP_FILE_OBJECT][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.PP_FILE_OBJECT][m] == old(Mem[T.PP_FILE_OBJECT])[m]);
+assume (forall m:int :: {Mem[T.PUINT4][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.PUINT4][m] == old(Mem[T.PUINT4])[m]);
+assume (forall m:int :: {Mem[T.PVOID][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.PVOID][m] == old(Mem[T.PVOID])[m]);
+assume (forall m:int :: {Mem[T.P_DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.P_DEVICE_EXTENSION][m] == old(Mem[T.P_DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.P_DEVICE_OBJECT][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.P_DEVICE_OBJECT][m] == old(Mem[T.P_DEVICE_OBJECT])[m]);
+assume (forall m:int :: {Mem[T.P_FILE_OBJECT][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.P_FILE_OBJECT][m] == old(Mem[T.P_FILE_OBJECT])[m]);
+assume (forall m:int :: {Mem[T.P_IRP][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.P_IRP][m] == old(Mem[T.P_IRP])[m]);
+assume (forall m:int :: {Mem[T.P_LIST_ENTRY][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.P_LIST_ENTRY][m] == old(Mem[T.P_LIST_ENTRY])[m]);
+assume (forall m:int :: {Mem[T.P_MOUSE_INPUT_DATA][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.P_MOUSE_INPUT_DATA][m] == old(Mem[T.P_MOUSE_INPUT_DATA])[m]);
+assume (forall m:int :: {Mem[T.P_PORT][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.P_PORT][m] == old(Mem[T.P_PORT])[m]);
+assume (forall m:int :: {Mem[T.PnP__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.PnP__DEVICE_EXTENSION][m] == old(Mem[T.PnP__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.Port__PORT][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.Port__PORT][m] == old(Mem[T.Port__PORT])[m]);
+assume (forall m:int :: {Mem[T.RegistryPath__GLOBALS][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.RegistryPath__GLOBALS][m] == old(Mem[T.RegistryPath__GLOBALS])[m]);
+assume (forall m:int :: {Mem[T.Self__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.Self__DEVICE_EXTENSION][m] == old(Mem[T.Self__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.SpinLock__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.SpinLock__DEVICE_EXTENSION][m] == old(Mem[T.SpinLock__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.StackSize__DEVICE_OBJECT][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.StackSize__DEVICE_OBJECT][m] == old(Mem[T.StackSize__DEVICE_OBJECT])[m]);
+assume (forall m:int :: {Mem[T.Started__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.Started__DEVICE_EXTENSION][m] == old(Mem[T.Started__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.TopPort__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.TopPort__DEVICE_EXTENSION][m] == old(Mem[T.TopPort__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.UCHAR][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.UCHAR][m] == old(Mem[T.UCHAR])[m]);
+assume (forall m:int :: {Mem[T.UINT4][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.UINT4][m] == old(Mem[T.UINT4])[m]);
+assume (forall m:int :: {Mem[T.UnitId__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.UnitId__DEVICE_EXTENSION][m] == old(Mem[T.UnitId__DEVICE_EXTENSION])[m]);
+assume (forall m:int :: {Mem[T.WaitWakeSpinLock__DEVICE_EXTENSION][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[T.WaitWakeSpinLock__DEVICE_EXTENSION][m] == old(Mem[T.WaitWakeSpinLock__DEVICE_EXTENSION])[m]);
+return;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(2911)
+label_2:
+assume false;
+return;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(2811)
+label_3:
+goto label_4;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(2812)
+label_4:
+goto label_5;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(2813)
+label_5:
+goto label_6;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(2814)
+label_6:
+goto label_7;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(2818)
+label_7:
+call __PREfastPagedCode ();
+goto label_13;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(2820)
+label_10:
+// skip MouDebugPrint
+goto label_14;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(2820)
+label_13:
+call havoc_stringTemp := __HAVOC_malloc(1);
+$MouDebugPrint.arg.2$1$ := havoc_stringTemp ;
+goto label_10;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(2825)
+label_14:
+$entry$2$2811.16$MouseClassUnload$4 := Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))] ;
+goto label_15;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(2826)
+label_15:
+// loop entry initialization...
+LOOP_15_alloc := alloc;
+LOOP_15_Mem := Mem;
+LOOP_15_Res_DEVICE_STACK := Res_DEVICE_STACK;
+LOOP_15_Res_DEV_EXTN := Res_DEV_EXTN;
+LOOP_15_Res_DEV_OBJ_INIT := Res_DEV_OBJ_INIT;
+LOOP_15_Res_SPIN_LOCK := Res_SPIN_LOCK;
+goto label_15_head;
+
+
+label_15_head:
+// loop head assertions...
+//TAG: requires __pforall(_H_x, (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension), __inv_resource("DEV_OBJ_INIT", 1), ((struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension))->Self == _H_x && __resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension)) == 1)
+assert((forall _H_x:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)]} Inverse(Res_DEV_OBJ_INIT,1)[_H_x] ==> ((Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)])] == _H_x) && (Res_DEV_EXTN[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)]] == 1))));
+//TAG: requires __pforall(_H_z, _H_z->Self, __inv_resource("DEV_EXTN", 1), __resource("DEV_OBJ_INIT", _H_z->Self) == 1 && (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)(_H_z->Self))->DeviceExtension) == _H_z)
+assert((forall _H_z:int :: {Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)]} Inverse(Res_DEV_EXTN,1)[_H_z] ==> ((Res_DEV_OBJ_INIT[Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)]] == 1) && (Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)])] == _H_z))));
+//TAG: requires __forall(_H_z, __inv_resource("DEV_EXTN", 1), __resource("SPIN_LOCK", &_H_z->SpinLock) == 0 && __resource("SPIN_LOCK", &_H_z->WaitWakeSpinLock) == 0)
+assert((Subset(Empty(), Inverse(Res_DEV_EXTN,1)) && (forall _H_z : int :: {Inverse(Res_DEV_EXTN,1)[_H_z]} (Inverse(Res_DEV_EXTN,1)[_H_z]) ==> ((Res_SPIN_LOCK[SpinLock__DEVICE_EXTENSION(_H_z)] == 0) && (Res_SPIN_LOCK[WaitWakeSpinLock__DEVICE_EXTENSION(_H_z)] == 0)))));
+//TAG: requires 1 ==> (Globals.GrandMaster != (void *)0 ==> __resource("DEV_EXTN", Globals.GrandMaster) == 1)
+assert((true) ==> ((Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)] != 0) ==> (Res_DEV_EXTN[Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)]] == 1)));
+//TAG: requires 1 ==> __setin(&Globals.LegacyDeviceList, __btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList))
+assert((true) ==> (ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[LegacyDeviceList__GLOBALS(Globals)]));
+//TAG: requires 1 ==> __forall(_H_y, __btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList), _H_y == &Globals.LegacyDeviceList || __resource("DEV_EXTN", CONTAINING_RECORD(_H_y, struct _DEVICE_EXTENSION , Link)) == 1)
+assert((true) ==> ((Subset(Empty(), ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))) && (forall _H_y : int :: {ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[_H_y]} (ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[_H_y]) ==> ((_H_y == LegacyDeviceList__GLOBALS(Globals)) || (Res_DEV_EXTN[MINUS_LEFT_PTR(_H_y, 1, Link__DEVICE_EXTENSION(0))] == 1))))));
+//TAG: requires 1 ==> !__setin(&Globals.GrandMaster->Link, __setminus(__btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList), __set(&Globals.LegacyDeviceList)))
+assert((true) ==> (!(Difference(ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals)), Singleton(LegacyDeviceList__GLOBALS(Globals)))[Link__DEVICE_EXTENSION(Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)])])));
+//TAG: requires __setin(entry, __btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList))
+assert(ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[$entry$2$2811.16$MouseClassUnload$4]);
+assume(forall f:int :: {alloc[Base(f)]} LOOP_15_alloc[Base(f)] == UNALLOCATED || LOOP_15_alloc[Base(f)] == alloc[Base(f)]);
+
+
+//TAG: net change in resource DEVICE_STACK only for: __set_empty
+assert (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEVICE_STACK[r]} (Empty()[r]) || LOOP_15_Res_DEVICE_STACK[r] == Res_DEVICE_STACK[r]));
+
+//TAG: net change in resource DEV_EXTN only for: __set_true
+assert (Subset(Empty(), Union(Empty(), SetTrue())) && (forall r:int :: {Res_DEV_EXTN[r]} (SetTrue()[r]) || LOOP_15_Res_DEV_EXTN[r] == Res_DEV_EXTN[r]));
+
+//TAG: net change in resource DEV_OBJ_INIT only for: __set_true
+assert (Subset(Empty(), Union(Empty(), SetTrue())) && (forall r:int :: {Res_DEV_OBJ_INIT[r]} (SetTrue()[r]) || LOOP_15_Res_DEV_OBJ_INIT[r] == Res_DEV_OBJ_INIT[r]));
+
+//TAG: net change in resource SPIN_LOCK only for: __set_empty
+assert (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_SPIN_LOCK[r]} (Empty()[r]) || LOOP_15_Res_SPIN_LOCK[r] == Res_SPIN_LOCK[r]));
+//TAG: updated memory locations at Mem[T.MinorFunction__IO_STACK_LOCATION] only for: __set_empty
+assert (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.MinorFunction__IO_STACK_LOCATION][_m]} (Empty()[_m]) || Mem[T.MinorFunction__IO_STACK_LOCATION][_m] == LOOP_15_Mem[T.MinorFunction__IO_STACK_LOCATION][_m]));
+//TAG: updated memory locations at Mem[T.CurrentStackLocation___unnamed_4_a7aa989c] only for: __set_empty
+assert (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.CurrentStackLocation___unnamed_4_a7aa989c][_m]} (Empty()[_m]) || Mem[T.CurrentStackLocation___unnamed_4_a7aa989c][_m] == LOOP_15_Mem[T.CurrentStackLocation___unnamed_4_a7aa989c][_m]));
+//TAG: updated memory locations at Mem[T.DeviceExtension__DEVICE_OBJECT] only for: __set_empty
+assert (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.DeviceExtension__DEVICE_OBJECT][_m] == LOOP_15_Mem[T.DeviceExtension__DEVICE_OBJECT][_m]));
+//TAG: updated memory locations at Mem[T.Self__DEVICE_EXTENSION] only for: __set_empty
+assert (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Self__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Self__DEVICE_EXTENSION][_m] == LOOP_15_Mem[T.Self__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.Started__DEVICE_EXTENSION] only for: __set_empty
+assert (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Started__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Started__DEVICE_EXTENSION][_m] == LOOP_15_Mem[T.Started__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.GrandMaster__GLOBALS] only for: __set_empty
+assert (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.GrandMaster__GLOBALS][_m]} (Empty()[_m]) || Mem[T.GrandMaster__GLOBALS][_m] == LOOP_15_Mem[T.GrandMaster__GLOBALS][_m]));
+//TAG: updated memory locations at Mem[T.P_DEVICE_OBJECT] only for: __set_empty
+assert (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.P_DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.P_DEVICE_OBJECT][_m] == LOOP_15_Mem[T.P_DEVICE_OBJECT][_m]));
+
+// end loop head assertions
+
+goto label_15_true , label_15_false ;
+
+
+label_15_true :
+assume ($entry$2$2811.16$MouseClassUnload$4 != LegacyDeviceList__GLOBALS(Globals));
+goto label_16;
+
+
+label_15_false :
+assume !($entry$2$2811.16$MouseClassUnload$4 != LegacyDeviceList__GLOBALS(Globals));
+goto label_85;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(2829)
+label_16:
+goto label_17;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(2829)
+label_17:
+$enabled$6$2829.16$MouseClassUnload$4 := 0 ;
+goto label_18;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(2830)
+label_18:
+goto label_19;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(2830)
+label_19:
+Mem[T.P_FILE_OBJECT] := Mem[T.P_FILE_OBJECT][$file$7$2830.21$MouseClassUnload$4 := 0];
+goto label_20;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(2832)
+label_20:
+$data$3$2812.22$MouseClassUnload$4 := MINUS_LEFT_PTR($entry$2$2811.16$MouseClassUnload$4, 1, 252) ;
+goto label_21;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(2833)
+label_21:
+goto label_21_true , label_21_false ;
+
+
+label_21_true :
+assume (Mem[T.PnP__DEVICE_EXTENSION][PnP__DEVICE_EXTENSION($data$3$2812.22$MouseClassUnload$4)] != 0);
+goto label_25;
+
+
+label_21_false :
+assume (Mem[T.PnP__DEVICE_EXTENSION][PnP__DEVICE_EXTENSION($data$3$2812.22$MouseClassUnload$4)] == 0);
+goto label_27;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(2833)
+label_22:
+// skip RtlAssert
+goto label_27;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(2833)
+label_25:
+call havoc_stringTemp := __HAVOC_malloc(1);
+$RtlAssert.arg.2$2$ := havoc_stringTemp ;
+goto label_26;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(2833)
+label_26:
+call havoc_stringTemp := __HAVOC_malloc(1);
+$RtlAssert.arg.1$3$ := havoc_stringTemp ;
+goto label_22;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(2835)
+label_27:
+goto label_27_true , label_27_false ;
+
+
+label_27_true :
+assume (Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)] != 0);
+goto label_28;
+
+
+label_27_false :
+assume (Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)] == 0);
+goto label_40;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(2836)
+label_28:
+$port$4$2813.10$MouseClassUnload$4 := PLUS(Mem[T.AssocClassList__GLOBALS][AssocClassList__GLOBALS(Globals)], 12, Mem[T.UnitId__DEVICE_EXTENSION][UnitId__DEVICE_EXTENSION($data$3$2812.22$MouseClassUnload$4)]) ;
+goto label_29;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(2837)
+label_29:
+goto label_29_true , label_29_false ;
+
+
+label_29_true :
+assume (Mem[T.Port__PORT][Port__PORT($port$4$2813.10$MouseClassUnload$4)] == $data$3$2812.22$MouseClassUnload$4);
+goto label_35;
+
+
+label_29_false :
+assume !(Mem[T.Port__PORT][Port__PORT($port$4$2813.10$MouseClassUnload$4)] == $data$3$2812.22$MouseClassUnload$4);
+goto label_33;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(2837)
+label_30:
+// skip RtlAssert
+goto label_35;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(2837)
+label_33:
+call havoc_stringTemp := __HAVOC_malloc(1);
+$RtlAssert.arg.2$4$ := havoc_stringTemp ;
+goto label_34;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(2837)
+label_34:
+call havoc_stringTemp := __HAVOC_malloc(1);
+$RtlAssert.arg.1$5$ := havoc_stringTemp ;
+goto label_30;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(2839)
+label_35:
+$enabled$6$2829.16$MouseClassUnload$4 := Mem[T.Enabled__PORT][Enabled__PORT($port$4$2813.10$MouseClassUnload$4)] ;
+goto label_36;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(2840)
+label_36:
+Mem[T.P_FILE_OBJECT] := Mem[T.P_FILE_OBJECT][$file$7$2830.21$MouseClassUnload$4 := Mem[T.File__PORT][File__PORT($port$4$2813.10$MouseClassUnload$4)]];
+goto label_37;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(2842)
+label_37:
+Mem[T.Enabled__PORT] := Mem[T.Enabled__PORT][Enabled__PORT($port$4$2813.10$MouseClassUnload$4) := 0];
+goto label_38;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(2843)
+label_38:
+Mem[T.File__PORT] := Mem[T.File__PORT][File__PORT($port$4$2813.10$MouseClassUnload$4) := 0];
+goto label_39;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(2844)
+label_39:
+Mem[T.Free__PORT] := Mem[T.Free__PORT][Free__PORT($port$4$2813.10$MouseClassUnload$4) := 1];
+goto label_49;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(2847)
+label_40:
+$enabled$6$2829.16$MouseClassUnload$4 := Mem[T.Enabled__DEVICE_EXTENSION][Enabled__DEVICE_EXTENSION($data$3$2812.22$MouseClassUnload$4)] ;
+goto label_41;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(2848)
+label_41:
+Mem[T.P_FILE_OBJECT] := Mem[T.P_FILE_OBJECT][$file$7$2830.21$MouseClassUnload$4 := Mem[T.File__DEVICE_EXTENSION][File__DEVICE_EXTENSION($data$3$2812.22$MouseClassUnload$4)]];
+goto label_42;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(2849)
+label_42:
+goto label_42_true , label_42_false ;
+
+
+label_42_true :
+assume (Mem[T.File__DEVICE_EXTENSION][File__DEVICE_EXTENSION($data$3$2812.22$MouseClassUnload$4)] != 0);
+goto label_48;
+
+
+label_42_false :
+assume (Mem[T.File__DEVICE_EXTENSION][File__DEVICE_EXTENSION($data$3$2812.22$MouseClassUnload$4)] == 0);
+goto label_46;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(2849)
+label_43:
+// skip RtlAssert
+goto label_48;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(2849)
+label_46:
+call havoc_stringTemp := __HAVOC_malloc(1);
+$RtlAssert.arg.2$6$ := havoc_stringTemp ;
+goto label_47;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(2849)
+label_47:
+call havoc_stringTemp := __HAVOC_malloc(1);
+$RtlAssert.arg.1$7$ := havoc_stringTemp ;
+goto label_43;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(2850)
+label_48:
+Mem[T.Enabled__DEVICE_EXTENSION] := Mem[T.Enabled__DEVICE_EXTENSION][Enabled__DEVICE_EXTENSION($data$3$2812.22$MouseClassUnload$4) := 0];
+goto label_49;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(2853)
+label_49:
+goto label_49_true , label_49_false ;
+
+
+label_49_true :
+assume ($enabled$6$2829.16$MouseClassUnload$4 != 0);
+goto label_53;
+
+
+label_49_false :
+assume ($enabled$6$2829.16$MouseClassUnload$4 == 0);
+goto label_62;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(2854)
+label_50:
+call $result.IoAllocateIrp$2854.31$8$ := IoAllocateIrp ($IoAllocateIrp.arg.1$9$, 0);
+goto label_54;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(2854)
+label_53:
+$IoAllocateIrp.arg.1$9$ := PLUS(Mem[T.StackSize__DEVICE_OBJECT][StackSize__DEVICE_OBJECT(Mem[T.TopPort__DEVICE_EXTENSION][TopPort__DEVICE_EXTENSION($data$3$2812.22$MouseClassUnload$4)])], 1, 1) ;
+goto label_50;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(2854)
+label_54:
+$irp$5$2814.9$MouseClassUnload$4 := $result.IoAllocateIrp$2854.31$8$ ;
+goto label_55;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(2855)
+label_55:
+goto label_55_true , label_55_false ;
+
+
+label_55_true :
+assume ($irp$5$2814.9$MouseClassUnload$4 != 0);
+goto label_56;
+
+
+label_55_false :
+assume ($irp$5$2814.9$MouseClassUnload$4 == 0);
+goto label_62;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(2856)
+label_56:
+call $result.MouEnableDisablePort$2856.37$10$ := MouEnableDisablePort (0, $irp$5$2814.9$MouseClassUnload$4, $data$3$2812.22$MouseClassUnload$4, $file$7$2830.21$MouseClassUnload$4);
+goto label_59;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(2857)
+label_59:
+call IoFreeIrp ($irp$5$2814.9$MouseClassUnload$4);
+goto label_62;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(2866)
+label_62:
+goto label_62_true , label_62_false ;
+
+
+label_62_true :
+assume (Mem[T.P_FILE_OBJECT][$file$7$2830.21$MouseClassUnload$4] != 0);
+goto label_63;
+
+
+label_62_false :
+assume (Mem[T.P_FILE_OBJECT][$file$7$2830.21$MouseClassUnload$4] == 0);
+goto label_66;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(2867)
+label_63:
+call $result.ObfDereferenceObject$2867.12$11$ := ObfDereferenceObject (Mem[T.P_FILE_OBJECT][$file$7$2830.21$MouseClassUnload$4]);
+goto label_66;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(2874)
+label_66:
+goto label_66_true , label_66_false ;
+
+
+label_66_true :
+assume (Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)] != 0);
+goto label_70;
+
+
+label_66_false :
+assume (Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)] == 0);
+goto label_67;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(2875)
+label_67:
+call MouseClassCleanupQueue (Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION($data$3$2812.22$MouseClassUnload$4)], $data$3$2812.22$MouseClassUnload$4, 0);
+goto label_70;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(2878)
+label_70:
+call $result.RemoveEntryList$2878.24$12$ := RemoveEntryList (Link__DEVICE_EXTENSION($data$3$2812.22$MouseClassUnload$4));
+goto label_73;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(2879)
+label_73:
+$entry$2$2811.16$MouseClassUnload$4 := Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY($entry$2$2811.16$MouseClassUnload$4)] ;
+goto label_74;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(2881)
+label_74:
+goto label_74_true , label_74_false ;
+
+
+label_74_true :
+assume (Mem[T.InputData__DEVICE_EXTENSION][InputData__DEVICE_EXTENSION($data$3$2812.22$MouseClassUnload$4)] != 0);
+goto label_75;
+
+
+label_74_false :
+assume (Mem[T.InputData__DEVICE_EXTENSION][InputData__DEVICE_EXTENSION($data$3$2812.22$MouseClassUnload$4)] == 0);
+goto label_81;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(2881)
+label_75:
+call ExFreePoolWithTag (Mem[T.InputData__DEVICE_EXTENSION][InputData__DEVICE_EXTENSION($data$3$2812.22$MouseClassUnload$4)], 0);
+goto label_78;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(2881)
+label_78:
+Mem[T.DataOut__DEVICE_EXTENSION] := Mem[T.DataOut__DEVICE_EXTENSION][DataOut__DEVICE_EXTENSION($data$3$2812.22$MouseClassUnload$4) := 0];
+goto label_79;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(2881)
+label_79:
+Mem[T.DataIn__DEVICE_EXTENSION] := Mem[T.DataIn__DEVICE_EXTENSION][DataIn__DEVICE_EXTENSION($data$3$2812.22$MouseClassUnload$4) := Mem[T.DataOut__DEVICE_EXTENSION][DataOut__DEVICE_EXTENSION($data$3$2812.22$MouseClassUnload$4)]];
+goto label_80;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(2881)
+label_80:
+Mem[T.InputData__DEVICE_EXTENSION] := Mem[T.InputData__DEVICE_EXTENSION][InputData__DEVICE_EXTENSION($data$3$2812.22$MouseClassUnload$4) := Mem[T.DataIn__DEVICE_EXTENSION][DataIn__DEVICE_EXTENSION($data$3$2812.22$MouseClassUnload$4)]];
+goto label_81;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(2881)
+label_81:
+call IoDeleteDevice (Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION($data$3$2812.22$MouseClassUnload$4)]);
+goto label_84;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(2881)
+label_84:
+$data$3$2812.22$MouseClassUnload$4 := 0 ;
+goto label_15_head;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(2887)
+label_85:
+goto label_85_true , label_85_false ;
+
+
+label_85_true :
+assume (Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)] != 0);
+goto label_86;
+
+
+label_85_false :
+assume (Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)] == 0);
+goto label_102;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(2888)
+label_86:
+$data$3$2812.22$MouseClassUnload$4 := Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)] ;
+goto label_87;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(2889)
+label_87:
+Mem[T.GrandMaster__GLOBALS] := Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals) := 0];
+goto label_88;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(2891)
+label_88:
+call MouseClassCleanupQueue (Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION($data$3$2812.22$MouseClassUnload$4)], $data$3$2812.22$MouseClassUnload$4, 0);
+goto label_91;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(2892)
+label_91:
+goto label_91_true , label_91_false ;
+
+
+label_91_true :
+assume (Mem[T.InputData__DEVICE_EXTENSION][InputData__DEVICE_EXTENSION($data$3$2812.22$MouseClassUnload$4)] != 0);
+goto label_92;
+
+
+label_91_false :
+assume (Mem[T.InputData__DEVICE_EXTENSION][InputData__DEVICE_EXTENSION($data$3$2812.22$MouseClassUnload$4)] == 0);
+goto label_98;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(2892)
+label_92:
+call ExFreePoolWithTag (Mem[T.InputData__DEVICE_EXTENSION][InputData__DEVICE_EXTENSION($data$3$2812.22$MouseClassUnload$4)], 0);
+goto label_95;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(2892)
+label_95:
+Mem[T.DataOut__DEVICE_EXTENSION] := Mem[T.DataOut__DEVICE_EXTENSION][DataOut__DEVICE_EXTENSION($data$3$2812.22$MouseClassUnload$4) := 0];
+goto label_96;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(2892)
+label_96:
+Mem[T.DataIn__DEVICE_EXTENSION] := Mem[T.DataIn__DEVICE_EXTENSION][DataIn__DEVICE_EXTENSION($data$3$2812.22$MouseClassUnload$4) := Mem[T.DataOut__DEVICE_EXTENSION][DataOut__DEVICE_EXTENSION($data$3$2812.22$MouseClassUnload$4)]];
+goto label_97;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(2892)
+label_97:
+Mem[T.InputData__DEVICE_EXTENSION] := Mem[T.InputData__DEVICE_EXTENSION][InputData__DEVICE_EXTENSION($data$3$2812.22$MouseClassUnload$4) := Mem[T.DataIn__DEVICE_EXTENSION][DataIn__DEVICE_EXTENSION($data$3$2812.22$MouseClassUnload$4)]];
+goto label_98;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(2892)
+label_98:
+call IoDeleteDevice (Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION($data$3$2812.22$MouseClassUnload$4)]);
+goto label_101;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(2892)
+label_101:
+$data$3$2812.22$MouseClassUnload$4 := 0 ;
+goto label_102;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(2895)
+label_102:
+call ExFreePoolWithTag (Mem[T.Buffer__UNICODE_STRING][Buffer__UNICODE_STRING(RegistryPath__GLOBALS(Globals))], 0);
+goto label_105;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(2896)
+label_105:
+goto label_105_true , label_105_false ;
+
+
+label_105_true :
+assume (Mem[T.AssocClassList__GLOBALS][AssocClassList__GLOBALS(Globals)] != 0);
+goto label_106;
+
+
+label_105_false :
+assume (Mem[T.AssocClassList__GLOBALS][AssocClassList__GLOBALS(Globals)] == 0);
+goto label_134;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(2898)
+label_106:
+goto label_107;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(2900)
+label_107:
+$i$8$2898.14$MouseClassUnload$4 := 0 ;
+goto label_108;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(2900)
+label_108:
+// loop entry initialization...
+LOOP_108_alloc := alloc;
+LOOP_108_Mem := Mem;
+LOOP_108_Res_DEVICE_STACK := Res_DEVICE_STACK;
+LOOP_108_Res_DEV_EXTN := Res_DEV_EXTN;
+LOOP_108_Res_DEV_OBJ_INIT := Res_DEV_OBJ_INIT;
+LOOP_108_Res_SPIN_LOCK := Res_SPIN_LOCK;
+goto label_108_head;
+
+
+label_108_head:
+// loop head assertions...
+//TAG: requires __pforall(_H_x, (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension), __inv_resource("DEV_OBJ_INIT", 1), ((struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension))->Self == _H_x && __resource("DEV_EXTN", (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)_H_x)->DeviceExtension)) == 1)
+assert((forall _H_x:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)]} Inverse(Res_DEV_OBJ_INIT,1)[_H_x] ==> ((Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)])] == _H_x) && (Res_DEV_EXTN[Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(_H_x)]] == 1))));
+//TAG: requires __pforall(_H_z, _H_z->Self, __inv_resource("DEV_EXTN", 1), __resource("DEV_OBJ_INIT", _H_z->Self) == 1 && (struct _DEVICE_EXTENSION *)(((struct _DEVICE_OBJECT *)(_H_z->Self))->DeviceExtension) == _H_z)
+assert((forall _H_z:int :: {Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)]} Inverse(Res_DEV_EXTN,1)[_H_z] ==> ((Res_DEV_OBJ_INIT[Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)]] == 1) && (Mem[T.DeviceExtension__DEVICE_OBJECT][DeviceExtension__DEVICE_OBJECT(Mem[T.Self__DEVICE_EXTENSION][Self__DEVICE_EXTENSION(_H_z)])] == _H_z))));
+//TAG: requires __forall(_H_z, __inv_resource("DEV_EXTN", 1), __resource("SPIN_LOCK", &_H_z->SpinLock) == 0 && __resource("SPIN_LOCK", &_H_z->WaitWakeSpinLock) == 0)
+assert((Subset(Empty(), Inverse(Res_DEV_EXTN,1)) && (forall _H_z : int :: {Inverse(Res_DEV_EXTN,1)[_H_z]} (Inverse(Res_DEV_EXTN,1)[_H_z]) ==> ((Res_SPIN_LOCK[SpinLock__DEVICE_EXTENSION(_H_z)] == 0) && (Res_SPIN_LOCK[WaitWakeSpinLock__DEVICE_EXTENSION(_H_z)] == 0)))));
+//TAG: requires 1 ==> (Globals.GrandMaster != (void *)0 ==> __resource("DEV_EXTN", Globals.GrandMaster) == 1)
+assert((true) ==> ((Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)] != 0) ==> (Res_DEV_EXTN[Mem[T.GrandMaster__GLOBALS][GrandMaster__GLOBALS(Globals)]] == 1)));
+//TAG: requires 1 ==> __setin(&Globals.LegacyDeviceList, __btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList))
+assert((true) ==> (ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[LegacyDeviceList__GLOBALS(Globals)]));
+//TAG: requires 1 ==> __forall(_H_y, __btwn(__offset((*((struct _LIST_ENTRY *)0)).Flink), (&Globals.LegacyDeviceList)->Flink, &Globals.LegacyDeviceList), _H_y == &Globals.LegacyDeviceList || __resource("DEV_EXTN", CONTAINING_RECORD(_H_y, struct _DEVICE_EXTENSION , Link)) == 1)
+assert((true) ==> ((Subset(Empty(), ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))) && (forall _H_y : int :: {ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[_H_y]} (ReachBetweenSet(Shift_Flink__LIST_ENTRY(Mem[T.Flink__LIST_ENTRY]), Mem[T.Flink__LIST_ENTRY][Flink__LIST_ENTRY(LegacyDeviceList__GLOBALS(Globals))], LegacyDeviceList__GLOBALS(Globals))[_H_y]) ==> ((_H_y == LegacyDeviceList__GLOBALS(Globals)) || (Res_DEV_EXTN[MINUS_LEFT_PTR(_H_y, 1, Link__DEVICE_EXTENSION(0))] == 1))))));
+//TAG: requires __preserves_resource("DEV_OBJ_INIT")
+assert(Res_DEV_OBJ_INIT == LOOP_108_Res_DEV_OBJ_INIT);
+//TAG: requires __preserves_resource("DEV_EXTN")
+assert(Res_DEV_EXTN == LOOP_108_Res_DEV_EXTN);
+//TAG: requires __preserves_field_map(__offset((*((struct _LIST_ENTRY *)0)).Flink))
+assert(Mem[T.Flink__LIST_ENTRY] == LOOP_108_Mem[T.Flink__LIST_ENTRY]);
+assume(forall f:int :: {alloc[Base(f)]} LOOP_108_alloc[Base(f)] == UNALLOCATED || LOOP_108_alloc[Base(f)] == alloc[Base(f)]);
+
+
+//TAG: net change in resource DEVICE_STACK only for: __set_empty
+assert (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEVICE_STACK[r]} (Empty()[r]) || LOOP_108_Res_DEVICE_STACK[r] == Res_DEVICE_STACK[r]));
+
+//TAG: net change in resource DEV_EXTN only for: __set_empty
+assert (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_EXTN[r]} (Empty()[r]) || LOOP_108_Res_DEV_EXTN[r] == Res_DEV_EXTN[r]));
+
+//TAG: net change in resource DEV_OBJ_INIT only for: __set_empty
+assert (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_DEV_OBJ_INIT[r]} (Empty()[r]) || LOOP_108_Res_DEV_OBJ_INIT[r] == Res_DEV_OBJ_INIT[r]));
+
+//TAG: net change in resource SPIN_LOCK only for: __set_empty
+assert (Subset(Empty(), Union(Empty(), Empty())) && (forall r:int :: {Res_SPIN_LOCK[r]} (Empty()[r]) || LOOP_108_Res_SPIN_LOCK[r] == Res_SPIN_LOCK[r]));
+//TAG: updated memory locations at Mem[T.MinorFunction__IO_STACK_LOCATION] only for: __set_empty
+assert (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.MinorFunction__IO_STACK_LOCATION][_m]} (Empty()[_m]) || Mem[T.MinorFunction__IO_STACK_LOCATION][_m] == LOOP_108_Mem[T.MinorFunction__IO_STACK_LOCATION][_m]));
+//TAG: updated memory locations at Mem[T.CurrentStackLocation___unnamed_4_a7aa989c] only for: __set_empty
+assert (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.CurrentStackLocation___unnamed_4_a7aa989c][_m]} (Empty()[_m]) || Mem[T.CurrentStackLocation___unnamed_4_a7aa989c][_m] == LOOP_108_Mem[T.CurrentStackLocation___unnamed_4_a7aa989c][_m]));
+//TAG: updated memory locations at Mem[T.DeviceExtension__DEVICE_OBJECT] only for: __set_empty
+assert (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.DeviceExtension__DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.DeviceExtension__DEVICE_OBJECT][_m] == LOOP_108_Mem[T.DeviceExtension__DEVICE_OBJECT][_m]));
+//TAG: updated memory locations at Mem[T.Self__DEVICE_EXTENSION] only for: __set_empty
+assert (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Self__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Self__DEVICE_EXTENSION][_m] == LOOP_108_Mem[T.Self__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.Started__DEVICE_EXTENSION] only for: __set_empty
+assert (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.Started__DEVICE_EXTENSION][_m]} (Empty()[_m]) || Mem[T.Started__DEVICE_EXTENSION][_m] == LOOP_108_Mem[T.Started__DEVICE_EXTENSION][_m]));
+//TAG: updated memory locations at Mem[T.GrandMaster__GLOBALS] only for: __set_empty
+assert (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.GrandMaster__GLOBALS][_m]} (Empty()[_m]) || Mem[T.GrandMaster__GLOBALS][_m] == LOOP_108_Mem[T.GrandMaster__GLOBALS][_m]));
+//TAG: updated memory locations at Mem[T.P_DEVICE_OBJECT] only for: __set_empty
+assert (Subset(Empty(), Union(Empty(), Empty())) && (forall _m:int :: {Mem[T.P_DEVICE_OBJECT][_m]} (Empty()[_m]) || Mem[T.P_DEVICE_OBJECT][_m] == LOOP_108_Mem[T.P_DEVICE_OBJECT][_m]));
+
+// end loop head assertions
+
+goto label_108_true , label_108_false ;
+
+
+label_108_true :
+assume ($i$8$2898.14$MouseClassUnload$4 < Mem[T.NumAssocClass__GLOBALS][NumAssocClass__GLOBALS(Globals)]);
+goto label_109;
+
+
+label_108_false :
+assume !($i$8$2898.14$MouseClassUnload$4 < Mem[T.NumAssocClass__GLOBALS][NumAssocClass__GLOBALS(Globals)]);
+goto label_128;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(2901)
+label_109:
+goto label_109_true , label_109_false ;
+
+
+label_109_true :
+assume (Mem[T.Free__PORT][Free__PORT(PLUS(Mem[T.AssocClassList__GLOBALS][AssocClassList__GLOBALS(Globals)], 12, $i$8$2898.14$MouseClassUnload$4))] == 1);
+goto label_115;
+
+
+label_109_false :
+assume !(Mem[T.Free__PORT][Free__PORT(PLUS(Mem[T.AssocClassList__GLOBALS][AssocClassList__GLOBALS(Globals)], 12, $i$8$2898.14$MouseClassUnload$4))] == 1);
+goto label_113;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(2901)
+label_110:
+// skip RtlAssert
+goto label_115;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(2901)
+label_113:
+call havoc_stringTemp := __HAVOC_malloc(1);
+$RtlAssert.arg.2$13$ := havoc_stringTemp ;
+goto label_114;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(2901)
+label_114:
+call havoc_stringTemp := __HAVOC_malloc(1);
+$RtlAssert.arg.1$14$ := havoc_stringTemp ;
+goto label_110;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(2902)
+label_115:
+goto label_115_true , label_115_false ;
+
+
+label_115_true :
+assume (Mem[T.Enabled__PORT][Enabled__PORT(PLUS(Mem[T.AssocClassList__GLOBALS][AssocClassList__GLOBALS(Globals)], 12, $i$8$2898.14$MouseClassUnload$4))] != 0);
+goto label_119;
+
+
+label_115_false :
+assume (Mem[T.Enabled__PORT][Enabled__PORT(PLUS(Mem[T.AssocClassList__GLOBALS][AssocClassList__GLOBALS(Globals)], 12, $i$8$2898.14$MouseClassUnload$4))] == 0);
+goto label_121;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(2902)
+label_116:
+// skip RtlAssert
+goto label_121;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(2902)
+label_119:
+call havoc_stringTemp := __HAVOC_malloc(1);
+$RtlAssert.arg.2$15$ := havoc_stringTemp ;
+goto label_120;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(2902)
+label_120:
+call havoc_stringTemp := __HAVOC_malloc(1);
+$RtlAssert.arg.1$16$ := havoc_stringTemp ;
+goto label_116;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(2903)
+label_121:
+goto label_121_true , label_121_false ;
+
+
+label_121_true :
+assume (Mem[T.File__PORT][File__PORT(PLUS(Mem[T.AssocClassList__GLOBALS][AssocClassList__GLOBALS(Globals)], 12, $i$8$2898.14$MouseClassUnload$4))] != 0);
+goto label_125;
+
+
+label_121_false :
+assume (Mem[T.File__PORT][File__PORT(PLUS(Mem[T.AssocClassList__GLOBALS][AssocClassList__GLOBALS(Globals)], 12, $i$8$2898.14$MouseClassUnload$4))] == 0);
+goto label_127;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(2903)
+label_122:
+// skip RtlAssert
+goto label_127;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(2903)
+label_125:
+call havoc_stringTemp := __HAVOC_malloc(1);
+$RtlAssert.arg.2$17$ := havoc_stringTemp ;
+goto label_126;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(2903)
+label_126:
+call havoc_stringTemp := __HAVOC_malloc(1);
+$RtlAssert.arg.1$18$ := havoc_stringTemp ;
+goto label_122;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(2900)
+label_127:
+$i$8$2898.14$MouseClassUnload$4 := PLUS($i$8$2898.14$MouseClassUnload$4, 1, 1) ;
+goto label_108_head;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(2907)
+label_128:
+call ExFreePoolWithTag (Mem[T.AssocClassList__GLOBALS][AssocClassList__GLOBALS(Globals)], 0);
+goto label_134;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(2910)
+label_131:
+// skip MouDebugPrint
+goto label_1;
+
+
+// e:\esp1\esp\tests\hvdrivers\houdini\mouclass_fbl_fbs_dev2_ntfs\mouclass.c(2910)
+label_134:
+call havoc_stringTemp := __HAVOC_malloc(1);
+$MouDebugPrint.arg.2$19$ := havoc_stringTemp ;
+goto label_131;
+
+}
+
diff --git a/Test/havoc0/Output b/Test/havoc0/Output
new file mode 100644
index 00000000..80fd4aa3
--- /dev/null
+++ b/Test/havoc0/Output
@@ -0,0 +1,12 @@
+
+Boogie program verifier finished with 1 verified, 0 errors
+
+Boogie program verifier finished with 1 verified, 0 errors
+
+Boogie program verifier finished with 1 verified, 0 errors
+
+Boogie program verifier finished with 1 verified, 0 errors
+
+Boogie program verifier finished with 1 verified, 0 errors
+
+Boogie program verifier finished with 1 verified, 0 errors
diff --git a/Test/havoc0/runtest.bat b/Test/havoc0/runtest.bat
new file mode 100644
index 00000000..1be15364
--- /dev/null
+++ b/Test/havoc0/runtest.bat
@@ -0,0 +1,13 @@
+@echo off
+setlocal
+
+set BGEXE=..\..\Binaries\Boogie.exe
+rem set BGEXE=mono ..\..\Binaries\Boogie.exe
+
+%BGEXE% %* /monomorphize KbdCreateClassObject.bpl
+%BGEXE% %* /monomorphize KeyboardClassFindMorePorts.bpl
+%BGEXE% %* /monomorphize KeyboardClassUnload.bpl
+%BGEXE% %* /monomorphize MouCreateClassObject.bpl
+%BGEXE% %* /monomorphize MouseClassFindMorePorts.bpl
+%BGEXE% %* /monomorphize MouseClassUnload.bpl
+
diff --git a/Test/houdini/Answer b/Test/houdini/Answer
new file mode 100644
index 00000000..8c0f30ea
--- /dev/null
+++ b/Test/houdini/Answer
@@ -0,0 +1,78 @@
+
+-------------------- houd1.bpl --------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
+
+-------------------- houd2.bpl --------------------
+----------------------------------------
+Functions: Errors
+ bar
+----------------------------------------
+houd2.bpl(12,1): Error BP5003: A postcondition might not hold at this return statement.
+houd2.bpl(9,1): Related location: This is the postcondition that might not hold.
+Execution trace:
+ houd2.bpl(11,3): anon0
+
+Boogie program verifier finished with 1 verified, 1 error
+
+-------------------- houd3.bpl --------------------
+
+Boogie program verifier finished with 2 verified, 0 errors
+
+-------------------- houd4.bpl --------------------
+
+Boogie program verifier finished with 2 verified, 0 errors
+
+-------------------- houd5.bpl --------------------
+
+Boogie program verifier finished with 2 verified, 0 errors
+
+-------------------- houd6.bpl --------------------
+
+Boogie program verifier finished with 3 verified, 0 errors
+
+-------------------- houd7.bpl --------------------
+
+Boogie program verifier finished with 2 verified, 0 errors
+
+-------------------- houd8.bpl --------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
+
+-------------------- houd9.bpl --------------------
+----------------------------------------
+Functions: Errors
+ foo
+----------------------------------------
+houd9.bpl(19,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ houd9.bpl(18,9): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+
+-------------------- houd10.bpl --------------------
+----------------------------------------
+Functions: Errors
+ foo
+----------------------------------------
+houd10.bpl(15,3): Error BP5002: A precondition for this call might not hold.
+houd10.bpl(20,1): Related location: This is the precondition that might not hold.
+Execution trace:
+ houd10.bpl(14,9): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+
+-------------------- houd11.bpl --------------------
+----------------------------------------
+Functions: Errors
+ foo
+----------------------------------------
+houd11.bpl(8,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ houd11.bpl(7,9): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+
+-------------------- houd12.bpl --------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
diff --git a/Test/houdini/houd1.bpl b/Test/houdini/houd1.bpl
new file mode 100644
index 00000000..4acea845
--- /dev/null
+++ b/Test/houdini/houd1.bpl
@@ -0,0 +1,19 @@
+const {:existential true} b1:bool;
+
+var myVar: int;
+
+procedure foo (i:int)
+modifies myVar;
+// comment
+ensures b1 ==> myVar>0;
+ensures myVar!=-1;
+{
+ if (i>0) {
+ myVar := 5;
+ } else {
+ myVar := 0;
+ }
+}
+
+// expected output: Correct
+// expected end assigment: b1->False \ No newline at end of file
diff --git a/Test/houdini/houd10.bpl b/Test/houdini/houd10.bpl
new file mode 100644
index 00000000..1eea1691
--- /dev/null
+++ b/Test/houdini/houd10.bpl
@@ -0,0 +1,23 @@
+const {:existential true} b1:bool;
+const {:existential true} b2:bool;
+const {:existential true} b3:bool;
+
+var fooVar: int;
+var xVar: int;
+
+procedure foo()
+modifies fooVar;
+modifies xVar;
+ensures b1 ==> fooVar==0;
+ensures b3 ==> xVar<0;
+{
+ fooVar:=5;
+ call bar();
+}
+
+procedure bar();
+modifies xVar;
+requires fooVar!=5;
+
+// expected outcome: Errors
+// expected assigment: b1->True,b2->True,b3->True \ No newline at end of file
diff --git a/Test/houdini/houd11.bpl b/Test/houdini/houd11.bpl
new file mode 100644
index 00000000..df9f9e3f
--- /dev/null
+++ b/Test/houdini/houd11.bpl
@@ -0,0 +1,13 @@
+
+var fooVar: int;
+
+procedure foo()
+modifies fooVar;
+{
+ fooVar:=5;
+ assert(fooVar==4);
+ assert(fooVar==3);
+}
+
+// expected outcome: Errors
+// expected assigment: [] \ No newline at end of file
diff --git a/Test/houdini/houd12.bpl b/Test/houdini/houd12.bpl
new file mode 100644
index 00000000..f3152720
--- /dev/null
+++ b/Test/houdini/houd12.bpl
@@ -0,0 +1,58 @@
+// Example to test candidate annotations on loops
+
+const {:existential true} b1:bool;
+const {:existential true} b2:bool;
+const {:existential true} b3:bool;
+const {:existential true} b4:bool;
+const {:existential true} b5:bool;
+const {:existential true} b6:bool;
+const {:existential true} b7:bool;
+
+var x: int;
+var y: int;
+
+
+procedure foo()
+modifies x;
+modifies y;
+ensures (b4 ==> x == 0);
+ensures (b5 ==> y == 10);
+ensures (b6 ==> x == 10);
+ensures (b7 ==> y == 11);
+
+{
+ x := 10;
+ y := 0;
+
+ goto Head;
+
+Head:
+
+ //loop invariants
+ assert (b1 ==> x < 0);
+ assert (b2 ==> x >= 0);
+ assert (b3 ==> x + y == 10);
+ goto Body, Exit;
+
+Body:
+ assume x > 0;
+ x := x - 1;
+ y := y + 1;
+
+
+ goto Head;
+
+Exit:
+ assume !(x > 0);
+ return;
+}
+
+// expected outcome: Correct
+// expected assigment: b1->False,b2->True,b3->True,b4->True, b5->True, b6->False,b7->False
+
+
+
+
+
+
+
diff --git a/Test/houdini/houd2.bpl b/Test/houdini/houd2.bpl
new file mode 100644
index 00000000..375f662e
--- /dev/null
+++ b/Test/houdini/houd2.bpl
@@ -0,0 +1,27 @@
+const {:existential true} b1:bool;
+const {:existential true} b2:bool;
+
+
+var myVar: int;
+
+procedure bar(i:int)
+modifies myVar;
+ensures myVar>0;
+{
+ call foo(5);
+}
+
+procedure foo (i:int)
+modifies myVar;
+ensures b1 ==> myVar>0;
+ensures myVar!=-1;
+{
+ if (i>0) {
+ myVar := 5;
+ } else {
+ myVar := 0;
+ }
+}
+
+// expected output: Errors
+// expected end assigment: b1->False b2->True
diff --git a/Test/houdini/houd3.bpl b/Test/houdini/houd3.bpl
new file mode 100644
index 00000000..4cff2cad
--- /dev/null
+++ b/Test/houdini/houd3.bpl
@@ -0,0 +1,27 @@
+const {:existential true} b1:bool;
+const {:existential true} b2:bool;
+
+
+var myVar: int;
+
+procedure bar(i:int)
+modifies myVar;
+ensures b2==>myVar>0;
+{
+ call foo(5);
+}
+
+procedure foo (i:int)
+modifies myVar;
+ensures b1 ==> myVar>0;
+ensures myVar!=-1;
+{
+ if (i>0) {
+ myVar := 5;
+ } else {
+ myVar := 0;
+ }
+}
+
+// expected output: Correct
+// expected end assigment: b1->False b2->False \ No newline at end of file
diff --git a/Test/houdini/houd4.bpl b/Test/houdini/houd4.bpl
new file mode 100644
index 00000000..9895d633
--- /dev/null
+++ b/Test/houdini/houd4.bpl
@@ -0,0 +1,27 @@
+const {:existential true} b1:bool;
+const {:existential true} b2:bool;
+const {:existential true} b3:bool;
+const {:existential true} b4:bool;
+
+var array:[int]int;
+
+procedure foo (i:int)
+requires b2 ==> i > 0;
+ensures b3 ==> array[i] > 0;
+modifies array;
+ensures (forall x:int :: {array[x]} x == i || array[x] == old(array)[x]);
+{
+ array[i] := 2 * i;
+}
+
+procedure bar (j:int) returns (result:int)
+requires b4 ==> j > 0;
+modifies array;
+ensures (forall x:int :: {array[x]} (b1 && x == j) || array[x] == old(array)[x]);
+{
+ call foo(j);
+ result := array[j];
+}
+
+// expected outcome: Correct
+// expected assignment: b1->True,b2->True,b3->True,b4->True \ No newline at end of file
diff --git a/Test/houdini/houd5.bpl b/Test/houdini/houd5.bpl
new file mode 100644
index 00000000..9cd9363f
--- /dev/null
+++ b/Test/houdini/houd5.bpl
@@ -0,0 +1,29 @@
+const {:existential true} b1:bool;
+const {:existential true} b2:bool;
+const {:existential true} b3:bool;
+const {:existential true} b4:bool;
+const {:existential true} b5:bool;
+
+var array:[int]int;
+
+procedure foo (i:int)
+requires b1 ==> i == 0;
+requires b2 ==> i > 0;
+requires b3 ==> i < 0;
+ensures b4 ==> array[i] > 0;
+modifies array;
+ensures (forall x:int :: {array[x]} x == i || array[x] == old(array)[x]);
+{
+ array[i] := 2 * i;
+}
+
+procedure bar (j:int) returns (result:int)
+requires b5 ==> j > 0;
+modifies array;
+{
+ call foo(j);
+ result := array[j];
+}
+
+// expected outcome: Correct
+// expected assigment: b1->False,b2->true,b3->False,b4->True,b5->True \ No newline at end of file
diff --git a/Test/houdini/houd6.bpl b/Test/houdini/houd6.bpl
new file mode 100644
index 00000000..09f2dd0e
--- /dev/null
+++ b/Test/houdini/houd6.bpl
@@ -0,0 +1,44 @@
+const {:existential true} b1:bool;
+const {:existential true} b2:bool;
+const {:existential true} b3:bool;
+const {:existential true} b4:bool;
+const {:existential true} b5:bool;
+const {:existential true} b6:bool;
+const {:existential true} b7:bool;
+const {:existential true} b8:bool;
+
+var array:[int]int;
+
+procedure foo (i:int)
+requires b6 ==> i < 0;
+requires b5 ==> i == 0;
+requires b2 ==> i > 0;
+ensures b3 ==> array[i] > 0;
+modifies array;
+ensures (forall x:int :: {array[x]} x == i || array[x] == old(array)[x]);
+{
+ array[i] := 2 * i;
+}
+
+procedure bar (j:int) returns (result:int)
+requires b8 ==> j < 0;
+requires b7 ==> j == 0;
+requires b4 ==> j > 0;
+modifies array;
+ensures (forall x:int :: {array[x]} (x == j) || array[x] == old(array)[x]);
+ensures (b1 ==> array[j] == old(array)[j]);
+{
+ call foo(j);
+ result := array[j];
+}
+
+var p:int;
+
+procedure main() returns (result: int)
+modifies array;
+{
+ call result:= bar(p);
+}
+
+// expected outcome: Correct
+// expected assigment: bi->True forall i \ No newline at end of file
diff --git a/Test/houdini/houd7.bpl b/Test/houdini/houd7.bpl
new file mode 100644
index 00000000..aaa1971d
--- /dev/null
+++ b/Test/houdini/houd7.bpl
@@ -0,0 +1,35 @@
+const {:existential true} b1:bool;
+const {:existential true} b2:bool;
+const {:existential true} b3:bool;
+
+var myVar: int;
+
+procedure foo(i:int)
+requires b1 ==> i>0;
+requires b2 ==> i==0;
+requires b3 ==> i<0;
+modifies myVar;
+ensures myVar>0;
+{
+ myVar:=5;
+}
+
+procedure bar(i:int)
+modifies myVar;
+{
+ call foo(5);
+}
+// expected outcome: Correct
+// expected Assigment: b1->True,b2->False,b3->False
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Test/houdini/houd8.bpl b/Test/houdini/houd8.bpl
new file mode 100644
index 00000000..b57ef305
--- /dev/null
+++ b/Test/houdini/houd8.bpl
@@ -0,0 +1,30 @@
+const {:existential true} b1:bool;
+const {:existential true} b2:bool;
+const {:existential true} b3:bool;
+
+var myVar: int;
+
+procedure foo(i:int)
+modifies myVar;
+ensures b1 ==> myVar>0;
+ensures b2 ==> myVar==0;
+ensures b3 ==> myVar<0;
+{
+ myVar:=5;
+}
+
+// expected outcome: Correct
+// expected assigment: b1->True,b2->False,b3->False
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Test/houdini/houd9.bpl b/Test/houdini/houd9.bpl
new file mode 100644
index 00000000..a43a2bbb
--- /dev/null
+++ b/Test/houdini/houd9.bpl
@@ -0,0 +1,32 @@
+const {:existential true} b1:bool;
+const {:existential true} b2:bool;
+const {:existential true} b3:bool;
+
+axiom(b1 && b2 && b3);
+
+var fooVar: int;
+var xVar: int;
+
+
+procedure foo()
+modifies fooVar;
+modifies xVar;
+ensures b1 ==> fooVar>0;
+ensures b2 ==> fooVar==0;
+ensures b3 ==> xVar<0;
+{
+ fooVar:=5;
+ assert(fooVar>5);
+ xVar:=0;
+ assert(xVar>0);
+}
+
+// expected outcome: Errors
+// expected assigment: b1->True,b2->True,b3->True
+
+
+
+
+
+
+
diff --git a/Test/houdini/runtest.bat b/Test/houdini/runtest.bat
new file mode 100644
index 00000000..ae82455a
--- /dev/null
+++ b/Test/houdini/runtest.bat
@@ -0,0 +1,11 @@
+@echo off
+setlocal
+
+set BGEXE=..\..\Binaries\Boogie.exe
+
+for %%f in (houd1.bpl houd2.bpl houd3.bpl houd4.bpl houd5.bpl houd6.bpl houd7.bpl houd8.bpl houd9.bpl houd10.bpl houd11.bpl houd12.bpl) do (
+ echo.
+ echo -------------------- %%f --------------------
+ %BGEXE% %* /nologo /prover:z3 /Houdini:ci %%f
+rem %BGEXE% %* /nologo /prover:z3api /Houdini:ci %%f
+)
diff --git a/Test/inline/Answer b/Test/inline/Answer
new file mode 100644
index 00000000..39d5a5b4
--- /dev/null
+++ b/Test/inline/Answer
@@ -0,0 +1,983 @@
+-------------------- test1.bpl --------------------
+
+procedure Main();
+
+
+
+implementation Main()
+{
+ var x: int;
+ var y: int;
+
+ anon0:
+ x := 1;
+ y := 0;
+ call x := inc(x, 5);
+ call y := incdec(x, 2);
+ assert x - 1 == y;
+ return;
+}
+
+
+
+procedure {:inline 1} incdec(x: int, y: int) returns (z: int);
+ ensures z == x + 1 - y;
+
+
+
+implementation incdec(x: int, y: int) returns (z: int)
+{
+
+ anon0:
+ z := x;
+ z := x + 1;
+ call z := dec(z, y);
+ return;
+}
+
+
+
+procedure {:inline 1} inc(x: int, i: int) returns (y: int);
+ ensures y == x + i;
+
+
+
+implementation inc(x: int, i: int) returns (y: int)
+{
+
+ anon0:
+ y := x;
+ y := x + i;
+ return;
+}
+
+
+
+procedure {:inline 1} dec(x: int, i: int) returns (y: int);
+ ensures y == x - i;
+
+
+
+implementation dec(x: int, i: int) returns (y: int)
+{
+
+ anon0:
+ y := x;
+ y := x - i;
+ return;
+}
+
+
+after inlining procedure calls
+procedure Main();
+
+
+implementation Main()
+{
+ var x: int;
+ var y: int;
+ var inline$inc$0$x: int;
+ var inline$inc$0$i: int;
+ var inline$inc$0$y: int;
+ var inline$incdec$0$x: int;
+ var inline$incdec$0$y: int;
+ var inline$incdec$0$z: int;
+ var inline$dec$0$x: int;
+ var inline$dec$0$i: int;
+ var inline$dec$0$y: int;
+
+ anon0:
+ x := 1;
+ y := 0;
+ goto inline$inc$0$Entry;
+
+ inline$inc$0$Entry:
+ inline$inc$0$x := x;
+ inline$inc$0$i := 5;
+ goto inline$inc$0$anon0;
+
+ inline$inc$0$anon0:
+ inline$inc$0$y := inline$inc$0$x;
+ inline$inc$0$y := inline$inc$0$x + inline$inc$0$i;
+ goto inline$inc$0$Return;
+
+ inline$inc$0$Return:
+ assert inline$inc$0$y == inline$inc$0$x + inline$inc$0$i;
+ x := inline$inc$0$y;
+ goto anon0$1;
+
+ anon0$1:
+ goto inline$incdec$0$Entry;
+
+ inline$incdec$0$Entry:
+ inline$incdec$0$x := x;
+ inline$incdec$0$y := 2;
+ goto inline$incdec$0$anon0;
+
+ inline$incdec$0$anon0:
+ inline$incdec$0$z := inline$incdec$0$x;
+ inline$incdec$0$z := inline$incdec$0$x + 1;
+ goto inline$dec$0$Entry;
+
+ inline$dec$0$Entry:
+ inline$dec$0$x := inline$incdec$0$z;
+ inline$dec$0$i := inline$incdec$0$y;
+ goto inline$dec$0$anon0;
+
+ inline$dec$0$anon0:
+ inline$dec$0$y := inline$dec$0$x;
+ inline$dec$0$y := inline$dec$0$x - inline$dec$0$i;
+ goto inline$dec$0$Return;
+
+ inline$dec$0$Return:
+ assert inline$dec$0$y == inline$dec$0$x - inline$dec$0$i;
+ inline$incdec$0$z := inline$dec$0$y;
+ goto inline$incdec$0$anon0$1;
+
+ inline$incdec$0$anon0$1:
+ goto inline$incdec$0$Return;
+
+ inline$incdec$0$Return:
+ assert inline$incdec$0$z == inline$incdec$0$x + 1 - inline$incdec$0$y;
+ y := inline$incdec$0$z;
+ goto anon0$2;
+
+ anon0$2:
+ assert x - 1 == y;
+ return;
+}
+
+
+after inlining procedure calls
+procedure {:inline 1} incdec(x: int, y: int) returns (z: int);
+ ensures z == x + 1 - y;
+
+
+implementation incdec(x: int, y: int) returns (z: int)
+{
+ var inline$dec$0$x: int;
+ var inline$dec$0$i: int;
+ var inline$dec$0$y: int;
+
+ anon0:
+ z := x;
+ z := x + 1;
+ goto inline$dec$0$Entry;
+
+ inline$dec$0$Entry:
+ inline$dec$0$x := z;
+ inline$dec$0$i := y;
+ goto inline$dec$0$anon0;
+
+ inline$dec$0$anon0:
+ inline$dec$0$y := inline$dec$0$x;
+ inline$dec$0$y := inline$dec$0$x - inline$dec$0$i;
+ goto inline$dec$0$Return;
+
+ inline$dec$0$Return:
+ assert inline$dec$0$y == inline$dec$0$x - inline$dec$0$i;
+ z := inline$dec$0$y;
+ goto anon0$1;
+
+ anon0$1:
+ return;
+}
+
+
+
+Boogie program verifier finished with 4 verified, 0 errors
+-------------------- test2.bpl --------------------
+
+var glb: int;
+
+procedure calculate();
+ modifies glb;
+
+
+
+implementation calculate()
+{
+ var x: int;
+ var y: int;
+
+ anon0:
+ y := 5;
+ call x := increase(y);
+ return;
+}
+
+
+
+procedure {:inline 1} increase(i: int) returns (k: int);
+ modifies glb;
+
+
+
+implementation increase(i: int) returns (k: int)
+{
+ var j: int;
+
+ anon0:
+ j := i;
+ j := j + 1;
+ glb := glb + j;
+ k := j;
+ return;
+}
+
+
+after inlining procedure calls
+procedure calculate();
+ modifies glb;
+
+
+implementation calculate()
+{
+ var x: int;
+ var y: int;
+ var inline$increase$0$j: int;
+ var inline$increase$0$i: int;
+ var inline$increase$0$k: int;
+ var inline$increase$0$glb: int;
+
+ anon0:
+ y := 5;
+ goto inline$increase$0$Entry;
+
+ inline$increase$0$Entry:
+ inline$increase$0$i := y;
+ inline$increase$0$glb := glb;
+ goto inline$increase$0$anon0;
+
+ inline$increase$0$anon0:
+ inline$increase$0$j := inline$increase$0$i;
+ inline$increase$0$j := inline$increase$0$j + 1;
+ glb := glb + inline$increase$0$j;
+ inline$increase$0$k := inline$increase$0$j;
+ goto inline$increase$0$Return;
+
+ inline$increase$0$Return:
+ x := inline$increase$0$k;
+ goto anon0$1;
+
+ anon0$1:
+ return;
+}
+
+
+
+Boogie program verifier finished with 2 verified, 0 errors
+-------------------- test3.bpl --------------------
+
+var glb: int;
+
+procedure recursivetest();
+ modifies glb;
+
+
+
+implementation recursivetest()
+{
+
+ anon0:
+ glb := 5;
+ call glb := recursive(glb);
+ return;
+}
+
+
+
+procedure {:inline 3} recursive(x: int) returns (y: int);
+
+
+
+implementation recursive(x: int) returns (y: int)
+{
+ var k: int;
+
+ anon0:
+ goto anon3_Then, anon3_Else;
+
+ anon3_Then:
+ assume x == 0;
+ y := 1;
+ return;
+
+ anon3_Else:
+ assume x != 0;
+ goto anon2;
+
+ anon2:
+ call k := recursive(x - 1);
+ y := y + k;
+ return;
+}
+
+
+after inlining procedure calls
+procedure recursivetest();
+ modifies glb;
+
+
+implementation recursivetest()
+{
+ var inline$recursive$0$k: int;
+ var inline$recursive$0$x: int;
+ var inline$recursive$0$y: int;
+ var inline$recursive$1$k: int;
+ var inline$recursive$1$x: int;
+ var inline$recursive$1$y: int;
+ var inline$recursive$2$k: int;
+ var inline$recursive$2$x: int;
+ var inline$recursive$2$y: int;
+
+ anon0:
+ glb := 5;
+ goto inline$recursive$0$Entry;
+
+ inline$recursive$0$Entry:
+ inline$recursive$0$x := glb;
+ goto inline$recursive$0$anon0;
+
+ inline$recursive$0$anon0:
+ goto inline$recursive$0$anon3_Then, inline$recursive$0$anon3_Else;
+
+ inline$recursive$0$anon3_Then:
+ assume inline$recursive$0$x == 0;
+ inline$recursive$0$y := 1;
+ goto inline$recursive$0$Return;
+
+ inline$recursive$0$anon3_Else:
+ assume inline$recursive$0$x != 0;
+ goto inline$recursive$0$anon2;
+
+ inline$recursive$0$anon2:
+ goto inline$recursive$1$Entry;
+
+ inline$recursive$1$Entry:
+ inline$recursive$1$x := inline$recursive$0$x - 1;
+ goto inline$recursive$1$anon0;
+
+ inline$recursive$1$anon0:
+ goto inline$recursive$1$anon3_Then, inline$recursive$1$anon3_Else;
+
+ inline$recursive$1$anon3_Then:
+ assume inline$recursive$1$x == 0;
+ inline$recursive$1$y := 1;
+ goto inline$recursive$1$Return;
+
+ inline$recursive$1$anon3_Else:
+ assume inline$recursive$1$x != 0;
+ goto inline$recursive$1$anon2;
+
+ inline$recursive$1$anon2:
+ goto inline$recursive$2$Entry;
+
+ inline$recursive$2$Entry:
+ inline$recursive$2$x := inline$recursive$1$x - 1;
+ goto inline$recursive$2$anon0;
+
+ inline$recursive$2$anon0:
+ goto inline$recursive$2$anon3_Then, inline$recursive$2$anon3_Else;
+
+ inline$recursive$2$anon3_Then:
+ assume inline$recursive$2$x == 0;
+ inline$recursive$2$y := 1;
+ goto inline$recursive$2$Return;
+
+ inline$recursive$2$anon3_Else:
+ assume inline$recursive$2$x != 0;
+ goto inline$recursive$2$anon2;
+
+ inline$recursive$2$anon2:
+ call inline$recursive$2$k := recursive(inline$recursive$2$x - 1);
+ inline$recursive$2$y := inline$recursive$2$y + inline$recursive$2$k;
+ goto inline$recursive$2$Return;
+
+ inline$recursive$2$Return:
+ inline$recursive$1$k := inline$recursive$2$y;
+ goto inline$recursive$1$anon2$1;
+
+ inline$recursive$1$anon2$1:
+ inline$recursive$1$y := inline$recursive$1$y + inline$recursive$1$k;
+ goto inline$recursive$1$Return;
+
+ inline$recursive$1$Return:
+ inline$recursive$0$k := inline$recursive$1$y;
+ goto inline$recursive$0$anon2$1;
+
+ inline$recursive$0$anon2$1:
+ inline$recursive$0$y := inline$recursive$0$y + inline$recursive$0$k;
+ goto inline$recursive$0$Return;
+
+ inline$recursive$0$Return:
+ glb := inline$recursive$0$y;
+ goto anon0$1;
+
+ anon0$1:
+ return;
+}
+
+
+after inlining procedure calls
+procedure {:inline 3} recursive(x: int) returns (y: int);
+
+
+implementation recursive(x: int) returns (y: int)
+{
+ var k: int;
+ var inline$recursive$0$k: int;
+ var inline$recursive$0$x: int;
+ var inline$recursive$0$y: int;
+ var inline$recursive$1$k: int;
+ var inline$recursive$1$x: int;
+ var inline$recursive$1$y: int;
+ var inline$recursive$2$k: int;
+ var inline$recursive$2$x: int;
+ var inline$recursive$2$y: int;
+
+ anon0:
+ goto anon3_Then, anon3_Else;
+
+ anon3_Then:
+ assume x == 0;
+ y := 1;
+ return;
+
+ anon3_Else:
+ assume x != 0;
+ goto anon2;
+
+ anon2:
+ goto inline$recursive$0$Entry;
+
+ inline$recursive$0$Entry:
+ inline$recursive$0$x := x - 1;
+ goto inline$recursive$0$anon0;
+
+ inline$recursive$0$anon0:
+ goto inline$recursive$0$anon3_Then, inline$recursive$0$anon3_Else;
+
+ inline$recursive$0$anon3_Then:
+ assume inline$recursive$0$x == 0;
+ inline$recursive$0$y := 1;
+ goto inline$recursive$0$Return;
+
+ inline$recursive$0$anon3_Else:
+ assume inline$recursive$0$x != 0;
+ goto inline$recursive$0$anon2;
+
+ inline$recursive$0$anon2:
+ goto inline$recursive$1$Entry;
+
+ inline$recursive$1$Entry:
+ inline$recursive$1$x := inline$recursive$0$x - 1;
+ goto inline$recursive$1$anon0;
+
+ inline$recursive$1$anon0:
+ goto inline$recursive$1$anon3_Then, inline$recursive$1$anon3_Else;
+
+ inline$recursive$1$anon3_Then:
+ assume inline$recursive$1$x == 0;
+ inline$recursive$1$y := 1;
+ goto inline$recursive$1$Return;
+
+ inline$recursive$1$anon3_Else:
+ assume inline$recursive$1$x != 0;
+ goto inline$recursive$1$anon2;
+
+ inline$recursive$1$anon2:
+ goto inline$recursive$2$Entry;
+
+ inline$recursive$2$Entry:
+ inline$recursive$2$x := inline$recursive$1$x - 1;
+ goto inline$recursive$2$anon0;
+
+ inline$recursive$2$anon0:
+ goto inline$recursive$2$anon3_Then, inline$recursive$2$anon3_Else;
+
+ inline$recursive$2$anon3_Then:
+ assume inline$recursive$2$x == 0;
+ inline$recursive$2$y := 1;
+ goto inline$recursive$2$Return;
+
+ inline$recursive$2$anon3_Else:
+ assume inline$recursive$2$x != 0;
+ goto inline$recursive$2$anon2;
+
+ inline$recursive$2$anon2:
+ call inline$recursive$2$k := recursive(inline$recursive$2$x - 1);
+ inline$recursive$2$y := inline$recursive$2$y + inline$recursive$2$k;
+ goto inline$recursive$2$Return;
+
+ inline$recursive$2$Return:
+ inline$recursive$1$k := inline$recursive$2$y;
+ goto inline$recursive$1$anon2$1;
+
+ inline$recursive$1$anon2$1:
+ inline$recursive$1$y := inline$recursive$1$y + inline$recursive$1$k;
+ goto inline$recursive$1$Return;
+
+ inline$recursive$1$Return:
+ inline$recursive$0$k := inline$recursive$1$y;
+ goto inline$recursive$0$anon2$1;
+
+ inline$recursive$0$anon2$1:
+ inline$recursive$0$y := inline$recursive$0$y + inline$recursive$0$k;
+ goto inline$recursive$0$Return;
+
+ inline$recursive$0$Return:
+ k := inline$recursive$0$y;
+ goto anon2$1;
+
+ anon2$1:
+ y := y + k;
+ return;
+}
+
+
+
+Boogie program verifier finished with 2 verified, 0 errors
+-------------------- test4.bpl --------------------
+
+procedure main(x: int);
+
+
+
+implementation main(x: int)
+{
+ var A: [int]int;
+ var i: int;
+ var b: bool;
+ var size: int;
+
+ anon0:
+ call i, b := find(A, size, x);
+ goto anon3_Then, anon3_Else;
+
+ anon3_Then:
+ assume b;
+ assert i > 0 && A[i] == x;
+ goto anon2;
+
+ anon3_Else:
+ assume !b;
+ goto anon2;
+
+ anon2:
+ return;
+}
+
+
+
+procedure {:inline 1} find(A: [int]int, size: int, x: int) returns (ret: int, found: bool);
+
+
+
+implementation find(A: [int]int, size: int, x: int) returns (ret: int, found: bool)
+{
+ var i: int;
+ var b: bool;
+
+ anon0:
+ ret := 0 - 1;
+ b := false;
+ found := b;
+ i := 0;
+ goto anon4_LoopHead;
+
+ anon4_LoopHead:
+ goto anon4_LoopDone, anon4_LoopBody;
+
+ anon4_LoopBody:
+ assume i < size;
+ call b := check(A, i, x);
+ goto anon5_Then, anon5_Else;
+
+ anon5_Then:
+ assume b;
+ ret := i;
+ found := b;
+ goto anon3;
+
+ anon5_Else:
+ assume !b;
+ goto anon4_LoopHead;
+
+ anon4_LoopDone:
+ assume i >= size;
+ goto anon3;
+
+ anon3:
+ return;
+}
+
+
+
+procedure {:inline 3} check(A: [int]int, i: int, c: int) returns (ret: bool);
+ requires i >= 0;
+ ensures old(A[i]) > c ==> ret == true;
+
+
+
+implementation check(A: [int]int, i: int, c: int) returns (ret: bool)
+{
+
+ anon0:
+ goto anon4_Then, anon4_Else;
+
+ anon4_Then:
+ assume A[i] == c;
+ ret := true;
+ goto anon3;
+
+ anon4_Else:
+ assume A[i] != c;
+ ret := false;
+ goto anon3;
+
+ anon3:
+ return;
+}
+
+
+after inlining procedure calls
+procedure main(x: int);
+
+
+implementation main(x: int)
+{
+ var A: [int]int;
+ var i: int;
+ var b: bool;
+ var size: int;
+ var inline$find$0$i: int;
+ var inline$find$0$b: bool;
+ var inline$find$0$A: [int]int;
+ var inline$find$0$size: int;
+ var inline$find$0$x: int;
+ var inline$find$0$ret: int;
+ var inline$find$0$found: bool;
+ var inline$check$0$A: [int]int;
+ var inline$check$0$i: int;
+ var inline$check$0$c: int;
+ var inline$check$0$ret: bool;
+
+ anon0:
+ goto inline$find$0$Entry;
+
+ inline$find$0$Entry:
+ inline$find$0$A := A;
+ inline$find$0$size := size;
+ inline$find$0$x := x;
+ goto inline$find$0$anon0;
+
+ inline$find$0$anon0:
+ inline$find$0$ret := 0 - 1;
+ inline$find$0$b := false;
+ inline$find$0$found := inline$find$0$b;
+ inline$find$0$i := 0;
+ goto inline$find$0$anon4_LoopHead;
+
+ inline$find$0$anon4_LoopHead:
+ goto inline$find$0$anon4_LoopDone, inline$find$0$anon4_LoopBody;
+
+ inline$find$0$anon4_LoopBody:
+ assume inline$find$0$i < inline$find$0$size;
+ goto inline$check$0$Entry;
+
+ inline$check$0$Entry:
+ inline$check$0$A := inline$find$0$A;
+ inline$check$0$i := inline$find$0$i;
+ inline$check$0$c := inline$find$0$x;
+ assert inline$check$0$i >= 0;
+ goto inline$check$0$anon0;
+
+ inline$check$0$anon0:
+ goto inline$check$0$anon4_Then, inline$check$0$anon4_Else;
+
+ inline$check$0$anon4_Then:
+ assume inline$check$0$A[inline$check$0$i] == inline$check$0$c;
+ inline$check$0$ret := true;
+ goto inline$check$0$anon3;
+
+ inline$check$0$anon4_Else:
+ assume inline$check$0$A[inline$check$0$i] != inline$check$0$c;
+ inline$check$0$ret := false;
+ goto inline$check$0$anon3;
+
+ inline$check$0$anon3:
+ goto inline$check$0$Return;
+
+ inline$check$0$Return:
+ assert inline$check$0$A[inline$check$0$i] > inline$check$0$c ==> (inline$check$0$ret <==> true);
+ inline$find$0$b := inline$check$0$ret;
+ goto inline$find$0$anon4_LoopBody$1;
+
+ inline$find$0$anon4_LoopBody$1:
+ goto inline$find$0$anon5_Then, inline$find$0$anon5_Else;
+
+ inline$find$0$anon5_Then:
+ assume inline$find$0$b;
+ inline$find$0$ret := inline$find$0$i;
+ inline$find$0$found := inline$find$0$b;
+ goto inline$find$0$anon3;
+
+ inline$find$0$anon5_Else:
+ assume !inline$find$0$b;
+ goto inline$find$0$anon4_LoopHead;
+
+ inline$find$0$anon4_LoopDone:
+ assume inline$find$0$i >= inline$find$0$size;
+ goto inline$find$0$anon3;
+
+ inline$find$0$anon3:
+ goto inline$find$0$Return;
+
+ inline$find$0$Return:
+ i := inline$find$0$ret;
+ b := inline$find$0$found;
+ goto anon0$1;
+
+ anon0$1:
+ goto anon3_Then, anon3_Else;
+
+ anon3_Then:
+ assume b;
+ assert i > 0 && A[i] == x;
+ goto anon2;
+
+ anon3_Else:
+ assume !b;
+ goto anon2;
+
+ anon2:
+ return;
+}
+
+
+after inlining procedure calls
+procedure {:inline 1} find(A: [int]int, size: int, x: int) returns (ret: int, found: bool);
+
+
+implementation find(A: [int]int, size: int, x: int) returns (ret: int, found: bool)
+{
+ var i: int;
+ var b: bool;
+ var inline$check$0$A: [int]int;
+ var inline$check$0$i: int;
+ var inline$check$0$c: int;
+ var inline$check$0$ret: bool;
+
+ anon0:
+ ret := 0 - 1;
+ b := false;
+ found := b;
+ i := 0;
+ goto anon4_LoopHead;
+
+ anon4_LoopHead:
+ goto anon4_LoopDone, anon4_LoopBody;
+
+ anon4_LoopBody:
+ assume i < size;
+ goto inline$check$0$Entry;
+
+ inline$check$0$Entry:
+ inline$check$0$A := A;
+ inline$check$0$i := i;
+ inline$check$0$c := x;
+ assert inline$check$0$i >= 0;
+ goto inline$check$0$anon0;
+
+ inline$check$0$anon0:
+ goto inline$check$0$anon4_Then, inline$check$0$anon4_Else;
+
+ inline$check$0$anon4_Then:
+ assume inline$check$0$A[inline$check$0$i] == inline$check$0$c;
+ inline$check$0$ret := true;
+ goto inline$check$0$anon3;
+
+ inline$check$0$anon4_Else:
+ assume inline$check$0$A[inline$check$0$i] != inline$check$0$c;
+ inline$check$0$ret := false;
+ goto inline$check$0$anon3;
+
+ inline$check$0$anon3:
+ goto inline$check$0$Return;
+
+ inline$check$0$Return:
+ assert inline$check$0$A[inline$check$0$i] > inline$check$0$c ==> (inline$check$0$ret <==> true);
+ b := inline$check$0$ret;
+ goto anon4_LoopBody$1;
+
+ anon4_LoopBody$1:
+ goto anon5_Then, anon5_Else;
+
+ anon5_Then:
+ assume b;
+ ret := i;
+ found := b;
+ goto anon3;
+
+ anon5_Else:
+ assume !b;
+ goto anon4_LoopHead;
+
+ anon4_LoopDone:
+ assume i >= size;
+ goto anon3;
+
+ anon3:
+ return;
+}
+
+
+<console>(68,4): Error BP5003: A postcondition might not hold at this return statement.
+<console>(78,2): Related location: This is the postcondition that might not hold.
+Execution trace:
+ <console>(19,0): anon0
+ <console>(22,0): inline$find$0$Entry
+ <console>(28,0): inline$find$0$anon0
+ <console>(38,0): inline$find$0$anon4_LoopBody
+ <console>(42,0): inline$check$0$Entry
+ <console>(57,0): inline$check$0$anon4_Else
+ <console>(62,0): inline$check$0$anon3
+ <console>(65,0): inline$check$0$Return
+<console>(100,4): Error BP5001: This assertion might not hold.
+Execution trace:
+ <console>(19,0): anon0
+ <console>(22,0): inline$find$0$Entry
+ <console>(28,0): inline$find$0$anon0
+ <console>(38,0): inline$find$0$anon4_LoopBody
+ <console>(42,0): inline$check$0$Entry
+ <console>(52,0): inline$check$0$anon4_Then
+ <console>(65,0): inline$check$0$Return
+ <console>(73,0): inline$find$0$anon5_Then
+ <console>(87,0): inline$find$0$anon3
+ <console>(90,0): inline$find$0$Return
+ <console>(95,0): anon0$1
+ <console>(98,0): anon3_Then
+<console>(50,4): Error BP5003: A postcondition might not hold at this return statement.
+<console>(78,2): Related location: This is the postcondition that might not hold.
+Execution trace:
+ <console>(10,0): anon0
+ <console>(20,0): anon4_LoopBody
+ <console>(24,0): inline$check$0$Entry
+ <console>(39,0): inline$check$0$anon4_Else
+ <console>(44,0): inline$check$0$anon3
+ <console>(47,0): inline$check$0$Return
+<console>(99,0): Error BP5003: A postcondition might not hold at this return statement.
+<console>(78,2): Related location: This is the postcondition that might not hold.
+Execution trace:
+ <console>(85,0): anon0
+ <console>(93,0): anon4_Else
+ <console>(98,0): anon3
+
+Boogie program verifier finished with 0 verified, 4 errors
+-------------------- test5.bpl --------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
+-------------------- test6.bpl --------------------
+test6.bpl(1,22): Error: the inlined procedure is recursive, call stack: foo -> foo
+test6.bpl(15,22): Error: the inlined procedure is recursive, call stack: foo2 -> foo3 -> foo1 -> foo2
+test6.bpl(22,22): Error: the inlined procedure is recursive, call stack: foo3 -> foo1 -> foo2 -> foo3
+test6.bpl(8,22): Error: the inlined procedure is recursive, call stack: foo1 -> foo2 -> foo3 -> foo1
+test6.bpl(1,22): Error: the inlined procedure is recursive, call stack: foo -> foo
+test6.bpl(8,22): Error: the inlined procedure is recursive, call stack: foo1 -> foo2 -> foo3 -> foo1
+6 type checking errors detected in test6.bpl
+-------------------- expansion.bpl --------------------
+expansion.bpl(29,14): Error: invalid type for argument 0 in application of foo1: bool (expected: int)
+expansion.bpl(13,16): Error: expansion: {:inline ...} expects either true or false as the argument
+expansion.bpl(14,22): Error: expansion: identifier was not quantified over
+expansion.bpl(15,22): Error: expansion: identifier was not quantified over
+expansion.bpl(16,22): Error: expansion: more variables quantified over, than used in function
+expansion.bpl(18,21): Error: expansion: axiom to be expanded must have form (forall VARS :: f(VARS) == expr(VARS))
+expansion.bpl(19,53): Error: expansion: only identifiers supported as function arguments
+expansion.bpl(33,22): Error: expansion: an identifier was used more than once
+8 type checking errors detected in expansion.bpl
+-------------------- expansion3.bpl --------------------
+*** detected expansion loop on foo3
+*** detected expansion loop on foo3
+*** detected expansion loop on foo3
+*** more than one possible expansion for x1
+expansion3.bpl(18,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ expansion3.bpl(18,3): anon0
+
+Boogie program verifier finished with 1 verified, 1 error
+-------------------- Elevator.bpl --------------------
+Elevator.bpl(17,5): Error BP5005: This loop invariant might not be maintained by the loop.
+Execution trace:
+ Elevator.bpl(15,3): anon0
+ Elevator.bpl(68,23): inline$Initialize$0$Entry
+ Elevator.bpl(71,13): inline$Initialize$0$anon0
+ Elevator.bpl(68,23): inline$Initialize$0$Return
+ Elevator.bpl(15,3): anon0$1
+ Elevator.bpl(16,3): anon10_LoopHead
+ Elevator.bpl(19,5): anon10_LoopBody
+ Elevator.bpl(19,5): anon11_Else
+ Elevator.bpl(19,5): anon12_Else
+ Elevator.bpl(24,7): anon13_Then
+ Elevator.bpl(94,23): inline$MoveDown_Error$0$Entry
+ Elevator.bpl(99,3): inline$MoveDown_Error$0$anon0
+ Elevator.bpl(94,23): inline$MoveDown_Error$0$Return
+ Elevator.bpl(24,7): anon13_Then$1
+
+Boogie program verifier finished with 1 verified, 1 error
+-------------------- expansion2.bpl --------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
+
+---------- EXPANSION2.SX: 0
+
+---------- EXPANSION2.SX: 0
+-------------------- expansion4.bpl --------------------
+
+Boogie program verifier finished with 3 verified, 0 errors
+-------------------- fundef.bpl --------------------
+
+function {:inline true} foo(x: int) returns (bool)
+{
+ x > 0
+}
+
+function {:inline false} foo2(x: int) returns (bool);
+
+// autogenerated definition axiom
+axiom (forall x: int :: {:inline false} { foo2(x):bool } foo2(x):bool == (x > 0));
+
+function foo3(x: int) returns (bool);
+
+// autogenerated definition axiom
+axiom (forall x: int :: { foo3(x):bool } foo3(x):bool == (x > 0));
+
+Boogie program verifier finished with 0 verified, 0 errors
+fundef2.bpl(6,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ fundef2.bpl(5,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+-------------------- polyInline.bpl --------------------
+polyInline.bpl(27,9): Warning: type parameter alpha is ambiguous, instantiating to int
+polyInline.bpl(31,9): Warning: type parameter alpha is ambiguous, instantiating to int
+polyInline.bpl(35,9): Warning: type parameter alpha is ambiguous, instantiating to int
+polyInline.bpl(23,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ polyInline.bpl(20,3): anon0
+polyInline.bpl(39,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ polyInline.bpl(27,3): anon0
+
+Boogie program verifier finished with 0 verified, 2 errors
+polyInline.bpl(27,9): Warning: type parameter alpha is ambiguous, instantiating to int
+polyInline.bpl(31,9): Warning: type parameter alpha is ambiguous, instantiating to int
+polyInline.bpl(35,9): Warning: type parameter alpha is ambiguous, instantiating to int
+polyInline.bpl(23,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ polyInline.bpl(20,3): anon0
+polyInline.bpl(39,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ polyInline.bpl(27,3): anon0
+
+Boogie program verifier finished with 0 verified, 2 errors
diff --git a/Test/inline/Elevator.asml b/Test/inline/Elevator.asml
new file mode 100644
index 00000000..02a58d10
--- /dev/null
+++ b/Test/inline/Elevator.asml
@@ -0,0 +1,56 @@
+var floors as Set of Integer
+var DoorsOpen as Set of Integer = {}
+var liftDoorOpen as Boolean = false
+var liftLevel as Integer = 1
+var moving as Boolean = false
+var headingTo as Integer = 0
+
+[Action]
+ButtonPress(i as Integer)
+ require i in floors
+ headingTo := i
+
+[Action]
+MoveUp()
+ require liftDoorOpen = false and liftLevel < headingTo
+ require not (liftLevel in DoorsOpen)
+ moving := true
+ liftLevel:= liftLevel + 1
+
+[Action]
+MoveDown()
+ //bug, should require that liftDoorOpen = false
+ require liftLevel > headingTo and headingTo > 0
+ require not (liftLevel in DoorsOpen)
+ moving := true
+ liftLevel := liftLevel - 1
+
+[Action]
+Stop()
+ require liftLevel = headingTo
+ moving := false
+
+[Action]
+OpenLiftDoor()
+ require moving = false
+ liftDoorOpen := true
+
+[Action]
+CloseLiftDoor()
+ liftDoorOpen := false
+
+[Action]
+OpenFloorDoor(i as Integer)
+ require liftLevel = i
+ DoorsOpen := DoorsOpen union {i}
+
+[Action]
+CloseFloorDoor(i as Integer)
+ DoorsOpen := DoorsOpen - {i}
+
+
+Invariant ()
+ require not (liftDoorOpen = true and moving = true)
+
+
+ \ No newline at end of file
diff --git a/Test/inline/Elevator.bpl b/Test/inline/Elevator.bpl
new file mode 100644
index 00000000..4ee1e997
--- /dev/null
+++ b/Test/inline/Elevator.bpl
@@ -0,0 +1,153 @@
+// A Boogie version of Elevator.asml (see Boogie/Test/inline/Elevator.asml)
+
+var floors: [int]bool; // set of integer
+var DoorsOpen: [int]bool;
+var liftDoorOpen: bool;
+var liftLevel: int;
+var moving: bool;
+var headingTo: int;
+
+procedure Main_Error()
+ modifies floors, DoorsOpen, liftDoorOpen, liftLevel, moving, headingTo;
+{
+ var i: int;
+
+ call Initialize();
+ while (true)
+ invariant !(liftDoorOpen && moving);
+ {
+ if (*) {
+ havoc i; call ButtonPress(i);
+ } else if (*) {
+ call MoveUp();
+ } else if (*) {
+ call MoveDown_Error();
+ } else if (*) {
+ call Stop();
+ } else if (*) {
+ call OpenLiftDoor();
+ } else if (*) {
+ call CloseLiftDoor();
+ } else if (*) {
+ havoc i; call OpenFloorDoor(i);
+ } else {
+ havoc i; call CloseFloorDoor(i);
+ }
+ }
+}
+
+procedure Main_Correct()
+ modifies floors, DoorsOpen, liftDoorOpen, liftLevel, moving, headingTo;
+{
+ var i: int;
+
+ call Initialize();
+ while (true)
+ invariant !(liftDoorOpen && moving);
+ {
+ if (*) {
+ havoc i; call ButtonPress(i);
+ } else if (*) {
+ call MoveUp();
+ } else if (*) {
+ call MoveDown_Correct();
+ } else if (*) {
+ call Stop();
+ } else if (*) {
+ call OpenLiftDoor();
+ } else if (*) {
+ call CloseLiftDoor();
+ } else if (*) {
+ havoc i; call OpenFloorDoor(i);
+ } else {
+ havoc i; call CloseFloorDoor(i);
+ }
+ }
+}
+
+procedure {:inline 1} Initialize()
+ modifies floors, DoorsOpen, liftDoorOpen, liftLevel, moving, headingTo;
+{
+ DoorsOpen := EmptySet;
+ liftDoorOpen := false;
+ liftLevel := 1;
+ moving := false;
+ headingTo := 0;
+}
+
+procedure {:inline 1} ButtonPress(i: int)
+ modifies headingTo;
+{
+ assume floors[i];
+ headingTo := i;
+}
+
+procedure {:inline 1} MoveUp()
+ modifies moving, liftLevel;
+{
+ assume !liftDoorOpen && liftLevel < headingTo;
+ assume !DoorsOpen[liftLevel];
+ moving := true;
+ liftLevel:= liftLevel + 1;
+}
+
+procedure {:inline 1} MoveDown_Error()
+ modifies moving, liftLevel;
+{
+ //bug, should require that liftDoorOpen = false
+ // assume !liftDoorOpen;
+ assume liftLevel > headingTo && headingTo > 0;
+ assume !DoorsOpen[liftLevel];
+ moving := true;
+ liftLevel := liftLevel - 1;
+}
+
+procedure {:inline 1} MoveDown_Correct()
+ modifies moving, liftLevel;
+{
+ assume !liftDoorOpen;
+ assume liftLevel > headingTo && headingTo > 0;
+ assume !DoorsOpen[liftLevel];
+ moving := true;
+ liftLevel := liftLevel - 1;
+}
+
+procedure {:inline 1} Stop()
+ modifies moving;
+{
+ assume liftLevel == headingTo;
+ moving := false;
+}
+
+procedure {:inline 1} OpenLiftDoor()
+ modifies liftDoorOpen;
+{
+ assume !moving;
+ liftDoorOpen := true;
+}
+
+procedure {:inline 1} CloseLiftDoor()
+ modifies liftDoorOpen;
+{
+ liftDoorOpen := false;
+}
+
+procedure {:inline 1} OpenFloorDoor(i: int)
+ modifies DoorsOpen;
+{
+ assume liftLevel == i;
+ DoorsOpen[i] := true; // DoorsOpen := DoorsOpen union {i};
+}
+
+procedure {:inline 1} CloseFloorDoor(i: int)
+ modifies DoorsOpen;
+{
+ DoorsOpen[i] := false; // DoorsOpen := DoorsOpen - {i}
+}
+
+// ---------------------------------------------------------------
+
+const EmptySet: [int]bool;
+axiom (forall o: int :: { EmptySet[o] } !EmptySet[o]);
+
+// ---------------------------------------------------------------
diff --git a/Test/inline/Output b/Test/inline/Output
new file mode 100644
index 00000000..39d5a5b4
--- /dev/null
+++ b/Test/inline/Output
@@ -0,0 +1,983 @@
+-------------------- test1.bpl --------------------
+
+procedure Main();
+
+
+
+implementation Main()
+{
+ var x: int;
+ var y: int;
+
+ anon0:
+ x := 1;
+ y := 0;
+ call x := inc(x, 5);
+ call y := incdec(x, 2);
+ assert x - 1 == y;
+ return;
+}
+
+
+
+procedure {:inline 1} incdec(x: int, y: int) returns (z: int);
+ ensures z == x + 1 - y;
+
+
+
+implementation incdec(x: int, y: int) returns (z: int)
+{
+
+ anon0:
+ z := x;
+ z := x + 1;
+ call z := dec(z, y);
+ return;
+}
+
+
+
+procedure {:inline 1} inc(x: int, i: int) returns (y: int);
+ ensures y == x + i;
+
+
+
+implementation inc(x: int, i: int) returns (y: int)
+{
+
+ anon0:
+ y := x;
+ y := x + i;
+ return;
+}
+
+
+
+procedure {:inline 1} dec(x: int, i: int) returns (y: int);
+ ensures y == x - i;
+
+
+
+implementation dec(x: int, i: int) returns (y: int)
+{
+
+ anon0:
+ y := x;
+ y := x - i;
+ return;
+}
+
+
+after inlining procedure calls
+procedure Main();
+
+
+implementation Main()
+{
+ var x: int;
+ var y: int;
+ var inline$inc$0$x: int;
+ var inline$inc$0$i: int;
+ var inline$inc$0$y: int;
+ var inline$incdec$0$x: int;
+ var inline$incdec$0$y: int;
+ var inline$incdec$0$z: int;
+ var inline$dec$0$x: int;
+ var inline$dec$0$i: int;
+ var inline$dec$0$y: int;
+
+ anon0:
+ x := 1;
+ y := 0;
+ goto inline$inc$0$Entry;
+
+ inline$inc$0$Entry:
+ inline$inc$0$x := x;
+ inline$inc$0$i := 5;
+ goto inline$inc$0$anon0;
+
+ inline$inc$0$anon0:
+ inline$inc$0$y := inline$inc$0$x;
+ inline$inc$0$y := inline$inc$0$x + inline$inc$0$i;
+ goto inline$inc$0$Return;
+
+ inline$inc$0$Return:
+ assert inline$inc$0$y == inline$inc$0$x + inline$inc$0$i;
+ x := inline$inc$0$y;
+ goto anon0$1;
+
+ anon0$1:
+ goto inline$incdec$0$Entry;
+
+ inline$incdec$0$Entry:
+ inline$incdec$0$x := x;
+ inline$incdec$0$y := 2;
+ goto inline$incdec$0$anon0;
+
+ inline$incdec$0$anon0:
+ inline$incdec$0$z := inline$incdec$0$x;
+ inline$incdec$0$z := inline$incdec$0$x + 1;
+ goto inline$dec$0$Entry;
+
+ inline$dec$0$Entry:
+ inline$dec$0$x := inline$incdec$0$z;
+ inline$dec$0$i := inline$incdec$0$y;
+ goto inline$dec$0$anon0;
+
+ inline$dec$0$anon0:
+ inline$dec$0$y := inline$dec$0$x;
+ inline$dec$0$y := inline$dec$0$x - inline$dec$0$i;
+ goto inline$dec$0$Return;
+
+ inline$dec$0$Return:
+ assert inline$dec$0$y == inline$dec$0$x - inline$dec$0$i;
+ inline$incdec$0$z := inline$dec$0$y;
+ goto inline$incdec$0$anon0$1;
+
+ inline$incdec$0$anon0$1:
+ goto inline$incdec$0$Return;
+
+ inline$incdec$0$Return:
+ assert inline$incdec$0$z == inline$incdec$0$x + 1 - inline$incdec$0$y;
+ y := inline$incdec$0$z;
+ goto anon0$2;
+
+ anon0$2:
+ assert x - 1 == y;
+ return;
+}
+
+
+after inlining procedure calls
+procedure {:inline 1} incdec(x: int, y: int) returns (z: int);
+ ensures z == x + 1 - y;
+
+
+implementation incdec(x: int, y: int) returns (z: int)
+{
+ var inline$dec$0$x: int;
+ var inline$dec$0$i: int;
+ var inline$dec$0$y: int;
+
+ anon0:
+ z := x;
+ z := x + 1;
+ goto inline$dec$0$Entry;
+
+ inline$dec$0$Entry:
+ inline$dec$0$x := z;
+ inline$dec$0$i := y;
+ goto inline$dec$0$anon0;
+
+ inline$dec$0$anon0:
+ inline$dec$0$y := inline$dec$0$x;
+ inline$dec$0$y := inline$dec$0$x - inline$dec$0$i;
+ goto inline$dec$0$Return;
+
+ inline$dec$0$Return:
+ assert inline$dec$0$y == inline$dec$0$x - inline$dec$0$i;
+ z := inline$dec$0$y;
+ goto anon0$1;
+
+ anon0$1:
+ return;
+}
+
+
+
+Boogie program verifier finished with 4 verified, 0 errors
+-------------------- test2.bpl --------------------
+
+var glb: int;
+
+procedure calculate();
+ modifies glb;
+
+
+
+implementation calculate()
+{
+ var x: int;
+ var y: int;
+
+ anon0:
+ y := 5;
+ call x := increase(y);
+ return;
+}
+
+
+
+procedure {:inline 1} increase(i: int) returns (k: int);
+ modifies glb;
+
+
+
+implementation increase(i: int) returns (k: int)
+{
+ var j: int;
+
+ anon0:
+ j := i;
+ j := j + 1;
+ glb := glb + j;
+ k := j;
+ return;
+}
+
+
+after inlining procedure calls
+procedure calculate();
+ modifies glb;
+
+
+implementation calculate()
+{
+ var x: int;
+ var y: int;
+ var inline$increase$0$j: int;
+ var inline$increase$0$i: int;
+ var inline$increase$0$k: int;
+ var inline$increase$0$glb: int;
+
+ anon0:
+ y := 5;
+ goto inline$increase$0$Entry;
+
+ inline$increase$0$Entry:
+ inline$increase$0$i := y;
+ inline$increase$0$glb := glb;
+ goto inline$increase$0$anon0;
+
+ inline$increase$0$anon0:
+ inline$increase$0$j := inline$increase$0$i;
+ inline$increase$0$j := inline$increase$0$j + 1;
+ glb := glb + inline$increase$0$j;
+ inline$increase$0$k := inline$increase$0$j;
+ goto inline$increase$0$Return;
+
+ inline$increase$0$Return:
+ x := inline$increase$0$k;
+ goto anon0$1;
+
+ anon0$1:
+ return;
+}
+
+
+
+Boogie program verifier finished with 2 verified, 0 errors
+-------------------- test3.bpl --------------------
+
+var glb: int;
+
+procedure recursivetest();
+ modifies glb;
+
+
+
+implementation recursivetest()
+{
+
+ anon0:
+ glb := 5;
+ call glb := recursive(glb);
+ return;
+}
+
+
+
+procedure {:inline 3} recursive(x: int) returns (y: int);
+
+
+
+implementation recursive(x: int) returns (y: int)
+{
+ var k: int;
+
+ anon0:
+ goto anon3_Then, anon3_Else;
+
+ anon3_Then:
+ assume x == 0;
+ y := 1;
+ return;
+
+ anon3_Else:
+ assume x != 0;
+ goto anon2;
+
+ anon2:
+ call k := recursive(x - 1);
+ y := y + k;
+ return;
+}
+
+
+after inlining procedure calls
+procedure recursivetest();
+ modifies glb;
+
+
+implementation recursivetest()
+{
+ var inline$recursive$0$k: int;
+ var inline$recursive$0$x: int;
+ var inline$recursive$0$y: int;
+ var inline$recursive$1$k: int;
+ var inline$recursive$1$x: int;
+ var inline$recursive$1$y: int;
+ var inline$recursive$2$k: int;
+ var inline$recursive$2$x: int;
+ var inline$recursive$2$y: int;
+
+ anon0:
+ glb := 5;
+ goto inline$recursive$0$Entry;
+
+ inline$recursive$0$Entry:
+ inline$recursive$0$x := glb;
+ goto inline$recursive$0$anon0;
+
+ inline$recursive$0$anon0:
+ goto inline$recursive$0$anon3_Then, inline$recursive$0$anon3_Else;
+
+ inline$recursive$0$anon3_Then:
+ assume inline$recursive$0$x == 0;
+ inline$recursive$0$y := 1;
+ goto inline$recursive$0$Return;
+
+ inline$recursive$0$anon3_Else:
+ assume inline$recursive$0$x != 0;
+ goto inline$recursive$0$anon2;
+
+ inline$recursive$0$anon2:
+ goto inline$recursive$1$Entry;
+
+ inline$recursive$1$Entry:
+ inline$recursive$1$x := inline$recursive$0$x - 1;
+ goto inline$recursive$1$anon0;
+
+ inline$recursive$1$anon0:
+ goto inline$recursive$1$anon3_Then, inline$recursive$1$anon3_Else;
+
+ inline$recursive$1$anon3_Then:
+ assume inline$recursive$1$x == 0;
+ inline$recursive$1$y := 1;
+ goto inline$recursive$1$Return;
+
+ inline$recursive$1$anon3_Else:
+ assume inline$recursive$1$x != 0;
+ goto inline$recursive$1$anon2;
+
+ inline$recursive$1$anon2:
+ goto inline$recursive$2$Entry;
+
+ inline$recursive$2$Entry:
+ inline$recursive$2$x := inline$recursive$1$x - 1;
+ goto inline$recursive$2$anon0;
+
+ inline$recursive$2$anon0:
+ goto inline$recursive$2$anon3_Then, inline$recursive$2$anon3_Else;
+
+ inline$recursive$2$anon3_Then:
+ assume inline$recursive$2$x == 0;
+ inline$recursive$2$y := 1;
+ goto inline$recursive$2$Return;
+
+ inline$recursive$2$anon3_Else:
+ assume inline$recursive$2$x != 0;
+ goto inline$recursive$2$anon2;
+
+ inline$recursive$2$anon2:
+ call inline$recursive$2$k := recursive(inline$recursive$2$x - 1);
+ inline$recursive$2$y := inline$recursive$2$y + inline$recursive$2$k;
+ goto inline$recursive$2$Return;
+
+ inline$recursive$2$Return:
+ inline$recursive$1$k := inline$recursive$2$y;
+ goto inline$recursive$1$anon2$1;
+
+ inline$recursive$1$anon2$1:
+ inline$recursive$1$y := inline$recursive$1$y + inline$recursive$1$k;
+ goto inline$recursive$1$Return;
+
+ inline$recursive$1$Return:
+ inline$recursive$0$k := inline$recursive$1$y;
+ goto inline$recursive$0$anon2$1;
+
+ inline$recursive$0$anon2$1:
+ inline$recursive$0$y := inline$recursive$0$y + inline$recursive$0$k;
+ goto inline$recursive$0$Return;
+
+ inline$recursive$0$Return:
+ glb := inline$recursive$0$y;
+ goto anon0$1;
+
+ anon0$1:
+ return;
+}
+
+
+after inlining procedure calls
+procedure {:inline 3} recursive(x: int) returns (y: int);
+
+
+implementation recursive(x: int) returns (y: int)
+{
+ var k: int;
+ var inline$recursive$0$k: int;
+ var inline$recursive$0$x: int;
+ var inline$recursive$0$y: int;
+ var inline$recursive$1$k: int;
+ var inline$recursive$1$x: int;
+ var inline$recursive$1$y: int;
+ var inline$recursive$2$k: int;
+ var inline$recursive$2$x: int;
+ var inline$recursive$2$y: int;
+
+ anon0:
+ goto anon3_Then, anon3_Else;
+
+ anon3_Then:
+ assume x == 0;
+ y := 1;
+ return;
+
+ anon3_Else:
+ assume x != 0;
+ goto anon2;
+
+ anon2:
+ goto inline$recursive$0$Entry;
+
+ inline$recursive$0$Entry:
+ inline$recursive$0$x := x - 1;
+ goto inline$recursive$0$anon0;
+
+ inline$recursive$0$anon0:
+ goto inline$recursive$0$anon3_Then, inline$recursive$0$anon3_Else;
+
+ inline$recursive$0$anon3_Then:
+ assume inline$recursive$0$x == 0;
+ inline$recursive$0$y := 1;
+ goto inline$recursive$0$Return;
+
+ inline$recursive$0$anon3_Else:
+ assume inline$recursive$0$x != 0;
+ goto inline$recursive$0$anon2;
+
+ inline$recursive$0$anon2:
+ goto inline$recursive$1$Entry;
+
+ inline$recursive$1$Entry:
+ inline$recursive$1$x := inline$recursive$0$x - 1;
+ goto inline$recursive$1$anon0;
+
+ inline$recursive$1$anon0:
+ goto inline$recursive$1$anon3_Then, inline$recursive$1$anon3_Else;
+
+ inline$recursive$1$anon3_Then:
+ assume inline$recursive$1$x == 0;
+ inline$recursive$1$y := 1;
+ goto inline$recursive$1$Return;
+
+ inline$recursive$1$anon3_Else:
+ assume inline$recursive$1$x != 0;
+ goto inline$recursive$1$anon2;
+
+ inline$recursive$1$anon2:
+ goto inline$recursive$2$Entry;
+
+ inline$recursive$2$Entry:
+ inline$recursive$2$x := inline$recursive$1$x - 1;
+ goto inline$recursive$2$anon0;
+
+ inline$recursive$2$anon0:
+ goto inline$recursive$2$anon3_Then, inline$recursive$2$anon3_Else;
+
+ inline$recursive$2$anon3_Then:
+ assume inline$recursive$2$x == 0;
+ inline$recursive$2$y := 1;
+ goto inline$recursive$2$Return;
+
+ inline$recursive$2$anon3_Else:
+ assume inline$recursive$2$x != 0;
+ goto inline$recursive$2$anon2;
+
+ inline$recursive$2$anon2:
+ call inline$recursive$2$k := recursive(inline$recursive$2$x - 1);
+ inline$recursive$2$y := inline$recursive$2$y + inline$recursive$2$k;
+ goto inline$recursive$2$Return;
+
+ inline$recursive$2$Return:
+ inline$recursive$1$k := inline$recursive$2$y;
+ goto inline$recursive$1$anon2$1;
+
+ inline$recursive$1$anon2$1:
+ inline$recursive$1$y := inline$recursive$1$y + inline$recursive$1$k;
+ goto inline$recursive$1$Return;
+
+ inline$recursive$1$Return:
+ inline$recursive$0$k := inline$recursive$1$y;
+ goto inline$recursive$0$anon2$1;
+
+ inline$recursive$0$anon2$1:
+ inline$recursive$0$y := inline$recursive$0$y + inline$recursive$0$k;
+ goto inline$recursive$0$Return;
+
+ inline$recursive$0$Return:
+ k := inline$recursive$0$y;
+ goto anon2$1;
+
+ anon2$1:
+ y := y + k;
+ return;
+}
+
+
+
+Boogie program verifier finished with 2 verified, 0 errors
+-------------------- test4.bpl --------------------
+
+procedure main(x: int);
+
+
+
+implementation main(x: int)
+{
+ var A: [int]int;
+ var i: int;
+ var b: bool;
+ var size: int;
+
+ anon0:
+ call i, b := find(A, size, x);
+ goto anon3_Then, anon3_Else;
+
+ anon3_Then:
+ assume b;
+ assert i > 0 && A[i] == x;
+ goto anon2;
+
+ anon3_Else:
+ assume !b;
+ goto anon2;
+
+ anon2:
+ return;
+}
+
+
+
+procedure {:inline 1} find(A: [int]int, size: int, x: int) returns (ret: int, found: bool);
+
+
+
+implementation find(A: [int]int, size: int, x: int) returns (ret: int, found: bool)
+{
+ var i: int;
+ var b: bool;
+
+ anon0:
+ ret := 0 - 1;
+ b := false;
+ found := b;
+ i := 0;
+ goto anon4_LoopHead;
+
+ anon4_LoopHead:
+ goto anon4_LoopDone, anon4_LoopBody;
+
+ anon4_LoopBody:
+ assume i < size;
+ call b := check(A, i, x);
+ goto anon5_Then, anon5_Else;
+
+ anon5_Then:
+ assume b;
+ ret := i;
+ found := b;
+ goto anon3;
+
+ anon5_Else:
+ assume !b;
+ goto anon4_LoopHead;
+
+ anon4_LoopDone:
+ assume i >= size;
+ goto anon3;
+
+ anon3:
+ return;
+}
+
+
+
+procedure {:inline 3} check(A: [int]int, i: int, c: int) returns (ret: bool);
+ requires i >= 0;
+ ensures old(A[i]) > c ==> ret == true;
+
+
+
+implementation check(A: [int]int, i: int, c: int) returns (ret: bool)
+{
+
+ anon0:
+ goto anon4_Then, anon4_Else;
+
+ anon4_Then:
+ assume A[i] == c;
+ ret := true;
+ goto anon3;
+
+ anon4_Else:
+ assume A[i] != c;
+ ret := false;
+ goto anon3;
+
+ anon3:
+ return;
+}
+
+
+after inlining procedure calls
+procedure main(x: int);
+
+
+implementation main(x: int)
+{
+ var A: [int]int;
+ var i: int;
+ var b: bool;
+ var size: int;
+ var inline$find$0$i: int;
+ var inline$find$0$b: bool;
+ var inline$find$0$A: [int]int;
+ var inline$find$0$size: int;
+ var inline$find$0$x: int;
+ var inline$find$0$ret: int;
+ var inline$find$0$found: bool;
+ var inline$check$0$A: [int]int;
+ var inline$check$0$i: int;
+ var inline$check$0$c: int;
+ var inline$check$0$ret: bool;
+
+ anon0:
+ goto inline$find$0$Entry;
+
+ inline$find$0$Entry:
+ inline$find$0$A := A;
+ inline$find$0$size := size;
+ inline$find$0$x := x;
+ goto inline$find$0$anon0;
+
+ inline$find$0$anon0:
+ inline$find$0$ret := 0 - 1;
+ inline$find$0$b := false;
+ inline$find$0$found := inline$find$0$b;
+ inline$find$0$i := 0;
+ goto inline$find$0$anon4_LoopHead;
+
+ inline$find$0$anon4_LoopHead:
+ goto inline$find$0$anon4_LoopDone, inline$find$0$anon4_LoopBody;
+
+ inline$find$0$anon4_LoopBody:
+ assume inline$find$0$i < inline$find$0$size;
+ goto inline$check$0$Entry;
+
+ inline$check$0$Entry:
+ inline$check$0$A := inline$find$0$A;
+ inline$check$0$i := inline$find$0$i;
+ inline$check$0$c := inline$find$0$x;
+ assert inline$check$0$i >= 0;
+ goto inline$check$0$anon0;
+
+ inline$check$0$anon0:
+ goto inline$check$0$anon4_Then, inline$check$0$anon4_Else;
+
+ inline$check$0$anon4_Then:
+ assume inline$check$0$A[inline$check$0$i] == inline$check$0$c;
+ inline$check$0$ret := true;
+ goto inline$check$0$anon3;
+
+ inline$check$0$anon4_Else:
+ assume inline$check$0$A[inline$check$0$i] != inline$check$0$c;
+ inline$check$0$ret := false;
+ goto inline$check$0$anon3;
+
+ inline$check$0$anon3:
+ goto inline$check$0$Return;
+
+ inline$check$0$Return:
+ assert inline$check$0$A[inline$check$0$i] > inline$check$0$c ==> (inline$check$0$ret <==> true);
+ inline$find$0$b := inline$check$0$ret;
+ goto inline$find$0$anon4_LoopBody$1;
+
+ inline$find$0$anon4_LoopBody$1:
+ goto inline$find$0$anon5_Then, inline$find$0$anon5_Else;
+
+ inline$find$0$anon5_Then:
+ assume inline$find$0$b;
+ inline$find$0$ret := inline$find$0$i;
+ inline$find$0$found := inline$find$0$b;
+ goto inline$find$0$anon3;
+
+ inline$find$0$anon5_Else:
+ assume !inline$find$0$b;
+ goto inline$find$0$anon4_LoopHead;
+
+ inline$find$0$anon4_LoopDone:
+ assume inline$find$0$i >= inline$find$0$size;
+ goto inline$find$0$anon3;
+
+ inline$find$0$anon3:
+ goto inline$find$0$Return;
+
+ inline$find$0$Return:
+ i := inline$find$0$ret;
+ b := inline$find$0$found;
+ goto anon0$1;
+
+ anon0$1:
+ goto anon3_Then, anon3_Else;
+
+ anon3_Then:
+ assume b;
+ assert i > 0 && A[i] == x;
+ goto anon2;
+
+ anon3_Else:
+ assume !b;
+ goto anon2;
+
+ anon2:
+ return;
+}
+
+
+after inlining procedure calls
+procedure {:inline 1} find(A: [int]int, size: int, x: int) returns (ret: int, found: bool);
+
+
+implementation find(A: [int]int, size: int, x: int) returns (ret: int, found: bool)
+{
+ var i: int;
+ var b: bool;
+ var inline$check$0$A: [int]int;
+ var inline$check$0$i: int;
+ var inline$check$0$c: int;
+ var inline$check$0$ret: bool;
+
+ anon0:
+ ret := 0 - 1;
+ b := false;
+ found := b;
+ i := 0;
+ goto anon4_LoopHead;
+
+ anon4_LoopHead:
+ goto anon4_LoopDone, anon4_LoopBody;
+
+ anon4_LoopBody:
+ assume i < size;
+ goto inline$check$0$Entry;
+
+ inline$check$0$Entry:
+ inline$check$0$A := A;
+ inline$check$0$i := i;
+ inline$check$0$c := x;
+ assert inline$check$0$i >= 0;
+ goto inline$check$0$anon0;
+
+ inline$check$0$anon0:
+ goto inline$check$0$anon4_Then, inline$check$0$anon4_Else;
+
+ inline$check$0$anon4_Then:
+ assume inline$check$0$A[inline$check$0$i] == inline$check$0$c;
+ inline$check$0$ret := true;
+ goto inline$check$0$anon3;
+
+ inline$check$0$anon4_Else:
+ assume inline$check$0$A[inline$check$0$i] != inline$check$0$c;
+ inline$check$0$ret := false;
+ goto inline$check$0$anon3;
+
+ inline$check$0$anon3:
+ goto inline$check$0$Return;
+
+ inline$check$0$Return:
+ assert inline$check$0$A[inline$check$0$i] > inline$check$0$c ==> (inline$check$0$ret <==> true);
+ b := inline$check$0$ret;
+ goto anon4_LoopBody$1;
+
+ anon4_LoopBody$1:
+ goto anon5_Then, anon5_Else;
+
+ anon5_Then:
+ assume b;
+ ret := i;
+ found := b;
+ goto anon3;
+
+ anon5_Else:
+ assume !b;
+ goto anon4_LoopHead;
+
+ anon4_LoopDone:
+ assume i >= size;
+ goto anon3;
+
+ anon3:
+ return;
+}
+
+
+<console>(68,4): Error BP5003: A postcondition might not hold at this return statement.
+<console>(78,2): Related location: This is the postcondition that might not hold.
+Execution trace:
+ <console>(19,0): anon0
+ <console>(22,0): inline$find$0$Entry
+ <console>(28,0): inline$find$0$anon0
+ <console>(38,0): inline$find$0$anon4_LoopBody
+ <console>(42,0): inline$check$0$Entry
+ <console>(57,0): inline$check$0$anon4_Else
+ <console>(62,0): inline$check$0$anon3
+ <console>(65,0): inline$check$0$Return
+<console>(100,4): Error BP5001: This assertion might not hold.
+Execution trace:
+ <console>(19,0): anon0
+ <console>(22,0): inline$find$0$Entry
+ <console>(28,0): inline$find$0$anon0
+ <console>(38,0): inline$find$0$anon4_LoopBody
+ <console>(42,0): inline$check$0$Entry
+ <console>(52,0): inline$check$0$anon4_Then
+ <console>(65,0): inline$check$0$Return
+ <console>(73,0): inline$find$0$anon5_Then
+ <console>(87,0): inline$find$0$anon3
+ <console>(90,0): inline$find$0$Return
+ <console>(95,0): anon0$1
+ <console>(98,0): anon3_Then
+<console>(50,4): Error BP5003: A postcondition might not hold at this return statement.
+<console>(78,2): Related location: This is the postcondition that might not hold.
+Execution trace:
+ <console>(10,0): anon0
+ <console>(20,0): anon4_LoopBody
+ <console>(24,0): inline$check$0$Entry
+ <console>(39,0): inline$check$0$anon4_Else
+ <console>(44,0): inline$check$0$anon3
+ <console>(47,0): inline$check$0$Return
+<console>(99,0): Error BP5003: A postcondition might not hold at this return statement.
+<console>(78,2): Related location: This is the postcondition that might not hold.
+Execution trace:
+ <console>(85,0): anon0
+ <console>(93,0): anon4_Else
+ <console>(98,0): anon3
+
+Boogie program verifier finished with 0 verified, 4 errors
+-------------------- test5.bpl --------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
+-------------------- test6.bpl --------------------
+test6.bpl(1,22): Error: the inlined procedure is recursive, call stack: foo -> foo
+test6.bpl(15,22): Error: the inlined procedure is recursive, call stack: foo2 -> foo3 -> foo1 -> foo2
+test6.bpl(22,22): Error: the inlined procedure is recursive, call stack: foo3 -> foo1 -> foo2 -> foo3
+test6.bpl(8,22): Error: the inlined procedure is recursive, call stack: foo1 -> foo2 -> foo3 -> foo1
+test6.bpl(1,22): Error: the inlined procedure is recursive, call stack: foo -> foo
+test6.bpl(8,22): Error: the inlined procedure is recursive, call stack: foo1 -> foo2 -> foo3 -> foo1
+6 type checking errors detected in test6.bpl
+-------------------- expansion.bpl --------------------
+expansion.bpl(29,14): Error: invalid type for argument 0 in application of foo1: bool (expected: int)
+expansion.bpl(13,16): Error: expansion: {:inline ...} expects either true or false as the argument
+expansion.bpl(14,22): Error: expansion: identifier was not quantified over
+expansion.bpl(15,22): Error: expansion: identifier was not quantified over
+expansion.bpl(16,22): Error: expansion: more variables quantified over, than used in function
+expansion.bpl(18,21): Error: expansion: axiom to be expanded must have form (forall VARS :: f(VARS) == expr(VARS))
+expansion.bpl(19,53): Error: expansion: only identifiers supported as function arguments
+expansion.bpl(33,22): Error: expansion: an identifier was used more than once
+8 type checking errors detected in expansion.bpl
+-------------------- expansion3.bpl --------------------
+*** detected expansion loop on foo3
+*** detected expansion loop on foo3
+*** detected expansion loop on foo3
+*** more than one possible expansion for x1
+expansion3.bpl(18,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ expansion3.bpl(18,3): anon0
+
+Boogie program verifier finished with 1 verified, 1 error
+-------------------- Elevator.bpl --------------------
+Elevator.bpl(17,5): Error BP5005: This loop invariant might not be maintained by the loop.
+Execution trace:
+ Elevator.bpl(15,3): anon0
+ Elevator.bpl(68,23): inline$Initialize$0$Entry
+ Elevator.bpl(71,13): inline$Initialize$0$anon0
+ Elevator.bpl(68,23): inline$Initialize$0$Return
+ Elevator.bpl(15,3): anon0$1
+ Elevator.bpl(16,3): anon10_LoopHead
+ Elevator.bpl(19,5): anon10_LoopBody
+ Elevator.bpl(19,5): anon11_Else
+ Elevator.bpl(19,5): anon12_Else
+ Elevator.bpl(24,7): anon13_Then
+ Elevator.bpl(94,23): inline$MoveDown_Error$0$Entry
+ Elevator.bpl(99,3): inline$MoveDown_Error$0$anon0
+ Elevator.bpl(94,23): inline$MoveDown_Error$0$Return
+ Elevator.bpl(24,7): anon13_Then$1
+
+Boogie program verifier finished with 1 verified, 1 error
+-------------------- expansion2.bpl --------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
+
+---------- EXPANSION2.SX: 0
+
+---------- EXPANSION2.SX: 0
+-------------------- expansion4.bpl --------------------
+
+Boogie program verifier finished with 3 verified, 0 errors
+-------------------- fundef.bpl --------------------
+
+function {:inline true} foo(x: int) returns (bool)
+{
+ x > 0
+}
+
+function {:inline false} foo2(x: int) returns (bool);
+
+// autogenerated definition axiom
+axiom (forall x: int :: {:inline false} { foo2(x):bool } foo2(x):bool == (x > 0));
+
+function foo3(x: int) returns (bool);
+
+// autogenerated definition axiom
+axiom (forall x: int :: { foo3(x):bool } foo3(x):bool == (x > 0));
+
+Boogie program verifier finished with 0 verified, 0 errors
+fundef2.bpl(6,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ fundef2.bpl(5,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+-------------------- polyInline.bpl --------------------
+polyInline.bpl(27,9): Warning: type parameter alpha is ambiguous, instantiating to int
+polyInline.bpl(31,9): Warning: type parameter alpha is ambiguous, instantiating to int
+polyInline.bpl(35,9): Warning: type parameter alpha is ambiguous, instantiating to int
+polyInline.bpl(23,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ polyInline.bpl(20,3): anon0
+polyInline.bpl(39,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ polyInline.bpl(27,3): anon0
+
+Boogie program verifier finished with 0 verified, 2 errors
+polyInline.bpl(27,9): Warning: type parameter alpha is ambiguous, instantiating to int
+polyInline.bpl(31,9): Warning: type parameter alpha is ambiguous, instantiating to int
+polyInline.bpl(35,9): Warning: type parameter alpha is ambiguous, instantiating to int
+polyInline.bpl(23,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ polyInline.bpl(20,3): anon0
+polyInline.bpl(39,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ polyInline.bpl(27,3): anon0
+
+Boogie program verifier finished with 0 verified, 2 errors
diff --git a/Test/inline/expansion.bpl b/Test/inline/expansion.bpl
new file mode 100644
index 00000000..41acfb44
--- /dev/null
+++ b/Test/inline/expansion.bpl
@@ -0,0 +1,33 @@
+const q : int;
+const p : bool;
+function foo(x:int, y:bool) returns(bool);
+function foo1(x:int, y:bool) returns(bool);
+function foo2(x:int, y:bool) returns(bool);
+function foo3(x:int, y:bool) returns(bool);
+// OK
+axiom {:inline false} (forall x:int, y:bool :: foo(x,p) <==> x > 10 && y);
+axiom {:inline true} (forall x:int, y:bool :: foo1(x,y) == (x > 10 && y));
+axiom {:inline true} (forall x:int, y:bool :: foo2(x,y) == (q > 10 && y));
+axiom {:inline true} (forall y:bool, x:int :: foo3(x,y) == foo3(x,y));
+// fail
+axiom {:inline 1} (forall x:int, y:bool :: foo(x,y) <==> x > 10 && y);
+axiom {:inline true} (forall x:int, y:bool :: foo(x,p) <==> x > 10 && y);
+axiom {:inline true} (forall y:bool :: foo(q,y) == (q > 10 && y));
+axiom {:inline true} (forall x:int, y:bool, z:int :: foo(x,y) == (q > 10 && y));
+axiom {:inline true} (forall y:bool, x:int :: foo3(x,y) == (q > 10 && y));
+axiom {:inline true} true;
+axiom {:inline true} (forall y:bool, x:int :: foo3(x,true) == (q > 10 && y));
+
+
+procedure baz1()
+{
+ assert foo3(1,true);
+}
+
+procedure baz2()
+{
+ assert foo1(true,true);
+}
+
+function foo4(x:int, y:int) returns(bool);
+axiom {:inline true} (forall x:int,z:int :: foo4(x,x) == (x > 0));
diff --git a/Test/inline/expansion2.bpl b/Test/inline/expansion2.bpl
new file mode 100644
index 00000000..fc14a0eb
--- /dev/null
+++ b/Test/inline/expansion2.bpl
@@ -0,0 +1,14 @@
+function xxgz(x:int) returns(bool);
+function xxf1(x:int,y:bool) returns(int);
+axiom {:inline true} (forall x:int :: xxgz(x) <==> x > 0);
+axiom {:inline true} (forall x:int, y:bool :: xxf1(x,y) == x+1);
+
+axiom (forall z:int :: z>12 ==> xxgz(z));
+axiom (forall y:int, x:bool :: xxf1(y, x) > 1 ==> y > 0);
+
+procedure foo()
+{
+ assert xxgz(12);
+ assert xxf1(3,true) == 4;
+}
+
diff --git a/Test/inline/expansion2.sx b/Test/inline/expansion2.sx
new file mode 100644
index 00000000..7417aab2
--- /dev/null
+++ b/Test/inline/expansion2.sx
@@ -0,0 +1,178 @@
+; Boogie program verifier version 2.00, Copyright (c) 2003-2009, Microsoft.
+; Command Line Options: -nologo -logPrefix:inline /proverLog:expansion2.sx expansion2.bpl
+; Proof obligation: foo
+; Z3 command line: c:\Program Files\Microsoft Research\Z3-2.0\bin\z3.exe /si /@ /cex:5 /t:0
+; User supplied Z3 options:
+; Prover options:
+;
+(SETPARAMETER MODEL_PARTIAL true)
+(SETPARAMETER MODEL_VALUE_COMPLETION false)
+(SETPARAMETER MODEL_HIDE_UNUSED_PARTITIONS false)
+(SETPARAMETER MODEL_V1 true)
+(SETPARAMETER ASYNC_COMMANDS false)
+(SETPARAMETER PHASE_SELECTION 0)
+(SETPARAMETER RESTART_STRATEGY 0)
+(SETPARAMETER RESTART_FACTOR |1.5|)
+(SETPARAMETER NNF_SK_HACK true)
+(SETPARAMETER QI_EAGER_THRESHOLD 100)
+(SETPARAMETER ARITH_RANDOM_INITIAL_VALUE true)
+(SETPARAMETER SORT_AND_OR false)
+(SETPARAMETER CASE_SPLIT 3)
+(SETPARAMETER DELAY_UNITS true)
+(SETPARAMETER DELAY_UNITS_THRESHOLD 16)
+(SETPARAMETER TYPE_CHECK true)
+(SETPARAMETER BV_REFLECT true)
+; -------------------------------------------------------------------------
+; Boogie 2 universal background predicate for Z3 (Simplify notation with types)
+; Copyright (c) 2004-2009, Microsoft Corp.
+
+(DEFTYPE $int :BUILTIN Int)
+(DEFTYPE $bool :BUILTIN bool)
+(DEFTYPE U)
+(DEFTYPE T)
+
+(DEFOP <: U U $bool) ; used for translation with type premisses
+(DEFOP <:: T U U $bool) ; used for translation with type arguments
+
+(BG_PUSH (AND
+
+ ; false is not true
+
+ (DISTINCT |@false| |@true|)
+
+ ; we assume type correctness of the operations here
+ ; a-l>=0 ==> (v ++ w:l)[a:b] = v[a-l:b-l]
+ (FORALL (v lv w lw lvw a b)
+ (QID bv:e:c1)
+ (PATS ($bv_extract ($bv_concat v lv w lw) lvw a b))
+ (IMPLIES
+ (>= (- a lw) 0)
+ (EQ ($bv_extract ($bv_concat v lv w lw) lvw a b) ($bv_extract v lv (- a lw) (- b lw)))))
+
+ ; b<=l ==> (v ++ w:l)[a:b] = w[a:b]
+ (FORALL (v lv w lw lvw a b)
+ (QID bv:e:c2)
+ (PATS ($bv_extract ($bv_concat v lv w lw) lvw a b))
+ (IMPLIES
+ (<= b lw)
+ (EQ ($bv_extract ($bv_concat v lv w lw) lvw a b) ($bv_extract w lw a b))))
+
+ ; v:l
+ ; a>=x || b<=y ==> (v[x:l] ++ w ++ v[0:y])[a:b] = v[a:b]
+ (FORALL (v lv x lxv w lw lwy y a b)
+ (QID bv:e:c3)
+ (PATS
+ ($bv_extract
+ ($bv_concat
+ ($bv_extract v lv x lv) lxv
+ ($bv_concat
+ w lw
+ ($bv_extract v lv 0 y) y) lwy) lv a b))
+ (IMPLIES
+ (AND
+ (EQ lw (- x y))
+ (EQ lxv (- lv x))
+ (EQ lwy (+ w y))
+ (OR (>= a x) (<= b y)))
+ (EQ
+ ($bv_extract
+ ($bv_concat
+ ($bv_extract v lv x lv) lxv
+ ($bv_concat
+ w lw
+ ($bv_extract v lv 0 y) y) lwy) lv a b)
+ ($bv_extract v lv a b))))
+
+ ; a>=x ==> (v[x:l] ++ w)[a:b] = v[a:b]
+ (FORALL (v lv x lxv w a b)
+ (QID bv:e:c4)
+ (PATS
+ ($bv_extract
+ ($bv_concat
+ ($bv_extract v lv x lv) lxv
+ w x)
+ lv a b))
+ (IMPLIES
+ (AND
+ (EQ lxv (- lv x))
+ (>= a x))
+ (EQ
+ ($bv_extract
+ ($bv_concat
+ ($bv_extract v lv x lv) lxv
+ w x)
+ lv a b)
+ ($bv_extract v lv a b))))
+
+ (FORALL (v l)
+ (QID bv:e:0)
+ (PATS ($bv_extract v l 0 l))
+ (EQ ($bv_extract v l 0 l) v))
+
+ (FORALL (n)
+ (QID bv:pow)
+ (PATS ($pow2 n))
+ (IMPLIES (> n 0) (EQ ($pow2 n) (* 2 ($pow2 (- n 1))))))
+
+ (EQ ($pow2 0) 1)
+
+ ; 0 <= v < 2^Y ==> 0bvX ++ v[0:Y] == v
+ (FORALL (v l a b)
+ (QID bv:e:pow)
+ (PATS ($bv_concat 0 b ($bv_extract v l 0 a) a))
+ (IMPLIES
+ (AND
+ (<= 0 v)
+ (< v ($pow2 a))
+ (EQ l (+ a b)))
+ (EQ ($bv_concat 0 b ($bv_extract v l 0 a) a) v)))
+
+ ; X > 0 ==> 0bvX ++ v >= 0
+ (FORALL (v a b)
+ (QID bv:e:pos)
+ (PATS ($bv_concat 0 b v a))
+ (IMPLIES
+ (> b 0)
+ (>= ($bv_concat 0 b v a) 0)))
+
+ ;; unsound?
+; (FORALL (lv w lw)
+; (QID bv:c:0)
+; (PATS ($bv_concat 0 lv w lw))
+; (EQ ($bv_concat 0 lv w lw) w))
+ ;; matching loop
+; (FORALL (v l1 a b l2 c d)
+; (QID bv:e:e)
+; (PATS ($bv_extract ($bv_extract v l1 a b) l2 c d))
+; (EQ ($bv_extract ($bv_extract v l1 a b) l2 c d) ($bv_extract v l1 (+ c a) (+ d a))))
+
+
+ ; Reflect plus
+ (FORALL (a b) (PATS (Reflect$Add a b)) (EQ (Reflect$Add a b) (+ a b)))
+
+)) ;; AND, BG_PUSH
+; End Boogie universal background predicate
+; -------------------------------------------------------------------------
+
+
+
+(DEFOP Ctor T $int)
+(DEFOP intType T)
+(DEFOP boolType T)
+(DEFOP int_2_U $int U)
+(DEFOP U_2_int U $int)
+(DEFOP type U T)
+(DEFOP bool_2_U $bool U)
+(DEFOP U_2_bool U $bool)
+(BG_PUSH
+(AND (EQ (Ctor (intType)) 0) (EQ (Ctor (boolType)) 1) (FORALL (arg0 :TYPE $int) (PATS (int_2_U arg0)) (QID typeInv:U_2_int) (EQ (U_2_int (int_2_U arg0)) arg0)) (FORALL (x :TYPE U) (PATS (int_2_U (U_2_int x))) (QID cast:U_2_int) (IMPLIES (EQ (type x) (intType)) (EQ (int_2_U (U_2_int x)) x))) (FORALL (arg0@@0 :TYPE $int) (PATS (int_2_U arg0@@0)) (QID funType:int_2_U) (EQ (type (int_2_U arg0@@0)) (intType))) (FORALL (arg0@@1 :TYPE $bool) (PATS (bool_2_U arg0@@1)) (QID typeInv:U_2_bool) (IFF (U_2_bool (bool_2_U arg0@@1)) arg0@@1)) (FORALL (x@@0 :TYPE U) (PATS (bool_2_U (U_2_bool x@@0))) (QID cast:U_2_bool) (IMPLIES (EQ (type x@@0) (boolType)) (EQ (bool_2_U (U_2_bool x@@0)) x@@0))) (FORALL (arg0@@2 :TYPE $bool) (PATS (bool_2_U arg0@@2)) (QID funType:bool_2_U) (EQ (type (bool_2_U arg0@@2)) (boolType))))
+)
+(BG_PUSH
+(AND (FORALL (x@@1 :TYPE U) (NOPATS (U_2_int x@@1) (U_2_bool x@@1)) (QID bg:subtype-refl) (<: x@@1 x@@1)) (FORALL (x@@2 :TYPE U y :TYPE U z :TYPE U) (PATS (MPAT (<: x@@2 y) (<: y z))) (QID bg:subtype-trans) (LET ((TERM alpha (type x@@2))) (IMPLIES (AND (EQ (type y) alpha) (EQ (type z) alpha)) (IMPLIES (AND (<: x@@2 y) (<: y z)) (<: x@@2 z))))) (FORALL (x@@3 :TYPE U y@@0 :TYPE U) (PATS (MPAT (<: x@@3 y@@0) (<: y@@0 x@@3))) (QID bg:subtype-antisymm) (LET ((TERM alpha@@0 (type x@@3))) (IMPLIES (EQ (type y@@0) alpha@@0) (IMPLIES (AND (<: x@@3 y@@0) (<: y@@0 x@@3)) (EQ x@@3 y@@0))))) (FORALL (z@@0 :TYPE $int) (QID expansio.6:15) (SKOLEMID 2) (IMPLIES (> z@@0 12) (> z@@0 0))) (FORALL (y@@1 :TYPE $int) (QID expansio.7:15) (SKOLEMID 3) (IMPLIES (> (+ y@@1 1) 1) (> y@@1 0))))
+)
+; Initialized all axioms.
+(BG_PUSH
+TRUE
+)
+(LET ((FORMULA anon0_correct (IMPLIES (LBLPOS |+107| TRUE) (IMPLIES TRUE (AND (LBLNEG |@164| (> 12 0)) (IMPLIES (> 12 0) (AND (LBLNEG |@168| (EQ (+ 3 1) 4)) (IMPLIES (EQ (+ 3 1) 4) (IMPLIES TRUE TRUE))))))))) anon0_correct)
+; Valid
diff --git a/Test/inline/expansion3.bpl b/Test/inline/expansion3.bpl
new file mode 100644
index 00000000..1fd3d853
--- /dev/null
+++ b/Test/inline/expansion3.bpl
@@ -0,0 +1,19 @@
+function foo3(x:int, y:bool) returns(bool);
+axiom {:inline true} (forall y:bool, x:int :: foo3(x,y) == foo3(x,y));
+
+axiom foo3(1,false);
+
+procedure baz1()
+ requires foo3(2,false);
+{
+ assume foo3(1,true);
+}
+
+function x1(x:int) returns(bool);
+axiom {:inline true} (forall x:int :: x1(x) <==> x > 0);
+axiom {:inline true} (forall x:int :: x1(x) <==> x >= 1);
+
+procedure bar()
+{
+ assert x1(3);
+}
diff --git a/Test/inline/expansion4.bpl b/Test/inline/expansion4.bpl
new file mode 100644
index 00000000..593fa9fb
--- /dev/null
+++ b/Test/inline/expansion4.bpl
@@ -0,0 +1,31 @@
+function f(x:int) returns(bool);
+axiom {:ignore "bvInt"} {:inline true} (forall x:int :: f(x) <==> true);
+axiom {:ignore "bvDefSem"} {:inline true} (forall x:int :: f(x) <==> false);
+
+procedure {:forceBvZ3Native true} foo()
+{
+ assert f(3);
+}
+
+procedure {:forceBvInt true} foo2()
+{
+ assert !f(3);
+}
+
+axiom (forall x: bv64, y: bv64 :: { $sub.unchk.u8(x, y) } $check.sub.u8(x, y) ==> $sub.u8(x, y) == $sub.unchk.u8(x, y));
+axiom {:inline true} {:ignore "bvDefSem"} (forall x: bv64, y: bv64 :: { $check.sub.u8(x, y) }
+$check.sub.u8(x, y) <==> $_inrange.u8($sub.i8(x, y)));
+
+function $check.sub.u8(x: bv64, y: bv64) returns (bool);
+function $_inrange.u8(bv64) returns (bool);
+function {:bvbuiltin "bvsub"} $sub.unchk.u8(x: bv64, y: bv64) returns (bv64);
+function {:bvbuiltin "bvsub"} {:bvint "-"} $sub.i8(x: bv64, y: bv64) returns (bv64);
+function {:bvbuiltin "bvsub"} {:bvint "-"} $sub.u8(x: bv64, y: bv64) returns (bv64);
+
+
+procedure {:forceBvZ3Native true} baz()
+{
+ return;
+}
+
+
diff --git a/Test/inline/fundef.bpl b/Test/inline/fundef.bpl
new file mode 100644
index 00000000..46ce65bd
--- /dev/null
+++ b/Test/inline/fundef.bpl
@@ -0,0 +1,6 @@
+function {:inline true} foo(x:int) returns(bool)
+ { x > 0 }
+function {:inline false} foo2(x:int) returns(bool)
+ { x > 0 }
+function foo3(x:int) returns(bool)
+ { x > 0 }
diff --git a/Test/inline/fundef2.bpl b/Test/inline/fundef2.bpl
new file mode 100644
index 00000000..2e005fcc
--- /dev/null
+++ b/Test/inline/fundef2.bpl
@@ -0,0 +1,7 @@
+function {:inline true} foo(x:int) returns(bool)
+ { x > 0 }
+
+procedure P() {
+ assert foo(13);
+ assert foo(-5); // error
+} \ No newline at end of file
diff --git a/Test/inline/polyInline.bpl b/Test/inline/polyInline.bpl
new file mode 100644
index 00000000..320259bd
--- /dev/null
+++ b/Test/inline/polyInline.bpl
@@ -0,0 +1,40 @@
+
+const C:int;
+const D:bool;
+
+function empty<alpha>() returns (alpha);
+
+function eqC<alpha>(x:alpha) returns (bool) { x == C }
+function giveEmpty<alpha>() returns (alpha) { empty() }
+
+function {:inline true} eqC2<alpha>(x:alpha) returns (bool) { x == C }
+function {:inline true} giveEmpty2<alpha>() returns (alpha) { empty() }
+
+function eqC3<alpha>(x:alpha) returns (bool);
+axiom {:inline true} (forall<alpha> x:alpha :: eqC3(x) == (x == C));
+
+function giveEmpty3<alpha>() returns (alpha);
+axiom {:inline true} (forall<alpha> :: giveEmpty3():alpha == empty());
+
+procedure P() {
+ assert eqC(C);
+ assert eqC2(C);
+ assert eqC3(C);
+ assert eqC2(D); // should not be provable
+}
+
+procedure Q() {
+ assert giveEmpty() == empty();
+ assert giveEmpty() == empty():int;
+ assert giveEmpty():bool == empty();
+
+ assert giveEmpty2() == empty();
+ assert giveEmpty2() == empty():int;
+ assert giveEmpty2():bool == empty();
+
+ assert giveEmpty3() == empty();
+ assert giveEmpty3() == empty():int;
+ assert giveEmpty3():bool == empty();
+
+ assert giveEmpty3() == C; // should not be provable
+} \ No newline at end of file
diff --git a/Test/inline/runtest.bat b/Test/inline/runtest.bat
new file mode 100644
index 00000000..3040d5b0
--- /dev/null
+++ b/Test/inline/runtest.bat
@@ -0,0 +1,30 @@
+@echo off
+setlocal
+
+set BGEXE=..\..\Binaries\Boogie.exe
+
+for %%f in (test1.bpl test2.bpl test3.bpl test4.bpl) do (
+ echo -------------------- %%f --------------------
+ %BGEXE% %* /inline:b /print:- /env:0 /printInlined /noinfer %%f
+)
+
+for %%f in (test5.bpl test6.bpl expansion.bpl expansion3.bpl Elevator.bpl) do (
+ echo -------------------- %%f --------------------
+ %BGEXE% %* %%f
+)
+
+echo -------------------- expansion2.bpl --------------------
+%BGEXE% %* /proverLog:expansion2.sx expansion2.bpl
+%SystemRoot%\system32\find.exe /C "xxgz" expansion2.sx
+%SystemRoot%\system32\find.exe /C "xxf1" expansion2.sx
+
+echo -------------------- expansion4.bpl --------------------
+%BGEXE% %* /bv:i expansion4.bpl
+
+echo -------------------- fundef.bpl --------------------
+%BGEXE% %* /print:- /env:0 fundef.bpl
+%BGEXE% %* fundef2.bpl
+
+echo -------------------- polyInline.bpl --------------------
+%BGEXE% %* /typeEncoding:predicates /logPrefix:p polyInline.bpl
+%BGEXE% %* /typeEncoding:arguments /logPrefix:a polyInline.bpl
diff --git a/Test/inline/test1.bpl b/Test/inline/test1.bpl
new file mode 100644
index 00000000..db847b25
--- /dev/null
+++ b/Test/inline/test1.bpl
@@ -0,0 +1,45 @@
+
+procedure Main()
+{
+
+ var x:int;
+ var y:int;
+
+ x := 1;
+ y := 0;
+
+ call x := inc(x, 5);
+ call y := incdec(x, 2);
+
+ assert(x - 1 == y);
+
+}
+
+procedure {:inline 1} incdec(x:int, y:int) returns (z:int)
+ ensures z == x + 1 - y;
+{
+ z := x;
+ z := x + 1;
+ call z := dec(z, y);
+
+ return;
+
+}
+
+procedure {:inline 1} inc(x:int, i:int) returns (y:int)
+ ensures y == x + i;
+{
+ y := x;
+ y := x + i;
+ return;
+
+}
+
+procedure {:inline 1} dec(x:int, i:int) returns (y:int)
+ ensures y == x - i;
+{
+ y := x;
+ y := x - i;
+ return;
+
+} \ No newline at end of file
diff --git a/Test/inline/test2.bpl b/Test/inline/test2.bpl
new file mode 100644
index 00000000..a45e86d5
--- /dev/null
+++ b/Test/inline/test2.bpl
@@ -0,0 +1,31 @@
+
+var glb:int;
+
+procedure calculate()
+modifies glb;
+{
+ var x:int;
+ var y:int;
+
+ y := 5;
+
+ call x := increase(y);
+
+ return;
+}
+
+
+procedure {:inline 1} increase (i:int) returns (k:int)
+modifies glb;
+{
+ var j:int;
+
+ j := i;
+ j := j + 1;
+
+ glb := glb + j;
+
+ k := j;
+
+ return;
+}
diff --git a/Test/inline/test3.bpl b/Test/inline/test3.bpl
new file mode 100644
index 00000000..f705e7b0
--- /dev/null
+++ b/Test/inline/test3.bpl
@@ -0,0 +1,28 @@
+
+var glb:int;
+
+procedure recursivetest()
+modifies glb;
+{
+ glb := 5;
+ call glb := recursive(glb);
+
+ return;
+
+}
+
+procedure {:inline 3} recursive(x:int) returns (y:int)
+{
+
+ var k: int;
+
+ if(x == 0) {
+ y := 1;
+ return;
+ }
+
+ call k := recursive(x-1);
+ y := y + k;
+ return;
+
+} \ No newline at end of file
diff --git a/Test/inline/test4.bpl b/Test/inline/test4.bpl
new file mode 100644
index 00000000..4a740bbc
--- /dev/null
+++ b/Test/inline/test4.bpl
@@ -0,0 +1,53 @@
+
+procedure main(x:int)
+{
+ var A:[int]int;
+ var i:int;
+ var b:bool;
+ var size:int;
+
+ call i,b := find(A, size, x);
+
+ if(b) {
+ assert(i > 0 && A[i] == x);
+ }
+
+ return;
+}
+
+procedure {:inline 1} find(A:[int]int, size:int, x:int) returns (ret:int, found:bool)
+{
+ var i:int;
+ var b:bool;
+
+ ret := -1;
+ b := false;
+ found := b;
+ i := 0;
+
+ while(i < size) {
+ call b := check(A, i, x);
+ if(b) {
+ ret := i;
+ found := b;
+ break;
+ }
+
+ }
+
+ return;
+
+}
+
+
+procedure {:inline 3} check (A:[int]int, i:int, c:int) returns (ret:bool)
+ requires i >= 0;
+ ensures (old(A[i]) > c) ==> ret == true;
+{
+ if(A[i] == c) {
+ ret := true;
+ } else {
+ ret := false;
+ }
+ return;
+} \ No newline at end of file
diff --git a/Test/inline/test5.bpl b/Test/inline/test5.bpl
new file mode 100644
index 00000000..0132f60a
--- /dev/null
+++ b/Test/inline/test5.bpl
@@ -0,0 +1,20 @@
+// test a case, where the inlined proc comes before the caller
+
+procedure {:inline 2} foo()
+ modifies x;
+{
+ x := x + 1;
+}
+
+var x:int;
+
+procedure bar()
+ modifies x;
+{
+ x := 3;
+ call foo();
+ assert x == 4;
+ call foo();
+ assert x == 5;
+}
+
diff --git a/Test/inline/test6.bpl b/Test/inline/test6.bpl
new file mode 100644
index 00000000..394be89e
--- /dev/null
+++ b/Test/inline/test6.bpl
@@ -0,0 +1,37 @@
+procedure {:inline 2} foo()
+ modifies x;
+{
+ x := x + 1;
+ call foo();
+}
+
+procedure {:inline 2} foo1()
+ modifies x;
+{
+ x := x + 1;
+ call foo2();
+}
+
+procedure {:inline 2} foo2()
+ modifies x;
+{
+ x := x + 1;
+ call foo3();
+}
+
+procedure {:inline 2} foo3()
+ modifies x;
+{
+ x := x + 1;
+ call foo1();
+}
+
+var x:int;
+
+procedure bar()
+ modifies x;
+{
+ call foo();
+ call foo1();
+}
+
diff --git a/Test/lock/Answer b/Test/lock/Answer
new file mode 100644
index 00000000..bcfc9f1c
--- /dev/null
+++ b/Test/lock/Answer
@@ -0,0 +1,8 @@
+
+Boogie program verifier finished with 3 verified, 0 errors
+LockIncorrect.bpl(17,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ LockIncorrect.bpl(9,1): start
+ LockIncorrect.bpl(14,1): LoopHead
+
+Boogie program verifier finished with 0 verified, 1 error
diff --git a/Test/lock/Lock.bpl b/Test/lock/Lock.bpl
new file mode 100644
index 00000000..ed24a710
--- /dev/null
+++ b/Test/lock/Lock.bpl
@@ -0,0 +1,122 @@
+procedure LockingExample();
+
+implementation LockingExample()
+{
+var x: int;
+var y: int;
+var held: int;
+
+start:
+ held := 0;
+ x := 0;
+ goto LoopHead;
+
+LoopHead:
+ // Lock
+ assert held == 0;
+ held := 1;
+
+ y := x;
+ goto UnlockNow, LoopEnd;
+
+UnlockNow:
+ // Unlock
+ assert held == 1;
+ held := 0;
+
+ x := x + 1;
+ goto LoopEnd;
+
+LoopEnd:
+ goto ContinueIteration, EndIteration;
+
+ContinueIteration:
+ assume x != y;
+ goto LoopHead;
+
+EndIteration:
+ assume x == y;
+ goto AfterLoop;
+
+AfterLoop:
+ // Unlock
+ assert held == 1;
+ held := 0;
+
+ return;
+
+}
+
+
+procedure StructuredLockingExample()
+{
+ var x: int;
+ var y: int;
+ var held: bool;
+
+ held := false;
+ x := 0;
+
+ while (true)
+ invariant !held;
+ {
+ // Lock
+ assert !held;
+ held := true;
+
+ y := x;
+ if (*) {
+ // Unlock
+ assert held;
+ held := false;
+
+ x := x + 1;
+ }
+
+ if (x == y) { break; }
+ }
+
+ // Unlock
+ assert held;
+ held := false;
+}
+
+procedure StructuredLockingExampleWithCalls()
+{
+ var x: int;
+ var y: int;
+ var mutex: Mutex;
+
+ call mutex := Initialize();
+ x := 0;
+
+ while (true)
+ invariant !IsHeld(mutex);
+ {
+ call mutex := Acquire(mutex);
+
+ y := x;
+ if (*) {
+ call mutex := Release(mutex);
+ x := x + 1;
+ }
+
+ if (x == y) { break; }
+ }
+
+ call mutex := Release(mutex);
+}
+
+type Mutex;
+function IsHeld(Mutex) returns (bool);
+
+procedure Initialize() returns (post: Mutex);
+ ensures !IsHeld(post);
+
+procedure Acquire(pre: Mutex) returns (post: Mutex);
+ requires !IsHeld(pre);
+ ensures IsHeld(post);
+
+procedure Release(pre: Mutex) returns (post: Mutex);
+ requires IsHeld(pre);
+ ensures !IsHeld(post);
diff --git a/Test/lock/LockIncorrect.bpl b/Test/lock/LockIncorrect.bpl
new file mode 100644
index 00000000..776f8af6
--- /dev/null
+++ b/Test/lock/LockIncorrect.bpl
@@ -0,0 +1,51 @@
+procedure LockingExample();
+
+implementation LockingExample()
+{
+var x: int;
+var y: int;
+var held: int;
+
+start:
+ held := 0;
+ x := 0;
+ goto LoopHead;
+
+LoopHead:
+ // Lock
+ held := held + 6;
+ assert held == 0;
+ held := 1;
+
+ y := x;
+ goto UnlockNow, LoopEnd;
+
+UnlockNow:
+ // Unlock
+ assert held == 1;
+ held := 0;
+
+ x := x + 1;
+ goto LoopEnd;
+
+LoopEnd:
+ goto ContinueIteration, EndIteration;
+
+ContinueIteration:
+ assume x != y;
+ goto LoopHead;
+
+EndIteration:
+ assume x == y;
+ goto AfterLoop;
+
+AfterLoop:
+ // Unlock
+ assert held == 1;
+ held := 0;
+
+ return;
+
+}
+
+
diff --git a/Test/lock/Output b/Test/lock/Output
new file mode 100644
index 00000000..bcfc9f1c
--- /dev/null
+++ b/Test/lock/Output
@@ -0,0 +1,8 @@
+
+Boogie program verifier finished with 3 verified, 0 errors
+LockIncorrect.bpl(17,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ LockIncorrect.bpl(9,1): start
+ LockIncorrect.bpl(14,1): LoopHead
+
+Boogie program verifier finished with 0 verified, 1 error
diff --git a/Test/lock/runtest.bat b/Test/lock/runtest.bat
new file mode 100644
index 00000000..a90972c9
--- /dev/null
+++ b/Test/lock/runtest.bat
@@ -0,0 +1,7 @@
+@echo off
+setlocal
+
+set BGEXE=..\..\Binaries\Boogie.exe
+
+%BGEXE% %* Lock.bpl
+%BGEXE% %* LockIncorrect.bpl
diff --git a/Test/rtest b/Test/rtest
new file mode 100644
index 00000000..55386bf0
--- /dev/null
+++ b/Test/rtest
@@ -0,0 +1,25 @@
+#!/usr/bin/bash
+
+if [ $# -eq 0 ] ; then
+ echo "rtest: Error: Syntax: rtest testDirectory [ additionalTestArguments ... ]"
+ exit 1
+elif [ ! -d $1 ] ; then
+ echo rtest: Error: There is no test directory $1
+ exit 1
+fi
+
+TESTDIR=$1
+echo ----- Running regression test $TESTDIR
+cd $TESTDIR
+
+shift
+cmd /c .\\runtest.bat -nologo -logPrefix:$TESTDIR "$@" > Output
+# perl ../filter.pl Output Output.filtered
+# perl ../filter.pl Answer Answer.filtered
+# diff -w Answer.filtered Output.filtered > Diffs
+if c:/Windows/system32/fc /W Answer Output > /dev/null ; then
+ echo Succeeded
+else
+ echo FAILED
+fi
+cd ..
diff --git a/Test/rtestall b/Test/rtestall
new file mode 100644
index 00000000..eecb5fda
--- /dev/null
+++ b/Test/rtestall
@@ -0,0 +1,32 @@
+#!/usr/bin/bash
+
+if [ "$1" == "short" ] ; then
+ shift
+ ALL_TESTS=`cat alltests.txt | grep -E "^[^[:space:]]+[[:space:]]+Use[[:space:]]" | awk '{print $1}'`
+elif [ "$1" == "long" ] ; then
+ shift
+ ALL_TESTS=`cat alltests.txt | grep -E "^[^[:space:]]+[[:space:]]+Long[[:space:]]" | awk '{print $1}'`
+else
+ ALL_TESTS=`cat alltests.txt | grep -E "^[^[:space:]]+[[:space:]]+(Use|Long)[[:space:]]" | awk '{print $1}'`
+fi
+
+if [ "$1" == "time" ] ; then
+ shift
+ TIME_CMD="time -p"
+else
+ TIME_CMD=""
+fi
+
+if [ "$1" == "reverse" ] || [ "$1" == "rev" ]; then
+ shift
+ ALL_TESTS=`echo ${ALL_TESTS} | sed -e 's/ /\n/g' | awk '{a[NR] = $0} END { for(i=NR; i; --i) print a[i]}'`
+fi
+
+for t in ${ALL_TESTS} ; do
+ # ${TIME_CMD} bash rtest $t "$@"
+ if [ "${TIME_CMD}" == "" ] ; then
+ ./runtest.bat $t "$@"
+ else
+ time -p ./runtest.bat $t "$@"
+ fi
+done
diff --git a/Test/runtest.bat b/Test/runtest.bat
new file mode 100644
index 00000000..424ede10
--- /dev/null
+++ b/Test/runtest.bat
@@ -0,0 +1,36 @@
+@echo off
+rem Usage: runtest.bat <dir>
+if "%1" == "" goto noDirSpecified
+if not exist %1\nul goto noDirExists
+echo ----- Running regression test %1
+pushd %1
+if not exist runtest.bat goto noRunTest
+call runtest.bat -nologo -logPrefix:%1 %2 %3 %4 %5 %6 %7 %8 %9 > Output
+fc /W Answer Output > nul
+if not errorlevel 1 goto passTest
+echo FAILED
+goto errorEnd
+
+:passTest
+echo Succeeded
+goto end
+
+:noDirSpecified
+echo runtest: Error: Syntax: runtest testDirectory [ additionalTestArguments ... ]
+goto errorEnd
+
+:noDirExists
+echo runtest: Error: There is no test directory %1
+goto errorEnd
+
+:noRunTest
+echo runtest: Error: no runtest.bat found in test directory %1
+goto errorEnd
+
+:errorEnd
+popd
+exit /b 1
+
+:end
+popd
+exit /b 0
diff --git a/Test/runtestall.bat b/Test/runtestall.bat
new file mode 100644
index 00000000..207bb030
--- /dev/null
+++ b/Test/runtestall.bat
@@ -0,0 +1,24 @@
+@echo off
+setlocal
+
+set errors=0
+
+if "%1" == "short" goto UseShort
+
+set IncludeLong=True
+goto Loop
+
+:UseShort
+set IncludeLong=False
+shift
+goto Loop
+
+:Loop
+for /F "eol=; tokens=1,2,3*" %%i in (alltests.txt) do if %%j==Use call runtest.bat %%i %1 %2 %3 %4 %5 %6 %7 %8 %9 || set errors=1
+
+if not %IncludeLong%==True goto End
+
+for /F "eol=; tokens=1,2,3*" %%i in (alltests.txt) do if %%j==Long call runtest.bat %%i %1 %2 %3 %4 %5 %6 %7 %8 %9 || set errors=1
+
+:End
+exit /b %errors% \ No newline at end of file
diff --git a/Test/smoke/Answer b/Test/smoke/Answer
new file mode 100644
index 00000000..4141bdb0
--- /dev/null
+++ b/Test/smoke/Answer
@@ -0,0 +1,25 @@
+-------------------- smoke0.bpl --------------------
+found unreachable code:
+implementation b(x: int)
+{
+ var y: int;
+ var y@0: int;
+
+
+ anon0:
+ assume true;
+ assume true;
+ goto anon3_Then;
+
+ anon3_Then:
+ assume true;
+ assume x < 0;
+ y := 1;
+ assume 1 <= y && y <= 1;
+ assert false;
+ return;
+}
+
+
+
+Boogie program verifier finished with 4 verified, 0 errors
diff --git a/Test/smoke/Output b/Test/smoke/Output
new file mode 100644
index 00000000..4141bdb0
--- /dev/null
+++ b/Test/smoke/Output
@@ -0,0 +1,25 @@
+-------------------- smoke0.bpl --------------------
+found unreachable code:
+implementation b(x: int)
+{
+ var y: int;
+ var y@0: int;
+
+
+ anon0:
+ assume true;
+ assume true;
+ goto anon3_Then;
+
+ anon3_Then:
+ assume true;
+ assume x < 0;
+ y := 1;
+ assume 1 <= y && y <= 1;
+ assert false;
+ return;
+}
+
+
+
+Boogie program verifier finished with 4 verified, 0 errors
diff --git a/Test/smoke/runtest.bat b/Test/smoke/runtest.bat
new file mode 100644
index 00000000..7728d5ef
--- /dev/null
+++ b/Test/smoke/runtest.bat
@@ -0,0 +1,11 @@
+@echo off
+setlocal
+
+set BOOGIEDIR=..\..\Binaries
+set BGEXE=%BOOGIEDIR%\Boogie.exe
+
+for %%f in (smoke0.bpl) do (
+ echo -------------------- %%f --------------------
+ %BGEXE% /smoke %* %%f
+)
+
diff --git a/Test/smoke/smoke0.bpl b/Test/smoke/smoke0.bpl
new file mode 100644
index 00000000..85deb324
--- /dev/null
+++ b/Test/smoke/smoke0.bpl
@@ -0,0 +1,53 @@
+procedure a(x:int)
+{
+ var y : int;
+
+ if(x<0) {
+ y := 1;
+ } else {
+ y := 2;
+ }
+}
+
+
+procedure b(x:int)
+ requires x>0;
+{
+ var y : int;
+
+ if(x<0) {
+ y := 1;
+ } else {
+ y := 2;
+ }
+}
+
+
+
+procedure c(x:int)
+ requires x>0;
+{
+ var y : int;
+
+ if(x<0) {
+ y := 1;
+ assert false;
+ } else {
+ y := 2;
+ }
+}
+
+procedure d(x:int)
+ requires x>0;
+{
+ var y : int;
+
+ if(x<0) {
+ assert false;
+ y := 1;
+ } else {
+ y := 2;
+ }
+}
+
+
diff --git a/Test/test0/Answer b/Test/test0/Answer
new file mode 100644
index 00000000..e8ea231e
--- /dev/null
+++ b/Test/test0/Answer
@@ -0,0 +1,252 @@
+
+Boogie program verifier finished with 0 verified, 0 errors
+
+Boogie program verifier finished with 0 verified, 0 errors
+Triggers0.bpl(14,31): Error: the 'nopats' quantifier attribute expects a string-literal parameter
+1 parse errors detected in Triggers0.bpl
+Triggers1.bpl(7,17): Error: boolean operators are not allowed in triggers
+Triggers1.bpl(11,21): Error: boolean operators are not allowed in triggers
+Triggers1.bpl(15,9): Error: boolean operators are not allowed in triggers
+Triggers1.bpl(19,10): Error: boolean operators are not allowed in triggers
+Triggers1.bpl(23,17): Error: boolean operators are not allowed in triggers
+Triggers1.bpl(27,17): Error: boolean operators are not allowed in triggers
+Triggers1.bpl(32,17): Error: equality is not allowed in triggers
+Triggers1.bpl(36,17): Error: arithmetic comparisons are not allowed in triggers
+Triggers1.bpl(45,10): Error: quantifiers are not allowed in triggers
+Triggers1.bpl(53,7): Error: trigger must mention all quantified variables, but does not mention: x
+Triggers1.bpl(61,7): Error: trigger must mention all quantified variables, but does not mention: y
+Triggers1.bpl(62,7): Error: trigger must mention all quantified variables, but does not mention: x
+Triggers1.bpl(70,9): Error: a matching pattern must be more than just a variable by itself: x
+Triggers1.bpl(82,7): Error: trigger must mention all quantified variables, but does not mention: z
+Triggers1.bpl(94,16): Error: a matching pattern must be more than just a variable by itself: x
+Triggers1.bpl(95,16): Error: a matching pattern must be more than just a variable by itself: g
+Triggers1.bpl(105,40): Error: trigger must mention all quantified variables, but does not mention: y
+Triggers1.bpl(106,40): Error: trigger must mention all quantified variables, but does not mention: x
+Triggers1.bpl(109,57): Error: trigger must mention all quantified variables, but does not mention: z
+Triggers1.bpl(110,57): Error: trigger must mention all quantified variables, but does not mention: y
+Triggers1.bpl(111,57): Error: trigger must mention all quantified variables, but does not mention: x
+Triggers1.bpl(119,33): Error: cannot refer to a global variable in this context: h1
+Triggers1.bpl(120,33): Error: cannot refer to a global variable in this context: h0
+23 name resolution errors detected in Triggers1.bpl
+const x: int;
+
+const y: int;
+
+const z: int;
+
+const P: bool;
+
+const Q: bool;
+
+const R: bool;
+
+axiom x * (y + z) == x + y * z;
+
+axiom x * y + z == (x + y) * z;
+
+axiom x * y * z == x * y * z;
+
+axiom x * y * z * x == x * y * z;
+
+axiom x / y / z == x / (y / z);
+
+axiom x / y / (z / x) == x / y / z;
+
+axiom x - y - z == x - (y - z);
+
+axiom x - y - (z - x) == x - y - z;
+
+axiom x + y - z - x + y == 0;
+
+axiom x + y - z - x + y == x + y - (z - (x + y));
+
+axiom P ==> Q ==> R <==> P ==> Q ==> R;
+
+axiom (P ==> Q) ==> R ==> P <==> (P ==> Q) ==> R;
+
+axiom P <==> Q <==> R;
+
+axiom P ==> Q <==> Q ==> R <==> R ==> P;
+
+axiom (P && Q) || (Q && R);
+
+axiom (P || Q) && (Q || R);
+
+axiom P || Q || Q || R;
+
+axiom P && Q && Q && R;
+
+function f(int) returns (int);
+
+axiom (forall x: int :: {:xname "hello"} {:weight 5} {:ValueFunc f(x + 1)} { f(x + x) } { f(x) * f(x) } {:nopats f(x + x + x) } f(f(x)) < 200);
+
+Boogie program verifier finished with 0 verified, 0 errors
+
+Boogie program verifier finished with 0 verified, 0 errors
+Arrays1.bpl(11,11): Error: command assigns to a global variable that is not in the enclosing method's modifies clause: Q
+Arrays1.bpl(14,15): Error: command assigns to a global variable that is not in the enclosing method's modifies clause: Q
+2 type checking errors detected in Arrays1.bpl
+Types0.bpl(6,18): Error: expected identifier before ':'
+1 parse errors detected in Types0.bpl
+Types1.bpl(6,11): Error: undeclared type: x
+Types1.bpl(7,18): Error: undeclared type: x
+2 name resolution errors detected in Types1.bpl
+WhereParsing.bpl(14,37): Error: where clause not allowed here
+WhereParsing.bpl(15,33): Error: where clause not allowed here
+2 parse errors detected in WhereParsing.bpl
+WhereParsing0.bpl(17,38): Error: where clause not allowed here
+WhereParsing0.bpl(18,38): Error: where clause not allowed here
+2 parse errors detected in WhereParsing0.bpl
+WhereParsing1.bpl(14,27): syntax error: ) expected
+1 parse errors detected in WhereParsing1.bpl
+WhereParsing2.bpl(1,14): syntax error: ; expected
+1 parse errors detected in WhereParsing2.bpl
+WhereResolution.bpl(28,38): Error: undeclared identifier: alpha
+WhereResolution.bpl(32,30): Error: old expressions allowed only in two-state contexts
+2 name resolution errors detected in WhereResolution.bpl
+BadLabels0.bpl(4,2): Error: more than one declaration of block name: X
+BadLabels0.bpl(11,4): Error: more than one declaration of block name: Y
+2 name resolution errors detected in BadLabels0.bpl
+BadLabels1.bpl(4,3): Error: Error: goto label 'X' is undefined or out of reach
+BadLabels1.bpl(5,3): Error: Error: goto label 'Y' is undefined or out of reach
+BadLabels1.bpl(10,3): Error: Error: goto label 'X' is undefined or out of reach
+BadLabels1.bpl(24,5): Error: Error: goto label 'K' is undefined or out of reach
+BadLabels1.bpl(30,5): Error: Error: goto label 'A' is undefined or out of reach
+BadLabels1.bpl(38,7): Error: Error: goto label 'M' is undefined or out of reach
+BadLabels1.bpl(41,3): Error: Error: goto label 'B' is undefined or out of reach
+BadLabels1.bpl(47,3): Error: Error: break statement is not inside a loop
+BadLabels1.bpl(49,5): Error: Error: break statement is not inside a loop
+BadLabels1.bpl(60,5): Error: Error: break label 'B' must designate an enclosing statement
+BadLabels1.bpl(63,5): Error: Error: break label 'A' must designate an enclosing statement
+BadLabels1.bpl(64,5): Error: Error: break label 'C' must designate an enclosing statement
+BadLabels1.bpl(65,8): Error: Error: break label 'F' must designate an enclosing statement
+13 parse errors detected in BadLabels1.bpl
+LineParse.bpl(1,0): Error: Malformed (#line num [filename]) pragma: #line
+LineParse.bpl(2,0): Error: Malformed (#line num [filename]) pragma: #line
+LineParse.bpl(1,0): Error: Unrecognized pragma: #dontknow what this is No, I don't well, it's an error is what it is
+LineParse.bpl(3,0): Error: Unrecognized pragma: #define ASSERT(x) {if (!(x)) { crash(); }} // error: A B C . txt(12,0)
+LineParse.bpl(6,2): syntax error: EOF expected
+5 parse errors detected in LineParse.bpl
+LineResolve.bpl(5,1): Error: undeclared identifier: a
+LineResolve.bpl(7,2): Error: undeclared identifier: b
+LineResolve.bpl(12,0): Error: undeclared identifier: c
+LineResolve.bpl(13,10): Error: undeclared identifier: d
+LineResolve.bpl(12,0): Error: undeclared identifier: e
+LineResolve.bpl(2,0): Error: undeclared identifier: f
+LineResolve.bpl(900,0): Error: undeclared identifier: g
+Abc.txt(11,3): Error: undeclared identifier: h
+Abc.txt(13,0): Error: undeclared identifier: i
+Abc.txt(99,0): Error: undeclared identifier: j
+c:\Users\leino\Documents\Programs\MyClass.ssc(104,0): Error: undeclared identifier: k
+A B C . txt(12,0): Error: undeclared identifier: l
+12 name resolution errors detected in LineResolve.bpl
+AttributeParsingErr.bpl(1,33): Error: only attributes, not triggers, allowed here
+AttributeParsingErr.bpl(3,33): Error: only attributes, not triggers, allowed here
+AttributeParsingErr.bpl(5,52): Error: only attributes, not triggers, allowed here
+AttributeParsingErr.bpl(7,37): Error: only attributes, not triggers, allowed here
+AttributeParsingErr.bpl(9,31): Error: only attributes, not triggers, allowed here
+AttributeParsingErr.bpl(11,29): Error: only attributes, not triggers, allowed here
+AttributeParsingErr.bpl(13,13): Error: only attributes, not triggers, allowed here
+AttributeParsingErr.bpl(15,18): Error: only attributes, not triggers, allowed here
+AttributeParsingErr.bpl(20,26): Error: only attributes, not triggers, allowed here
+9 parse errors detected in AttributeParsingErr.bpl
+
+type {:sourcefile "test.ssc"} T;
+
+function {:source "test.scc"} f(int) returns (int);
+
+const {:description "The largest integer value"} unique MAXINT: int;
+
+axiom {:naming "MyFavoriteAxiom"} (forall i: int :: { f(i) } f(i) == i + 1);
+
+var {:description "memory"} $Heap: [ref,name]any;
+
+var {:sort_of_like_a_trigger (forall i: int :: true)} Bla: [ref,name]any;
+
+procedure {:use_impl 1} foo(x: int) returns (n: int);
+
+
+
+implementation {:id 1} foo(x: int) returns (n: int)
+{
+ block1:
+ return;
+}
+
+
+
+implementation {:id 2} foo(x: int) returns (n: int)
+{
+ block1:
+ return;
+}
+
+
+
+type ref;
+
+type any;
+
+type name;
+
+Boogie program verifier finished with 0 verified, 0 errors
+AttributeResolution.bpl(1,18): Error: undeclared identifier: foo
+AttributeResolution.bpl(3,18): Error: undeclared identifier: bar
+AttributeResolution.bpl(7,15): Error: undeclared identifier: qux
+AttributeResolution.bpl(7,41): Error: undeclared identifier: ij
+AttributeResolution.bpl(13,21): Error: undeclared identifier: bzzt
+AttributeResolution.bpl(15,20): Error: undeclared identifier: blt
+AttributeResolution.bpl(5,20): Error: undeclared identifier: baz
+AttributeResolution.bpl(9,18): Error: undeclared identifier: mux
+AttributeResolution.bpl(11,29): Error: undeclared identifier: fux
+9 name resolution errors detected in AttributeResolution.bpl
+
+function \true() returns (bool);
+
+type \procedure;
+
+procedure \old(any: \procedure) returns (\var: \procedure);
+
+
+
+implementation \old(any: \procedure) returns (\var: \procedure)
+{
+ var \modifies: \procedure;
+
+ \modifies := any;
+ \var := \modifies;
+}
+
+
+
+procedure qux(a: \procedure);
+
+
+
+implementation qux(a: \procedure)
+{
+ var \var: \procedure;
+ var x: bool;
+
+ call \var := \old(a);
+ x := \true();
+}
+
+
+
+Boogie program verifier finished with 0 verified, 0 errors
+
+Boogie program verifier finished with 0 verified, 0 errors
+MapsResolutionErrors.bpl(6,9): Error: type variable must occur in map arguments: b
+MapsResolutionErrors.bpl(20,10): Error: type variable must occur in procedure arguments: a
+2 name resolution errors detected in MapsResolutionErrors.bpl
+Orderings.bpl(12,20): Error: undeclared identifier: x
+Orderings.bpl(15,23): Error: c0 occurs more than once as parent
+Orderings.bpl(16,19): Error: constant cannot be its own parent
+Orderings.bpl(18,20): Error: the parent of a constant has to be a constant
+4 name resolution errors detected in Orderings.bpl
+BadQuantifier.bpl(3,15): syntax error: invalid QuantifierBody
+1 parse errors detected in BadQuantifier.bpl
+EmptyCallArgs.bpl(31,2): Error: type variable must occur in types of given arguments: a
+EmptyCallArgs.bpl(32,2): Error: type variable must occur in types of given arguments: a
+2 name resolution errors detected in EmptyCallArgs.bpl
diff --git a/Test/test0/Arrays0.bpl b/Test/test0/Arrays0.bpl
new file mode 100644
index 00000000..0098c4a8
--- /dev/null
+++ b/Test/test0/Arrays0.bpl
@@ -0,0 +1,3 @@
+var one: [int]int;
+var two: [int,int]int;
+var three: [int,int,int]int; // three's a crowd
diff --git a/Test/test0/Arrays1.bpl b/Test/test0/Arrays1.bpl
new file mode 100644
index 00000000..db12ecb3
--- /dev/null
+++ b/Test/test0/Arrays1.bpl
@@ -0,0 +1,16 @@
+var Q: [int,int][int]int;
+
+procedure P()
+{
+ var q: [int]int;
+
+ start:
+ // here's how to do it:
+ q := Q[5,8];
+ q[13] := 21;
+ Q[5,8] := q;
+
+ // not like this:
+ Q[5,8][13] := 21; // error: the updated array must be an identifier
+ return;
+}
diff --git a/Test/test0/AttributeParsing.bpl b/Test/test0/AttributeParsing.bpl
new file mode 100644
index 00000000..a6a8418b
--- /dev/null
+++ b/Test/test0/AttributeParsing.bpl
@@ -0,0 +1,25 @@
+type {:sourcefile "test.ssc"} T;
+
+function {:source "test.scc"} f(int) returns (int);
+
+const {:description "The largest integer value"} unique MAXINT: int;
+
+axiom {:naming "MyFavoriteAxiom"} (forall i: int :: {f(i)} f(i) == i+1);
+
+var {:description "memory"} $Heap: [ref, name]any;
+
+var {:sort_of_like_a_trigger (forall i: int :: true)} Bla: [ref, name]any;
+
+procedure {:use_impl 1} foo(x : int) returns(n : int);
+
+implementation {:id 1} foo(x : int) returns(n : int)
+{
+ block1: return;
+}
+
+implementation {:id 2} foo(x : int) returns(n : int)
+{
+ block1: return;
+}
+
+type ref, any, name;
diff --git a/Test/test0/AttributeParsingErr.bpl b/Test/test0/AttributeParsingErr.bpl
new file mode 100644
index 00000000..cdf8646f
--- /dev/null
+++ b/Test/test0/AttributeParsingErr.bpl
@@ -0,0 +1,23 @@
+type {:sourcefile "test.ssc"} {1} T;
+
+function {:source "test.scc"} {1} f(int) returns (int);
+
+const {:description "The largest integer value"} {1} unique MAXINT: int;
+
+axiom {:naming "MyFavoriteAxiom"} {1} (forall i: int :: {f(i)} f(i) == i+1);
+
+var {:description "memory"} {1} $Heap: [ref, name]any;
+
+var {(forall i: int :: true)} Bla: [ref, name]any;
+
+procedure {1} {:use_impl 1} foo(x : int) returns(n : int);
+
+implementation {1} {:id 1} foo(x : int) returns(n : int)
+{
+ block1: return;
+}
+
+implementation {:id 2} {1} foo(x : int) returns(n : int)
+{
+ block1: return;
+}
diff --git a/Test/test0/AttributeResolution.bpl b/Test/test0/AttributeResolution.bpl
new file mode 100644
index 00000000..c667b530
--- /dev/null
+++ b/Test/test0/AttributeResolution.bpl
@@ -0,0 +1,38 @@
+type {:sourcefile foo} T;
+
+function {:source bar} f(int) returns (int);
+
+const {:description baz} unique MAXINT: int;
+
+axiom {:naming qux} (forall i: int :: {f(ij)} f(i) == i+1);
+
+var {:description mux} $Heap: [ref, int]bool;
+
+var {:sort_of_like_a_trigger fux} Bla: [ref, int]bool;
+
+procedure {:use_impl bzzt} foo(x : int) returns(n : int);
+
+implementation {:id blt} foo(x : int) returns(n : int)
+{
+ block1: return;
+}
+
+// ------ and here are various correct things
+
+
+
+const {:Correct hux0 + F(hux1)} hux0: int;
+
+function {:Correct F(hux0) + hux1} F(int) returns (int);
+
+axiom {:Correct F(hux0 + hux1)} true;
+
+var {:Correct hux0*hux1} hux1: int;
+
+procedure {:Correct hux0 - hux1} P();
+
+implementation {:Correct hux0 + hux1} {:AlsoCorrect "hello"} P()
+{
+}
+
+type ref;
diff --git a/Test/test0/BadLabels0.bpl b/Test/test0/BadLabels0.bpl
new file mode 100644
index 00000000..89cf7a36
--- /dev/null
+++ b/Test/test0/BadLabels0.bpl
@@ -0,0 +1,13 @@
+procedure Dup(y: int)
+{
+ X:
+ X: // error: duplicate label
+ while (y < 100)
+ {
+ Y:
+ }
+ while (y < 1000)
+ {
+ Y: // error: duplicate label (labels must be unique in entire procedure body)
+ }
+}
diff --git a/Test/test0/BadLabels1.bpl b/Test/test0/BadLabels1.bpl
new file mode 100644
index 00000000..b4bb6948
--- /dev/null
+++ b/Test/test0/BadLabels1.bpl
@@ -0,0 +1,81 @@
+procedure P0()
+{
+ // these labels don't exist at all
+ goto X; // error: undefined label
+ goto Y; // error: undefined label
+}
+
+procedure P1(y: int)
+{
+ goto X; // error: label out of reach
+ while (y < 100)
+ {
+ X:
+ }
+
+ Q:
+ if (y == 102) {
+ A:
+ goto Q;
+ } else if (y == 104) {
+ B:
+ } else {
+ C:
+ goto K; // error: label out of reach
+ }
+
+ while (y < 1000)
+ {
+ K:
+ goto A; // error: label out of reach
+ if (y % 2 == 0) {
+ goto L;
+ M:
+ }
+ goto K, L;
+ L:
+ if (*) {
+ goto M; // error: label out of reach
+ }
+ }
+ goto B; // error: label out of reach
+}
+
+
+procedure Break(n: int)
+{
+ break; // error: break not inside a loop
+ if (*) {
+ break; // error: label-less break not inside a loop
+ }
+
+ A:
+ if (*) {
+ break A; // this is fine, since the break statement uses a label
+ }
+
+ B:
+ assert 2 <= n;
+ while (*) {
+ break B; // error: B does not label a loop
+ break;
+ C: while (*) { assert n < 100; }
+ break A; // error: A does not label a loop
+ break C; // error: A does not label an enclosing loop
+ F: break F; // error: F does not label an enclosing loop
+ }
+
+ D:
+ while (*) {
+ E:
+ while (*) {
+ if (*) {
+ break;
+ } else if (*) {
+ if (*) { break E; }
+ } else {
+ break D;
+ }
+ }
+ }
+}
diff --git a/Test/test0/BadQuantifier.bpl b/Test/test0/BadQuantifier.bpl
new file mode 100644
index 00000000..b06ab0d9
--- /dev/null
+++ b/Test/test0/BadQuantifier.bpl
@@ -0,0 +1,3 @@
+
+function f(int) returns (bool);
+axiom (forall int x :: f(x) <== x >= 0);
diff --git a/Test/test0/EmptyCallArgs.bpl b/Test/test0/EmptyCallArgs.bpl
new file mode 100644
index 00000000..eb1c43b7
--- /dev/null
+++ b/Test/test0/EmptyCallArgs.bpl
@@ -0,0 +1,33 @@
+type C;
+
+procedure P(x:int, y:bool) returns (z:C);
+procedure Q<a>(x:int, y:a) returns (z:a);
+
+procedure CallP() {
+ var x:int;
+ var y:bool;
+ var z:C;
+
+ call z := P(x, y);
+ call * := P(x, y);
+ call z := P(*, y);
+ call z := P(x, *);
+ call * := P(*, y);
+ call * := P(x, *);
+ call z := P(*, *);
+ call * := P(*, *);
+}
+
+procedure CallQ() {
+ var x:int;
+ var y:bool;
+ var z:bool;
+
+ call z := Q(x, y);
+ call * := Q(x, y);
+ call z := Q(*, y);
+ call z := Q(x, *);
+ call * := Q(*, y);
+ call * := Q(x, *); // problem: type parameter cannot be inferred
+ call * := Q(*, *); // problem: type parameter cannot be inferred
+} \ No newline at end of file
diff --git a/Test/test0/LargeLiterals0.bpl b/Test/test0/LargeLiterals0.bpl
new file mode 100644
index 00000000..be459bf5
--- /dev/null
+++ b/Test/test0/LargeLiterals0.bpl
@@ -0,0 +1,7 @@
+// Test to parse large integer literals
+
+axiom 1234567890987654321 == 1234567890987654321;
+
+function f(int) returns (int);
+
+axiom f(1234567890987654321) == 0;
diff --git a/Test/test0/LineParse.bpl b/Test/test0/LineParse.bpl
new file mode 100644
index 00000000..a64eed0b
--- /dev/null
+++ b/Test/test0/LineParse.bpl
@@ -0,0 +1,12 @@
+#line
+#line
+#line 0
+#line 0
+
+#dontknow what this is No, I don't well, it's an error is what it is
+
+#define ASSERT(x) {if (!(x)) { crash(); }} // error: A B C . txt(12,0)
+
+// this is line 5; an error occurs on line 6:
+ #line 10 // this is not even scanned like a pragma, because the # is not in column 0
+
diff --git a/Test/test0/LineResolve.bpl b/Test/test0/LineResolve.bpl
new file mode 100644
index 00000000..b0c578c7
--- /dev/null
+++ b/Test/test0/LineResolve.bpl
@@ -0,0 +1,38 @@
+procedure P() {
+var x: int;
+x :=
+
+ a+ // error: LineResolve.bpl(5,1)
+
+ b+ // error: LineResolve.bpl(7,2)
+#line 12
+c+ // error: LineResolve.bpl(12,0)
+ d+ // error: LineResolve.bpl(13,10)
+#line 12
+e+ // error: LineResolve.bpl(12,0)
+#line 2
+f+ // error: LineResolve.bpl(2,0)
+#line 1000
+#line 900
+g+ // error: LineResolve.bpl(900,0)
+
+#line 10 Abc.txt
+
+ h+ // error: Abc.txt(11,3)
+
+i+ // error: Abc.txt(13,0)
+#line 98
+
+j+ // error: Abc.txt(99,0)
+
+#line 103 c:\Users\leino\Documents\Programs\MyClass.ssc
+
+k+ // error: c:\Users\leino\Documents\Programs\MyClass.ssc(104,0)
+
+#line -58
+
+#line 12 A B C . txt
+l+ // error: A B C . txt(12,0)
+
+0;
+}
diff --git a/Test/test0/MapsResolutionErrors.bpl b/Test/test0/MapsResolutionErrors.bpl
new file mode 100644
index 00000000..d529cb9c
--- /dev/null
+++ b/Test/test0/MapsResolutionErrors.bpl
@@ -0,0 +1,28 @@
+
+var m: []int;
+var p: <a>[]a;
+
+type C _;
+var bad: <a,b>[]C a; // error: b is not used
+
+function F<a>(a, int) returns (bool) { true }
+
+type Set _;
+function EmptySet<a>() returns (Set a);
+function G<a>(a, int) returns (Set a) { EmptySet() }
+
+function H<a>(int) returns (Set a);
+
+function {:inline true} K<a>(int) returns (Set a)
+{ EmptySet() }
+
+
+procedure P<a>(x: int, y: bool) returns (z: int, w: bool); // error: "a" is not used
+
+procedure Q<a>(x: int, y: bool) returns (z: int, w: a);
+procedure R<a>(x: int, y: bool) returns (z: int, w: Set a);
+procedure S<a>(x: a, y: bool) returns (z: int, w: Set a);
+
+
+function K2<a>(int) returns (Set a) // now ok
+{ EmptySet() }
diff --git a/Test/test0/ModifiedBag.bpl b/Test/test0/ModifiedBag.bpl
new file mode 100644
index 00000000..09edbd12
--- /dev/null
+++ b/Test/test0/ModifiedBag.bpl
@@ -0,0 +1,371 @@
+// ----------- BEGIN PRELUDE
+type real;
+
+type elements;
+
+type name;
+
+const $CALL: name;
+
+const $REQ: name;
+
+const $ENS: name;
+
+const $PACK: name;
+
+const $UNPACK: name;
+
+const $HEAD: name;
+
+const $THROW: name;
+
+var $RefHeap: [ref, name]ref;
+
+var $IntHeap: [ref, name]int;
+
+var $RealHeap: [ref, name]real;
+
+var $BoolHeap: [ref, name]bool;
+
+var $ArrayHeap: [ref, name]elements;
+
+const $allocated: name;
+
+const $elements: name;
+
+function $ArrayLength(ref) returns (int);
+
+function $RefArrayGet(elements, int) returns (ref);
+
+function $RefArraySet(elements, int, ref) returns (elements);
+
+function $IntArrayGet(elements, int) returns (value: int);
+
+function $IntArraySet(elements, int, value: int) returns (elements);
+
+function $RealArrayGet(elements, int) returns (value: real);
+
+function $RealArraySet(elements, int, value: real) returns (elements);
+
+function $BoolArrayGet(elements, int) returns (value: bool);
+
+function $BoolArraySet(elements, int, value: bool) returns (elements);
+
+function $ArrayArrayGet(elements, int) returns (value: elements);
+
+function $ArrayArraySet(elements, int, value: elements) returns (elements);
+
+axiom (forall A: elements, i: int, x: ref :: $RefArrayGet($RefArraySet(A, i, x), i) == x);
+
+axiom (forall A: elements, i: int, j: int, x: ref :: i != j ==> $RefArrayGet($RefArraySet(A, i, x), j) == $RefArrayGet(A, j));
+
+axiom (forall A: elements, i: int, x: int :: $IntArrayGet($IntArraySet(A, i, x), i) == x);
+
+axiom (forall A: elements, i: int, j: int, x: int :: i != j ==> $IntArrayGet($IntArraySet(A, i, x), j) == $IntArrayGet(A, j));
+
+axiom (forall A: elements, i: int, x: real :: $RealArrayGet($RealArraySet(A, i, x), i) == x);
+
+axiom (forall A: elements, i: int, j: int, x: real :: i != j ==> $RealArrayGet($RealArraySet(A, i, x), j) == $RealArrayGet(A, j));
+
+axiom (forall A: elements, i: int, x: bool :: $BoolArrayGet($BoolArraySet(A, i, x), i) == x);
+
+axiom (forall A: elements, i: int, j: int, x: bool :: i != j ==> $BoolArrayGet($BoolArraySet(A, i, x), j) == $BoolArrayGet(A, j));
+
+axiom (forall A: elements, i: int, x: elements :: $ArrayArrayGet($ArrayArraySet(A, i, x), i) == x);
+
+axiom (forall A: elements, i: int, j: int, x: elements :: i != j ==> $ArrayArrayGet($ArrayArraySet(A, i, x), j) == $ArrayArrayGet(A, j));
+
+axiom (forall a: ref :: 0 <= $ArrayLength(a));
+
+function $typeof(ref) returns (name);
+
+function $BoolIs(bool, name) returns (bool);
+
+function $RealIs(real, name) returns (bool);
+
+function $IntIs(int, name) returns (bool);
+
+const System.Int16: name;
+
+const System.Int32: name;
+
+const System.Int64: name;
+
+const System.Int16.MinValue: int;
+
+const System.Int16.MaxValue: int;
+
+const System.Int32.MinValue: int;
+
+const System.Int32.MaxValue: int;
+
+const System.Int64.MinValue: int;
+
+const System.Int64.MaxValue: int;
+
+axiom System.Int64.MinValue < System.Int32.MinValue;
+
+axiom System.Int32.MinValue < System.Int16.MinValue;
+
+axiom System.Int16.MinValue < System.Int16.MaxValue;
+
+axiom System.Int16.MaxValue < System.Int32.MaxValue;
+
+axiom System.Int32.MaxValue < System.Int64.MaxValue;
+
+axiom (forall i: int :: $IntIs(i, System.Int16) <==> System.Int16.MinValue <= i && i <= System.Int16.MaxValue);
+
+axiom (forall i: int :: $IntIs(i, System.Int32) <==> System.Int32.MinValue <= i && i <= System.Int32.MaxValue);
+
+axiom (forall i: int :: $IntIs(i, System.Int64) <==> System.Int64.MinValue <= i && i <= System.Int64.MaxValue);
+
+function $RefIs(ref, name) returns (bool);
+
+axiom (forall o: ref, T: name :: $RefIs(o, T) <==> o == null || $typeof(o) <: T);
+
+axiom (forall o: ref, T: name :: $RefIs(o, $NotNull(T)) <==> o != null && $RefIs(o, T));
+
+axiom (forall a: ref, T: name, i: int, $ArrayHeap: [ref, name]elements :: $RefIs(a, $IntArray(T)) && a != null ==> $IntIs($IntArrayGet($ArrayHeap[a, $elements], i), T));
+
+axiom (forall a: ref, T: name, i: int, $ArrayHeap: [ref, name]elements :: $RefIs(a, $RealArray(T)) && a != null ==> $RealIs($RealArrayGet($ArrayHeap[a, $elements], i), T));
+
+axiom (forall a: ref, T: name, i: int, $ArrayHeap: [ref, name]elements :: $RefIs(a, $BoolArray(T)) && a != null ==> $BoolIs($BoolArrayGet($ArrayHeap[a, $elements], i), T));
+
+axiom (forall a: ref, T: name, i: int, $ArrayHeap: [ref, name]elements :: $RefIs(a, $RefArray(T)) && a != null ==> $RefIs($RefArrayGet($ArrayHeap[a, $elements], i), T));
+
+function $NotNull(name) returns (name);
+
+function $IntArray(name) returns (name);
+
+function $BoolArray(name) returns (name);
+
+function $RealArray(name) returns (name);
+
+function $RefArray(name) returns (name);
+// ----------- END PRELUDE
+const Bag.a: name;
+
+const Bag.n: name;
+
+const Bag: name;
+
+
+
+
+
+procedure Bag..ctor$(this: ref, initialElements$in: ref);
+
+
+
+
+
+
+procedure System.Object..ctor(this: ref);
+
+
+
+procedure System.Array.CopyTo$System.Array$System.Int32(this: ref, array$in: ref, index$in: int);
+
+
+
+procedure Bag..ctor$$System.Int32$System.Int32(this: ref, initialElements$in: ref, start$in: int, howMany$in: int);
+ requires 0 <= howMany$in;
+ requires start$in + howMany$in <= $ArrayLength(initialElements$in);
+ modifies $IntHeap, $RefHeap;
+
+
+
+implementation Bag..ctor$$System.Int32$System.Int32(this: ref, initialElements$in: ref, start$in: int, howMany$in: int)
+{
+ var initialElements: ref, start: int, howMany: int, stack0i: int, stack0o: ref, stack1i: int, stack2i: int;
+
+ entry:
+ assume $RefIs(this, $NotNull(Bag));
+ initialElements := initialElements$in;
+ assume $RefIs(initialElements, $NotNull($IntArray(System.Int32)));
+ start := start$in;
+ assume $IntIs(start, System.Int32);
+ howMany := howMany$in;
+ assume $IntIs(howMany, System.Int32);
+ goto block165;
+
+ block165:
+ call System.Object..ctor(this);
+ $IntHeap[this, Bag.n] := howMany;
+ stack0i := howMany;
+ havoc stack0o;
+ assume $BoolHeap[stack0o, $allocated] == true && $ArrayLength(stack0o) == stack0i;
+ $RefHeap[this, Bag.a] := stack0o;
+ stack0o := $RefHeap[this, Bag.a];
+ stack1i := 0;
+ stack2i := start + howMany;
+ call System.Array.Copy$System.Array$System.Int32$System.Array$System.Int32$System.Int32(initialElements, start, stack0o, stack1i, stack2i);
+ assert this != null;
+ assert 0 <= $IntHeap[this, Bag.n] && $IntHeap[this, Bag.n] <= $ArrayLength($RefHeap[this, Bag.a]);
+ return;
+}
+
+
+
+procedure System.Array.Copy$System.Array$System.Int32$System.Array$System.Int32$System.Int32(sourceArray$in: ref, sourceIndex$in: int, destinationArray$in: ref, destinationIndex$in: int, length$in: int);
+
+
+
+procedure Bag.Add$System.Int32(this: ref, x$in: int);
+ modifies $ArrayHeap, $IntHeap;
+
+
+
+implementation Bag.Add$System.Int32(this: ref, x$in: int)
+{
+ var x: int, stack0i: int, stack1o: ref, stack1i: int, stack0b: bool, stack0o: ref, stack2i: int, b: ref;
+
+ entry:
+ assume $RefIs(this, $NotNull(Bag));
+ x := x$in;
+ assume $IntIs(x, System.Int32);
+ assert this != null;
+ assume 0 <= $IntHeap[this, Bag.n] && $IntHeap[this, Bag.n] <= $ArrayLength($RefHeap[this, Bag.a]);
+ goto block205;
+
+ block205:
+ stack0i := $IntHeap[this, Bag.n];
+ stack1o := $RefHeap[this, Bag.a];
+ stack1i := $ArrayLength(stack1o);
+ stack1i := stack1i;
+ stack0b := stack0i != stack1i;
+ goto trueblock208, falseblock206;
+
+ trueblock208:
+ assume stack0b == true;
+assume false;
+// goto block208;
+return;
+
+ falseblock206:
+ assume stack0b == false;
+ goto block206;
+
+ block206:
+// assert label-([$PACK@0:3:4425:0], $IntHeap[this, Bag.n] <= 2 * $ArrayLength($RefHeap[this, Bag.a]));
+ stack0i := 2;
+ stack1o := $RefHeap[this, Bag.a];
+ stack1i := $ArrayLength(stack1o);
+ stack1i := stack1i;
+ stack0i := stack0i * stack1i;
+ stack0i := stack0i;
+ assert $IntHeap[this, Bag.n] <= stack0i;
+// havoc b;
+// assume $BoolHeap[b, $allocated] == true && $ArrayLength(b) == stack0i;
+// assert label-([$PACK@0:3:4427:0], $IntHeap[this, Bag.n] <= $ArrayLength(b));
+// stack0o := $RefHeap[this, Bag.a];
+// stack1i := 0;
+// call [$CALL@0:7:39:0] System.Array.CopyTo$System.Array$System.Int32(stack0o, b, stack1i);
+// $RefHeap[this, Bag.a] := b;
+// assert label-([$PACK@0:3:4428:0], $IntHeap[this, Bag.n] <= $ArrayLength($RefHeap[this, Bag.a]));
+// goto block208;
+ return;
+
+ block208:
+ stack0o := $RefHeap[this, Bag.a];
+ stack1i := $IntHeap[this, Bag.n];
+ $ArrayHeap[stack0o, $elements] := $IntArraySet($ArrayHeap[stack0o, $elements], stack1i, x);
+ stack0o := this;
+ stack1o := stack0o;
+ stack1i := $IntHeap[stack1o, Bag.n];
+ stack2i := 1;
+ stack1i := stack1i + stack2i;
+ $IntHeap[stack0o, Bag.n] := stack1i;
+ assert this != null;
+ assert 0 <= $IntHeap[this, Bag.n];
+ assert $IntHeap[this, Bag.n] <= $ArrayLength($RefHeap[this, Bag.a]);
+ return;
+
+}
+
+
+
+procedure Bag.ExtractMin(this: ref) returns ($result: int);
+ modifies $IntHeap, $ArrayHeap;
+
+
+
+implementation Bag.ExtractMin(this: ref) returns ($result: int)
+{
+ var m: int, mindex: int, i: int, stack0i: int, stack0b: bool, stack0o: ref, stack1o: ref, stack1i: int, stack2i: int, CS$00000003$00000000: int;
+
+ entry:
+ assume $RefIs(this, $NotNull(Bag));
+ assert this != null;
+ assume 0 <= $IntHeap[this, Bag.n] && $IntHeap[this, Bag.n] <= $ArrayLength($RefHeap[this, Bag.a]);
+ goto block282;
+
+ block282:
+ m := 2147483647;
+ mindex := 0;
+ i := 1;
+ goto block286;
+
+ block285:
+ stack0i := 1;
+ stack0i := i + stack0i;
+ i := stack0i;
+ goto block286;
+
+ block286:
+ stack0i := $IntHeap[this, Bag.n];
+ stack0b := i <= stack0i;
+ goto trueblock283, falseblock287;
+
+ trueblock283:
+ assume stack0b == true;
+ goto block283;
+
+ falseblock287:
+ assume stack0b == false;
+ goto block287;
+
+ block283:
+ stack0o := $RefHeap[this, Bag.a];
+ stack0i := $IntArrayGet($ArrayHeap[stack0o, $elements], i);
+ stack0b := stack0i >= m;
+ goto trueblock285, falseblock284;
+
+ block287:
+ stack0o := this;
+ stack1o := stack0o;
+ stack1i := $IntHeap[stack1o, Bag.n];
+ stack2i := 1;
+ stack1i := stack1i - stack2i;
+ $IntHeap[stack0o, Bag.n] := stack1i;
+ stack0o := $RefHeap[this, Bag.a];
+ stack1o := $RefHeap[this, Bag.a];
+ stack2i := $IntHeap[this, Bag.n];
+ stack1i := $IntArrayGet($ArrayHeap[stack1o, $elements], stack2i);
+ $ArrayHeap[stack0o, $elements] := $IntArraySet($ArrayHeap[stack0o, $elements], mindex, stack1i);
+ CS$00000003$00000000 := m;
+ goto block289;
+
+ trueblock285:
+ assume stack0b == true;
+ goto block285;
+
+ falseblock284:
+ assume stack0b == false;
+ goto block284;
+
+ block284:
+ mindex := i;
+ stack0o := $RefHeap[this, Bag.a];
+ m := $IntArrayGet($ArrayHeap[stack0o, $elements], i);
+ goto block285;
+
+ block289:
+ $result := CS$00000003$00000000;
+ assert this != null;
+ assert 0 <= $IntHeap[this, Bag.n] && $IntHeap[this, Bag.n] <= $ArrayLength($RefHeap[this, Bag.a]);
+ return;
+}
+
+type ref;
+const null : ref;
diff --git a/Test/test0/Orderings.bpl b/Test/test0/Orderings.bpl
new file mode 100644
index 00000000..0ba6c69c
--- /dev/null
+++ b/Test/test0/Orderings.bpl
@@ -0,0 +1,20 @@
+
+type C;
+
+const c:int extends a;
+const d:int extends a complete;
+const e:int extends unique a, b;
+const f:int extends complete;
+
+const a:int;
+const b:int;
+
+const g:int extends x; // error: undeclared parent
+
+const c0:C;
+const c1:C extends c0, c0; // error: parent mentioned twice
+const c2:C extends c2; // error: constant as its own parent
+
+const h:int extends y; // error: variable cannot be parent
+
+var y:int; \ No newline at end of file
diff --git a/Test/test0/Output b/Test/test0/Output
new file mode 100644
index 00000000..e8ea231e
--- /dev/null
+++ b/Test/test0/Output
@@ -0,0 +1,252 @@
+
+Boogie program verifier finished with 0 verified, 0 errors
+
+Boogie program verifier finished with 0 verified, 0 errors
+Triggers0.bpl(14,31): Error: the 'nopats' quantifier attribute expects a string-literal parameter
+1 parse errors detected in Triggers0.bpl
+Triggers1.bpl(7,17): Error: boolean operators are not allowed in triggers
+Triggers1.bpl(11,21): Error: boolean operators are not allowed in triggers
+Triggers1.bpl(15,9): Error: boolean operators are not allowed in triggers
+Triggers1.bpl(19,10): Error: boolean operators are not allowed in triggers
+Triggers1.bpl(23,17): Error: boolean operators are not allowed in triggers
+Triggers1.bpl(27,17): Error: boolean operators are not allowed in triggers
+Triggers1.bpl(32,17): Error: equality is not allowed in triggers
+Triggers1.bpl(36,17): Error: arithmetic comparisons are not allowed in triggers
+Triggers1.bpl(45,10): Error: quantifiers are not allowed in triggers
+Triggers1.bpl(53,7): Error: trigger must mention all quantified variables, but does not mention: x
+Triggers1.bpl(61,7): Error: trigger must mention all quantified variables, but does not mention: y
+Triggers1.bpl(62,7): Error: trigger must mention all quantified variables, but does not mention: x
+Triggers1.bpl(70,9): Error: a matching pattern must be more than just a variable by itself: x
+Triggers1.bpl(82,7): Error: trigger must mention all quantified variables, but does not mention: z
+Triggers1.bpl(94,16): Error: a matching pattern must be more than just a variable by itself: x
+Triggers1.bpl(95,16): Error: a matching pattern must be more than just a variable by itself: g
+Triggers1.bpl(105,40): Error: trigger must mention all quantified variables, but does not mention: y
+Triggers1.bpl(106,40): Error: trigger must mention all quantified variables, but does not mention: x
+Triggers1.bpl(109,57): Error: trigger must mention all quantified variables, but does not mention: z
+Triggers1.bpl(110,57): Error: trigger must mention all quantified variables, but does not mention: y
+Triggers1.bpl(111,57): Error: trigger must mention all quantified variables, but does not mention: x
+Triggers1.bpl(119,33): Error: cannot refer to a global variable in this context: h1
+Triggers1.bpl(120,33): Error: cannot refer to a global variable in this context: h0
+23 name resolution errors detected in Triggers1.bpl
+const x: int;
+
+const y: int;
+
+const z: int;
+
+const P: bool;
+
+const Q: bool;
+
+const R: bool;
+
+axiom x * (y + z) == x + y * z;
+
+axiom x * y + z == (x + y) * z;
+
+axiom x * y * z == x * y * z;
+
+axiom x * y * z * x == x * y * z;
+
+axiom x / y / z == x / (y / z);
+
+axiom x / y / (z / x) == x / y / z;
+
+axiom x - y - z == x - (y - z);
+
+axiom x - y - (z - x) == x - y - z;
+
+axiom x + y - z - x + y == 0;
+
+axiom x + y - z - x + y == x + y - (z - (x + y));
+
+axiom P ==> Q ==> R <==> P ==> Q ==> R;
+
+axiom (P ==> Q) ==> R ==> P <==> (P ==> Q) ==> R;
+
+axiom P <==> Q <==> R;
+
+axiom P ==> Q <==> Q ==> R <==> R ==> P;
+
+axiom (P && Q) || (Q && R);
+
+axiom (P || Q) && (Q || R);
+
+axiom P || Q || Q || R;
+
+axiom P && Q && Q && R;
+
+function f(int) returns (int);
+
+axiom (forall x: int :: {:xname "hello"} {:weight 5} {:ValueFunc f(x + 1)} { f(x + x) } { f(x) * f(x) } {:nopats f(x + x + x) } f(f(x)) < 200);
+
+Boogie program verifier finished with 0 verified, 0 errors
+
+Boogie program verifier finished with 0 verified, 0 errors
+Arrays1.bpl(11,11): Error: command assigns to a global variable that is not in the enclosing method's modifies clause: Q
+Arrays1.bpl(14,15): Error: command assigns to a global variable that is not in the enclosing method's modifies clause: Q
+2 type checking errors detected in Arrays1.bpl
+Types0.bpl(6,18): Error: expected identifier before ':'
+1 parse errors detected in Types0.bpl
+Types1.bpl(6,11): Error: undeclared type: x
+Types1.bpl(7,18): Error: undeclared type: x
+2 name resolution errors detected in Types1.bpl
+WhereParsing.bpl(14,37): Error: where clause not allowed here
+WhereParsing.bpl(15,33): Error: where clause not allowed here
+2 parse errors detected in WhereParsing.bpl
+WhereParsing0.bpl(17,38): Error: where clause not allowed here
+WhereParsing0.bpl(18,38): Error: where clause not allowed here
+2 parse errors detected in WhereParsing0.bpl
+WhereParsing1.bpl(14,27): syntax error: ) expected
+1 parse errors detected in WhereParsing1.bpl
+WhereParsing2.bpl(1,14): syntax error: ; expected
+1 parse errors detected in WhereParsing2.bpl
+WhereResolution.bpl(28,38): Error: undeclared identifier: alpha
+WhereResolution.bpl(32,30): Error: old expressions allowed only in two-state contexts
+2 name resolution errors detected in WhereResolution.bpl
+BadLabels0.bpl(4,2): Error: more than one declaration of block name: X
+BadLabels0.bpl(11,4): Error: more than one declaration of block name: Y
+2 name resolution errors detected in BadLabels0.bpl
+BadLabels1.bpl(4,3): Error: Error: goto label 'X' is undefined or out of reach
+BadLabels1.bpl(5,3): Error: Error: goto label 'Y' is undefined or out of reach
+BadLabels1.bpl(10,3): Error: Error: goto label 'X' is undefined or out of reach
+BadLabels1.bpl(24,5): Error: Error: goto label 'K' is undefined or out of reach
+BadLabels1.bpl(30,5): Error: Error: goto label 'A' is undefined or out of reach
+BadLabels1.bpl(38,7): Error: Error: goto label 'M' is undefined or out of reach
+BadLabels1.bpl(41,3): Error: Error: goto label 'B' is undefined or out of reach
+BadLabels1.bpl(47,3): Error: Error: break statement is not inside a loop
+BadLabels1.bpl(49,5): Error: Error: break statement is not inside a loop
+BadLabels1.bpl(60,5): Error: Error: break label 'B' must designate an enclosing statement
+BadLabels1.bpl(63,5): Error: Error: break label 'A' must designate an enclosing statement
+BadLabels1.bpl(64,5): Error: Error: break label 'C' must designate an enclosing statement
+BadLabels1.bpl(65,8): Error: Error: break label 'F' must designate an enclosing statement
+13 parse errors detected in BadLabels1.bpl
+LineParse.bpl(1,0): Error: Malformed (#line num [filename]) pragma: #line
+LineParse.bpl(2,0): Error: Malformed (#line num [filename]) pragma: #line
+LineParse.bpl(1,0): Error: Unrecognized pragma: #dontknow what this is No, I don't well, it's an error is what it is
+LineParse.bpl(3,0): Error: Unrecognized pragma: #define ASSERT(x) {if (!(x)) { crash(); }} // error: A B C . txt(12,0)
+LineParse.bpl(6,2): syntax error: EOF expected
+5 parse errors detected in LineParse.bpl
+LineResolve.bpl(5,1): Error: undeclared identifier: a
+LineResolve.bpl(7,2): Error: undeclared identifier: b
+LineResolve.bpl(12,0): Error: undeclared identifier: c
+LineResolve.bpl(13,10): Error: undeclared identifier: d
+LineResolve.bpl(12,0): Error: undeclared identifier: e
+LineResolve.bpl(2,0): Error: undeclared identifier: f
+LineResolve.bpl(900,0): Error: undeclared identifier: g
+Abc.txt(11,3): Error: undeclared identifier: h
+Abc.txt(13,0): Error: undeclared identifier: i
+Abc.txt(99,0): Error: undeclared identifier: j
+c:\Users\leino\Documents\Programs\MyClass.ssc(104,0): Error: undeclared identifier: k
+A B C . txt(12,0): Error: undeclared identifier: l
+12 name resolution errors detected in LineResolve.bpl
+AttributeParsingErr.bpl(1,33): Error: only attributes, not triggers, allowed here
+AttributeParsingErr.bpl(3,33): Error: only attributes, not triggers, allowed here
+AttributeParsingErr.bpl(5,52): Error: only attributes, not triggers, allowed here
+AttributeParsingErr.bpl(7,37): Error: only attributes, not triggers, allowed here
+AttributeParsingErr.bpl(9,31): Error: only attributes, not triggers, allowed here
+AttributeParsingErr.bpl(11,29): Error: only attributes, not triggers, allowed here
+AttributeParsingErr.bpl(13,13): Error: only attributes, not triggers, allowed here
+AttributeParsingErr.bpl(15,18): Error: only attributes, not triggers, allowed here
+AttributeParsingErr.bpl(20,26): Error: only attributes, not triggers, allowed here
+9 parse errors detected in AttributeParsingErr.bpl
+
+type {:sourcefile "test.ssc"} T;
+
+function {:source "test.scc"} f(int) returns (int);
+
+const {:description "The largest integer value"} unique MAXINT: int;
+
+axiom {:naming "MyFavoriteAxiom"} (forall i: int :: { f(i) } f(i) == i + 1);
+
+var {:description "memory"} $Heap: [ref,name]any;
+
+var {:sort_of_like_a_trigger (forall i: int :: true)} Bla: [ref,name]any;
+
+procedure {:use_impl 1} foo(x: int) returns (n: int);
+
+
+
+implementation {:id 1} foo(x: int) returns (n: int)
+{
+ block1:
+ return;
+}
+
+
+
+implementation {:id 2} foo(x: int) returns (n: int)
+{
+ block1:
+ return;
+}
+
+
+
+type ref;
+
+type any;
+
+type name;
+
+Boogie program verifier finished with 0 verified, 0 errors
+AttributeResolution.bpl(1,18): Error: undeclared identifier: foo
+AttributeResolution.bpl(3,18): Error: undeclared identifier: bar
+AttributeResolution.bpl(7,15): Error: undeclared identifier: qux
+AttributeResolution.bpl(7,41): Error: undeclared identifier: ij
+AttributeResolution.bpl(13,21): Error: undeclared identifier: bzzt
+AttributeResolution.bpl(15,20): Error: undeclared identifier: blt
+AttributeResolution.bpl(5,20): Error: undeclared identifier: baz
+AttributeResolution.bpl(9,18): Error: undeclared identifier: mux
+AttributeResolution.bpl(11,29): Error: undeclared identifier: fux
+9 name resolution errors detected in AttributeResolution.bpl
+
+function \true() returns (bool);
+
+type \procedure;
+
+procedure \old(any: \procedure) returns (\var: \procedure);
+
+
+
+implementation \old(any: \procedure) returns (\var: \procedure)
+{
+ var \modifies: \procedure;
+
+ \modifies := any;
+ \var := \modifies;
+}
+
+
+
+procedure qux(a: \procedure);
+
+
+
+implementation qux(a: \procedure)
+{
+ var \var: \procedure;
+ var x: bool;
+
+ call \var := \old(a);
+ x := \true();
+}
+
+
+
+Boogie program verifier finished with 0 verified, 0 errors
+
+Boogie program verifier finished with 0 verified, 0 errors
+MapsResolutionErrors.bpl(6,9): Error: type variable must occur in map arguments: b
+MapsResolutionErrors.bpl(20,10): Error: type variable must occur in procedure arguments: a
+2 name resolution errors detected in MapsResolutionErrors.bpl
+Orderings.bpl(12,20): Error: undeclared identifier: x
+Orderings.bpl(15,23): Error: c0 occurs more than once as parent
+Orderings.bpl(16,19): Error: constant cannot be its own parent
+Orderings.bpl(18,20): Error: the parent of a constant has to be a constant
+4 name resolution errors detected in Orderings.bpl
+BadQuantifier.bpl(3,15): syntax error: invalid QuantifierBody
+1 parse errors detected in BadQuantifier.bpl
+EmptyCallArgs.bpl(31,2): Error: type variable must occur in types of given arguments: a
+EmptyCallArgs.bpl(32,2): Error: type variable must occur in types of given arguments: a
+2 name resolution errors detected in EmptyCallArgs.bpl
diff --git a/Test/test0/PrettyPrint.bpl b/Test/test0/PrettyPrint.bpl
new file mode 100644
index 00000000..a1f941d8
--- /dev/null
+++ b/Test/test0/PrettyPrint.bpl
@@ -0,0 +1,40 @@
+const x: int;
+const y: int;
+const z: int;
+const P: bool;
+const Q: bool;
+const R: bool;
+
+axiom x * (y + z) == x + (y * z);
+axiom (x * y) + z == (x + y) * z;
+
+axiom x * y * z == (x * (y * z));
+axiom (x * y) * (z * x) == (x * y) * z;
+
+axiom x / y / z == (x / (y / z));
+axiom (x / y) / (z / x) == (x / y) / z;
+
+axiom x - y - z == (x - (y - z));
+axiom (x - y) - (z - x) == (x - y) - z;
+
+axiom x + y - z - x + y == 0;
+axiom ((((x + y) - z) - x) + y) == (x + (y - (z - (x + y))));
+
+axiom P ==> Q ==> R <==> (P ==> (Q ==> R));
+axiom ((P ==> Q) ==> (R ==> P)) == ((P ==> Q) ==> R);
+
+axiom P <==> Q <==> R;
+axiom P ==> Q <==> Q ==> R <==> R ==> P;
+
+axiom (P && Q) || (Q && R);
+axiom (P || Q) && (Q || R);
+axiom (P || Q) || (Q || R);
+axiom (P && Q) && (Q && R);
+
+// -------------- quantifier key-value decorations
+
+function f(int) returns (int);
+
+axiom (forall x: int :: {:xname "hello"}
+ { :weight 5} {f(x+x)} {:ValueFunc f(x+1) } {f(x)*f(x)} {:nopats f(x+x+x)}
+ f(f(x)) < 200);
diff --git a/Test/test0/Prog0.bpl b/Test/test0/Prog0.bpl
new file mode 100644
index 00000000..ac87476f
--- /dev/null
+++ b/Test/test0/Prog0.bpl
@@ -0,0 +1,51 @@
+// BoogiePL Examples
+type real;
+type elements;
+
+var x:int; var y:real; var z:ref; // Variables
+var x.3:bool; var $ar:ref; // Names can have glyphs
+
+const a, b, c:int; // Consts
+
+function f (int, int) returns (int); // Function with arity 2
+function g ( int , int) returns (int); // Function with arity 2
+function h(int,int) returns (int); // Function with arity 2
+
+function m (int) returns (int); // Function with arity 1
+function k(int) returns (int); // Function with arity 1
+
+
+axiom
+ (forall x : int :: f(g(h(a,b),c),x) > 100) ;
+
+procedure p (x:int, y:ref) returns (z:int, w:[int,ref]ref, q:int);
+
+
+procedure q(x:int, y:ref) returns (z:int) // Procedure with output params
+ requires x > 0; // as many req/ens/mod you want
+ ensures z > 3;
+ ensures old(x) == 1; // old only in ensures..
+ modifies z,y,$ar;
+{
+ var t, s: int;
+ var r: [int,ref]ref;
+
+ start: // one label per block
+ t := x;
+ s := t;
+ z := x + t;
+ call s, r,z := p(t,r[3,null]); // procedure call with mutiple returns
+ goto continue, end ; // as many labels as you like
+
+ continue:
+ return; // ends control flow
+
+ end:
+ goto start;
+}
+
+procedure s(e: elements) { L: return; }
+procedure r (x:int, y:ref) returns (z:int);
+
+type ref;
+const null : ref;
diff --git a/Test/test0/Quoting.bpl b/Test/test0/Quoting.bpl
new file mode 100644
index 00000000..eaf8fe7a
--- /dev/null
+++ b/Test/test0/Quoting.bpl
@@ -0,0 +1,16 @@
+function \true() returns(bool);
+
+type \procedure;
+procedure \old(\any : \procedure) returns(\var : \procedure)
+{
+ var \modifies : \procedure;
+ \modifies := \any;
+ \var := \modifies;
+}
+
+procedure qux(a : \procedure)
+{
+ var \var : \procedure; var x : bool;
+ call \var := \old(a);
+ x := \true();
+}
diff --git a/Test/test0/Triggers0.bpl b/Test/test0/Triggers0.bpl
new file mode 100644
index 00000000..6750d77d
--- /dev/null
+++ b/Test/test0/Triggers0.bpl
@@ -0,0 +1,15 @@
+// Trigger errors
+
+function f(int, int) returns (int);
+function P(int, int) returns (bool);
+
+// -------------- tests specific to pattern exclusions
+
+axiom (forall x: int ::
+ {:nopats f(x,10) }
+ { : nopats f(x,10) }
+ f(x,10) == 3);
+
+axiom (forall x: int ::
+ {:nopats f(x,10), f(x,x) } // error: a pattern exclusion can only mention one expression
+ f(x,10) == 3);
diff --git a/Test/test0/Triggers1.bpl b/Test/test0/Triggers1.bpl
new file mode 100644
index 00000000..02c63406
--- /dev/null
+++ b/Test/test0/Triggers1.bpl
@@ -0,0 +1,127 @@
+// Trigger errors
+
+function f(int, int) returns (int);
+function P(int, int) returns (bool);
+
+axiom (forall x: int ::
+ { f(x,10) && f(x,9) } // error: && not allowed
+ f(x,10) == 3);
+
+axiom (forall x: int ::
+ { ((((f(x,10) || f(x,9))))) } // error: || not allowed
+ f(x,10) == 3);
+
+axiom (forall x: int ::
+ { !f(x,10) } // error: ! not allowed
+ f(x,10) == 3);
+
+axiom (forall x: int ::
+ { (!f(x,10)) } // error: ! not allowed
+ f(x,10) == 3);
+
+axiom (forall x: int ::
+ { P(x,10) ==> P(20,x) } // error: ==> not allowed
+ f(x,10) == 3);
+
+axiom (forall x: int ::
+ { P(x,10) <==> P(20,x) } // error: <==> not allowed
+ f(x,10) == 3);
+
+
+axiom (forall x: int ::
+ { f(x,10) == 3 } // error: == not allowed
+ f(x,10) == 3);
+
+axiom (forall x: int ::
+ { f(x,10) < 3 } // error: < not allowed
+ f(x,10) == 3);
+
+
+axiom (forall x: int ::
+ { f(x,10) + f(x,x) != 3 } // yes, != is allowed
+ f(x,10) == 3);
+
+axiom (forall b: bool ::
+ { (forall y: int :: b) } // error: quantifiers not allowed
+ b);
+
+// -------------- tests of free variables
+
+const g: int;
+
+axiom (forall x: int ::
+ { false, 6 } // error: does not mention "x"
+ x < x + 1);
+
+axiom (forall x: int ::
+ { false, x+1, 6 } // allowed
+ x < x + 1);
+
+axiom (forall x: int, y: int ::
+ { x+1 } // error: does not mention "y"
+ { y+1 } // error: does not mention "x"
+ x < y + 1);
+
+axiom (forall x: int ::
+ { g+x != 65 } // allowed
+ x < x + 1);
+
+axiom (forall x: int ::
+ { x } // "x" by itself is not a good trigger
+ x < x + 1);
+
+//axiom (forall x: any :: // PR: removed for the time being
+// { cast(x,int) } // can't fool me, still not allowed
+// x == x );
+
+// --- multiple triggers
+
+axiom (forall x: int, y: int, z: int ::
+ { x+y+z } // good
+ { x+y, y+z } // also good
+ { f(f(x,y),y) } // error: does not mention z
+ x == x );
+
+// --- multi-triggers
+
+axiom (forall x: int, y: int, z: int ::
+ { f(x,x), f(y,y), f(z,z) } // good
+ f(x,y) < f(y,z) );
+
+// --- pattern exclusion
+
+axiom (forall x: int, y: int ::
+ {:nopats x } // error: "x" by itself is not allowed here either
+ {:nopats g } // error: "g" by itself is not allowed here either
+ x < y);
+
+axiom (forall x: int, y: int ::
+ {:nopats f(g,g) } // but it is okay not to mention the bound variables (in a pattern exclusion)
+ x < y);
+
+// --- merging of nested quantifiers
+
+axiom (forall x:int :: (forall y:int :: { f(x,y) } f(x,y) > 0)); // OK
+axiom (forall x:int :: (forall y:int :: { f(x,x) } f(x,x) > 0)); // error
+axiom (forall x:int :: (forall y:int :: { f(y,y) } f(y,y) > 0)); // error
+
+// three levels
+axiom (forall x:int :: (forall y:int :: (forall z:int :: { f(x,y) } f(y,y) > 0))); // error
+axiom (forall x:int :: (forall y:int :: (forall z:int :: { f(x,z) } f(y,y) > 0))); // error
+axiom (forall x:int :: (forall y:int :: (forall z:int :: { f(y,z) } f(y,y) > 0))); // error
+axiom (forall x:int :: (forall y:int :: (forall z:int :: { f(x,y), f(y,z) } f(y,y) > 0))); // OK
+
+// --- no free variables
+
+var h0: int;
+var h1: [ref,ref]int;
+
+axiom (forall o: ref, f: ref :: h1[o,f] // error: cannot mention free variable "h1"
+ < h0); // error: cannot mention free variable "h0"
+
+const c0: int;
+const c1: [ref,ref]int;
+
+axiom (forall o: ref, f: ref :: c1[o,f] < c0);
+
+type ref;
diff --git a/Test/test0/Types0.bpl b/Test/test0/Types0.bpl
new file mode 100644
index 00000000..7bb1dcef
--- /dev/null
+++ b/Test/test0/Types0.bpl
@@ -0,0 +1,8 @@
+type T, U;
+type V;
+
+function f([U,V]T, int) returns (U);
+function g(x: [U,V]T, y: int) returns (z: U);
+function h([U,V]T: int, y: int) returns (z: U); // parse error
+function k(T: int, y: int) returns (U: [any]int);
+function l(x) returns (int); // resolve error
diff --git a/Test/test0/Types1.bpl b/Test/test0/Types1.bpl
new file mode 100644
index 00000000..f743be85
--- /dev/null
+++ b/Test/test0/Types1.bpl
@@ -0,0 +1,7 @@
+type T, U;
+type V;
+
+function h(T) returns (int);
+function k(x:T) returns (int);
+function l(x) returns (int); // resolve error
+function m(x:int, x) returns (bool); // resolve error
diff --git a/Test/test0/WhereParsing.bpl b/Test/test0/WhereParsing.bpl
new file mode 100644
index 00000000..ec18dc3b
--- /dev/null
+++ b/Test/test0/WhereParsing.bpl
@@ -0,0 +1,25 @@
+const x: int;
+
+function R(int) returns (bool);
+function Even(int) returns (bool);
+
+var y: int where R(y);
+var g: int where g == 12;
+
+procedure P(x: int where x > 0) returns (y: int where y < 0);
+ requires x < 100;
+ modifies g;
+ ensures -100 < y;
+
+implementation P(xx: int where xx > 0) // error: where not allowed in implementation decl
+ returns (yy: int where yy < 0) // error: where not allowed in implementation decl
+{
+ var a: int where a == b; // b is not allowed to be mentioned here, but this test is only
+ var b: int; // for parsing, so no complaint will be issued
+
+ start:
+ a := xx;
+ call b := P(a);
+ yy := b;
+ return;
+}
diff --git a/Test/test0/WhereParsing0.bpl b/Test/test0/WhereParsing0.bpl
new file mode 100644
index 00000000..84f92741
--- /dev/null
+++ b/Test/test0/WhereParsing0.bpl
@@ -0,0 +1,28 @@
+const x: int;
+
+function R(int) returns (bool);
+function Even(int) returns (bool);
+
+var y: int where R(y);
+var g: int where g == 12;
+
+procedure P(x: int where x > 0) returns (y: int where y < 0);
+ requires x < 100;
+ modifies g;
+ ensures -100 < y;
+
+procedure Q(x: int where x > 0) returns (y: int where y < 0)
+ requires x < 100;
+ modifies g;
+ ensures (forall t: int where Even(t) :: -100 < y + t) || // error: where not allowed in quant
+ (exists t: int where Even(t) :: -100 < y + t); // error: where not allowed in quant
+{
+ var a: int;
+ var b: int;
+
+ start:
+ a := x;
+ call b := P(a);
+ y := b;
+ return;
+}
diff --git a/Test/test0/WhereParsing1.bpl b/Test/test0/WhereParsing1.bpl
new file mode 100644
index 00000000..402071bf
--- /dev/null
+++ b/Test/test0/WhereParsing1.bpl
@@ -0,0 +1,15 @@
+const x: int;
+
+function R(int) returns (bool);
+function Even(int) returns (bool);
+
+var y: int where R(y);
+var g: int where g == 12;
+
+procedure P(x: int where x > 0) returns (y: int where y < 0);
+ requires x < 100;
+ modifies g;
+ ensures -100 < y;
+
+function f(a: int, b: int where b < 0) // error: where not allowed among function parameters
+ returns (bool);
diff --git a/Test/test0/WhereParsing2.bpl b/Test/test0/WhereParsing2.bpl
new file mode 100644
index 00000000..d85287f3
--- /dev/null
+++ b/Test/test0/WhereParsing2.bpl
@@ -0,0 +1,2 @@
+const x: int where x < 0; // error: where clauses not allowed on constants
+
diff --git a/Test/test0/WhereResolution.bpl b/Test/test0/WhereResolution.bpl
new file mode 100644
index 00000000..6b28a035
--- /dev/null
+++ b/Test/test0/WhereResolution.bpl
@@ -0,0 +1,62 @@
+type double;
+
+function R(int) returns (bool);
+function K(double, bool) returns (bool);
+
+var y: int where R(y);
+var g: int where h ==> g == 12;
+var h: bool where g < 100;
+var k: double where K(k, h);
+
+procedure P(x: int where x > 0) returns (y: int where y < 0);
+ requires x < 100;
+ modifies g;
+ ensures -100 < y;
+
+implementation P(xx: int) returns (yy: int)
+{
+ var a: int where a == 10;
+ var b: int where a == b && b < g;
+
+ start:
+ a := xx;
+ call b := P(a);
+ yy := b;
+ return;
+}
+
+procedure Q(w: int where x < w || x > alpha/*error: out-parameter alpha is not in scope*/, x: int where x + w > 0)
+ returns (v: bool where v,
+ y: int where x + y + z < 0,
+ z: int where g == 12,
+ alpha: ref where old(alpha) != null, // error: cannot use old in where clause
+ beta: ref where (forall r: ref :: r == beta ==> beta == null))
+ requires x < 100;
+ modifies g;
+ ensures -100 < y;
+{
+ var a: int;
+ var b: int;
+
+ start:
+ a := x;
+ call b := P(a);
+ y := b;
+ return;
+}
+
+const SomeConstant: ref;
+
+procedure Cnst(n: ref where n != SomeConstant) returns (SomeConstant: int)
+{
+ var m: ref where m != SomeConstant;
+ var k: int where k != SomeConstant;
+ var r: ref where (forall abc: ref :: abc == SomeConstant);
+ var b: bool;
+ start:
+ b := (forall l: ref :: l == SomeConstant);
+ return;
+}
+
+type ref;
+const null : ref;
diff --git a/Test/test0/runtest.bat b/Test/test0/runtest.bat
new file mode 100644
index 00000000..c7c6ee3d
--- /dev/null
+++ b/Test/test0/runtest.bat
@@ -0,0 +1,33 @@
+@echo off
+setlocal
+
+set BGEXE=..\..\Binaries\Boogie.exe
+rem set BGEXE=mono ..\..\Binaries\Boogie.exe
+
+%BGEXE% %* /noVerify Prog0.bpl
+%BGEXE% %* /noVerify ModifiedBag.bpl
+%BGEXE% %* /noVerify Triggers0.bpl
+%BGEXE% %* /noVerify Triggers1.bpl
+%BGEXE% %* /noVerify /printInstrumented PrettyPrint.bpl
+%BGEXE% %* /noVerify Arrays0.bpl
+%BGEXE% %* /noVerify Arrays1.bpl
+%BGEXE% %* /noVerify Types0.bpl
+%BGEXE% %* /noVerify Types1.bpl
+%BGEXE% %* /noVerify WhereParsing.bpl
+%BGEXE% %* /noVerify WhereParsing0.bpl
+%BGEXE% %* /noVerify WhereParsing1.bpl
+%BGEXE% %* /noVerify WhereParsing2.bpl
+%BGEXE% %* /noVerify WhereResolution.bpl
+%BGEXE% %* /noVerify BadLabels0.bpl
+%BGEXE% %* /noVerify BadLabels1.bpl
+%BGEXE% %* /noVerify LineParse.bpl
+%BGEXE% %* /noVerify LineResolve.bpl
+%BGEXE% %* /noVerify AttributeParsingErr.bpl
+%BGEXE% %* /noVerify /print:- /env:0 AttributeParsing.bpl
+%BGEXE% %* /noVerify AttributeResolution.bpl
+%BGEXE% %* /noVerify /print:- /env:0 Quoting.bpl
+%BGEXE% %* /noVerify LargeLiterals0.bpl
+%BGEXE% %* /noVerify MapsResolutionErrors.bpl
+%BGEXE% %* /noVerify Orderings.bpl
+%BGEXE% %* /noVerify BadQuantifier.bpl
+%BGEXE% %* /noVerify EmptyCallArgs.bpl
diff --git a/Test/test1/Answer b/Test/test1/Answer
new file mode 100644
index 00000000..b0f4aac3
--- /dev/null
+++ b/Test/test1/Answer
@@ -0,0 +1,137 @@
+Frame0.bpl(10,11): Error: undeclared identifier: a
+Frame0.bpl(12,11): Error: undeclared identifier: b
+2 name resolution errors detected in Frame0.bpl
+Frame1.bpl(16,7): Error: command assigns to a global variable that is not in the enclosing method's modifies clause: g1
+Frame1.bpl(17,6): Error: command assigns to an immutable variable: a
+Frame1.bpl(22,4): Error: command assigns to a global variable that is not in the enclosing method's modifies clause: g1
+Frame1.bpl(23,4): Error: command assigns to an immutable variable: a
+Frame1.bpl(27,12): Error: command assigns to an immutable variable: hh
+Frame1.bpl(28,12): Error: command assigns to a global variable that is not in the enclosing method's modifies clause: h0
+Frame1.bpl(30,7): Error: command assigns to an immutable variable: hh
+Frame1.bpl(31,7): Error: command assigns to a global variable that is not in the enclosing method's modifies clause: h0
+Frame1.bpl(33,4): Error: command assigns to an immutable variable: hh
+Frame1.bpl(34,4): Error: command assigns to a global variable that is not in the enclosing method's modifies clause: h0
+Frame1.bpl(55,4): Error: command assigns to a global variable that is not in the enclosing method's modifies clause: g0
+Frame1.bpl(68,4): Error: command assigns to a global variable that is not in the enclosing method's modifies clause: g0
+Frame1.bpl(68,4): Error: command assigns to a global variable that is not in the enclosing method's modifies clause: g1
+Frame1.bpl(68,4): Error: command assigns to a global variable that is not in the enclosing method's modifies clause: h0
+Frame1.bpl(84,15): Error: mismatched type of in-parameter in implementation MismatchedTypes: x
+Frame1.bpl(89,15): Error: mismatched type of in-parameter in implementation MismatchedTypes: x (named y in implementation)
+16 type checking errors detected in Frame1.bpl
+
+Boogie program verifier finished with 0 verified, 0 errors
+Arrays.bpl(15,14): Error: wrong number of arguments in map select: 2 instead of 1
+Arrays.bpl(16,14): Error: wrong number of arguments in map select: 1 instead of 2
+Arrays.bpl(20,7): Error: wrong number of arguments in map assignment: 2 instead of 1
+Arrays.bpl(21,7): Error: wrong number of arguments in map assignment: 1 instead of 2
+Arrays.bpl(41,13): Error: invalid type for argument 0 in map select: bool (expected: int)
+Arrays.bpl(42,16): Error: invalid argument types (bool and int) to binary operator ==
+Arrays.bpl(43,13): Error: invalid type for argument 0 in map select: int (expected: bool)
+Arrays.bpl(43,15): Error: invalid type for argument 1 in map select: int (expected: ref)
+Arrays.bpl(44,15): Error: invalid type for argument 1 in map select: bool (expected: ref)
+Arrays.bpl(44,23): Error: invalid type for argument 0 in map select: ref (expected: bool)
+Arrays.bpl(45,13): Error: invalid type for argument 0 in map select: ref (expected: bool)
+Arrays.bpl(45,18): Error: invalid type for argument 1 in map select: int (expected: ref)
+Arrays.bpl(45,2): Error: preconditions must be of type bool
+Arrays.bpl(46,13): Error: invalid type for argument 0 in map select: int (expected: bool)
+Arrays.bpl(46,15): Error: invalid type for argument 1 in map select: int (expected: ref)
+Arrays.bpl(50,6): Error: invalid type for argument 0 in map assignment: bool (expected: int)
+Arrays.bpl(51,6): Error: invalid type for argument 0 in map assignment: int (expected: bool)
+Arrays.bpl(51,8): Error: invalid type for argument 1 in map assignment: int (expected: ref)
+Arrays.bpl(51,5): Error: mismatched types in assignment command (cannot assign ref to int)
+Arrays.bpl(52,7): Error: invalid type for argument 0 in map assignment: bool (expected: int)
+Arrays.bpl(52,5): Error: mismatched types in assignment command (cannot assign int to bool)
+Arrays.bpl(53,12): Error: invalid type for argument 1 in map assignment: bool (expected: ref)
+Arrays.bpl(113,11): Error: invalid type for argument 0 in map select: name (expected: [int,int]bool)
+Arrays.bpl(114,4): Error: mismatched types in assignment command (cannot assign [int,int]bool to [[int,int]bool,[name]name]int)
+Arrays.bpl(115,4): Error: mismatched types in assignment command (cannot assign name to [int,int]bool)
+Arrays.bpl(116,5): Error: mismatched types in assignment command (cannot assign name to bool)
+Arrays.bpl(117,8): Error: invalid type for argument 1 in map assignment: name (expected: [name]name)
+Arrays.bpl(118,4): Error: mismatched types in assignment command (cannot assign [int,int][int]int to [[int,int]bool,[name]name]int)
+Arrays.bpl(123,10): Error: wrong number of arguments in map select: 1 instead of 2
+Arrays.bpl(124,14): Error: wrong number of arguments in map select: 1 instead of 2
+Arrays.bpl(125,6): Error: invalid type for argument 0 in map assignment: bool (expected: int)
+Arrays.bpl(126,4): Error: mismatched types in assignment command (cannot assign [int,int][int]int to [int,int][name]int)
+Arrays.bpl(127,4): Error: mismatched types in assignment command (cannot assign [int,int][name]int to [int,int][int]int)
+Arrays.bpl(130,21): Error: wrong number of arguments in map select: 2 instead of 1
+Arrays.bpl(131,5): Error: wrong number of arguments in map assignment: 2 instead of 1
+Arrays.bpl(132,13): Error: wrong number of arguments in map select: 2 instead of 1
+Arrays.bpl(133,17): Error: wrong number of arguments in map select: 1 instead of 2
+Arrays.bpl(134,14): Error: wrong number of arguments in map select: 2 instead of 1
+Arrays.bpl(166,12): Error: invalid type for argument 0 in application of Sf: [int,int]bool (expected: any)
+Arrays.bpl(176,4): Error: mismatched types in assignment command (cannot assign [int,int]bool to <a>[int,a]bool)
+Arrays.bpl(177,4): Error: mismatched types in assignment command (cannot assign <a>[int,a]bool to [int,int]bool)
+Arrays.bpl(178,4): Error: mismatched types in assignment command (cannot assign [any,any]bool to <a>[int,a]bool)
+Arrays.bpl(179,4): Error: mismatched types in assignment command (cannot assign <a>[int,a]bool to [any,any]bool)
+Arrays.bpl(180,4): Error: mismatched types in assignment command (cannot assign [ref]bool to [any]bool)
+Arrays.bpl(191,18): Error: invalid type for argument 0 in map select: any (expected: int)
+Arrays.bpl(198,11): Error: invalid type for argument 0 in map assignment: any (expected: int)
+Arrays.bpl(214,24): Error: invalid type for argument 0 in call to IntMethod: int (expected: any)
+Arrays.bpl(214,9): Error: invalid type for out-parameter 0 in call to IntMethod: any (expected: int)
+Arrays.bpl(215,4): Error: mismatched types in assignment command (cannot assign int to any)
+Arrays.bpl(216,4): Error: mismatched types in assignment command (cannot assign any to int)
+Arrays.bpl(218,24): Error: invalid type for argument 0 in call to AnyMethod: any (expected: int)
+Arrays.bpl(218,9): Error: invalid type for out-parameter 0 in call to AnyMethod: int (expected: any)
+52 type checking errors detected in Arrays.bpl
+WhereTyping.bpl(25,34): Error: invalid argument types (double and int) to binary operator +
+WhereTyping.bpl(26,12): Error: where clauses must be of type bool
+WhereTyping.bpl(36,22): Error: invalid argument types (name and int) to binary operator !=
+WhereTyping.bpl(41,30): Error: invalid argument types (name and int) to binary operator ==
+4 type checking errors detected in WhereTyping.bpl
+Family.bpl(30,4): Error: mismatched types in assignment command (cannot assign int to bool)
+Family.bpl(31,8): Error: mismatched types in assignment command (cannot assign bool to int)
+Family.bpl(33,8): Error: mismatched types in assignment command (cannot assign int to y)
+Family.bpl(34,15): Error: invalid type for argument 1 in map assignment: any (expected: Field x)
+Family.bpl(35,15): Error: invalid type for argument 1 in map assignment: any (expected: Field x)
+Family.bpl(37,8): Error: mismatched types in assignment command (cannot assign bool to any)
+Family.bpl(38,8): Error: mismatched types in assignment command (cannot assign Field any to any)
+Family.bpl(39,8): Error: mismatched types in assignment command (cannot assign Field y to any)
+8 type checking errors detected in Family.bpl
+AttributeTyping.bpl(3,23): Error: ++ operands need to be bitvectors (got int, int)
+AttributeTyping.bpl(5,29): Error: invalid type for argument 0 in application of F0: bool (expected: int)
+AttributeTyping.bpl(7,26): Error: invalid type for argument 0 in application of F0: bool (expected: int)
+AttributeTyping.bpl(9,21): Error: invalid argument types (int and int) to binary operator &&
+AttributeTyping.bpl(11,22): Error: invalid argument type (int) to unary operator !
+AttributeTyping.bpl(13,32): Error: invalid argument types (int and int) to binary operator ==>
+6 type checking errors detected in AttributeTyping.bpl
+UpdateExprTyping.bpl(3,11): Error: invalid argument types ([int]bool and [int]ref) to binary operator ==
+UpdateExprTyping.bpl(4,11): Error: invalid argument types ([int]bool and [bool]bool) to binary operator ==
+UpdateExprTyping.bpl(7,16): Error: invalid type for argument 0 in map store: bool (expected: int)
+UpdateExprTyping.bpl(8,21): Error: right-hand side in map store with wrong type: int (expected: bool)
+UpdateExprTyping.bpl(9,11): Error: invalid argument types ([int]bool and [int]ref) to binary operator ==
+UpdateExprTyping.bpl(15,18): Error: invalid type for argument 0 in map store: ref (expected: int)
+UpdateExprTyping.bpl(16,20): Error: invalid type for argument 1 in map store: bool (expected: ref)
+UpdateExprTyping.bpl(17,28): Error: right-hand side in map store with wrong type: ref (expected: bool)
+UpdateExprTyping.bpl(32,2): Error: mismatched types in assignment command (cannot assign int to any)
+UpdateExprTyping.bpl(36,28): Error: right-hand side in map store with wrong type: ref (expected: any)
+UpdateExprTyping.bpl(38,27): Error: right-hand side in map store with wrong type: ref (expected: int)
+UpdateExprTyping.bpl(39,27): Error: right-hand side in map store with wrong type: int (expected: ref)
+12 type checking errors detected in UpdateExprTyping.bpl
+CallForallResolve.bpl(15,2): Error: call forall is allowed only on procedures with no modifies clause: Q
+1 type checking errors detected in CallForallResolve.bpl
+MapsTypeErrors.bpl(26,6): Error: command assigns to a global variable that is not in the enclosing method's modifies clause: m
+MapsTypeErrors.bpl(32,2): Error: mismatched types in assignment command (cannot assign int to []int)
+MapsTypeErrors.bpl(33,3): Error: mismatched types in assignment command (cannot assign []int to int)
+MapsTypeErrors.bpl(39,3): Error: mismatched types in assignment command (cannot assign bool to int)
+MapsTypeErrors.bpl(67,14): Error: invalid argument types (Field int and Field bool) to binary operator ==
+MapsTypeErrors.bpl(70,27): Error: invalid type for argument 1 in application of StrictEqual: Field bool (expected: a)
+MapsTypeErrors.bpl(75,33): Error: invalid type for argument 1 in application of StrictEqual: Field int (expected: a)
+MapsTypeErrors.bpl(77,31): Error: invalid type for argument 1 in application of IntEqual: Field alpha (expected: Field int)
+MapsTypeErrors.bpl(90,8): Error: extract operand must be a bitvector of at least 32 bits (got bv31)
+MapsTypeErrors.bpl(91,8): Error: extract operand must be a bitvector of at least 32 bits (got int)
+MapsTypeErrors.bpl(95,2): Error: mismatched types in assignment command (cannot assign bv33 to bv32)
+MapsTypeErrors.bpl(104,2): Error: mismatched types in assignment command (cannot assign bv20 to bv32)
+MapsTypeErrors.bpl(110,56): Error: invalid type for argument 1 in application of Same: bv18 (expected: T)
+MapsTypeErrors.bpl(120,4): Error: mismatched types in assignment command (cannot assign [?, ?]? to [int,int]bool)
+MapsTypeErrors.bpl(122,4): Error: mismatched types in assignment command (cannot assign [?, ?]? to HeapType)
+15 type checking errors detected in MapsTypeErrors.bpl
+Orderings.bpl(6,19): Error: parent of constant has incompatible type (int instead of C)
+1 type checking errors detected in Orderings.bpl
+EmptyCallArgs.bpl(15,17): Error: invalid type for argument 0 in call to P: int (expected: bool)
+EmptyCallArgs.bpl(26,7): Error: invalid type for out-parameter 0 in call to Q: int (expected: bool)
+EmptyCallArgs.bpl(28,7): Error: invalid type for out-parameter 0 in call to Q: int (expected: bool)
+3 type checking errors detected in EmptyCallArgs.bpl
+FunBody.bpl(6,45): Error: function body with invalid type: bool (expected: int)
+FunBody.bpl(8,61): Error: function body with invalid type: int (expected: alpha)
+FunBody.bpl(10,58): Error: function body with invalid type: int (expected: alpha)
+3 type checking errors detected in FunBody.bpl
diff --git a/Test/test1/Arrays.bpl b/Test/test1/Arrays.bpl
new file mode 100644
index 00000000..85ee783b
--- /dev/null
+++ b/Test/test1/Arrays.bpl
@@ -0,0 +1,224 @@
+var one: [int]int;
+var two: [int, int]int;
+
+procedure Good0(x: int, y: int)
+ requires one[x] == two[x,y];
+ modifies one, two;
+{
+ start:
+ one[x] := two[x,y];
+ two[x,y] := one[x];
+ return;
+}
+
+procedure Bad0(x: int, y: int)
+ requires one[x,y] == 7;
+ requires two[x] == 8;
+ modifies one, two;
+{
+ start:
+ one[x,y] := 10;
+ two[x] := 11;
+ return;
+}
+
+var A: [int]bool;
+var B: [bool, ref]int;
+
+procedure Good1(x: int, b: bool, o: ref)
+ requires A[x] && B[b,o] == 18;
+ modifies A, B;
+{
+ start:
+ A[x] := true;
+ B[b,o] := 19;
+ A[100] := false;
+ B[false,null] := 70;
+ return;
+}
+
+procedure Bad1(x: int, b: bool, o: ref)
+ requires A[b];
+ requires A[x] == 7;
+ requires B[x,x] < 12;
+ requires B[b,b] == B[o,o];
+ requires B[null,5];
+ requires B[7,7] == A[7];
+ modifies A, B;
+{
+ start:
+ A[b] := true;
+ B[3,14] := null;
+ A[A[x]] := 9;
+ B[false,false] := 70;
+ return;
+}
+
+var M: [ [int,int]bool, [name]name ]int;
+var Q: [int,int][int]int;
+var R: [int][int,int]int;
+
+procedure Good2(k: [int,int]bool, l: [name]name) returns (n: int)
+ modifies M, Q, R;
+{
+ var m: [ [int,int]bool, [name]name ]int;
+ var p: [int,int]bool;
+ var q: [int]int;
+ var qq: [int,int][int]int;
+ var r: [int,int]int;
+
+ start:
+ n := M[k,l];
+ m := M;
+ p := k;
+ p[5,8] := true;
+ m[p,l] := 13;
+ M := m;
+ goto next;
+
+ next:
+ qq := Q;
+ q := Q[13,21];
+ n := n + Q[34,55][89];
+ R[1] := R[2];
+ n := n + R[1][2,3];
+ Q[144,233] := q;
+ goto deepUpdate;
+
+ deepUpdate:
+ // To effectively do:
+ // Q[5,8][13] := 21;
+ // do:
+ q := Q[5,8];
+ q[13] := 21;
+ Q[5,8] := q;
+ return;
+}
+
+const Sven: name;
+const Mia: name;
+const Tryggve: name;
+const Gunnel: name;
+
+procedure Bad2(k: [int,int]bool, l: [name]name) returns (n: int)
+ modifies M, Q, R;
+{
+ var m: [ [int,int]bool, [name]name ]int;
+ var p: [int,int]bool;
+ var q: [int]int;
+ var qq: [int,int][int]int;
+ var qqx: [int,int][name]int;
+
+ start:
+ n := M[Sven,l];
+ m := p;
+ p := l[Mia];
+ p[5,8] := Tryggve;
+ m[p,Gunnel] := 13;
+ M := qq;
+ goto next;
+
+ next:
+ qq := Q; // okay
+ q := Q[13];
+ n := n - Q[89][34,55];
+ Q[true,233] := q;
+ qqx := qq;
+ Q := qqx;
+ qqx := qqx; // okay
+ Q := Q; // okay
+ n := n + Q[34,55][144,169];
+ R[1,2] := 0;
+ R[1] := R[2,3];
+ n := n + R[1][2];
+ n := n + R[1,2];
+ return;
+}
+
+type MyType;
+var S0: bool;
+var S1: [ref]bool;
+var S2: [ref,int]bool;
+var S3: [[ref,int]bool,MyType]MyType;
+var S4: <a>[int,a]bool;
+var S5: [int,int]bool;
+var S6: [any,any]bool;
+var S7: [int,any]any;
+var S8: [any]bool;
+
+function Sf(any) returns (bool);
+
+procedure SubtypesGood(a: any)
+ modifies S0;
+{
+ var t: MyType;
+ var b: bool;
+
+ start:
+ S0 := S1[null]; // bool := bool
+ S0 := S2[null,0]; // bool := bool
+ t := S3[S2,t];
+ goto next;
+ next:
+ b := S4[4,a];
+ b := S4[5,null]; // any := ref
+ b := S4[6,S4]; // any := [int,any]bool
+ b := Sf(S5);
+ return;
+}
+
+procedure SubtypesBad()
+ modifies S4,S5,S6;
+ modifies S8;
+{
+ start:
+ S4 := S4;
+ S4 := S5; // no
+ S5 := S4; // no
+ S4 := S6; // no
+ S6 := S4; // no
+ S8 := S1; // no
+ return;
+}
+
+// ----------------------------------------------------
+
+var ArrayA: [int]bool;
+var ArrayB: <a>[a]bool;
+
+procedure ArrayP(x: int, y: any)
+ requires ArrayA[x];
+ requires ArrayA[y]; // error
+ requires ArrayB[x];
+ requires ArrayB[y];
+ modifies ArrayA, ArrayB;
+{
+ start:
+ ArrayA[x] := true;
+ ArrayA[y] := true; // error
+ ArrayB[x] := true;
+ ArrayB[y] := true;
+ return;
+}
+
+// ----------------------------------------------------
+
+procedure IntMethod(p: any) returns (r: int);
+procedure AnyMethod(p: int) returns (r: any);
+
+procedure IntMethodCaller()
+{
+ var x: any, y: int;
+ entry:
+ call x := AnyMethod(y); // types are exact
+ call x := IntMethod(y); // error: type mismatch for out-parameter
+ x := y;
+ y := x; // error: cannot assign any to int
+ call y := IntMethod(x); // types are exact
+ call y := AnyMethod(x); // type error on both in-parameter and out-parameter
+ return;
+}
+
+
+type ref, any, name;
+const null : ref;
diff --git a/Test/test1/AttributeTyping.bpl b/Test/test1/AttributeTyping.bpl
new file mode 100644
index 00000000..204ac2ac
--- /dev/null
+++ b/Test/test1/AttributeTyping.bpl
@@ -0,0 +1,36 @@
+
+
+const {:Incorrect pux0 ++ F0(pux1)} pux0: int;
+
+function {:Incorrect F0(pux0 < 0) + pux1} F0(int) returns (int);
+
+axiom {:Incorrect F0(pux0 == pux1)} true;
+
+var {:Incorrect pux0 && pux1} pux1: int;
+
+procedure {:Incorrect !(pux0 - pux1)} P();
+
+implementation {:Incorrect pux0 ==> pux1} P()
+{
+}
+
+// ------ and here are various correct things
+
+
+
+const {:Correct hux0 + F1(hux1)} hux0: int;
+
+function {:Correct F1(hux0) + hux1} F1(int) returns (int);
+
+axiom {:Correct F1(hux0 + hux1)} true;
+
+var {:Correct hux0*hux1} hux1: int;
+
+procedure {:Correct hux0 - hux1} H();
+
+implementation {:Correct hux0 + hux1} {:AlsoCorrect "hello"} H()
+{
+}
+
+
+type any; \ No newline at end of file
diff --git a/Test/test1/CallForallResolve.bpl b/Test/test1/CallForallResolve.bpl
new file mode 100644
index 00000000..374db174
--- /dev/null
+++ b/Test/test1/CallForallResolve.bpl
@@ -0,0 +1,23 @@
+procedure P(x: int) returns (y: int);
+
+procedure CallP()
+{
+ call forall P(5); // P is allowed here, even if it has out parameters
+}
+
+var global: bool;
+
+procedure Q(x: int);
+ modifies global;
+
+procedure CallQ()
+{
+ call forall Q(5); // error: P is not allowed here, because it has a modifies clause
+}
+
+procedure R(x: int);
+
+procedure CallR()
+{
+ call forall R(5); // no problem that R has no body, though
+}
diff --git a/Test/test1/EmptyCallArgs.bpl b/Test/test1/EmptyCallArgs.bpl
new file mode 100644
index 00000000..18d837a9
--- /dev/null
+++ b/Test/test1/EmptyCallArgs.bpl
@@ -0,0 +1,31 @@
+type C;
+
+procedure P(x:int, y:bool) returns (z:C);
+procedure Q<a>(x:int, y:a) returns (z:a);
+
+procedure CallP() {
+ var x:int;
+ var y:bool;
+ var z:C;
+
+ call z := P(x, y);
+ call * := P(x, y);
+ call z := P(*, y);
+ call z := P(x, *);
+ call * := P(*, x); // type error
+ call * := P(x, *);
+ call z := P(*, *);
+ call * := P(*, *);
+}
+
+procedure CallQ() {
+ var x:int;
+ var y:bool;
+ var z:bool;
+
+ call x := Q(x, y); // type error
+ call * := Q(x, y);
+ call x := Q(*, y); // type error
+ call x := Q(x, *);
+ call * := Q(*, y);
+} \ No newline at end of file
diff --git a/Test/test1/Family.bpl b/Test/test1/Family.bpl
new file mode 100644
index 00000000..1c650d3d
--- /dev/null
+++ b/Test/test1/Family.bpl
@@ -0,0 +1,47 @@
+type T;
+
+var Heap: <x>[ref,Field x]x;
+
+function IsHeap(<x>[ref,Field x]x) returns (bool);
+
+const alloc: Field bool;
+const C.x: Field int;
+
+axiom (forall h: <x>[ref,Field x]x, f: Field ref, o: ref :: IsHeap(h) && o != null ==> h[h[o,f], alloc]);
+
+procedure P(this: ref) returns (r: int)
+ modifies Heap;
+{
+ start:
+ r := Heap[this, C.x];
+ Heap[this, C.x] := r;
+ return;
+}
+
+// -----------------
+
+procedure R(this: ref)
+ modifies Heap;
+{
+ var field: any, refField: Field ref, yField: Field y, anyField: Field any;
+ var b: bool, a: any;
+
+ start:
+ b := Heap[this, C.x]; // type error
+ Heap[this, C.x] := true; // type error
+ Heap[this, refField] := this;
+ Heap[this, yField] := 2; // type error
+ Heap[this, field] := a; // type error
+ Heap[this, field] := b; // type error
+ Heap[this, anyField] := a;
+ Heap[this, anyField] := b;
+ Heap[this, anyField] := anyField;
+ Heap[this, anyField] := yField;
+ Heap[this, anyField] := field;
+ return;
+}
+
+type Field a;
+type y;
+type ref, any;
+const null : ref;
diff --git a/Test/test1/Frame0.bpl b/Test/test1/Frame0.bpl
new file mode 100644
index 00000000..02a5af46
--- /dev/null
+++ b/Test/test1/Frame0.bpl
@@ -0,0 +1,15 @@
+var g0: int;
+var g1: int;
+
+var h0: [ref, name]any;
+var h1: [ref, name]any;
+
+const X: name;
+
+procedure P(a: ref, hh: [ref, name]any) returns (b: int, hout: [ref, name]any);
+ modifies a; // in-parameters are not mutable
+ modifies h1, g0;
+ modifies b; // out-parameters are not allowed explicitly in modifies clause
+
+
+type ref, name, any;
diff --git a/Test/test1/Frame1.bpl b/Test/test1/Frame1.bpl
new file mode 100644
index 00000000..469f43ba
--- /dev/null
+++ b/Test/test1/Frame1.bpl
@@ -0,0 +1,97 @@
+var g0: int;
+var g1: int;
+
+var h0: [ref, name]int;
+var h1: [ref, name]int;
+
+const X: name;
+
+procedure P(a: ref, hh: [ref, name]int) returns (b: int, hout: [ref, name]any);
+ modifies h1, g0;
+
+implementation P(a: ref, hh: [ref, name]int)
+ returns (b: int, hout: [ref, name]any) {
+ start:
+ g0 := 5;
+ g1 := 6; // error: g1 is not in modifies clause
+ a := null; // error: in-parameters are not mutable
+ b := 12;
+ goto next;
+ next:
+ havoc g0;
+ havoc g1; // error: g1 is not in modifies clause
+ havoc a; // error: in-parameters are not mutable
+ havoc b;
+ goto more;
+ more:
+ hh[a,X] := 101; // error: in-parameter (hh) is not mutable
+ h0[a,X] := 102; // error: h0 is not in modifies clause
+ h1[a,X] := 103;
+ hh := h0; // error: in-parameter is not mutable
+ h0 := h1; // error: h0 is not in modifies clause
+ h1 := hh;
+ havoc hh; // error: in-parameter is not mutable
+ havoc h0; // error: h0 is not in modifies clause
+ havoc h1;
+ return;
+}
+
+procedure PX();
+ modifies h1, g0;
+
+procedure PY()
+ modifies h1, g0;
+{
+ start:
+ call PX();
+ call PY();
+ return;
+}
+
+procedure PZ()
+ modifies h1;
+{
+ start:
+ call PX(); // error: PX has larger frame than PZ
+ return;
+}
+
+procedure Q() returns (x: int, y: int, h: [ref, name]int)
+{
+ start:
+ return;
+}
+
+procedure QCallerBad()
+{
+ start:
+ call g0, g1, h0 := Q();
+ return;
+}
+
+procedure QCallerGood()
+ modifies g0, h0;
+{
+ var t: int;
+
+ start:
+ call t, g0, h0 := Q();
+ return;
+}
+
+procedure MismatchedTypes(x: int);
+
+implementation MismatchedTypes(x: bool) // error
+{
+ start:
+ return;
+}
+implementation MismatchedTypes(y: bool) // error (this time with a different name for the formal)
+{
+ start:
+ return;
+}
+
+
+type ref, name, any;
+const null : ref;
diff --git a/Test/test1/FunBody.bpl b/Test/test1/FunBody.bpl
new file mode 100644
index 00000000..867942ff
--- /dev/null
+++ b/Test/test1/FunBody.bpl
@@ -0,0 +1,13 @@
+
+function g0<beta>(x:beta) returns (beta);
+function g1<beta>() returns (beta);
+
+function {:inline true} f1() returns (int) { 13 }
+function {:inline true} f2() returns (int) { true } // wrong type
+function {:inline true} f3<alpha>(x:alpha) returns (alpha) { g0(x) }
+function {:inline true} f4<alpha>(x:alpha) returns (alpha) { g0(5) } // wrong type
+function {:inline true} f5<alpha>() returns (alpha) { g1() }
+function {:inline true} f6<alpha>() returns (alpha) { g1():int } // wrong type
+
+
+
diff --git a/Test/test1/LogicalExprs.bpl b/Test/test1/LogicalExprs.bpl
new file mode 100644
index 00000000..028d18f4
--- /dev/null
+++ b/Test/test1/LogicalExprs.bpl
@@ -0,0 +1,6 @@
+const P: bool;
+const Q: bool;
+
+axiom (forall x: int :: x < 0);
+axiom Q ==> P;
+axiom (forall x: int :: x < 0) ==> P;
diff --git a/Test/test1/MapsTypeErrors.bpl b/Test/test1/MapsTypeErrors.bpl
new file mode 100644
index 00000000..0e68440d
--- /dev/null
+++ b/Test/test1/MapsTypeErrors.bpl
@@ -0,0 +1,127 @@
+var m: []int;
+var p: <a>[]a;
+
+type ref;
+const null: ref;
+
+procedure P()
+ requires m[] == 5;
+ modifies m;
+ modifies p;
+ ensures m[] == 30;
+ ensures p[] + p[] == 24;
+ ensures p[] == null;
+{
+ m[] := 12;
+ p[] := 12;
+ p[] := true;
+ assert p[] == m[];
+ assert p[];
+ m := m[:= 30];
+ p := p[:=null];
+}
+
+procedure A()
+{
+ m[] := 12; // error: illegal assignment, because m is not in modifies clause
+}
+
+procedure B()
+ modifies m;
+{
+ m := m[]; // type error
+ m[] := m; // type error
+}
+
+procedure C()
+ modifies m;
+{
+ m[] := true; // type error
+}
+
+// -----
+
+procedure Genrc<T>(x: int) returns (t: T);
+
+procedure Caller() returns (b: bool)
+{
+ var y: ref;
+ call y := Genrc(5);
+ b := y == null;
+}
+
+// ----
+
+type Field a;
+type HeapType = <a>[ref, Field a]a;
+const F0: Field int;
+const F1: Field bool;
+const alloc: Field bool;
+var Heap: HeapType;
+
+function LiberalEqual<a,b>(a, b) returns (bool);
+function StrictEqual<a>(a,a) returns (bool);
+function IntEqual(Field int,Field int) returns (bool);
+
+procedure FrameCondition(this: ref)
+ requires F0 == F1; // error
+ requires LiberalEqual(F0, F1);
+ requires StrictEqual(F0, F0);
+ requires StrictEqual(F0, F1); // error
+ modifies Heap;
+ ensures (forall<alpha> o: ref, f: Field alpha ::
+ Heap[o,f] == old(Heap)[o,f] ||
+ !old(Heap)[o,alloc] ||
+ (o == this && StrictEqual(f, F0)) || // error: f and F0 don't have the same type
+ (o == this && LiberalEqual(f, f)) ||
+ (o == this && IntEqual(F0, f)) // error: f and F0 don't have the same type
+ );
+{
+}
+
+// ---- bitvector inference ----
+
+function Gimmie<T>() returns (T);
+function Same<T>(T,T) returns (T);
+procedure ConsumeAnything<T>(t: T);
+
+procedure Bvs(x: bv31, y: int) returns (a: bv32)
+{
+ a := x[50 : 18]; // error
+ a := y[50 : 18]; // error
+
+ a := Gimmie(); // fine, this can be made to have at least 32 bits
+ a := Gimmie()[50 : 18]; // fine, result is always 32 bits and Gimmie() can be made to have at least 50 bits
+ a := Gimmie()[50 : 17]; // error, result is 33 bits (but there's nothing wrong with Gimmie())
+
+ a := Gimmie() ++ Gimmie() ++ Gimmie();
+ a := Gimmie() ++ Gimmie()[20:0];
+ a := 0bv0 ++ Gimmie()[6:6] ++ Gimmie()[17:12] ++ Gimmie() ++ Gimmie() ++ Gimmie()[27:0];
+ a := 0bv0 ++ Gimmie()[6:6] ++ Gimmie()[17:12] ++ Gimmie() ++ Gimmie() ++ Gimmie()[22:0];
+ a := 0bv0 ++ Gimmie()[6:6] ++ Gimmie()[17:12] ++ Gimmie() ++ Gimmie()[22:0] ++ Gimmie();
+ a := Gimmie() ++ 0bv0 ++ Gimmie()[6:6] ++ Gimmie()[17:12] ++ Gimmie() ++ Gimmie()[22:0];
+ a := Same(Gimmie(), Gimmie());
+ a := Same(Gimmie()[20:0], Gimmie()); // error, have only bv20, need bv32
+
+ a := Same(Gimmie() ++ Gimmie()[20:0], 0bv32);
+ a := Same(Gimmie() ++ Gimmie()[20:0], Gimmie());
+ a := Same(Gimmie() ++ Gimmie()[20:0], Gimmie() ++ Gimmie());
+ a := Same(Gimmie() ++ Gimmie()[20:0], Gimmie()[40:30] ++ Gimmie());
+ call ConsumeAnything(Same(Gimmie() ++ Gimmie()[20:0], 0bv18)); // error, can't make things smaller
+}
+
+// ---- maps again ----
+
+procedure Mmm() returns (a: [int,int]bool, b: HeapType, c: int)
+{
+ if (Gimmie()[null] == Gimmie()) {
+ a := Same(Gimmie()[Gimmie(), Gimmie() := Gimmie()], Gimmie());
+ b := Same(Gimmie()[Gimmie(), Gimmie() := Gimmie()], Gimmie());
+ a := Same(Gimmie()[Gimmie(), Gimmie() := 4], Gimmie()); // error
+ b := Same(Gimmie()[Gimmie(), Gimmie() := 5], Gimmie());
+ b := Same(Gimmie()[Gimmie(), 6 := Gimmie()], Gimmie()); // error
+ }
+ c := Gimmie()[Gimmie() := 10][null];
+ c := Gimmie()[Gimmie() := Gimmie()][null];
+ c := Gimmie()[Gimmie() := false][null];
+}
diff --git a/Test/test1/Orderings.bpl b/Test/test1/Orderings.bpl
new file mode 100644
index 00000000..be0502fa
--- /dev/null
+++ b/Test/test1/Orderings.bpl
@@ -0,0 +1,8 @@
+
+type C;
+
+const c1:C;
+const c2:C extends c1;
+const c0:C extends a; // error: parent of wrong type
+
+const a:int;
diff --git a/Test/test1/Output b/Test/test1/Output
new file mode 100644
index 00000000..b0f4aac3
--- /dev/null
+++ b/Test/test1/Output
@@ -0,0 +1,137 @@
+Frame0.bpl(10,11): Error: undeclared identifier: a
+Frame0.bpl(12,11): Error: undeclared identifier: b
+2 name resolution errors detected in Frame0.bpl
+Frame1.bpl(16,7): Error: command assigns to a global variable that is not in the enclosing method's modifies clause: g1
+Frame1.bpl(17,6): Error: command assigns to an immutable variable: a
+Frame1.bpl(22,4): Error: command assigns to a global variable that is not in the enclosing method's modifies clause: g1
+Frame1.bpl(23,4): Error: command assigns to an immutable variable: a
+Frame1.bpl(27,12): Error: command assigns to an immutable variable: hh
+Frame1.bpl(28,12): Error: command assigns to a global variable that is not in the enclosing method's modifies clause: h0
+Frame1.bpl(30,7): Error: command assigns to an immutable variable: hh
+Frame1.bpl(31,7): Error: command assigns to a global variable that is not in the enclosing method's modifies clause: h0
+Frame1.bpl(33,4): Error: command assigns to an immutable variable: hh
+Frame1.bpl(34,4): Error: command assigns to a global variable that is not in the enclosing method's modifies clause: h0
+Frame1.bpl(55,4): Error: command assigns to a global variable that is not in the enclosing method's modifies clause: g0
+Frame1.bpl(68,4): Error: command assigns to a global variable that is not in the enclosing method's modifies clause: g0
+Frame1.bpl(68,4): Error: command assigns to a global variable that is not in the enclosing method's modifies clause: g1
+Frame1.bpl(68,4): Error: command assigns to a global variable that is not in the enclosing method's modifies clause: h0
+Frame1.bpl(84,15): Error: mismatched type of in-parameter in implementation MismatchedTypes: x
+Frame1.bpl(89,15): Error: mismatched type of in-parameter in implementation MismatchedTypes: x (named y in implementation)
+16 type checking errors detected in Frame1.bpl
+
+Boogie program verifier finished with 0 verified, 0 errors
+Arrays.bpl(15,14): Error: wrong number of arguments in map select: 2 instead of 1
+Arrays.bpl(16,14): Error: wrong number of arguments in map select: 1 instead of 2
+Arrays.bpl(20,7): Error: wrong number of arguments in map assignment: 2 instead of 1
+Arrays.bpl(21,7): Error: wrong number of arguments in map assignment: 1 instead of 2
+Arrays.bpl(41,13): Error: invalid type for argument 0 in map select: bool (expected: int)
+Arrays.bpl(42,16): Error: invalid argument types (bool and int) to binary operator ==
+Arrays.bpl(43,13): Error: invalid type for argument 0 in map select: int (expected: bool)
+Arrays.bpl(43,15): Error: invalid type for argument 1 in map select: int (expected: ref)
+Arrays.bpl(44,15): Error: invalid type for argument 1 in map select: bool (expected: ref)
+Arrays.bpl(44,23): Error: invalid type for argument 0 in map select: ref (expected: bool)
+Arrays.bpl(45,13): Error: invalid type for argument 0 in map select: ref (expected: bool)
+Arrays.bpl(45,18): Error: invalid type for argument 1 in map select: int (expected: ref)
+Arrays.bpl(45,2): Error: preconditions must be of type bool
+Arrays.bpl(46,13): Error: invalid type for argument 0 in map select: int (expected: bool)
+Arrays.bpl(46,15): Error: invalid type for argument 1 in map select: int (expected: ref)
+Arrays.bpl(50,6): Error: invalid type for argument 0 in map assignment: bool (expected: int)
+Arrays.bpl(51,6): Error: invalid type for argument 0 in map assignment: int (expected: bool)
+Arrays.bpl(51,8): Error: invalid type for argument 1 in map assignment: int (expected: ref)
+Arrays.bpl(51,5): Error: mismatched types in assignment command (cannot assign ref to int)
+Arrays.bpl(52,7): Error: invalid type for argument 0 in map assignment: bool (expected: int)
+Arrays.bpl(52,5): Error: mismatched types in assignment command (cannot assign int to bool)
+Arrays.bpl(53,12): Error: invalid type for argument 1 in map assignment: bool (expected: ref)
+Arrays.bpl(113,11): Error: invalid type for argument 0 in map select: name (expected: [int,int]bool)
+Arrays.bpl(114,4): Error: mismatched types in assignment command (cannot assign [int,int]bool to [[int,int]bool,[name]name]int)
+Arrays.bpl(115,4): Error: mismatched types in assignment command (cannot assign name to [int,int]bool)
+Arrays.bpl(116,5): Error: mismatched types in assignment command (cannot assign name to bool)
+Arrays.bpl(117,8): Error: invalid type for argument 1 in map assignment: name (expected: [name]name)
+Arrays.bpl(118,4): Error: mismatched types in assignment command (cannot assign [int,int][int]int to [[int,int]bool,[name]name]int)
+Arrays.bpl(123,10): Error: wrong number of arguments in map select: 1 instead of 2
+Arrays.bpl(124,14): Error: wrong number of arguments in map select: 1 instead of 2
+Arrays.bpl(125,6): Error: invalid type for argument 0 in map assignment: bool (expected: int)
+Arrays.bpl(126,4): Error: mismatched types in assignment command (cannot assign [int,int][int]int to [int,int][name]int)
+Arrays.bpl(127,4): Error: mismatched types in assignment command (cannot assign [int,int][name]int to [int,int][int]int)
+Arrays.bpl(130,21): Error: wrong number of arguments in map select: 2 instead of 1
+Arrays.bpl(131,5): Error: wrong number of arguments in map assignment: 2 instead of 1
+Arrays.bpl(132,13): Error: wrong number of arguments in map select: 2 instead of 1
+Arrays.bpl(133,17): Error: wrong number of arguments in map select: 1 instead of 2
+Arrays.bpl(134,14): Error: wrong number of arguments in map select: 2 instead of 1
+Arrays.bpl(166,12): Error: invalid type for argument 0 in application of Sf: [int,int]bool (expected: any)
+Arrays.bpl(176,4): Error: mismatched types in assignment command (cannot assign [int,int]bool to <a>[int,a]bool)
+Arrays.bpl(177,4): Error: mismatched types in assignment command (cannot assign <a>[int,a]bool to [int,int]bool)
+Arrays.bpl(178,4): Error: mismatched types in assignment command (cannot assign [any,any]bool to <a>[int,a]bool)
+Arrays.bpl(179,4): Error: mismatched types in assignment command (cannot assign <a>[int,a]bool to [any,any]bool)
+Arrays.bpl(180,4): Error: mismatched types in assignment command (cannot assign [ref]bool to [any]bool)
+Arrays.bpl(191,18): Error: invalid type for argument 0 in map select: any (expected: int)
+Arrays.bpl(198,11): Error: invalid type for argument 0 in map assignment: any (expected: int)
+Arrays.bpl(214,24): Error: invalid type for argument 0 in call to IntMethod: int (expected: any)
+Arrays.bpl(214,9): Error: invalid type for out-parameter 0 in call to IntMethod: any (expected: int)
+Arrays.bpl(215,4): Error: mismatched types in assignment command (cannot assign int to any)
+Arrays.bpl(216,4): Error: mismatched types in assignment command (cannot assign any to int)
+Arrays.bpl(218,24): Error: invalid type for argument 0 in call to AnyMethod: any (expected: int)
+Arrays.bpl(218,9): Error: invalid type for out-parameter 0 in call to AnyMethod: int (expected: any)
+52 type checking errors detected in Arrays.bpl
+WhereTyping.bpl(25,34): Error: invalid argument types (double and int) to binary operator +
+WhereTyping.bpl(26,12): Error: where clauses must be of type bool
+WhereTyping.bpl(36,22): Error: invalid argument types (name and int) to binary operator !=
+WhereTyping.bpl(41,30): Error: invalid argument types (name and int) to binary operator ==
+4 type checking errors detected in WhereTyping.bpl
+Family.bpl(30,4): Error: mismatched types in assignment command (cannot assign int to bool)
+Family.bpl(31,8): Error: mismatched types in assignment command (cannot assign bool to int)
+Family.bpl(33,8): Error: mismatched types in assignment command (cannot assign int to y)
+Family.bpl(34,15): Error: invalid type for argument 1 in map assignment: any (expected: Field x)
+Family.bpl(35,15): Error: invalid type for argument 1 in map assignment: any (expected: Field x)
+Family.bpl(37,8): Error: mismatched types in assignment command (cannot assign bool to any)
+Family.bpl(38,8): Error: mismatched types in assignment command (cannot assign Field any to any)
+Family.bpl(39,8): Error: mismatched types in assignment command (cannot assign Field y to any)
+8 type checking errors detected in Family.bpl
+AttributeTyping.bpl(3,23): Error: ++ operands need to be bitvectors (got int, int)
+AttributeTyping.bpl(5,29): Error: invalid type for argument 0 in application of F0: bool (expected: int)
+AttributeTyping.bpl(7,26): Error: invalid type for argument 0 in application of F0: bool (expected: int)
+AttributeTyping.bpl(9,21): Error: invalid argument types (int and int) to binary operator &&
+AttributeTyping.bpl(11,22): Error: invalid argument type (int) to unary operator !
+AttributeTyping.bpl(13,32): Error: invalid argument types (int and int) to binary operator ==>
+6 type checking errors detected in AttributeTyping.bpl
+UpdateExprTyping.bpl(3,11): Error: invalid argument types ([int]bool and [int]ref) to binary operator ==
+UpdateExprTyping.bpl(4,11): Error: invalid argument types ([int]bool and [bool]bool) to binary operator ==
+UpdateExprTyping.bpl(7,16): Error: invalid type for argument 0 in map store: bool (expected: int)
+UpdateExprTyping.bpl(8,21): Error: right-hand side in map store with wrong type: int (expected: bool)
+UpdateExprTyping.bpl(9,11): Error: invalid argument types ([int]bool and [int]ref) to binary operator ==
+UpdateExprTyping.bpl(15,18): Error: invalid type for argument 0 in map store: ref (expected: int)
+UpdateExprTyping.bpl(16,20): Error: invalid type for argument 1 in map store: bool (expected: ref)
+UpdateExprTyping.bpl(17,28): Error: right-hand side in map store with wrong type: ref (expected: bool)
+UpdateExprTyping.bpl(32,2): Error: mismatched types in assignment command (cannot assign int to any)
+UpdateExprTyping.bpl(36,28): Error: right-hand side in map store with wrong type: ref (expected: any)
+UpdateExprTyping.bpl(38,27): Error: right-hand side in map store with wrong type: ref (expected: int)
+UpdateExprTyping.bpl(39,27): Error: right-hand side in map store with wrong type: int (expected: ref)
+12 type checking errors detected in UpdateExprTyping.bpl
+CallForallResolve.bpl(15,2): Error: call forall is allowed only on procedures with no modifies clause: Q
+1 type checking errors detected in CallForallResolve.bpl
+MapsTypeErrors.bpl(26,6): Error: command assigns to a global variable that is not in the enclosing method's modifies clause: m
+MapsTypeErrors.bpl(32,2): Error: mismatched types in assignment command (cannot assign int to []int)
+MapsTypeErrors.bpl(33,3): Error: mismatched types in assignment command (cannot assign []int to int)
+MapsTypeErrors.bpl(39,3): Error: mismatched types in assignment command (cannot assign bool to int)
+MapsTypeErrors.bpl(67,14): Error: invalid argument types (Field int and Field bool) to binary operator ==
+MapsTypeErrors.bpl(70,27): Error: invalid type for argument 1 in application of StrictEqual: Field bool (expected: a)
+MapsTypeErrors.bpl(75,33): Error: invalid type for argument 1 in application of StrictEqual: Field int (expected: a)
+MapsTypeErrors.bpl(77,31): Error: invalid type for argument 1 in application of IntEqual: Field alpha (expected: Field int)
+MapsTypeErrors.bpl(90,8): Error: extract operand must be a bitvector of at least 32 bits (got bv31)
+MapsTypeErrors.bpl(91,8): Error: extract operand must be a bitvector of at least 32 bits (got int)
+MapsTypeErrors.bpl(95,2): Error: mismatched types in assignment command (cannot assign bv33 to bv32)
+MapsTypeErrors.bpl(104,2): Error: mismatched types in assignment command (cannot assign bv20 to bv32)
+MapsTypeErrors.bpl(110,56): Error: invalid type for argument 1 in application of Same: bv18 (expected: T)
+MapsTypeErrors.bpl(120,4): Error: mismatched types in assignment command (cannot assign [?, ?]? to [int,int]bool)
+MapsTypeErrors.bpl(122,4): Error: mismatched types in assignment command (cannot assign [?, ?]? to HeapType)
+15 type checking errors detected in MapsTypeErrors.bpl
+Orderings.bpl(6,19): Error: parent of constant has incompatible type (int instead of C)
+1 type checking errors detected in Orderings.bpl
+EmptyCallArgs.bpl(15,17): Error: invalid type for argument 0 in call to P: int (expected: bool)
+EmptyCallArgs.bpl(26,7): Error: invalid type for out-parameter 0 in call to Q: int (expected: bool)
+EmptyCallArgs.bpl(28,7): Error: invalid type for out-parameter 0 in call to Q: int (expected: bool)
+3 type checking errors detected in EmptyCallArgs.bpl
+FunBody.bpl(6,45): Error: function body with invalid type: bool (expected: int)
+FunBody.bpl(8,61): Error: function body with invalid type: int (expected: alpha)
+FunBody.bpl(10,58): Error: function body with invalid type: int (expected: alpha)
+3 type checking errors detected in FunBody.bpl
diff --git a/Test/test1/UpdateExprTyping.bpl b/Test/test1/UpdateExprTyping.bpl
new file mode 100644
index 00000000..e495cb51
--- /dev/null
+++ b/Test/test1/UpdateExprTyping.bpl
@@ -0,0 +1,43 @@
+procedure P(a: [int]bool, b: [int]ref, c: [bool]bool)
+{
+ assert a == b; // type error
+ assert a == c; // type error
+
+ assert a == a[5 := true];
+ assert a == a[true := true]; // type error
+ assert a == a[5 := 5]; // type error in RHS
+ assert a == b[5 := null]; // type error
+}
+
+procedure Q(aa: [int,ref]bool)
+{
+ assert aa[5,null := true] != aa[2,null := false];
+ assert aa == aa[null,null := true]; // type error, index 0
+ assert aa == aa[5,true := true]; // type error, index 1
+ assert aa == aa[5,null := null]; // type error, RHS
+}
+
+type Field a;
+const unique IntField: Field int;
+const unique RefField: Field ref;
+const unique SomeField: Field any;
+
+procedure R(H: <x>[ref,Field x]x, this: ref)
+{
+ var i: int, r: ref, y: any;
+ var K: <wz>[ref,Field wz]wz;
+
+ i := H[this, IntField];
+ r := H[this, RefField];
+ y := H[this, IntField]; // type error, wrong LHS
+ y := H[this, SomeField];
+
+ K := H[this, IntField := i][this, RefField := r][this, SomeField := y];
+ K := H[this, SomeField := r]; // type error, wrong RHS
+
+ K := K[this, IntField := r]; // RHS has wrong type (ref, expecting int)
+ K := K[this, RefField := i]; // RHS has wrong type (int, expecting ref)
+}
+
+type ref, any;
+const null : ref;
diff --git a/Test/test1/WhereTyping.bpl b/Test/test1/WhereTyping.bpl
new file mode 100644
index 00000000..dba628ee
--- /dev/null
+++ b/Test/test1/WhereTyping.bpl
@@ -0,0 +1,45 @@
+var g: int where g == 12;
+
+procedure P(x: int where x > 0) returns (y: int where y < 0);
+ requires x < 100;
+ modifies g;
+ ensures -100 < y;
+
+implementation P(xx: int) returns (yy: int)
+{
+ var a: int;
+ var b: int;
+
+ start:
+ a := xx;
+ call b := P(a);
+ yy := b;
+ return;
+}
+
+type double;
+function F(double) returns (double);
+function G(double) returns (bool);
+
+procedure Q(omega: double where omega == F(omega),
+ psi: double where psi + 1 == 0, // error: psi doesn't have right type for +
+ pi: double where F(pi), // error: F has wrong return type
+ sigma: double where G(sigma));
+
+
+const SomeConstant: name;
+function fgh(int) returns (int);
+
+procedure Cnst(n: name where n <: SomeConstant /*this SomeConstant refers to the const*/) returns (SomeConstant: int)
+{
+ var k: int where k != SomeConstant; // fine, since SomeConstants refers to the out parameter
+ var m: name where m != SomeConstant; // error: types don't match up
+ var r: ref where (forall abc: int :: abc == SomeConstant);
+ var b: bool;
+ start:
+ b := (forall x: int :: fgh(x) < SomeConstant);
+ b := (forall l: name :: l == SomeConstant); // error: SomeConstant here refers to the out parameter
+ return;
+}
+
+type ref, name;
diff --git a/Test/test1/runtest.bat b/Test/test1/runtest.bat
new file mode 100644
index 00000000..c6881263
--- /dev/null
+++ b/Test/test1/runtest.bat
@@ -0,0 +1,19 @@
+@echo off
+setlocal
+
+set BGEXE=..\..\Binaries\Boogie.exe
+rem set BGEXE=mono ..\..\Binaries\Boogie.exe
+
+%BGEXE% %* /noVerify Frame0.bpl
+%BGEXE% %* /noVerify Frame1.bpl
+%BGEXE% %* /noVerify LogicalExprs.bpl
+%BGEXE% %* /noVerify Arrays.bpl
+%BGEXE% %* /noVerify WhereTyping.bpl
+%BGEXE% %* /noVerify Family.bpl
+%BGEXE% %* /noVerify AttributeTyping.bpl
+%BGEXE% %* /noVerify UpdateExprTyping.bpl
+%BGEXE% %* /noVerify CallForallResolve.bpl
+%BGEXE% %* /noVerify MapsTypeErrors.bpl
+%BGEXE% %* /noVerify Orderings.bpl
+%BGEXE% %* /noVerify EmptyCallArgs.bpl
+%BGEXE% %* /noVerify FunBody.bpl
diff --git a/Test/test13/Answer b/Test/test13/Answer
new file mode 100644
index 00000000..c8263ac1
--- /dev/null
+++ b/Test/test13/Answer
@@ -0,0 +1,15 @@
+
+-------------------- ErrorTraceTestLoopInvViolationBPL --------------------
+ErrorTraceTestLoopInvViolationBPL.bpl(7,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ ErrorTraceTestLoopInvViolationBPL.bpl(5,5): anon0
+ErrorTraceTestLoopInvViolationBPL.bpl(16,16): Error BP5004: This loop invariant might not hold on entry.
+Execution trace:
+ ErrorTraceTestLoopInvViolationBPL.bpl(14,5): anon0
+ErrorTraceTestLoopInvViolationBPL.bpl(27,17): Error BP5005: This loop invariant might not be maintained by the loop.
+Execution trace:
+ ErrorTraceTestLoopInvViolationBPL.bpl(25,5): anon0
+ ErrorTraceTestLoopInvViolationBPL.bpl(27,3): anon2_LoopHead
+ ErrorTraceTestLoopInvViolationBPL.bpl(28,7): anon2_LoopBody
+
+Boogie program verifier finished with 0 verified, 3 errors
diff --git a/Test/test13/ErrorTraceTestLoopInvViolationBPL.bpl b/Test/test13/ErrorTraceTestLoopInvViolationBPL.bpl
new file mode 100644
index 00000000..f1be4414
--- /dev/null
+++ b/Test/test13/ErrorTraceTestLoopInvViolationBPL.bpl
@@ -0,0 +1,30 @@
+// simple assert
+procedure asserting() {
+ var x: int;
+
+ x := 0;
+
+ assert x == 1;
+}
+
+// invariant failing initially
+procedure loopInvInitiallyViolated(y: int) {
+ var x: int;
+
+ x := y;
+
+ while (true) invariant (x == 1); {
+ x := 1;
+ }
+}
+
+// invariant failing after iteration
+procedure loopInvMaintenanceViolated() {
+ var x: int;
+
+ x := 0;
+
+ while (true) invariant x == 0; {
+ x := 1;
+ }
+}
diff --git a/Test/test13/Output b/Test/test13/Output
new file mode 100644
index 00000000..c8263ac1
--- /dev/null
+++ b/Test/test13/Output
@@ -0,0 +1,15 @@
+
+-------------------- ErrorTraceTestLoopInvViolationBPL --------------------
+ErrorTraceTestLoopInvViolationBPL.bpl(7,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ ErrorTraceTestLoopInvViolationBPL.bpl(5,5): anon0
+ErrorTraceTestLoopInvViolationBPL.bpl(16,16): Error BP5004: This loop invariant might not hold on entry.
+Execution trace:
+ ErrorTraceTestLoopInvViolationBPL.bpl(14,5): anon0
+ErrorTraceTestLoopInvViolationBPL.bpl(27,17): Error BP5005: This loop invariant might not be maintained by the loop.
+Execution trace:
+ ErrorTraceTestLoopInvViolationBPL.bpl(25,5): anon0
+ ErrorTraceTestLoopInvViolationBPL.bpl(27,3): anon2_LoopHead
+ ErrorTraceTestLoopInvViolationBPL.bpl(28,7): anon2_LoopBody
+
+Boogie program verifier finished with 0 verified, 3 errors
diff --git a/Test/test13/runtest.bat b/Test/test13/runtest.bat
new file mode 100644
index 00000000..e394fb2c
--- /dev/null
+++ b/Test/test13/runtest.bat
@@ -0,0 +1,11 @@
+@echo off
+setlocal
+
+set BOOGIEDIR=..\..\Binaries
+set BPLEXE=%BOOGIEDIR%\Boogie.exe
+
+for %%f in (ErrorTraceTestLoopInvViolationBPL) do (
+ echo.
+ echo -------------------- %%f --------------------
+ "%BPLEXE%" %* %%f.bpl
+)
diff --git a/Test/test15/Answer b/Test/test15/Answer
new file mode 100644
index 00000000..2054998f
--- /dev/null
+++ b/Test/test15/Answer
@@ -0,0 +1,177 @@
+
+-------------------- NullInModel --------------------
+Z3 error model:
+partitions:
+*0 -> true
+*1 -> false
+*2 {@true} -> 3:int
+*3 {@false} -> 4:int
+*4 {intType}
+*5 {boolType}
+*6 {refType}
+*7 {s null}
+*8 -> 0:int
+*9 -> 1:int
+*10 -> 2:int
+*11
+function interpretations:
+$pow2 -> {
+ *8 -> *9
+ else -> #unspecified
+}
+Ctor -> {
+ *4 -> *8
+ *5 -> *9
+ *6 -> *10
+ else -> #unspecified
+}
+type -> {
+ *7 -> *6
+ else -> #unspecified
+}
+END_OF_MODEL
+.
+identifierToPartition:
+@true : *2
+@false : *3
+intType : *4
+boolType : *5
+refType : *6
+s : *7
+null : *7
+valueToPartition:
+True : *0
+False : *1
+3 : *2
+4 : *3
+0 : *8
+1 : *9
+2 : *10
+End of model.
+NullInModel.bpl(2,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ NullInModel.bpl(2,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+
+-------------------- IntInModel --------------------
+Z3 error model:
+partitions:
+*0 -> true
+*1 -> false
+*2 {@true} -> 2:int
+*3 {@false} -> 3:int
+*4 {intType}
+*5 {boolType}
+*6 {i} -> 0:int
+*7 -> 1:int
+*8
+function interpretations:
+$pow2 -> {
+ *6 -> *7
+ else -> #unspecified
+}
+Ctor -> {
+ *4 -> *6
+ *5 -> *7
+ else -> #unspecified
+}
+END_OF_MODEL
+.
+identifierToPartition:
+@true : *2
+@false : *3
+intType : *4
+boolType : *5
+i : *6
+valueToPartition:
+True : *0
+False : *1
+2 : *2
+3 : *3
+0 : *6
+1 : *7
+End of model.
+IntInModel.bpl(2,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ IntInModel.bpl(2,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+
+-------------------- ModelTest --------------------
+Z3 error model:
+partitions:
+*0 -> true
+*1 -> false
+*2 {@true} -> 5:int
+*3 {@false} -> 6:int
+*4 {intType}
+*5 {boolType}
+*6 {refType}
+*7 {s}
+*8 {r}
+*9 {i@0} -> 1:int
+*10 {j@0} -> 2:int
+*11 {j@1} -> 3:int
+*12 {j@2} -> 4:int
+*13 -> 0:int
+*14
+function interpretations:
+$pow2 -> {
+ *13 -> *9
+ else -> #unspecified
+}
+Ctor -> {
+ *4 -> *13
+ *5 -> *9
+ *6 -> *10
+ else -> #unspecified
+}
+type -> {
+ *7 -> *6
+ *8 -> *6
+ else -> #unspecified
+}
+END_OF_MODEL
+.
+identifierToPartition:
+@true : *2
+@false : *3
+intType : *4
+boolType : *5
+refType : *6
+s : *7
+r : *8
+i@0 : *9
+j@0 : *10
+j@1 : *11
+j@2 : *12
+valueToPartition:
+True : *0
+False : *1
+5 : *2
+6 : *3
+1 : *9
+2 : *10
+3 : *11
+4 : *12
+0 : *13
+End of model.
+ModelTest.bpl(7,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ ModelTest.bpl(3,5): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+
+-------------------- InterpretedFunctionTests --------------------
+InterpretedFunctionTests.bpl(4,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ InterpretedFunctionTests.bpl(2,3): anon0
+InterpretedFunctionTests.bpl(10,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ InterpretedFunctionTests.bpl(8,3): anon0
+InterpretedFunctionTests.bpl(16,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ InterpretedFunctionTests.bpl(14,3): anon0
+
+Boogie program verifier finished with 0 verified, 3 errors
diff --git a/Test/test15/IntInModel.bpl b/Test/test15/IntInModel.bpl
new file mode 100644
index 00000000..09fc1436
--- /dev/null
+++ b/Test/test15/IntInModel.bpl
@@ -0,0 +1,3 @@
+procedure M (i: int) {
+ assert i != 0;
+}
diff --git a/Test/test15/InterpretedFunctionTests.bpl b/Test/test15/InterpretedFunctionTests.bpl
new file mode 100644
index 00000000..ec57ae8e
--- /dev/null
+++ b/Test/test15/InterpretedFunctionTests.bpl
@@ -0,0 +1,17 @@
+procedure addition(x: int, y: int) {
+ assume x == 1;
+ assume y == 2;
+ assert x + y == 4;
+}
+
+procedure subtraction(x: int, y: int) {
+ assume x == 1;
+ assume y == 2;
+ assert x - y == 4; //only shows x-y == -1 when run with /method:subtraction, WHY???
+}
+
+procedure multiplication(x: int, y: int) {
+ assume x == 1;
+ assume y == 2;
+ assert x * y == 4;
+}
diff --git a/Test/test15/ModelTest.bpl b/Test/test15/ModelTest.bpl
new file mode 100644
index 00000000..6f03d0bd
--- /dev/null
+++ b/Test/test15/ModelTest.bpl
@@ -0,0 +1,10 @@
+procedure M (s : ref, r : ref) {
+ var i : int, j : int;
+ i := 0 + 1;
+ j := i + 1;
+ j := j + 1;
+ j := j + 1;
+ assert i == j;
+ assert s == r;
+}
+type ref;
diff --git a/Test/test15/NullInModel.bpl b/Test/test15/NullInModel.bpl
new file mode 100644
index 00000000..67c34e3d
--- /dev/null
+++ b/Test/test15/NullInModel.bpl
@@ -0,0 +1,5 @@
+procedure M (s: ref) {
+ assert s != null;
+}
+type ref;
+const null: ref;
diff --git a/Test/test15/Output b/Test/test15/Output
new file mode 100644
index 00000000..2054998f
--- /dev/null
+++ b/Test/test15/Output
@@ -0,0 +1,177 @@
+
+-------------------- NullInModel --------------------
+Z3 error model:
+partitions:
+*0 -> true
+*1 -> false
+*2 {@true} -> 3:int
+*3 {@false} -> 4:int
+*4 {intType}
+*5 {boolType}
+*6 {refType}
+*7 {s null}
+*8 -> 0:int
+*9 -> 1:int
+*10 -> 2:int
+*11
+function interpretations:
+$pow2 -> {
+ *8 -> *9
+ else -> #unspecified
+}
+Ctor -> {
+ *4 -> *8
+ *5 -> *9
+ *6 -> *10
+ else -> #unspecified
+}
+type -> {
+ *7 -> *6
+ else -> #unspecified
+}
+END_OF_MODEL
+.
+identifierToPartition:
+@true : *2
+@false : *3
+intType : *4
+boolType : *5
+refType : *6
+s : *7
+null : *7
+valueToPartition:
+True : *0
+False : *1
+3 : *2
+4 : *3
+0 : *8
+1 : *9
+2 : *10
+End of model.
+NullInModel.bpl(2,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ NullInModel.bpl(2,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+
+-------------------- IntInModel --------------------
+Z3 error model:
+partitions:
+*0 -> true
+*1 -> false
+*2 {@true} -> 2:int
+*3 {@false} -> 3:int
+*4 {intType}
+*5 {boolType}
+*6 {i} -> 0:int
+*7 -> 1:int
+*8
+function interpretations:
+$pow2 -> {
+ *6 -> *7
+ else -> #unspecified
+}
+Ctor -> {
+ *4 -> *6
+ *5 -> *7
+ else -> #unspecified
+}
+END_OF_MODEL
+.
+identifierToPartition:
+@true : *2
+@false : *3
+intType : *4
+boolType : *5
+i : *6
+valueToPartition:
+True : *0
+False : *1
+2 : *2
+3 : *3
+0 : *6
+1 : *7
+End of model.
+IntInModel.bpl(2,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ IntInModel.bpl(2,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+
+-------------------- ModelTest --------------------
+Z3 error model:
+partitions:
+*0 -> true
+*1 -> false
+*2 {@true} -> 5:int
+*3 {@false} -> 6:int
+*4 {intType}
+*5 {boolType}
+*6 {refType}
+*7 {s}
+*8 {r}
+*9 {i@0} -> 1:int
+*10 {j@0} -> 2:int
+*11 {j@1} -> 3:int
+*12 {j@2} -> 4:int
+*13 -> 0:int
+*14
+function interpretations:
+$pow2 -> {
+ *13 -> *9
+ else -> #unspecified
+}
+Ctor -> {
+ *4 -> *13
+ *5 -> *9
+ *6 -> *10
+ else -> #unspecified
+}
+type -> {
+ *7 -> *6
+ *8 -> *6
+ else -> #unspecified
+}
+END_OF_MODEL
+.
+identifierToPartition:
+@true : *2
+@false : *3
+intType : *4
+boolType : *5
+refType : *6
+s : *7
+r : *8
+i@0 : *9
+j@0 : *10
+j@1 : *11
+j@2 : *12
+valueToPartition:
+True : *0
+False : *1
+5 : *2
+6 : *3
+1 : *9
+2 : *10
+3 : *11
+4 : *12
+0 : *13
+End of model.
+ModelTest.bpl(7,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ ModelTest.bpl(3,5): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+
+-------------------- InterpretedFunctionTests --------------------
+InterpretedFunctionTests.bpl(4,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ InterpretedFunctionTests.bpl(2,3): anon0
+InterpretedFunctionTests.bpl(10,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ InterpretedFunctionTests.bpl(8,3): anon0
+InterpretedFunctionTests.bpl(16,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ InterpretedFunctionTests.bpl(14,3): anon0
+
+Boogie program verifier finished with 0 verified, 3 errors
diff --git a/Test/test15/runtest.bat b/Test/test15/runtest.bat
new file mode 100644
index 00000000..90771065
--- /dev/null
+++ b/Test/test15/runtest.bat
@@ -0,0 +1,16 @@
+@echo off
+setlocal
+
+set BOOGIEDIR=..\..\Binaries
+set BGEXE=%BOOGIEDIR%\boogie.exe
+
+for %%f in (NullInModel IntInModel ModelTest) do (
+ echo.
+ echo -------------------- %%f --------------------
+ "%BGEXE%" %* %%f.bpl /printModel:2
+)
+for %%f in (InterpretedFunctionTests) do (
+ echo.
+ echo -------------------- %%f --------------------
+ "%BGEXE%" %* %%f.bpl
+)
diff --git a/Test/test16/Answer b/Test/test16/Answer
new file mode 100644
index 00000000..5fac425b
--- /dev/null
+++ b/Test/test16/Answer
@@ -0,0 +1,23 @@
+-------------------- LoopUnroll.bpl /loopUnroll:1 --------------------
+LoopUnroll.bpl(56,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ LoopUnroll.bpl(52,5): anon0#1
+ LoopUnroll.bpl(53,3): anon2_LoopHead#1
+ LoopUnroll.bpl(55,5): anon2_LoopBody#1
+
+Boogie program verifier finished with 2 verified, 1 error
+-------------------- LoopUnroll.bpl /loopUnroll:2 --------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
+-------------------- LoopUnroll.bpl /loopUnroll:3 --------------------
+LoopUnroll.bpl(74,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ LoopUnroll.bpl(68,5): anon0#3
+ LoopUnroll.bpl(69,3): anon2_LoopHead#3
+ LoopUnroll.bpl(71,5): anon2_LoopBody#3
+ LoopUnroll.bpl(69,3): anon2_LoopHead#2
+ LoopUnroll.bpl(71,5): anon2_LoopBody#2
+ LoopUnroll.bpl(69,3): anon2_LoopHead#1
+ LoopUnroll.bpl(71,5): anon2_LoopBody#1
+
+Boogie program verifier finished with 0 verified, 1 error
diff --git a/Test/test16/LoopUnroll.bpl b/Test/test16/LoopUnroll.bpl
new file mode 100644
index 00000000..83bf2686
--- /dev/null
+++ b/Test/test16/LoopUnroll.bpl
@@ -0,0 +1,79 @@
+procedure P()
+{
+ var x: int;
+
+ A:
+ x := 0;
+ goto B, Goner, C;
+
+ B:
+ x := 1;
+ goto D;
+
+ C:
+ x := 2;
+ goto D;
+
+ Goner:
+ x := 5;
+ assume false;
+ x := 6;
+ goto B;
+
+ D:
+ x := 3;
+ goto LoopHead;
+
+ LoopHead:
+ assert x < 100;
+ goto LoopBody, LoopDone;
+
+ LoopBody:
+ x := x + 1;
+ goto LoopHead, LoopBodyMore;
+
+ LoopBodyMore:
+ x := x + 2;
+ goto LoopHead;
+
+ LoopDone:
+ x := 88;
+ return;
+}
+
+type MyValue;
+const SpecialValue: MyValue;
+
+procedure WrongRange(a: [int]MyValue, N: int)
+ requires 0 <= N;
+{
+ var i: int, v: MyValue;
+
+ i := 1; // bad idea
+ while (i <= N) // also a bad idea
+ {
+ assert 0 <= i; // lower bounds check
+ assert i < N; // error: upper bounds check
+ v := a[i];
+ i := i + 1;
+ }
+}
+
+procedure ManyIterations(a: [int]MyValue, N: int)
+ requires 0 <= N;
+ requires a[0] != SpecialValue && a[1] != SpecialValue;
+{
+ var i: int, v: MyValue;
+
+ i := 0;
+ while (i < N)
+ {
+ assert 0 <= i; // lower bounds check
+ assert i < N; // upper bounds check
+ v := a[i];
+ assert a[i] != SpecialValue; // error: after more than 2 loop unrollings
+ i := i + 1;
+ }
+}
+
+// ERROR: /printInstrumented seems to erase filename source-location information
diff --git a/Test/test16/Output b/Test/test16/Output
new file mode 100644
index 00000000..5fac425b
--- /dev/null
+++ b/Test/test16/Output
@@ -0,0 +1,23 @@
+-------------------- LoopUnroll.bpl /loopUnroll:1 --------------------
+LoopUnroll.bpl(56,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ LoopUnroll.bpl(52,5): anon0#1
+ LoopUnroll.bpl(53,3): anon2_LoopHead#1
+ LoopUnroll.bpl(55,5): anon2_LoopBody#1
+
+Boogie program verifier finished with 2 verified, 1 error
+-------------------- LoopUnroll.bpl /loopUnroll:2 --------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
+-------------------- LoopUnroll.bpl /loopUnroll:3 --------------------
+LoopUnroll.bpl(74,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ LoopUnroll.bpl(68,5): anon0#3
+ LoopUnroll.bpl(69,3): anon2_LoopHead#3
+ LoopUnroll.bpl(71,5): anon2_LoopBody#3
+ LoopUnroll.bpl(69,3): anon2_LoopHead#2
+ LoopUnroll.bpl(71,5): anon2_LoopBody#2
+ LoopUnroll.bpl(69,3): anon2_LoopHead#1
+ LoopUnroll.bpl(71,5): anon2_LoopBody#1
+
+Boogie program verifier finished with 0 verified, 1 error
diff --git a/Test/test16/runtest.bat b/Test/test16/runtest.bat
new file mode 100644
index 00000000..069ecd63
--- /dev/null
+++ b/Test/test16/runtest.bat
@@ -0,0 +1,13 @@
+@echo off
+setlocal
+
+set BOOGIEDIR=..\..\Binaries
+set BPLEXE=%BOOGIEDIR%\Boogie.exe
+
+echo -------------------- LoopUnroll.bpl /loopUnroll:1 --------------------
+"%BPLEXE%" %* /loopUnroll:1 /logPrefix:-lu1 LoopUnroll.bpl
+echo -------------------- LoopUnroll.bpl /loopUnroll:2 --------------------
+"%BPLEXE%" %* LoopUnroll.bpl /logPrefix:-lu2 /proc:ManyIterations /loopUnroll:2
+echo -------------------- LoopUnroll.bpl /loopUnroll:3 --------------------
+"%BPLEXE%" %* LoopUnroll.bpl /logPrefix:-lu3 /proc:ManyIterations /loopUnroll:3
+
diff --git a/Test/test17/Answer b/Test/test17/Answer
new file mode 100644
index 00000000..8a1a816b
--- /dev/null
+++ b/Test/test17/Answer
@@ -0,0 +1,8 @@
+
+-------------------- contractinfer --------------------
+
+Boogie program verifier finished with 2 verified, 0 errors
+
+-------------------- flpydisk --------------------
+
+Boogie program verifier finished with 2 verified, 0 errors
diff --git a/Test/test17/contractinfer.bpl b/Test/test17/contractinfer.bpl
new file mode 100644
index 00000000..aeec020a
--- /dev/null
+++ b/Test/test17/contractinfer.bpl
@@ -0,0 +1,24 @@
+const {:existential true} b1:bool;
+const {:existential true} b2:bool;
+const {:existential true} b3:bool;
+const {:existential true} b4:bool;
+
+var array:[int]int;
+
+procedure foo (i:int)
+requires b2 ==> i > 0;
+ensures b3 ==> array[i] > 0;
+modifies array;
+ensures (forall x:int :: {array[x]} x == i || array[x] == old(array)[x]);
+{
+ array[i] := 2 * i;
+}
+
+procedure bar (j:int) returns (result:int)
+requires b4 ==> j > 0;
+modifies array;
+ensures (forall x:int :: {array[x]} (b1 && x == j) || array[x] == old(array)[x]);
+{
+ call foo(j);
+ result := array[j];
+} \ No newline at end of file
diff --git a/Test/test17/flpydisk.bpl b/Test/test17/flpydisk.bpl
new file mode 100644
index 00000000..4883f080
--- /dev/null
+++ b/Test/test17/flpydisk.bpl
@@ -0,0 +1,2295 @@
+type ptr;
+function Ptr(ref, int) returns (ptr);
+function Obj(ptr) returns (ref);
+function Off(ptr) returns (int);
+
+// Ptr, Obj, Off axioms
+axiom(forall x:ptr :: {Obj(x)}{Off(x)} x == Ptr(Obj(x), Off(x)));
+axiom(forall x_obj:ref, x_off:int :: {Ptr(x_obj, x_off)} x_obj == Obj(Ptr(x_obj, x_off)));
+axiom(forall x_obj:ref, x_off:int :: {Ptr(x_obj, x_off)} x_off == Off(Ptr(x_obj, x_off)));
+
+// Mutable
+var Mem:[ptr]ptr;
+var alloc:[ref]name;
+var BS:[ptr]bool;
+const field:[ptr]name;
+
+// Immutable
+function Size(ref) returns (int);
+function Type(ref) returns (int);
+function IsHeap(ref) returns (bool); //if the object was allocated by malloc or allocation due to address taken
+
+// Constants
+const unique UNALLOCATED:name;
+const unique ALLOCATED:name;
+
+function In(ptr, [ptr]bool) returns (bool);
+function Subset([ptr]bool, [ptr]bool) returns (bool);
+//function Equal([ptr]bool, [ptr]bool) returns (bool);
+function Disjoint([ptr]bool, [ptr]bool) returns (bool);
+//function UniqueDereference([ptr]bool, [ptr]ptr, ptr) returns (bool);
+
+//function Element(a:ptr) returns (bool);
+//axiom(forall a:ptr, S:[ptr]bool :: {In(a,S)} Element(a));
+
+function Empty() returns ([ptr]bool);
+function Singleton(ptr) returns ([ptr]bool);
+function Reachable([ptr,ptr]bool, ptr) returns ([ptr]bool);
+function Union([ptr]bool, [ptr]bool) returns ([ptr]bool);
+function Intersection([ptr]bool, [ptr]bool) returns ([ptr]bool);
+function Difference([ptr]bool, [ptr]bool) returns ([ptr]bool);
+function Decrement([ptr]bool, int) returns ([ptr]bool);
+function Increment([ptr]bool, int) returns ([ptr]bool);
+function Dereference([ptr]bool, [ptr]ptr) returns ([ptr]bool);
+function Array(ptr, int, ptr) returns ([ptr]bool);
+function Array1(ptr, ptr) returns ([ptr]bool);
+
+
+axiom(forall x:ptr :: !In(x, Empty()));
+
+axiom(forall x:ptr, y:ptr :: {In(x, Singleton(y))} In(x, Singleton(y)) ==> x == y);
+axiom(forall y:ptr :: {Singleton(y)} In(y, Singleton(y)));
+
+/* this formulation of Union IS more complete than the earlier one */
+/* In(e, A U B), In(d, A), A U B = Singleton(c), d != e */
+axiom(forall x:ptr, S:[ptr]bool, T:[ptr]bool :: {In(x, Union(S,T))} In(x, Union(S,T)) ==> In(x, S) || In(x,T));
+axiom(forall x:ptr, S:[ptr]bool, T:[ptr]bool :: {Union(S,T), In(x,S)} In(x, S) ==> In(x, Union(S,T)));
+axiom(forall x:ptr, S:[ptr]bool, T:[ptr]bool :: {Union(S,T), In(x,T)} In(x, T) ==> In(x, Union(S,T)));
+
+axiom(forall x:ptr, S:[ptr]bool, T:[ptr]bool :: {In(x,S), In(x,T), Intersection(S,T)} In(x,S) && In(x,T) ==> In(x, Intersection(S,T)));
+axiom(forall x:ptr, S:[ptr]bool, T:[ptr]bool :: {In(x,Intersection(S,T))} In(x, Intersection(S,T)) ==> In(x,S) && In(x,T));
+
+axiom(forall x:ptr, S:[ptr]bool, T:[ptr]bool :: {Difference(S,T), In(x,S)} In(x, S) ==> In(x, Difference(S,T)) || In(x,T));
+axiom(forall x:ptr, S:[ptr]bool, T:[ptr]bool :: {In(x,Difference(S,T))} In(x, Difference(S,T)) ==> In(x, S));
+axiom(forall x:ptr, S:[ptr]bool, T:[ptr]bool :: {In(x,Difference(S,T)), In(x,T)} !(In(x, Difference(S,T)) && In(x,T)));
+
+axiom(forall x:ptr, n:int, S:[ptr]bool :: {In(x, Decrement(S,n))} In(x, Decrement(S,n)) <==> In(Ptr(Obj(x),Off(x)+n),S));
+axiom(forall x:ptr, n:int, S:[ptr]bool :: {In(x, Increment(S,n))} In(x, Increment(S,n)) <==> In(Ptr(Obj(x),Off(x)-n),S));
+
+axiom(forall x:ptr, S:[ptr]bool, M:[ptr]ptr :: {In(x, Dereference(S,M))} In(x, Dereference(S,M)) ==> (exists y:ptr :: x == M[y] && In(y,S)));
+axiom(forall x:ptr, S:[ptr]bool, M:[ptr]ptr :: {M[x], In(x, S), Dereference(S,M)} In(x, S) ==> In(M[x], Dereference(S,M)));
+
+axiom(forall a:ptr, x:ptr, n:int, z:ptr :: {In(a,Array(x,n,z))}
+ In(a,Array(x,n,z)) ==>
+ (Obj(a) == Obj(x) && Obj(z) == null && (exists k:int :: 0 <= k && k < Off(z) && Off(a) == Off(x) + n*k)));
+
+axiom(forall a:ptr, x:ptr, n:int, z:ptr :: {In(a, Array(x,n,z))}
+ In(a, Array(x,n,z)) ==> (exists k:int :: 0 <= k && a == PLUS(x,n,Ptr(null,k))));
+axiom(forall x:ptr, n:int, z:ptr :: {Array(x,n,z)} Obj(z) == null && Off(z) > 0 ==> In(x, Array(x,n,z)));
+axiom(forall x:ptr, n:int, y:ptr, z:ptr :: {PLUS(x,n,y), Array(x,n,z)}
+ Obj(y) == null && Obj(z) == null && Off(x) <= Off(PLUS(x,n,y)) && Off(PLUS(x,n,y)) < Off(PLUS(x,n,z)) <==> In(PLUS(x,n,y), Array(x,n,z)));
+
+axiom(forall x:ptr, y:ptr, z:ptr :: {In(x,Array1(y,z))}
+ In(x,Array1(y,z)) <==>
+ (Obj(x) == Obj(y) && Off(y) <= Off(x) && Off(x) < Off(y) + Off(z)));
+
+
+/*
+axiom(forall x:ptr :: !In(x, Empty()));
+axiom(forall x:ptr, y:ptr :: {In(x, Singleton(y))} In(x, Singleton(y)) <==> x == y);
+
+axiom(forall x:ptr, S:[ptr]bool, T:[ptr]bool :: {In(x, Union(S,T))} In(x, Union(S,T)) <==> In(x, S) || In(x,T));
+axiom(forall x:ptr, S:[ptr]bool, T:[ptr]bool :: {Union(S,T), In(x,S)} In(x, S) ==> In(x, Union(S,T)));
+axiom(forall x:ptr, S:[ptr]bool, T:[ptr]bool :: {Union(S,T), In(x,T)} In(x, T) ==> In(x, Union(S,T)));
+
+axiom(forall x:ptr, S:[ptr]bool, T:[ptr]bool :: {In(x, Difference(S,T))} In(x, Difference(S,T)) <==> In(x, S) && !In(x,T));
+axiom(forall x:ptr, S:[ptr]bool, T:[ptr]bool :: {Difference(S,T), In(x,S), In(x,T)} (In(x, S) && !In(x,T)) ==> In(x, Difference(S,T)));
+
+axiom(forall x:ptr, n:int, S:[ptr]bool :: {In(x, Decrement(S,n))} In(x, Decrement(S,n)) <==> In(Ptr(Obj(x),Off(x)+n),S));
+axiom(forall x:ptr, n:int, S:[ptr]bool :: {In(x, Increment(S,n))} In(x, Increment(S,n)) <==> In(Ptr(Obj(x),Off(x)-n),S));
+axiom(forall x:ptr, S:[ptr]bool, M:[ptr]ptr :: {In(x, Dereference(S,M))} In(x, Dereference(S,M)) <==> (exists y:ptr :: x == M[y] && In(y,S)));
+axiom(forall x:ptr, S:[ptr]bool, M:[ptr]ptr :: {In(x, S), Dereference(S,M)} In(x, S) ==> In(M[x], Dereference(S,M)));
+
+axiom(forall a:ptr, x:ptr, n:int, z:ptr :: {In(a,Array(x,n,z))}
+ In(a,Array(x,n,z)) ==>
+ (Obj(a) == Obj(x) && Obj(z) == null && (exists k:int :: 0 <= k && k < Off(z) && Off(a) == Off(x) + n*k)));
+
+axiom(forall a:ptr, x:ptr, n:int, z:ptr :: {In(a, Array(x,n,z))}
+ In(a, Array(x,n,z)) ==> (exists k:int :: 0 <= k && a == PLUS(x,n,Ptr(null,k))));
+axiom(forall x:ptr, n:int, z:ptr :: {Array(x,n,z)} Obj(z) == null && Off(z) > 0 ==> In(x, Array(x,n,z)));
+axiom(forall x:ptr, n:int, y:ptr, z:ptr :: {PLUS(x,n,y), Array(x,n,z)}
+ Obj(y) == null && Obj(z) == null && Off(x) <= Off(PLUS(x,n,y)) && Off(PLUS(x,n,y)) < Off(PLUS(x,n,z)) <==> In(PLUS(x,n,y), Array(x,n,z)));
+
+axiom(forall x:ptr, y:ptr, z:ptr :: {In(x,Array1(y,z))}
+ In(x,Array1(y,z)) <==>
+ (Obj(x) == Obj(y) && Off(y) <= Off(x) && Off(x) < Off(y) + Off(z)));
+*/
+
+axiom(forall x:ptr, S:[ptr]bool, T:[ptr]bool :: {In(x,S), Subset(S,T)} In(x,S) && Subset(S,T) ==> In(x,T));
+axiom(forall S:[ptr]bool, T:[ptr]bool :: {Subset(S,T)} Subset(S,T) || (exists x:ptr :: In(x,S) && !In(x,T)));
+axiom(forall x:ptr, S:[ptr]bool, T:[ptr]bool :: {In(x,S), Disjoint(S,T), In(x,T)} !(In(x,S) && Disjoint(S,T) && In(x,T)));
+axiom(forall S:[ptr]bool, T:[ptr]bool :: {Disjoint(S,T)} Disjoint(S,T) || (exists x:ptr :: In(x,S) && In(x,T)));
+
+/*
+axiom(forall S:[ptr]bool, T:[ptr]bool :: {Subset(S,T)} Subset(S,T) <==> (forall x:ptr :: In(x,S) ==> In(x,T)));
+axiom(forall S:[ptr]bool, T:[ptr]bool :: {Equal(S,T)} Equal(S,T) <==> Subset(T,S) && Subset(S,T));
+axiom(forall S:[ptr]bool, T:[ptr]bool :: {Disjoint(S,T)} Disjoint(S,T) <==> (forall x:ptr :: !(In(x,S) && In(x,T))));
+axiom(forall S:[ptr]bool, M:[ptr]ptr, p:ptr :: {UniqueDereference(S,M,p)}
+ UniqueDereference(S,M,p) <==>
+ (forall x:ptr, y:ptr :: {M[x],M[y]} In(x,S) && In(y,S) && M[x] == M[y] ==> x == y || M[x] == p));
+*/
+
+
+function ByteCapacity__DISKETTE_EXTENSION(ptr) returns (ptr);
+function home_ByteCapacity__DISKETTE_EXTENSION(ptr) returns (ptr);
+function _S_ByteCapacity__DISKETTE_EXTENSION([ptr]bool) returns ([ptr]bool);
+function _S_home_ByteCapacity__DISKETTE_EXTENSION([ptr]bool) returns ([ptr]bool);
+
+axiom (forall x:ptr :: {ByteCapacity__DISKETTE_EXTENSION(x)} home_ByteCapacity__DISKETTE_EXTENSION(ByteCapacity__DISKETTE_EXTENSION(x)) == x);
+axiom (forall x:ptr :: {home_ByteCapacity__DISKETTE_EXTENSION(x)} ByteCapacity__DISKETTE_EXTENSION(home_ByteCapacity__DISKETTE_EXTENSION(x)) == x);
+axiom (forall x:ptr :: {ByteCapacity__DISKETTE_EXTENSION(x)} ByteCapacity__DISKETTE_EXTENSION(x) == Ptr(Obj(x), Off(x) + 152));
+axiom (forall x:ptr :: {home_ByteCapacity__DISKETTE_EXTENSION(x)} home_ByteCapacity__DISKETTE_EXTENSION(x) == Ptr(Obj(x), Off(x) - 152));
+
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, _S_ByteCapacity__DISKETTE_EXTENSION(S))} In(x, _S_ByteCapacity__DISKETTE_EXTENSION(S)) ==> In(home_ByteCapacity__DISKETTE_EXTENSION(x), S));
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, _S_home_ByteCapacity__DISKETTE_EXTENSION(S))} In(x, _S_home_ByteCapacity__DISKETTE_EXTENSION(S)) ==> In(ByteCapacity__DISKETTE_EXTENSION(x), S));
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, S), _S_ByteCapacity__DISKETTE_EXTENSION(S)} In(x, S) ==> In(ByteCapacity__DISKETTE_EXTENSION(x), _S_ByteCapacity__DISKETTE_EXTENSION(S)));
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, S), _S_home_ByteCapacity__DISKETTE_EXTENSION(S)} In(x, S) ==> In(home_ByteCapacity__DISKETTE_EXTENSION(x), _S_home_ByteCapacity__DISKETTE_EXTENSION(S)));
+
+axiom (forall x:ptr :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, Ptr(null,152), 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, Ptr(null,152), 1) == home_ByteCapacity__DISKETTE_EXTENSION(x));
+axiom (forall x:ptr :: {MINUS_LEFT_PTR(x, 1, Ptr(null,152))} MINUS_LEFT_PTR(x, 1, Ptr(null,152)) == home_ByteCapacity__DISKETTE_EXTENSION(x));
+
+
+
+
+
+function ByteOffset___unnamed_16_39e6661e(ptr) returns (ptr);
+function home_ByteOffset___unnamed_16_39e6661e(ptr) returns (ptr);
+function _S_ByteOffset___unnamed_16_39e6661e([ptr]bool) returns ([ptr]bool);
+function _S_home_ByteOffset___unnamed_16_39e6661e([ptr]bool) returns ([ptr]bool);
+
+axiom (forall x:ptr :: {ByteOffset___unnamed_16_39e6661e(x)} home_ByteOffset___unnamed_16_39e6661e(ByteOffset___unnamed_16_39e6661e(x)) == x);
+axiom (forall x:ptr :: {home_ByteOffset___unnamed_16_39e6661e(x)} ByteOffset___unnamed_16_39e6661e(home_ByteOffset___unnamed_16_39e6661e(x)) == x);
+axiom (forall x:ptr :: {ByteOffset___unnamed_16_39e6661e(x)} ByteOffset___unnamed_16_39e6661e(x) == Ptr(Obj(x), Off(x) + 8));
+axiom (forall x:ptr :: {home_ByteOffset___unnamed_16_39e6661e(x)} home_ByteOffset___unnamed_16_39e6661e(x) == Ptr(Obj(x), Off(x) - 8));
+
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, _S_ByteOffset___unnamed_16_39e6661e(S))} In(x, _S_ByteOffset___unnamed_16_39e6661e(S)) ==> In(home_ByteOffset___unnamed_16_39e6661e(x), S));
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, _S_home_ByteOffset___unnamed_16_39e6661e(S))} In(x, _S_home_ByteOffset___unnamed_16_39e6661e(S)) ==> In(ByteOffset___unnamed_16_39e6661e(x), S));
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, S), _S_ByteOffset___unnamed_16_39e6661e(S)} In(x, S) ==> In(ByteOffset___unnamed_16_39e6661e(x), _S_ByteOffset___unnamed_16_39e6661e(S)));
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, S), _S_home_ByteOffset___unnamed_16_39e6661e(S)} In(x, S) ==> In(home_ByteOffset___unnamed_16_39e6661e(x), _S_home_ByteOffset___unnamed_16_39e6661e(S)));
+
+axiom (forall x:ptr :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, Ptr(null,8), 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, Ptr(null,8), 1) == home_ByteOffset___unnamed_16_39e6661e(x));
+axiom (forall x:ptr :: {MINUS_LEFT_PTR(x, 1, Ptr(null,8))} MINUS_LEFT_PTR(x, 1, Ptr(null,8)) == home_ByteOffset___unnamed_16_39e6661e(x));
+
+
+
+
+
+function BytesPerSector__DISKETTE_EXTENSION(ptr) returns (ptr);
+function home_BytesPerSector__DISKETTE_EXTENSION(ptr) returns (ptr);
+function _S_BytesPerSector__DISKETTE_EXTENSION([ptr]bool) returns ([ptr]bool);
+function _S_home_BytesPerSector__DISKETTE_EXTENSION([ptr]bool) returns ([ptr]bool);
+
+axiom (forall x:ptr :: {BytesPerSector__DISKETTE_EXTENSION(x)} home_BytesPerSector__DISKETTE_EXTENSION(BytesPerSector__DISKETTE_EXTENSION(x)) == x);
+axiom (forall x:ptr :: {home_BytesPerSector__DISKETTE_EXTENSION(x)} BytesPerSector__DISKETTE_EXTENSION(home_BytesPerSector__DISKETTE_EXTENSION(x)) == x);
+axiom (forall x:ptr :: {BytesPerSector__DISKETTE_EXTENSION(x)} BytesPerSector__DISKETTE_EXTENSION(x) == Ptr(Obj(x), Off(x) + 148));
+axiom (forall x:ptr :: {home_BytesPerSector__DISKETTE_EXTENSION(x)} home_BytesPerSector__DISKETTE_EXTENSION(x) == Ptr(Obj(x), Off(x) - 148));
+
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, _S_BytesPerSector__DISKETTE_EXTENSION(S))} In(x, _S_BytesPerSector__DISKETTE_EXTENSION(S)) ==> In(home_BytesPerSector__DISKETTE_EXTENSION(x), S));
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, _S_home_BytesPerSector__DISKETTE_EXTENSION(S))} In(x, _S_home_BytesPerSector__DISKETTE_EXTENSION(S)) ==> In(BytesPerSector__DISKETTE_EXTENSION(x), S));
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, S), _S_BytesPerSector__DISKETTE_EXTENSION(S)} In(x, S) ==> In(BytesPerSector__DISKETTE_EXTENSION(x), _S_BytesPerSector__DISKETTE_EXTENSION(S)));
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, S), _S_home_BytesPerSector__DISKETTE_EXTENSION(S)} In(x, S) ==> In(home_BytesPerSector__DISKETTE_EXTENSION(x), _S_home_BytesPerSector__DISKETTE_EXTENSION(S)));
+
+axiom (forall x:ptr :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, Ptr(null,148), 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, Ptr(null,148), 1) == home_BytesPerSector__DISKETTE_EXTENSION(x));
+axiom (forall x:ptr :: {MINUS_LEFT_PTR(x, 1, Ptr(null,148))} MINUS_LEFT_PTR(x, 1, Ptr(null,148)) == home_BytesPerSector__DISKETTE_EXTENSION(x));
+
+
+
+
+
+function CancelRoutine__IRP(ptr) returns (ptr);
+function home_CancelRoutine__IRP(ptr) returns (ptr);
+function _S_CancelRoutine__IRP([ptr]bool) returns ([ptr]bool);
+function _S_home_CancelRoutine__IRP([ptr]bool) returns ([ptr]bool);
+
+axiom (forall x:ptr :: {CancelRoutine__IRP(x)} home_CancelRoutine__IRP(CancelRoutine__IRP(x)) == x);
+axiom (forall x:ptr :: {home_CancelRoutine__IRP(x)} CancelRoutine__IRP(home_CancelRoutine__IRP(x)) == x);
+axiom (forall x:ptr :: {CancelRoutine__IRP(x)} CancelRoutine__IRP(x) == Ptr(Obj(x), Off(x) + 56));
+axiom (forall x:ptr :: {home_CancelRoutine__IRP(x)} home_CancelRoutine__IRP(x) == Ptr(Obj(x), Off(x) - 56));
+
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, _S_CancelRoutine__IRP(S))} In(x, _S_CancelRoutine__IRP(S)) ==> In(home_CancelRoutine__IRP(x), S));
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, _S_home_CancelRoutine__IRP(S))} In(x, _S_home_CancelRoutine__IRP(S)) ==> In(CancelRoutine__IRP(x), S));
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, S), _S_CancelRoutine__IRP(S)} In(x, S) ==> In(CancelRoutine__IRP(x), _S_CancelRoutine__IRP(S)));
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, S), _S_home_CancelRoutine__IRP(S)} In(x, S) ==> In(home_CancelRoutine__IRP(x), _S_home_CancelRoutine__IRP(S)));
+
+axiom (forall x:ptr :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, Ptr(null,56), 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, Ptr(null,56), 1) == home_CancelRoutine__IRP(x));
+axiom (forall x:ptr :: {MINUS_LEFT_PTR(x, 1, Ptr(null,56))} MINUS_LEFT_PTR(x, 1, Ptr(null,56)) == home_CancelRoutine__IRP(x));
+
+
+
+
+
+function Cancel__IRP(ptr) returns (ptr);
+function home_Cancel__IRP(ptr) returns (ptr);
+function _S_Cancel__IRP([ptr]bool) returns ([ptr]bool);
+function _S_home_Cancel__IRP([ptr]bool) returns ([ptr]bool);
+
+axiom (forall x:ptr :: {Cancel__IRP(x)} home_Cancel__IRP(Cancel__IRP(x)) == x);
+axiom (forall x:ptr :: {home_Cancel__IRP(x)} Cancel__IRP(home_Cancel__IRP(x)) == x);
+axiom (forall x:ptr :: {Cancel__IRP(x)} Cancel__IRP(x) == Ptr(Obj(x), Off(x) + 36));
+axiom (forall x:ptr :: {home_Cancel__IRP(x)} home_Cancel__IRP(x) == Ptr(Obj(x), Off(x) - 36));
+
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, _S_Cancel__IRP(S))} In(x, _S_Cancel__IRP(S)) ==> In(home_Cancel__IRP(x), S));
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, _S_home_Cancel__IRP(S))} In(x, _S_home_Cancel__IRP(S)) ==> In(Cancel__IRP(x), S));
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, S), _S_Cancel__IRP(S)} In(x, S) ==> In(Cancel__IRP(x), _S_Cancel__IRP(S)));
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, S), _S_home_Cancel__IRP(S)} In(x, S) ==> In(home_Cancel__IRP(x), _S_home_Cancel__IRP(S)));
+
+axiom (forall x:ptr :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, Ptr(null,36), 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, Ptr(null,36), 1) == home_Cancel__IRP(x));
+axiom (forall x:ptr :: {MINUS_LEFT_PTR(x, 1, Ptr(null,36))} MINUS_LEFT_PTR(x, 1, Ptr(null,36)) == home_Cancel__IRP(x));
+
+
+
+
+
+function Control__IO_STACK_LOCATION(ptr) returns (ptr);
+function home_Control__IO_STACK_LOCATION(ptr) returns (ptr);
+function _S_Control__IO_STACK_LOCATION([ptr]bool) returns ([ptr]bool);
+function _S_home_Control__IO_STACK_LOCATION([ptr]bool) returns ([ptr]bool);
+
+axiom (forall x:ptr :: {Control__IO_STACK_LOCATION(x)} home_Control__IO_STACK_LOCATION(Control__IO_STACK_LOCATION(x)) == x);
+axiom (forall x:ptr :: {home_Control__IO_STACK_LOCATION(x)} Control__IO_STACK_LOCATION(home_Control__IO_STACK_LOCATION(x)) == x);
+axiom (forall x:ptr :: {Control__IO_STACK_LOCATION(x)} Control__IO_STACK_LOCATION(x) == Ptr(Obj(x), Off(x) + 3));
+axiom (forall x:ptr :: {home_Control__IO_STACK_LOCATION(x)} home_Control__IO_STACK_LOCATION(x) == Ptr(Obj(x), Off(x) - 3));
+
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, _S_Control__IO_STACK_LOCATION(S))} In(x, _S_Control__IO_STACK_LOCATION(S)) ==> In(home_Control__IO_STACK_LOCATION(x), S));
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, _S_home_Control__IO_STACK_LOCATION(S))} In(x, _S_home_Control__IO_STACK_LOCATION(S)) ==> In(Control__IO_STACK_LOCATION(x), S));
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, S), _S_Control__IO_STACK_LOCATION(S)} In(x, S) ==> In(Control__IO_STACK_LOCATION(x), _S_Control__IO_STACK_LOCATION(S)));
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, S), _S_home_Control__IO_STACK_LOCATION(S)} In(x, S) ==> In(home_Control__IO_STACK_LOCATION(x), _S_home_Control__IO_STACK_LOCATION(S)));
+
+axiom (forall x:ptr :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, Ptr(null,3), 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, Ptr(null,3), 1) == home_Control__IO_STACK_LOCATION(x));
+axiom (forall x:ptr :: {MINUS_LEFT_PTR(x, 1, Ptr(null,3))} MINUS_LEFT_PTR(x, 1, Ptr(null,3)) == home_Control__IO_STACK_LOCATION(x));
+
+
+
+
+
+function CurrentStackLocation___unnamed_4_f80453a0(ptr) returns (ptr);
+function home_CurrentStackLocation___unnamed_4_f80453a0(ptr) returns (ptr);
+function _S_CurrentStackLocation___unnamed_4_f80453a0([ptr]bool) returns ([ptr]bool);
+function _S_home_CurrentStackLocation___unnamed_4_f80453a0([ptr]bool) returns ([ptr]bool);
+
+axiom (forall x:ptr :: {CurrentStackLocation___unnamed_4_f80453a0(x)} home_CurrentStackLocation___unnamed_4_f80453a0(CurrentStackLocation___unnamed_4_f80453a0(x)) == x);
+axiom (forall x:ptr :: {home_CurrentStackLocation___unnamed_4_f80453a0(x)} CurrentStackLocation___unnamed_4_f80453a0(home_CurrentStackLocation___unnamed_4_f80453a0(x)) == x);
+axiom (forall x:ptr :: {CurrentStackLocation___unnamed_4_f80453a0(x)} CurrentStackLocation___unnamed_4_f80453a0(x) == Ptr(Obj(x), Off(x) + 0));
+axiom (forall x:ptr :: {home_CurrentStackLocation___unnamed_4_f80453a0(x)} home_CurrentStackLocation___unnamed_4_f80453a0(x) == Ptr(Obj(x), Off(x) - 0));
+
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, _S_CurrentStackLocation___unnamed_4_f80453a0(S))} In(x, _S_CurrentStackLocation___unnamed_4_f80453a0(S)) ==> In(home_CurrentStackLocation___unnamed_4_f80453a0(x), S));
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, _S_home_CurrentStackLocation___unnamed_4_f80453a0(S))} In(x, _S_home_CurrentStackLocation___unnamed_4_f80453a0(S)) ==> In(CurrentStackLocation___unnamed_4_f80453a0(x), S));
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, S), _S_CurrentStackLocation___unnamed_4_f80453a0(S)} In(x, S) ==> In(CurrentStackLocation___unnamed_4_f80453a0(x), _S_CurrentStackLocation___unnamed_4_f80453a0(S)));
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, S), _S_home_CurrentStackLocation___unnamed_4_f80453a0(S)} In(x, S) ==> In(home_CurrentStackLocation___unnamed_4_f80453a0(x), _S_home_CurrentStackLocation___unnamed_4_f80453a0(S)));
+
+axiom (forall x:ptr :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, Ptr(null,0), 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, Ptr(null,0), 1) == home_CurrentStackLocation___unnamed_4_f80453a0(x));
+axiom (forall x:ptr :: {MINUS_LEFT_PTR(x, 1, Ptr(null,0))} MINUS_LEFT_PTR(x, 1, Ptr(null,0)) == home_CurrentStackLocation___unnamed_4_f80453a0(x));
+
+
+
+
+
+function DeviceExtension__DEVICE_OBJECT(ptr) returns (ptr);
+function home_DeviceExtension__DEVICE_OBJECT(ptr) returns (ptr);
+function _S_DeviceExtension__DEVICE_OBJECT([ptr]bool) returns ([ptr]bool);
+function _S_home_DeviceExtension__DEVICE_OBJECT([ptr]bool) returns ([ptr]bool);
+
+axiom (forall x:ptr :: {DeviceExtension__DEVICE_OBJECT(x)} home_DeviceExtension__DEVICE_OBJECT(DeviceExtension__DEVICE_OBJECT(x)) == x);
+axiom (forall x:ptr :: {home_DeviceExtension__DEVICE_OBJECT(x)} DeviceExtension__DEVICE_OBJECT(home_DeviceExtension__DEVICE_OBJECT(x)) == x);
+axiom (forall x:ptr :: {DeviceExtension__DEVICE_OBJECT(x)} DeviceExtension__DEVICE_OBJECT(x) == Ptr(Obj(x), Off(x) + 40));
+axiom (forall x:ptr :: {home_DeviceExtension__DEVICE_OBJECT(x)} home_DeviceExtension__DEVICE_OBJECT(x) == Ptr(Obj(x), Off(x) - 40));
+
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, _S_DeviceExtension__DEVICE_OBJECT(S))} In(x, _S_DeviceExtension__DEVICE_OBJECT(S)) ==> In(home_DeviceExtension__DEVICE_OBJECT(x), S));
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, _S_home_DeviceExtension__DEVICE_OBJECT(S))} In(x, _S_home_DeviceExtension__DEVICE_OBJECT(S)) ==> In(DeviceExtension__DEVICE_OBJECT(x), S));
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, S), _S_DeviceExtension__DEVICE_OBJECT(S)} In(x, S) ==> In(DeviceExtension__DEVICE_OBJECT(x), _S_DeviceExtension__DEVICE_OBJECT(S)));
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, S), _S_home_DeviceExtension__DEVICE_OBJECT(S)} In(x, S) ==> In(home_DeviceExtension__DEVICE_OBJECT(x), _S_home_DeviceExtension__DEVICE_OBJECT(S)));
+
+axiom (forall x:ptr :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, Ptr(null,40), 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, Ptr(null,40), 1) == home_DeviceExtension__DEVICE_OBJECT(x));
+axiom (forall x:ptr :: {MINUS_LEFT_PTR(x, 1, Ptr(null,40))} MINUS_LEFT_PTR(x, 1, Ptr(null,40)) == home_DeviceExtension__DEVICE_OBJECT(x));
+
+
+
+
+
+function DeviceObject__DISKETTE_EXTENSION(ptr) returns (ptr);
+function home_DeviceObject__DISKETTE_EXTENSION(ptr) returns (ptr);
+function _S_DeviceObject__DISKETTE_EXTENSION([ptr]bool) returns ([ptr]bool);
+function _S_home_DeviceObject__DISKETTE_EXTENSION([ptr]bool) returns ([ptr]bool);
+
+axiom (forall x:ptr :: {DeviceObject__DISKETTE_EXTENSION(x)} home_DeviceObject__DISKETTE_EXTENSION(DeviceObject__DISKETTE_EXTENSION(x)) == x);
+axiom (forall x:ptr :: {home_DeviceObject__DISKETTE_EXTENSION(x)} DeviceObject__DISKETTE_EXTENSION(home_DeviceObject__DISKETTE_EXTENSION(x)) == x);
+axiom (forall x:ptr :: {DeviceObject__DISKETTE_EXTENSION(x)} DeviceObject__DISKETTE_EXTENSION(x) == Ptr(Obj(x), Off(x) + 28));
+axiom (forall x:ptr :: {home_DeviceObject__DISKETTE_EXTENSION(x)} home_DeviceObject__DISKETTE_EXTENSION(x) == Ptr(Obj(x), Off(x) - 28));
+
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, _S_DeviceObject__DISKETTE_EXTENSION(S))} In(x, _S_DeviceObject__DISKETTE_EXTENSION(S)) ==> In(home_DeviceObject__DISKETTE_EXTENSION(x), S));
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, _S_home_DeviceObject__DISKETTE_EXTENSION(S))} In(x, _S_home_DeviceObject__DISKETTE_EXTENSION(S)) ==> In(DeviceObject__DISKETTE_EXTENSION(x), S));
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, S), _S_DeviceObject__DISKETTE_EXTENSION(S)} In(x, S) ==> In(DeviceObject__DISKETTE_EXTENSION(x), _S_DeviceObject__DISKETTE_EXTENSION(S)));
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, S), _S_home_DeviceObject__DISKETTE_EXTENSION(S)} In(x, S) ==> In(home_DeviceObject__DISKETTE_EXTENSION(x), _S_home_DeviceObject__DISKETTE_EXTENSION(S)));
+
+axiom (forall x:ptr :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, Ptr(null,28), 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, Ptr(null,28), 1) == home_DeviceObject__DISKETTE_EXTENSION(x));
+axiom (forall x:ptr :: {MINUS_LEFT_PTR(x, 1, Ptr(null,28))} MINUS_LEFT_PTR(x, 1, Ptr(null,28)) == home_DeviceObject__DISKETTE_EXTENSION(x));
+
+
+
+
+
+function FlCancelSpinLock__DISKETTE_EXTENSION(ptr) returns (ptr);
+function home_FlCancelSpinLock__DISKETTE_EXTENSION(ptr) returns (ptr);
+function _S_FlCancelSpinLock__DISKETTE_EXTENSION([ptr]bool) returns ([ptr]bool);
+function _S_home_FlCancelSpinLock__DISKETTE_EXTENSION([ptr]bool) returns ([ptr]bool);
+
+axiom (forall x:ptr :: {FlCancelSpinLock__DISKETTE_EXTENSION(x)} home_FlCancelSpinLock__DISKETTE_EXTENSION(FlCancelSpinLock__DISKETTE_EXTENSION(x)) == x);
+axiom (forall x:ptr :: {home_FlCancelSpinLock__DISKETTE_EXTENSION(x)} FlCancelSpinLock__DISKETTE_EXTENSION(home_FlCancelSpinLock__DISKETTE_EXTENSION(x)) == x);
+axiom (forall x:ptr :: {FlCancelSpinLock__DISKETTE_EXTENSION(x)} FlCancelSpinLock__DISKETTE_EXTENSION(x) == Ptr(Obj(x), Off(x) + 0));
+axiom (forall x:ptr :: {home_FlCancelSpinLock__DISKETTE_EXTENSION(x)} home_FlCancelSpinLock__DISKETTE_EXTENSION(x) == Ptr(Obj(x), Off(x) - 0));
+
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, _S_FlCancelSpinLock__DISKETTE_EXTENSION(S))} In(x, _S_FlCancelSpinLock__DISKETTE_EXTENSION(S)) ==> In(home_FlCancelSpinLock__DISKETTE_EXTENSION(x), S));
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, _S_home_FlCancelSpinLock__DISKETTE_EXTENSION(S))} In(x, _S_home_FlCancelSpinLock__DISKETTE_EXTENSION(S)) ==> In(FlCancelSpinLock__DISKETTE_EXTENSION(x), S));
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, S), _S_FlCancelSpinLock__DISKETTE_EXTENSION(S)} In(x, S) ==> In(FlCancelSpinLock__DISKETTE_EXTENSION(x), _S_FlCancelSpinLock__DISKETTE_EXTENSION(S)));
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, S), _S_home_FlCancelSpinLock__DISKETTE_EXTENSION(S)} In(x, S) ==> In(home_FlCancelSpinLock__DISKETTE_EXTENSION(x), _S_home_FlCancelSpinLock__DISKETTE_EXTENSION(S)));
+
+axiom (forall x:ptr :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, Ptr(null,0), 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, Ptr(null,0), 1) == home_FlCancelSpinLock__DISKETTE_EXTENSION(x));
+axiom (forall x:ptr :: {MINUS_LEFT_PTR(x, 1, Ptr(null,0))} MINUS_LEFT_PTR(x, 1, Ptr(null,0)) == home_FlCancelSpinLock__DISKETTE_EXTENSION(x));
+
+
+
+
+
+function HoldNewReqMutex__DISKETTE_EXTENSION(ptr) returns (ptr);
+function home_HoldNewReqMutex__DISKETTE_EXTENSION(ptr) returns (ptr);
+function _S_HoldNewReqMutex__DISKETTE_EXTENSION([ptr]bool) returns ([ptr]bool);
+function _S_home_HoldNewReqMutex__DISKETTE_EXTENSION([ptr]bool) returns ([ptr]bool);
+
+axiom (forall x:ptr :: {HoldNewReqMutex__DISKETTE_EXTENSION(x)} home_HoldNewReqMutex__DISKETTE_EXTENSION(HoldNewReqMutex__DISKETTE_EXTENSION(x)) == x);
+axiom (forall x:ptr :: {home_HoldNewReqMutex__DISKETTE_EXTENSION(x)} HoldNewReqMutex__DISKETTE_EXTENSION(home_HoldNewReqMutex__DISKETTE_EXTENSION(x)) == x);
+axiom (forall x:ptr :: {HoldNewReqMutex__DISKETTE_EXTENSION(x)} HoldNewReqMutex__DISKETTE_EXTENSION(x) == Ptr(Obj(x), Off(x) + 316));
+axiom (forall x:ptr :: {home_HoldNewReqMutex__DISKETTE_EXTENSION(x)} home_HoldNewReqMutex__DISKETTE_EXTENSION(x) == Ptr(Obj(x), Off(x) - 316));
+
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, _S_HoldNewReqMutex__DISKETTE_EXTENSION(S))} In(x, _S_HoldNewReqMutex__DISKETTE_EXTENSION(S)) ==> In(home_HoldNewReqMutex__DISKETTE_EXTENSION(x), S));
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, _S_home_HoldNewReqMutex__DISKETTE_EXTENSION(S))} In(x, _S_home_HoldNewReqMutex__DISKETTE_EXTENSION(S)) ==> In(HoldNewReqMutex__DISKETTE_EXTENSION(x), S));
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, S), _S_HoldNewReqMutex__DISKETTE_EXTENSION(S)} In(x, S) ==> In(HoldNewReqMutex__DISKETTE_EXTENSION(x), _S_HoldNewReqMutex__DISKETTE_EXTENSION(S)));
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, S), _S_home_HoldNewReqMutex__DISKETTE_EXTENSION(S)} In(x, S) ==> In(home_HoldNewReqMutex__DISKETTE_EXTENSION(x), _S_home_HoldNewReqMutex__DISKETTE_EXTENSION(S)));
+
+axiom (forall x:ptr :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, Ptr(null,316), 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, Ptr(null,316), 1) == home_HoldNewReqMutex__DISKETTE_EXTENSION(x));
+axiom (forall x:ptr :: {MINUS_LEFT_PTR(x, 1, Ptr(null,316))} MINUS_LEFT_PTR(x, 1, Ptr(null,316)) == home_HoldNewReqMutex__DISKETTE_EXTENSION(x));
+
+
+
+
+
+function HoldNewRequests__DISKETTE_EXTENSION(ptr) returns (ptr);
+function home_HoldNewRequests__DISKETTE_EXTENSION(ptr) returns (ptr);
+function _S_HoldNewRequests__DISKETTE_EXTENSION([ptr]bool) returns ([ptr]bool);
+function _S_home_HoldNewRequests__DISKETTE_EXTENSION([ptr]bool) returns ([ptr]bool);
+
+axiom (forall x:ptr :: {HoldNewRequests__DISKETTE_EXTENSION(x)} home_HoldNewRequests__DISKETTE_EXTENSION(HoldNewRequests__DISKETTE_EXTENSION(x)) == x);
+axiom (forall x:ptr :: {home_HoldNewRequests__DISKETTE_EXTENSION(x)} HoldNewRequests__DISKETTE_EXTENSION(home_HoldNewRequests__DISKETTE_EXTENSION(x)) == x);
+axiom (forall x:ptr :: {HoldNewRequests__DISKETTE_EXTENSION(x)} HoldNewRequests__DISKETTE_EXTENSION(x) == Ptr(Obj(x), Off(x) + 14));
+axiom (forall x:ptr :: {home_HoldNewRequests__DISKETTE_EXTENSION(x)} home_HoldNewRequests__DISKETTE_EXTENSION(x) == Ptr(Obj(x), Off(x) - 14));
+
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, _S_HoldNewRequests__DISKETTE_EXTENSION(S))} In(x, _S_HoldNewRequests__DISKETTE_EXTENSION(S)) ==> In(home_HoldNewRequests__DISKETTE_EXTENSION(x), S));
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, _S_home_HoldNewRequests__DISKETTE_EXTENSION(S))} In(x, _S_home_HoldNewRequests__DISKETTE_EXTENSION(S)) ==> In(HoldNewRequests__DISKETTE_EXTENSION(x), S));
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, S), _S_HoldNewRequests__DISKETTE_EXTENSION(S)} In(x, S) ==> In(HoldNewRequests__DISKETTE_EXTENSION(x), _S_HoldNewRequests__DISKETTE_EXTENSION(S)));
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, S), _S_home_HoldNewRequests__DISKETTE_EXTENSION(S)} In(x, S) ==> In(home_HoldNewRequests__DISKETTE_EXTENSION(x), _S_home_HoldNewRequests__DISKETTE_EXTENSION(S)));
+
+axiom (forall x:ptr :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, Ptr(null,14), 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, Ptr(null,14), 1) == home_HoldNewRequests__DISKETTE_EXTENSION(x));
+axiom (forall x:ptr :: {MINUS_LEFT_PTR(x, 1, Ptr(null,14))} MINUS_LEFT_PTR(x, 1, Ptr(null,14)) == home_HoldNewRequests__DISKETTE_EXTENSION(x));
+
+
+
+
+
+function Information__IO_STATUS_BLOCK(ptr) returns (ptr);
+function home_Information__IO_STATUS_BLOCK(ptr) returns (ptr);
+function _S_Information__IO_STATUS_BLOCK([ptr]bool) returns ([ptr]bool);
+function _S_home_Information__IO_STATUS_BLOCK([ptr]bool) returns ([ptr]bool);
+
+axiom (forall x:ptr :: {Information__IO_STATUS_BLOCK(x)} home_Information__IO_STATUS_BLOCK(Information__IO_STATUS_BLOCK(x)) == x);
+axiom (forall x:ptr :: {home_Information__IO_STATUS_BLOCK(x)} Information__IO_STATUS_BLOCK(home_Information__IO_STATUS_BLOCK(x)) == x);
+axiom (forall x:ptr :: {Information__IO_STATUS_BLOCK(x)} Information__IO_STATUS_BLOCK(x) == Ptr(Obj(x), Off(x) + 4));
+axiom (forall x:ptr :: {home_Information__IO_STATUS_BLOCK(x)} home_Information__IO_STATUS_BLOCK(x) == Ptr(Obj(x), Off(x) - 4));
+
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, _S_Information__IO_STATUS_BLOCK(S))} In(x, _S_Information__IO_STATUS_BLOCK(S)) ==> In(home_Information__IO_STATUS_BLOCK(x), S));
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, _S_home_Information__IO_STATUS_BLOCK(S))} In(x, _S_home_Information__IO_STATUS_BLOCK(S)) ==> In(Information__IO_STATUS_BLOCK(x), S));
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, S), _S_Information__IO_STATUS_BLOCK(S)} In(x, S) ==> In(Information__IO_STATUS_BLOCK(x), _S_Information__IO_STATUS_BLOCK(S)));
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, S), _S_home_Information__IO_STATUS_BLOCK(S)} In(x, S) ==> In(home_Information__IO_STATUS_BLOCK(x), _S_home_Information__IO_STATUS_BLOCK(S)));
+
+axiom (forall x:ptr :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, Ptr(null,4), 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, Ptr(null,4), 1) == home_Information__IO_STATUS_BLOCK(x));
+axiom (forall x:ptr :: {MINUS_LEFT_PTR(x, 1, Ptr(null,4))} MINUS_LEFT_PTR(x, 1, Ptr(null,4)) == home_Information__IO_STATUS_BLOCK(x));
+
+
+
+
+
+function IoStatus__IRP(ptr) returns (ptr);
+function home_IoStatus__IRP(ptr) returns (ptr);
+function _S_IoStatus__IRP([ptr]bool) returns ([ptr]bool);
+function _S_home_IoStatus__IRP([ptr]bool) returns ([ptr]bool);
+
+axiom (forall x:ptr :: {IoStatus__IRP(x)} home_IoStatus__IRP(IoStatus__IRP(x)) == x);
+axiom (forall x:ptr :: {home_IoStatus__IRP(x)} IoStatus__IRP(home_IoStatus__IRP(x)) == x);
+axiom (forall x:ptr :: {IoStatus__IRP(x)} IoStatus__IRP(x) == Ptr(Obj(x), Off(x) + 24));
+axiom (forall x:ptr :: {home_IoStatus__IRP(x)} home_IoStatus__IRP(x) == Ptr(Obj(x), Off(x) - 24));
+
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, _S_IoStatus__IRP(S))} In(x, _S_IoStatus__IRP(S)) ==> In(home_IoStatus__IRP(x), S));
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, _S_home_IoStatus__IRP(S))} In(x, _S_home_IoStatus__IRP(S)) ==> In(IoStatus__IRP(x), S));
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, S), _S_IoStatus__IRP(S)} In(x, S) ==> In(IoStatus__IRP(x), _S_IoStatus__IRP(S)));
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, S), _S_home_IoStatus__IRP(S)} In(x, S) ==> In(home_IoStatus__IRP(x), _S_home_IoStatus__IRP(S)));
+
+axiom (forall x:ptr :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, Ptr(null,24), 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, Ptr(null,24), 1) == home_IoStatus__IRP(x));
+axiom (forall x:ptr :: {MINUS_LEFT_PTR(x, 1, Ptr(null,24))} MINUS_LEFT_PTR(x, 1, Ptr(null,24)) == home_IoStatus__IRP(x));
+
+
+
+
+
+function IsRemoved__DISKETTE_EXTENSION(ptr) returns (ptr);
+function home_IsRemoved__DISKETTE_EXTENSION(ptr) returns (ptr);
+function _S_IsRemoved__DISKETTE_EXTENSION([ptr]bool) returns ([ptr]bool);
+function _S_home_IsRemoved__DISKETTE_EXTENSION([ptr]bool) returns ([ptr]bool);
+
+axiom (forall x:ptr :: {IsRemoved__DISKETTE_EXTENSION(x)} home_IsRemoved__DISKETTE_EXTENSION(IsRemoved__DISKETTE_EXTENSION(x)) == x);
+axiom (forall x:ptr :: {home_IsRemoved__DISKETTE_EXTENSION(x)} IsRemoved__DISKETTE_EXTENSION(home_IsRemoved__DISKETTE_EXTENSION(x)) == x);
+axiom (forall x:ptr :: {IsRemoved__DISKETTE_EXTENSION(x)} IsRemoved__DISKETTE_EXTENSION(x) == Ptr(Obj(x), Off(x) + 13));
+axiom (forall x:ptr :: {home_IsRemoved__DISKETTE_EXTENSION(x)} home_IsRemoved__DISKETTE_EXTENSION(x) == Ptr(Obj(x), Off(x) - 13));
+
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, _S_IsRemoved__DISKETTE_EXTENSION(S))} In(x, _S_IsRemoved__DISKETTE_EXTENSION(S)) ==> In(home_IsRemoved__DISKETTE_EXTENSION(x), S));
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, _S_home_IsRemoved__DISKETTE_EXTENSION(S))} In(x, _S_home_IsRemoved__DISKETTE_EXTENSION(S)) ==> In(IsRemoved__DISKETTE_EXTENSION(x), S));
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, S), _S_IsRemoved__DISKETTE_EXTENSION(S)} In(x, S) ==> In(IsRemoved__DISKETTE_EXTENSION(x), _S_IsRemoved__DISKETTE_EXTENSION(S)));
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, S), _S_home_IsRemoved__DISKETTE_EXTENSION(S)} In(x, S) ==> In(home_IsRemoved__DISKETTE_EXTENSION(x), _S_home_IsRemoved__DISKETTE_EXTENSION(S)));
+
+axiom (forall x:ptr :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, Ptr(null,13), 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, Ptr(null,13), 1) == home_IsRemoved__DISKETTE_EXTENSION(x));
+axiom (forall x:ptr :: {MINUS_LEFT_PTR(x, 1, Ptr(null,13))} MINUS_LEFT_PTR(x, 1, Ptr(null,13)) == home_IsRemoved__DISKETTE_EXTENSION(x));
+
+
+
+
+
+function IsStarted__DISKETTE_EXTENSION(ptr) returns (ptr);
+function home_IsStarted__DISKETTE_EXTENSION(ptr) returns (ptr);
+function _S_IsStarted__DISKETTE_EXTENSION([ptr]bool) returns ([ptr]bool);
+function _S_home_IsStarted__DISKETTE_EXTENSION([ptr]bool) returns ([ptr]bool);
+
+axiom (forall x:ptr :: {IsStarted__DISKETTE_EXTENSION(x)} home_IsStarted__DISKETTE_EXTENSION(IsStarted__DISKETTE_EXTENSION(x)) == x);
+axiom (forall x:ptr :: {home_IsStarted__DISKETTE_EXTENSION(x)} IsStarted__DISKETTE_EXTENSION(home_IsStarted__DISKETTE_EXTENSION(x)) == x);
+axiom (forall x:ptr :: {IsStarted__DISKETTE_EXTENSION(x)} IsStarted__DISKETTE_EXTENSION(x) == Ptr(Obj(x), Off(x) + 12));
+axiom (forall x:ptr :: {home_IsStarted__DISKETTE_EXTENSION(x)} home_IsStarted__DISKETTE_EXTENSION(x) == Ptr(Obj(x), Off(x) - 12));
+
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, _S_IsStarted__DISKETTE_EXTENSION(S))} In(x, _S_IsStarted__DISKETTE_EXTENSION(S)) ==> In(home_IsStarted__DISKETTE_EXTENSION(x), S));
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, _S_home_IsStarted__DISKETTE_EXTENSION(S))} In(x, _S_home_IsStarted__DISKETTE_EXTENSION(S)) ==> In(IsStarted__DISKETTE_EXTENSION(x), S));
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, S), _S_IsStarted__DISKETTE_EXTENSION(S)} In(x, S) ==> In(IsStarted__DISKETTE_EXTENSION(x), _S_IsStarted__DISKETTE_EXTENSION(S)));
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, S), _S_home_IsStarted__DISKETTE_EXTENSION(S)} In(x, S) ==> In(home_IsStarted__DISKETTE_EXTENSION(x), _S_home_IsStarted__DISKETTE_EXTENSION(S)));
+
+axiom (forall x:ptr :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, Ptr(null,12), 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, Ptr(null,12), 1) == home_IsStarted__DISKETTE_EXTENSION(x));
+axiom (forall x:ptr :: {MINUS_LEFT_PTR(x, 1, Ptr(null,12))} MINUS_LEFT_PTR(x, 1, Ptr(null,12)) == home_IsStarted__DISKETTE_EXTENSION(x));
+
+
+
+
+
+function Length___unnamed_16_39e6661e(ptr) returns (ptr);
+function home_Length___unnamed_16_39e6661e(ptr) returns (ptr);
+function _S_Length___unnamed_16_39e6661e([ptr]bool) returns ([ptr]bool);
+function _S_home_Length___unnamed_16_39e6661e([ptr]bool) returns ([ptr]bool);
+
+axiom (forall x:ptr :: {Length___unnamed_16_39e6661e(x)} home_Length___unnamed_16_39e6661e(Length___unnamed_16_39e6661e(x)) == x);
+axiom (forall x:ptr :: {home_Length___unnamed_16_39e6661e(x)} Length___unnamed_16_39e6661e(home_Length___unnamed_16_39e6661e(x)) == x);
+axiom (forall x:ptr :: {Length___unnamed_16_39e6661e(x)} Length___unnamed_16_39e6661e(x) == Ptr(Obj(x), Off(x) + 0));
+axiom (forall x:ptr :: {home_Length___unnamed_16_39e6661e(x)} home_Length___unnamed_16_39e6661e(x) == Ptr(Obj(x), Off(x) - 0));
+
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, _S_Length___unnamed_16_39e6661e(S))} In(x, _S_Length___unnamed_16_39e6661e(S)) ==> In(home_Length___unnamed_16_39e6661e(x), S));
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, _S_home_Length___unnamed_16_39e6661e(S))} In(x, _S_home_Length___unnamed_16_39e6661e(S)) ==> In(Length___unnamed_16_39e6661e(x), S));
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, S), _S_Length___unnamed_16_39e6661e(S)} In(x, S) ==> In(Length___unnamed_16_39e6661e(x), _S_Length___unnamed_16_39e6661e(S)));
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, S), _S_home_Length___unnamed_16_39e6661e(S)} In(x, S) ==> In(home_Length___unnamed_16_39e6661e(x), _S_home_Length___unnamed_16_39e6661e(S)));
+
+axiom (forall x:ptr :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, Ptr(null,0), 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, Ptr(null,0), 1) == home_Length___unnamed_16_39e6661e(x));
+axiom (forall x:ptr :: {MINUS_LEFT_PTR(x, 1, Ptr(null,0))} MINUS_LEFT_PTR(x, 1, Ptr(null,0)) == home_Length___unnamed_16_39e6661e(x));
+
+
+
+
+
+function ListEntry___unnamed_12_003c1454(ptr) returns (ptr);
+function home_ListEntry___unnamed_12_003c1454(ptr) returns (ptr);
+function _S_ListEntry___unnamed_12_003c1454([ptr]bool) returns ([ptr]bool);
+function _S_home_ListEntry___unnamed_12_003c1454([ptr]bool) returns ([ptr]bool);
+
+axiom (forall x:ptr :: {ListEntry___unnamed_12_003c1454(x)} home_ListEntry___unnamed_12_003c1454(ListEntry___unnamed_12_003c1454(x)) == x);
+axiom (forall x:ptr :: {home_ListEntry___unnamed_12_003c1454(x)} ListEntry___unnamed_12_003c1454(home_ListEntry___unnamed_12_003c1454(x)) == x);
+axiom (forall x:ptr :: {ListEntry___unnamed_12_003c1454(x)} ListEntry___unnamed_12_003c1454(x) == Ptr(Obj(x), Off(x) + 0));
+axiom (forall x:ptr :: {home_ListEntry___unnamed_12_003c1454(x)} home_ListEntry___unnamed_12_003c1454(x) == Ptr(Obj(x), Off(x) - 0));
+
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, _S_ListEntry___unnamed_12_003c1454(S))} In(x, _S_ListEntry___unnamed_12_003c1454(S)) ==> In(home_ListEntry___unnamed_12_003c1454(x), S));
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, _S_home_ListEntry___unnamed_12_003c1454(S))} In(x, _S_home_ListEntry___unnamed_12_003c1454(S)) ==> In(ListEntry___unnamed_12_003c1454(x), S));
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, S), _S_ListEntry___unnamed_12_003c1454(S)} In(x, S) ==> In(ListEntry___unnamed_12_003c1454(x), _S_ListEntry___unnamed_12_003c1454(S)));
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, S), _S_home_ListEntry___unnamed_12_003c1454(S)} In(x, S) ==> In(home_ListEntry___unnamed_12_003c1454(x), _S_home_ListEntry___unnamed_12_003c1454(S)));
+
+axiom (forall x:ptr :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, Ptr(null,0), 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, Ptr(null,0), 1) == home_ListEntry___unnamed_12_003c1454(x));
+axiom (forall x:ptr :: {MINUS_LEFT_PTR(x, 1, Ptr(null,0))} MINUS_LEFT_PTR(x, 1, Ptr(null,0)) == home_ListEntry___unnamed_12_003c1454(x));
+
+
+
+
+
+function ListSpinLock__DISKETTE_EXTENSION(ptr) returns (ptr);
+function home_ListSpinLock__DISKETTE_EXTENSION(ptr) returns (ptr);
+function _S_ListSpinLock__DISKETTE_EXTENSION([ptr]bool) returns ([ptr]bool);
+function _S_home_ListSpinLock__DISKETTE_EXTENSION([ptr]bool) returns ([ptr]bool);
+
+axiom (forall x:ptr :: {ListSpinLock__DISKETTE_EXTENSION(x)} home_ListSpinLock__DISKETTE_EXTENSION(ListSpinLock__DISKETTE_EXTENSION(x)) == x);
+axiom (forall x:ptr :: {home_ListSpinLock__DISKETTE_EXTENSION(x)} ListSpinLock__DISKETTE_EXTENSION(home_ListSpinLock__DISKETTE_EXTENSION(x)) == x);
+axiom (forall x:ptr :: {ListSpinLock__DISKETTE_EXTENSION(x)} ListSpinLock__DISKETTE_EXTENSION(x) == Ptr(Obj(x), Off(x) + 52));
+axiom (forall x:ptr :: {home_ListSpinLock__DISKETTE_EXTENSION(x)} home_ListSpinLock__DISKETTE_EXTENSION(x) == Ptr(Obj(x), Off(x) - 52));
+
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, _S_ListSpinLock__DISKETTE_EXTENSION(S))} In(x, _S_ListSpinLock__DISKETTE_EXTENSION(S)) ==> In(home_ListSpinLock__DISKETTE_EXTENSION(x), S));
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, _S_home_ListSpinLock__DISKETTE_EXTENSION(S))} In(x, _S_home_ListSpinLock__DISKETTE_EXTENSION(S)) ==> In(ListSpinLock__DISKETTE_EXTENSION(x), S));
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, S), _S_ListSpinLock__DISKETTE_EXTENSION(S)} In(x, S) ==> In(ListSpinLock__DISKETTE_EXTENSION(x), _S_ListSpinLock__DISKETTE_EXTENSION(S)));
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, S), _S_home_ListSpinLock__DISKETTE_EXTENSION(S)} In(x, S) ==> In(home_ListSpinLock__DISKETTE_EXTENSION(x), _S_home_ListSpinLock__DISKETTE_EXTENSION(S)));
+
+axiom (forall x:ptr :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, Ptr(null,52), 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, Ptr(null,52), 1) == home_ListSpinLock__DISKETTE_EXTENSION(x));
+axiom (forall x:ptr :: {MINUS_LEFT_PTR(x, 1, Ptr(null,52))} MINUS_LEFT_PTR(x, 1, Ptr(null,52)) == home_ListSpinLock__DISKETTE_EXTENSION(x));
+
+
+
+
+
+function LowPart___unnamed_8_34582070(ptr) returns (ptr);
+function home_LowPart___unnamed_8_34582070(ptr) returns (ptr);
+function _S_LowPart___unnamed_8_34582070([ptr]bool) returns ([ptr]bool);
+function _S_home_LowPart___unnamed_8_34582070([ptr]bool) returns ([ptr]bool);
+
+axiom (forall x:ptr :: {LowPart___unnamed_8_34582070(x)} home_LowPart___unnamed_8_34582070(LowPart___unnamed_8_34582070(x)) == x);
+axiom (forall x:ptr :: {home_LowPart___unnamed_8_34582070(x)} LowPart___unnamed_8_34582070(home_LowPart___unnamed_8_34582070(x)) == x);
+axiom (forall x:ptr :: {LowPart___unnamed_8_34582070(x)} LowPart___unnamed_8_34582070(x) == Ptr(Obj(x), Off(x) + 0));
+axiom (forall x:ptr :: {home_LowPart___unnamed_8_34582070(x)} home_LowPart___unnamed_8_34582070(x) == Ptr(Obj(x), Off(x) - 0));
+
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, _S_LowPart___unnamed_8_34582070(S))} In(x, _S_LowPart___unnamed_8_34582070(S)) ==> In(home_LowPart___unnamed_8_34582070(x), S));
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, _S_home_LowPart___unnamed_8_34582070(S))} In(x, _S_home_LowPart___unnamed_8_34582070(S)) ==> In(LowPart___unnamed_8_34582070(x), S));
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, S), _S_LowPart___unnamed_8_34582070(S)} In(x, S) ==> In(LowPart___unnamed_8_34582070(x), _S_LowPart___unnamed_8_34582070(S)));
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, S), _S_home_LowPart___unnamed_8_34582070(S)} In(x, S) ==> In(home_LowPart___unnamed_8_34582070(x), _S_home_LowPart___unnamed_8_34582070(S)));
+
+axiom (forall x:ptr :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, Ptr(null,0), 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, Ptr(null,0), 1) == home_LowPart___unnamed_8_34582070(x));
+axiom (forall x:ptr :: {MINUS_LEFT_PTR(x, 1, Ptr(null,0))} MINUS_LEFT_PTR(x, 1, Ptr(null,0)) == home_LowPart___unnamed_8_34582070(x));
+
+
+
+
+
+function MediaType__DISKETTE_EXTENSION(ptr) returns (ptr);
+function home_MediaType__DISKETTE_EXTENSION(ptr) returns (ptr);
+function _S_MediaType__DISKETTE_EXTENSION([ptr]bool) returns ([ptr]bool);
+function _S_home_MediaType__DISKETTE_EXTENSION([ptr]bool) returns ([ptr]bool);
+
+axiom (forall x:ptr :: {MediaType__DISKETTE_EXTENSION(x)} home_MediaType__DISKETTE_EXTENSION(MediaType__DISKETTE_EXTENSION(x)) == x);
+axiom (forall x:ptr :: {home_MediaType__DISKETTE_EXTENSION(x)} MediaType__DISKETTE_EXTENSION(home_MediaType__DISKETTE_EXTENSION(x)) == x);
+axiom (forall x:ptr :: {MediaType__DISKETTE_EXTENSION(x)} MediaType__DISKETTE_EXTENSION(x) == Ptr(Obj(x), Off(x) + 156));
+axiom (forall x:ptr :: {home_MediaType__DISKETTE_EXTENSION(x)} home_MediaType__DISKETTE_EXTENSION(x) == Ptr(Obj(x), Off(x) - 156));
+
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, _S_MediaType__DISKETTE_EXTENSION(S))} In(x, _S_MediaType__DISKETTE_EXTENSION(S)) ==> In(home_MediaType__DISKETTE_EXTENSION(x), S));
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, _S_home_MediaType__DISKETTE_EXTENSION(S))} In(x, _S_home_MediaType__DISKETTE_EXTENSION(S)) ==> In(MediaType__DISKETTE_EXTENSION(x), S));
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, S), _S_MediaType__DISKETTE_EXTENSION(S)} In(x, S) ==> In(MediaType__DISKETTE_EXTENSION(x), _S_MediaType__DISKETTE_EXTENSION(S)));
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, S), _S_home_MediaType__DISKETTE_EXTENSION(S)} In(x, S) ==> In(home_MediaType__DISKETTE_EXTENSION(x), _S_home_MediaType__DISKETTE_EXTENSION(S)));
+
+axiom (forall x:ptr :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, Ptr(null,156), 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, Ptr(null,156), 1) == home_MediaType__DISKETTE_EXTENSION(x));
+axiom (forall x:ptr :: {MINUS_LEFT_PTR(x, 1, Ptr(null,156))} MINUS_LEFT_PTR(x, 1, Ptr(null,156)) == home_MediaType__DISKETTE_EXTENSION(x));
+
+
+
+
+
+function NewRequestQueueSpinLock__DISKETTE_EXTENSION(ptr) returns (ptr);
+function home_NewRequestQueueSpinLock__DISKETTE_EXTENSION(ptr) returns (ptr);
+function _S_NewRequestQueueSpinLock__DISKETTE_EXTENSION([ptr]bool) returns ([ptr]bool);
+function _S_home_NewRequestQueueSpinLock__DISKETTE_EXTENSION([ptr]bool) returns ([ptr]bool);
+
+axiom (forall x:ptr :: {NewRequestQueueSpinLock__DISKETTE_EXTENSION(x)} home_NewRequestQueueSpinLock__DISKETTE_EXTENSION(NewRequestQueueSpinLock__DISKETTE_EXTENSION(x)) == x);
+axiom (forall x:ptr :: {home_NewRequestQueueSpinLock__DISKETTE_EXTENSION(x)} NewRequestQueueSpinLock__DISKETTE_EXTENSION(home_NewRequestQueueSpinLock__DISKETTE_EXTENSION(x)) == x);
+axiom (forall x:ptr :: {NewRequestQueueSpinLock__DISKETTE_EXTENSION(x)} NewRequestQueueSpinLock__DISKETTE_EXTENSION(x) == Ptr(Obj(x), Off(x) + 24));
+axiom (forall x:ptr :: {home_NewRequestQueueSpinLock__DISKETTE_EXTENSION(x)} home_NewRequestQueueSpinLock__DISKETTE_EXTENSION(x) == Ptr(Obj(x), Off(x) - 24));
+
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, _S_NewRequestQueueSpinLock__DISKETTE_EXTENSION(S))} In(x, _S_NewRequestQueueSpinLock__DISKETTE_EXTENSION(S)) ==> In(home_NewRequestQueueSpinLock__DISKETTE_EXTENSION(x), S));
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, _S_home_NewRequestQueueSpinLock__DISKETTE_EXTENSION(S))} In(x, _S_home_NewRequestQueueSpinLock__DISKETTE_EXTENSION(S)) ==> In(NewRequestQueueSpinLock__DISKETTE_EXTENSION(x), S));
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, S), _S_NewRequestQueueSpinLock__DISKETTE_EXTENSION(S)} In(x, S) ==> In(NewRequestQueueSpinLock__DISKETTE_EXTENSION(x), _S_NewRequestQueueSpinLock__DISKETTE_EXTENSION(S)));
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, S), _S_home_NewRequestQueueSpinLock__DISKETTE_EXTENSION(S)} In(x, S) ==> In(home_NewRequestQueueSpinLock__DISKETTE_EXTENSION(x), _S_home_NewRequestQueueSpinLock__DISKETTE_EXTENSION(S)));
+
+axiom (forall x:ptr :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, Ptr(null,24), 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, Ptr(null,24), 1) == home_NewRequestQueueSpinLock__DISKETTE_EXTENSION(x));
+axiom (forall x:ptr :: {MINUS_LEFT_PTR(x, 1, Ptr(null,24))} MINUS_LEFT_PTR(x, 1, Ptr(null,24)) == home_NewRequestQueueSpinLock__DISKETTE_EXTENSION(x));
+
+
+
+
+
+function NewRequestQueue__DISKETTE_EXTENSION(ptr) returns (ptr);
+function home_NewRequestQueue__DISKETTE_EXTENSION(ptr) returns (ptr);
+function _S_NewRequestQueue__DISKETTE_EXTENSION([ptr]bool) returns ([ptr]bool);
+function _S_home_NewRequestQueue__DISKETTE_EXTENSION([ptr]bool) returns ([ptr]bool);
+
+axiom (forall x:ptr :: {NewRequestQueue__DISKETTE_EXTENSION(x)} home_NewRequestQueue__DISKETTE_EXTENSION(NewRequestQueue__DISKETTE_EXTENSION(x)) == x);
+axiom (forall x:ptr :: {home_NewRequestQueue__DISKETTE_EXTENSION(x)} NewRequestQueue__DISKETTE_EXTENSION(home_NewRequestQueue__DISKETTE_EXTENSION(x)) == x);
+axiom (forall x:ptr :: {NewRequestQueue__DISKETTE_EXTENSION(x)} NewRequestQueue__DISKETTE_EXTENSION(x) == Ptr(Obj(x), Off(x) + 16));
+axiom (forall x:ptr :: {home_NewRequestQueue__DISKETTE_EXTENSION(x)} home_NewRequestQueue__DISKETTE_EXTENSION(x) == Ptr(Obj(x), Off(x) - 16));
+
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, _S_NewRequestQueue__DISKETTE_EXTENSION(S))} In(x, _S_NewRequestQueue__DISKETTE_EXTENSION(S)) ==> In(home_NewRequestQueue__DISKETTE_EXTENSION(x), S));
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, _S_home_NewRequestQueue__DISKETTE_EXTENSION(S))} In(x, _S_home_NewRequestQueue__DISKETTE_EXTENSION(S)) ==> In(NewRequestQueue__DISKETTE_EXTENSION(x), S));
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, S), _S_NewRequestQueue__DISKETTE_EXTENSION(S)} In(x, S) ==> In(NewRequestQueue__DISKETTE_EXTENSION(x), _S_NewRequestQueue__DISKETTE_EXTENSION(S)));
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, S), _S_home_NewRequestQueue__DISKETTE_EXTENSION(S)} In(x, S) ==> In(home_NewRequestQueue__DISKETTE_EXTENSION(x), _S_home_NewRequestQueue__DISKETTE_EXTENSION(S)));
+
+axiom (forall x:ptr :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, Ptr(null,16), 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, Ptr(null,16), 1) == home_NewRequestQueue__DISKETTE_EXTENSION(x));
+axiom (forall x:ptr :: {MINUS_LEFT_PTR(x, 1, Ptr(null,16))} MINUS_LEFT_PTR(x, 1, Ptr(null,16)) == home_NewRequestQueue__DISKETTE_EXTENSION(x));
+
+
+
+
+
+function Overlay___unnamed_48_c27ef811(ptr) returns (ptr);
+function home_Overlay___unnamed_48_c27ef811(ptr) returns (ptr);
+function _S_Overlay___unnamed_48_c27ef811([ptr]bool) returns ([ptr]bool);
+function _S_home_Overlay___unnamed_48_c27ef811([ptr]bool) returns ([ptr]bool);
+
+axiom (forall x:ptr :: {Overlay___unnamed_48_c27ef811(x)} home_Overlay___unnamed_48_c27ef811(Overlay___unnamed_48_c27ef811(x)) == x);
+axiom (forall x:ptr :: {home_Overlay___unnamed_48_c27ef811(x)} Overlay___unnamed_48_c27ef811(home_Overlay___unnamed_48_c27ef811(x)) == x);
+axiom (forall x:ptr :: {Overlay___unnamed_48_c27ef811(x)} Overlay___unnamed_48_c27ef811(x) == Ptr(Obj(x), Off(x) + 0));
+axiom (forall x:ptr :: {home_Overlay___unnamed_48_c27ef811(x)} home_Overlay___unnamed_48_c27ef811(x) == Ptr(Obj(x), Off(x) - 0));
+
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, _S_Overlay___unnamed_48_c27ef811(S))} In(x, _S_Overlay___unnamed_48_c27ef811(S)) ==> In(home_Overlay___unnamed_48_c27ef811(x), S));
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, _S_home_Overlay___unnamed_48_c27ef811(S))} In(x, _S_home_Overlay___unnamed_48_c27ef811(S)) ==> In(Overlay___unnamed_48_c27ef811(x), S));
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, S), _S_Overlay___unnamed_48_c27ef811(S)} In(x, S) ==> In(Overlay___unnamed_48_c27ef811(x), _S_Overlay___unnamed_48_c27ef811(S)));
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, S), _S_home_Overlay___unnamed_48_c27ef811(S)} In(x, S) ==> In(home_Overlay___unnamed_48_c27ef811(x), _S_home_Overlay___unnamed_48_c27ef811(S)));
+
+axiom (forall x:ptr :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, Ptr(null,0), 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, Ptr(null,0), 1) == home_Overlay___unnamed_48_c27ef811(x));
+axiom (forall x:ptr :: {MINUS_LEFT_PTR(x, 1, Ptr(null,0))} MINUS_LEFT_PTR(x, 1, Ptr(null,0)) == home_Overlay___unnamed_48_c27ef811(x));
+
+
+
+
+
+function Parameters__IO_STACK_LOCATION(ptr) returns (ptr);
+function home_Parameters__IO_STACK_LOCATION(ptr) returns (ptr);
+function _S_Parameters__IO_STACK_LOCATION([ptr]bool) returns ([ptr]bool);
+function _S_home_Parameters__IO_STACK_LOCATION([ptr]bool) returns ([ptr]bool);
+
+axiom (forall x:ptr :: {Parameters__IO_STACK_LOCATION(x)} home_Parameters__IO_STACK_LOCATION(Parameters__IO_STACK_LOCATION(x)) == x);
+axiom (forall x:ptr :: {home_Parameters__IO_STACK_LOCATION(x)} Parameters__IO_STACK_LOCATION(home_Parameters__IO_STACK_LOCATION(x)) == x);
+axiom (forall x:ptr :: {Parameters__IO_STACK_LOCATION(x)} Parameters__IO_STACK_LOCATION(x) == Ptr(Obj(x), Off(x) + 4));
+axiom (forall x:ptr :: {home_Parameters__IO_STACK_LOCATION(x)} home_Parameters__IO_STACK_LOCATION(x) == Ptr(Obj(x), Off(x) - 4));
+
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, _S_Parameters__IO_STACK_LOCATION(S))} In(x, _S_Parameters__IO_STACK_LOCATION(S)) ==> In(home_Parameters__IO_STACK_LOCATION(x), S));
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, _S_home_Parameters__IO_STACK_LOCATION(S))} In(x, _S_home_Parameters__IO_STACK_LOCATION(S)) ==> In(Parameters__IO_STACK_LOCATION(x), S));
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, S), _S_Parameters__IO_STACK_LOCATION(S)} In(x, S) ==> In(Parameters__IO_STACK_LOCATION(x), _S_Parameters__IO_STACK_LOCATION(S)));
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, S), _S_home_Parameters__IO_STACK_LOCATION(S)} In(x, S) ==> In(home_Parameters__IO_STACK_LOCATION(x), _S_home_Parameters__IO_STACK_LOCATION(S)));
+
+axiom (forall x:ptr :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, Ptr(null,4), 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, Ptr(null,4), 1) == home_Parameters__IO_STACK_LOCATION(x));
+axiom (forall x:ptr :: {MINUS_LEFT_PTR(x, 1, Ptr(null,4))} MINUS_LEFT_PTR(x, 1, Ptr(null,4)) == home_Parameters__IO_STACK_LOCATION(x));
+
+
+
+
+
+function Read___unnamed_16_c0f0e7de(ptr) returns (ptr);
+function home_Read___unnamed_16_c0f0e7de(ptr) returns (ptr);
+function _S_Read___unnamed_16_c0f0e7de([ptr]bool) returns ([ptr]bool);
+function _S_home_Read___unnamed_16_c0f0e7de([ptr]bool) returns ([ptr]bool);
+
+axiom (forall x:ptr :: {Read___unnamed_16_c0f0e7de(x)} home_Read___unnamed_16_c0f0e7de(Read___unnamed_16_c0f0e7de(x)) == x);
+axiom (forall x:ptr :: {home_Read___unnamed_16_c0f0e7de(x)} Read___unnamed_16_c0f0e7de(home_Read___unnamed_16_c0f0e7de(x)) == x);
+axiom (forall x:ptr :: {Read___unnamed_16_c0f0e7de(x)} Read___unnamed_16_c0f0e7de(x) == Ptr(Obj(x), Off(x) + 0));
+axiom (forall x:ptr :: {home_Read___unnamed_16_c0f0e7de(x)} home_Read___unnamed_16_c0f0e7de(x) == Ptr(Obj(x), Off(x) - 0));
+
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, _S_Read___unnamed_16_c0f0e7de(S))} In(x, _S_Read___unnamed_16_c0f0e7de(S)) ==> In(home_Read___unnamed_16_c0f0e7de(x), S));
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, _S_home_Read___unnamed_16_c0f0e7de(S))} In(x, _S_home_Read___unnamed_16_c0f0e7de(S)) ==> In(Read___unnamed_16_c0f0e7de(x), S));
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, S), _S_Read___unnamed_16_c0f0e7de(S)} In(x, S) ==> In(Read___unnamed_16_c0f0e7de(x), _S_Read___unnamed_16_c0f0e7de(S)));
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, S), _S_home_Read___unnamed_16_c0f0e7de(S)} In(x, S) ==> In(home_Read___unnamed_16_c0f0e7de(x), _S_home_Read___unnamed_16_c0f0e7de(S)));
+
+axiom (forall x:ptr :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, Ptr(null,0), 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, Ptr(null,0), 1) == home_Read___unnamed_16_c0f0e7de(x));
+axiom (forall x:ptr :: {MINUS_LEFT_PTR(x, 1, Ptr(null,0))} MINUS_LEFT_PTR(x, 1, Ptr(null,0)) == home_Read___unnamed_16_c0f0e7de(x));
+
+
+
+
+
+function Status___unnamed_4_c7b3d275(ptr) returns (ptr);
+function home_Status___unnamed_4_c7b3d275(ptr) returns (ptr);
+function _S_Status___unnamed_4_c7b3d275([ptr]bool) returns ([ptr]bool);
+function _S_home_Status___unnamed_4_c7b3d275([ptr]bool) returns ([ptr]bool);
+
+axiom (forall x:ptr :: {Status___unnamed_4_c7b3d275(x)} home_Status___unnamed_4_c7b3d275(Status___unnamed_4_c7b3d275(x)) == x);
+axiom (forall x:ptr :: {home_Status___unnamed_4_c7b3d275(x)} Status___unnamed_4_c7b3d275(home_Status___unnamed_4_c7b3d275(x)) == x);
+axiom (forall x:ptr :: {Status___unnamed_4_c7b3d275(x)} Status___unnamed_4_c7b3d275(x) == Ptr(Obj(x), Off(x) + 0));
+axiom (forall x:ptr :: {home_Status___unnamed_4_c7b3d275(x)} home_Status___unnamed_4_c7b3d275(x) == Ptr(Obj(x), Off(x) - 0));
+
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, _S_Status___unnamed_4_c7b3d275(S))} In(x, _S_Status___unnamed_4_c7b3d275(S)) ==> In(home_Status___unnamed_4_c7b3d275(x), S));
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, _S_home_Status___unnamed_4_c7b3d275(S))} In(x, _S_home_Status___unnamed_4_c7b3d275(S)) ==> In(Status___unnamed_4_c7b3d275(x), S));
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, S), _S_Status___unnamed_4_c7b3d275(S)} In(x, S) ==> In(Status___unnamed_4_c7b3d275(x), _S_Status___unnamed_4_c7b3d275(S)));
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, S), _S_home_Status___unnamed_4_c7b3d275(S)} In(x, S) ==> In(home_Status___unnamed_4_c7b3d275(x), _S_home_Status___unnamed_4_c7b3d275(S)));
+
+axiom (forall x:ptr :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, Ptr(null,0), 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, Ptr(null,0), 1) == home_Status___unnamed_4_c7b3d275(x));
+axiom (forall x:ptr :: {MINUS_LEFT_PTR(x, 1, Ptr(null,0))} MINUS_LEFT_PTR(x, 1, Ptr(null,0)) == home_Status___unnamed_4_c7b3d275(x));
+
+
+
+
+
+function Tail__IRP(ptr) returns (ptr);
+function home_Tail__IRP(ptr) returns (ptr);
+function _S_Tail__IRP([ptr]bool) returns ([ptr]bool);
+function _S_home_Tail__IRP([ptr]bool) returns ([ptr]bool);
+
+axiom (forall x:ptr :: {Tail__IRP(x)} home_Tail__IRP(Tail__IRP(x)) == x);
+axiom (forall x:ptr :: {home_Tail__IRP(x)} Tail__IRP(home_Tail__IRP(x)) == x);
+axiom (forall x:ptr :: {Tail__IRP(x)} Tail__IRP(x) == Ptr(Obj(x), Off(x) + 64));
+axiom (forall x:ptr :: {home_Tail__IRP(x)} home_Tail__IRP(x) == Ptr(Obj(x), Off(x) - 64));
+
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, _S_Tail__IRP(S))} In(x, _S_Tail__IRP(S)) ==> In(home_Tail__IRP(x), S));
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, _S_home_Tail__IRP(S))} In(x, _S_home_Tail__IRP(S)) ==> In(Tail__IRP(x), S));
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, S), _S_Tail__IRP(S)} In(x, S) ==> In(Tail__IRP(x), _S_Tail__IRP(S)));
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, S), _S_home_Tail__IRP(S)} In(x, S) ==> In(home_Tail__IRP(x), _S_home_Tail__IRP(S)));
+
+axiom (forall x:ptr :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, Ptr(null,64), 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, Ptr(null,64), 1) == home_Tail__IRP(x));
+axiom (forall x:ptr :: {MINUS_LEFT_PTR(x, 1, Ptr(null,64))} MINUS_LEFT_PTR(x, 1, Ptr(null,64)) == home_Tail__IRP(x));
+
+
+
+
+
+function __unnamed_12_003c1454___unnamed_40_6ef75b20(ptr) returns (ptr);
+function home___unnamed_12_003c1454___unnamed_40_6ef75b20(ptr) returns (ptr);
+function _S___unnamed_12_003c1454___unnamed_40_6ef75b20([ptr]bool) returns ([ptr]bool);
+function _S_home___unnamed_12_003c1454___unnamed_40_6ef75b20([ptr]bool) returns ([ptr]bool);
+
+axiom (forall x:ptr :: {__unnamed_12_003c1454___unnamed_40_6ef75b20(x)} home___unnamed_12_003c1454___unnamed_40_6ef75b20(__unnamed_12_003c1454___unnamed_40_6ef75b20(x)) == x);
+axiom (forall x:ptr :: {home___unnamed_12_003c1454___unnamed_40_6ef75b20(x)} __unnamed_12_003c1454___unnamed_40_6ef75b20(home___unnamed_12_003c1454___unnamed_40_6ef75b20(x)) == x);
+axiom (forall x:ptr :: {__unnamed_12_003c1454___unnamed_40_6ef75b20(x)} __unnamed_12_003c1454___unnamed_40_6ef75b20(x) == Ptr(Obj(x), Off(x) + 24));
+axiom (forall x:ptr :: {home___unnamed_12_003c1454___unnamed_40_6ef75b20(x)} home___unnamed_12_003c1454___unnamed_40_6ef75b20(x) == Ptr(Obj(x), Off(x) - 24));
+
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, _S___unnamed_12_003c1454___unnamed_40_6ef75b20(S))} In(x, _S___unnamed_12_003c1454___unnamed_40_6ef75b20(S)) ==> In(home___unnamed_12_003c1454___unnamed_40_6ef75b20(x), S));
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, _S_home___unnamed_12_003c1454___unnamed_40_6ef75b20(S))} In(x, _S_home___unnamed_12_003c1454___unnamed_40_6ef75b20(S)) ==> In(__unnamed_12_003c1454___unnamed_40_6ef75b20(x), S));
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, S), _S___unnamed_12_003c1454___unnamed_40_6ef75b20(S)} In(x, S) ==> In(__unnamed_12_003c1454___unnamed_40_6ef75b20(x), _S___unnamed_12_003c1454___unnamed_40_6ef75b20(S)));
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, S), _S_home___unnamed_12_003c1454___unnamed_40_6ef75b20(S)} In(x, S) ==> In(home___unnamed_12_003c1454___unnamed_40_6ef75b20(x), _S_home___unnamed_12_003c1454___unnamed_40_6ef75b20(S)));
+
+axiom (forall x:ptr :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, Ptr(null,24), 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, Ptr(null,24), 1) == home___unnamed_12_003c1454___unnamed_40_6ef75b20(x));
+axiom (forall x:ptr :: {MINUS_LEFT_PTR(x, 1, Ptr(null,24))} MINUS_LEFT_PTR(x, 1, Ptr(null,24)) == home___unnamed_12_003c1454___unnamed_40_6ef75b20(x));
+
+
+
+
+
+function __unnamed_4_c7b3d275__IO_STATUS_BLOCK(ptr) returns (ptr);
+function home___unnamed_4_c7b3d275__IO_STATUS_BLOCK(ptr) returns (ptr);
+function _S___unnamed_4_c7b3d275__IO_STATUS_BLOCK([ptr]bool) returns ([ptr]bool);
+function _S_home___unnamed_4_c7b3d275__IO_STATUS_BLOCK([ptr]bool) returns ([ptr]bool);
+
+axiom (forall x:ptr :: {__unnamed_4_c7b3d275__IO_STATUS_BLOCK(x)} home___unnamed_4_c7b3d275__IO_STATUS_BLOCK(__unnamed_4_c7b3d275__IO_STATUS_BLOCK(x)) == x);
+axiom (forall x:ptr :: {home___unnamed_4_c7b3d275__IO_STATUS_BLOCK(x)} __unnamed_4_c7b3d275__IO_STATUS_BLOCK(home___unnamed_4_c7b3d275__IO_STATUS_BLOCK(x)) == x);
+axiom (forall x:ptr :: {__unnamed_4_c7b3d275__IO_STATUS_BLOCK(x)} __unnamed_4_c7b3d275__IO_STATUS_BLOCK(x) == Ptr(Obj(x), Off(x) + 0));
+axiom (forall x:ptr :: {home___unnamed_4_c7b3d275__IO_STATUS_BLOCK(x)} home___unnamed_4_c7b3d275__IO_STATUS_BLOCK(x) == Ptr(Obj(x), Off(x) - 0));
+
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, _S___unnamed_4_c7b3d275__IO_STATUS_BLOCK(S))} In(x, _S___unnamed_4_c7b3d275__IO_STATUS_BLOCK(S)) ==> In(home___unnamed_4_c7b3d275__IO_STATUS_BLOCK(x), S));
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, _S_home___unnamed_4_c7b3d275__IO_STATUS_BLOCK(S))} In(x, _S_home___unnamed_4_c7b3d275__IO_STATUS_BLOCK(S)) ==> In(__unnamed_4_c7b3d275__IO_STATUS_BLOCK(x), S));
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, S), _S___unnamed_4_c7b3d275__IO_STATUS_BLOCK(S)} In(x, S) ==> In(__unnamed_4_c7b3d275__IO_STATUS_BLOCK(x), _S___unnamed_4_c7b3d275__IO_STATUS_BLOCK(S)));
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, S), _S_home___unnamed_4_c7b3d275__IO_STATUS_BLOCK(S)} In(x, S) ==> In(home___unnamed_4_c7b3d275__IO_STATUS_BLOCK(x), _S_home___unnamed_4_c7b3d275__IO_STATUS_BLOCK(S)));
+
+axiom (forall x:ptr :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, Ptr(null,0), 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, Ptr(null,0), 1) == home___unnamed_4_c7b3d275__IO_STATUS_BLOCK(x));
+axiom (forall x:ptr :: {MINUS_LEFT_PTR(x, 1, Ptr(null,0))} MINUS_LEFT_PTR(x, 1, Ptr(null,0)) == home___unnamed_4_c7b3d275__IO_STATUS_BLOCK(x));
+
+
+
+
+
+function __unnamed_4_f80453a0___unnamed_12_003c1454(ptr) returns (ptr);
+function home___unnamed_4_f80453a0___unnamed_12_003c1454(ptr) returns (ptr);
+function _S___unnamed_4_f80453a0___unnamed_12_003c1454([ptr]bool) returns ([ptr]bool);
+function _S_home___unnamed_4_f80453a0___unnamed_12_003c1454([ptr]bool) returns ([ptr]bool);
+
+axiom (forall x:ptr :: {__unnamed_4_f80453a0___unnamed_12_003c1454(x)} home___unnamed_4_f80453a0___unnamed_12_003c1454(__unnamed_4_f80453a0___unnamed_12_003c1454(x)) == x);
+axiom (forall x:ptr :: {home___unnamed_4_f80453a0___unnamed_12_003c1454(x)} __unnamed_4_f80453a0___unnamed_12_003c1454(home___unnamed_4_f80453a0___unnamed_12_003c1454(x)) == x);
+axiom (forall x:ptr :: {__unnamed_4_f80453a0___unnamed_12_003c1454(x)} __unnamed_4_f80453a0___unnamed_12_003c1454(x) == Ptr(Obj(x), Off(x) + 8));
+axiom (forall x:ptr :: {home___unnamed_4_f80453a0___unnamed_12_003c1454(x)} home___unnamed_4_f80453a0___unnamed_12_003c1454(x) == Ptr(Obj(x), Off(x) - 8));
+
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, _S___unnamed_4_f80453a0___unnamed_12_003c1454(S))} In(x, _S___unnamed_4_f80453a0___unnamed_12_003c1454(S)) ==> In(home___unnamed_4_f80453a0___unnamed_12_003c1454(x), S));
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, _S_home___unnamed_4_f80453a0___unnamed_12_003c1454(S))} In(x, _S_home___unnamed_4_f80453a0___unnamed_12_003c1454(S)) ==> In(__unnamed_4_f80453a0___unnamed_12_003c1454(x), S));
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, S), _S___unnamed_4_f80453a0___unnamed_12_003c1454(S)} In(x, S) ==> In(__unnamed_4_f80453a0___unnamed_12_003c1454(x), _S___unnamed_4_f80453a0___unnamed_12_003c1454(S)));
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, S), _S_home___unnamed_4_f80453a0___unnamed_12_003c1454(S)} In(x, S) ==> In(home___unnamed_4_f80453a0___unnamed_12_003c1454(x), _S_home___unnamed_4_f80453a0___unnamed_12_003c1454(S)));
+
+axiom (forall x:ptr :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, Ptr(null,8), 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, Ptr(null,8), 1) == home___unnamed_4_f80453a0___unnamed_12_003c1454(x));
+axiom (forall x:ptr :: {MINUS_LEFT_PTR(x, 1, Ptr(null,8))} MINUS_LEFT_PTR(x, 1, Ptr(null,8)) == home___unnamed_4_f80453a0___unnamed_12_003c1454(x));
+
+
+
+
+
+function __unnamed_8_34582070__LARGE_INTEGER(ptr) returns (ptr);
+function home___unnamed_8_34582070__LARGE_INTEGER(ptr) returns (ptr);
+function _S___unnamed_8_34582070__LARGE_INTEGER([ptr]bool) returns ([ptr]bool);
+function _S_home___unnamed_8_34582070__LARGE_INTEGER([ptr]bool) returns ([ptr]bool);
+
+axiom (forall x:ptr :: {__unnamed_8_34582070__LARGE_INTEGER(x)} home___unnamed_8_34582070__LARGE_INTEGER(__unnamed_8_34582070__LARGE_INTEGER(x)) == x);
+axiom (forall x:ptr :: {home___unnamed_8_34582070__LARGE_INTEGER(x)} __unnamed_8_34582070__LARGE_INTEGER(home___unnamed_8_34582070__LARGE_INTEGER(x)) == x);
+axiom (forall x:ptr :: {__unnamed_8_34582070__LARGE_INTEGER(x)} __unnamed_8_34582070__LARGE_INTEGER(x) == Ptr(Obj(x), Off(x) + 0));
+axiom (forall x:ptr :: {home___unnamed_8_34582070__LARGE_INTEGER(x)} home___unnamed_8_34582070__LARGE_INTEGER(x) == Ptr(Obj(x), Off(x) - 0));
+
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, _S___unnamed_8_34582070__LARGE_INTEGER(S))} In(x, _S___unnamed_8_34582070__LARGE_INTEGER(S)) ==> In(home___unnamed_8_34582070__LARGE_INTEGER(x), S));
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, _S_home___unnamed_8_34582070__LARGE_INTEGER(S))} In(x, _S_home___unnamed_8_34582070__LARGE_INTEGER(S)) ==> In(__unnamed_8_34582070__LARGE_INTEGER(x), S));
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, S), _S___unnamed_8_34582070__LARGE_INTEGER(S)} In(x, S) ==> In(__unnamed_8_34582070__LARGE_INTEGER(x), _S___unnamed_8_34582070__LARGE_INTEGER(S)));
+axiom (forall x:ptr, S:[ptr]bool :: {In(x, S), _S_home___unnamed_8_34582070__LARGE_INTEGER(S)} In(x, S) ==> In(home___unnamed_8_34582070__LARGE_INTEGER(x), _S_home___unnamed_8_34582070__LARGE_INTEGER(S)));
+
+axiom (forall x:ptr :: {MINUS_BOTH_PTR_OR_BOTH_INT(x, Ptr(null,0), 1)} MINUS_BOTH_PTR_OR_BOTH_INT(x, Ptr(null,0), 1) == home___unnamed_8_34582070__LARGE_INTEGER(x));
+axiom (forall x:ptr :: {MINUS_LEFT_PTR(x, 1, Ptr(null,0))} MINUS_LEFT_PTR(x, 1, Ptr(null,0)) == home___unnamed_8_34582070__LARGE_INTEGER(x));
+
+
+
+// Axiom for null constraint
+//modifying to make the signature match with old BSConstraint that constrains Mem
+function BSConstraint
+(
+ BS:[ptr]bool,
+ Mem:[ptr]ptr
+) returns (bool);
+
+axiom (
+ forall
+ BS:[ptr]bool, Mem:[ptr]ptr :: {BSConstraint(BS,Mem)}
+
+ BSConstraint(BS,Mem)
+ ==>
+ (
+ (forall i:int :: {Ptr(null,i)} BS[Ptr(null,i)])
+/*
+ &&
+
+ (forall a:ptr :: {BS[a]} Element(a))
+*/
+ )
+);
+procedure __delBS(a:ptr);
+requires(BS[a]);
+modifies BS;
+ensures(forall x:ptr :: {BS[x]} x == a || (old(BS)[x] <==> BS[x]));
+ensures(!BS[a]);
+
+procedure __addBS(a:ptr);
+requires(!BS[a]);
+modifies BS;
+ensures(forall x:ptr :: {BS[x]} x == a || (old(BS)[x] <==> BS[x]));
+ensures(BS[a]);
+
+function MINUS_BOTH_PTR_OR_BOTH_INT(a:ptr, b:ptr, size:int) returns (ptr);
+axiom(forall a:ptr, b:ptr, size:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(a,b,size)}
+(Obj(a) == Obj(b) ==> Obj(MINUS_BOTH_PTR_OR_BOTH_INT(a,b,size)) == null && size * Off(MINUS_BOTH_PTR_OR_BOTH_INT(a,b,size)) == Off(a) - Off(b))
+&&
+(Obj(b) == null && size == 1 ==> Obj(MINUS_BOTH_PTR_OR_BOTH_INT(a,b,size)) == Obj(a) && Off(MINUS_BOTH_PTR_OR_BOTH_INT(a,b,size)) == Off(a) - Off(b))
+&&
+(Obj(MINUS_BOTH_PTR_OR_BOTH_INT(a,b,size)) == null || Obj(MINUS_BOTH_PTR_OR_BOTH_INT(a,b,size)) == Obj(a) || Obj(MINUS_BOTH_PTR_OR_BOTH_INT(a,b,size)) == Obj(b))
+);
+
+function MINUS_LEFT_PTR(a:ptr, a_size:int, b:ptr) returns (ptr);
+axiom(forall a:ptr, a_size:int, b:ptr :: {MINUS_LEFT_PTR(a,a_size,b)}
+(Obj(b) == null ==> Obj(MINUS_LEFT_PTR(a,a_size,b)) == Obj(a) && Off(MINUS_LEFT_PTR(a,a_size,b)) == Off(a) - a_size * Off(b))
+&&
+(Obj(a) == Obj(b) && a_size == 1 ==> Obj(MINUS_LEFT_PTR(a,a_size,b)) == null && Off(MINUS_LEFT_PTR(a,a_size,b)) == Off(a) - Off(b))
+&&
+(Obj(MINUS_LEFT_PTR(a,a_size,b)) == null || Obj(MINUS_LEFT_PTR(a,a_size,b)) == Obj(a) || Obj(MINUS_LEFT_PTR(a,a_size,b)) == Obj(b))
+);
+
+function PLUS(a:ptr, a_size:int, b:ptr) returns (ptr);
+axiom(forall a:ptr, a_size:int, b:ptr :: {PLUS(a,a_size,b)}
+(Obj(b) == null ==> Obj(PLUS(a,a_size,b)) == Obj(a) && Off(PLUS(a,a_size,b)) == Off(a) + a_size * Off(b))
+&&
+(Obj(a) == null && a_size == 1 ==> Obj(PLUS(a,a_size,b)) == Obj(b) && Off(PLUS(a,a_size,b)) == Off(a) + Off(b))
+&&
+(Obj(PLUS(a,a_size,b)) == null || Obj(PLUS(a,a_size,b)) == Obj(a) || Obj(PLUS(a,a_size,b)) == Obj(b))
+);
+
+function MULT(a:ptr, b:ptr) returns (ptr);
+axiom(forall a:ptr, b:ptr :: {MULT(a,b)} Obj(MULT(a,b)) == null);
+
+function BINARY_BOTH_INT(a:ptr, b:ptr) returns (ptr);
+axiom(forall a:ptr, b:ptr :: {BINARY_BOTH_INT(a,b)} Obj(BINARY_BOTH_INT(a,b)) == null);
+
+function POW2(a:ptr) returns (bool);
+axiom POW2(Ptr(null,1));
+axiom POW2(Ptr(null,2));
+axiom POW2(Ptr(null,4));
+axiom POW2(Ptr(null,8));
+axiom POW2(Ptr(null,16));
+axiom POW2(Ptr(null,32));
+axiom POW2(Ptr(null,64));
+axiom POW2(Ptr(null,128));
+axiom POW2(Ptr(null,256));
+axiom POW2(Ptr(null,512));
+axiom POW2(Ptr(null,1024));
+axiom POW2(Ptr(null,2048));
+axiom POW2(Ptr(null,4096));
+axiom POW2(Ptr(null,8192));
+axiom POW2(Ptr(null,16384));
+axiom POW2(Ptr(null,32768));
+axiom POW2(Ptr(null,65536));
+axiom POW2(Ptr(null,131072));
+axiom POW2(Ptr(null,262144));
+axiom POW2(Ptr(null,524288));
+axiom POW2(Ptr(null,1048576));
+axiom POW2(Ptr(null,2097152));
+axiom POW2(Ptr(null,4194304));
+axiom POW2(Ptr(null,8388608));
+axiom POW2(Ptr(null,16777216));
+axiom POW2(Ptr(null,33554432));
+
+axiom (forall n:int, m:int :: {Ptr(null,n),POW2(Ptr(null,m))} POW2(Ptr(null,m)) && m < n && n < 2*m ==> !POW2(Ptr(null,n)));
+
+function choose(a:bool, b:ptr, c:ptr) returns (x:ptr);
+axiom(forall a:bool, b:ptr, c:ptr :: {choose(a,b,c)} a ==> choose(a,b,c) == b);
+axiom(forall a:bool, b:ptr, c:ptr :: {choose(a,b,c)} !a ==> choose(a,b,c) == c);
+
+function BIT_BAND(a:ptr, b:ptr) returns (x:ptr);
+axiom(forall a:ptr, b:ptr :: {BIT_BAND(a,b)} Obj(BIT_BAND(a,b)) == null || Obj(BIT_BAND(a,b)) == Obj(a) || Obj(BIT_BAND(a,b)) == Obj(b));
+axiom(forall a:ptr, b:ptr :: {BIT_BAND(a,b)} a == b ==> BIT_BAND(a,b) == a);
+axiom(forall a:ptr, b:ptr :: {BIT_BAND(a,b)} POW2(a) && POW2(b) && a != b ==> BIT_BAND(a,b) == Ptr(null,0));
+axiom(forall a:ptr, b:ptr :: {BIT_BAND(a,b)} a == Ptr(null,0) || b == Ptr(null,0) ==> BIT_BAND(a,b) == Ptr(null,0));
+axiom(forall a:ptr, b:ptr, c:ptr :: {BIT_BAND(BIT_BAND(a,b),c)} BIT_BAND(BIT_BAND(a,b),c) == c <==> BIT_BAND(a,c) == c && BIT_BAND(b,c) == c);
+
+function BIT_BOR(a:ptr, b:ptr) returns (x:ptr);
+axiom(forall a:ptr, b:ptr :: {BIT_BOR(a,b)} Obj(BIT_BOR(a,b)) == null || Obj(BIT_BOR(a,b)) == Obj(a) || Obj(BIT_BOR(a,b)) == Obj(b));
+axiom(forall a:ptr, b:ptr, c:ptr :: {BIT_BAND(BIT_BOR(a,b),c)} BIT_BAND(a,c) != Ptr(null,0) || BIT_BAND(b,c) != Ptr(null,0) <==> BIT_BAND(BIT_BOR(a,b),c) != Ptr(null,0));
+axiom(forall n:int, m:int :: {POW2(Ptr(null,n)), POW2(Ptr(null,m))} n > 0 && POW2(Ptr(null,m)) && m < n && 2*m > n ==>
+ Ptr(null, n) == BIT_BOR(Ptr(null, m), Ptr(null, n - m)));
+
+
+function BIT_BXOR(a:ptr, b:ptr) returns (x:ptr);
+axiom(forall a:ptr, b:ptr :: {BIT_BXOR(a,b)} Obj(BIT_BXOR(a,b)) == null || Obj(BIT_BXOR(a,b)) == Obj(a) || Obj(BIT_BXOR(a,b)) == Obj(b));
+
+function BIT_BNOT(a:ptr) returns (ptr);
+axiom(forall a:ptr, b:ptr :: {BIT_BAND(a,b)} a == BIT_BNOT(b) || b == BIT_BNOT(a) ==> BIT_BAND(a,b) == Ptr(null,0));
+axiom(forall a:ptr, b:ptr :: {BIT_BNOT(BIT_BOR(a,b))} BIT_BNOT(BIT_BOR(a,b)) == BIT_BAND(BIT_BNOT(a),BIT_BNOT(b)));
+axiom(forall a:ptr, b:ptr, c:ptr :: {BIT_BAND(BIT_BAND(a,b),c)} a == BIT_BNOT(c) || b == BIT_BNOT(c) ==> BIT_BAND(BIT_BAND(a,b),c) == Ptr(null,0));
+axiom(forall a:ptr, b:ptr, c:ptr :: {BIT_BAND(BIT_BAND(BIT_BNOT(a),b),c)} POW2(c) && POW2(a) && c != a ==>
+ (BIT_BAND(b,c) != Ptr(null,0) <==> BIT_BAND(BIT_BAND(BIT_BNOT(a),b),c) != Ptr(null,0)));
+axiom(forall a:ptr, b:ptr, c:ptr :: {BIT_BAND(BIT_BAND(a,BIT_BNOT(b)),c)} POW2(c) && POW2(b) && c != b ==>
+ (BIT_BAND(a,c) != Ptr(null,0) <==> BIT_BAND(BIT_BAND(a,BIT_BNOT(b)),c) != Ptr(null,0)));
+
+
+function LIFT(a:bool) returns (ptr);
+axiom(forall a:bool :: {LIFT(a)} a <==> LIFT(a) != Ptr(null,0));
+axiom(forall a:bool :: {LIFT(a)} Obj(LIFT(a)) == null); // need to show T_char(LIFT(a))
+
+function NOT(a:ptr) returns (ptr);
+axiom(forall a:ptr :: {NOT(a)} a == Ptr(null,0) ==> NOT(a) != Ptr(null,0));
+axiom(forall a:ptr :: {NOT(a)} a != Ptr(null,0) ==> NOT(a) == Ptr(null,0));
+
+function NULL_CHECK(a:ptr) returns (ptr);
+axiom(forall a:ptr :: {NULL_CHECK(a)} a == Ptr(null,0) ==> NULL_CHECK(a) != Ptr(null,0));
+axiom(forall a:ptr :: {NULL_CHECK(a)} a != Ptr(null,0) ==> NULL_CHECK(a) == Ptr(null,0));
+
+
+function FreshObj(alloc:[ref]name, old_alloc:[ref]name, p: ptr) returns (bool);
+axiom(forall alloc:[ref]name, old_alloc:[ref]name, p: ptr :: {FreshObj(alloc, old_alloc, p)}
+ FreshObj(alloc, old_alloc, p) <==> alloc[Obj(p)] == ALLOCATED && old_alloc[Obj(p)] == UNALLOCATED
+);
+
+
+procedure nondet_choice() returns (x:ptr);
+ensures (Obj(x) == null);
+
+procedure CreateMutexA$12 (a0:ptr, a1:ptr, a2:ptr) returns (new:ptr);
+modifies alloc;
+ensures (old(alloc)[Obj(new)] == UNALLOCATED && alloc[Obj(new)] == ALLOCATED);
+ensures (Size(Obj(new)) == 1);
+ensures (Off(new) == 0);
+ensures (Obj(new) != null);
+ensures (forall i:int :: BS[Ptr(Obj(new), i)]);
+ensures (forall i:int :: Obj(Mem[Ptr(Obj(new), i)]) == null);
+ensures (forall x_obj:ref :: {alloc[x_obj]} x_obj == Obj(new) || old(alloc)[x_obj] == alloc[x_obj]);
+ensures (Mem[new] == Ptr(null,0));
+
+procedure WaitForSingleObject$8 (lock :ptr, wait:ptr) returns (status:ptr);
+modifies Mem;
+ensures (forall x:ptr :: {Mem[x]} x == lock || old(Mem)[x] == Mem[x]);
+ensures (old(Mem)[lock] == Ptr(null,0) && Mem[lock] == Ptr(null,1));
+
+procedure ReleaseMutex$4 (lock:ptr) returns (status:ptr);
+modifies Mem;
+ensures (forall x:ptr :: {Mem[x]} x == lock || old(Mem)[x] == Mem[x]);
+ensures (old(Mem)[lock] == Ptr(null,1) && Mem[lock] == Ptr(null,0));
+
+
+
+procedure havoc_assert(i:ptr);
+requires (i != Ptr(null, 0));
+
+procedure havoc_assume(i:ptr);
+ensures (i != Ptr(null, 0));
+
+
+procedure __HAVOC_free(a:ptr);
+modifies alloc;
+//requires (alloc[Obj(a)] == ALLOCATED);
+//requires (Off(a) == 0);
+ensures (alloc[Obj(a)] != UNALLOCATED);
+ensures (alloc[Obj(a)] != ALLOCATED);
+ensures (forall x_obj:ref :: {alloc[x_obj]} Obj(a) == x_obj || old(alloc)[x_obj] == alloc[x_obj]);
+
+procedure __HAVOC_malloc_heap(obj_size:ptr) returns (new:ptr);
+modifies alloc;
+ensures (old(alloc)[Obj(new)] == UNALLOCATED && alloc[Obj(new)] == ALLOCATED);
+ensures (Size(Obj(new)) == Off(obj_size));
+ensures (Off(new) == 0);
+ensures (Obj(new) != null);
+ensures (IsHeap(Obj(new)));
+ensures (forall i:int :: BS[Ptr(Obj(new), i)]);
+ensures (forall i:int :: Obj(Mem[Ptr(Obj(new), i)]) == null);
+ensures (forall x_obj:ref :: {alloc[x_obj]} x_obj == Obj(new) || old(alloc)[x_obj] == alloc[x_obj]);
+
+
+procedure __HAVOC_malloc_stack(obj_size:ptr) returns (new:ptr);
+modifies alloc;
+ensures (old(alloc)[Obj(new)] == UNALLOCATED && alloc[Obj(new)] == ALLOCATED);
+ensures (Size(Obj(new)) == Off(obj_size));
+ensures (Off(new) == 0);
+ensures (Obj(new) != null);
+ensures (!IsHeap(Obj(new)));
+ensures (forall i:int :: BS[Ptr(Obj(new), i)]);
+ensures (forall i:int :: Obj(Mem[Ptr(Obj(new), i)]) == null);
+ensures (forall x_obj:ref :: {alloc[x_obj]} x_obj == Obj(new) || old(alloc)[x_obj] == alloc[x_obj]);
+
+procedure _strdup(str:ptr) returns (new:ptr);
+modifies alloc;
+ensures (old(alloc)[Obj(new)] == UNALLOCATED && alloc[Obj(new)] == ALLOCATED);
+ensures (Off(new) == 0);
+ensures (Obj(new) != null);
+ensures (forall i:int :: BS[Ptr(Obj(new), i)]);
+ensures (forall i:int :: Obj(Mem[Ptr(Obj(new), i)]) == null);
+ensures (forall x_obj:ref :: {alloc[x_obj]} x_obj == Obj(new) || old(alloc)[x_obj] == alloc[x_obj]);
+
+procedure _xstrcasecmp(a0:ptr, a1:ptr) returns (ret:ptr);
+
+procedure _xstrcmp(a0:ptr, a1:ptr) returns (ret:ptr);
+var Mem_ByteCapacity__DISKETTE_EXTENSION:[ptr]ptr;
+var Mem_ByteOffset___unnamed_16_39e6661e:[ptr]ptr;
+var Mem_BytesPerSector__DISKETTE_EXTENSION:[ptr]ptr;
+var Mem_CHAR:[ptr]ptr;
+var Mem_CancelRoutine__IRP:[ptr]ptr;
+var Mem_Cancel__IRP:[ptr]ptr;
+var Mem_Control__IO_STACK_LOCATION:[ptr]ptr;
+var Mem_CurrentStackLocation___unnamed_4_f80453a0:[ptr]ptr;
+var Mem_DeviceExtension__DEVICE_OBJECT:[ptr]ptr;
+var Mem_DeviceObject__DISKETTE_EXTENSION:[ptr]ptr;
+var Mem_FUNCTION:[ptr]ptr;
+var Mem_FlCancelSpinLock__DISKETTE_EXTENSION:[ptr]ptr;
+var Mem_HoldNewReqMutex__DISKETTE_EXTENSION:[ptr]ptr;
+var Mem_HoldNewRequests__DISKETTE_EXTENSION:[ptr]ptr;
+var Mem_INT4:[ptr]ptr;
+var Mem_Information__IO_STATUS_BLOCK:[ptr]ptr;
+var Mem_IoStatus__IRP:[ptr]ptr;
+var Mem_IsRemoved__DISKETTE_EXTENSION:[ptr]ptr;
+var Mem_IsStarted__DISKETTE_EXTENSION:[ptr]ptr;
+var Mem_Length___unnamed_16_39e6661e:[ptr]ptr;
+var Mem_ListEntry___unnamed_12_003c1454:[ptr]ptr;
+var Mem_ListSpinLock__DISKETTE_EXTENSION:[ptr]ptr;
+var Mem_LowPart___unnamed_8_34582070:[ptr]ptr;
+var Mem_MediaType__DISKETTE_EXTENSION:[ptr]ptr;
+var Mem_NewRequestQueueSpinLock__DISKETTE_EXTENSION:[ptr]ptr;
+var Mem_NewRequestQueue__DISKETTE_EXTENSION:[ptr]ptr;
+var Mem_Overlay___unnamed_48_c27ef811:[ptr]ptr;
+var Mem_PCHAR:[ptr]ptr;
+var Mem_PFUNCTION:[ptr]ptr;
+var Mem_PPFUNCTION:[ptr]ptr;
+var Mem_PUINT4:[ptr]ptr;
+var Mem_PVOID:[ptr]ptr;
+var Mem_P_DISKETTE_EXTENSION:[ptr]ptr;
+var Mem_P_FAST_MUTEX:[ptr]ptr;
+var Mem_P_IO_STACK_LOCATION:[ptr]ptr;
+var Mem_P_LIST_ENTRY:[ptr]ptr;
+var Mem_Parameters__IO_STACK_LOCATION:[ptr]ptr;
+var Mem_Read___unnamed_16_c0f0e7de:[ptr]ptr;
+var Mem_Status___unnamed_4_c7b3d275:[ptr]ptr;
+var Mem_Tail__IRP:[ptr]ptr;
+var Mem_UCHAR:[ptr]ptr;
+var Mem_UINT4:[ptr]ptr;
+var Mem___unnamed_12_003c1454___unnamed_40_6ef75b20:[ptr]ptr;
+var Mem___unnamed_4_c7b3d275__IO_STATUS_BLOCK:[ptr]ptr;
+var Mem___unnamed_4_f80453a0___unnamed_12_003c1454:[ptr]ptr;
+var Mem___unnamed_8_34582070__LARGE_INTEGER:[ptr]ptr;
+
+var Res_IRQL:[ptr]ptr;
+var Res_SPINLOCK:[ptr]ptr;
+var Res_SPINLOCK_IRQL:[ptr]ptr;
+
+
+
+const unique DriverEntry : ptr;
+const unique DriverEntry_ref : ref;
+const unique FloppyCancelQueuedRequest : ptr;
+const unique FloppyCancelQueuedRequest_ref : ref;
+var FloppyDebugLevel : ptr;
+var PagingMutex : ptr;
+var PagingReferenceCount : ptr;
+const {:existential true} $FloppyQueueRequest$pre$0 : bool;
+const {:existential true} $FloppyQueueRequest$pre$1 : bool;
+const {:existential true} $FloppyQueueRequest$pre$2 : bool;
+const {:existential true} $FloppyQueueRequest$pre$3 : bool;
+const {:existential true} $FloppyQueueRequest$post$12 : bool;
+const {:existential true} $FloppyQueueRequest$post$13 : bool;
+const {:existential true} $FloppyQueueRequest$post$14 : bool;
+const {:existential true} $FloppyQueueRequest$post$15 : bool;
+const {:existential true} $FloppyQueueRequest$mod$16 : bool;
+const {:existential true} $FloppyQueueRequest$mod$17 : bool;
+const {:existential true} $FloppyQueueRequest$mod$18 : bool;
+const {:existential true} $FloppyQueueRequest$mod$19 : bool;
+const {:existential true} $FloppyQueueRequest$mod$20 : bool;
+const {:existential true} $FloppyQueueRequest$mod$21 : bool;
+const {:existential true} $FloppyReadWrite$pre$42 : bool;
+const {:existential true} $FloppyReadWrite$pre$43 : bool;
+const {:existential true} $FloppyReadWrite$pre$44 : bool;
+const {:existential true} $FloppyReadWrite$pre$45 : bool;
+const {:existential true} $FloppyReadWrite$pre$46 : bool;
+const {:existential true} $FloppyReadWrite$post$57 : bool;
+const {:existential true} $FloppyReadWrite$post$58 : bool;
+const {:existential true} $FloppyReadWrite$post$59 : bool;
+const {:existential true} $FloppyReadWrite$post$60 : bool;
+const {:existential true} $FloppyReadWrite$post$61 : bool;
+const {:existential true} $FloppyReadWrite$mod$62 : bool;
+const {:existential true} $FloppyReadWrite$mod$63 : bool;
+const {:existential true} $FloppyReadWrite$mod$64 : bool;
+const {:existential true} $FloppyReadWrite$mod$65 : bool;
+const {:existential true} $FloppyReadWrite$mod$66 : bool;
+const {:existential true} $FloppyReadWrite$mod$67 : bool;
+
+
+procedure ExAcquireFastMutex ( a0:ptr) ;
+
+
+procedure ExReleaseFastMutex ( a0:ptr) ;
+
+
+procedure ExfInterlockedInsertTailList ( a0:ptr, a1:ptr, a2:ptr) returns (ret:ptr);
+
+
+procedure FlQueueIrpToThread ( Irp$21:ptr, DisketteExtension$11:ptr) returns ( $result.FlQueueIrpToThread$861.0$1$:ptr) ;
+
+
+
+
+
+procedure IofCompleteRequest ( a0:ptr, a1:ptr) ;
+
+
+procedure KfAcquireSpinLock ( SpinLock1:ptr) returns ( $result.__prototypewdm_KfAcquireSpinLock$92.0$1$__prototypewdm_KfAcquireSpinLock$4:ptr) ;
+
+//TAG: requires __resource("SPINLOCK", SpinLock) == 0
+requires(Res_SPINLOCK[SpinLock1] == Ptr(null, 0));
+//TAG: ensures __resource("SPINLOCK", SpinLock) == 1
+ensures(Res_SPINLOCK[SpinLock1] == Ptr(null, 1));
+//TAG: ensures __resource("SPINLOCK_IRQL", SpinLock) == __return
+ensures(Res_SPINLOCK_IRQL[SpinLock1] == $result.__prototypewdm_KfAcquireSpinLock$92.0$1$__prototypewdm_KfAcquireSpinLock$4);
+//TAG: ensures __global_resource("IRQL") == 2
+ensures(Res_IRQL[Ptr(null,1)] == Ptr(null, 2));
+//TAG: ensures __return == __old_global_resource("IRQL")
+ensures($result.__prototypewdm_KfAcquireSpinLock$92.0$1$__prototypewdm_KfAcquireSpinLock$4 == old(Res_IRQL)[Ptr(null,1)]);
+
+modifies Res_IRQL;
+ensures(forall r:ptr :: {Res_IRQL[r]} (Ptr(null, 1) == r) || Off(old(Res_IRQL)[r]) == Off(Res_IRQL[r]));
+free requires ((forall __x:ptr :: {Res_IRQL[__x]} Obj(Res_IRQL[__x]) == null && Off(Res_IRQL[__x]) >= 0));
+free ensures ((forall __x:ptr :: {Res_IRQL[__x]} Obj(Res_IRQL[__x]) == null && Off(Res_IRQL[__x]) >= 0));
+free requires (Res_IRQL[Ptr(null,0)] == Ptr(null,0));
+free ensures (Res_IRQL[Ptr(null,0)] == Ptr(null,0));
+modifies Res_SPINLOCK;
+//TAG: net change in resource SPINLOCK only for: SpinLock
+ensures(forall r:ptr :: {Res_SPINLOCK[r]} (SpinLock1 == r) || Off(old(Res_SPINLOCK)[r]) == Off(Res_SPINLOCK[r]));
+free requires ((forall __x:ptr :: {Res_SPINLOCK[__x]} Obj(Res_SPINLOCK[__x]) == null && Off(Res_SPINLOCK[__x]) >= 0));
+free ensures ((forall __x:ptr :: {Res_SPINLOCK[__x]} Obj(Res_SPINLOCK[__x]) == null && Off(Res_SPINLOCK[__x]) >= 0));
+free requires (Res_SPINLOCK[Ptr(null,0)] == Ptr(null,0));
+free ensures (Res_SPINLOCK[Ptr(null,0)] == Ptr(null,0));
+modifies Res_SPINLOCK_IRQL;
+//TAG: net change in resource SPINLOCK_IRQL only for: SpinLock
+ensures(forall r:ptr :: {Res_SPINLOCK_IRQL[r]} (SpinLock1 == r) || Off(old(Res_SPINLOCK_IRQL)[r]) == Off(Res_SPINLOCK_IRQL[r]));
+free requires ((forall __x:ptr :: {Res_SPINLOCK_IRQL[__x]} Obj(Res_SPINLOCK_IRQL[__x]) == null && Off(Res_SPINLOCK_IRQL[__x]) >= 0));
+free ensures ((forall __x:ptr :: {Res_SPINLOCK_IRQL[__x]} Obj(Res_SPINLOCK_IRQL[__x]) == null && Off(Res_SPINLOCK_IRQL[__x]) >= 0));
+free requires (Res_SPINLOCK_IRQL[Ptr(null,0)] == Ptr(null,0));
+free ensures (Res_SPINLOCK_IRQL[Ptr(null,0)] == Ptr(null,0));
+
+
+
+procedure KfReleaseSpinLock ( SpinLock$11:ptr, NewIrql1:ptr);
+
+//TAG: requires __global_resource("IRQL") == 2
+requires(Res_IRQL[Ptr(null,1)] == Ptr(null, 2));
+//TAG: requires __resource("SPINLOCK", SpinLock) == 1
+requires(Res_SPINLOCK[SpinLock$11] == Ptr(null, 1));
+//TAG: requires __resource("SPINLOCK_IRQL", SpinLock) == NewIrql
+requires(Res_SPINLOCK_IRQL[SpinLock$11] == NewIrql1);
+//TAG: ensures __resource("SPINLOCK", SpinLock) == 0
+ensures(Res_SPINLOCK[SpinLock$11] == Ptr(null, 0));
+//TAG: ensures __global_resource("IRQL") == NewIrql
+ensures(Res_IRQL[Ptr(null,1)] == NewIrql1);
+
+modifies Res_IRQL;
+ensures(forall r:ptr :: {Res_IRQL[r]} (Ptr(null, 1) == r) || Off(old(Res_IRQL)[r]) == Off(Res_IRQL[r]));
+free requires ((forall __x:ptr :: {Res_IRQL[__x]} Obj(Res_IRQL[__x]) == null && Off(Res_IRQL[__x]) >= 0));
+free ensures ((forall __x:ptr :: {Res_IRQL[__x]} Obj(Res_IRQL[__x]) == null && Off(Res_IRQL[__x]) >= 0));
+free requires (Res_IRQL[Ptr(null,0)] == Ptr(null,0));
+free ensures (Res_IRQL[Ptr(null,0)] == Ptr(null,0));
+modifies Res_SPINLOCK;
+//TAG: net change in resource SPINLOCK only for: SpinLock
+ensures(forall r:ptr :: {Res_SPINLOCK[r]} (SpinLock$11 == r) || Off(old(Res_SPINLOCK)[r]) == Off(Res_SPINLOCK[r]));
+free requires ((forall __x:ptr :: {Res_SPINLOCK[__x]} Obj(Res_SPINLOCK[__x]) == null && Off(Res_SPINLOCK[__x]) >= 0));
+free ensures ((forall __x:ptr :: {Res_SPINLOCK[__x]} Obj(Res_SPINLOCK[__x]) == null && Off(Res_SPINLOCK[__x]) >= 0));
+free requires (Res_SPINLOCK[Ptr(null,0)] == Ptr(null,0));
+free ensures (Res_SPINLOCK[Ptr(null,0)] == Ptr(null,0));
+
+
+
+procedure MmPageEntireDriver ( a0:ptr) returns (ret:ptr);
+
+
+procedure MmResetDriverPaging ( a0:ptr) ;
+
+
+procedure FloppyQueueRequest ( DisketteExtension1:ptr, Irp1:ptr) returns ( $result.FloppyQueueRequest$5780.0$1$:ptr)
+
+//TAG: requires $FloppyQueueRequest$pre$0 || (1 ==> __resource("SPINLOCK", &((DISKETTE_EXTENSION *)DeviceExtension)->ListSpinLock) == 0)
+requires($FloppyQueueRequest$pre$0 || ((true) ==> (Res_SPINLOCK[ListSpinLock__DISKETTE_EXTENSION(DisketteExtension1)] == Ptr(null, 0))));
+//TAG: requires $FloppyQueueRequest$pre$1 || (1 ==> __resource("SPINLOCK", &((DISKETTE_EXTENSION *)DeviceExtension)->FlCancelSpinLock) == 0)
+requires($FloppyQueueRequest$pre$1 || ((true) ==> (Res_SPINLOCK[FlCancelSpinLock__DISKETTE_EXTENSION(DisketteExtension1)] == Ptr(null, 0))));
+//TAG: requires $FloppyQueueRequest$pre$2 || (1 ==> __resource("SPINLOCK", &((DISKETTE_EXTENSION *)DeviceExtension)->NewRequestQueueSpinLock) == 0)
+requires($FloppyQueueRequest$pre$2 || ((true) ==> (Res_SPINLOCK[NewRequestQueueSpinLock__DISKETTE_EXTENSION(DisketteExtension1)] == Ptr(null, 0))));
+//TAG: requires $FloppyQueueRequest$pre$3 || (1 ==> ((DISKETTE_EXTENSION *)DeviceExtension)->DeviceObject->DeviceExtension == DeviceExtension)
+requires($FloppyQueueRequest$pre$3 || ((true) ==> (Mem_DeviceExtension__DEVICE_OBJECT[DeviceExtension__DEVICE_OBJECT(Mem_DeviceObject__DISKETTE_EXTENSION[DeviceObject__DISKETTE_EXTENSION(DisketteExtension1)])] == DisketteExtension1)));
+//TAG: ensures $FloppyQueueRequest$post$12 || (1 ==> __resource("SPINLOCK", &((DISKETTE_EXTENSION *)DeviceExtension)->ListSpinLock) == 0)
+ensures($FloppyQueueRequest$post$12 || ((true) ==> (Res_SPINLOCK[ListSpinLock__DISKETTE_EXTENSION(DisketteExtension1)] == Ptr(null, 0))));
+//TAG: ensures $FloppyQueueRequest$post$13 || (1 ==> __resource("SPINLOCK", &((DISKETTE_EXTENSION *)DeviceExtension)->FlCancelSpinLock) == 0)
+ensures($FloppyQueueRequest$post$13 || ((true) ==> (Res_SPINLOCK[FlCancelSpinLock__DISKETTE_EXTENSION(DisketteExtension1)] == Ptr(null, 0))));
+//TAG: ensures $FloppyQueueRequest$post$14 || (1 ==> __resource("SPINLOCK", &((DISKETTE_EXTENSION *)DeviceExtension)->NewRequestQueueSpinLock) == 0)
+ensures($FloppyQueueRequest$post$14 || ((true) ==> (Res_SPINLOCK[NewRequestQueueSpinLock__DISKETTE_EXTENSION(DisketteExtension1)] == Ptr(null, 0))));
+//TAG: ensures $FloppyQueueRequest$post$15 || (1 ==> ((DISKETTE_EXTENSION *)DeviceExtension)->DeviceObject->DeviceExtension == DeviceExtension)
+ensures($FloppyQueueRequest$post$15 || ((true) ==> (Mem_DeviceExtension__DEVICE_OBJECT[DeviceExtension__DEVICE_OBJECT(Mem_DeviceObject__DISKETTE_EXTENSION[DeviceObject__DISKETTE_EXTENSION(DisketteExtension1)])] == DisketteExtension1)));
+modifies alloc;
+free ensures(forall f:ref :: {alloc[f]} old(alloc)[f] != UNALLOCATED ==> alloc[f] == old(alloc)[f]);
+
+modifies Res_IRQL;
+//TAG: no net change in resource IRQL
+ensures(forall r:ptr :: {Res_IRQL[r]} Off(old(Res_IRQL)[r]) == Off(Res_IRQL[r]));
+free requires ((forall __x:ptr :: {Res_IRQL[__x]} Obj(Res_IRQL[__x]) == null && Off(Res_IRQL[__x]) >= 0));
+free ensures ((forall __x:ptr :: {Res_IRQL[__x]} Obj(Res_IRQL[__x]) == null && Off(Res_IRQL[__x]) >= 0));
+free requires (Res_IRQL[Ptr(null,0)] == Ptr(null,0));
+free ensures (Res_IRQL[Ptr(null,0)] == Ptr(null,0));
+modifies Res_SPINLOCK;
+//TAG: net change in resource SPINLOCK only for: &DeviceExtension->ListSpinLock, &DeviceExtension->FlCancelSpinLock, &DeviceExtension->NewRequestQueueSpinLock
+ensures(forall r:ptr :: {Res_SPINLOCK[r]} (!$FloppyQueueRequest$mod$16 && ListSpinLock__DISKETTE_EXTENSION(DisketteExtension1) == r) || (!$FloppyQueueRequest$mod$18 && FlCancelSpinLock__DISKETTE_EXTENSION(DisketteExtension1) == r) || (!$FloppyQueueRequest$mod$20 && NewRequestQueueSpinLock__DISKETTE_EXTENSION(DisketteExtension1) == r) || Off(old(Res_SPINLOCK)[r]) == Off(Res_SPINLOCK[r]));
+free requires ((forall __x:ptr :: {Res_SPINLOCK[__x]} Obj(Res_SPINLOCK[__x]) == null && Off(Res_SPINLOCK[__x]) >= 0));
+free ensures ((forall __x:ptr :: {Res_SPINLOCK[__x]} Obj(Res_SPINLOCK[__x]) == null && Off(Res_SPINLOCK[__x]) >= 0));
+free requires (Res_SPINLOCK[Ptr(null,0)] == Ptr(null,0));
+free ensures (Res_SPINLOCK[Ptr(null,0)] == Ptr(null,0));
+modifies Res_SPINLOCK_IRQL;
+//TAG: net change in resource SPINLOCK_IRQL only for: &DeviceExtension->ListSpinLock, &DeviceExtension->FlCancelSpinLock, &DeviceExtension->NewRequestQueueSpinLock
+ensures(forall r:ptr :: {Res_SPINLOCK_IRQL[r]} (!$FloppyQueueRequest$mod$17 && ListSpinLock__DISKETTE_EXTENSION(DisketteExtension1) == r) || (!$FloppyQueueRequest$mod$19 && FlCancelSpinLock__DISKETTE_EXTENSION(DisketteExtension1) == r) || (!$FloppyQueueRequest$mod$21 && NewRequestQueueSpinLock__DISKETTE_EXTENSION(DisketteExtension1) == r) || Off(old(Res_SPINLOCK_IRQL)[r]) == Off(Res_SPINLOCK_IRQL[r]));
+free requires ((forall __x:ptr :: {Res_SPINLOCK_IRQL[__x]} Obj(Res_SPINLOCK_IRQL[__x]) == null && Off(Res_SPINLOCK_IRQL[__x]) >= 0));
+free ensures ((forall __x:ptr :: {Res_SPINLOCK_IRQL[__x]} Obj(Res_SPINLOCK_IRQL[__x]) == null && Off(Res_SPINLOCK_IRQL[__x]) >= 0));
+free requires (Res_SPINLOCK_IRQL[Ptr(null,0)] == Ptr(null,0));
+free ensures (Res_SPINLOCK_IRQL[Ptr(null,0)] == Ptr(null,0));
+modifies Mem_Control__IO_STACK_LOCATION;
+//TAG: no updated memory locations
+free ensures(forall m:ptr :: {Mem_Control__IO_STACK_LOCATION[m]} Mem_Control__IO_STACK_LOCATION[m] == old(Mem_Control__IO_STACK_LOCATION)[m]);
+free ensures(Mem_Control__IO_STACK_LOCATION[Ptr(null,0)] == old(Mem_Control__IO_STACK_LOCATION)[Ptr(null,0)]);
+modifies Mem_FUNCTION;
+//TAG: no updated memory locations
+free ensures(forall m:ptr :: {Mem_FUNCTION[m]} Mem_FUNCTION[m] == old(Mem_FUNCTION)[m]);
+free ensures(Mem_FUNCTION[Ptr(null,0)] == old(Mem_FUNCTION)[Ptr(null,0)]);
+modifies Mem_FlCancelSpinLock__DISKETTE_EXTENSION;
+//TAG: no updated memory locations
+free ensures(forall m:ptr :: {Mem_FlCancelSpinLock__DISKETTE_EXTENSION[m]} Mem_FlCancelSpinLock__DISKETTE_EXTENSION[m] == old(Mem_FlCancelSpinLock__DISKETTE_EXTENSION)[m]);
+free ensures(Mem_FlCancelSpinLock__DISKETTE_EXTENSION[Ptr(null,0)] == old(Mem_FlCancelSpinLock__DISKETTE_EXTENSION)[Ptr(null,0)]);
+modifies Mem_Information__IO_STATUS_BLOCK;
+//TAG: no updated memory locations
+free ensures(forall m:ptr :: {Mem_Information__IO_STATUS_BLOCK[m]} Mem_Information__IO_STATUS_BLOCK[m] == old(Mem_Information__IO_STATUS_BLOCK)[m]);
+free ensures(Mem_Information__IO_STATUS_BLOCK[Ptr(null,0)] == old(Mem_Information__IO_STATUS_BLOCK)[Ptr(null,0)]);
+modifies Mem_NewRequestQueueSpinLock__DISKETTE_EXTENSION;
+//TAG: no updated memory locations
+free ensures(forall m:ptr :: {Mem_NewRequestQueueSpinLock__DISKETTE_EXTENSION[m]} Mem_NewRequestQueueSpinLock__DISKETTE_EXTENSION[m] == old(Mem_NewRequestQueueSpinLock__DISKETTE_EXTENSION)[m]);
+free ensures(Mem_NewRequestQueueSpinLock__DISKETTE_EXTENSION[Ptr(null,0)] == old(Mem_NewRequestQueueSpinLock__DISKETTE_EXTENSION)[Ptr(null,0)]);
+modifies Mem_Status___unnamed_4_c7b3d275;
+//TAG: no updated memory locations
+free ensures(forall m:ptr :: {Mem_Status___unnamed_4_c7b3d275[m]} Mem_Status___unnamed_4_c7b3d275[m] == old(Mem_Status___unnamed_4_c7b3d275)[m]);
+free ensures(Mem_Status___unnamed_4_c7b3d275[Ptr(null,0)] == old(Mem_Status___unnamed_4_c7b3d275)[Ptr(null,0)]);
+modifies Mem_UINT4;
+//TAG: no updated memory locations
+free ensures(forall m:ptr :: {Mem_UINT4[m]} Mem_UINT4[m] == old(Mem_UINT4)[m]);
+free ensures(Mem_UINT4[Ptr(null,0)] == old(Mem_UINT4)[Ptr(null,0)]);
+
+{
+var havoc_stringTemp:ptr;
+var condVal:ptr;
+var DisketteExtension : ptr;
+var Irp : ptr;
+var $RtlAssert.arg.1$3$ : ptr;
+var $RtlAssert.arg.2$2$ : ptr;
+var $_InterlockedExchange.arg.1$7$ : ptr;
+var $_InterlockedExchange.arg.1$9$ : ptr;
+var $_InterlockedExchange.arg.2$6$ : ptr;
+var $ntStatus$4$5806.24$ : ptr;
+var $oldIrql$3$5805.24$ : ptr;
+var $result.ExfInterlockedInsertTailList$5854.36$11$ : ptr;
+var $result.KfAcquireSpinLock$5825.4$4$ : ptr;
+var $result.MmPageEntireDriver$5842.8$10$ : ptr;
+var $result._InterlockedExchange$5826.4$5$ : ptr;
+var $result._InterlockedExchange$5831.26$8$ : ptr;
+var tempBoogie0:ptr;
+var tempBoogie1:ptr;
+var tempBoogie2:ptr;
+var tempBoogie3:ptr;
+var tempBoogie4:ptr;
+var tempBoogie5:ptr;
+var tempBoogie6:ptr;
+var tempBoogie7:ptr;
+var tempBoogie8:ptr;
+var tempBoogie9:ptr;
+var tempBoogie10:ptr;
+var tempBoogie11:ptr;
+var tempBoogie12:ptr;
+var tempBoogie13:ptr;
+var tempBoogie14:ptr;
+var tempBoogie15:ptr;
+var tempBoogie16:ptr;
+var tempBoogie17:ptr;
+var tempBoogie18:ptr;
+var tempBoogie19:ptr;
+
+
+start:
+
+assume (alloc[Obj(DisketteExtension1)] != UNALLOCATED);
+assume (alloc[Obj(Irp1)] != UNALLOCATED);
+DisketteExtension := Ptr(null, 0);
+Irp := Ptr(null, 0);
+$RtlAssert.arg.1$3$ := Ptr(null, 0);
+$RtlAssert.arg.2$2$ := Ptr(null, 0);
+$_InterlockedExchange.arg.1$7$ := Ptr(null, 0);
+$_InterlockedExchange.arg.1$9$ := Ptr(null, 0);
+$_InterlockedExchange.arg.2$6$ := Ptr(null, 0);
+$ntStatus$4$5806.24$ := Ptr(null, 0);
+$oldIrql$3$5805.24$ := Ptr(null, 0);
+$result.ExfInterlockedInsertTailList$5854.36$11$ := Ptr(null, 0);
+$result.KfAcquireSpinLock$5825.4$4$ := Ptr(null, 0);
+$result.MmPageEntireDriver$5842.8$10$ := Ptr(null, 0);
+$result._InterlockedExchange$5826.4$5$ := Ptr(null, 0);
+$result._InterlockedExchange$5831.26$8$ := Ptr(null, 0);
+DisketteExtension := DisketteExtension1;
+Irp := Irp1;
+$result.FloppyQueueRequest$5780.0$1$ := Ptr(null,0);
+goto label_3;
+
+
+// c:\nt\drivers\storage\fdc\flpydisk\floppy.c(5864)
+label_1:
+assume (forall m:ptr :: {Mem_Control__IO_STACK_LOCATION[m]} alloc[Obj(m)] != ALLOCATED && old(alloc)[Obj(m)] != ALLOCATED ==> Mem_Control__IO_STACK_LOCATION[m] == old(Mem_Control__IO_STACK_LOCATION)[m]);
+assume (forall m:ptr :: {Mem_FUNCTION[m]} alloc[Obj(m)] != ALLOCATED && old(alloc)[Obj(m)] != ALLOCATED ==> Mem_FUNCTION[m] == old(Mem_FUNCTION)[m]);
+assume (forall m:ptr :: {Mem_FlCancelSpinLock__DISKETTE_EXTENSION[m]} alloc[Obj(m)] != ALLOCATED && old(alloc)[Obj(m)] != ALLOCATED ==> Mem_FlCancelSpinLock__DISKETTE_EXTENSION[m] == old(Mem_FlCancelSpinLock__DISKETTE_EXTENSION)[m]);
+assume (forall m:ptr :: {Mem_Information__IO_STATUS_BLOCK[m]} alloc[Obj(m)] != ALLOCATED && old(alloc)[Obj(m)] != ALLOCATED ==> Mem_Information__IO_STATUS_BLOCK[m] == old(Mem_Information__IO_STATUS_BLOCK)[m]);
+assume (forall m:ptr :: {Mem_NewRequestQueueSpinLock__DISKETTE_EXTENSION[m]} alloc[Obj(m)] != ALLOCATED && old(alloc)[Obj(m)] != ALLOCATED ==> Mem_NewRequestQueueSpinLock__DISKETTE_EXTENSION[m] == old(Mem_NewRequestQueueSpinLock__DISKETTE_EXTENSION)[m]);
+assume (forall m:ptr :: {Mem_Status___unnamed_4_c7b3d275[m]} alloc[Obj(m)] != ALLOCATED && old(alloc)[Obj(m)] != ALLOCATED ==> Mem_Status___unnamed_4_c7b3d275[m] == old(Mem_Status___unnamed_4_c7b3d275)[m]);
+assume (forall m:ptr :: {Mem_UINT4[m]} alloc[Obj(m)] != ALLOCATED && old(alloc)[Obj(m)] != ALLOCATED ==> Mem_UINT4[m] == old(Mem_UINT4)[m]);
+return;
+
+
+// c:\nt\drivers\storage\fdc\flpydisk\floppy.c(5864)
+label_2:
+assume false;
+return;
+
+
+// c:\nt\drivers\storage\fdc\flpydisk\floppy.c(5805)
+label_3:
+goto label_4;
+
+
+// c:\nt\drivers\storage\fdc\flpydisk\floppy.c(5806)
+label_4:
+goto label_5;
+
+
+// c:\nt\drivers\storage\fdc\flpydisk\floppy.c(5811)
+label_5:
+call ExAcquireFastMutex (Mem_P_FAST_MUTEX[PagingMutex]);
+goto label_8;
+
+
+// c:\nt\drivers\storage\fdc\flpydisk\floppy.c(5811)
+label_8:
+tempBoogie0 := Ptr(Obj(Mem_UINT4[PagingReferenceCount]), Off(Mem_UINT4[PagingReferenceCount]) + 1 * 1) ;
+Mem_UINT4[PagingReferenceCount] := tempBoogie0;
+goto label_8_true , label_8_false ;
+
+
+label_8_true :
+assume (Mem_UINT4[PagingReferenceCount] == Ptr(null, 1));
+goto label_12;
+
+
+label_8_false :
+assume !(Mem_UINT4[PagingReferenceCount] == Ptr(null, 1));
+goto label_9;
+
+
+// c:\nt\drivers\storage\fdc\flpydisk\floppy.c(5811)
+label_9:
+call ExReleaseFastMutex (Mem_P_FAST_MUTEX[PagingMutex]);
+goto label_15;
+
+
+// c:\nt\drivers\storage\fdc\flpydisk\floppy.c(5811)
+label_12:
+call MmResetDriverPaging (DriverEntry);
+goto label_9;
+
+
+// c:\nt\drivers\storage\fdc\flpydisk\floppy.c(5816)
+label_15:
+goto label_15_true , label_15_false ;
+
+
+label_15_true :
+assume (Mem_HoldNewRequests__DISKETTE_EXTENSION[HoldNewRequests__DISKETTE_EXTENSION(DisketteExtension)] != Ptr(null,0));
+goto label_17;
+
+
+label_15_false :
+assume (Mem_HoldNewRequests__DISKETTE_EXTENSION[HoldNewRequests__DISKETTE_EXTENSION(DisketteExtension)] == Ptr(null,0));
+goto label_16;
+
+
+// c:\nt\drivers\storage\fdc\flpydisk\floppy.c(5816)
+label_16:
+call havoc_stringTemp := __HAVOC_malloc_stack(Ptr(null,1));
+$RtlAssert.arg.2$2$ := havoc_stringTemp ;
+goto label_61;
+
+
+// c:\nt\drivers\storage\fdc\flpydisk\floppy.c(5825)
+label_17:
+assume (Mem_FlCancelSpinLock__DISKETTE_EXTENSION[FlCancelSpinLock__DISKETTE_EXTENSION(DisketteExtension)] == Mem_UINT4[FlCancelSpinLock__DISKETTE_EXTENSION(DisketteExtension)]);
+call $result.KfAcquireSpinLock$5825.4$4$ := KfAcquireSpinLock (FlCancelSpinLock__DISKETTE_EXTENSION(DisketteExtension));
+Mem_FlCancelSpinLock__DISKETTE_EXTENSION[FlCancelSpinLock__DISKETTE_EXTENSION(DisketteExtension)] := Mem_UINT4[FlCancelSpinLock__DISKETTE_EXTENSION(DisketteExtension)];
+goto label_20;
+
+
+// c:\nt\drivers\storage\fdc\flpydisk\floppy.c(5825)
+label_20:
+$oldIrql$3$5805.24$ := $result.KfAcquireSpinLock$5825.4$4$ ;
+goto label_21;
+
+
+// c:\nt\drivers\storage\fdc\flpydisk\floppy.c(5826)
+label_21:
+$_InterlockedExchange.arg.2$6$ := FloppyCancelQueuedRequest ;
+goto label_22;
+
+
+// c:\nt\drivers\storage\fdc\flpydisk\floppy.c(5826)
+label_22:
+$_InterlockedExchange.arg.1$7$ := CancelRoutine__IRP(Irp) ;
+goto label_23;
+
+
+// c:\nt\drivers\storage\fdc\flpydisk\floppy.c(5826)
+label_23:
+// ignoring intrinsic intrinsic._InterlockedExchange
+havoc $result._InterlockedExchange$5826.4$5$;
+goto label_26;
+
+
+// c:\nt\drivers\storage\fdc\flpydisk\floppy.c(5831)
+label_26:
+goto label_26_true , label_26_false ;
+
+
+label_26_true :
+assume (Mem_Cancel__IRP[Cancel__IRP(Irp)] != Ptr(null,0));
+goto label_28;
+
+
+label_26_false :
+assume (Mem_Cancel__IRP[Cancel__IRP(Irp)] == Ptr(null,0));
+goto label_27;
+
+
+// c:\nt\drivers\storage\fdc\flpydisk\floppy.c(5850)
+label_27:
+Mem_Status___unnamed_4_c7b3d275[Status___unnamed_4_c7b3d275(__unnamed_4_c7b3d275__IO_STATUS_BLOCK(IoStatus__IRP(Irp)))] := Ptr(null, 259) ;
+goto label_53;
+
+
+// c:\nt\drivers\storage\fdc\flpydisk\floppy.c(5831)
+label_28:
+$_InterlockedExchange.arg.1$9$ := CancelRoutine__IRP(Irp) ;
+goto label_29;
+
+
+// c:\nt\drivers\storage\fdc\flpydisk\floppy.c(5831)
+label_29:
+// ignoring intrinsic intrinsic._InterlockedExchange
+havoc $result._InterlockedExchange$5831.26$8$;
+goto label_32;
+
+
+// c:\nt\drivers\storage\fdc\flpydisk\floppy.c(5831)
+label_32:
+goto label_32_true , label_32_false ;
+
+
+label_32_true :
+assume ($result._InterlockedExchange$5831.26$8$ != Ptr(null,0));
+goto label_33;
+
+
+label_32_false :
+assume ($result._InterlockedExchange$5831.26$8$ == Ptr(null,0));
+goto label_27;
+
+
+// c:\nt\drivers\storage\fdc\flpydisk\floppy.c(5836)
+label_33:
+Mem_Status___unnamed_4_c7b3d275[Status___unnamed_4_c7b3d275(__unnamed_4_c7b3d275__IO_STATUS_BLOCK(IoStatus__IRP(Irp)))] := Ptr(null, -1073741536) ;
+goto label_34;
+
+
+// c:\nt\drivers\storage\fdc\flpydisk\floppy.c(5837)
+label_34:
+Mem_Information__IO_STATUS_BLOCK[Information__IO_STATUS_BLOCK(IoStatus__IRP(Irp))] := Ptr(null, 0) ;
+goto label_35;
+
+
+// c:\nt\drivers\storage\fdc\flpydisk\floppy.c(5839)
+label_35:
+assume (Mem_FlCancelSpinLock__DISKETTE_EXTENSION[FlCancelSpinLock__DISKETTE_EXTENSION(DisketteExtension)] == Mem_UINT4[FlCancelSpinLock__DISKETTE_EXTENSION(DisketteExtension)]);
+call KfReleaseSpinLock (FlCancelSpinLock__DISKETTE_EXTENSION(DisketteExtension), $oldIrql$3$5805.24$);
+Mem_FlCancelSpinLock__DISKETTE_EXTENSION[FlCancelSpinLock__DISKETTE_EXTENSION(DisketteExtension)] := Mem_UINT4[FlCancelSpinLock__DISKETTE_EXTENSION(DisketteExtension)];
+goto label_38;
+
+
+// c:\nt\drivers\storage\fdc\flpydisk\floppy.c(5840)
+label_38:
+call IofCompleteRequest (Irp, Ptr(null, 0));
+goto label_41;
+
+
+// c:\nt\drivers\storage\fdc\flpydisk\floppy.c(5842)
+label_41:
+call ExAcquireFastMutex (Mem_P_FAST_MUTEX[PagingMutex]);
+goto label_44;
+
+
+// c:\nt\drivers\storage\fdc\flpydisk\floppy.c(5842)
+label_44:
+tempBoogie0 := Ptr(Obj(Mem_UINT4[PagingReferenceCount]), Off(Mem_UINT4[PagingReferenceCount]) - 1) ;
+Mem_UINT4[PagingReferenceCount] := tempBoogie0;
+goto label_44_true , label_44_false ;
+
+
+label_44_true :
+assume (Mem_UINT4[PagingReferenceCount] != Ptr(null,0));
+goto label_48;
+
+
+label_44_false :
+assume (Mem_UINT4[PagingReferenceCount] == Ptr(null,0));
+goto label_45;
+
+
+// c:\nt\drivers\storage\fdc\flpydisk\floppy.c(5842)
+label_45:
+call $result.MmPageEntireDriver$5842.8$10$ := MmPageEntireDriver (DriverEntry);
+goto label_48;
+
+
+// c:\nt\drivers\storage\fdc\flpydisk\floppy.c(5842)
+label_48:
+call ExReleaseFastMutex (Mem_P_FAST_MUTEX[PagingMutex]);
+goto label_51;
+
+
+// c:\nt\drivers\storage\fdc\flpydisk\floppy.c(5844)
+label_51:
+$ntStatus$4$5806.24$ := Ptr(null, -1073741536) ;
+goto label_52;
+
+
+// c:\nt\drivers\storage\fdc\flpydisk\floppy.c(5863)
+label_52:
+$result.FloppyQueueRequest$5780.0$1$ := $ntStatus$4$5806.24$ ;
+goto label_1;
+
+
+// c:\nt\drivers\storage\fdc\flpydisk\floppy.c(5852)
+label_53:
+tempBoogie0 := BIT_BOR(Mem_Control__IO_STACK_LOCATION[Control__IO_STACK_LOCATION(Mem_CurrentStackLocation___unnamed_4_f80453a0[CurrentStackLocation___unnamed_4_f80453a0(__unnamed_4_f80453a0___unnamed_12_003c1454(__unnamed_12_003c1454___unnamed_40_6ef75b20(Overlay___unnamed_48_c27ef811(Tail__IRP(Irp)))))])], Ptr(null, 1)) ;
+Mem_Control__IO_STACK_LOCATION[Control__IO_STACK_LOCATION(Mem_CurrentStackLocation___unnamed_4_f80453a0[CurrentStackLocation___unnamed_4_f80453a0(__unnamed_4_f80453a0___unnamed_12_003c1454(__unnamed_12_003c1454___unnamed_40_6ef75b20(Overlay___unnamed_48_c27ef811(Tail__IRP(Irp)))))])] := tempBoogie0 ;
+goto label_54;
+
+
+// c:\nt\drivers\storage\fdc\flpydisk\floppy.c(5854)
+label_54:
+assume (Mem_NewRequestQueueSpinLock__DISKETTE_EXTENSION[NewRequestQueueSpinLock__DISKETTE_EXTENSION(DisketteExtension)] == Mem_UINT4[NewRequestQueueSpinLock__DISKETTE_EXTENSION(DisketteExtension)]);
+call $result.ExfInterlockedInsertTailList$5854.36$11$ := ExfInterlockedInsertTailList (NewRequestQueue__DISKETTE_EXTENSION(DisketteExtension), ListEntry___unnamed_12_003c1454(__unnamed_12_003c1454___unnamed_40_6ef75b20(Overlay___unnamed_48_c27ef811(Tail__IRP(Irp)))), NewRequestQueueSpinLock__DISKETTE_EXTENSION(DisketteExtension));
+Mem_NewRequestQueueSpinLock__DISKETTE_EXTENSION[NewRequestQueueSpinLock__DISKETTE_EXTENSION(DisketteExtension)] := Mem_UINT4[NewRequestQueueSpinLock__DISKETTE_EXTENSION(DisketteExtension)];
+goto label_57;
+
+
+// c:\nt\drivers\storage\fdc\flpydisk\floppy.c(5858)
+label_57:
+assume (Mem_FlCancelSpinLock__DISKETTE_EXTENSION[FlCancelSpinLock__DISKETTE_EXTENSION(DisketteExtension)] == Mem_UINT4[FlCancelSpinLock__DISKETTE_EXTENSION(DisketteExtension)]);
+call KfReleaseSpinLock (FlCancelSpinLock__DISKETTE_EXTENSION(DisketteExtension), $oldIrql$3$5805.24$);
+Mem_FlCancelSpinLock__DISKETTE_EXTENSION[FlCancelSpinLock__DISKETTE_EXTENSION(DisketteExtension)] := Mem_UINT4[FlCancelSpinLock__DISKETTE_EXTENSION(DisketteExtension)];
+goto label_60;
+
+
+// c:\nt\drivers\storage\fdc\flpydisk\floppy.c(5860)
+label_60:
+$ntStatus$4$5806.24$ := Ptr(null, 259) ;
+goto label_52;
+
+
+// c:\nt\drivers\storage\fdc\flpydisk\floppy.c(5816)
+label_61:
+call havoc_stringTemp := __HAVOC_malloc_stack(Ptr(null,1));
+$RtlAssert.arg.1$3$ := havoc_stringTemp ;
+goto label_62;
+
+
+// c:\nt\drivers\storage\fdc\flpydisk\floppy.c(5816)
+label_62:
+// skip RtlAssert
+goto label_17;
+
+}
+
+
+
+procedure FloppyReadWrite ( DeviceObject1:ptr, Irp$11:ptr) returns ( $result.FloppyReadWrite$2203.0$1$:ptr)
+
+//TAG: requires $FloppyReadWrite$pre$42 || (1 ==> __resource("SPINLOCK", &((DISKETTE_EXTENSION *)(DISKETTE_EXTENSION *)(DeviceObject->DeviceExtension))->ListSpinLock) == 0)
+requires($FloppyReadWrite$pre$42 || ((true) ==> (Res_SPINLOCK[ListSpinLock__DISKETTE_EXTENSION(Mem_DeviceExtension__DEVICE_OBJECT[DeviceExtension__DEVICE_OBJECT(DeviceObject1)])] == Ptr(null, 0))));
+//TAG: requires $FloppyReadWrite$pre$43 || (1 ==> __resource("SPINLOCK", &((DISKETTE_EXTENSION *)(DISKETTE_EXTENSION *)(DeviceObject->DeviceExtension))->FlCancelSpinLock) == 0)
+requires($FloppyReadWrite$pre$43 || ((true) ==> (Res_SPINLOCK[FlCancelSpinLock__DISKETTE_EXTENSION(Mem_DeviceExtension__DEVICE_OBJECT[DeviceExtension__DEVICE_OBJECT(DeviceObject1)])] == Ptr(null, 0))));
+//TAG: requires $FloppyReadWrite$pre$44 || (1 ==> __resource("SPINLOCK", &((DISKETTE_EXTENSION *)(DISKETTE_EXTENSION *)(DeviceObject->DeviceExtension))->NewRequestQueueSpinLock) == 0)
+requires($FloppyReadWrite$pre$44 || ((true) ==> (Res_SPINLOCK[NewRequestQueueSpinLock__DISKETTE_EXTENSION(Mem_DeviceExtension__DEVICE_OBJECT[DeviceExtension__DEVICE_OBJECT(DeviceObject1)])] == Ptr(null, 0))));
+//TAG: requires $FloppyReadWrite$pre$45 || (1 ==> ((DISKETTE_EXTENSION *)(DISKETTE_EXTENSION *)(DeviceObject->DeviceExtension))->DeviceObject->DeviceExtension == (DISKETTE_EXTENSION *)(DeviceObject->DeviceExtension))
+requires($FloppyReadWrite$pre$45 || ((true) ==> (Mem_DeviceExtension__DEVICE_OBJECT[DeviceExtension__DEVICE_OBJECT(Mem_DeviceObject__DISKETTE_EXTENSION[DeviceObject__DISKETTE_EXTENSION(Mem_DeviceExtension__DEVICE_OBJECT[DeviceExtension__DEVICE_OBJECT(DeviceObject1)])])] == Mem_DeviceExtension__DEVICE_OBJECT[DeviceExtension__DEVICE_OBJECT(DeviceObject1)])));
+//TAG: requires $FloppyReadWrite$pre$46 || (((DISKETTE_EXTENSION *)(DeviceObject->DeviceExtension))->DeviceObject == DeviceObject)
+requires($FloppyReadWrite$pre$46 || (Mem_DeviceObject__DISKETTE_EXTENSION[DeviceObject__DISKETTE_EXTENSION(Mem_DeviceExtension__DEVICE_OBJECT[DeviceExtension__DEVICE_OBJECT(DeviceObject1)])] == DeviceObject1));
+//TAG: ensures $FloppyReadWrite$post$57 || (1 ==> __resource("SPINLOCK", &((DISKETTE_EXTENSION *)(DISKETTE_EXTENSION *)(DeviceObject->DeviceExtension))->ListSpinLock) == 0)
+ensures($FloppyReadWrite$post$57 || ((true) ==> (Res_SPINLOCK[ListSpinLock__DISKETTE_EXTENSION(Mem_DeviceExtension__DEVICE_OBJECT[DeviceExtension__DEVICE_OBJECT(DeviceObject1)])] == Ptr(null, 0))));
+//TAG: ensures $FloppyReadWrite$post$58 || (1 ==> __resource("SPINLOCK", &((DISKETTE_EXTENSION *)(DISKETTE_EXTENSION *)(DeviceObject->DeviceExtension))->FlCancelSpinLock) == 0)
+ensures($FloppyReadWrite$post$58 || ((true) ==> (Res_SPINLOCK[FlCancelSpinLock__DISKETTE_EXTENSION(Mem_DeviceExtension__DEVICE_OBJECT[DeviceExtension__DEVICE_OBJECT(DeviceObject1)])] == Ptr(null, 0))));
+//TAG: ensures $FloppyReadWrite$post$59 || (1 ==> __resource("SPINLOCK", &((DISKETTE_EXTENSION *)(DISKETTE_EXTENSION *)(DeviceObject->DeviceExtension))->NewRequestQueueSpinLock) == 0)
+ensures($FloppyReadWrite$post$59 || ((true) ==> (Res_SPINLOCK[NewRequestQueueSpinLock__DISKETTE_EXTENSION(Mem_DeviceExtension__DEVICE_OBJECT[DeviceExtension__DEVICE_OBJECT(DeviceObject1)])] == Ptr(null, 0))));
+//TAG: ensures $FloppyReadWrite$post$60 || (1 ==> ((DISKETTE_EXTENSION *)(DISKETTE_EXTENSION *)(DeviceObject->DeviceExtension))->DeviceObject->DeviceExtension == (DISKETTE_EXTENSION *)(DeviceObject->DeviceExtension))
+ensures($FloppyReadWrite$post$60 || ((true) ==> (Mem_DeviceExtension__DEVICE_OBJECT[DeviceExtension__DEVICE_OBJECT(Mem_DeviceObject__DISKETTE_EXTENSION[DeviceObject__DISKETTE_EXTENSION(Mem_DeviceExtension__DEVICE_OBJECT[DeviceExtension__DEVICE_OBJECT(DeviceObject1)])])] == Mem_DeviceExtension__DEVICE_OBJECT[DeviceExtension__DEVICE_OBJECT(DeviceObject1)])));
+//TAG: ensures $FloppyReadWrite$post$61 || (((DISKETTE_EXTENSION *)(DeviceObject->DeviceExtension))->DeviceObject == DeviceObject)
+ensures($FloppyReadWrite$post$61 || (Mem_DeviceObject__DISKETTE_EXTENSION[DeviceObject__DISKETTE_EXTENSION(Mem_DeviceExtension__DEVICE_OBJECT[DeviceExtension__DEVICE_OBJECT(DeviceObject1)])] == DeviceObject1));
+modifies alloc;
+free ensures(forall f:ref :: {alloc[f]} old(alloc)[f] != UNALLOCATED ==> alloc[f] == old(alloc)[f]);
+
+modifies Res_IRQL;
+//TAG: no net change in resource IRQL
+ensures(forall r:ptr :: {Res_IRQL[r]} Off(old(Res_IRQL)[r]) == Off(Res_IRQL[r]));
+free requires ((forall __x:ptr :: {Res_IRQL[__x]} Obj(Res_IRQL[__x]) == null && Off(Res_IRQL[__x]) >= 0));
+free ensures ((forall __x:ptr :: {Res_IRQL[__x]} Obj(Res_IRQL[__x]) == null && Off(Res_IRQL[__x]) >= 0));
+free requires (Res_IRQL[Ptr(null,0)] == Ptr(null,0));
+free ensures (Res_IRQL[Ptr(null,0)] == Ptr(null,0));
+modifies Res_SPINLOCK;
+//TAG: net change in resource SPINLOCK only for: &((DISKETTE_EXTENSION *)(DeviceObject->DeviceExtension))->ListSpinLock, &((DISKETTE_EXTENSION *)(DeviceObject->DeviceExtension))->FlCancelSpinLock, &((DISKETTE_EXTENSION *)(DeviceObject->DeviceExtension))->NewRequestQueueSpinLock
+ensures(forall r:ptr :: {Res_SPINLOCK[r]} (!$FloppyReadWrite$mod$62 && ListSpinLock__DISKETTE_EXTENSION(Mem_DeviceExtension__DEVICE_OBJECT[DeviceExtension__DEVICE_OBJECT(DeviceObject1)]) == r) || (!$FloppyReadWrite$mod$64 && FlCancelSpinLock__DISKETTE_EXTENSION(Mem_DeviceExtension__DEVICE_OBJECT[DeviceExtension__DEVICE_OBJECT(DeviceObject1)]) == r) || (!$FloppyReadWrite$mod$66 && NewRequestQueueSpinLock__DISKETTE_EXTENSION(Mem_DeviceExtension__DEVICE_OBJECT[DeviceExtension__DEVICE_OBJECT(DeviceObject1)]) == r) || Off(old(Res_SPINLOCK)[r]) == Off(Res_SPINLOCK[r]));
+free requires ((forall __x:ptr :: {Res_SPINLOCK[__x]} Obj(Res_SPINLOCK[__x]) == null && Off(Res_SPINLOCK[__x]) >= 0));
+free ensures ((forall __x:ptr :: {Res_SPINLOCK[__x]} Obj(Res_SPINLOCK[__x]) == null && Off(Res_SPINLOCK[__x]) >= 0));
+free requires (Res_SPINLOCK[Ptr(null,0)] == Ptr(null,0));
+free ensures (Res_SPINLOCK[Ptr(null,0)] == Ptr(null,0));
+modifies Res_SPINLOCK_IRQL;
+//TAG: net change in resource SPINLOCK_IRQL only for: &((DISKETTE_EXTENSION *)(DeviceObject->DeviceExtension))->ListSpinLock, &((DISKETTE_EXTENSION *)(DeviceObject->DeviceExtension))->FlCancelSpinLock, &((DISKETTE_EXTENSION *)(DeviceObject->DeviceExtension))->NewRequestQueueSpinLock
+ensures(forall r:ptr :: {Res_SPINLOCK_IRQL[r]} (!$FloppyReadWrite$mod$63 && ListSpinLock__DISKETTE_EXTENSION(Mem_DeviceExtension__DEVICE_OBJECT[DeviceExtension__DEVICE_OBJECT(DeviceObject1)]) == r) || (!$FloppyReadWrite$mod$65 && FlCancelSpinLock__DISKETTE_EXTENSION(Mem_DeviceExtension__DEVICE_OBJECT[DeviceExtension__DEVICE_OBJECT(DeviceObject1)]) == r) || (!$FloppyReadWrite$mod$67 && NewRequestQueueSpinLock__DISKETTE_EXTENSION(Mem_DeviceExtension__DEVICE_OBJECT[DeviceExtension__DEVICE_OBJECT(DeviceObject1)]) == r) || Off(old(Res_SPINLOCK_IRQL)[r]) == Off(Res_SPINLOCK_IRQL[r]));
+free requires ((forall __x:ptr :: {Res_SPINLOCK_IRQL[__x]} Obj(Res_SPINLOCK_IRQL[__x]) == null && Off(Res_SPINLOCK_IRQL[__x]) >= 0));
+free ensures ((forall __x:ptr :: {Res_SPINLOCK_IRQL[__x]} Obj(Res_SPINLOCK_IRQL[__x]) == null && Off(Res_SPINLOCK_IRQL[__x]) >= 0));
+free requires (Res_SPINLOCK_IRQL[Ptr(null,0)] == Ptr(null,0));
+free ensures (Res_SPINLOCK_IRQL[Ptr(null,0)] == Ptr(null,0));
+modifies Mem_Control__IO_STACK_LOCATION;
+//TAG: no updated memory locations
+free ensures(forall m:ptr :: {Mem_Control__IO_STACK_LOCATION[m]} Mem_Control__IO_STACK_LOCATION[m] == old(Mem_Control__IO_STACK_LOCATION)[m]);
+free ensures(Mem_Control__IO_STACK_LOCATION[Ptr(null,0)] == old(Mem_Control__IO_STACK_LOCATION)[Ptr(null,0)]);
+modifies Mem_FUNCTION;
+//TAG: no updated memory locations
+free ensures(forall m:ptr :: {Mem_FUNCTION[m]} Mem_FUNCTION[m] == old(Mem_FUNCTION)[m]);
+free ensures(Mem_FUNCTION[Ptr(null,0)] == old(Mem_FUNCTION)[Ptr(null,0)]);
+modifies Mem_FlCancelSpinLock__DISKETTE_EXTENSION;
+//TAG: no updated memory locations
+free ensures(forall m:ptr :: {Mem_FlCancelSpinLock__DISKETTE_EXTENSION[m]} Mem_FlCancelSpinLock__DISKETTE_EXTENSION[m] == old(Mem_FlCancelSpinLock__DISKETTE_EXTENSION)[m]);
+free ensures(Mem_FlCancelSpinLock__DISKETTE_EXTENSION[Ptr(null,0)] == old(Mem_FlCancelSpinLock__DISKETTE_EXTENSION)[Ptr(null,0)]);
+modifies Mem_Information__IO_STATUS_BLOCK;
+//TAG: no updated memory locations
+free ensures(forall m:ptr :: {Mem_Information__IO_STATUS_BLOCK[m]} Mem_Information__IO_STATUS_BLOCK[m] == old(Mem_Information__IO_STATUS_BLOCK)[m]);
+free ensures(Mem_Information__IO_STATUS_BLOCK[Ptr(null,0)] == old(Mem_Information__IO_STATUS_BLOCK)[Ptr(null,0)]);
+modifies Mem_NewRequestQueueSpinLock__DISKETTE_EXTENSION;
+//TAG: no updated memory locations
+free ensures(forall m:ptr :: {Mem_NewRequestQueueSpinLock__DISKETTE_EXTENSION[m]} Mem_NewRequestQueueSpinLock__DISKETTE_EXTENSION[m] == old(Mem_NewRequestQueueSpinLock__DISKETTE_EXTENSION)[m]);
+free ensures(Mem_NewRequestQueueSpinLock__DISKETTE_EXTENSION[Ptr(null,0)] == old(Mem_NewRequestQueueSpinLock__DISKETTE_EXTENSION)[Ptr(null,0)]);
+modifies Mem_Status___unnamed_4_c7b3d275;
+//TAG: no updated memory locations
+free ensures(forall m:ptr :: {Mem_Status___unnamed_4_c7b3d275[m]} Mem_Status___unnamed_4_c7b3d275[m] == old(Mem_Status___unnamed_4_c7b3d275)[m]);
+free ensures(Mem_Status___unnamed_4_c7b3d275[Ptr(null,0)] == old(Mem_Status___unnamed_4_c7b3d275)[Ptr(null,0)]);
+modifies Mem_UINT4;
+//TAG: no updated memory locations
+free ensures(forall m:ptr :: {Mem_UINT4[m]} Mem_UINT4[m] == old(Mem_UINT4)[m]);
+free ensures(Mem_UINT4[Ptr(null,0)] == old(Mem_UINT4)[Ptr(null,0)]);
+
+{
+var havoc_stringTemp:ptr;
+var condVal:ptr;
+var $DbgPrint.arg.1$10$ : ptr;
+var $DbgPrint.arg.1$13$ : ptr;
+var $DbgPrint.arg.1$15$ : ptr;
+var $DbgPrint.arg.1$3$ : ptr;
+var $DbgPrint.arg.1$6$ : ptr;
+var $DbgPrint.arg.1$8$ : ptr;
+var DeviceObject : ptr;
+var Irp$1 : ptr;
+var $disketteExtension$5$2232.24$ : ptr;
+var $irpSp$3$2230.23$ : ptr;
+var $ntStatus$4$2231.13$ : ptr;
+var $result.DbgPrint$2234.4$2$ : ptr;
+var $result.DbgPrint$2278.0$5$ : ptr;
+var $result.DbgPrint$2280.0$7$ : ptr;
+var $result.DbgPrint$2305.0$9$ : ptr;
+var $result.DbgPrint$2317.0$12$ : ptr;
+var $result.DbgPrint$2327.0$14$ : ptr;
+var $result.FlQueueIrpToThread$2308.41$11$ : ptr;
+var $result.FloppyQueueRequest$2247.37$4$ : ptr;
+var tempBoogie0:ptr;
+var tempBoogie1:ptr;
+var tempBoogie2:ptr;
+var tempBoogie3:ptr;
+var tempBoogie4:ptr;
+var tempBoogie5:ptr;
+var tempBoogie6:ptr;
+var tempBoogie7:ptr;
+var tempBoogie8:ptr;
+var tempBoogie9:ptr;
+var tempBoogie10:ptr;
+var tempBoogie11:ptr;
+var tempBoogie12:ptr;
+var tempBoogie13:ptr;
+var tempBoogie14:ptr;
+var tempBoogie15:ptr;
+var tempBoogie16:ptr;
+var tempBoogie17:ptr;
+var tempBoogie18:ptr;
+var tempBoogie19:ptr;
+
+
+start:
+
+assume (alloc[Obj(DeviceObject1)] != UNALLOCATED);
+assume (alloc[Obj(Irp$11)] != UNALLOCATED);
+$DbgPrint.arg.1$10$ := Ptr(null, 0);
+$DbgPrint.arg.1$13$ := Ptr(null, 0);
+$DbgPrint.arg.1$15$ := Ptr(null, 0);
+$DbgPrint.arg.1$3$ := Ptr(null, 0);
+$DbgPrint.arg.1$6$ := Ptr(null, 0);
+$DbgPrint.arg.1$8$ := Ptr(null, 0);
+DeviceObject := Ptr(null, 0);
+Irp$1 := Ptr(null, 0);
+$disketteExtension$5$2232.24$ := Ptr(null, 0);
+$irpSp$3$2230.23$ := Ptr(null, 0);
+$ntStatus$4$2231.13$ := Ptr(null, 0);
+$result.DbgPrint$2234.4$2$ := Ptr(null, 0);
+$result.DbgPrint$2278.0$5$ := Ptr(null, 0);
+$result.DbgPrint$2280.0$7$ := Ptr(null, 0);
+$result.DbgPrint$2305.0$9$ := Ptr(null, 0);
+$result.DbgPrint$2317.0$12$ := Ptr(null, 0);
+$result.DbgPrint$2327.0$14$ := Ptr(null, 0);
+$result.FlQueueIrpToThread$2308.41$11$ := Ptr(null, 0);
+$result.FloppyQueueRequest$2247.37$4$ := Ptr(null, 0);
+DeviceObject := DeviceObject1;
+Irp$1 := Irp$11;
+$result.FloppyReadWrite$2203.0$1$ := Ptr(null,0);
+goto label_3;
+
+
+// c:\nt\drivers\storage\fdc\flpydisk\floppy.c(2334)
+label_1:
+assume (forall m:ptr :: {Mem_Control__IO_STACK_LOCATION[m]} alloc[Obj(m)] != ALLOCATED && old(alloc)[Obj(m)] != ALLOCATED ==> Mem_Control__IO_STACK_LOCATION[m] == old(Mem_Control__IO_STACK_LOCATION)[m]);
+assume (forall m:ptr :: {Mem_FUNCTION[m]} alloc[Obj(m)] != ALLOCATED && old(alloc)[Obj(m)] != ALLOCATED ==> Mem_FUNCTION[m] == old(Mem_FUNCTION)[m]);
+assume (forall m:ptr :: {Mem_FlCancelSpinLock__DISKETTE_EXTENSION[m]} alloc[Obj(m)] != ALLOCATED && old(alloc)[Obj(m)] != ALLOCATED ==> Mem_FlCancelSpinLock__DISKETTE_EXTENSION[m] == old(Mem_FlCancelSpinLock__DISKETTE_EXTENSION)[m]);
+assume (forall m:ptr :: {Mem_Information__IO_STATUS_BLOCK[m]} alloc[Obj(m)] != ALLOCATED && old(alloc)[Obj(m)] != ALLOCATED ==> Mem_Information__IO_STATUS_BLOCK[m] == old(Mem_Information__IO_STATUS_BLOCK)[m]);
+assume (forall m:ptr :: {Mem_NewRequestQueueSpinLock__DISKETTE_EXTENSION[m]} alloc[Obj(m)] != ALLOCATED && old(alloc)[Obj(m)] != ALLOCATED ==> Mem_NewRequestQueueSpinLock__DISKETTE_EXTENSION[m] == old(Mem_NewRequestQueueSpinLock__DISKETTE_EXTENSION)[m]);
+assume (forall m:ptr :: {Mem_Status___unnamed_4_c7b3d275[m]} alloc[Obj(m)] != ALLOCATED && old(alloc)[Obj(m)] != ALLOCATED ==> Mem_Status___unnamed_4_c7b3d275[m] == old(Mem_Status___unnamed_4_c7b3d275)[m]);
+assume (forall m:ptr :: {Mem_UINT4[m]} alloc[Obj(m)] != ALLOCATED && old(alloc)[Obj(m)] != ALLOCATED ==> Mem_UINT4[m] == old(Mem_UINT4)[m]);
+return;
+
+
+// c:\nt\drivers\storage\fdc\flpydisk\floppy.c(2334)
+label_2:
+assume false;
+return;
+
+
+// c:\nt\drivers\storage\fdc\flpydisk\floppy.c(2230)
+label_3:
+goto label_4;
+
+
+// c:\nt\drivers\storage\fdc\flpydisk\floppy.c(2231)
+label_4:
+goto label_5;
+
+
+// c:\nt\drivers\storage\fdc\flpydisk\floppy.c(2232)
+label_5:
+goto label_6;
+
+
+// c:\nt\drivers\storage\fdc\flpydisk\floppy.c(2234)
+label_6:
+goto label_6_true , label_6_false ;
+
+
+label_6_true :
+assume (BIT_BAND(Mem_UINT4[FloppyDebugLevel], Ptr(null, 8)) != Ptr(null,0));
+goto label_8;
+
+
+label_6_false :
+assume (BIT_BAND(Mem_UINT4[FloppyDebugLevel], Ptr(null, 8)) == Ptr(null,0));
+goto label_7;
+
+
+// c:\nt\drivers\storage\fdc\flpydisk\floppy.c(2236)
+label_7:
+$disketteExtension$5$2232.24$ := Mem_DeviceExtension__DEVICE_OBJECT[DeviceExtension__DEVICE_OBJECT(DeviceObject)] ;
+goto label_12;
+
+
+// c:\nt\drivers\storage\fdc\flpydisk\floppy.c(2234)
+label_8:
+call havoc_stringTemp := __HAVOC_malloc_stack(Ptr(null,1));
+$DbgPrint.arg.1$3$ := havoc_stringTemp ;
+goto label_9;
+
+
+// c:\nt\drivers\storage\fdc\flpydisk\floppy.c(2234)
+label_9:
+havoc $result.DbgPrint$2234.4$2$;
+// skip DbgPrint
+goto label_7;
+
+
+// c:\nt\drivers\storage\fdc\flpydisk\floppy.c(2238)
+label_12:
+$irpSp$3$2230.23$ := Mem_CurrentStackLocation___unnamed_4_f80453a0[CurrentStackLocation___unnamed_4_f80453a0(__unnamed_4_f80453a0___unnamed_12_003c1454(__unnamed_12_003c1454___unnamed_40_6ef75b20(Overlay___unnamed_48_c27ef811(Tail__IRP(Irp$1)))))] ;
+goto label_13;
+
+
+// c:\nt\drivers\storage\fdc\flpydisk\floppy.c(2244)
+label_13:
+call ExAcquireFastMutex (HoldNewReqMutex__DISKETTE_EXTENSION($disketteExtension$5$2232.24$));
+goto label_16;
+
+
+// c:\nt\drivers\storage\fdc\flpydisk\floppy.c(2245)
+label_16:
+goto label_16_true , label_16_false ;
+
+
+label_16_true :
+assume (Mem_HoldNewRequests__DISKETTE_EXTENSION[HoldNewRequests__DISKETTE_EXTENSION($disketteExtension$5$2232.24$)] != Ptr(null,0));
+goto label_18;
+
+
+label_16_false :
+assume (Mem_HoldNewRequests__DISKETTE_EXTENSION[HoldNewRequests__DISKETTE_EXTENSION($disketteExtension$5$2232.24$)] == Ptr(null,0));
+goto label_17;
+
+
+// c:\nt\drivers\storage\fdc\flpydisk\floppy.c(2257)
+label_17:
+goto label_17_true , label_17_false ;
+
+
+label_17_true :
+assume (Mem_IsRemoved__DISKETTE_EXTENSION[IsRemoved__DISKETTE_EXTENSION($disketteExtension$5$2232.24$)] != Ptr(null,0));
+goto label_27;
+
+
+label_17_false :
+assume (Mem_IsRemoved__DISKETTE_EXTENSION[IsRemoved__DISKETTE_EXTENSION($disketteExtension$5$2232.24$)] == Ptr(null,0));
+goto label_26;
+
+
+// c:\nt\drivers\storage\fdc\flpydisk\floppy.c(2247)
+label_18:
+call $result.FloppyQueueRequest$2247.37$4$ := FloppyQueueRequest ($disketteExtension$5$2232.24$, Irp$1);
+goto label_21;
+
+
+// c:\nt\drivers\storage\fdc\flpydisk\floppy.c(2247)
+label_21:
+$ntStatus$4$2231.13$ := $result.FloppyQueueRequest$2247.37$4$ ;
+goto label_22;
+
+
+// c:\nt\drivers\storage\fdc\flpydisk\floppy.c(2249)
+label_22:
+call ExReleaseFastMutex (HoldNewReqMutex__DISKETTE_EXTENSION($disketteExtension$5$2232.24$));
+goto label_25;
+
+
+// c:\nt\drivers\storage\fdc\flpydisk\floppy.c(2250)
+label_25:
+$result.FloppyReadWrite$2203.0$1$ := $ntStatus$4$2231.13$ ;
+goto label_1;
+
+
+// c:\nt\drivers\storage\fdc\flpydisk\floppy.c(2257)
+label_26:
+goto label_26_true , label_26_false ;
+
+
+label_26_true :
+assume (Mem_IsStarted__DISKETTE_EXTENSION[IsStarted__DISKETTE_EXTENSION($disketteExtension$5$2232.24$)] != Ptr(null,0));
+goto label_39;
+
+
+label_26_false :
+assume (Mem_IsStarted__DISKETTE_EXTENSION[IsStarted__DISKETTE_EXTENSION($disketteExtension$5$2232.24$)] == Ptr(null,0));
+goto label_27;
+
+
+// c:\nt\drivers\storage\fdc\flpydisk\floppy.c(2259)
+label_27:
+call ExReleaseFastMutex (HoldNewReqMutex__DISKETTE_EXTENSION($disketteExtension$5$2232.24$));
+goto label_30;
+
+
+// c:\nt\drivers\storage\fdc\flpydisk\floppy.c(2261)
+label_30:
+goto label_30_true , label_30_false ;
+
+
+label_30_true :
+assume (Mem_IsRemoved__DISKETTE_EXTENSION[IsRemoved__DISKETTE_EXTENSION($disketteExtension$5$2232.24$)] != Ptr(null,0));
+goto label_32;
+
+
+label_30_false :
+assume (Mem_IsRemoved__DISKETTE_EXTENSION[IsRemoved__DISKETTE_EXTENSION($disketteExtension$5$2232.24$)] == Ptr(null,0));
+goto label_31;
+
+
+// c:\nt\drivers\storage\fdc\flpydisk\floppy.c(2264)
+label_31:
+$ntStatus$4$2231.13$ := Ptr(null, -1073741823) ;
+goto label_33;
+
+
+// c:\nt\drivers\storage\fdc\flpydisk\floppy.c(2262)
+label_32:
+$ntStatus$4$2231.13$ := Ptr(null, -1073741738) ;
+goto label_33;
+
+
+// c:\nt\drivers\storage\fdc\flpydisk\floppy.c(2266)
+label_33:
+Mem_Information__IO_STATUS_BLOCK[Information__IO_STATUS_BLOCK(IoStatus__IRP(Irp$1))] := Ptr(null, 0) ;
+goto label_34;
+
+
+// c:\nt\drivers\storage\fdc\flpydisk\floppy.c(2267)
+label_34:
+Mem_Status___unnamed_4_c7b3d275[Status___unnamed_4_c7b3d275(__unnamed_4_c7b3d275__IO_STATUS_BLOCK(IoStatus__IRP(Irp$1)))] := $ntStatus$4$2231.13$ ;
+goto label_35;
+
+
+// c:\nt\drivers\storage\fdc\flpydisk\floppy.c(2268)
+label_35:
+call IofCompleteRequest (Irp$1, Ptr(null, 0));
+goto label_38;
+
+
+// c:\nt\drivers\storage\fdc\flpydisk\floppy.c(2269)
+label_38:
+$result.FloppyReadWrite$2203.0$1$ := $ntStatus$4$2231.13$ ;
+goto label_1;
+
+
+// c:\nt\drivers\storage\fdc\flpydisk\floppy.c(2272)
+label_39:
+assume (null == Obj(Mem_MediaType__DISKETTE_EXTENSION[MediaType__DISKETTE_EXTENSION($disketteExtension$5$2232.24$)]));
+goto label_39_true , label_39_false ;
+
+
+label_39_true :
+assume (0 < Off(Mem_MediaType__DISKETTE_EXTENSION[MediaType__DISKETTE_EXTENSION($disketteExtension$5$2232.24$)]));
+goto label_41;
+
+
+label_39_false :
+assume !(0 < Off(Mem_MediaType__DISKETTE_EXTENSION[MediaType__DISKETTE_EXTENSION($disketteExtension$5$2232.24$)]));
+goto label_40;
+
+
+// c:\nt\drivers\storage\fdc\flpydisk\floppy.c(2299)
+label_40:
+goto label_40_true , label_40_false ;
+
+
+label_40_true :
+assume (Mem_Length___unnamed_16_39e6661e[Length___unnamed_16_39e6661e(Read___unnamed_16_c0f0e7de(Parameters__IO_STACK_LOCATION($irpSp$3$2230.23$)))] != Ptr(null,0));
+goto label_69;
+
+
+label_40_false :
+assume (Mem_Length___unnamed_16_39e6661e[Length___unnamed_16_39e6661e(Read___unnamed_16_c0f0e7de(Parameters__IO_STACK_LOCATION($irpSp$3$2230.23$)))] == Ptr(null,0));
+goto label_68;
+
+
+// c:\nt\drivers\storage\fdc\flpydisk\floppy.c(2274)
+label_41:
+assume (Obj(Mem_ByteCapacity__DISKETTE_EXTENSION[ByteCapacity__DISKETTE_EXTENSION($disketteExtension$5$2232.24$)]) == Obj(PLUS(Mem_LowPart___unnamed_8_34582070[LowPart___unnamed_8_34582070(__unnamed_8_34582070__LARGE_INTEGER(ByteOffset___unnamed_16_39e6661e(Read___unnamed_16_c0f0e7de(Parameters__IO_STACK_LOCATION($irpSp$3$2230.23$)))))], 1, Mem_Length___unnamed_16_39e6661e[Length___unnamed_16_39e6661e(Read___unnamed_16_c0f0e7de(Parameters__IO_STACK_LOCATION($irpSp$3$2230.23$)))])));
+goto label_41_true , label_41_false ;
+
+
+label_41_true :
+assume (Off(Mem_ByteCapacity__DISKETTE_EXTENSION[ByteCapacity__DISKETTE_EXTENSION($disketteExtension$5$2232.24$)]) < Off(PLUS(Mem_LowPart___unnamed_8_34582070[LowPart___unnamed_8_34582070(__unnamed_8_34582070__LARGE_INTEGER(ByteOffset___unnamed_16_39e6661e(Read___unnamed_16_c0f0e7de(Parameters__IO_STACK_LOCATION($irpSp$3$2230.23$)))))], 1, Mem_Length___unnamed_16_39e6661e[Length___unnamed_16_39e6661e(Read___unnamed_16_c0f0e7de(Parameters__IO_STACK_LOCATION($irpSp$3$2230.23$)))])));
+goto label_43;
+
+
+label_41_false :
+assume !(Off(Mem_ByteCapacity__DISKETTE_EXTENSION[ByteCapacity__DISKETTE_EXTENSION($disketteExtension$5$2232.24$)]) < Off(PLUS(Mem_LowPart___unnamed_8_34582070[LowPart___unnamed_8_34582070(__unnamed_8_34582070__LARGE_INTEGER(ByteOffset___unnamed_16_39e6661e(Read___unnamed_16_c0f0e7de(Parameters__IO_STACK_LOCATION($irpSp$3$2230.23$)))))], 1, Mem_Length___unnamed_16_39e6661e[Length___unnamed_16_39e6661e(Read___unnamed_16_c0f0e7de(Parameters__IO_STACK_LOCATION($irpSp$3$2230.23$)))])));
+goto label_42;
+
+
+// c:\nt\drivers\storage\fdc\flpydisk\floppy.c(2275)
+label_42:
+goto label_42_true , label_42_false ;
+
+
+label_42_true :
+assume (BIT_BAND(Mem_Length___unnamed_16_39e6661e[Length___unnamed_16_39e6661e(Read___unnamed_16_c0f0e7de(Parameters__IO_STACK_LOCATION($irpSp$3$2230.23$)))], Ptr(Obj(Mem_BytesPerSector__DISKETTE_EXTENSION[BytesPerSector__DISKETTE_EXTENSION($disketteExtension$5$2232.24$)]), Off(Mem_BytesPerSector__DISKETTE_EXTENSION[BytesPerSector__DISKETTE_EXTENSION($disketteExtension$5$2232.24$)]) - 1)) != Ptr(null,0));
+goto label_43;
+
+
+label_42_false :
+assume (BIT_BAND(Mem_Length___unnamed_16_39e6661e[Length___unnamed_16_39e6661e(Read___unnamed_16_c0f0e7de(Parameters__IO_STACK_LOCATION($irpSp$3$2230.23$)))], Ptr(Obj(Mem_BytesPerSector__DISKETTE_EXTENSION[BytesPerSector__DISKETTE_EXTENSION($disketteExtension$5$2232.24$)]), Off(Mem_BytesPerSector__DISKETTE_EXTENSION[BytesPerSector__DISKETTE_EXTENSION($disketteExtension$5$2232.24$)]) - 1)) == Ptr(null,0));
+goto label_40;
+
+
+// c:\nt\drivers\storage\fdc\flpydisk\floppy.c(2278)
+label_43:
+goto label_43_true , label_43_false ;
+
+
+label_43_true :
+assume (BIT_BAND(Mem_UINT4[FloppyDebugLevel], Ptr(null, 1)) != Ptr(null,0));
+goto label_45;
+
+
+label_43_false :
+assume (BIT_BAND(Mem_UINT4[FloppyDebugLevel], Ptr(null, 1)) == Ptr(null,0));
+goto label_44;
+
+
+// c:\nt\drivers\storage\fdc\flpydisk\floppy.c(2280)
+label_44:
+goto label_44_true , label_44_false ;
+
+
+label_44_true :
+assume (BIT_BAND(Mem_UINT4[FloppyDebugLevel], Ptr(null, 2)) != Ptr(null,0));
+goto label_50;
+
+
+label_44_false :
+assume (BIT_BAND(Mem_UINT4[FloppyDebugLevel], Ptr(null, 2)) == Ptr(null,0));
+goto label_49;
+
+
+// c:\nt\drivers\storage\fdc\flpydisk\floppy.c(2278)
+label_45:
+call havoc_stringTemp := __HAVOC_malloc_stack(Ptr(null,1));
+$DbgPrint.arg.1$6$ := havoc_stringTemp ;
+goto label_46;
+
+
+// c:\nt\drivers\storage\fdc\flpydisk\floppy.c(2278)
+label_46:
+havoc $result.DbgPrint$2278.0$5$;
+// skip DbgPrint
+goto label_44;
+
+
+// c:\nt\drivers\storage\fdc\flpydisk\floppy.c(2290)
+label_49:
+$ntStatus$4$2231.13$ := Ptr(null, -1073741811) ;
+goto label_54;
+
+
+// c:\nt\drivers\storage\fdc\flpydisk\floppy.c(2280)
+label_50:
+call havoc_stringTemp := __HAVOC_malloc_stack(Ptr(null,1));
+$DbgPrint.arg.1$8$ := havoc_stringTemp ;
+goto label_51;
+
+
+// c:\nt\drivers\storage\fdc\flpydisk\floppy.c(2280)
+label_51:
+havoc $result.DbgPrint$2280.0$7$;
+// skip DbgPrint
+goto label_49;
+
+
+// c:\nt\drivers\storage\fdc\flpydisk\floppy.c(2323)
+label_54:
+call ExReleaseFastMutex (HoldNewReqMutex__DISKETTE_EXTENSION($disketteExtension$5$2232.24$));
+goto label_57;
+
+
+// c:\nt\drivers\storage\fdc\flpydisk\floppy.c(2325)
+label_57:
+goto label_57_true , label_57_false ;
+
+
+label_57_true :
+assume ($ntStatus$4$2231.13$ != Ptr(null, 259));
+goto label_59;
+
+
+label_57_false :
+assume !($ntStatus$4$2231.13$ != Ptr(null, 259));
+goto label_58;
+
+
+// c:\nt\drivers\storage\fdc\flpydisk\floppy.c(2333)
+label_58:
+$result.FloppyReadWrite$2203.0$1$ := $ntStatus$4$2231.13$ ;
+goto label_1;
+
+
+// c:\nt\drivers\storage\fdc\flpydisk\floppy.c(2326)
+label_59:
+Mem_Status___unnamed_4_c7b3d275[Status___unnamed_4_c7b3d275(__unnamed_4_c7b3d275__IO_STATUS_BLOCK(IoStatus__IRP(Irp$1)))] := $ntStatus$4$2231.13$ ;
+goto label_60;
+
+
+// c:\nt\drivers\storage\fdc\flpydisk\floppy.c(2327)
+label_60:
+goto label_60_true , label_60_false ;
+
+
+label_60_true :
+assume (BIT_BAND(Mem_UINT4[FloppyDebugLevel], Ptr(null, 1)) != Ptr(null,0));
+goto label_64;
+
+
+label_60_false :
+assume (BIT_BAND(Mem_UINT4[FloppyDebugLevel], Ptr(null, 1)) == Ptr(null,0));
+goto label_61;
+
+
+// c:\nt\drivers\storage\fdc\flpydisk\floppy.c(2330)
+label_61:
+call IofCompleteRequest (Irp$1, Ptr(null, 0));
+goto label_58;
+
+
+// c:\nt\drivers\storage\fdc\flpydisk\floppy.c(2327)
+label_64:
+call havoc_stringTemp := __HAVOC_malloc_stack(Ptr(null,1));
+$DbgPrint.arg.1$15$ := havoc_stringTemp ;
+goto label_65;
+
+
+// c:\nt\drivers\storage\fdc\flpydisk\floppy.c(2327)
+label_65:
+havoc $result.DbgPrint$2327.0$14$;
+// skip DbgPrint
+goto label_61;
+
+
+// c:\nt\drivers\storage\fdc\flpydisk\floppy.c(2315)
+label_68:
+Mem_Information__IO_STATUS_BLOCK[Information__IO_STATUS_BLOCK(IoStatus__IRP(Irp$1))] := Ptr(null, 0) ;
+goto label_78;
+
+
+// c:\nt\drivers\storage\fdc\flpydisk\floppy.c(2305)
+label_69:
+goto label_69_true , label_69_false ;
+
+
+label_69_true :
+assume (BIT_BAND(Mem_UINT4[FloppyDebugLevel], Ptr(null, 16)) != Ptr(null,0));
+goto label_73;
+
+
+label_69_false :
+assume (BIT_BAND(Mem_UINT4[FloppyDebugLevel], Ptr(null, 16)) == Ptr(null,0));
+goto label_70;
+
+
+// c:\nt\drivers\storage\fdc\flpydisk\floppy.c(2308)
+label_70:
+call $result.FlQueueIrpToThread$2308.41$11$ := FlQueueIrpToThread (Irp$1, $disketteExtension$5$2232.24$);
+goto label_77;
+
+
+// c:\nt\drivers\storage\fdc\flpydisk\floppy.c(2305)
+label_73:
+call havoc_stringTemp := __HAVOC_malloc_stack(Ptr(null,1));
+$DbgPrint.arg.1$10$ := havoc_stringTemp ;
+goto label_74;
+
+
+// c:\nt\drivers\storage\fdc\flpydisk\floppy.c(2305)
+label_74:
+havoc $result.DbgPrint$2305.0$9$;
+// skip DbgPrint
+goto label_70;
+
+
+// c:\nt\drivers\storage\fdc\flpydisk\floppy.c(2308)
+label_77:
+$ntStatus$4$2231.13$ := $result.FlQueueIrpToThread$2308.41$11$ ;
+goto label_54;
+
+
+// c:\nt\drivers\storage\fdc\flpydisk\floppy.c(2316)
+label_78:
+Mem_Status___unnamed_4_c7b3d275[Status___unnamed_4_c7b3d275(__unnamed_4_c7b3d275__IO_STATUS_BLOCK(IoStatus__IRP(Irp$1)))] := Ptr(null, 0) ;
+goto label_79;
+
+
+// c:\nt\drivers\storage\fdc\flpydisk\floppy.c(2317)
+label_79:
+goto label_79_true , label_79_false ;
+
+
+label_79_true :
+assume (BIT_BAND(Mem_UINT4[FloppyDebugLevel], Ptr(null, 1)) != Ptr(null,0));
+goto label_81;
+
+
+label_79_false :
+assume (BIT_BAND(Mem_UINT4[FloppyDebugLevel], Ptr(null, 1)) == Ptr(null,0));
+goto label_80;
+
+
+// c:\nt\drivers\storage\fdc\flpydisk\floppy.c(2319)
+label_80:
+$ntStatus$4$2231.13$ := Ptr(null, 0) ;
+goto label_54;
+
+
+// c:\nt\drivers\storage\fdc\flpydisk\floppy.c(2317)
+label_81:
+call havoc_stringTemp := __HAVOC_malloc_stack(Ptr(null,1));
+$DbgPrint.arg.1$13$ := havoc_stringTemp ;
+goto label_82;
+
+
+// c:\nt\drivers\storage\fdc\flpydisk\floppy.c(2317)
+label_82:
+havoc $result.DbgPrint$2317.0$12$;
+// skip DbgPrint
+goto label_80;
+
+}
+
diff --git a/Test/test17/runtest.bat b/Test/test17/runtest.bat
new file mode 100644
index 00000000..727d4a89
--- /dev/null
+++ b/Test/test17/runtest.bat
@@ -0,0 +1,12 @@
+@echo off
+setlocal
+
+set BOOGIEDIR=..\..\Binaries
+set BGEXE=%BOOGIEDIR%\Boogie.exe
+
+
+for %%f in (contractinfer flpydisk) do (
+ echo.
+ echo -------------------- %%f --------------------
+ %BGEXE% %* /errorLimit:1 /contractInfer /z3mam:4 /subsumption:0 %%f.bpl
+)
diff --git a/Test/test2/Answer b/Test/test2/Answer
new file mode 100644
index 00000000..7876d732
--- /dev/null
+++ b/Test/test2/Answer
@@ -0,0 +1,359 @@
+
+-------------------- FormulaTerm.bpl --------------------
+FormulaTerm.bpl(10,3): Error BP5003: A postcondition might not hold at this return statement.
+FormulaTerm.bpl(4,3): Related location: This is the postcondition that might not hold.
+Execution trace:
+ FormulaTerm.bpl(8,1): start
+
+Boogie program verifier finished with 11 verified, 1 error
+
+-------------------- FormulaTerm2.bpl --------------------
+FormulaTerm2.bpl(39,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ FormulaTerm2.bpl(36,3): start
+FormulaTerm2.bpl(47,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ FormulaTerm2.bpl(45,3): start
+
+Boogie program verifier finished with 2 verified, 2 errors
+
+-------------------- Passification.bpl --------------------
+Passification.bpl(44,3): Error BP5003: A postcondition might not hold at this return statement.
+Passification.bpl(36,3): Related location: This is the postcondition that might not hold.
+Execution trace:
+ Passification.bpl(39,1): A
+Passification.bpl(116,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Passification.bpl(106,1): L0
+ Passification.bpl(111,1): L1
+ Passification.bpl(115,1): L2
+Passification.bpl(151,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Passification.bpl(144,1): L0
+ Passification.bpl(150,1): L2
+Passification.bpl(165,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Passification.bpl(158,1): L0
+ Passification.bpl(161,1): L1
+ Passification.bpl(164,1): L2
+
+Boogie program verifier finished with 7 verified, 4 errors
+
+-------------------- B.bpl --------------------
+
+Boogie program verifier finished with 4 verified, 0 errors
+
+-------------------- Ensures.bpl --------------------
+Ensures.bpl(30,5): Error BP5003: A postcondition might not hold at this return statement.
+Ensures.bpl(19,3): Related location: This is the postcondition that might not hold.
+Execution trace:
+ Ensures.bpl(28,3): start
+Ensures.bpl(35,5): Error BP5003: A postcondition might not hold at this return statement.
+Ensures.bpl(19,3): Related location: This is the postcondition that might not hold.
+Execution trace:
+ Ensures.bpl(34,3): start
+Ensures.bpl(41,5): Error BP5003: A postcondition might not hold at this return statement.
+Ensures.bpl(19,3): Related location: This is the postcondition that might not hold.
+Execution trace:
+ Ensures.bpl(39,3): start
+Ensures.bpl(47,5): Error BP5003: A postcondition might not hold at this return statement.
+Ensures.bpl(19,3): Related location: This is the postcondition that might not hold.
+Execution trace:
+ Ensures.bpl(45,3): start
+Ensures.bpl(72,5): Error BP5003: A postcondition might not hold at this return statement.
+Ensures.bpl(19,3): Related location: This is the postcondition that might not hold.
+Execution trace:
+ Ensures.bpl(70,3): start
+
+Boogie program verifier finished with 5 verified, 5 errors
+
+-------------------- Old.bpl --------------------
+Old.bpl(29,5): Error BP5003: A postcondition might not hold at this return statement.
+Old.bpl(26,3): Related location: This is the postcondition that might not hold.
+Execution trace:
+ Old.bpl(28,3): start
+
+Boogie program verifier finished with 7 verified, 1 error
+
+-------------------- OldIllegal.bpl --------------------
+OldIllegal.bpl(7,11): Error: old expressions allowed only in two-state contexts
+OldIllegal.bpl(14,23): Error: old expressions allowed only in two-state contexts
+2 name resolution errors detected in OldIllegal.bpl
+
+-------------------- Arrays.bpl --------------------
+Arrays.bpl(46,5): Error BP5003: A postcondition might not hold at this return statement.
+Arrays.bpl(38,3): Related location: This is the postcondition that might not hold.
+Execution trace:
+ Arrays.bpl(42,3): start
+Arrays.bpl(127,5): Error BP5003: A postcondition might not hold at this return statement.
+Arrays.bpl(119,3): Related location: This is the postcondition that might not hold.
+Execution trace:
+ Arrays.bpl(123,3): start
+
+Boogie program verifier finished with 8 verified, 2 errors
+
+-------------------- Axioms.bpl --------------------
+Axioms.bpl(19,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ Axioms.bpl(18,3): start
+
+Boogie program verifier finished with 2 verified, 1 error
+
+-------------------- Quantifiers.bpl --------------------
+Quantifiers.bpl(20,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ Quantifiers.bpl(19,3): start
+Quantifiers.bpl(43,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ Quantifiers.bpl(42,3): start
+Quantifiers.bpl(65,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ Quantifiers.bpl(64,3): start
+Quantifiers.bpl(73,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ Quantifiers.bpl(71,3): start
+Quantifiers.bpl(125,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ Quantifiers.bpl(124,3): start
+Quantifiers.bpl(150,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ Quantifiers.bpl(149,3): start
+
+Boogie program verifier finished with 8 verified, 6 errors
+
+-------------------- Call.bpl --------------------
+Call.bpl(13,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ Call.bpl(9,3): entry
+Call.bpl(46,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ Call.bpl(45,3): start
+Call.bpl(55,5): Error BP5003: A postcondition might not hold at this return statement.
+Call.bpl(20,3): Related location: This is the postcondition that might not hold.
+Execution trace:
+ Call.bpl(53,3): start
+
+Boogie program verifier finished with 2 verified, 3 errors
+
+-------------------- AssumeEnsures.bpl --------------------
+AssumeEnsures.bpl(28,9): Error BP5001: This assertion might not hold.
+Execution trace:
+ AssumeEnsures.bpl(26,5): entry
+AssumeEnsures.bpl(47,9): Error BP5001: This assertion might not hold.
+Execution trace:
+ AssumeEnsures.bpl(46,5): entry
+AssumeEnsures.bpl(62,9): Error BP5001: This assertion might not hold.
+Execution trace:
+ AssumeEnsures.bpl(60,5): entry
+
+Boogie program verifier finished with 4 verified, 3 errors
+
+-------------------- CutBackEdge.bpl --------------------
+CutBackEdge.bpl(10,5): Error BP5005: This loop invariant might not be maintained by the loop.
+Execution trace:
+ CutBackEdge.bpl(5,3): entry
+ CutBackEdge.bpl(9,3): block850
+
+Boogie program verifier finished with 0 verified, 1 error
+
+-------------------- False.bpl --------------------
+
+Boogie program verifier finished with 2 verified, 0 errors
+
+-------------------- LoopInvAssume.bpl --------------------
+LoopInvAssume.bpl(18,7): Error BP5001: This assertion might not hold.
+Execution trace:
+ LoopInvAssume.bpl(8,4): entry
+ LoopInvAssume.bpl(16,4): exit
+
+Boogie program verifier finished with 0 verified, 1 error
+
+-------------------- strings-no-where.bpl --------------------
+strings-no-where.bpl(201,103): Error: invalid argument types (any and name) to binary operator ==
+strings-no-where.bpl(203,105): Error: invalid argument types (any and name) to binary operator ==
+strings-no-where.bpl(209,106): Error: invalid type for argument 1 in application of IsAllocated: struct (expected: any)
+strings-no-where.bpl(211,72): Error: invalid type for argument 1 in application of IsAllocated: ref (expected: any)
+strings-no-where.bpl(211,108): Error: invalid type for argument 1 in application of IsAllocated: elements (expected: any)
+strings-no-where.bpl(211,130): Error: invalid type for argument 1 in application of IsAllocated: ref (expected: any)
+strings-no-where.bpl(213,78): Error: invalid type for argument 1 in application of IsAllocated: ref (expected: any)
+strings-no-where.bpl(235,98): Error: invalid argument types (any and name) to binary operator ==
+strings-no-where.bpl(249,118): Error: invalid argument types (any and name) to binary operator ==
+strings-no-where.bpl(699,34): Error: invalid type for argument 1 in application of IsAllocated: int (expected: any)
+strings-no-where.bpl(728,9): Error: mismatched types in assignment command (cannot assign bool to any)
+strings-no-where.bpl(737,9): Error: mismatched types in assignment command (cannot assign bool to any)
+strings-no-where.bpl(751,9): Error: mismatched types in assignment command (cannot assign bool to any)
+strings-no-where.bpl(760,9): Error: mismatched types in assignment command (cannot assign bool to any)
+strings-no-where.bpl(926,36): Error: invalid argument types (any and name) to binary operator ==
+strings-no-where.bpl(949,36): Error: invalid argument types (any and name) to binary operator ==
+strings-no-where.bpl(975,9): Error: mismatched types in assignment command (cannot assign name to any)
+strings-no-where.bpl(990,36): Error: invalid argument types (any and name) to binary operator ==
+18 type checking errors detected in strings-no-where.bpl
+
+-------------------- strings-where.bpl --------------------
+strings-where.bpl(201,103): Error: invalid argument types (any and name) to binary operator ==
+strings-where.bpl(203,105): Error: invalid argument types (any and name) to binary operator ==
+strings-where.bpl(209,106): Error: invalid type for argument 1 in application of IsAllocated: struct (expected: any)
+strings-where.bpl(211,72): Error: invalid type for argument 1 in application of IsAllocated: ref (expected: any)
+strings-where.bpl(211,108): Error: invalid type for argument 1 in application of IsAllocated: elements (expected: any)
+strings-where.bpl(211,130): Error: invalid type for argument 1 in application of IsAllocated: ref (expected: any)
+strings-where.bpl(213,78): Error: invalid type for argument 1 in application of IsAllocated: ref (expected: any)
+strings-where.bpl(235,98): Error: invalid argument types (any and name) to binary operator ==
+strings-where.bpl(249,118): Error: invalid argument types (any and name) to binary operator ==
+strings-where.bpl(699,34): Error: invalid type for argument 1 in application of IsAllocated: int (expected: any)
+strings-where.bpl(728,9): Error: mismatched types in assignment command (cannot assign bool to any)
+strings-where.bpl(737,9): Error: mismatched types in assignment command (cannot assign bool to any)
+strings-where.bpl(751,9): Error: mismatched types in assignment command (cannot assign bool to any)
+strings-where.bpl(760,9): Error: mismatched types in assignment command (cannot assign bool to any)
+strings-where.bpl(926,36): Error: invalid argument types (any and name) to binary operator ==
+strings-where.bpl(949,36): Error: invalid argument types (any and name) to binary operator ==
+strings-where.bpl(975,9): Error: mismatched types in assignment command (cannot assign name to any)
+strings-where.bpl(990,36): Error: invalid argument types (any and name) to binary operator ==
+18 type checking errors detected in strings-where.bpl
+
+-------------------- Structured.bpl --------------------
+Structured.bpl(252,14): Error BP5003: A postcondition might not hold at this return statement.
+Structured.bpl(243,3): Related location: This is the postcondition that might not hold.
+Execution trace:
+ Structured.bpl(245,3): anon0
+ Structured.bpl(245,3): anon6_LoopHead
+ Structured.bpl(246,5): anon6_LoopBody
+ Structured.bpl(247,7): anon7_LoopBody
+ Structured.bpl(252,5): anon4
+ Structured.bpl(252,14): anon9_Then
+Structured.bpl(303,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Structured.bpl(299,5): anon0
+ Structured.bpl(300,3): anon3_Else
+ Structured.bpl(303,3): anon2
+Structured.bpl(311,7): Error BP5001: This assertion might not hold.
+Execution trace:
+ Structured.bpl(308,3): anon0
+ Structured.bpl(308,3): anon1_Then
+ Structured.bpl(309,5): A
+
+Boogie program verifier finished with 15 verified, 3 errors
+
+-------------------- Where.bpl --------------------
+Where.bpl(8,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Where.bpl(6,3): anon0
+Where.bpl(22,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Where.bpl(16,5): anon0
+Where.bpl(32,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Where.bpl(30,3): anon0
+Where.bpl(44,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Where.bpl(40,5): anon0
+Where.bpl(57,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Where.bpl(52,3): anon0
+Where.bpl(111,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Where.bpl(102,5): anon0
+ Where.bpl(104,3): anon3_LoopHead
+ Where.bpl(110,3): anon2
+Where.bpl(128,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Where.bpl(121,5): anon0
+ Where.bpl(122,3): anon3_LoopHead
+ Where.bpl(125,3): anon2
+Where.bpl(145,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Where.bpl(138,5): anon0
+ Where.bpl(139,3): anon3_LoopHead
+ Where.bpl(142,3): anon2
+Where.bpl(162,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Where.bpl(155,5): anon0
+ Where.bpl(156,3): anon3_LoopHead
+ Where.bpl(159,3): anon2
+
+Boogie program verifier finished with 2 verified, 9 errors
+
+-------------------- UpdateExpr.bpl --------------------
+UpdateExpr.bpl(14,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ UpdateExpr.bpl(14,3): anon0
+UpdateExpr.bpl(19,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ UpdateExpr.bpl(19,3): anon0
+UpdateExpr.bpl(32,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ UpdateExpr.bpl(32,3): anon0
+UpdateExpr.bpl(38,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ UpdateExpr.bpl(38,3): anon0
+UpdateExpr.bpl(52,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ UpdateExpr.bpl(51,5): anon0
+
+Boogie program verifier finished with 5 verified, 5 errors
+
+-------------------- NeverPattern.bpl --------------------
+NeverPattern.bpl(16,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ NeverPattern.bpl(15,3): anon0
+NeverPattern.bpl(22,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ NeverPattern.bpl(21,3): anon0
+NeverPattern.bpl(28,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ NeverPattern.bpl(27,3): anon0
+
+Boogie program verifier finished with 1 verified, 3 errors
+
+-------------------- NullaryMaps.bpl --------------------
+NullaryMaps.bpl(28,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ NullaryMaps.bpl(28,3): anon0
+NullaryMaps.bpl(30,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ NullaryMaps.bpl(28,3): anon0
+NullaryMaps.bpl(36,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ NullaryMaps.bpl(36,3): anon0
+
+Boogie program verifier finished with 2 verified, 3 errors
+
+-------------------- Implies.bpl --------------------
+Implies.bpl(12,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Implies.bpl(11,3): anon0
+Implies.bpl(15,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Implies.bpl(11,3): anon0
+
+Boogie program verifier finished with 0 verified, 2 errors
+-------------------- sk_hack.bpl --------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
+
+-------------------- CallForall.bpl --------------------
+CallForall.bpl(17,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ CallForall.bpl(17,3): anon0
+CallForall.bpl(29,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ CallForall.bpl(28,3): anon0
+CallForall.bpl(41,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ CallForall.bpl(40,3): anon0
+CallForall.bpl(47,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ CallForall.bpl(46,3): anon0
+CallForall.bpl(75,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ CallForall.bpl(75,3): anon0
+CallForall.bpl(111,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ CallForall.bpl(109,3): anon0
+CallForall.bpl(118,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ CallForall.bpl(117,3): anon0
+CallForall.bpl(125,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ CallForall.bpl(124,3): anon0
+
+Boogie program verifier finished with 10 verified, 8 errors
diff --git a/Test/test2/Arrays.bpl b/Test/test2/Arrays.bpl
new file mode 100644
index 00000000..d0f712c9
--- /dev/null
+++ b/Test/test2/Arrays.bpl
@@ -0,0 +1,180 @@
+// -------------------- 1-dimensional arrays --------------------
+
+var A: [ref]int;
+
+procedure P0(o: ref, q: ref, y: int)
+ requires o != q;
+ modifies A;
+ ensures A[o] == old(A[o]) + y;
+ ensures (forall p: ref :: A[p] == old(A[p]) || p == o);
+{
+ var k: int;
+
+ start:
+ k := A[q];
+ A[o] := y + A[o];
+ A[q] := k;
+ return;
+}
+
+procedure P1(o: ref, q: ref, y: int)
+ // This procedure does not have the assumption that o != q.
+ modifies A;
+ // It also does not ensures anything about A[o]
+ ensures (forall p: ref :: A[p] == old(A[p]) || p == o);
+{
+ var k: int;
+
+ start:
+ k := A[q];
+ A[o] := y + A[o];
+ A[q] := k;
+ return;
+}
+
+procedure P2(o: ref, q: ref, y: int)
+ // This procedure does not have the assumption that o != q.
+ modifies A;
+ ensures A[o] == old(A[o]) + y;
+{
+ var k: int;
+
+ start:
+ k := A[q];
+ A[o] := y + A[o];
+ A[q] := k;
+ return;
+} // error: postcondition violated (if o == q)
+
+// -------------------- 2-dimensional arrays --------------------
+
+var B: [ref,name]int;
+const F: name;
+
+procedure Q0(o: ref, q: ref, y: int, G: name)
+ requires o != q && F != G;
+ modifies B;
+ ensures B[o,F] == old(B[o,F]) + y;
+ ensures (forall p: ref, f: name :: B[p,f] == old(B[p,f]) ||
+ (p == o && f == F));
+{
+ var k: int;
+
+ start:
+ k := B[q,G];
+ B[o,F] := y + B[o,F];
+ B[q,G] := k;
+ return;
+}
+
+procedure Q1(o: ref, q: ref, y: int, G: name)
+ // This procedure does not have the assumption that o != q && F != G.
+ modifies B;
+ // It also does not ensures anything about B[o,F]
+ ensures (forall p: ref, f: name :: B[p,f] == old(B[p,f]) ||
+ (p == o && f == F));
+{
+ var k: int;
+
+ start:
+ k := B[q,G];
+ B[o,F] := y + B[o,F];
+ B[q,G] := k;
+ return;
+}
+
+procedure Q2(o: ref, q: ref, y: int, G: name)
+ requires F != G;
+ // This procedure does not have the assumption that o != q.
+ modifies B;
+ ensures B[o,F] == old(B[o,F]) + y;
+{
+ var k: int;
+
+ start:
+ k := B[q,G];
+ B[o,F] := y + B[o,F];
+ B[q,G] := k;
+ return;
+}
+
+procedure Q3(o: ref, q: ref, y: int, G: name)
+ requires o != q;
+ // This procedure does not have the assumption that F != G.
+ modifies B;
+ ensures B[o,F] == old(B[o,F]) + y;
+{
+ var k: int;
+
+ start:
+ k := B[q,G];
+ B[o,F] := y + B[o,F];
+ B[q,G] := k;
+ return;
+}
+
+procedure Q4(o: ref, q: ref, y: int, G: name)
+ // This procedure does not have either of the assumptions o != q and F != G.
+ modifies B;
+ ensures B[o,F] == old(B[o,F]) + y;
+{
+ var k: int;
+
+ start:
+ k := B[q,G];
+ B[o,F] := y + B[o,F];
+ B[q,G] := k;
+ return;
+} // error: postcondition violated
+
+// -------------------- more tests --------------------
+
+procedure Skip0(o: ref, q: ref, G: name, H: name)
+ modifies A,B;
+ ensures (forall p: ref :: A[p] == old(A[p]));
+ ensures (forall p: ref, g: name :: B[p,g] == old(B[p,g]));
+{
+ start:
+ return;
+}
+
+procedure Skip1(o: ref, q: ref, G: name, H: name)
+ modifies A,B;
+ ensures (forall p: ref :: A[p] == old(A[p]));
+ ensures (forall p: ref, g: name :: B[p,g] == old(B[p,g]));
+{
+ var k: int;
+ var l: int;
+
+ start:
+ k := A[o];
+ l := A[q];
+ goto oneWay, theOtherWay;
+
+ oneWay:
+ A[o] := k;
+ A[q] := l;
+ goto next;
+
+ theOtherWay:
+ A[q] := l;
+ A[o] := k;
+ goto next;
+
+ next:
+ k := B[o,G];
+ l := B[q,H];
+ goto Lx, Ly;
+
+ Lx:
+ B[o,G] := k;
+ B[q,H] := l;
+ return;
+
+ Ly:
+ B[q,H] := l;
+ B[o,G] := k;
+ return;
+}
+
+type name, ref;
diff --git a/Test/test2/AssumeEnsures.bpl b/Test/test2/AssumeEnsures.bpl
new file mode 100644
index 00000000..901c06c8
--- /dev/null
+++ b/Test/test2/AssumeEnsures.bpl
@@ -0,0 +1,69 @@
+var g: int;
+
+procedure Foo() returns ();
+ modifies g;
+ free ensures 0 <= g;
+
+implementation Foo() returns ()
+{
+ entry:
+ g := g + 1;
+ return;
+}
+
+procedure BarGood() returns ()
+ modifies g;
+{
+ entry:
+ call Foo();
+ assert 0 <= g;
+ return;
+}
+
+procedure BarBad() returns ()
+ modifies g;
+{
+ entry:
+ call Foo();
+ assert 0 < g;
+ return;
+}
+
+// ----- Free preconditions
+
+procedure Proc() returns ();
+ free requires g == 15;
+
+implementation Proc() returns ()
+{
+ entry:
+ assert g > 10; // yes, this condition can be used here
+ return;
+}
+
+implementation Proc() returns ()
+{
+ entry:
+ assert g < 10; // error
+ return;
+}
+
+procedure Caller0() returns ()
+{
+ entry:
+ call Proc(); // yes, legal, since the precondition is not checked
+ return;
+}
+
+procedure Caller1() returns ()
+{
+ entry:
+ call Proc();
+ assert g > 10; // error, because:
+ // Free preconditions are ignored (that is, treated as "skip") for the caller.
+ // This is a BoogiePL design choice. Another alternative would be to treat free
+ // preconditions as assume commands also on the caller side, either in the order
+ // that all preconditions are given, or before or after all the checked preconditions
+ // have been checked.
+ return;
+}
diff --git a/Test/test2/Axioms.bpl b/Test/test2/Axioms.bpl
new file mode 100644
index 00000000..4fe7a8a7
--- /dev/null
+++ b/Test/test2/Axioms.bpl
@@ -0,0 +1,29 @@
+const Seven: int;
+axiom Seven == 7;
+
+function inc(int) returns (int);
+axiom (forall j: int :: inc(j) == j+1);
+
+procedure P()
+{
+ start:
+ assert 4 <= Seven;
+ assert Seven < inc(Seven);
+ assert inc(5) + inc(inc(2)) == Seven + 3;
+ return;
+}
+
+procedure Q()
+{
+ start:
+ assert inc(5) + inc(inc(2)) == Seven; // error
+ return;
+}
+
+function inc2(x:int) returns(int) { x + 2 }
+
+procedure ExpandTest()
+{
+ var q:int;
+ assert inc(inc(q)) == inc2(q);
+}
diff --git a/Test/test2/B.bpl b/Test/test2/B.bpl
new file mode 100644
index 00000000..553d5002
--- /dev/null
+++ b/Test/test2/B.bpl
@@ -0,0 +1,86 @@
+// ----------- BEGIN PRELUDE
+
+var Heap: [ref, name]int;
+const N: name;
+
+procedure Q0()
+{
+ var h: int;
+
+ entry:
+ goto Else;
+
+ Then:
+ h := 15;
+ goto end;
+
+ Else:
+ assume h == 0;
+ goto end;
+
+ end:
+ assert 0 <= h;
+ return;
+}
+
+procedure Q1()
+{
+ var h: int;
+
+ entry:
+ goto Else;
+
+ Then:
+ h := -15;
+ goto end;
+
+ Else:
+ assume h == 0;
+ goto end;
+
+ end:
+ h := -h;
+ assert 0 <= h;
+ return;
+}
+
+procedure P0(this: ref)
+ modifies Heap;
+{
+ entry:
+ goto Else;
+
+ Then:
+ Heap[this, N] := 15;
+ goto end;
+
+ Else:
+ assume Heap[this, N] == 0;
+ goto end;
+
+ end:
+ assert 0 <= Heap[this, N];
+ return;
+}
+
+procedure P1(this: ref)
+ modifies Heap;
+{
+ entry:
+ goto Else;
+
+ Then:
+ Heap[this, N] := -15;
+ goto end;
+
+ Else:
+ assume Heap[this, N] == 0;
+ goto end;
+
+ end:
+ Heap[this, N] := -Heap[this, N];
+ assert 0 <= Heap[this, N];
+ return;
+}
+
+type name, ref;
diff --git a/Test/test2/Call.bpl b/Test/test2/Call.bpl
new file mode 100644
index 00000000..c1de1e71
--- /dev/null
+++ b/Test/test2/Call.bpl
@@ -0,0 +1,60 @@
+procedure Bar() returns (barresult: ref);
+
+procedure Foo();
+
+implementation Foo()
+{
+ var x: ref;
+
+ entry:
+ call x := Bar();
+ assume x == null;
+ call x := Bar();
+ assert x == null;
+ return;
+
+}
+
+procedure DifferentFormalNames(x: int, y: int) returns (z: int);
+ requires x < y;
+ ensures z == x;
+
+implementation DifferentFormalNames(x: int, y: int) returns (z: int)
+{
+ start:
+ assert x < y;
+ z := x;
+ return;
+}
+
+implementation DifferentFormalNames(y: int, x: int) returns (w: int)
+{
+ start:
+ goto A, B;
+ A:
+ assert y < x;
+ assume false;
+ return;
+ B:
+ w := y;
+ return;
+}
+
+implementation DifferentFormalNames(y: int, x: int) returns (w: int)
+{
+ start:
+ assert x < y; // error
+ w := y;
+ return;
+}
+
+implementation DifferentFormalNames(y: int, x: int) returns (w: int)
+{
+ start:
+ w := x;
+ return; // error: postcondition violation
+}
+
+type ref;
+
+const null : ref;
diff --git a/Test/test2/CallForall.bpl b/Test/test2/CallForall.bpl
new file mode 100644
index 00000000..98a62103
--- /dev/null
+++ b/Test/test2/CallForall.bpl
@@ -0,0 +1,134 @@
+function G(int) returns (int);
+axiom (forall x: int :: { G(x) } 0 <= x ==> G(x) == x);
+
+function F(int) returns (int);
+axiom (forall x: int :: { F(G(x)) } 0 <= x ==> F(G(x)) == 5);
+
+procedure Lemma(y: int)
+ requires 0 <= y;
+ ensures F(y) == 5;
+{
+ // proof:
+ assert G(y) == y;
+}
+
+procedure Main0()
+{
+ assert F(2) == 5; // error: cannot prove this directly, because of the trigger
+}
+
+procedure Main1()
+{
+ call Lemma(2);
+ assert F(2) == 5;
+}
+
+procedure Main2()
+{
+ call Lemma(3);
+ assert F(2) == 5; // error: Lemma was instantiated the wrong way
+}
+
+procedure Main3()
+{
+ call forall Lemma(*);
+ assert F(2) == 5;
+}
+
+procedure Main4()
+{
+ call forall Lemma(*);
+ assert false; // error
+}
+
+procedure Main5(z: int)
+{
+ call forall Lemma(*);
+ assert F(z) == 5; // error: z might be negative
+}
+
+procedure Main6(z: int)
+ requires 0 <= z;
+{
+ call forall Lemma(*);
+ assert F(z) == 5;
+}
+
+// ------------ several parameters
+
+function K(int, int) returns (int);
+axiom (forall x: int, y: int :: { K(G(x), G(y)) } 0 <= x && 0 <= y ==> K(G(x), G(y)) == 25);
+
+procedure MultivarLemma(x: int, y: int)
+ requires 0 <= x;
+ requires 0 <= y;
+ ensures K(x,y) == 25;
+{
+ // proof:
+ assert G(x) == x;
+ assert G(y) == y;
+}
+
+procedure Multi0(x: int, y: int)
+ requires 0 <= x && 0 <= y;
+{
+ assert K(x,y) == 25; // error
+}
+
+procedure Multi1(x: int, y: int)
+ requires 0 <= x && 0 <= y;
+{
+ call MultivarLemma(x, y);
+ assert K(x,y) == 25;
+}
+
+procedure Multi2(x: int, y: int)
+ requires 0 <= x && 0 <= y;
+{
+ call forall MultivarLemma(x, y);
+ assert K(x,y) == 25;
+}
+
+procedure Multi3(x: int, y: int)
+ requires 0 <= x && 0 <= y;
+{
+ call forall MultivarLemma(*, y);
+ assert K(x,y) == 25;
+}
+
+procedure Multi4(x: int, y: int)
+ requires 0 <= x && 0 <= y;
+{
+ call forall MultivarLemma(x, *);
+ assert K(x,y) == 25;
+}
+
+procedure Multi5(x: int, y: int)
+ requires 0 <= x && 0 <= y;
+{
+ call forall MultivarLemma(2 + 100, *);
+ assert K(102, y) == 25;
+ assert false; // error
+}
+
+procedure Multi6(x: int, y: int)
+ requires 0 <= x && 0 <= y;
+{
+ call forall MultivarLemma(*, y);
+ assert K(x+2,y+2) == 25; // error
+}
+
+procedure Multi7(x: int, y: int)
+ requires 0 <= x && 0 <= y;
+{
+ call forall MultivarLemma(x, *);
+ assert K(x+2,y+2) == 25; // error
+}
+
+procedure Multi8(x: int, y: int)
+ requires 0 <= x && 0 <= y;
+{
+ call forall MultivarLemma(*, *);
+ assert K(x+2,y+2) == 25; // that's the ticket!
+}
+
diff --git a/Test/test2/CutBackEdge.bpl b/Test/test2/CutBackEdge.bpl
new file mode 100644
index 00000000..934974aa
--- /dev/null
+++ b/Test/test2/CutBackEdge.bpl
@@ -0,0 +1,14 @@
+procedure Test()
+{
+ var i: int;
+
+ entry:
+ i := 0;
+ goto block850;
+
+ block850:
+ assert i == 0;
+ havoc i;
+ goto block850;
+
+}
diff --git a/Test/test2/Ensures.bpl b/Test/test2/Ensures.bpl
new file mode 100644
index 00000000..4e36c108
--- /dev/null
+++ b/Test/test2/Ensures.bpl
@@ -0,0 +1,75 @@
+var H: [ref,name]int;
+var that: ref;
+
+const X: name;
+const Y: name;
+
+procedure P(this: ref);
+ modifies H;
+ ensures H[this,X] == 5;
+
+implementation P(this: ref) {
+ start:
+ H[this,X] := 5;
+ return;
+}
+
+procedure Q(this: ref);
+ modifies H;
+ ensures (forall o: ref, F: name :: o == this && F == X ==> H[o,F] == 5);
+
+implementation Q(this: ref) {
+ start:
+ H[this,X] := 5;
+ return;
+}
+
+implementation Q(this: ref) {
+ start:
+ H[this,X] := 7;
+ return; // error
+}
+
+implementation Q(this: ref) {
+ start:
+ return; // error
+}
+
+implementation Q(this: ref) {
+ start:
+ H[that,X] := 5;
+ return; // error
+}
+
+implementation Q(this: ref) {
+ start:
+ H[this,Y] := 5;
+ return; // error
+}
+
+implementation Q(this: ref) {
+ start:
+ call P(this);
+ return;
+}
+
+implementation Q(this: ref) {
+ start:
+ call Q(this);
+ return;
+}
+
+implementation Q(this: ref) {
+ start:
+ call P(this);
+ call Q(this);
+ return;
+}
+
+implementation Q(this: ref) {
+ start:
+ call P(that);
+ return; // error
+}
+
+type name, ref;
diff --git a/Test/test2/False.bpl b/Test/test2/False.bpl
new file mode 100644
index 00000000..3fe14865
--- /dev/null
+++ b/Test/test2/False.bpl
@@ -0,0 +1,16 @@
+procedure Test1()
+{
+ entry:
+ assert !true == false;
+ return;
+}
+
+procedure Test2()
+{
+ var b: bool;
+
+ entry:
+ assume b != false;
+ assert b;
+ return;
+}
diff --git a/Test/test2/FormulaTerm.bpl b/Test/test2/FormulaTerm.bpl
new file mode 100644
index 00000000..e14707cb
--- /dev/null
+++ b/Test/test2/FormulaTerm.bpl
@@ -0,0 +1,139 @@
+// Test formula-term distinction in Simplify
+
+procedure plus(x: int, y: int) returns (z: int);
+ ensures z == x + y;
+
+implementation plus(x: int, y: int) returns (z: int)
+{
+start:
+ assume z == 3;
+ return; // ERROR: postcondition possibly violated
+}
+
+implementation plus(x: int, y: int) returns (z: int)
+{
+start:
+ z := x + y;
+ return;
+}
+
+implementation plus(x: int, y: int) returns (z: int)
+{
+start:
+ z := x + y;
+ z := 0 + z;
+ return;
+}
+
+procedure plus2(x: int, y: int) returns (z: int)
+ ensures z == x + y;
+{
+start:
+ z := x + y;
+ return;
+}
+
+procedure or(x: int, y: int, a: int, b: int) returns (z: int)
+ requires a == b;
+{
+var t: bool;
+start:
+ t := (x < y || x > y || x == y || x != y) && a >= b && a <= b;
+ assert (x < y || x > y || x == y || x != y) && a >= b && a <= b;
+ assert t;
+ return;
+}
+
+procedure less(x: int, y: int) returns (z: bool);
+ requires x < y;
+ ensures z == (x < y);
+
+implementation less(x: int, y: int) returns (z: bool)
+{
+start:
+ z := x < y;
+ return;
+}
+
+implementation less(x: int, y: int) returns (z: bool)
+{
+start:
+ goto yes, no;
+yes:
+ assume x < y;
+ z := true;
+ return;
+no:
+ assume !(x < y);
+ z := false;
+ return;
+}
+
+implementation less(x: int, y: int) returns (z: bool)
+{
+start:
+ goto yes, no;
+yes:
+ assume x < y;
+ z := true;
+ return;
+no:
+ assume x >= y;
+ z := false;
+ return;
+}
+
+procedure LESS(x: int, y: int) returns (z: bool);
+ requires x < y;
+ ensures z <==> (x < y);
+
+implementation LESS(x: int, y: int) returns (z: bool)
+{
+start:
+ z := x < y;
+ return;
+}
+
+implementation LESS(x: int, y: int) returns (z: bool)
+{
+start:
+ goto yes, no;
+yes:
+ assume x < y;
+ z := true;
+ return;
+no:
+ assume !(x < y);
+ z := false;
+ return;
+}
+
+implementation LESS(x: int, y: int) returns (z: bool)
+{
+start:
+ goto yes, no;
+yes:
+ assume x < y;
+ z := true;
+ return;
+no:
+ assume x >= y;
+ z := false;
+ return;
+}
+
+procedure Assignments()
+{
+ var b: bool;
+ var c: bool;
+ var d: bool;
+ var x: bool, y: bool;
+
+ entry:
+ b := c || d;
+ b := c && d;
+ x := c <==> d;
+ y := c ==> d;
+ assert x ==> y;
+ return;
+}
diff --git a/Test/test2/FormulaTerm2.bpl b/Test/test2/FormulaTerm2.bpl
new file mode 100644
index 00000000..6c5e4bf3
--- /dev/null
+++ b/Test/test2/FormulaTerm2.bpl
@@ -0,0 +1,49 @@
+// This file has been created to test some of the formula/term issues in Zap.
+// However, the test harness does not specify any particular prover to be used,
+// since these tests should pass regardless of which prover is used.
+
+procedure P()
+{
+ var a: int, b: int, t: bool;
+
+ start:
+ assume a == b;
+ t := a == b;
+ assert t;
+ return;
+}
+
+function f(bool) returns (int);
+const A: int;
+const B: int;
+
+axiom f(A < B) == 5;
+
+procedure Q()
+{
+ start:
+ assume A < B;
+ assert f(true) == 5;
+ return;
+}
+
+// ----- and now some erroneous procedures
+
+procedure PX()
+{
+ var a: int, b: int, t: bool;
+
+ start:
+ assume a == b;
+ t := a == b;
+ assert !t; // error
+ return;
+}
+
+procedure QX()
+{
+ start:
+ assume A < B;
+ assert f(true) < 2; // error
+ return;
+}
diff --git a/Test/test2/Implies.bpl b/Test/test2/Implies.bpl
new file mode 100644
index 00000000..3034f973
--- /dev/null
+++ b/Test/test2/Implies.bpl
@@ -0,0 +1,16 @@
+
+const a:bool;
+const b:bool;
+const c:bool;
+const d:bool;
+
+function f(int) returns (bool);
+axiom (forall x:int :: f(x) <== x >= 0);
+
+procedure P() {
+ assert (a ==> (b ==> c) ==> d) == (d <== (c <== b) <== a);
+ assert (a ==> b ==> c) == (c <== (a ==> b)); // error
+
+ assert f(23);
+ assert f(-5); // error
+} \ No newline at end of file
diff --git a/Test/test2/LoopInvAssume.bpl b/Test/test2/LoopInvAssume.bpl
new file mode 100644
index 00000000..1304e668
--- /dev/null
+++ b/Test/test2/LoopInvAssume.bpl
@@ -0,0 +1,20 @@
+// Check that assumes in loop invariants are handled correctly
+
+var x : int;
+
+procedure Test()
+ modifies x;
+{
+ entry:
+ goto loophead, exit;
+
+ loophead:
+ assume x >= 0;
+ x := 0;
+ goto loophead, exit;
+
+ exit:
+ assume x < 0;
+ assert false;
+ return;
+}
diff --git a/Test/test2/NeverPattern.bpl b/Test/test2/NeverPattern.bpl
new file mode 100644
index 00000000..f0478077
--- /dev/null
+++ b/Test/test2/NeverPattern.bpl
@@ -0,0 +1,29 @@
+function {:never_pattern true} f1(x:int) returns(int);
+function {:never_pattern false} f2(x:int) returns(int);
+function f3(x:int) returns(int);
+
+
+procedure foo()
+{
+ assume (forall x : int :: f1(x) > 0 && f2(x) > 0 && f3(x) > 0);
+ assert f2(3) > 0;
+ assert f3(4) > 0;
+}
+
+procedure bar()
+{
+ assume (forall x : int :: f1(x) > 0 && f2(x) > 0 && f3(x) > 0 && f1(7) == 3);
+ assert f1(3) > 0;
+}
+
+procedure bar1()
+{
+ assume (forall x : int :: {:nopats f2(x)} f1(x) > 0 && f2(x) > 0 && f3(x) > 0 && f1(7) == 3);
+ assert f1(3) > 0;
+}
+
+procedure bar2()
+{
+ assume (forall x : int :: {:nopats f2(x)} f1(x) > 0 && f2(x) > 0 && f3(x) > 0 && f1(7) == 3);
+ assert f2(3) > 0;
+}
diff --git a/Test/test2/NullaryMaps.bpl b/Test/test2/NullaryMaps.bpl
new file mode 100644
index 00000000..1bc18c41
--- /dev/null
+++ b/Test/test2/NullaryMaps.bpl
@@ -0,0 +1,57 @@
+// aren't these cool!
+
+var m: []int;
+var p: <a>[]a;
+
+type ref;
+const null: ref;
+
+procedure P()
+ requires m[] == 5;
+ modifies m;
+ modifies p;
+ ensures m[] == 30;
+ ensures p[] == null;
+{
+ m[] := 12;
+ p[] := 12;
+ p[] := true;
+ assert p[] == m[];
+ assert p[];
+ m := m[:= 30];
+ p := p[:=null];
+}
+
+procedure Q()
+ modifies m;
+{
+ assert m[] == 5; // error
+ m[] := 30;
+ assert m[] == 5; // error
+}
+
+procedure R()
+ modifies p;
+{
+ assert p[] < 3; // error
+}
+
+// ----
+
+type Field a;
+type HeapType = <a>[ref, Field a]a;
+const F0: Field int;
+const F1: Field bool;
+const alloc: Field bool;
+var Heap: HeapType;
+procedure FrameCondition(this: ref)
+ modifies Heap;
+ ensures (forall<a> o: ref, f: Field a ::
+ Heap[o,f] == old(Heap)[o,f] ||
+ !old(Heap)[o,alloc] ||
+ (o == this && f == F0) ||
+ (o == this && f == F1)
+ );
+{
+}
+
diff --git a/Test/test2/Old.bpl b/Test/test2/Old.bpl
new file mode 100644
index 00000000..00f798bc
--- /dev/null
+++ b/Test/test2/Old.bpl
@@ -0,0 +1,132 @@
+var x: int;
+var y: int;
+
+procedure P()
+ modifies x;
+ ensures x == old(x) + 1;
+{
+ start:
+ x := 1 + x;
+ return;
+}
+
+procedure Q();
+ modifies x;
+ ensures x == old(x) + 1;
+
+implementation Q()
+{
+ start:
+ x := 1 + x;
+ return;
+}
+
+procedure R()
+ modifies x;
+ ensures x == old(x) + 1;
+{
+ start:
+ return;
+} // error: does not establish postcondition
+
+procedure Swap()
+ modifies x, y;
+ ensures x == old(y) && y == old(x);
+{
+ var t: int;
+
+ start:
+ goto A, B;
+ A:
+ t := x;
+ x := y;
+ y := t;
+ goto end;
+ B:
+ x := x - y; // x == old(x) - old(y)
+ y := y + x; // y == old(y) + (old(x) - old(y)) == old(x)
+ x := y - x; // x == old(x) - (old(x) - old(y)) == old(y)
+ goto end;
+ end:
+ return;
+}
+
+procedure OutParam0(x: int) returns (y: int)
+ ensures y == x + 1;
+{
+ start:
+ y := x + 1;
+ return;
+}
+
+// OutParam1 is like OutParam0, except that there's now a separate
+// implementation declaration, which means that the specification
+// and body use different AST nodes for the formal parameters. This
+// may make a difference in the various substitutions going on.
+// (Indeed, a previous bug caused OutParam0 to verify but not OutParam1.)
+procedure OutParam1(x: int) returns (y: int);
+ ensures y == x + 1;
+implementation OutParam1(x: int) returns (y: int)
+{
+ start:
+ y := x + 1;
+ return;
+}
+
+var a: [ref]int;
+var b: [ref]int;
+
+procedure SwapElems(o: ref) returns (p: ref)
+ modifies a, b;
+ ensures a[o] == old(b[p]) && b[o] == old(a[p]);
+{
+ var ta: int, tb: int;
+
+ start:
+ goto A, B, C;
+ A:
+ havoc p;
+ goto B, C;
+ B:
+ ta := a[p];
+ tb := b[p];
+ a[o] := tb;
+ b[o] := ta;
+ return;
+ C:
+ assume a[o] == b[o];assume false;
+
+ p := o;
+ return;
+}
+
+
+
+//-------------------------------------------------------------------------
+// Test old in Boogie PL code
+//-------------------------------------------------------------------------
+
+var Global0: int;
+
+// Good
+procedure OldInCode0()
+ requires Global0 >= 0;
+ ensures Global0 <= old(Global0) + 1;
+ modifies Global0;
+{
+ var local0: int;
+
+ start:
+ goto A,B;
+ A:
+ assert Global0 == old(Global0);
+ return;
+
+ B:
+ local0 := Global0 + 1;
+ local0 := local0 - 1;
+ Global0 := old(local0 + 1);
+ return;
+}
+
+type ref;
diff --git a/Test/test2/OldIllegal.bpl b/Test/test2/OldIllegal.bpl
new file mode 100644
index 00000000..342c5b19
--- /dev/null
+++ b/Test/test2/OldIllegal.bpl
@@ -0,0 +1,16 @@
+// Test old appearing in illegal locations
+
+var Global0: int;
+
+// Bad
+procedure OldInCode1()
+ requires old(Global0) == 0;
+{
+ start:
+ return;
+}
+
+// Bad
+axiom (forall o:ref :: old(o) == o);
+
+type ref;
diff --git a/Test/test2/Output b/Test/test2/Output
new file mode 100644
index 00000000..7876d732
--- /dev/null
+++ b/Test/test2/Output
@@ -0,0 +1,359 @@
+
+-------------------- FormulaTerm.bpl --------------------
+FormulaTerm.bpl(10,3): Error BP5003: A postcondition might not hold at this return statement.
+FormulaTerm.bpl(4,3): Related location: This is the postcondition that might not hold.
+Execution trace:
+ FormulaTerm.bpl(8,1): start
+
+Boogie program verifier finished with 11 verified, 1 error
+
+-------------------- FormulaTerm2.bpl --------------------
+FormulaTerm2.bpl(39,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ FormulaTerm2.bpl(36,3): start
+FormulaTerm2.bpl(47,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ FormulaTerm2.bpl(45,3): start
+
+Boogie program verifier finished with 2 verified, 2 errors
+
+-------------------- Passification.bpl --------------------
+Passification.bpl(44,3): Error BP5003: A postcondition might not hold at this return statement.
+Passification.bpl(36,3): Related location: This is the postcondition that might not hold.
+Execution trace:
+ Passification.bpl(39,1): A
+Passification.bpl(116,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Passification.bpl(106,1): L0
+ Passification.bpl(111,1): L1
+ Passification.bpl(115,1): L2
+Passification.bpl(151,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Passification.bpl(144,1): L0
+ Passification.bpl(150,1): L2
+Passification.bpl(165,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Passification.bpl(158,1): L0
+ Passification.bpl(161,1): L1
+ Passification.bpl(164,1): L2
+
+Boogie program verifier finished with 7 verified, 4 errors
+
+-------------------- B.bpl --------------------
+
+Boogie program verifier finished with 4 verified, 0 errors
+
+-------------------- Ensures.bpl --------------------
+Ensures.bpl(30,5): Error BP5003: A postcondition might not hold at this return statement.
+Ensures.bpl(19,3): Related location: This is the postcondition that might not hold.
+Execution trace:
+ Ensures.bpl(28,3): start
+Ensures.bpl(35,5): Error BP5003: A postcondition might not hold at this return statement.
+Ensures.bpl(19,3): Related location: This is the postcondition that might not hold.
+Execution trace:
+ Ensures.bpl(34,3): start
+Ensures.bpl(41,5): Error BP5003: A postcondition might not hold at this return statement.
+Ensures.bpl(19,3): Related location: This is the postcondition that might not hold.
+Execution trace:
+ Ensures.bpl(39,3): start
+Ensures.bpl(47,5): Error BP5003: A postcondition might not hold at this return statement.
+Ensures.bpl(19,3): Related location: This is the postcondition that might not hold.
+Execution trace:
+ Ensures.bpl(45,3): start
+Ensures.bpl(72,5): Error BP5003: A postcondition might not hold at this return statement.
+Ensures.bpl(19,3): Related location: This is the postcondition that might not hold.
+Execution trace:
+ Ensures.bpl(70,3): start
+
+Boogie program verifier finished with 5 verified, 5 errors
+
+-------------------- Old.bpl --------------------
+Old.bpl(29,5): Error BP5003: A postcondition might not hold at this return statement.
+Old.bpl(26,3): Related location: This is the postcondition that might not hold.
+Execution trace:
+ Old.bpl(28,3): start
+
+Boogie program verifier finished with 7 verified, 1 error
+
+-------------------- OldIllegal.bpl --------------------
+OldIllegal.bpl(7,11): Error: old expressions allowed only in two-state contexts
+OldIllegal.bpl(14,23): Error: old expressions allowed only in two-state contexts
+2 name resolution errors detected in OldIllegal.bpl
+
+-------------------- Arrays.bpl --------------------
+Arrays.bpl(46,5): Error BP5003: A postcondition might not hold at this return statement.
+Arrays.bpl(38,3): Related location: This is the postcondition that might not hold.
+Execution trace:
+ Arrays.bpl(42,3): start
+Arrays.bpl(127,5): Error BP5003: A postcondition might not hold at this return statement.
+Arrays.bpl(119,3): Related location: This is the postcondition that might not hold.
+Execution trace:
+ Arrays.bpl(123,3): start
+
+Boogie program verifier finished with 8 verified, 2 errors
+
+-------------------- Axioms.bpl --------------------
+Axioms.bpl(19,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ Axioms.bpl(18,3): start
+
+Boogie program verifier finished with 2 verified, 1 error
+
+-------------------- Quantifiers.bpl --------------------
+Quantifiers.bpl(20,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ Quantifiers.bpl(19,3): start
+Quantifiers.bpl(43,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ Quantifiers.bpl(42,3): start
+Quantifiers.bpl(65,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ Quantifiers.bpl(64,3): start
+Quantifiers.bpl(73,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ Quantifiers.bpl(71,3): start
+Quantifiers.bpl(125,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ Quantifiers.bpl(124,3): start
+Quantifiers.bpl(150,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ Quantifiers.bpl(149,3): start
+
+Boogie program verifier finished with 8 verified, 6 errors
+
+-------------------- Call.bpl --------------------
+Call.bpl(13,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ Call.bpl(9,3): entry
+Call.bpl(46,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ Call.bpl(45,3): start
+Call.bpl(55,5): Error BP5003: A postcondition might not hold at this return statement.
+Call.bpl(20,3): Related location: This is the postcondition that might not hold.
+Execution trace:
+ Call.bpl(53,3): start
+
+Boogie program verifier finished with 2 verified, 3 errors
+
+-------------------- AssumeEnsures.bpl --------------------
+AssumeEnsures.bpl(28,9): Error BP5001: This assertion might not hold.
+Execution trace:
+ AssumeEnsures.bpl(26,5): entry
+AssumeEnsures.bpl(47,9): Error BP5001: This assertion might not hold.
+Execution trace:
+ AssumeEnsures.bpl(46,5): entry
+AssumeEnsures.bpl(62,9): Error BP5001: This assertion might not hold.
+Execution trace:
+ AssumeEnsures.bpl(60,5): entry
+
+Boogie program verifier finished with 4 verified, 3 errors
+
+-------------------- CutBackEdge.bpl --------------------
+CutBackEdge.bpl(10,5): Error BP5005: This loop invariant might not be maintained by the loop.
+Execution trace:
+ CutBackEdge.bpl(5,3): entry
+ CutBackEdge.bpl(9,3): block850
+
+Boogie program verifier finished with 0 verified, 1 error
+
+-------------------- False.bpl --------------------
+
+Boogie program verifier finished with 2 verified, 0 errors
+
+-------------------- LoopInvAssume.bpl --------------------
+LoopInvAssume.bpl(18,7): Error BP5001: This assertion might not hold.
+Execution trace:
+ LoopInvAssume.bpl(8,4): entry
+ LoopInvAssume.bpl(16,4): exit
+
+Boogie program verifier finished with 0 verified, 1 error
+
+-------------------- strings-no-where.bpl --------------------
+strings-no-where.bpl(201,103): Error: invalid argument types (any and name) to binary operator ==
+strings-no-where.bpl(203,105): Error: invalid argument types (any and name) to binary operator ==
+strings-no-where.bpl(209,106): Error: invalid type for argument 1 in application of IsAllocated: struct (expected: any)
+strings-no-where.bpl(211,72): Error: invalid type for argument 1 in application of IsAllocated: ref (expected: any)
+strings-no-where.bpl(211,108): Error: invalid type for argument 1 in application of IsAllocated: elements (expected: any)
+strings-no-where.bpl(211,130): Error: invalid type for argument 1 in application of IsAllocated: ref (expected: any)
+strings-no-where.bpl(213,78): Error: invalid type for argument 1 in application of IsAllocated: ref (expected: any)
+strings-no-where.bpl(235,98): Error: invalid argument types (any and name) to binary operator ==
+strings-no-where.bpl(249,118): Error: invalid argument types (any and name) to binary operator ==
+strings-no-where.bpl(699,34): Error: invalid type for argument 1 in application of IsAllocated: int (expected: any)
+strings-no-where.bpl(728,9): Error: mismatched types in assignment command (cannot assign bool to any)
+strings-no-where.bpl(737,9): Error: mismatched types in assignment command (cannot assign bool to any)
+strings-no-where.bpl(751,9): Error: mismatched types in assignment command (cannot assign bool to any)
+strings-no-where.bpl(760,9): Error: mismatched types in assignment command (cannot assign bool to any)
+strings-no-where.bpl(926,36): Error: invalid argument types (any and name) to binary operator ==
+strings-no-where.bpl(949,36): Error: invalid argument types (any and name) to binary operator ==
+strings-no-where.bpl(975,9): Error: mismatched types in assignment command (cannot assign name to any)
+strings-no-where.bpl(990,36): Error: invalid argument types (any and name) to binary operator ==
+18 type checking errors detected in strings-no-where.bpl
+
+-------------------- strings-where.bpl --------------------
+strings-where.bpl(201,103): Error: invalid argument types (any and name) to binary operator ==
+strings-where.bpl(203,105): Error: invalid argument types (any and name) to binary operator ==
+strings-where.bpl(209,106): Error: invalid type for argument 1 in application of IsAllocated: struct (expected: any)
+strings-where.bpl(211,72): Error: invalid type for argument 1 in application of IsAllocated: ref (expected: any)
+strings-where.bpl(211,108): Error: invalid type for argument 1 in application of IsAllocated: elements (expected: any)
+strings-where.bpl(211,130): Error: invalid type for argument 1 in application of IsAllocated: ref (expected: any)
+strings-where.bpl(213,78): Error: invalid type for argument 1 in application of IsAllocated: ref (expected: any)
+strings-where.bpl(235,98): Error: invalid argument types (any and name) to binary operator ==
+strings-where.bpl(249,118): Error: invalid argument types (any and name) to binary operator ==
+strings-where.bpl(699,34): Error: invalid type for argument 1 in application of IsAllocated: int (expected: any)
+strings-where.bpl(728,9): Error: mismatched types in assignment command (cannot assign bool to any)
+strings-where.bpl(737,9): Error: mismatched types in assignment command (cannot assign bool to any)
+strings-where.bpl(751,9): Error: mismatched types in assignment command (cannot assign bool to any)
+strings-where.bpl(760,9): Error: mismatched types in assignment command (cannot assign bool to any)
+strings-where.bpl(926,36): Error: invalid argument types (any and name) to binary operator ==
+strings-where.bpl(949,36): Error: invalid argument types (any and name) to binary operator ==
+strings-where.bpl(975,9): Error: mismatched types in assignment command (cannot assign name to any)
+strings-where.bpl(990,36): Error: invalid argument types (any and name) to binary operator ==
+18 type checking errors detected in strings-where.bpl
+
+-------------------- Structured.bpl --------------------
+Structured.bpl(252,14): Error BP5003: A postcondition might not hold at this return statement.
+Structured.bpl(243,3): Related location: This is the postcondition that might not hold.
+Execution trace:
+ Structured.bpl(245,3): anon0
+ Structured.bpl(245,3): anon6_LoopHead
+ Structured.bpl(246,5): anon6_LoopBody
+ Structured.bpl(247,7): anon7_LoopBody
+ Structured.bpl(252,5): anon4
+ Structured.bpl(252,14): anon9_Then
+Structured.bpl(303,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Structured.bpl(299,5): anon0
+ Structured.bpl(300,3): anon3_Else
+ Structured.bpl(303,3): anon2
+Structured.bpl(311,7): Error BP5001: This assertion might not hold.
+Execution trace:
+ Structured.bpl(308,3): anon0
+ Structured.bpl(308,3): anon1_Then
+ Structured.bpl(309,5): A
+
+Boogie program verifier finished with 15 verified, 3 errors
+
+-------------------- Where.bpl --------------------
+Where.bpl(8,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Where.bpl(6,3): anon0
+Where.bpl(22,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Where.bpl(16,5): anon0
+Where.bpl(32,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Where.bpl(30,3): anon0
+Where.bpl(44,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Where.bpl(40,5): anon0
+Where.bpl(57,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Where.bpl(52,3): anon0
+Where.bpl(111,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Where.bpl(102,5): anon0
+ Where.bpl(104,3): anon3_LoopHead
+ Where.bpl(110,3): anon2
+Where.bpl(128,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Where.bpl(121,5): anon0
+ Where.bpl(122,3): anon3_LoopHead
+ Where.bpl(125,3): anon2
+Where.bpl(145,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Where.bpl(138,5): anon0
+ Where.bpl(139,3): anon3_LoopHead
+ Where.bpl(142,3): anon2
+Where.bpl(162,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Where.bpl(155,5): anon0
+ Where.bpl(156,3): anon3_LoopHead
+ Where.bpl(159,3): anon2
+
+Boogie program verifier finished with 2 verified, 9 errors
+
+-------------------- UpdateExpr.bpl --------------------
+UpdateExpr.bpl(14,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ UpdateExpr.bpl(14,3): anon0
+UpdateExpr.bpl(19,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ UpdateExpr.bpl(19,3): anon0
+UpdateExpr.bpl(32,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ UpdateExpr.bpl(32,3): anon0
+UpdateExpr.bpl(38,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ UpdateExpr.bpl(38,3): anon0
+UpdateExpr.bpl(52,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ UpdateExpr.bpl(51,5): anon0
+
+Boogie program verifier finished with 5 verified, 5 errors
+
+-------------------- NeverPattern.bpl --------------------
+NeverPattern.bpl(16,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ NeverPattern.bpl(15,3): anon0
+NeverPattern.bpl(22,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ NeverPattern.bpl(21,3): anon0
+NeverPattern.bpl(28,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ NeverPattern.bpl(27,3): anon0
+
+Boogie program verifier finished with 1 verified, 3 errors
+
+-------------------- NullaryMaps.bpl --------------------
+NullaryMaps.bpl(28,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ NullaryMaps.bpl(28,3): anon0
+NullaryMaps.bpl(30,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ NullaryMaps.bpl(28,3): anon0
+NullaryMaps.bpl(36,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ NullaryMaps.bpl(36,3): anon0
+
+Boogie program verifier finished with 2 verified, 3 errors
+
+-------------------- Implies.bpl --------------------
+Implies.bpl(12,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Implies.bpl(11,3): anon0
+Implies.bpl(15,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Implies.bpl(11,3): anon0
+
+Boogie program verifier finished with 0 verified, 2 errors
+-------------------- sk_hack.bpl --------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
+
+-------------------- CallForall.bpl --------------------
+CallForall.bpl(17,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ CallForall.bpl(17,3): anon0
+CallForall.bpl(29,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ CallForall.bpl(28,3): anon0
+CallForall.bpl(41,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ CallForall.bpl(40,3): anon0
+CallForall.bpl(47,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ CallForall.bpl(46,3): anon0
+CallForall.bpl(75,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ CallForall.bpl(75,3): anon0
+CallForall.bpl(111,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ CallForall.bpl(109,3): anon0
+CallForall.bpl(118,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ CallForall.bpl(117,3): anon0
+CallForall.bpl(125,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ CallForall.bpl(124,3): anon0
+
+Boogie program verifier finished with 10 verified, 8 errors
diff --git a/Test/test2/Passification.bpl b/Test/test2/Passification.bpl
new file mode 100644
index 00000000..e13d3e49
--- /dev/null
+++ b/Test/test2/Passification.bpl
@@ -0,0 +1,169 @@
+// VC generation tests: passification
+
+procedure good0(x: int) returns (y: int, z: int)
+ ensures z == 4 || z == 4+x;
+{
+var t: int;
+A:
+ t := y;
+ z := 3;
+ goto B, C;
+B:
+ z := z + x;
+ goto D;
+C:
+ goto D;
+D:
+ z := z + 1;
+ y := t;
+ return;
+}
+
+procedure good1(x: int) returns (y: int, z: int)
+ ensures z == x + 4;
+{
+var t: int;
+A:
+ t := y;
+ z := 3;
+ z := z + x;
+ z := z + 1;
+ y := t;
+ return;
+}
+
+procedure bad0(x: int) returns (y: int, z: int)
+ ensures y == 4; // ERROR: postcondition violation
+{
+var t: int;
+A:
+ t := z;
+ z := 3;
+ z := z + 1;
+ y := t;
+ return;
+}
+
+procedure Loop()
+{
+start:
+ goto start;
+}
+
+procedure UnreachableBlock()
+{
+start:
+ return;
+notReached:
+ goto start;
+reallyNeverReached:
+ goto reallyNeverReached;
+}
+
+procedure Loop0() returns (z: int)
+ ensures 10 <= z;
+{
+var x: int;
+A:
+ goto B, C;
+B:
+ assume x < 10;
+ x := x + 1;
+ goto A;
+C:
+ assume !(x < 10);
+ z := x;
+ return;
+}
+
+const unique A0: name;
+const unique A1: name;
+const unique A2: name;
+
+procedure Array0() returns (z: int)
+ ensures z >= 5;
+{
+var a: [name,name]int;
+L0:
+ a[A0,A2] := 5;
+ a[A0,A1] := 20;
+ assert a[A0,A1] == 20;
+ goto L1,L2;
+L1:
+ a[A0,A2] := 18;
+ assert a[A0,A2] == 18;
+ goto L2;
+L2:
+ assert a[A0,A1] == 20;
+ z := a[A0,A2];
+ return;
+}
+
+procedure Array1(o0: ref, o1: ref) returns (z: int)
+ ensures z >= 5;
+{
+var a: [ref,name]int;
+L0:
+ a[o1,A0] := 5;
+ a[o0,A0] := 20;
+ assert a[o0,A0] == 20;
+ goto L1,L2;
+L1:
+ a[o1,A0] := 18;
+ assert a[o1,A0] == 18;
+ goto L2;
+L2:
+ assert a[o0,A0] == 20; // ERROR: assertion failure
+ z := a[o1,A0];
+ return;
+}
+
+procedure Array2(o0: ref, o1: ref) returns (z: int)
+ ensures z >= 5;
+{
+var a: [ref,name]int;
+L0:
+ assume o1 != o0;
+ a[o1,A0] := 5;
+ a[o0,A0] := 20;
+ assert a[o0,A0] == 20;
+ goto L1,L2;
+L1:
+ a[o1,A0] := 18;
+ assert a[o1,A0] == 18;
+ goto L2;
+L2:
+ assert a[o0,A0] == 20;
+ z := a[o1,A0];
+ return;
+}
+
+procedure P()
+{
+var t: int;
+L0:
+ t := 0;
+ goto L1, L2;
+L1:
+ t := 1;
+ goto L2;
+L2:
+ assert t == 1; // ERROR: assert failure
+ return;
+}
+
+procedure Q()
+{
+var t: int;
+L0:
+ t := 0;
+ goto L1, L2;
+L1:
+ t := 1;
+ goto L2;
+L2:
+ assert t == 0; // ERROR: assert failure
+ return;
+}
+
+type name, ref;
diff --git a/Test/test2/Quantifiers.bpl b/Test/test2/Quantifiers.bpl
new file mode 100644
index 00000000..d368fe1f
--- /dev/null
+++ b/Test/test2/Quantifiers.bpl
@@ -0,0 +1,154 @@
+// ----------------------------------------------------------------------- single trigger
+
+function f(int, int) returns (int);
+
+axiom (forall x: int, y: int :: f(x,y) < x+y);
+axiom (forall x: int :: { f(x,10) } f(x,10) == 3);
+
+procedure P(a: int, b: int)
+ requires a <= 25 && b <= 30;
+{
+ start:
+ assert f(a,b) <= 100;
+ return;
+}
+
+procedure Q(a: int, b: int)
+ requires a + 2 <= b;
+{
+ start:
+ assert f(a,b) == 3; // not provable with the trigger given above
+ return;
+}
+
+procedure R(a: int, b: int)
+ requires a + 2 <= b;
+{
+ start:
+ assume b <= 10 && 8 <= a;
+ assert f(a,b) == 3; // now, the trigger should fire
+ return;
+}
+
+// ----------------------------------------------------------------------- multi trigger
+
+function g(int, int) returns (int);
+
+axiom (forall x: int, y: int :: { g(x,10),g(x,y) } g(x,y) == 3); // multi-trigger
+
+procedure S(a: int, b: int)
+ requires a + 2 <= b;
+{
+ start:
+ assert g(a,b) == 3; // not provable with the trigger given above
+ return;
+}
+
+procedure T(a: int, b: int)
+ requires a + 2 <= b;
+{
+ start:
+ assume b <= 10 && 8 <= a;
+ assert g(a,b) == 3; // this should trigger
+ return;
+}
+
+// ----------------------------------------------------------------------- several triggers
+
+function h(int, int) returns (int);
+
+axiom (forall y: int :: { g(y,y) } { h(y,h(y,10)) } h(y, h(y,y)) == y); // several triggers
+
+procedure U0(a: int)
+{
+ start:
+ assert h(a,h(a,a)) == a; // not provable with the triggers given above
+ return;
+}
+
+procedure U1(a: int, b: int)
+{
+ start:
+ assume g(a,b) == 5;
+ assert h(a,h(a,a)) == a; // not provable with the triggers given above
+ return;
+}
+
+procedure V0(a: int, b: int)
+ requires a == b;
+{
+ start:
+ assume g(a,b) == 5;
+ assert h(a,h(a,a)) == a; // this should trigger
+ return;
+}
+
+procedure V1(a: int, b: int)
+{
+ start:
+ assume a == 10;
+ assert h(a,h(a,a)) == a; // this should trigger
+ return;
+}
+
+procedure V2(a: int, b: int)
+{
+ start:
+ assume 0 <= h(a,h(a,10));
+ assume a == 17;
+ assert h(a,h(a,a)) == a; // this should trigger
+ return;
+}
+
+// ----------------------------------------------------------------------- negated triggers
+
+function ka(ref) returns (int);
+function kb(ref) returns (int);
+function kbSynonym(ref) returns (int);
+function isA(ref, name) returns (bool);
+function isB(ref, name) returns (bool);
+const $T: name;
+
+axiom (forall o: ref ::
+ isA(o, $T) ==> ka(o) < ka(o)); // automatically inferred triggers can be both isA(o,$T) and ka(o)
+
+axiom (forall o: ref ::
+ {:nopats isB(o, $T) }
+ isB(o, $T) ==> kb(o) < kbSynonym(o)); // prevent isB(o,$T) from being used as a trigger
+
+axiom (forall o: ref :: kb(o) == kbSynonym(o));
+
+procedure W(o: ref, e: int)
+ requires isB(o, $T);
+{
+ start:
+ assert e > 20; // the isB axiom should not trigger, so this cannot be proved
+ return;
+}
+
+procedure X0(o: ref, e: int)
+ requires isA(o, $T);
+{
+ start:
+ assert e > 20; // this should trigger the isA axiom, so anything is provable
+ return;
+}
+
+procedure X1(o: ref, e: int, u: int)
+ requires isB(o, $T);
+{
+ start:
+ assume f(kb(o), kb(o)) == u;
+ assert e > 20; // this should now trigger the isB axiom, so anything is provable
+ return;
+}
+
+procedure X2(o: ref, e: int, u: int)
+ requires isB(o, $T);
+{
+ start:
+ assert e > 20; // error is report here, providing evidence that the isB axiom has not been triggered
+ return;
+}
+
+type name, ref;
diff --git a/Test/test2/Structured.bpl b/Test/test2/Structured.bpl
new file mode 100644
index 00000000..ce97b145
--- /dev/null
+++ b/Test/test2/Structured.bpl
@@ -0,0 +1,327 @@
+
+const K: int;
+
+function f(int) returns (int);
+
+axiom (exists k: int :: f(k) == K);
+
+procedure Find(a: int, b: int) returns (k: int);
+ requires a <= b && (forall j: int :: a < j && j < b ==> f(j) != K);
+ ensures f(k) == K;
+
+// nondeterministic, unstructured, recursive version
+implementation Find(a: int, b: int) returns (k: int)
+{
+ entry:
+ goto A, B, C;
+
+ A:
+ assume f(a) == K;
+ k := a;
+ return;
+
+ B:
+ assume f(b) == K;
+ k := b;
+ return;
+
+ C:
+ assume f(a) != K && f(b) != K;
+ call k := Find(a-1, b+1);
+ return;
+}
+
+// nondeterministic, recursive version
+implementation Find(a: int, b: int) returns (k: int)
+{
+ if (*) {
+ assume f(a) == K;
+ k := a;
+ } else if (*) {
+ assume f(b) == K;
+ k := b;
+ } else {
+ assume f(a) != K && f(b) != K;
+ call k := Find(a-1, b+1);
+ }
+}
+
+// deterministic, structured, recursive version
+implementation Find(a: int, b: int) returns (k: int)
+{
+ if (f(a) == K) {
+ k := a;
+ } else if (f(b) == K) {
+ k := b;
+ } else {
+ call k := Find(a-1, b+1);
+ }
+}
+
+// deterministic, structured, iterative version
+implementation Find(a: int, b: int) returns (k: int)
+{
+ var x: int, y: int;
+
+ x := a;
+ y := b;
+
+ while (f(x) != K && f(y) != K)
+ invariant x <= y && (forall j: int :: x < j && j < y ==> f(j) != K);
+ {
+ x := x-1;
+ y := y+1;
+ }
+
+ if (f(x) == K) {
+ k := x;
+ } else {
+ k := y;
+ }
+}
+
+// deterministic, structured, iterative version with breaks
+implementation Find(a: int, b: int) returns (k: int)
+{
+ var x: int, y: int;
+
+ x := a;
+ y := b;
+
+ while (true)
+ invariant x <= y && (forall j: int :: x < j && j < y ==> f(j) != K);
+ {
+ if (f(x) == K) {
+ k := x;
+ break;
+ } else if (f(y) == K) {
+ k := y;
+ break;
+ }
+ x := x-1;
+ y := y+1;
+ }
+}
+
+// deterministic, somewhat structured, iterative version
+implementation Find(a: int, b: int) returns (k: int)
+{
+ var x: int, y: int;
+
+ x := a;
+ y := b;
+
+ while (true)
+ invariant x <= y && (forall j: int :: x < j && j < y ==> f(j) != K);
+ {
+ if (f(x) == K) {
+ goto FoundX;
+ } else if (f(y) == K) {
+ goto FoundY;
+ }
+ x := x-1;
+ y := y+1;
+ }
+
+ FoundX:
+ k := x;
+ return;
+
+ FoundY:
+ k := y;
+ return;
+}
+
+// deterministic, structured, iterative version with breaks
+implementation Find(a: int, b: int) returns (k: int)
+{
+ var x: int, y: int;
+
+ x := a;
+ y := b;
+
+ outer:
+ if (true) {
+ inner:
+ while (true)
+ invariant x <= y && (forall j: int :: x < j && j < y ==> f(j) != K);
+ {
+ if (f(x) == K) {
+ break inner;
+ } else if (f(y) == K) {
+ break outer;
+ }
+ x := x-1;
+ y := y+1;
+ }
+
+ k := x;
+ return;
+ }
+ k := y;
+}
+
+// ----- free invariant -----
+
+function Teal(int) returns (bool);
+function ShadeOfGreen(int) returns (bool);
+axiom (forall w: int :: Teal(w) ==> ShadeOfGreen(w));
+
+procedure P(x: int) returns (y: int)
+ requires Teal(x);
+ ensures ShadeOfGreen(y);
+{
+ y := x;
+ while (y < 100)
+ free invariant Teal(y);
+ {
+ y := y + 5;
+ }
+}
+
+// ----- run off the end of the BigBlock -----
+
+procedure RunOffEnd0() returns (x: int)
+ ensures x == 3;
+{
+ x := 0;
+ Label0:
+ x := x + 1;
+ Label1:
+ x := x + 1;
+ Label2:
+ Label3:
+ Label4:
+ x := x + 1;
+}
+
+procedure RunOffEnd1() returns (x: int)
+ ensures x == 4;
+{
+ x := 0;
+ Label0:
+ x := x + 1;
+ Label1:
+ if (*) {
+ Label2:
+ x := x + 2;
+ } else if (*) {
+ Label3:
+ x := 2;
+ x := x + 2;
+ Label4:
+ Label5:
+ x := x - 1;
+ } else {
+ if (*) {
+ x := 0;
+ while (x < 3)
+ invariant x <= 3;
+ { x := x + 1; }
+ } else {
+ x := x + 2;
+ }
+ }
+ x := x + 1;
+}
+
+procedure RunOffEnd2() returns (x: int)
+ ensures x == 10;
+{
+ while (true) {
+ while (true) {
+ if (*) {
+ x := 10;
+ break;
+ }
+ }
+ if (*) { break; }
+ }
+}
+
+procedure RunOffEnd3() returns (x: int)
+ ensures x == 9;
+{
+ while (true) {
+ while (true) {
+ if (*) {
+ x := 10;
+ break;
+ }
+ }
+ if (*) { break; }
+ } // error: violated postcondition
+}
+
+procedure RunOffEnd4() returns (x: int)
+{
+ var y: int;
+ var bad: bool;
+
+ while (true) {
+ y := x;
+ bad := false;
+ if (*) {
+ x := x + 1;
+ bad := true;
+ }
+ if (x == y) { break; }
+ }
+ assert !bad;
+}
+
+procedure RunOffEnd5() returns (x: int)
+{
+ while (true) {
+ if (x == 5) { }
+ }
+ assert false;
+}
+
+procedure RunOffEnd6() returns (x: int)
+{
+ x := 7;
+ while (true)
+ invariant x == 7;
+ {
+ x := 5;
+ MyLabel:
+ x := 7;
+ }
+}
+
+// ----- jump optimizations -----
+
+procedure Q0()
+{
+ var x: int;
+
+ x := 0;
+ if (*) {
+ x := 1;
+ }
+ assert x == 1; // error
+}
+
+procedure Q1() returns (x: int)
+{
+ if (x == 0) {
+ A:
+ x := x + 0;
+ assert x == 0; // error
+ B:
+ x := x + 1;
+ goto A;
+ }
+}
+
+procedure Q2() returns (x: int)
+{
+ if (x == 0) {
+ while (x < 10)
+ invariant x <= 10;
+ {
+ x := x + 1;
+ }
+ }
+}
diff --git a/Test/test2/UpdateExpr.bpl b/Test/test2/UpdateExpr.bpl
new file mode 100644
index 00000000..8f950073
--- /dev/null
+++ b/Test/test2/UpdateExpr.bpl
@@ -0,0 +1,81 @@
+
+const a: [int]bool;
+
+// element 5 of a stores the value true
+axiom a == a[5 := true];
+
+procedure P()
+{
+ assert a[5];
+}
+
+procedure Q()
+{
+ assert a[4]; // error
+}
+
+procedure R()
+{
+ assert !a[5]; // error
+}
+
+procedure S(y: int, t: bool)
+ requires y <= 5;
+{
+ if (a[y := t][5] == false) {
+ assert y == 5;
+ }
+}
+
+procedure T0(aa: [int,ref]bool)
+{
+ assert aa[5,null := true] != aa[2,null := false]; // error
+}
+
+procedure T1(aa: [int,ref]bool)
+ requires aa[5,null] && !aa[2,null];
+{
+ assert aa[5,null := true] == aa[2,null := false]; // error, because we have no extensionality
+}
+
+procedure T2(aa: [int,ref]bool)
+ requires aa[5,null] && !aa[2,null];
+{
+ assert (forall x: int, y: ref :: aa[5,null := true][x,y] == aa[2,null := false][x,y]);
+}
+
+procedure U0(a: [int]int)
+{
+ var b: [int]int;
+
+ b := a[5 := 12];
+ assert a == b; // error
+}
+
+procedure U1() returns (a: [int]int)
+{
+ var b: [int]int;
+
+ b := a[5 := 12];
+ a[5] := 12;
+ assert a == b;
+}
+
+type Field a;
+const unique IntField: Field int;
+const unique RefField: Field ref;
+const unique SomeField: Field int;
+
+procedure FieldProc(H: <a>[ref,Field a]a, this: ref)
+{
+ var i: int, r: ref, y: any;
+ var K: <a>[ref,Field a]a;
+
+ K := H[this, IntField := 5][this, RefField := null][this, SomeField := 100][this, IntField := 7];
+ assert K[this, IntField] == 7;
+ assert K[this, RefField] == null;
+ assert K[this, SomeField] == 100;
+}
+
+type ref, any;
+const null : ref;
diff --git a/Test/test2/Where.bpl b/Test/test2/Where.bpl
new file mode 100644
index 00000000..96ffcf04
--- /dev/null
+++ b/Test/test2/Where.bpl
@@ -0,0 +1,163 @@
+procedure P0()
+{
+ var x: int where 0 <= x;
+ var y: int where x <= y;
+
+ assert 0 <= x;
+ assert x <= y;
+ assert y < 5; // error
+}
+
+procedure P1()
+{
+ var x: int where 0 <= x;
+ var y: int where x <= y;
+
+ x := 5;
+ havoc y;
+ assert 5 <= y;
+
+ havoc x;
+ assert 0 <= x;
+ assert x <= y; // error
+}
+
+procedure P2()
+{
+ var x: int where 0 <= x;
+ var y: int where x <= y;
+
+ havoc y; // y first
+ havoc x;
+ assert x <= y; // error
+}
+
+procedure P3()
+{
+ var x: int where 0 <= x;
+ var y: int where x <= y;
+
+ x := 5;
+ havoc x; // this time, x first
+ havoc y;
+ assert x <= y; // yeah!
+ assert 5 <= y; // error
+}
+
+procedure P4()
+{
+ var x: int where 0 <= x;
+ var y: int where x <= y;
+
+ havoc x, y; // both at the same time
+ assert 0 <= x && x <= y;
+ havoc y, x; // or in the other order
+ assert 0 <= x && x <= y;
+
+ assert x == 7; // error
+}
+
+procedure R0() returns (wProc: int where wProc == xProc,
+ xProc: int where 0 <= xProc,
+ yProc: int where xProc <= yProc);
+implementation R0() returns (w: int, x: int, y: int)
+{
+ while (*) {
+ assert w == x;
+ assert 0 <= x;
+ assert x <= y;
+ }
+ while (*) {
+ assert w == x;
+ assert 0 <= x;
+ assert x <= y;
+ // the following makes w, x, y loop targets
+ w := w + 1;
+ havoc x;
+ y := w;
+ }
+ assert w == x;
+ assert 0 <= x;
+ assert x <= y;
+}
+
+procedure R1()
+{
+ var a: int;
+ var b: int;
+ var c: int;
+
+ call a, b, c := R0();
+ assert a == b;
+ assert 0 <= b;
+ assert b <= c;
+}
+
+procedure R2()
+{
+ var w: int where w == x;
+ var x: int where 0 <= x;
+ var y: int where x <= y;
+
+ x := 5;
+ y := 10;
+ while (*) {
+ w := w + 1;
+ assert w == 6;
+ y := y + 2;
+ assert 7 <= y;
+ }
+ assert x == 5 && 0 <= y - w;
+ assert y == 10; // error
+}
+
+procedure R3()
+{
+ var w: int where w == x;
+ var x: int where 0 <= x;
+ var y: int where x <= y;
+
+ // change w and x
+ y := 10;
+ while (*) {
+ w := w; x := x;
+ }
+ assert w == x;
+ assert 0 <= x;
+ assert y == 10;
+ assert w <= 10; // error
+}
+
+procedure R4()
+{
+ var w: int where w == x;
+ var x: int where 0 <= x;
+ var y: int where x <= y;
+
+ // change x and y
+ w := 12;
+ while (*) {
+ x := x; y := y;
+ }
+ assert 0 <= x;
+ assert x <= y;
+ assert w == 12;
+ assert 8 <= y; // error
+}
+
+procedure R5(K: int)
+{
+ var w: int where w == x;
+ var x: int where 0 <= x;
+ var y: int where x <= y;
+
+ // change w and y
+ x := K;
+ while (*) {
+ w := w; y := y;
+ }
+ assert w == K;
+ assert K <= y;
+ assert x == K;
+ assert 0 <= x; // error
+}
diff --git a/Test/test2/runtest.bat b/Test/test2/runtest.bat
new file mode 100644
index 00000000..5f48a799
--- /dev/null
+++ b/Test/test2/runtest.bat
@@ -0,0 +1,26 @@
+@echo off
+setlocal
+
+set BGEXE=..\..\Binaries\Boogie.exe
+rem set BGEXE=mono ..\..\Binaries\Boogie.exe
+
+for %%f in (FormulaTerm.bpl FormulaTerm2.bpl Passification.bpl B.bpl
+ Ensures.bpl Old.bpl OldIllegal.bpl Arrays.bpl Axioms.bpl
+ Quantifiers.bpl Call.bpl AssumeEnsures.bpl
+ CutBackEdge.bpl False.bpl LoopInvAssume.bpl
+ strings-no-where.bpl strings-where.bpl
+ Structured.bpl Where.bpl UpdateExpr.bpl
+ NeverPattern.bpl NullaryMaps.bpl Implies.bpl) do (
+ echo.
+ echo -------------------- %%f --------------------
+ %BGEXE% %* /noinfer %%f
+)
+
+echo -------------------- sk_hack.bpl --------------------
+%BGEXE% %* /noinfer /bv:z sk_hack.bpl
+
+for %%f in (CallForall.bpl) do (
+ echo.
+ echo -------------------- %%f --------------------
+ %BGEXE% %* %%f
+)
diff --git a/Test/test2/sk_hack.bpl b/Test/test2/sk_hack.bpl
new file mode 100644
index 00000000..df942317
--- /dev/null
+++ b/Test/test2/sk_hack.bpl
@@ -0,0 +1,32 @@
+function in_set(int) returns(bool);
+function next(int) returns(int);
+function f(int) returns(bool);
+function g(int) returns(bool);
+
+// this function is treated specially by Z3 when used in triggers
+// sk_hack(f(x)) means to activate the e-node f(x0) when trying to prove
+// !(forall x : T :: {sk_hack(f(x))} p(x)) by proving !p(x0)
+// (i.e., after skolemization of x to x0).
+function sk_hack(bool) returns(bool);
+
+// PR: sk_hack cannot be defined as a polymorphic function
+// when using /quantifierTypePremisses:a, because then it would
+// get an additional explicit type parameter, and Z3 would
+// no longer recognise it.
+
+procedure foo()
+{
+ assume (forall x:int :: {in_set(next(x))}
+ in_set(x) ==> in_set(next(x)));
+
+ assume (forall x:int :: {in_set(x)}
+ in_set(x) ==> f(x));
+
+ assume (forall x:int :: {f(next(x))}
+ f(next(x)) ==> g(x));
+
+ assert (forall x:int ::
+ { sk_hack(in_set(next(x))) }
+ in_set(x) ==> g(x));
+ }
+
diff --git a/Test/test2/strings-no-where.bpl b/Test/test2/strings-no-where.bpl
new file mode 100644
index 00000000..ff723db2
--- /dev/null
+++ b/Test/test2/strings-no-where.bpl
@@ -0,0 +1,995 @@
+type real;
+
+type elements;
+
+type struct;
+
+var $Heap: [ref,name]any;
+function cast<S,T>(S) returns (T);
+function IsHeap(h: [ref,name]any) returns (bool);
+
+const unique $allocated: name;
+
+const unique $elements: name;
+
+const unique $inv: name;
+
+const unique $writable: name;
+
+const unique $sharingMode: name;
+
+const unique $SharingMode_Unshared: name;
+
+const unique $SharingMode_LockProtected: name;
+
+function ClassRepr(class: name) returns (ref);
+
+axiom (forall c0: name, c1: name :: c0 != c1 ==> ClassRepr(c0) != ClassRepr(c1));
+
+axiom (forall T: name :: !($typeof(ClassRepr(T)) <: System.Object));
+
+axiom (forall T: name :: ClassRepr(T) != null);
+
+axiom (forall T: name, h: [ref,name]any :: { h[ClassRepr(T), $writable] } IsHeap(h) ==> cast(h[ClassRepr(T), $writable]):bool);
+
+function IsDirectlyModifiableField(f: name) returns (bool);
+
+axiom !IsDirectlyModifiableField($allocated);
+
+axiom IsDirectlyModifiableField($elements);
+
+axiom !IsDirectlyModifiableField($inv);
+
+axiom !IsDirectlyModifiableField($writable);
+
+function IsStaticField(f: name) returns (bool);
+
+axiom !IsStaticField($allocated);
+
+axiom !IsStaticField($elements);
+
+axiom !IsStaticField($inv);
+
+axiom !IsStaticField($writable);
+
+function ValueArrayGet(elements, int) returns (any);
+
+function ValueArraySet(elements, int, any) returns (elements);
+
+function RefArrayGet(elements, int) returns (ref);
+
+function RefArraySet(elements, int, ref) returns (elements);
+
+axiom (forall A: elements, i: int, x: any :: ValueArrayGet(ValueArraySet(A, i, x), i) == x);
+
+axiom (forall A: elements, i: int, j: int, x: any :: i != j ==> ValueArrayGet(ValueArraySet(A, i, x), j) == ValueArrayGet(A, j));
+
+axiom (forall A: elements, i: int, x: ref :: RefArrayGet(RefArraySet(A, i, x), i) == x);
+
+axiom (forall A: elements, i: int, j: int, x: ref :: i != j ==> RefArrayGet(RefArraySet(A, i, x), j) == RefArrayGet(A, j));
+
+function ArrayIndex(arr: ref, dim: int, indexAtDim: int, remainingIndexContribution: int) returns (int);
+
+axiom (forall a: ref, d: int, x: int, y: int, x': int, y': int :: ArrayIndex(a, d, x, y) == ArrayIndex(a, d, x', y') ==> x == x' && y == y');
+
+axiom (forall a: ref, T: name, i: int, r: int, heap: [ref,name]any :: $typeof(a) <: RefArray(T, r) ==> $Is(RefArrayGet(cast(heap[a, $elements]):elements, i), T));
+
+function $Rank(ref) returns (int);
+
+axiom (forall a: ref :: 1 <= $Rank(a));
+
+axiom (forall a: ref, T: name, r: int :: { $Is(a, ValueArray(T, r)) } $Is(a, ValueArray(T, r)) ==> $Rank(a) == r);
+
+axiom (forall a: ref, T: name, r: int :: { $Is(a, RefArray(T, r)) } $Is(a, RefArray(T, r)) ==> $Rank(a) == r);
+
+function $Length(ref) returns (int);
+
+axiom (forall a: ref :: { $Length(a) } 0 <= $Length(a));
+
+function $DimLength(ref, int) returns (int);
+
+axiom (forall a: ref, i: int :: 0 <= $DimLength(a, i));
+
+axiom (forall a: ref :: $Rank(a) == 1 ==> $DimLength(a, 0) == $Length(a));
+
+function $LBound(ref, int) returns (int);
+
+function $UBound(ref, int) returns (int);
+
+axiom (forall a: ref, i: int :: { $LBound(a, i) } $LBound(a, i) == 0);
+
+axiom (forall a: ref, i: int :: { $UBound(a, i) } $UBound(a, i) == $DimLength(a, i) - 1);
+
+const unique System.Array: name;
+
+axiom $IsClass(System.Array);
+
+axiom System.Array <: System.Object;
+
+function $ElementType(name) returns (name);
+
+function ValueArray(elementType: name, rank: int) returns (name);
+
+axiom (forall T: name, r: int :: { ValueArray(T, r) } ValueArray(T, r) <: System.Array);
+
+function RefArray(elementType: name, rank: int) returns (name);
+
+axiom (forall T: name, r: int :: { RefArray(T, r) } RefArray(T, r) <: System.Array);
+
+axiom (forall T: name, U: name, r: int :: U <: T ==> RefArray(U, r) <: RefArray(T, r));
+
+axiom (forall A: name, r: int :: $ElementType(ValueArray(A, r)) == A);
+
+axiom (forall A: name, r: int :: $ElementType(RefArray(A, r)) == A);
+
+axiom (forall A: name, r: int, T: name :: { T <: RefArray(A, r) } T <: RefArray(A, r) ==> T == RefArray($ElementType(T), r) && $ElementType(T) <: A);
+
+axiom (forall A: name, r: int, T: name :: { T <: ValueArray(A, r) } T <: ValueArray(A, r) ==> T == ValueArray(A, r));
+
+axiom (forall A: name, r: int, T: name :: RefArray(A, r) <: T ==> System.Array <: T || (T == RefArray($ElementType(T), r) && A <: $ElementType(T)));
+
+axiom (forall A: name, r: int, T: name :: ValueArray(A, r) <: T ==> System.Array <: T || T == ValueArray(A, r));
+
+function $ArrayPtr(elementType: name) returns (name);
+
+function $StructGet(struct, name) returns (any);
+
+function $StructSet(struct, name, any) returns (struct);
+
+axiom (forall s: struct, f: name, x: any :: $StructGet($StructSet(s, f, x), f) == x);
+
+axiom (forall s: struct, f: name, f': name, x: any :: f != f' ==> $StructGet($StructSet(s, f, x), f') == $StructGet(s, f'));
+
+function ZeroInit(s: struct, typ: name) returns (bool);
+
+function $typeof(ref) returns (name);
+
+function Implements(class: name, interface: name) returns (bool);
+
+axiom (forall T: name, J: name :: { Implements(T, J) } Implements(T, J) ==> T <: J);
+
+function InterfaceExtends(subIntf: name, superIntf: name) returns (bool);
+
+axiom (forall J: name, K: name :: { InterfaceExtends(J, K) } InterfaceExtends(J, K) ==> J <: K);
+
+function $IsClass(name) returns (bool);
+
+axiom (forall C: name :: { $IsClass(C) } $IsClass(C) ==> C <: C);
+
+function AsDirectSubClass(sub: name, base: name) returns (sub': name);
+
+function OneClassDown(sub: name, base: name) returns (directSub: name);
+
+axiom (forall A: name, B: name, C: name :: { C <: AsDirectSubClass(B, A) } C <: AsDirectSubClass(B, A) ==> OneClassDown(C, A) == B);
+
+function $IsInterface(name) returns (bool);
+
+axiom (forall J: name :: { $IsInterface(J) } $IsInterface(J) ==> J <: System.Object);
+
+function $IsValueType(name) returns (bool);
+
+axiom (forall T: name :: $IsValueType(T) ==> (forall U: name :: T <: U ==> T == U) && (forall U: name :: U <: T ==> T == U));
+
+const unique System.Object: name;
+
+axiom $IsClass(System.Object);
+
+function $IsTokenForType(struct, name) returns (bool);
+
+function TypeObject(name) returns (ref);
+
+const unique System.Type: name;
+
+axiom System.Type <: System.Object;
+
+axiom (forall T: name :: { TypeObject(T) } $IsNotNull(TypeObject(T), System.Type));
+
+function $Is(ref, name) returns (bool);
+
+axiom (forall o: ref, T: name :: { $Is(o, T) } $Is(o, T) <==> o == null || $typeof(o) <: T);
+
+function $IsNotNull(ref, name) returns (bool);
+
+axiom (forall o: ref, T: name :: { $IsNotNull(o, T) } $IsNotNull(o, T) <==> o != null && $Is(o, T));
+
+function $As(ref, name) returns (ref);
+
+axiom (forall o: ref, T: name :: $Is(o, T) ==> $As(o, T) == o);
+
+axiom (forall o: ref, T: name :: !$Is(o, T) ==> $As(o, T) == null);
+
+axiom (forall heap: [ref,name]any, o: ref, A: name, r: int :: $Is(o, RefArray(A, r)) ==> heap[o, $inv] == $typeof(o));
+
+axiom (forall heap: [ref,name]any, o: ref, A: name, r: int :: $Is(o, ValueArray(A, r)) ==> heap[o, $inv] == $typeof(o));
+
+function IsAllocated(h: [ref,name]any, o: any) returns (bool);
+
+axiom (forall h: [ref,name]any, o: ref, f: name :: { IsAllocated(h, h[o, f]) } IsHeap(h) ==> IsAllocated(h, h[o, f]));
+
+axiom (forall h: [ref,name]any, s: struct, f: name :: { IsAllocated(h, $StructGet(s, f)) } IsAllocated(h, s) ==> IsAllocated(h, $StructGet(s, f)));
+
+axiom (forall h: [ref,name]any, e: elements, i: int :: { IsAllocated(h, RefArrayGet(e, i)) } IsAllocated(h, e) ==> IsAllocated(h, RefArrayGet(e, i)));
+
+axiom (forall h: [ref,name]any, o: ref :: { h[o, $allocated] } IsAllocated(h, o) ==> cast(h[o, $allocated]):bool);
+
+axiom (forall h: [ref,name]any, c: name :: { h[ClassRepr(c), $allocated] } IsHeap(h) ==> cast(h[ClassRepr(c), $allocated]):bool);
+
+function DeclType(field: name) returns (class: name);
+
+function AsNonNullRefField(field: name, T: name) returns (f: name);
+
+function AsRefField(field: name, T: name) returns (f: name);
+
+function AsRangeField(field: name, T: name) returns (f: name);
+
+axiom (forall f: name, T: name :: { AsNonNullRefField(f, T) } AsNonNullRefField(f, T) == f ==> AsRefField(f, T) == f);
+
+axiom (forall h: [ref,name]any, o: ref, f: name, T: name :: { h[o, AsRefField(f, T)] } IsHeap(h) ==> $Is(cast(h[o, AsRefField(f, T)]):ref, T));
+
+axiom (forall h: [ref,name]any, o: ref, f: name, T: name :: { h[o, AsNonNullRefField(f, T)] } IsHeap(h) ==> cast(h[o, AsNonNullRefField(f, T)]):ref != null);
+
+axiom (forall h: [ref,name]any, o: ref, f: name, T: name :: { h[o, AsRangeField(f, T)] } IsHeap(h) ==> InRange(cast(h[o, AsRangeField(f, T)]):int, T));
+
+const unique System.String: name;
+
+axiom (forall h: [ref,name]any, s: ref :: IsHeap(h) && $typeof(s) == System.String ==> h[s, $inv] == $typeof(s) && cast(h[s, $writable]):bool);
+
+function AsOwnedField(f: name) returns (name);
+
+axiom (forall h: [ref,name]any, o: ref, f: name :: { h[o, AsOwnedField(f)] } IsHeap(h) && cast(h[o, $inv]):name <: DeclType(AsOwnedField(f)) ==> cast(h[o, AsOwnedField(f)]):ref == null || $typeof(cast(h[o, AsOwnedField(f)]):ref) == System.String || !cast(h[cast(h[o, AsOwnedField(f)]):ref, $writable]):bool);
+
+axiom (forall h: [ref,name]any, o: ref :: { h[o, $writable] } IsHeap(h) && !cast(h[o, $writable]):bool ==> cast(h[o, $inv]):name == $typeof(o));
+
+function Box(any, ref) returns (ref);
+
+function Unbox(ref) returns (any);
+
+axiom (forall x: any, p: ref :: { Unbox(Box(x, p)) } Unbox(Box(x, p)) == x);
+
+axiom (forall heap: [ref,name]any, x: any, p: ref :: { heap[Box(x, p), $inv] } IsHeap(heap) ==> heap[Box(x, p), $inv] == $typeof(Box(x, p)));
+
+function UnboxedType(ref) returns (name);
+
+function BoxTester(p: ref, typ: name) returns (ref);
+
+axiom (forall p: ref, typ: name :: { BoxTester(p, typ) } UnboxedType(p) == typ <==> BoxTester(p, typ) != null);
+
+const unique System.Int16: name;
+
+axiom $IsValueType(System.Int16);
+
+const unique System.Int32: name;
+
+axiom $IsValueType(System.Int32);
+
+const unique System.Int64: name;
+
+axiom $IsValueType(System.Int64);
+
+const unique System.Byte: name;
+
+axiom $IsValueType(System.Byte);
+
+const unique System.Int16.MinValue: int;
+
+const unique System.Int16.MaxValue: int;
+
+const unique System.Int32.MinValue: int;
+
+const unique System.Int32.MaxValue: int;
+
+const unique System.Int64.MinValue: int;
+
+const unique System.Int64.MaxValue: int;
+
+axiom System.Int64.MinValue < System.Int32.MinValue;
+
+axiom System.Int32.MinValue < System.Int16.MinValue;
+
+axiom System.Int16.MinValue < System.Int16.MaxValue;
+
+axiom System.Int16.MaxValue < System.Int32.MaxValue;
+
+axiom System.Int32.MaxValue < System.Int64.MaxValue;
+
+function InRange(i: int, T: name) returns (bool);
+
+axiom (forall i: int :: InRange(i, System.Int16) <==> System.Int16.MinValue <= i && i <= System.Int16.MaxValue);
+
+axiom (forall i: int :: InRange(i, System.Int32) <==> System.Int32.MinValue <= i && i <= System.Int32.MaxValue);
+
+axiom (forall i: int :: InRange(i, System.Int64) <==> System.Int64.MinValue <= i && i <= System.Int64.MaxValue);
+
+axiom (forall i: int :: { InRange(i, System.Byte) } InRange(i, System.Byte) <==> 0 <= i && i < 256);
+
+function $RealToInt(real) returns (int);
+
+function $IntToReal(int) returns (real);
+
+function $SizeIs(name, int) returns (bool);
+
+function $IfThenElse(bool, any, any) returns (any);
+
+axiom (forall b: bool, x: any, y: any :: { $IfThenElse(b, x, y) } b ==> $IfThenElse(b, x, y) == x);
+
+axiom (forall b: bool, x: any, y: any :: { $IfThenElse(b, x, y) } !b ==> $IfThenElse(b, x, y) == y);
+
+function #neg(int) returns (int);
+
+function #rneg(real) returns (real);
+
+function #rdiv(real, real) returns (real);
+
+function #and(int, int) returns (int);
+
+function #or(int, int) returns (int);
+
+function #xor(int, int) returns (int);
+
+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 % y } 0 <= x && 0 < y ==> 0 <= x % y && x % 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 % y } x <= 0 && 0 < y ==> 0 - y < x % y && x % 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 + y) % y } 0 <= x && 0 <= y ==> (x + y) % y == x % 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 :: { (x - y) % y } 0 <= x - y && 0 <= y ==> (x - y) % y == x % 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 i: int :: { #shl(i, 0) } #shl(i, 0) == i);
+
+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);
+
+const unique $UnknownRef: ref;
+
+const unique System.IComparable: name;
+
+const unique Microsoft.Singularity.Applications.ThreadTest: name;
+
+const unique System.Threading.Thread: name;
+
+const unique System.Collections.IEnumerable: name;
+
+const unique System.Threading.ThreadStart: name;
+
+const unique System.ICloneable: name;
+
+const unique System.MulticastDelegate: name;
+
+const unique System.Delegate: name;
+
+const unique $stringLiteral0: ref;
+
+axiom (forall heap: [ref,name]any :: { cast(heap[$stringLiteral0, $allocated]):bool } IsHeap(heap) ==> cast(heap[$stringLiteral0, $allocated]):bool) && $IsNotNull($stringLiteral0, System.String) && $Length($stringLiteral0) == 13;
+
+const unique $stringLiteral1: ref;
+
+axiom (forall heap: [ref,name]any :: { cast(heap[$stringLiteral1, $allocated]):bool } IsHeap(heap) ==> cast(heap[$stringLiteral1, $allocated]):bool) && $IsNotNull($stringLiteral1, System.String) && $Length($stringLiteral1) == 14;
+
+const unique $stringLiteral2: ref;
+
+axiom (forall heap: [ref,name]any :: { cast(heap[$stringLiteral2, $allocated]):bool } IsHeap(heap) ==> cast(heap[$stringLiteral2, $allocated]):bool) && $IsNotNull($stringLiteral2, System.String) && $Length($stringLiteral2) == 11;
+
+const unique $stringLiteral3: ref;
+
+axiom (forall heap: [ref,name]any :: { cast(heap[$stringLiteral3, $allocated]):bool } IsHeap(heap) ==> cast(heap[$stringLiteral3, $allocated]):bool) && $IsNotNull($stringLiteral3, System.String) && $Length($stringLiteral3) == 18;
+
+const unique $stringLiteral4: ref;
+
+axiom (forall heap: [ref,name]any :: { cast(heap[$stringLiteral4, $allocated]):bool } IsHeap(heap) ==> cast(heap[$stringLiteral4, $allocated]):bool) && $IsNotNull($stringLiteral4, System.String) && $Length($stringLiteral4) == 19;
+
+const unique $stringLiteral5: ref;
+
+axiom (forall heap: [ref,name]any :: { cast(heap[$stringLiteral5, $allocated]):bool } IsHeap(heap) ==> cast(heap[$stringLiteral5, $allocated]):bool) && $IsNotNull($stringLiteral5, System.String) && $Length($stringLiteral5) == 14;
+
+const unique $stringLiteral6: ref;
+
+axiom (forall heap: [ref,name]any :: { cast(heap[$stringLiteral6, $allocated]):bool } IsHeap(heap) ==> cast(heap[$stringLiteral6, $allocated]):bool) && $IsNotNull($stringLiteral6, System.String) && $Length($stringLiteral6) == 15;
+
+const unique $stringLiteral7: ref;
+
+axiom (forall heap: [ref,name]any :: { cast(heap[$stringLiteral7, $allocated]):bool } IsHeap(heap) ==> cast(heap[$stringLiteral7, $allocated]):bool) && $IsNotNull($stringLiteral7, System.String) && $Length($stringLiteral7) == 11;
+
+const unique $stringLiteral8: ref;
+
+axiom (forall heap: [ref,name]any :: { cast(heap[$stringLiteral8, $allocated]):bool } IsHeap(heap) ==> cast(heap[$stringLiteral8, $allocated]):bool) && $IsNotNull($stringLiteral8, System.String) && $Length($stringLiteral8) == 19;
+
+const unique $stringLiteral9: ref;
+
+axiom (forall heap: [ref,name]any :: { cast(heap[$stringLiteral9, $allocated]):bool } IsHeap(heap) ==> cast(heap[$stringLiteral9, $allocated]):bool) && $IsNotNull($stringLiteral9, System.String) && $Length($stringLiteral9) == 20;
+
+const unique $stringLiteral10: ref;
+
+axiom (forall heap: [ref,name]any :: { cast(heap[$stringLiteral10, $allocated]):bool } IsHeap(heap) ==> cast(heap[$stringLiteral10, $allocated]):bool) && $IsNotNull($stringLiteral10, System.String) && $Length($stringLiteral10) == 22;
+
+const unique $stringLiteral11: ref;
+
+axiom (forall heap: [ref,name]any :: { cast(heap[$stringLiteral11, $allocated]):bool } IsHeap(heap) ==> cast(heap[$stringLiteral11, $allocated]):bool) && $IsNotNull($stringLiteral11, System.String) && $Length($stringLiteral11) == 21;
+
+const unique $stringLiteral12: ref;
+
+axiom (forall heap: [ref,name]any :: { cast(heap[$stringLiteral12, $allocated]):bool } IsHeap(heap) ==> cast(heap[$stringLiteral12, $allocated]):bool) && $IsNotNull($stringLiteral12, System.String) && $Length($stringLiteral12) == 23;
+
+const unique $stringLiteral13: ref;
+
+axiom (forall heap: [ref,name]any :: { cast(heap[$stringLiteral13, $allocated]):bool } IsHeap(heap) ==> cast(heap[$stringLiteral13, $allocated]):bool) && $IsNotNull($stringLiteral13, System.String) && $Length($stringLiteral13) == 22;
+
+axiom $IsClass(Microsoft.Singularity.Applications.ThreadTest);
+
+axiom Microsoft.Singularity.Applications.ThreadTest <: System.Object && AsDirectSubClass(Microsoft.Singularity.Applications.ThreadTest, System.Object) == Microsoft.Singularity.Applications.ThreadTest;
+
+axiom (forall $K: name :: { Microsoft.Singularity.Applications.ThreadTest <: $K } Microsoft.Singularity.Applications.ThreadTest <: $K <==> Microsoft.Singularity.Applications.ThreadTest == $K || System.Object <: $K);
+
+function Inv_Microsoft.Singularity.Applications.ThreadTest(object: ref, heap: [ref,name]any) returns (result: bool);
+
+axiom (forall this: ref, heap: [ref,name]any :: { Inv_Microsoft.Singularity.Applications.ThreadTest(this, heap) } Inv_Microsoft.Singularity.Applications.ThreadTest(this, heap) <==> true);
+
+axiom (forall $o: ref, heap: [ref,name]any :: { cast(heap[$o, $inv]):name <: Microsoft.Singularity.Applications.ThreadTest } { Inv_Microsoft.Singularity.Applications.ThreadTest($o, heap) } IsHeap(heap) && cast(heap[$o, $inv]):name <: Microsoft.Singularity.Applications.ThreadTest ==> Inv_Microsoft.Singularity.Applications.ThreadTest($o, heap));
+
+procedure Microsoft.Singularity.Applications.ThreadTest.FirstThreadMethod();
+ modifies $Heap;
+ free ensures IsHeap($Heap);
+ free ensures (forall $o: ref, $f: name :: $f != $inv && $o != null && cast(old($Heap)[$o, $allocated]):bool == true && cast(old($Heap)[$o, $writable]):bool == true && (!IsStaticField($f) || !IsDirectlyModifiableField($f)) ==> old($Heap[$o, $f]) == $Heap[$o, $f]);
+ free ensures (forall $o: ref :: old($Heap)[$o, $inv] == $Heap[$o, $inv] || cast(old($Heap)[$o, $allocated]):bool != true);
+ free ensures (forall $o: ref :: cast(old($Heap)[$o, $allocated]):bool ==> cast($Heap[$o, $allocated]):bool);
+ free ensures (forall $o: ref :: old($Heap[$o, $sharingMode]) == $Heap[$o, $sharingMode]);
+
+
+
+implementation Microsoft.Singularity.Applications.ThreadTest.FirstThreadMethod()
+{
+ var stack0o: ref, i: int, stack0i: int, stack0b: bool, local1: int, $Heap$block1513$LoopPreheader: [ref,name]any;
+
+ entry:
+ assume IsHeap($Heap);
+ goto block1479;
+
+ block1479:
+ goto block1496;
+
+ block1496:
+ // ----- load constant First thread! ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(21,13)
+ stack0o := $stringLiteral0;
+ // ----- call ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(21,13)
+ call System.Console.WriteLine$System.String(stack0o);
+ // ----- load constant First thread! ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(22,13)
+ stack0o := $stringLiteral1;
+ // ----- call ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(22,13)
+ call Microsoft.Singularity.DebugStub.Print$System.String(stack0o);
+ // ----- load constant 0 ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(24,18)
+ i := 0;
+ goto block1513$LoopPreheader;
+
+ block1513:
+ // ----- default loop invariant: $inv field ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(24,29)
+ assert (forall $o: ref :: $Heap$block1513$LoopPreheader[$o, $inv] == $Heap[$o, $inv] || cast($Heap$block1513$LoopPreheader[$o, $allocated]):bool != true);
+ assert (forall $o: ref :: cast($Heap$block1513$LoopPreheader[$o, $allocated]):bool ==> cast($Heap[$o, $allocated]):bool);
+ // ----- load constant 10 ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(24,29)
+ stack0i := 10;
+ // ----- binary operator ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(24,29)
+ stack0b := i >= stack0i;
+ // ----- branch ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(24,29)
+ goto true1513to1547, false1513to1530;
+
+ true1513to1547:
+ assume stack0b == true;
+ goto block1547;
+
+ false1513to1530:
+ assume stack0b == false;
+ goto block1530;
+
+ block1547:
+ // ----- load constant First thread done! ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(29,13)
+ stack0o := $stringLiteral3;
+ // ----- call ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(29,13)
+ call System.Console.WriteLine$System.String(stack0o);
+ // ----- load constant First thread done! ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(30,13)
+ stack0o := $stringLiteral4;
+ // ----- call ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(30,13)
+ call Microsoft.Singularity.DebugStub.Print$System.String(stack0o);
+ // ----- return ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(31,10)
+ return;
+
+ block1530:
+ // ----- load constant [0] ... ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(25,17)
+ stack0o := $stringLiteral2;
+ // ----- call ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(25,17)
+ // Commented out, to avoid problems with the theorem prover nondeterministically choosing this error over the one 12 lines above: call System.Console.WriteLine$System.String(stack0o);
+ // ----- call ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(26,17)
+ call System.Threading.Thread.Yield();
+ // ----- copy ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(24,37)
+ local1 := i;
+ // ----- load constant 1
+ stack0i := 1;
+ // ----- binary operator
+ stack0i := local1 + stack0i;
+ // ----- copy
+ i := stack0i;
+ // ----- copy
+ stack0i := local1;
+ // ----- branch
+ goto block1513;
+
+ block1513$LoopPreheader:
+ $Heap$block1513$LoopPreheader := $Heap;
+ goto block1513;
+
+}
+
+
+
+axiom $IsClass(System.String);
+
+axiom System.String <: System.Object && AsDirectSubClass(System.String, System.Object) == System.String;
+
+axiom $IsInterface(System.IComparable);
+
+axiom (forall $K: name :: { System.IComparable <: $K } System.IComparable <: $K <==> System.IComparable == $K || System.Object == $K);
+
+axiom Implements(System.String, System.IComparable);
+
+axiom $IsInterface(System.ICloneable);
+
+axiom (forall $K: name :: { System.ICloneable <: $K } System.ICloneable <: $K <==> System.ICloneable == $K || System.Object == $K);
+
+axiom Implements(System.String, System.ICloneable);
+
+axiom $IsInterface(System.Collections.IEnumerable);
+
+axiom (forall $K: name :: { System.Collections.IEnumerable <: $K } System.Collections.IEnumerable <: $K <==> System.Collections.IEnumerable == $K || System.Object == $K);
+
+axiom Implements(System.String, System.Collections.IEnumerable);
+
+axiom (forall $K: name :: { System.String <: $K } System.String <: $K <==> System.String == $K || System.Object <: $K || System.IComparable <: $K || System.ICloneable <: $K || System.Collections.IEnumerable <: $K);
+
+axiom (forall $U: name :: { $U <: System.String } $U <: System.String ==> $U == System.String);
+
+function Inv_System.String(object: ref, heap: [ref,name]any) returns (result: bool);
+
+axiom (forall this: ref, heap: [ref,name]any :: { Inv_System.String(this, heap) } Inv_System.String(this, heap) <==> true);
+
+axiom (forall $o: ref, heap: [ref,name]any :: { cast(heap[$o, $inv]):name <: System.String } { Inv_System.String($o, heap) } IsHeap(heap) && cast(heap[$o, $inv]):name <: System.String ==> Inv_System.String($o, heap));
+
+procedure System.Console.WriteLine$System.String(value$in: ref);
+ requires value$in == null || (cast($Heap[value$in, $writable]):bool == true && cast($Heap[value$in, $inv]):name == $typeof(value$in));
+ modifies $Heap;
+ free ensures IsHeap($Heap);
+ free ensures (forall $o: ref, $f: name :: $f != $inv && $o != null && cast(old($Heap)[$o, $allocated]):bool == true && cast(old($Heap)[$o, $writable]):bool == true && (!IsStaticField($f) || !IsDirectlyModifiableField($f)) ==> old($Heap[$o, $f]) == $Heap[$o, $f]);
+ free ensures (forall $o: ref :: old($Heap)[$o, $inv] == $Heap[$o, $inv] || cast(old($Heap)[$o, $allocated]):bool != true);
+ free ensures (forall $o: ref :: cast(old($Heap)[$o, $allocated]):bool ==> cast($Heap[$o, $allocated]):bool);
+ free ensures (forall $o: ref :: old($Heap[$o, $sharingMode]) == $Heap[$o, $sharingMode]);
+
+
+
+procedure Microsoft.Singularity.DebugStub.Print$System.String(value$in: ref);
+ requires value$in == null || (cast($Heap[value$in, $writable]):bool == true && cast($Heap[value$in, $inv]):name == $typeof(value$in));
+ modifies $Heap;
+ free ensures IsHeap($Heap);
+ free ensures (forall $o: ref, $f: name :: $f != $inv && $o != null && cast(old($Heap)[$o, $allocated]):bool == true && cast(old($Heap)[$o, $writable]):bool == true && (!IsStaticField($f) || !IsDirectlyModifiableField($f)) ==> old($Heap[$o, $f]) == $Heap[$o, $f]);
+ free ensures (forall $o: ref :: old($Heap)[$o, $inv] == $Heap[$o, $inv] || cast(old($Heap)[$o, $allocated]):bool != true);
+ free ensures (forall $o: ref :: cast(old($Heap)[$o, $allocated]):bool ==> cast($Heap[$o, $allocated]):bool);
+ free ensures (forall $o: ref :: old($Heap[$o, $sharingMode]) == $Heap[$o, $sharingMode]);
+
+
+
+procedure System.Threading.Thread.Yield();
+ modifies $Heap;
+ free ensures IsHeap($Heap);
+ free ensures (forall $o: ref, $f: name :: $f != $inv && $o != null && cast(old($Heap)[$o, $allocated]):bool == true && cast(old($Heap)[$o, $writable]):bool == true && (!IsStaticField($f) || !IsDirectlyModifiableField($f)) ==> old($Heap[$o, $f]) == $Heap[$o, $f]);
+ free ensures (forall $o: ref :: old($Heap)[$o, $inv] == $Heap[$o, $inv] || cast(old($Heap)[$o, $allocated]):bool != true);
+ free ensures (forall $o: ref :: cast(old($Heap)[$o, $allocated]):bool ==> cast($Heap[$o, $allocated]):bool);
+ free ensures (forall $o: ref :: old($Heap[$o, $sharingMode]) == $Heap[$o, $sharingMode]);
+
+
+
+procedure Microsoft.Singularity.Applications.ThreadTest.SecondThreadMethod();
+ modifies $Heap;
+ free ensures IsHeap($Heap);
+ free ensures (forall $o: ref, $f: name :: $f != $inv && $o != null && cast(old($Heap)[$o, $allocated]):bool == true && cast(old($Heap)[$o, $writable]):bool == true && (!IsStaticField($f) || !IsDirectlyModifiableField($f)) ==> old($Heap[$o, $f]) == $Heap[$o, $f]);
+ free ensures (forall $o: ref :: old($Heap)[$o, $inv] == $Heap[$o, $inv] || cast(old($Heap)[$o, $allocated]):bool != true);
+ free ensures (forall $o: ref :: cast(old($Heap)[$o, $allocated]):bool ==> cast($Heap[$o, $allocated]):bool);
+ free ensures (forall $o: ref :: old($Heap[$o, $sharingMode]) == $Heap[$o, $sharingMode]);
+
+
+
+implementation Microsoft.Singularity.Applications.ThreadTest.SecondThreadMethod()
+{
+ var stack0o: ref, i: int, stack0i: int, stack0b: bool, local1: int, $Heap$block2516$LoopPreheader: [ref,name]any;
+
+ entry:
+ assume IsHeap($Heap);
+ goto block2482;
+
+ block2482:
+ goto block2499;
+
+ block2499:
+ // ----- load constant Second thread! ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(35,13)
+ stack0o := $stringLiteral5;
+ // ----- call ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(35,13)
+ call System.Console.WriteLine$System.String(stack0o);
+ // ----- load constant Second thread! ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(36,13)
+ stack0o := $stringLiteral6;
+ // ----- call ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(36,13)
+ call Microsoft.Singularity.DebugStub.Print$System.String(stack0o);
+ // ----- load constant 0 ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(38,18)
+ i := 0;
+ goto block2516$LoopPreheader;
+
+ block2516:
+ // ----- default loop invariant: $inv field ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(38,29)
+ assert (forall $o: ref :: $Heap$block2516$LoopPreheader[$o, $inv] == $Heap[$o, $inv] || cast($Heap$block2516$LoopPreheader[$o, $allocated]):bool != true);
+ assert (forall $o: ref :: cast($Heap$block2516$LoopPreheader[$o, $allocated]):bool ==> cast($Heap[$o, $allocated]):bool);
+ // ----- load constant 10 ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(38,29)
+ stack0i := 10;
+ // ----- binary operator ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(38,29)
+ stack0b := i >= stack0i;
+ // ----- branch ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(38,29)
+ goto true2516to2550, false2516to2533;
+
+ true2516to2550:
+ assume stack0b == true;
+ goto block2550;
+
+ false2516to2533:
+ assume stack0b == false;
+ goto block2533;
+
+ block2550:
+ // ----- load constant Second thread done! ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(44,13)
+ stack0o := $stringLiteral8;
+ // ----- call ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(44,13)
+ call System.Console.WriteLine$System.String(stack0o);
+ // ----- load constant Second thread done! ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(45,13)
+ stack0o := $stringLiteral9;
+ // ----- call ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(45,13)
+ call Microsoft.Singularity.DebugStub.Print$System.String(stack0o);
+ // ----- return ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(46,10)
+ return;
+
+ block2533:
+ // ----- load constant ... [1] ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(40,17)
+ stack0o := $stringLiteral7;
+ // ----- call ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(40,17)
+ // Commented out, to avoid problems with the theorem prover nondeterministically choosing this error over the one 12 lines above: call System.Console.WriteLine$System.String(stack0o);
+ // ----- call ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(41,17)
+ call System.Threading.Thread.Yield();
+ // ----- copy ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(38,37)
+ local1 := i;
+ // ----- load constant 1
+ stack0i := 1;
+ // ----- binary operator
+ stack0i := local1 + stack0i;
+ // ----- copy
+ i := stack0i;
+ // ----- copy
+ stack0i := local1;
+ // ----- branch
+ goto block2516;
+
+ block2516$LoopPreheader:
+ $Heap$block2516$LoopPreheader := $Heap;
+ goto block2516;
+
+}
+
+
+
+procedure Microsoft.Singularity.Applications.ThreadTest.Main$System.String.array(args$in: ref) returns ($result: int);
+ requires args$in == null || (cast($Heap[args$in, $writable]):bool == true && cast($Heap[args$in, $inv]):name == $typeof(args$in));
+ modifies $Heap;
+ free ensures IsHeap($Heap);
+ free ensures IsAllocated($Heap, $result);
+ free ensures (forall $o: ref, $f: name :: $f != $inv && $o != null && cast(old($Heap)[$o, $allocated]):bool == true && cast(old($Heap)[$o, $writable]):bool == true && (!IsStaticField($f) || !IsDirectlyModifiableField($f)) ==> old($Heap[$o, $f]) == $Heap[$o, $f]);
+ free ensures (forall $o: ref :: old($Heap)[$o, $inv] == $Heap[$o, $inv] || cast(old($Heap)[$o, $allocated]):bool != true);
+ free ensures (forall $o: ref :: cast(old($Heap)[$o, $allocated]):bool ==> cast($Heap[$o, $allocated]):bool);
+ free ensures (forall $o: ref :: old($Heap[$o, $sharingMode]) == $Heap[$o, $sharingMode]);
+
+
+
+implementation Microsoft.Singularity.Applications.ThreadTest.Main$System.String.array(args$in: ref) returns ($result: int)
+{
+ var args: ref, stack0o: ref, stack1o: ref, stack50000o: ref, t1: ref, t2: ref, i: int, stack0i: int, stack0b: bool, local3: int, return.value: int, SS$Display.Return.Local: int, $Heap$block3825$LoopPreheader: [ref,name]any;
+
+ entry:
+ assume IsHeap($Heap);
+ args := args$in;
+ assume $Is(args, RefArray(System.String, 1));
+ assume cast($Heap[args$in, $allocated]):bool == true;
+ goto block3791;
+
+ block3791:
+ goto block3808;
+
+ block3808:
+ stack0o := null;
+ // ----- load function ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(51,13)
+ havoc stack1o;
+ // ----- new object ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(51,13)
+ havoc stack50000o;
+ assume cast($Heap[stack50000o, $allocated]):bool == false && stack50000o != null && $typeof(stack50000o) == System.Threading.ThreadStart;
+ $Heap[stack50000o, $allocated] := true;
+ // ----- call ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(51,13)
+ assert stack50000o != null;
+ call System.Threading.ThreadStart..ctor$System.Object$System.IntPtr(stack50000o, stack0o, stack1o);
+ // ----- copy ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(51,13)
+ stack0o := stack50000o;
+ // ----- new object ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(51,13)
+ havoc stack50000o;
+ assume cast($Heap[stack50000o, $allocated]):bool == false && stack50000o != null && $typeof(stack50000o) == System.Threading.Thread;
+ $Heap[stack50000o, $allocated] := true;
+ // ----- call ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(51,13)
+ assert stack50000o != null;
+ call System.Threading.Thread..ctor$System.Threading.ThreadStart(stack50000o, stack0o);
+ // ----- copy ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(51,13)
+ stack0o := stack50000o;
+ // ----- copy ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(51,13)
+ t1 := stack0o;
+ stack0o := null;
+ // ----- load function ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(52,13)
+ havoc stack1o;
+ // ----- new object ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(52,13)
+ havoc stack50000o;
+ assume cast($Heap[stack50000o, $allocated]):bool == false && stack50000o != null && $typeof(stack50000o) == System.Threading.ThreadStart;
+ $Heap[stack50000o, $allocated] := true;
+ // ----- call ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(52,13)
+ assert stack50000o != null;
+ call System.Threading.ThreadStart..ctor$System.Object$System.IntPtr(stack50000o, stack0o, stack1o);
+ // ----- copy ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(52,13)
+ stack0o := stack50000o;
+ // ----- new object ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(52,13)
+ havoc stack50000o;
+ assume cast($Heap[stack50000o, $allocated]):bool == false && stack50000o != null && $typeof(stack50000o) == System.Threading.Thread;
+ $Heap[stack50000o, $allocated] := true;
+ // ----- call ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(52,13)
+ assert stack50000o != null;
+ call System.Threading.Thread..ctor$System.Threading.ThreadStart(stack50000o, stack0o);
+ // ----- copy ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(52,13)
+ stack0o := stack50000o;
+ // ----- copy ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(52,13)
+ t2 := stack0o;
+ // ----- load constant Starting first thread. ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(54,13)
+ stack0o := $stringLiteral10;
+ // ----- call ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(54,13)
+ call System.Console.WriteLine$System.String(stack0o);
+ // ----- call ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(55,13)
+ assert t1 != null;
+ call System.Threading.Thread.Start(t1);
+ // ----- load constant Started first thread. ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(56,13)
+ stack0o := $stringLiteral11;
+ // ----- call ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(56,13)
+ call System.Console.WriteLine$System.String(stack0o);
+ // ----- load constant Starting second thread. ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(58,13)
+ stack0o := $stringLiteral12;
+ // ----- call ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(58,13)
+ call System.Console.WriteLine$System.String(stack0o);
+ // ----- call ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(59,13)
+ assert t2 != null;
+ call System.Threading.Thread.Start(t2);
+ // ----- load constant Started second thread. ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(60,13)
+ stack0o := $stringLiteral13;
+ // ----- call ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(60,13)
+ call System.Console.WriteLine$System.String(stack0o);
+ // ----- load constant 0 ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(62,18)
+ i := 0;
+ goto block3825$LoopPreheader;
+
+ block3825:
+ // ----- default loop invariant: $inv field ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(62,29)
+ assert (forall $o: ref :: $Heap$block3825$LoopPreheader[$o, $inv] == $Heap[$o, $inv] || cast($Heap$block3825$LoopPreheader[$o, $allocated]):bool != true);
+ assert (forall $o: ref :: cast($Heap$block3825$LoopPreheader[$o, $allocated]):bool ==> cast($Heap[$o, $allocated]):bool);
+ // ----- load constant 30 ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(62,29)
+ stack0i := 30;
+ // ----- binary operator ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(62,29)
+ stack0b := i >= stack0i;
+ // ----- branch ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(62,29)
+ goto true3825to3859, false3825to3842;
+
+ true3825to3859:
+ assume stack0b == true;
+ goto block3859;
+
+ false3825to3842:
+ assume stack0b == false;
+ goto block3842;
+
+ block3859:
+ // ----- load constant 0 ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(66,13)
+ return.value := 0;
+ // ----- branch
+ goto block3876;
+
+ block3842:
+ // ----- call ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(64,17)
+ call System.Threading.Thread.Yield();
+ // ----- copy ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(62,37)
+ local3 := i;
+ // ----- load constant 1
+ stack0i := 1;
+ // ----- binary operator
+ stack0i := local3 + stack0i;
+ // ----- copy
+ i := stack0i;
+ // ----- copy
+ stack0i := local3;
+ // ----- branch
+ goto block3825;
+
+ block3876:
+ // ----- copy
+ SS$Display.Return.Local := return.value;
+ // ----- copy ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(67,10)
+ stack0i := return.value;
+ // ----- return ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(67,10)
+ $result := stack0i;
+ return;
+
+ block3825$LoopPreheader:
+ $Heap$block3825$LoopPreheader := $Heap;
+ goto block3825;
+
+}
+
+
+
+axiom $IsClass(System.Threading.ThreadStart);
+
+axiom $IsClass(System.MulticastDelegate);
+
+axiom $IsClass(System.Delegate);
+
+axiom System.Delegate <: System.Object && AsDirectSubClass(System.Delegate, System.Object) == System.Delegate;
+
+axiom Implements(System.Delegate, System.ICloneable);
+
+axiom (forall $K: name :: { System.Delegate <: $K } System.Delegate <: $K <==> System.Delegate == $K || System.Object <: $K || System.ICloneable <: $K);
+
+function Inv_System.Delegate(object: ref, heap: [ref,name]any) returns (result: bool);
+
+axiom (forall this: ref, heap: [ref,name]any :: { Inv_System.Delegate(this, heap) } Inv_System.Delegate(this, heap) <==> true);
+
+axiom (forall $o: ref, heap: [ref,name]any :: { cast(heap[$o, $inv]):name <: System.Delegate } { Inv_System.Delegate($o, heap) } IsHeap(heap) && cast(heap[$o, $inv]):name <: System.Delegate ==> Inv_System.Delegate($o, heap));
+
+axiom System.MulticastDelegate <: System.Delegate && AsDirectSubClass(System.MulticastDelegate, System.Delegate) == System.MulticastDelegate;
+
+axiom (forall $K: name :: { System.MulticastDelegate <: $K } System.MulticastDelegate <: $K <==> System.MulticastDelegate == $K || System.Delegate <: $K);
+
+function Inv_System.MulticastDelegate(object: ref, heap: [ref,name]any) returns (result: bool);
+
+axiom (forall this: ref, heap: [ref,name]any :: { Inv_System.MulticastDelegate(this, heap) } Inv_System.MulticastDelegate(this, heap) <==> true);
+
+axiom (forall $o: ref, heap: [ref,name]any :: { cast(heap[$o, $inv]):name <: System.MulticastDelegate } { Inv_System.MulticastDelegate($o, heap) } IsHeap(heap) && cast(heap[$o, $inv]):name <: System.MulticastDelegate ==> Inv_System.MulticastDelegate($o, heap));
+
+axiom System.Threading.ThreadStart <: System.MulticastDelegate && AsDirectSubClass(System.Threading.ThreadStart, System.MulticastDelegate) == System.Threading.ThreadStart;
+
+axiom (forall $K: name :: { System.Threading.ThreadStart <: $K } System.Threading.ThreadStart <: $K <==> System.Threading.ThreadStart == $K || System.MulticastDelegate <: $K);
+
+axiom (forall $U: name :: { $U <: System.Threading.ThreadStart } $U <: System.Threading.ThreadStart ==> $U == System.Threading.ThreadStart);
+
+function Inv_System.Threading.ThreadStart(object: ref, heap: [ref,name]any) returns (result: bool);
+
+axiom (forall this: ref, heap: [ref,name]any :: { Inv_System.Threading.ThreadStart(this, heap) } Inv_System.Threading.ThreadStart(this, heap) <==> true);
+
+axiom (forall $o: ref, heap: [ref,name]any :: { cast(heap[$o, $inv]):name <: System.Threading.ThreadStart } { Inv_System.Threading.ThreadStart($o, heap) } IsHeap(heap) && cast(heap[$o, $inv]):name <: System.Threading.ThreadStart ==> Inv_System.Threading.ThreadStart($o, heap));
+
+procedure System.Threading.ThreadStart..ctor$System.Object$System.IntPtr(this: ref, object$in: ref, method$in: ref);
+ modifies $Heap;
+ free ensures IsHeap($Heap);
+ free ensures (forall $o: ref, $f: name :: $f != $inv && $o != null && cast(old($Heap)[$o, $allocated]):bool == true && cast(old($Heap)[$o, $writable]):bool == true && (!IsStaticField($f) || !IsDirectlyModifiableField($f)) ==> old($Heap[$o, $f]) == $Heap[$o, $f]);
+ free ensures (forall $o: ref :: old($Heap)[$o, $inv] == $Heap[$o, $inv] || cast(old($Heap)[$o, $allocated]):bool != true);
+ free ensures (forall $o: ref :: cast(old($Heap)[$o, $allocated]):bool ==> cast($Heap[$o, $allocated]):bool);
+ free ensures (forall $o: ref :: old($Heap[$o, $sharingMode]) == $Heap[$o, $sharingMode]);
+ ensures cast($Heap[this, $writable]):bool == true && cast($Heap[this, $inv]):name == System.Threading.ThreadStart;
+
+
+
+axiom $IsClass(System.Threading.Thread);
+
+axiom System.Threading.Thread <: System.Object && AsDirectSubClass(System.Threading.Thread, System.Object) == System.Threading.Thread;
+
+axiom (forall $K: name :: { System.Threading.Thread <: $K } System.Threading.Thread <: $K <==> System.Threading.Thread == $K || System.Object <: $K);
+
+axiom (forall $U: name :: { $U <: System.Threading.Thread } $U <: System.Threading.Thread ==> $U == System.Threading.Thread);
+
+function Inv_System.Threading.Thread(object: ref, heap: [ref,name]any) returns (result: bool);
+
+axiom (forall this: ref, heap: [ref,name]any :: { Inv_System.Threading.Thread(this, heap) } Inv_System.Threading.Thread(this, heap) <==> true);
+
+axiom (forall $o: ref, heap: [ref,name]any :: { cast(heap[$o, $inv]):name <: System.Threading.Thread } { Inv_System.Threading.Thread($o, heap) } IsHeap(heap) && cast(heap[$o, $inv]):name <: System.Threading.Thread ==> Inv_System.Threading.Thread($o, heap));
+
+procedure System.Threading.Thread..ctor$System.Threading.ThreadStart(this: ref, start$in: ref);
+ requires start$in == null || (cast($Heap[start$in, $writable]):bool == true && cast($Heap[start$in, $inv]):name == $typeof(start$in));
+ modifies $Heap;
+ free ensures IsHeap($Heap);
+ free ensures (forall $o: ref, $f: name :: $f != $inv && $o != null && cast(old($Heap)[$o, $allocated]):bool == true && cast(old($Heap)[$o, $writable]):bool == true && (!IsStaticField($f) || !IsDirectlyModifiableField($f)) && ($o != this || !(System.Threading.Thread <: DeclType($f))) ==> old($Heap[$o, $f]) == $Heap[$o, $f]);
+ free ensures (forall $o: ref :: $o == this || old($Heap)[$o, $inv] == $Heap[$o, $inv] || cast(old($Heap)[$o, $allocated]):bool != true);
+ free ensures (forall $o: ref :: cast(old($Heap)[$o, $allocated]):bool ==> cast($Heap[$o, $allocated]):bool);
+ free ensures (forall $o: ref :: $o == this || old($Heap[$o, $sharingMode]) == $Heap[$o, $sharingMode]);
+ ensures cast($Heap[this, $writable]):bool == true && cast($Heap[this, $inv]):name == System.Threading.Thread;
+ ensures $Heap[this, $sharingMode] == $SharingMode_Unshared;
+
+
+
+procedure System.Threading.Thread.Start(this: ref);
+ requires cast($Heap[this, $writable]):bool == true && cast($Heap[this, $inv]):name == $typeof(this);
+ modifies $Heap;
+ free ensures IsHeap($Heap);
+ free ensures (forall $o: ref, $f: name :: $f != $inv && $o != null && cast(old($Heap)[$o, $allocated]):bool == true && cast(old($Heap)[$o, $writable]):bool == true && (!IsStaticField($f) || !IsDirectlyModifiableField($f)) ==> old($Heap[$o, $f]) == $Heap[$o, $f]);
+ free ensures (forall $o: ref :: old($Heap)[$o, $inv] == $Heap[$o, $inv] || cast(old($Heap)[$o, $allocated]):bool != true);
+ free ensures (forall $o: ref :: cast(old($Heap)[$o, $allocated]):bool ==> cast($Heap[$o, $allocated]):bool);
+ free ensures (forall $o: ref :: old($Heap[$o, $sharingMode]) == $Heap[$o, $sharingMode]);
+
+
+
+procedure Microsoft.Singularity.Applications.ThreadTest..ctor(this: ref);
+ modifies $Heap;
+ free ensures IsHeap($Heap);
+ free ensures (forall $o: ref, $f: name :: $f != $inv && $o != null && cast(old($Heap)[$o, $allocated]):bool == true && cast(old($Heap)[$o, $writable]):bool == true && (!IsStaticField($f) || !IsDirectlyModifiableField($f)) && ($o != this || !(Microsoft.Singularity.Applications.ThreadTest <: DeclType($f))) ==> old($Heap[$o, $f]) == $Heap[$o, $f]);
+ free ensures (forall $o: ref :: $o == this || old($Heap)[$o, $inv] == $Heap[$o, $inv] || cast(old($Heap)[$o, $allocated]):bool != true);
+ free ensures (forall $o: ref :: cast(old($Heap)[$o, $allocated]):bool ==> cast($Heap[$o, $allocated]):bool);
+ free ensures (forall $o: ref :: $o == this || old($Heap[$o, $sharingMode]) == $Heap[$o, $sharingMode]);
+ ensures cast($Heap[this, $writable]):bool == true && cast($Heap[this, $inv]):name == Microsoft.Singularity.Applications.ThreadTest;
+ ensures $Heap[this, $sharingMode] == $SharingMode_Unshared;
+
+
+
+implementation Microsoft.Singularity.Applications.ThreadTest..ctor(this: ref)
+{
+
+ entry:
+ assume IsHeap($Heap);
+ assume $IsNotNull(this, Microsoft.Singularity.Applications.ThreadTest);
+ assume cast($Heap[this, $allocated]):bool == true;
+ assume cast($Heap[this, $writable]):bool == true && cast($Heap[this, $inv]):name == System.Object;
+ goto block4777;
+
+ block4777:
+ goto block4794;
+
+ block4794:
+ // ----- call ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(17,18)
+ assert this != null;
+ call System.Object..ctor(this);
+ // ----- return ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(17,28)
+ assert this != null;
+ assert cast($Heap[this, $writable]):bool == true && System.Object <: cast($Heap[this, $inv]):name;
+ assert cast($Heap[this, $writable]):bool == true && cast($Heap[this, $inv]):name == System.Object;
+ assert Inv_Microsoft.Singularity.Applications.ThreadTest(this, $Heap);
+ $Heap[this, $inv] := Microsoft.Singularity.Applications.ThreadTest;
+ return;
+
+}
+
+
+
+procedure System.Object..ctor(this: ref);
+ modifies $Heap;
+ free ensures IsHeap($Heap);
+ free ensures (forall $o: ref, $f: name :: $f != $inv && $o != null && cast(old($Heap)[$o, $allocated]):bool == true && cast(old($Heap)[$o, $writable]):bool == true && (!IsStaticField($f) || !IsDirectlyModifiableField($f)) && ($o != this || !(System.Object <: DeclType($f))) ==> old($Heap[$o, $f]) == $Heap[$o, $f]);
+ free ensures (forall $o: ref :: $o == this || old($Heap)[$o, $inv] == $Heap[$o, $inv] || cast(old($Heap)[$o, $allocated]):bool != true);
+ free ensures (forall $o: ref :: cast(old($Heap)[$o, $allocated]):bool ==> cast($Heap[$o, $allocated]):bool);
+ free ensures (forall $o: ref :: $o == this || old($Heap[$o, $sharingMode]) == $Heap[$o, $sharingMode]);
+ ensures cast($Heap[this, $writable]):bool == true && cast($Heap[this, $inv]):name == System.Object;
+ ensures $Heap[this, $sharingMode] == $SharingMode_Unshared;
+
+
+
+type ref, name, any;
+const null : ref;
diff --git a/Test/test2/strings-where.bpl b/Test/test2/strings-where.bpl
new file mode 100644
index 00000000..da529b84
--- /dev/null
+++ b/Test/test2/strings-where.bpl
@@ -0,0 +1,995 @@
+type real;
+
+type elements;
+
+type struct;
+
+var $Heap: [ref,name]any where IsHeap($Heap);
+function cast<S,T>(S) returns (T);
+function IsHeap(h: [ref,name]any) returns (bool);
+
+const unique $allocated: name;
+
+const unique $elements: name;
+
+const unique $inv: name;
+
+const unique $writable: name;
+
+const unique $sharingMode: name;
+
+const unique $SharingMode_Unshared: name;
+
+const unique $SharingMode_LockProtected: name;
+
+function ClassRepr(class: name) returns (ref);
+
+axiom (forall c0: name, c1: name :: c0 != c1 ==> ClassRepr(c0) != ClassRepr(c1));
+
+axiom (forall T: name :: !($typeof(ClassRepr(T)) <: System.Object));
+
+axiom (forall T: name :: ClassRepr(T) != null);
+
+axiom (forall T: name, h: [ref,name]any :: { h[ClassRepr(T), $writable] } IsHeap(h) ==> cast(h[ClassRepr(T), $writable]):bool);
+
+function IsDirectlyModifiableField(f: name) returns (bool);
+
+axiom !IsDirectlyModifiableField($allocated);
+
+axiom IsDirectlyModifiableField($elements);
+
+axiom !IsDirectlyModifiableField($inv);
+
+axiom !IsDirectlyModifiableField($writable);
+
+function IsStaticField(f: name) returns (bool);
+
+axiom !IsStaticField($allocated);
+
+axiom !IsStaticField($elements);
+
+axiom !IsStaticField($inv);
+
+axiom !IsStaticField($writable);
+
+function ValueArrayGet(elements, int) returns (any);
+
+function ValueArraySet(elements, int, any) returns (elements);
+
+function RefArrayGet(elements, int) returns (ref);
+
+function RefArraySet(elements, int, ref) returns (elements);
+
+axiom (forall A: elements, i: int, x: any :: ValueArrayGet(ValueArraySet(A, i, x), i) == x);
+
+axiom (forall A: elements, i: int, j: int, x: any :: i != j ==> ValueArrayGet(ValueArraySet(A, i, x), j) == ValueArrayGet(A, j));
+
+axiom (forall A: elements, i: int, x: ref :: RefArrayGet(RefArraySet(A, i, x), i) == x);
+
+axiom (forall A: elements, i: int, j: int, x: ref :: i != j ==> RefArrayGet(RefArraySet(A, i, x), j) == RefArrayGet(A, j));
+
+function ArrayIndex(arr: ref, dim: int, indexAtDim: int, remainingIndexContribution: int) returns (int);
+
+axiom (forall a: ref, d: int, x: int, y: int, x': int, y': int :: ArrayIndex(a, d, x, y) == ArrayIndex(a, d, x', y') ==> x == x' && y == y');
+
+axiom (forall a: ref, T: name, i: int, r: int, heap: [ref,name]any :: $typeof(a) <: RefArray(T, r) ==> $Is(RefArrayGet(cast(heap[a, $elements]):elements, i), T));
+
+function $Rank(ref) returns (int);
+
+axiom (forall a: ref :: 1 <= $Rank(a));
+
+axiom (forall a: ref, T: name, r: int :: { $Is(a, ValueArray(T, r)) } $Is(a, ValueArray(T, r)) ==> $Rank(a) == r);
+
+axiom (forall a: ref, T: name, r: int :: { $Is(a, RefArray(T, r)) } $Is(a, RefArray(T, r)) ==> $Rank(a) == r);
+
+function $Length(ref) returns (int);
+
+axiom (forall a: ref :: { $Length(a) } 0 <= $Length(a));
+
+function $DimLength(ref, int) returns (int);
+
+axiom (forall a: ref, i: int :: 0 <= $DimLength(a, i));
+
+axiom (forall a: ref :: $Rank(a) == 1 ==> $DimLength(a, 0) == $Length(a));
+
+function $LBound(ref, int) returns (int);
+
+function $UBound(ref, int) returns (int);
+
+axiom (forall a: ref, i: int :: { $LBound(a, i) } $LBound(a, i) == 0);
+
+axiom (forall a: ref, i: int :: { $UBound(a, i) } $UBound(a, i) == $DimLength(a, i) - 1);
+
+const unique System.Array: name;
+
+axiom $IsClass(System.Array);
+
+axiom System.Array <: System.Object;
+
+function $ElementType(name) returns (name);
+
+function ValueArray(elementType: name, rank: int) returns (name);
+
+axiom (forall T: name, r: int :: { ValueArray(T, r) } ValueArray(T, r) <: System.Array);
+
+function RefArray(elementType: name, rank: int) returns (name);
+
+axiom (forall T: name, r: int :: { RefArray(T, r) } RefArray(T, r) <: System.Array);
+
+axiom (forall T: name, U: name, r: int :: U <: T ==> RefArray(U, r) <: RefArray(T, r));
+
+axiom (forall A: name, r: int :: $ElementType(ValueArray(A, r)) == A);
+
+axiom (forall A: name, r: int :: $ElementType(RefArray(A, r)) == A);
+
+axiom (forall A: name, r: int, T: name :: { T <: RefArray(A, r) } T <: RefArray(A, r) ==> T == RefArray($ElementType(T), r) && $ElementType(T) <: A);
+
+axiom (forall A: name, r: int, T: name :: { T <: ValueArray(A, r) } T <: ValueArray(A, r) ==> T == ValueArray(A, r));
+
+axiom (forall A: name, r: int, T: name :: RefArray(A, r) <: T ==> System.Array <: T || (T == RefArray($ElementType(T), r) && A <: $ElementType(T)));
+
+axiom (forall A: name, r: int, T: name :: ValueArray(A, r) <: T ==> System.Array <: T || T == ValueArray(A, r));
+
+function $ArrayPtr(elementType: name) returns (name);
+
+function $StructGet(struct, name) returns (any);
+
+function $StructSet(struct, name, any) returns (struct);
+
+axiom (forall s: struct, f: name, x: any :: $StructGet($StructSet(s, f, x), f) == x);
+
+axiom (forall s: struct, f: name, f': name, x: any :: f != f' ==> $StructGet($StructSet(s, f, x), f') == $StructGet(s, f'));
+
+function ZeroInit(s: struct, typ: name) returns (bool);
+
+function $typeof(ref) returns (name);
+
+function Implements(class: name, interface: name) returns (bool);
+
+axiom (forall T: name, J: name :: { Implements(T, J) } Implements(T, J) ==> T <: J);
+
+function InterfaceExtends(subIntf: name, superIntf: name) returns (bool);
+
+axiom (forall J: name, K: name :: { InterfaceExtends(J, K) } InterfaceExtends(J, K) ==> J <: K);
+
+function $IsClass(name) returns (bool);
+
+axiom (forall C: name :: { $IsClass(C) } $IsClass(C) ==> C <: C);
+
+function AsDirectSubClass(sub: name, base: name) returns (sub': name);
+
+function OneClassDown(sub: name, base: name) returns (directSub: name);
+
+axiom (forall A: name, B: name, C: name :: { C <: AsDirectSubClass(B, A) } C <: AsDirectSubClass(B, A) ==> OneClassDown(C, A) == B);
+
+function $IsInterface(name) returns (bool);
+
+axiom (forall J: name :: { $IsInterface(J) } $IsInterface(J) ==> J <: System.Object);
+
+function $IsValueType(name) returns (bool);
+
+axiom (forall T: name :: $IsValueType(T) ==> (forall U: name :: T <: U ==> T == U) && (forall U: name :: U <: T ==> T == U));
+
+const unique System.Object: name;
+
+axiom $IsClass(System.Object);
+
+function $IsTokenForType(struct, name) returns (bool);
+
+function TypeObject(name) returns (ref);
+
+const unique System.Type: name;
+
+axiom System.Type <: System.Object;
+
+axiom (forall T: name :: { TypeObject(T) } $IsNotNull(TypeObject(T), System.Type));
+
+function $Is(ref, name) returns (bool);
+
+axiom (forall o: ref, T: name :: { $Is(o, T) } $Is(o, T) <==> o == null || $typeof(o) <: T);
+
+function $IsNotNull(ref, name) returns (bool);
+
+axiom (forall o: ref, T: name :: { $IsNotNull(o, T) } $IsNotNull(o, T) <==> o != null && $Is(o, T));
+
+function $As(ref, name) returns (ref);
+
+axiom (forall o: ref, T: name :: $Is(o, T) ==> $As(o, T) == o);
+
+axiom (forall o: ref, T: name :: !$Is(o, T) ==> $As(o, T) == null);
+
+axiom (forall heap: [ref,name]any, o: ref, A: name, r: int :: $Is(o, RefArray(A, r)) ==> heap[o, $inv] == $typeof(o));
+
+axiom (forall heap: [ref,name]any, o: ref, A: name, r: int :: $Is(o, ValueArray(A, r)) ==> heap[o, $inv] == $typeof(o));
+
+function IsAllocated(h: [ref,name]any, o: any) returns (bool);
+
+axiom (forall h: [ref,name]any, o: ref, f: name :: { IsAllocated(h, h[o, f]) } IsHeap(h) ==> IsAllocated(h, h[o, f]));
+
+axiom (forall h: [ref,name]any, s: struct, f: name :: { IsAllocated(h, $StructGet(s, f)) } IsAllocated(h, s) ==> IsAllocated(h, $StructGet(s, f)));
+
+axiom (forall h: [ref,name]any, e: elements, i: int :: { IsAllocated(h, RefArrayGet(e, i)) } IsAllocated(h, e) ==> IsAllocated(h, RefArrayGet(e, i)));
+
+axiom (forall h: [ref,name]any, o: ref :: { h[o, $allocated] } IsAllocated(h, o) ==> cast(h[o, $allocated]):bool);
+
+axiom (forall h: [ref,name]any, c: name :: { h[ClassRepr(c), $allocated] } IsHeap(h) ==> cast(h[ClassRepr(c), $allocated]):bool);
+
+function DeclType(field: name) returns (class: name);
+
+function AsNonNullRefField(field: name, T: name) returns (f: name);
+
+function AsRefField(field: name, T: name) returns (f: name);
+
+function AsRangeField(field: name, T: name) returns (f: name);
+
+axiom (forall f: name, T: name :: { AsNonNullRefField(f, T) } AsNonNullRefField(f, T) == f ==> AsRefField(f, T) == f);
+
+axiom (forall h: [ref,name]any, o: ref, f: name, T: name :: { h[o, AsRefField(f, T)] } IsHeap(h) ==> $Is(cast(h[o, AsRefField(f, T)]):ref, T));
+
+axiom (forall h: [ref,name]any, o: ref, f: name, T: name :: { h[o, AsNonNullRefField(f, T)] } IsHeap(h) ==> cast(h[o, AsNonNullRefField(f, T)]):ref != null);
+
+axiom (forall h: [ref,name]any, o: ref, f: name, T: name :: { h[o, AsRangeField(f, T)] } IsHeap(h) ==> InRange(cast(h[o, AsRangeField(f, T)]):int, T));
+
+const unique System.String: name;
+
+axiom (forall h: [ref,name]any, s: ref :: IsHeap(h) && $typeof(s) == System.String ==> h[s, $inv] == $typeof(s) && cast(h[s, $writable]):bool);
+
+function AsOwnedField(f: name) returns (name);
+
+axiom (forall h: [ref,name]any, o: ref, f: name :: { h[o, AsOwnedField(f)] } IsHeap(h) && cast(h[o, $inv]):name <: DeclType(AsOwnedField(f)) ==> cast(h[o, AsOwnedField(f)]):ref == null || $typeof(cast(h[o, AsOwnedField(f)]):ref) == System.String || !cast(h[cast(h[o, AsOwnedField(f)]):ref, $writable]):bool);
+
+axiom (forall h: [ref,name]any, o: ref :: { h[o, $writable] } IsHeap(h) && !cast(h[o, $writable]):bool ==> cast(h[o, $inv]):name == $typeof(o));
+
+function Box(any, ref) returns (ref);
+
+function Unbox(ref) returns (any);
+
+axiom (forall x: any, p: ref :: { Unbox(Box(x, p)) } Unbox(Box(x, p)) == x);
+
+axiom (forall heap: [ref,name]any, x: any, p: ref :: { heap[Box(x, p), $inv] } IsHeap(heap) ==> heap[Box(x, p), $inv] == $typeof(Box(x, p)));
+
+function UnboxedType(ref) returns (name);
+
+function BoxTester(p: ref, typ: name) returns (ref);
+
+axiom (forall p: ref, typ: name :: { BoxTester(p, typ) } UnboxedType(p) == typ <==> BoxTester(p, typ) != null);
+
+const unique System.Int16: name;
+
+axiom $IsValueType(System.Int16);
+
+const unique System.Int32: name;
+
+axiom $IsValueType(System.Int32);
+
+const unique System.Int64: name;
+
+axiom $IsValueType(System.Int64);
+
+const unique System.Byte: name;
+
+axiom $IsValueType(System.Byte);
+
+const unique System.Int16.MinValue: int;
+
+const unique System.Int16.MaxValue: int;
+
+const unique System.Int32.MinValue: int;
+
+const unique System.Int32.MaxValue: int;
+
+const unique System.Int64.MinValue: int;
+
+const unique System.Int64.MaxValue: int;
+
+axiom System.Int64.MinValue < System.Int32.MinValue;
+
+axiom System.Int32.MinValue < System.Int16.MinValue;
+
+axiom System.Int16.MinValue < System.Int16.MaxValue;
+
+axiom System.Int16.MaxValue < System.Int32.MaxValue;
+
+axiom System.Int32.MaxValue < System.Int64.MaxValue;
+
+function InRange(i: int, T: name) returns (bool);
+
+axiom (forall i: int :: InRange(i, System.Int16) <==> System.Int16.MinValue <= i && i <= System.Int16.MaxValue);
+
+axiom (forall i: int :: InRange(i, System.Int32) <==> System.Int32.MinValue <= i && i <= System.Int32.MaxValue);
+
+axiom (forall i: int :: InRange(i, System.Int64) <==> System.Int64.MinValue <= i && i <= System.Int64.MaxValue);
+
+axiom (forall i: int :: { InRange(i, System.Byte) } InRange(i, System.Byte) <==> 0 <= i && i < 256);
+
+function $RealToInt(real) returns (int);
+
+function $IntToReal(int) returns (real);
+
+function $SizeIs(name, int) returns (bool);
+
+function $IfThenElse(bool, any, any) returns (any);
+
+axiom (forall b: bool, x: any, y: any :: { $IfThenElse(b, x, y) } b ==> $IfThenElse(b, x, y) == x);
+
+axiom (forall b: bool, x: any, y: any :: { $IfThenElse(b, x, y) } !b ==> $IfThenElse(b, x, y) == y);
+
+function #neg(int) returns (int);
+
+function #rneg(real) returns (real);
+
+function #rdiv(real, real) returns (real);
+
+function #and(int, int) returns (int);
+
+function #or(int, int) returns (int);
+
+function #xor(int, int) returns (int);
+
+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 % y } 0 <= x && 0 < y ==> 0 <= x % y && x % 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 % y } x <= 0 && 0 < y ==> 0 - y < x % y && x % 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 + y) % y } 0 <= x && 0 <= y ==> (x + y) % y == x % 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 :: { (x - y) % y } 0 <= x - y && 0 <= y ==> (x - y) % y == x % 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 i: int :: { #shl(i, 0) } #shl(i, 0) == i);
+
+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);
+
+const unique $UnknownRef: ref;
+
+const unique System.IComparable: name;
+
+const unique Microsoft.Singularity.Applications.ThreadTest: name;
+
+const unique System.Threading.Thread: name;
+
+const unique System.Collections.IEnumerable: name;
+
+const unique System.Threading.ThreadStart: name;
+
+const unique System.ICloneable: name;
+
+const unique System.MulticastDelegate: name;
+
+const unique System.Delegate: name;
+
+const unique $stringLiteral0: ref;
+
+axiom (forall heap: [ref,name]any :: { cast(heap[$stringLiteral0, $allocated]):bool } IsHeap(heap) ==> cast(heap[$stringLiteral0, $allocated]):bool) && $IsNotNull($stringLiteral0, System.String) && $Length($stringLiteral0) == 13;
+
+const unique $stringLiteral1: ref;
+
+axiom (forall heap: [ref,name]any :: { cast(heap[$stringLiteral1, $allocated]):bool } IsHeap(heap) ==> cast(heap[$stringLiteral1, $allocated]):bool) && $IsNotNull($stringLiteral1, System.String) && $Length($stringLiteral1) == 14;
+
+const unique $stringLiteral2: ref;
+
+axiom (forall heap: [ref,name]any :: { cast(heap[$stringLiteral2, $allocated]):bool } IsHeap(heap) ==> cast(heap[$stringLiteral2, $allocated]):bool) && $IsNotNull($stringLiteral2, System.String) && $Length($stringLiteral2) == 11;
+
+const unique $stringLiteral3: ref;
+
+axiom (forall heap: [ref,name]any :: { cast(heap[$stringLiteral3, $allocated]):bool } IsHeap(heap) ==> cast(heap[$stringLiteral3, $allocated]):bool) && $IsNotNull($stringLiteral3, System.String) && $Length($stringLiteral3) == 18;
+
+const unique $stringLiteral4: ref;
+
+axiom (forall heap: [ref,name]any :: { cast(heap[$stringLiteral4, $allocated]):bool } IsHeap(heap) ==> cast(heap[$stringLiteral4, $allocated]):bool) && $IsNotNull($stringLiteral4, System.String) && $Length($stringLiteral4) == 19;
+
+const unique $stringLiteral5: ref;
+
+axiom (forall heap: [ref,name]any :: { cast(heap[$stringLiteral5, $allocated]):bool } IsHeap(heap) ==> cast(heap[$stringLiteral5, $allocated]):bool) && $IsNotNull($stringLiteral5, System.String) && $Length($stringLiteral5) == 14;
+
+const unique $stringLiteral6: ref;
+
+axiom (forall heap: [ref,name]any :: { cast(heap[$stringLiteral6, $allocated]):bool } IsHeap(heap) ==> cast(heap[$stringLiteral6, $allocated]):bool) && $IsNotNull($stringLiteral6, System.String) && $Length($stringLiteral6) == 15;
+
+const unique $stringLiteral7: ref;
+
+axiom (forall heap: [ref,name]any :: { cast(heap[$stringLiteral7, $allocated]):bool } IsHeap(heap) ==> cast(heap[$stringLiteral7, $allocated]):bool) && $IsNotNull($stringLiteral7, System.String) && $Length($stringLiteral7) == 11;
+
+const unique $stringLiteral8: ref;
+
+axiom (forall heap: [ref,name]any :: { cast(heap[$stringLiteral8, $allocated]):bool } IsHeap(heap) ==> cast(heap[$stringLiteral8, $allocated]):bool) && $IsNotNull($stringLiteral8, System.String) && $Length($stringLiteral8) == 19;
+
+const unique $stringLiteral9: ref;
+
+axiom (forall heap: [ref,name]any :: { cast(heap[$stringLiteral9, $allocated]):bool } IsHeap(heap) ==> cast(heap[$stringLiteral9, $allocated]):bool) && $IsNotNull($stringLiteral9, System.String) && $Length($stringLiteral9) == 20;
+
+const unique $stringLiteral10: ref;
+
+axiom (forall heap: [ref,name]any :: { cast(heap[$stringLiteral10, $allocated]):bool } IsHeap(heap) ==> cast(heap[$stringLiteral10, $allocated]):bool) && $IsNotNull($stringLiteral10, System.String) && $Length($stringLiteral10) == 22;
+
+const unique $stringLiteral11: ref;
+
+axiom (forall heap: [ref,name]any :: { cast(heap[$stringLiteral11, $allocated]):bool } IsHeap(heap) ==> cast(heap[$stringLiteral11, $allocated]):bool) && $IsNotNull($stringLiteral11, System.String) && $Length($stringLiteral11) == 21;
+
+const unique $stringLiteral12: ref;
+
+axiom (forall heap: [ref,name]any :: { cast(heap[$stringLiteral12, $allocated]):bool } IsHeap(heap) ==> cast(heap[$stringLiteral12, $allocated]):bool) && $IsNotNull($stringLiteral12, System.String) && $Length($stringLiteral12) == 23;
+
+const unique $stringLiteral13: ref;
+
+axiom (forall heap: [ref,name]any :: { cast(heap[$stringLiteral13, $allocated]):bool } IsHeap(heap) ==> cast(heap[$stringLiteral13, $allocated]):bool) && $IsNotNull($stringLiteral13, System.String) && $Length($stringLiteral13) == 22;
+
+axiom $IsClass(Microsoft.Singularity.Applications.ThreadTest);
+
+axiom Microsoft.Singularity.Applications.ThreadTest <: System.Object && AsDirectSubClass(Microsoft.Singularity.Applications.ThreadTest, System.Object) == Microsoft.Singularity.Applications.ThreadTest;
+
+axiom (forall $K: name :: { Microsoft.Singularity.Applications.ThreadTest <: $K } Microsoft.Singularity.Applications.ThreadTest <: $K <==> Microsoft.Singularity.Applications.ThreadTest == $K || System.Object <: $K);
+
+function Inv_Microsoft.Singularity.Applications.ThreadTest(object: ref, heap: [ref,name]any) returns (result: bool);
+
+axiom (forall this: ref, heap: [ref,name]any :: { Inv_Microsoft.Singularity.Applications.ThreadTest(this, heap) } Inv_Microsoft.Singularity.Applications.ThreadTest(this, heap) <==> true);
+
+axiom (forall $o: ref, heap: [ref,name]any :: { cast(heap[$o, $inv]):name <: Microsoft.Singularity.Applications.ThreadTest } { Inv_Microsoft.Singularity.Applications.ThreadTest($o, heap) } IsHeap(heap) && cast(heap[$o, $inv]):name <: Microsoft.Singularity.Applications.ThreadTest ==> Inv_Microsoft.Singularity.Applications.ThreadTest($o, heap));
+
+procedure Microsoft.Singularity.Applications.ThreadTest.FirstThreadMethod();
+ modifies $Heap;
+ free ensures IsHeap($Heap);
+ free ensures (forall $o: ref, $f: name :: $f != $inv && $o != null && cast(old($Heap)[$o, $allocated]):bool == true && cast(old($Heap)[$o, $writable]):bool == true && (!IsStaticField($f) || !IsDirectlyModifiableField($f)) ==> old($Heap[$o, $f]) == $Heap[$o, $f]);
+ free ensures (forall $o: ref :: old($Heap)[$o, $inv] == $Heap[$o, $inv] || cast(old($Heap)[$o, $allocated]):bool != true);
+ free ensures (forall $o: ref :: cast(old($Heap)[$o, $allocated]):bool ==> cast($Heap[$o, $allocated]):bool);
+ free ensures (forall $o: ref :: old($Heap[$o, $sharingMode]) == $Heap[$o, $sharingMode]);
+
+
+
+implementation Microsoft.Singularity.Applications.ThreadTest.FirstThreadMethod()
+{
+ var stack0o: ref, i: int, stack0i: int, stack0b: bool, local1: int, $Heap$block1513$LoopPreheader: [ref,name]any;
+
+ entry:
+ assume IsHeap($Heap);
+ goto block1479;
+
+ block1479:
+ goto block1496;
+
+ block1496:
+ // ----- load constant First thread! ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(21,13)
+ stack0o := $stringLiteral0;
+ // ----- call ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(21,13)
+ call System.Console.WriteLine$System.String(stack0o);
+ // ----- load constant First thread! ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(22,13)
+ stack0o := $stringLiteral1;
+ // ----- call ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(22,13)
+ call Microsoft.Singularity.DebugStub.Print$System.String(stack0o);
+ // ----- load constant 0 ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(24,18)
+ i := 0;
+ goto block1513$LoopPreheader;
+
+ block1513:
+ // ----- default loop invariant: $inv field ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(24,29)
+ assert (forall $o: ref :: $Heap$block1513$LoopPreheader[$o, $inv] == $Heap[$o, $inv] || cast($Heap$block1513$LoopPreheader[$o, $allocated]):bool != true);
+ assert (forall $o: ref :: cast($Heap$block1513$LoopPreheader[$o, $allocated]):bool ==> cast($Heap[$o, $allocated]):bool);
+ // ----- load constant 10 ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(24,29)
+ stack0i := 10;
+ // ----- binary operator ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(24,29)
+ stack0b := i >= stack0i;
+ // ----- branch ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(24,29)
+ goto true1513to1547, false1513to1530;
+
+ true1513to1547:
+ assume stack0b == true;
+ goto block1547;
+
+ false1513to1530:
+ assume stack0b == false;
+ goto block1530;
+
+ block1547:
+ // ----- load constant First thread done! ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(29,13)
+ stack0o := $stringLiteral3;
+ // ----- call ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(29,13)
+ call System.Console.WriteLine$System.String(stack0o);
+ // ----- load constant First thread done! ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(30,13)
+ stack0o := $stringLiteral4;
+ // ----- call ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(30,13)
+ call Microsoft.Singularity.DebugStub.Print$System.String(stack0o);
+ // ----- return ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(31,10)
+ return;
+
+ block1530:
+ // ----- load constant [0] ... ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(25,17)
+ stack0o := $stringLiteral2;
+ // ----- call ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(25,17)
+ call System.Console.WriteLine$System.String(stack0o);
+ // ----- call ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(26,17)
+ call System.Threading.Thread.Yield();
+ // ----- copy ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(24,37)
+ local1 := i;
+ // ----- load constant 1
+ stack0i := 1;
+ // ----- binary operator
+ stack0i := local1 + stack0i;
+ // ----- copy
+ i := stack0i;
+ // ----- copy
+ stack0i := local1;
+ // ----- branch
+ goto block1513;
+
+ block1513$LoopPreheader:
+ $Heap$block1513$LoopPreheader := $Heap;
+ goto block1513;
+
+}
+
+
+
+axiom $IsClass(System.String);
+
+axiom System.String <: System.Object && AsDirectSubClass(System.String, System.Object) == System.String;
+
+axiom $IsInterface(System.IComparable);
+
+axiom (forall $K: name :: { System.IComparable <: $K } System.IComparable <: $K <==> System.IComparable == $K || System.Object == $K);
+
+axiom Implements(System.String, System.IComparable);
+
+axiom $IsInterface(System.ICloneable);
+
+axiom (forall $K: name :: { System.ICloneable <: $K } System.ICloneable <: $K <==> System.ICloneable == $K || System.Object == $K);
+
+axiom Implements(System.String, System.ICloneable);
+
+axiom $IsInterface(System.Collections.IEnumerable);
+
+axiom (forall $K: name :: { System.Collections.IEnumerable <: $K } System.Collections.IEnumerable <: $K <==> System.Collections.IEnumerable == $K || System.Object == $K);
+
+axiom Implements(System.String, System.Collections.IEnumerable);
+
+axiom (forall $K: name :: { System.String <: $K } System.String <: $K <==> System.String == $K || System.Object <: $K || System.IComparable <: $K || System.ICloneable <: $K || System.Collections.IEnumerable <: $K);
+
+axiom (forall $U: name :: { $U <: System.String } $U <: System.String ==> $U == System.String);
+
+function Inv_System.String(object: ref, heap: [ref,name]any) returns (result: bool);
+
+axiom (forall this: ref, heap: [ref,name]any :: { Inv_System.String(this, heap) } Inv_System.String(this, heap) <==> true);
+
+axiom (forall $o: ref, heap: [ref,name]any :: { cast(heap[$o, $inv]):name <: System.String } { Inv_System.String($o, heap) } IsHeap(heap) && cast(heap[$o, $inv]):name <: System.String ==> Inv_System.String($o, heap));
+
+procedure System.Console.WriteLine$System.String(value$in: ref);
+ requires value$in == null || (cast($Heap[value$in, $writable]):bool == true && cast($Heap[value$in, $inv]):name == $typeof(value$in));
+ modifies $Heap;
+ free ensures IsHeap($Heap);
+ free ensures (forall $o: ref, $f: name :: $f != $inv && $o != null && cast(old($Heap)[$o, $allocated]):bool == true && cast(old($Heap)[$o, $writable]):bool == true && (!IsStaticField($f) || !IsDirectlyModifiableField($f)) ==> old($Heap[$o, $f]) == $Heap[$o, $f]);
+ free ensures (forall $o: ref :: old($Heap)[$o, $inv] == $Heap[$o, $inv] || cast(old($Heap)[$o, $allocated]):bool != true);
+ free ensures (forall $o: ref :: cast(old($Heap)[$o, $allocated]):bool ==> cast($Heap[$o, $allocated]):bool);
+ free ensures (forall $o: ref :: old($Heap[$o, $sharingMode]) == $Heap[$o, $sharingMode]);
+
+
+
+procedure Microsoft.Singularity.DebugStub.Print$System.String(value$in: ref);
+ requires value$in == null || (cast($Heap[value$in, $writable]):bool == true && cast($Heap[value$in, $inv]):name == $typeof(value$in));
+ modifies $Heap;
+ free ensures IsHeap($Heap);
+ free ensures (forall $o: ref, $f: name :: $f != $inv && $o != null && cast(old($Heap)[$o, $allocated]):bool == true && cast(old($Heap)[$o, $writable]):bool == true && (!IsStaticField($f) || !IsDirectlyModifiableField($f)) ==> old($Heap[$o, $f]) == $Heap[$o, $f]);
+ free ensures (forall $o: ref :: old($Heap)[$o, $inv] == $Heap[$o, $inv] || cast(old($Heap)[$o, $allocated]):bool != true);
+ free ensures (forall $o: ref :: cast(old($Heap)[$o, $allocated]):bool ==> cast($Heap[$o, $allocated]):bool);
+ free ensures (forall $o: ref :: old($Heap[$o, $sharingMode]) == $Heap[$o, $sharingMode]);
+
+
+
+procedure System.Threading.Thread.Yield();
+ modifies $Heap;
+ free ensures IsHeap($Heap);
+ free ensures (forall $o: ref, $f: name :: $f != $inv && $o != null && cast(old($Heap)[$o, $allocated]):bool == true && cast(old($Heap)[$o, $writable]):bool == true && (!IsStaticField($f) || !IsDirectlyModifiableField($f)) ==> old($Heap[$o, $f]) == $Heap[$o, $f]);
+ free ensures (forall $o: ref :: old($Heap)[$o, $inv] == $Heap[$o, $inv] || cast(old($Heap)[$o, $allocated]):bool != true);
+ free ensures (forall $o: ref :: cast(old($Heap)[$o, $allocated]):bool ==> cast($Heap[$o, $allocated]):bool);
+ free ensures (forall $o: ref :: old($Heap[$o, $sharingMode]) == $Heap[$o, $sharingMode]);
+
+
+
+procedure Microsoft.Singularity.Applications.ThreadTest.SecondThreadMethod();
+ modifies $Heap;
+ free ensures IsHeap($Heap);
+ free ensures (forall $o: ref, $f: name :: $f != $inv && $o != null && cast(old($Heap)[$o, $allocated]):bool == true && cast(old($Heap)[$o, $writable]):bool == true && (!IsStaticField($f) || !IsDirectlyModifiableField($f)) ==> old($Heap[$o, $f]) == $Heap[$o, $f]);
+ free ensures (forall $o: ref :: old($Heap)[$o, $inv] == $Heap[$o, $inv] || cast(old($Heap)[$o, $allocated]):bool != true);
+ free ensures (forall $o: ref :: cast(old($Heap)[$o, $allocated]):bool ==> cast($Heap[$o, $allocated]):bool);
+ free ensures (forall $o: ref :: old($Heap[$o, $sharingMode]) == $Heap[$o, $sharingMode]);
+
+
+
+implementation Microsoft.Singularity.Applications.ThreadTest.SecondThreadMethod()
+{
+ var stack0o: ref, i: int, stack0i: int, stack0b: bool, local1: int, $Heap$block2516$LoopPreheader: [ref,name]any;
+
+ entry:
+ assume IsHeap($Heap);
+ goto block2482;
+
+ block2482:
+ goto block2499;
+
+ block2499:
+ // ----- load constant Second thread! ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(35,13)
+ stack0o := $stringLiteral5;
+ // ----- call ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(35,13)
+ call System.Console.WriteLine$System.String(stack0o);
+ // ----- load constant Second thread! ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(36,13)
+ stack0o := $stringLiteral6;
+ // ----- call ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(36,13)
+ call Microsoft.Singularity.DebugStub.Print$System.String(stack0o);
+ // ----- load constant 0 ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(38,18)
+ i := 0;
+ goto block2516$LoopPreheader;
+
+ block2516:
+ // ----- default loop invariant: $inv field ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(38,29)
+ assert (forall $o: ref :: $Heap$block2516$LoopPreheader[$o, $inv] == $Heap[$o, $inv] || cast($Heap$block2516$LoopPreheader[$o, $allocated]):bool != true);
+ assert (forall $o: ref :: cast($Heap$block2516$LoopPreheader[$o, $allocated]):bool ==> cast($Heap[$o, $allocated]):bool);
+ // ----- load constant 10 ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(38,29)
+ stack0i := 10;
+ // ----- binary operator ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(38,29)
+ stack0b := i >= stack0i;
+ // ----- branch ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(38,29)
+ goto true2516to2550, false2516to2533;
+
+ true2516to2550:
+ assume stack0b == true;
+ goto block2550;
+
+ false2516to2533:
+ assume stack0b == false;
+ goto block2533;
+
+ block2550:
+ // ----- load constant Second thread done! ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(44,13)
+ stack0o := $stringLiteral8;
+ // ----- call ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(44,13)
+ call System.Console.WriteLine$System.String(stack0o);
+ // ----- load constant Second thread done! ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(45,13)
+ stack0o := $stringLiteral9;
+ // ----- call ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(45,13)
+ call Microsoft.Singularity.DebugStub.Print$System.String(stack0o);
+ // ----- return ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(46,10)
+ return;
+
+ block2533:
+ // ----- load constant ... [1] ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(40,17)
+ stack0o := $stringLiteral7;
+ // ----- call ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(40,17)
+ call System.Console.WriteLine$System.String(stack0o);
+ // ----- call ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(41,17)
+ call System.Threading.Thread.Yield();
+ // ----- copy ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(38,37)
+ local1 := i;
+ // ----- load constant 1
+ stack0i := 1;
+ // ----- binary operator
+ stack0i := local1 + stack0i;
+ // ----- copy
+ i := stack0i;
+ // ----- copy
+ stack0i := local1;
+ // ----- branch
+ goto block2516;
+
+ block2516$LoopPreheader:
+ $Heap$block2516$LoopPreheader := $Heap;
+ goto block2516;
+
+}
+
+
+
+procedure Microsoft.Singularity.Applications.ThreadTest.Main$System.String.array(args$in: ref) returns ($result: int);
+ requires args$in == null || (cast($Heap[args$in, $writable]):bool == true && cast($Heap[args$in, $inv]):name == $typeof(args$in));
+ modifies $Heap;
+ free ensures IsHeap($Heap);
+ free ensures IsAllocated($Heap, $result);
+ free ensures (forall $o: ref, $f: name :: $f != $inv && $o != null && cast(old($Heap)[$o, $allocated]):bool == true && cast(old($Heap)[$o, $writable]):bool == true && (!IsStaticField($f) || !IsDirectlyModifiableField($f)) ==> old($Heap[$o, $f]) == $Heap[$o, $f]);
+ free ensures (forall $o: ref :: old($Heap)[$o, $inv] == $Heap[$o, $inv] || cast(old($Heap)[$o, $allocated]):bool != true);
+ free ensures (forall $o: ref :: cast(old($Heap)[$o, $allocated]):bool ==> cast($Heap[$o, $allocated]):bool);
+ free ensures (forall $o: ref :: old($Heap[$o, $sharingMode]) == $Heap[$o, $sharingMode]);
+
+
+
+implementation Microsoft.Singularity.Applications.ThreadTest.Main$System.String.array(args$in: ref) returns ($result: int)
+{
+ var args: ref, stack0o: ref, stack1o: ref, stack50000o: ref, t1: ref, t2: ref, i: int, stack0i: int, stack0b: bool, local3: int, return.value: int, SS$Display.Return.Local: int, $Heap$block3825$LoopPreheader: [ref,name]any;
+
+ entry:
+ assume IsHeap($Heap);
+ args := args$in;
+ assume $Is(args, RefArray(System.String, 1));
+ assume cast($Heap[args$in, $allocated]):bool == true;
+ goto block3791;
+
+ block3791:
+ goto block3808;
+
+ block3808:
+ stack0o := null;
+ // ----- load function ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(51,13)
+ havoc stack1o;
+ // ----- new object ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(51,13)
+ havoc stack50000o;
+ assume cast($Heap[stack50000o, $allocated]):bool == false && stack50000o != null && $typeof(stack50000o) == System.Threading.ThreadStart;
+ $Heap[stack50000o, $allocated] := true;
+ // ----- call ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(51,13)
+ assert stack50000o != null;
+ call System.Threading.ThreadStart..ctor$System.Object$System.IntPtr(stack50000o, stack0o, stack1o);
+ // ----- copy ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(51,13)
+ stack0o := stack50000o;
+ // ----- new object ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(51,13)
+ havoc stack50000o;
+ assume cast($Heap[stack50000o, $allocated]):bool == false && stack50000o != null && $typeof(stack50000o) == System.Threading.Thread;
+ $Heap[stack50000o, $allocated] := true;
+ // ----- call ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(51,13)
+ assert stack50000o != null;
+ call System.Threading.Thread..ctor$System.Threading.ThreadStart(stack50000o, stack0o);
+ // ----- copy ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(51,13)
+ stack0o := stack50000o;
+ // ----- copy ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(51,13)
+ t1 := stack0o;
+ stack0o := null;
+ // ----- load function ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(52,13)
+ havoc stack1o;
+ // ----- new object ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(52,13)
+ havoc stack50000o;
+ assume cast($Heap[stack50000o, $allocated]):bool == false && stack50000o != null && $typeof(stack50000o) == System.Threading.ThreadStart;
+ $Heap[stack50000o, $allocated] := true;
+ // ----- call ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(52,13)
+ assert stack50000o != null;
+ call System.Threading.ThreadStart..ctor$System.Object$System.IntPtr(stack50000o, stack0o, stack1o);
+ // ----- copy ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(52,13)
+ stack0o := stack50000o;
+ // ----- new object ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(52,13)
+ havoc stack50000o;
+ assume cast($Heap[stack50000o, $allocated]):bool == false && stack50000o != null && $typeof(stack50000o) == System.Threading.Thread;
+ $Heap[stack50000o, $allocated] := true;
+ // ----- call ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(52,13)
+ assert stack50000o != null;
+ call System.Threading.Thread..ctor$System.Threading.ThreadStart(stack50000o, stack0o);
+ // ----- copy ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(52,13)
+ stack0o := stack50000o;
+ // ----- copy ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(52,13)
+ t2 := stack0o;
+ // ----- load constant Starting first thread. ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(54,13)
+ stack0o := $stringLiteral10;
+ // ----- call ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(54,13)
+ call System.Console.WriteLine$System.String(stack0o);
+ // ----- call ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(55,13)
+ assert t1 != null;
+ call System.Threading.Thread.Start(t1);
+ // ----- load constant Started first thread. ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(56,13)
+ stack0o := $stringLiteral11;
+ // ----- call ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(56,13)
+ call System.Console.WriteLine$System.String(stack0o);
+ // ----- load constant Starting second thread. ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(58,13)
+ stack0o := $stringLiteral12;
+ // ----- call ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(58,13)
+ call System.Console.WriteLine$System.String(stack0o);
+ // ----- call ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(59,13)
+ assert t2 != null;
+ call System.Threading.Thread.Start(t2);
+ // ----- load constant Started second thread. ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(60,13)
+ stack0o := $stringLiteral13;
+ // ----- call ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(60,13)
+ call System.Console.WriteLine$System.String(stack0o);
+ // ----- load constant 0 ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(62,18)
+ i := 0;
+ goto block3825$LoopPreheader;
+
+ block3825:
+ // ----- default loop invariant: $inv field ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(62,29)
+ assert (forall $o: ref :: $Heap$block3825$LoopPreheader[$o, $inv] == $Heap[$o, $inv] || cast($Heap$block3825$LoopPreheader[$o, $allocated]):bool != true);
+ assert (forall $o: ref :: cast($Heap$block3825$LoopPreheader[$o, $allocated]):bool ==> cast($Heap[$o, $allocated]):bool);
+ // ----- load constant 30 ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(62,29)
+ stack0i := 30;
+ // ----- binary operator ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(62,29)
+ stack0b := i >= stack0i;
+ // ----- branch ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(62,29)
+ goto true3825to3859, false3825to3842;
+
+ true3825to3859:
+ assume stack0b == true;
+ goto block3859;
+
+ false3825to3842:
+ assume stack0b == false;
+ goto block3842;
+
+ block3859:
+ // ----- load constant 0 ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(66,13)
+ return.value := 0;
+ // ----- branch
+ goto block3876;
+
+ block3842:
+ // ----- call ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(64,17)
+ call System.Threading.Thread.Yield();
+ // ----- copy ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(62,37)
+ local3 := i;
+ // ----- load constant 1
+ stack0i := 1;
+ // ----- binary operator
+ stack0i := local3 + stack0i;
+ // ----- copy
+ i := stack0i;
+ // ----- copy
+ stack0i := local3;
+ // ----- branch
+ goto block3825;
+
+ block3876:
+ // ----- copy
+ SS$Display.Return.Local := return.value;
+ // ----- copy ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(67,10)
+ stack0i := return.value;
+ // ----- return ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(67,10)
+ $result := stack0i;
+ return;
+
+ block3825$LoopPreheader:
+ $Heap$block3825$LoopPreheader := $Heap;
+ goto block3825;
+
+}
+
+
+
+axiom $IsClass(System.Threading.ThreadStart);
+
+axiom $IsClass(System.MulticastDelegate);
+
+axiom $IsClass(System.Delegate);
+
+axiom System.Delegate <: System.Object && AsDirectSubClass(System.Delegate, System.Object) == System.Delegate;
+
+axiom Implements(System.Delegate, System.ICloneable);
+
+axiom (forall $K: name :: { System.Delegate <: $K } System.Delegate <: $K <==> System.Delegate == $K || System.Object <: $K || System.ICloneable <: $K);
+
+function Inv_System.Delegate(object: ref, heap: [ref,name]any) returns (result: bool);
+
+axiom (forall this: ref, heap: [ref,name]any :: { Inv_System.Delegate(this, heap) } Inv_System.Delegate(this, heap) <==> true);
+
+axiom (forall $o: ref, heap: [ref,name]any :: { cast(heap[$o, $inv]):name <: System.Delegate } { Inv_System.Delegate($o, heap) } IsHeap(heap) && cast(heap[$o, $inv]):name <: System.Delegate ==> Inv_System.Delegate($o, heap));
+
+axiom System.MulticastDelegate <: System.Delegate && AsDirectSubClass(System.MulticastDelegate, System.Delegate) == System.MulticastDelegate;
+
+axiom (forall $K: name :: { System.MulticastDelegate <: $K } System.MulticastDelegate <: $K <==> System.MulticastDelegate == $K || System.Delegate <: $K);
+
+function Inv_System.MulticastDelegate(object: ref, heap: [ref,name]any) returns (result: bool);
+
+axiom (forall this: ref, heap: [ref,name]any :: { Inv_System.MulticastDelegate(this, heap) } Inv_System.MulticastDelegate(this, heap) <==> true);
+
+axiom (forall $o: ref, heap: [ref,name]any :: { cast(heap[$o, $inv]):name <: System.MulticastDelegate } { Inv_System.MulticastDelegate($o, heap) } IsHeap(heap) && cast(heap[$o, $inv]):name <: System.MulticastDelegate ==> Inv_System.MulticastDelegate($o, heap));
+
+axiom System.Threading.ThreadStart <: System.MulticastDelegate && AsDirectSubClass(System.Threading.ThreadStart, System.MulticastDelegate) == System.Threading.ThreadStart;
+
+axiom (forall $K: name :: { System.Threading.ThreadStart <: $K } System.Threading.ThreadStart <: $K <==> System.Threading.ThreadStart == $K || System.MulticastDelegate <: $K);
+
+axiom (forall $U: name :: { $U <: System.Threading.ThreadStart } $U <: System.Threading.ThreadStart ==> $U == System.Threading.ThreadStart);
+
+function Inv_System.Threading.ThreadStart(object: ref, heap: [ref,name]any) returns (result: bool);
+
+axiom (forall this: ref, heap: [ref,name]any :: { Inv_System.Threading.ThreadStart(this, heap) } Inv_System.Threading.ThreadStart(this, heap) <==> true);
+
+axiom (forall $o: ref, heap: [ref,name]any :: { cast(heap[$o, $inv]):name <: System.Threading.ThreadStart } { Inv_System.Threading.ThreadStart($o, heap) } IsHeap(heap) && cast(heap[$o, $inv]):name <: System.Threading.ThreadStart ==> Inv_System.Threading.ThreadStart($o, heap));
+
+procedure System.Threading.ThreadStart..ctor$System.Object$System.IntPtr(this: ref, object$in: ref, method$in: ref);
+ modifies $Heap;
+ free ensures IsHeap($Heap);
+ free ensures (forall $o: ref, $f: name :: $f != $inv && $o != null && cast(old($Heap)[$o, $allocated]):bool == true && cast(old($Heap)[$o, $writable]):bool == true && (!IsStaticField($f) || !IsDirectlyModifiableField($f)) ==> old($Heap[$o, $f]) == $Heap[$o, $f]);
+ free ensures (forall $o: ref :: old($Heap)[$o, $inv] == $Heap[$o, $inv] || cast(old($Heap)[$o, $allocated]):bool != true);
+ free ensures (forall $o: ref :: cast(old($Heap)[$o, $allocated]):bool ==> cast($Heap[$o, $allocated]):bool);
+ free ensures (forall $o: ref :: old($Heap[$o, $sharingMode]) == $Heap[$o, $sharingMode]);
+ ensures cast($Heap[this, $writable]):bool == true && cast($Heap[this, $inv]):name == System.Threading.ThreadStart;
+
+
+
+axiom $IsClass(System.Threading.Thread);
+
+axiom System.Threading.Thread <: System.Object && AsDirectSubClass(System.Threading.Thread, System.Object) == System.Threading.Thread;
+
+axiom (forall $K: name :: { System.Threading.Thread <: $K } System.Threading.Thread <: $K <==> System.Threading.Thread == $K || System.Object <: $K);
+
+axiom (forall $U: name :: { $U <: System.Threading.Thread } $U <: System.Threading.Thread ==> $U == System.Threading.Thread);
+
+function Inv_System.Threading.Thread(object: ref, heap: [ref,name]any) returns (result: bool);
+
+axiom (forall this: ref, heap: [ref,name]any :: { Inv_System.Threading.Thread(this, heap) } Inv_System.Threading.Thread(this, heap) <==> true);
+
+axiom (forall $o: ref, heap: [ref,name]any :: { cast(heap[$o, $inv]):name <: System.Threading.Thread } { Inv_System.Threading.Thread($o, heap) } IsHeap(heap) && cast(heap[$o, $inv]):name <: System.Threading.Thread ==> Inv_System.Threading.Thread($o, heap));
+
+procedure System.Threading.Thread..ctor$System.Threading.ThreadStart(this: ref, start$in: ref);
+ requires start$in == null || (cast($Heap[start$in, $writable]):bool == true && cast($Heap[start$in, $inv]):name == $typeof(start$in));
+ modifies $Heap;
+ free ensures IsHeap($Heap);
+ free ensures (forall $o: ref, $f: name :: $f != $inv && $o != null && cast(old($Heap)[$o, $allocated]):bool == true && cast(old($Heap)[$o, $writable]):bool == true && (!IsStaticField($f) || !IsDirectlyModifiableField($f)) && ($o != this || !(System.Threading.Thread <: DeclType($f))) ==> old($Heap[$o, $f]) == $Heap[$o, $f]);
+ free ensures (forall $o: ref :: $o == this || old($Heap)[$o, $inv] == $Heap[$o, $inv] || cast(old($Heap)[$o, $allocated]):bool != true);
+ free ensures (forall $o: ref :: cast(old($Heap)[$o, $allocated]):bool ==> cast($Heap[$o, $allocated]):bool);
+ free ensures (forall $o: ref :: $o == this || old($Heap[$o, $sharingMode]) == $Heap[$o, $sharingMode]);
+ ensures cast($Heap[this, $writable]):bool == true && cast($Heap[this, $inv]):name == System.Threading.Thread;
+ ensures $Heap[this, $sharingMode] == $SharingMode_Unshared;
+
+
+
+procedure System.Threading.Thread.Start(this: ref);
+ requires cast($Heap[this, $writable]):bool == true && cast($Heap[this, $inv]):name == $typeof(this);
+ modifies $Heap;
+ free ensures IsHeap($Heap);
+ free ensures (forall $o: ref, $f: name :: $f != $inv && $o != null && cast(old($Heap)[$o, $allocated]):bool == true && cast(old($Heap)[$o, $writable]):bool == true && (!IsStaticField($f) || !IsDirectlyModifiableField($f)) ==> old($Heap[$o, $f]) == $Heap[$o, $f]);
+ free ensures (forall $o: ref :: old($Heap)[$o, $inv] == $Heap[$o, $inv] || cast(old($Heap)[$o, $allocated]):bool != true);
+ free ensures (forall $o: ref :: cast(old($Heap)[$o, $allocated]):bool ==> cast($Heap[$o, $allocated]):bool);
+ free ensures (forall $o: ref :: old($Heap[$o, $sharingMode]) == $Heap[$o, $sharingMode]);
+
+
+
+procedure Microsoft.Singularity.Applications.ThreadTest..ctor(this: ref);
+ modifies $Heap;
+ free ensures IsHeap($Heap);
+ free ensures (forall $o: ref, $f: name :: $f != $inv && $o != null && cast(old($Heap)[$o, $allocated]):bool == true && cast(old($Heap)[$o, $writable]):bool == true && (!IsStaticField($f) || !IsDirectlyModifiableField($f)) && ($o != this || !(Microsoft.Singularity.Applications.ThreadTest <: DeclType($f))) ==> old($Heap[$o, $f]) == $Heap[$o, $f]);
+ free ensures (forall $o: ref :: $o == this || old($Heap)[$o, $inv] == $Heap[$o, $inv] || cast(old($Heap)[$o, $allocated]):bool != true);
+ free ensures (forall $o: ref :: cast(old($Heap)[$o, $allocated]):bool ==> cast($Heap[$o, $allocated]):bool);
+ free ensures (forall $o: ref :: $o == this || old($Heap[$o, $sharingMode]) == $Heap[$o, $sharingMode]);
+ ensures cast($Heap[this, $writable]):bool == true && cast($Heap[this, $inv]):name == Microsoft.Singularity.Applications.ThreadTest;
+ ensures $Heap[this, $sharingMode] == $SharingMode_Unshared;
+
+
+
+implementation Microsoft.Singularity.Applications.ThreadTest..ctor(this: ref)
+{
+
+ entry:
+ assume IsHeap($Heap);
+ assume $IsNotNull(this, Microsoft.Singularity.Applications.ThreadTest);
+ assume cast($Heap[this, $allocated]):bool == true;
+ assume cast($Heap[this, $writable]):bool == true && cast($Heap[this, $inv]):name == System.Object;
+ goto block4777;
+
+ block4777:
+ goto block4794;
+
+ block4794:
+ // ----- call ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(17,18)
+ assert this != null;
+ call System.Object..ctor(this);
+ // ----- return ----- C:\Maf\Singularity\base\Applications\Tests\ThreadTest\ThreadTest.cs(17,28)
+ assert this != null;
+ assert cast($Heap[this, $writable]):bool == true && System.Object <: cast($Heap[this, $inv]):name;
+ assert cast($Heap[this, $writable]):bool == true && cast($Heap[this, $inv]):name == System.Object;
+ assert Inv_Microsoft.Singularity.Applications.ThreadTest(this, $Heap);
+ $Heap[this, $inv] := Microsoft.Singularity.Applications.ThreadTest;
+ return;
+
+}
+
+
+
+procedure System.Object..ctor(this: ref);
+ modifies $Heap;
+ free ensures IsHeap($Heap);
+ free ensures (forall $o: ref, $f: name :: $f != $inv && $o != null && cast(old($Heap)[$o, $allocated]):bool == true && cast(old($Heap)[$o, $writable]):bool == true && (!IsStaticField($f) || !IsDirectlyModifiableField($f)) && ($o != this || !(System.Object <: DeclType($f))) ==> old($Heap[$o, $f]) == $Heap[$o, $f]);
+ free ensures (forall $o: ref :: $o == this || old($Heap)[$o, $inv] == $Heap[$o, $inv] || cast(old($Heap)[$o, $allocated]):bool != true);
+ free ensures (forall $o: ref :: cast(old($Heap)[$o, $allocated]):bool ==> cast($Heap[$o, $allocated]):bool);
+ free ensures (forall $o: ref :: $o == this || old($Heap[$o, $sharingMode]) == $Heap[$o, $sharingMode]);
+ ensures cast($Heap[this, $writable]):bool == true && cast($Heap[this, $inv]):name == System.Object;
+ ensures $Heap[this, $sharingMode] == $SharingMode_Unshared;
+
+
+
+type ref, name, any;
+const null : ref;
diff --git a/Test/test20/Answer b/Test/test20/Answer
new file mode 100644
index 00000000..a4b991f7
--- /dev/null
+++ b/Test/test20/Answer
@@ -0,0 +1,192 @@
+TypeDecls0.bpl(20,5): Error: more than one declaration of type name: C
+TypeDecls0.bpl(13,12): Error: more than one declaration of type variable: a
+TypeDecls0.bpl(14,18): Error: more than one declaration of type variable: a
+TypeDecls0.bpl(18,17): Error: type variable must occur in map arguments: b
+TypeDecls0.bpl(22,9): Error: type constructor received wrong number of arguments: C
+TypeDecls0.bpl(24,9): Error: undeclared type: A0
+TypeDecls0.bpl(25,9): Error: undeclared type: F
+TypeDecls0.bpl(28,9): Error: type constructor received wrong number of arguments: E
+TypeDecls0.bpl(30,9): Error: type constructor received wrong number of arguments: E
+TypeDecls0.bpl(32,9): Error: type constructor received wrong number of arguments: E
+TypeDecls0.bpl(38,11): Error: type constructor received wrong number of arguments: E
+TypeDecls0.bpl(38,13): Error: type constructor received wrong number of arguments: E
+12 name resolution errors detected in TypeDecls0.bpl
+TypeDecls1.bpl(7,13): Error: invalid type for argument 0 in map select: int (expected: <b>[b]a)
+TypeDecls1.bpl(13,25): Error: right-hand side in map store with wrong type: int (expected: bool)
+TypeDecls1.bpl(19,36): Error: invalid type for argument 0 in map select: <c>[c]c (expected: <b>[b]a)
+TypeDecls1.bpl(21,13): Error: invalid type for argument 0 in map select: <a>[<b>[b]a]bool (expected: <b>[b]a)
+4 type checking errors detected in TypeDecls1.bpl
+Prog0.bpl(17,10): Error: type variable must occur in map arguments: a
+Prog0.bpl(29,27): Error: more than one declaration of type variable: beta
+Prog0.bpl(32,22): Error: undeclared type: alpha
+Prog0.bpl(33,35): Error: undeclared type: alpha
+4 name resolution errors detected in Prog0.bpl
+Prog1.bpl(18,11): Error: invalid type for argument 0 in map select: int (expected: ref)
+Prog1.bpl(19,14): Error: invalid type for argument 1 in map select: int (expected: Field a)
+Prog1.bpl(20,17): Error: invalid argument types (bool and int) to binary operator >=
+3 type checking errors detected in Prog1.bpl
+Prog2.bpl(6,14): Error: trigger does not mention alpha, which does not occur in variables types either
+1 type checking errors detected in Prog2.bpl
+PolyFuns0.bpl(23,33): Error: invalid type for argument 1 in application of fieldValue: ref (expected: Field a)
+PolyFuns0.bpl(40,18): Error: invalid type for argument 1 in application of lessThan: bool (expected: a)
+PolyFuns0.bpl(41,43): Error: invalid type for argument 1 in application of lessThan: b (expected: a)
+PolyFuns0.bpl(53,55): Error: invalid argument types (<c>[Field c]a and <d>[Field d]d) to binary operator ==
+4 type checking errors detected in PolyFuns0.bpl
+PolyFuns1.bpl(10,9): Error: invalid type for argument 0 in application of F: <c>[c]c (expected: <b>[b]a)
+PolyFuns1.bpl(11,9): Error: invalid type for argument 0 in map select: <c>[c]c (expected: <b>[b]a)
+PolyFuns1.bpl(12,31): Error: invalid type for argument 0 in application of F: <c>[c]c (expected: <b>[b]a)
+PolyFuns1.bpl(13,31): Error: invalid type for argument 0 in map select: <c>[c]c (expected: <b>[b]a)
+PolyFuns1.bpl(17,55): Error: invalid argument types (<c>[Field c]a and <d>[Field d]d) to binary operator ==
+PolyFuns1.bpl(18,55): Error: invalid argument types (<c>[Field c]a and <d>[Field d]d) to binary operator ==
+PolyFuns1.bpl(28,11): Error: invalid type for argument 0 in call to Uhu: <dd>[Field dd]dd (expected: <c>[Field c]a)
+PolyFuns1.bpl(29,15): Error: invalid type for argument 1 in call to Uhu: <cc>[Field cc]T (expected: <d>[Field d]d)
+PolyFuns1.bpl(30,12): Error: invalid argument types (<cc>[Field cc]T and <dd>[Field dd]dd) to binary operator ==
+PolyFuns1.bpl(31,12): Error: invalid argument types (<dd>[Field dd]dd and <cc>[Field cc]T) to binary operator ==
+PolyFuns1.bpl(33,15): Error: invalid type for argument 1 in call to Uhu: <ee>[Field T]ee (expected: <d>[Field d]d)
+PolyFuns1.bpl(41,11): Error: invalid argument types (<a>[a,a]int and <b>[b,int]int) to binary operator ==
+PolyFuns1.bpl(42,11): Error: invalid argument types (<b>[b,int]int and <c>[int,c]int) to binary operator ==
+PolyFuns1.bpl(43,11): Error: invalid argument types (<a>[a,a]int and <c>[int,c]int) to binary operator ==
+PolyFuns1.bpl(50,11): Error: invalid argument types (<a,b>[a,a,b]int and <a,b>[a,b,b]int) to binary operator ==
+PolyFuns1.bpl(57,54): Error: invalid argument types (Field b and NagainCtor b) to binary operator ==
+16 type checking errors detected in PolyFuns1.bpl
+PolyProcs0.bpl(11,16): Error: invalid type for argument 0 in map select: Field b (expected: ref)
+PolyProcs0.bpl(11,19): Error: invalid type for argument 1 in map select: ref (expected: Field a)
+PolyProcs0.bpl(21,30): Error: invalid type for argument 1 in call to FieldAccess: Field int (expected: ref)
+PolyProcs0.bpl(21,34): Error: invalid type for argument 2 in call to FieldAccess: ref (expected: Field b)
+PolyProcs0.bpl(25,7): Error: invalid type for out-parameter 0 in call to FieldAccess: bool (expected: int)
+PolyProcs0.bpl(26,35): Error: invalid type for argument 2 in call to FieldAccess: ref (expected: Field b)
+PolyProcs0.bpl(41,35): Error: invalid type for argument 1 in call forall to injective: Field int (expected: ref)
+7 type checking errors detected in PolyProcs0.bpl
+TypeSynonyms0.bpl(9,5): Error: type synonym could not be resolved because of cycles: Cyclic0 (replacing body with "bool" to continue resolving)
+TypeSynonyms0.bpl(10,5): Error: type synonym could not be resolved because of cycles: Cyclic1 (replacing body with "bool" to continue resolving)
+TypeSynonyms0.bpl(12,5): Error: type synonym could not be resolved because of cycles: AlsoCyclic (replacing body with "bool" to continue resolving)
+TypeSynonyms0.bpl(22,10): Error: type constructor received wrong number of arguments: Field
+TypeSynonyms0.bpl(23,10): Error: type synonym received wrong number of arguments: Set
+TypeSynonyms0.bpl(26,10): Error: type variable must occur in map arguments: a
+6 name resolution errors detected in TypeSynonyms0.bpl
+TypeSynonyms1.bpl(46,8): Error: invalid type for argument 0 in application of h: <b>[b,b,<b2>[b2,b,int]int]int (expected: nested2)
+1 type checking errors detected in TypeSynonyms1.bpl
+
+Boogie program verifier finished with 1 verified, 0 errors
+
+type Set a = [a]bool;
+
+type Field _;
+
+type Heap = <a>[ref,Field a]a;
+
+type notAllParams a b = Field b;
+
+type Cyclic0 = Cyclic1;
+
+type Cyclic1 = Cyclic0;
+
+type AlsoCyclic a = <b>[AlsoCyclic b]int;
+
+type C _ _;
+
+type C2 b a = C a b;
+
+function f(C int bool) returns (int);
+
+const x: C2 bool int;
+
+const y: Field int bool;
+
+const z: Set int bool;
+
+const d: <a,b>[notAllParams a b]int;
+
+type ref;
+<console>(10,-1): Error: type synonym could not be resolved because of cycles: Cyclic0 (replacing body with "bool" to continue resolving)
+<console>(12,-1): Error: type synonym could not be resolved because of cycles: Cyclic1 (replacing body with "bool" to continue resolving)
+<console>(14,-1): Error: type synonym could not be resolved because of cycles: AlsoCyclic (replacing body with "bool" to continue resolving)
+<console>(24,8): Error: type constructor received wrong number of arguments: Field
+<console>(26,8): Error: type synonym received wrong number of arguments: Set
+<console>(28,8): Error: type variable must occur in map arguments: a
+6 name resolution errors detected in TypeSynonyms0.bpl
+
+type Set a = [a]bool;
+
+function union<a>(x: Set a, y: Set a) returns (Set a);
+
+axiom (forall<a> x: Set a, y: Set a, z: a :: (x[z] || y[z]) == union(x, y)[z]);
+
+const intSet0: Set int;
+
+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));
+
+procedure P();
+
+
+
+implementation P()
+{
+ assert (forall x: int :: union(intSet0, intSet1)[x] == (x == 0 - 5 || x == 0 || x == 2 || x == 3));
+}
+
+
+
+type Set a = [a]bool;
+
+function union<a>(x: Set a, y: Set a) returns (Set a);
+
+axiom (forall<a> x: Set a, y: Set a, z: a :: x[z] || y[z] <==> union(x, y)[z]);
+
+const intSet0: Set int;
+
+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);
+
+procedure P();
+
+
+
+implementation P()
+{
+ assert (forall x: int :: union(intSet0, intSet1)[x] <==> x == 0 - 5 || x == 0 || x == 2 || x == 3);
+}
+
+
+
+Boogie program verifier finished with 0 verified, 0 errors
+PolyPolyPoly.bpl(12,26): Error: invalid argument types ([]? and <a>[]C a) to binary operator ==
+PolyPolyPoly.bpl(15,23): Error: invalid argument types ([]? and <a>[]C a) to binary operator ==
+PolyPolyPoly.bpl(21,57): Error: invalid type for argument 1 in map select: b (expected: a)
+3 type checking errors detected in PolyPolyPoly.bpl
+PolyPolyPoly2.bpl(5,8): Warning: type parameter a is ambiguous, instantiating to int
+PolyPolyPoly2.bpl(7,8): Warning: type parameter a is ambiguous, instantiating to <arg0,res>[arg0]res
+PolyPolyPoly2.bpl(11,8): Warning: type parameter a is ambiguous, instantiating to bv0
+PolyPolyPoly2.bpl(11,15): Warning: type parameter a is ambiguous, instantiating to bv0
+PolyPolyPoly2.bpl(11,27): Warning: type parameter a is ambiguous, instantiating to bv17
+PolyPolyPoly2.bpl(12,8): Warning: type parameter a is ambiguous, instantiating to bv17
+PolyPolyPoly2.bpl(12,15): Warning: type parameter a is ambiguous, instantiating to bv0
+PolyPolyPoly2.bpl(22,7): Warning: type parameter a is ambiguous, instantiating to int
+PolyPolyPoly2.bpl(31,3): Warning: type parameter a is ambiguous, instantiating to int
+PolyPolyPoly2.bpl(32,3): Warning: type parameter a is ambiguous, instantiating to int
+
+Boogie program verifier finished with 0 verified, 0 errors
+ProcParamReordering.bpl(13,15): Error: mismatched type of in-parameter in implementation P: y (named b in implementation)
+ProcParamReordering.bpl(15,15): Error: mismatched number of type parameters in procedure implementation: P
+2 type checking errors detected in ProcParamReordering.bpl
+ParallelAssignment.bpl(17,2): Error: mismatched types in assignment command (cannot assign bool to int)
+ParallelAssignment.bpl(18,4): Error: invalid type for argument 0 in map assignment: bool (expected: int)
+ParallelAssignment.bpl(20,4): Error: command assigns to a global variable that is not in the enclosing method's modifies clause: z
+3 type checking errors detected in ParallelAssignment.bpl
+ParallelAssignment2.bpl(9,7): Error: number of left-hand sides does not match number of right-hand sides
+ParallelAssignment2.bpl(10,9): Error: variable a is assigned more than once in parallel assignment
+2 name resolution errors detected in ParallelAssignment2.bpl
+Coercions.bpl(11,8): Error: int cannot be coerced to E <a>[a]int
+Coercions.bpl(13,8): Error: C cannot be coerced to D
+Coercions.bpl(15,9): Error: int cannot be coerced to D
+Coercions.bpl(16,9): Error: int cannot be coerced to E int
+4 type checking errors detected in Coercions.bpl
+
+Boogie program verifier finished with 0 verified, 0 errors
diff --git a/Test/test20/Coercions.bpl b/Test/test20/Coercions.bpl
new file mode 100644
index 00000000..cab68149
--- /dev/null
+++ b/Test/test20/Coercions.bpl
@@ -0,0 +1,17 @@
+
+
+type C, D, E _;
+
+const x:int;
+const c:C;
+const d:D;
+
+axiom (x:int > 0);
+axiom (x:int < 0);
+axiom (x:E <a>[a]int < 0); // impossible coercion
+
+axiom (c:D == d); // impossible coercion
+
+axiom (15:D == d); // impossible coercion
+axiom (15:E int == d); // impossible coercion
+axiom ((18*15):int == 0);
diff --git a/Test/test20/EmptySeq.bpl b/Test/test20/EmptySeq.bpl
new file mode 100644
index 00000000..8fecfdf4
--- /dev/null
+++ b/Test/test20/EmptySeq.bpl
@@ -0,0 +1,6 @@
+type Seq T;
+
+function Seq#Length<T>(Seq T) returns (int);
+function Seq#Empty<T>() returns (Seq T);
+
+axiom (forall<T> :: Seq#Length(Seq#Empty(): Seq T) == 0);
diff --git a/Test/test20/Output b/Test/test20/Output
new file mode 100644
index 00000000..a4b991f7
--- /dev/null
+++ b/Test/test20/Output
@@ -0,0 +1,192 @@
+TypeDecls0.bpl(20,5): Error: more than one declaration of type name: C
+TypeDecls0.bpl(13,12): Error: more than one declaration of type variable: a
+TypeDecls0.bpl(14,18): Error: more than one declaration of type variable: a
+TypeDecls0.bpl(18,17): Error: type variable must occur in map arguments: b
+TypeDecls0.bpl(22,9): Error: type constructor received wrong number of arguments: C
+TypeDecls0.bpl(24,9): Error: undeclared type: A0
+TypeDecls0.bpl(25,9): Error: undeclared type: F
+TypeDecls0.bpl(28,9): Error: type constructor received wrong number of arguments: E
+TypeDecls0.bpl(30,9): Error: type constructor received wrong number of arguments: E
+TypeDecls0.bpl(32,9): Error: type constructor received wrong number of arguments: E
+TypeDecls0.bpl(38,11): Error: type constructor received wrong number of arguments: E
+TypeDecls0.bpl(38,13): Error: type constructor received wrong number of arguments: E
+12 name resolution errors detected in TypeDecls0.bpl
+TypeDecls1.bpl(7,13): Error: invalid type for argument 0 in map select: int (expected: <b>[b]a)
+TypeDecls1.bpl(13,25): Error: right-hand side in map store with wrong type: int (expected: bool)
+TypeDecls1.bpl(19,36): Error: invalid type for argument 0 in map select: <c>[c]c (expected: <b>[b]a)
+TypeDecls1.bpl(21,13): Error: invalid type for argument 0 in map select: <a>[<b>[b]a]bool (expected: <b>[b]a)
+4 type checking errors detected in TypeDecls1.bpl
+Prog0.bpl(17,10): Error: type variable must occur in map arguments: a
+Prog0.bpl(29,27): Error: more than one declaration of type variable: beta
+Prog0.bpl(32,22): Error: undeclared type: alpha
+Prog0.bpl(33,35): Error: undeclared type: alpha
+4 name resolution errors detected in Prog0.bpl
+Prog1.bpl(18,11): Error: invalid type for argument 0 in map select: int (expected: ref)
+Prog1.bpl(19,14): Error: invalid type for argument 1 in map select: int (expected: Field a)
+Prog1.bpl(20,17): Error: invalid argument types (bool and int) to binary operator >=
+3 type checking errors detected in Prog1.bpl
+Prog2.bpl(6,14): Error: trigger does not mention alpha, which does not occur in variables types either
+1 type checking errors detected in Prog2.bpl
+PolyFuns0.bpl(23,33): Error: invalid type for argument 1 in application of fieldValue: ref (expected: Field a)
+PolyFuns0.bpl(40,18): Error: invalid type for argument 1 in application of lessThan: bool (expected: a)
+PolyFuns0.bpl(41,43): Error: invalid type for argument 1 in application of lessThan: b (expected: a)
+PolyFuns0.bpl(53,55): Error: invalid argument types (<c>[Field c]a and <d>[Field d]d) to binary operator ==
+4 type checking errors detected in PolyFuns0.bpl
+PolyFuns1.bpl(10,9): Error: invalid type for argument 0 in application of F: <c>[c]c (expected: <b>[b]a)
+PolyFuns1.bpl(11,9): Error: invalid type for argument 0 in map select: <c>[c]c (expected: <b>[b]a)
+PolyFuns1.bpl(12,31): Error: invalid type for argument 0 in application of F: <c>[c]c (expected: <b>[b]a)
+PolyFuns1.bpl(13,31): Error: invalid type for argument 0 in map select: <c>[c]c (expected: <b>[b]a)
+PolyFuns1.bpl(17,55): Error: invalid argument types (<c>[Field c]a and <d>[Field d]d) to binary operator ==
+PolyFuns1.bpl(18,55): Error: invalid argument types (<c>[Field c]a and <d>[Field d]d) to binary operator ==
+PolyFuns1.bpl(28,11): Error: invalid type for argument 0 in call to Uhu: <dd>[Field dd]dd (expected: <c>[Field c]a)
+PolyFuns1.bpl(29,15): Error: invalid type for argument 1 in call to Uhu: <cc>[Field cc]T (expected: <d>[Field d]d)
+PolyFuns1.bpl(30,12): Error: invalid argument types (<cc>[Field cc]T and <dd>[Field dd]dd) to binary operator ==
+PolyFuns1.bpl(31,12): Error: invalid argument types (<dd>[Field dd]dd and <cc>[Field cc]T) to binary operator ==
+PolyFuns1.bpl(33,15): Error: invalid type for argument 1 in call to Uhu: <ee>[Field T]ee (expected: <d>[Field d]d)
+PolyFuns1.bpl(41,11): Error: invalid argument types (<a>[a,a]int and <b>[b,int]int) to binary operator ==
+PolyFuns1.bpl(42,11): Error: invalid argument types (<b>[b,int]int and <c>[int,c]int) to binary operator ==
+PolyFuns1.bpl(43,11): Error: invalid argument types (<a>[a,a]int and <c>[int,c]int) to binary operator ==
+PolyFuns1.bpl(50,11): Error: invalid argument types (<a,b>[a,a,b]int and <a,b>[a,b,b]int) to binary operator ==
+PolyFuns1.bpl(57,54): Error: invalid argument types (Field b and NagainCtor b) to binary operator ==
+16 type checking errors detected in PolyFuns1.bpl
+PolyProcs0.bpl(11,16): Error: invalid type for argument 0 in map select: Field b (expected: ref)
+PolyProcs0.bpl(11,19): Error: invalid type for argument 1 in map select: ref (expected: Field a)
+PolyProcs0.bpl(21,30): Error: invalid type for argument 1 in call to FieldAccess: Field int (expected: ref)
+PolyProcs0.bpl(21,34): Error: invalid type for argument 2 in call to FieldAccess: ref (expected: Field b)
+PolyProcs0.bpl(25,7): Error: invalid type for out-parameter 0 in call to FieldAccess: bool (expected: int)
+PolyProcs0.bpl(26,35): Error: invalid type for argument 2 in call to FieldAccess: ref (expected: Field b)
+PolyProcs0.bpl(41,35): Error: invalid type for argument 1 in call forall to injective: Field int (expected: ref)
+7 type checking errors detected in PolyProcs0.bpl
+TypeSynonyms0.bpl(9,5): Error: type synonym could not be resolved because of cycles: Cyclic0 (replacing body with "bool" to continue resolving)
+TypeSynonyms0.bpl(10,5): Error: type synonym could not be resolved because of cycles: Cyclic1 (replacing body with "bool" to continue resolving)
+TypeSynonyms0.bpl(12,5): Error: type synonym could not be resolved because of cycles: AlsoCyclic (replacing body with "bool" to continue resolving)
+TypeSynonyms0.bpl(22,10): Error: type constructor received wrong number of arguments: Field
+TypeSynonyms0.bpl(23,10): Error: type synonym received wrong number of arguments: Set
+TypeSynonyms0.bpl(26,10): Error: type variable must occur in map arguments: a
+6 name resolution errors detected in TypeSynonyms0.bpl
+TypeSynonyms1.bpl(46,8): Error: invalid type for argument 0 in application of h: <b>[b,b,<b2>[b2,b,int]int]int (expected: nested2)
+1 type checking errors detected in TypeSynonyms1.bpl
+
+Boogie program verifier finished with 1 verified, 0 errors
+
+type Set a = [a]bool;
+
+type Field _;
+
+type Heap = <a>[ref,Field a]a;
+
+type notAllParams a b = Field b;
+
+type Cyclic0 = Cyclic1;
+
+type Cyclic1 = Cyclic0;
+
+type AlsoCyclic a = <b>[AlsoCyclic b]int;
+
+type C _ _;
+
+type C2 b a = C a b;
+
+function f(C int bool) returns (int);
+
+const x: C2 bool int;
+
+const y: Field int bool;
+
+const z: Set int bool;
+
+const d: <a,b>[notAllParams a b]int;
+
+type ref;
+<console>(10,-1): Error: type synonym could not be resolved because of cycles: Cyclic0 (replacing body with "bool" to continue resolving)
+<console>(12,-1): Error: type synonym could not be resolved because of cycles: Cyclic1 (replacing body with "bool" to continue resolving)
+<console>(14,-1): Error: type synonym could not be resolved because of cycles: AlsoCyclic (replacing body with "bool" to continue resolving)
+<console>(24,8): Error: type constructor received wrong number of arguments: Field
+<console>(26,8): Error: type synonym received wrong number of arguments: Set
+<console>(28,8): Error: type variable must occur in map arguments: a
+6 name resolution errors detected in TypeSynonyms0.bpl
+
+type Set a = [a]bool;
+
+function union<a>(x: Set a, y: Set a) returns (Set a);
+
+axiom (forall<a> x: Set a, y: Set a, z: a :: (x[z] || y[z]) == union(x, y)[z]);
+
+const intSet0: Set int;
+
+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));
+
+procedure P();
+
+
+
+implementation P()
+{
+ assert (forall x: int :: union(intSet0, intSet1)[x] == (x == 0 - 5 || x == 0 || x == 2 || x == 3));
+}
+
+
+
+type Set a = [a]bool;
+
+function union<a>(x: Set a, y: Set a) returns (Set a);
+
+axiom (forall<a> x: Set a, y: Set a, z: a :: x[z] || y[z] <==> union(x, y)[z]);
+
+const intSet0: Set int;
+
+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);
+
+procedure P();
+
+
+
+implementation P()
+{
+ assert (forall x: int :: union(intSet0, intSet1)[x] <==> x == 0 - 5 || x == 0 || x == 2 || x == 3);
+}
+
+
+
+Boogie program verifier finished with 0 verified, 0 errors
+PolyPolyPoly.bpl(12,26): Error: invalid argument types ([]? and <a>[]C a) to binary operator ==
+PolyPolyPoly.bpl(15,23): Error: invalid argument types ([]? and <a>[]C a) to binary operator ==
+PolyPolyPoly.bpl(21,57): Error: invalid type for argument 1 in map select: b (expected: a)
+3 type checking errors detected in PolyPolyPoly.bpl
+PolyPolyPoly2.bpl(5,8): Warning: type parameter a is ambiguous, instantiating to int
+PolyPolyPoly2.bpl(7,8): Warning: type parameter a is ambiguous, instantiating to <arg0,res>[arg0]res
+PolyPolyPoly2.bpl(11,8): Warning: type parameter a is ambiguous, instantiating to bv0
+PolyPolyPoly2.bpl(11,15): Warning: type parameter a is ambiguous, instantiating to bv0
+PolyPolyPoly2.bpl(11,27): Warning: type parameter a is ambiguous, instantiating to bv17
+PolyPolyPoly2.bpl(12,8): Warning: type parameter a is ambiguous, instantiating to bv17
+PolyPolyPoly2.bpl(12,15): Warning: type parameter a is ambiguous, instantiating to bv0
+PolyPolyPoly2.bpl(22,7): Warning: type parameter a is ambiguous, instantiating to int
+PolyPolyPoly2.bpl(31,3): Warning: type parameter a is ambiguous, instantiating to int
+PolyPolyPoly2.bpl(32,3): Warning: type parameter a is ambiguous, instantiating to int
+
+Boogie program verifier finished with 0 verified, 0 errors
+ProcParamReordering.bpl(13,15): Error: mismatched type of in-parameter in implementation P: y (named b in implementation)
+ProcParamReordering.bpl(15,15): Error: mismatched number of type parameters in procedure implementation: P
+2 type checking errors detected in ProcParamReordering.bpl
+ParallelAssignment.bpl(17,2): Error: mismatched types in assignment command (cannot assign bool to int)
+ParallelAssignment.bpl(18,4): Error: invalid type for argument 0 in map assignment: bool (expected: int)
+ParallelAssignment.bpl(20,4): Error: command assigns to a global variable that is not in the enclosing method's modifies clause: z
+3 type checking errors detected in ParallelAssignment.bpl
+ParallelAssignment2.bpl(9,7): Error: number of left-hand sides does not match number of right-hand sides
+ParallelAssignment2.bpl(10,9): Error: variable a is assigned more than once in parallel assignment
+2 name resolution errors detected in ParallelAssignment2.bpl
+Coercions.bpl(11,8): Error: int cannot be coerced to E <a>[a]int
+Coercions.bpl(13,8): Error: C cannot be coerced to D
+Coercions.bpl(15,9): Error: int cannot be coerced to D
+Coercions.bpl(16,9): Error: int cannot be coerced to E int
+4 type checking errors detected in Coercions.bpl
+
+Boogie program verifier finished with 0 verified, 0 errors
diff --git a/Test/test20/ParallelAssignment.bpl b/Test/test20/ParallelAssignment.bpl
new file mode 100644
index 00000000..3ca196c8
--- /dev/null
+++ b/Test/test20/ParallelAssignment.bpl
@@ -0,0 +1,23 @@
+// Examples from the Boogie2 language report
+// (stuff where resolution succeeds, but typechecking might fail)
+
+type C, D;
+
+var x : int;
+var y : int;
+var z : int;
+var a : [int]int;
+var b : [int][C, D]int;
+
+procedure P(i:int, j:int, m:C, n:D) returns () modifies x, y, a, b; {
+ x := x+1;
+ a[i] := 12;
+ x, y := y, x;
+ x, a[i] := x+1, x;
+ x := true; // type error
+ a[true] := 5; // type error
+
+ z := 23; // assignment to non-modifiable variable
+ b[i][m, n] := 17;
+ b[i][m, n], x := a[x], y;
+} \ No newline at end of file
diff --git a/Test/test20/ParallelAssignment2.bpl b/Test/test20/ParallelAssignment2.bpl
new file mode 100644
index 00000000..7d1f0daf
--- /dev/null
+++ b/Test/test20/ParallelAssignment2.bpl
@@ -0,0 +1,11 @@
+// Examples from the Boogie2 language report
+// (examples where already resolution fails)
+
+var x : int;
+var y : int;
+var a : [int]int;
+
+procedure P(i:int, j:int) returns () modifies x, y, a; {
+ x, y := 1; // wrong number of rhss
+ a[i], a[j] := a[j], a[i]; // variable assigned more than once
+} \ No newline at end of file
diff --git a/Test/test20/PolyFuns0.bpl b/Test/test20/PolyFuns0.bpl
new file mode 100644
index 00000000..938bc197
--- /dev/null
+++ b/Test/test20/PolyFuns0.bpl
@@ -0,0 +1,55 @@
+
+
+function size<alpha>(x : alpha) returns (int);
+
+axiom (forall x:int :: size(x) == 0);
+axiom (forall<alpha> x:alpha :: size(x) >= 0);
+
+axiom (forall m:[int]int, x:int :: size(m) >= m[x]);
+axiom (forall m:<a>[a]int :: size(m) == 13);
+
+type Field a;
+
+function fieldValue<a>(ref, Field a) returns (a);
+
+const intField : Field int;
+const refField : Field ref;
+const obj : ref;
+const someInt : int;
+
+axiom someInt == fieldValue(obj, intField);
+axiom someInt == fieldValue(fieldValue(obj, refField), intField);
+
+axiom someInt == fieldValue(obj, fieldValue(obj, refField)); // error: wrong argument type
+
+axiom (forall<a> f : Field a ::
+ (exists x:a :: fieldValue(obj, f) == x));
+
+axiom (forall<beta, alpha> a:alpha, b:beta ::
+ a == b ==> (exists c:alpha :: c == b));
+axiom (forall<a> f : Field a ::
+ (exists<b> x:b :: fieldValue(obj, f) == x));
+axiom (forall<a> f : Field a ::
+ (exists x:int :: fieldValue(obj, f) == x));
+
+function lessThan<a>(x : a, y : a) returns (bool);
+
+axiom (forall x:int, y:int :: x < y ==> lessThan(x, y));
+axiom lessThan(false, true);
+
+axiom lessThan(5, true); // error: incompatible arguments
+axiom (forall<a,b> x:a, y:b :: lessThan(x, y)); // error: incompatible arguments
+
+function lessThan2<a,b>(x : a, y : b) returns (bool);
+
+axiom (forall<a> x:a, y:a :: lessThan(x,y) == lessThan2(x,y));
+axiom (forall<a> x:a :: (exists m:a :: (forall y:a :: lessThan2(m, y))));
+
+axiom (exists<a,b> x:a, y:b :: lessThan2(x, y) == lessThan2(y, x));
+
+axiom (exists<a,b> x:<c>[Field c]a, y:<d>[Field d]b :: x == y);
+axiom (exists<a> x:<c>[Field c]a, y:<d>[Field d]int :: x == y);
+axiom (exists<a> x:<c>[Field c]int, y:<d>[Field d]a :: x == y);
+axiom (exists<a> x:<c>[Field c]a, y:<d>[Field d]d :: x == y); // error: not unifiable
+
+type ref;
diff --git a/Test/test20/PolyFuns1.bpl b/Test/test20/PolyFuns1.bpl
new file mode 100644
index 00000000..eaca67bf
--- /dev/null
+++ b/Test/test20/PolyFuns1.bpl
@@ -0,0 +1,59 @@
+
+function F<a>( <b>[b]a ) returns (bool);
+const M: <a>[ <b>[b]a ] bool;
+
+procedure P()
+{
+ var f: <c>[c]c;
+ var b: bool;
+
+ b := F(f); // type error
+ b := M[f]; // type error
+ b := (forall g: <c>[c]c :: F(g)); // type error
+ b := (forall g: <c>[c]c :: M[g]); // type error
+}
+
+type Field a;
+axiom (exists<a> x:<c>[Field c]a, y:<d>[Field d]d :: x == y); // error: not unifiable
+axiom (forall<a> x:<c>[Field c]a, y:<d>[Field d]d :: x == y); // error: not unifiable
+
+procedure Uhu<a>(x: <c>[Field c]a, y: <d>[Field d]d);
+procedure Oyeah<T>(t: T)
+{
+ var xx: <cc>[Field cc]T;
+ var yy: <dd>[Field dd]dd;
+ var zz: <ee>[Field T]ee;
+
+ call Uhu(xx, yy);
+ call Uhu(yy, yy); // type error in argument 0
+ call Uhu(xx, xx); // type error in argument 1
+ assert xx == yy; // error: not unifiable
+ assert yy == xx; // error: not unifiable
+
+ call Uhu(xx, zz); // type error in argument 1
+}
+
+procedure Jitters()
+{
+ var x: <a>[a,a]int;
+ var y: <b>[b,int]int;
+ var z: <c>[int,c]int;
+ assert x == y; // error: not unifiable
+ assert y == z; // error: not unifiable
+ assert x == z; // error: not unifiable
+}
+
+procedure Nuther()
+{
+ var x: <a,b>[a,a,b]int;
+ var y: <a,b>[a,b,b]int;
+ assert x == y; // error: not unifiable
+}
+
+type NagainCtor a;
+procedure Nagain()
+ requires (forall<a,b> x: a, y: b :: x == y);
+ ensures (forall<a,b> x: a, y: Field b, z: NagainCtor b :: x == y && x == z);
+ ensures (forall<b> y: Field b, z: NagainCtor b :: y == z); // error: types not unifiable
+{
+}
diff --git a/Test/test20/PolyPolyPoly.bpl b/Test/test20/PolyPolyPoly.bpl
new file mode 100644
index 00000000..8666d1fc
--- /dev/null
+++ b/Test/test20/PolyPolyPoly.bpl
@@ -0,0 +1,22 @@
+
+type C _;
+
+const p: <a>[]a;
+const q: <a>[a, a]a;
+const r: <a>[](C a);
+
+const x: C int;
+const y: C bool;
+
+axiom (p[][:= 5][:= true] == p);
+axiom (p[][:= 5][:= true] == r); // error
+axiom (p[][:= x][:= y] == p);
+axiom (p[][:= x][:= y] == r);
+axiom (p[][:= x][:= 5] == r); // error
+axiom (p[][:= x][:= y] == p[][:= 5][:= true]);
+axiom (q[p[][:= x][:= y], p[][:= 5][:= true]] == p);
+axiom (q[p[], p[]][:= 5][:= true] == p);
+
+axiom (exists<a> x:a :: p[][:= 5][:= true] == x);
+axiom (exists<a,b> x:a, y:b :: p[][:= 5][:= true] == q[x,y]); // error
+axiom (exists<a,b> x:a, y:b :: q[x, x] == q[y, y]);
diff --git a/Test/test20/PolyPolyPoly2.bpl b/Test/test20/PolyPolyPoly2.bpl
new file mode 100644
index 00000000..b07c565a
--- /dev/null
+++ b/Test/test20/PolyPolyPoly2.bpl
@@ -0,0 +1,34 @@
+
+const p: <a>[]a;
+const q: <a,b>[a]b;
+
+axiom (p[] == p[]); // warning
+axiom (p[][13 := false] == q);
+axiom (p[][13 := false] == p[]); // warning
+
+const c: bv17;
+
+axiom (p[] ++ p[] ++ c == p[]); // warning
+axiom (p[] ++ p[] == c); // warning
+axiom (p[] == c);
+
+type List _;
+
+function emptyList<a>() returns (List a);
+function append<a>(List a, List a) returns (List a);
+
+axiom (forall<a> l:List a :: append(emptyList(), l) == l);
+axiom (forall<a> l:List a :: append(l, emptyList()) == l);
+axiom (append(emptyList(), emptyList()) == emptyList()); // warning
+axiom (forall<a> l:List a :: l==emptyList() ==> append(l, emptyList()) == emptyList());
+
+var x: <a>[]a;
+var y: <a>[a]a;
+
+procedure P() returns () modifies x, y; {
+ x[] := 15;
+ x[] := false;
+ x[] := p[]; // warning
+ x[] := q[false]; // warning
+ y[13] := q[false];
+} \ No newline at end of file
diff --git a/Test/test20/PolyProcs0.bpl b/Test/test20/PolyProcs0.bpl
new file mode 100644
index 00000000..609f1167
--- /dev/null
+++ b/Test/test20/PolyProcs0.bpl
@@ -0,0 +1,44 @@
+
+
+type Field a;
+
+function FieldAccessFun<b>(heap : <a>[ref, Field a]a, obj : ref, f : Field b)
+ returns (res:b);
+
+procedure FieldAccess<b>(heap : <a>[ref, Field a]a, obj : ref, f : Field b)
+ returns (res:b) {
+ start:
+ res := heap[f, obj]; // error: wrong argument order
+ res := heap[obj, f];
+ assert res == FieldAccessFun(heap, obj, f);
+ return;
+}
+
+procedure UseHeap(heap : <a>[ref, Field a]a) {
+ var f1 : Field int; var f2 : Field bool; var obj : ref;
+ var x : int; var y : bool;
+
+ call x := FieldAccess(heap, f1, obj); // error: wrong argument order
+ call x := FieldAccess(heap, obj, f1);
+ call y := FieldAccess(heap, obj, f2);
+
+ call y := FieldAccess(heap, obj, f1); // error: wrong result type
+ call x := FieldAccess(heap, obj, obj); // error: wrong argument type
+}
+
+procedure injective<b>(heap : <a>[ref, Field a]a, obj0 : ref, obj1 : ref, f : Field b);
+ requires obj0 != obj1;
+ ensures heap[obj0, f] != heap[obj1, f];
+
+procedure testCallForall(heap : <a>[ref, Field a]a) {
+ var f1 : Field int; var f2 : Field bool;
+
+ start:
+ call forall injective(heap, *, *, f1);
+ call forall injective(heap, *, *, f2);
+ call forall injective(heap, *, *, *);
+
+ call forall injective(heap, *, f1, *); // error: wrong argument type
+}
+
+type ref;
diff --git a/Test/test20/ProcParamReordering.bpl b/Test/test20/ProcParamReordering.bpl
new file mode 100644
index 00000000..404b41a3
--- /dev/null
+++ b/Test/test20/ProcParamReordering.bpl
@@ -0,0 +1,15 @@
+
+type C _;
+
+
+procedure P<a, b>(x : a, y : b) returns ();
+
+implementation P<a, b>(x : a, y : b) returns () {}
+
+implementation P<c, d>(a : c, b : d) returns () {}
+
+implementation P<d, c>(a : c, b : d) returns () {}
+
+implementation P<d, c>(a : c, b : C d) returns () {}
+
+implementation P<a>(x : a, y : a) returns () {} \ No newline at end of file
diff --git a/Test/test20/Prog0.bpl b/Test/test20/Prog0.bpl
new file mode 100644
index 00000000..ea71b8a8
--- /dev/null
+++ b/Test/test20/Prog0.bpl
@@ -0,0 +1,35 @@
+// Let's test some Boogie 2 features ...
+type real;
+type elements;
+
+type Field a;
+var heap : <a> [ref, Field a] a;
+
+const emptyset : <a> [a] bool;
+
+function union(<a> [a] bool, <a> [a] bool) returns (<a> [a] bool);
+
+axiom (forall x : <a> [a] bool, y : <a> [a] bool,
+ z : int ::
+ { union(x, y)[z] }
+ union(x, y)[z] == (x[z] || y[z]));
+
+var tau : <a> [ref] int; // error: type variable has to occur in arguments
+
+axiom (forall x : int :: !emptyset[x]);
+
+// the more general version of the axiom that also uses type quantifiers
+
+axiom (forall<alpha>
+ x : <a> [a] bool, y : <a> [a] bool,
+ z : alpha ::
+ { union(x, y)[z] }
+ union(x, y)[z] == (x[z] || y[z]));
+
+axiom (forall<beta, alpha, beta> a:alpha, b:beta :: // error: variable bound twice
+ a == b ==> (exists c:alpha :: c == b));
+
+axiom (forall<beta> a:alpha, b:beta :: // error: alpha is not declared
+ a == b ==> (exists c:alpha :: c == b));
+
+type ref;
diff --git a/Test/test20/Prog1.bpl b/Test/test20/Prog1.bpl
new file mode 100644
index 00000000..1d75805c
--- /dev/null
+++ b/Test/test20/Prog1.bpl
@@ -0,0 +1,26 @@
+// Let's test some Boogie 2 features ...
+type real;
+type elements;
+
+type Field a;
+var heap : <a> [ref, Field a] a;
+
+
+
+procedure p (x:int, y:ref, z:<a> [ref, Field a] a) returns (newHeap : <a> [ref, Field a] a) {
+
+ var f : Field int;
+ var g : Field bool;
+
+ var heap : <a> [ref, Field a] a;
+
+ assert z[y, f] >= 0;
+ assert z[x, f] >= 0; // error: x has wrong type
+ assert z[y, x] >= 0; // error: x has wrong type
+ assert z[y, g] >= 0; // error: result of map select has wrong type
+
+ heap[y, g] := false;
+
+}
+
+type ref;
diff --git a/Test/test20/Prog2.bpl b/Test/test20/Prog2.bpl
new file mode 100644
index 00000000..43b9b28f
--- /dev/null
+++ b/Test/test20/Prog2.bpl
@@ -0,0 +1,16 @@
+function union(<a> [a] bool, <a> [a] bool) returns (<a> [a] bool);
+
+axiom (forall<alpha> // error: alpha has to occur in dummy types
+ x : <a> [a] bool, y : <a> [a] bool,
+ z : int ::
+ { union(x, y)[z] }
+ union(x, y)[z] == (x[z] || y[z]));
+
+function poly<a>() returns (a);
+
+axiom (forall<alpha>
+ x : <a> [a] bool, y : <a> [a] bool,
+ z : int ::
+ { union(x, y)[z], poly() : alpha }
+ union(x, y)[z] == (x[z] || y[z]));
+
diff --git a/Test/test20/TypeDecls0.bpl b/Test/test20/TypeDecls0.bpl
new file mode 100644
index 00000000..898e0d1a
--- /dev/null
+++ b/Test/test20/TypeDecls0.bpl
@@ -0,0 +1,45 @@
+type C a _ b;
+type D;
+type E _;
+
+var A0 : D;
+
+var A1 : C D D D;
+
+var A2 : <a,b> [b, C a b D] C a D [D]a;
+
+var A3 : <a,b> [b, C a int D] C bool ref [bv32]a;
+
+var A4 : <a,a> [a] a; // error: a bound twice
+var A5 : <a> [a] <a> [a] int; // error: a bound twice
+
+var A6 : <a> [a] <b> [b] int;
+
+var A7 : <a> [a] <b> [int] int; // error: b does not occur as map argument
+
+type C _ _; // error: C is already declared
+
+var A8 : C int ref; // error: wrong number of arguments
+
+var A9 : A0; // error: undeclared type
+var A10: F int; // error: undeclared type
+
+var A11: E D;
+var A12: E E D; // error: wrong number of arguments
+var A13: E (E D);
+var A14: E E E D; // error: wrong number of arguments
+
+var A15: E E int; // error: wrong number of arguments
+var A16: E (E int);
+
+var A17: bv64;
+var A18: [int] bv64;
+
+var A19: C E E D; // error: wrong number of arguments
+var A20: C (E (E D)) int [int] int;
+var A21: C (<a> [a] <b> [b] int) int [int] int;
+
+var A22: (D);
+var A23: ((D));
+
+type ref;
diff --git a/Test/test20/TypeDecls1.bpl b/Test/test20/TypeDecls1.bpl
new file mode 100644
index 00000000..02c5536a
--- /dev/null
+++ b/Test/test20/TypeDecls1.bpl
@@ -0,0 +1,23 @@
+
+// set of maps from anything to a specific type a
+const mapSet : <a>[<b>[b]a]bool;
+
+const emptySet : <a>[a]bool;
+
+axiom mapSet[5]; // type error
+
+axiom mapSet[emptySet] == true;
+
+axiom mapSet[emptySet := false] != mapSet;
+
+axiom mapSet[emptySet := 5] == mapSet; // type error
+
+axiom emptySet[13 := true][13] == true;
+
+axiom (forall f : <c>[c]int, x : ref :: mapSet[f] ==> f[x] >= 0);
+
+axiom (forall f : <c>[c]c :: mapSet[f]); // type error
+
+axiom mapSet[mapSet] == true; // type error
+
+type ref;
diff --git a/Test/test20/TypeSynonyms0.bpl b/Test/test20/TypeSynonyms0.bpl
new file mode 100644
index 00000000..d161b5df
--- /dev/null
+++ b/Test/test20/TypeSynonyms0.bpl
@@ -0,0 +1,29 @@
+
+
+type Set a = [a]bool;
+
+type Field a, Heap = <a>[ref, Field a]a;
+
+type notAllParams a b = Field b;
+
+type Cyclic0 = Cyclic1;
+type Cyclic1 = Cyclic0;
+
+type AlsoCyclic a = <b>[AlsoCyclic b]int;
+
+type C a b;
+
+type C2 b a = C a b;
+
+function f(C int bool) returns (int);
+const x : C2 bool int;
+
+
+const y : Field int bool; // wrong number of arguments
+const z : Set int bool; // wrong number of arguments
+
+
+const d : <a,b>[notAllParams a b]int; // error: not all parameters are used
+
+
+type ref;
diff --git a/Test/test20/TypeSynonyms1.bpl b/Test/test20/TypeSynonyms1.bpl
new file mode 100644
index 00000000..45b7e46d
--- /dev/null
+++ b/Test/test20/TypeSynonyms1.bpl
@@ -0,0 +1,47 @@
+
+
+
+type C a b;
+type C2 b a = C a b;
+
+
+// ordering of map type parameters
+function g0(<a,b>[C2 a b]int) returns (int);
+function g1(<a,b>[C2 b a]int) returns (int);
+function g2(<a,b>[C a b]int) returns (int);
+function g3(<a,b>[C b a]int) returns (int);
+
+const c0 : <a,b>[C2 a b]int;
+const c1 : <a,b>[C2 b a]int;
+const c2 : <a,b>[C a b]int;
+const c3 : <a,b>[C b a]int;
+
+axiom g0(c0) == 0;
+axiom g1(c0) == 0;
+axiom g2(c0) == 0;
+axiom g3(c0) == 0;
+axiom g0(c1) == 0;
+axiom g1(c1) == 0;
+axiom g2(c1) == 0;
+axiom g3(c1) == 0;
+axiom g0(c2) == 0;
+axiom g1(c2) == 0;
+axiom g2(c2) == 0;
+axiom g3(c2) == 0;
+axiom g0(c3) == 0;
+axiom g1(c3) == 0;
+axiom g2(c3) == 0;
+axiom g3(c3) == 0;
+
+
+type nested a = <b>[b, b, a]int;
+type nested2 = nested (nested int);
+
+
+function h(nested2) returns (bool);
+const e : <b>[b, b, <b2>[b2, b2, int]int]int;
+axiom h(e);
+
+const e2 : <b>[b, b, <b2>[b2, b, int]int]int; // wrong binding
+axiom h(e2);
+
diff --git a/Test/test20/TypeSynonyms2.bpl b/Test/test20/TypeSynonyms2.bpl
new file mode 100644
index 00000000..f6fee1f3
--- /dev/null
+++ b/Test/test20/TypeSynonyms2.bpl
@@ -0,0 +1,20 @@
+
+
+type Set a = [a]bool;
+
+function union<a>(x : Set a, y : Set a) returns (Set a);
+axiom (forall<a> x : Set a, y : Set a, z : a :: (x[z] || y[z]) == union(x, y)[z]);
+
+
+const intSet0 : Set int;
+axiom (forall x:int :: intSet0[x] == (x == 0 || x == 2 || x == 3));
+
+const intSet1 : Set int;
+axiom (forall x:int :: intSet1[x] == (x == -5 || x == 3));
+
+
+procedure P() returns () {
+ assert (forall x:int :: union(intSet0, intSet1)[x] ==
+ (x == -5 || x == 0 || x == 2 || x == 3));
+}
+
diff --git a/Test/test20/runtest.bat b/Test/test20/runtest.bat
new file mode 100644
index 00000000..0e607a1f
--- /dev/null
+++ b/Test/test20/runtest.bat
@@ -0,0 +1,26 @@
+@echo off
+setlocal
+
+set BGEXE=..\..\Binaries\Boogie.exe
+rem set BGEXE=mono ..\..\Binaries\Boogie.exe
+
+%BGEXE% %* /noVerify TypeDecls0.bpl
+%BGEXE% %* /noVerify TypeDecls1.bpl
+%BGEXE% %* /noVerify Prog0.bpl
+%BGEXE% %* /noVerify Prog1.bpl
+%BGEXE% %* /noVerify Prog2.bpl
+%BGEXE% %* /noVerify PolyFuns0.bpl
+%BGEXE% %* /noVerify PolyFuns1.bpl
+%BGEXE% %* /noVerify PolyProcs0.bpl
+%BGEXE% %* /noVerify TypeSynonyms0.bpl
+%BGEXE% %* /noVerify TypeSynonyms1.bpl
+%BGEXE% %* TypeSynonyms2.bpl
+%BGEXE% %* /noVerify /print:- /env:0 TypeSynonyms0.bpl
+%BGEXE% %* /noVerify /print:- /env:0 /printDesugared TypeSynonyms2.bpl
+%BGEXE% %* /noVerify PolyPolyPoly.bpl
+%BGEXE% %* /noVerify PolyPolyPoly2.bpl
+%BGEXE% %* /noVerify ProcParamReordering.bpl
+%BGEXE% %* /noVerify ParallelAssignment.bpl
+%BGEXE% %* /noVerify ParallelAssignment2.bpl
+%BGEXE% %* /noVerify Coercions.bpl
+%BGEXE% %* /noVerify EmptySeq.bpl
diff --git a/Test/test21/Answer b/Test/test21/Answer
new file mode 100644
index 00000000..bda444d2
--- /dev/null
+++ b/Test/test21/Answer
@@ -0,0 +1,1677 @@
+--------------------- TypeEncoding n ----------------------------
+--------------------- File DisjointDomains.bpl ----------------------------
+
+Boogie program verifier finished with 3 verified, 0 errors
+--------------------- File DisjointDomains2.bpl ----------------------------
+DisjointDomains2.bpl(11,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ DisjointDomains2.bpl(9,3): start
+DisjointDomains2.bpl(18,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ DisjointDomains2.bpl(16,3): start
+
+Boogie program verifier finished with 4 verified, 2 errors
+--------------------- File FunAxioms.bpl ----------------------------
+FunAxioms.bpl(30,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ FunAxioms.bpl(18,3): anon0
+
+Boogie program verifier finished with 1 verified, 1 error
+--------------------- File FunAxioms2.bpl ----------------------------
+FunAxioms2.bpl(20,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ FunAxioms2.bpl(16,5): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File PolyList.bpl ----------------------------
+PolyList.bpl(42,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ PolyList.bpl(27,7): anon0
+PolyList.bpl(60,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ PolyList.bpl(49,7): anon0
+
+Boogie program verifier finished with 0 verified, 2 errors
+--------------------- File Maps0.bpl ----------------------------
+Maps0.bpl(23,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Maps0.bpl(14,3): anon0
+Maps0.bpl(46,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Maps0.bpl(41,9): anon0
+Maps0.bpl(49,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Maps0.bpl(41,9): anon0
+Maps0.bpl(52,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Maps0.bpl(41,9): anon0
+Maps0.bpl(53,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Maps0.bpl(41,9): anon0
+
+Boogie program verifier finished with 1 verified, 5 errors
+--------------------- File Maps1.bpl ----------------------------
+Maps1.bpl(26,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Maps1.bpl(19,3): anon0
+Maps1.bpl(31,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Maps1.bpl(19,3): anon0
+
+Boogie program verifier finished with 0 verified, 2 errors
+--------------------- File InterestingExamples0.bpl ----------------------------
+InterestingExamples0.bpl(7,1): Error BP5001: This assertion might not hold.
+Execution trace:
+ InterestingExamples0.bpl(5,6): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File InterestingExamples1.bpl ----------------------------
+InterestingExamples1.bpl(16,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ InterestingExamples1.bpl(13,5): anon0
+InterestingExamples1.bpl(22,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ InterestingExamples1.bpl(13,5): anon0
+
+Boogie program verifier finished with 0 verified, 2 errors
+--------------------- File InterestingExamples2.bpl ----------------------------
+InterestingExamples2.bpl(9,1): Error BP5001: This assertion might not hold.
+Execution trace:
+ InterestingExamples2.bpl(8,6): anon0
+InterestingExamples2.bpl(10,1): Error BP5001: This assertion might not hold.
+Execution trace:
+ InterestingExamples2.bpl(8,6): anon0
+
+Boogie program verifier finished with 0 verified, 2 errors
+--------------------- File InterestingExamples3.bpl ----------------------------
+InterestingExamples3.bpl(15,2): Error BP5001: This assertion might not hold.
+Execution trace:
+ InterestingExamples3.bpl(13,2): anon0
+
+Boogie program verifier finished with 2 verified, 1 error
+--------------------- File InterestingExamples4.bpl ----------------------------
+InterestingExamples4.bpl(36,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ InterestingExamples4.bpl(36,3): anon0
+InterestingExamples4.bpl(39,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ InterestingExamples4.bpl(36,3): anon0
+
+Boogie program verifier finished with 0 verified, 2 errors
+--------------------- File InterestingExamples5.bpl ----------------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
+--------------------- File Colors.bpl ----------------------------
+Colors.bpl(13,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Colors.bpl(12,3): anon0
+Colors.bpl(20,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Colors.bpl(19,3): anon0
+
+Boogie program verifier finished with 0 verified, 2 errors
+--------------------- File HeapAbstraction.bpl ----------------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
+--------------------- File HeapAxiom.bpl ----------------------------
+HeapAxiom.bpl(24,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ HeapAxiom.bpl(13,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File Triggers0.bpl ----------------------------
+Triggers0.bpl(39,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Triggers0.bpl(39,3): anon0
+Triggers0.bpl(43,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Triggers0.bpl(39,3): anon0
+
+Boogie program verifier finished with 1 verified, 2 errors
+--------------------- File Triggers1.bpl ----------------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
+--------------------- File Keywords.bpl ----------------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
+--------------------- File Casts.bpl ----------------------------
+Casts.bpl(10,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Casts.bpl(6,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File EmptyList.bpl ----------------------------
+EmptyList.bpl(46,9): Warning: type parameter a is ambiguous, instantiating to List int
+EmptyList.bpl(28,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ EmptyList.bpl(26,5): anon0
+EmptyList.bpl(42,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ EmptyList.bpl(26,5): anon0
+EmptyList.bpl(46,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ EmptyList.bpl(46,3): anon0
+
+Boogie program verifier finished with 0 verified, 3 errors
+--------------------- File Boxing.bpl ----------------------------
+Boxing.bpl(19,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Boxing.bpl(15,6): anon0
+Boxing.bpl(20,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Boxing.bpl(15,6): anon0
+
+Boogie program verifier finished with 0 verified, 2 errors
+--------------------- File MapOutputTypeParams.bpl ----------------------------
+MapOutputTypeParams.bpl(29,3): Warning: type parameter a is ambiguous, instantiating to int
+MapOutputTypeParams.bpl(12,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ MapOutputTypeParams.bpl(7,9): anon0
+MapOutputTypeParams.bpl(13,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ MapOutputTypeParams.bpl(7,9): anon0
+MapOutputTypeParams.bpl(23,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ MapOutputTypeParams.bpl(19,9): anon0
+MapOutputTypeParams.bpl(24,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ MapOutputTypeParams.bpl(19,9): anon0
+MapOutputTypeParams.bpl(31,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ MapOutputTypeParams.bpl(28,8): anon0
+MapOutputTypeParams.bpl(32,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ MapOutputTypeParams.bpl(28,8): anon0
+
+Boogie program verifier finished with 0 verified, 6 errors
+--------------------- File ParallelAssignment.bpl ----------------------------
+ParallelAssignment.bpl(26,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ ParallelAssignment.bpl(15,5): anon0
+ParallelAssignment.bpl(35,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ ParallelAssignment.bpl(15,5): anon0
+ParallelAssignment.bpl(54,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ ParallelAssignment.bpl(40,11): anon0
+
+Boogie program verifier finished with 0 verified, 3 errors
+--------------------- File BooleanQuantification.bpl ----------------------------
+BooleanQuantification.bpl(10,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ BooleanQuantification.bpl(10,3): anon0
+BooleanQuantification.bpl(18,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ BooleanQuantification.bpl(18,3): anon0
+BooleanQuantification.bpl(19,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ BooleanQuantification.bpl(18,3): anon0
+BooleanQuantification.bpl(29,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ BooleanQuantification.bpl(29,3): anon0
+BooleanQuantification.bpl(31,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ BooleanQuantification.bpl(29,3): anon0
+
+Boogie program verifier finished with 1 verified, 5 errors
+--------------------- File BooleanQuantification2.bpl ----------------------------
+BooleanQuantification2.bpl(13,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ BooleanQuantification2.bpl(10,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File Flattening.bpl ----------------------------
+Flattening.bpl(12,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Flattening.bpl(12,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File Orderings.bpl ----------------------------
+Orderings.bpl(14,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Orderings.bpl(9,3): anon0
+
+Boogie program verifier finished with 1 verified, 1 error
+--------------------- File Orderings2.bpl ----------------------------
+Orderings2.bpl(17,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Orderings2.bpl(12,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File Orderings3.bpl ----------------------------
+Orderings3.bpl(29,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Orderings3.bpl(15,3): anon0
+Orderings3.bpl(34,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Orderings3.bpl(34,3): anon0
+Orderings3.bpl(36,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Orderings3.bpl(34,3): anon0
+
+Boogie program verifier finished with 0 verified, 3 errors
+--------------------- File Orderings4.bpl ----------------------------
+Orderings4.bpl(10,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Orderings4.bpl(9,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File EmptySetBug.bpl ----------------------------
+EmptySetBug.bpl(27,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ EmptySetBug.bpl(25,5): anon0
+EmptySetBug.bpl(29,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ EmptySetBug.bpl(25,5): anon0
+
+Boogie program verifier finished with 0 verified, 2 errors
+--------------------- File Coercions2.bpl ----------------------------
+Coercions2.bpl(12,23): Warning: type parameter a is ambiguous, instantiating to int
+Coercions2.bpl(18,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Coercions2.bpl(18,3): anon0
+Coercions2.bpl(23,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Coercions2.bpl(18,3): anon0
+
+Boogie program verifier finished with 0 verified, 2 errors
+--------------------- File MapAxiomsConsistency.bpl ----------------------------
+MapAxiomsConsistency.bpl(94,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ MapAxiomsConsistency.bpl(79,13): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File LargeLiterals0.bpl ----------------------------
+LargeLiterals0.bpl(18,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ LargeLiterals0.bpl(7,5): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File NameClash.bpl ----------------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
+--------------------- File LetSorting.bpl ----------------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
+--------------------- File Keywords.bpl ----------------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
+--------------------- File LargeLiterals0.bpl ----------------------------
+LargeLiterals0.bpl(18,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ LargeLiterals0.bpl(7,5): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- TypeEncoding p ----------------------------
+--------------------- File DisjointDomains.bpl ----------------------------
+DisjointDomains.bpl(14,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ DisjointDomains.bpl(11,3): start
+DisjointDomains.bpl(21,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ DisjointDomains.bpl(20,3): start
+DisjointDomains.bpl(27,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ DisjointDomains.bpl(26,3): start
+
+Boogie program verifier finished with 0 verified, 3 errors
+--------------------- File DisjointDomains2.bpl ----------------------------
+DisjointDomains2.bpl(11,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ DisjointDomains2.bpl(9,3): start
+DisjointDomains2.bpl(18,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ DisjointDomains2.bpl(16,3): start
+DisjointDomains2.bpl(32,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ DisjointDomains2.bpl(30,3): start
+DisjointDomains2.bpl(39,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ DisjointDomains2.bpl(37,3): start
+DisjointDomains2.bpl(49,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ DisjointDomains2.bpl(45,3): start
+DisjointDomains2.bpl(63,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ DisjointDomains2.bpl(58,3): start
+
+Boogie program verifier finished with 0 verified, 6 errors
+--------------------- File FunAxioms.bpl ----------------------------
+FunAxioms.bpl(30,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ FunAxioms.bpl(18,3): anon0
+
+Boogie program verifier finished with 1 verified, 1 error
+--------------------- File FunAxioms2.bpl ----------------------------
+FunAxioms2.bpl(20,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ FunAxioms2.bpl(16,5): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File PolyList.bpl ----------------------------
+PolyList.bpl(42,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ PolyList.bpl(27,7): anon0
+PolyList.bpl(60,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ PolyList.bpl(49,7): anon0
+
+Boogie program verifier finished with 0 verified, 2 errors
+--------------------- File Maps0.bpl ----------------------------
+Maps0.bpl(23,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Maps0.bpl(14,3): anon0
+Maps0.bpl(32,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Maps0.bpl(32,3): anon0
+Maps0.bpl(53,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Maps0.bpl(41,9): anon0
+
+Boogie program verifier finished with 0 verified, 3 errors
+--------------------- File Maps1.bpl ----------------------------
+Maps1.bpl(31,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Maps1.bpl(19,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File InterestingExamples0.bpl ----------------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
+--------------------- File InterestingExamples1.bpl ----------------------------
+InterestingExamples1.bpl(22,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ InterestingExamples1.bpl(13,5): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File InterestingExamples2.bpl ----------------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
+--------------------- File InterestingExamples3.bpl ----------------------------
+InterestingExamples3.bpl(15,2): Error BP5001: This assertion might not hold.
+Execution trace:
+ InterestingExamples3.bpl(13,2): anon0
+
+Boogie program verifier finished with 2 verified, 1 error
+--------------------- File InterestingExamples4.bpl ----------------------------
+InterestingExamples4.bpl(39,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ InterestingExamples4.bpl(36,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File InterestingExamples5.bpl ----------------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
+--------------------- File Colors.bpl ----------------------------
+Colors.bpl(13,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Colors.bpl(12,3): anon0
+
+Boogie program verifier finished with 1 verified, 1 error
+--------------------- File HeapAbstraction.bpl ----------------------------
+HeapAbstraction.bpl(15,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ HeapAbstraction.bpl(14,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File HeapAxiom.bpl ----------------------------
+HeapAxiom.bpl(24,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ HeapAxiom.bpl(13,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File Triggers0.bpl ----------------------------
+Triggers0.bpl(39,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Triggers0.bpl(39,3): anon0
+Triggers0.bpl(43,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Triggers0.bpl(39,3): anon0
+
+Boogie program verifier finished with 1 verified, 2 errors
+--------------------- File Triggers1.bpl ----------------------------
+Triggers1.bpl(16,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Triggers1.bpl(12,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File Keywords.bpl ----------------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
+--------------------- File Casts.bpl ----------------------------
+Casts.bpl(10,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Casts.bpl(6,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File EmptyList.bpl ----------------------------
+EmptyList.bpl(46,9): Warning: type parameter a is ambiguous, instantiating to List int
+EmptyList.bpl(42,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ EmptyList.bpl(26,5): anon0
+
+Boogie program verifier finished with 1 verified, 1 error
+--------------------- File Boxing.bpl ----------------------------
+Boxing.bpl(20,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Boxing.bpl(15,6): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File MapOutputTypeParams.bpl ----------------------------
+MapOutputTypeParams.bpl(29,3): Warning: type parameter a is ambiguous, instantiating to int
+MapOutputTypeParams.bpl(13,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ MapOutputTypeParams.bpl(7,9): anon0
+MapOutputTypeParams.bpl(24,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ MapOutputTypeParams.bpl(19,9): anon0
+MapOutputTypeParams.bpl(32,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ MapOutputTypeParams.bpl(28,8): anon0
+
+Boogie program verifier finished with 0 verified, 3 errors
+--------------------- File ParallelAssignment.bpl ----------------------------
+ParallelAssignment.bpl(26,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ ParallelAssignment.bpl(15,5): anon0
+ParallelAssignment.bpl(35,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ ParallelAssignment.bpl(15,5): anon0
+ParallelAssignment.bpl(54,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ ParallelAssignment.bpl(40,11): anon0
+
+Boogie program verifier finished with 0 verified, 3 errors
+--------------------- File BooleanQuantification.bpl ----------------------------
+BooleanQuantification.bpl(10,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ BooleanQuantification.bpl(10,3): anon0
+BooleanQuantification.bpl(18,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ BooleanQuantification.bpl(18,3): anon0
+BooleanQuantification.bpl(19,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ BooleanQuantification.bpl(18,3): anon0
+BooleanQuantification.bpl(29,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ BooleanQuantification.bpl(29,3): anon0
+BooleanQuantification.bpl(31,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ BooleanQuantification.bpl(29,3): anon0
+
+Boogie program verifier finished with 1 verified, 5 errors
+--------------------- File BooleanQuantification2.bpl ----------------------------
+BooleanQuantification2.bpl(13,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ BooleanQuantification2.bpl(10,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File Flattening.bpl ----------------------------
+Flattening.bpl(12,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Flattening.bpl(12,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File Orderings.bpl ----------------------------
+Orderings.bpl(14,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Orderings.bpl(9,3): anon0
+
+Boogie program verifier finished with 1 verified, 1 error
+--------------------- File Orderings2.bpl ----------------------------
+Orderings2.bpl(17,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Orderings2.bpl(12,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File Orderings3.bpl ----------------------------
+Orderings3.bpl(29,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Orderings3.bpl(15,3): anon0
+Orderings3.bpl(34,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Orderings3.bpl(34,3): anon0
+Orderings3.bpl(36,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Orderings3.bpl(34,3): anon0
+
+Boogie program verifier finished with 0 verified, 3 errors
+--------------------- File Orderings4.bpl ----------------------------
+Orderings4.bpl(10,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Orderings4.bpl(9,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File EmptySetBug.bpl ----------------------------
+EmptySetBug.bpl(29,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ EmptySetBug.bpl(25,5): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File Coercions2.bpl ----------------------------
+Coercions2.bpl(12,23): Warning: type parameter a is ambiguous, instantiating to int
+Coercions2.bpl(23,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Coercions2.bpl(18,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File MapAxiomsConsistency.bpl ----------------------------
+MapAxiomsConsistency.bpl(94,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ MapAxiomsConsistency.bpl(79,13): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File LargeLiterals0.bpl ----------------------------
+LargeLiterals0.bpl(18,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ LargeLiterals0.bpl(7,5): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File NameClash.bpl ----------------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
+--------------------- File LetSorting.bpl ----------------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
+--------------------- File Keywords.bpl ----------------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
+--------------------- File LargeLiterals0.bpl ----------------------------
+LargeLiterals0.bpl(18,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ LargeLiterals0.bpl(7,5): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- TypeEncoding a ----------------------------
+--------------------- File DisjointDomains.bpl ----------------------------
+DisjointDomains.bpl(14,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ DisjointDomains.bpl(11,3): start
+DisjointDomains.bpl(21,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ DisjointDomains.bpl(20,3): start
+DisjointDomains.bpl(27,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ DisjointDomains.bpl(26,3): start
+
+Boogie program verifier finished with 0 verified, 3 errors
+--------------------- File DisjointDomains2.bpl ----------------------------
+DisjointDomains2.bpl(11,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ DisjointDomains2.bpl(9,3): start
+DisjointDomains2.bpl(18,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ DisjointDomains2.bpl(16,3): start
+DisjointDomains2.bpl(32,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ DisjointDomains2.bpl(30,3): start
+DisjointDomains2.bpl(39,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ DisjointDomains2.bpl(37,3): start
+DisjointDomains2.bpl(49,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ DisjointDomains2.bpl(45,3): start
+DisjointDomains2.bpl(63,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ DisjointDomains2.bpl(58,3): start
+
+Boogie program verifier finished with 0 verified, 6 errors
+--------------------- File FunAxioms.bpl ----------------------------
+FunAxioms.bpl(30,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ FunAxioms.bpl(18,3): anon0
+
+Boogie program verifier finished with 1 verified, 1 error
+--------------------- File FunAxioms2.bpl ----------------------------
+FunAxioms2.bpl(20,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ FunAxioms2.bpl(16,5): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File PolyList.bpl ----------------------------
+PolyList.bpl(42,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ PolyList.bpl(27,7): anon0
+PolyList.bpl(60,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ PolyList.bpl(49,7): anon0
+
+Boogie program verifier finished with 0 verified, 2 errors
+--------------------- File Maps0.bpl ----------------------------
+Maps0.bpl(23,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Maps0.bpl(14,3): anon0
+Maps0.bpl(32,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Maps0.bpl(32,3): anon0
+Maps0.bpl(53,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Maps0.bpl(41,9): anon0
+
+Boogie program verifier finished with 0 verified, 3 errors
+--------------------- File Maps1.bpl ----------------------------
+Maps1.bpl(31,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Maps1.bpl(19,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File InterestingExamples0.bpl ----------------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
+--------------------- File InterestingExamples1.bpl ----------------------------
+InterestingExamples1.bpl(22,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ InterestingExamples1.bpl(13,5): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File InterestingExamples2.bpl ----------------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
+--------------------- File InterestingExamples3.bpl ----------------------------
+InterestingExamples3.bpl(15,2): Error BP5001: This assertion might not hold.
+Execution trace:
+ InterestingExamples3.bpl(13,2): anon0
+
+Boogie program verifier finished with 2 verified, 1 error
+--------------------- File InterestingExamples4.bpl ----------------------------
+InterestingExamples4.bpl(36,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ InterestingExamples4.bpl(36,3): anon0
+InterestingExamples4.bpl(39,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ InterestingExamples4.bpl(36,3): anon0
+
+Boogie program verifier finished with 0 verified, 2 errors
+--------------------- File InterestingExamples5.bpl ----------------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
+--------------------- File Colors.bpl ----------------------------
+Colors.bpl(13,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Colors.bpl(12,3): anon0
+Colors.bpl(20,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Colors.bpl(19,3): anon0
+
+Boogie program verifier finished with 0 verified, 2 errors
+--------------------- File HeapAbstraction.bpl ----------------------------
+HeapAbstraction.bpl(15,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ HeapAbstraction.bpl(14,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File HeapAxiom.bpl ----------------------------
+HeapAxiom.bpl(24,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ HeapAxiom.bpl(13,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File Triggers0.bpl ----------------------------
+Triggers0.bpl(39,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Triggers0.bpl(39,3): anon0
+Triggers0.bpl(43,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Triggers0.bpl(39,3): anon0
+
+Boogie program verifier finished with 1 verified, 2 errors
+--------------------- File Triggers1.bpl ----------------------------
+Triggers1.bpl(16,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Triggers1.bpl(12,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File Keywords.bpl ----------------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
+--------------------- File Casts.bpl ----------------------------
+Casts.bpl(10,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Casts.bpl(6,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File EmptyList.bpl ----------------------------
+EmptyList.bpl(46,9): Warning: type parameter a is ambiguous, instantiating to List int
+EmptyList.bpl(42,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ EmptyList.bpl(26,5): anon0
+
+Boogie program verifier finished with 1 verified, 1 error
+--------------------- File Boxing.bpl ----------------------------
+Boxing.bpl(20,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Boxing.bpl(15,6): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File MapOutputTypeParams.bpl ----------------------------
+MapOutputTypeParams.bpl(29,3): Warning: type parameter a is ambiguous, instantiating to int
+MapOutputTypeParams.bpl(13,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ MapOutputTypeParams.bpl(7,9): anon0
+MapOutputTypeParams.bpl(24,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ MapOutputTypeParams.bpl(19,9): anon0
+MapOutputTypeParams.bpl(32,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ MapOutputTypeParams.bpl(28,8): anon0
+
+Boogie program verifier finished with 0 verified, 3 errors
+--------------------- File ParallelAssignment.bpl ----------------------------
+ParallelAssignment.bpl(26,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ ParallelAssignment.bpl(15,5): anon0
+ParallelAssignment.bpl(35,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ ParallelAssignment.bpl(15,5): anon0
+ParallelAssignment.bpl(54,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ ParallelAssignment.bpl(40,11): anon0
+
+Boogie program verifier finished with 0 verified, 3 errors
+--------------------- File BooleanQuantification.bpl ----------------------------
+BooleanQuantification.bpl(10,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ BooleanQuantification.bpl(10,3): anon0
+BooleanQuantification.bpl(18,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ BooleanQuantification.bpl(18,3): anon0
+BooleanQuantification.bpl(19,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ BooleanQuantification.bpl(18,3): anon0
+BooleanQuantification.bpl(29,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ BooleanQuantification.bpl(29,3): anon0
+BooleanQuantification.bpl(31,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ BooleanQuantification.bpl(29,3): anon0
+
+Boogie program verifier finished with 1 verified, 5 errors
+--------------------- File BooleanQuantification2.bpl ----------------------------
+BooleanQuantification2.bpl(13,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ BooleanQuantification2.bpl(10,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File Flattening.bpl ----------------------------
+Flattening.bpl(12,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Flattening.bpl(12,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File Orderings.bpl ----------------------------
+Orderings.bpl(14,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Orderings.bpl(9,3): anon0
+
+Boogie program verifier finished with 1 verified, 1 error
+--------------------- File Orderings2.bpl ----------------------------
+Orderings2.bpl(17,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Orderings2.bpl(12,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File Orderings3.bpl ----------------------------
+Orderings3.bpl(29,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Orderings3.bpl(15,3): anon0
+Orderings3.bpl(34,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Orderings3.bpl(34,3): anon0
+Orderings3.bpl(36,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Orderings3.bpl(34,3): anon0
+
+Boogie program verifier finished with 0 verified, 3 errors
+--------------------- File Orderings4.bpl ----------------------------
+Orderings4.bpl(10,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Orderings4.bpl(9,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File EmptySetBug.bpl ----------------------------
+EmptySetBug.bpl(29,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ EmptySetBug.bpl(25,5): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File Coercions2.bpl ----------------------------
+Coercions2.bpl(12,23): Warning: type parameter a is ambiguous, instantiating to int
+Coercions2.bpl(23,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Coercions2.bpl(18,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File MapAxiomsConsistency.bpl ----------------------------
+MapAxiomsConsistency.bpl(94,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ MapAxiomsConsistency.bpl(79,13): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File LargeLiterals0.bpl ----------------------------
+LargeLiterals0.bpl(18,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ LargeLiterals0.bpl(7,5): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File NameClash.bpl ----------------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
+--------------------- File LetSorting.bpl ----------------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
+--------------------- File Keywords.bpl ----------------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
+--------------------- File LargeLiterals0.bpl ----------------------------
+LargeLiterals0.bpl(18,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ LargeLiterals0.bpl(7,5): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- TypeEncoding n z3types ----------------------------
+--------------------- File DisjointDomains.bpl ----------------------------
+
+Boogie program verifier finished with 3 verified, 0 errors
+--------------------- File DisjointDomains2.bpl ----------------------------
+DisjointDomains2.bpl(11,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ DisjointDomains2.bpl(9,3): start
+DisjointDomains2.bpl(18,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ DisjointDomains2.bpl(16,3): start
+
+Boogie program verifier finished with 4 verified, 2 errors
+--------------------- File FunAxioms.bpl ----------------------------
+FunAxioms.bpl(30,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ FunAxioms.bpl(18,3): anon0
+
+Boogie program verifier finished with 1 verified, 1 error
+--------------------- File FunAxioms2.bpl ----------------------------
+FunAxioms2.bpl(20,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ FunAxioms2.bpl(16,5): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File PolyList.bpl ----------------------------
+PolyList.bpl(42,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ PolyList.bpl(27,7): anon0
+PolyList.bpl(60,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ PolyList.bpl(49,7): anon0
+
+Boogie program verifier finished with 0 verified, 2 errors
+--------------------- File Maps0.bpl ----------------------------
+Maps0.bpl(23,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Maps0.bpl(14,3): anon0
+Maps0.bpl(46,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Maps0.bpl(41,9): anon0
+Maps0.bpl(49,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Maps0.bpl(41,9): anon0
+Maps0.bpl(52,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Maps0.bpl(41,9): anon0
+Maps0.bpl(53,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Maps0.bpl(41,9): anon0
+
+Boogie program verifier finished with 1 verified, 5 errors
+--------------------- File Maps1.bpl ----------------------------
+Maps1.bpl(26,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Maps1.bpl(19,3): anon0
+Maps1.bpl(31,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Maps1.bpl(19,3): anon0
+
+Boogie program verifier finished with 0 verified, 2 errors
+--------------------- File InterestingExamples0.bpl ----------------------------
+InterestingExamples0.bpl(7,1): Error BP5001: This assertion might not hold.
+Execution trace:
+ InterestingExamples0.bpl(5,6): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File InterestingExamples1.bpl ----------------------------
+InterestingExamples1.bpl(16,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ InterestingExamples1.bpl(13,5): anon0
+InterestingExamples1.bpl(22,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ InterestingExamples1.bpl(13,5): anon0
+
+Boogie program verifier finished with 0 verified, 2 errors
+--------------------- File InterestingExamples2.bpl ----------------------------
+InterestingExamples2.bpl(9,1): Error BP5001: This assertion might not hold.
+Execution trace:
+ InterestingExamples2.bpl(8,6): anon0
+InterestingExamples2.bpl(10,1): Error BP5001: This assertion might not hold.
+Execution trace:
+ InterestingExamples2.bpl(8,6): anon0
+
+Boogie program verifier finished with 0 verified, 2 errors
+--------------------- File InterestingExamples3.bpl ----------------------------
+InterestingExamples3.bpl(15,2): Error BP5001: This assertion might not hold.
+Execution trace:
+ InterestingExamples3.bpl(13,2): anon0
+
+Boogie program verifier finished with 2 verified, 1 error
+--------------------- File InterestingExamples4.bpl ----------------------------
+InterestingExamples4.bpl(36,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ InterestingExamples4.bpl(36,3): anon0
+InterestingExamples4.bpl(39,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ InterestingExamples4.bpl(36,3): anon0
+
+Boogie program verifier finished with 0 verified, 2 errors
+--------------------- File InterestingExamples5.bpl ----------------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
+--------------------- File Colors.bpl ----------------------------
+Colors.bpl(13,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Colors.bpl(12,3): anon0
+Colors.bpl(20,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Colors.bpl(19,3): anon0
+
+Boogie program verifier finished with 0 verified, 2 errors
+--------------------- File HeapAbstraction.bpl ----------------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
+--------------------- File HeapAxiom.bpl ----------------------------
+HeapAxiom.bpl(24,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ HeapAxiom.bpl(13,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File Triggers0.bpl ----------------------------
+Triggers0.bpl(39,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Triggers0.bpl(39,3): anon0
+Triggers0.bpl(43,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Triggers0.bpl(39,3): anon0
+
+Boogie program verifier finished with 1 verified, 2 errors
+--------------------- File Triggers1.bpl ----------------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
+--------------------- File Keywords.bpl ----------------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
+--------------------- File Casts.bpl ----------------------------
+Casts.bpl(10,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Casts.bpl(6,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File BooleanQuantification.bpl ----------------------------
+BooleanQuantification.bpl(19,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ BooleanQuantification.bpl(18,3): anon0
+BooleanQuantification.bpl(31,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ BooleanQuantification.bpl(29,3): anon0
+
+Boogie program verifier finished with 2 verified, 2 errors
+--------------------- File EmptyList.bpl ----------------------------
+EmptyList.bpl(46,9): Warning: type parameter a is ambiguous, instantiating to List int
+EmptyList.bpl(28,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ EmptyList.bpl(26,5): anon0
+EmptyList.bpl(42,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ EmptyList.bpl(26,5): anon0
+EmptyList.bpl(46,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ EmptyList.bpl(46,3): anon0
+
+Boogie program verifier finished with 0 verified, 3 errors
+--------------------- File Boxing.bpl ----------------------------
+Boxing.bpl(19,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Boxing.bpl(15,6): anon0
+Boxing.bpl(20,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Boxing.bpl(15,6): anon0
+
+Boogie program verifier finished with 0 verified, 2 errors
+--------------------- File MapOutputTypeParams.bpl ----------------------------
+MapOutputTypeParams.bpl(29,3): Warning: type parameter a is ambiguous, instantiating to int
+MapOutputTypeParams.bpl(12,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ MapOutputTypeParams.bpl(7,9): anon0
+MapOutputTypeParams.bpl(13,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ MapOutputTypeParams.bpl(7,9): anon0
+MapOutputTypeParams.bpl(23,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ MapOutputTypeParams.bpl(19,9): anon0
+MapOutputTypeParams.bpl(24,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ MapOutputTypeParams.bpl(19,9): anon0
+MapOutputTypeParams.bpl(31,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ MapOutputTypeParams.bpl(28,8): anon0
+MapOutputTypeParams.bpl(32,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ MapOutputTypeParams.bpl(28,8): anon0
+
+Boogie program verifier finished with 0 verified, 6 errors
+--------------------- File ParallelAssignment.bpl ----------------------------
+ParallelAssignment.bpl(26,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ ParallelAssignment.bpl(15,5): anon0
+ParallelAssignment.bpl(35,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ ParallelAssignment.bpl(15,5): anon0
+ParallelAssignment.bpl(54,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ ParallelAssignment.bpl(40,11): anon0
+
+Boogie program verifier finished with 0 verified, 3 errors
+--------------------- File BooleanQuantification2.bpl ----------------------------
+BooleanQuantification2.bpl(13,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ BooleanQuantification2.bpl(10,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File Flattening.bpl ----------------------------
+Flattening.bpl(12,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Flattening.bpl(12,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File Orderings.bpl ----------------------------
+Orderings.bpl(14,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Orderings.bpl(9,3): anon0
+
+Boogie program verifier finished with 1 verified, 1 error
+--------------------- File Orderings2.bpl ----------------------------
+Orderings2.bpl(17,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Orderings2.bpl(12,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File Orderings3.bpl ----------------------------
+Orderings3.bpl(29,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Orderings3.bpl(15,3): anon0
+Orderings3.bpl(34,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Orderings3.bpl(34,3): anon0
+Orderings3.bpl(36,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Orderings3.bpl(34,3): anon0
+
+Boogie program verifier finished with 0 verified, 3 errors
+--------------------- File Orderings4.bpl ----------------------------
+Orderings4.bpl(10,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Orderings4.bpl(9,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File EmptySetBug.bpl ----------------------------
+EmptySetBug.bpl(27,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ EmptySetBug.bpl(25,5): anon0
+EmptySetBug.bpl(29,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ EmptySetBug.bpl(25,5): anon0
+
+Boogie program verifier finished with 0 verified, 2 errors
+--------------------- File Coercions2.bpl ----------------------------
+Coercions2.bpl(12,23): Warning: type parameter a is ambiguous, instantiating to int
+Coercions2.bpl(18,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Coercions2.bpl(18,3): anon0
+Coercions2.bpl(23,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Coercions2.bpl(18,3): anon0
+
+Boogie program verifier finished with 0 verified, 2 errors
+--------------------- File MapAxiomsConsistency.bpl ----------------------------
+MapAxiomsConsistency.bpl(94,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ MapAxiomsConsistency.bpl(79,13): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File LargeLiterals0.bpl ----------------------------
+LargeLiterals0.bpl(18,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ LargeLiterals0.bpl(7,5): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File LetSorting.bpl ----------------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
+--------------------- TypeEncoding p z3types ----------------------------
+--------------------- File DisjointDomains.bpl ----------------------------
+DisjointDomains.bpl(14,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ DisjointDomains.bpl(11,3): start
+DisjointDomains.bpl(21,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ DisjointDomains.bpl(20,3): start
+DisjointDomains.bpl(27,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ DisjointDomains.bpl(26,3): start
+
+Boogie program verifier finished with 0 verified, 3 errors
+--------------------- File DisjointDomains2.bpl ----------------------------
+DisjointDomains2.bpl(11,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ DisjointDomains2.bpl(9,3): start
+DisjointDomains2.bpl(18,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ DisjointDomains2.bpl(16,3): start
+DisjointDomains2.bpl(32,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ DisjointDomains2.bpl(30,3): start
+DisjointDomains2.bpl(39,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ DisjointDomains2.bpl(37,3): start
+DisjointDomains2.bpl(49,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ DisjointDomains2.bpl(45,3): start
+DisjointDomains2.bpl(63,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ DisjointDomains2.bpl(58,3): start
+
+Boogie program verifier finished with 0 verified, 6 errors
+--------------------- File FunAxioms.bpl ----------------------------
+FunAxioms.bpl(30,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ FunAxioms.bpl(18,3): anon0
+
+Boogie program verifier finished with 1 verified, 1 error
+--------------------- File FunAxioms2.bpl ----------------------------
+FunAxioms2.bpl(20,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ FunAxioms2.bpl(16,5): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File PolyList.bpl ----------------------------
+PolyList.bpl(42,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ PolyList.bpl(27,7): anon0
+PolyList.bpl(60,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ PolyList.bpl(49,7): anon0
+
+Boogie program verifier finished with 0 verified, 2 errors
+--------------------- File Maps0.bpl ----------------------------
+Maps0.bpl(23,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Maps0.bpl(14,3): anon0
+Maps0.bpl(32,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Maps0.bpl(32,3): anon0
+Maps0.bpl(53,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Maps0.bpl(41,9): anon0
+
+Boogie program verifier finished with 0 verified, 3 errors
+--------------------- File Maps1.bpl ----------------------------
+Maps1.bpl(31,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Maps1.bpl(19,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File InterestingExamples0.bpl ----------------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
+--------------------- File InterestingExamples1.bpl ----------------------------
+InterestingExamples1.bpl(22,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ InterestingExamples1.bpl(13,5): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File InterestingExamples2.bpl ----------------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
+--------------------- File InterestingExamples3.bpl ----------------------------
+InterestingExamples3.bpl(15,2): Error BP5001: This assertion might not hold.
+Execution trace:
+ InterestingExamples3.bpl(13,2): anon0
+
+Boogie program verifier finished with 2 verified, 1 error
+--------------------- File InterestingExamples4.bpl ----------------------------
+InterestingExamples4.bpl(39,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ InterestingExamples4.bpl(36,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File InterestingExamples5.bpl ----------------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
+--------------------- File Colors.bpl ----------------------------
+Colors.bpl(13,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Colors.bpl(12,3): anon0
+
+Boogie program verifier finished with 1 verified, 1 error
+--------------------- File HeapAbstraction.bpl ----------------------------
+HeapAbstraction.bpl(15,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ HeapAbstraction.bpl(14,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File HeapAxiom.bpl ----------------------------
+HeapAxiom.bpl(24,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ HeapAxiom.bpl(13,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File Triggers0.bpl ----------------------------
+Triggers0.bpl(39,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Triggers0.bpl(39,3): anon0
+Triggers0.bpl(43,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Triggers0.bpl(39,3): anon0
+
+Boogie program verifier finished with 1 verified, 2 errors
+--------------------- File Triggers1.bpl ----------------------------
+Triggers1.bpl(16,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Triggers1.bpl(12,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File Keywords.bpl ----------------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
+--------------------- File Casts.bpl ----------------------------
+Casts.bpl(10,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Casts.bpl(6,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File BooleanQuantification.bpl ----------------------------
+BooleanQuantification.bpl(19,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ BooleanQuantification.bpl(18,3): anon0
+BooleanQuantification.bpl(31,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ BooleanQuantification.bpl(29,3): anon0
+
+Boogie program verifier finished with 2 verified, 2 errors
+--------------------- File EmptyList.bpl ----------------------------
+EmptyList.bpl(46,9): Warning: type parameter a is ambiguous, instantiating to List int
+EmptyList.bpl(42,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ EmptyList.bpl(26,5): anon0
+
+Boogie program verifier finished with 1 verified, 1 error
+--------------------- File Boxing.bpl ----------------------------
+Boxing.bpl(20,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Boxing.bpl(15,6): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File MapOutputTypeParams.bpl ----------------------------
+MapOutputTypeParams.bpl(29,3): Warning: type parameter a is ambiguous, instantiating to int
+MapOutputTypeParams.bpl(13,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ MapOutputTypeParams.bpl(7,9): anon0
+MapOutputTypeParams.bpl(24,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ MapOutputTypeParams.bpl(19,9): anon0
+MapOutputTypeParams.bpl(32,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ MapOutputTypeParams.bpl(28,8): anon0
+
+Boogie program verifier finished with 0 verified, 3 errors
+--------------------- File ParallelAssignment.bpl ----------------------------
+ParallelAssignment.bpl(26,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ ParallelAssignment.bpl(15,5): anon0
+ParallelAssignment.bpl(35,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ ParallelAssignment.bpl(15,5): anon0
+ParallelAssignment.bpl(54,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ ParallelAssignment.bpl(40,11): anon0
+
+Boogie program verifier finished with 0 verified, 3 errors
+--------------------- File BooleanQuantification2.bpl ----------------------------
+BooleanQuantification2.bpl(13,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ BooleanQuantification2.bpl(10,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File Flattening.bpl ----------------------------
+Flattening.bpl(12,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Flattening.bpl(12,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File Orderings.bpl ----------------------------
+Orderings.bpl(14,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Orderings.bpl(9,3): anon0
+
+Boogie program verifier finished with 1 verified, 1 error
+--------------------- File Orderings2.bpl ----------------------------
+Orderings2.bpl(17,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Orderings2.bpl(12,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File Orderings3.bpl ----------------------------
+Orderings3.bpl(29,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Orderings3.bpl(15,3): anon0
+Orderings3.bpl(34,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Orderings3.bpl(34,3): anon0
+Orderings3.bpl(36,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Orderings3.bpl(34,3): anon0
+
+Boogie program verifier finished with 0 verified, 3 errors
+--------------------- File Orderings4.bpl ----------------------------
+Orderings4.bpl(10,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Orderings4.bpl(9,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File EmptySetBug.bpl ----------------------------
+EmptySetBug.bpl(29,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ EmptySetBug.bpl(25,5): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File Coercions2.bpl ----------------------------
+Coercions2.bpl(12,23): Warning: type parameter a is ambiguous, instantiating to int
+Coercions2.bpl(23,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Coercions2.bpl(18,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File MapAxiomsConsistency.bpl ----------------------------
+MapAxiomsConsistency.bpl(94,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ MapAxiomsConsistency.bpl(79,13): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File LargeLiterals0.bpl ----------------------------
+LargeLiterals0.bpl(18,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ LargeLiterals0.bpl(7,5): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File LetSorting.bpl ----------------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
+--------------------- TypeEncoding a z3types ----------------------------
+--------------------- File DisjointDomains.bpl ----------------------------
+DisjointDomains.bpl(14,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ DisjointDomains.bpl(11,3): start
+DisjointDomains.bpl(21,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ DisjointDomains.bpl(20,3): start
+DisjointDomains.bpl(27,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ DisjointDomains.bpl(26,3): start
+
+Boogie program verifier finished with 0 verified, 3 errors
+--------------------- File DisjointDomains2.bpl ----------------------------
+DisjointDomains2.bpl(11,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ DisjointDomains2.bpl(9,3): start
+DisjointDomains2.bpl(18,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ DisjointDomains2.bpl(16,3): start
+DisjointDomains2.bpl(32,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ DisjointDomains2.bpl(30,3): start
+DisjointDomains2.bpl(39,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ DisjointDomains2.bpl(37,3): start
+DisjointDomains2.bpl(49,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ DisjointDomains2.bpl(45,3): start
+DisjointDomains2.bpl(63,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ DisjointDomains2.bpl(58,3): start
+
+Boogie program verifier finished with 0 verified, 6 errors
+--------------------- File FunAxioms.bpl ----------------------------
+FunAxioms.bpl(30,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ FunAxioms.bpl(18,3): anon0
+
+Boogie program verifier finished with 1 verified, 1 error
+--------------------- File FunAxioms2.bpl ----------------------------
+FunAxioms2.bpl(20,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ FunAxioms2.bpl(16,5): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File PolyList.bpl ----------------------------
+PolyList.bpl(42,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ PolyList.bpl(27,7): anon0
+PolyList.bpl(60,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ PolyList.bpl(49,7): anon0
+
+Boogie program verifier finished with 0 verified, 2 errors
+--------------------- File Maps0.bpl ----------------------------
+Maps0.bpl(23,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Maps0.bpl(14,3): anon0
+Maps0.bpl(32,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Maps0.bpl(32,3): anon0
+Maps0.bpl(53,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Maps0.bpl(41,9): anon0
+
+Boogie program verifier finished with 0 verified, 3 errors
+--------------------- File Maps1.bpl ----------------------------
+Maps1.bpl(31,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Maps1.bpl(19,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File InterestingExamples0.bpl ----------------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
+--------------------- File InterestingExamples1.bpl ----------------------------
+InterestingExamples1.bpl(22,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ InterestingExamples1.bpl(13,5): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File InterestingExamples2.bpl ----------------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
+--------------------- File InterestingExamples3.bpl ----------------------------
+InterestingExamples3.bpl(15,2): Error BP5001: This assertion might not hold.
+Execution trace:
+ InterestingExamples3.bpl(13,2): anon0
+
+Boogie program verifier finished with 2 verified, 1 error
+--------------------- File InterestingExamples4.bpl ----------------------------
+InterestingExamples4.bpl(36,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ InterestingExamples4.bpl(36,3): anon0
+InterestingExamples4.bpl(39,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ InterestingExamples4.bpl(36,3): anon0
+
+Boogie program verifier finished with 0 verified, 2 errors
+--------------------- File InterestingExamples5.bpl ----------------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
+--------------------- File Colors.bpl ----------------------------
+Colors.bpl(13,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Colors.bpl(12,3): anon0
+Colors.bpl(20,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Colors.bpl(19,3): anon0
+
+Boogie program verifier finished with 0 verified, 2 errors
+--------------------- File HeapAbstraction.bpl ----------------------------
+HeapAbstraction.bpl(15,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ HeapAbstraction.bpl(14,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File HeapAxiom.bpl ----------------------------
+HeapAxiom.bpl(24,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ HeapAxiom.bpl(13,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File Triggers0.bpl ----------------------------
+Triggers0.bpl(39,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Triggers0.bpl(39,3): anon0
+Triggers0.bpl(43,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Triggers0.bpl(39,3): anon0
+
+Boogie program verifier finished with 1 verified, 2 errors
+--------------------- File Triggers1.bpl ----------------------------
+Triggers1.bpl(16,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Triggers1.bpl(12,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File Keywords.bpl ----------------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
+--------------------- File Casts.bpl ----------------------------
+Casts.bpl(10,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Casts.bpl(6,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File BooleanQuantification.bpl ----------------------------
+BooleanQuantification.bpl(19,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ BooleanQuantification.bpl(18,3): anon0
+BooleanQuantification.bpl(31,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ BooleanQuantification.bpl(29,3): anon0
+
+Boogie program verifier finished with 2 verified, 2 errors
+--------------------- File EmptyList.bpl ----------------------------
+EmptyList.bpl(46,9): Warning: type parameter a is ambiguous, instantiating to List int
+EmptyList.bpl(42,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ EmptyList.bpl(26,5): anon0
+
+Boogie program verifier finished with 1 verified, 1 error
+--------------------- File Boxing.bpl ----------------------------
+Boxing.bpl(20,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Boxing.bpl(15,6): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File MapOutputTypeParams.bpl ----------------------------
+MapOutputTypeParams.bpl(29,3): Warning: type parameter a is ambiguous, instantiating to int
+MapOutputTypeParams.bpl(13,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ MapOutputTypeParams.bpl(7,9): anon0
+MapOutputTypeParams.bpl(24,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ MapOutputTypeParams.bpl(19,9): anon0
+MapOutputTypeParams.bpl(32,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ MapOutputTypeParams.bpl(28,8): anon0
+
+Boogie program verifier finished with 0 verified, 3 errors
+--------------------- File ParallelAssignment.bpl ----------------------------
+ParallelAssignment.bpl(26,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ ParallelAssignment.bpl(15,5): anon0
+ParallelAssignment.bpl(35,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ ParallelAssignment.bpl(15,5): anon0
+ParallelAssignment.bpl(54,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ ParallelAssignment.bpl(40,11): anon0
+
+Boogie program verifier finished with 0 verified, 3 errors
+--------------------- File BooleanQuantification2.bpl ----------------------------
+BooleanQuantification2.bpl(13,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ BooleanQuantification2.bpl(10,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File Flattening.bpl ----------------------------
+Flattening.bpl(12,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Flattening.bpl(12,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File Orderings.bpl ----------------------------
+Orderings.bpl(14,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Orderings.bpl(9,3): anon0
+
+Boogie program verifier finished with 1 verified, 1 error
+--------------------- File Orderings2.bpl ----------------------------
+Orderings2.bpl(17,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Orderings2.bpl(12,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File Orderings3.bpl ----------------------------
+Orderings3.bpl(29,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Orderings3.bpl(15,3): anon0
+Orderings3.bpl(34,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Orderings3.bpl(34,3): anon0
+Orderings3.bpl(36,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Orderings3.bpl(34,3): anon0
+
+Boogie program verifier finished with 0 verified, 3 errors
+--------------------- File Orderings4.bpl ----------------------------
+Orderings4.bpl(10,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Orderings4.bpl(9,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File EmptySetBug.bpl ----------------------------
+EmptySetBug.bpl(29,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ EmptySetBug.bpl(25,5): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File Coercions2.bpl ----------------------------
+Coercions2.bpl(12,23): Warning: type parameter a is ambiguous, instantiating to int
+Coercions2.bpl(23,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Coercions2.bpl(18,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File MapAxiomsConsistency.bpl ----------------------------
+MapAxiomsConsistency.bpl(94,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ MapAxiomsConsistency.bpl(79,13): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File LargeLiterals0.bpl ----------------------------
+LargeLiterals0.bpl(18,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ LargeLiterals0.bpl(7,5): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File LetSorting.bpl ----------------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
diff --git a/Test/test21/BooleanQuantification.bpl b/Test/test21/BooleanQuantification.bpl
new file mode 100644
index 00000000..52416e9d
--- /dev/null
+++ b/Test/test21/BooleanQuantification.bpl
@@ -0,0 +1,32 @@
+
+
+
+function f(bool) returns (int);
+
+axiom f(true) == 17;
+axiom f(false) == 19;
+
+procedure P() returns () {
+ assert (forall x:bool :: f(x) >= 0);
+}
+
+procedure Q() returns () {
+ assert (forall x:int :: (x==7 || x==9) ==> x >= 0);
+}
+
+procedure R() returns () {
+ assert f((forall x:bool :: f(x) >= 10)) < 19;
+ assert (exists x:bool :: f(x) > 20); // should not be provable
+}
+
+
+function g<a>(a) returns (int);
+
+axiom g(true) == 17;
+axiom g(false) == 21;
+
+procedure S() returns () {
+ assert (forall x:bool :: g(x) >= 0);
+ assert g((forall x:bool :: g(x) >= 0)) >= 17;
+ assert (forall x:bool :: f(x) == g(x)); // should not be provable
+} \ No newline at end of file
diff --git a/Test/test21/BooleanQuantification2.bpl b/Test/test21/BooleanQuantification2.bpl
new file mode 100644
index 00000000..af6e1f4f
--- /dev/null
+++ b/Test/test21/BooleanQuantification2.bpl
@@ -0,0 +1,14 @@
+
+
+axiom (forall x:bool :: x || !x);
+axiom (forall x:bool :: x == true || x == false);
+
+procedure P() returns () {
+ var i : int;
+ var j : bool;
+
+ assert i != 3 || i != 4;
+ assert j || !j;
+
+ assert false;
+} \ No newline at end of file
diff --git a/Test/test21/Boxing.bpl b/Test/test21/Boxing.bpl
new file mode 100644
index 00000000..08967891
--- /dev/null
+++ b/Test/test21/Boxing.bpl
@@ -0,0 +1,21 @@
+
+type Box;
+
+function box<a>(a) returns (Box);
+function unbox<a>(Box) returns (a);
+
+axiom (forall<a> x:a :: unbox(box(x)) == x);
+
+var b1: Box;
+var b2: Box;
+var b3: Box;
+
+procedure P() returns ()
+ modifies b1, b2, b3; {
+ b1 := box(13);
+ b2 := box(true);
+ b3 := box(b1);
+
+ assert unbox(b1) == 13 && unbox(b2) == true && unbox(unbox(b3)) == 13;
+ assert unbox(b1) == true; // error
+} \ No newline at end of file
diff --git a/Test/test21/Casts.bpl b/Test/test21/Casts.bpl
new file mode 100644
index 00000000..5173021e
--- /dev/null
+++ b/Test/test21/Casts.bpl
@@ -0,0 +1,11 @@
+
+
+procedure P() returns () {
+ var m : [int]int, n : [int]int, x : int;
+
+ assume m[x] == x;
+ assume n[x] == 1;
+
+ assert n[m[x]] == 1;
+ assert m[n[x]] == 1; // should not be provable
+} \ No newline at end of file
diff --git a/Test/test21/Coercions2.bpl b/Test/test21/Coercions2.bpl
new file mode 100644
index 00000000..c5abb724
--- /dev/null
+++ b/Test/test21/Coercions2.bpl
@@ -0,0 +1,24 @@
+
+
+type Box, C;
+
+function box<a>(a) returns (Box);
+function unbox<a>(Box) returns (a);
+
+axiom (forall<a> x:a :: unbox(box(x)) == x);
+
+axiom (forall<a> x:Box :: {unbox(x):a} box(unbox(x):a) == x);
+
+axiom (forall x:Box :: box(unbox(x)) == x); // warning
+
+procedure P() {
+ var b : Box;
+ var i : C;
+
+ assert unbox(box(13)) == 13;
+
+ i := unbox(b);
+ assert b == box(i);
+
+ assert false;
+} \ No newline at end of file
diff --git a/Test/test21/Colors.bpl b/Test/test21/Colors.bpl
new file mode 100644
index 00000000..be25cc15
--- /dev/null
+++ b/Test/test21/Colors.bpl
@@ -0,0 +1,21 @@
+
+
+type Color;
+
+const Blue, Red, Green : Color;
+
+axiom (forall x : Color :: x == Blue || x == Red || x == Green);
+
+procedure P() returns () {
+ var x : Color;
+
+ assume x != Blue;
+ assert x == Red; // should not be provable
+}
+
+procedure Q() returns () {
+ var x : Color;
+
+ assume x != Blue && x != Green;
+ assert x == Red;
+} \ No newline at end of file
diff --git a/Test/test21/DisjointDomains.bpl b/Test/test21/DisjointDomains.bpl
new file mode 100644
index 00000000..88647e6b
--- /dev/null
+++ b/Test/test21/DisjointDomains.bpl
@@ -0,0 +1,30 @@
+type C _;
+
+function f<a>(C a) returns (int);
+
+axiom (forall x : C int :: f(x) == 3);
+axiom (forall x : C bool :: f(x) == 7);
+
+procedure P() returns () {
+ var a : C int, b : C bool, c : C ref;
+
+ start:
+ assert f(a) == 3;
+ assert f(b) == 7;
+ assert f(b) == 8; // should not be provable
+}
+
+procedure Q() returns () {
+ var c : C ref;
+
+ start:
+ assert f(c) == 7; // should not be provable
+}
+
+procedure R<a>(c : C a) returns () {
+
+ start:
+ assert f(c) == 7; // should not be provable
+}
+
+type ref;
diff --git a/Test/test21/DisjointDomains2.bpl b/Test/test21/DisjointDomains2.bpl
new file mode 100644
index 00000000..3cac88ca
--- /dev/null
+++ b/Test/test21/DisjointDomains2.bpl
@@ -0,0 +1,64 @@
+type C _;
+
+function f<a>(C a) returns (int);
+
+axiom (forall<a> x : C a :: f(x) == 42);
+
+procedure P(a : C int) returns () {
+
+ start:
+ assert f(a) == 42;
+ assert f(a) == 43; // should not be provable
+}
+
+procedure Q<a>(c : C a) returns () {
+
+ start:
+ assert f(c) == 42;
+ assert f(c) == 43; // should not be provable
+}
+
+function g<a,b>(a, b) returns (int);
+
+
+axiom (forall x : int, y : bool :: g(x,y) == 13);
+axiom (forall<a> x : int, y : C a :: g(x,y) == 42);
+axiom (forall<a,z> x : C z, y : C a :: g(x,y) == 43);
+
+procedure R() returns () {
+
+ start:
+ assert g(7, true) == 13;
+ assert g(7, false) == 15; // should not be provable
+}
+
+procedure S<b>(y : C b) returns () {
+
+ start:
+ assert g(3, y) == f(y);
+ assert g(y, false) == 15; // should not be provable
+}
+
+procedure T<a,b>(y : C b, param : a) returns () {
+ var x : C a; var z : C b;
+
+ start:
+ assert g(y, x) == g(x, y);
+ assert g(y, x) == 43;
+ assert g(f(x), y) == 42;
+ assert g(y, z) == 15; // should not be provable
+}
+
+
+type D _ _;
+
+procedure U() returns () {
+ var u : D int bool, v : D bool int;
+
+ start:
+ assume (forall<a,b> x:D a b, y:b :: g(x, y) == -3);
+
+ assert g(v, 32) == -3;
+ assert g(v, 716371398712982312321) == -3;
+ assert g(u, 1) == -3; // should not be provable
+}
diff --git a/Test/test21/EmptyList.bpl b/Test/test21/EmptyList.bpl
new file mode 100644
index 00000000..a6b90638
--- /dev/null
+++ b/Test/test21/EmptyList.bpl
@@ -0,0 +1,47 @@
+
+
+type List _;
+
+function NIL<a>() returns (List a);
+function Cons<a>(a, List a) returns (List a);
+
+function car<a>(List a) returns (a);
+function cdr<a>(List a) returns (List a);
+
+axiom (forall<a> x:a, l:List a :: car(Cons(x, l)) == x);
+axiom (forall<a> x:a, l:List a :: cdr(Cons(x, l)) == l);
+
+axiom (forall<a> x:a, l:List a :: Cons(x, l) != NIL());
+
+var l:List bool;
+
+var m:List int;
+var mar:[int](List int);
+
+procedure P() returns ()
+ requires m != NIL();
+ requires mar[0] == m && (forall i:int :: i > 0 ==> mar[i] == cdr(mar[i-1]));
+ modifies l, m, mar; {
+
+ l := Cons(true, NIL());
+
+ assert l != NIL();
+ l := cdr(l);
+
+ assert l == NIL();
+ l := Cons(true, l);
+ l := Cons(false, l);
+
+ assert car(mar[1]) == car(cdr(m));
+ mar[0] := NIL();
+ assert mar[0] != m;
+
+ assert !car(l) && car(cdr(l));
+ l := cdr(cdr(l));
+
+ assert (forall i:int :: i > 0 ==> mar[i] == cdr(mar[i-1])); // error
+}
+
+procedure Q() returns () {
+ assert Cons(NIL(), NIL()) != NIL(); // warning, but provable
+} \ No newline at end of file
diff --git a/Test/test21/EmptySetBug.bpl b/Test/test21/EmptySetBug.bpl
new file mode 100644
index 00000000..424d998c
--- /dev/null
+++ b/Test/test21/EmptySetBug.bpl
@@ -0,0 +1,30 @@
+type ref;
+
+const null: ref;
+
+type Set T = [T]bool;
+
+function Set#Empty<T>() returns (Set T);
+
+axiom (forall<T> o: T :: { Set#Empty()[o] } !Set#Empty()[o]);
+
+function Set#Singleton<T>(T) returns (Set T);
+
+axiom (forall<T> r: T :: { Set#Singleton(r) } Set#Singleton(r)[r]);
+
+axiom (forall<T> r: T, o: T :: { Set#Singleton(r)[o] } Set#Singleton(r)[o] <==> r == o);
+
+function Set#UnionOne<T>(Set T, T) returns (Set T);
+
+axiom (forall<T> a: Set T, x: T, o: T :: { Set#UnionOne(a, x)[o] } Set#UnionOne(a, x)[o] <==> o == x || a[o]);
+
+procedure Test(this: ref)
+{
+ var s: Set ref;
+
+ s := Set#UnionOne(Set#Empty(), this);
+ assert s[this];
+ assert !Set#Empty()[this];
+
+ assert Set#Singleton(this)[null]; // should not be provable
+}
diff --git a/Test/test21/Flattening.bpl b/Test/test21/Flattening.bpl
new file mode 100644
index 00000000..10899931
--- /dev/null
+++ b/Test/test21/Flattening.bpl
@@ -0,0 +1,13 @@
+
+
+function g(int) returns (int);
+function f(bool) returns (int);
+
+
+axiom (f((exists x:int :: g(x) >= 12)) == 3);
+axiom (f((exists x:int :: g(f((forall y:int :: g(x+y) >= 0))) >= 12)) == 3);
+
+
+procedure P() returns () {
+ assert false;
+} \ No newline at end of file
diff --git a/Test/test21/FunAxioms.bpl b/Test/test21/FunAxioms.bpl
new file mode 100644
index 00000000..850f4d08
--- /dev/null
+++ b/Test/test21/FunAxioms.bpl
@@ -0,0 +1,40 @@
+
+
+type Pair a b;
+
+function MP<a,b>(x:a, y:b) returns (Pair a b);
+function Left<a,b>(Pair a b) returns (a);
+function Right<a,b>(Pair a b) returns (b);
+
+axiom (forall<a,b> x:a, y:b :: Left(MP(x,y)) == x);
+axiom (forall<a,b> x:a, y:b :: Right(MP(x,y)) == y);
+
+type A, B;
+
+procedure P() returns () {
+
+ var x:A, y:B, z:A, p : Pair A B;
+
+ assert Left(MP(x,y)) == x;
+ assert Right(MP(x,y)) == y;
+ assert Right(MP(x,MP(x,y))) == MP(x,y);
+ assert Left(MP(x,MP(x,y))) == x;
+ assert Right(Right(MP(x,MP(x,y)))) == y;
+
+ p := MP(x, y);
+
+ p := MP(Left(p), y);
+
+ assert Left(p) == x && Right(p) == y;
+
+ assert Left(p) == z; // should not be provable
+
+}
+
+procedure Q() returns () {
+
+ assert Left(MP(1,3)) == 1;
+ assert Right(MP(1,3)) == 3;
+ assert Right(MP(1,true)) == true;
+
+} \ No newline at end of file
diff --git a/Test/test21/FunAxioms2.bpl b/Test/test21/FunAxioms2.bpl
new file mode 100644
index 00000000..f487dcab
--- /dev/null
+++ b/Test/test21/FunAxioms2.bpl
@@ -0,0 +1,21 @@
+
+type T;
+
+function f() returns (int); // functions without arguments
+function g() returns (T);
+
+
+const c : T;
+
+axiom (f() >= 13);
+axiom (g() != c);
+
+procedure P() returns () {
+ var x : int;
+
+ x := f();
+
+ assert x >= 0 && f() >= 7;
+ assert g() != c;
+ assert f() >= 20; // should not be provable
+} \ No newline at end of file
diff --git a/Test/test21/HeapAbstraction.bpl b/Test/test21/HeapAbstraction.bpl
new file mode 100644
index 00000000..1d2a7f99
--- /dev/null
+++ b/Test/test21/HeapAbstraction.bpl
@@ -0,0 +1,19 @@
+
+
+type Field a, Heap = <a>[ref, Field a]a;
+
+function f<b>(<a>[b, Field a]a) returns (int);
+
+axiom (forall x:<a>[int, Field a]a :: f(x) == 17);
+
+axiom (forall x:<a>[ref, Field a]a :: f(x) == 42);
+
+procedure P() returns () {
+ var h : Heap, g : <a>[bool, Field a]a;
+
+ assert f(h) == 42;
+ assert f(g) >= 0; // should not be provable
+}
+
+type ref;
+const null : ref;
diff --git a/Test/test21/HeapAxiom.bpl b/Test/test21/HeapAxiom.bpl
new file mode 100644
index 00000000..8972c6af
--- /dev/null
+++ b/Test/test21/HeapAxiom.bpl
@@ -0,0 +1,27 @@
+
+
+type Field a, Heap = <a>[ref, Field a]a;
+
+function IsHeap(Heap) returns (bool);
+const alloc : Field bool;
+
+axiom (forall H:Heap, o:ref, f:Field ref ::
+ IsHeap(H) && H[o,alloc] ==> H[H[o,f], alloc]);
+
+procedure P() returns () {
+ var h : Heap, o : ref, g : Field ref, i : Field ref, o2 : ref;
+ assume IsHeap(h) && h[o, alloc];
+
+ o2 := h[o, g];
+ assert h[o2, alloc];
+
+ o2 := h[o2, g];
+ assert h[o2, alloc];
+
+ h[o2, alloc] := false;
+
+ o2 := h[o2, g];
+ assert h[o2, alloc]; // should not be provable
+}
+
+type ref;
diff --git a/Test/test21/InterestingExamples0.bpl b/Test/test21/InterestingExamples0.bpl
new file mode 100644
index 00000000..d1b90d10
--- /dev/null
+++ b/Test/test21/InterestingExamples0.bpl
@@ -0,0 +1,8 @@
+
+procedure P() returns () {
+var a : <t>[t]int;
+
+a[5] := 0;
+a[true] := 1;
+assert a[5] == 0;
+} \ No newline at end of file
diff --git a/Test/test21/InterestingExamples1.bpl b/Test/test21/InterestingExamples1.bpl
new file mode 100644
index 00000000..3ec7449e
--- /dev/null
+++ b/Test/test21/InterestingExamples1.bpl
@@ -0,0 +1,27 @@
+
+type Set = <a> [a] bool;
+type Field a;
+type Heap = <b> [ref, Field b] b;
+
+
+const emptySet : Set;
+axiom (forall<t> x:t :: !emptySet[x]);
+
+procedure P() returns () {
+ var x : Set, f : Field Set, g : Field int, heap : Heap, o : ref;
+
+ x := emptySet;
+ heap[o, f] := x;
+ heap[o, g] := 13;
+ assert heap[o, f] == emptySet && heap[o, g] == 13;
+
+ heap[o, f] := heap[o, f][17 := true];
+ heap[o, f] := heap[o, f][g := true];
+
+ assert (forall<t> y:t :: heap[o, f][y] == (y == 17 || y == g));
+ assert (forall<t> y:t :: heap[o, f][y] == (y == 16 || y == g)); // should not hold
+
+}
+
+type ref;
+
diff --git a/Test/test21/InterestingExamples2.bpl b/Test/test21/InterestingExamples2.bpl
new file mode 100644
index 00000000..62374cb6
--- /dev/null
+++ b/Test/test21/InterestingExamples2.bpl
@@ -0,0 +1,14 @@
+
+
+procedure P() returns () {
+var m : <a>[a]ref;
+var n : <b>[b]b;
+var o : ref;
+
+m[5] := null;
+assert m[true := o][5] == null;
+assert m[n[true] := o][5] == null;
+}
+
+type ref;
+const null : ref;
diff --git a/Test/test21/InterestingExamples3.bpl b/Test/test21/InterestingExamples3.bpl
new file mode 100644
index 00000000..8eef3dff
--- /dev/null
+++ b/Test/test21/InterestingExamples3.bpl
@@ -0,0 +1,27 @@
+
+procedure P() returns () {
+
+ assume (forall<t> m : [t]bool :: // uses "infinitely many" map types
+ (forall x : t :: m[x] == false));
+
+}
+
+
+procedure Q() returns () {
+ var h : [int] bool;
+
+ assume (forall<t> m : [t]bool, x : t :: m[x] == false);
+ assert !h[42];
+ assert false; // should really be provable
+}
+
+
+
+procedure R() returns () {
+ var h : [int] bool;
+
+ assume (forall<t> m : [t]bool, x : t :: m[x] == false);
+ assert !h[42];
+ assert !h[42 := true][42];
+ assert false; // wow
+}
diff --git a/Test/test21/InterestingExamples4.bpl b/Test/test21/InterestingExamples4.bpl
new file mode 100644
index 00000000..371724f5
--- /dev/null
+++ b/Test/test21/InterestingExamples4.bpl
@@ -0,0 +1,42 @@
+// a property that should hold according to the Boogie semantics
+// (but no automatic theorem prover will be able to prove it)
+
+
+type C a;
+
+function sameType<a,b>(x:a, y:b) returns (bool);
+
+axiom (forall<a,b> x:a, y:b :: sameType(x,y) == (exists z:a :: y==z));
+
+// Will be defined to hold whenever the type of y (i.e., b)
+// can be reached from the type of x (a) by applying the type
+// constructor C a finite number of times. In order words,
+// b = C^n(a)
+function rel<a,b>(x:a, y:b) returns (bool);
+
+function relHelp<a,b>(x:a, y:b, int) returns (bool);
+
+axiom (forall<a, b> x:a, y:b :: relHelp(x, y, 0) == sameType(x, y));
+axiom (forall<a, b> n:int, x:a, y:b ::
+ (n >= 0 ==>
+ relHelp(x, y, n+1) ==
+ (exists<c> z:c, y' : C c :: relHelp(x, z, n) && y==y')));
+
+axiom (forall<a, b> x:a, y:b ::
+ rel(x, y) == (exists n:int :: n >= 0 && relHelp(x, y, n)));
+
+// Assert that from every type we can reach a type that is
+// minimal, i.e., that cannot be reached by applying C to some
+// other type. This will only hold in well-founded type
+// hierarchies
+
+procedure P() returns () {
+ var v : C int;
+
+ assert relHelp(7, 13, 0);
+ assert rel(7, 13);
+
+ assert (forall<b> y:b :: (exists<a> x:a :: // too hard for a theorem prover
+ rel(x, y) &&
+ (forall<c> z:c :: (rel(z, x) ==> sameType(z, x)))));
+}
diff --git a/Test/test21/InterestingExamples5.bpl b/Test/test21/InterestingExamples5.bpl
new file mode 100644
index 00000000..b6c48b63
--- /dev/null
+++ b/Test/test21/InterestingExamples5.bpl
@@ -0,0 +1,16 @@
+
+
+type C a;
+
+function f<a>(C a) returns (int);
+
+//axiom (forall<a> x:C a :: {f(x)} (exists y:C a :: f(y) == 42));
+
+function g<a>(C a) returns (C a);
+axiom (forall<a> x:C a :: f(g(x)) == 42);
+
+procedure P() returns () {
+ var z : C int;
+ assume g(z) == z;
+ assert (exists x : C int :: f(x) == 42);
+} \ No newline at end of file
diff --git a/Test/test21/Keywords.bpl b/Test/test21/Keywords.bpl
new file mode 100644
index 00000000..daf38b45
--- /dev/null
+++ b/Test/test21/Keywords.bpl
@@ -0,0 +1,9 @@
+
+
+function NOT(x:int) returns(int);
+
+axiom (forall x:int :: NOT(x) == 1 - x);
+
+procedure P() returns () {
+ assert NOT(5) == -4;
+} \ No newline at end of file
diff --git a/Test/test21/LargeLiterals0.bpl b/Test/test21/LargeLiterals0.bpl
new file mode 100644
index 00000000..a77ffadd
--- /dev/null
+++ b/Test/test21/LargeLiterals0.bpl
@@ -0,0 +1,20 @@
+
+
+var x : int;
+
+procedure P() modifies x; {
+
+ x := 1000000;
+ assert x > 0 && x < 2000000;
+
+ x := x + 256;
+ assert x == 1000256;
+
+ x := 1000000000000;
+ x := x + 100100;
+ x := x - 100;
+ assert x == 1000000100000;
+
+ assert x < -123456789; // error
+
+} \ No newline at end of file
diff --git a/Test/test21/LetSorting.bpl b/Test/test21/LetSorting.bpl
new file mode 100644
index 00000000..3dc59fde
--- /dev/null
+++ b/Test/test21/LetSorting.bpl
@@ -0,0 +1,15 @@
+
+
+procedure Array0() returns (z: int)
+ ensures z >= 5;
+{
+L0:
+ goto L1, L2;
+L1:
+ z := 10;
+L2:
+ z := 20;
+ return;
+}
+
+
diff --git a/Test/test21/MapAxiomsConsistency.bpl b/Test/test21/MapAxiomsConsistency.bpl
new file mode 100644
index 00000000..d5344449
--- /dev/null
+++ b/Test/test21/MapAxiomsConsistency.bpl
@@ -0,0 +1,97 @@
+// Dafny program verifier version 0.92, Copyright (c) 2003-2008, Microsoft.
+// Command Line Options: /trace /typeEncoding:arguments /print:test.bpl test.dfy
+
+type ref;
+
+const null: ref;
+
+type Set T = [T]bool;
+function Set#Empty<T>() returns (Set T);
+function Set#Singleton<T>(T) returns (Set T);
+function Set#UnionOne<T>(Set T, T) returns (Set T);
+function Set#Union<T>(Set T, Set T) returns (Set T);
+function Set#Intersection<T>(Set T, Set T) returns (Set T);
+function Set#Difference<T>(Set T, Set T) returns (Set T);
+function Set#Subset<T>(Set T, Set T) returns (bool);
+function Set#Equal<T>(Set T, Set T) returns (bool);
+function Set#Disjoint<T>(Set T, Set T) returns (bool);
+
+type Seq _;
+function Seq#Length<T>(Seq T) returns (int);
+function Seq#Empty<T>() returns (Seq T);
+function Seq#Singleton<T>(T) returns (Seq T);
+function Seq#Build<T>(s: Seq T, index: int, val: T, newLength: int) returns (Seq T);
+function Seq#Append<T>(Seq T, Seq T) returns (Seq T);
+function Seq#Index<T>(Seq T, int) returns (T);
+function Seq#Contains<T>(Seq T, T) returns (bool);
+function Seq#Equal<T>(Seq T, Seq T) returns (bool);
+function Seq#SameUntil<T>(Seq T, Seq T, int) returns (bool);
+function Seq#Take<T>(Seq T, howMany: int) returns (Seq T);
+function Seq#Drop<T>(Seq T, howMany: int) returns (Seq T);
+
+type Field _;
+type HeapType = <alpha>[ref,Field alpha]alpha;
+function $IsGoodHeap(HeapType) returns (bool);
+var $Heap: HeapType where $IsGoodHeap($Heap);
+const alloc: Field bool;
+function $HeapSucc(HeapType, HeapType) returns (bool);
+
+const unique Node.list: Field (Seq ref);
+const unique Node.footprint: Field [ref]bool;
+const unique Node.data: Field ref;
+const unique Node.next: Field ref;
+function Node.Valid($heap: HeapType, this: ref) returns (bool);
+
+
+
+
+axiom (forall<T> r: T, o: T :: { Set#Singleton(r)[o] } Set#Singleton(r)[o] <==> r == o);
+
+axiom (forall $Heap: HeapType, this: ref :: { Node.Valid($Heap, this) } this != null && $IsGoodHeap($Heap) ==> Node.Valid($Heap, this) == ($Heap[this, Node.footprint][this] && !$Heap[this, Node.footprint][null] && (forall n: ref :: $Heap[this, Node.footprint][n] ==> $Heap[n, Node.footprint][n] && !$Heap[n, Node.footprint][null] && Set#Subset($Heap[n, Node.footprint], $Heap[this, Node.footprint]) && ($Heap[n, Node.next] == null ==> Seq#Equal($Heap[n, Node.list], Seq#Build(Seq#Empty(), 0, $Heap[n, Node.data], 1))) && ($Heap[n, Node.next] != null ==> $Heap[n, Node.footprint][$Heap[n, Node.next]] && Set#Subset($Heap[$Heap[n, Node.next], Node.footprint], $Heap[n, Node.footprint]) && !$Heap[$Heap[n, Node.next], Node.footprint][n] && Seq#Equal($Heap[n, Node.list], Seq#Append(Seq#Build(Seq#Empty(), 0, $Heap[n, Node.data], 1), $Heap[$Heap[n, Node.next], Node.list])))) && ($Heap[this, Node.next] != null ==> Node.Valid($Heap, $Heap[this, Node.next]))));
+
+
+
+
+procedure Node.ReverseInPlace(this: ref where this != null && $Heap[this, alloc]) returns (reverse: ref where reverse == null || $Heap[reverse, alloc]);
+ // user-defined preconditions
+ free requires Node.Valid($Heap, this);
+ requires $Heap[this, Node.footprint][this];
+ requires !$Heap[this, Node.footprint][null];
+ requires $Heap[this, Node.next] != null ==> Node.Valid($Heap, $Heap[this, Node.next]);
+ modifies $Heap;
+ // frame condition
+ // boilerplate
+ free ensures $HeapSucc(old($Heap), $Heap);
+
+
+
+procedure CheckWellformed$$Node.Valid(this: ref where this != null && $Heap[this, alloc]);
+
+
+
+
+
+implementation Node.ReverseInPlace(this: ref) returns (reverse: ref)
+{
+ var current: ref where current == null || $Heap[current, alloc], $PreLoopHeap0: HeapType, nx: ref where nx == null || $Heap[nx, alloc];
+
+ // ----- var-declaration statement ----- test.dfy(28,9)
+ current := $Heap[this, Node.next];
+
+
+ // ----- assignment statement ----- test.dfy(29,13)
+ reverse := this;
+ // ----- assignment statement ----- test.dfy(30,18)
+ $Heap[reverse, Node.next] := null;
+ assume $IsGoodHeap($Heap);
+
+
+
+ // ----- assignment statement ----- test.dfy(31,23)
+ $Heap[reverse, Node.footprint] := // Set#UnionOne(Set#Empty(), reverse);
+ Set#Singleton(reverse);
+
+ assert current == null;
+}
+
+
diff --git a/Test/test21/MapOutputTypeParams.bpl b/Test/test21/MapOutputTypeParams.bpl
new file mode 100644
index 00000000..f0ca307f
--- /dev/null
+++ b/Test/test21/MapOutputTypeParams.bpl
@@ -0,0 +1,33 @@
+
+
+
+var p : <a>[int]a;
+
+procedure P() returns () modifies p; {
+ p[13] := 5;
+ p[17] := true;
+ p[13] := false;
+ p[17] := 8;
+
+ assert p[13] == 5 && !p[13] && p[17] == 8 && p[17];
+ assert p == p[28 := p]; // error
+}
+
+var q : <a, b>[int][a]b;
+
+procedure Q() returns () modifies q; {
+ q[17] := q[17][true := 13];
+ q[17] := q[17][true := false];
+ q[16] := q[17][true := 14];
+
+ assert q[17][true] == 13 && !q[17][true];
+ assert q[17][true] == 14; // error
+}
+
+procedure R() returns () modifies p; {
+ p[7] := 28;
+ p[5] := p[7];
+
+ assert p[7] == 28;
+ assert p[6] == 28; // error
+} \ No newline at end of file
diff --git a/Test/test21/Maps0.bpl b/Test/test21/Maps0.bpl
new file mode 100644
index 00000000..6c382a96
--- /dev/null
+++ b/Test/test21/Maps0.bpl
@@ -0,0 +1,56 @@
+
+
+const a : [int] bool;
+const b : [int, bool] int;
+
+function f<a>(a) returns (int);
+
+axiom (forall x : [int] bool :: f(x) == 7);
+axiom (forall y : [int, bool] int :: f(y) == 7);
+
+procedure P() returns () {
+ var x : [int] bool;
+
+ assert f(a) > 0;
+ assert f(b) > 0;
+
+ x := a;
+ x[17] := false;
+ x[16] := true;
+
+ assert x[15] == a[15] && !x[17];
+ assert f(x) == 7;
+ assert f(x) == 8; // should not be provable
+}
+
+
+type Field a;
+
+const heap : <a>[ref, Field a] a;
+
+procedure Q() returns () {
+ assert f(heap) > 0; // should not be provable
+}
+
+
+procedure R() returns () {
+ var o : ref;
+ var e : Field int, g : Field bool, h : Field (Field int), i : Field int;
+ var heap2 : <a>[ref, Field a] a;
+
+ heap2 := heap;
+ heap2[o, e] := 17;
+ assert heap2 == heap[o, e := 17];
+
+ heap2[o, g] := true;
+ assert heap2[o, e] == 17 && heap2[o, g];
+
+ heap2[o, h] := e;
+ assert heap2[o, heap2[o, h]] == 17;
+
+ heap2[o, i] := 16;
+ assert heap2[o, g];
+ assert heap2[o, heap2[o, h]] == 17; // should no longer be provable
+}
+
+type ref;
diff --git a/Test/test21/Maps1.bpl b/Test/test21/Maps1.bpl
new file mode 100644
index 00000000..94d29e32
--- /dev/null
+++ b/Test/test21/Maps1.bpl
@@ -0,0 +1,36 @@
+
+
+// different map type classes with the same arity
+
+const c : [int] bool;
+const d : [ref] bool;
+const e : <a> [a] bool;
+const f : <a> [a] a;
+
+axiom (c[17] ==> c[19]);
+axiom (forall<t> x:t :: e[x]);
+axiom (!d[null]);
+axiom (forall<t> x:t :: f[x] == x);
+
+procedure P() returns () {
+
+ var x : <a> [a] bool;
+
+ assume !c[19];
+ assert !c[17];
+
+ x := e;
+ x[true] := false;
+ x[17] := true;
+
+ assert !x[true];
+ assert !(forall<t> y:t :: x[y]);
+ assert x != e;
+
+ assert f[x] == x;
+ assert f[17] > 17; // should not be provable
+
+}
+
+type ref;
+const null : ref;
diff --git a/Test/test21/Maps2.bpl b/Test/test21/Maps2.bpl
new file mode 100644
index 00000000..3f055c1d
--- /dev/null
+++ b/Test/test21/Maps2.bpl
@@ -0,0 +1,24 @@
+
+type T;
+
+function f(x : [T][int]int) returns (int);
+
+axiom (forall x:[T][int]int :: {f(x)}
+ (exists t:T :: x[t][13] == 42) ==> f(x) == 5);
+
+procedure P() returns () {
+ var x : [T][int]int, t : T;
+
+ x[t] := x[t][13 := 42];
+
+ assert f(x) == 5;
+}
+
+
+type name;
+
+function Field(int) returns (name);
+function Unified([name][int]int) returns ([int]int);
+
+axiom(forall M:[name][int]int, x:int, y:int :: {Unified(M[Field(x) := M[Field(x)][x := y]])}
+ Unified(M[Field(x) := M[Field(x)][x := y]]) == Unified(M)[x := y]);
diff --git a/Test/test21/NameClash.bpl b/Test/test21/NameClash.bpl
new file mode 100644
index 00000000..6e1ade48
--- /dev/null
+++ b/Test/test21/NameClash.bpl
@@ -0,0 +1,8 @@
+
+
+function f(int) returns (int);
+axiom f(13) == 0;
+
+procedure P() returns () {
+ assert (exists f:int :: 0 == f(f));
+} \ No newline at end of file
diff --git a/Test/test21/Orderings.bpl b/Test/test21/Orderings.bpl
new file mode 100644
index 00000000..78439bc1
--- /dev/null
+++ b/Test/test21/Orderings.bpl
@@ -0,0 +1,20 @@
+
+
+const a, b:int;
+const c:int extends a, b;
+
+procedure P() returns () {
+ var x:int;
+
+ assert c <: a;
+
+ assume c <: x && x <: a;
+ assert x == c || a == x;
+
+ assert x == b; // should not be provable
+}
+
+procedure Q() returns () {
+ assume b <: a;
+ assert b == a;
+} \ No newline at end of file
diff --git a/Test/test21/Orderings2.bpl b/Test/test21/Orderings2.bpl
new file mode 100644
index 00000000..75becb2a
--- /dev/null
+++ b/Test/test21/Orderings2.bpl
@@ -0,0 +1,18 @@
+
+
+const b:int;
+const a:int extends b complete;
+
+const c:int extends a;
+const d:int extends a;
+
+procedure P() returns () {
+ var x:int;
+
+ assert c <: b && d <: a;
+
+ assume x <: a && !(x <: c) && x != a;
+ assert x <: d;
+
+ assert b <: x; // should not be provable
+} \ No newline at end of file
diff --git a/Test/test21/Orderings3.bpl b/Test/test21/Orderings3.bpl
new file mode 100644
index 00000000..c94d298c
--- /dev/null
+++ b/Test/test21/Orderings3.bpl
@@ -0,0 +1,38 @@
+// Example from the Boogie 2 language report
+
+
+type Wicket;
+
+
+const unique a: Wicket extends complete;
+const unique b: Wicket;
+const unique c: Wicket extends a, b complete;
+const unique d: Wicket extends c;
+const unique e: Wicket;
+
+procedure P() returns () {
+
+ assert !(exists x:Wicket :: a <: x && a != x);
+ assert (forall x:Wicket :: x <: a ==> x == a || x <: c);
+
+ assert c <: b && !(exists x:Wicket :: c <: x && x <: b && x != c && x != b);
+
+ assert !(b <: a) && !(b <: c);
+
+ assert c <: a && c <: b && d <: c;
+ assert (forall x:Wicket :: c <: x ==> c==x || a <: x || b <: x);
+ assert (forall x:Wicket :: x <: c ==> c==x || x <: d);
+
+ assert d <: c;
+ assert !(a <: d) && !(b <: d) && !(c <: d);
+
+ assert false; // unprovable
+}
+
+procedure Q() returns () {
+
+ assert (forall x:Wicket :: x <: b && x != b ==> x <: c); // unprovable
+
+ assert !(exists x:Wicket :: b <: x && b != x); // unprovable
+
+} \ No newline at end of file
diff --git a/Test/test21/Orderings4.bpl b/Test/test21/Orderings4.bpl
new file mode 100644
index 00000000..3058287f
--- /dev/null
+++ b/Test/test21/Orderings4.bpl
@@ -0,0 +1,11 @@
+
+
+type Wicket;
+
+const unique r: Wicket;
+const unique s, t: Wicket extends unique r;
+
+procedure P() returns () {
+ assert (forall x:Wicket, y:Wicket :: x <: s && y <: t ==> x != y);
+ assert false; // unprovable
+} \ No newline at end of file
diff --git a/Test/test21/Output b/Test/test21/Output
new file mode 100644
index 00000000..bda444d2
--- /dev/null
+++ b/Test/test21/Output
@@ -0,0 +1,1677 @@
+--------------------- TypeEncoding n ----------------------------
+--------------------- File DisjointDomains.bpl ----------------------------
+
+Boogie program verifier finished with 3 verified, 0 errors
+--------------------- File DisjointDomains2.bpl ----------------------------
+DisjointDomains2.bpl(11,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ DisjointDomains2.bpl(9,3): start
+DisjointDomains2.bpl(18,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ DisjointDomains2.bpl(16,3): start
+
+Boogie program verifier finished with 4 verified, 2 errors
+--------------------- File FunAxioms.bpl ----------------------------
+FunAxioms.bpl(30,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ FunAxioms.bpl(18,3): anon0
+
+Boogie program verifier finished with 1 verified, 1 error
+--------------------- File FunAxioms2.bpl ----------------------------
+FunAxioms2.bpl(20,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ FunAxioms2.bpl(16,5): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File PolyList.bpl ----------------------------
+PolyList.bpl(42,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ PolyList.bpl(27,7): anon0
+PolyList.bpl(60,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ PolyList.bpl(49,7): anon0
+
+Boogie program verifier finished with 0 verified, 2 errors
+--------------------- File Maps0.bpl ----------------------------
+Maps0.bpl(23,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Maps0.bpl(14,3): anon0
+Maps0.bpl(46,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Maps0.bpl(41,9): anon0
+Maps0.bpl(49,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Maps0.bpl(41,9): anon0
+Maps0.bpl(52,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Maps0.bpl(41,9): anon0
+Maps0.bpl(53,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Maps0.bpl(41,9): anon0
+
+Boogie program verifier finished with 1 verified, 5 errors
+--------------------- File Maps1.bpl ----------------------------
+Maps1.bpl(26,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Maps1.bpl(19,3): anon0
+Maps1.bpl(31,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Maps1.bpl(19,3): anon0
+
+Boogie program verifier finished with 0 verified, 2 errors
+--------------------- File InterestingExamples0.bpl ----------------------------
+InterestingExamples0.bpl(7,1): Error BP5001: This assertion might not hold.
+Execution trace:
+ InterestingExamples0.bpl(5,6): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File InterestingExamples1.bpl ----------------------------
+InterestingExamples1.bpl(16,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ InterestingExamples1.bpl(13,5): anon0
+InterestingExamples1.bpl(22,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ InterestingExamples1.bpl(13,5): anon0
+
+Boogie program verifier finished with 0 verified, 2 errors
+--------------------- File InterestingExamples2.bpl ----------------------------
+InterestingExamples2.bpl(9,1): Error BP5001: This assertion might not hold.
+Execution trace:
+ InterestingExamples2.bpl(8,6): anon0
+InterestingExamples2.bpl(10,1): Error BP5001: This assertion might not hold.
+Execution trace:
+ InterestingExamples2.bpl(8,6): anon0
+
+Boogie program verifier finished with 0 verified, 2 errors
+--------------------- File InterestingExamples3.bpl ----------------------------
+InterestingExamples3.bpl(15,2): Error BP5001: This assertion might not hold.
+Execution trace:
+ InterestingExamples3.bpl(13,2): anon0
+
+Boogie program verifier finished with 2 verified, 1 error
+--------------------- File InterestingExamples4.bpl ----------------------------
+InterestingExamples4.bpl(36,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ InterestingExamples4.bpl(36,3): anon0
+InterestingExamples4.bpl(39,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ InterestingExamples4.bpl(36,3): anon0
+
+Boogie program verifier finished with 0 verified, 2 errors
+--------------------- File InterestingExamples5.bpl ----------------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
+--------------------- File Colors.bpl ----------------------------
+Colors.bpl(13,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Colors.bpl(12,3): anon0
+Colors.bpl(20,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Colors.bpl(19,3): anon0
+
+Boogie program verifier finished with 0 verified, 2 errors
+--------------------- File HeapAbstraction.bpl ----------------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
+--------------------- File HeapAxiom.bpl ----------------------------
+HeapAxiom.bpl(24,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ HeapAxiom.bpl(13,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File Triggers0.bpl ----------------------------
+Triggers0.bpl(39,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Triggers0.bpl(39,3): anon0
+Triggers0.bpl(43,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Triggers0.bpl(39,3): anon0
+
+Boogie program verifier finished with 1 verified, 2 errors
+--------------------- File Triggers1.bpl ----------------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
+--------------------- File Keywords.bpl ----------------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
+--------------------- File Casts.bpl ----------------------------
+Casts.bpl(10,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Casts.bpl(6,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File EmptyList.bpl ----------------------------
+EmptyList.bpl(46,9): Warning: type parameter a is ambiguous, instantiating to List int
+EmptyList.bpl(28,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ EmptyList.bpl(26,5): anon0
+EmptyList.bpl(42,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ EmptyList.bpl(26,5): anon0
+EmptyList.bpl(46,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ EmptyList.bpl(46,3): anon0
+
+Boogie program verifier finished with 0 verified, 3 errors
+--------------------- File Boxing.bpl ----------------------------
+Boxing.bpl(19,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Boxing.bpl(15,6): anon0
+Boxing.bpl(20,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Boxing.bpl(15,6): anon0
+
+Boogie program verifier finished with 0 verified, 2 errors
+--------------------- File MapOutputTypeParams.bpl ----------------------------
+MapOutputTypeParams.bpl(29,3): Warning: type parameter a is ambiguous, instantiating to int
+MapOutputTypeParams.bpl(12,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ MapOutputTypeParams.bpl(7,9): anon0
+MapOutputTypeParams.bpl(13,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ MapOutputTypeParams.bpl(7,9): anon0
+MapOutputTypeParams.bpl(23,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ MapOutputTypeParams.bpl(19,9): anon0
+MapOutputTypeParams.bpl(24,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ MapOutputTypeParams.bpl(19,9): anon0
+MapOutputTypeParams.bpl(31,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ MapOutputTypeParams.bpl(28,8): anon0
+MapOutputTypeParams.bpl(32,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ MapOutputTypeParams.bpl(28,8): anon0
+
+Boogie program verifier finished with 0 verified, 6 errors
+--------------------- File ParallelAssignment.bpl ----------------------------
+ParallelAssignment.bpl(26,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ ParallelAssignment.bpl(15,5): anon0
+ParallelAssignment.bpl(35,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ ParallelAssignment.bpl(15,5): anon0
+ParallelAssignment.bpl(54,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ ParallelAssignment.bpl(40,11): anon0
+
+Boogie program verifier finished with 0 verified, 3 errors
+--------------------- File BooleanQuantification.bpl ----------------------------
+BooleanQuantification.bpl(10,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ BooleanQuantification.bpl(10,3): anon0
+BooleanQuantification.bpl(18,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ BooleanQuantification.bpl(18,3): anon0
+BooleanQuantification.bpl(19,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ BooleanQuantification.bpl(18,3): anon0
+BooleanQuantification.bpl(29,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ BooleanQuantification.bpl(29,3): anon0
+BooleanQuantification.bpl(31,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ BooleanQuantification.bpl(29,3): anon0
+
+Boogie program verifier finished with 1 verified, 5 errors
+--------------------- File BooleanQuantification2.bpl ----------------------------
+BooleanQuantification2.bpl(13,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ BooleanQuantification2.bpl(10,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File Flattening.bpl ----------------------------
+Flattening.bpl(12,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Flattening.bpl(12,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File Orderings.bpl ----------------------------
+Orderings.bpl(14,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Orderings.bpl(9,3): anon0
+
+Boogie program verifier finished with 1 verified, 1 error
+--------------------- File Orderings2.bpl ----------------------------
+Orderings2.bpl(17,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Orderings2.bpl(12,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File Orderings3.bpl ----------------------------
+Orderings3.bpl(29,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Orderings3.bpl(15,3): anon0
+Orderings3.bpl(34,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Orderings3.bpl(34,3): anon0
+Orderings3.bpl(36,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Orderings3.bpl(34,3): anon0
+
+Boogie program verifier finished with 0 verified, 3 errors
+--------------------- File Orderings4.bpl ----------------------------
+Orderings4.bpl(10,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Orderings4.bpl(9,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File EmptySetBug.bpl ----------------------------
+EmptySetBug.bpl(27,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ EmptySetBug.bpl(25,5): anon0
+EmptySetBug.bpl(29,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ EmptySetBug.bpl(25,5): anon0
+
+Boogie program verifier finished with 0 verified, 2 errors
+--------------------- File Coercions2.bpl ----------------------------
+Coercions2.bpl(12,23): Warning: type parameter a is ambiguous, instantiating to int
+Coercions2.bpl(18,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Coercions2.bpl(18,3): anon0
+Coercions2.bpl(23,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Coercions2.bpl(18,3): anon0
+
+Boogie program verifier finished with 0 verified, 2 errors
+--------------------- File MapAxiomsConsistency.bpl ----------------------------
+MapAxiomsConsistency.bpl(94,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ MapAxiomsConsistency.bpl(79,13): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File LargeLiterals0.bpl ----------------------------
+LargeLiterals0.bpl(18,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ LargeLiterals0.bpl(7,5): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File NameClash.bpl ----------------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
+--------------------- File LetSorting.bpl ----------------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
+--------------------- File Keywords.bpl ----------------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
+--------------------- File LargeLiterals0.bpl ----------------------------
+LargeLiterals0.bpl(18,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ LargeLiterals0.bpl(7,5): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- TypeEncoding p ----------------------------
+--------------------- File DisjointDomains.bpl ----------------------------
+DisjointDomains.bpl(14,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ DisjointDomains.bpl(11,3): start
+DisjointDomains.bpl(21,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ DisjointDomains.bpl(20,3): start
+DisjointDomains.bpl(27,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ DisjointDomains.bpl(26,3): start
+
+Boogie program verifier finished with 0 verified, 3 errors
+--------------------- File DisjointDomains2.bpl ----------------------------
+DisjointDomains2.bpl(11,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ DisjointDomains2.bpl(9,3): start
+DisjointDomains2.bpl(18,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ DisjointDomains2.bpl(16,3): start
+DisjointDomains2.bpl(32,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ DisjointDomains2.bpl(30,3): start
+DisjointDomains2.bpl(39,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ DisjointDomains2.bpl(37,3): start
+DisjointDomains2.bpl(49,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ DisjointDomains2.bpl(45,3): start
+DisjointDomains2.bpl(63,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ DisjointDomains2.bpl(58,3): start
+
+Boogie program verifier finished with 0 verified, 6 errors
+--------------------- File FunAxioms.bpl ----------------------------
+FunAxioms.bpl(30,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ FunAxioms.bpl(18,3): anon0
+
+Boogie program verifier finished with 1 verified, 1 error
+--------------------- File FunAxioms2.bpl ----------------------------
+FunAxioms2.bpl(20,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ FunAxioms2.bpl(16,5): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File PolyList.bpl ----------------------------
+PolyList.bpl(42,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ PolyList.bpl(27,7): anon0
+PolyList.bpl(60,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ PolyList.bpl(49,7): anon0
+
+Boogie program verifier finished with 0 verified, 2 errors
+--------------------- File Maps0.bpl ----------------------------
+Maps0.bpl(23,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Maps0.bpl(14,3): anon0
+Maps0.bpl(32,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Maps0.bpl(32,3): anon0
+Maps0.bpl(53,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Maps0.bpl(41,9): anon0
+
+Boogie program verifier finished with 0 verified, 3 errors
+--------------------- File Maps1.bpl ----------------------------
+Maps1.bpl(31,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Maps1.bpl(19,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File InterestingExamples0.bpl ----------------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
+--------------------- File InterestingExamples1.bpl ----------------------------
+InterestingExamples1.bpl(22,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ InterestingExamples1.bpl(13,5): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File InterestingExamples2.bpl ----------------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
+--------------------- File InterestingExamples3.bpl ----------------------------
+InterestingExamples3.bpl(15,2): Error BP5001: This assertion might not hold.
+Execution trace:
+ InterestingExamples3.bpl(13,2): anon0
+
+Boogie program verifier finished with 2 verified, 1 error
+--------------------- File InterestingExamples4.bpl ----------------------------
+InterestingExamples4.bpl(39,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ InterestingExamples4.bpl(36,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File InterestingExamples5.bpl ----------------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
+--------------------- File Colors.bpl ----------------------------
+Colors.bpl(13,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Colors.bpl(12,3): anon0
+
+Boogie program verifier finished with 1 verified, 1 error
+--------------------- File HeapAbstraction.bpl ----------------------------
+HeapAbstraction.bpl(15,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ HeapAbstraction.bpl(14,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File HeapAxiom.bpl ----------------------------
+HeapAxiom.bpl(24,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ HeapAxiom.bpl(13,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File Triggers0.bpl ----------------------------
+Triggers0.bpl(39,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Triggers0.bpl(39,3): anon0
+Triggers0.bpl(43,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Triggers0.bpl(39,3): anon0
+
+Boogie program verifier finished with 1 verified, 2 errors
+--------------------- File Triggers1.bpl ----------------------------
+Triggers1.bpl(16,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Triggers1.bpl(12,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File Keywords.bpl ----------------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
+--------------------- File Casts.bpl ----------------------------
+Casts.bpl(10,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Casts.bpl(6,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File EmptyList.bpl ----------------------------
+EmptyList.bpl(46,9): Warning: type parameter a is ambiguous, instantiating to List int
+EmptyList.bpl(42,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ EmptyList.bpl(26,5): anon0
+
+Boogie program verifier finished with 1 verified, 1 error
+--------------------- File Boxing.bpl ----------------------------
+Boxing.bpl(20,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Boxing.bpl(15,6): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File MapOutputTypeParams.bpl ----------------------------
+MapOutputTypeParams.bpl(29,3): Warning: type parameter a is ambiguous, instantiating to int
+MapOutputTypeParams.bpl(13,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ MapOutputTypeParams.bpl(7,9): anon0
+MapOutputTypeParams.bpl(24,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ MapOutputTypeParams.bpl(19,9): anon0
+MapOutputTypeParams.bpl(32,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ MapOutputTypeParams.bpl(28,8): anon0
+
+Boogie program verifier finished with 0 verified, 3 errors
+--------------------- File ParallelAssignment.bpl ----------------------------
+ParallelAssignment.bpl(26,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ ParallelAssignment.bpl(15,5): anon0
+ParallelAssignment.bpl(35,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ ParallelAssignment.bpl(15,5): anon0
+ParallelAssignment.bpl(54,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ ParallelAssignment.bpl(40,11): anon0
+
+Boogie program verifier finished with 0 verified, 3 errors
+--------------------- File BooleanQuantification.bpl ----------------------------
+BooleanQuantification.bpl(10,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ BooleanQuantification.bpl(10,3): anon0
+BooleanQuantification.bpl(18,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ BooleanQuantification.bpl(18,3): anon0
+BooleanQuantification.bpl(19,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ BooleanQuantification.bpl(18,3): anon0
+BooleanQuantification.bpl(29,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ BooleanQuantification.bpl(29,3): anon0
+BooleanQuantification.bpl(31,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ BooleanQuantification.bpl(29,3): anon0
+
+Boogie program verifier finished with 1 verified, 5 errors
+--------------------- File BooleanQuantification2.bpl ----------------------------
+BooleanQuantification2.bpl(13,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ BooleanQuantification2.bpl(10,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File Flattening.bpl ----------------------------
+Flattening.bpl(12,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Flattening.bpl(12,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File Orderings.bpl ----------------------------
+Orderings.bpl(14,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Orderings.bpl(9,3): anon0
+
+Boogie program verifier finished with 1 verified, 1 error
+--------------------- File Orderings2.bpl ----------------------------
+Orderings2.bpl(17,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Orderings2.bpl(12,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File Orderings3.bpl ----------------------------
+Orderings3.bpl(29,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Orderings3.bpl(15,3): anon0
+Orderings3.bpl(34,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Orderings3.bpl(34,3): anon0
+Orderings3.bpl(36,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Orderings3.bpl(34,3): anon0
+
+Boogie program verifier finished with 0 verified, 3 errors
+--------------------- File Orderings4.bpl ----------------------------
+Orderings4.bpl(10,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Orderings4.bpl(9,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File EmptySetBug.bpl ----------------------------
+EmptySetBug.bpl(29,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ EmptySetBug.bpl(25,5): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File Coercions2.bpl ----------------------------
+Coercions2.bpl(12,23): Warning: type parameter a is ambiguous, instantiating to int
+Coercions2.bpl(23,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Coercions2.bpl(18,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File MapAxiomsConsistency.bpl ----------------------------
+MapAxiomsConsistency.bpl(94,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ MapAxiomsConsistency.bpl(79,13): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File LargeLiterals0.bpl ----------------------------
+LargeLiterals0.bpl(18,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ LargeLiterals0.bpl(7,5): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File NameClash.bpl ----------------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
+--------------------- File LetSorting.bpl ----------------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
+--------------------- File Keywords.bpl ----------------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
+--------------------- File LargeLiterals0.bpl ----------------------------
+LargeLiterals0.bpl(18,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ LargeLiterals0.bpl(7,5): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- TypeEncoding a ----------------------------
+--------------------- File DisjointDomains.bpl ----------------------------
+DisjointDomains.bpl(14,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ DisjointDomains.bpl(11,3): start
+DisjointDomains.bpl(21,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ DisjointDomains.bpl(20,3): start
+DisjointDomains.bpl(27,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ DisjointDomains.bpl(26,3): start
+
+Boogie program verifier finished with 0 verified, 3 errors
+--------------------- File DisjointDomains2.bpl ----------------------------
+DisjointDomains2.bpl(11,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ DisjointDomains2.bpl(9,3): start
+DisjointDomains2.bpl(18,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ DisjointDomains2.bpl(16,3): start
+DisjointDomains2.bpl(32,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ DisjointDomains2.bpl(30,3): start
+DisjointDomains2.bpl(39,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ DisjointDomains2.bpl(37,3): start
+DisjointDomains2.bpl(49,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ DisjointDomains2.bpl(45,3): start
+DisjointDomains2.bpl(63,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ DisjointDomains2.bpl(58,3): start
+
+Boogie program verifier finished with 0 verified, 6 errors
+--------------------- File FunAxioms.bpl ----------------------------
+FunAxioms.bpl(30,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ FunAxioms.bpl(18,3): anon0
+
+Boogie program verifier finished with 1 verified, 1 error
+--------------------- File FunAxioms2.bpl ----------------------------
+FunAxioms2.bpl(20,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ FunAxioms2.bpl(16,5): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File PolyList.bpl ----------------------------
+PolyList.bpl(42,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ PolyList.bpl(27,7): anon0
+PolyList.bpl(60,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ PolyList.bpl(49,7): anon0
+
+Boogie program verifier finished with 0 verified, 2 errors
+--------------------- File Maps0.bpl ----------------------------
+Maps0.bpl(23,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Maps0.bpl(14,3): anon0
+Maps0.bpl(32,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Maps0.bpl(32,3): anon0
+Maps0.bpl(53,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Maps0.bpl(41,9): anon0
+
+Boogie program verifier finished with 0 verified, 3 errors
+--------------------- File Maps1.bpl ----------------------------
+Maps1.bpl(31,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Maps1.bpl(19,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File InterestingExamples0.bpl ----------------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
+--------------------- File InterestingExamples1.bpl ----------------------------
+InterestingExamples1.bpl(22,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ InterestingExamples1.bpl(13,5): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File InterestingExamples2.bpl ----------------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
+--------------------- File InterestingExamples3.bpl ----------------------------
+InterestingExamples3.bpl(15,2): Error BP5001: This assertion might not hold.
+Execution trace:
+ InterestingExamples3.bpl(13,2): anon0
+
+Boogie program verifier finished with 2 verified, 1 error
+--------------------- File InterestingExamples4.bpl ----------------------------
+InterestingExamples4.bpl(36,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ InterestingExamples4.bpl(36,3): anon0
+InterestingExamples4.bpl(39,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ InterestingExamples4.bpl(36,3): anon0
+
+Boogie program verifier finished with 0 verified, 2 errors
+--------------------- File InterestingExamples5.bpl ----------------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
+--------------------- File Colors.bpl ----------------------------
+Colors.bpl(13,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Colors.bpl(12,3): anon0
+Colors.bpl(20,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Colors.bpl(19,3): anon0
+
+Boogie program verifier finished with 0 verified, 2 errors
+--------------------- File HeapAbstraction.bpl ----------------------------
+HeapAbstraction.bpl(15,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ HeapAbstraction.bpl(14,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File HeapAxiom.bpl ----------------------------
+HeapAxiom.bpl(24,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ HeapAxiom.bpl(13,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File Triggers0.bpl ----------------------------
+Triggers0.bpl(39,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Triggers0.bpl(39,3): anon0
+Triggers0.bpl(43,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Triggers0.bpl(39,3): anon0
+
+Boogie program verifier finished with 1 verified, 2 errors
+--------------------- File Triggers1.bpl ----------------------------
+Triggers1.bpl(16,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Triggers1.bpl(12,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File Keywords.bpl ----------------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
+--------------------- File Casts.bpl ----------------------------
+Casts.bpl(10,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Casts.bpl(6,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File EmptyList.bpl ----------------------------
+EmptyList.bpl(46,9): Warning: type parameter a is ambiguous, instantiating to List int
+EmptyList.bpl(42,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ EmptyList.bpl(26,5): anon0
+
+Boogie program verifier finished with 1 verified, 1 error
+--------------------- File Boxing.bpl ----------------------------
+Boxing.bpl(20,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Boxing.bpl(15,6): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File MapOutputTypeParams.bpl ----------------------------
+MapOutputTypeParams.bpl(29,3): Warning: type parameter a is ambiguous, instantiating to int
+MapOutputTypeParams.bpl(13,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ MapOutputTypeParams.bpl(7,9): anon0
+MapOutputTypeParams.bpl(24,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ MapOutputTypeParams.bpl(19,9): anon0
+MapOutputTypeParams.bpl(32,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ MapOutputTypeParams.bpl(28,8): anon0
+
+Boogie program verifier finished with 0 verified, 3 errors
+--------------------- File ParallelAssignment.bpl ----------------------------
+ParallelAssignment.bpl(26,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ ParallelAssignment.bpl(15,5): anon0
+ParallelAssignment.bpl(35,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ ParallelAssignment.bpl(15,5): anon0
+ParallelAssignment.bpl(54,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ ParallelAssignment.bpl(40,11): anon0
+
+Boogie program verifier finished with 0 verified, 3 errors
+--------------------- File BooleanQuantification.bpl ----------------------------
+BooleanQuantification.bpl(10,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ BooleanQuantification.bpl(10,3): anon0
+BooleanQuantification.bpl(18,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ BooleanQuantification.bpl(18,3): anon0
+BooleanQuantification.bpl(19,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ BooleanQuantification.bpl(18,3): anon0
+BooleanQuantification.bpl(29,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ BooleanQuantification.bpl(29,3): anon0
+BooleanQuantification.bpl(31,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ BooleanQuantification.bpl(29,3): anon0
+
+Boogie program verifier finished with 1 verified, 5 errors
+--------------------- File BooleanQuantification2.bpl ----------------------------
+BooleanQuantification2.bpl(13,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ BooleanQuantification2.bpl(10,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File Flattening.bpl ----------------------------
+Flattening.bpl(12,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Flattening.bpl(12,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File Orderings.bpl ----------------------------
+Orderings.bpl(14,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Orderings.bpl(9,3): anon0
+
+Boogie program verifier finished with 1 verified, 1 error
+--------------------- File Orderings2.bpl ----------------------------
+Orderings2.bpl(17,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Orderings2.bpl(12,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File Orderings3.bpl ----------------------------
+Orderings3.bpl(29,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Orderings3.bpl(15,3): anon0
+Orderings3.bpl(34,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Orderings3.bpl(34,3): anon0
+Orderings3.bpl(36,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Orderings3.bpl(34,3): anon0
+
+Boogie program verifier finished with 0 verified, 3 errors
+--------------------- File Orderings4.bpl ----------------------------
+Orderings4.bpl(10,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Orderings4.bpl(9,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File EmptySetBug.bpl ----------------------------
+EmptySetBug.bpl(29,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ EmptySetBug.bpl(25,5): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File Coercions2.bpl ----------------------------
+Coercions2.bpl(12,23): Warning: type parameter a is ambiguous, instantiating to int
+Coercions2.bpl(23,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Coercions2.bpl(18,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File MapAxiomsConsistency.bpl ----------------------------
+MapAxiomsConsistency.bpl(94,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ MapAxiomsConsistency.bpl(79,13): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File LargeLiterals0.bpl ----------------------------
+LargeLiterals0.bpl(18,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ LargeLiterals0.bpl(7,5): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File NameClash.bpl ----------------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
+--------------------- File LetSorting.bpl ----------------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
+--------------------- File Keywords.bpl ----------------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
+--------------------- File LargeLiterals0.bpl ----------------------------
+LargeLiterals0.bpl(18,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ LargeLiterals0.bpl(7,5): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- TypeEncoding n z3types ----------------------------
+--------------------- File DisjointDomains.bpl ----------------------------
+
+Boogie program verifier finished with 3 verified, 0 errors
+--------------------- File DisjointDomains2.bpl ----------------------------
+DisjointDomains2.bpl(11,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ DisjointDomains2.bpl(9,3): start
+DisjointDomains2.bpl(18,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ DisjointDomains2.bpl(16,3): start
+
+Boogie program verifier finished with 4 verified, 2 errors
+--------------------- File FunAxioms.bpl ----------------------------
+FunAxioms.bpl(30,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ FunAxioms.bpl(18,3): anon0
+
+Boogie program verifier finished with 1 verified, 1 error
+--------------------- File FunAxioms2.bpl ----------------------------
+FunAxioms2.bpl(20,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ FunAxioms2.bpl(16,5): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File PolyList.bpl ----------------------------
+PolyList.bpl(42,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ PolyList.bpl(27,7): anon0
+PolyList.bpl(60,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ PolyList.bpl(49,7): anon0
+
+Boogie program verifier finished with 0 verified, 2 errors
+--------------------- File Maps0.bpl ----------------------------
+Maps0.bpl(23,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Maps0.bpl(14,3): anon0
+Maps0.bpl(46,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Maps0.bpl(41,9): anon0
+Maps0.bpl(49,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Maps0.bpl(41,9): anon0
+Maps0.bpl(52,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Maps0.bpl(41,9): anon0
+Maps0.bpl(53,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Maps0.bpl(41,9): anon0
+
+Boogie program verifier finished with 1 verified, 5 errors
+--------------------- File Maps1.bpl ----------------------------
+Maps1.bpl(26,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Maps1.bpl(19,3): anon0
+Maps1.bpl(31,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Maps1.bpl(19,3): anon0
+
+Boogie program verifier finished with 0 verified, 2 errors
+--------------------- File InterestingExamples0.bpl ----------------------------
+InterestingExamples0.bpl(7,1): Error BP5001: This assertion might not hold.
+Execution trace:
+ InterestingExamples0.bpl(5,6): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File InterestingExamples1.bpl ----------------------------
+InterestingExamples1.bpl(16,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ InterestingExamples1.bpl(13,5): anon0
+InterestingExamples1.bpl(22,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ InterestingExamples1.bpl(13,5): anon0
+
+Boogie program verifier finished with 0 verified, 2 errors
+--------------------- File InterestingExamples2.bpl ----------------------------
+InterestingExamples2.bpl(9,1): Error BP5001: This assertion might not hold.
+Execution trace:
+ InterestingExamples2.bpl(8,6): anon0
+InterestingExamples2.bpl(10,1): Error BP5001: This assertion might not hold.
+Execution trace:
+ InterestingExamples2.bpl(8,6): anon0
+
+Boogie program verifier finished with 0 verified, 2 errors
+--------------------- File InterestingExamples3.bpl ----------------------------
+InterestingExamples3.bpl(15,2): Error BP5001: This assertion might not hold.
+Execution trace:
+ InterestingExamples3.bpl(13,2): anon0
+
+Boogie program verifier finished with 2 verified, 1 error
+--------------------- File InterestingExamples4.bpl ----------------------------
+InterestingExamples4.bpl(36,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ InterestingExamples4.bpl(36,3): anon0
+InterestingExamples4.bpl(39,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ InterestingExamples4.bpl(36,3): anon0
+
+Boogie program verifier finished with 0 verified, 2 errors
+--------------------- File InterestingExamples5.bpl ----------------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
+--------------------- File Colors.bpl ----------------------------
+Colors.bpl(13,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Colors.bpl(12,3): anon0
+Colors.bpl(20,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Colors.bpl(19,3): anon0
+
+Boogie program verifier finished with 0 verified, 2 errors
+--------------------- File HeapAbstraction.bpl ----------------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
+--------------------- File HeapAxiom.bpl ----------------------------
+HeapAxiom.bpl(24,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ HeapAxiom.bpl(13,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File Triggers0.bpl ----------------------------
+Triggers0.bpl(39,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Triggers0.bpl(39,3): anon0
+Triggers0.bpl(43,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Triggers0.bpl(39,3): anon0
+
+Boogie program verifier finished with 1 verified, 2 errors
+--------------------- File Triggers1.bpl ----------------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
+--------------------- File Keywords.bpl ----------------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
+--------------------- File Casts.bpl ----------------------------
+Casts.bpl(10,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Casts.bpl(6,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File BooleanQuantification.bpl ----------------------------
+BooleanQuantification.bpl(19,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ BooleanQuantification.bpl(18,3): anon0
+BooleanQuantification.bpl(31,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ BooleanQuantification.bpl(29,3): anon0
+
+Boogie program verifier finished with 2 verified, 2 errors
+--------------------- File EmptyList.bpl ----------------------------
+EmptyList.bpl(46,9): Warning: type parameter a is ambiguous, instantiating to List int
+EmptyList.bpl(28,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ EmptyList.bpl(26,5): anon0
+EmptyList.bpl(42,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ EmptyList.bpl(26,5): anon0
+EmptyList.bpl(46,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ EmptyList.bpl(46,3): anon0
+
+Boogie program verifier finished with 0 verified, 3 errors
+--------------------- File Boxing.bpl ----------------------------
+Boxing.bpl(19,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Boxing.bpl(15,6): anon0
+Boxing.bpl(20,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Boxing.bpl(15,6): anon0
+
+Boogie program verifier finished with 0 verified, 2 errors
+--------------------- File MapOutputTypeParams.bpl ----------------------------
+MapOutputTypeParams.bpl(29,3): Warning: type parameter a is ambiguous, instantiating to int
+MapOutputTypeParams.bpl(12,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ MapOutputTypeParams.bpl(7,9): anon0
+MapOutputTypeParams.bpl(13,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ MapOutputTypeParams.bpl(7,9): anon0
+MapOutputTypeParams.bpl(23,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ MapOutputTypeParams.bpl(19,9): anon0
+MapOutputTypeParams.bpl(24,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ MapOutputTypeParams.bpl(19,9): anon0
+MapOutputTypeParams.bpl(31,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ MapOutputTypeParams.bpl(28,8): anon0
+MapOutputTypeParams.bpl(32,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ MapOutputTypeParams.bpl(28,8): anon0
+
+Boogie program verifier finished with 0 verified, 6 errors
+--------------------- File ParallelAssignment.bpl ----------------------------
+ParallelAssignment.bpl(26,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ ParallelAssignment.bpl(15,5): anon0
+ParallelAssignment.bpl(35,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ ParallelAssignment.bpl(15,5): anon0
+ParallelAssignment.bpl(54,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ ParallelAssignment.bpl(40,11): anon0
+
+Boogie program verifier finished with 0 verified, 3 errors
+--------------------- File BooleanQuantification2.bpl ----------------------------
+BooleanQuantification2.bpl(13,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ BooleanQuantification2.bpl(10,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File Flattening.bpl ----------------------------
+Flattening.bpl(12,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Flattening.bpl(12,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File Orderings.bpl ----------------------------
+Orderings.bpl(14,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Orderings.bpl(9,3): anon0
+
+Boogie program verifier finished with 1 verified, 1 error
+--------------------- File Orderings2.bpl ----------------------------
+Orderings2.bpl(17,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Orderings2.bpl(12,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File Orderings3.bpl ----------------------------
+Orderings3.bpl(29,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Orderings3.bpl(15,3): anon0
+Orderings3.bpl(34,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Orderings3.bpl(34,3): anon0
+Orderings3.bpl(36,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Orderings3.bpl(34,3): anon0
+
+Boogie program verifier finished with 0 verified, 3 errors
+--------------------- File Orderings4.bpl ----------------------------
+Orderings4.bpl(10,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Orderings4.bpl(9,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File EmptySetBug.bpl ----------------------------
+EmptySetBug.bpl(27,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ EmptySetBug.bpl(25,5): anon0
+EmptySetBug.bpl(29,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ EmptySetBug.bpl(25,5): anon0
+
+Boogie program verifier finished with 0 verified, 2 errors
+--------------------- File Coercions2.bpl ----------------------------
+Coercions2.bpl(12,23): Warning: type parameter a is ambiguous, instantiating to int
+Coercions2.bpl(18,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Coercions2.bpl(18,3): anon0
+Coercions2.bpl(23,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Coercions2.bpl(18,3): anon0
+
+Boogie program verifier finished with 0 verified, 2 errors
+--------------------- File MapAxiomsConsistency.bpl ----------------------------
+MapAxiomsConsistency.bpl(94,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ MapAxiomsConsistency.bpl(79,13): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File LargeLiterals0.bpl ----------------------------
+LargeLiterals0.bpl(18,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ LargeLiterals0.bpl(7,5): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File LetSorting.bpl ----------------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
+--------------------- TypeEncoding p z3types ----------------------------
+--------------------- File DisjointDomains.bpl ----------------------------
+DisjointDomains.bpl(14,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ DisjointDomains.bpl(11,3): start
+DisjointDomains.bpl(21,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ DisjointDomains.bpl(20,3): start
+DisjointDomains.bpl(27,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ DisjointDomains.bpl(26,3): start
+
+Boogie program verifier finished with 0 verified, 3 errors
+--------------------- File DisjointDomains2.bpl ----------------------------
+DisjointDomains2.bpl(11,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ DisjointDomains2.bpl(9,3): start
+DisjointDomains2.bpl(18,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ DisjointDomains2.bpl(16,3): start
+DisjointDomains2.bpl(32,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ DisjointDomains2.bpl(30,3): start
+DisjointDomains2.bpl(39,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ DisjointDomains2.bpl(37,3): start
+DisjointDomains2.bpl(49,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ DisjointDomains2.bpl(45,3): start
+DisjointDomains2.bpl(63,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ DisjointDomains2.bpl(58,3): start
+
+Boogie program verifier finished with 0 verified, 6 errors
+--------------------- File FunAxioms.bpl ----------------------------
+FunAxioms.bpl(30,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ FunAxioms.bpl(18,3): anon0
+
+Boogie program verifier finished with 1 verified, 1 error
+--------------------- File FunAxioms2.bpl ----------------------------
+FunAxioms2.bpl(20,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ FunAxioms2.bpl(16,5): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File PolyList.bpl ----------------------------
+PolyList.bpl(42,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ PolyList.bpl(27,7): anon0
+PolyList.bpl(60,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ PolyList.bpl(49,7): anon0
+
+Boogie program verifier finished with 0 verified, 2 errors
+--------------------- File Maps0.bpl ----------------------------
+Maps0.bpl(23,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Maps0.bpl(14,3): anon0
+Maps0.bpl(32,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Maps0.bpl(32,3): anon0
+Maps0.bpl(53,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Maps0.bpl(41,9): anon0
+
+Boogie program verifier finished with 0 verified, 3 errors
+--------------------- File Maps1.bpl ----------------------------
+Maps1.bpl(31,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Maps1.bpl(19,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File InterestingExamples0.bpl ----------------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
+--------------------- File InterestingExamples1.bpl ----------------------------
+InterestingExamples1.bpl(22,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ InterestingExamples1.bpl(13,5): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File InterestingExamples2.bpl ----------------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
+--------------------- File InterestingExamples3.bpl ----------------------------
+InterestingExamples3.bpl(15,2): Error BP5001: This assertion might not hold.
+Execution trace:
+ InterestingExamples3.bpl(13,2): anon0
+
+Boogie program verifier finished with 2 verified, 1 error
+--------------------- File InterestingExamples4.bpl ----------------------------
+InterestingExamples4.bpl(39,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ InterestingExamples4.bpl(36,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File InterestingExamples5.bpl ----------------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
+--------------------- File Colors.bpl ----------------------------
+Colors.bpl(13,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Colors.bpl(12,3): anon0
+
+Boogie program verifier finished with 1 verified, 1 error
+--------------------- File HeapAbstraction.bpl ----------------------------
+HeapAbstraction.bpl(15,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ HeapAbstraction.bpl(14,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File HeapAxiom.bpl ----------------------------
+HeapAxiom.bpl(24,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ HeapAxiom.bpl(13,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File Triggers0.bpl ----------------------------
+Triggers0.bpl(39,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Triggers0.bpl(39,3): anon0
+Triggers0.bpl(43,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Triggers0.bpl(39,3): anon0
+
+Boogie program verifier finished with 1 verified, 2 errors
+--------------------- File Triggers1.bpl ----------------------------
+Triggers1.bpl(16,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Triggers1.bpl(12,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File Keywords.bpl ----------------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
+--------------------- File Casts.bpl ----------------------------
+Casts.bpl(10,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Casts.bpl(6,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File BooleanQuantification.bpl ----------------------------
+BooleanQuantification.bpl(19,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ BooleanQuantification.bpl(18,3): anon0
+BooleanQuantification.bpl(31,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ BooleanQuantification.bpl(29,3): anon0
+
+Boogie program verifier finished with 2 verified, 2 errors
+--------------------- File EmptyList.bpl ----------------------------
+EmptyList.bpl(46,9): Warning: type parameter a is ambiguous, instantiating to List int
+EmptyList.bpl(42,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ EmptyList.bpl(26,5): anon0
+
+Boogie program verifier finished with 1 verified, 1 error
+--------------------- File Boxing.bpl ----------------------------
+Boxing.bpl(20,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Boxing.bpl(15,6): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File MapOutputTypeParams.bpl ----------------------------
+MapOutputTypeParams.bpl(29,3): Warning: type parameter a is ambiguous, instantiating to int
+MapOutputTypeParams.bpl(13,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ MapOutputTypeParams.bpl(7,9): anon0
+MapOutputTypeParams.bpl(24,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ MapOutputTypeParams.bpl(19,9): anon0
+MapOutputTypeParams.bpl(32,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ MapOutputTypeParams.bpl(28,8): anon0
+
+Boogie program verifier finished with 0 verified, 3 errors
+--------------------- File ParallelAssignment.bpl ----------------------------
+ParallelAssignment.bpl(26,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ ParallelAssignment.bpl(15,5): anon0
+ParallelAssignment.bpl(35,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ ParallelAssignment.bpl(15,5): anon0
+ParallelAssignment.bpl(54,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ ParallelAssignment.bpl(40,11): anon0
+
+Boogie program verifier finished with 0 verified, 3 errors
+--------------------- File BooleanQuantification2.bpl ----------------------------
+BooleanQuantification2.bpl(13,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ BooleanQuantification2.bpl(10,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File Flattening.bpl ----------------------------
+Flattening.bpl(12,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Flattening.bpl(12,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File Orderings.bpl ----------------------------
+Orderings.bpl(14,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Orderings.bpl(9,3): anon0
+
+Boogie program verifier finished with 1 verified, 1 error
+--------------------- File Orderings2.bpl ----------------------------
+Orderings2.bpl(17,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Orderings2.bpl(12,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File Orderings3.bpl ----------------------------
+Orderings3.bpl(29,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Orderings3.bpl(15,3): anon0
+Orderings3.bpl(34,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Orderings3.bpl(34,3): anon0
+Orderings3.bpl(36,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Orderings3.bpl(34,3): anon0
+
+Boogie program verifier finished with 0 verified, 3 errors
+--------------------- File Orderings4.bpl ----------------------------
+Orderings4.bpl(10,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Orderings4.bpl(9,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File EmptySetBug.bpl ----------------------------
+EmptySetBug.bpl(29,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ EmptySetBug.bpl(25,5): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File Coercions2.bpl ----------------------------
+Coercions2.bpl(12,23): Warning: type parameter a is ambiguous, instantiating to int
+Coercions2.bpl(23,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Coercions2.bpl(18,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File MapAxiomsConsistency.bpl ----------------------------
+MapAxiomsConsistency.bpl(94,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ MapAxiomsConsistency.bpl(79,13): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File LargeLiterals0.bpl ----------------------------
+LargeLiterals0.bpl(18,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ LargeLiterals0.bpl(7,5): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File LetSorting.bpl ----------------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
+--------------------- TypeEncoding a z3types ----------------------------
+--------------------- File DisjointDomains.bpl ----------------------------
+DisjointDomains.bpl(14,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ DisjointDomains.bpl(11,3): start
+DisjointDomains.bpl(21,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ DisjointDomains.bpl(20,3): start
+DisjointDomains.bpl(27,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ DisjointDomains.bpl(26,3): start
+
+Boogie program verifier finished with 0 verified, 3 errors
+--------------------- File DisjointDomains2.bpl ----------------------------
+DisjointDomains2.bpl(11,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ DisjointDomains2.bpl(9,3): start
+DisjointDomains2.bpl(18,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ DisjointDomains2.bpl(16,3): start
+DisjointDomains2.bpl(32,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ DisjointDomains2.bpl(30,3): start
+DisjointDomains2.bpl(39,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ DisjointDomains2.bpl(37,3): start
+DisjointDomains2.bpl(49,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ DisjointDomains2.bpl(45,3): start
+DisjointDomains2.bpl(63,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ DisjointDomains2.bpl(58,3): start
+
+Boogie program verifier finished with 0 verified, 6 errors
+--------------------- File FunAxioms.bpl ----------------------------
+FunAxioms.bpl(30,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ FunAxioms.bpl(18,3): anon0
+
+Boogie program verifier finished with 1 verified, 1 error
+--------------------- File FunAxioms2.bpl ----------------------------
+FunAxioms2.bpl(20,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ FunAxioms2.bpl(16,5): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File PolyList.bpl ----------------------------
+PolyList.bpl(42,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ PolyList.bpl(27,7): anon0
+PolyList.bpl(60,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ PolyList.bpl(49,7): anon0
+
+Boogie program verifier finished with 0 verified, 2 errors
+--------------------- File Maps0.bpl ----------------------------
+Maps0.bpl(23,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Maps0.bpl(14,3): anon0
+Maps0.bpl(32,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Maps0.bpl(32,3): anon0
+Maps0.bpl(53,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Maps0.bpl(41,9): anon0
+
+Boogie program verifier finished with 0 verified, 3 errors
+--------------------- File Maps1.bpl ----------------------------
+Maps1.bpl(31,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Maps1.bpl(19,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File InterestingExamples0.bpl ----------------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
+--------------------- File InterestingExamples1.bpl ----------------------------
+InterestingExamples1.bpl(22,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ InterestingExamples1.bpl(13,5): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File InterestingExamples2.bpl ----------------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
+--------------------- File InterestingExamples3.bpl ----------------------------
+InterestingExamples3.bpl(15,2): Error BP5001: This assertion might not hold.
+Execution trace:
+ InterestingExamples3.bpl(13,2): anon0
+
+Boogie program verifier finished with 2 verified, 1 error
+--------------------- File InterestingExamples4.bpl ----------------------------
+InterestingExamples4.bpl(36,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ InterestingExamples4.bpl(36,3): anon0
+InterestingExamples4.bpl(39,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ InterestingExamples4.bpl(36,3): anon0
+
+Boogie program verifier finished with 0 verified, 2 errors
+--------------------- File InterestingExamples5.bpl ----------------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
+--------------------- File Colors.bpl ----------------------------
+Colors.bpl(13,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Colors.bpl(12,3): anon0
+Colors.bpl(20,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Colors.bpl(19,3): anon0
+
+Boogie program verifier finished with 0 verified, 2 errors
+--------------------- File HeapAbstraction.bpl ----------------------------
+HeapAbstraction.bpl(15,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ HeapAbstraction.bpl(14,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File HeapAxiom.bpl ----------------------------
+HeapAxiom.bpl(24,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ HeapAxiom.bpl(13,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File Triggers0.bpl ----------------------------
+Triggers0.bpl(39,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Triggers0.bpl(39,3): anon0
+Triggers0.bpl(43,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Triggers0.bpl(39,3): anon0
+
+Boogie program verifier finished with 1 verified, 2 errors
+--------------------- File Triggers1.bpl ----------------------------
+Triggers1.bpl(16,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Triggers1.bpl(12,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File Keywords.bpl ----------------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
+--------------------- File Casts.bpl ----------------------------
+Casts.bpl(10,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Casts.bpl(6,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File BooleanQuantification.bpl ----------------------------
+BooleanQuantification.bpl(19,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ BooleanQuantification.bpl(18,3): anon0
+BooleanQuantification.bpl(31,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ BooleanQuantification.bpl(29,3): anon0
+
+Boogie program verifier finished with 2 verified, 2 errors
+--------------------- File EmptyList.bpl ----------------------------
+EmptyList.bpl(46,9): Warning: type parameter a is ambiguous, instantiating to List int
+EmptyList.bpl(42,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ EmptyList.bpl(26,5): anon0
+
+Boogie program verifier finished with 1 verified, 1 error
+--------------------- File Boxing.bpl ----------------------------
+Boxing.bpl(20,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Boxing.bpl(15,6): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File MapOutputTypeParams.bpl ----------------------------
+MapOutputTypeParams.bpl(29,3): Warning: type parameter a is ambiguous, instantiating to int
+MapOutputTypeParams.bpl(13,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ MapOutputTypeParams.bpl(7,9): anon0
+MapOutputTypeParams.bpl(24,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ MapOutputTypeParams.bpl(19,9): anon0
+MapOutputTypeParams.bpl(32,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ MapOutputTypeParams.bpl(28,8): anon0
+
+Boogie program verifier finished with 0 verified, 3 errors
+--------------------- File ParallelAssignment.bpl ----------------------------
+ParallelAssignment.bpl(26,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ ParallelAssignment.bpl(15,5): anon0
+ParallelAssignment.bpl(35,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ ParallelAssignment.bpl(15,5): anon0
+ParallelAssignment.bpl(54,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ ParallelAssignment.bpl(40,11): anon0
+
+Boogie program verifier finished with 0 verified, 3 errors
+--------------------- File BooleanQuantification2.bpl ----------------------------
+BooleanQuantification2.bpl(13,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ BooleanQuantification2.bpl(10,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File Flattening.bpl ----------------------------
+Flattening.bpl(12,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Flattening.bpl(12,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File Orderings.bpl ----------------------------
+Orderings.bpl(14,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Orderings.bpl(9,3): anon0
+
+Boogie program verifier finished with 1 verified, 1 error
+--------------------- File Orderings2.bpl ----------------------------
+Orderings2.bpl(17,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Orderings2.bpl(12,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File Orderings3.bpl ----------------------------
+Orderings3.bpl(29,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Orderings3.bpl(15,3): anon0
+Orderings3.bpl(34,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Orderings3.bpl(34,3): anon0
+Orderings3.bpl(36,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Orderings3.bpl(34,3): anon0
+
+Boogie program verifier finished with 0 verified, 3 errors
+--------------------- File Orderings4.bpl ----------------------------
+Orderings4.bpl(10,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Orderings4.bpl(9,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File EmptySetBug.bpl ----------------------------
+EmptySetBug.bpl(29,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ EmptySetBug.bpl(25,5): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File Coercions2.bpl ----------------------------
+Coercions2.bpl(12,23): Warning: type parameter a is ambiguous, instantiating to int
+Coercions2.bpl(23,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ Coercions2.bpl(18,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File MapAxiomsConsistency.bpl ----------------------------
+MapAxiomsConsistency.bpl(94,5): Error BP5001: This assertion might not hold.
+Execution trace:
+ MapAxiomsConsistency.bpl(79,13): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File LargeLiterals0.bpl ----------------------------
+LargeLiterals0.bpl(18,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ LargeLiterals0.bpl(7,5): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+--------------------- File LetSorting.bpl ----------------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
diff --git a/Test/test21/ParallelAssignment.bpl b/Test/test21/ParallelAssignment.bpl
new file mode 100644
index 00000000..05791b8e
--- /dev/null
+++ b/Test/test21/ParallelAssignment.bpl
@@ -0,0 +1,56 @@
+// Examples from the Boogie2 language report
+
+type C, D;
+
+var x : int;
+var y : int;
+var z : int;
+var a : [int]int;
+var b : [int][C, D]int;
+
+procedure P(i:int, j:int, m:C, n:D) returns () modifies x, y, a, b; {
+ var x1 : int;
+ var y1 : int;
+
+ x := x+1;
+ a[i] := 12;
+
+ assert a[i] == 12;
+
+ x1 := x;
+ y1 := y;
+
+ x, y := y, x;
+
+ assert x == y1 && y == x1;
+ assert x == x1; // error
+
+ x, a[i] := x+1, x;
+ assert x == y1+1 && a[i] == y1;
+
+ b[i][m, n] := 17;
+ b[i][m, n], x := a[x], y;
+
+ assert b[i][m, n] == a[y1+1];
+ assert false; // error
+}
+
+procedure Q() returns () modifies x, y, z; {
+
+ x, y, z := 1, 2, 3;
+
+ x, y, z := y, z, x;
+ x, y, z := y, z, x;
+ x, y, z := y, z, x;
+
+ assert x == 1 && y == 2 && z == 3;
+
+ x, y, z := y+1, z+1, x+1;
+ x, y, z := y+1, z+1, x+1;
+ x, y, z := y+1, z+1, x+1;
+
+ assert x == 4 && y == 5 && z == 6;
+
+ assert a[x] == a[y]; // error
+
+} \ No newline at end of file
diff --git a/Test/test21/PolyList.bpl b/Test/test21/PolyList.bpl
new file mode 100644
index 00000000..49d515f9
--- /dev/null
+++ b/Test/test21/PolyList.bpl
@@ -0,0 +1,62 @@
+
+
+
+type List a;
+
+function Cons<a>(x:a, y:List a) returns (List a);
+
+// we need some argument ... ugly
+function Nil<a>(a) returns (List a);
+
+function Car<a>(List a) returns (a);
+function Cdr<a>(List a) returns (List a);
+
+axiom (forall<a> x:a, y:List a :: Car(Cons(x, y)) == x);
+axiom (forall<a> x:a, y:List a :: Cdr(Cons(x, y)) == y);
+
+function Len<a>(List a) returns (int);
+
+axiom (forall <a> x:a :: Len(Nil(x)) == 0);
+axiom (forall <a> x:a, y:List a :: Len(Cons(x, y)) == 1 + Len(y));
+
+
+
+procedure P<a>(param : a) returns () {
+ var x:a, NIL : List a, l : List a;
+
+ NIL := Nil(x);
+
+ assert Len(NIL) == 0;
+ assert Len(Cons(x,Cons(x,NIL))) == 2;
+
+ l := Cons(x,Cons(x,NIL));
+ assert Len(l) == 2;
+
+ l := Cons(x, l);
+ assert Len(l) == 3 && Car(l) == x && Len(Cdr(l)) < Len(l);
+ assert (forall m : List a, y : a :: Len(Cons(y, m)) > Len(m));
+
+ l := Cdr(l);
+ assert Len(l) == 2 && Car(l) == x;
+
+ assert Len(Cons(x,Cons(x,Cons(x,NIL)))) == 2; // should not be provable
+
+}
+
+procedure Q() returns () {
+ var NIL : List int, l : List int;
+
+ NIL := Nil(0);
+
+ assert Len(NIL) == 0;
+ assert Len(Cons(1,Cons(2,NIL))) == 2;
+
+ l := NIL;
+ l := Cons(42, l);
+ l := Cons(Car(l) + 17, Cdr(l));
+
+ assert Len(l) == 1 && Car(l) == 59;
+
+ assert Len(Cons(1,Cons(2,Cons(3,NIL)))) == 2; // should not be provable
+
+} \ No newline at end of file
diff --git a/Test/test21/Triggers0.bpl b/Test/test21/Triggers0.bpl
new file mode 100644
index 00000000..4f7a8d11
--- /dev/null
+++ b/Test/test21/Triggers0.bpl
@@ -0,0 +1,44 @@
+
+
+const ar : [int]bool;
+axiom (forall x:int :: {ar[x]} !ar[x]);
+
+type S, T, C a b;
+
+function m(T,S) returns (bool);
+function n(T,T) returns (bool);
+function f<a>(C a T, a) returns (int);
+function f2<a>(C a T, a) returns (int);
+function g(T) returns (T);
+function h<a>(a) returns (a);
+function k<a>(C a a) returns (bool);
+function l<a>(a) returns (bool);
+function o<a>(a) returns (bool);
+
+const con : T;
+const someConst : int;
+
+axiom (forall <b> x:C b b :: k(x));
+axiom (forall x:C S T, y : S :: f(x,y) == f2(x,y));
+axiom (forall x:S, y:T :: l(x) && n(y, con) == m(y,x));
+axiom (forall x:T :: {g(h(x))} {g(x)} x == x);
+axiom (forall <b> x:b :: {h(x)} x == x);
+axiom (forall <b> x:b, y:b :: {o(x), o(y)} o(x) ==> someConst == 42);
+axiom (forall <b> x:C b b :: {k(x)} k(x));
+
+procedure P() returns () {
+ var v0 : C S S, v1 : C S T, v2 : S, v3 : T;
+
+ assert ar[27] == false;
+ assert k(v0);
+ assert f(v1, v2) == f2(v1, v2);
+ assert n(v3, con) == m(v3, v2);
+}
+
+procedure Q<a>(x : a) returns () {
+ assert someConst == 42; // should not be provable
+
+ assume o(x) == o(x);
+ assert someConst == 42;
+ assert someConst == 43; // should not be provable
+} \ No newline at end of file
diff --git a/Test/test21/Triggers1.bpl b/Test/test21/Triggers1.bpl
new file mode 100644
index 00000000..3633e704
--- /dev/null
+++ b/Test/test21/Triggers1.bpl
@@ -0,0 +1,17 @@
+
+
+
+function f<a>(a) returns (bool);
+function g(int) returns (bool);
+
+axiom (forall x:int :: f(x));
+axiom (forall x:int :: g(x));
+
+procedure P() returns () {
+ var x : int, m : [int]int;
+ assert f(x);
+ assert f(m[x]);
+ assert g(x);
+ assert g(m[x]);
+ assert f(true); // should not be provable
+} \ No newline at end of file
diff --git a/Test/test21/runtest.bat b/Test/test21/runtest.bat
new file mode 100644
index 00000000..223f278b
--- /dev/null
+++ b/Test/test21/runtest.bat
@@ -0,0 +1,53 @@
+@echo off
+setlocal
+
+set BGEXE=..\..\Binaries\Boogie.exe
+rem set BGEXE=mono ..\..\Binaries\Boogie.exe
+
+for %%m in (
+ n p a
+ ) do (
+echo --------------------- TypeEncoding %%m ----------------------------
+for %%f in (DisjointDomains.bpl DisjointDomains2.bpl FunAxioms.bpl
+ FunAxioms2.bpl PolyList.bpl Maps0.bpl Maps1.bpl
+ InterestingExamples0.bpl InterestingExamples1.bpl InterestingExamples2.bpl
+ InterestingExamples3.bpl InterestingExamples4.bpl InterestingExamples5.bpl
+ Colors.bpl HeapAbstraction.bpl HeapAxiom.bpl Triggers0.bpl Triggers1.bpl
+ Keywords.bpl Casts.bpl EmptyList.bpl Boxing.bpl MapOutputTypeParams.bpl
+ ParallelAssignment.bpl BooleanQuantification.bpl BooleanQuantification2.bpl
+ Flattening.bpl Orderings.bpl Orderings2.bpl Orderings3.bpl Orderings4.bpl
+ EmptySetBug.bpl Coercions2.bpl MapAxiomsConsistency.bpl LargeLiterals0.bpl) do (
+ echo --------------------- File %%f ----------------------------
+ %BGEXE% %* /typeEncoding:%%m /logPrefix:0%%m /bv:n %%f
+)
+
+echo --------------------- File NameClash.bpl ----------------------------
+%BGEXE% %* /typeEncoding:%%m /logPrefix:0%%m /logPrefix:S NameClash.bpl
+echo --------------------- File LetSorting.bpl ----------------------------
+%BGEXE% %* /typeEncoding:%%m /logPrefix:0%%m /logPrefix:S /vc:n LetSorting.bpl
+echo --------------------- File Keywords.bpl ----------------------------
+%BGEXE% %* /typeEncoding:%%m /logPrefix:0%%m /logPrefix:S Keywords.bpl
+echo --------------------- File LargeLiterals0.bpl ----------------------------
+%BGEXE% %* /typeEncoding:%%m /logPrefix:0%%m /logPrefix:S LargeLiterals0.bpl
+)
+
+for %%m in (
+ n p a
+ ) do (
+echo --------------------- TypeEncoding %%m z3types ----------------------------
+for %%f in (DisjointDomains.bpl DisjointDomains2.bpl FunAxioms.bpl
+ FunAxioms2.bpl PolyList.bpl Maps0.bpl Maps1.bpl
+ InterestingExamples0.bpl InterestingExamples1.bpl InterestingExamples2.bpl
+ InterestingExamples3.bpl InterestingExamples4.bpl InterestingExamples5.bpl
+ Colors.bpl HeapAbstraction.bpl HeapAxiom.bpl Triggers0.bpl Triggers1.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 (
+ echo --------------------- File %%f ----------------------------
+ %BGEXE% %* /typeEncoding:%%m /logPrefix:1%%m %%f
+)
+
+echo --------------------- File LetSorting.bpl ----------------------------
+%BGEXE% %* /typeEncoding:%%m /logPrefix:1%%m /logPrefix:z3t /z3types /vc:n LetSorting.bpl
+)
diff --git a/Test/test21/test3_AddMethod_conv.bpl b/Test/test21/test3_AddMethod_conv.bpl
new file mode 100644
index 00000000..1382fdeb
--- /dev/null
+++ b/Test/test21/test3_AddMethod_conv.bpl
@@ -0,0 +1,1820 @@
+// Spec# program verifier version 0.90, Copyright (c) 2003-2008, Microsoft.
+// Command Line Options: /print:debug.txt AddMethod.dll
+
+type real;
+
+type elements;
+
+type struct;
+
+type name;
+type any;
+
+type exposeVersionType;
+
+type Field a;
+type Heap = <x>[ref,Field x]x;
+
+var $Heap: Heap where IsHeap($Heap);
+
+type ActivityType;
+
+var $ActivityIndicator: ActivityType;
+
+function IsHeap(h: Heap) returns (bool);
+
+const unique $allocated: Field bool;
+
+const unique $elements: Field elements;
+
+function DeclType222<a>(Field a) returns (name);
+
+axiom DeclType222($elements) == System.Object;
+
+const unique $inv: Field name;
+
+const unique $localinv: Field name;
+
+const unique $exposeVersion: Field exposeVersionType;
+
+axiom DeclType222($exposeVersion) == System.Object;
+
+const unique $sharingMode: Field any;
+
+const unique $SharingMode_Unshared: any;
+
+const unique $SharingMode_LockProtected: any;
+
+const unique $ownerRef: Field ref;
+
+const unique $ownerFrame: Field name;
+
+const unique $PeerGroupPlaceholder: name;
+
+function ClassRepr(class: name) returns (ref);
+
+function ClassReprInv(ref) returns (name);
+
+axiom (forall c: name :: { ClassRepr(c) } ClassReprInv(ClassRepr(c)) == c);
+
+axiom (forall T: name :: !($typeof(ClassRepr(T)) <: System.Object));
+
+axiom (forall T: name :: ClassRepr(T) != null);
+
+axiom (forall T: name, h: Heap :: { h[ClassRepr(T), $ownerFrame] } IsHeap(h) ==> h[ClassRepr(T), $ownerFrame] == $PeerGroupPlaceholder);
+
+function IncludeInMainFrameCondition<a>(f: Field a) returns (bool);
+
+axiom IncludeInMainFrameCondition($allocated);
+
+axiom IncludeInMainFrameCondition($elements);
+
+axiom !IncludeInMainFrameCondition($inv);
+
+axiom !IncludeInMainFrameCondition($localinv);
+
+axiom IncludeInMainFrameCondition($ownerRef);
+
+axiom IncludeInMainFrameCondition($ownerFrame);
+
+axiom IncludeInMainFrameCondition($exposeVersion);
+
+axiom !IncludeInMainFrameCondition($FirstConsistentOwner);
+
+function IsStaticField<a>(f: Field a) returns (bool);
+
+axiom !IsStaticField($allocated);
+
+axiom !IsStaticField($elements);
+
+axiom !IsStaticField($inv);
+
+axiom !IsStaticField($localinv);
+
+axiom !IsStaticField($exposeVersion);
+
+function $IncludedInModifiesStar<a>(f: Field a) returns (bool);
+
+axiom !$IncludedInModifiesStar($ownerRef);
+
+axiom !$IncludedInModifiesStar($ownerFrame);
+
+axiom $IncludedInModifiesStar($exposeVersion);
+
+axiom $IncludedInModifiesStar($elements);
+
+function ValueArrayGet(elements, int) returns (any);
+
+function ValueArraySet(elements, int, any) returns (elements);
+
+function IntArrayGet(elements, int) returns (int);
+
+function IntArraySet(elements, int, int) returns (elements);
+
+function RefArrayGet(elements, int) returns (ref);
+
+function RefArraySet(elements, int, ref) returns (elements);
+
+axiom (forall A: elements, i: int, x: any :: ValueArrayGet(ValueArraySet(A, i, x), i) == x);
+
+axiom (forall A: elements, i: int, j: int, x: any :: i != j ==> ValueArrayGet(ValueArraySet(A, i, x), j) == ValueArrayGet(A, j));
+
+axiom (forall A: elements, i: int, x: int :: IntArrayGet(IntArraySet(A, i, x), i) == x);
+
+axiom (forall A: elements, i: int, j: int, x: int :: i != j ==> IntArrayGet(IntArraySet(A, i, x), j) == IntArrayGet(A, j));
+
+axiom (forall A: elements, i: int, x: ref :: RefArrayGet(RefArraySet(A, i, x), i) == x);
+
+axiom (forall A: elements, i: int, j: int, x: ref :: i != j ==> RefArrayGet(RefArraySet(A, i, x), j) == RefArrayGet(A, j));
+
+function ArrayIndex(arr: ref, dim: int, indexAtDim: int, remainingIndexContribution: int) returns (int);
+
+function ArrayIndexInvX(arrayIndex: int) returns (indexAtDim: int);
+
+function ArrayIndexInvY(arrayIndex: int) returns (remainingIndexContribution: int);
+
+axiom (forall a: ref, d: int, x: int, y: int :: { ArrayIndex(a, d, x, y) } ArrayIndexInvX(ArrayIndex(a, d, x, y)) == x);
+
+axiom (forall a: ref, d: int, x: int, y: int :: { ArrayIndex(a, d, x, y) } ArrayIndexInvY(ArrayIndex(a, d, x, y)) == y);
+
+axiom (forall a: ref, i: int, heap: Heap :: { IntArrayGet(heap[a, $elements], i) } IsHeap(heap) ==> InRange(IntArrayGet(heap[a, $elements], i), $ElementType($typeof(a))));
+
+axiom (forall a: ref, i: int, heap: Heap :: { $typeof(RefArrayGet(heap[a, $elements], i)) } IsHeap(heap) && RefArrayGet(heap[a, $elements], i) != null ==> $typeof(RefArrayGet(heap[a, $elements], i)) <: $ElementType($typeof(a)));
+
+axiom (forall a: ref, T: name, i: int, r: int, heap: Heap :: { $typeof(a) <: NonNullRefArray(T, r), RefArrayGet(heap[a, $elements], i) } IsHeap(heap) && $typeof(a) <: NonNullRefArray(T, r) ==> RefArrayGet(heap[a, $elements], i) != null);
+
+function $Rank(ref) returns (int);
+
+axiom (forall a: ref :: 1 <= $Rank(a));
+
+axiom (forall a: ref, T: name, r: int :: { $typeof(a) <: RefArray(T, r) } a != null && $typeof(a) <: RefArray(T, r) ==> $Rank(a) == r);
+
+axiom (forall a: ref, T: name, r: int :: { $typeof(a) <: NonNullRefArray(T, r) } a != null && $typeof(a) <: NonNullRefArray(T, r) ==> $Rank(a) == r);
+
+axiom (forall a: ref, T: name, r: int :: { $typeof(a) <: ValueArray(T, r) } a != null && $typeof(a) <: ValueArray(T, r) ==> $Rank(a) == r);
+
+axiom (forall a: ref, T: name, r: int :: { $typeof(a) <: IntArray(T, r) } a != null && $typeof(a) <: IntArray(T, r) ==> $Rank(a) == r);
+
+function $Length(ref) returns (int);
+
+axiom (forall a: ref :: { $Length(a) } 0 <= $Length(a) && $Length(a) <= int#2147483647);
+
+function $DimLength(ref, int) returns (int);
+
+axiom (forall a: ref, i: int :: 0 <= $DimLength(a, i));
+
+axiom (forall a: ref :: { $DimLength(a, 0) } $Rank(a) == 1 ==> $DimLength(a, 0) == $Length(a));
+
+function $LBound(ref, int) returns (int);
+
+function $UBound(ref, int) returns (int);
+
+axiom (forall a: ref, i: int :: { $LBound(a, i) } $LBound(a, i) == 0);
+
+axiom (forall a: ref, i: int :: { $UBound(a, i) } $UBound(a, i) == $DimLength(a, i) - 1);
+
+const unique $ArrayCategoryValue: name;
+
+const unique $ArrayCategoryInt: name;
+
+const unique $ArrayCategoryRef: name;
+
+const unique $ArrayCategoryNonNullRef: name;
+
+function $ArrayCategory(arrayType: name) returns (arrayCategory: name);
+
+axiom (forall T: name, ET: name, r: int :: { T <: ValueArray(ET, r) } T <: ValueArray(ET, r) ==> $ArrayCategory(T) == $ArrayCategoryValue);
+
+axiom (forall T: name, ET: name, r: int :: { T <: IntArray(ET, r) } T <: IntArray(ET, r) ==> $ArrayCategory(T) == $ArrayCategoryInt);
+
+axiom (forall T: name, ET: name, r: int :: { T <: RefArray(ET, r) } T <: RefArray(ET, r) ==> $ArrayCategory(T) == $ArrayCategoryRef);
+
+axiom (forall T: name, ET: name, r: int :: { T <: NonNullRefArray(ET, r) } T <: NonNullRefArray(ET, r) ==> $ArrayCategory(T) == $ArrayCategoryNonNullRef);
+
+const unique System.Array: name;
+
+axiom System.Array <: System.Object;
+
+function $ElementType(name) returns (name);
+
+function ValueArray(elementType: name, rank: int) returns (name);
+
+axiom (forall T: name, r: int :: { ValueArray(T, r) } ValueArray(T, r) <: ValueArray(T, r) && ValueArray(T, r) <: System.Array);
+
+function IntArray(elementType: name, rank: int) returns (name);
+
+axiom (forall T: name, r: int :: { IntArray(T, r) } IntArray(T, r) <: IntArray(T, r) && IntArray(T, r) <: System.Array);
+
+function RefArray(elementType: name, rank: int) returns (name);
+
+axiom (forall T: name, r: int :: { RefArray(T, r) } RefArray(T, r) <: RefArray(T, r) && RefArray(T, r) <: System.Array);
+
+function NonNullRefArray(elementType: name, rank: int) returns (name);
+
+axiom (forall T: name, r: int :: { NonNullRefArray(T, r) } NonNullRefArray(T, r) <: NonNullRefArray(T, r) && NonNullRefArray(T, r) <: System.Array);
+
+function NonNullRefArrayRaw(array: ref, elementType: name, rank: int) returns (bool);
+
+axiom (forall array: ref, elementType: name, rank: int :: { NonNullRefArrayRaw(array, elementType, rank) } NonNullRefArrayRaw(array, elementType, rank) ==> $typeof(array) <: System.Array && $Rank(array) == rank && elementType <: $ElementType($typeof(array)));
+
+axiom (forall T: name, U: name, r: int :: U <: T ==> RefArray(U, r) <: RefArray(T, r));
+
+axiom (forall T: name, U: name, r: int :: U <: T ==> NonNullRefArray(U, r) <: NonNullRefArray(T, r));
+
+axiom (forall A: name, r: int :: $ElementType(ValueArray(A, r)) == A);
+
+axiom (forall A: name, r: int :: $ElementType(IntArray(A, r)) == A);
+
+axiom (forall A: name, r: int :: $ElementType(RefArray(A, r)) == A);
+
+axiom (forall A: name, r: int :: $ElementType(NonNullRefArray(A, r)) == A);
+
+axiom (forall A: name, r: int, T: name :: { T <: RefArray(A, r) } T <: RefArray(A, r) ==> T != A && T == RefArray($ElementType(T), r) && $ElementType(T) <: A);
+
+axiom (forall A: name, r: int, T: name :: { T <: NonNullRefArray(A, r) } T <: NonNullRefArray(A, r) ==> T != A && T == NonNullRefArray($ElementType(T), r) && $ElementType(T) <: A);
+
+axiom (forall A: name, r: int, T: name :: { T <: ValueArray(A, r) } T <: ValueArray(A, r) ==> T == ValueArray(A, r));
+
+axiom (forall A: name, r: int, T: name :: { T <: IntArray(A, r) } T <: IntArray(A, r) ==> T == IntArray(A, r));
+
+axiom (forall A: name, r: int, T: name :: { RefArray(A, r) <: T } RefArray(A, r) <: T ==> System.Array <: T || (T == RefArray($ElementType(T), r) && A <: $ElementType(T)));
+
+axiom (forall A: name, r: int, T: name :: { NonNullRefArray(A, r) <: T } NonNullRefArray(A, r) <: T ==> System.Array <: T || (T == NonNullRefArray($ElementType(T), r) && A <: $ElementType(T)));
+
+axiom (forall A: name, r: int, T: name :: { ValueArray(A, r) <: T } ValueArray(A, r) <: T ==> System.Array <: T || T == ValueArray(A, r));
+
+axiom (forall A: name, r: int, T: name :: { IntArray(A, r) <: T } IntArray(A, r) <: T ==> System.Array <: T || T == IntArray(A, r));
+
+function $ArrayPtr(elementType: name) returns (name);
+
+function $ElementProxy(ref, int) returns (ref);
+
+function $ElementProxyStruct(struct, int) returns (ref);
+
+axiom (forall a: ref, i: int, heap: Heap :: { heap[RefArrayGet(heap[a, $elements], i), $ownerRef] } { heap[RefArrayGet(heap[a, $elements], i), $ownerFrame] } IsHeap(heap) && $typeof(a) <: System.Array ==> RefArrayGet(heap[a, $elements], i) == null || $IsImmutable($typeof(RefArrayGet(heap[a, $elements], i))) || (heap[RefArrayGet(heap[a, $elements], i), $ownerRef] == heap[$ElementProxy(a, 0 - 1), $ownerRef] && heap[RefArrayGet(heap[a, $elements], i), $ownerFrame] == heap[$ElementProxy(a, 0 - 1), $ownerFrame]));
+
+axiom (forall a: ref, heap: Heap :: { IsAllocated(heap, a) } IsHeap(heap) && IsAllocated(heap, a) && $typeof(a) <: System.Array ==> IsAllocated(heap, $ElementProxy(a, 0 - 1)));
+
+axiom (forall o: ref, pos: int :: { $typeof($ElementProxy(o, pos)) } $typeof($ElementProxy(o, pos)) == System.Object);
+
+axiom (forall o: struct, pos: int :: { $typeof($ElementProxyStruct(o, pos)) } $typeof($ElementProxyStruct(o, pos)) == System.Object);
+
+function $StructGet(struct, name) returns (any);
+
+function $StructSet(struct, name, any) returns (struct);
+
+axiom (forall s: struct, f: name, x: any :: $StructGet($StructSet(s, f, x), f) == x);
+
+axiom (forall s: struct, f: name, f': name, x: any :: f != f' ==> $StructGet($StructSet(s, f, x), f') == $StructGet(s, f'));
+
+function ZeroInit(s: struct, typ: name) returns (bool);
+
+function $typeof(ref) returns (name);
+
+function $BaseClass(sub: name) returns (base: name);
+
+axiom (forall T: name :: { $BaseClass(T) } T <: $BaseClass(T) && (T != System.Object ==> T != $BaseClass(T)));
+
+function AsDirectSubClass(sub: name, base: name) returns (sub': name);
+
+function OneClassDown(sub: name, base: name) returns (directSub: name);
+
+axiom (forall A: name, B: name, C: name :: { C <: AsDirectSubClass(B, A) } C <: AsDirectSubClass(B, A) ==> OneClassDown(C, A) == B);
+
+function $IsValueType(name) returns (bool);
+
+axiom (forall T: name :: $IsValueType(T) ==> (forall U: name :: T <: U ==> T == U) && (forall U: name :: U <: T ==> T == U));
+
+const unique System.Boolean: name;
+
+axiom $IsValueType(System.Boolean);
+
+const unique System.Object: name;
+
+function $IsTokenForType(struct, name) returns (bool);
+
+function TypeObject(name) returns (ref);
+
+const unique System.Type: name;
+
+axiom System.Type <: System.Object;
+
+axiom (forall T: name :: { TypeObject(T) } $IsNotNull(TypeObject(T), System.Type));
+
+function TypeName(ref) returns (name);
+
+axiom (forall T: name :: { TypeObject(T) } TypeName(TypeObject(T)) == T);
+
+function $Is(ref, name) returns (bool);
+
+axiom (forall o: ref, T: name :: { $Is(o, T) } $Is(o, T) <==> o == null || $typeof(o) <: T);
+
+function $IsNotNull(ref, name) returns (bool);
+
+axiom (forall o: ref, T: name :: { $IsNotNull(o, T) } $IsNotNull(o, T) <==> o != null && $Is(o, T));
+
+function $As(ref, name) returns (ref);
+
+axiom (forall o: ref, T: name :: $Is(o, T) ==> $As(o, T) == o);
+
+axiom (forall o: ref, T: name :: !$Is(o, T) ==> $As(o, T) == null);
+
+axiom (forall h: Heap, o: ref :: { $typeof(o) <: System.Array, h[o, $inv] } IsHeap(h) && o != null && $typeof(o) <: System.Array ==> h[o, $inv] == $typeof(o) && h[o, $localinv] == $typeof(o));
+
+function IsAllocated<a>(h: Heap, o: a) returns (bool);
+
+axiom (forall<a> h: Heap, o: ref, f: Field a :: { IsAllocated(h, h[o, f]) } IsHeap(h) && h[o, $allocated] ==> IsAllocated(h, h[o, f]));
+
+axiom (forall h: Heap, o: ref, f: Field ref :: { h[h[o, f], $allocated] } IsHeap(h) && h[o, $allocated] ==> h[h[o, f], $allocated]);
+
+axiom (forall h: Heap, s: struct, f: name :: { IsAllocated(h, $StructGet(s, f)) } IsAllocated(h, s) ==> IsAllocated(h, $StructGet(s, f)));
+
+axiom (forall h: Heap, e: elements, i: int :: { IsAllocated(h, RefArrayGet(e, i)) } IsAllocated(h, e) ==> IsAllocated(h, RefArrayGet(e, i)));
+
+axiom (forall h: Heap, e: elements, i: int :: { IsAllocated(h, ValueArrayGet(e, i)) } IsAllocated(h, e) ==> IsAllocated(h, ValueArrayGet(e, i)));
+
+axiom (forall h: Heap, o: ref :: { h[o, $allocated] } IsAllocated(h, o) ==> h[o, $allocated]);
+
+axiom (forall h: Heap, c: name :: { h[ClassRepr(c), $allocated] } IsHeap(h) ==> h[ClassRepr(c), $allocated]);
+
+const $BeingConstructed: ref;
+
+const unique $NonNullFieldsAreInitialized: Field bool;
+
+const $PurityAxiomsCanBeAssumed: bool;
+
+axiom DeclType222($NonNullFieldsAreInitialized) == System.Object;
+
+
+
+function AsNonNullRefField(field: Field ref, T: name) returns (f: Field ref);
+
+function AsRefField(field: Field ref, T: name) returns (f: Field ref);
+
+function AsRangeField(field: Field int, T: name) returns (f: Field int);
+
+axiom (forall f: Field ref, T: name :: { AsNonNullRefField(f, T) } AsNonNullRefField(f, T) == f ==> AsRefField(f, T) == f);
+
+axiom (forall h: Heap, o: ref, f: Field ref, T: name :: { h[o, AsRefField(f, T)] } IsHeap(h) ==> $Is(h[o, AsRefField(f, T)], T));
+
+axiom (forall h: Heap, o: ref, f: Field ref, T: name :: { h[o, AsNonNullRefField(f, T)] } IsHeap(h) && o != null && (o != $BeingConstructed || h[$BeingConstructed, $NonNullFieldsAreInitialized] == true) ==> h[o, AsNonNullRefField(f, T)] != null);
+
+axiom (forall h: Heap, o: ref, f: Field int, T: name :: { h[o, AsRangeField(f, T)] } IsHeap(h) ==> InRange(h[o, AsRangeField(f, T)], T));
+
+function $IsMemberlessType(name) returns (bool);
+
+axiom (forall o: ref :: { $IsMemberlessType($typeof(o)) } !$IsMemberlessType($typeof(o)));
+
+function $AsInterface(name) returns (name);
+
+axiom (forall $J: name, s: any, b: ref :: { UnboxedType(Box(s, b)) <: $AsInterface($J) } $AsInterface($J) == $J && Box(s, b) == b && UnboxedType(Box(s, b)) <: $AsInterface($J) ==> $typeof(b) <: $J);
+
+function $HeapSucc(oldHeap: Heap, newHeap: Heap) returns (bool);
+
+function $IsImmutable(T: name) returns (bool);
+
+axiom !$IsImmutable(System.Object);
+
+function $AsImmutable(T: name) returns (theType: name);
+
+function $AsMutable(T: name) returns (theType: name);
+
+axiom (forall T: name, U: name :: { U <: $AsImmutable(T) } U <: $AsImmutable(T) ==> $IsImmutable(U) && $AsImmutable(U) == U);
+
+axiom (forall T: name, U: name :: { U <: $AsMutable(T) } U <: $AsMutable(T) ==> !$IsImmutable(U) && $AsMutable(U) == U);
+
+function AsOwner(string: ref, owner: ref) returns (theString: ref);
+
+axiom (forall o: ref, T: name :: { $typeof(o) <: $AsImmutable(T) } o != null && o != $BeingConstructed && $typeof(o) <: $AsImmutable(T) ==> (forall h: Heap :: { IsHeap(h) } IsHeap(h) ==> h[o, $inv] == $typeof(o) && h[o, $localinv] == $typeof(o) && h[o, $ownerFrame] == $PeerGroupPlaceholder && AsOwner(o, h[o, $ownerRef]) == o && (forall t: ref :: { AsOwner(o, h[t, $ownerRef]) } AsOwner(o, h[t, $ownerRef]) == o ==> t == o || h[t, $ownerFrame] != $PeerGroupPlaceholder)));
+
+const unique System.String: name;
+
+function $StringLength(ref) returns (int);
+
+axiom (forall s: ref :: { $StringLength(s) } 0 <= $StringLength(s));
+
+function AsRepField(f: Field ref, declaringType: name) returns (theField: Field ref);
+
+axiom (forall h: Heap, o: ref, f: Field ref, T: name :: { h[o, AsRepField(f, T)] } IsHeap(h) && h[o, AsRepField(f, T)] != null ==> h[h[o, AsRepField(f, T)], $ownerRef] == o && h[h[o, AsRepField(f, T)], $ownerFrame] == T);
+
+function AsPeerField(f: Field ref) returns (theField: Field ref);
+
+axiom (forall h: Heap, o: ref, f: Field ref :: { h[o, AsPeerField(f)] } IsHeap(h) && h[o, AsPeerField(f)] != null ==> h[h[o, AsPeerField(f)], $ownerRef] == h[o, $ownerRef] && h[h[o, AsPeerField(f)], $ownerFrame] == h[o, $ownerFrame]);
+
+function AsElementsRepField(f: Field ref, declaringType: name, position: int) returns (theField: Field ref);
+
+axiom (forall h: Heap, o: ref, f: Field ref, T: name, i: int :: { h[o, AsElementsRepField(f, T, i)] } IsHeap(h) && h[o, AsElementsRepField(f, T, i)] != null ==> h[$ElementProxy(h[o, AsElementsRepField(f, T, i)], i), $ownerRef] == o && h[$ElementProxy(h[o, AsElementsRepField(f, T, i)], i), $ownerFrame] == T);
+
+function AsElementsPeerField(f: Field ref, position: int) returns (theField: Field ref);
+
+axiom (forall h: Heap, o: ref, f: Field ref, i: int :: { h[o, AsElementsPeerField(f, i)] } IsHeap(h) && h[o, AsElementsPeerField(f, i)] != null ==> h[$ElementProxy(h[o, AsElementsPeerField(f, i)], i), $ownerRef] == h[o, $ownerRef] && h[$ElementProxy(h[o, AsElementsPeerField(f, i)], i), $ownerFrame] == h[o, $ownerFrame]);
+
+axiom (forall h: Heap, o: ref :: { h[h[o, $ownerRef], $inv] <: h[o, $ownerFrame] } IsHeap(h) && h[o, $ownerFrame] != $PeerGroupPlaceholder && h[h[o, $ownerRef], $inv] <: h[o, $ownerFrame] && h[h[o, $ownerRef], $localinv] != $BaseClass(h[o, $ownerFrame]) ==> h[o, $inv] == $typeof(o) && h[o, $localinv] == $typeof(o));
+
+procedure $SetOwner(o: ref, ow: ref, fr: name);
+ modifies $Heap;
+ ensures (forall<a> p: ref, F: Field a :: { $Heap[p, F] } (F != $ownerRef && F != $ownerFrame) || old($Heap[p, $ownerRef] != $Heap[o, $ownerRef]) || old($Heap[p, $ownerFrame] != $Heap[o, $ownerFrame]) ==> old($Heap[p, F]) == $Heap[p, F]);
+ ensures (forall p: ref :: { $Heap[p, $ownerRef] } { $Heap[p, $ownerFrame] } old($Heap[p, $ownerRef] == $Heap[o, $ownerRef]) && old($Heap[p, $ownerFrame] == $Heap[o, $ownerFrame]) ==> $Heap[p, $ownerRef] == ow && $Heap[p, $ownerFrame] == fr);
+ free ensures $HeapSucc(old($Heap), $Heap);
+
+
+
+procedure $UpdateOwnersForRep(o: ref, T: name, e: ref);
+ modifies $Heap;
+ ensures (forall<a> p: ref, F: Field a :: { $Heap[p, F] } (F != $ownerRef && F != $ownerFrame) || old($Heap[p, $ownerRef] != $Heap[e, $ownerRef]) || old($Heap[p, $ownerFrame] != $Heap[e, $ownerFrame]) ==> old($Heap[p, F]) == $Heap[p, F]);
+ ensures e == null ==> $Heap == old($Heap);
+ ensures e != null ==> (forall p: ref :: { $Heap[p, $ownerRef] } { $Heap[p, $ownerFrame] } old($Heap[p, $ownerRef] == $Heap[e, $ownerRef]) && old($Heap[p, $ownerFrame] == $Heap[e, $ownerFrame]) ==> $Heap[p, $ownerRef] == o && $Heap[p, $ownerFrame] == T);
+ free ensures $HeapSucc(old($Heap), $Heap);
+
+
+
+procedure $UpdateOwnersForPeer(c: ref, d: ref);
+ modifies $Heap;
+ ensures (forall<a> p: ref, F: Field a :: { $Heap[p, F] } (F != $ownerRef && F != $ownerFrame) || old($Heap[p, $ownerRef] != $Heap[d, $ownerRef] || $Heap[p, $ownerFrame] != $Heap[d, $ownerFrame]) ==> old($Heap[p, F]) == $Heap[p, F]);
+ ensures d == null ==> $Heap == old($Heap);
+ ensures d != null ==> (forall p: ref :: { $Heap[p, $ownerRef] } { $Heap[p, $ownerFrame] } old($Heap[p, $ownerRef] == $Heap[d, $ownerRef] && $Heap[p, $ownerFrame] == $Heap[d, $ownerFrame]) ==> $Heap[p, $ownerRef] == old($Heap)[c, $ownerRef] && $Heap[p, $ownerFrame] == old($Heap)[c, $ownerFrame]);
+ free ensures $HeapSucc(old($Heap), $Heap);
+
+
+
+const unique $FirstConsistentOwner: Field ref;
+
+function $AsPureObject(ref) returns (ref);
+
+function ##FieldDependsOnFCO<a>(o: ref, f: Field a, ev: exposeVersionType) returns (value: any);
+
+axiom (forall<a> o: ref, f: Field a, h: Heap :: { h[$AsPureObject(o), f] } IsHeap(h) && o != null && h[o, $allocated] == true && $AsPureObject(o) == o && h[o, $ownerFrame] != $PeerGroupPlaceholder && h[h[o, $ownerRef], $inv] <: h[o, $ownerFrame] && h[h[o, $ownerRef], $localinv] != $BaseClass(h[o, $ownerFrame]) ==> h[o, f] == ##FieldDependsOnFCO(o, f, h[h[o, $FirstConsistentOwner], $exposeVersion]));
+
+axiom (forall o: ref, h: Heap :: { h[o, $FirstConsistentOwner] } IsHeap(h) && o != null && h[o, $allocated] == true && h[o, $ownerFrame] != $PeerGroupPlaceholder && h[h[o, $ownerRef], $inv] <: h[o, $ownerFrame] && h[h[o, $ownerRef], $localinv] != $BaseClass(h[o, $ownerFrame]) ==> h[o, $FirstConsistentOwner] != null && h[h[o, $FirstConsistentOwner], $allocated] == true && (h[h[o, $FirstConsistentOwner], $ownerFrame] == $PeerGroupPlaceholder || !(h[h[h[o, $FirstConsistentOwner], $ownerRef], $inv] <: h[h[o, $FirstConsistentOwner], $ownerFrame]) || h[h[h[o, $FirstConsistentOwner], $ownerRef], $localinv] == $BaseClass(h[h[o, $FirstConsistentOwner], $ownerFrame])));
+
+function Box<a>(a, ref) returns (ref);
+
+function Unbox(ref) returns (any);
+
+type NondetType;
+
+function MeldNondets(NondetType, any) returns (NondetType);
+
+function BoxFunc<a>(value: a, typ: name) returns (boxedValue: ref);
+
+function AllocFunc(typ: name) returns (newValue: ref);
+
+function NewInstance(object: ref, occurrence: NondetType, activity: ActivityType) returns (newInstance: ref);
+
+axiom (forall value: any, typ: name, occurrence: NondetType, activity: ActivityType :: { NewInstance(BoxFunc(value, typ), occurrence, activity) } Box(value, NewInstance(BoxFunc(value, typ), occurrence, activity)) == NewInstance(BoxFunc(value, typ), occurrence, activity) && UnboxedType(NewInstance(BoxFunc(value, typ), occurrence, activity)) == typ);
+
+axiom (forall x: ref, typ: name, occurrence: NondetType, activity: ActivityType :: !$IsValueType(UnboxedType(x)) ==> NewInstance(BoxFunc(x, typ), occurrence, activity) == x);
+
+axiom (forall x: any, p: ref :: { Unbox(Box(x, p)) } Unbox(Box(x, p)) == x);
+
+function UnboxedType(ref) returns (name);
+
+axiom (forall p: ref :: { $IsValueType(UnboxedType(p)) } $IsValueType(UnboxedType(p)) ==> (forall heap: Heap, x: any :: { heap[Box(x, p), $inv] } IsHeap(heap) ==> heap[Box(x, p), $inv] == $typeof(Box(x, p)) && heap[Box(x, p), $localinv] == $typeof(Box(x, p))));
+
+axiom (forall<a> x: a, p: ref :: { UnboxedType(Box(x, p)) <: System.Object } UnboxedType(Box(x, p)) <: System.Object && Box(x, p) == p ==> x == p);
+
+function BoxTester(p: ref, typ: name) returns (ref);
+
+axiom (forall p: ref, typ: name :: { BoxTester(p, typ) } UnboxedType(p) == typ <==> BoxTester(p, typ) != null);
+
+axiom (forall p: ref, typ: name :: { BoxTester(p, typ) } BoxTester(p, typ) != null ==> Box(Unbox(p), p) == p);
+
+axiom (forall typ: name, occurrence: NondetType, activity: ActivityType :: { NewInstance(AllocFunc(typ), occurrence, activity) } $typeof(NewInstance(AllocFunc(typ), occurrence, activity)) == typ && NewInstance(AllocFunc(typ), occurrence, activity) != null);
+
+axiom (forall typ: name, occurrence: NondetType, activity: ActivityType, heap: Heap :: { heap[NewInstance(AllocFunc(typ), occurrence, activity), $allocated] } IsHeap(heap) ==> heap[NewInstance(AllocFunc(typ), occurrence, activity), $allocated]);
+
+const unique System.SByte: name;
+
+axiom $IsValueType(System.SByte);
+
+const unique System.Byte: name;
+
+axiom $IsValueType(System.Byte);
+
+const unique System.Int16: name;
+
+axiom $IsValueType(System.Int16);
+
+const unique System.UInt16: name;
+
+axiom $IsValueType(System.UInt16);
+
+const unique System.Int32: name;
+
+axiom $IsValueType(System.Int32);
+
+const unique System.UInt32: name;
+
+axiom $IsValueType(System.UInt32);
+
+const unique System.Int64: name;
+
+axiom $IsValueType(System.Int64);
+
+const unique System.UInt64: name;
+
+axiom $IsValueType(System.UInt64);
+
+const unique System.Char: name;
+
+axiom $IsValueType(System.Char);
+
+const unique System.UIntPtr: name;
+
+axiom $IsValueType(System.UIntPtr);
+
+const unique System.IntPtr: name;
+
+axiom $IsValueType(System.IntPtr);
+
+const int#m2147483648: int;
+
+const int#2147483647: int;
+
+const int#4294967295: int;
+
+const int#m9223372036854775808: int;
+
+const int#9223372036854775807: int;
+
+const int#18446744073709551615: int;
+
+axiom int#m9223372036854775808 < int#m2147483648;
+
+axiom int#m2147483648 < 0 - 100000;
+
+axiom 100000 < int#2147483647;
+
+axiom int#2147483647 < int#4294967295;
+
+axiom int#4294967295 < int#9223372036854775807;
+
+axiom int#9223372036854775807 < int#18446744073709551615;
+
+axiom int#m9223372036854775808 + 1 == 0 - int#9223372036854775807;
+
+axiom int#m2147483648 + 1 == 0 - int#2147483647;
+
+function InRange(i: int, T: name) returns (bool);
+
+axiom (forall i: int :: InRange(i, System.SByte) <==> 0 - 128 <= i && i < 128);
+
+axiom (forall i: int :: InRange(i, System.Byte) <==> 0 <= i && i < 256);
+
+axiom (forall i: int :: InRange(i, System.Int16) <==> 0 - 32768 <= i && i < 32768);
+
+axiom (forall i: int :: InRange(i, System.UInt16) <==> 0 <= i && i < 65536);
+
+axiom (forall i: int :: InRange(i, System.Int32) <==> int#m2147483648 <= i && i <= int#2147483647);
+
+axiom (forall i: int :: InRange(i, System.UInt32) <==> 0 <= i && i <= int#4294967295);
+
+axiom (forall i: int :: InRange(i, System.Int64) <==> int#m9223372036854775808 <= i && i <= int#9223372036854775807);
+
+axiom (forall i: int :: InRange(i, System.UInt64) <==> 0 <= i && i <= int#18446744073709551615);
+
+axiom (forall i: int :: InRange(i, System.Char) <==> 0 <= i && i < 65536);
+
+function $IntToInt(val: int, fromType: name, toType: name) returns (int);
+
+function $IntToReal(int, fromType: name, toType: name) returns (real);
+
+function $RealToInt(real, fromType: name, toType: name) returns (int);
+
+function $RealToReal(val: real, fromType: name, toType: name) returns (real);
+
+axiom (forall z: int, B: name, C: name :: InRange(z, C) ==> $IntToInt(z, B, C) == z);
+
+function $SizeIs(name, int) returns (bool);
+
+function $IfThenElse(bool, any, any) returns (any);
+
+axiom (forall b: bool, x: any, y: any :: { $IfThenElse(b, x, y) } b ==> $IfThenElse(b, x, y) == x);
+
+axiom (forall b: bool, x: any, y: any :: { $IfThenElse(b, x, y) } !b ==> $IfThenElse(b, x, y) == y);
+
+function #neg(int) returns (int);
+
+function #and(int, int) returns (int);
+
+function #or(int, int) returns (int);
+
+function #xor(int, int) returns (int);
+
+function #shl(int, int) returns (int);
+
+function #shr(int, int) returns (int);
+
+function #rneg(real) returns (real);
+
+function #radd(real, real) returns (real);
+
+function #rsub(real, real) returns (real);
+
+function #rmul(real, real) returns (real);
+
+function #rdiv(real, real) returns (real);
+
+function #rmod(real, real) returns (real);
+
+function #rLess(real, real) returns (bool);
+
+function #rAtmost(real, real) returns (bool);
+
+function #rEq(real, real) returns (bool);
+
+function #rNeq(real, real) returns (bool);
+
+function #rAtleast(real, real) returns (bool);
+
+function #rGreater(real, real) returns (bool);
+
+axiom (forall x: int, y: int :: { x % y } { x / y } x % y == x - x / 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 % y } 0 <= x && y < 0 ==> 0 <= x % y && x % 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 % y } x <= 0 && y < 0 ==> y < x % y && x % 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 :: { (y + x) % y } 0 <= x && 0 <= y ==> (y + x) % y == x % y);
+
+axiom (forall x: int, y: int :: { (x - y) % y } 0 <= x - y && 0 <= y ==> (x - y) % y == x % 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 x: int, y: int :: { #and(x, y) } 0 <= x || 0 <= y ==> 0 <= #and(x, y));
+
+axiom (forall x: int, y: int :: { #or(x, y) } 0 <= x && 0 <= y ==> 0 <= #or(x, y) && #or(x, y) <= x + y);
+
+axiom (forall i: int :: { #shl(i, 0) } #shl(i, 0) == i);
+
+axiom (forall i: int, j: int :: { #shl(i, j) } 1 <= j ==> #shl(i, j) == #shl(i, j - 1) * 2);
+
+axiom (forall i: int, j: int :: { #shl(i, j) } 0 <= i && i < 32768 && 0 <= j && j <= 16 ==> 0 <= #shl(i, j) && #shl(i, j) <= int#2147483647);
+
+axiom (forall i: int :: { #shr(i, 0) } #shr(i, 0) == i);
+
+axiom (forall i: int, j: int :: { #shr(i, j) } 1 <= j ==> #shr(i, j) == #shr(i, j - 1) / 2);
+
+function #min(int, int) returns (int);
+
+function #max(int, int) returns (int);
+
+axiom (forall x: int, y: int :: { #min(x, y) } (#min(x, y) == x || #min(x, y) == y) && #min(x, y) <= x && #min(x, y) <= y);
+
+axiom (forall x: int, y: int :: { #max(x, y) } (#max(x, y) == x || #max(x, y) == y) && x <= #max(x, y) && y <= #max(x, y));
+
+function #System.String.IsInterned$System.String$notnull(Heap, ref) returns (ref);
+
+function #System.String.Equals$System.String(Heap, ref, ref) returns (bool);
+
+function #System.String.Equals$System.String$System.String(Heap, ref, ref) returns (bool);
+
+function ##StringEquals(ref, ref) returns (bool);
+
+axiom (forall h: Heap, a: ref, b: ref :: { #System.String.Equals$System.String(h, a, b) } #System.String.Equals$System.String(h, a, b) == #System.String.Equals$System.String$System.String(h, a, b));
+
+axiom (forall h: Heap, a: ref, b: ref :: { #System.String.Equals$System.String$System.String(h, a, b) } #System.String.Equals$System.String$System.String(h, a, b) == ##StringEquals(a, b) && #System.String.Equals$System.String$System.String(h, a, b) == ##StringEquals(b, a) && (a == b ==> ##StringEquals(a, b)));
+
+axiom (forall a: ref, b: ref, c: ref :: ##StringEquals(a, b) && ##StringEquals(b, c) ==> ##StringEquals(a, c));
+
+axiom (forall h: Heap, a: ref, b: ref :: { #System.String.Equals$System.String$System.String(h, a, b) } a != null && b != null && #System.String.Equals$System.String$System.String(h, a, b) ==> #System.String.IsInterned$System.String$notnull(h, a) == #System.String.IsInterned$System.String$notnull(h, b));
+
+const $UnknownRef: ref;
+
+const unique Bag.a: Field ref;
+
+const unique Bag.n: Field int;
+
+const unique Microsoft.Contracts.GuardException: name;
+
+const unique System.ICloneable: name;
+
+const unique Microsoft.Contracts.ObjectInvariantException: name;
+
+const unique System.Exception: name;
+
+const unique System.Collections.IEnumerable: name;
+
+const unique System.Collections.IList: name;
+
+const unique Microsoft.Contracts.ICheckedException: name;
+
+const unique System.Reflection.MemberInfo: name;
+
+const unique Bag: name;
+
+const unique System.Reflection.IReflect: name;
+
+const unique System.Runtime.InteropServices._MemberInfo: name;
+
+const unique System.Runtime.InteropServices._Type: name;
+
+const unique System.Collections.ICollection: name;
+
+const unique System.Runtime.InteropServices._Exception: name;
+
+const unique System.Runtime.Serialization.ISerializable: name;
+
+const unique System.Reflection.ICustomAttributeProvider: name;
+
+axiom !IsStaticField(Bag.n);
+
+axiom IncludeInMainFrameCondition(Bag.n);
+
+axiom $IncludedInModifiesStar(Bag.n);
+
+axiom DeclType222(Bag.n) == Bag;
+
+axiom AsRangeField(Bag.n, System.Int32) == Bag.n;
+
+axiom !IsStaticField(Bag.a);
+
+axiom IncludeInMainFrameCondition(Bag.a);
+
+axiom $IncludedInModifiesStar(Bag.a);
+
+axiom AsRepField(Bag.a, Bag) == Bag.a;
+
+axiom DeclType222(Bag.a) == Bag;
+
+axiom AsNonNullRefField(Bag.a, IntArray(System.Int32, 1)) == Bag.a;
+
+axiom Bag <: Bag;
+
+axiom $BaseClass(Bag) == System.Object && AsDirectSubClass(Bag, $BaseClass(Bag)) == Bag;
+
+axiom !$IsImmutable(Bag) && $AsMutable(Bag) == Bag;
+
+axiom System.Array <: System.Array;
+
+axiom $BaseClass(System.Array) == System.Object && AsDirectSubClass(System.Array, $BaseClass(System.Array)) == System.Array;
+
+axiom !$IsImmutable(System.Array) && $AsMutable(System.Array) == System.Array;
+
+axiom System.ICloneable <: System.ICloneable;
+
+axiom System.ICloneable <: System.Object;
+
+axiom $IsMemberlessType(System.ICloneable);
+
+axiom $AsInterface(System.ICloneable) == System.ICloneable;
+
+axiom System.Array <: System.ICloneable;
+
+axiom System.Collections.IList <: System.Collections.IList;
+
+axiom System.Collections.IList <: System.Object;
+
+axiom System.Collections.ICollection <: System.Collections.ICollection;
+
+axiom System.Collections.ICollection <: System.Object;
+
+axiom System.Collections.IEnumerable <: System.Collections.IEnumerable;
+
+axiom System.Collections.IEnumerable <: System.Object;
+
+axiom $IsMemberlessType(System.Collections.IEnumerable);
+
+axiom $AsInterface(System.Collections.IEnumerable) == System.Collections.IEnumerable;
+
+axiom System.Collections.ICollection <: System.Collections.IEnumerable;
+
+axiom $IsMemberlessType(System.Collections.ICollection);
+
+axiom $AsInterface(System.Collections.ICollection) == System.Collections.ICollection;
+
+axiom System.Collections.IList <: System.Collections.ICollection;
+
+axiom System.Collections.IList <: System.Collections.IEnumerable;
+
+axiom $IsMemberlessType(System.Collections.IList);
+
+axiom $AsInterface(System.Collections.IList) == System.Collections.IList;
+
+axiom System.Array <: System.Collections.IList;
+
+axiom System.Array <: System.Collections.ICollection;
+
+axiom System.Array <: System.Collections.IEnumerable;
+
+axiom $IsMemberlessType(System.Array);
+
+// System.Array object invariant
+axiom (forall $oi: ref, $h: Heap :: { $h[$oi, $inv] <: System.Array } IsHeap($h) && $h[$oi, $inv] <: System.Array && $h[$oi, $localinv] != $BaseClass(System.Array) ==> true);
+
+// Bag object invariant
+axiom (forall $oi: ref, $h: Heap :: { $h[$oi, $inv] <: Bag } IsHeap($h) && $h[$oi, $inv] <: Bag && $h[$oi, $localinv] != $BaseClass(Bag) ==> 0 <= $h[$oi, Bag.n] && $h[$oi, Bag.n] <= $Length($h[$oi, Bag.a]));
+
+procedure Bag.SpecSharp.CheckInvariant$System.Boolean(this: ref where $IsNotNull(this, Bag) && $Heap[this, $allocated], throwException$in: bool where true) returns ($result: bool where true);
+ // user-declared preconditions
+ requires ($Heap[this, $ownerFrame] == $PeerGroupPlaceholder || !($Heap[$Heap[this, $ownerRef], $inv] <: $Heap[this, $ownerFrame]) || $Heap[$Heap[this, $ownerRef], $localinv] == $BaseClass($Heap[this, $ownerFrame])) && $Heap[this, $inv] == System.Object && $Heap[this, $localinv] == $typeof(this) && (forall $p: ref :: $p != null && $Heap[$p, $allocated] && $Heap[$p, $ownerRef] == this && $Heap[$p, $ownerFrame] == Bag ==> $Heap[$p, $inv] == $typeof($p) && $Heap[$p, $localinv] == $typeof($p));
+ free requires $BeingConstructed == null;
+ free requires $PurityAxiomsCanBeAssumed;
+ modifies $Heap, $ActivityIndicator;
+ // newly allocated objects are fully valid
+ free ensures (forall $o: ref :: { $Heap[$o, $localinv] } { $Heap[$o, $inv] } $o != null && !old($Heap)[$o, $allocated] && $Heap[$o, $allocated] ==> $Heap[$o, $inv] == $typeof($o) && $Heap[$o, $localinv] == $typeof($o));
+ // first consistent owner unchanged if its exposeVersion is
+ free ensures (forall $o: ref :: { $Heap[$o, $FirstConsistentOwner] } old($Heap)[old($Heap)[$o, $FirstConsistentOwner], $exposeVersion] == $Heap[old($Heap)[$o, $FirstConsistentOwner], $exposeVersion] ==> old($Heap)[$o, $FirstConsistentOwner] == $Heap[$o, $FirstConsistentOwner]);
+ // frame condition
+ ensures (forall<a> $o: ref, $f: Field a :: { $Heap[$o, $f] } IncludeInMainFrameCondition($f) && $o != null && old($Heap)[$o, $allocated] && (old($Heap)[$o, $ownerFrame] == $PeerGroupPlaceholder || !(old($Heap)[old($Heap)[$o, $ownerRef], $inv] <: old($Heap)[$o, $ownerFrame]) || old($Heap)[old($Heap)[$o, $ownerRef], $localinv] == $BaseClass(old($Heap)[$o, $ownerFrame])) && old($o != this || !($typeof(this) <: DeclType222($f)) || !$IncludedInModifiesStar($f)) && old(true) ==> old($Heap)[$o, $f] == $Heap[$o, $f]);
+ free ensures $HeapSucc(old($Heap), $Heap);
+ // inv/localinv change only in blocks
+ free ensures (forall $o: ref :: { $Heap[$o, $localinv] } { $Heap[$o, $inv] } old($Heap)[$o, $allocated] ==> old($Heap)[$o, $inv] == $Heap[$o, $inv] && old($Heap)[$o, $localinv] == $Heap[$o, $localinv]);
+ free ensures (forall $o: ref :: { $Heap[$o, $allocated] } old($Heap)[$o, $allocated] ==> $Heap[$o, $allocated]) && (forall $ot: ref :: { $Heap[$ot, $ownerFrame] } { $Heap[$ot, $ownerRef] } old($Heap)[$ot, $allocated] && old($Heap)[$ot, $ownerFrame] != $PeerGroupPlaceholder ==> $Heap[$ot, $ownerRef] == old($Heap)[$ot, $ownerRef] && $Heap[$ot, $ownerFrame] == old($Heap)[$ot, $ownerFrame]) && old($Heap)[$BeingConstructed, $NonNullFieldsAreInitialized] == $Heap[$BeingConstructed, $NonNullFieldsAreInitialized];
+ free ensures (forall $o: ref :: { $Heap[$o, $sharingMode] } old($Heap[$o, $sharingMode]) == $Heap[$o, $sharingMode]);
+
+
+
+implementation Bag.SpecSharp.CheckInvariant$System.Boolean(this: ref, throwException$in: bool) returns ($result: bool)
+{
+ var throwException: bool where true, stack0i: int, stack1i: int, stack0b: bool, stack1o: ref, return.value: bool where true, stack50000o: ref, stack0o: ref, SS$Display.Return.Local: bool where true;
+
+ entry:
+ throwException := throwException$in;
+ goto block2380;
+
+ block2380:
+ goto block2482;
+
+ block2482:
+ // ----- nop
+ // ----- load constant 0
+ stack0i := 0;
+ // ----- load field
+ assert this != null;
+ stack1i := $Heap[this, Bag.n];
+ // ----- binary operator
+ // ----- branch
+ goto true2482to2550, false2482to2414;
+
+ true2482to2550:
+ assume stack0i > stack1i;
+ goto block2550;
+
+ false2482to2414:
+ assume stack0i <= stack1i;
+ goto block2414;
+
+ block2550:
+ // ----- copy
+ stack0b := throwException;
+ // ----- unary operator
+ // ----- branch
+ goto true2550to2584, false2550to2601;
+
+ block2414:
+ // ----- load field
+ assert this != null;
+ stack0i := $Heap[this, Bag.n];
+ // ----- load field
+ assert this != null;
+ stack1o := $Heap[this, Bag.a];
+ // ----- unary operator
+ assert stack1o != null;
+ stack1i := $Length(stack1o);
+ // ----- unary operator
+ stack1i := $IntToInt(stack1i, System.UIntPtr, System.Int32);
+ // ----- binary operator
+ // ----- branch
+ goto true2414to2550, false2414to2465;
+
+ true2414to2550:
+ assume stack0i > stack1i;
+ goto block2550;
+
+ false2414to2465:
+ assume stack0i <= stack1i;
+ goto block2465;
+
+ block2465:
+ // ----- branch
+ goto block2448;
+
+ true2550to2584:
+ assume !stack0b;
+ goto block2584;
+
+ false2550to2601:
+ assume stack0b;
+ goto block2601;
+
+ block2584:
+ // ----- load constant 0
+ return.value := false;
+ // ----- branch
+ goto block2567;
+
+ block2601:
+ assume false;
+ // ----- new object
+ havoc stack50000o;
+ assume $Heap[stack50000o, $allocated] == false && stack50000o != null && $typeof(stack50000o) == Microsoft.Contracts.ObjectInvariantException;
+ assume $Heap[stack50000o, $ownerRef] == stack50000o && $Heap[stack50000o, $ownerFrame] == $PeerGroupPlaceholder;
+ // ----- call
+ assert stack50000o != null;
+ call Microsoft.Contracts.ObjectInvariantException..ctor(stack50000o);
+ // ----- copy
+ stack0o := stack50000o;
+ // ----- throw
+ assert stack0o != null;
+ assume false;
+ return;
+
+ block2448:
+ // ----- load constant 1
+ return.value := true;
+ // ----- branch
+ goto block2567;
+
+ block2567:
+ // ----- copy
+ SS$Display.Return.Local := return.value;
+ // ----- copy
+ stack0b := return.value;
+ // ----- return
+ $result := stack0b;
+ return;
+}
+
+
+
+axiom Microsoft.Contracts.ObjectInvariantException <: Microsoft.Contracts.ObjectInvariantException;
+
+axiom Microsoft.Contracts.GuardException <: Microsoft.Contracts.GuardException;
+
+axiom System.Exception <: System.Exception;
+
+axiom $BaseClass(System.Exception) == System.Object && AsDirectSubClass(System.Exception, $BaseClass(System.Exception)) == System.Exception;
+
+axiom !$IsImmutable(System.Exception) && $AsMutable(System.Exception) == System.Exception;
+
+axiom System.Runtime.Serialization.ISerializable <: System.Runtime.Serialization.ISerializable;
+
+axiom System.Runtime.Serialization.ISerializable <: System.Object;
+
+axiom $IsMemberlessType(System.Runtime.Serialization.ISerializable);
+
+axiom $AsInterface(System.Runtime.Serialization.ISerializable) == System.Runtime.Serialization.ISerializable;
+
+axiom System.Exception <: System.Runtime.Serialization.ISerializable;
+
+axiom System.Runtime.InteropServices._Exception <: System.Runtime.InteropServices._Exception;
+
+axiom System.Runtime.InteropServices._Exception <: System.Object;
+
+axiom $IsMemberlessType(System.Runtime.InteropServices._Exception);
+
+axiom $AsInterface(System.Runtime.InteropServices._Exception) == System.Runtime.InteropServices._Exception;
+
+axiom System.Exception <: System.Runtime.InteropServices._Exception;
+
+// System.Exception object invariant
+axiom (forall $oi: ref, $h: Heap :: { $h[$oi, $inv] <: System.Exception } IsHeap($h) && $h[$oi, $inv] <: System.Exception && $h[$oi, $localinv] != $BaseClass(System.Exception) ==> true);
+
+axiom $BaseClass(Microsoft.Contracts.GuardException) == System.Exception && AsDirectSubClass(Microsoft.Contracts.GuardException, $BaseClass(Microsoft.Contracts.GuardException)) == Microsoft.Contracts.GuardException;
+
+axiom !$IsImmutable(Microsoft.Contracts.GuardException) && $AsMutable(Microsoft.Contracts.GuardException) == Microsoft.Contracts.GuardException;
+
+// Microsoft.Contracts.GuardException object invariant
+axiom (forall $oi: ref, $h: Heap :: { $h[$oi, $inv] <: Microsoft.Contracts.GuardException } IsHeap($h) && $h[$oi, $inv] <: Microsoft.Contracts.GuardException && $h[$oi, $localinv] != $BaseClass(Microsoft.Contracts.GuardException) ==> true);
+
+axiom $BaseClass(Microsoft.Contracts.ObjectInvariantException) == Microsoft.Contracts.GuardException && AsDirectSubClass(Microsoft.Contracts.ObjectInvariantException, $BaseClass(Microsoft.Contracts.ObjectInvariantException)) == Microsoft.Contracts.ObjectInvariantException;
+
+axiom !$IsImmutable(Microsoft.Contracts.ObjectInvariantException) && $AsMutable(Microsoft.Contracts.ObjectInvariantException) == Microsoft.Contracts.ObjectInvariantException;
+
+// Microsoft.Contracts.ObjectInvariantException object invariant
+axiom (forall $oi: ref, $h: Heap :: { $h[$oi, $inv] <: Microsoft.Contracts.ObjectInvariantException } IsHeap($h) && $h[$oi, $inv] <: Microsoft.Contracts.ObjectInvariantException && $h[$oi, $localinv] != $BaseClass(Microsoft.Contracts.ObjectInvariantException) ==> true);
+
+procedure Microsoft.Contracts.ObjectInvariantException..ctor(this: ref where $IsNotNull(this, Microsoft.Contracts.ObjectInvariantException) && $Heap[this, $allocated]);
+ // object is fully unpacked: this.inv == Object
+ free requires ($Heap[this, $ownerFrame] == $PeerGroupPlaceholder || !($Heap[$Heap[this, $ownerRef], $inv] <: $Heap[this, $ownerFrame]) || $Heap[$Heap[this, $ownerRef], $localinv] == $BaseClass($Heap[this, $ownerFrame])) && $Heap[this, $inv] == System.Object && $Heap[this, $localinv] == $typeof(this);
+ // nothing is owned by [this,*] and 'this' is alone in its own peer group
+ free requires (forall $o: ref :: $o != this ==> $Heap[$o, $ownerRef] != this) && $Heap[this, $ownerRef] == this && $Heap[this, $ownerFrame] == $PeerGroupPlaceholder;
+ free requires $BeingConstructed == this;
+ free requires $PurityAxiomsCanBeAssumed;
+ modifies $Heap, $ActivityIndicator;
+ // target object is allocated upon return
+ free ensures $Heap[this, $allocated];
+ // target object is additively exposable for Microsoft.Contracts.ObjectInvariantException
+ ensures ($Heap[this, $ownerFrame] == $PeerGroupPlaceholder || !($Heap[$Heap[this, $ownerRef], $inv] <: $Heap[this, $ownerFrame]) || $Heap[$Heap[this, $ownerRef], $localinv] == $BaseClass($Heap[this, $ownerFrame])) && $Heap[this, $inv] == Microsoft.Contracts.ObjectInvariantException && $Heap[this, $localinv] == $typeof(this);
+ ensures $Heap[this, $ownerRef] == old($Heap)[this, $ownerRef] && $Heap[this, $ownerFrame] == old($Heap)[this, $ownerFrame];
+ ensures $Heap[this, $sharingMode] == $SharingMode_Unshared;
+ // newly allocated objects are fully valid
+ free ensures (forall $o: ref :: { $Heap[$o, $localinv] } { $Heap[$o, $inv] } $o != null && !old($Heap)[$o, $allocated] && $Heap[$o, $allocated] ==> $Heap[$o, $inv] == $typeof($o) && $Heap[$o, $localinv] == $typeof($o));
+ // first consistent owner unchanged if its exposeVersion is
+ free ensures (forall $o: ref :: { $Heap[$o, $FirstConsistentOwner] } old($Heap)[old($Heap)[$o, $FirstConsistentOwner], $exposeVersion] == $Heap[old($Heap)[$o, $FirstConsistentOwner], $exposeVersion] ==> old($Heap)[$o, $FirstConsistentOwner] == $Heap[$o, $FirstConsistentOwner]);
+ // frame condition
+ ensures (forall<a> $o: ref, $f: Field a :: { $Heap[$o, $f] } IncludeInMainFrameCondition($f) && $o != null && old($Heap)[$o, $allocated] && (old($Heap)[$o, $ownerFrame] == $PeerGroupPlaceholder || !(old($Heap)[old($Heap)[$o, $ownerRef], $inv] <: old($Heap)[$o, $ownerFrame]) || old($Heap)[old($Heap)[$o, $ownerRef], $localinv] == $BaseClass(old($Heap)[$o, $ownerFrame])) && ($o != this || !(Microsoft.Contracts.ObjectInvariantException <: DeclType222($f))) && old(true) && old(true) ==> old($Heap)[$o, $f] == $Heap[$o, $f]);
+ free ensures $HeapSucc(old($Heap), $Heap);
+ // inv/localinv change only in blocks
+ free ensures (forall $o: ref :: { $Heap[$o, $localinv] } { $Heap[$o, $inv] } old($Heap)[$o, $allocated] && $o != this ==> old($Heap)[$o, $inv] == $Heap[$o, $inv] && old($Heap)[$o, $localinv] == $Heap[$o, $localinv]);
+ free ensures (forall $o: ref :: { $Heap[$o, $allocated] } old($Heap)[$o, $allocated] ==> $Heap[$o, $allocated]) && (forall $ot: ref :: { $Heap[$ot, $ownerFrame] } { $Heap[$ot, $ownerRef] } old($Heap)[$ot, $allocated] && old($Heap)[$ot, $ownerFrame] != $PeerGroupPlaceholder ==> $Heap[$ot, $ownerRef] == old($Heap)[$ot, $ownerRef] && $Heap[$ot, $ownerFrame] == old($Heap)[$ot, $ownerFrame]) && old($Heap)[$BeingConstructed, $NonNullFieldsAreInitialized] == $Heap[$BeingConstructed, $NonNullFieldsAreInitialized];
+ free ensures (forall $o: ref :: { $Heap[$o, $sharingMode] } $o == this || old($Heap[$o, $sharingMode]) == $Heap[$o, $sharingMode]);
+
+
+
+procedure Bag..ctor$System.Int32.array$notnull(this: ref where $IsNotNull(this, Bag) && $Heap[this, $allocated], initialElements$in: ref where $IsNotNull(initialElements$in, IntArray(System.Int32, 1)) && $Heap[initialElements$in, $allocated]);
+ // object is fully unpacked: this.inv == Object
+ free requires ($Heap[this, $ownerFrame] == $PeerGroupPlaceholder || !($Heap[$Heap[this, $ownerRef], $inv] <: $Heap[this, $ownerFrame]) || $Heap[$Heap[this, $ownerRef], $localinv] == $BaseClass($Heap[this, $ownerFrame])) && $Heap[this, $inv] == System.Object && $Heap[this, $localinv] == $typeof(this);
+ // initialElements is peer consistent
+ requires (forall $pc: ref :: { $typeof($pc) } { $Heap[$pc, $localinv] } { $Heap[$pc, $inv] } { $Heap[$pc, $ownerFrame] } { $Heap[$pc, $ownerRef] } $pc != null && $Heap[$pc, $allocated] && $Heap[$pc, $ownerRef] == $Heap[initialElements$in, $ownerRef] && $Heap[$pc, $ownerFrame] == $Heap[initialElements$in, $ownerFrame] ==> $Heap[$pc, $inv] == $typeof($pc) && $Heap[$pc, $localinv] == $typeof($pc));
+ // initialElements is peer consistent (owner must not be valid)
+ requires $Heap[initialElements$in, $ownerFrame] == $PeerGroupPlaceholder || !($Heap[$Heap[initialElements$in, $ownerRef], $inv] <: $Heap[initialElements$in, $ownerFrame]) || $Heap[$Heap[initialElements$in, $ownerRef], $localinv] == $BaseClass($Heap[initialElements$in, $ownerFrame]);
+ // nothing is owned by [this,*] and 'this' is alone in its own peer group
+ free requires (forall $o: ref :: $o != this ==> $Heap[$o, $ownerRef] != this) && $Heap[this, $ownerRef] == this && $Heap[this, $ownerFrame] == $PeerGroupPlaceholder;
+ free requires $BeingConstructed == this;
+ free requires $PurityAxiomsCanBeAssumed;
+ modifies $Heap, $ActivityIndicator;
+ // target object is allocated upon return
+ free ensures $Heap[this, $allocated];
+ // target object is additively exposable for Bag
+ ensures ($Heap[this, $ownerFrame] == $PeerGroupPlaceholder || !($Heap[$Heap[this, $ownerRef], $inv] <: $Heap[this, $ownerFrame]) || $Heap[$Heap[this, $ownerRef], $localinv] == $BaseClass($Heap[this, $ownerFrame])) && $Heap[this, $inv] == Bag && $Heap[this, $localinv] == $typeof(this);
+ ensures $Heap[this, $ownerRef] == old($Heap)[this, $ownerRef] && $Heap[this, $ownerFrame] == old($Heap)[this, $ownerFrame];
+ ensures $Heap[this, $sharingMode] == $SharingMode_Unshared;
+ // newly allocated objects are fully valid
+ free ensures (forall $o: ref :: { $Heap[$o, $localinv] } { $Heap[$o, $inv] } $o != null && !old($Heap)[$o, $allocated] && $Heap[$o, $allocated] ==> $Heap[$o, $inv] == $typeof($o) && $Heap[$o, $localinv] == $typeof($o));
+ // first consistent owner unchanged if its exposeVersion is
+ free ensures (forall $o: ref :: { $Heap[$o, $FirstConsistentOwner] } old($Heap)[old($Heap)[$o, $FirstConsistentOwner], $exposeVersion] == $Heap[old($Heap)[$o, $FirstConsistentOwner], $exposeVersion] ==> old($Heap)[$o, $FirstConsistentOwner] == $Heap[$o, $FirstConsistentOwner]);
+ // frame condition
+ ensures (forall<a> $o: ref, $f: Field a :: { $Heap[$o, $f] } IncludeInMainFrameCondition($f) && $o != null && old($Heap)[$o, $allocated] && (old($Heap)[$o, $ownerFrame] == $PeerGroupPlaceholder || !(old($Heap)[old($Heap)[$o, $ownerRef], $inv] <: old($Heap)[$o, $ownerFrame]) || old($Heap)[old($Heap)[$o, $ownerRef], $localinv] == $BaseClass(old($Heap)[$o, $ownerFrame])) && ($o != this || !(Bag <: DeclType222($f))) && old(true) && old(true) ==> old($Heap)[$o, $f] == $Heap[$o, $f]);
+ free ensures $HeapSucc(old($Heap), $Heap);
+ // inv/localinv change only in blocks
+ free ensures (forall $o: ref :: { $Heap[$o, $localinv] } { $Heap[$o, $inv] } old($Heap)[$o, $allocated] && $o != this ==> old($Heap)[$o, $inv] == $Heap[$o, $inv] && old($Heap)[$o, $localinv] == $Heap[$o, $localinv]);
+ free ensures (forall $o: ref :: { $Heap[$o, $allocated] } old($Heap)[$o, $allocated] ==> $Heap[$o, $allocated]) && (forall $ot: ref :: { $Heap[$ot, $ownerFrame] } { $Heap[$ot, $ownerRef] } old($Heap)[$ot, $allocated] && old($Heap)[$ot, $ownerFrame] != $PeerGroupPlaceholder ==> $Heap[$ot, $ownerRef] == old($Heap)[$ot, $ownerRef] && $Heap[$ot, $ownerFrame] == old($Heap)[$ot, $ownerFrame]) && old($Heap)[$BeingConstructed, $NonNullFieldsAreInitialized] == $Heap[$BeingConstructed, $NonNullFieldsAreInitialized];
+ free ensures (forall $o: ref :: { $Heap[$o, $sharingMode] } $o == this || old($Heap[$o, $sharingMode]) == $Heap[$o, $sharingMode]);
+
+
+
+implementation Bag..ctor$System.Int32.array$notnull(this: ref, initialElements$in: ref)
+{
+ var initialElements: ref where $IsNotNull(initialElements, IntArray(System.Int32, 1)) && $Heap[initialElements, $allocated], stack0o: ref, stack0i: int, temp0: exposeVersionType, temp1: ref, temp2: exposeVersionType, stack1i: int, temp3: ref;
+
+ entry:
+ initialElements := initialElements$in;
+ assume $Heap[this, Bag.n] == 0;
+ goto block3332;
+
+ block3332:
+ goto block3468;
+
+ block3468:
+ // ----- nop
+ // ----- copy ----- AddMethod.ssc(13,5)
+ stack0o := initialElements;
+ // ----- unary operator ----- AddMethod.ssc(13,5)
+ assert stack0o != null;
+ stack0i := $Length(stack0o);
+ // ----- unary operator ----- AddMethod.ssc(13,5)
+ stack0i := $IntToInt(stack0i, System.UIntPtr, System.Int32);
+ // ----- store field ----- AddMethod.ssc(13,5)
+ assert this != null;
+ assert $Heap[this, $ownerFrame] == $PeerGroupPlaceholder || !($Heap[$Heap[this, $ownerRef], $inv] <: $Heap[this, $ownerFrame]) || $Heap[$Heap[this, $ownerRef], $localinv] == $BaseClass($Heap[this, $ownerFrame]);
+ havoc temp0;
+ $Heap[this, $exposeVersion] := temp0;
+ $Heap[this, Bag.n] := stack0i;
+ assert !($Heap[this, $inv] <: Bag && $Heap[this, $localinv] != $BaseClass(Bag)) || 0 <= $Heap[this, Bag.n];
+ assert !($Heap[this, $inv] <: Bag && $Heap[this, $localinv] != $BaseClass(Bag)) || $Heap[this, Bag.n] <= $Length($Heap[this, Bag.a]);
+ assume IsHeap($Heap);
+ // ----- copy ----- AddMethod.ssc(14,5)
+ stack0o := initialElements;
+ // ----- unary operator ----- AddMethod.ssc(14,5)
+ assert stack0o != null;
+ stack0i := $Length(stack0o);
+ // ----- unary operator ----- AddMethod.ssc(14,5)
+ stack0i := $IntToInt(stack0i, System.UIntPtr, System.Int32);
+ // ----- new array ----- AddMethod.ssc(14,5)
+ assert 0 <= stack0i;
+ havoc temp1;
+ assume $Heap[temp1, $allocated] == false && $Length(temp1) == stack0i;
+ assume $Heap[$ElementProxy(temp1, -1), $allocated] == false && $ElementProxy(temp1, -1) != temp1 && $ElementProxy(temp1, -1) != null;
+ assume temp1 != null;
+ assume $typeof(temp1) == IntArray(System.Int32, 1);
+ assume $Heap[temp1, $ownerRef] == temp1 && $Heap[temp1, $ownerFrame] == $PeerGroupPlaceholder;
+ assume $Heap[$ElementProxy(temp1, -1), $ownerRef] == $ElementProxy(temp1, -1) && $Heap[$ElementProxy(temp1, -1), $ownerFrame] == $PeerGroupPlaceholder;
+ assume $Heap[temp1, $inv] == $typeof(temp1) && $Heap[temp1, $localinv] == $typeof(temp1);
+ assume (forall $i: int :: IntArrayGet($Heap[temp1, $elements], $i) == 0);
+ $Heap[temp1, $allocated] := true;
+ call System.Object..ctor($ElementProxy(temp1, -1));
+ stack0o := temp1;
+ assume IsHeap($Heap);
+ // ----- store field ----- AddMethod.ssc(14,5)
+ assert this != null;
+ assert $Heap[this, $ownerFrame] == $PeerGroupPlaceholder || !($Heap[$Heap[this, $ownerRef], $inv] <: $Heap[this, $ownerFrame]) || $Heap[$Heap[this, $ownerRef], $localinv] == $BaseClass($Heap[this, $ownerFrame]);
+ assert ($Heap[stack0o, $ownerRef] == this && $Heap[stack0o, $ownerFrame] == Bag) || $Heap[stack0o, $ownerFrame] == $PeerGroupPlaceholder;
+ assert $Heap[stack0o, $ownerFrame] == $PeerGroupPlaceholder && $Heap[this, $inv] <: Bag && $Heap[this, $localinv] != $BaseClass(Bag) ==> (forall $pc: ref :: { $typeof($pc) } { $Heap[$pc, $localinv] } { $Heap[$pc, $inv] } { $Heap[$pc, $ownerFrame] } { $Heap[$pc, $ownerRef] } $pc != null && $Heap[$pc, $allocated] && $Heap[$pc, $ownerRef] == $Heap[stack0o, $ownerRef] && $Heap[$pc, $ownerFrame] == $Heap[stack0o, $ownerFrame] ==> $Heap[$pc, $inv] == $typeof($pc) && $Heap[$pc, $localinv] == $typeof($pc));
+ assert $Heap[stack0o, $ownerFrame] == $PeerGroupPlaceholder && $Heap[this, $inv] <: Bag && $Heap[this, $localinv] != $BaseClass(Bag) ==> $Heap[this, $ownerRef] != $Heap[stack0o, $ownerRef] || $Heap[this, $ownerFrame] != $Heap[stack0o, $ownerFrame];
+ call $UpdateOwnersForRep(this, Bag, stack0o);
+ havoc temp2;
+ $Heap[this, $exposeVersion] := temp2;
+ $Heap[this, Bag.a] := stack0o;
+ assert !($Heap[this, $inv] <: Bag && $Heap[this, $localinv] != $BaseClass(Bag)) || 0 <= $Heap[this, Bag.n];
+ assert !($Heap[this, $inv] <: Bag && $Heap[this, $localinv] != $BaseClass(Bag)) || $Heap[this, Bag.n] <= $Length($Heap[this, Bag.a]);
+ assume IsHeap($Heap);
+ // ----- call ----- AddMethod.ssc(15,5)
+ assert this != null;
+ call System.Object..ctor(this);
+ $Heap[this, $NonNullFieldsAreInitialized] := true;
+ assume IsHeap($Heap);
+ goto block3417;
+
+ block3417:
+ // ----- load field ----- AddMethod.ssc(16,5)
+ assert this != null;
+ stack0o := $Heap[this, Bag.a];
+ // ----- load constant 0 ----- AddMethod.ssc(16,5)
+ stack1i := 0;
+ // ----- call ----- AddMethod.ssc(16,5)
+ assert initialElements != null;
+ call System.Array.CopyTo$System.Array$notnull$System.Int32$.Virtual.$(initialElements, stack0o, stack1i);
+ // ----- FrameGuard processing ----- AddMethod.ssc(17,3)
+ temp3 := this;
+ // ----- classic pack ----- AddMethod.ssc(17,3)
+ assert temp3 != null;
+ assert $Heap[temp3, $inv] == System.Object && $Heap[temp3, $localinv] == $typeof(temp3);
+ assert 0 <= $Heap[temp3, Bag.n];
+ assert $Heap[temp3, Bag.n] <= $Length($Heap[temp3, Bag.a]);
+ assert (forall $p: ref :: $p != null && $Heap[$p, $allocated] && $Heap[$p, $ownerRef] == temp3 && $Heap[$p, $ownerFrame] == Bag ==> $Heap[$p, $inv] == $typeof($p) && $Heap[$p, $localinv] == $typeof($p));
+ $Heap[temp3, $inv] := Bag;
+ assume IsHeap($Heap);
+ // ----- return
+ return;
+}
+
+
+
+procedure System.Object..ctor(this: ref where $IsNotNull(this, System.Object) && $Heap[this, $allocated]);
+ // object is fully unpacked: this.inv == Object
+ free requires ($Heap[this, $ownerFrame] == $PeerGroupPlaceholder || !($Heap[$Heap[this, $ownerRef], $inv] <: $Heap[this, $ownerFrame]) || $Heap[$Heap[this, $ownerRef], $localinv] == $BaseClass($Heap[this, $ownerFrame])) && $Heap[this, $inv] == System.Object && $Heap[this, $localinv] == $typeof(this);
+ // nothing is owned by [this,*] and 'this' is alone in its own peer group
+ free requires (forall $o: ref :: $o != this ==> $Heap[$o, $ownerRef] != this) && $Heap[this, $ownerRef] == this && $Heap[this, $ownerFrame] == $PeerGroupPlaceholder;
+ free requires $BeingConstructed == this;
+ free requires $PurityAxiomsCanBeAssumed;
+ modifies $Heap, $ActivityIndicator;
+ // target object is allocated upon return
+ free ensures $Heap[this, $allocated];
+ // target object is additively exposable for System.Object
+ ensures ($Heap[this, $ownerFrame] == $PeerGroupPlaceholder || !($Heap[$Heap[this, $ownerRef], $inv] <: $Heap[this, $ownerFrame]) || $Heap[$Heap[this, $ownerRef], $localinv] == $BaseClass($Heap[this, $ownerFrame])) && $Heap[this, $inv] == System.Object && $Heap[this, $localinv] == $typeof(this);
+ ensures $Heap[this, $ownerRef] == old($Heap)[this, $ownerRef] && $Heap[this, $ownerFrame] == old($Heap)[this, $ownerFrame];
+ ensures $Heap[this, $sharingMode] == $SharingMode_Unshared;
+ // newly allocated objects are fully valid
+ free ensures (forall $o: ref :: { $Heap[$o, $localinv] } { $Heap[$o, $inv] } $o != null && !old($Heap)[$o, $allocated] && $Heap[$o, $allocated] ==> $Heap[$o, $inv] == $typeof($o) && $Heap[$o, $localinv] == $typeof($o));
+ // first consistent owner unchanged if its exposeVersion is
+ free ensures (forall $o: ref :: { $Heap[$o, $FirstConsistentOwner] } old($Heap)[old($Heap)[$o, $FirstConsistentOwner], $exposeVersion] == $Heap[old($Heap)[$o, $FirstConsistentOwner], $exposeVersion] ==> old($Heap)[$o, $FirstConsistentOwner] == $Heap[$o, $FirstConsistentOwner]);
+ // frame condition
+ ensures (forall<a> $o: ref, $f: Field a :: { $Heap[$o, $f] } IncludeInMainFrameCondition($f) && $o != null && old($Heap)[$o, $allocated] && (old($Heap)[$o, $ownerFrame] == $PeerGroupPlaceholder || !(old($Heap)[old($Heap)[$o, $ownerRef], $inv] <: old($Heap)[$o, $ownerFrame]) || old($Heap)[old($Heap)[$o, $ownerRef], $localinv] == $BaseClass(old($Heap)[$o, $ownerFrame])) && ($o != this || !(System.Object <: DeclType222($f))) && old(true) && old(true) ==> old($Heap)[$o, $f] == $Heap[$o, $f]);
+ free ensures $HeapSucc(old($Heap), $Heap);
+ // inv/localinv change only in blocks
+ free ensures (forall $o: ref :: { $Heap[$o, $localinv] } { $Heap[$o, $inv] } old($Heap)[$o, $allocated] && $o != this ==> old($Heap)[$o, $inv] == $Heap[$o, $inv] && old($Heap)[$o, $localinv] == $Heap[$o, $localinv]);
+ free ensures (forall $o: ref :: { $Heap[$o, $allocated] } old($Heap)[$o, $allocated] ==> $Heap[$o, $allocated]) && (forall $ot: ref :: { $Heap[$ot, $ownerFrame] } { $Heap[$ot, $ownerRef] } old($Heap)[$ot, $allocated] && old($Heap)[$ot, $ownerFrame] != $PeerGroupPlaceholder ==> $Heap[$ot, $ownerRef] == old($Heap)[$ot, $ownerRef] && $Heap[$ot, $ownerFrame] == old($Heap)[$ot, $ownerFrame]) && old($Heap)[$BeingConstructed, $NonNullFieldsAreInitialized] == $Heap[$BeingConstructed, $NonNullFieldsAreInitialized];
+ free ensures (forall $o: ref :: { $Heap[$o, $sharingMode] } $o == this || old($Heap[$o, $sharingMode]) == $Heap[$o, $sharingMode]);
+
+
+
+procedure System.Array.CopyTo$System.Array$notnull$System.Int32$.Virtual.$(this: ref where $IsNotNull(this, System.Array) && $Heap[this, $allocated], array$in: ref where $IsNotNull(array$in, System.Array) && $Heap[array$in, $allocated], index$in: int where InRange(index$in, System.Int32));
+ // user-declared preconditions
+ requires array$in != null;
+ requires $LBound(array$in, 0) <= index$in;
+ requires $Rank(this) == 1;
+ requires $Rank(array$in) == 1;
+ requires $Length(this) <= $UBound(array$in, 0) + 1 - index$in;
+ // target object is peer consistent
+ requires (forall $pc: ref :: { $typeof($pc) } { $Heap[$pc, $localinv] } { $Heap[$pc, $inv] } { $Heap[$pc, $ownerFrame] } { $Heap[$pc, $ownerRef] } $pc != null && $Heap[$pc, $allocated] && $Heap[$pc, $ownerRef] == $Heap[this, $ownerRef] && $Heap[$pc, $ownerFrame] == $Heap[this, $ownerFrame] ==> $Heap[$pc, $inv] == $typeof($pc) && $Heap[$pc, $localinv] == $typeof($pc));
+ // target object is peer consistent (owner must not be valid)
+ requires $Heap[this, $ownerFrame] == $PeerGroupPlaceholder || !($Heap[$Heap[this, $ownerRef], $inv] <: $Heap[this, $ownerFrame]) || $Heap[$Heap[this, $ownerRef], $localinv] == $BaseClass($Heap[this, $ownerFrame]);
+ // array is peer consistent
+ requires (forall $pc: ref :: { $typeof($pc) } { $Heap[$pc, $localinv] } { $Heap[$pc, $inv] } { $Heap[$pc, $ownerFrame] } { $Heap[$pc, $ownerRef] } $pc != null && $Heap[$pc, $allocated] && $Heap[$pc, $ownerRef] == $Heap[array$in, $ownerRef] && $Heap[$pc, $ownerFrame] == $Heap[array$in, $ownerFrame] ==> $Heap[$pc, $inv] == $typeof($pc) && $Heap[$pc, $localinv] == $typeof($pc));
+ // array is peer consistent (owner must not be valid)
+ requires $Heap[array$in, $ownerFrame] == $PeerGroupPlaceholder || !($Heap[$Heap[array$in, $ownerRef], $inv] <: $Heap[array$in, $ownerFrame]) || $Heap[$Heap[array$in, $ownerRef], $localinv] == $BaseClass($Heap[array$in, $ownerFrame]);
+ free requires $BeingConstructed == null;
+ free requires $PurityAxiomsCanBeAssumed;
+ modifies $Heap, $ActivityIndicator;
+ // hard-coded postcondition
+ ensures (forall $k: int :: { ValueArrayGet($Heap[array$in, $elements], $k) } (index$in <= $k && $k < index$in + $Length(this) ==> old(ValueArrayGet($Heap[this, $elements], $k + 0 - index$in)) == ValueArrayGet($Heap[array$in, $elements], $k)) && (!(index$in <= $k && $k < index$in + $Length(this)) ==> old(ValueArrayGet($Heap[array$in, $elements], $k)) == ValueArrayGet($Heap[array$in, $elements], $k)));
+ ensures (forall $k: int :: { IntArrayGet($Heap[array$in, $elements], $k) } (index$in <= $k && $k < index$in + $Length(this) ==> old(IntArrayGet($Heap[this, $elements], $k + 0 - index$in)) == IntArrayGet($Heap[array$in, $elements], $k)) && (!(index$in <= $k && $k < index$in + $Length(this)) ==> old(IntArrayGet($Heap[array$in, $elements], $k)) == IntArrayGet($Heap[array$in, $elements], $k)));
+ ensures (forall $k: int :: { RefArrayGet($Heap[array$in, $elements], $k) } (index$in <= $k && $k < index$in + $Length(this) ==> old(RefArrayGet($Heap[this, $elements], $k + 0 - index$in)) == RefArrayGet($Heap[array$in, $elements], $k)) && (!(index$in <= $k && $k < index$in + $Length(this)) ==> old(RefArrayGet($Heap[array$in, $elements], $k)) == RefArrayGet($Heap[array$in, $elements], $k)));
+ // newly allocated objects are fully valid
+ free ensures (forall $o: ref :: { $Heap[$o, $localinv] } { $Heap[$o, $inv] } $o != null && !old($Heap)[$o, $allocated] && $Heap[$o, $allocated] ==> $Heap[$o, $inv] == $typeof($o) && $Heap[$o, $localinv] == $typeof($o));
+ // first consistent owner unchanged if its exposeVersion is
+ free ensures (forall $o: ref :: { $Heap[$o, $FirstConsistentOwner] } old($Heap)[old($Heap)[$o, $FirstConsistentOwner], $exposeVersion] == $Heap[old($Heap)[$o, $FirstConsistentOwner], $exposeVersion] ==> old($Heap)[$o, $FirstConsistentOwner] == $Heap[$o, $FirstConsistentOwner]);
+ // frame condition
+ ensures (forall<a> $o: ref, $f: Field a :: { $Heap[$o, $f] } IncludeInMainFrameCondition($f) && $o != null && old($Heap)[$o, $allocated] && (old($Heap)[$o, $ownerFrame] == $PeerGroupPlaceholder || !(old($Heap)[old($Heap)[$o, $ownerRef], $inv] <: old($Heap)[$o, $ownerFrame]) || old($Heap)[old($Heap)[$o, $ownerRef], $localinv] == $BaseClass(old($Heap)[$o, $ownerFrame])) && old($o != array$in || !($typeof(array$in) <: DeclType222($f)) || !$IncludedInModifiesStar($f)) && old($o != array$in || $f != $exposeVersion) ==> old($Heap)[$o, $f] == $Heap[$o, $f]);
+ free ensures $HeapSucc(old($Heap), $Heap);
+ // inv/localinv change only in blocks
+ free ensures (forall $o: ref :: { $Heap[$o, $localinv] } { $Heap[$o, $inv] } old($Heap)[$o, $allocated] ==> old($Heap)[$o, $inv] == $Heap[$o, $inv] && old($Heap)[$o, $localinv] == $Heap[$o, $localinv]);
+ free ensures (forall $o: ref :: { $Heap[$o, $allocated] } old($Heap)[$o, $allocated] ==> $Heap[$o, $allocated]) && (forall $ot: ref :: { $Heap[$ot, $ownerFrame] } { $Heap[$ot, $ownerRef] } old($Heap)[$ot, $allocated] && old($Heap)[$ot, $ownerFrame] != $PeerGroupPlaceholder ==> $Heap[$ot, $ownerRef] == old($Heap)[$ot, $ownerRef] && $Heap[$ot, $ownerFrame] == old($Heap)[$ot, $ownerFrame]) && old($Heap)[$BeingConstructed, $NonNullFieldsAreInitialized] == $Heap[$BeingConstructed, $NonNullFieldsAreInitialized];
+ free ensures (forall $o: ref :: { $Heap[$o, $sharingMode] } old($Heap[$o, $sharingMode]) == $Heap[$o, $sharingMode]);
+
+
+
+procedure Bag.Add$System.Int32(this: ref where $IsNotNull(this, Bag) && $Heap[this, $allocated], x$in: int where InRange(x$in, System.Int32));
+ // target object is peer consistent
+ requires (forall $pc: ref :: { $typeof($pc) } { $Heap[$pc, $localinv] } { $Heap[$pc, $inv] } { $Heap[$pc, $ownerFrame] } { $Heap[$pc, $ownerRef] } $pc != null && $Heap[$pc, $allocated] && $Heap[$pc, $ownerRef] == $Heap[this, $ownerRef] && $Heap[$pc, $ownerFrame] == $Heap[this, $ownerFrame] ==> $Heap[$pc, $inv] == $typeof($pc) && $Heap[$pc, $localinv] == $typeof($pc));
+ // target object is peer consistent (owner must not be valid)
+ requires $Heap[this, $ownerFrame] == $PeerGroupPlaceholder || !($Heap[$Heap[this, $ownerRef], $inv] <: $Heap[this, $ownerFrame]) || $Heap[$Heap[this, $ownerRef], $localinv] == $BaseClass($Heap[this, $ownerFrame]);
+ free requires $BeingConstructed == null;
+ free requires $PurityAxiomsCanBeAssumed;
+ modifies $Heap, $ActivityIndicator;
+ // newly allocated objects are fully valid
+ free ensures (forall $o: ref :: { $Heap[$o, $localinv] } { $Heap[$o, $inv] } $o != null && !old($Heap)[$o, $allocated] && $Heap[$o, $allocated] ==> $Heap[$o, $inv] == $typeof($o) && $Heap[$o, $localinv] == $typeof($o));
+ // first consistent owner unchanged if its exposeVersion is
+ free ensures (forall $o: ref :: { $Heap[$o, $FirstConsistentOwner] } old($Heap)[old($Heap)[$o, $FirstConsistentOwner], $exposeVersion] == $Heap[old($Heap)[$o, $FirstConsistentOwner], $exposeVersion] ==> old($Heap)[$o, $FirstConsistentOwner] == $Heap[$o, $FirstConsistentOwner]);
+ // frame condition
+ ensures (forall<a> $o: ref, $f: Field a :: { $Heap[$o, $f] } IncludeInMainFrameCondition($f) && $o != null && old($Heap)[$o, $allocated] && (old($Heap)[$o, $ownerFrame] == $PeerGroupPlaceholder || !(old($Heap)[old($Heap)[$o, $ownerRef], $inv] <: old($Heap)[$o, $ownerFrame]) || old($Heap)[old($Heap)[$o, $ownerRef], $localinv] == $BaseClass(old($Heap)[$o, $ownerFrame])) && old($o != this || !($typeof(this) <: DeclType222($f)) || !$IncludedInModifiesStar($f)) && old($o != this || $f != $exposeVersion) ==> old($Heap)[$o, $f] == $Heap[$o, $f]);
+ free ensures $HeapSucc(old($Heap), $Heap);
+ // inv/localinv change only in blocks
+ free ensures (forall $o: ref :: { $Heap[$o, $localinv] } { $Heap[$o, $inv] } old($Heap)[$o, $allocated] ==> old($Heap)[$o, $inv] == $Heap[$o, $inv] && old($Heap)[$o, $localinv] == $Heap[$o, $localinv]);
+ free ensures (forall $o: ref :: { $Heap[$o, $allocated] } old($Heap)[$o, $allocated] ==> $Heap[$o, $allocated]) && (forall $ot: ref :: { $Heap[$ot, $ownerFrame] } { $Heap[$ot, $ownerRef] } old($Heap)[$ot, $allocated] && old($Heap)[$ot, $ownerFrame] != $PeerGroupPlaceholder ==> $Heap[$ot, $ownerRef] == old($Heap)[$ot, $ownerRef] && $Heap[$ot, $ownerFrame] == old($Heap)[$ot, $ownerFrame]) && old($Heap)[$BeingConstructed, $NonNullFieldsAreInitialized] == $Heap[$BeingConstructed, $NonNullFieldsAreInitialized];
+ free ensures (forall $o: ref :: { $Heap[$o, $sharingMode] } old($Heap[$o, $sharingMode]) == $Heap[$o, $sharingMode]);
+
+
+
+implementation Bag.Add$System.Int32(this: ref, x$in: int)
+{
+ var x: int where InRange(x, System.Int32), temp0: ref, stack1s: struct, stack1o: ref, temp1: exposeVersionType, local2: ref where $Is(local2, System.Exception) && $Heap[local2, $allocated], stack0i: int, stack1i: int, stack0b: bool, b: ref where $Is(b, IntArray(System.Int32, 1)) && $Heap[b, $allocated], temp2: ref, stack0o: ref, stack2o: ref, stack3i: int, stack4o: ref, stack4i: int, temp3: exposeVersionType, local4: int where InRange(local4, System.Int32), temp4: exposeVersionType, stack0s: struct;
+
+ entry:
+ x := x$in;
+ goto block4335;
+
+ block4335:
+ goto block4488;
+
+ block4488:
+ // ----- nop
+ // ----- FrameGuard processing ----- AddMethod.ssc(22,13)
+ temp0 := this;
+ // ----- load token ----- AddMethod.ssc(22,13)
+ havoc stack1s;
+ assume $IsTokenForType(stack1s, Bag);
+ // ----- statically resolved GetTypeFromHandle call ----- AddMethod.ssc(22,13)
+ stack1o := TypeObject(Bag);
+ // ----- local unpack ----- AddMethod.ssc(22,13)
+ assert temp0 != null;
+ assert ($Heap[temp0, $ownerFrame] == $PeerGroupPlaceholder || !($Heap[$Heap[temp0, $ownerRef], $inv] <: $Heap[temp0, $ownerFrame]) || $Heap[$Heap[temp0, $ownerRef], $localinv] == $BaseClass($Heap[temp0, $ownerFrame])) && $Heap[temp0, $inv] <: Bag && $Heap[temp0, $localinv] == $typeof(temp0);
+ $Heap[temp0, $localinv] := System.Object;
+ havoc temp1;
+ $Heap[temp0, $exposeVersion] := temp1;
+ assume IsHeap($Heap);
+ local2 := null;
+ goto block4505;
+
+ block4505:
+ // ----- load field ----- AddMethod.ssc(24,7)
+ assert this != null;
+ stack0i := $Heap[this, Bag.n];
+ // ----- load field ----- AddMethod.ssc(24,7)
+ assert this != null;
+ stack1o := $Heap[this, Bag.a];
+ // ----- unary operator ----- AddMethod.ssc(24,7)
+ assert stack1o != null;
+ stack1i := $Length(stack1o);
+ // ----- unary operator ----- AddMethod.ssc(24,7)
+ stack1i := $IntToInt(stack1i, System.UIntPtr, System.Int32);
+ // ----- binary operator ----- AddMethod.ssc(24,7)
+ // ----- branch ----- AddMethod.ssc(24,7)
+ goto true4505to4539, false4505to4522;
+
+ true4505to4539:
+ assume stack0i != stack1i;
+ goto block4539;
+
+ false4505to4522:
+ assume stack0i == stack1i;
+ goto block4522;
+
+ block4539:
+ // ----- load field ----- AddMethod.ssc(30,7)
+ assert this != null;
+ stack0o := $Heap[this, Bag.a];
+ // ----- load field ----- AddMethod.ssc(30,7)
+ assert this != null;
+ stack1i := $Heap[this, Bag.n];
+ // ----- store element ----- AddMethod.ssc(30,7)
+ assert stack0o != null;
+ assert 0 <= stack1i;
+ assert stack1i < $Length(stack0o);
+ assert $Heap[stack0o, $ownerFrame] == $PeerGroupPlaceholder || !($Heap[$Heap[stack0o, $ownerRef], $inv] <: $Heap[stack0o, $ownerFrame]) || $Heap[$Heap[stack0o, $ownerRef], $localinv] == $BaseClass($Heap[stack0o, $ownerFrame]);
+ $Heap[stack0o, $elements] := IntArraySet($Heap[stack0o, $elements], stack1i, x);
+ assume IsHeap($Heap);
+ // ----- load field ----- AddMethod.ssc(31,7)
+ assert this != null;
+ local4 := $Heap[this, Bag.n];
+ // ----- load constant 1 ----- AddMethod.ssc(31,7)
+ stack0i := 1;
+ // ----- binary operator ----- AddMethod.ssc(31,7)
+ stack0i := local4 + stack0i;
+ // ----- store field ----- AddMethod.ssc(31,7)
+ assert this != null;
+ assert $Heap[this, $ownerFrame] == $PeerGroupPlaceholder || !($Heap[$Heap[this, $ownerRef], $inv] <: $Heap[this, $ownerFrame]) || $Heap[$Heap[this, $ownerRef], $localinv] == $BaseClass($Heap[this, $ownerFrame]);
+ havoc temp4;
+ $Heap[this, $exposeVersion] := temp4;
+ $Heap[this, Bag.n] := stack0i;
+ assert !($Heap[this, $inv] <: Bag && $Heap[this, $localinv] != $BaseClass(Bag)) || 0 <= $Heap[this, Bag.n];
+ assert !($Heap[this, $inv] <: Bag && $Heap[this, $localinv] != $BaseClass(Bag)) || $Heap[this, Bag.n] <= $Length($Heap[this, Bag.a]);
+ assume IsHeap($Heap);
+ // ----- copy
+ stack0i := local4;
+ // ----- branch
+ goto block4658;
+
+ block4522:
+ // ----- load constant 2 ----- AddMethod.ssc(26,15)
+ stack0i := 2;
+ // ----- load field ----- AddMethod.ssc(26,15)
+ assert this != null;
+ stack1o := $Heap[this, Bag.a];
+ // ----- unary operator ----- AddMethod.ssc(26,15)
+ assert stack1o != null;
+ stack1i := $Length(stack1o);
+ // ----- unary operator ----- AddMethod.ssc(26,15)
+ stack1i := $IntToInt(stack1i, System.UIntPtr, System.Int32);
+ // ----- binary operator ----- AddMethod.ssc(26,15)
+ stack0i := stack0i * stack1i;
+ // ----- load constant 1 ----- AddMethod.ssc(26,15)
+ stack1i := 1;
+ // ----- binary operator ----- AddMethod.ssc(26,15)
+ stack0i := stack0i + stack1i;
+ // ----- new array ----- AddMethod.ssc(26,15)
+ assert 0 <= stack0i;
+ havoc temp2;
+ assume $Heap[temp2, $allocated] == false && $Length(temp2) == stack0i;
+ assume $Heap[$ElementProxy(temp2, -1), $allocated] == false && $ElementProxy(temp2, -1) != temp2 && $ElementProxy(temp2, -1) != null;
+ assume temp2 != null;
+ assume $typeof(temp2) == IntArray(System.Int32, 1);
+ assume $Heap[temp2, $ownerRef] == temp2 && $Heap[temp2, $ownerFrame] == $PeerGroupPlaceholder;
+ assume $Heap[$ElementProxy(temp2, -1), $ownerRef] == $ElementProxy(temp2, -1) && $Heap[$ElementProxy(temp2, -1), $ownerFrame] == $PeerGroupPlaceholder;
+ assume $Heap[temp2, $inv] == $typeof(temp2) && $Heap[temp2, $localinv] == $typeof(temp2);
+ assume (forall $i: int :: IntArrayGet($Heap[temp2, $elements], $i) == 0);
+ $Heap[temp2, $allocated] := true;
+ call System.Object..ctor($ElementProxy(temp2, -1));
+ b := temp2;
+ assume IsHeap($Heap);
+ // ----- load field ----- AddMethod.ssc(27,9)
+ assert this != null;
+ stack0o := $Heap[this, Bag.a];
+ // ----- load constant 0 ----- AddMethod.ssc(27,9)
+ stack1i := 0;
+ // ----- copy ----- AddMethod.ssc(27,9)
+ stack2o := b;
+ // ----- load constant 0 ----- AddMethod.ssc(27,9)
+ stack3i := 0;
+ // ----- load field ----- AddMethod.ssc(27,9)
+ assert this != null;
+ stack4o := $Heap[this, Bag.a];
+ // ----- unary operator ----- AddMethod.ssc(27,9)
+ assert stack4o != null;
+ stack4i := $Length(stack4o);
+ // ----- unary operator ----- AddMethod.ssc(27,9)
+ stack4i := $IntToInt(stack4i, System.UIntPtr, System.Int32);
+ // ----- call ----- AddMethod.ssc(27,9)
+ call System.Array.Copy$System.Array$notnull$System.Int32$System.Array$notnull$System.Int32$System.Int32(stack0o, stack1i, stack2o, stack3i, stack4i);
+ // ----- store field ----- AddMethod.ssc(28,9)
+ assert this != null;
+ assert $Heap[this, $ownerFrame] == $PeerGroupPlaceholder || !($Heap[$Heap[this, $ownerRef], $inv] <: $Heap[this, $ownerFrame]) || $Heap[$Heap[this, $ownerRef], $localinv] == $BaseClass($Heap[this, $ownerFrame]);
+ assert ($Heap[b, $ownerRef] == this && $Heap[b, $ownerFrame] == Bag) || $Heap[b, $ownerFrame] == $PeerGroupPlaceholder;
+ assert $Heap[b, $ownerFrame] == $PeerGroupPlaceholder && $Heap[this, $inv] <: Bag && $Heap[this, $localinv] != $BaseClass(Bag) ==> (forall $pc: ref :: { $typeof($pc) } { $Heap[$pc, $localinv] } { $Heap[$pc, $inv] } { $Heap[$pc, $ownerFrame] } { $Heap[$pc, $ownerRef] } $pc != null && $Heap[$pc, $allocated] && $Heap[$pc, $ownerRef] == $Heap[b, $ownerRef] && $Heap[$pc, $ownerFrame] == $Heap[b, $ownerFrame] ==> $Heap[$pc, $inv] == $typeof($pc) && $Heap[$pc, $localinv] == $typeof($pc));
+ assert $Heap[b, $ownerFrame] == $PeerGroupPlaceholder && $Heap[this, $inv] <: Bag && $Heap[this, $localinv] != $BaseClass(Bag) ==> $Heap[this, $ownerRef] != $Heap[b, $ownerRef] || $Heap[this, $ownerFrame] != $Heap[b, $ownerFrame];
+ call $UpdateOwnersForRep(this, Bag, b);
+ havoc temp3;
+ $Heap[this, $exposeVersion] := temp3;
+ $Heap[this, Bag.a] := b;
+ assert !($Heap[this, $inv] <: Bag && $Heap[this, $localinv] != $BaseClass(Bag)) || 0 <= $Heap[this, Bag.n];
+ assert !($Heap[this, $inv] <: Bag && $Heap[this, $localinv] != $BaseClass(Bag)) || $Heap[this, Bag.n] <= $Length($Heap[this, Bag.a]);
+ assume IsHeap($Heap);
+ goto block4539;
+
+ block4658:
+ stack0o := null;
+ // ----- binary operator
+ // ----- branch
+ goto true4658to4624, false4658to4641;
+
+ true4658to4624:
+ assume local2 == stack0o;
+ goto block4624;
+
+ false4658to4641:
+ assume local2 != stack0o;
+ goto block4641;
+
+ block4624:
+ // ----- load token ----- AddMethod.ssc(32,5)
+ havoc stack0s;
+ assume $IsTokenForType(stack0s, Bag);
+ // ----- statically resolved GetTypeFromHandle call ----- AddMethod.ssc(32,5)
+ stack0o := TypeObject(Bag);
+ // ----- local pack ----- AddMethod.ssc(32,5)
+ assert temp0 != null;
+ assert $Heap[temp0, $localinv] == System.Object;
+ assert 0 <= $Heap[temp0, Bag.n];
+ assert $Heap[temp0, Bag.n] <= $Length($Heap[temp0, Bag.a]);
+ assert (forall $p: ref :: $p != null && $Heap[$p, $allocated] && $Heap[$p, $ownerRef] == temp0 && $Heap[$p, $ownerFrame] == Bag ==> $Heap[$p, $inv] == $typeof($p) && $Heap[$p, $localinv] == $typeof($p));
+ $Heap[temp0, $localinv] := $typeof(temp0);
+ assume IsHeap($Heap);
+ goto block4726;
+
+ block4641:
+ // ----- is instance
+ // ----- branch
+ goto true4641to4624, false4641to4692;
+
+ true4641to4624:
+ assume $As(local2, Microsoft.Contracts.ICheckedException) != null;
+ goto block4624;
+
+ false4641to4692:
+ assume $As(local2, Microsoft.Contracts.ICheckedException) == null;
+ goto block4692;
+
+ block4692:
+ // ----- branch
+ goto block4726;
+
+ block4726:
+ // ----- nop
+ // ----- branch
+ goto block4590;
+
+ block4590:
+ // ----- return
+ return;
+}
+
+
+
+axiom System.Type <: System.Type;
+
+axiom System.Reflection.MemberInfo <: System.Reflection.MemberInfo;
+
+axiom $BaseClass(System.Reflection.MemberInfo) == System.Object && AsDirectSubClass(System.Reflection.MemberInfo, $BaseClass(System.Reflection.MemberInfo)) == System.Reflection.MemberInfo;
+
+axiom $IsImmutable(System.Reflection.MemberInfo) && $AsImmutable(System.Reflection.MemberInfo) == System.Reflection.MemberInfo;
+
+axiom System.Reflection.ICustomAttributeProvider <: System.Reflection.ICustomAttributeProvider;
+
+axiom System.Reflection.ICustomAttributeProvider <: System.Object;
+
+axiom $IsMemberlessType(System.Reflection.ICustomAttributeProvider);
+
+axiom $AsInterface(System.Reflection.ICustomAttributeProvider) == System.Reflection.ICustomAttributeProvider;
+
+axiom System.Reflection.MemberInfo <: System.Reflection.ICustomAttributeProvider;
+
+axiom System.Runtime.InteropServices._MemberInfo <: System.Runtime.InteropServices._MemberInfo;
+
+axiom System.Runtime.InteropServices._MemberInfo <: System.Object;
+
+axiom $IsMemberlessType(System.Runtime.InteropServices._MemberInfo);
+
+axiom $AsInterface(System.Runtime.InteropServices._MemberInfo) == System.Runtime.InteropServices._MemberInfo;
+
+axiom System.Reflection.MemberInfo <: System.Runtime.InteropServices._MemberInfo;
+
+axiom $IsMemberlessType(System.Reflection.MemberInfo);
+
+// System.Reflection.MemberInfo object invariant
+axiom (forall $oi: ref, $h: Heap :: { $h[$oi, $inv] <: System.Reflection.MemberInfo } IsHeap($h) && $h[$oi, $inv] <: System.Reflection.MemberInfo && $h[$oi, $localinv] != $BaseClass(System.Reflection.MemberInfo) ==> true);
+
+axiom $BaseClass(System.Type) == System.Reflection.MemberInfo && AsDirectSubClass(System.Type, $BaseClass(System.Type)) == System.Type;
+
+axiom $IsImmutable(System.Type) && $AsImmutable(System.Type) == System.Type;
+
+axiom System.Runtime.InteropServices._Type <: System.Runtime.InteropServices._Type;
+
+axiom System.Runtime.InteropServices._Type <: System.Object;
+
+axiom $IsMemberlessType(System.Runtime.InteropServices._Type);
+
+axiom $AsInterface(System.Runtime.InteropServices._Type) == System.Runtime.InteropServices._Type;
+
+axiom System.Type <: System.Runtime.InteropServices._Type;
+
+axiom System.Reflection.IReflect <: System.Reflection.IReflect;
+
+axiom System.Reflection.IReflect <: System.Object;
+
+axiom $IsMemberlessType(System.Reflection.IReflect);
+
+axiom $AsInterface(System.Reflection.IReflect) == System.Reflection.IReflect;
+
+axiom System.Type <: System.Reflection.IReflect;
+
+axiom $IsMemberlessType(System.Type);
+
+// System.Type object invariant
+axiom (forall $oi: ref, $h: Heap :: { $h[$oi, $inv] <: System.Type } IsHeap($h) && $h[$oi, $inv] <: System.Type && $h[$oi, $localinv] != $BaseClass(System.Type) ==> true);
+
+procedure System.Array.Copy$System.Array$notnull$System.Int32$System.Array$notnull$System.Int32$System.Int32(sourceArray$in: ref where $IsNotNull(sourceArray$in, System.Array) && $Heap[sourceArray$in, $allocated], sourceIndex$in: int where InRange(sourceIndex$in, System.Int32), destinationArray$in: ref where $IsNotNull(destinationArray$in, System.Array) && $Heap[destinationArray$in, $allocated], destinationIndex$in: int where InRange(destinationIndex$in, System.Int32), length$in: int where InRange(length$in, System.Int32));
+ // user-declared preconditions
+ requires sourceArray$in != null;
+ requires destinationArray$in != null;
+ requires $Rank(sourceArray$in) == $Rank(destinationArray$in);
+ requires sourceIndex$in >= $LBound(sourceArray$in, 0);
+ requires destinationIndex$in >= $LBound(destinationArray$in, 0);
+ requires length$in >= 0;
+ requires sourceIndex$in + length$in <= $LBound(sourceArray$in, 0) + $Length(sourceArray$in);
+ requires destinationIndex$in + length$in <= $LBound(destinationArray$in, 0) + $Length(destinationArray$in);
+ // sourceArray is peer consistent
+ requires (forall $pc: ref :: { $typeof($pc) } { $Heap[$pc, $localinv] } { $Heap[$pc, $inv] } { $Heap[$pc, $ownerFrame] } { $Heap[$pc, $ownerRef] } $pc != null && $Heap[$pc, $allocated] && $Heap[$pc, $ownerRef] == $Heap[sourceArray$in, $ownerRef] && $Heap[$pc, $ownerFrame] == $Heap[sourceArray$in, $ownerFrame] ==> $Heap[$pc, $inv] == $typeof($pc) && $Heap[$pc, $localinv] == $typeof($pc));
+ // sourceArray is peer consistent (owner must not be valid)
+ requires $Heap[sourceArray$in, $ownerFrame] == $PeerGroupPlaceholder || !($Heap[$Heap[sourceArray$in, $ownerRef], $inv] <: $Heap[sourceArray$in, $ownerFrame]) || $Heap[$Heap[sourceArray$in, $ownerRef], $localinv] == $BaseClass($Heap[sourceArray$in, $ownerFrame]);
+ // destinationArray is peer consistent
+ requires (forall $pc: ref :: { $typeof($pc) } { $Heap[$pc, $localinv] } { $Heap[$pc, $inv] } { $Heap[$pc, $ownerFrame] } { $Heap[$pc, $ownerRef] } $pc != null && $Heap[$pc, $allocated] && $Heap[$pc, $ownerRef] == $Heap[destinationArray$in, $ownerRef] && $Heap[$pc, $ownerFrame] == $Heap[destinationArray$in, $ownerFrame] ==> $Heap[$pc, $inv] == $typeof($pc) && $Heap[$pc, $localinv] == $typeof($pc));
+ // destinationArray is peer consistent (owner must not be valid)
+ requires $Heap[destinationArray$in, $ownerFrame] == $PeerGroupPlaceholder || !($Heap[$Heap[destinationArray$in, $ownerRef], $inv] <: $Heap[destinationArray$in, $ownerFrame]) || $Heap[$Heap[destinationArray$in, $ownerRef], $localinv] == $BaseClass($Heap[destinationArray$in, $ownerFrame]);
+ free requires $BeingConstructed == null;
+ free requires $PurityAxiomsCanBeAssumed;
+ modifies $Heap, $ActivityIndicator;
+ // hard-coded postcondition
+ ensures (forall $k: int :: { ValueArrayGet($Heap[destinationArray$in, $elements], $k) } (destinationIndex$in <= $k && $k < destinationIndex$in + length$in ==> old(ValueArrayGet($Heap[sourceArray$in, $elements], $k + sourceIndex$in - destinationIndex$in)) == ValueArrayGet($Heap[destinationArray$in, $elements], $k)) && (!(destinationIndex$in <= $k && $k < destinationIndex$in + length$in) ==> old(ValueArrayGet($Heap[destinationArray$in, $elements], $k)) == ValueArrayGet($Heap[destinationArray$in, $elements], $k)));
+ ensures (forall $k: int :: { IntArrayGet($Heap[destinationArray$in, $elements], $k) } (destinationIndex$in <= $k && $k < destinationIndex$in + length$in ==> old(IntArrayGet($Heap[sourceArray$in, $elements], $k + sourceIndex$in - destinationIndex$in)) == IntArrayGet($Heap[destinationArray$in, $elements], $k)) && (!(destinationIndex$in <= $k && $k < destinationIndex$in + length$in) ==> old(IntArrayGet($Heap[destinationArray$in, $elements], $k)) == IntArrayGet($Heap[destinationArray$in, $elements], $k)));
+ ensures (forall $k: int :: { RefArrayGet($Heap[destinationArray$in, $elements], $k) } (destinationIndex$in <= $k && $k < destinationIndex$in + length$in ==> old(RefArrayGet($Heap[sourceArray$in, $elements], $k + sourceIndex$in - destinationIndex$in)) == RefArrayGet($Heap[destinationArray$in, $elements], $k)) && (!(destinationIndex$in <= $k && $k < destinationIndex$in + length$in) ==> old(RefArrayGet($Heap[destinationArray$in, $elements], $k)) == RefArrayGet($Heap[destinationArray$in, $elements], $k)));
+ // newly allocated objects are fully valid
+ free ensures (forall $o: ref :: { $Heap[$o, $localinv] } { $Heap[$o, $inv] } $o != null && !old($Heap)[$o, $allocated] && $Heap[$o, $allocated] ==> $Heap[$o, $inv] == $typeof($o) && $Heap[$o, $localinv] == $typeof($o));
+ // first consistent owner unchanged if its exposeVersion is
+ free ensures (forall $o: ref :: { $Heap[$o, $FirstConsistentOwner] } old($Heap)[old($Heap)[$o, $FirstConsistentOwner], $exposeVersion] == $Heap[old($Heap)[$o, $FirstConsistentOwner], $exposeVersion] ==> old($Heap)[$o, $FirstConsistentOwner] == $Heap[$o, $FirstConsistentOwner]);
+ // frame condition
+ ensures (forall<a> $o: ref, $f: Field a :: { $Heap[$o, $f] } IncludeInMainFrameCondition($f) && $o != null && old($Heap)[$o, $allocated] && (old($Heap)[$o, $ownerFrame] == $PeerGroupPlaceholder || !(old($Heap)[old($Heap)[$o, $ownerRef], $inv] <: old($Heap)[$o, $ownerFrame]) || old($Heap)[old($Heap)[$o, $ownerRef], $localinv] == $BaseClass(old($Heap)[$o, $ownerFrame])) && old($o != destinationArray$in || !($typeof(destinationArray$in) <: DeclType222($f)) || !$IncludedInModifiesStar($f)) && old($o != destinationArray$in || $f != $exposeVersion) ==> old($Heap)[$o, $f] == $Heap[$o, $f]);
+ free ensures $HeapSucc(old($Heap), $Heap);
+ // inv/localinv change only in blocks
+ free ensures (forall $o: ref :: { $Heap[$o, $localinv] } { $Heap[$o, $inv] } old($Heap)[$o, $allocated] ==> old($Heap)[$o, $inv] == $Heap[$o, $inv] && old($Heap)[$o, $localinv] == $Heap[$o, $localinv]);
+ free ensures (forall $o: ref :: { $Heap[$o, $allocated] } old($Heap)[$o, $allocated] ==> $Heap[$o, $allocated]) && (forall $ot: ref :: { $Heap[$ot, $ownerFrame] } { $Heap[$ot, $ownerRef] } old($Heap)[$ot, $allocated] && old($Heap)[$ot, $ownerFrame] != $PeerGroupPlaceholder ==> $Heap[$ot, $ownerRef] == old($Heap)[$ot, $ownerRef] && $Heap[$ot, $ownerFrame] == old($Heap)[$ot, $ownerFrame]) && old($Heap)[$BeingConstructed, $NonNullFieldsAreInitialized] == $Heap[$BeingConstructed, $NonNullFieldsAreInitialized];
+ free ensures (forall $o: ref :: { $Heap[$o, $sharingMode] } old($Heap[$o, $sharingMode]) == $Heap[$o, $sharingMode]);
+
+
+
+axiom Microsoft.Contracts.ICheckedException <: Microsoft.Contracts.ICheckedException;
+
+axiom Microsoft.Contracts.ICheckedException <: System.Object;
+
+axiom $IsMemberlessType(Microsoft.Contracts.ICheckedException);
+
+axiom $AsInterface(Microsoft.Contracts.ICheckedException) == Microsoft.Contracts.ICheckedException;
+
+procedure Bag.AddAgain$System.Int32(this: ref where $IsNotNull(this, Bag) && $Heap[this, $allocated], x$in: int where InRange(x$in, System.Int32));
+ // target object is peer consistent
+ requires (forall $pc: ref :: { $typeof($pc) } { $Heap[$pc, $localinv] } { $Heap[$pc, $inv] } { $Heap[$pc, $ownerFrame] } { $Heap[$pc, $ownerRef] } $pc != null && $Heap[$pc, $allocated] && $Heap[$pc, $ownerRef] == $Heap[this, $ownerRef] && $Heap[$pc, $ownerFrame] == $Heap[this, $ownerFrame] ==> $Heap[$pc, $inv] == $typeof($pc) && $Heap[$pc, $localinv] == $typeof($pc));
+ // target object is peer consistent (owner must not be valid)
+ requires $Heap[this, $ownerFrame] == $PeerGroupPlaceholder || !($Heap[$Heap[this, $ownerRef], $inv] <: $Heap[this, $ownerFrame]) || $Heap[$Heap[this, $ownerRef], $localinv] == $BaseClass($Heap[this, $ownerFrame]);
+ free requires $BeingConstructed == null;
+ free requires $PurityAxiomsCanBeAssumed;
+ modifies $Heap, $ActivityIndicator;
+ // newly allocated objects are fully valid
+ free ensures (forall $o: ref :: { $Heap[$o, $localinv] } { $Heap[$o, $inv] } $o != null && !old($Heap)[$o, $allocated] && $Heap[$o, $allocated] ==> $Heap[$o, $inv] == $typeof($o) && $Heap[$o, $localinv] == $typeof($o));
+ // first consistent owner unchanged if its exposeVersion is
+ free ensures (forall $o: ref :: { $Heap[$o, $FirstConsistentOwner] } old($Heap)[old($Heap)[$o, $FirstConsistentOwner], $exposeVersion] == $Heap[old($Heap)[$o, $FirstConsistentOwner], $exposeVersion] ==> old($Heap)[$o, $FirstConsistentOwner] == $Heap[$o, $FirstConsistentOwner]);
+ // frame condition
+ ensures (forall<a> $o: ref, $f: Field a :: { $Heap[$o, $f] } IncludeInMainFrameCondition($f) && $o != null && old($Heap)[$o, $allocated] && (old($Heap)[$o, $ownerFrame] == $PeerGroupPlaceholder || !(old($Heap)[old($Heap)[$o, $ownerRef], $inv] <: old($Heap)[$o, $ownerFrame]) || old($Heap)[old($Heap)[$o, $ownerRef], $localinv] == $BaseClass(old($Heap)[$o, $ownerFrame])) && old($o != this || !($typeof(this) <: DeclType222($f)) || !$IncludedInModifiesStar($f)) && old($o != this || $f != $exposeVersion) ==> old($Heap)[$o, $f] == $Heap[$o, $f]);
+ free ensures $HeapSucc(old($Heap), $Heap);
+ // inv/localinv change only in blocks
+ free ensures (forall $o: ref :: { $Heap[$o, $localinv] } { $Heap[$o, $inv] } old($Heap)[$o, $allocated] ==> old($Heap)[$o, $inv] == $Heap[$o, $inv] && old($Heap)[$o, $localinv] == $Heap[$o, $localinv]);
+ free ensures (forall $o: ref :: { $Heap[$o, $allocated] } old($Heap)[$o, $allocated] ==> $Heap[$o, $allocated]) && (forall $ot: ref :: { $Heap[$ot, $ownerFrame] } { $Heap[$ot, $ownerRef] } old($Heap)[$ot, $allocated] && old($Heap)[$ot, $ownerFrame] != $PeerGroupPlaceholder ==> $Heap[$ot, $ownerRef] == old($Heap)[$ot, $ownerRef] && $Heap[$ot, $ownerFrame] == old($Heap)[$ot, $ownerFrame]) && old($Heap)[$BeingConstructed, $NonNullFieldsAreInitialized] == $Heap[$BeingConstructed, $NonNullFieldsAreInitialized];
+ free ensures (forall $o: ref :: { $Heap[$o, $sharingMode] } old($Heap[$o, $sharingMode]) == $Heap[$o, $sharingMode]);
+
+
+
+implementation Bag.AddAgain$System.Int32(this: ref, x$in: int)
+{
+ var x: int where InRange(x, System.Int32), temp0: ref, stack1s: struct, stack1o: ref, temp1: exposeVersionType, local2: ref where $Is(local2, System.Exception) && $Heap[local2, $allocated], stack0i: int, stack1i: int, stack0b: bool, stack0o: ref, local4: int where InRange(local4, System.Int32), temp2: exposeVersionType, b: ref where $Is(b, IntArray(System.Int32, 1)) && $Heap[b, $allocated], temp3: ref, stack2i: int, temp4: exposeVersionType, stack0s: struct;
+
+ entry:
+ x := x$in;
+ goto block6188;
+
+ block6188:
+ goto block6341;
+
+ block6341:
+ // ----- nop
+ // ----- FrameGuard processing ----- AddMethod.ssc(38,13)
+ temp0 := this;
+ // ----- load token ----- AddMethod.ssc(38,13)
+ havoc stack1s;
+ assume $IsTokenForType(stack1s, Bag);
+ // ----- statically resolved GetTypeFromHandle call ----- AddMethod.ssc(38,13)
+ stack1o := TypeObject(Bag);
+ // ----- local unpack ----- AddMethod.ssc(38,13)
+ assert temp0 != null;
+ assert ($Heap[temp0, $ownerFrame] == $PeerGroupPlaceholder || !($Heap[$Heap[temp0, $ownerRef], $inv] <: $Heap[temp0, $ownerFrame]) || $Heap[$Heap[temp0, $ownerRef], $localinv] == $BaseClass($Heap[temp0, $ownerFrame])) && $Heap[temp0, $inv] <: Bag && $Heap[temp0, $localinv] == $typeof(temp0);
+ $Heap[temp0, $localinv] := System.Object;
+ havoc temp1;
+ $Heap[temp0, $exposeVersion] := temp1;
+ assume IsHeap($Heap);
+ local2 := null;
+ goto block6358;
+
+ block6358:
+ // ----- load field ----- AddMethod.ssc(40,7)
+ assert this != null;
+ stack0i := $Heap[this, Bag.n];
+ // ----- load field ----- AddMethod.ssc(40,7)
+ assert this != null;
+ stack1o := $Heap[this, Bag.a];
+ // ----- unary operator ----- AddMethod.ssc(40,7)
+ assert stack1o != null;
+ stack1i := $Length(stack1o);
+ // ----- unary operator ----- AddMethod.ssc(40,7)
+ stack1i := $IntToInt(stack1i, System.UIntPtr, System.Int32);
+ // ----- binary operator ----- AddMethod.ssc(40,7)
+ // ----- branch ----- AddMethod.ssc(40,7)
+ goto true6358to6392, false6358to6375;
+
+ true6358to6392:
+ assume stack0i != stack1i;
+ goto block6392;
+
+ false6358to6375:
+ assume stack0i == stack1i;
+ goto block6375;
+
+ block6392:
+ // ----- load field ----- AddMethod.ssc(46,7)
+ assert this != null;
+ stack0o := $Heap[this, Bag.a];
+ // ----- load field ----- AddMethod.ssc(46,7)
+ assert this != null;
+ stack1i := $Heap[this, Bag.n];
+ // ----- store element ----- AddMethod.ssc(46,7)
+ assert stack0o != null;
+ assert 0 <= stack1i;
+ assert stack1i < $Length(stack0o);
+ assert $Heap[stack0o, $ownerFrame] == $PeerGroupPlaceholder || !($Heap[$Heap[stack0o, $ownerRef], $inv] <: $Heap[stack0o, $ownerFrame]) || $Heap[$Heap[stack0o, $ownerRef], $localinv] == $BaseClass($Heap[stack0o, $ownerFrame]);
+ $Heap[stack0o, $elements] := IntArraySet($Heap[stack0o, $elements], stack1i, x);
+ assume IsHeap($Heap);
+ // ----- load field ----- AddMethod.ssc(47,7)
+ assert this != null;
+ local4 := $Heap[this, Bag.n];
+ // ----- load constant 1 ----- AddMethod.ssc(47,7)
+ stack0i := 1;
+ // ----- binary operator ----- AddMethod.ssc(47,7)
+ stack0i := local4 + stack0i;
+ // ----- store field ----- AddMethod.ssc(47,7)
+ assert this != null;
+ assert $Heap[this, $ownerFrame] == $PeerGroupPlaceholder || !($Heap[$Heap[this, $ownerRef], $inv] <: $Heap[this, $ownerFrame]) || $Heap[$Heap[this, $ownerRef], $localinv] == $BaseClass($Heap[this, $ownerFrame]);
+ havoc temp2;
+ $Heap[this, $exposeVersion] := temp2;
+ $Heap[this, Bag.n] := stack0i;
+ assert !($Heap[this, $inv] <: Bag && $Heap[this, $localinv] != $BaseClass(Bag)) || 0 <= $Heap[this, Bag.n];
+ assert !($Heap[this, $inv] <: Bag && $Heap[this, $localinv] != $BaseClass(Bag)) || $Heap[this, Bag.n] <= $Length($Heap[this, Bag.a]);
+ assume IsHeap($Heap);
+ // ----- copy
+ stack0i := local4;
+ // ----- branch
+ goto block6562;
+
+ block6375:
+ // ----- load constant 2 ----- AddMethod.ssc(42,15)
+ stack0i := 2;
+ // ----- load field ----- AddMethod.ssc(42,15)
+ assert this != null;
+ stack1o := $Heap[this, Bag.a];
+ // ----- unary operator ----- AddMethod.ssc(42,15)
+ assert stack1o != null;
+ stack1i := $Length(stack1o);
+ // ----- unary operator ----- AddMethod.ssc(42,15)
+ stack1i := $IntToInt(stack1i, System.UIntPtr, System.Int32);
+ // ----- binary operator ----- AddMethod.ssc(42,15)
+ stack0i := stack0i * stack1i;
+ // ----- load constant 1 ----- AddMethod.ssc(42,15)
+ stack1i := 1;
+ // ----- binary operator ----- AddMethod.ssc(42,15)
+ stack0i := stack0i + stack1i;
+ // ----- new array ----- AddMethod.ssc(42,15)
+ assert 0 <= stack0i;
+ havoc temp3;
+ assume $Heap[temp3, $allocated] == false && $Length(temp3) == stack0i;
+ assume $Heap[$ElementProxy(temp3, -1), $allocated] == false && $ElementProxy(temp3, -1) != temp3 && $ElementProxy(temp3, -1) != null;
+ assume temp3 != null;
+ assume $typeof(temp3) == IntArray(System.Int32, 1);
+ assume $Heap[temp3, $ownerRef] == temp3 && $Heap[temp3, $ownerFrame] == $PeerGroupPlaceholder;
+ assume $Heap[$ElementProxy(temp3, -1), $ownerRef] == $ElementProxy(temp3, -1) && $Heap[$ElementProxy(temp3, -1), $ownerFrame] == $PeerGroupPlaceholder;
+ assume $Heap[temp3, $inv] == $typeof(temp3) && $Heap[temp3, $localinv] == $typeof(temp3);
+ assume (forall $i: int :: IntArrayGet($Heap[temp3, $elements], $i) == 0);
+ $Heap[temp3, $allocated] := true;
+ call System.Object..ctor($ElementProxy(temp3, -1));
+ b := temp3;
+ assume IsHeap($Heap);
+ // ----- load field ----- AddMethod.ssc(43,9)
+ assert this != null;
+ stack0o := $Heap[this, Bag.a];
+ // ----- copy ----- AddMethod.ssc(43,9)
+ stack1o := b;
+ // ----- load constant 0 ----- AddMethod.ssc(43,9)
+ stack2i := 0;
+ // ----- call ----- AddMethod.ssc(43,9)
+ assert stack0o != null;
+ call System.Array.CopyTo$System.Array$notnull$System.Int32$.Virtual.$(stack0o, stack1o, stack2i);
+ // ----- store field ----- AddMethod.ssc(44,9)
+ assert this != null;
+ assert $Heap[this, $ownerFrame] == $PeerGroupPlaceholder || !($Heap[$Heap[this, $ownerRef], $inv] <: $Heap[this, $ownerFrame]) || $Heap[$Heap[this, $ownerRef], $localinv] == $BaseClass($Heap[this, $ownerFrame]);
+ assert ($Heap[b, $ownerRef] == this && $Heap[b, $ownerFrame] == Bag) || $Heap[b, $ownerFrame] == $PeerGroupPlaceholder;
+ assert $Heap[b, $ownerFrame] == $PeerGroupPlaceholder && $Heap[this, $inv] <: Bag && $Heap[this, $localinv] != $BaseClass(Bag) ==> (forall $pc: ref :: { $typeof($pc) } { $Heap[$pc, $localinv] } { $Heap[$pc, $inv] } { $Heap[$pc, $ownerFrame] } { $Heap[$pc, $ownerRef] } $pc != null && $Heap[$pc, $allocated] && $Heap[$pc, $ownerRef] == $Heap[b, $ownerRef] && $Heap[$pc, $ownerFrame] == $Heap[b, $ownerFrame] ==> $Heap[$pc, $inv] == $typeof($pc) && $Heap[$pc, $localinv] == $typeof($pc));
+ assert $Heap[b, $ownerFrame] == $PeerGroupPlaceholder && $Heap[this, $inv] <: Bag && $Heap[this, $localinv] != $BaseClass(Bag) ==> $Heap[this, $ownerRef] != $Heap[b, $ownerRef] || $Heap[this, $ownerFrame] != $Heap[b, $ownerFrame];
+ call $UpdateOwnersForRep(this, Bag, b);
+ havoc temp4;
+ $Heap[this, $exposeVersion] := temp4;
+ $Heap[this, Bag.a] := b;
+ assert !($Heap[this, $inv] <: Bag && $Heap[this, $localinv] != $BaseClass(Bag)) || 0 <= $Heap[this, Bag.n];
+ assert !($Heap[this, $inv] <: Bag && $Heap[this, $localinv] != $BaseClass(Bag)) || $Heap[this, Bag.n] <= $Length($Heap[this, Bag.a]);
+ assume IsHeap($Heap);
+ goto block6392;
+
+ block6562:
+ stack0o := null;
+ // ----- binary operator
+ // ----- branch
+ goto true6562to6477, false6562to6579;
+
+ true6562to6477:
+ assume local2 == stack0o;
+ goto block6477;
+
+ false6562to6579:
+ assume local2 != stack0o;
+ goto block6579;
+
+ block6477:
+ // ----- load token ----- AddMethod.ssc(48,5)
+ havoc stack0s;
+ assume $IsTokenForType(stack0s, Bag);
+ // ----- statically resolved GetTypeFromHandle call ----- AddMethod.ssc(48,5)
+ stack0o := TypeObject(Bag);
+ // ----- local pack ----- AddMethod.ssc(48,5)
+ assert temp0 != null;
+ assert $Heap[temp0, $localinv] == System.Object;
+ assert 0 <= $Heap[temp0, Bag.n];
+ assert $Heap[temp0, Bag.n] <= $Length($Heap[temp0, Bag.a]);
+ assert (forall $p: ref :: $p != null && $Heap[$p, $allocated] && $Heap[$p, $ownerRef] == temp0 && $Heap[$p, $ownerFrame] == Bag ==> $Heap[$p, $inv] == $typeof($p) && $Heap[$p, $localinv] == $typeof($p));
+ $Heap[temp0, $localinv] := $typeof(temp0);
+ assume IsHeap($Heap);
+ goto block6545;
+
+ block6579:
+ // ----- is instance
+ // ----- branch
+ goto true6579to6477, false6579to6528;
+
+ true6579to6477:
+ assume $As(local2, Microsoft.Contracts.ICheckedException) != null;
+ goto block6477;
+
+ false6579to6528:
+ assume $As(local2, Microsoft.Contracts.ICheckedException) == null;
+ goto block6528;
+
+ block6528:
+ // ----- branch
+ goto block6545;
+
+ block6545:
+ // ----- nop
+ // ----- branch
+ goto block6443;
+
+ block6443:
+ // ----- return
+ return;
+}
+
+
+
+procedure Bag..cctor();
+ free requires $BeingConstructed == null;
+ free requires $PurityAxiomsCanBeAssumed;
+ modifies $Heap, $ActivityIndicator;
+ // newly allocated objects are fully valid
+ free ensures (forall $o: ref :: { $Heap[$o, $localinv] } { $Heap[$o, $inv] } $o != null && !old($Heap)[$o, $allocated] && $Heap[$o, $allocated] ==> $Heap[$o, $inv] == $typeof($o) && $Heap[$o, $localinv] == $typeof($o));
+ // first consistent owner unchanged if its exposeVersion is
+ free ensures (forall $o: ref :: { $Heap[$o, $FirstConsistentOwner] } old($Heap)[old($Heap)[$o, $FirstConsistentOwner], $exposeVersion] == $Heap[old($Heap)[$o, $FirstConsistentOwner], $exposeVersion] ==> old($Heap)[$o, $FirstConsistentOwner] == $Heap[$o, $FirstConsistentOwner]);
+ // frame condition
+ ensures (forall<a> $o: ref, $f: Field a :: { $Heap[$o, $f] } IncludeInMainFrameCondition($f) && $o != null && old($Heap)[$o, $allocated] && (old($Heap)[$o, $ownerFrame] == $PeerGroupPlaceholder || !(old($Heap)[old($Heap)[$o, $ownerRef], $inv] <: old($Heap)[$o, $ownerFrame]) || old($Heap)[old($Heap)[$o, $ownerRef], $localinv] == $BaseClass(old($Heap)[$o, $ownerFrame])) && old(true) && old(true) ==> old($Heap)[$o, $f] == $Heap[$o, $f]);
+ free ensures $HeapSucc(old($Heap), $Heap);
+ // inv/localinv change only in blocks
+ free ensures (forall $o: ref :: { $Heap[$o, $localinv] } { $Heap[$o, $inv] } old($Heap)[$o, $allocated] ==> old($Heap)[$o, $inv] == $Heap[$o, $inv] && old($Heap)[$o, $localinv] == $Heap[$o, $localinv]);
+ free ensures (forall $o: ref :: { $Heap[$o, $allocated] } old($Heap)[$o, $allocated] ==> $Heap[$o, $allocated]) && (forall $ot: ref :: { $Heap[$ot, $ownerFrame] } { $Heap[$ot, $ownerRef] } old($Heap)[$ot, $allocated] && old($Heap)[$ot, $ownerFrame] != $PeerGroupPlaceholder ==> $Heap[$ot, $ownerRef] == old($Heap)[$ot, $ownerRef] && $Heap[$ot, $ownerFrame] == old($Heap)[$ot, $ownerFrame]) && old($Heap)[$BeingConstructed, $NonNullFieldsAreInitialized] == $Heap[$BeingConstructed, $NonNullFieldsAreInitialized];
+ free ensures (forall $o: ref :: { $Heap[$o, $sharingMode] } old($Heap[$o, $sharingMode]) == $Heap[$o, $sharingMode]);
+
+
+
+implementation Bag..cctor()
+{
+
+ entry:
+ goto block7650;
+
+ block7650:
+ goto block7701;
+
+ block7701:
+ // ----- nop
+ // ----- return
+ return;
+}
+
+
diff --git a/Test/test7/Answer b/Test/test7/Answer
new file mode 100644
index 00000000..82c84446
--- /dev/null
+++ b/Test/test7/Answer
@@ -0,0 +1,64 @@
+------------------------------ NestedVC.bpl ---------------------
+NestedVC.bpl(15,4): Error BP5001: This assertion might not hold.
+Execution trace:
+ NestedVC.bpl(14,1): A
+ NestedVC.bpl(15,1): B
+
+Boogie program verifier finished with 1 verified, 1 error
+------------------------------ UnreachableBlocks.bpl ---------------------
+
+Boogie program verifier finished with 4 verified, 0 errors
+------------------------------ MultipleErrors.bpl ---------------------
+
+----- /vc:block
+MultipleErrors.bpl(7,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ MultipleErrors.bpl(3,1): start
+ MultipleErrors.bpl(6,1): A
+
+Boogie program verifier finished with 0 verified, 1 error
+
+----- /vc:local
+MultipleErrors.bpl(11,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ MultipleErrors.bpl(10,1): B
+
+Boogie program verifier finished with 0 verified, 1 error
+
+----- /vc:dag
+MultipleErrors.bpl(7,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ MultipleErrors.bpl(3,1): start
+ MultipleErrors.bpl(6,1): A
+
+Boogie program verifier finished with 0 verified, 1 error
+
+----- /errorLimit:10 /vc:local
+MultipleErrors.bpl(7,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ MultipleErrors.bpl(6,1): A
+MultipleErrors.bpl(11,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ MultipleErrors.bpl(10,1): B
+MultipleErrors.bpl(15,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ MultipleErrors.bpl(14,1): C
+
+Boogie program verifier finished with 0 verified, 3 errors
+
+----- /errorLimit:10 /vc:dag
+MultipleErrors.bpl(7,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ MultipleErrors.bpl(3,1): start
+ MultipleErrors.bpl(6,1): A
+MultipleErrors.bpl(11,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ MultipleErrors.bpl(3,1): start
+ MultipleErrors.bpl(10,1): B
+MultipleErrors.bpl(15,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ MultipleErrors.bpl(3,1): start
+ MultipleErrors.bpl(6,1): A
+ MultipleErrors.bpl(14,1): C
+
+Boogie program verifier finished with 0 verified, 3 errors
diff --git a/Test/test7/MultipleErrors.bpl b/Test/test7/MultipleErrors.bpl
new file mode 100644
index 00000000..5a2024d4
--- /dev/null
+++ b/Test/test7/MultipleErrors.bpl
@@ -0,0 +1,17 @@
+procedure P(x: int)
+{
+start:
+ goto A, B;
+
+A:
+ assert 0 <= x;
+ goto C;
+
+B:
+ assert x < 100;
+ goto C;
+
+C:
+ assert x == 87;
+ return;
+}
diff --git a/Test/test7/NestedVC.bpl b/Test/test7/NestedVC.bpl
new file mode 100644
index 00000000..d88eefea
--- /dev/null
+++ b/Test/test7/NestedVC.bpl
@@ -0,0 +1,21 @@
+procedure P()
+{
+A: goto B, C;
+B: goto G;
+C: goto D, E;
+D: goto F;
+E: goto F;
+F: goto G;
+G: return;
+}
+
+procedure Q(x: bool)
+{
+A: goto B, C;
+B: assert x; goto G;
+C: goto D, E;
+D: goto F;
+E: goto F;
+F: goto G;
+G: return;
+}
diff --git a/Test/test7/Output b/Test/test7/Output
new file mode 100644
index 00000000..82c84446
--- /dev/null
+++ b/Test/test7/Output
@@ -0,0 +1,64 @@
+------------------------------ NestedVC.bpl ---------------------
+NestedVC.bpl(15,4): Error BP5001: This assertion might not hold.
+Execution trace:
+ NestedVC.bpl(14,1): A
+ NestedVC.bpl(15,1): B
+
+Boogie program verifier finished with 1 verified, 1 error
+------------------------------ UnreachableBlocks.bpl ---------------------
+
+Boogie program verifier finished with 4 verified, 0 errors
+------------------------------ MultipleErrors.bpl ---------------------
+
+----- /vc:block
+MultipleErrors.bpl(7,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ MultipleErrors.bpl(3,1): start
+ MultipleErrors.bpl(6,1): A
+
+Boogie program verifier finished with 0 verified, 1 error
+
+----- /vc:local
+MultipleErrors.bpl(11,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ MultipleErrors.bpl(10,1): B
+
+Boogie program verifier finished with 0 verified, 1 error
+
+----- /vc:dag
+MultipleErrors.bpl(7,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ MultipleErrors.bpl(3,1): start
+ MultipleErrors.bpl(6,1): A
+
+Boogie program verifier finished with 0 verified, 1 error
+
+----- /errorLimit:10 /vc:local
+MultipleErrors.bpl(7,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ MultipleErrors.bpl(6,1): A
+MultipleErrors.bpl(11,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ MultipleErrors.bpl(10,1): B
+MultipleErrors.bpl(15,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ MultipleErrors.bpl(14,1): C
+
+Boogie program verifier finished with 0 verified, 3 errors
+
+----- /errorLimit:10 /vc:dag
+MultipleErrors.bpl(7,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ MultipleErrors.bpl(3,1): start
+ MultipleErrors.bpl(6,1): A
+MultipleErrors.bpl(11,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ MultipleErrors.bpl(3,1): start
+ MultipleErrors.bpl(10,1): B
+MultipleErrors.bpl(15,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ MultipleErrors.bpl(3,1): start
+ MultipleErrors.bpl(6,1): A
+ MultipleErrors.bpl(14,1): C
+
+Boogie program verifier finished with 0 verified, 3 errors
diff --git a/Test/test7/UnreachableBlocks.bpl b/Test/test7/UnreachableBlocks.bpl
new file mode 100644
index 00000000..6ed287a3
--- /dev/null
+++ b/Test/test7/UnreachableBlocks.bpl
@@ -0,0 +1,40 @@
+// In the following program, block "A" has no dominator, which would cause Boogie
+// to crash if Boogie didn't first remove unreachable blocks. That is essentially
+// what this test tests
+procedure P()
+{
+entry:
+ goto A;
+A:
+ return;
+B:
+ goto A;
+}
+
+procedure Q()
+{
+entry:
+ goto entry, A;
+A:
+ return;
+}
+
+procedure R()
+{
+entry:
+ return;
+A:
+ goto A;
+}
+
+procedure S()
+{
+entry:
+ return;
+A:
+ goto C;
+B:
+ goto C;
+C: // C has no dominator
+ return;
+}
diff --git a/Test/test7/runtest.bat b/Test/test7/runtest.bat
new file mode 100644
index 00000000..8da87233
--- /dev/null
+++ b/Test/test7/runtest.bat
@@ -0,0 +1,34 @@
+@echo off
+setlocal
+
+set BOOGIEDIR=..\..\Binaries
+set BGEXE=%BOOGIEDIR%\Boogie.exe
+
+echo ------------------------------ NestedVC.bpl ---------------------
+%BGEXE% %* /vc:nested NestedVC.bpl
+
+echo ------------------------------ UnreachableBlocks.bpl ---------------------
+%BGEXE% %* /vc:nested UnreachableBlocks.bpl
+
+echo ------------------------------ MultipleErrors.bpl ---------------------
+rem The following tests are rather fickle at the moment--different errors
+rem may be reported during different runs. Moreover, it is conceivable that
+rem the error trace would be reported in different orders, since we do not
+rem attempt to sort the trace labels at this time.
+rem An interesting thing is that /vc:local can with Simplify report more than one
+rem error for this file, even with /errorLimit:1. Other than that, only
+rem local and dag produce VCs to which Simplify actually produces different
+rem counterexamples.
+
+setlocal
+for %%f in (block local dag) do (
+ echo.
+ echo ----- /vc:%%f
+ %BGEXE% %* /errorLimit:1 /errorTrace:1 /vc:%%f /logPrefix:-1%%f MultipleErrors.bpl
+)
+for %%f in (local dag) do (
+ echo.
+ echo ----- /errorLimit:10 /vc:%%f
+ %BGEXE% %* /errorLimit:10 /errorTrace:1 /vc:%%f /logPrefix:-10%%f MultipleErrors.bpl
+)
+endlocal
diff --git a/Test/textbook/Answer b/Test/textbook/Answer
new file mode 100644
index 00000000..9e2227dc
--- /dev/null
+++ b/Test/textbook/Answer
@@ -0,0 +1,12 @@
+
+------------------------------ Find.bpl ---------------------
+
+Boogie program verifier finished with 2 verified, 0 errors
+
+------------------------------ DutchFlag.bpl ---------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
+
+------------------------------ Bubble.bpl ---------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
diff --git a/Test/textbook/Bubble.bpl b/Test/textbook/Bubble.bpl
new file mode 100644
index 00000000..51a8cefa
--- /dev/null
+++ b/Test/textbook/Bubble.bpl
@@ -0,0 +1,66 @@
+// Bubble sort, where specification says the output is a permutation of its input
+// Rustan Leino, 30 April 2009
+
+const N: int;
+axiom 0 <= N;
+
+var a: [int]int;
+
+procedure BubbleSort() returns (perm: [int]int)
+ modifies a;
+ // array is sorted
+ ensures (forall i, j: int :: 0 <= i && i <= j && j < N ==> a[i] <= a[j]);
+ // perm is a permutation
+ ensures (forall i: int :: 0 <= i && i < N ==> 0 <= perm[i] && perm[i] < N);
+ ensures (forall i, j: int :: 0 <= i && i < j && j < N ==> perm[i] != perm[j]);
+ // the final array is that permutation of the input array
+ ensures (forall i: int :: 0 <= i && i < N ==> a[i] == old(a)[perm[i]]);
+{
+ var n, p, tmp: int;
+
+ n := 0;
+ while (n < N)
+ invariant n <= N;
+ invariant (forall i: int :: 0 <= i && i < n ==> perm[i] == i);
+ {
+ perm[n] := n;
+ n := n + 1;
+ }
+
+ while (true)
+ invariant 0 <= n && n <= N;
+ // array is sorted from n onwards
+ invariant (forall i, k: int :: n <= i && i < N && 0 <= k && k < i ==> a[k] <= a[i]);
+ // perm is a permutation
+ invariant (forall i: int :: 0 <= i && i < N ==> 0 <= perm[i] && perm[i] < N);
+ invariant (forall i, j: int :: 0 <= i && i < j && j < N ==> perm[i] != perm[j]);
+ // the current array is that permutation of the input array
+ invariant (forall i: int :: 0 <= i && i < N ==> a[i] == old(a)[perm[i]]);
+ {
+ n := n - 1;
+ if (n < 0) {
+ break;
+ }
+
+ p := 0;
+ while (p < n)
+ invariant p <= n;
+ // array is sorted from n+1 onwards
+ invariant (forall i, k: int :: n+1 <= i && i < N && 0 <= k && k < i ==> a[k] <= a[i]);
+ // perm is a permutation
+ invariant (forall i: int :: 0 <= i && i < N ==> 0 <= perm[i] && perm[i] < N);
+ invariant (forall i, j: int :: 0 <= i && i < j && j < N ==> perm[i] != perm[j]);
+ // the current array is that permutation of the input array
+ invariant (forall i: int :: 0 <= i && i < N ==> a[i] == old(a)[perm[i]]);
+ // a[p] is at least as large as any of the first p elements
+ invariant (forall k: int :: 0 <= k && k < p ==> a[k] <= a[p]);
+ {
+ if (a[p+1] < a[p]) {
+ tmp := a[p]; a[p] := a[p+1]; a[p+1] := tmp;
+ tmp := perm[p]; perm[p] := perm[p+1]; perm[p+1] := tmp;
+ }
+
+ p := p + 1;
+ }
+ }
+}
diff --git a/Test/textbook/DutchFlag.bpl b/Test/textbook/DutchFlag.bpl
new file mode 100644
index 00000000..34065b7d
--- /dev/null
+++ b/Test/textbook/DutchFlag.bpl
@@ -0,0 +1,62 @@
+
+var A: [int]int;
+const N: int;
+
+procedure Partition(l: int, r: int) returns (result: int)
+ requires 0 <= l && l+2 <= r && r <= N;
+ modifies A;
+ ensures l <= result && result < r;
+ ensures (forall k: int, j: int :: l <= k && k < result && result <= j && j < r ==> A[k] <= A[j]);
+ ensures (forall k: int :: l <= k && k < result ==> A[k] <= old(A)[l]);
+ ensures (forall k: int :: result <= k && k < r ==> old(A)[l] <= A[k]);
+{
+ var pv: int;
+ var i: int;
+ var j: int;
+ var tmp: int;
+
+ start:
+ pv := A[l];
+ i := l;
+ j := r-1;
+ // swap A[l] and A[j]
+ tmp := A[l];
+ A[l] := A[j];
+ A[j] := tmp;
+ goto LoopHead;
+
+ LoopHead:
+ assert (forall k: int :: l <= k && k < i ==> A[k] <= pv);
+ assert (forall k: int :: j <= k && k < r ==> pv <= A[k]);
+ assert l <= i && i <= j && j < r;
+ goto A, B, C, exit;
+
+ A:
+ assume i < j;
+ assume A[i] <= pv;
+ i := i + 1;
+ goto LoopHead;
+
+ B:
+ assume i < j;
+ assume pv <= A[j-1];
+ j := j - 1;
+ goto LoopHead;
+
+ C:
+ assume i < j;
+ assume A[j-1] < pv && pv < A[i];
+ // swap A[j-1] and A[i]
+ tmp := A[i];
+ A[i] := A[j-1];
+ A[j-1] := tmp;
+ assert A[i] < pv && pv < A[j-1];
+ i := i + 1;
+ j := j - 1;
+ goto LoopHead;
+
+ exit:
+ assume i == j;
+ result := i;
+ return;
+}
diff --git a/Test/textbook/Find.bpl b/Test/textbook/Find.bpl
new file mode 100644
index 00000000..d84209e1
--- /dev/null
+++ b/Test/textbook/Find.bpl
@@ -0,0 +1,39 @@
+// This program is featured in KRML 168, the Marktoberdorf lecture notes
+// "A verifying compiler for a multi-threaded object-oriented language" by
+// Leino and Schulte.
+
+const K: int;
+function f(int) returns (int);
+axiom (exists k: int :: f(k) == K);
+
+procedure Find(a: int, b: int) returns (k: int);
+ requires a <= b;
+ requires (forall j: int :: a < j && j < b ==> f(j) != K);
+ ensures f(k) == K;
+
+implementation Find(a: int, b: int) returns (k: int)
+{
+ entry:
+ goto A, B, C;
+
+ A:
+ assume f(a) == K; k := a;
+ return;
+
+ B:
+ assume f(b) == K; k := b;
+ return;
+
+ C:
+ assume f(a) != K && f(b) != K;
+ call k := Find(a-1, b+1);
+ return;
+}
+
+procedure Main() returns (k: int)
+ ensures f(k) == K;
+{
+ entry:
+ call k := Find(0, 0);
+ return;
+}
diff --git a/Test/textbook/Output b/Test/textbook/Output
new file mode 100644
index 00000000..9e2227dc
--- /dev/null
+++ b/Test/textbook/Output
@@ -0,0 +1,12 @@
+
+------------------------------ Find.bpl ---------------------
+
+Boogie program verifier finished with 2 verified, 0 errors
+
+------------------------------ DutchFlag.bpl ---------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
+
+------------------------------ Bubble.bpl ---------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
diff --git a/Test/textbook/runtest.bat b/Test/textbook/runtest.bat
new file mode 100644
index 00000000..6e39e589
--- /dev/null
+++ b/Test/textbook/runtest.bat
@@ -0,0 +1,13 @@
+@echo off
+
+set BOOGIEDIR=..\..\Binaries
+set BPLEXE=%BOOGIEDIR%\Boogie.exe
+
+REM ======================
+REM ====================== Examples written in Boogie
+REM ======================
+for %%f in (Find.bpl DutchFlag.bpl Bubble.bpl) do (
+ echo.
+ echo ------------------------------ %%f ---------------------
+ %BPLEXE% %* %%f
+)
diff --git a/Test/z3api/Answer b/Test/z3api/Answer
new file mode 100644
index 00000000..782aa852
--- /dev/null
+++ b/Test/z3api/Answer
@@ -0,0 +1,187 @@
+
+-------------------- boog0.bpl --------------------
+boog0.bpl(51,1): Error BP5003: A postcondition might not hold at this return statement.
+boog0.bpl(45,3): Related location: This is the postcondition that might not hold.
+Execution trace:
+ boog0.bpl(48,7): anon0
+
+Boogie program verifier finished with 1 verified, 1 error
+
+-------------------- boog1.bpl --------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
+
+-------------------- boog2.bpl --------------------
+boog2.bpl(23,1): Error BP5003: A postcondition might not hold at this return statement.
+boog2.bpl(19,3): Related location: This is the postcondition that might not hold.
+Execution trace:
+ boog2.bpl(22,8): anon0
+
+Boogie program verifier finished with 1 verified, 1 error
+
+-------------------- boog3.bpl --------------------
+boog3.bpl(6,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ boog3.bpl(6,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+
+-------------------- boog4.bpl --------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
+
+-------------------- boog5.bpl --------------------
+boog5.bpl(36,3): Error BP5003: A postcondition might not hold at this return statement.
+boog5.bpl(29,3): Related location: This is the postcondition that might not hold.
+Execution trace:
+ boog5.bpl(32,3): anon0
+ boog5.bpl(35,13): anon3_Else
+
+Boogie program verifier finished with 0 verified, 1 error
+
+-------------------- boog6.bpl --------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
+
+-------------------- boog7.bpl --------------------
+boog7.bpl(17,1): Error BP5003: A postcondition might not hold at this return statement.
+boog7.bpl(13,3): Related location: This is the postcondition that might not hold.
+Execution trace:
+ boog7.bpl(16,11): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+
+-------------------- boog8.bpl --------------------
+boog8.bpl(7,12): Error: no bitvector handling specified, please use /bv:i or /bv:z flag
+boog8.bpl(7,18): Error: no bitvector handling specified, please use /bv:i or /bv:z flag
+2 type checking errors detected in boog8.bpl
+
+-------------------- boog9.bpl --------------------
+boog9.bpl(19,1): Error BP5003: A postcondition might not hold at this return statement.
+boog9.bpl(15,3): Related location: This is the postcondition that might not hold.
+Execution trace:
+ boog9.bpl(18,11): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+
+-------------------- boog10.bpl --------------------
+boog10.bpl(18,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ boog10.bpl(18,3): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+
+-------------------- boog11.bpl --------------------
+boog11.bpl(14,1): Error BP5003: A postcondition might not hold at this return statement.
+boog11.bpl(10,3): Related location: This is the postcondition that might not hold.
+Execution trace:
+ boog11.bpl(13,8): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+
+-------------------- boog12.bpl --------------------
+boog12.bpl(18,1): Error BP5003: A postcondition might not hold at this return statement.
+boog12.bpl(13,3): Related location: This is the postcondition that might not hold.
+Execution trace:
+ boog12.bpl(16,16): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+
+-------------------- boog13.bpl --------------------
+boog13.bpl(9,11): Error: more than one declaration of variable name: v
+1 name resolution errors detected in boog13.bpl
+
+-------------------- boog14.bpl --------------------
+boog14.bpl(11,1): Error BP5003: A postcondition might not hold at this return statement.
+boog14.bpl(8,1): Related location: This is the postcondition that might not hold.
+Execution trace:
+ boog14.bpl(10,8): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+
+-------------------- boog15.bpl --------------------
+boog15.bpl(10,1): Error BP5003: A postcondition might not hold at this return statement.
+boog15.bpl(7,1): Related location: This is the postcondition that might not hold.
+Execution trace:
+ boog15.bpl(9,8): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+
+-------------------- boog16.bpl --------------------
+boog16.bpl(11,1): Error BP5003: A postcondition might not hold at this return statement.
+boog16.bpl(8,1): Related location: This is the postcondition that might not hold.
+Execution trace:
+ boog16.bpl(10,8): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+
+-------------------- boog17.bpl --------------------
+boog17.bpl(24,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ boog17.bpl(15,1): start
+ boog17.bpl(19,1): label_3
+ boog17.bpl(22,1): label_4
+
+Boogie program verifier finished with 0 verified, 1 error
+
+-------------------- boog18.bpl --------------------
+boog18.bpl(15,1): Error BP5003: A postcondition might not hold at this return statement.
+boog18.bpl(12,1): Related location: This is the postcondition that might not hold.
+Execution trace:
+ boog18.bpl(14,4): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+
+-------------------- boog19.bpl --------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
+
+-------------------- boog20.bpl --------------------
+boog20.bpl(15,1): Error BP5001: This assertion might not hold.
+Execution trace:
+ boog20.bpl(15,1): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+
+-------------------- boog21.bpl --------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
+
+-------------------- boog22.bpl --------------------
+boog22.bpl(4,9): Error: more than one declaration of function/procedure name: f1
+1 name resolution errors detected in boog22.bpl
+
+-------------------- boog23.bpl --------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
+
+-------------------- boog24.bpl --------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
+
+-------------------- boog25.bpl --------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
+
+-------------------- boog28.bpl --------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
+
+-------------------- boog29.bpl --------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
+
+-------------------- boog30.bpl --------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
+
+-------------------- boog31.bpl --------------------
+boog31.bpl(12,1): Error BP5001: This assertion might not hold.
+Execution trace:
+ boog31.bpl(12,1): anon0
+
+Boogie program verifier finished with 0 verified, 1 error
+
+-------------------- boog34.bpl --------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
diff --git a/Test/z3api/Boog24.bpl b/Test/z3api/Boog24.bpl
new file mode 100644
index 00000000..c5e2eea6
--- /dev/null
+++ b/Test/z3api/Boog24.bpl
@@ -0,0 +1,16 @@
+
+function LIFT(a:bool) returns (int);
+axiom(forall a:bool :: {LIFT(a)} a <==> LIFT(a) != 0);
+
+procedure main ( )
+
+{
+var a : int;
+var b : int;
+var c : int;
+
+c := LIFT (b < a) ;
+assert (c != 0 <==> b < a);
+
+}
+
diff --git a/Test/z3api/boog0.bpl b/Test/z3api/boog0.bpl
new file mode 100644
index 00000000..1b9bee36
--- /dev/null
+++ b/Test/z3api/boog0.bpl
@@ -0,0 +1,48 @@
+type Wicket;
+const w: Wicket;
+var favorite: Wicket;
+function age(Wicket) returns (int);
+
+axiom age(w)==7;
+
+procedure NewFavorite(p: Wicket);
+ modifies favorite ;
+
+ ensures favorite==p;
+
+implementation NewFavorite(l: Wicket) {
+ favorite:=l;
+}
+
+const myBool: bool;
+const myRef: ref;
+const v: Wicket;
+
+axiom 7 < 8;
+axiom 7 <= 8;
+axiom 8 > 7;
+axiom 8 >= 7;
+axiom 6 != 7;
+
+axiom 7+1==8;
+axiom 8-1==7;
+axiom 7/1==7;
+axiom 7%2==1;
+axiom 4*2==8;
+
+axiom ((7==7) || (8==8));
+axiom ((7==7) ==> (7<8));
+axiom ((7==7) <==> (10==10));
+axiom ((7==7) && (8==8));
+
+var favorite2: Wicket;
+procedure SwapFavorites()
+ modifies favorite,favorite2 ;
+
+ ensures (favorite==old(favorite2)) && (favorite2==old(favorite));
+{
+ var temp: Wicket;
+ temp:=favorite;
+ favorite:=favorite2;
+ // favorite2:=temp; // commenting this line seeds a bug
+}
diff --git a/Test/z3api/boog1.bpl b/Test/z3api/boog1.bpl
new file mode 100644
index 00000000..6b6cce75
--- /dev/null
+++ b/Test/z3api/boog1.bpl
@@ -0,0 +1,16 @@
+type Wicket;
+const w: Wicket;
+var favorite: Wicket;
+
+function age(Wicket) returns (int);
+
+axiom age(w)==7;
+
+procedure NewFavorite(p: Wicket);
+ modifies favorite ;
+
+ ensures favorite==p;
+
+implementation NewFavorite(l: Wicket) {
+ favorite:=l;
+} \ No newline at end of file
diff --git a/Test/z3api/boog10.bpl b/Test/z3api/boog10.bpl
new file mode 100644
index 00000000..5ac43287
--- /dev/null
+++ b/Test/z3api/boog10.bpl
@@ -0,0 +1,22 @@
+// types
+type Color;
+const unique red: Color;
+const unique blue: Color;
+const unique green: Color;
+
+axiom (forall ce:Color :: ce==red || ce==blue || ce==green);
+var myColor: Color;
+
+// procedure
+procedure SetTo(c: Color);
+ modifies myColor ;
+
+ ensures myColor==c;
+
+implementation SetTo(c: Color) {
+ assert (blue==green);
+ myColor:=blue;
+}
+
+
+
diff --git a/Test/z3api/boog11.bpl b/Test/z3api/boog11.bpl
new file mode 100644
index 00000000..e66802ea
--- /dev/null
+++ b/Test/z3api/boog11.bpl
@@ -0,0 +1,16 @@
+// types
+const top: ref;
+var myRef: ref;
+
+// procedure
+procedure SetTo(r: ref);
+ modifies myRef ;
+
+ ensures myRef==r;
+
+implementation SetTo(c: ref) {
+ myRef:=top;
+}
+
+
+
diff --git a/Test/z3api/boog12.bpl b/Test/z3api/boog12.bpl
new file mode 100644
index 00000000..d20a8f35
--- /dev/null
+++ b/Test/z3api/boog12.bpl
@@ -0,0 +1,20 @@
+// types
+type Color;
+const blue: Color;
+
+var myArray:[int] Color;
+var myMatrix:[int,int] Color;
+
+// procedure
+procedure SetTo(c: Color);
+ modifies myArray, myMatrix ;
+
+ ensures myArray[0]==c;
+
+implementation SetTo(c: Color) {
+ myMatrix[0,1]:=c;
+ myArray[0]:=blue;
+}
+
+
+
diff --git a/Test/z3api/boog13.bpl b/Test/z3api/boog13.bpl
new file mode 100644
index 00000000..a4f854f5
--- /dev/null
+++ b/Test/z3api/boog13.bpl
@@ -0,0 +1,25 @@
+// types
+type Wicket;
+var favorite: Wicket;
+var v: Wicket;
+
+function age(w:Wicket) returns (int);
+
+axiom (exists v:Wicket :: age(v)<8 &&
+ (forall v:Wicket :: age(v)==7)
+
+ );
+
+
+// procedure
+procedure SetToSeven(p: Wicket);
+ modifies favorite ;
+
+ ensures favorite==p;
+
+implementation SetToSeven(l: Wicket) {
+ favorite:=favorite;
+}
+
+
+
diff --git a/Test/z3api/boog14.bpl b/Test/z3api/boog14.bpl
new file mode 100644
index 00000000..c163ed18
--- /dev/null
+++ b/Test/z3api/boog14.bpl
@@ -0,0 +1,11 @@
+function choose(a:bool, b:int, c:int) returns (x:int);
+axiom(forall a:bool, b:int, c:int :: {choose(a,b,c)} a ==> choose(a,b,c) == b);
+
+
+var myInt:int;
+procedure main()
+modifies myInt;
+ensures myInt==5;
+{
+ myInt:=4;
+} \ No newline at end of file
diff --git a/Test/z3api/boog15.bpl b/Test/z3api/boog15.bpl
new file mode 100644
index 00000000..ef792b2b
--- /dev/null
+++ b/Test/z3api/boog15.bpl
@@ -0,0 +1,10 @@
+function AtLeast(int, int) returns ([int]bool);
+axiom(forall n:int, x:int :: {AtLeast(n,x)} AtLeast(n,x)[x]);
+
+var myInt:int;
+procedure main()
+modifies myInt;
+ensures myInt==5;
+{
+ myInt:=4;
+} \ No newline at end of file
diff --git a/Test/z3api/boog16.bpl b/Test/z3api/boog16.bpl
new file mode 100644
index 00000000..48afd41d
--- /dev/null
+++ b/Test/z3api/boog16.bpl
@@ -0,0 +1,11 @@
+function choose(a:bool, b:int, c:int) returns (x:int);
+axiom(forall a:bool, b:int, c:int ::
+ {choose(a,b,c)} !a ==> choose(a,b,c) == c);
+
+var myInt:int;
+procedure main()
+modifies myInt;
+ensures myInt==5;
+{
+ myInt:=4;
+} \ No newline at end of file
diff --git a/Test/z3api/boog17.bpl b/Test/z3api/boog17.bpl
new file mode 100644
index 00000000..6f886f49
--- /dev/null
+++ b/Test/z3api/boog17.bpl
@@ -0,0 +1,25 @@
+const unique g : int;
+axiom(g != 0);
+
+const unique PINT4_name:name;
+
+function PLUS(a:int, a_size:int, b:int) returns (int);
+axiom(forall a:int, a_size:int, b:int :: {PLUS(a,a_size,b)} PLUS(a,a_size,b) == a + a_size * b);
+
+function HasType(v:int, t:name) returns (bool);
+
+
+procedure main ( ) returns ($result.main$11.5$1$:int) {
+ var p : int;
+
+start:
+ assume(HasType(p, PINT4_name));
+ goto label_3;
+
+label_3:
+ goto label_4;
+
+label_4:
+ p := PLUS(g, 4, 55) ;
+ assert(HasType(p, PINT4_name));
+} \ No newline at end of file
diff --git a/Test/z3api/boog18.bpl b/Test/z3api/boog18.bpl
new file mode 100644
index 00000000..fe0cbc10
--- /dev/null
+++ b/Test/z3api/boog18.bpl
@@ -0,0 +1,15 @@
+const A100INT4_name:int;
+
+function Match(a:int, t:int) returns (int);
+function Array(int, int, int) returns (bool);
+
+axiom(forall a:int :: {Match(a, A100INT4_name)} Array(a, 4, 100));
+
+const myNull: int;
+var p: int;
+procedure main()
+modifies p;
+ensures p!=myNull;
+{
+ p:=myNull;
+} \ No newline at end of file
diff --git a/Test/z3api/boog19.bpl b/Test/z3api/boog19.bpl
new file mode 100644
index 00000000..17b199dd
--- /dev/null
+++ b/Test/z3api/boog19.bpl
@@ -0,0 +1,228 @@
+var alloc:[int]name;
+
+
+function Field(int) returns (name);
+function Base(int) returns (int);
+
+// Constants
+const unique UNALLOCATED:name;
+const unique ALLOCATED: name;
+const unique FREED:name;
+
+const unique BYTE:name;
+
+function Equal([int]bool, [int]bool) returns (bool);
+function Subset([int]bool, [int]bool) returns (bool);
+function Disjoint([int]bool, [int]bool) returns (bool);
+
+function Empty() returns ([int]bool);
+function Singleton(int) returns ([int]bool);
+function Reachable([int,int]bool, int) returns ([int]bool);
+function Union([int]bool, [int]bool) returns ([int]bool);
+function Intersection([int]bool, [int]bool) returns ([int]bool);
+function Difference([int]bool, [int]bool) returns ([int]bool);
+function Dereference([int]bool, [int]int) returns ([int]bool);
+function Inverse(f:[int]int, x:int) returns ([int]bool);
+
+function AtLeast(int, int) returns ([int]bool);
+function Rep(int, int) returns (int);
+axiom(forall n:int, x:int, y:int :: {AtLeast(n,x)[y]} AtLeast(n,x)[y] ==> x <= y && Rep(n,x) == Rep(n,y));
+axiom(forall n:int, x:int, y:int :: {AtLeast(n,x),Rep(n,x),Rep(n,y)} x <= y && Rep(n,x) == Rep(n,y) ==> AtLeast(n,x)[y]);
+axiom(forall n:int, x:int :: {AtLeast(n,x)} AtLeast(n,x)[x]);
+axiom(forall n:int, x:int, z:int :: {PLUS(x,n,z)} Rep(n,x) == Rep(n,PLUS(x,n,z)));
+axiom(forall n:int, x:int :: {Rep(n,x)} (exists k:int :: Rep(n,x) - x == n*k));
+
+
+function Array(int, int, int) returns ([int]bool);
+axiom(forall x:int, n:int, z:int :: {Array(x,n,z)} z <= 0 ==> Equal(Array(x,n,z), Empty()));
+axiom(forall x:int, n:int, z:int :: {Array(x,n,z)} z > 0 ==> Equal(Array(x,n,z), Difference(AtLeast(n,x),AtLeast(n,PLUS(x,n,z)))));
+
+
+axiom(forall x:int :: !Empty()[x]);
+
+axiom(forall x:int, y:int :: {Singleton(y)[x]} Singleton(y)[x] <==> x == y);
+axiom(forall y:int :: {Singleton(y)} Singleton(y)[y]);
+
+/* this formulation of Union IS more complete than the earlier one */
+/* (A U B)[e], A[d], A U B = Singleton(c), d != e */
+axiom(forall x:int, S:[int]bool, T:[int]bool :: {Union(S,T)[x]} Union(S,T)[x] <==> S[x] || T[x]);
+axiom(forall x:int, S:[int]bool, T:[int]bool :: {Union(S,T), S[x]} S[x] ==> Union(S,T)[x]);
+axiom(forall x:int, S:[int]bool, T:[int]bool :: {Union(S,T), T[x]} T[x] ==> Union(S,T)[x]);
+
+axiom(forall x:int, S:[int]bool, T:[int]bool :: {Intersection(S,T)[x]} Intersection(S,T)[x] <==> S[x] && T[x]);
+axiom(forall x:int, S:[int]bool, T:[int]bool :: {Intersection(S,T), S[x]} S[x] && T[x] ==> Intersection(S,T)[x]);
+axiom(forall x:int, S:[int]bool, T:[int]bool :: {Intersection(S,T), T[x]} S[x] && T[x] ==> Intersection(S,T)[x]);
+
+axiom(forall x:int, S:[int]bool, T:[int]bool :: {Difference(S,T)[x]} Difference(S,T)[x] <==> S[x] && !T[x]);
+axiom(forall x:int, S:[int]bool, T:[int]bool :: {Difference(S,T), S[x]} S[x] ==> Difference(S,T)[x] || T[x]);
+
+axiom(forall x:int, S:[int]bool, M:[int]int :: {Dereference(S,M)[x]} Dereference(S,M)[x] ==> (exists y:int :: x == M[y] && S[y]));
+axiom(forall x:int, S:[int]bool, M:[int]int :: {M[x], S[x], Dereference(S,M)} S[x] ==> Dereference(S,M)[M[x]]);
+axiom(forall x:int, y:int, S:[int]bool, M:[int]int :: {Dereference(S,M[x := y])} !S[x] ==> Equal(Dereference(S,M[x := y]), Dereference(S,M)));
+axiom(forall x:int, y:int, S:[int]bool, M:[int]int :: {Dereference(S,M[x := y])}
+ S[x] && Equal(Intersection(Inverse(M,M[x]), S), Singleton(x)) ==> Equal(Dereference(S,M[x := y]), Union(Difference(Dereference(S,M), Singleton(M[x])), Singleton(y))));
+axiom(forall x:int, y:int, S:[int]bool, M:[int]int :: {Dereference(S,M[x := y])}
+ S[x] && !Equal(Intersection(Inverse(M,M[x]), S), Singleton(x)) ==> Equal(Dereference(S,M[x := y]), Union(Dereference(S,M), Singleton(y))));
+
+axiom(forall f:[int]int, x:int :: {Inverse(f,f[x])} Inverse(f,f[x])[x]);
+axiom(forall f:[int]int, x:int, y:int :: {Inverse(f[x := y],y)} Equal(Inverse(f[x := y],y), Union(Inverse(f,y), Singleton(x))));
+axiom(forall f:[int]int, x:int, y:int, z:int :: {Inverse(f[x := y],z)} y == z || Equal(Inverse(f[x := y],z), Difference(Inverse(f,z), Singleton(x))));
+
+axiom(forall S:[int]bool, T:[int]bool :: {Equal(S,T)} Equal(S,T) <==> Subset(S,T) && Subset(T,S));
+axiom(forall x:int, S:[int]bool, T:[int]bool :: {S[x], Subset(S,T)} S[x] && Subset(S,T) ==> T[x]);
+axiom(forall S:[int]bool, T:[int]bool :: {Subset(S,T)} Subset(S,T) || (exists x:int :: S[x] && !T[x]));
+axiom(forall x:int, S:[int]bool, T:[int]bool :: {S[x], Disjoint(S,T), T[x]} !(S[x] && Disjoint(S,T) && T[x]));
+axiom(forall S:[int]bool, T:[int]bool :: {Disjoint(S,T)} Disjoint(S,T) || (exists x:int :: S[x] && T[x]));
+
+function Unified([name][int]int) returns ([int]int);
+axiom(forall M:[name][int]int, x:int :: {Unified(M)[x]} Unified(M)[x] == M[Field(x)][x]);
+axiom(forall M:[name][int]int, x:int, y:int :: {Unified(M[Field(x) := M[Field(x)][x := y]])} Unified(M[Field(x) := M[Field(x)][x := y]]) == Unified(M)[x := y]);
+// Memory model
+
+var Mem: [name][int]int;
+
+function Match(a:int, t:name) returns (bool);
+function HasType(v:int, t:name) returns (bool);
+function Values(t:name) returns ([int]bool);
+
+axiom(forall v:int, t:name :: {Values(t)[v]} Values(t)[v] ==> HasType(v, t));
+axiom(forall v:int, t:name :: {HasType(v, t), Values(t)} HasType(v, t) ==> Values(t)[v]);
+
+// Field declarations
+
+
+// Type declarations
+
+const unique A100INT4_name:name;
+const unique INT4_name:name;
+const unique PA100INT4_name:name;
+const unique PINT4_name:name;
+const unique PPINT4_name:name;
+
+// Field definitions
+
+// Type definitions
+
+axiom(forall a:int :: {Match(a, A100INT4_name)} Subset(Empty(), Array(a, 4, 100)));
+axiom(forall a:int, e:int :: {Match(a, A100INT4_name), Array(a, 4, 100)[e]}
+ Match(a, A100INT4_name) && Array(a, 4, 100)[e] ==> Match(e, INT4_name));
+
+axiom(forall a:int :: {Match(a, INT4_name)}
+ Match(a, INT4_name) <==> Field(a) == INT4_name);
+axiom(forall v:int :: HasType(v, INT4_name));
+
+axiom(forall a:int :: {Match(a, PA100INT4_name)}
+ Match(a, PA100INT4_name) <==> Field(a) == PA100INT4_name);
+axiom(forall v:int :: {HasType(v, PA100INT4_name)} {Match(v, A100INT4_name)}
+ HasType(v, PA100INT4_name) <==> (v == 0 || (v > 0 && Match(v, A100INT4_name))));
+
+axiom(forall a:int :: {Match(a, PINT4_name)}
+ Match(a, PINT4_name) <==> Field(a) == PINT4_name);
+axiom(forall v:int :: {HasType(v, PINT4_name)} {Match(v, INT4_name)}
+ HasType(v, PINT4_name) <==> (v == 0 || (v > 0 && Match(v, INT4_name))));
+
+axiom(forall a:int :: {Match(a, PPINT4_name)}
+ Match(a, PPINT4_name) <==> Field(a) == PPINT4_name);
+axiom(forall v:int :: {HasType(v, PPINT4_name)} {Match(v, PINT4_name)}
+ HasType(v, PPINT4_name) <==> (v == 0 || (v > 0 && Match(v, PINT4_name))));
+
+function MINUS_BOTH_PTR_OR_BOTH_INT(a:int, b:int, size:int) returns (int);
+axiom(forall a:int, b:int, size:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(a,b,size)}
+size * MINUS_BOTH_PTR_OR_BOTH_INT(a,b,size) <= a - b && a - b < size * (MINUS_BOTH_PTR_OR_BOTH_INT(a,b,size) + 1));
+
+function MINUS_LEFT_PTR(a:int, a_size:int, b:int) returns (int);
+axiom(forall a:int, a_size:int, b:int :: {MINUS_LEFT_PTR(a,a_size,b)} MINUS_LEFT_PTR(a,a_size,b) == a - a_size * b);
+
+function PLUS(a:int, a_size:int, b:int) returns (int);
+axiom(forall a:int, a_size:int, b:int :: {PLUS(a,a_size,b)} PLUS(a,a_size,b) == a + a_size * b);
+
+function MULT(a:int, b:int) returns (int); // a*b
+axiom(forall a:int, b:int :: {MULT(a,b)} MULT(a,b) == a * b);
+
+function DIV(a:int, b:int) returns (int); // a/b
+
+axiom(forall a:int, b:int :: {DIV(a,b)}
+a >= 0 && b > 0 ==> b * DIV(a,b) <= a && a < b * (DIV(a,b) + 1)
+);
+
+axiom(forall a:int, b:int :: {DIV(a,b)}
+a >= 0 && b < 0 ==> b * DIV(a,b) <= a && a < b * (DIV(a,b) - 1)
+);
+
+axiom(forall a:int, b:int :: {DIV(a,b)}
+a < 0 && b > 0 ==> b * DIV(a,b) >= a && a > b * (DIV(a,b) - 1)
+);
+
+axiom(forall a:int, b:int :: {DIV(a,b)}
+a < 0 && b < 0 ==> b * DIV(a,b) >= a && a > b * (DIV(a,b) + 1)
+);
+
+function BINARY_BOTH_INT(a:int, b:int) returns (int);
+/*
+function POW2(a:int) returns (bool);
+axiom POW2(1);
+axiom POW2(2);
+axiom POW2(4);
+axiom POW2(8);
+axiom POW2(16);
+axiom POW2(32);
+axiom POW2(64);
+axiom POW2(128);
+axiom POW2(256);
+axiom POW2(512);
+axiom POW2(1024);
+axiom POW2(2048);
+axiom POW2(4096);
+axiom POW2(8192);
+axiom POW2(16384);
+axiom POW2(32768);
+axiom POW2(65536);
+axiom POW2(131072);
+axiom POW2(262144);
+axiom POW2(524288);
+axiom POW2(1048576);
+axiom POW2(2097152);
+axiom POW2(4194304);
+axiom POW2(8388608);
+axiom POW2(16777216);
+axiom POW2(33554432);
+*/
+function LIFT(a:bool) returns (int);
+axiom(forall a:bool :: {LIFT(a)} a <==> LIFT(a) != 0);
+
+function NOT(a:int) returns (int);
+axiom(forall a:int :: {NOT(a)} a == 0 ==> NOT(a) != 0);
+axiom(forall a:int :: {NOT(a)} a != 0 ==> NOT(a) == 0);
+
+function NULL_CHECK(a:int) returns (int);
+axiom(forall a:int :: {NULL_CHECK(a)} a == 0 ==> NULL_CHECK(a) != 0);
+axiom(forall a:int :: {NULL_CHECK(a)} a != 0 ==> NULL_CHECK(a) == 0);
+
+const unique g : int;
+axiom(g != 0);
+
+
+procedure main ( ) returns ($result.main$11.5$1$:int)
+
+//TAG: requires __objectOf(g) != 0
+requires(Base(g) != 0);
+
+//TAG: requires __allocated(g)
+requires(alloc[Base(g)] == ALLOCATED);
+
+//TAG: requires __allocated(g + 55)
+requires(alloc[Base(PLUS(g, 4, 55))] == ALLOCATED);
+
+//TAG: Type Safety Precondition
+requires(forall a:int :: {Mem[Field(a)][a]} HasType(Mem[Field(a)][a], Field(a)));
+requires(HasType(g, PA100INT4_name));
+
+{
+var p : int;
+
+assume(HasType(p, PINT4_name));
+p := PLUS(g, 4, 55) ;
+assert(HasType(p, PINT4_name));
+
+}
+
diff --git a/Test/z3api/boog2.bpl b/Test/z3api/boog2.bpl
new file mode 100644
index 00000000..74c05a28
--- /dev/null
+++ b/Test/z3api/boog2.bpl
@@ -0,0 +1,22 @@
+type Wicket;
+
+var favorite: Wicket;
+var hate: Wicket;
+
+procedure NewFavorite(p: Wicket);
+ modifies favorite ;
+
+ ensures favorite==p;
+
+implementation NewFavorite(l: Wicket) {
+ favorite:=l;
+}
+
+
+procedure Swap();
+ modifies favorite,hate;
+ ensures favorite==old(hate);
+
+implementation Swap() {
+ hate := favorite;
+} \ No newline at end of file
diff --git a/Test/z3api/boog20.bpl b/Test/z3api/boog20.bpl
new file mode 100644
index 00000000..fa714972
--- /dev/null
+++ b/Test/z3api/boog20.bpl
@@ -0,0 +1,17 @@
+
+function PLUS(int, int, int) returns (int);
+function Rep(int, int) returns (int);
+
+//PLUS(a,b,z)
+// ERROR
+
+axiom(forall a:int, b:int, z:int :: Rep(a,b) == Rep(a,0));
+axiom(forall n:int, x:int :: {Rep(n,x)} (exists k:int :: Rep(n,x) == x));
+// END ERROR
+
+
+procedure main ( )
+{
+assert (PLUS(0, 4, 55)!=0);
+}
+
diff --git a/Test/z3api/boog21.bpl b/Test/z3api/boog21.bpl
new file mode 100644
index 00000000..1f4fa6dc
--- /dev/null
+++ b/Test/z3api/boog21.bpl
@@ -0,0 +1,17 @@
+
+function PLUS(int, int, int) returns (int);
+function Rep(int,int) returns (int);
+
+
+// ERROR
+
+axiom(forall a:int, b:int, z:int :: Rep(a,b) == PLUS(a,b,z ));
+axiom(forall n:int, x:int :: {Rep(n,x)} (exists k:int :: Rep(n,x) == x));
+// END ERROR
+
+
+procedure main ( )
+{
+assert (PLUS(0, 4, 55)!=0);
+}
+
diff --git a/Test/z3api/boog22.bpl b/Test/z3api/boog22.bpl
new file mode 100644
index 00000000..95e45849
--- /dev/null
+++ b/Test/z3api/boog22.bpl
@@ -0,0 +1,10 @@
+type W;
+
+function f1(W,int) returns (int);
+function f1(W,int,int) returns (int);
+
+procedure main()
+{
+ var w: W;
+ assert(f1(w,0)==f1(w,0,0));
+} \ No newline at end of file
diff --git a/Test/z3api/boog23.bpl b/Test/z3api/boog23.bpl
new file mode 100644
index 00000000..41c68790
--- /dev/null
+++ b/Test/z3api/boog23.bpl
@@ -0,0 +1,410 @@
+type byte;
+function OneByteToInt(byte) returns (int);
+function TwoBytesToInt(byte, byte) returns (int);
+function FourBytesToInt(byte, byte, byte, byte) returns (int);
+axiom(forall b0:byte, c0:byte :: {OneByteToInt(b0), OneByteToInt(c0)} OneByteToInt(b0) == OneByteToInt(c0) ==> b0 == c0);
+axiom(forall b0:byte, b1: byte, c0:byte, c1:byte :: {TwoBytesToInt(b0, b1), TwoBytesToInt(c0, c1)} TwoBytesToInt(b0, b1) == TwoBytesToInt(c0, c1) ==> b0 == c0 && b1 == c1);
+axiom(forall b0:byte, b1: byte, b2:byte, b3:byte, c0:byte, c1:byte, c2:byte, c3:byte :: {FourBytesToInt(b0, b1, b2, b3), FourBytesToInt(c0, c1, c2, c3)} FourBytesToInt(b0, b1, b2, b3) == FourBytesToInt(c0, c1, c2, c3) ==> b0 == c0 && b1 == c1 && b2 == c2 && b3 == c3);
+
+// Mutable
+var Mem_BYTE:[int]byte;
+var alloc:[int]name;
+
+
+function Field(int) returns (name);
+function Base(int) returns (int);
+
+// Constants
+const unique UNALLOCATED:name;
+const unique ALLOCATED: name;
+const unique FREED:name;
+
+const unique BYTE:name;
+
+function Equal([int]bool, [int]bool) returns (bool);
+function Subset([int]bool, [int]bool) returns (bool);
+function Disjoint([int]bool, [int]bool) returns (bool);
+
+function Empty() returns ([int]bool);
+function Singleton(int) returns ([int]bool);
+function Reachable([int,int]bool, int) returns ([int]bool);
+function Union([int]bool, [int]bool) returns ([int]bool);
+function Intersection([int]bool, [int]bool) returns ([int]bool);
+function Difference([int]bool, [int]bool) returns ([int]bool);
+function Dereference([int]bool, [int]int) returns ([int]bool);
+function Inverse(f:[int]int, x:int) returns ([int]bool);
+
+function AtLeast(int, int) returns ([int]bool);
+function Rep(int, int) returns (int);
+axiom(forall n:int, x:int, y:int :: {AtLeast(n,x)[y]} AtLeast(n,x)[y] ==> x <= y && Rep(n,x) == Rep(n,y));
+axiom(forall n:int, x:int, y:int :: {AtLeast(n,x),Rep(n,x),Rep(n,y)} x <= y && Rep(n,x) == Rep(n,y) ==> AtLeast(n,x)[y]);
+axiom(forall n:int, x:int :: {AtLeast(n,x)} AtLeast(n,x)[x]);
+axiom(forall n:int, x:int, z:int :: {PLUS(x,n,z)} Rep(n,x) == Rep(n,PLUS(x,n,z)));
+axiom(forall n:int, x:int :: {Rep(n,x)} (exists k:int :: Rep(n,x) - x == n*k));
+
+function Array(int, int, int) returns ([int]bool);
+axiom(forall x:int, n:int, z:int :: {Array(x,n,z)} z <= 0 ==> Equal(Array(x,n,z), Empty()));
+axiom(forall x:int, n:int, z:int :: {Array(x,n,z)} z > 0 ==> Equal(Array(x,n,z), Difference(AtLeast(n,x),AtLeast(n,PLUS(x,n,z)))));
+
+
+axiom(forall x:int :: !Empty()[x]);
+
+axiom(forall x:int, y:int :: {Singleton(y)[x]} Singleton(y)[x] <==> x == y);
+axiom(forall y:int :: {Singleton(y)} Singleton(y)[y]);
+
+/* this formulation of Union IS more complete than the earlier one */
+/* (A U B)[e], A[d], A U B = Singleton(c), d != e */
+axiom(forall x:int, S:[int]bool, T:[int]bool :: {Union(S,T)[x]} Union(S,T)[x] <==> S[x] || T[x]);
+axiom(forall x:int, S:[int]bool, T:[int]bool :: {Union(S,T), S[x]} S[x] ==> Union(S,T)[x]);
+axiom(forall x:int, S:[int]bool, T:[int]bool :: {Union(S,T), T[x]} T[x] ==> Union(S,T)[x]);
+
+axiom(forall x:int, S:[int]bool, T:[int]bool :: {Intersection(S,T)[x]} Intersection(S,T)[x] <==> S[x] && T[x]);
+axiom(forall x:int, S:[int]bool, T:[int]bool :: {Intersection(S,T), S[x]} S[x] && T[x] ==> Intersection(S,T)[x]);
+axiom(forall x:int, S:[int]bool, T:[int]bool :: {Intersection(S,T), T[x]} S[x] && T[x] ==> Intersection(S,T)[x]);
+
+axiom(forall x:int, S:[int]bool, T:[int]bool :: {Difference(S,T)[x]} Difference(S,T)[x] <==> S[x] && !T[x]);
+axiom(forall x:int, S:[int]bool, T:[int]bool :: {Difference(S,T), S[x]} S[x] ==> Difference(S,T)[x] || T[x]);
+
+axiom(forall x:int, S:[int]bool, M:[int]int :: {Dereference(S,M)[x]} Dereference(S,M)[x] ==> (exists y:int :: x == M[y] && S[y]));
+axiom(forall x:int, S:[int]bool, M:[int]int :: {M[x], S[x], Dereference(S,M)} S[x] ==> Dereference(S,M)[M[x]]);
+axiom(forall x:int, y:int, S:[int]bool, M:[int]int :: {Dereference(S,M[x := y])} !S[x] ==> Equal(Dereference(S,M[x := y]), Dereference(S,M)));
+axiom(forall x:int, y:int, S:[int]bool, M:[int]int :: {Dereference(S,M[x := y])}
+ S[x] && Equal(Intersection(Inverse(M,M[x]), S), Singleton(x)) ==> Equal(Dereference(S,M[x := y]), Union(Difference(Dereference(S,M), Singleton(M[x])), Singleton(y))));
+axiom(forall x:int, y:int, S:[int]bool, M:[int]int :: {Dereference(S,M[x := y])}
+ S[x] && !Equal(Intersection(Inverse(M,M[x]), S), Singleton(x)) ==> Equal(Dereference(S,M[x := y]), Union(Dereference(S,M), Singleton(y))));
+
+axiom(forall f:[int]int, x:int :: {Inverse(f,f[x])} Inverse(f,f[x])[x]);
+axiom(forall f:[int]int, x:int, y:int :: {Inverse(f[x := y],y)} Equal(Inverse(f[x := y],y), Union(Inverse(f,y), Singleton(x))));
+axiom(forall f:[int]int, x:int, y:int, z:int :: {Inverse(f[x := y],z)} y == z || Equal(Inverse(f[x := y],z), Difference(Inverse(f,z), Singleton(x))));
+
+axiom(forall S:[int]bool, T:[int]bool :: {Equal(S,T)} Equal(S,T) <==> Subset(S,T) && Subset(T,S));
+axiom(forall x:int, S:[int]bool, T:[int]bool :: {S[x], Subset(S,T)} S[x] && Subset(S,T) ==> T[x]);
+axiom(forall S:[int]bool, T:[int]bool :: {Subset(S,T)} Subset(S,T) || (exists x:int :: S[x] && !T[x]));
+axiom(forall x:int, S:[int]bool, T:[int]bool :: {S[x], Disjoint(S,T), T[x]} !(S[x] && Disjoint(S,T) && T[x]));
+axiom(forall S:[int]bool, T:[int]bool :: {Disjoint(S,T)} Disjoint(S,T) || (exists x:int :: S[x] && T[x]));
+
+function Unified([name][int]int) returns ([int]int);
+axiom(forall M:[name][int]int, x:int :: {Unified(M)[x]} Unified(M)[x] == M[Field(x)][x]);
+axiom(forall M:[name][int]int, x:int, y:int :: {Unified(M[Field(x) := M[Field(x)][x := y]])} Unified(M[Field(x) := M[Field(x)][x := y]]) == Unified(M)[x := y]);
+// Memory model
+
+var Mem: [name][int]int;
+
+function Match(a:int, t:name) returns (bool);
+function HasType(v:int, t:name) returns (bool);
+function Values(t:name) returns ([int]bool);
+
+axiom(forall v:int, t:name :: {Values(t)[v]} Values(t)[v] ==> HasType(v, t));
+axiom(forall v:int, t:name :: {HasType(v, t), Values(t)} HasType(v, t) ==> Values(t)[v]);
+
+// Field declarations
+
+
+// Type declarations
+
+const unique INT4_name:name;
+const unique PINT4_name:name;
+
+// Field definitions
+
+// Type definitions
+
+axiom(forall a:int :: {Match(a, INT4_name)}
+ Match(a, INT4_name) <==> Field(a) == INT4_name);
+axiom(forall v:int :: HasType(v, INT4_name));
+
+axiom(forall a:int :: {Match(a, PINT4_name)}
+ Match(a, PINT4_name) <==> Field(a) == PINT4_name);
+axiom(forall v:int :: {HasType(v, PINT4_name)} {Match(v, INT4_name)}
+ HasType(v, PINT4_name) <==> (v == 0 || (v > 0 && Match(v, INT4_name))));
+
+function MINUS_BOTH_PTR_OR_BOTH_INT(a:int, b:int, size:int) returns (int);
+axiom(forall a:int, b:int, size:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(a,b,size)}
+size * MINUS_BOTH_PTR_OR_BOTH_INT(a,b,size) <= a - b && a - b < size * (MINUS_BOTH_PTR_OR_BOTH_INT(a,b,size) + 1));
+
+function MINUS_LEFT_PTR(a:int, a_size:int, b:int) returns (int);
+axiom(forall a:int, a_size:int, b:int :: {MINUS_LEFT_PTR(a,a_size,b)} MINUS_LEFT_PTR(a,a_size,b) == a - a_size * b);
+
+function PLUS(a:int, a_size:int, b:int) returns (int);
+axiom(forall a:int, a_size:int, b:int :: {PLUS(a,a_size,b)} PLUS(a,a_size,b) == a + a_size * b);
+
+function MULT(a:int, b:int) returns (int); // a*b
+axiom(forall a:int, b:int :: {MULT(a,b)} MULT(a,b) == a * b);
+
+function DIV(a:int, b:int) returns (int); // a/b
+
+axiom(forall a:int, b:int :: {DIV(a,b)}
+a >= 0 && b > 0 ==> b * DIV(a,b) <= a && a < b * (DIV(a,b) + 1)
+);
+
+axiom(forall a:int, b:int :: {DIV(a,b)}
+a >= 0 && b < 0 ==> b * DIV(a,b) <= a && a < b * (DIV(a,b) - 1)
+);
+
+axiom(forall a:int, b:int :: {DIV(a,b)}
+a < 0 && b > 0 ==> b * DIV(a,b) >= a && a > b * (DIV(a,b) - 1)
+);
+
+axiom(forall a:int, b:int :: {DIV(a,b)}
+a < 0 && b < 0 ==> b * DIV(a,b) >= a && a > b * (DIV(a,b) + 1)
+);
+
+function BINARY_BOTH_INT(a:int, b:int) returns (int);
+
+function POW2(a:int) returns (bool);
+axiom POW2(1);
+axiom POW2(2);
+axiom POW2(4);
+axiom POW2(8);
+axiom POW2(16);
+axiom POW2(32);
+axiom POW2(64);
+axiom POW2(128);
+axiom POW2(256);
+axiom POW2(512);
+axiom POW2(1024);
+axiom POW2(2048);
+axiom POW2(4096);
+axiom POW2(8192);
+axiom POW2(16384);
+axiom POW2(32768);
+axiom POW2(65536);
+axiom POW2(131072);
+axiom POW2(262144);
+axiom POW2(524288);
+axiom POW2(1048576);
+axiom POW2(2097152);
+axiom POW2(4194304);
+axiom POW2(8388608);
+axiom POW2(16777216);
+axiom POW2(33554432);
+
+function choose(a:bool, b:int, c:int) returns (x:int);
+axiom(forall a:bool, b:int, c:int :: {choose(a,b,c)} a ==> choose(a,b,c) == b);
+axiom(forall a:bool, b:int, c:int :: {choose(a,b,c)} !a ==> choose(a,b,c) == c);
+
+function BIT_BAND(a:int, b:int) returns (x:int);
+axiom(forall a:int, b:int :: {BIT_BAND(a,b)} a == b ==> BIT_BAND(a,b) == a);
+axiom(forall a:int, b:int :: {BIT_BAND(a,b)} POW2(a) && POW2(b) && a != b ==> BIT_BAND(a,b) == 0);
+axiom(forall a:int, b:int :: {BIT_BAND(a,b)} a == 0 || b == 0 ==> BIT_BAND(a,b) == 0);
+
+function BIT_BOR(a:int, b:int) returns (x:int);
+
+function BIT_BXOR(a:int, b:int) returns (x:int);
+
+function BIT_BNOT(a:int) returns (int);
+
+function LIFT(a:bool) returns (int);
+axiom(forall a:bool :: {LIFT(a)} a <==> LIFT(a) != 0);
+
+function NOT(a:int) returns (int);
+axiom(forall a:int :: {NOT(a)} a == 0 ==> NOT(a) != 0);
+axiom(forall a:int :: {NOT(a)} a != 0 ==> NOT(a) == 0);
+
+function NULL_CHECK(a:int) returns (int);
+axiom(forall a:int :: {NULL_CHECK(a)} a == 0 ==> NULL_CHECK(a) != 0);
+axiom(forall a:int :: {NULL_CHECK(a)} a != 0 ==> NULL_CHECK(a) == 0);
+
+procedure nondet_choice() returns (x:int);
+
+
+procedure havoc_assert(i:int);
+requires (i != 0);
+
+procedure havoc_assume(i:int);
+ensures (i != 0);
+
+procedure __HAVOC_free(a:int);
+modifies alloc;
+ensures (forall x:int :: {alloc[x]} x == a || old(alloc)[x] == alloc[x]);
+ensures (alloc[a] == FREED);
+// Additional checks guarded by tranlator flags
+// requires alloc[a] == ALLOCATED;
+// requires Base(a) == a;
+
+procedure __HAVOC_malloc(obj_size:int) returns (new:int);
+requires obj_size >= 0;
+modifies alloc;
+ensures (new > 0);
+ensures (forall x:int :: {Base(x)} new <= x && x < new+obj_size ==> Base(x) == new);
+ensures (forall x:int :: {alloc[x]} x == new || old(alloc)[x] == alloc[x]);
+ensures old(alloc)[new] == UNALLOCATED && alloc[new] == ALLOCATED;
+
+procedure _strdup(str:int) returns (new:int);
+
+procedure _xstrcasecmp(a0:int, a1:int) returns (ret:int);
+
+procedure _xstrcmp(a0:int, a1:int) returns (ret:int);
+
+
+
+
+
+procedure main ( ) returns ($result.main$3.5$1$:int)
+
+modifies alloc;
+//TAG: no freed locations
+ensures(forall f:int :: {alloc[Base(f)]} old(alloc)[Base(f)] == UNALLOCATED || old(alloc)[Base(f)] == alloc[Base(f)]);
+
+modifies Mem;
+//TAG: no updated memory locations
+ensures(forall f: name, m:int :: {Mem[f][m]} Mem[f][m] == old(Mem[f])[m]);
+free ensures(Mem[Field(0)][0] == old(Mem[Field(0)])[0]);
+
+//TAG: Type Safety Precondition
+requires(forall a:int :: {Mem[Field(a)][a]} HasType(Mem[Field(a)][a], Field(a)));
+//TAG: Type Safety Postcondition
+ensures(forall a:int :: {Mem[Field(a)][a]} HasType(Mem[Field(a)][a], Field(a)));
+ensures(HasType($result.main$3.5$1$, INT4_name));
+{
+var havoc_stringTemp:int;
+var condVal:int;
+var $a$1$4.6$main : int;
+var b : int;
+var c : int;
+var flag : int;
+var tempBoogie0:int;
+var tempBoogie1:int;
+var tempBoogie2:int;
+var tempBoogie3:int;
+var tempBoogie4:int;
+var tempBoogie5:int;
+var tempBoogie6:int;
+var tempBoogie7:int;
+var tempBoogie8:int;
+var tempBoogie9:int;
+var tempBoogie10:int;
+var tempBoogie11:int;
+var tempBoogie12:int;
+var tempBoogie13:int;
+var tempBoogie14:int;
+var tempBoogie15:int;
+var tempBoogie16:int;
+var tempBoogie17:int;
+var tempBoogie18:int;
+var tempBoogie19:int;
+
+
+start:
+
+assume(HasType($a$1$4.6$main, INT4_name));
+assume(HasType(b, INT4_name));
+assume(HasType(c, INT4_name));
+assume(HasType(flag, INT4_name));
+assume(HasType($result.main$3.5$1$, INT4_name));
+goto label_3;
+
+
+// c:\espmain1\esp\tests\hvregr\split_memory\014\bool_vals_gt.c(20)
+label_1:
+assume (forall m:int :: {Mem[Field(m)][m]} alloc[Base(m)] != ALLOCATED && old(alloc)[Base(m)] != ALLOCATED ==> Mem[Field(m)][m] == old(Mem[Field(m)])[m]);
+return;
+
+
+// c:\espmain1\esp\tests\hvregr\split_memory\014\bool_vals_gt.c(20)
+label_2:
+assume false;
+return;
+
+
+// c:\espmain1\esp\tests\hvregr\split_memory\014\bool_vals_gt.c(4)
+label_3:
+goto label_4;
+
+
+// c:\espmain1\esp\tests\hvregr\split_memory\014\bool_vals_gt.c(4)
+label_4:
+goto label_5;
+
+
+// c:\espmain1\esp\tests\hvregr\split_memory\014\bool_vals_gt.c(4)
+label_5:
+goto label_6;
+
+
+// c:\espmain1\esp\tests\hvregr\split_memory\014\bool_vals_gt.c(5)
+label_6:
+goto label_7;
+
+
+// c:\espmain1\esp\tests\hvregr\split_memory\014\bool_vals_gt.c(7)
+label_7:
+c := LIFT(b < $a$1$4.6$main) ;
+//TAG: Type Safety Assertion
+assert(forall a:int :: {Mem[Field(a)][a]} HasType(Mem[Field(a)][a], Field(a)));
+assert(HasType($a$1$4.6$main, INT4_name));
+assert(HasType(b, INT4_name));
+assert(HasType(c, INT4_name));
+assert(HasType(flag, INT4_name));
+goto label_8;
+
+
+// c:\espmain1\esp\tests\hvregr\split_memory\014\bool_vals_gt.c(9)
+label_8:
+goto label_8_true , label_8_false ;
+
+
+label_8_true :
+assume (c != 0);
+goto label_10;
+
+
+label_8_false :
+assume (c == 0);
+goto label_9;
+
+
+// c:\espmain1\esp\tests\hvregr\split_memory\014\bool_vals_gt.c(12)
+label_9:
+flag := 0 ;
+//TAG: Type Safety Assertion
+assert(forall a:int :: {Mem[Field(a)][a]} HasType(Mem[Field(a)][a], Field(a)));
+assert(HasType($a$1$4.6$main, INT4_name));
+assert(HasType(b, INT4_name));
+assert(HasType(c, INT4_name));
+assert(HasType(flag, INT4_name));
+goto label_11;
+
+
+// c:\espmain1\esp\tests\hvregr\split_memory\014\bool_vals_gt.c(10)
+label_10:
+flag := 1 ;
+//TAG: Type Safety Assertion
+assert(forall a:int :: {Mem[Field(a)][a]} HasType(Mem[Field(a)][a], Field(a)));
+assert(HasType($a$1$4.6$main, INT4_name));
+assert(HasType(b, INT4_name));
+assert(HasType(c, INT4_name));
+assert(HasType(flag, INT4_name));
+goto label_11;
+
+
+// c:\espmain1\esp\tests\hvregr\split_memory\014\bool_vals_gt.c(15)
+label_11:
+goto label_11_true , label_11_false ;
+
+
+label_11_true :
+assume (b < $a$1$4.6$main);
+goto label_13;
+
+
+label_11_false :
+assume !(b < $a$1$4.6$main);
+goto label_12;
+
+
+// c:\espmain1\esp\tests\hvregr\split_memory\014\bool_vals_gt.c(18)
+label_12:
+//TAG: flag == 0
+assert (flag == 0);
+goto label_1;
+
+
+// c:\espmain1\esp\tests\hvregr\split_memory\014\bool_vals_gt.c(16)
+label_13:
+//TAG: flag == 1
+assert (flag == 1);
+goto label_1;
+
+}
+
diff --git a/Test/z3api/boog25.bpl b/Test/z3api/boog25.bpl
new file mode 100644
index 00000000..0a8b5e92
--- /dev/null
+++ b/Test/z3api/boog25.bpl
@@ -0,0 +1,282 @@
+type byte;
+function OneByteToInt(byte) returns (int);
+function TwoBytesToInt(byte, byte) returns (int);
+function FourBytesToInt(byte, byte, byte, byte) returns (int);
+axiom(forall b0:byte, c0:byte :: {OneByteToInt(b0), OneByteToInt(c0)} OneByteToInt(b0) == OneByteToInt(c0) ==> b0 == c0);
+axiom(forall b0:byte, b1: byte, c0:byte, c1:byte :: {TwoBytesToInt(b0, b1), TwoBytesToInt(c0, c1)} TwoBytesToInt(b0, b1) == TwoBytesToInt(c0, c1) ==> b0 == c0 && b1 == c1);
+axiom(forall b0:byte, b1: byte, b2:byte, b3:byte, c0:byte, c1:byte, c2:byte, c3:byte :: {FourBytesToInt(b0, b1, b2, b3), FourBytesToInt(c0, c1, c2, c3)} FourBytesToInt(b0, b1, b2, b3) == FourBytesToInt(c0, c1, c2, c3) ==> b0 == c0 && b1 == c1 && b2 == c2 && b3 == c3);
+
+// Mutable
+var Mem_BYTE:[int]byte;
+var alloc:[int]name;
+
+
+function Field(int) returns (name);
+function Base(int) returns (int);
+
+// Constants
+const unique UNALLOCATED:name;
+const unique ALLOCATED: name;
+const unique FREED:name;
+
+const unique BYTE:name;
+
+function Equal([int]bool, [int]bool) returns (bool);
+function Subset([int]bool, [int]bool) returns (bool);
+function Disjoint([int]bool, [int]bool) returns (bool);
+
+function Empty() returns ([int]bool);
+function Singleton(int) returns ([int]bool);
+function Reachable([int,int]bool, int) returns ([int]bool);
+function Union([int]bool, [int]bool) returns ([int]bool);
+function Intersection([int]bool, [int]bool) returns ([int]bool);
+function Difference([int]bool, [int]bool) returns ([int]bool);
+function Dereference([int]bool, [int]int) returns ([int]bool);
+function Inverse(f:[int]int, x:int) returns ([int]bool);
+
+function AtLeast(int, int) returns ([int]bool);
+function Rep(int, int) returns (int);
+axiom(forall n:int, x:int, y:int :: {AtLeast(n,x)[y]} AtLeast(n,x)[y] ==> x <= y && Rep(n,x) == Rep(n,y));
+axiom(forall n:int, x:int, y:int :: {AtLeast(n,x),Rep(n,x),Rep(n,y)} x <= y && Rep(n,x) == Rep(n,y) ==> AtLeast(n,x)[y]);
+axiom(forall n:int, x:int :: {AtLeast(n,x)} AtLeast(n,x)[x]);
+axiom(forall n:int, x:int, z:int :: {PLUS(x,n,z)} Rep(n,x) == Rep(n,PLUS(x,n,z)));
+axiom(forall n:int, x:int :: {Rep(n,x)} (exists k:int :: Rep(n,x) - x == n*k));
+
+/*
+function AtLeast(int, int) returns ([int]bool);
+function ModEqual(int, int, int) returns (bool);
+axiom(forall n:int, x:int :: ModEqual(n,x,x));
+axiom(forall n:int, x:int, y:int :: {ModEqual(n,x,y)} ModEqual(n,x,y) ==> ModEqual(n,y,x));
+axiom(forall n:int, x:int, y:int, z:int :: {ModEqual(n,x,y), ModEqual(n,y,z)} ModEqual(n,x,y) && ModEqual(n,y,z) ==> ModEqual(n,x,z));
+axiom(forall n:int, x:int, z:int :: {PLUS(x,n,z)} ModEqual(n,x,PLUS(x,n,z)));
+axiom(forall n:int, x:int, y:int :: {ModEqual(n,x,y)} ModEqual(n,x,y) ==> (exists k:int :: x - y == n*k));
+axiom(forall x:int, n:int, y:int :: {AtLeast(n,x)[y]}{ModEqual(n,x,y)} AtLeast(n,x)[y] <==> x <= y && ModEqual(n,x,y));
+axiom(forall x:int, n:int :: {AtLeast(n,x)} AtLeast(n,x)[x]);
+*/
+
+function Array(int, int, int) returns ([int]bool);
+axiom(forall x:int, n:int, z:int :: {Array(x,n,z)} z <= 0 ==> Equal(Array(x,n,z), Empty()));
+axiom(forall x:int, n:int, z:int :: {Array(x,n,z)} z > 0 ==> Equal(Array(x,n,z), Difference(AtLeast(n,x),AtLeast(n,PLUS(x,n,z)))));
+
+
+axiom(forall x:int :: !Empty()[x]);
+
+axiom(forall x:int, y:int :: {Singleton(y)[x]} Singleton(y)[x] <==> x == y);
+axiom(forall y:int :: {Singleton(y)} Singleton(y)[y]);
+
+/* this formulation of Union IS more complete than the earlier one */
+/* (A U B)[e], A[d], A U B = Singleton(c), d != e */
+axiom(forall x:int, S:[int]bool, T:[int]bool :: {Union(S,T)[x]} Union(S,T)[x] <==> S[x] || T[x]);
+axiom(forall x:int, S:[int]bool, T:[int]bool :: {Union(S,T), S[x]} S[x] ==> Union(S,T)[x]);
+axiom(forall x:int, S:[int]bool, T:[int]bool :: {Union(S,T), T[x]} T[x] ==> Union(S,T)[x]);
+
+axiom(forall x:int, S:[int]bool, T:[int]bool :: {Intersection(S,T)[x]} Intersection(S,T)[x] <==> S[x] && T[x]);
+axiom(forall x:int, S:[int]bool, T:[int]bool :: {Intersection(S,T), S[x]} S[x] && T[x] ==> Intersection(S,T)[x]);
+axiom(forall x:int, S:[int]bool, T:[int]bool :: {Intersection(S,T), T[x]} S[x] && T[x] ==> Intersection(S,T)[x]);
+
+axiom(forall x:int, S:[int]bool, T:[int]bool :: {Difference(S,T)[x]} Difference(S,T)[x] <==> S[x] && !T[x]);
+axiom(forall x:int, S:[int]bool, T:[int]bool :: {Difference(S,T), S[x]} S[x] ==> Difference(S,T)[x] || T[x]);
+
+axiom(forall x:int, S:[int]bool, M:[int]int :: {Dereference(S,M)[x]} Dereference(S,M)[x] ==> (exists y:int :: x == M[y] && S[y]));
+axiom(forall x:int, S:[int]bool, M:[int]int :: {M[x], S[x], Dereference(S,M)} S[x] ==> Dereference(S,M)[M[x]]);
+axiom(forall x:int, y:int, S:[int]bool, M:[int]int :: {Dereference(S,M[x := y])} !S[x] ==> Equal(Dereference(S,M[x := y]), Dereference(S,M)));
+axiom(forall x:int, y:int, S:[int]bool, M:[int]int :: {Dereference(S,M[x := y])}
+ S[x] && Equal(Intersection(Inverse(M,M[x]), S), Singleton(x)) ==> Equal(Dereference(S,M[x := y]), Union(Difference(Dereference(S,M), Singleton(M[x])), Singleton(y))));
+axiom(forall x:int, y:int, S:[int]bool, M:[int]int :: {Dereference(S,M[x := y])}
+ S[x] && !Equal(Intersection(Inverse(M,M[x]), S), Singleton(x)) ==> Equal(Dereference(S,M[x := y]), Union(Dereference(S,M), Singleton(y))));
+
+axiom(forall f:[int]int, x:int :: {Inverse(f,f[x])} Inverse(f,f[x])[x]);
+axiom(forall f:[int]int, x:int, y:int :: {Inverse(f[x := y],y)} Equal(Inverse(f[x := y],y), Union(Inverse(f,y), Singleton(x))));
+axiom(forall f:[int]int, x:int, y:int, z:int :: {Inverse(f[x := y],z)} y == z || Equal(Inverse(f[x := y],z), Difference(Inverse(f,z), Singleton(x))));
+
+axiom(forall S:[int]bool, T:[int]bool :: {Equal(S,T)} Equal(S,T) <==> Subset(S,T) && Subset(T,S));
+axiom(forall x:int, S:[int]bool, T:[int]bool :: {S[x], Subset(S,T)} S[x] && Subset(S,T) ==> T[x]);
+axiom(forall S:[int]bool, T:[int]bool :: {Subset(S,T)} Subset(S,T) || (exists x:int :: S[x] && !T[x]));
+axiom(forall x:int, S:[int]bool, T:[int]bool :: {S[x], Disjoint(S,T), T[x]} !(S[x] && Disjoint(S,T) && T[x]));
+axiom(forall S:[int]bool, T:[int]bool :: {Disjoint(S,T)} Disjoint(S,T) || (exists x:int :: S[x] && T[x]));
+
+function Unified([name][int]int) returns ([int]int);
+axiom(forall M:[name][int]int, x:int :: {Unified(M)[x]} Unified(M)[x] == M[Field(x)][x]);
+axiom(forall M:[name][int]int, x:int, y:int :: {Unified(M[Field(x) := M[Field(x)][x := y]])} Unified(M[Field(x) := M[Field(x)][x := y]]) == Unified(M)[x := y]);
+// Memory model
+
+var Mem: [name][int]int;
+
+function Match(a:int, t:name) returns (bool);
+function HasType(v:int, t:name) returns (bool);
+function Values(t:name) returns ([int]bool);
+
+axiom(forall v:int, t:name :: {Values(t)[v]} Values(t)[v] ==> HasType(v, t));
+axiom(forall v:int, t:name :: {HasType(v, t), Values(t)} HasType(v, t) ==> Values(t)[v]);
+
+// Field declarations
+
+
+// Type declarations
+
+const unique INT4_name:name;
+const unique PINT4_name:name;
+
+// Field definitions
+
+// Type definitions
+
+axiom(forall a:int :: {Match(a, INT4_name)}
+ Match(a, INT4_name) <==> Field(a) == INT4_name);
+axiom(forall v:int :: HasType(v, INT4_name));
+
+axiom(forall a:int :: {Match(a, PINT4_name)}
+ Match(a, PINT4_name) <==> Field(a) == PINT4_name);
+axiom(forall v:int :: {HasType(v, PINT4_name)} {Match(v, INT4_name)}
+ HasType(v, PINT4_name) <==> (v == 0 || (v > 0 && Match(v, INT4_name))));
+
+function MINUS_BOTH_PTR_OR_BOTH_INT(a:int, b:int, size:int) returns (int);
+axiom(forall a:int, b:int, size:int :: {MINUS_BOTH_PTR_OR_BOTH_INT(a,b,size)}
+size * MINUS_BOTH_PTR_OR_BOTH_INT(a,b,size) <= a - b && a - b < size * (MINUS_BOTH_PTR_OR_BOTH_INT(a,b,size) + 1));
+
+function MINUS_LEFT_PTR(a:int, a_size:int, b:int) returns (int);
+axiom(forall a:int, a_size:int, b:int :: {MINUS_LEFT_PTR(a,a_size,b)} MINUS_LEFT_PTR(a,a_size,b) == a - a_size * b);
+
+function PLUS(a:int, a_size:int, b:int) returns (int);
+axiom(forall a:int, a_size:int, b:int :: {PLUS(a,a_size,b)} PLUS(a,a_size,b) == a + a_size * b);
+
+function MULT(a:int, b:int) returns (int); // a*b
+axiom(forall a:int, b:int :: {MULT(a,b)} MULT(a,b) == a * b);
+
+function DIV(a:int, b:int) returns (int); // a/b
+
+axiom(forall a:int, b:int :: {DIV(a,b)}
+a >= 0 && b > 0 ==> b * DIV(a,b) <= a && a < b * (DIV(a,b) + 1)
+);
+
+axiom(forall a:int, b:int :: {DIV(a,b)}
+a >= 0 && b < 0 ==> b * DIV(a,b) <= a && a < b * (DIV(a,b) - 1)
+);
+
+axiom(forall a:int, b:int :: {DIV(a,b)}
+a < 0 && b > 0 ==> b * DIV(a,b) >= a && a > b * (DIV(a,b) - 1)
+);
+
+axiom(forall a:int, b:int :: {DIV(a,b)}
+a < 0 && b < 0 ==> b * DIV(a,b) >= a && a > b * (DIV(a,b) + 1)
+);
+
+function BINARY_BOTH_INT(a:int, b:int) returns (int);
+
+function POW2(a:int) returns (bool);
+axiom POW2(1);
+axiom POW2(2);
+axiom POW2(4);
+axiom POW2(8);
+axiom POW2(16);
+axiom POW2(32);
+axiom POW2(64);
+axiom POW2(128);
+axiom POW2(256);
+axiom POW2(512);
+axiom POW2(1024);
+axiom POW2(2048);
+axiom POW2(4096);
+axiom POW2(8192);
+axiom POW2(16384);
+axiom POW2(32768);
+axiom POW2(65536);
+axiom POW2(131072);
+axiom POW2(262144);
+axiom POW2(524288);
+axiom POW2(1048576);
+axiom POW2(2097152);
+axiom POW2(4194304);
+axiom POW2(8388608);
+axiom POW2(16777216);
+axiom POW2(33554432);
+
+function choose(a:bool, b:int, c:int) returns (x:int);
+axiom(forall a:bool, b:int, c:int :: {choose(a,b,c)} a ==> choose(a,b,c) == b);
+axiom(forall a:bool, b:int, c:int :: {choose(a,b,c)} !a ==> choose(a,b,c) == c);
+
+function BIT_BAND(a:int, b:int) returns (x:int);
+axiom(forall a:int, b:int :: {BIT_BAND(a,b)} a == b ==> BIT_BAND(a,b) == a);
+axiom(forall a:int, b:int :: {BIT_BAND(a,b)} POW2(a) && POW2(b) && a != b ==> BIT_BAND(a,b) == 0);
+axiom(forall a:int, b:int :: {BIT_BAND(a,b)} a == 0 || b == 0 ==> BIT_BAND(a,b) == 0);
+
+function BIT_BOR(a:int, b:int) returns (x:int);
+
+function BIT_BXOR(a:int, b:int) returns (x:int);
+
+function BIT_BNOT(a:int) returns (int);
+
+function LIFT(a:bool) returns (int);
+axiom(forall a:bool :: {LIFT(a)} a <==> LIFT(a) != 0);
+
+function NOT(a:int) returns (int);
+axiom(forall a:int :: {NOT(a)} a == 0 ==> NOT(a) != 0);
+axiom(forall a:int :: {NOT(a)} a != 0 ==> NOT(a) == 0);
+
+function NULL_CHECK(a:int) returns (int);
+axiom(forall a:int :: {NULL_CHECK(a)} a == 0 ==> NULL_CHECK(a) != 0);
+axiom(forall a:int :: {NULL_CHECK(a)} a != 0 ==> NULL_CHECK(a) == 0);
+
+procedure nondet_choice() returns (x:int);
+
+
+procedure havoc_assert(i:int);
+requires (i != 0);
+
+procedure havoc_assume(i:int);
+ensures (i != 0);
+
+procedure __HAVOC_free(a:int);
+modifies alloc;
+ensures (forall x:int :: {alloc[x]} x == a || old(alloc)[x] == alloc[x]);
+ensures (alloc[a] == FREED);
+// Additional checks guarded by tranlator flags
+// requires alloc[a] == ALLOCATED;
+// requires Base(a) == a;
+
+procedure __HAVOC_malloc(obj_size:int) returns (new:int);
+requires obj_size >= 0;
+modifies alloc;
+ensures (new > 0);
+ensures (forall x:int :: {Base(x)} new <= x && x < new+obj_size ==> Base(x) == new);
+ensures (forall x:int :: {alloc[x]} x == new || old(alloc)[x] == alloc[x]);
+ensures old(alloc)[new] == UNALLOCATED && alloc[new] == ALLOCATED;
+
+procedure _strdup(str:int) returns (new:int);
+
+procedure _xstrcasecmp(a0:int, a1:int) returns (ret:int);
+
+procedure _xstrcmp(a0:int, a1:int) returns (ret:int);
+
+
+
+
+
+procedure main ( ) returns ($result.main$3.5$1$:int)
+
+modifies alloc;
+//TAG: no freed locations
+ensures(forall f:int :: {alloc[Base(f)]} old(alloc)[Base(f)] == UNALLOCATED || old(alloc)[Base(f)] == alloc[Base(f)]);
+
+modifies Mem;
+//TAG: no updated memory locations
+ensures(forall f: name, m:int :: {Mem[f][m]} Mem[f][m] == old(Mem[f])[m]);
+free ensures(Mem[Field(0)][0] == old(Mem[Field(0)])[0]);
+
+//TAG: Type Safety Precondition
+requires(forall a:int :: {Mem[Field(a)][a]} HasType(Mem[Field(a)][a], Field(a)));
+//TAG: Type Safety Postcondition
+ensures(forall a:int :: {Mem[Field(a)][a]} HasType(Mem[Field(a)][a], Field(a)));
+ensures(HasType($result.main$3.5$1$, INT4_name));
+{
+
+var a : int;
+var b : int;
+var c : int;
+
+c := LIFT (b < a) ;
+assert (c != 0 <==> b < a);
+
+
+}
+
diff --git a/Test/z3api/boog28.bpl b/Test/z3api/boog28.bpl
new file mode 100644
index 00000000..989dbf75
--- /dev/null
+++ b/Test/z3api/boog28.bpl
@@ -0,0 +1,16 @@
+
+function LIFT(x:bool) returns (int);
+axiom(forall x:bool :: {LIFT(x)} x <==> LIFT(x) != 0);
+
+procedure main ( )
+
+{
+var a : int;
+var b : int;
+var c : int;
+
+c := LIFT (b == a) ;
+assert (c != 0 <==> b == a);
+
+}
+
diff --git a/Test/z3api/boog29.bpl b/Test/z3api/boog29.bpl
new file mode 100644
index 00000000..8a97944d
--- /dev/null
+++ b/Test/z3api/boog29.bpl
@@ -0,0 +1,19 @@
+
+function LIFT(x:bool) returns (int);
+axiom(forall x:bool :: {LIFT(x)} x <==> LIFT(x) != 0);
+
+procedure main ( )
+
+{
+var c: int;
+c := LIFT(false);
+assert (c==0);
+
+c := LIFT(true);
+assert (c!=0);
+/*
+c := LIFT(1==5);
+assert (c==0);
+*/
+}
+
diff --git a/Test/z3api/boog3.bpl b/Test/z3api/boog3.bpl
new file mode 100644
index 00000000..9e04ac5b
--- /dev/null
+++ b/Test/z3api/boog3.bpl
@@ -0,0 +1,7 @@
+type Wicket;
+
+procedure Dummy();
+implementation Dummy() {
+ var x: Wicket;
+ assert (x!=x);
+} \ No newline at end of file
diff --git a/Test/z3api/boog30.bpl b/Test/z3api/boog30.bpl
new file mode 100644
index 00000000..ae682156
--- /dev/null
+++ b/Test/z3api/boog30.bpl
@@ -0,0 +1,13 @@
+
+function LIFT(x:bool) returns (int);
+axiom(forall x:bool :: {LIFT(x)} x <==> LIFT(x) != 0);
+
+procedure main ( )
+
+{
+var c: int;
+
+c := LIFT(1==5);
+assert (c==0);
+}
+
diff --git a/Test/z3api/boog31.bpl b/Test/z3api/boog31.bpl
new file mode 100644
index 00000000..219effce
--- /dev/null
+++ b/Test/z3api/boog31.bpl
@@ -0,0 +1,14 @@
+
+const b1:bool;
+const b2:bool;
+const b3:bool;
+
+axiom (b1==true && b2==false && b3==true);
+
+procedure main ( )
+
+{
+var c: int;
+assert (c==0);
+}
+
diff --git a/Test/z3api/boog34.bpl b/Test/z3api/boog34.bpl
new file mode 100644
index 00000000..62e7e82b
--- /dev/null
+++ b/Test/z3api/boog34.bpl
@@ -0,0 +1,10 @@
+
+function Rep(int, int) returns (int);
+axiom(forall n:int, x:int :: {Rep(n,x)}
+ (exists k:int :: Rep(n,x) - x == n*k));
+
+procedure main(x:int)
+{
+assert((Rep(0,x)==x));
+return;
+} \ No newline at end of file
diff --git a/Test/z3api/boog4.bpl b/Test/z3api/boog4.bpl
new file mode 100644
index 00000000..46eda549
--- /dev/null
+++ b/Test/z3api/boog4.bpl
@@ -0,0 +1,40 @@
+type Wicket;
+
+const w: Wicket;
+const myBool: bool;
+const v: Wicket;
+
+var favorite: Wicket;
+
+function age(Wicket) returns (int);
+
+axiom age(w)==7;
+axiom 7 < 8;
+axiom 7 <= 8;
+axiom 8 > 7;
+axiom 8 >= 7;
+axiom 6 != 7;
+axiom 7+1==8;
+axiom 8-1==7;
+axiom 7/1==7;
+axiom 7%2==1;
+axiom 4*2==8;
+axiom ((7==7) || (8==8));
+axiom ((7==7) ==> (7<8));
+axiom ((7==7) <==> (10==10));
+axiom ((7==7) && (8==8));
+
+axiom 7!=7;
+
+
+procedure NewFavorite(p: Wicket);
+ modifies favorite ;
+
+ ensures favorite==p;
+
+implementation NewFavorite(l: Wicket) {
+ favorite:=l;
+}
+
+
+
diff --git a/Test/z3api/boog5.bpl b/Test/z3api/boog5.bpl
new file mode 100644
index 00000000..0db94bba
--- /dev/null
+++ b/Test/z3api/boog5.bpl
@@ -0,0 +1,40 @@
+// types
+type Wicket;
+
+// consts
+const w: Wicket;
+const myBool: bool;
+const v: Wicket;
+const u: Wicket;
+const x: Wicket;
+
+
+// vars
+var favorite: Wicket;
+
+// functions
+function age(Wicket) returns (int);
+
+// axioms
+axiom age(w)==6;
+axiom age(u)==5;
+axiom age(x)==4;
+
+
+// procedure
+procedure SetToSeven(p: Wicket);
+ modifies favorite ;
+
+ ensures favorite==p;
+
+implementation SetToSeven(l: Wicket) {
+ if (age(w)==7) {
+ favorite:=l;
+ } else {
+ favorite:=v;
+ }
+
+}
+
+
+
diff --git a/Test/z3api/boog6.bpl b/Test/z3api/boog6.bpl
new file mode 100644
index 00000000..55c1dc7e
--- /dev/null
+++ b/Test/z3api/boog6.bpl
@@ -0,0 +1,22 @@
+// types
+type Wicket;
+
+// consts
+var favorite: Wicket;
+
+// axioms
+const b: bool;
+axiom b==true;
+
+// procedure
+procedure SetToSeven(p: Wicket);
+ modifies favorite ;
+
+ ensures favorite==p;
+
+implementation SetToSeven(l: Wicket) {
+ favorite:=l;
+}
+
+
+
diff --git a/Test/z3api/boog7.bpl b/Test/z3api/boog7.bpl
new file mode 100644
index 00000000..36f952d1
--- /dev/null
+++ b/Test/z3api/boog7.bpl
@@ -0,0 +1,19 @@
+// consts
+const w: int;
+
+
+// vars
+var favorite: int;
+
+// procedure
+procedure SetToSeven(p: int);
+ modifies favorite ;
+
+ ensures favorite==p;
+
+implementation SetToSeven(l: int) {
+ favorite:=w;
+}
+
+
+
diff --git a/Test/z3api/boog8.bpl b/Test/z3api/boog8.bpl
new file mode 100644
index 00000000..0ac4f163
--- /dev/null
+++ b/Test/z3api/boog8.bpl
@@ -0,0 +1,24 @@
+// types
+type Wicket;
+var favorite: Wicket;
+
+
+const myBv: bv5;
+axiom myBv==1bv2++2bv3;
+
+const myBool: bool;
+axiom myBool==true;
+
+
+// procedure
+procedure SetToSeven(p: Wicket);
+ modifies favorite ;
+
+ ensures favorite==p;
+
+implementation SetToSeven(l: Wicket) {
+ favorite:=favorite;
+}
+
+
+
diff --git a/Test/z3api/boog9.bpl b/Test/z3api/boog9.bpl
new file mode 100644
index 00000000..55897a1d
--- /dev/null
+++ b/Test/z3api/boog9.bpl
@@ -0,0 +1,21 @@
+// types
+type Wicket;
+var favorite: Wicket;
+
+function age(w:Wicket) returns (int);
+axiom (forall v:Wicket :: age(v)==7);
+axiom (exists v:Wicket :: age(v)<8);
+
+
+// procedure
+procedure SetToSeven(p: Wicket);
+ modifies favorite ;
+
+ ensures favorite==p;
+
+implementation SetToSeven(l: Wicket) {
+ favorite:=favorite;
+}
+
+
+
diff --git a/Test/z3api/runtest.bat b/Test/z3api/runtest.bat
new file mode 100644
index 00000000..5daa36c0
--- /dev/null
+++ b/Test/z3api/runtest.bat
@@ -0,0 +1,10 @@
+@echo off
+setlocal
+
+set BGEXE=..\..\Binaries\Boogie.exe
+
+for %%f in (boog0.bpl boog1.bpl boog2.bpl boog3.bpl boog4.bpl boog5.bpl boog6.bpl boog7.bpl boog8.bpl boog9.bpl boog10.bpl boog11.bpl boog12.bpl boog13.bpl boog14.bpl boog15.bpl boog16.bpl boog17.bpl boog18.bpl boog19.bpl boog20.bpl boog21.bpl boog22.bpl boog23.bpl boog24.bpl boog25.bpl boog28.bpl boog29.bpl boog30.bpl boog31.bpl boog34.bpl) do (
+ echo.
+ echo -------------------- %%f --------------------
+ %BGEXE% %* /nologo /prover:z3api %%f
+)
diff --git a/Util/Emacs/boogie-mode.el b/Util/Emacs/boogie-mode.el
new file mode 100644
index 00000000..1d8ffb05
--- /dev/null
+++ b/Util/Emacs/boogie-mode.el
@@ -0,0 +1,120 @@
+;; boogie-mode.el - GNU Emacs mode for Boogie 2
+;; Adapted by Rustan Leino from Jean-Christophe FILLIATRE's GNU Emancs mode for Why
+
+(defvar boogie-mode-hook nil)
+
+(defvar boogie-mode-map nil
+ "Keymap for Boogie major mode")
+
+(if boogie-mode-map nil
+ (setq boogie-mode-map (make-keymap))
+ (define-key boogie-mode-map "\C-c\C-c" 'boogie-run-boogie)
+ (define-key boogie-mode-map [(control return)] 'font-lock-fontify-buffer))
+
+(setq auto-mode-alist
+ (append
+ '(("\\.bpl" . boogie-mode))
+ auto-mode-alist))
+
+;; font-lock
+
+(defun boogie-regexp-opt (l)
+ (concat "\\<" (concat (regexp-opt l t) "\\>")))
+
+(defconst boogie-font-lock-keywords-1
+ (list
+ ; comments have the form /* ... */
+ '("/\\*\\([^*]\\|\\*[^/]\\)*\\*/" . font-lock-comment-face)
+ ; or // ...
+ '("//\\([^
+]\\)*" . font-lock-comment-face)
+
+ `(,(boogie-regexp-opt '(
+ "type" "const" "function" "axiom" "var" "procedure" "implementation"
+ "returns" "where" "requires" "ensures" "modifies" "free" "unique"
+ "invariant" "extends" "complete"
+ )) . font-lock-builtin-face)
+ `(,(boogie-regexp-opt '(
+ "assert" "assume" "break" "call" "else" "havoc" "if" "goto" "return" "while"
+ "old" "forall" "exists" "cast"
+ "false" "true")) . font-lock-keyword-face)
+ `(,(boogie-regexp-opt '("bool" "int"
+ "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"
+ "bv30" "bv31" "bv32" "bv33" "bv34" "bv35" "bv36" "bv37" "bv38" "bv39"
+ "bv40" "bv41" "bv42" "bv43" "bv44" "bv45" "bv46" "bv47" "bv48" "bv49"
+ "bv50" "bv51" "bv52" "bv53" "bv54" "bv55" "bv56" "bv57" "bv58" "bv59"
+ "bv60" "bv61" "bv62" "bv63" "bv64" ; and so on
+ )) . font-lock-type-face)
+ )
+ "Minimal highlighting for Boogie mode")
+
+(defvar boogie-font-lock-keywords boogie-font-lock-keywords-1
+ "Default highlighting for Boogie mode")
+
+;; syntax
+
+(defvar boogie-mode-syntax-table nil
+ "Syntax table for boogie-mode")
+
+(defun boogie-create-syntax-table ()
+ (if boogie-mode-syntax-table
+ ()
+ (setq boogie-mode-syntax-table (make-syntax-table))
+ (set-syntax-table boogie-mode-syntax-table)
+ (modify-syntax-entry ?' "w" boogie-mode-syntax-table)
+ (modify-syntax-entry ?_ "w" boogie-mode-syntax-table)))
+
+;; menu
+
+(require 'easymenu)
+
+(defun boogie-menu ()
+ (easy-menu-define
+ boogie-mode-menu (list boogie-mode-map)
+ "Boogie Mode Menu."
+ '("Boogie"
+ ["Run Boogie" boogie-run-boogie t]
+ "---"
+ ["Recolor buffer" font-lock-fontify-buffer t]
+ "---"
+ ))
+ (easy-menu-add boogie-mode-menu))
+
+;; commands
+
+(defun boogie-command-line (file)
+ (concat "boogie -nologo -abbrevOutput " file))
+
+(defun boogie-run-boogie ()
+ "run Boogie to check the Boogie program"
+ (interactive)
+ (let ((f (buffer-name)))
+ (compile (boogie-command-line f))))
+
+;; setting the mode
+
+(defun boogie-mode ()
+ "Major mode for editing Boogie programs.
+
+\\{boogie-mode-map}"
+ (interactive)
+ (kill-all-local-variables)
+ (boogie-create-syntax-table)
+ ; hilight
+ (make-local-variable 'font-lock-defaults)
+ (setq font-lock-defaults '(boogie-font-lock-keywords))
+ ; indentation
+ ; (make-local-variable 'indent-line-function)
+ ; (setq indent-line-function 'boogie-indent-line)
+ ; menu
+ ; providing the mode
+ (setq major-mode 'boogie-mode)
+ (setq mode-name "Boogie")
+ (use-local-map boogie-mode-map)
+ (font-lock-mode 1)
+ (boogie-menu)
+ (run-hooks 'boogie-mode-hook))
+
+(provide 'boogie-mode)
diff --git a/Util/Emacs/chalice-mode.el b/Util/Emacs/chalice-mode.el
new file mode 100644
index 00000000..91c69120
--- /dev/null
+++ b/Util/Emacs/chalice-mode.el
@@ -0,0 +1,115 @@
+;; chalice-mode.el - GNU Emacs mode for Chalice
+;; Adapted by Rustan Leino from Jean-Christophe FILLIATRE's GNU Emancs mode for Why
+
+(defvar chalice-mode-hook nil)
+
+(defvar chalice-mode-map nil
+ "Keymap for Chalice major mode")
+
+(if chalice-mode-map nil
+ (setq chalice-mode-map (make-keymap))
+ (define-key chalice-mode-map "\C-c\C-c" 'chalice-run-boogie)
+ (define-key chalice-mode-map [(control return)] 'font-lock-fontify-buffer))
+
+(setq auto-mode-alist
+ (append
+ '(("\\.chalice" . chalice-mode))
+ auto-mode-alist))
+
+;; font-lock
+
+(defun chalice-regexp-opt (l)
+ (concat "\\<" (concat (regexp-opt l t) "\\>")))
+
+(defconst chalice-font-lock-keywords-1
+ (list
+ ; comments have the form /* ... */
+ '("/\\*\\([^*]\\|\\*[^/]\\)*\\*/" . font-lock-comment-face)
+ ; or // ...
+ '("//\\([^
+]\\)*" . font-lock-comment-face)
+
+ `(,(chalice-regexp-opt '(
+ "class" "ghost" "var" "const" "external" "function" "method"
+ "predicate" "returns" "requires" "ensures" "lockchange"
+ "invariant"
+ )) . font-lock-builtin-face)
+ `(,(chalice-regexp-opt '(
+ "above" "acc" "acquire" "and" "assert" "assigned" "assume"
+ "below" "between" "call"
+ "downgrade" "else" "eval" "exists" "fold" "forall" "fork" "free" "havoc" "holds"
+ "if" "in" "install" "ite" "join" "lock" "lockbottom" "maxlock" "module" "new" "nil"
+ "old" "rd" "release" "result" "share" "this" "unfold" "unfolding" "unshare" "while"
+ "false" "true" "null")) . font-lock-keyword-face)
+ `(,(chalice-regexp-opt '("bool" "int" "seq" "token")) . font-lock-type-face)
+ )
+ "Minimal highlighting for Chalice mode")
+
+(defvar chalice-font-lock-keywords chalice-font-lock-keywords-1
+ "Default highlighting for Chalice mode")
+
+;; syntax
+
+(defvar chalice-mode-syntax-table nil
+ "Syntax table for chalice-mode")
+
+(defun chalice-create-syntax-table ()
+ (if chalice-mode-syntax-table
+ ()
+ (setq chalice-mode-syntax-table (make-syntax-table))
+ (set-syntax-table chalice-mode-syntax-table)
+ (modify-syntax-entry ?' "w" chalice-mode-syntax-table)
+ (modify-syntax-entry ?_ "w" chalice-mode-syntax-table)))
+
+;; menu
+
+(require 'easymenu)
+
+(defun chalice-menu ()
+ (easy-menu-define
+ chalice-mode-menu (list chalice-mode-map)
+ "Chalice Mode Menu."
+ '("Chalice"
+ ["Run Boogie" chalice-run-boogie t]
+ "---"
+ ["Recolor buffer" font-lock-fontify-buffer t]
+ "---"
+ ))
+ (easy-menu-add chalice-mode-menu))
+
+;; commands
+
+(defun chalice-command-line (file)
+ (concat "boogie " file))
+
+(defun chalice-run-boogie ()
+ "run Boogie to check the Chalice program"
+ (interactive)
+ (let ((f (buffer-name)))
+ (compile (chalice-command-line f))))
+
+;; setting the mode
+
+(defun chalice-mode ()
+ "Major mode for editing Chalice programs.
+
+\\{chalice-mode-map}"
+ (interactive)
+ (kill-all-local-variables)
+ (chalice-create-syntax-table)
+ ; hilight
+ (make-local-variable 'font-lock-defaults)
+ (setq font-lock-defaults '(chalice-font-lock-keywords))
+ ; indentation
+ ; (make-local-variable 'indent-line-function)
+ ; (setq indent-line-function 'chalice-indent-line)
+ ; menu
+ ; providing the mode
+ (setq major-mode 'chalice-mode)
+ (setq mode-name "Chalice")
+ (use-local-map chalice-mode-map)
+ (font-lock-mode 1)
+ (chalice-menu)
+ (run-hooks 'chalice-mode-hook))
+
+(provide 'chalice-mode)
diff --git a/Util/Emacs/dafny-mode.el b/Util/Emacs/dafny-mode.el
new file mode 100644
index 00000000..508ffbaf
--- /dev/null
+++ b/Util/Emacs/dafny-mode.el
@@ -0,0 +1,112 @@
+;; dafny-mode.el - GNU Emacs mode for Dafny
+;; Adapted by Rustan Leino from Jean-Christophe FILLIATRE's GNU Emancs mode for Why
+
+(defvar dafny-mode-hook nil)
+
+(defvar dafny-mode-map nil
+ "Keymap for Dafny major mode")
+
+(if dafny-mode-map nil
+ (setq dafny-mode-map (make-keymap))
+ (define-key dafny-mode-map "\C-c\C-c" 'dafny-run-boogie)
+ (define-key dafny-mode-map [(control return)] 'font-lock-fontify-buffer))
+
+(setq auto-mode-alist
+ (append
+ '(("\\.dfy" . dafny-mode))
+ auto-mode-alist))
+
+;; font-lock
+
+(defun dafny-regexp-opt (l)
+ (concat "\\<" (concat (regexp-opt l t) "\\>")))
+
+(defconst dafny-font-lock-keywords-1
+ (list
+ ; comments have the form /* ... */
+ '("/\\*\\([^*]\\|\\*[^/]\\)*\\*/" . font-lock-comment-face)
+ ; or // ...
+ '("//\\([^
+]\\)*" . font-lock-comment-face)
+
+ `(,(dafny-regexp-opt '(
+ "class" "function" "frame" "var" "method"
+ "returns" "requires" "ensures" "modifies" "reads" "free"
+ "invariant" "decreases"
+ )) . font-lock-builtin-face)
+ `(,(dafny-regexp-opt '(
+ "assert" "assume" "break" "call" "else" "havoc" "if" "label" "return" "while"
+ "old" "forall" "exists" "new" "foreach" "in" "this" "fresh" "use"
+ "false" "true" "null")) . font-lock-keyword-face)
+ `(,(dafny-regexp-opt '("bool" "int" "object" "set" "seq")) . font-lock-type-face)
+ )
+ "Minimal highlighting for Dafny mode")
+
+(defvar dafny-font-lock-keywords dafny-font-lock-keywords-1
+ "Default highlighting for Dafny mode")
+
+;; syntax
+
+(defvar dafny-mode-syntax-table nil
+ "Syntax table for dafny-mode")
+
+(defun dafny-create-syntax-table ()
+ (if dafny-mode-syntax-table
+ ()
+ (setq dafny-mode-syntax-table (make-syntax-table))
+ (set-syntax-table dafny-mode-syntax-table)
+ (modify-syntax-entry ?' "w" dafny-mode-syntax-table)
+ (modify-syntax-entry ?_ "w" dafny-mode-syntax-table)))
+
+;; menu
+
+(require 'easymenu)
+
+(defun dafny-menu ()
+ (easy-menu-define
+ dafny-mode-menu (list dafny-mode-map)
+ "Dafny Mode Menu."
+ '("Dafny"
+ ["Run Boogie" dafny-run-boogie t]
+ "---"
+ ["Recolor buffer" font-lock-fontify-buffer t]
+ "---"
+ ))
+ (easy-menu-add dafny-mode-menu))
+
+;; commands
+
+(defun dafny-command-line (file)
+ (concat "boogie " file))
+
+(defun dafny-run-boogie ()
+ "run Boogie to check the Dafny program"
+ (interactive)
+ (let ((f (buffer-name)))
+ (compile (dafny-command-line f))))
+
+;; setting the mode
+
+(defun dafny-mode ()
+ "Major mode for editing Dafny programs.
+
+\\{dafny-mode-map}"
+ (interactive)
+ (kill-all-local-variables)
+ (dafny-create-syntax-table)
+ ; hilight
+ (make-local-variable 'font-lock-defaults)
+ (setq font-lock-defaults '(dafny-font-lock-keywords))
+ ; indentation
+ ; (make-local-variable 'indent-line-function)
+ ; (setq indent-line-function 'dafny-indent-line)
+ ; menu
+ ; providing the mode
+ (setq major-mode 'dafny-mode)
+ (setq mode-name "Dafny")
+ (use-local-map dafny-mode-map)
+ (font-lock-mode 1)
+ (dafny-menu)
+ (run-hooks 'dafny-mode-hook))
+
+(provide 'dafny-mode)
diff --git a/Util/latex/boogie.sty b/Util/latex/boogie.sty
new file mode 100644
index 00000000..bda9f10a
--- /dev/null
+++ b/Util/latex/boogie.sty
@@ -0,0 +1,120 @@
+% boogie.sty
+% Boogie mode for the LaTeX listings package.
+% Rustan Leino, 30 May 2008.
+% Example:
+% \begin{boogie}
+% type Field \alpha;
+% var Heap: <<\alpha>>[ref, Field \alpha]\alpha where IsHeap(Heap);
+% function IsHeap(<<\alpha>>[ref, Field \alpha]\alpha) returns (bool);
+% procedure Inc(x: int) returns (y: int)
+% modifies Heap;
+% {
+% havoc Heap;
+% if (0 <= x && x < 100) {
+% y := x + 1;
+% }
+% }
+% \end{boogie}
+
+\usepackage{listings}
+
+\lstdefinelanguage{boogie}{
+ morekeywords={type,finite,bool,int,ref,%
+ 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,%
+ bv30,bv31,bv32,bv33,bv34,bv35,bv36,bv37,bv38,bv39,%
+ bv40,bv41,bv42,bv43,bv44,bv45,bv46,bv47,bv48,bv49,%
+ bv50,bv51,bv52,bv53,bv54,bv55,bv56,bv57,bv58,bv59,%
+ bv60,bv61,bv62,bv63,bv64,% ...
+ const,unique,complete,partition,
+ axiom,
+ function,returns,
+ var,where,
+ procedure,implementation,
+ requires,modifies,ensures,free,
+ % expressions
+ false,true,null,old,
+ % statements
+ assert,assume,havoc,call,if,else,while,invariant,break,return,goto,
+ },
+ literate=%
+ {:}{$\colon$}1
+ {::}{$\bullet$}2
+ {:=}{$:$$=$}2
+ {!}{$\lnot$}1
+ {==}{$=$}1
+ {!=}{$\neq$}1
+ {&&}{$\land$}1
+ {||}{$\lor$}1
+ {<=}{$\le$}1
+ {=>}{$\ge$}1
+ {==>}{$\Longrightarrow$}3
+ {<==>}{$\Longleftrightarrow$}4
+ {forall}{$\forall$}1
+ {exists}{$\exists$}1
+ % the following isn't actually Boogie, but it gives the option to produce nicer latex
+ {<<}{$\langle$}1
+ {>>}{$\rangle$}1
+ {\\alpha}{$\alpha$}1
+ {\\beta}{$\beta$}1
+ {\\gamma}{$\gamma$}1
+ {\\delta}{$\delta$}1
+ {\\epsilon}{$\epsilon$}1
+ {\\zeta}{$\zeta$}1
+ {\\eta}{$\eta$}1
+ {\\theta}{$\theta$}1
+ {\\iota}{$\iota$}1
+ {\\kappa}{$\kappa$}1
+ {\\lambda}{$\lambda$}1
+ {\\mu}{$\mu$}1
+ {\\nu}{$\nu$}1
+ {\\xi}{$\xi$}1
+ {\\pi}{$\pi$}1
+ {\\rho}{$\rho$}1
+ {\\sigma}{$\sigma$}1
+ {\\tau}{$\tau$}1
+ {\\upsilon}{$\upsilon$}1
+ {\\phi}{$\phi$}1
+ {\\chi}{$\chi$}1
+ {\\psi}{$\psi$}1
+ {\\omega}{$\omega$}1
+ {\\Gamma}{$\Gamma$}1
+ {\\Delta}{$\Delta$}1
+ {\\Theta}{$\Theta$}1
+ {\\Lambda}{$\Lambda$}1
+ {\\Xi}{$\Xi$}1
+ {\\Pi}{$\Pi$}1
+ {\\Sigma}{$\Sigma$}1
+ {\\Upsilon}{$\Upsilon$}1
+ {\\Phi}{$\Phi$}1
+ {\\Psi}{$\Psi$}1
+ {\\Omega}{$\Omega$}1
+ ,
+ sensitive=true, % case sensitive
+ morecomment=[l]{//},
+ morecomment=[s]{/*}{*/},
+ morestring=[b]",
+ numbers=none,
+ firstnumber=0,
+ numberstyle=\tiny,
+ stepnumber=5,
+ basicstyle=\scriptsize\sffamily,
+ commentstyle=\itshape,
+ keywordstyle=\bfseries,
+ ndkeywordstyle=\bfseries,
+}
+\lstnewenvironment{boogie}[1][]{%
+ \lstset{language=boogie,
+ floatplacement={tbp},captionpos=b,
+ frame=lines,xleftmargin=8pt,xrightmargin=8pt,basicstyle=\ttfamily,#1}}{}
+\lstnewenvironment{boogieNoLines}[1][]{%
+ \lstset{language=boogie,
+ floatplacement={tbp},captionpos=b,
+ xleftmargin=8pt,xrightmargin=8pt,basicstyle=\ttfamily,#1}}{}
+\def\inlineboogie{%
+ \lstinline[language=boogie,basicstyle=\ttfamily,columns=fixed]}
+\newcommand{\lstfile}[1]{
+ \lstinputlisting[language=boogie,%
+ frame=lines,xleftmargin=8pt,xrightmargin=8pt,basicstyle=\ttfamily,columns=fixed]{#1}
+}
diff --git a/Util/latex/chalice.sty b/Util/latex/chalice.sty
new file mode 100644
index 00000000..f9ba5234
--- /dev/null
+++ b/Util/latex/chalice.sty
@@ -0,0 +1,63 @@
+\usepackage{listings}
+%\lstloadlanguages{C}
+\lstdefinestyle{chalice}{%
+ numbers=none,
+ firstnumber=0,
+ numberstyle=\tiny,
+ stepnumber=5,
+% basicstyle=\scriptsize\sffamily,%
+% commentstyle=\itshape,%
+% keywordstyle=\bfseries,%
+% ndkeywordstyle=\bfseries,%
+% language=[Sharp]C,
+ morekeywords={%
+ above,acc,acquire,and,assert,assigned,assume,%
+ below,between,bool,%
+ call,class,const,%
+ downgrade,%
+ else,ensures,eval,exists,%
+ false,fold,forall,fork,free,function,%
+ ghost,%
+ holds,%
+ if,in,int,invariant,ite,%
+ join,%
+ lock,lockbottom,lockchange,%
+ maxlock,method,module,%
+ new,nil,null,%
+ old,%
+ predicate,%
+ rd,reorder,release,requires,result,returns,%
+ seq,share,%
+ this,token,true,%
+ unfold,unfolding,unshare,%
+ var,%
+ while},
+ literate=%
+ {=}{{=~}}1%
+ {+=}{{+}{=}~}3%
+ {-=}{{-}{=}~}3%
+ {*=}{{*}{=}~}3%
+ {++}{{+}{+}}2%
+ {--}{{-}{-}}2%
+ {==}{==}2%
+ {<=}{<=}2%
+ {=>}{=>}2%
+ {==>}{==>}3 %
+ {<==>}{<==>}4 %
+%% % {!}{$\lnot$}1% don't do this if ! is also used to indicate non-null types
+ {!=}{!=}2%
+}%
+\lstnewenvironment{chalice}[1][]{%
+ \lstset{style=chalice,
+ floatplacement={tbp},showstringspaces=false,captionpos=b,
+ frame=lines,xleftmargin=8pt,xrightmargin=8pt,basicstyle=\ttfamily,#1}}{}%
+\lstnewenvironment{chaliceNoLines}[1][]{%
+ \lstset{style=chalice,
+ floatplacement={tbp},showstringspaces=false,captionpos=b,
+ xleftmargin=8pt,xrightmargin=8pt,basicstyle=\ttfamily,#1}}{}%
+\def\S{%
+ \lstinline[style=chalice,basicstyle=\ttfamily,columns=fixed]}
+\newcommand{\lstfile}[1]{
+ \lstinputlisting[style=chalice,%
+ frame=lines,xleftmargin=8pt,xrightmargin=8pt,basicstyle=\ttfamily,columns=fixed]{#1}
+}
diff --git a/Util/latex/dafny.sty b/Util/latex/dafny.sty
new file mode 100644
index 00000000..9f7a76b3
--- /dev/null
+++ b/Util/latex/dafny.sty
@@ -0,0 +1,101 @@
+% dafny.sty
+% Dafny mode for the LaTeX listings package.
+% Rustan Leino, 22 June 2008.
+
+\usepackage{listings}
+
+\lstdefinelanguage{dafny}{
+ morekeywords={class,bool,int,object,set,seq,%
+ function,returns,
+ var,
+ method,in,
+ requires,modifies,ensures,reads,free,
+ % expressions
+ false,true,null,old,fresh,this,
+ % statements
+ assert,assume,new,havoc,call,if,else,while,invariant,break,return,foreach,
+ },
+ literate=%
+ {:}{$\colon$}1
+ {::}{$\bullet$}2
+ {:=}{$:$$=$}2
+ {!}{$\lnot$}1
+ {!!}{$\nparallel$}1
+ {==}{$=$}1
+ {!=}{$\neq$}1
+ {&&}{$\land$}1
+ {||}{$\lor$}1
+ {<=}{$\le$}1
+ {=>}{$\ge$}1
+ {<=set}{$\subseteq$}1
+ {+set}{$\cup$}1
+ {==>}{$\Longrightarrow$}3
+ {<==>}{$\Longleftrightarrow$}4
+ {forall}{$\forall$}1
+ {exists}{$\exists$}1
+ {\\in}{$\in$}1
+ % the following isn't actually Dafny, but it gives the option to produce nicer latex
+ {<<}{$\langle$}1
+ {>>}{$\rangle$}1
+ {\\alpha}{$\alpha$}1
+ {\\beta}{$\beta$}1
+ {\\gamma}{$\gamma$}1
+ {\\delta}{$\delta$}1
+ {\\epsilon}{$\epsilon$}1
+ {\\zeta}{$\zeta$}1
+ {\\eta}{$\eta$}1
+ {\\theta}{$\theta$}1
+ {\\iota}{$\iota$}1
+ {\\kappa}{$\kappa$}1
+ {\\lambda}{$\lambda$}1
+ {\\mu}{$\mu$}1
+ {\\nu}{$\nu$}1
+ {\\xi}{$\xi$}1
+ {\\pi}{$\pi$}1
+ {\\rho}{$\rho$}1
+ {\\sigma}{$\sigma$}1
+ {\\tau}{$\tau$}1
+ {\\upsilon}{$\upsilon$}1
+ {\\phi}{$\phi$}1
+ {\\chi}{$\chi$}1
+ {\\psi}{$\psi$}1
+ {\\omega}{$\omega$}1
+ {\\Gamma}{$\Gamma$}1
+ {\\Delta}{$\Delta$}1
+ {\\Theta}{$\Theta$}1
+ {\\Lambda}{$\Lambda$}1
+ {\\Xi}{$\Xi$}1
+ {\\Pi}{$\Pi$}1
+ {\\Sigma}{$\Sigma$}1
+ {\\Upsilon}{$\Upsilon$}1
+ {\\Phi}{$\Phi$}1
+ {\\Psi}{$\Psi$}1
+ {\\Omega}{$\Omega$}1
+ ,
+ sensitive=true, % case sensitive
+ morecomment=[l]{//},
+ morecomment=[s]{/*}{*/},
+ morestring=[b]",
+ numbers=none,
+ firstnumber=0,
+ numberstyle=\tiny,
+ stepnumber=5,
+ basicstyle=\scriptsize\sffamily,
+ commentstyle=\itshape,
+ keywordstyle=\bfseries,
+ ndkeywordstyle=\bfseries,
+}
+\lstnewenvironment{dafny}[1][]{%
+ \lstset{language=dafny,
+ floatplacement={tbp},captionpos=b,
+ frame=lines,xleftmargin=8pt,xrightmargin=8pt,basicstyle=\ttfamily,#1}}{}
+\lstnewenvironment{dafnyNoLines}[1][]{%
+ \lstset{language=dafny,
+ floatplacement={tbp},captionpos=b,
+ xleftmargin=8pt,xrightmargin=8pt,basicstyle=\ttfamily,#1}}{}
+\def\inlinedafny{%
+ \lstinline[language=dafny,basicstyle=\ttfamily,columns=fixed]}
+\newcommand{\lstfile}[1]{
+ \lstinputlisting[language=dafny,%
+ frame=lines,xleftmargin=8pt,xrightmargin=8pt,basicstyle=\ttfamily,columns=fixed]{#1}
+}