package libsail

  1. Overview
  2. Docs

Compile Sail builtins to SMT bitvector expressions

type checks

The main limitiation when converting Sail into pure SMT bitvectors is that Sail has arbitrary precision types, as well as types like real and string that are not very SMT friendly. We can add dynamic assertions that effectivly check at runtime that we never exceed some upper bound on bitvector size, and log if we ever use features like strings or real numbers.

type 'a check_writer

We generate primitives in a monad that accumulates any required dynamic checks, and contains the location information for any error messages.

val current_location : Parse_ast.l check_writer

The SMT generation monad contains the location of the expression or definition we are generating SMT for

val return : 'a -> 'a check_writer
val bind : 'a check_writer -> ('a -> 'b check_writer) -> 'b check_writer
val fmap : ('a -> 'b) -> 'a check_writer -> 'b check_writer
val let* : 'a check_writer -> ('a -> 'b check_writer) -> 'b check_writer
val let+ : 'a check_writer -> ('a -> 'b) -> 'b check_writer
val mapM : ('a -> 'b check_writer) -> 'a list -> 'b list check_writer
val run : 'a check_writer -> Parse_ast.l -> 'a * checks
val signed_size : ?checked:bool -> into:int -> from:int -> Smt_exp.smt_exp -> Smt_exp.smt_exp check_writer

Convert a SMT bitvector expression of size from into a SMT bitvector expression of size into with the same signed value. When into < from inserts a dynamic check that the original value is representable at the new length.

val unsigned_size : ?max_value:int -> ?checked:bool -> into:int -> from:int -> Smt_exp.smt_exp -> Smt_exp.smt_exp check_writer

Similar to signed_size, except it assumes the bitvector is representing an unsigned value.

bvint sz n Create a (two's complement) SMT bitvector representing a the number n in a bitvector of length sz. Raises an error if this is not possible.

module type CONFIG = sig ... end
module type PRIMOP_GEN = sig ... end

Some Sail primitives we can't directly convert to pure SMT bitvectors, either because they don't exist in SMTLIB (like count_leading_zeros), or they involve input/output. In these cases we provide a module so the backend can generate the required implementations for these primitives.

module Make (Config : CONFIG) (Primop_gen : PRIMOP_GEN) : sig ... end