Skip to main content

Viper Output (--viper)

Emit Viper code for manual inspection, debugging, or understanding how Sector9 translates contracts and permissions.

The --viper flag runs the translation pipeline and outputs the intermediate Viper representation to stdout without invoking the SMT solver. This is the same Viper program shape that --verify sends to Silicon.

Basic Usage

sector9 --viper file.sr9

Output goes to stdout. Redirect to a file for inspection:

sector9 --viper file.sr9 > output.vpr

When to Use --viper

Use --viper when you need to:

  1. Debug verification failures - Understand how your contracts are encoded
  2. Inspect quantifier triggers - See what triggers were inferred or applied
  3. Learn the translation - Study how Sector9 constructs map to Viper primitives
  4. Test Viper edits directly - Modify generated code and test hypotheses
  5. Diagnose permission issues - See how reads/modifies become acc(...) permissions

Example

Given this Sector9 source:

persistent actor ArithmeticAdd {
public func add(a : Int, b : Int) : async Int
ensures result == a + b;
{
a + b
};
}

Running sector9 --viper add.sr9 produces Viper code including:

method add($Self: Ref, a: Int, b: Int) returns ($Res: Int)
requires $Inv($Self)
ensures ($Inv($Self) && ($Res == (a + b)))
{
$Res := (a + b);
goto $Ret;
label $Ret;
$expire_borrows(2);
}

Key observations:

  • result becomes $Res in the postcondition
  • The actor invariant $Inv($Self) is required and ensured
  • The async method becomes a synchronous Viper method
  • Control flow uses labels and gotos

Output Structure

The generated .vpr file has these sections:

1. Prelude Import

import "/tmp/sector9/sector9/prelude.vpr"

The prelude contains array encoding, method tokens, numeric bounds helpers, and definitions shared across verification programs.

2. Per-File Definitions

Type-specific field declarations and array initialization methods:

field $array$int: Int
field $array$nat: Int

method $Array_init$nat($n: Int) returns ($arr: Array)
requires $n >= 0
ensures $size($arr) == $n
ensures $array_acc($arr, $array$nat, write)
ensures $nat_array_bounds($arr)

3. Imported Modules

Methods and functions from imported modules:

/* --- Imported Modules --- */
method $alloc_actor() returns ($r: Ref)
ensures (($r != null) && true)

4. Spec Functions

Pure functions translated as Viper functions (prefixed with $spec$):

/* --- Spec Functions --- */
function $spec$Math$square(p$x: Int): Int
{
(p$x * p$x)
}

5. Async Infrastructure

Future payload domains encoding async return values:

/* --- Async Infrastructure --- */
domain $FuturePayload {
function $Consumed(): $FuturePayload
function $F_add($F_add$0: Int, ...): $FuturePayload
// Discriminators, destructors, and axioms
}

6. Actor

Methods, fields, invariants, and predicates:

/* --- Actor --- */
field fld$count: Int

method increment($Self: Ref)
requires $Inv($Self)
ensures $Inv($Self)
{ ... }

predicate $Inv($Self: Ref) {
acc(($Self).fld$count, write) && ($Self).fld$count >= 0
}

--viper vs --verify

Aspect--viper--verify
TranslationYesYes
SMT solvingNoYes
OutputViper code to stdoutVerification result
SpeedFastSlower (depends on proof)
Use caseDebugging, learningPre-deployment validation

With --verify

When using --verify, you can save the intermediate Viper:

# Save Viper while verifying
sector9 --verify --verify-vpr-out output.vpr file.sr9

# Keep Viper files even on success (normally deleted)
sector9 --verify --viper-keep-vpr file.sr9

Integer Modes

The --int-mode flag affects the current Viper verification encoding. Use checked; the Viper lane rejects bitvec and unchecked today.

# Checked fixed-width arithmetic encoding (the verified lane)
sector9 --viper --int-mode checked file.sr9

Other Useful Flags

# Suppress warnings in output
sector9 --viper --hide-warnings file.sr9

# Ensure deterministic output (for diffing)
sector9 --viper --deterministic file.sr9

Debugging Workflow

When verification fails with --verify, use --viper to investigate:

# 1. Verification fails
sector9 --package core ./core/src --verify my_actor.sr9
# Error: Postcondition might not hold

# 2. Generate Viper to inspect
sector9 --package core ./core/src --viper my_actor.sr9 > debug.vpr

# 3. Examine the encoding
# - Check how your contract was translated
# - Look for permission issues (acc(...))
# - Inspect quantifier triggers

# 4. Optionally test Viper edits directly
./scripts/verify-vpr.sh debug.vpr

scripts/verify-vpr.sh runs raw Silicon with one verifier worker by default. Use VERIFY_VPR_PARALLEL_VERIFIERS=N only when you are deliberately comparing Silicon worker counts; for repeatable generated-VPR baselines, keep the default and parallelize multiple files outside the helper.

What to Look For in Viper Output

Contracts

  • requires becomes method preconditions
  • ensures becomes method postconditions
  • result becomes $Res in postconditions
  • old(...) becomes a snapshot expression captured at method entry or at the relevant labeled point

Fields and Permissions

  • modifies x generates acc(($Self).fld$x, write) permission
  • reads x generates acc(($Self).fld$x, wildcard) permission
  • Actor invariants become $Inv($Self) predicates
  • Mutable records introduce generated Owned$MutRec$... predicates; see mutable record ownership.

Quantifiers

forall i: Int :: {arr[i]} 0 <= i && i < len ==> arr[i] >= 0
^^^^^^^^^^^^^
This is the trigger

Triggers guide SMT solver instantiation. Missing or bad triggers cause performance issues.

Collections

  • Map<K, V> becomes Map[K, V]
  • Set<T> becomes Set[T]
  • Seq<T> becomes Seq[T]

Operations lower into Viper collection operations such as map lookup, set membership, sequence length, and multiset cardinality. Use the emitted .vpr to inspect the exact encoding for a proof.

Exit Codes

CodeMeaning
0Translation succeeded, Viper emitted
1Translation failed (type errors, unsupported features)
2Invalid arguments

Troubleshooting

Output is empty or minimal

Run --check first for source, import, and type errors. Translation only runs on well-formed programs.

"Unsupported" errors

Some inherited or advanced Sector9 constructs are not yet supported for verification. Check the current limitations documentation.

Determinism issues

If the same file produces different Viper output on different runs, use --deterministic:

sector9 --viper --deterministic file.sr9 > a.vpr
sector9 --viper --deterministic file.sr9 > b.vpr
diff a.vpr b.vpr # Should be identical

Summary

  • --viper outputs the Viper intermediate representation without verifying
  • Useful for debugging verification failures and understanding the translation
  • Combine with --verify-vpr-out to save Viper during verification
  • The output shows how contracts, fields, and collections are encoded
  • Use this to diagnose permission issues, quantifier triggers, and encoding problems