summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/_tags11
-rw-r--r--src/bitfield.ml51
-rw-r--r--src/initial_check.ml7
-rw-r--r--src/interpreter.ml222
-rw-r--r--src/isail.ml113
-rw-r--r--src/myocamlbuild.ml5
-rw-r--r--src/ocaml_backend.ml2
-rw-r--r--src/rewrites.ml3
-rw-r--r--src/sail.ml8
-rw-r--r--src/sail_lib.ml4
-rw-r--r--src/type_check.ml16
-rw-r--r--src/type_check.mli2
-rw-r--r--src/value.ml104
13 files changed, 451 insertions, 97 deletions
diff --git a/src/_tags b/src/_tags
index efe34d17..f1d54db1 100644
--- a/src/_tags
+++ b/src/_tags
@@ -1,15 +1,16 @@
true: -traverse, debug, use_menhir
<**/*.ml>: bin_annot, annot
# <lem_interp> or <test>: include
-<sail.{byte,native}>: package(zarith), use_pprint, use_nums, use_unix, use_str, use_lem
-<isail.{byte,native}>: package(zarith), package(linenoise), use_pprint, use_nums, use_unix, use_str, use_lem
+<sail.{byte,native}>: package(zarith), use_pprint, use_unix, use_str, package(lem)
+<isail.{byte,native}>: package(zarith), package(linenoise), package(linksem), package(lem), use_pprint
<isail.ml>: package(linenoise)
+<elf_loader.ml>: package(linksem)
<pprint> or <pprint/src>: include
-<*.m{l,li}>: use_lem
+<*.m{l,li}>: package(lem)
# see http://caml.inria.fr/mantis/view.php?id=4943
-<lem_interp/*> and not <lem_interp/*.cmxa>: use_nums, use_lem
-<test/*> and not <test/*.cmxa>: use_nums, use_lem, use_str
+<lem_interp/*> and not <lem_interp/*.cmxa>: use_nums, package(lem)
+<test/*> and not <test/*.cmxa>: use_nums, package(lem), use_str
# disable partial match and unused variable warnings
<**/*.ml>: warn_y
diff --git a/src/bitfield.ml b/src/bitfield.ml
index 0a32654d..db3411b1 100644
--- a/src/bitfield.ml
+++ b/src/bitfield.ml
@@ -1,3 +1,52 @@
+(**************************************************************************)
+(* Sail *)
+(* *)
+(* Copyright (c) 2013-2017 *)
+(* Kathyrn Gray *)
+(* Shaked Flur *)
+(* Stephen Kell *)
+(* Gabriel Kerneis *)
+(* Robert Norton-Wright *)
+(* Christopher Pulte *)
+(* Peter Sewell *)
+(* Alasdair Armstrong *)
+(* Brian Campbell *)
+(* Thomas Bauereiss *)
+(* Anthony Fox *)
+(* Jon French *)
+(* Dominic Mulligan *)
+(* Stephen Kell *)
+(* Mark Wassell *)
+(* *)
+(* All rights reserved. *)
+(* *)
+(* This software was developed by the University of Cambridge Computer *)
+(* Laboratory as part of the Rigorous Engineering of Mainstream Systems *)
+(* (REMS) project, funded by EPSRC grant EP/K008528/1. *)
+(* *)
+(* Redistribution and use in source and binary forms, with or without *)
+(* modification, are permitted provided that the following conditions *)
+(* are met: *)
+(* 1. Redistributions of source code must retain the above copyright *)
+(* notice, this list of conditions and the following disclaimer. *)
+(* 2. Redistributions in binary form must reproduce the above copyright *)
+(* notice, this list of conditions and the following disclaimer in *)
+(* the documentation and/or other materials provided with the *)
+(* distribution. *)
+(* *)
+(* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' *)
+(* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *)
+(* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *)
+(* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR *)
+(* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, *)
+(* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT *)
+(* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF *)
+(* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND *)
+(* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, *)
+(* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT *)
+(* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF *)
+(* SUCH DAMAGE. *)
+(**************************************************************************)
module Big_int = Nat_big_num
@@ -18,6 +67,7 @@ let newtype name size order =
let nt = Printf.sprintf "newtype %s = Mk_%s : %s" name name (bitvec size order) in
ast_of_def_string order nt
+(* These functions define the getter and setter for all the bits in the field. *)
let full_getter name size order =
let fg_val = Printf.sprintf "val _get_%s : %s -> %s" name name (bitvec size order) in
let fg_function = Printf.sprintf "function _get_%s Mk_%s(v) = v" name name in
@@ -41,6 +91,7 @@ let full_overload name order =
let full_accessor name size order =
combine [full_getter name size order; full_setter name size order; full_overload name order]
+(* For every index range, create a getter and setter *)
let index_range_getter' name field order start stop =
let size = if start > stop then start - (stop - 1) else stop - (start - 1) in
let irg_val = Printf.sprintf "val _get_%s : %s -> %s" field name (bitvec size order) in
diff --git a/src/initial_check.ml b/src/initial_check.ml
index 4e466596..28579291 100644
--- a/src/initial_check.ml
+++ b/src/initial_check.ml
@@ -964,7 +964,8 @@ let typschm_of_string order str =
let (typschm, _, _) = to_ast_typschm initial_kind_env order typschm in
typschm
-let val_spec_of_string order id str = mk_val_spec (VS_val_spec (typschm_of_string order str, id, (fun _ -> Some (string_of_id id)), false))
+let extern_of_string order id str = mk_val_spec (VS_val_spec (typschm_of_string order str, id, (fun _ -> Some (string_of_id id)), false))
+let val_spec_of_string order id str = mk_val_spec (VS_val_spec (typschm_of_string order str, id, (fun _ -> None), false))
let val_spec_ids (Defs defs) =
let val_spec_id (VS_aux (vs_aux, _)) =
@@ -1003,7 +1004,7 @@ let have_undefined_builtins = ref false
let generate_undefineds vs_ids (Defs defs) =
let gen_vs id str =
- if (IdSet.mem id vs_ids) then [] else [val_spec_of_string dec_ord id str]
+ if (IdSet.mem id vs_ids) then [] else [extern_of_string dec_ord id str]
in
let undefined_builtins =
if !have_undefined_builtins then
@@ -1022,7 +1023,7 @@ let generate_undefineds vs_ids (Defs defs) =
gen_vs (mk_id "undefined_list") "forall ('a:Type). 'a -> list('a) effect {undef}";
gen_vs (mk_id "undefined_range") "forall 'n 'm. (atom('n), atom('m)) -> range('n,'m) effect {undef}";
(* FIXME: How to handle inc/dec order correctly? *)
- gen_vs (mk_id "undefined_vector") "forall 'n ('a:Type). (atom('n), 'a) -> vector('n, dec,'a) effect {undef}";
+ gen_vs (mk_id "undefined_vector") "forall 'n ('a:Type) ('ord : Order). (atom('n), 'a) -> vector('n, 'ord,'a) effect {undef}";
(* Only used with lem_mwords *)
gen_vs (mk_id "undefined_bitvector") "forall 'n. atom('n) -> vector('n, dec, bit) effect {undef}";
gen_vs (mk_id "undefined_unit") "unit -> unit effect {undef}"]
diff --git a/src/interpreter.ml b/src/interpreter.ml
index 7a4b6b33..59b20a17 100644
--- a/src/interpreter.ml
+++ b/src/interpreter.ml
@@ -54,7 +54,7 @@ open Value
type gstate =
{ registers : value Bindings.t;
- letbinds : (Type_check.tannot letbind) list
+ letbinds : (Type_check.tannot letbind) list;
}
type lstate =
@@ -70,7 +70,7 @@ let rec ast_letbinds (Defs defs) =
let initial_gstate ast =
{ registers = Bindings.empty;
- letbinds = ast_letbinds ast
+ letbinds = ast_letbinds ast;
}
let initial_lstate =
@@ -179,6 +179,22 @@ let assertion_failed msg = Yield (Assertion_failed msg)
let liftM2 f m1 m2 = m1 >>= fun x -> m2 >>= fun y -> return (f x y)
+let rec pat_ids (P_aux (pat_aux, _)) =
+ match pat_aux with
+ | P_lit _ | P_wild -> IdSet.empty
+ | P_id id -> IdSet.singleton id
+ | P_as (pat, id) -> IdSet.add id (pat_ids pat)
+ | P_var (pat, _) | P_typ (_, pat) -> pat_ids pat
+ | P_app (_, pats) | P_tup pats | P_vector pats | P_vector_concat pats | P_list pats ->
+ List.fold_right IdSet.union (List.map pat_ids pats) IdSet.empty
+ | P_cons (pat1, pat2) ->
+ IdSet.union (pat_ids pat1) (pat_ids pat2)
+ | P_record (fpats, _) ->
+ List.fold_right IdSet.union (List.map fpat_ids fpats) IdSet.empty
+and fpat_ids (FP_aux (FP_Fpat (_, pat), _)) = pat_ids pat
+
+let letbind_pat_ids (LB_aux (LB_val (pat, _), _)) = pat_ids pat
+
let rec subst id value (E_aux (e_aux, annot) as exp) =
let wrap e_aux = E_aux (e_aux, annot) in
let e_aux = match e_aux with
@@ -187,34 +203,96 @@ let rec subst id value (E_aux (e_aux, annot) as exp) =
| E_id id' -> if Id.compare id id' = 0 then unaux_exp (exp_of_value value) else E_id id'
| E_lit lit -> E_lit lit
| E_cast (typ, exp) -> E_cast (typ, subst id value exp)
+
| E_app (fn, exps) -> E_app (fn, List.map (subst id value) exps)
| E_app_infix (exp1, op, exp2) -> E_app_infix (subst id value exp1, op, subst id value exp2)
+
| E_tuple exps -> E_tuple (List.map (subst id value) exps)
- | E_assign (lexp, exp) -> E_assign (subst_lexp id value lexp, subst id value exp) (* Shadowing... *)
- | E_let (LB_aux (LB_val (pat, bind), lb_annot), body) ->
- (* TODO: Fix shadowing *)
- E_let (LB_aux (LB_val (pat, subst id value bind), lb_annot), subst id value body)
+
| E_if (cond, then_exp, else_exp) ->
E_if (subst id value cond, subst id value then_exp, subst id value else_exp)
+
+ | E_loop (loop, cond, body) ->
+ E_loop (loop, subst id value cond, subst id value body)
+ | E_for (id', exp1, exp2, exp3, order, body) when Id.compare id id' = 0 ->
+ E_for (id', exp1, exp2, exp3, order, body)
+ | E_for (id', exp1, exp2, exp3, order, body) ->
+ E_for (id', subst id value exp1, subst id value exp2, subst id value exp3, order, subst id value body)
+
| E_vector exps -> E_vector (List.map (subst id value) exps)
+ | E_vector_access (exp1, exp2) -> E_vector_access (subst id value exp1, subst id value exp2)
+ | E_vector_subrange (exp1, exp2, exp3) -> E_vector_subrange (subst id value exp1, subst id value exp2, subst id value exp3)
+ | E_vector_update (exp1, exp2, exp3) -> E_vector_update (subst id value exp1, subst id value exp2, subst id value exp3)
+ | E_vector_update_subrange (exp1, exp2, exp3, exp4) ->
+ E_vector_update_subrange (subst id value exp1, subst id value exp2, subst id value exp3, subst id value exp4)
+ | E_vector_append (exp1, exp2) -> E_vector_append (subst id value exp1, subst id value exp2)
+
+ | E_list exps -> E_list (List.map (subst id value) exps)
+ | E_cons (exp1, exp2) -> E_cons (subst id value exp1, subst id value exp2)
+
+ | E_record fexps -> E_record (subst_fexps id value fexps)
+ | E_record_update (exp, fexps) -> E_record_update (subst id value exp, subst_fexps id value fexps)
+ | E_field (exp, id') -> E_field (subst id value exp, id')
+
+ | E_case (exp, pexps) ->
+ E_case (subst id value exp, List.map (subst_pexp id value) pexps)
+
+ | E_let (LB_aux (LB_val (pat, bind), lb_annot), body) ->
+ E_let (LB_aux (LB_val (pat, subst id value bind), lb_annot),
+ if IdSet.mem id (pat_ids pat) then body else subst id value body)
+
+ | E_assign (lexp, exp) -> E_assign (subst_lexp id value lexp, subst id value exp) (* Shadowing... *)
+
+ (* Should be re-written *)
+ | E_sizeof nexp -> E_sizeof nexp
+ | E_constraint nc -> E_constraint nc
+
| E_return exp -> E_return (subst id value exp)
+ | E_exit exp -> E_exit (subst id value exp)
+ (* Not sure about this, but id should always be immutable while id' must be mutable so should be ok. *)
+ | E_ref id' -> E_ref id'
+ | E_throw exp -> E_throw (subst id value exp)
+
+ | E_try (exp, pexps) ->
+ E_try (subst id value exp, List.map (subst_pexp id value) pexps)
+
| E_assert (exp1, exp2) -> E_assert (subst id value exp1, subst id value exp2)
+
| E_internal_value v -> E_internal_value v
| _ -> failwith ("subst " ^ string_of_exp exp)
in
wrap e_aux
+and subst_pexp id value (Pat_aux (pexp_aux, annot)) =
+ let pexp_aux = match pexp_aux with
+ | Pat_exp (pat, exp) when IdSet.mem id (pat_ids pat) -> Pat_exp (pat, exp)
+ | Pat_exp (pat, exp) -> Pat_exp (pat, subst id value exp)
+ | Pat_when (pat, guard, exp) when IdSet.mem id (pat_ids pat) -> Pat_when (pat, guard, exp)
+ | Pat_when (pat, guard, exp) -> Pat_when (pat, subst id value guard, subst id value exp)
+ in
+ Pat_aux (pexp_aux, annot)
+
+
+and subst_fexps id value (FES_aux (FES_Fexps (fexps, flag), annot)) =
+ FES_aux (FES_Fexps (List.map (subst_fexp id value) fexps, flag), annot)
+
+and subst_fexp id value (FE_aux (FE_Fexp (id', exp), annot)) =
+ FE_aux (FE_Fexp (id', subst id value exp), annot)
+
and subst_lexp id value (LEXP_aux (lexp_aux, annot) as lexp) =
let wrap lexp_aux = LEXP_aux (lexp_aux, annot) in
let lexp_aux = match lexp_aux with
| LEXP_deref exp -> LEXP_deref (subst id value exp)
| LEXP_id id' -> LEXP_id id'
| LEXP_memory (f, exps) -> LEXP_memory (f, List.map (subst id value) exps)
- | _ -> failwith ("subst lexp")
+ | LEXP_cast (typ, id') -> LEXP_cast (typ, id')
+ | LEXP_tup lexps -> LEXP_tup (List.map (subst_lexp id value) lexps)
+ | LEXP_vector (lexp, exp) -> LEXP_vector (subst_lexp id value lexp, subst id value exp)
+ | LEXP_vector_range (lexp, exp1, exp2) -> LEXP_vector_range (subst_lexp id value lexp, subst id value exp1, subst id value exp2)
+ | LEXP_field (lexp, id') -> LEXP_field (subst_lexp id value lexp, id')
in
wrap lexp_aux
-
(**************************************************************************)
(* 2. Expression Evaluation *)
(**************************************************************************)
@@ -224,13 +302,14 @@ let unit_exp = E_lit (L_aux (L_unit, Parse_ast.Unknown))
let is_value_fexp (FE_aux (FE_Fexp (id, exp), _)) = is_value exp
let value_of_fexp (FE_aux (FE_Fexp (id, exp), _)) = (string_of_id id, value_of_exp exp)
-let rec build_letchain lbs (E_aux (_, annot) as exp) =
- print_endline ("LETCHAIN " ^ string_of_exp exp);
+let rec build_letchain id lbs (E_aux (_, annot) as exp) =
+ (* print_endline ("LETCHAIN " ^ string_of_exp exp); *)
match lbs with
| [] -> exp
- | lb :: lbs ->
+ | lb :: lbs when IdSet.mem id (letbind_pat_ids lb)->
let exp = E_aux (E_let (lb, exp), annot) in
- build_letchain lbs exp
+ build_letchain id lbs exp
+ | _ :: lbs -> build_letchain id lbs exp
let rec step (E_aux (e_aux, annot) as orig_exp) =
let wrap e_aux' = return (E_aux (e_aux', annot)) in
@@ -248,6 +327,12 @@ let rec step (E_aux (e_aux, annot) as orig_exp) =
| E_if (exp, then_exp, else_exp) ->
step exp >>= fun exp' -> wrap (E_if (exp', then_exp, else_exp))
+ | E_loop (While, exp, body) when not (is_value exp) ->
+ step exp >>= fun exp' -> wrap (E_loop (While, exp', body))
+ | E_loop (While, exp, body) when is_true exp -> wrap (E_block [body; orig_exp])
+ | E_loop (While, exp, body) when is_false exp -> wrap unit_exp
+ | E_loop _ -> assert false (* Impossible *)
+
| E_assert (exp, msg) when is_true exp -> wrap unit_exp
| E_assert (exp, msg) when is_false exp -> assertion_failed "FIXME"
| E_assert (exp, msg) ->
@@ -262,6 +347,15 @@ let rec step (E_aux (e_aux, annot) as orig_exp) =
| [] -> return (exp_of_value (V_vector (List.map value_of_exp evaluated)))
end
+ | E_list exps ->
+ let evaluated, unevaluated = Util.take_drop is_value exps in
+ begin
+ match unevaluated with
+ | exp :: exps ->
+ step exp >>= fun exp' -> wrap (E_list (evaluated @ exp' :: exps))
+ | [] -> return (exp_of_value (V_list (List.map value_of_exp evaluated)))
+ end
+
(* Special rules for short circuting boolean operators *)
| E_app (id, [x; y]) when (string_of_id id = "and_bool" || string_of_id id = "or_bool") && not (is_value x) ->
step x >>= fun x' -> wrap (E_app (id, [x'; y]))
@@ -273,7 +367,7 @@ let rec step (E_aux (e_aux, annot) as orig_exp) =
| E_let (LB_aux (LB_val (pat, bind), lb_annot), body) when not (is_value bind) ->
step bind >>= fun bind' -> wrap (E_let (LB_aux (LB_val (pat, bind'), lb_annot), body))
| E_let (LB_aux (LB_val (pat, bind), lb_annot), body) ->
- let matched, bindings = pattern_match pat (value_of_exp bind) in
+ let matched, bindings = pattern_match (Type_check.env_of orig_exp) pat (value_of_exp bind) in
if matched then
return (List.fold_left (fun body (id, v) -> subst id v body) body (Bindings.bindings bindings))
else
@@ -323,16 +417,29 @@ let rec step (E_aux (e_aux, annot) as orig_exp) =
step exp >>= fun exp' -> wrap (E_case (exp', pexps))
| E_case (_, []) -> failwith "Pattern matching failed"
| E_case (exp, Pat_aux (Pat_exp (pat, body), _) :: pexps) ->
- let matched, bindings = pattern_match pat (value_of_exp exp) in
+ let matched, bindings = pattern_match (Type_check.env_of body) pat (value_of_exp exp) in
if matched then
return (List.fold_left (fun body (id, v) -> subst id v body) body (Bindings.bindings bindings))
else
wrap (E_case (exp, pexps))
+ | E_case (exp, Pat_aux (Pat_when (pat, guard, body), pat_annot) :: pexps) when not (is_value guard) ->
+ let matched, bindings = pattern_match (Type_check.env_of body) pat (value_of_exp exp) in
+ if matched then
+ let guard = List.fold_left (fun guard (id, v) -> subst id v guard) guard (Bindings.bindings bindings) in
+ let body = List.fold_left (fun body (id, v) -> subst id v body) body (Bindings.bindings bindings) in
+ step guard >>= fun guard' ->
+ wrap (E_case (exp, Pat_aux (Pat_when (pat, guard', body), pat_annot) :: pexps))
+ else
+ wrap (E_case (exp, pexps))
+ | E_case (exp, Pat_aux (Pat_when (pat, guard, body), pat_annot) :: pexps) when is_true guard -> return body
+ | E_case (exp, Pat_aux (Pat_when (pat, guard, body), pat_annot) :: pexps) when is_false guard -> wrap (E_case (exp, pexps))
| E_cast (typ, exp) -> return exp
| E_throw exp when is_value exp -> throw (value_of_exp exp)
| E_throw exp -> step exp >>= fun exp' -> wrap (E_throw exp')
+ | E_exit exp when is_value exp -> throw (V_ctor ("Exit", [value_of_exp exp]))
+ | E_exit exp -> step exp >>= fun exp' -> wrap (E_exit exp')
| E_ref id -> return (exp_of_value (V_ref (string_of_id id)))
| E_id id ->
@@ -350,9 +457,10 @@ let rec step (E_aux (e_aux, annot) as orig_exp) =
return exp
| Local (Mutable, _) -> return (exp_of_value (Bindings.find id lstate.locals))
| Local (Immutable, _) ->
- let chain = build_letchain gstate.letbinds orig_exp in
- print_endline "CHAINED";
+ let chain = build_letchain id gstate.letbinds orig_exp in
return chain
+ | Enum _ ->
+ return (exp_of_value (V_ctor (string_of_id id, [])))
| _ -> failwith "id"
end
@@ -388,19 +496,23 @@ let rec step (E_aux (e_aux, annot) as orig_exp) =
|> return
end
+ | E_field (exp, id) when not (is_value exp) ->
+ step exp >>= fun exp' -> wrap (E_field (exp', id))
+ | E_field (exp, id) ->
+ let record = coerce_record (value_of_exp exp) in
+ return (exp_of_value (StringMap.find (string_of_id id) record))
+
| E_assign (lexp, exp) when not (is_value exp) -> step exp >>= fun exp' -> wrap (E_assign (lexp, exp'))
| E_assign (LEXP_aux (LEXP_memory (id, args), _), exp) -> wrap (E_app (id, args @ [exp]))
- | E_assign (LEXP_aux (LEXP_field (lexp, id), _), exp) ->
+ | E_assign (LEXP_aux (LEXP_field (lexp, id), ul), exp) ->
let open Type_check in
let lexp_exp = infer_exp (env_of_annot annot) (exp_of_lexp (strip_lexp lexp)) in
- let ul = (Parse_ast.Unknown, None) in
let exp' = E_aux (E_record_update (lexp_exp, FES_aux (FES_Fexps ([FE_aux (FE_Fexp (id, exp), ul)], false), ul)), ul) in
wrap (E_assign (lexp, exp'))
- | E_assign (LEXP_aux (LEXP_vector (vec, n), _), exp) ->
+ | E_assign (LEXP_aux (LEXP_vector (vec, n), lexp_annot), exp) ->
let open Type_check in
let vec_exp = infer_exp (env_of_annot annot) (exp_of_lexp (strip_lexp vec)) in
- let ul = (Parse_ast.Unknown, None) in
- let exp' = E_aux (E_vector_update (vec_exp, n, exp), ul) in
+ let exp' = E_aux (E_vector_update (vec_exp, n, exp), lexp_annot) in
wrap (E_assign (vec, exp'))
| E_assign (LEXP_aux (LEXP_id id, _), exp) | E_assign (LEXP_aux (LEXP_cast (_, id), _), exp) ->
begin
@@ -419,7 +531,12 @@ let rec step (E_aux (e_aux, annot) as orig_exp) =
let id = Id_aux (Id (coerce_ref (value_of_exp reference)), Parse_ast.Unknown) in
gets >>= fun (lstate, gstate) ->
puts (lstate, { gstate with registers = Bindings.add id (value_of_exp exp) gstate.registers }) >> wrap unit_exp
- | E_assign _ -> assert false
+ | E_assign (LEXP_aux (LEXP_tup lexps, annot), exp) -> failwith "Tuple assignment"
+ (*
+ let values = coerce_tuple (value_of_exp exp) in
+ wrap (E_block (List.map2 (fun lexp v -> E_aux (E_assign (lexp, exp_of_value v), (Parse_ast.Unknown, None))) lexps values))
+ *)
+ | E_assign _ -> failwith (string_of_exp orig_exp);
| E_try (exp, pexps) when is_value exp -> return exp
| E_try (exp, pexps) ->
@@ -452,40 +569,51 @@ and exp_of_lexp (LEXP_aux (lexp_aux, _) as lexp) =
| LEXP_field (lexp, id) -> mk_exp (E_field (exp_of_lexp lexp, id))
and lexp_assign (LEXP_aux (lexp_aux, _) as lexp) value =
- print_endline ("Assigning: " ^ string_of_lexp lexp ^ " to " ^ string_of_value value |> Util.yellow |> Util.clear);
+ (* print_endline ("Assigning: " ^ string_of_lexp lexp ^ " to " ^ string_of_value value |> Util.yellow |> Util.clear); *)
match lexp_aux with
| LEXP_id id -> Bindings.singleton id value
| _ -> failwith "Unhandled lexp_assign"
-and pattern_match (P_aux (p_aux, _) as pat) value =
- print_endline ("Matching: " ^ string_of_pat pat ^ " with " ^ string_of_value value |> Util.yellow |> Util.clear);
+and pattern_match env (P_aux (p_aux, _) as pat) value =
+ (* print_endline ("Matching: " ^ string_of_pat pat ^ " with " ^ string_of_value value |> Util.yellow |> Util.clear); *)
match p_aux with
| P_lit lit -> eq_value (value_of_lit lit) value, Bindings.empty
| P_wild -> true, Bindings.empty
| P_as (pat, id) ->
- let matched, bindings = pattern_match pat value in
+ let matched, bindings = pattern_match env pat value in
matched, Bindings.add id value bindings
- | P_typ (_, pat) -> pattern_match pat value
- | P_id id -> true, Bindings.singleton id value
- | P_var (pat, _) -> pattern_match pat value
+ | P_typ (_, pat) -> pattern_match env pat value
+ | P_id id ->
+ let open Type_check in
+ begin
+ match Env.lookup_id id env with
+ | Enum _ | Union _ ->
+ if is_ctor value && string_of_id id = fst (coerce_ctor value)
+ then true, Bindings.empty
+ else false, Bindings.empty
+ | _ -> true, Bindings.singleton id value
+ end
+ | P_var (pat, _) -> pattern_match env pat value
| P_app (id, pats) ->
let (ctor, vals) = coerce_ctor value in
if Id.compare id (mk_id ctor) = 0 then
- let matches = List.map2 pattern_match pats vals in
+ let matches = List.map2 (pattern_match env) pats vals in
List.for_all fst matches, List.fold_left (Bindings.merge combine) Bindings.empty (List.map snd matches)
else
false, Bindings.empty
| P_record _ -> assert false (* TODO *)
- | P_vector _ -> assert false (* TODO *)
+ | P_vector pats ->
+ let matches = List.map2 (pattern_match env) pats (coerce_gv value) in
+ List.for_all fst matches, List.fold_left (Bindings.merge combine) Bindings.empty (List.map snd matches)
| P_vector_concat _ -> assert false (* TODO *)
| P_tup pats | P_list pats ->
- let matches = List.map2 pattern_match pats (coerce_listlike value) in
+ let matches = List.map2 (pattern_match env) pats (coerce_listlike value) in
List.for_all fst matches, List.fold_left (Bindings.merge combine) Bindings.empty (List.map snd matches)
| P_cons _ -> assert false (* TODO *)
-let exp_of_fundef (FD_aux (FD_function (_, _, _, funcls), _)) value =
+let exp_of_fundef (FD_aux (FD_function (_, _, _, funcls), annot)) value =
let pexp_of_funcl (FCL_aux (FCL_Funcl (_, pexp), _)) = pexp in
- E_aux (E_case (exp_of_value value, List.map pexp_of_funcl funcls), (Parse_ast.Unknown, None))
+ E_aux (E_case (exp_of_value value, List.map pexp_of_funcl funcls), annot)
let rec get_fundef id (Defs defs) =
match defs with
@@ -500,31 +628,45 @@ let stack_state (_, lstate, _) = lstate
type frame =
| Done of state * value
| Step of string * state * (Type_check.tannot exp) monad * (string * lstate * (value -> (Type_check.tannot exp) monad)) list
+ | Break of frame
-let rec eval_frame ast = function
+let rec eval_frame' ast = function
| Done (state, v) -> Done (state, v)
+ | Break frame -> Break frame
| Step (out, state, m, stack) ->
match (m, stack) with
| Pure v, [] when is_value v -> Done (state, value_of_exp v)
| Pure v, (head :: stack') when is_value v ->
- print_endline ("Returning value: " ^ string_of_value (value_of_exp v) |> Util.cyan |> Util.clear);
+ (* print_endline ("Returning value: " ^ string_of_value (value_of_exp v) |> Util.cyan |> Util.clear); *)
Step (stack_string head, (stack_state head, snd state), stack_cont head (value_of_exp v), stack')
| Pure exp', _ ->
let out' = Pretty_print_sail.to_string (Pretty_print_sail.doc_exp exp') in
Step (out', state, step exp', stack)
+ | Yield (Call(id, vals, cont)), _ when string_of_id id = "break" ->
+ let arg = if List.length vals != 1 then tuple_value vals else List.hd vals in
+ let body = exp_of_fundef (get_fundef id ast) arg in
+ Break (Step ("", (initial_lstate, snd state), return body, (out, fst state, cont) :: stack))
| Yield (Call(id, vals, cont)), _ ->
- print_endline ("Calling " ^ string_of_id id |> Util.cyan |> Util.clear);
+ (* print_endline ("Calling " ^ string_of_id id |> Util.cyan |> Util.clear); *)
let arg = if List.length vals != 1 then tuple_value vals else List.hd vals in
let body = exp_of_fundef (get_fundef id ast) arg in
Step ("", (initial_lstate, snd state), return body, (out, fst state, cont) :: stack)
| Yield (Gets cont), _ ->
- eval_frame ast (Step (out, state, cont state, stack))
+ eval_frame' ast (Step (out, state, cont state, stack))
| Yield (Puts (state', cont)), _ ->
- eval_frame ast (Step (out, state', cont (), stack))
+ eval_frame' ast (Step (out, state', cont (), stack))
| Yield (Early_return v), [] -> Done (state, v)
| Yield (Early_return v), (head :: stack') ->
- print_endline ("Returning value: " ^ string_of_value v |> Util.cyan |> Util.clear);
+ (* print_endline ("Returning value: " ^ string_of_value v |> Util.cyan |> Util.clear); *)
Step (stack_string head, (stack_state head, snd state), stack_cont head v, stack')
| Yield (Assertion_failed msg), _ ->
failwith msg
+ | Yield (Exception v), _ ->
+ print_endline ("Uncaught Exception" |> Util.cyan |> Util.clear);
+ Done (state, v)
| _ -> assert false
+
+let eval_frame ast frame =
+ try eval_frame' ast frame with
+ | Type_check.Type_error (l, err) ->
+ raise (Reporting_basic.err_typ l (Type_check.string_of_type_error err))
diff --git a/src/isail.ml b/src/isail.ml
index 5452b7a9..6b60581b 100644
--- a/src/isail.ml
+++ b/src/isail.ml
@@ -76,7 +76,10 @@ let rec user_input callback =
| None -> ()
| Some v ->
mode_clear ();
- callback v;
+ begin
+ try callback v with
+ | Reporting_basic.Fatal_error e -> Reporting_basic.report_error e
+ end;
user_input callback
let termcode n = "\x1B[" ^ string_of_int n ^ "m"
@@ -86,25 +89,72 @@ let clear str = str ^ termcode 0
let sail_logo =
let banner str = str |> bold |> red |> clear in
- [ " ___ ___ ___ ___ ";
- " /\\ \\ /\\ \\ /\\ \\ /\\__\\";
- " /::\\ \\ /::\\ \\ _\\:\\ \\ /:/ /";
- " /\\:\\:\\__\\ /::\\:\\__\\ /\\/::\\__\\ /:/__/ ";
- " \\:\\:\\/__/ \\/\\::/ / \\::/\\/__/ \\:\\ \\ ";
- " \\::/ / /:/ / \\:\\__\\ \\:\\__\\";
- " \\/__/ \\/__/ \\/__/ \\/__/";
+ [ {| ___ ___ ___ ___ |};
+ {| /\ \ /\ \ /\ \ /\__\|};
+ {| /::\ \ /::\ \ _\:\ \ /:/ /|};
+ {| /\:\:\__\ /::\:\__\ /\/::\__\ /:/__/ |};
+ {| \:\:\/__/ \/\::/ / \::/\/__/ \:\ \ |};
+ {| \::/ / /:/ / \:\__\ \:\__\|};
+ {| \/__/ \/__/ \/__/ \/__/|};
""
]
|> List.map banner
let vs_ids = ref (Initial_check.val_spec_ids !interactive_ast)
+let print_program () =
+ match !current_mode with
+ | Normal -> ()
+ | Evaluation (Step (out, _, _, stack)) ->
+ let sep = "-----------------------------------------------------" |> Util.blue |> Util.clear in
+ List.map stack_string stack |> List.rev |> List.iter (fun code -> print_endline code; print_endline sep);
+ print_endline out
+ | Evaluation _ -> ()
+
+let interactive_state = ref (initial_state !interactive_ast)
+
+let rec run () =
+ match !current_mode with
+ | Normal -> ()
+ | Evaluation frame ->
+ begin
+ match frame with
+ | Done (state, v) ->
+ interactive_state := state;
+ print_endline ("Result = " ^ Value.string_of_value v);
+ current_mode := Normal
+ | Step (out, state, _, stack) ->
+ current_mode := Evaluation (eval_frame !interactive_ast frame);
+ run ()
+ | Break frame ->
+ print_endline "Breakpoint";
+ current_mode := Evaluation frame
+ end
+
+let rec run_steps n =
+ match !current_mode with
+ | _ when n <= 0 -> ()
+ | Normal -> ()
+ | Evaluation frame ->
+ begin
+ match frame with
+ | Done (state, v) ->
+ interactive_state := state;
+ print_endline ("Result = " ^ Value.string_of_value v);
+ current_mode := Normal
+ | Step (out, state, _, stack) ->
+ current_mode := Evaluation (eval_frame !interactive_ast frame);
+ run_steps (n - 1)
+ | Break frame ->
+ print_endline "Breakpoint";
+ current_mode := Evaluation frame
+ end
+
let handle_input input =
+ LNoise.history_add input |> ignore;
match !current_mode with
| Normal ->
begin
- LNoise.history_add input |> ignore;
-
if input <> "" && input.[0] = ':' then
let n = try String.index input ' ' with Not_found -> String.length input in
let cmd = Str.string_before input n in
@@ -114,37 +164,50 @@ let handle_input input =
let typq, typ = Type_check.Env.get_val_spec (mk_id arg) !interactive_env in
pretty_sail stdout (doc_binding (typq, typ));
print_newline ();
- | ":q" | ":quit" ->
- exit 0
+ | ":elf" ->
+ Elf_loader.load_elf arg
+ | ":q" | ":quit" -> exit 0
| ":i" | ":infer" ->
let exp = Initial_check.exp_of_string dec_ord arg in
let exp = Type_check.infer_exp !interactive_env exp in
pretty_sail stdout (doc_typ (Type_check.typ_of exp));
print_newline ()
| ":v" | ":verbose" ->
- Type_check.opt_tc_debug := (!Type_check.opt_tc_debug + 1) mod 2
+ Type_check.opt_tc_debug := (!Type_check.opt_tc_debug + 1) mod 3;
+ print_endline ("Verbosity: " ^ string_of_int !Type_check.opt_tc_debug)
| _ -> print_endline ("Unrecognised command " ^ input)
else if input <> "" then
let exp = Type_check.infer_exp !interactive_env (Initial_check.exp_of_string Ast_util.dec_ord input) in
- current_mode := Evaluation (eval_frame !interactive_ast (Step ("", initial_state !interactive_ast, return exp, [])))
+ current_mode := Evaluation (eval_frame !interactive_ast (Step ("", !interactive_state, return exp, [])));
+ print_program ()
else ()
end
| Evaluation frame ->
begin
- match frame with
- | Done (_, v) ->
- print_endline ("Result = " ^ Value.string_of_value v);
- current_mode := Normal
- | Step (out, _, _, stack) ->
- let sep = "-----------------------------------------------------" |> Util.blue |> Util.clear in
- List.map stack_string stack |> List.rev |> List.iter (fun code -> print_endline code; print_endline sep);
- print_endline out;
- current_mode := Evaluation (eval_frame !interactive_ast frame)
+ if input <> "" && input.[0] = ':' then
+ let n = try String.index input ' ' with Not_found -> String.length input in
+ let cmd = Str.string_before input n in
+ let arg = String.trim (Str.string_after input n) in
+ match cmd with
+ | ":r" | ":run" ->
+ run ()
+ | ":s" | ":step" ->
+ run_steps (int_of_string arg)
+ | ":q" | ":quit" -> exit 0
+ | _ -> print_endline ("Unrecognised command " ^ input)
+ else
+ match frame with
+ | Done (state, v) ->
+ interactive_state := state;
+ print_endline ("Result = " ^ Value.string_of_value v);
+ current_mode := Normal
+ | Step (out, state, _, stack) ->
+ interactive_state := state;
+ current_mode := Evaluation (eval_frame !interactive_ast frame);
+ print_program ()
end
-
-
let () =
(* Auto complete function names based on val specs *)
LNoise.set_completion_callback
diff --git a/src/myocamlbuild.ml b/src/myocamlbuild.ml
index 1babc1c9..ae58f7b2 100644
--- a/src/myocamlbuild.ml
+++ b/src/myocamlbuild.ml
@@ -69,8 +69,6 @@ let split ch s =
let lem_dir =
try Sys.getenv "LEM_DIR" (* LEM_DIR must contain an absolute path *)
with Not_found -> "../../../lem" ;;
-let lem_libdir = lem_dir / "ocaml-lib" / "_build_zarith";;
-let lem_lib = lem_libdir / "extract" ;;
let lem = lem_dir / "lem" ;;
(* All -wl ignores should be removed if you want to see the pattern compilation, exhaustive, and unused var warnings *)
@@ -85,9 +83,8 @@ let lem_opts = [A "-lib"; P "../lem_interp";
dispatch begin function
| After_rules ->
(* ocaml_lib "lem_interp/interp"; *)
- ocaml_lib ~extern:true ~dir:lem_libdir ~tag_name:"use_lem" lem_lib;
ocaml_lib ~extern:false ~dir:"pprint/src" ~tag_name:"use_pprint" "pprint/src/PPrintLib";
-
+
rule "lem -> ml"
~prod: "%.ml"
~dep: "%.lem"
diff --git a/src/ocaml_backend.ml b/src/ocaml_backend.ml
index 89220356..55695114 100644
--- a/src/ocaml_backend.ml
+++ b/src/ocaml_backend.ml
@@ -647,7 +647,7 @@ let ocaml_main spec =
^//^ (string "Random.self_init ();"
^/^ string "load_elf ();"
^/^ string (if !opt_trace_ocaml then "Sail_lib.opt_trace := true;" else "Sail_lib.opt_trace := false;")
- ^/^ string "initialize_registers ();"
+ ^/^ string "zinitializze_registers ();"
^/^ string "Printexc.record_backtrace true;"
^/^ string "zmain ()")
]
diff --git a/src/rewrites.ml b/src/rewrites.ml
index 2ecaf91d..3b74d38a 100644
--- a/src/rewrites.ml
+++ b/src/rewrites.ml
@@ -2924,6 +2924,9 @@ let rewrite_defs_ocaml = [
]
let rewrite_defs_interpreter = [
+ ("tuple_vector_assignments", rewrite_tuple_vector_assignments);
+ ("tuple_assignments", rewrite_tuple_assignments);
+ ("remove_vector_concat", rewrite_defs_remove_vector_concat);
("constraint", rewrite_constraint);
("trivial_sizeof", rewrite_trivial_sizeof);
("sizeof", rewrite_sizeof);
diff --git a/src/sail.ml b/src/sail.ml
index 974885c6..eee80045 100644
--- a/src/sail.ml
+++ b/src/sail.ml
@@ -60,7 +60,6 @@ let opt_print_lem_ast = ref false
let opt_print_lem = ref false
let opt_print_sil = ref false
let opt_print_ocaml = ref false
-let opt_convert = ref false
let opt_memo_z3 = ref false
let opt_sanity = ref false
let opt_libs_lem = ref ([]:string list)
@@ -118,9 +117,6 @@ let options = Arg.align ([
( "-no_effects",
Arg.Set Type_check.opt_no_effects,
" (experimental) turn off effect checking");
- ( "-convert",
- Arg.Set opt_convert,
- " (experimental) convert sail to new syntax for use with -new_parser");
( "-just_check",
Arg.Set opt_just_check,
" (experimental) terminate immediately after typechecking");
@@ -185,10 +181,6 @@ let main() =
-> Parse_ast.Defs (ast_nodes@later_nodes)) parsed (Parse_ast.Defs []) in
let ast = convert_ast Ast_util.inc_ord ast in
- if !opt_convert
- then (Pretty_print_sail.pp_defs stdout ast; exit 0)
- else ();
-
let (ast, type_envs) = check_ast ast in
let (ast, type_envs) =
diff --git a/src/sail_lib.ml b/src/sail_lib.ml
index b4dffba9..72974b9a 100644
--- a/src/sail_lib.ml
+++ b/src/sail_lib.ml
@@ -87,10 +87,10 @@ let undefined_bit () =
let undefined_bool () =
if !random then Random.bool () else false
-let rec undefined_vector (start_index, len, item) =
+let rec undefined_vector (len, item) =
if Big_int.equal len Big_int.zero
then []
- else item :: undefined_vector (start_index, Big_int.sub len (Big_int.of_int 1), item)
+ else item :: undefined_vector (Big_int.sub len (Big_int.of_int 1), item)
let undefined_string () = ""
diff --git a/src/type_check.ml b/src/type_check.ml
index 3269de1d..b77d800e 100644
--- a/src/type_check.ml
+++ b/src/type_check.ml
@@ -76,7 +76,7 @@ type type_error =
(* First parameter is the error that caused us to start doing type
coercions, the second is the errors encountered by all possible
coercions *)
- | Err_no_casts of type_error * type_error list
+ | Err_no_casts of unit exp * type_error * type_error list
| Err_no_overloading of id * (id * type_error) list
| Err_unresolved_quants of id * quant_item list
| Err_subtype of typ * typ * n_constraint list
@@ -86,11 +86,13 @@ type type_error =
let pp_type_error err =
let open PPrint in
let rec pp_err = function
- | Err_no_casts (trigger, []) ->
- (string "Tried performing type coercion because" ^//^ pp_err trigger)
- ^/^ string "No possible coercions"
- | Err_no_casts (trigger, errs) ->
- (string "Tried performing type coerction because" ^//^ pp_err trigger)
+ | Err_no_casts (exp, trigger, []) ->
+ (string "Tried performing type coercion on" ^//^ Pretty_print_sail.doc_exp exp)
+ ^/^ (string "Failed because" ^//^ pp_err trigger)
+ ^/^ string "There were no possible casts"
+ | Err_no_casts (exp, trigger, errs) ->
+ (string "Tried performing type coercion on" ^//^ Pretty_print_sail.doc_exp exp)
+ ^/^ string "Failed because" ^//^ pp_err trigger
| Err_no_overloading (id, errs) ->
string ("No overloadings for " ^ string_of_id id ^ ", tried:") ^//^
group (separate_map hardline (fun (id, err) -> string (string_of_id id) ^^ colon ^^ space ^^ pp_err err) errs)
@@ -2173,7 +2175,7 @@ and type_coercion env (E_aux (_, (l, _)) as annotated_exp) typ =
| _ -> failwith "Cannot switch type for unannotated function"
in
let rec try_casts trigger errs = function
- | [] -> typ_raise l (Err_no_casts (trigger, errs))
+ | [] -> typ_raise l (Err_no_casts (strip_exp annotated_exp, trigger, errs))
| (cast :: casts) -> begin
typ_print ("Casting with " ^ string_of_id cast ^ " expression " ^ string_of_exp annotated_exp ^ " to " ^ string_of_typ typ);
try
diff --git a/src/type_check.mli b/src/type_check.mli
index 33615e43..b43cab6b 100644
--- a/src/type_check.mli
+++ b/src/type_check.mli
@@ -56,7 +56,7 @@ val opt_tc_debug : int ref
val opt_no_effects : bool ref
type type_error =
- | Err_no_casts of type_error * type_error list
+ | Err_no_casts of unit exp * type_error * type_error list
| Err_no_overloading of id * (id * type_error) list
| Err_unresolved_quants of id * quant_item list
| Err_subtype of typ * typ * n_constraint list
diff --git a/src/value.ml b/src/value.ml
index d9690899..2ddeecae 100644
--- a/src/value.ml
+++ b/src/value.ml
@@ -186,6 +186,10 @@ let value_append = function
| [v1; v2] -> V_vector (coerce_gv v1 @ coerce_gv v2)
| _ -> failwith "value append"
+let value_slice = function
+ | [v1; v2; v3] -> V_vector (Sail_lib.slice (coerce_gv v1, coerce_int v2, coerce_int v3))
+ | _ -> failwith "value slice"
+
let value_not = function
| [v] -> V_bool (not (coerce_bool v))
| _ -> failwith "value not"
@@ -214,6 +218,21 @@ let value_get_slice_int = function
| [v1; v2; v3] -> mk_vector (Sail_lib.get_slice_int (coerce_int v1, coerce_int v2, coerce_int v3))
| _ -> failwith "value get_slice_int"
+let value_set_slice_int = function
+ | [v1; v2; v3; v4] ->
+ V_int (Sail_lib.set_slice_int (coerce_int v1, coerce_int v2, coerce_int v3, coerce_bv v4))
+ | _ -> failwith "value set_slice_int"
+
+let value_set_slice = function
+ | [v1; v2; v3; v4; v5] ->
+ mk_vector (Sail_lib.set_slice (coerce_int v1, coerce_int v2, coerce_bv v3, coerce_int v4, coerce_bv v5))
+ | _ -> failwith "value set_slice"
+
+let value_hex_slice = function
+ | [v1; v2; v3] ->
+ mk_vector (Sail_lib.hex_slice (coerce_string v1, coerce_int v2, coerce_int v3))
+ | _ -> failwith "value hex_slice"
+
let value_add = function
| [v1; v2] -> V_int (Sail_lib.add (coerce_int v1, coerce_int v2))
| _ -> failwith "value add"
@@ -222,6 +241,46 @@ let value_sub = function
| [v1; v2] -> V_int (Sail_lib.sub (coerce_int v1, coerce_int v2))
| _ -> failwith "value sub"
+let value_mult = function
+ | [v1; v2] -> V_int (Sail_lib.mult (coerce_int v1, coerce_int v2))
+ | _ -> failwith "value mult"
+
+let value_quotient = function
+ | [v1; v2] -> V_int (Sail_lib.quotient (coerce_int v1, coerce_int v2))
+ | _ -> failwith "value quotient"
+
+let value_modulus = function
+ | [v1; v2] -> V_int (Sail_lib.modulus (coerce_int v1, coerce_int v2))
+ | _ -> failwith "value modulus"
+
+let value_add_vec_int = function
+ | [v1; v2] -> mk_vector (Sail_lib.add_vec_int (coerce_bv v1, coerce_int v2))
+ | _ -> failwith "value add_vec_int"
+
+let value_add_vec = function
+ | [v1; v2] -> mk_vector (Sail_lib.add_vec (coerce_bv v1, coerce_bv v2))
+ | _ -> failwith "value add_vec"
+
+let value_sub_vec = function
+ | [v1; v2] -> mk_vector (Sail_lib.sub_vec (coerce_bv v1, coerce_bv v2))
+ | _ -> failwith "value sub_vec"
+
+let value_shl_int = function
+ | [v1; v2] -> V_int (Sail_lib.shl_int (coerce_int v1, coerce_int v2))
+ | _ -> failwith "value shl_int"
+
+let value_shr_int = function
+ | [v1; v2] -> V_int (Sail_lib.shr_int (coerce_int v1, coerce_int v2))
+ | _ -> failwith "value shr_int"
+
+let value_max_int = function
+ | [v1; v2] -> V_int (Sail_lib.max_int (coerce_int v1, coerce_int v2))
+ | _ -> failwith "value max_int"
+
+let value_min_int = function
+ | [v1; v2] -> V_int (Sail_lib.min_int (coerce_int v1, coerce_int v2))
+ | _ -> failwith "value min_int"
+
let value_replicate_bits = function
| [v1; v2] -> mk_vector (Sail_lib.replicate_bits (coerce_bv v1, coerce_int v2))
| _ -> failwith "value replicate_bits"
@@ -230,6 +289,11 @@ let is_bit = function
| V_bit _ -> true
| _ -> false
+
+let is_ctor = function
+ | V_ctor _ -> true
+ | _ -> false
+
let rec string_of_value = function
| V_vector vs when List.for_all is_bit vs -> Sail_lib.string_of_bits (List.map coerce_bit vs)
| V_vector vs -> "[" ^ Util.string_of_list ", " string_of_value vs ^ "]"
@@ -257,10 +321,28 @@ let value_print = function
| [v] -> print_endline (string_of_value v |> Util.red |> Util.clear); V_unit
| _ -> assert false
+let value_internal_pick = function
+ | [v1] -> List.hd (coerce_listlike v1);
+ | _ -> failwith "value internal_pick"
+
let value_undefined_vector = function
- | [v1; v2; v3] -> V_vector (Sail_lib.undefined_vector (coerce_int v1, coerce_int v2, v3))
+ | [v1; v2] -> V_vector (Sail_lib.undefined_vector (coerce_int v1, v2))
| _ -> failwith "value undefined_vector"
+let value_read_ram = function
+ | [v1; v2; v3; v4] -> mk_vector (Sail_lib.read_ram (coerce_int v1, coerce_int v2, coerce_bv v3, coerce_bv v4))
+ | _ -> failwith "value read_ram"
+
+let value_write_ram = function
+ | [v1; v2; v3; v4; v5] ->
+ Sail_lib.write_ram (coerce_int v1, coerce_int v2, coerce_bv v3, coerce_bv v4, coerce_bv v5);
+ V_unit
+ | _ -> failwith "value write_ram"
+
+let value_putchar = function
+ | [v] -> Sail_lib.putchar (coerce_int v); V_unit
+ | _ -> failwith "value putchar"
+
let primops =
List.fold_left
(fun r (x, y) -> StringMap.add x y r)
@@ -269,6 +351,7 @@ let primops =
("or_bool", or_bool);
("print_endline", value_print);
("prerr_endline", value_print);
+ ("putchar", value_putchar);
("string_of_bits", fun vs -> V_string (string_of_value (List.hd vs)));
("print_bits", fun [msg; bits] -> print_endline (coerce_string msg ^ string_of_value bits); V_unit);
("eq_int", value_eq_int);
@@ -284,6 +367,7 @@ let primops =
("access", value_access);
("update", value_update);
("update_subrange", value_update_subrange);
+ ("slice", value_slice);
("append", value_append);
("not", value_not);
("not_vec", value_not_vec);
@@ -292,10 +376,28 @@ let primops =
("uint", value_uint);
("sint", value_sint);
("get_slice_int", value_get_slice_int);
+ ("set_slice_int", value_set_slice_int);
+ ("set_slice", value_set_slice);
+ ("hex_slice", value_hex_slice);
("add", value_add);
("sub", value_sub);
+ ("mult", value_mult);
+ ("quotient", value_quotient);
+ ("modulus", value_modulus);
+ ("shr_int", value_shr_int);
+ ("shl_int", value_shl_int);
+ ("max_int", value_max_int);
+ ("min_int", value_min_int);
+ ("add_vec_int", value_add_vec_int);
+ ("add_vec", value_add_vec);
+ ("sub_vec", value_sub_vec);
+ ("read_ram", value_read_ram);
+ ("write_ram", value_write_ram);
("undefined_bit", fun _ -> V_bit Sail_lib.B0);
+ ("undefined_int", fun _ -> V_int Big_int.zero);
+ ("undefined_bool", fun _ -> V_bool false);
("undefined_vector", value_undefined_vector);
+ ("internal_pick", value_internal_pick);
("replicate_bits", value_replicate_bits);
("Elf_loader.elf_entry", fun _ -> V_int (Big_int.of_int 0));
]