diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/Makefile | 2 | ||||
| -rw-r--r-- | src/ast_util.ml | 15 | ||||
| -rw-r--r-- | src/ast_util.mli | 1 | ||||
| -rw-r--r-- | src/gen_lib/sail_operators.lem | 18 | ||||
| -rw-r--r-- | src/gen_lib/sail_operators_mwords.lem | 14 | ||||
| -rw-r--r-- | src/gen_lib/state.lem | 41 | ||||
| -rw-r--r-- | src/initial_check.ml | 13 | ||||
| -rw-r--r-- | src/initial_check.mli | 2 | ||||
| -rw-r--r-- | src/pretty_print_common.ml | 2 | ||||
| -rw-r--r-- | src/pretty_print_lem.ml | 88 | ||||
| -rw-r--r-- | src/pretty_print_lem_ast.ml | 1 | ||||
| -rw-r--r-- | src/process_file.ml | 41 | ||||
| -rw-r--r-- | src/process_file.mli | 3 | ||||
| -rw-r--r-- | src/rewriter.ml | 54 | ||||
| -rw-r--r-- | src/sail.ml | 13 | ||||
| -rw-r--r-- | src/util.ml | 9 | ||||
| -rw-r--r-- | src/util.mli | 5 |
17 files changed, 209 insertions, 113 deletions
diff --git a/src/Makefile b/src/Makefile index 4147b10c..6cfcf874 100644 --- a/src/Makefile +++ b/src/Makefile @@ -173,7 +173,7 @@ _build/cheri_notlb.lem: $(CHERI_NOTLB_SAILS) ./sail.native _build/cheri_embed_types_sequential.lem: $(CHERI_SAILS) ./sail.native mkdir -p _build cd _build ;\ - ../sail.native -lem_lib "Mips_extras_embed" -lem -o cheri $(CHERI_SAILS) + ../sail.native -lem_lib "Mips_extras_embed" -lem -lem_sequential -lem_mwords -o cheri $(CHERI_SAILS) _build/Cheri_embed_sequential.thy: _build/cheri_embed_types_sequential.lem cd _build ;\ diff --git a/src/ast_util.ml b/src/ast_util.ml index 5740a3c7..aef1a05d 100644 --- a/src/ast_util.ml +++ b/src/ast_util.ml @@ -392,6 +392,11 @@ and string_of_n_constraint = function | NC_aux (NC_true, _) -> "true" | NC_aux (NC_false, _) -> "false" +let string_of_annot = function + | Some (_, typ, eff) -> + "Some (_, " ^ string_of_typ typ ^ ", " ^ string_of_effect eff ^ ")" + | None -> "None" + let string_of_quant_item_aux = function | QI_id (KOpt_aux (KOpt_none kid, _)) -> string_of_kid kid | QI_id (KOpt_aux (KOpt_kind (k, kid), _)) -> string_of_kind k ^ " " ^ string_of_kid kid @@ -629,13 +634,17 @@ let rec is_vector_typ = function let typ_app_args_of = function | Typ_aux (Typ_app (Id_aux (Id c,_), targs), l) -> (c, List.map (fun (Typ_arg_aux (a,_)) -> a) targs, l) - | Typ_aux (_, l) -> raise (Reporting_basic.err_typ l "typ_app_args_of called on non-app type") + | Typ_aux (_, l) as typ -> + raise (Reporting_basic.err_typ l + ("typ_app_args_of called on non-app type " ^ string_of_typ typ)) let rec vector_typ_args_of typ = match typ_app_args_of typ with | ("vector", [Typ_arg_nexp start; Typ_arg_nexp len; Typ_arg_order ord; Typ_arg_typ etyp], _) -> - (start, len, ord, etyp) + (simplify_nexp start, simplify_nexp len, ord, etyp) | ("register", [Typ_arg_typ rtyp], _) -> vector_typ_args_of rtyp - | (_, _, l) -> raise (Reporting_basic.err_typ l "vector_typ_args_of called on non-vector type") + | (_, _, l) -> + raise (Reporting_basic.err_typ l + ("vector_typ_args_of called on non-vector type " ^ string_of_typ typ)) let is_order_inc = function | Ord_aux (Ord_inc, _) -> true diff --git a/src/ast_util.mli b/src/ast_util.mli index 6a150872..e6823ee9 100644 --- a/src/ast_util.mli +++ b/src/ast_util.mli @@ -146,6 +146,7 @@ val string_of_order : order -> string val string_of_nexp : nexp -> string val string_of_typ : typ -> string val string_of_typ_arg : typ_arg -> string +val string_of_annot : ('a * typ * effect) option -> string val string_of_n_constraint : n_constraint -> string val string_of_quant_item : quant_item -> string val string_of_typquant : typquant -> string diff --git a/src/gen_lib/sail_operators.lem b/src/gen_lib/sail_operators.lem index fbe096c9..a760fb42 100644 --- a/src/gen_lib/sail_operators.lem +++ b/src/gen_lib/sail_operators.lem @@ -205,6 +205,7 @@ let modulo (l,r) = hardware_mod l r let quot = hardware_quot let power (l,r) = integerPow l r +let add_int = add let sub_int = sub let mult_int = mult @@ -452,6 +453,9 @@ let rec repeat xs n = let duplicate (bit, length) = Vector (repeat [bit] length) (length - 1) false +let replicate_bits (v, count) = + Vector (repeat (get_elems v) count) ((length v * count) - 1) false + let compare_op op (l,r) = (op l r) let lt = compare_op (<) @@ -531,3 +535,17 @@ let make_bitvector_undef length = let mask' (start, n, Vector bits _ dir) = let current_size = List.length bits in Vector (drop (current_size - (natFromInteger n)) bits) start dir + + +(* Register operations *) + +let update_reg_range i j reg_val new_val = update reg_val i j new_val +let update_reg_bit i reg_val bit = update_pos reg_val i bit +let update_reg_field_range regfield i j reg_val new_val = + let current_field_value = regfield.get_field reg_val in + let new_field_value = update current_field_value i j new_val in + regfield.set_field reg_val new_field_value +let write_reg_field_bit regfield i reg_val bit = + let current_field_value = regfield.get_field reg_val in + let new_field_value = update_pos current_field_value i bit in + regfield.set_field reg_val new_field_value diff --git a/src/gen_lib/sail_operators_mwords.lem b/src/gen_lib/sail_operators_mwords.lem index 9bc81b3e..44ae9d7c 100644 --- a/src/gen_lib/sail_operators_mwords.lem +++ b/src/gen_lib/sail_operators_mwords.lem @@ -245,6 +245,7 @@ let modulo (l,r) = hardware_mod l r let quot = hardware_quot let power (l,r) = integerPow l r +let add_int = add let sub_int = sub let mult_int = mult @@ -574,3 +575,16 @@ let make_bitvector_undef length = (* TODO *) val mask : forall 'a 'b. Size 'b => (integer * integer * bitvector 'a) -> bitvector 'b let mask (start, _, Bitvector w _ dir) = (Bitvector (zeroExtend w) start dir) + +(* Register operations *) + +let update_reg_range i j reg_val new_val = bvupdate reg_val i j new_val +let update_reg_bit i reg_val bit = bvupdate_pos reg_val i bit +let update_reg_field_range regfield i j reg_val new_val = + let current_field_value = regfield.get_field reg_val in + let new_field_value = bvupdate current_field_value i j new_val in + regfield.set_field reg_val new_field_value +let write_reg_field_bit regfield i reg_val bit = + let current_field_value = regfield.get_field reg_val in + let new_field_value = bvupdate_pos current_field_value i bit in + regfield.set_field reg_val new_field_value diff --git a/src/gen_lib/state.lem b/src/gen_lib/state.lem index d5866cde..914955e0 100644 --- a/src/gen_lib/state.lem +++ b/src/gen_lib/state.lem @@ -1,7 +1,6 @@ open import Pervasives_extra open import Sail_impl_base open import Sail_values -open import Sail_operators_mwords (* 'a is result type *) @@ -51,7 +50,7 @@ let inline (>>) m n = m >>= fun _ -> n val exit : forall 'regs 'e 'a. 'e -> M 'regs 'a let exit _ s = [(Right (), s)] -val early_return : forall 'regs 'r. 'r -> MR 'regs unit 'r +val early_return : forall 'regs 'a 'r. 'r -> MR 'regs 'a 'r let early_return r s = [(Right (Just r), s)] val catch_early_return : forall 'regs 'a. MR 'regs 'a 'a -> M 'regs 'a @@ -76,12 +75,11 @@ let set_reg state reg v = <| state with regstate = reg.write_to state.regstate v |> -val read_mem : forall 'regs 'a 'b. Size 'b => bool -> read_kind -> bitvector 'a -> integer -> M 'regs (bitvector 'b) +val read_mem : forall 'regs 'a 'b. Size 'b => bool -> read_kind -> integer -> integer -> M 'regs (vector bitU) let read_mem dir read_kind addr sz state = - let addr = unsigned addr in let addrs = range addr (addr+sz-1) in let memory_value = List.map (fun addr -> Map_extra.find addr state.memstate) addrs in - let value = vec_to_bvec (Sail_values.internal_mem_value dir memory_value) in + let value = Sail_values.internal_mem_value dir memory_value in let is_exclusive = match read_kind with | Sail_impl_base.Read_plain -> false | Sail_impl_base.Read_reserve -> true @@ -98,9 +96,9 @@ let read_mem dir read_kind addr sz state = (* caps are aligned at 32 bytes *) let cap_alignment = (32 : integer) -val read_tag : forall 'regs 'a. bool -> read_kind -> bitvector 'a -> M 'regs bitU +val read_tag : forall 'regs 'a. bool -> read_kind -> integer -> M 'regs bitU let read_tag dir read_kind addr state = - let addr = (unsigned addr) / cap_alignment in + let addr = addr / cap_alignment in let tag = match (Map.lookup addr state.tagstate) with | Just t -> t | Nothing -> B0 @@ -125,18 +123,17 @@ let excl_result () state = (Left true, <| state with last_exclusive_operation_was_load = false |>) in (Left false, state) :: if state.last_exclusive_operation_was_load then [success] else [] -val write_mem_ea : forall 'regs 'a. write_kind -> bitvector 'a -> integer -> M 'regs unit +val write_mem_ea : forall 'regs 'a. write_kind -> integer -> integer -> M 'regs unit let write_mem_ea write_kind addr sz state = - let addr = unsigned addr in [(Left (), <| state with write_ea = Just (write_kind,addr,sz) |>)] -val write_mem_val : forall 'regs 'b. bitvector 'b -> M 'regs bool +val write_mem_val : forall 'regs 'b. vector bitU -> M 'regs bool let write_mem_val v state = let (write_kind,addr,sz) = match state.write_ea with | Nothing -> failwith "write ea has not been announced yet" | Just write_ea -> write_ea end in let addrs = range addr (addr+sz-1) in - let v = external_mem_value (bvec_to_vec v) in + let v = external_mem_value v in let addresses_with_value = List.zip addrs v in let memstate = List.foldl (fun mem (addr,v) -> Map.insert addr v mem) state.memstate addresses_with_value in @@ -178,28 +175,6 @@ let update_reg reg f v state = let current_value = get_reg state reg in let new_value = f current_value v in [(Left (), set_reg state reg new_value)] -let write_reg_range reg i j v state = - let current_value = get_reg state reg in - let new_value = bvupdate current_value i j v in - [(Left (), set_reg state reg new_value)] -let write_reg_bit reg i bit state = - let current_value = get_reg state reg in - let new_value = bvupdate_pos current_value i bit in - [(Left (), set_reg state reg new_value)] -let write_reg_field reg regfield = - update_reg reg regfield.set_field -let write_reg_field_range reg regfield i j = - let upd regval v = - let current_field_value = regfield.get_field regval in - let new_field_value = bvupdate current_field_value i j v in - regfield.set_field regval new_field_value in - update_reg reg upd -let write_reg_field_bit reg regfield i = - let upd regval v = - let current_field_value = regfield.get_field regval in - let new_field_value = bvupdate_pos current_field_value i v in - regfield.set_field regval new_field_value in - update_reg reg upd val barrier : forall 'regs. barrier_kind -> M 'regs unit diff --git a/src/initial_check.ml b/src/initial_check.ml index e9695dd4..4c0a0db4 100644 --- a/src/initial_check.ml +++ b/src/initial_check.ml @@ -44,6 +44,8 @@ open Ast open Util open Ast_util +let opt_undefined_gen = ref false + module Envmap = Finite_map.Fmap_map(String) module Nameset' = Set.Make(String) module Nameset = struct @@ -1116,6 +1118,11 @@ let generate_initialize_registers vs_ids (Defs defs) = let process_ast order defs = let (ast, _, _) = to_ast Nameset.empty initial_kind_env order defs in - let vs_ids = val_spec_ids ast in - let ast = generate_undefineds vs_ids ast in - generate_initialize_registers vs_ids ast + if not !opt_undefined_gen + then ast + else + begin + let vs_ids = val_spec_ids ast in + let ast = generate_undefineds vs_ids ast in + generate_initialize_registers vs_ids ast + end diff --git a/src/initial_check.mli b/src/initial_check.mli index 86b5ca3b..feb9cb83 100644 --- a/src/initial_check.mli +++ b/src/initial_check.mli @@ -43,6 +43,8 @@ open Ast open Ast_util +val opt_undefined_gen : bool ref + val process_ast : order -> Parse_ast.defs -> unit defs val val_spec_ids : 'a defs -> IdSet.t diff --git a/src/pretty_print_common.ml b/src/pretty_print_common.ml index 70f5b749..02cc3574 100644 --- a/src/pretty_print_common.ml +++ b/src/pretty_print_common.ml @@ -212,7 +212,7 @@ let doc_typ, doc_atomic_typ, doc_nexp, doc_nexp_constraint = and atomic_nexp_typ ((Nexp_aux(n,_)) as ne) = match n with | Nexp_var v -> doc_var v | Nexp_id i -> braces (doc_id i) - | Nexp_constant i -> doc_int i + | Nexp_constant i -> if i < 0 then parens(doc_int i) else doc_int i | Nexp_neg _ | Nexp_exp _ | Nexp_times _ | Nexp_sum _ | Nexp_minus _-> group (parens (nexp ne)) diff --git a/src/pretty_print_lem.ml b/src/pretty_print_lem.ml index 3d4f3083..5e0d39a0 100644 --- a/src/pretty_print_lem.ml +++ b/src/pretty_print_lem.ml @@ -58,7 +58,11 @@ let langlebar = string "<|" let ranglebar = string "|>" let anglebars = enclose langlebar ranglebar -let fix_id name = match name with +let is_number_char c = + c = '0' || c = '1' || c = '2' || c = '3' || c = '4' || c = '5' || + c = '6' || c = '7' || c = '8' || c = '9' + +let fix_id remove_tick name = match name with | "assert" | "lsl" | "lsr" @@ -76,22 +80,17 @@ let fix_id name = match name with | "EQ" | "integer" -> name ^ "'" - | _ -> name - -let is_number char = - char = '0' || char = '1' || char = '2' || char = '3' || char = '4' || char = '5' || - char = '6' || char = '7' || char = '8' || char = '9' + | _ -> + if name.[0] = '\'' then + let var = String.sub name 1 (String.length name - 1) in + if remove_tick then var else (var ^ "'") + else if is_number_char(name.[0]) then + ("v" ^ name ^ "'") + else name let doc_id_lem (Id_aux(i,_)) = match i with - | Id i -> - (* this not the right place to do this, just a workaround *) - if i.[0] = '\'' then - string ((String.sub i 1 (String.length i - 1)) ^ "'") - else if is_number(i.[0]) then - string ("v" ^ i ^ "'") - else - string (fix_id i) + | Id i -> string (fix_id false i) | DeIid x -> (* add an extra space through empty to avoid a closing-comment * token in case of x ending with star. *) @@ -102,7 +101,7 @@ let doc_id_lem_type (Id_aux(i,_)) = | Id("int") -> string "ii" | Id("nat") -> string "ii" | Id("option") -> string "maybe" - | Id i -> string (fix_id i) + | Id i -> string (fix_id false i) | DeIid x -> (* add an extra space through empty to avoid a closing-comment * token in case of x ending with star. *) @@ -115,12 +114,14 @@ let doc_id_lem_ctor (Id_aux(i,_)) = | Id("nat") -> string "integer" | Id("Some") -> string "Just" | Id("None") -> string "Nothing" - | Id i -> string (fix_id (String.capitalize i)) + | Id i -> string (fix_id false (String.capitalize i)) | DeIid x -> (* add an extra space through empty to avoid a closing-comment * token in case of x ending with star. *) separate space [colon; string (String.capitalize x); empty] +let doc_var_lem kid = string (fix_id true (string_of_kid kid)) + let effectful_set = List.exists (fun (BE_aux (eff,_)) -> @@ -230,6 +231,7 @@ let rec contains_t_pp_var (Typ_aux (t,a) as typ) = match t with | Typ_wild -> true | Typ_id _ -> false | Typ_var _ -> true + | Typ_exist _ -> true | Typ_fn (t1,t2,_) -> contains_t_pp_var t1 || contains_t_pp_var t2 | Typ_tup ts -> List.exists contains_t_pp_var ts | Typ_app (c,targs) -> @@ -321,6 +323,7 @@ let rec doc_pat_lem sequential mwords apat_needed (P_aux (p,(l,annot)) as pa) = begin match id with | Id_aux (Id "None",_) -> string "Nothing" (* workaround temporary issue *) | _ -> doc_id_lem id end + | P_var kid -> doc_var_lem kid | P_as(p,id) -> parens (separate space [doc_pat_lem sequential mwords true p; string "as"; doc_id_lem id]) | P_typ(typ,p) -> let doc_p = doc_pat_lem sequential mwords true p in @@ -391,15 +394,16 @@ let doc_exp_lem, doc_let_lem = underscore ^^ doc_id_lem id in liftR ((prefix 2 1) - (string "write_reg_field_range") + (string "update_reg") (align (doc_lexp_deref_lem sequential mwords early_ret le ^^ space^^ - field_ref ^/^ expY e2 ^/^ expY e3 ^/^ expY e))) + parens (string "update_reg_field_range" ^/^ field_ref ^/^ expY e2 ^/^ expY e3) ^/^ expY e))) | _ -> liftR ((prefix 2 1) - (string "write_reg_range") - (align (doc_lexp_deref_lem sequential mwords early_ret le ^^ space ^^ expY e2 ^/^ expY e3 ^/^ expY e))) + (string "update_reg") + (align (doc_lexp_deref_lem sequential mwords early_ret le ^^ space ^^ + parens (string "update_reg_range" ^/^ expY e2 ^/^ expY e3) ^/^ expY e))) ) - | LEXP_vector (le,e2) when is_bit_typ t -> + | LEXP_vector (le,e2) -> (match le with | LEXP_aux (LEXP_field ((LEXP_aux (_, lannot) as le),id), fannot) -> if is_bit_typ (typ_of_annot fannot) then @@ -410,12 +414,14 @@ let doc_exp_lem, doc_let_lem = underscore ^^ doc_id_lem id in liftR ((prefix 2 1) - (string "write_reg_field_bit") - (align (doc_lexp_deref_lem sequential mwords early_ret le ^^ space ^^ field_ref ^/^ expY e2 ^/^ expY e))) + (string "update_reg") + (align (doc_lexp_deref_lem sequential mwords early_ret le ^^ space ^^ + parens (string "update_reg_field_bit" ^/^ field_ref ^/^ expY e2) ^/^ expY e))) | _ -> liftR ((prefix 2 1) - (string "write_reg_bit") - (doc_lexp_deref_lem sequential mwords early_ret le ^^ space ^^ expY e2 ^/^ expY e)) + (string "update_reg") + (doc_lexp_deref_lem sequential mwords early_ret le ^^ space ^^ + parens (string "update_reg_bit" ^/^ expY e2) ^/^ expY e)) ) (* | LEXP_field (le,id) when is_bit_typ t -> liftR ((prefix 2 1) @@ -425,9 +431,11 @@ let doc_exp_lem, doc_let_lem = let field_ref = doc_id_lem (typ_id_of (typ_of_annot lannot)) ^^ underscore ^^ - doc_id_lem id in + doc_id_lem id ^^ + dot ^^ + string "set_field" in liftR ((prefix 2 1) - (string "write_reg_field") + (string "update_reg") (doc_lexp_deref_lem sequential mwords early_ret le ^^ space ^^ field_ref ^/^ expY e)) (* | (LEXP_id id | LEXP_cast (_,id)), t, Alias alias_info -> @@ -692,7 +700,7 @@ let doc_exp_lem, doc_let_lem = let recordtyp = match annot with | Some (env, Typ_aux (Typ_id tid,_), _) when Env.is_record tid env -> tid - | _ -> raise (report l "cannot get record type") in + | _ -> raise (report l ("cannot get record type from annot " ^ string_of_annot annot ^ " of exp " ^ string_of_exp full_exp)) in let epp = anglebars (space ^^ (align (separate_map (semi_sp ^^ break 1) (doc_fexp sequential mwords early_ret recordtyp) fexps)) ^^ space) in @@ -702,7 +710,7 @@ let doc_exp_lem, doc_let_lem = let recordtyp = match eannot with | Some (env, Typ_aux (Typ_id tid,_), _) when Env.is_record tid env -> tid - | _ -> raise (report l "cannot get record type") in + | _ -> raise (report l ("cannot get record type from annot " ^ string_of_annot annot ^ " of exp " ^ string_of_exp full_exp)) in anglebars (doc_op (string "with") (expY e) (separate_map semi_sp (doc_fexp sequential mwords early_ret recordtyp) fexps)) | E_vector exps -> let t = Env.base_typ_of (env_of full_exp) (typ_of full_exp) in @@ -801,21 +809,26 @@ let doc_exp_lem, doc_let_lem = if aexp_needed then parens (align bepp) else bepp | E_vector_update(v,e1,e2) -> let t = typ_of full_exp in + let (_, _, ord, _) = vector_typ_args_of (Env.base_typ_of (env_of full_exp) t) in + let ord_suffix = if is_order_inc ord then "_inc" else "_dec" in let call = if is_bitvector_typ t (*&& mwords*) - then "bitvector_update_pos" - else "update_pos" in - let epp = separate space [string call;expY v;expY e1;expY e2] in + then "bitvector_update_pos" ^ ord_suffix + else "update_pos" ^ ord_suffix in + let epp = string call ^^ space ^^ parens (separate comma_sp [expY v;expY e1;expY e2]) in if aexp_needed then parens (align epp) else epp | E_vector_update_subrange(v,e1,e2,e3) -> let t = typ_of full_exp in + let (_, _, ord, _) = vector_typ_args_of (Env.base_typ_of (env_of full_exp) t) in + let ord_suffix = if is_order_inc ord then "_inc" else "_dec" in let call = if is_bitvector_typ t (*&& mwords*) - then "bitvector_update" - else "update" in - let epp = align (string call ^//^ - group (group (expY v) ^/^ group (expY e1) ^/^ group (expY e2)) ^/^ - group (expY e3)) in + then "bitvector_update" ^ ord_suffix + else "update" ^ ord_suffix in + let epp = + align (string call ^//^ + parens (separate comma_sp + [group (expY v); group (expY e1); group (expY e2); group (expY e3)])) in if aexp_needed then parens (align epp) else epp | E_list exps -> brackets (separate_map semi (expN) exps) @@ -1001,6 +1014,7 @@ let doc_exp_lem, doc_let_lem = top_exp sequential mwords early_ret true e]) | LEXP_id id -> doc_id_lem id | LEXP_cast (typ,id) -> doc_id_lem id + | LEXP_tup lexps -> parens (separate_map comma_sp (doc_lexp_deref_lem sequential mwords early_ret) lexps) | _ -> raise (Reporting_basic.err_unreachable l ("doc_lexp_deref_lem: Shouldn't happen")) (* expose doc_exp_lem and doc_let *) diff --git a/src/pretty_print_lem_ast.ml b/src/pretty_print_lem_ast.ml index c75c102f..5edf9d12 100644 --- a/src/pretty_print_lem_ast.ml +++ b/src/pretty_print_lem_ast.ml @@ -328,6 +328,7 @@ let rec pp_format_pat_lem (P_aux(p,(l,annot))) = | P_lit(lit) -> "(P_lit " ^ pp_format_lit_lem lit ^ ")" | P_wild -> "P_wild" | P_id(id) -> "(P_id " ^ pp_format_id_lem id ^ ")" + | P_var(kid) -> "(P_var " ^ pp_format_var_lem kid ^ ")" | P_as(pat,id) -> "(P_as " ^ pp_format_pat_lem pat ^ " " ^ pp_format_id_lem id ^ ")" | P_typ(typ,pat) -> "(P_typ " ^ pp_format_typ_lem typ ^ " " ^ pp_format_pat_lem pat ^ ")" | P_app(id,pats) -> "(P_app " ^ pp_format_id_lem id ^ " [" ^ diff --git a/src/process_file.ml b/src/process_file.ml index 46b6538e..0f789c9d 100644 --- a/src/process_file.ml +++ b/src/process_file.ml @@ -41,6 +41,8 @@ (**************************************************************************) let opt_new_parser = ref false +let opt_lem_sequential = ref false +let opt_lem_mwords = ref false type out_type = | Lem_ast_out @@ -136,31 +138,28 @@ let generated_line f = let output_lem filename libs defs = let generated_line = generated_line filename in - let types_module = (filename ^ "_embed_types") in - let types_module_seq = (filename ^ "_embed_types_sequential") in - let libs_seq = List.map (fun lib -> lib ^ "_sequential") libs in + let seq_suffix = if !opt_lem_sequential then "_sequential" else "" in + let types_module = (filename ^ "_embed_types" ^ seq_suffix) in + let monad_module = if !opt_lem_sequential then "State" else "Prompt" in + let operators_module = if !opt_lem_mwords then "Sail_operators_mwords" else "Sail_operators" in + let libs = List.map (fun lib -> lib ^ seq_suffix) libs in + let base_imports = [ + "Pervasives_extra"; + "Sail_impl_base"; + "Sail_values"; + operators_module; + monad_module + ] in let ((ot,_, _) as ext_ot) = - open_output_with_check_unformatted (filename ^ "_embed_types.lem") in - let ((ots,_, _) as ext_ots) = - open_output_with_check_unformatted (filename ^ "_embed_types_sequential.lem") in + open_output_with_check_unformatted (filename ^ "_embed_types" ^ seq_suffix ^ ".lem") in let ((o,_, _) as ext_o) = - open_output_with_check_unformatted (filename ^ "_embed.lem") in - let ((os,_, _) as ext_os) = - open_output_with_check_unformatted (filename ^ "_embed_sequential.lem") in - (Pretty_print.pp_defs_lem false false - (ot,["Pervasives_extra";"Sail_impl_base";"Sail_values";"Sail_operators";"Prompt"]) - (o,["Pervasives_extra";"Sail_impl_base";"Sail_values";"Sail_operators";"Prompt"; - String.capitalize types_module] @ libs) - defs generated_line); - (Pretty_print.pp_defs_lem true true - (ots,["Pervasives_extra";"Sail_impl_base";"Sail_values";"Sail_operators_mwords";"State"]) - (os,["Pervasives_extra";"Sail_impl_base";"Sail_values";"Sail_operators_mwords";"State"; - String.capitalize types_module_seq] @ libs_seq) + open_output_with_check_unformatted (filename ^ "_embed" ^ seq_suffix ^ ".lem") in + (Pretty_print.pp_defs_lem !opt_lem_sequential !opt_lem_mwords + (ot, base_imports) + (o, base_imports @ (String.capitalize types_module :: libs)) defs generated_line); close_output_with_check ext_ot; - close_output_with_check ext_ots; - close_output_with_check ext_o; - close_output_with_check ext_os + close_output_with_check ext_o let output1 libpath out_arg filename defs = let f' = Filename.basename (Filename.chop_extension filename) in diff --git a/src/process_file.mli b/src/process_file.mli index cd867b0d..53a6f3f2 100644 --- a/src/process_file.mli +++ b/src/process_file.mli @@ -52,6 +52,8 @@ val load_file_no_check : Ast.order -> string -> unit Ast.defs val load_file : Ast.order -> Type_check.Env.t -> string -> Type_check.tannot Ast.defs * Type_check.Env.t val opt_new_parser : bool ref +val opt_lem_sequential : bool ref +val opt_lem_mwords : bool ref val opt_just_check : bool ref val opt_ddump_tc_ast : bool ref val opt_ddump_rewrite_ast : ((string * int) option) ref @@ -73,4 +75,3 @@ val output : files existed before. If it is set to [false] and an output file already exists, the output file is only updated, if its content really changes. *) val always_replace_files : bool ref - diff --git a/src/rewriter.ml b/src/rewriter.ml index b180b0a1..78b29200 100644 --- a/src/rewriter.ml +++ b/src/rewriter.ml @@ -2183,6 +2183,15 @@ let id_is_local_var id env = match Env.lookup_id id env with | Local _ -> true | _ -> false +let rec lexp_is_local (LEXP_aux (lexp, _)) env = match lexp with + | LEXP_memory _ -> false + | LEXP_id id + | LEXP_cast (_, id) -> id_is_local_var id env + | LEXP_tup lexps -> List.for_all (fun lexp -> lexp_is_local lexp env) lexps + | LEXP_vector (lexp,_) + | LEXP_vector_range (lexp,_,_) + | LEXP_field (lexp,_) -> lexp_is_local lexp env + let id_is_unbound id env = match Env.lookup_id id env with | Unbound -> true | _ -> false @@ -2203,6 +2212,13 @@ let lexp_is_effectful (LEXP_aux (_, (_, annot))) = match annot with let rec rewrite_local_lexp ((LEXP_aux(lexp,((l,_) as annot))) as le) = match lexp with | LEXP_id id | LEXP_cast (_, id) -> (le, E_aux (E_id id, annot), (fun exp -> exp)) + | LEXP_tup les -> + let get_id (LEXP_aux(lexp,((l,_) as annot)) as le) = match lexp with + | LEXP_id id | LEXP_cast (_, id) -> E_aux (E_id id, annot) + | _ -> + raise (Reporting_basic.err_unreachable l + ("Unsupported sub-lexp " ^ string_of_lexp le ^ " in tuple")) in + (le, E_aux (E_tuple (List.map get_id les), annot), (fun exp -> exp)) | LEXP_vector (lexp, e) -> let (lexp, access, rexp) = rewrite_local_lexp lexp in (lexp, E_aux (E_vector_access (access, e), annot), @@ -2233,7 +2249,7 @@ let rewrite_exp_lift_assign_intro rewriters ((E_aux (exp,((l,_) as annot))) as f let rec walker exps = match exps with | [] -> [] | (E_aux(E_assign(le,e), ((l, Some (env,typ,eff)) as annot)) as exp)::exps - when lexp_is_local_intro le env && not (lexp_is_effectful le)-> + when lexp_is_local_intro le env && not (lexp_is_effectful le) -> let (le', _, re') = rewrite_local_lexp le in let e' = re' (rewrite_base e) in let exps' = walker exps in @@ -2371,12 +2387,11 @@ let rewrite_defs_early_return = | _ -> exp in let e_block es = - (* let rec walker = function - | e :: es -> if is_return e then [e] else e :: walker es - | [] -> [] in - let es = walker es in *) match es with | [E_aux (e, _)] -> e + | _ :: _ when is_return (Util.last es) -> + let (E_aux (_, annot) as e) = Util.last es in + E_return (E_aux (E_block (Util.butlast es @ [get_return e]), annot)) | _ -> E_block es in let e_if (e1, e2, e3) = @@ -2404,14 +2419,19 @@ let rewrite_defs_early_return = | _ -> full_exp in let rewrite_funcl_early_return _ (FCL_aux (FCL_Funcl (id, pat, exp), a)) = - let exp = fold_exp - { id_exp_alg with e_block = e_block; e_if = e_if; e_case = e_case; - e_aux = e_aux } exp in + let exp = + exp + (* Pull early returns out as far as possible *) + |> fold_exp { id_exp_alg with e_block = e_block; e_if = e_if; e_case = e_case } + (* Remove singleton E_return *) + |> get_return + (* Fix effect annotations *) + |> fold_exp { id_exp_alg with e_aux = e_aux } in let a = match a with | (l, Some (env, typ, eff)) -> (l, Some (env, typ, union_effects eff (effect_of exp))) | _ -> a in - FCL_aux (FCL_Funcl (id, pat, get_return exp), a) in + FCL_aux (FCL_Funcl (id, pat, exp), a) in let rewrite_fun_early_return rewriters (FD_aux (FD_function (rec_opt, tannot_opt, effect_opt, funcls), a)) = @@ -2948,8 +2968,19 @@ let rewrite_defs_letbind_effects = let rewrite_defs_effectful_let_expressions = + let rec pat_of_local_lexp (LEXP_aux (lexp, ((l, _) as annot))) = match lexp with + | LEXP_id id -> P_aux (P_id id, annot) + | LEXP_cast (typ, id) -> P_aux (P_typ (typ, P_aux (P_id id, annot)), annot) + | LEXP_tup lexps -> P_aux (P_tup (List.map pat_of_local_lexp lexps), annot) + | _ -> raise (Reporting_basic.err_unreachable l "unexpected local lexp") in + let e_let (lb,body) = match lb with + | LB_aux (LB_val_implicit (P_aux (P_wild, _), E_aux (E_assign ((LEXP_aux (_, annot) as le), exp), _)), _) + when lexp_is_local le (env_of_annot annot) -> + (* Rewrite assignments to local variables into let bindings *) + let (lhs, _, rhs) = rewrite_local_lexp le in + E_let (LB_aux (LB_val_implicit (pat_of_local_lexp lhs, rhs exp), annot), body) | LB_aux (LB_val_explicit (_,pat,exp'),annot') | LB_aux (LB_val_implicit (pat,exp'),annot') -> if effectful exp' @@ -3261,7 +3292,7 @@ let rec rewrite_var_updates ((E_aux (expaux,((l,_) as annot))) as exp) = "tail-position": check the definition nexp_term and where it is used. *) | _ -> exp -let replace_memwrite_e_assign exp = +let replace_memwrite_e_assign exp = let e_aux = fun (expaux,annot) -> match expaux with | E_assign (LEXP_aux (LEXP_memory (id,args),_),v) -> E_aux (E_app (id,args @ [v]),annot) @@ -3395,7 +3426,8 @@ let rewrite_defs_remove_e_assign = let recheck_defs defs = fst (check initial_env defs) let rewrite_defs_lem =[ - top_sort_defs; + (* top_sort_defs; *) + rewrite_trivial_sizeof; rewrite_sizeof; rewrite_defs_remove_vector_concat; rewrite_defs_remove_bitvector_pats; diff --git a/src/sail.ml b/src/sail.ml index 5e979738..b63f807c 100644 --- a/src/sail.ml +++ b/src/sail.ml @@ -65,7 +65,7 @@ let options = Arg.align ([ Arg.Set opt_print_lem, " output a Lem translated version of the input"); ( "-ocaml", - Arg.Set opt_print_ocaml, + Arg.Tuple [Arg.Set opt_print_ocaml; Arg.Set Initial_check.opt_undefined_gen], " output an OCaml translated version of the input"); ( "-lem_lib", Arg.String (fun l -> opt_libs_lem := l::!opt_libs_lem), @@ -73,6 +73,12 @@ let options = Arg.align ([ ( "-ocaml_lib", Arg.String (fun l -> opt_libs_ocaml := l::!opt_libs_ocaml), "<filename> provide additional library to open in OCaml output"); + ( "-lem_sequential", + Arg.Set Process_file.opt_lem_sequential, + " use sequential state monad for Lem output"); + ( "-lem_mwords", + Arg.Set Process_file.opt_lem_mwords, + " use native machine word library for Lem output"); (* ( "-i", Arg.String (fun l -> lib := l::!lib), @@ -93,7 +99,7 @@ let options = Arg.align ([ " (experimental) use new parser"); ( "-just_check", Arg.Set opt_just_check, - " (experimental) terminate immediately after typechecking, implies -new_typecheck"); + " (experimental) terminate immediately after typechecking"); ( "-ddump_tc_ast", Arg.Set opt_ddump_tc_ast, " (debug) dump the typechecked ast to stdout"); @@ -109,6 +115,9 @@ let options = Arg.align ([ ( "-no_effects", Arg.Set Type_check.opt_no_effects, " turn off effect checking"); + ( "-undefined-gen", + Arg.Set Initial_check.opt_undefined_gen, + " generate undefined_type functions for types in the specification"); ( "-v", Arg.Set opt_print_version, " print version"); diff --git a/src/util.ml b/src/util.ml index c89cc1ef..335fd36f 100644 --- a/src/util.ml +++ b/src/util.ml @@ -86,6 +86,15 @@ (* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *) (**************************************************************************) +let rec last = function + | [x] -> x + | _ :: xs -> last xs + | [] -> raise (Failure "last") + +let rec butlast = function + | [x] -> [] + | x :: xs -> x :: butlast xs + | [] -> [] module Duplicate(S : Set.S) = struct diff --git a/src/util.mli b/src/util.mli index f1182c61..11588de2 100644 --- a/src/util.mli +++ b/src/util.mli @@ -40,6 +40,11 @@ (* SUCH DAMAGE. *) (**************************************************************************) +(* Last element of a list *) +val last : 'a list -> 'a + +val butlast : 'a list -> 'a list + (** Mixed useful things *) module Duplicate(S : Set.S) : sig type dups = |
