15 Command-line reference
This chapter documents every option the boogie executable accepts. The authority is the source, not the built-in help text:
Source/ExecutionEngine/CommandLineOptionEngine.cs —
the generic parser (Parse, ParseOption, ProcessInfoFlags) and the four options every Boogie-derived tool inherits. Source/ExecutionEngine/CommandLineParseState.cs —
how an option’s argument is read (CheckBooleanFlag, GetIntArgument, GetUnsignedNumericArgument, GetDoubleArgument, ConfirmArgumentCount). Source/ExecutionEngine/CommandLineOptions.cs —
Boogie’s own options: 97 case labels (83 of them option names, the other 14 the argument values of /printModel, /inline, /typeEncoding and /instrumentInfer) plus 55 boolean flags, and the fields they set — which carry the real defaults. Two of the boolean flags are shadowed by case labels of the same name and are unreachable, so the tool answers to 140 distinct option names in all. Source/BoogieDriver/BoogieDriver.cs —
file-list handling and the process exit code.
This is Boogie 2 says nothing about the command line. The 2008 paper describes the language and its semantics; the tool’s option surface is not mentioned anywhere in it. Everything in this chapter comes from the implementation.
Examples in this chapter are run as boogie; the solver is Z3 5.0.0. Where an example’s output contains a // Command Line Options: banner it has been produced with /env:0 so that the banner is suppressed.
15.1 Invoking Boogie
15.1.1 Usage
boogie [ option ... ] [ filename ... ]
Arguments that do not begin with / or - are input files. Options and files may be interleaved freely; all files named on the command line are parsed and concatenated into a single Boogie program before resolution, unless /verifySeparately is given.
15.1.2 Option syntax
An argument is treated as an option if it starts with / or -. Both prefixes are accepted for every option: /trace and -trace are the same switch. Option names are case-sensitive.
An option that takes one argument accepts it in either of two forms:
Colon form —
/print:out.bpl. The parser splits at the first colon, so the argument may itself contain colons. Separate form —
/print out.bpl. This is not documented anywhere, but it falls out of ConfirmArgumentCount(1), which consumes args[i] when no colon argument was supplied. It works for every one-argument option.
boogie /proc Abs cli-abs.bpl
Boogie program verifier finished with 1 verified, 0 errors
The separate form is a trap for options whose argument is optional-looking. /prune takes an integer argument, so boogie /prune file.bpl tries to parse file.bpl as an integer and fails.
Boolean flags take no argument, and attaching one is an error rather than being ignored:
boogie /trace:1 cli-small.bpl
Boogie: Error: "/trace" cannot take a colon argument
Use /help for available options
Argument validation errors all take the same shape and stop the run before any file is read:
boogie /errorLimit
boogie /errorLimit cli-small.bpl
boogie /errorLimit:abc cli-small.bpl
boogie /errorLimit:-1 cli-small.bpl
Boogie: Error: "/errorLimit" expects 1 argument
Use /help for available options
Boogie: Error: Invalid argument "cli-small.bpl" to option /errorLimit
Use /help for available options
Boogie: Error: Invalid argument "abc" to option /errorLimit
Use /help for available options
Boogie: Error: Invalid argument "-1" to option /errorLimit
Use /help for available options
Note the second line: in the separate form the option swallowed the file name.
Integer arguments are read with Convert.ToInt32 and by default must be non-negative; several options add a stricter upper bound (for example /errorTrace requires 0 <= n < 3). Unsigned arguments use Convert.ToUInt32. Double arguments use Convert.ToDouble with the invariant culture and must be non-negative.
15.1.3 Unknown options behave differently on Unix
CommandLineOptionEngine.Parse contains a platform test: when
Path.DirectorySeparatorChar is / —
boogie /notAnOption cli-abs.bpl
*** Error: '/notAnOption': Filename extension '' is not supported. Input files must be BoogiePL programs (.bpl).
boogie -notAnOption cli-abs.bpl
Boogie: Error: unknown switch: -notAnOption
Use /help for available options
Both exit with status 1. On Unix, prefer - when you want typos to be reported as typos.
15.1.4 Input files
BoogieDriver.GetFileList applies two rules before anything is parsed:
A file whose extension is .txt (case-insensitively) is read as a list of file names. Its contents are split on spaces, carriage returns and newlines, and each resulting name is added to the file list. This is undocumented. List files are not expanded recursively —
a .txt named inside a .txt would be rejected in the next step. Every remaining name must end in .bpl. Any other extension is a fatal error.
echo 'cli-f1.bpl cli-f2.bpl' > files.txt
boogie files.txt
cli-f2.bpl(1,17): Error: this assertion could not be proved
Execution trace:
cli-f2.bpl(1,17): anon0
Boogie program verifier finished with 1 verified, 1 error
The file named stdin.bpl is special to the parser (Parser.Parse reads standard input for it), not to the driver: see Lexical structure.
15.1.5 Exit codes
Boogie’s exit code is not a verification verdict. Main returns 0 unless one of a small number of conditions holds:
Situation |
| Exit code |
Command-line parse error |
| 1 |
No input files |
| 1 |
Input file with an extension other than .bpl |
| 1 |
A ProverException during verification (bad /proverOpt, solver binary not found, ...) |
| 1 |
Cancellation by /processTimeLimit |
| 1 |
Parse errors in a .bpl file |
| 0 |
Name-resolution errors |
| 0 |
Type-checking errors |
| 0 |
Monomorphisation failure (Unable to monomorphize input program: ...) |
| 0 |
Verification errors, timeouts, out-of-resource, inconclusive |
| 0 |
Success |
| 0 |
boogie cli-abs.bpl ; echo "exit=$?"
cli-abs.bpl(11,1): Error: a postcondition could not be proved on this return path
cli-abs.bpl(8,3): Related location: this is the postcondition that could not be proved
Execution trace:
cli-abs.bpl(10,5): anon0
Boogie program verifier finished with 1 verified, 1 error
exit=0
Scripts must therefore inspect the output text (or the /xml file), not $?. Boogie’s own test suite does exactly this: its lit tests diff the output against a .expect file.
15.2 Informational options
These are handled by ProcessInfoFlags, which runs after argument parsing and before any file is read. If more than one is given, the first match in the order /version, /help, /attrHelp, /proverHelp wins, the rest are ignored, input files are not touched, and the process exits 0.
Option |
| Effect |
/version |
| Print "Boogie program verifier version v, Copyright (c) 2003-2014, Microsoft." The version is the assembly FileVersion. |
/help |
| Print the usage message. /? is an accepted synonym and is itself undocumented. |
/attrHelp |
| Print the list of supported declaration attributes (CommandLineOptions.AttributeHelp). This is the only place many attributes are documented in the tool. |
/proverHelp |
| Print the options accepted by /proverOpt for the selected prover back
end. ProverHelp is TheProverFactory.BlankProverOptions(this).Help
and is evaluated inside ProcessInfoFlags, after the whole
command line has been parsed, so a /proverDll on either side of
/proverHelp takes effect. In practice there is no other back end to
ask — |
Three more options are informational in spirit:
Option |
| Argument |
| Default |
| Effect |
/env:n |
| 0, 1 or 2 |
| 1 |
| Where to echo the command line. 0 = never; 1 = in the two-line
banner of whatever PrintBplFile writes (/print,
/civlDesugaredFile); 2 = also to standard output, one argument
per line, before verification starts. Those are the only two readers of
ShowEnv in the source — |
/wait |
| none |
| off |
| Print "Press Enter to exit." and block on standard input just before the process exits. |
/break, /launch |
| none |
| off |
| Call System.Diagnostics.Debugger.Launch() at the point the option is parsed. /launch is an undocumented synonym. With no debugger registered this is a no-op on Linux. |
boogie /env:2 /noVerify cli-small.bpl
---Command arguments
/env:2
/noVerify
cli-small.bpl
--------------------
Boogie program verifier finished with 0 verified, 0 errors
15.3 Selecting what to verify
15.3.1 /proc and /noProc
Option |
| Argument |
| Default |
/proc:p |
| glob pattern; repeatable |
| empty (check everything) |
/noProc:p |
| glob pattern; repeatable |
| empty |
Both accumulate into lists. ExecutionEngineOptions.UserWantsToCheckRoutine decides:
the pattern is Regex.Escaped, then every escaped * is turned back into .*, and the result is anchored with ^...$. So * is the only wildcard, and it matches any run of characters including none;
the match is against the implementation’s verbose name —
the value of {:verboseName "..."} if present, otherwise the implementation name; matching is case-sensitive;
an implementation is checked when ProcsToCheck is empty or some /proc pattern matches, and no /noProc pattern matches —
exclusions win.
procedure Abs(x: int) returns (r: int)
ensures 0 <= r;
{
if (x < 0) { r := -x; } else { r := x; }
}
procedure Bad(x: int) returns (r: int)
ensures 0 < r;
{
r := x;
}
boogie /proc:Abs cli-abs.bpl
Boogie program verifier finished with 1 verified, 0 errors
Case matters —
boogie '/proc:*a*' cli-abs.bpl
cli-abs.bpl(11,1): Error: a postcondition could not be proved on this return path
cli-abs.bpl(8,3): Related location: this is the postcondition that could not be proved
Execution trace:
cli-abs.bpl(10,5): anon0
Boogie program verifier finished with 0 verified, 1 error
boogie /noProc:Bad cli-abs.bpl
Boogie program verifier finished with 1 verified, 0 errors
Filtered-out implementations are neither verified nor inlined, but they are still parsed, resolved and type-checked, and they still contribute declarations to the program.
{:verboseName} changes both the name /proc matches and the name printed by /trace:
procedure {:verboseName "My Nice Name"} P()
{
assert true;
}
boogie /trace cli-verbosename.bpl
Parsing cli-verbosename.bpl
Coalescing blocks...
Inlining...
Verifying My Nice Name ...
[TRACE] Using prover: z3
[0.027 s, solver resource count: 98, 1 proof obligation] verified
Boogie program verifier finished with 1 verified, 0 errors
15.3.2 /verifySeparately
/verifySeparately (boolean, off by default) has an effect only when more than one file is named. Each file is then processed as its own program, from parsing through the trailer, and the overall result is the conjunction of the per-file results. Everything is reported once per file:
cli-f1.bpl and cli-f3.bpl both declare procedure A.
boogie /verifySeparately cli-f1.bpl cli-f3.bpl
Boogie program verifier finished with 1 verified, 0 errors
Boogie program verifier finished with 1 verified, 0 errors
Because the files never share a resolution scope, duplicate declarations across files stop being errors. Without the flag the same two files fail to resolve:
boogie cli-f1.bpl cli-f3.bpl
cli-f3.bpl(1,10): Error: more than one declaration of procedure name: A
1 name resolution errors detected in cli-f3.bpl
/verifySeparately also passes each file name as the program id used for result caching, so it composes with /verifySnapshots.
15.3.3 /noResolve, /noTypecheck, /noVerify
Option |
| Stops after |
/noResolve |
| parsing |
/noTypecheck |
| parsing and name resolution |
/noVerify |
| everything except VC generation and the prover |
All three are boolean flags, all off by default.
/noResolve and /noTypecheck return PipelineOutcome.Done from
ResolveAndTypecheck, and ProcessProgram then returns without writing a
trailer. The consequence is that these two options produce no output at all on
success —
boogie /noResolve cli-small.bpl ; echo "exit=$?"
exit=0
/noVerify stops later, after Civl rewriting, inlining and dead-variable elimination, and does print a trailer:
boogie /noVerify cli-abs.bpl
Boogie program verifier finished with 0 verified, 0 errors
/noVerify is the usual companion to the printing options in Printing the program: /print runs before verification, so you rarely want to pay for the prover as well.
15.3.4 /overlookTypeErrors
Boolean, off by default. It applies to resolution errors. The single site that reads OverlookBoogieTypeErrors is in Program.Resolve: if resolving a top-level declaration raised errors and that declaration is an Implementation, the errors are rolled back and the implementation is dropped. Type checking runs afterwards and is unaffected.
procedure Good()
{
assert true;
}
procedure Bad2()
{
assert undeclaredThing;
}
boogie /overlookTypeErrors cli-overlook.bpl
cli-overlook.bpl(8,9): Error: undeclared identifier: undeclaredThing
Warning: Ignoring implementation Bad2 because of translation resolution errors
Boogie program verifier finished with 1 verified, 0 errors
Replace the body with a genuine type error (assert 1 + true;) and the option makes no difference: the run still ends with 1 type checking errors detected.
15.4 Libraries
Option |
| Argument |
| Default |
/lib:name |
| library name; repeatable |
| none |
/lib:name loads name.bpl as an embedded resource named Core.name.bpl from Boogie.Core.dll and appends its declarations to the program after all command-line files have been parsed. The libraries actually embedded (see Source/Core/Core.csproj) are:
Name |
| Contents |
base |
| 323 lines: the Set, Map and Vec operations, the Option and Vec datatypes, One, Loc, Default, Identity, MapConst/MapIte |
node |
| 146 lines: the Node datatype with Between and Avoiding reachability predicates; built on base |
set_size |
| 29 lines: Set_Size and its cardinality axioms and lemmas; built on base |
The help text lists only base and node; set_size is undocumented.
boogie /lib:base cli-lib.bpl
Boogie program verifier finished with 1 verified, 0 errors
Two things surprise people:
Dependencies are not resolved. node and set_size both use base, so loading them alone leaves every base name undeclared: boogie /lib:node cli-small.bpl reports 183 name-resolution errors and /lib:set_size reports 20, all of them inside the library itself. You must list every library you need: /lib:base /lib:node.
A misspelled library is not fatal. It prints Error locating library: Core.nosuchlib.bpl not found, the program is abandoned, and the process still exits 0.
Libraries is a HashSet<string>, so repeating /lib:base is harmless but the order in which libraries are appended is not the order you wrote them.
Finally, ParseBoogieProgram adds base automatically whenever any top-level declaration carries a Civl attribute, and at the same time forces InferModifies on. A Civl program therefore never needs /lib:base or /inferModifies spelled out.
15.5 Printing the program
15.5.1 /print and the print modifiers
Option |
| Argument |
| Default |
/print:file |
| file name, or - for the console |
| off |
/pretty:n |
| 0 or 1 |
| 1 |
/printWithUniqueIds |
| none |
| off |
/printUnstructured |
| none |
| off |
/printDesugared |
| none |
| off |
/printLambdaLifting |
| none |
| off |
/printMeasureDesugaring |
| none |
| off |
/print by itself emits the program immediately after parsing —
boogie /print:- /noVerify cli-small.bpl
// Boogie program verifier version 3.5.7.0, Copyright (c) 2003-2014, Microsoft.
// Command Line Options: /print:- /noVerify cli-small.bpl
procedure Abs(x: int) returns (r: int);
ensures 0 <= r;
implementation Abs(x: int) returns (r: int)
{
if (x < 0)
{
r := -x;
}
else
{
r := x;
}
}
Boogie program verifier finished with 0 verified, 0 errors
Note that a procedure with a body is printed as a procedure declaration followed by a separate implementation, which is exactly how the parser represents it.
The modifiers change what is printed and, for three of them, when:
Modifier |
| Printed at |
/printUnstructured |
| same place as /print (formatting only) |
/printWithUniqueIds |
| same place as /print (formatting only) |
/printDesugared |
| additionally after resolution and type checking |
/printMeasureDesugaring |
| additionally after measure desugaring |
/printLambdaLifting |
| additionally after lambda lifting, inside InferAndVerify |
Because the last three add a printing point rather than moving it, the program is written out twice. So /print:out.bpl /printDesugared leaves only the second copy in out.bpl while /print:- /printDesugared shows both on the console.
/printUnstructured desugars structured statements into a goto graph while keeping the structured form in a comment:
boogie /print:- /noVerify /env:0 /printUnstructured cli-small.bpl
procedure Abs(x: int) returns (r: int);
ensures 0 <= r;
implementation Abs(x: int) returns (r: int)
{
/*** structured program:
if (x < 0)
{
r := -x;
}
else
{
r := x;
}
**** end structured program */
anon0:
goto anon3_Then, anon3_Else;
anon3_Then:
assume {:partition} x < 0;
r := -x;
return;
anon3_Else:
assume {:partition} 0 <= x;
r := x;
return;
}
Boogie program verifier finished with 0 verified, 0 errors
Internally PrintUnstructured is a three-valued field: 0 = structured only, 1 = both (what the flag sets), 2 = unstructured only. The flag can only reach 0 and 1. The only place in the source that sets 2 is the /printPassive writer, which is why the passive program printed below (/printPassive) carries no /*** structured program comment. /civlDesugaredFile and /printMeasureDesugaring set the field to 1, not 2, so their output still repeats the structured form in a comment.
/printDesugared expands calls into their assert/havoc/assume encoding, as a comment attached to the original call. Only the relevant part of the second copy is shown:
boogie /print:- /noVerify /env:0 /printDesugared cli-call.bpl
implementation Q()
{
var a: int;
call a := P(3);
/*** desugaring:
{
var call0formal#AT#x: int;
var call1old#AT#g: int;
var call2formal#AT#y: int;
call0formal#AT#x := 3;
assert 0 <= call0formal#AT#x;
call1old#AT#g := g;
havoc g, call2formal#AT#y;
assume call2formal#AT#y == call0formal#AT#x;
a := call2formal#AT#y;
}
**** end desugaring */
assert a == 3;
}
/printWithUniqueIds prefixes each identifier with the unique id of its declaration. Because /print runs before resolution, the ids are usually all NoDecl:
if (NoDecl^^x < 0)
{
NoDecl^^r := -NoDecl^^x;
}
Combine it with /printDesugared (which prints after resolution) to get real ids.
/pretty:0 turns off the line-breaking pass in TokenTextWriter. The difference only shows up when a sub-expression’s rendering exceeds 80 characters:
procedure Big(aaaaaaaaaa: int, bbbbbbbbbb: int, cccccccccc: int, dddddddddd: int)
{
assert aaaaaaaaaa < bbbbbbbbbb && bbbbbbbbbb < cccccccccc && cccccccccc < dddddddddd ==> aaaaaaaaaa < dddddddddd;
}
assert aaaaaaaaaa < bbbbbbbbbb && bbbbbbbbbb < cccccccccc && cccccccccc < dddddddddd
==> aaaaaaaaaa < dddddddddd;
versus, with /pretty:0:
assert aaaaaaaaaa < bbbbbbbbbb && bbbbbbbbbb < cccccccccc && cccccccccc < dddddddddd ==> aaaaaaaaaa < dddddddddd;
15.5.2 /printPassive
Option |
| Argument |
| Default |
/printPassive:file |
| file name |
| off |
/printPassive requires a file name, writes the passified program to that file directly, and is independent of /print. Because it takes an argument, giving it without one consumes the input file name (Invoking Boogie):
boogie /printPassive cli-small.bpl
*** Error: No input files were specified.
Given a file name it writes the fully passive (single-assignment, goto-only) program, at the point in VerificationConditionGenerator where passification finishes:
boogie /printPassive:passive.out cli-small.bpl > /dev/null ; cat passive.out
procedure Abs(x: int) returns (r: int);
ensures 0 <= r;
implementation Abs(x: int) returns (r: int)
{
var r#AT#0: int;
var r#AT#1: int;
anon0:
goto anon3_Then, anon3_Else;
anon3_Else:
assume {:partition} 0 <= x;
assume r#AT#1 == x;
goto GeneratedUnifiedExit;
GeneratedUnifiedExit:
assert 0 <= r#AT#1;
return;
anon3_Then:
assume {:partition} x < 0;
assume r#AT#0 == -x;
assume r#AT#1 == r#AT#0;
goto GeneratedUnifiedExit;
}
Note there is no /env banner: this writer is created directly and does not emit one. Note also that the file is rewritten from scratch every time an implementation is passified, and each write emits the whole program. The file you are left with is therefore the state of the program at the last write: with /vcsCores:1 that means every implementation appears, in passive form.
15.5.3 /printSplit, /printPruned and /printSplitDeclarations
Option |
| Argument |
| Default |
/printSplit:prefix |
| path prefix, or - for the console |
| off |
/printPruned:prefix |
| same --- exact synonym |
| off |
/printSplitDeclarations |
| none |
| off |
/printSplit and /printPruned share a case label and set the same field; only /printPruned is documented. Each VC split is written to prefix-name.spl, where name is the implementation name plus a suffix identifying the split, escaped for use in a file name. With - the splits go to the console (with a 100 ms sleep before each, to keep concurrent writers from interleaving).
mkdir -p sp
boogie /printSplit:sp/x cli-abs.bpl > /dev/null ; ls sp/
x-Abs--1.spl
x-Bad--1.spl
Boogie does not create the directory. If it does not exist the writer throws and the implementation is abandoned (the absolute paths have been shortened here):
boogie /printSplit:nosuchdir/x cli-abs.bpl
Advisory: Abs SKIPPED due to I/O exception: Could not find a part of the path '.../nosuchdir/x-Abs--1.spl'.
cli-abs.bpl(1,11): Verification encountered solver exception (Abs)
Advisory: Bad SKIPPED due to I/O exception: Could not find a part of the path '.../nosuchdir/x-Bad--1.spl'.
cli-abs.bpl(7,11): Verification encountered solver exception (Bad)
Boogie program verifier finished with 0 verified, 0 errors, 2 solver exceptions
The –1 suffix is "-" + SplitIndex + Token.ShortName with SplitIndex of -1; when {:focus} or {:split_here} produce manual splits the suffix becomes informative, for example Ex-2/focus[+16,-20,+25].
/printSplitDeclarations additionally appends the declarations that survived
pruning for that split. It is silently ignored unless pruning is on
(Split.PrintSplitDeclarations returns immediately when !Options.Prune), which
makes it a convenient probe for what /prune keeps —
15.5.4 /printInstrumented and /printInlined
/printInstrumented (boolean, off) prints the program after abstract-interpretation results have been instrumented into it; it is only useful together with /infer and is described in Inference. /printInlined (boolean, off) prints each implementation after calls to {:inline} procedures have been expanded; see Inlining and loops.
15.5.5 /printCFG
Option |
| Argument |
| Default |
/printCFG:prefix |
| path prefix |
| off |
After resolution and type checking, writes one Graphviz file per implementation, named prefix.implName.dot. The graph is the loop-processed control flow graph, so it reflects Boogie’s view of the blocks rather than the source’s structured statements.
boogie /printCFG:cfg /noVerify cli-small.bpl > /dev/null ; cat cfg.Abs.dot
digraph G {
"anon0" [shape=box];
"anon3_Then" [shape=box];
"anon3_Else" [shape=box];
"anon0" -> "anon3_Then";
"anon0" -> "anon3_Else";
}
15.5.6 /printLean
Option |
| Argument |
| Default |
/printLean:file |
| file name |
| off |
Completely undocumented. Passifies every implementation and emits the resulting verification conditions as a Lean 4 file that uses the Auto tactic library. The generated file starts with a preamble of SMT array definitions and lemmas and then one theorem per implementation. Verification still runs afterwards unless /noVerify is given. /prune is honoured: with pruning off the whole program’s declarations are emitted.
boogie /printLean:small.lean cli-small.bpl ; head -5 small.lean
Boogie program verifier finished with 1 verified, 0 errors
import Auto
import Auto.Tactic
import Auto.MathlibEmulator.Basic -- For `Real`
import Auto.Translation.SMTAttributes
open Lean Std Auto Auto.SMT.Attribute Classical
For the one-procedure program above the generated file is 146 lines: the first 97 are a fixed preamble of SMT array definitions and lemmas, then – Variables, – Functions, – Axioms and – Implementations sections, with theorem _boogie_Abs_correct at line 135.
15.5.7 /xml
Option |
| Argument |
| Default |
/xml:file |
| file name |
| off |
Writes a machine-readable transcript in parallel with the console output: one <method> element per implementation, an <assertionBatch> per VC split with the source location of each assertion, and an <error> element with the execution trace for each failure. Timings and Z3 resource counts are included.
boogie /xml:out.xml cli-abs.bpl > /dev/null ; cat out.xml
<?xml version="1.0" encoding="utf-8"?>
<boogie version="3.5.7.0" commandLine="... /xml:out.xml cli-abs.bpl">
<file name="cli-abs.bpl">
<fileFragment name="cli-abs.bpl" />
</file>
<error message="postcondition violation" file="cli-abs.bpl" line="11" column="1">
<related file="cli-abs.bpl" line="8" column="3" />
<trace>
<traceNode label="PreconditionGeneratedEntry" />
<traceNode file="cli-abs.bpl" line="10" column="5" label="anon0" />
</trace>
</error>
<method name="Abs" startTime="2026-08-07 23:09:29Z">
<assertionBatch number="0" iteration="0" startTime="2026-08-07 23:09:29Z">
<assertion file="cli-abs.bpl" line="2" column="3" />
<conclusion duration="0.0264656" outcome="valid" resourceCount="700" />
</assertionBatch>
<conclusion endTime="2026-08-07 23:09:29Z" duration="0.0264656" resourceCount="700" outcome="correct" />
</method>
<method name="Bad" startTime="2026-08-07 23:09:29Z">
<assertionBatch number="0" iteration="0" startTime="2026-08-07 23:09:29Z">
<assertion file="cli-abs.bpl" line="8" column="3" />
<conclusion duration="0.0144576" outcome="invalid" resourceCount="302" />
</assertionBatch>
<conclusion endTime="2026-08-07 23:09:29Z" duration="0.0144576" resourceCount="302" outcome="errors" />
</method>
</boogie>
(The commandLine attribute has been abbreviated above; it contains the full argument vector including the driver DLL path.)
15.5.8 File-name macros and /logPrefix
Four options expand macros in their file-name argument, in
CommandLineOptions.ApplyDefaultOptions —
Macro |
| Expands to |
@TIME@ |
| the process start time, ISO 8601 with : replaced by . |
@PREFIX@ |
| the concatenation of all /logPrefix arguments |
@FILE@ |
| the last file named on the command line, escaped for use in a file name |
@PROC@ |
| /proverLog only: one log per verification condition, named after the procedure |
The macros are applied to /xml, /print, /proverLog and /printModelToFile. /logPrefix:str appends str to the @PREFIX@ expansion, replacing / and \ with - so the result is always a single path component; it may be given more than once and the values are concatenated.
boogie /logPrefix:XY '/proverLog:log-@PREFIX@-@FILE@.smt2' cli-small.bpl > /dev/null ; ls log-*
log-XY-cli-small.bpl.smt2
15.5.9 /useBaseNameForFileName and /printVerifiedProceduresCount
/useBaseNameForFileName (boolean, off) makes the parser record only the base name of each file in the tokens it produces, so diagnostics are reported against abs.bpl instead of ./some/path/abs.bpl. It also affects the file name printed in "parse errors detected in ..." messages.
/printVerifiedProceduresCount:n (0 or 1, default 1) controls whether the trailer includes the verified count:
boogie /printVerifiedProceduresCount:0 cli-abs.bpl
cli-abs.bpl(11,1): Error: a postcondition could not be proved on this return path
cli-abs.bpl(8,3): Related location: this is the postcondition that could not be proved
Execution trace:
cli-abs.bpl(10,5): anon0
Boogie program verifier finished with 1 error
15.6 Verification-condition generation
15.6.1 Program transformations before VC generation
Option |
| Argument |
| Default |
| Effect |
/liveVariableAnalysis:c |
| 0, 1 or 2 |
| 1 |
| 0 = off, 1 = intraprocedural, 2 = interprocedural. Dead assignments are dropped during passification. |
/coalesceBlocks:c |
| 0 or 1 |
| 1 |
| Merge a block into its unique predecessor when the predecessor has a unique successor. |
/removeEmptyBlocks:c |
| 0 or 1 |
| 1 |
| Drop blocks with no commands during VC generation. |
/noPruneInfeasibleEdges |
| none |
| pruning on |
| Keep control-flow edges whose guard is syntactically infeasible. |
/inferModifies |
| none |
| off |
| Compute modifies clauses instead of requiring them. Forced on for Civl programs. |
The effects are visible in the passive program. With the default settings the assignments to a variable that is never read afterwards are gone:
procedure P(b: bool)
{
var y: int;
y := 1;
if (b) {
y := 2;
}
assert true;
}
boogie /liveVariableAnalysis:0 /printPassive:pb.out cli-blocks.bpl > /dev/null ; cat pb.out
procedure P(b: bool);
implementation P(b: bool)
{
var y: int;
var y#AT#0: int;
anon0:
goto anon3_Then, anon3_Else;
anon3_Else:
assume {:partition} !b;
assume y#AT#0 == 1;
goto anon2;
anon2:
assert true;
return;
anon3_Then:
assume {:partition} b;
assume y#AT#0 == 2;
goto anon2;
}
/removeEmptyBlocks:0 keeps the synthetic entry blocks. Running the same command with /removeEmptyBlocks:0 instead of /liveVariableAnalysis:0 yields a body that begins:
PreconditionGeneratedEntry:
goto 0;
0:
goto anon0;
anon0:
goto anon3_Then, anon3_Else;
/noPruneInfeasibleEdges keeps a branch whose guard is literally false reachable in the graph:
procedure P()
{
if (false) {
assert 1 == 2;
}
assert true;
}
boogie /noPruneInfeasibleEdges /printPassive:pi.out cli-infeasible.bpl > /dev/null ; cat pi.out
procedure P();
implementation P()
{
anon0:
goto anon3_Then, anon3_Else;
anon3_Else:
assume {:partition} !false;
goto anon2;
anon2:
assert true;
return;
anon3_Then:
assume {:partition} false;
assert 1 == 2;
goto anon2;
}
By default the edge from anon3_Then to anon2 is removed and anon2 is folded away.
/inferModifies rescues a program that would otherwise fail type checking:
var g: int;
procedure P()
{
g := 1;
}
boogie cli-modifies.bpl
boogie /inferModifies cli-modifies.bpl
cli-modifies.bpl(5,4): Error: command assigns to a global variable that is not in the enclosing procedure's modifies clause: g
1 type checking errors detected in cli-modifies.bpl
Boogie program verifier finished with 1 verified, 0 errors
15.6.2 /subsumption
Option |
| Argument |
| Default |
/subsumption:c |
| 0, 1 or 2 |
| 2 (always) |
After an assertion has been turned into a proof obligation, it is normally also assumed for the rest of the path. 0 never assumes, 1 assumes except for quantified assertions, 2 always assumes. Turning subsumption off makes later assertions independent of earlier ones, at the cost of a harder VC:
procedure P(x: int)
{
assert x > 0;
assert x > -1;
}
boogie /subsumption:0 cli-subsumption.bpl
cli-subsumption.bpl(3,3): Error: this assertion could not be proved
Execution trace:
cli-subsumption.bpl(3,3): anon0
cli-subsumption.bpl(4,3): Error: this assertion could not be proved
Execution trace:
cli-subsumption.bpl(3,3): anon0
Boogie program verifier finished with 0 verified, 2 errors
boogie /subsumption:2 cli-subsumption.bpl
cli-subsumption.bpl(3,3): Error: this assertion could not be proved
Execution trace:
cli-subsumption.bpl(3,3): anon0
Boogie program verifier finished with 0 verified, 1 error
With /subsumption:1 this program behaves like /subsumption:2, since neither assertion is quantified.
The per-assertion attribute {:subsumption n} overrides the command-line setting.
15.6.3 /alwaysAssumeFreeLoopInvariants
Boolean, off by default. A free invariant is always assumed at the loop head, so it is available inside the body and after the loop. What it is normally not part of is the two checking contexts that RemoveBackEdges builds: the block that enters the loop and the back-edge block. With this flag the free invariant is pushed into both (prefixOfPredicateCmdsInit and prefixOfPredicateCmdsMaintained), so two extra assumes appear in the passive program.
procedure P(n: int)
requires 0 <= n;
{
var i: int;
i := 0;
while (i < n)
free invariant 0 <= i;
{
i := i + 1;
}
assert 0 <= i;
}
boogie /printPassive:fi0.out cli-freeinv.bpl > /dev/null
boogie /alwaysAssumeFreeLoopInvariants /printPassive:fi1.out cli-freeinv.bpl > /dev/null
diff fi0.out fi1.out
14c14
< anon0:
---
> PreconditionGeneratedEntry:
15a16,19
> goto anon0;
>
> anon0:
> assume 0 <= 0;
24a29
> assume 0 <= i#AT#1;
assume 0 <= 0 is the invariant at the loop entry (with i still 0) and assume 0 <= i#AT#1 is the invariant at the back edge. Since a free invariant is never proved, adding it to the checking contexts can only weaken the obligations.
15.6.4 /prune
Option |
| Argument |
| Default |
/prune:n |
| 0 or 1 |
| 0 (off) |
CommandLineOptions.Prune is an auto-property with no initialiser, so its default is false. Pruning is off unless you ask for it.
Pruning removes top-level declarations that the implementation being verified cannot reach, using the dependency graph built from uses clauses, {:include_dep} and quantifier triggers. /printSplitDeclarations makes the difference visible, since it only prints anything when pruning is on:
function F(int): int uses {
axiom (forall x: int :: F(x) == 2 * x);
}
function G(int): int uses {
axiom (forall x: int :: G(x) == F(x) + 1);
}
procedure P(x: int)
ensures F(x) - x == x;
{ }
boogie /printSplit:- /printSplitDeclarations cli-prune.bpl
implementation P--1(x: int)
{
PreconditionGeneratedEntry:
goto anon0;
anon0:
assert F(x) - x == x;
return;
}
Boogie program verifier finished with 1 verified, 0 errors
boogie /prune:1 /printSplit:- /printSplitDeclarations cli-prune.bpl
implementation P--1(x: int)
{
PreconditionGeneratedEntry:
goto anon0;
anon0:
assert F(x) - x == x;
return;
}
function F(int) : int
uses {
axiom (forall x: int :: F(x) == 2 * x);
}
procedure P(x: int);
ensures F(x) - x == x;
implementation P(x: int)
{
assert F(x) - x == x;
}
Boogie program verifier finished with 1 verified, 0 errors
G and its axiom are gone. Two further interactions are worth knowing:
/smoke forcibly sets Prune = false as a side effect of parsing, and does so in the option handler, so /smoke /prune:1 does enable pruning while /prune:1 /smoke does not. Order matters.
Pruning is also what makes checker reuse conditional: CheckerPool will not reuse an idle checker across splits when Prune is on, because the axiom set differs per split.
15.6.5 Type and array encoding
Option |
| Argument |
| Default |
/typeEncoding:t |
| m/monomorphic, p/predicates, a/arguments |
| m |
/useArrayAxioms |
| none |
| off |
/reflectAdd |
| none |
| off |
/typeEncoding chooses how polymorphism is compiled away. With m, Boogie first
tries to monomorphise the whole program; if that fails it prints
Unable to monomorphize input program: unhandled polymorphic features detected or
... : expanding type cycle detected and stops —
UseArrayTheory is derived, not settable: it is !useArrayAxioms && TypeEncodingMethod == Monomorphic. So maps are compiled to the SMT theory of arrays only under monomorphic encoding, and /useArrayAxioms switches to explicit select/store axioms:
procedure P(m: [int]int, i: int, v: int)
{
assert m[i := v][i] == v;
}
boogie /proverLog:a0.smt2 cli-array.bpl
grep -nE 'Array|select|store' a0.smt2
14:(declare-fun m () (Array Int Int))
25: (=> (= (ControlFlow 0 0) 3) (let ((anon0_correct (=> (= (ControlFlow 0 2) (- 0 1)) (= (select (store m i v) i) v))))
boogie /useArrayAxioms /proverLog:a1.smt2 cli-array.bpl
grep -nE 'Select__|Store__' a1.smt2
15:(declare-fun |Select__T@[Int]Int_| (|T@[Int]Int| Int) Int)
16:(declare-fun |Store__T@[Int]Int_| (|T@[Int]Int| Int Int) |T@[Int]Int|)
17:(assert (forall ( ( ?x0 |T@[Int]Int|) ( ?x1 Int) ( ?x2 Int)) (! (= (|Select__T@[Int]Int_| (|Store__T@[Int]Int_| ?x0 ?x1 ?x2) ?x1) ?x2) :weight 0)))
18:(assert (forall ( ( ?x0 |T@[Int]Int|) ( ?x1 Int) ( ?y1 Int) ( ?x2 Int)) (! (=> (not (= ?x1 ?y1)) (= (|Select__T@[Int]Int_| (|Store__T@[Int]Int_| ?x0 ?x1 ?x2) ?y1) (|Select__T@[Int]Int_| ?x0 ?y1))) :weight 0)))
30: (=> (= (ControlFlow 0 0) 3) (let ((anon0_correct (=> (= (ControlFlow 0 2) (- 0 1)) (= (|Select__T@[Int]Int_| (|Store__T@[Int]Int_| m i v) i) v))))
/reflectAdd does nothing with the shipped back end. The only reader of ReflectAdd is VCExprASTPrinter.VisitAddOp, which is used for debug printing of VC expressions; the SMT-LIB output is produced by SMTLibLineariser, which never consults it. Comparing prover logs with and without the flag shows identical (+ a b) terms.
15.6.6 Prover-input stability
Option |
| Argument |
| Default |
/emitDebugInformation:n |
| 0 or 1 |
| 1 |
/normalizeNames:n |
| 0 or 1 |
| 0 |
/normalizeDeclarationOrder:n |
| 0 or 1 |
| 1 |
/randomSeed:s |
| integer |
| unset |
/randomizeVcIterations:n |
| integer >= 1 |
| 1 |
/randomSeedIterations:n |
| deprecated synonym |
|
/emitDebugInformation:0 suppresses the :qid and :skolemid annotations on quantifiers and the (set-info :boogie-vc-id ...) line. /normalizeNames:1 replaces Boogie names in the SMT input with $generated, $generated@@0, ... so that renaming a declaration in the source does not change the solver’s input:
boogie /proverLog:n0.smt2 cli-small.bpl
boogie /normalizeNames:1 /proverLog:n1.smt2 cli-small.bpl
sed -n '13,16p' n0.smt2 ; echo ---- ; sed -n '13,16p' n1.smt2
(declare-fun ControlFlow (Int Int) Int)
(declare-fun r@1 () Int)
(declare-fun x () Int)
(declare-fun r@0 () Int)
----
(declare-fun ControlFlow (Int Int) Int)
(declare-fun $generated () Int)
(declare-fun $generated@@0 () Int)
(declare-fun $generated@@1 () Int)
/randomizeVcIterations:n proves each VC n times with different random seeds, renaming variables and reordering declarations each time and setting matching solver options. It sets RandomSeed to 0 if /randomSeed was not given. /randomSeedIterations is a deprecated spelling of the same option, still accepted and undocumented. The per-implementation attributes {:random_seed N} override /randomSeed for one implementation.
boogie /randomizeVcIterations:3 /trace cli-small.bpl
Parsing cli-small.bpl
Coalescing blocks...
Inlining...
Verifying Abs ...
[TRACE] Using prover: z3
[0.042 s, solver resource count: 2070, 3 proof obligations] verified
Boogie program verifier finished with 1 verified, 0 errors
The single assertion has become three proof obligations.
15.6.7 /keepQuantifier and pool instantiation
Boolean, off by default. Pool-based quantifier instantiation (the {:pool} / {:add_to_pool} attributes) normally replaces a quantifier by the conjunction or disjunction of its instances. /keepQuantifier keeps the original quantifier alongside the instances. With the flag, the quantifier survives into the SMT input:
function F(int): int;
procedure P()
{
assume (forall {:pool "A"} x: int :: F(x) == x);
assert {:add_to_pool "A", 3} F(3) == 3;
}
boogie /proverLog:q0.smt2 cli-pool.bpl
boogie /keepQuantifier /proverLog:q1.smt2 cli-pool.bpl
grep -c forall q0.smt2 q1.smt2
q0.smt2:0
q1.smt2:1
15.7 Error reporting
15.7.1 /errorLimit
Option |
| Argument |
| Default |
/errorLimit:n |
| non-negative integer |
| 5 |
The maximum number of counterexamples extracted per verification condition. 0 means "keep going until every assertion has been falsified or proved". Note that this counts errors per VC, so splitting changes what it means.
procedure Many(a: int, b: int, c: int, d: int)
{
assert a == 1;
assert b == 2;
assert c == 3;
assert d == 4;
}
boogie cli-errs.bpl
cli-errs.bpl(3,3): Error: this assertion could not be proved
Execution trace:
cli-errs.bpl(3,3): anon0
cli-errs.bpl(4,3): Error: this assertion could not be proved
Execution trace:
cli-errs.bpl(3,3): anon0
cli-errs.bpl(5,3): Error: this assertion could not be proved
Execution trace:
cli-errs.bpl(3,3): anon0
cli-errs.bpl(6,3): Error: this assertion could not be proved
Execution trace:
cli-errs.bpl(3,3): anon0
Boogie program verifier finished with 0 verified, 4 errors
boogie /errorLimit:2 cli-errs.bpl
cli-errs.bpl(3,3): Error: this assertion could not be proved
Execution trace:
cli-errs.bpl(3,3): anon0
cli-errs.bpl(4,3): Error: this assertion could not be proved
Execution trace:
cli-errs.bpl(3,3): anon0
Boogie program verifier finished with 0 verified, 2 errors
ApplyDefaultOptions silently forces ErrorLimit = 1 when stratified inlining is active and the SMTLib back end is in use. Stratified inlining cannot be turned on from Boogie’s command line, so this only affects tools like Corral that subclass these options.
15.7.2 /errorTrace
Option |
| Argument |
| Default |
/errorTrace:n |
| 0, 1 or 2 |
| 1 |
0 prints only the error line. 1 prints the labelled execution trace. 2 is documented as "include all Trace labels"; in practice the difference from 1 is rarely visible.
boogie /errorTrace:0 cli-trace.bpl
boogie /errorTrace:1 cli-trace.bpl
cli-trace.bpl(8,3): Error: this assertion could not be proved
Boogie program verifier finished with 0 verified, 1 error
cli-trace.bpl(8,3): Error: this assertion could not be proved
Execution trace:
cli-trace.bpl(3,3): anon0
cli-trace.bpl(4,7): anon4_Then
cli-trace.bpl(8,3): anon3
Boogie program verifier finished with 0 verified, 1 error
/errorTrace:0 also suppresses the counterexample model. The code that honours /printModel and /enhancedErrorMessages sits inside the if (Options.ErrorTrace > 0) branch, so /errorTrace:0 /printModel:1 prints neither trace nor model.
15.7.3 /printModel, /printModelToFile and /mv
Option |
| Argument |
| Default |
/printModel:n |
| exactly 0 or 1 |
| 0 |
/printModelToFile:file |
| file name |
| off |
/mv:file |
| file name |
| off |
/printModel:1 prints the solver’s counterexample model after each error’s execution trace. Unlike most integer options, this one is parsed by comparing the argument string against "0" and "1", so /printModel:2 is rejected.
boogie /printModel:1 cli-trace.bpl
cli-trace.bpl(8,3): Error: this assertion could not be proved
Execution trace:
cli-trace.bpl(3,3): anon0
cli-trace.bpl(4,7): anon4_Then
cli-trace.bpl(8,3): anon3
*** MODEL
r ->
r@0 -> 1
r@1 -> 1
x -> (- 1)
ControlFlow -> {
0 0 -> 5
0 2 -> (- 1)
0 3 -> 2
0 5 -> 3
else -> 5
}
tickleBool -> {
false -> true
true -> true
else -> true
}
*** STATE <initial>
r ->
x -> (- 1)
*** END_STATE
*** END_MODEL
Boogie program verifier finished with 0 verified, 1 error
/printModelToFile:f sends the model to f instead of
the console —
/mv:file writes the model annotated with {:captureState} points. Each assume {:captureState "s"} ... in the program becomes a *** STATE s section listing the variables whose incarnation changed:
procedure P(x: int) returns (r: int)
{
assume {:captureState "start"} true;
r := x;
assume {:captureState "afterAssign"} true;
assert r == x + 1;
}
boogie /mv:mv.out cli-capture.bpl > /dev/null ; cat mv.out
*** MODEL
r ->
x -> 0
ControlFlow -> {
0 0 -> 3
0 2 -> (- 1)
0 3 -> 2
else -> (- 1)
}
tickleBool -> {
false -> true
true -> true
else -> true
}
*** STATE <initial>
r ->
x -> 0
*** END_STATE
*** STATE start
*** END_STATE
*** STATE afterAssign
r -> 0
*** END_STATE
*** END_MODEL
/mv does not need /printModel; setting ModelViewFile is enough to make ExpectingModel true, which is what causes the solver to be asked for a model at all.
15.7.4 /enhancedErrorMessages
Option |
| Argument |
| Default |
/enhancedErrorMessages:n |
| 0 or 1 |
| 0 |
With 1, statements carrying {:print e0, e1, ...} contribute an "augmented execution trace" showing the values of those expressions in the counterexample.
procedure P(x: int, y: int)
{
assert {:print x, y, x + y} x == y;
}
boogie /enhancedErrorMessages:1 cli-print.bpl
cli-print.bpl(3,3): Error: this assertion could not be proved
Execution trace:
cli-print.bpl(3,3): anon0
Augmented execution trace:
45x + y
Boogie program verifier finished with 0 verified, 1 error
That output is not a typo. ConditionGeneration.AddDebugInfo substitutes model values only for arguments that are plain IdentifierExprs; any other expression is printed as-is. And ExecutionEngine writes the elements with Write, with no separator. So x -> 4, y -> 5 and the literal text x + y are concatenated into 45x + y, followed by the newline the attribute handler appends.
15.7.5 /forceBplErrors
Boolean, off. An assertion carrying {:msg "..."} normally reports that message instead of Boogie’s own. /forceBplErrors restores the standard message:
procedure P(x: int)
{
assert {:msg "custom message"} x == 1;
}
boogie cli-msg.bpl
boogie /forceBplErrors cli-msg.bpl
custom message
Execution trace:
cli-msg.bpl(3,3): anon0
Boogie program verifier finished with 0 verified, 1 error
cli-msg.bpl(3,3): Error: this assertion could not be proved
Execution trace:
cli-msg.bpl(3,3): anon0
Boogie program verifier finished with 0 verified, 1 error
15.7.6 /trackVerificationCoverage and /warnVacuousProofs
Option |
| Argument |
| Default |
/trackVerificationCoverage |
| none |
| off |
/warnVacuousProofs |
| none |
| off |
/trackVerificationCoverage asks the solver for an unsat core and reports which program elements labelled with {:id "..."} were needed for the proof. It replaces the old undocumented /printNecessaryAssertions.
It requires /trace to print anything. Both report sites are guarded by Options.Trace:
procedure P(x: int)
requires {:id "reqPos"} 0 < x;
requires {:id "reqBig"} 100 < x;
{
assert {:id "goal"} 0 <= x;
}
boogie /trackVerificationCoverage cli-coverage.bpl
Boogie program verifier finished with 1 verified, 0 errors
boogie /trackVerificationCoverage /trace cli-coverage.bpl
Parsing cli-coverage.bpl
Coalescing blocks...
Inlining...
Verifying P ...
[TRACE] Using prover: z3
Proof dependencies:
goal
reqPos
[0.029 s, solver resource count: 547, 1 proof obligation] verified
Proof dependencies of whole program:
goal
reqPos
Boogie program verifier finished with 1 verified, 0 errors
reqBig is absent, so it was not needed.
/warnVacuousProofs is a superset: it adds synthetic {:id} attributes to every assumption, assertion, requires, ensures and call, turns on TrackVerificationCoverage (the getter returns trackVerificationCoverage || WarnVacuousProofs), and warns when a proof goal was discharged without being covered. It reports without /trace:
procedure P(x: int)
{
assume x == 1;
assume x == 2;
assert x == 3;
}
boogie /warnVacuousProofs cli-vacuous.bpl
cli-vacuous.bpl(5,2): Warning: Proved vacuously
Boogie program verifier finished with 1 verified, 0 errors
Both options make ProduceUnsatCores true, which changes the SMT-LIB stream ((set-option :produce-unsat-cores true) and named assertions) and can therefore change solver performance.
15.7.7 /smoke and /smokeTimeout
Option |
| Argument |
| Default |
/smoke |
| none |
| off |
/smokeTimeout:n |
| seconds |
| 10 |
The soundness smoke test inserts assert false at various points and reports the
ones the prover can discharge —
procedure P(x: int)
requires 0 < x;
{
var y: int;
if (x < 0) {
y := 1;
} else {
y := 2;
}
}
boogie /smoke cli-smoke.bpl
found unreachable code:
implementation P(x: int)
{
var y: int;
0:
goto anon0;
anon0:
goto anon3_Then;
anon3_Then:
assume {:partition} x < 0;
y := 1;
assert false;
return;
}
Boogie program verifier finished with 1 verified, 0 errors
Remember that /smoke sets Prune = false while the option is parsed.
15.8 Resource limits
Option |
| Argument |
| Default |
| Applies to |
/timeLimit:n |
| seconds (uint) |
| 0 = unlimited |
| one verification condition |
/rlimit:n |
| Z3 resource units (uint) |
| 0 = unlimited |
| one verification condition |
/processTimeLimit:n |
| seconds (uint) |
| 0 = unlimited |
| the whole boogie invocation |
/timeLimitPerAssertionInPercent:n |
| percent, > 0 |
| 10 |
| timeout diagnostics only |
/vcsKeepGoingTimeout:n |
| seconds (uint) |
| 1 |
| keep-going splits |
/vcsFinalAssertTimeout:n |
| seconds (uint) |
| 30 |
| the last single assertion in keep-going mode |
/smokeTimeout:n |
| seconds (uint) |
| 10 |
| smoke-test queries |
/timeLimit is turned into (set-option :timeout n000) per query; /rlimit into (set-option :rlimit n). The per-implementation attributes {:timeLimit N} and {:rlimit N} override them.
/processTimeLimit is described in the source as "a hidden option" and is not in the help. It cancels the top-level task after the given number of seconds. The cancellation propagates as PipelineOutcome.Cancelled, which falls through ProcessProgram’s switch to the default arm, so the run produces no output at all and exits 1:
time ( boogie /processTimeLimit:2 cli-timeout1.bpl ; echo "exit=$?" )
exit=1
real 0m2.203s
user 0m0.305s
sys 0m0.042s
(Without the limit that program runs for minutes.)
15.8.1 How a timeout is reported
This is the most surprising corner of the option set. Whether a timeout looks like a timeout depends on how many assertions are in the split.
If the split contains more than one assertion, the outcome is a proper time-out:
function {:bvbuiltin "bvmul"} bvmul(bv64, bv64): bv64;
function {:bvbuiltin "bvult"} bvult(bv64, bv64): bool;
procedure Factor(x: bv64, y: bv64, k: int)
requires bvult(1bv64, x) && bvult(1bv64, y);
requires bvult(x, 4294967296bv64) && bvult(y, 4294967296bv64);
{
assert k == k;
assert bvmul(x, y) != 9223372036854775783bv64;
}
boogie /timeLimit:5 cli-timeout.bpl
cli-timeout.bpl(4,11): Verification of 'Factor' timed out after 5 seconds
Boogie program verifier finished with 0 verified, 0 errors, 1 time out
Remove the trivial first assertion and the split becomes what Split.LastChance
calls a last chance —
boogie /timeLimit:5 cli-timeout1.bpl
cli-timeout1.bpl(8,3): Error: this assertion could not be proved
Execution trace:
cli-timeout1.bpl(8,3): anon0
Boogie program verifier finished with 0 verified, 1 error
A single-assertion timeout is indistinguishable from a genuine assertion failure. The same asymmetry applies to /rlimit:
boogie /rlimit:100000 cli-timeout.bpl
boogie /rlimit:100000 cli-timeout1.bpl
cli-timeout.bpl(4,11): Verification out of resource (Factor)
Boogie program verifier finished with 0 verified, 0 errors, 1 out of resource
cli-timeout1.bpl(8,3): Error: this assertion could not be proved
Execution trace:
cli-timeout1.bpl(8,3): anon0
Boogie program verifier finished with 0 verified, 1 error
15.8.2 /runDiagnosticsOnTimeout and /traceDiagnosticsOnTimeout
Both are undocumented booleans, off by default. When a query times out, /runDiagnosticsOnTimeout bisects the assertions of the split, re-checking subsets with a smaller per-assertion time limit (TimeLimit / 100 * TimeLimitPerAssertionInPercent milliseconds, or 1000 ms if /timeLimit was not given), until it can name the assertions that individually time out:
boogie /runDiagnosticsOnTimeout /timeLimit:5 cli-timeout.bpl
cli-timeout.bpl(4,11): Verification of 'Factor' timed out after 5 seconds with 1 check(s) that timed out individually
cli-timeout.bpl(9,3): Unverified check due to timeout: this assertion could not be proved
Boogie program verifier finished with 0 verified, 0 errors, 1 time out
/traceDiagnosticsOnTimeout adds a report of the search itself:
boogie /runDiagnosticsOnTimeout /traceDiagnosticsOnTimeout /timeLimit:5 cli-timeout.bpl
Starting timeout diagnostics with initial time limit 5000.
Terminated timeout diagnostics after 1013 ms and 3 prover queries.
Outcome: TimeOut
Unverified assertions: 1 (of 2)
cli-timeout.bpl(4,11): Verification of 'Factor' timed out after 5 seconds with 1 check(s) that timed out individually
cli-timeout.bpl(9,3): Unverified check due to timeout: this assertion could not be proved
Boogie program verifier finished with 0 verified, 0 errors, 1 time out
The per-assertion limit here is 5000 / 100 * 10 = 500 ms, from /timeLimitPerAssertionInPercent’s default of 10.
/runDiagnosticsOnTimeout also changes cache behaviour: a cached TimedOut result is re-verified rather than reused.
15.9 Prover selection and options
15.9.1 /proverDll
Option |
| Argument |
| Default |
/proverDll:tp |
| back-end name or DLL path |
| SMTLib |
A name without a path separator is resolved to Boogie.Provers.tp.dll next to the executing assembly; a name containing / or \ is used as a path. The DLL must export Microsoft.Boogie.tp.Factory.
In practice SMTLib is the only usable value. Boogie.Provers.LeanAuto.dll also ships, but it does not export a Factory type. Lean output is available through /printLean instead.
The option is processed eagerly, during parsing, which is why it must precede /proverHelp.
15.9.2 /proverOpt (/p)
Option |
| Argument |
| Default |
/proverOpt:KEY[=VALUE] |
| repeatable |
| none |
/p:KEY[=VALUE] |
| short form |
| none |
Options accumulate and are handed to the back end after parsing. An unrecognised key
becomes a ProverException at verification time —
boogie /proverOpt:NOPE=1 cli-small.bpl ; echo "exit=$?"
Fatal Error: ProverException: Unrecognised prover option: NOPE=1
exit=1
Either = or : separates key from value, and a bare key sets the value to the empty string. The keys the shipped back end accepts (/proverHelp):
Key |
| Type |
| Meaning |
PROVER_PATH |
| string |
| full path to the solver binary |
PROVER_NAME |
| string |
| solver executable name, looked up on PATH |
LOG_FILE |
| string |
| like /proverLog; @PROC@ supported |
APPEND_LOG_FILE |
| bool |
| append rather than overwrite |
FORCE_LOG_STATUS |
| bool |
| has no effect — |
MEMORY_LIMIT |
| int |
| solver memory limit in megabytes |
VERBOSITY |
| int |
| 1 echoes the solver’s replies and the launch line; 2 additionally echoes every command sent |
TIME_LIMIT |
| uint |
| per-VC time limit in milliseconds |
BATCH_MODE |
| bool |
| send all solver input in one batch instead of incrementally |
SOLVER |
| string |
| z3 (default), cvc5, yices2, noop |
LOGIC |
| string |
| emit (set-logic ...); defaults to empty for Z3 and to ALL for CVC5 and Yices2 |
USE_WEIGHTS |
| bool |
| emit :weight annotations (default true) |
INSPECTOR |
| string |
| path to a Z3Inspector binary |
O:<name>=<value> |
|
| emit (set-option :name value) | |
C:<string> |
|
| pass a literal argument on the solver's command line |
FORCE_LOG_STATUS is accepted by the parser but is neither listed in /proverHelp nor read anywhere: ForceLogStatus has no reader, and setting it leaves the prover log byte-for-byte unchanged.
SOLVER=noop runs no solver at all and returns unknown for every query, which is useful for measuring Boogie’s own cost:
boogie /proverOpt:SOLVER=noop cli-abs.bpl
cli-abs.bpl(1,11): Verification inconclusive (Abs)
cli-abs.bpl(7,11): Verification inconclusive (Bad)
Boogie program verifier finished with 0 verified, 0 errors, 2 inconclusives
If the solver binary cannot be found the run fails hard:
boogie /proverOpt:PROVER_PATH=/nonexistent/z3 cli-small.bpl ; echo "exit=$?"
Fatal Error: ProverException: Cannot find specified prover: /nonexistent/z3
exit=1
15.9.3 /proverLog, /proverLogAppend and /proverPreamble
Option |
| Argument |
| Default |
/proverLog:file |
| file name with macros |
| off |
/proverLogAppend |
| none |
| overwrite |
/proverPreamble:file |
| file name |
| off |
/proverLog records the exact SMT-LIB 2 stream sent to the solver. In addition to the macros of File-name macros and /logPrefix, @PROC@ splits the log into one file per verification condition:
boogie '/proverLog:p-@PROC@.smt2' cli-abs.bpl > /dev/null ; ls p-*.smt2
p-Abs.smt2
p-Bad.smt2
A log begins with the solver options Boogie sets and then the VC:
head -20 p-Abs.smt2
(set-option :print-success false)
(set-info :smt-lib-version 2.6)
(set-option :smt.mbqi false)
(set-option :model.compact false)
(set-option :model.v2 true)
(set-option :pp.bv_literals false)
; done setting options
(declare-fun tickleBool (Bool) Bool)
(assert (and (tickleBool true) (tickleBool false)))
(push 1)
(declare-fun ControlFlow (Int Int) Int)
(declare-fun r@1 () Int)
(declare-fun x () Int)
(declare-fun r@0 () Int)
(set-info :boogie-vc-id Abs)
(set-option :timeout 0)
(set-option :rlimit 0)
(set-option :smt.mbqi false)
/proverPreamble:file is undocumented. It does not inline the file’s text; it emits a single (include "file") command into the stream, right after the standard preamble. The path is interpreted by the solver, not by Boogie:
boogie /proverPreamble:pre.txt /proverLog:pre.smt2 cli-small.bpl > /dev/null
sed -n '10,13p' pre.smt2
(declare-fun tickleBool (Bool) Bool)
(assert (and (tickleBool true) (tickleBool false)))
(include "pre.txt")
(push 1)
15.9.4 Other prover-facing options
Option |
| Argument |
| Default |
| Effect |
/proverWarnings:n |
| 0, 1 or 2 |
| 0 |
| Where to print warnings reported by the solver: nowhere, stdout, stderr. |
/restartProver |
| none |
| off |
| Kill and restart the solver process after each verification condition — |
/enableUnSatCoreExtraction:n |
| integer |
| 0 |
| Undocumented. Its only effect is to make ProduceUnsatCores true when it equals 1, which turns on named assertions and (set-option :produce-unsat-cores true). Unlike other integer options it is parsed with a bare Int32.Parse. |
/useProverEvaluate |
| none |
| off |
| Undocumented. Use the prover’s (get-value ...) instead of the model to read variable values. In Boogie it only has the side effect of forcing ProduceModel on (and, under stratified inlining, suppressing model generation); the evaluation path itself is used by Corral. |
/boolControlVC |
| none |
| off |
| Undocumented. Emit control-flow as boolean control variables rather than the ControlFlow function. Only meaningful under stratified inlining, which Boogie’s own command line cannot enable. |
/vcBrackets:b |
| 0 or 1 |
| -1 (unset) |
| Has no effect. BracketIdsInVC is initialised to -1 and has no reader anywhere in the source apart from its own property. |
15.10 Splitting and parallelism
Boogie can break one implementation’s verification condition into several independent VCs. Splitting is driven by a cost model; the options below tune it. Per-implementation attributes {:vcs_max_cost}, {:vcs_max_splits}, {:vcs_max_keep_going_splits} and {:vcs_split_on_every_assert} override the corresponding options.
Option |
| Argument |
| Default |
/vcsMaxCost:f |
| double |
| 1.0 |
/vcsMaxSplits:n |
| integer |
| 1 |
/vcsMaxKeepGoingSplits:n |
| integer |
| 1 |
/vcsKeepGoingTimeout:n |
| uint seconds |
| 1 |
/vcsFinalAssertTimeout:n |
| uint seconds |
| 30 |
/vcsPathJoinMult:f |
| double |
| 0.8 |
/vcsPathCostMult:f |
| double |
| 1.0 |
/vcsAssumeMult:f |
| double |
| 0.01 |
/vcsPathSplitMult:f |
| double |
| 0.5 |
/vcsSplitOnEveryAssert |
| none |
| off |
/vcsDumpSplits |
| none |
| off |
/vcsCores:n |
| integer >= 1 |
| 1 |
/vcsLoad:f |
| double 0.0 <= f < 3.0 |
|
15.10.1 /vcsMaxCost
VcsMaxCost is initialised to 1.0. With that default, raising /vcsMaxSplits splits immediately, because almost every VC costs more than 1.0.
procedure Four(x: int)
{
assert x == x;
assert x + 0 == x;
assert x * 1 == x;
assert x - x == 0;
}
boogie /vcsMaxSplits:4 /trace cli-four.bpl
Verifying Four ...
[TRACE] Using prover: z3
checking split 1/4, 0.00%, (cost:4/1 last) ...
--> split #1 done, [0.0410743 s] Valid
checking split 2/4, 25.00%, (cost:4/1 last) ...
--> split #2 done, [0.009278 s] Valid
checking split 3/4, 50.00%, (cost:4/1 last) ...
--> split #3 done, [0.0022301 s] Valid
checking split 4/4, 75.00%, (cost:4/1 last) ...
--> split #4 done, [0.0020062 s] Valid
[0.055 s, solver resource count: 440, 4 proof obligations] verified
boogie /vcsMaxSplits:4 /vcsMaxCost:2000.0 /trace cli-four.bpl
Verifying Four ...
[TRACE] Using prover: z3
[0.038 s, solver resource count: 158, 4 proof obligations] verified
With a large enough /vcsMaxCost the same command does not split at all. Note also that after the first round of splitting SplitAndVerifyWorker resets maxVcCost to 1.0 regardless, so the option only ever controls the first round.
15.10.2 The splitting cost model
The cost of a block is
(<assert-cost> + vcsAssumeMult * <assume-cost>) * (1.0 + vcsPathCostMult * <entering-paths>)
where each individual assertion and assumption costs 1.0. vcsPathJoinMult scales the path count where control flow joins. When a VC exceeds vcsMaxCost, the splitter compares the best path split (into VCs of cost B and C, from an original of cost A) against vcsPathSplitMult: path splitting is used when A >= vcsPathSplitMult * (B+C), otherwise the assertions are split instead. Raising vcsPathSplitMult favours assertion splitting.
/vcsMaxKeepGoingSplits:n with n > 1 enables keep-going mode: a split that times out is re-split into n pieces and retried. In that mode /vcsKeepGoingTimeout applies to intermediate splits and /vcsFinalAssertTimeout to the final single-assertion split.
15.10.3 /vcsSplitOnEveryAssert and /vcsDumpSplits
/vcsSplitOnEveryAssert puts each assertion in its own VC, ignoring the cost model. It reports which source line each split covers:
boogie /vcsSplitOnEveryAssert /trace cli-errs.bpl
checking split 1/4 (line 3), 0.00%, (cost:4/1 last) ...
--> split #1 done, [0.0292285 s] Invalid
checking split 2/4 (line 4), 24.26%, (cost:4/1 last) ...
--> split #2 done, [0.0073756 s] Invalid
checking split 3/4 (line 5), 49.01%, (cost:4/1 last) ...
--> split #3 done, [0.0019102 s] Invalid
checking split 4/4 (line 6), 74.26%, (cost:4/1 last) ...
--> split #4 done, [0.0019043 s] Invalid
[0.040 s, solver resource count: 1188, 4 proof obligations] errors
/vcsDumpSplits writes each split to disk as a Graphviz graph and a Boogie implementation, named Impl.split.n.dot and Impl.split.n.bpl:
boogie /vcsDumpSplits /vcsMaxSplits:2 cli-errs.bpl > /dev/null ; ls *.split.*
Many.split.0.bpl
Many.split.0.dot
Many.split.1.bpl
Many.split.1.dot
The .dot labels carry the cost model’s numbers:
cat Many.split.0.dot
digraph G {
n0 -> n1;
n0 [label="PreconditionGeneratedEntry:\n(0.0+0.0)*1.0"];
n1 [label="anon0:\n(2.0+2.0)*1.0",shape=box];
}
The dump happens as part of reading each split’s result, so it takes part in error reporting.
15.10.4 /vcsCores and /vcsLoad
/vcsCores:n verifies up to n VCs concurrently, each with its own checker (and therefore its own solver process). /vcsLoad:f sets it to round(ProcessorCount * f), clamped below at 1; f must be less than 3.0:
boogie /vcsLoad:5 cli-small.bpl
Boogie: Error: surprisingly high load specified; got 5, expected nothing above 3.0
Use /help for available options
The bound is strict: /vcsLoad:3.0 is rejected with the same message, /vcsLoad:2.9 is accepted.
Because output from concurrent workers is serialised per implementation, raising /vcsCores reorders console output relative to a serial run.
15.10.5 /relaxFocus
Boolean, off by default. Controls how {:focus} annotations are turned into splits. The default (top-down) strategy can produce exponentially many splits; /relaxFocus processes foci bottom-up and produces a linear number. On Boogie’s own Test/implementationDivision/focus/focus.bpl:
boogie /printSplit:- /errorTrace:0 focus.bpl | grep '^implementation'
implementation Ex-0() returns (y: int)
implementation Ex-1/focus[+16,-20,-25]/afterSplit@15() returns (y: int)
implementation Ex-2/focus[+16,-20,+25]() returns (y: int)
implementation Ex-3/focus[+16,+20,-25]() returns (y: int)
implementation Ex-4/focus[+16,+20,+25]() returns (y: int)
implementation focusInconsistency--1/focus[+38](x: int) returns (y: int)
boogie /relaxFocus /printSplit:- /errorTrace:0 focus.bpl | grep '^implementation'
implementation Ex-0() returns (y: int)
implementation Ex-1/focus[-25,-20,+16]/afterSplit@15() returns (y: int)
implementation Ex-2/focus[-25,+20,-16]() returns (y: int)
implementation Ex-3/focus[+25,-20,-16]() returns (y: int)
implementation focusInconsistency--1/focus[+38](x: int) returns (y: int)
The +/- lists in the split names are the focus block line numbers that are kept and dropped.
15.11 Inference
15.11.1 Abstract interpretation: /infer
Option |
| Argument |
| Default |
/infer:flags |
| a string of flag characters |
| off |
/instrumentInfer:c |
| h or e |
| h |
/checkInfer |
| none |
| off |
/printInstrumented |
| none |
| off |
/infer takes a string in which each character is a flag:
Character |
| Meaning |
t |
| trivial bottom/top lattice |
j |
| intervals (the "stronger" domain) |
s |
| debug statistics |
0 to 9 |
| number of iterations before widening (default 0) |
Exactly one of t and j must appear; supplying both or neither is an error, and so is any other character:
boogie /infer:tj cli-infer.bpl
boogie /infer:x cli-infer.bpl
Boogie: Error: Option /infer requires the selection of exactly one abstract domain
Use /help for available options
Boogie: Error: Invalid argument 'x' to option /infer
Boogie: Error: Option /infer requires the selection of exactly one abstract domain
Use /help for available options
s is accepted but the interval domain does not implement it:
Microsoft.Boogie.AbstractInterpretation.NativeIntervalDomain currently does not support debug statistics
The domain matters. This program needs a loop invariant that the trivial domain cannot express:
procedure Down(n: int) returns (i: int)
requires 0 <= n;
ensures 0 <= i;
{
i := n;
while (0 < i) {
i := i - 1;
}
}
boogie cli-infer.bpl
cli-infer.bpl(6,3): Error: a postcondition could not be proved on this return path
cli-infer.bpl(3,3): Related location: this is the postcondition that could not be proved
Execution trace:
cli-infer.bpl(5,5): anon0
cli-infer.bpl(6,3): anon2_LoopDone
Boogie program verifier finished with 0 verified, 1 error
boogie /infer:t cli-infer.bpl
cli-infer.bpl(6,3): Error: a postcondition could not be proved on this return path
cli-infer.bpl(3,3): Related location: this is the postcondition that could not be proved
Execution trace:
cli-infer.bpl(5,5): anon0
cli-infer.bpl(6,3): anon2_LoopHead
cli-infer.bpl(6,3): anon2_LoopDone
Boogie program verifier finished with 0 verified, 1 error
boogie /infer:j cli-infer.bpl
Boogie program verifier finished with 1 verified, 0 errors
The trivial domain does insert a cut point (visible as the extra anon2_LoopHead step in the trace), but the invariant it infers is true.
/printInstrumented shows what was added:
boogie /infer:j /printInstrumented /noVerify cli-infer.bpl
procedure Down(n: int) returns (i: int);
requires 0 <= n;
ensures 0 <= i;
implementation Down(n: int) returns (i: int)
{
anon0:
i := n;
goto anon2_LoopHead;
anon2_LoopHead: // cut point
assume {:inferred} 0 <= i;
goto anon2_LoopDone, anon2_LoopBody;
anon2_LoopBody:
assume {:partition} 0 < i;
i := i - 1;
goto anon2_LoopHead;
anon2_LoopDone:
assume {:partition} i <= 0;
return;
}
Boogie program verifier finished with 0 verified, 0 errors
/checkInfer turns each assume {:inferred} into an assert {:inferred}, so the prover has to confirm the abstract interpreter’s results. The only line that changes is:
anon2_LoopHead: // cut point
assert {:inferred} 0 <= i;
/instrumentInfer:e instruments the beginning and end of every block instead of only loop headers. The help describes it as a debugging aid for abstract domains, and the output shows why:
boogie /infer:j /instrumentInfer:e /printInstrumented /noVerify cli-infer.bpl
procedure Down(n: int) returns (i: int);
requires 0 <= n;
ensures 0 <= i;
implementation Down(n: int) returns (i: int)
{
anon0:
assume {:inferred} 0 <= n;
i := n;
assume {:inferred} 0 <= n && 0 <= i;
goto anon2_LoopHead;
anon2_LoopHead: // cut point
assume {:inferred} 0 <= n && 0 <= i;
assume {:inferred} 0 <= n && 0 <= i;
goto anon2_LoopDone, anon2_LoopBody;
anon2_LoopBody:
assume {:inferred} 0 <= n && 0 <= i;
assume {:partition} 0 < i;
i := i - 1;
assume {:inferred} 0 <= n && 0 <= i;
goto anon2_LoopHead;
anon2_LoopDone:
assume {:inferred} 0 <= n && 0 <= i;
assume {:partition} i <= 0;
assume {:inferred} 0 <= n && i == 0;
return;
}
Boogie program verifier finished with 0 verified, 0 errors
15.11.2 Houdini: /contractInfer
Option |
| Argument |
| Default |
| Documented |
/contractInfer |
| none |
| off |
| yes |
/printAssignment |
| none |
| off |
| no |
/explainHoudini |
| none |
| off |
| no |
/reverseHoudiniWorklist |
| none |
| off |
| no |
/crossDependencies |
| none |
| off |
| no |
/useUnsatCoreForContractInfer |
| none |
| off |
| no |
/inlineDepth:n |
| integer |
| -1 |
| no |
/dbgRefuted |
| none |
| off |
| no |
Houdini searches for the largest assignment to global boolean constants marked {:existential true} that makes the program verify. Candidate specifications are written as implications guarded by those constants.
const {:existential true} b1: bool;
const {:existential true} b2: bool;
var g: int;
procedure P(i: int)
modifies g;
ensures b1 ==> g > 0;
ensures b2 ==> g < 0;
{
if (i > 0) { g := 5; } else { g := 1; }
}
boogie /contractInfer /printAssignment cli-houdini.bpl
Assignment computed by Houdini:
b1 = True
b2 = False
Boogie program verifier finished with 1 verified, 0 errors
Without /contractInfer the {:existential} attribute is ignored entirely. /trace shows the refutation loop and its statistics:
boogie /contractInfer /trace cli-houdini.bpl
Parsing cli-houdini.bpl
Coalescing blocks...
Inlining...
Collecting existential constants...
Building call graph...
Number of implementations = 1
[TRACE] Using prover: z3
Beginning VC generation for Houdini...
Generating VC for P
Verifying P
Houdini assignment axiom: Microsoft.Boogie.VCExprAST.VCExprNAryOp(Microsoft.Boogie.VCExprAST.VCExprNAryOp(true, b1), b2)
Outcome = Invalid
Time taken = 0.0204528
Removing b2
Verifying P
Houdini assignment axiom: Microsoft.Boogie.VCExprAST.VCExprNAryOp(Microsoft.Boogie.VCExprAST.VCExprNAryOp(true, b1), Microsoft.Boogie.VCExprAST.VCExprNAryOp(b2))
Outcome = Valid
Time taken = 0.0013537
Number of true assignments = 1
Number of false assignments = 1
Prover time = 0.02
Unsat core prover time = 0.00
Number of prover queries = 2
Number of unsat core prover queries = 0
Number of unsat core prunings = 0
verified
Boogie program verifier finished with 1 verified, 0 errors
The "Houdini assignment axiom" lines print the raw .NET ToString() of a VCExprNAryOp.
The remaining options tune the search:
/reverseHoudiniWorklist pops implementations from the end of the worklist instead of the front.
/crossDependencies records, for each candidate, the other candidates that depend on it, so refuting one can requeue the others.
/useUnsatCoreForContractInfer uses unsat cores to prune candidates faster; it makes ProduceUnsatCores true.
/explainHoudini decorates each candidate with a pair of control constants so that, when a candidate is refuted, Boogie can say whether it was refuted positively or negatively. Its output is a Graphviz file always named explainHoudini.dot in the current directory —
there is no option to change the name — and it also makes ProduceModel true. /inlineDepth:n inlines callees to depth n before running Houdini. In Boogie this option affects only Houdini: Inliner.ProcessImplementation (the /inline path) hard-codes -1, while Inliner.ProcessImplementationForHoudini passes Options.InlineDepth. Inside the inliner a non-negative depth overrides every {:inline N} attribute and additionally strips assertions from the inlined bodies.
/dbgRefuted writes refuted candidates to the /xml sink. It does nothing without /xml.
15.11.3 Staged and concurrent Houdini
Option |
| Argument |
| Default |
/stagedHoudini:s |
| COARSE, FINE or BALANCED |
| off |
/stagedHoudiniThreads:n |
| integer |
| 1 |
/stagedHoudiniReachabilityAnalysis |
| none |
| off |
/stagedHoudiniMergeIgnoredAnnotations |
| none |
| off |
/debugStagedHoudini |
| none |
| off |
/concurrentHoudini |
| none |
| off |
/modifyTopologicalSorting |
| none |
| off |
/debugConcurrentHoudini |
| none |
| off |
/variableDependenceIgnore:file |
| file name |
| off |
All of these are undocumented.
/stagedHoudini:s assigns the candidate annotations to stages using the annotation-dependence analysis of AnnotationDependenceAnalyser and then runs the stages as separate Houdini instances; the argument selects the granularity of that assignment. Anything other than the three names is rejected with Boogie: Error: Invalid argument "BOGUS" to option /stagedHoudini. /stagedHoudiniThreads is the number of parallel instances; /stagedHoudiniReachabilityAnalysis builds the dependence graph with a real reachability check instead of the trivial one; /stagedHoudiniMergeIgnoredAnnotations merges annotations the variable-dependence analysis considers irrelevant; /debugStagedHoudini traces the planner.
/concurrentHoudini runs several Houdini instances in parallel, one per entry of Options.Cho, the per-task configuration list read by Houdini.GetErrorLimit. Boogie has no command-line option that populates Cho; only tools that subclass CommandLineOptions and fill it in programmatically (GPUVerify did) supply one. /debugConcurrentHoudini traces the exchange of refuted annotations between the instances, and /modifyTopologicalSorting switches the block orders used by live variable analysis and passification to the reversed topological sort (dag.TopologicalSort(true)).
/variableDependenceIgnore:file names a file of variable names to exclude from the variable-dependence analysis used by staged Houdini.
15.12 Inlining and loops
15.12.1 /inline and /printInlined
Option |
| Argument |
| Default |
/inline:i |
| none, assume, assert or spec |
| assume |
/printInlined |
| none |
| off |
Inlining happens only if some procedure or implementation carries an {:inline N} attribute; otherwise the pass is skipped entirely. /inline says what to do at a call site once the depth budget N runs out:
Value |
| At exhausted depth |
| Callee verified? |
assume |
| replace the call by assume false |
| no |
assert |
| replace the call by assert false |
| no |
spec |
| leave the call, using the contract |
| yes |
none |
| ignore the attribute entirely |
| yes |
procedure {:inline 1} Double(x: int) returns (y: int)
{
y := 2 * x;
}
procedure Main()
{
var a: int;
call a := Double(3);
assert a == 6;
}
With the default the call is expanded and Double itself is not verified. With /inline:none the call uses Double’s (empty) contract, so the assertion fails:
boogie cli-inline.bpl
boogie /inline:none cli-inline.bpl
Boogie program verifier finished with 1 verified, 0 errors
cli-inline.bpl(10,3): Error: this assertion could not be proved
Execution trace:
cli-inline.bpl(9,3): anon0
Boogie program verifier finished with 1 verified, 1 error
Which implementations get verified is easy to see with /trace:
for i in none assume assert spec ; do
boogie /inline:$i /trace cli-inline.bpl | grep -E 'Verifying|finished'
done
Verifying Double ...
Verifying Main ...
Boogie program verifier finished with 1 verified, 1 error
Verifying Main ...
Boogie program verifier finished with 1 verified, 0 errors
Verifying Main ...
Boogie program verifier finished with 1 verified, 0 errors
Verifying Double ...
Verifying Main ...
Boogie program verifier finished with 2 verified, 0 errors
/printInlined prints each implementation after expansion, to the console:
boogie /printInlined /noVerify cli-inline.bpl
after inlining procedure calls
procedure Main();
implementation Main()
{
var a: int;
var inline$Double$0$x: int;
var inline$Double$0$y: int;
anon0:
goto inline$Double$0$Entry;
inline$Double$0$Entry:
inline$Double$0$x := 3;
havoc inline$Double$0$y;
goto inline$Double$0$anon0;
inline$Double$0$anon0:
inline$Double$0$y := 2 * inline$Double$0$x;
goto inline$Double$0$Return;
inline$Double$0$Return:
a := inline$Double$0$y;
goto anon0$1;
anon0$1:
assert a == 6;
return;
}
Boogie program verifier finished with 0 verified, 0 errors
15.12.2 Loop options
Option |
| Argument |
| Default |
/loopUnroll:n |
| integer |
| -1 (do not unroll) |
/soundLoopUnrolling |
| none |
| off |
/kInductionDepth:k |
| integer |
| -1 (off) |
/extractLoops |
| none |
| off |
/deterministicExtractLoops |
| none |
| off |
/loopUnroll:n replaces each loop by n copies of its body and drops the executions that would need more iterations. That is unsound by design: a program that fails with a missing invariant may verify after unrolling.
procedure Sum(n: int) returns (s: int)
requires 0 <= n;
ensures 0 <= s;
{
var i: int;
i := 0; s := 0;
while (i < n) {
s := s + i;
i := i + 1;
}
}
boogie cli-loop.bpl
boogie /loopUnroll:3 cli-loop.bpl
cli-loop.bpl(7,3): Error: a postcondition could not be proved on this return path
cli-loop.bpl(3,3): Related location: this is the postcondition that could not be proved
Execution trace:
cli-loop.bpl(6,5): anon0
cli-loop.bpl(7,3): anon2_LoopDone
Boogie program verifier finished with 0 verified, 1 error
Boogie program verifier finished with 1 verified, 0 errors
/soundLoopUnrolling adds an assertion that the loop really does finish within the bound, which restores soundness and, here, reports the truncation:
boogie /loopUnroll:3 /soundLoopUnrolling cli-loop.bpl
cli-loop.bpl(7,3): Error: this assertion could not be proved
Execution trace:
cli-loop.bpl(6,5): anon0#3
cli-loop.bpl(8,7): anon2_LoopBody#3
cli-loop.bpl(8,7): anon2_LoopBody#2
cli-loop.bpl(8,7): anon2_LoopBody#1
cli-loop.bpl(7,3): anon2_LoopHead#0
Boogie program verifier finished with 0 verified, 1 error
/extractLoops converts irreducible loops to reducible form by node splitting and turns every loop into a recursive procedure, which then shows up as its own verification task:
boogie /extractLoops /trace cli-loop.bpl | grep -E 'Verifying|finished|Error'
Verifying Sum ...
cli-loop.bpl(7,3): Error: a postcondition could not be proved on this return path
Verifying Sum_loop_anon2_LoopHead ...
Boogie program verifier finished with 1 verified, 1 error
/deterministicExtractLoops removes the non-determinism the plain extraction introduces: the loop procedure’s entry block no longer has a nondeterministic branch to an immediate exit block, the blocks that break out of the loop are added to the loop’s footprint (so their assignments become out-parameters), and dead-end blocks are not given an assume false. Note that the name appears both as a case label taking no argument and as a boolean flag in the default branch; the case label wins, but the two do the same thing.
/kInductionDepth:k replaces loop reasoning with combined-case
k-induction, unwinding proportionally to k. It is sound but usually needs a
carefully chosen k; -1 disables it —
boogie /kInductionDepth:-1 cli-small.bpl ; echo "exit=$?"
Boogie: Error: Invalid argument "-1" to option /kInductionDepth
Use /help for available options
exit=1
-1 is only reachable as the field’s initial value, i.e. by not passing the option at all.
15.12.3 Stratified inlining
StratifiedInlining can only be set programmatically: no Boogie option turns it on, so /boolControlVC and the StratifiedInlining branches of ApplyDefaultOptions are reachable only from tools that subclass CommandLineOptions, such as Corral.
15.12.4 Lambda-lifting options
Option |
| Argument |
| Default |
/freeVarLambdaLifting |
| none |
| off |
/printLambdaLifting |
| none |
| off |
Lambda expressions are replaced by generated functions plus defining axioms. By default the generated function’s parameters are the maximal sub-expressions of the body that do not mention the bound variables. /freeVarLambdaLifting instead uses the lambda’s free variables.
function F(int): int;
procedure P(a: int)
{
var m: [int]int;
m := (lambda i: int :: i + F(a) + 1);
assert m[0] == F(a) + 1;
}
Both commands below print the program twice; only the second, post-lifting copy is reproduced here.
boogie /print:- /printLambdaLifting /env:0 cli-lambda.bpl
implementation P(a: int)
{
var m: [int]int;
m := lambda#0(F(a), 1);
assert m[0] == F(a) + 1;
}
// auto-generated lambda function
function lambda#0(l#0: int, l#1: int) : [int]int
uses {
axiom (forall l#0: int, l#1: int, i: int ::
{ lambda#0(l#0, l#1)[i] }
lambda#0(l#0, l#1)[i] == i + l#0 + l#1);
}
boogie /print:- /printLambdaLifting /freeVarLambdaLifting /env:0 cli-lambda.bpl
implementation P(a: int)
{
var m: [int]int;
m := lambda#0(a);
assert m[0] == F(a) + 1;
}
// auto-generated lambda function
function lambda#0(a: int) : [int]int
uses {
axiom (forall a: int, i: int :: { lambda#0(a)[i] } lambda#0(a)[i] == i + F(a) + 1);
}
15.12.5 /printMeasureDesugaring
measure clauses on procedures become a non-negativity precondition plus a decrease check on each recursive call. /printMeasureDesugaring, combined with /print, shows the result:
procedure Down(n: int)
requires 0 <= n;
measure n;
{
if (n > 0) {
call Down(n - 1);
}
}
boogie /print:- /printMeasureDesugaring /env:0 cli-measure.bpl
Again only the second copy is shown. The measure clause has become a requires n >= 0 and an assert before the recursive call; note that the desugaring point also forces unstructured printing:
procedure Down(n: int);
requires 0 <= n;
requires n >= 0;
implementation Down(n: int)
{
/*** structured program:
if (n > 0)
{
call Down(n - 1);
}
**** end structured program */
anon0:
goto anon2_Then, anon2_Else;
anon2_Else:
assume {:partition} 0 >= n;
return;
anon2_Then:
assume {:partition} n > 0;
assert n - 1 < old(n);
call Down(n - 1);
return;
}
15.13 Caching and snapshots
Option |
| Argument |
| Default |
/verifySnapshots:n |
| 0, 1, 2 or 3 |
| -1 (option absent) |
/traceCaching:n |
| 0, 1, 2 or 3 |
| 0 |
15.13.1 /verifySnapshots
The field is initialised to -1, but the argument must be in 0..3, so -1 means "the option was not given". This matters because the snapshot search is guarded by 0 <= VerifySnapshots: /verifySnapshots:0 is not the same as omitting the option.
When the option is present, the file names on the command line are treated as base names. For each f.bpl, Boogie looks for f.v0.bpl, f.v1.bpl, ... and verifies each existing version in turn, as a separate program. The base file itself is never opened:
snap/prog.v0.bpl declares two trivially correct procedures; snap/prog.v1.bpl is the same file with Q’s assertion changed to assert 2 == 3; and its checksum bumped.
ls snap/
prog.v0.bpl
prog.v1.bpl
boogie /verifySnapshots:0 snap/prog.bpl
Boogie program verifier finished with 2 verified, 0 errors
snap/prog.v1.bpl(8,3): Error: this assertion could not be proved
Execution trace:
snap/prog.v1.bpl(8,3): anon0
Boogie program verifier finished with 1 verified, 1 error
Without the option the same command fails, because snap/prog.bpl does not exist (the absolute path in the second half of the message has been shortened here):
boogie snap/prog.bpl
Error opening file "snap/prog.bpl": Could not find file '.../snap/prog.bpl'.
The levels are:
Level |
| Meaning |
0 |
| run every snapshot, no result caching |
1 |
| basic result caching |
2 |
| advanced caching: unchanged implementations are skipped, and partially-changed ones get cached facts injected |
3 |
| as 2, and errors are re-reported at the new source locations (excluding /errorTrace and {:captureState} locations) |
Caching keys off two attributes: {:checksum "..."} on procedures and implementations, and {:id "..."} on implementations. An implementation is skipped only when its own checksum and the checksum of everything it depends on are unchanged. The "retrieving" message goes through Printer.Inform, so it is visible only with /trace:
# Test/snapshots/Snapshots1.v{0,1,2}.bpl from Boogie's own test suite
boogie /verifySnapshots:2 /trace Snapshots1.bpl | grep -E 'Verifying|Retrieving|finished'
Verifying P1 ...
Verifying P2 ...
Boogie program verifier finished with 1 verified, 1 error
Retrieving cached verification result for implementation P1...
Verifying P2 ...
Boogie program verifier finished with 1 verified, 1 error
Verifying P1 ...
Verifying P2 ...
Boogie program verifier finished with 1 verified, 1 error
15.13.2 /traceCaching
Level |
| Meaning |
0 |
| nothing (default) |
1 |
| "for testing": log every cache action applied to a command |
2 |
| "for benchmarking": CSV statistics per request |
3 |
| both, plus debugging output |
Level 1 names each transformation applied to a command. The interesting entries appear on the snapshot that actually has cached facts to inject:
boogie /verifySnapshots:2 /traceCaching:1 Snapshots1.bpl | grep -A1 'Processing'
Processing command (at Snapshots1.v0.bpl(13,5)) assert 1 != 1;
>>> DoNothingToAssert
--
Processing command (at Snapshots1.v1.bpl(13,5)) assert 2 != 2;
>>> DoNothingToAssert
--
Processing call to procedure P2 in implementation P1 (at Snapshots1.v2.bpl(5,5)):
>>> added after: a##cached##0 := a##cached##0 && true;
Processing implementation P2 (at Snapshots1.v2.bpl(12,51)):
>>> added after assuming the current precondition: a##cached##0 := a##cached##0 && true;
Processing command (at Snapshots1.v2.bpl(5,5)) assert false;
>>> DoNothingToAssert
Processing command (at <unknown location>) a##cached##0 := a##cached##0 && true;
>>> AssumeNegationOfAssumptionVariable
--
Processing command (at Snapshots1.v2.bpl(14,5)) assert 2 != 2;
>>> DoNothingToAssert
Level 2 emits two CSV tables after each snapshot, and the tables are cumulative: one row per request seen so far. This is the pair printed after the second snapshot of Snapshots1 (the Time (ms) columns vary from run to run):
Cached verification result injector statistics as CSV:
Request ID, Transformed, Low, Medium, High, Skipped, Time (ms)
auto_request_id_1 , 0, 0, 0, 0, 0, 0
auto_request_id_2 , 1, 0, 1, 0, 1, 2
Statistics per request as CSV:
Request ID, Time (ms), Error, E (C), Inconclusive, I (C), Out of Memory, OoM (C), Timeout, T (C), Verified, V (C), DoNothingToAssert, MarkAsPartiallyVerified, MarkAsFullyVerified, RecycleError, AssumeNegationOfAssumptionVariable, DropAssume
auto_request_id_1 , 123, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0
auto_request_id_2 , 19, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0
Total time (ms) since first request: 156
The (C) columns count cached outcomes: auto_request_id_2 has V (C) = 1, one verification result taken from the cache.
/traceCaching is only meaningful together with /verifySnapshots.
15.14 Civl
Option |
| Argument |
| Default |
| Skips |
/trustMoverTypes |
| none |
| off |
| commutativity (mover) checks |
/trustInvariants |
| none |
| off |
| yield-invariant checks |
/trustRefinement |
| none |
| off |
| refinement checks and action refinement |
/trustNoninterference |
| none |
| off |
| noninterference instrumentation |
/trustLayersUpto:n |
| integer |
| -1 |
| all checks at layers <= n |
/trustLayersDownto:n |
| integer |
| int.MaxValue |
| all checks at layers >= n |
/civlDesugaredFile:file |
| file name |
| off |
| --- |
/warnNotEliminatedVars |
| none |
| off |
| --- |
The /trust* options remove classes of generated proof obligations. They are for
triage —
var {:layer 0,2} x: int;
right action {:layer 1,2} AtomicIncr()
modifies x;
{
x := x + 1;
}
yield procedure {:layer 0} Incr();
refines AtomicIncr;
atomic action {:layer 2,2} AtomicIncrTwice()
modifies x;
{
x := x + 2;
}
yield procedure {:layer 1} IncrTwice()
refines AtomicIncrTwice;
{
call Incr();
call Incr();
}
boogie /trace cli-civl.bpl | grep -E 'Verifying|finished'
Verifying Civl_CommutativityChecker_AtomicIncr_AtomicIncrTwice ...
Verifying Civl_IncrTwice_1 ...
Verifying Civl_IncrTwice_Refine_1 ...
Boogie program verifier finished with 3 verified, 0 errors
boogie /trace /trustMoverTypes cli-civl.bpl | grep -E 'Verifying|finished'
boogie /trace /trustRefinement cli-civl.bpl | grep -E 'Verifying|finished'
boogie /trace /trustLayersUpto:1 cli-civl.bpl | grep -E 'Verifying|finished'
Verifying Civl_IncrTwice_1 ...
Verifying Civl_IncrTwice_Refine_1 ...
Boogie program verifier finished with 2 verified, 0 errors
Verifying Civl_CommutativityChecker_AtomicIncr_AtomicIncrTwice ...
Verifying Civl_IncrTwice_1 ...
Boogie program verifier finished with 2 verified, 0 errors
Verifying Civl_CommutativityChecker_AtomicIncr_AtomicIncrTwice ...
Boogie program verifier finished with 1 verified, 0 errors
The layer options are applied in YieldingProcChecker as TrustLayersDownto <= layerNum || layerNum <= TrustLayersUpto, so they suppress the per-layer yielding-procedure and refinement checkers but not the commutativity checkers, which are not attached to a single layer. That is why /trustLayersUpto:1 above leaves the commutativity check in place.
/civlDesugaredFile:file writes the plain Boogie program that Civl
rewriting produced —
/warnNotEliminatedVars is undocumented. During transition-relation computation Civl tries to eliminate intermediate variables; with this flag TransitionRelationComputation.AddPath emits a warning of the form "<prefix>: could not eliminate variables {v, w, ...} on some path" for each path where some remained.
On a larger example the trust options are easier to weigh. Boogie’s own
Test/civl/samples/2pc.bpl generates 8 checks by default; /trustRefinement
leaves 7, /trustInvariants 5, /trustMoverTypes 4, /trustLayersUpto:1 4
and /trustLayersDownto:1 4. /trustNoninterference leaves all 8 —
Remember that any Civl attribute in the program implicitly turns on /lib:base and /inferModifies.
15.15 Verbosity, tracing and debugging
15.15.1 Verbosity levels
Verbosity is a four-valued enum, default Normal. Three flags move it:
Option |
| Level |
| Trailer |
| Errors |
| Progress |
/silent |
| Silent |
| no |
| no |
| no |
/quiet |
| Quiet |
| no |
| yes |
| no |
(none) |
| Normal |
| yes |
| yes |
| no |
/trace |
| Trace |
| yes |
| yes |
| yes |
The flags are not exclusive; the last one on the command line wins, since each simply assigns to Verbosity.
boogie /quiet cli-abs.bpl
cli-abs.bpl(11,1): Error: a postcondition could not be proved on this return path
cli-abs.bpl(8,3): Related location: this is the postcondition that could not be proved
Execution trace:
cli-abs.bpl(10,5): anon0
boogie /silent cli-abs.bpl ; echo "exit=$?"
exit=0
/silent on a failing program produces no output and exit code 0 —
15.15.2 /trace and friends
Option |
| Effect |
/trace |
| Per-phase progress, per-implementation timings, resource counts, split progress, and (as a side effect) BoogieDebug.DoPrinting = true. |
/traceTimes |
| Elapsed time at fixed pipeline points. |
/tracePOs |
| Proof-obligation counts per implementation. Also enables the Inform channel, so the "Verifying X ..." lines appear without /trace. |
/traceverify |
| Dump the program at each stage of VC generation. Very verbose. |
boogie /trace cli-small.bpl
Parsing cli-small.bpl
Coalescing blocks...
Inlining...
Verifying Abs ...
[TRACE] Using prover: z3
[0.026 s, solver resource count: 700, 1 proof obligation] verified
Boogie program verifier finished with 1 verified, 0 errors
boogie /traceTimes cli-small.bpl
>>> Becoming sentient [-4.61E-05 s]
>>> Starting resolution [0.0249093 s]
>>> Starting typechecking [0.0378237 s]
>>> Starting implementation verification [0.0857793 s]
>>> Starting live variable analysis [0.0938588 s]
>>> Finished implementation verification [0.1856154 s]
Boogie program verifier finished with 1 verified, 0 errors
Times are measured against Helpers.StartUp, a static field initialised the first time Helpers is touched. Since that happens inside the first ExtraTraceInformation call, the first figure is a small negative number.
boogie /tracePOs cli-abs.bpl
Verifying Abs ...
[1 proof obligation] verified
Verifying Bad ...
[1 proof obligation] error
cli-abs.bpl(11,1): Error: a postcondition could not be proved on this return path
cli-abs.bpl(8,3): Related location: this is the postcondition that could not be proved
Execution trace:
cli-abs.bpl(10,5): anon0
Boogie program verifier finished with 1 verified, 1 error
/traceverify dumps the implementation at each stage of VC generation. Even on the one-procedure program above it produces 204 lines, beginning:
boogie /traceverify cli-small.bpl | head -6
Desugaring of lambda expressions produced 0 functions and 0 axioms:
original implementation
implementation Abs(x: int) returns (r: int)
{
anon0:
15.16 Options with no effect, and undocumented options
15.16.1 Options with no effect
Option |
| Why |
/vcBrackets:b |
| BracketIdsInVC has no reader. |
/reflectAdd |
| Only VCExprASTPrinter consults it; the SMT-LIB lineariser does not. |
/boolControlVC |
| Stratified inlining only, which the Boogie CLI cannot enable. |
/useProverEvaluate |
| The evaluation path is used by Corral; in Boogie it only forces model production. |
15.16.2 Undocumented options
The following are accepted but do not appear in /help. They are documented above, in their functional sections.
Group |
| Options |
General |
| /?, /launch |
Printing |
| /printSplit, /printSplitDeclarations, /printLean |
Prover |
| /proverPreamble, /enableUnSatCoreExtraction, /useProverEvaluate, /boolControlVC |
Limits |
| /processTimeLimit, /timeLimitPerAssertionInPercent, /runDiagnosticsOnTimeout, /traceDiagnosticsOnTimeout |
VC generation |
| /noPruneInfeasibleEdges, /deterministicExtractLoops, /randomSeedIterations |
Inference |
| /inlineDepth, /printAssignment, /explainHoudini, /reverseHoudiniWorklist, /crossDependencies, /useUnsatCoreForContractInfer, /dbgRefuted, /stagedHoudini, /stagedHoudiniThreads, /stagedHoudiniReachabilityAnalysis, /stagedHoudiniMergeIgnoredAnnotations, /debugStagedHoudini, /concurrentHoudini, /modifyTopologicalSorting, /debugConcurrentHoudini, /variableDependenceIgnore |
Civl |
| /warnNotEliminatedVars |
15.17 Complete option index
Every option name the parser recognises, with its argument shape and the default value of the field it sets. flag means a boolean switch that takes no argument.
Option |
| Argument |
| Default |
| Section |
/? |
| flag |
|
| ||
/alwaysAssumeFreeLoopInvariants |
| flag |
| off |
| |
/attrHelp |
| flag |
|
| ||
/boolControlVC |
| flag |
| off |
| |
/break |
| flag |
|
| ||
/checkInfer |
| flag |
| off |
| |
/civlDesugaredFile:file |
| file |
| off |
| |
/coalesceBlocks:c |
| 0/1 |
| 1 |
| |
/concurrentHoudini |
| flag |
| off |
| |
/contractInfer |
| flag |
| off |
| |
/crossDependencies |
| flag |
| off |
| |
/dbgRefuted |
| flag |
| off |
| |
/debugConcurrentHoudini |
| flag |
| off |
| |
/debugStagedHoudini |
| flag |
| off |
| |
/deterministicExtractLoops |
| flag |
| off |
| |
/emitDebugInformation:n |
| 0/1 |
| 1 |
| |
/enableUnSatCoreExtraction:n |
| int |
| 0 |
| |
/enhancedErrorMessages:n |
| 0/1 |
| 0 |
| |
/env:n |
| 0/1/2 |
| 1 |
| |
/errorLimit:n |
| int |
| 5 |
| |
/errorTrace:n |
| 0/1/2 |
| 1 |
| |
/explainHoudini |
| flag |
| off |
| |
/extractLoops |
| flag |
| off |
| |
/forceBplErrors |
| flag |
| off |
| |
/freeVarLambdaLifting |
| flag |
| off |
| |
/help |
| flag |
|
| ||
/infer:flags |
| flag string |
| off |
| |
/inferModifies |
| flag |
| off |
| |
/inline:i |
| none/assume/assert/spec |
| assume |
| |
/inlineDepth:n |
| int |
| -1 |
| |
/instrumentInfer:c |
| h/e |
| h |
| |
/kInductionDepth:k |
| int |
| -1 |
| |
/launch |
| flag |
|
| ||
/keepQuantifier |
| flag |
| off |
| |
/lib:name |
| library name |
| none |
| |
/liveVariableAnalysis:c |
| 0/1/2 |
| 1 |
| |
/logPrefix:str |
| string |
| empty |
| |
/loopUnroll:n |
| int |
| -1 |
| |
/modifyTopologicalSorting |
| flag |
| off |
| |
/mv:file |
| file |
| off |
| |
/noProc:p |
| pattern |
| none |
| |
/noPruneInfeasibleEdges |
| flag |
| pruning on |
| |
/noResolve |
| flag |
| off |
| |
/noTypecheck |
| flag |
| off |
| |
/noVerify |
| flag |
| off |
| |
/normalizeDeclarationOrder:n |
| 0/1 |
| 1 |
| |
/normalizeNames:n |
| 0/1 |
| 0 |
| |
/overlookTypeErrors |
| flag |
| off |
| |
/p:KEY |
| prover option |
| none |
| |
/pretty:n |
| 0/1 |
| 1 |
| |
/print:file |
| file or - |
| off |
| |
/printAssignment |
| flag |
| off |
| |
/printCFG:prefix |
| prefix |
| off |
| |
/printDesugared |
| flag |
| off |
| |
/printInlined |
| flag |
| off |
| |
/printInstrumented |
| flag |
| off |
| |
/printLambdaLifting |
| flag |
| off |
| |
/printLean:file |
| file |
| off |
| |
/printMeasureDesugaring |
| flag |
| off |
| |
/printModel:n |
| 0/1 |
| 0 |
| |
/printModelToFile:file |
| file |
| off |
| |
/printPassive:file |
| file |
| off |
| |
/printPruned:prefix |
| prefix or - |
| off |
| |
/printSplit:prefix |
| prefix or - |
| off |
| |
/printSplitDeclarations |
| flag |
| off |
| |
/printUnstructured |
| flag |
| off |
| |
/printVerifiedProceduresCount:n |
| 0/1 |
| 1 |
| |
/printWithUniqueIds |
| flag |
| off |
| |
/proc:p |
| pattern |
| none |
| |
/processTimeLimit:n |
| uint seconds |
| 0 |
| |
/proverDll:tp |
| name or path |
| SMTLib |
| |
/proverHelp |
| flag |
|
| ||
/proverLog:file |
| file |
| off |
| |
/proverLogAppend |
| flag |
| off |
| |
/proverOpt:KEY |
| prover option |
| none |
| |
/proverPreamble:file |
| file |
| off |
| |
/proverWarnings:n |
| 0/1/2 |
| 0 |
| |
/prune:n |
| 0/1 |
| 0 |
| |
/quiet |
| flag |
|
| ||
/randomizeVcIterations:n |
| int >= 1 |
| 1 |
| |
/randomSeed:s |
| int |
| unset |
| |
/randomSeedIterations:n |
| int >= 1 |
| 1 |
| |
/reflectAdd |
| flag |
| off |
| |
/relaxFocus |
| flag |
| off |
| |
/removeEmptyBlocks:c |
| 0/1 |
| 1 |
| |
/restartProver |
| flag |
| off |
| |
/reverseHoudiniWorklist |
| flag |
| off |
| |
/rlimit:n |
| uint |
| 0 |
| |
/runDiagnosticsOnTimeout |
| flag |
| off |
| |
/silent |
| flag |
|
| ||
/smoke |
| flag |
| off |
| |
/smokeTimeout:n |
| uint seconds |
| 10 |
| |
/soundLoopUnrolling |
| flag |
| off |
| |
/stagedHoudini:s |
| COARSE/FINE/BALANCED |
| off |
| |
/stagedHoudiniMergeIgnoredAnnotations |
| flag |
| off |
| |
/stagedHoudiniReachabilityAnalysis |
| flag |
| off |
| |
/stagedHoudiniThreads:n |
| int |
| 1 |
| |
/subsumption:c |
| 0/1/2 |
| 2 |
| |
/timeLimit:n |
| uint seconds |
| 0 |
| |
/timeLimitPerAssertionInPercent:n |
| uint > 0 |
| 10 |
| |
/trace |
| flag |
|
| ||
/traceCaching:n |
| 0..3 |
| 0 |
| |
/traceDiagnosticsOnTimeout |
| flag |
| off |
| |
/tracePOs |
| flag |
| off |
| |
/traceTimes |
| flag |
| off |
| |
/traceverify |
| flag |
| off |
| |
/trackVerificationCoverage |
| flag |
| off |
| |
/trustInvariants |
| flag |
| off |
| |
/trustLayersDownto:n |
| int |
| int.MaxValue |
| |
/trustLayersUpto:n |
| int |
| -1 |
| |
/trustMoverTypes |
| flag |
| off |
| |
/trustNoninterference |
| flag |
| off |
| |
/trustRefinement |
| flag |
| off |
| |
/typeEncoding:t |
| m/p/a |
| m |
| |
/useArrayAxioms |
| flag |
| off |
| |
/useBaseNameForFileName |
| flag |
| off |
| |
/useProverEvaluate |
| flag |
| off |
| |
/useUnsatCoreForContractInfer |
| flag |
| off |
| |
/variableDependenceIgnore:file |
| file |
| off |
| |
/vcBrackets:b |
| 0/1 |
| -1 |
| |
/vcsAssumeMult:f |
| double |
| 0.01 |
| |
/vcsCores:n |
| int >= 1 |
| 1 |
| |
/vcsDumpSplits |
| flag |
| off |
| |
/vcsFinalAssertTimeout:n |
| uint seconds |
| 30 |
| |
/vcsKeepGoingTimeout:n |
| uint seconds |
| 1 |
| |
/vcsLoad:f |
| double < 3.0 |
|
| ||
/vcsMaxCost:f |
| double |
| 1.0 |
| |
/vcsMaxKeepGoingSplits:n |
| int |
| 1 |
| |
/vcsMaxSplits:n |
| int |
| 1 |
| |
/vcsPathCostMult:f |
| double |
| 1.0 |
| |
/vcsPathJoinMult:f |
| double |
| 0.8 |
| |
/vcsPathSplitMult:f |
| double |
| 0.5 |
| |
/vcsSplitOnEveryAssert |
| flag |
| off |
| |
/verifySeparately |
| flag |
| off |
| |
/verifySnapshots:n |
| 0..3 |
| -1 |
| |
/version |
| flag |
|
| ||
/wait |
| flag |
| off |
| |
/warnNotEliminatedVars |
| flag |
| off |
| |
/warnVacuousProofs |
| flag |
| off |
| |
/xml:file |
| file |
| off |
|