diff options
Diffstat (limited to 'src/lem_interp')
| -rw-r--r-- | src/lem_interp/interp.lem | 334 | ||||
| -rw-r--r-- | src/lem_interp/interp_inter_imp.lem | 182 | ||||
| -rw-r--r-- | src/lem_interp/interp_interface.lem | 178 | ||||
| -rw-r--r-- | src/lem_interp/interp_utilities.lem | 4 | ||||
| -rw-r--r-- | src/lem_interp/printing_functions.ml | 25 |
5 files changed, 411 insertions, 312 deletions
diff --git a/src/lem_interp/interp.lem b/src/lem_interp/interp.lem index b1ee613d..ae773ad1 100644 --- a/src/lem_interp/interp.lem +++ b/src/lem_interp/interp.lem @@ -1,6 +1,7 @@ open import Pervasives import Map import Map_extra (* For 'find' instead of using lookup and maybe types, as we know it cannot fail *) +import Set_extra (* For 'to_list' because map only goes to set *) import List_extra (* For 'nth' and 'head' where we know that they cannot fail *) open import Show_extra (* for 'show' to convert nat to string) *) open import String_extra (* for chr *) @@ -36,10 +37,10 @@ let is_inc = function | IInc -> true | _ -> false end let id_of_string s = (Id_aux (Id s) Unknown) type reg_form = - | Reg of id * tannot + | Reg of id * tannot * i_direction | SubReg of id * reg_form * index_range -type ctor_kind = C_Enum | C_Union +type ctor_kind = C_Enum of nat | C_Union type value = | V_boxref of nat * t @@ -57,17 +58,6 @@ type value = | V_register_alias of (alias_spec tannot) * tannot (* Same as above, but to a concatenation of two registers *) | V_track of value * (list reg_form) (* Used when memory system wants to track what register(s) a value came from *) -(*let rec integerToString n acc = - if n = 0 then - acc - else - integerToString (n / 10) (chr (natFromInteger (n mod 10 + 48)) :: acc) - -let string_of_integer i = if i = 0 then "0" else toString(integerToString i [])*) -(*val string_of_integer : integer -> string -declare ocaml target_rep function string_of_integer = `Big_int_Z.string_of_big_int`*) - - let rec string_of_value v = match v with | V_boxref nat t -> "$#" ^ (show nat) ^ "$" | V_lit (L_aux lit _) -> @@ -124,6 +114,8 @@ and value_eq left right = t = t' && listEqualBy id_value_eq l l' | (V_ctor i t ckind v, V_ctor i' t' ckind' v') -> t = t' && ckind=ckind' && id_value_eq (i, v) (i', v') + | (V_ctor _ _ (C_Enum i) _,V_lit (L_aux (L_num j) _)) -> i = (natFromInteger j) + | (V_lit (L_aux (L_num j) _), V_ctor _ _ (C_Enum i) _) -> i = (natFromInteger j) | (V_unknown,_) -> true | (_,V_unknown) -> true | (V_track v _, v2) -> value_eq v v2 @@ -138,7 +130,7 @@ end let reg_start_pos reg = match reg with - | Reg _ (Just(typ,_,_,_)) -> + | Reg _ (Just(typ,_,_,_)) _ -> let start_from_vec targs = match targs with | T_args [T_arg_nexp (Ne_const s);_;_;_] -> natFromInteger s end in @@ -158,7 +150,7 @@ end let reg_size reg = match reg with - | Reg _ (Just(typ,_,_,_)) -> + | Reg _ (Just(typ,_,_,_)) _ -> let end_from_vec targs = match targs with | T_args [_;T_arg_nexp (Ne_const s);_;_] -> natFromInteger s end in @@ -190,17 +182,17 @@ let unitv = V_lit (L_aux L_unit Unknown) type lmem = LMem of nat * map nat value (* Environment for bindings *) -type env = list (id * value) +type env = map string value (* Environment for lexical bindings, nat is a counter to build new unique variables when necessary *) type lenv = LEnv of nat * env let emem = LMem 1 Map.empty -let eenv = LEnv 1 [] +let eenv = LEnv 1 Map.empty -type sub_reg_map = list (id * index_range) +type sub_reg_map = map string index_range (*top_level is a tuple of - (all definitions, + (function definitions environment, all extracted instructions (where possible), default direction letbound and enum values, @@ -208,7 +200,14 @@ type sub_reg_map = list (id * index_range) Typedef union constructors, sub register mappings, and register aliases) *) type top_level = - | Env of (defs tannot) * list instruction_form * i_direction * env * env * list (id * typ) * list (id * sub_reg_map) * list (id * (alias_spec tannot)) + | Env of map string (list (funcl tannot)) (*function definitions environment*) + * list instruction_form (* extracted instructions (where extractable) *) + * i_direction (*default direction*) + * env (*letbound and enum values*) + * env (*register values*) + * map string typ (*typedef union constructors *) + * map string sub_reg_map (*sub register mappings*) + * map string (alias_spec tannot) (*register aliases*) type action = | Read_reg of reg_form * maybe (nat * nat) @@ -220,16 +219,18 @@ type action = | Nondet of list (exp tannot) | Call_extern of string * value | Exit of (exp tannot) - (* For stepper, no action needed. String is function called, value is parameter, on next state is a new function body *) + (* For stepper, no action needed. String is function called, value is parameter where applicable *) | Step of l * maybe string * maybe value -(* Inverted call stack, where top item on the stack is waiting for an action to resolve and all other frames for the right stack *) +(* Inverted call stack, where the frame with a Top stack waits for an action to resolve and + all other frames for their inner stack *) type stack = | Top | Hole_frame of id * exp tannot * top_level * lenv * lmem * stack (* Stack frame waiting to fill a hole with a value *) | Thunk_frame of exp tannot * top_level * lenv * lmem * stack (* Paused stack frame *) -(*Internal representation of outcomes from running the interpreter. Actions request an external party to resolve a request or pause*) +(*Internal representation of outcomes from running the interpreter. + Actions request an external party to resolve a request *) type outcome = | Value of value | Action of action * stack @@ -248,91 +249,104 @@ val interp :interp_mode -> (i_direction -> outcome -> maybe value) -> defs tanno val resume : interp_mode -> stack -> maybe value -> outcome (* Internal definitions to setup top_level *) -val to_register_fields : defs tannot -> list (id * list (id * index_range)) +val to_fdefs : defs tannot -> map string (list (funcl tannot)) +let rec to_fdefs (Defs defs) = + match defs with + | [] -> Map.empty + | def::defs -> + match def with + | DEF_fundef f -> (match f with + | FD_aux (FD_function _ _ _ fcls) _ -> + match fcls with + | [] -> to_fdefs (Defs defs) + | (FCL_aux (FCL_Funcl name _ _) _)::_ -> + Map.insert (get_id name) fcls (to_fdefs (Defs defs)) end end) + | _ -> to_fdefs (Defs defs) end end + +val to_register_fields : defs tannot -> map string (map string index_range) let rec to_register_fields (Defs defs) = match defs with - | [ ] -> [ ] + | [ ] -> Map.empty | def::defs -> match def with | DEF_type (TD_aux (TD_register id n1 n2 indexes) l') -> - (id,List.map (fun (a,b) -> (b,a)) indexes)::(to_register_fields (Defs defs)) + Map.insert (get_id id) + (List.foldr (fun (a,b) imap -> Map.insert (get_id b) a imap) Map.empty indexes) + (to_register_fields (Defs defs)) | _ -> to_register_fields (Defs defs) end end -val to_registers : defs tannot -> env -let rec to_registers (Defs defs) = +val to_registers : i_direction -> defs tannot -> env +let rec to_registers dd (Defs defs) = match defs with - | [ ] -> [ ] + | [ ] -> Map.empty | def::defs -> match def with - | DEF_reg_dec (DEC_aux (DEC_reg typ id) (l,tannot)) -> (id, V_register(Reg id tannot)) :: (to_registers (Defs defs)) - | DEF_reg_dec (DEC_aux (DEC_alias id aspec) (l,tannot)) -> (id, V_register_alias aspec tannot) :: (to_registers (Defs defs)) - | _ -> to_registers (Defs defs) + | DEF_reg_dec (DEC_aux (DEC_reg typ id) (l,tannot)) -> + let dir = match tannot with + | Nothing -> dd + | Just(t, _, _, _) -> dd (*TODO, lets pull the direction out properly*) + end in + Map.insert (get_id id) (V_register(Reg id tannot dir)) (to_registers dd (Defs defs)) + | DEF_reg_dec (DEC_aux (DEC_alias id aspec) (l,tannot)) -> + Map.insert (get_id id) (V_register_alias aspec tannot) (to_registers dd (Defs defs)) + | _ -> to_registers dd (Defs defs) end end -val to_aliases : defs tannot -> list (id * (alias_spec tannot)) +val to_aliases : defs tannot -> map string (alias_spec tannot) let rec to_aliases (Defs defs) = match defs with - | [] -> [] + | [] -> Map.empty | def::defs -> match def with - | DEF_reg_dec (DEC_aux (DEC_alias id aspec) _) -> (id, aspec) :: (to_aliases (Defs defs)) - | DEF_reg_dec (DEC_aux (DEC_typ_alias typ id aspec) _) -> (id, aspec) :: (to_aliases (Defs defs)) + | DEF_reg_dec (DEC_aux (DEC_alias id aspec) _) -> + Map.insert (get_id id) aspec (to_aliases (Defs defs)) + | DEF_reg_dec (DEC_aux (DEC_typ_alias typ id aspec) _) -> + Map.insert (get_id id) aspec (to_aliases (Defs defs)) | _ -> to_aliases (Defs defs) end end -val to_data_constructors : defs tannot -> list (id * typ) +val to_data_constructors : defs tannot -> map string typ let rec to_data_constructors (Defs defs) = match defs with - | [] -> [] + | [] -> Map.empty | def :: defs -> match def with | DEF_type (TD_aux t _)-> match t with | TD_variant id _ tq tid_list _ -> - (List.map - (fun (Tu_aux t _) -> + (List.foldr + (fun (Tu_aux t _) map -> match t with - | (Tu_ty_id x y) -> (y,x) - | Tu_id x -> (x,unit_t) end) tid_list)++(to_data_constructors (Defs defs)) + | (Tu_ty_id x y) -> Map.insert (get_id y) x map + | Tu_id x -> Map.insert (get_id x) unit_t map end) + (to_data_constructors (Defs defs))) tid_list | _ -> to_data_constructors (Defs defs) end | _ -> to_data_constructors (Defs defs) end end (*Memory and environment helper functions*) -val in_env :forall 'a. (list (id * 'a)) -> id -> maybe 'a -let rec in_env env id = - match env with - | [] -> Nothing - | (eid,value)::env -> if (get_id eid) = (get_id id) then Just value else in_env env id - end +val env_from_list : list (id * value) -> env +let env_from_list ls = List.foldr (fun (id,v) env -> Map.insert (get_id id) v env) Map.empty ls + +val in_env :forall 'a. map string 'a -> string -> maybe 'a +let in_env env id = Map.lookup id env val in_lenv : lenv -> id -> value let in_lenv (LEnv _ env) id = - match in_env env id with + match in_env env (get_id id) with | Nothing -> V_unknown | Just v -> v end -(*Prefer entries in the first when conflict*) -let rec list_union first second = - match first with - | [] -> second - | (id,v)::frst -> - match in_env second id with - | Nothing -> (id,v)::(list_union frst second) - | Just _ -> (id,v)::(list_union frst - (List.deleteBy (fun (id,v) (id2,v2) -> (get_id id) = (get_id id2)) - (id,v) second)) end -end - +(*Prefer entries in the first when in conflict*) val union_env : lenv -> lenv -> lenv let union_env (LEnv i1 env1) (LEnv i2 env2) = let l = if i1 < i2 then i2 else i1 in - LEnv l (list_union env1 env2) + LEnv l (Map.(union) env2 env1) val fresh_var : lenv -> (id * lenv) let fresh_var (LEnv i env) = @@ -340,7 +354,7 @@ let fresh_var (LEnv i env) = ((Id_aux (Id ((show i) ^ "var")) Interp_ast.Unknown), lenv) val add_to_env : (id * value) -> lenv -> lenv -let add_to_env entry (LEnv i env) = (LEnv i (entry::env)) +let add_to_env (id, entry) (LEnv i env) = (LEnv i (Map.insert (get_id id) entry env)) val in_mem : lmem -> nat -> value let in_mem (LMem _ m) n = @@ -481,7 +495,7 @@ let slice_vector v n1 n2 = | V_vector m dir vs -> if is_inc(dir) then V_vector n1 dir (from_n_to_n (n1 - m) (n2 - m) vs) - else V_vector (n1 - n2 + 1) dir (from_n_to_n (m - n1) (m - n2) vs) + else V_vector n1 dir (from_n_to_n (m - n1) (m - n2) vs) | V_vector_sparse m n dir vs d -> let (slice, still_sparse) = if is_inc(dir) @@ -490,15 +504,15 @@ let slice_vector v n1 n2 = if still_sparse && is_inc(dir) then V_vector_sparse n1 (n2 - n1) dir slice d else if is_inc(dir) then V_vector 0 dir (List.map snd slice) - else if still_sparse then V_vector_sparse (n1 - n2 +1) (n1 - n2) dir slice d - else V_vector (n1 - n2 +1) dir (List.map snd slice) + else if still_sparse then V_vector_sparse n1 (n1 - n2) dir slice d + else V_vector n1 dir (List.map snd slice) end ) -val update_field_list : list (id * value) -> list (id * value) -> list (id * value) +val update_field_list : list (id * value) -> env -> list (id * value) let rec update_field_list base updates = match base with | [] -> [] - | (id,v)::bs -> match in_env updates id with + | (id,v)::bs -> match in_env updates (get_id id) with | Just v -> (id,v)::(update_field_list bs updates) | Nothing -> (id,v)::(update_field_list bs updates) end end @@ -507,7 +521,7 @@ val fupdate_record : value -> value -> value let fupdate_record base updates = let fupdate_record_helper base updates = (match (base,updates) with - | (V_record t bs,V_record _ us) -> V_record t (update_field_list bs us) + | (V_record t bs,V_record _ us) -> V_record t (update_field_list bs (env_from_list us)) end) in binary_taint fupdate_record_helper base updates @@ -654,7 +668,7 @@ val add_answer_to_stack : stack -> value -> stack let rec add_answer_to_stack stack v = match stack with | Top -> Top - | Hole_frame id e t_level (LEnv i env) mem Top -> Thunk_frame e t_level (LEnv i ((id,v)::env)) mem Top + | Hole_frame id e t_level env mem Top -> Thunk_frame e t_level (add_to_env (id,v) env) mem Top | Thunk_frame e t_level env mem Top -> Thunk_frame e t_level env mem Top | Hole_frame id e t_level env mem stack -> Hole_frame id e t_level env mem (add_answer_to_stack stack v) | Thunk_frame e t_level env mem stack -> Thunk_frame e t_level env mem (add_answer_to_stack stack v) @@ -717,7 +731,7 @@ let rec combine_typs ts = let reg_to_t r = match r with - | Reg id (Just (t,_,_,_)) -> t + | Reg _ (Just (t,_,_,_)) _ -> t | _ -> T_var "fresh" end @@ -765,7 +779,7 @@ let rec to_exp mode env v : (exp tannot * lenv) = (Interp_ast.Unknown, if is_ctor then match ctor_kind with - | Just(C_Enum) -> (enum_annot (val_typ v)) + | Just(C_Enum _) -> (enum_annot (val_typ v)) | _ -> (ctor_annot (val_typ v)) end else (val_annot (val_typ v))) in let annot = mk_annot false Nothing in @@ -775,7 +789,7 @@ let rec to_exp mode env v : (exp tannot * lenv) = if mode.track_values then ((e::es), union_env ev env) else ((e::es), env)) - ([],(LEnv l [])) vs in + ([],(LEnv l Map.empty)) vs in (es, union_env env lenv) in match v with @@ -827,7 +841,7 @@ let rec to_exp mode env v : (exp tannot * lenv) = else let (e,env') = (to_exp mode env vals) in (E_aux (E_app id [e]) annotation, env') | _ -> let (e,env') = (to_exp mode env vals) in (E_aux (E_app id [e]) annotation,env') end) - | V_register (Reg id tan) -> (E_aux (E_id id) annot, env) + | V_register (Reg id tan dir) -> (E_aux (E_id id) annot, env) | V_track v' _ -> if mode.track_values then begin let (fid,env') = fresh_var env in @@ -845,11 +859,11 @@ let rec env_to_let_help mode env taint_env = match env with let tan = (val_annot t) in let (e,taint_env) = to_exp mode taint_env v in let (rest,taint_env) = env_to_let_help mode env taint_env in - ((((P_aux (P_id i) (Unknown,tan)),e),t)::rest, taint_env) + ((((P_aux (P_id (id_of_string i)) (Unknown,tan)),e),t)::rest, taint_env) end let env_to_let mode (LEnv _ env) (E_aux e annot) taint_env = - match env_to_let_help mode env taint_env with + match env_to_let_help mode (Set_extra.toList (Map.toSet env)) taint_env with | ([],taint_env) -> (E_aux e annot,taint_env) | ([((p,e),t)],tain_env) -> (E_aux (E_let (LB_aux (LB_val_implicit p e) (Unknown,(val_annot t))) e) annot,taint_env) @@ -874,11 +888,11 @@ let rec match_pattern (P_aux p _) value_whole = match p with | P_lit(lit) -> if is_lit_vector lit then - let (V_vector n inc bits) = litV_to_vec lit IInc in (*TODO use type annotation to select between increasing and decreasing*) + let (V_vector n inc bits) = litV_to_vec lit IInc in match value with | V_lit litv -> if is_lit_vector litv then - let (V_vector n' inc' bits') = litV_to_vec litv IInc in (*TODO use type annotation to select between increasing and decreasing *) + let (V_vector n' inc' bits') = litV_to_vec litv IInc in if n=n' && inc = inc' then (foldr2 (fun l r rest -> (l = r) && rest) true bits bits',false, eenv) else (false,false,eenv) else (false,false,eenv) @@ -896,12 +910,12 @@ let rec match_pattern (P_aux p _) value_whole = end | P_wild -> (true,false,eenv) | P_as pat id -> - let (matched_p,used_unknown,(LEnv bi bounds)) = match_pattern pat value in + let (matched_p,used_unknown,bounds) = match_pattern pat value in if matched_p then - (matched_p,used_unknown,(LEnv bi ((id,value_whole)::bounds))) + (matched_p,used_unknown,(add_to_env (id,value_whole) bounds)) else (false,false,eenv) - | P_typ typ pat -> match_pattern pat value_whole (* Might like to destructure against the type to get information, but that's looking less useful *) - | P_id id -> (true, false, (LEnv 0 [(id,value_whole)])) + | P_typ typ pat -> match_pattern pat value_whole + | P_id id -> (true, false, (LEnv 0 (Map.fromList [((get_id id),value_whole)]))) | P_app (Id_aux id _) pats -> match value with | V_ctor (Id_aux cid _) t ckind (V_tuple vals) -> @@ -935,10 +949,11 @@ let rec match_pattern (P_aux p _) value_whole = | P_record fpats _ -> match value with | V_record t fvals -> + let fvals_env = env_from_list fvals in List.foldr (fun (FP_aux (FP_Fpat id pat) _) (matched_p,used_unknown,bounds) -> if matched_p then - let (matched_p,used_unknown',new_bounds) = match in_env fvals id with + let (matched_p,used_unknown',new_bounds) = match in_env fvals_env (get_id id) with | Nothing -> (false,false,eenv) | Just v -> match_pattern pat v end in (matched_p, (used_unknown || used_unknown'), (union_env new_bounds bounds)) @@ -1055,10 +1070,11 @@ and vec_concat_match_plev pat r_vals dir l t = | P_id id -> (match t with | T_app "vector" (T_args [T_arg_nexp _;T_arg_nexp (Ne_const i);_;_]) -> let wilds = List.genlist (fun _ -> P_aux P_wild (l,Nothing)) (natFromInteger i) in - let (matched_p,used_unknown,(LEnv bi bounds),matcheds,r_vals) = vec_concat_match wilds r_vals in + let (matched_p,used_unknown,bounds,matcheds,r_vals) = vec_concat_match wilds r_vals in if matched_p then (matched_p, used_unknown, - (LEnv bi ((id,(V_vector (if is_inc(dir) then 0 else (List.length matcheds)) dir matcheds))::bounds)), + (add_to_env (id,(V_vector (if is_inc(dir) then 0 else (List.length matcheds)) dir matcheds)) + bounds), matcheds,r_vals) else (false,false,eenv,[],[]) | T_app "vector" (T_args [T_arg_nexp _;T_arg_nexp nc;_;_]) -> @@ -1072,10 +1088,10 @@ and vec_concat_match_plev pat r_vals dir l t = (false,false,eenv,[],[]) (*TODO see if can have some constraint bounds here*) | _ -> (false,false,eenv,[],[]) end) | P_as (P_aux pat (l',Just(t,_,_,_))) id -> - let (matched_p, used_unknown, (LEnv bi bounds),matcheds,r_vals) = vec_concat_match_plev pat r_vals dir l t in + let (matched_p, used_unknown, bounds,matcheds,r_vals) = vec_concat_match_plev pat r_vals dir l t in if matched_p then (matched_p, used_unknown, - (LEnv bi ((id,V_vector (if is_inc(dir) then 0 else (List.length matcheds)) dir matcheds)::bounds)), + (add_to_env (id,V_vector (if is_inc(dir) then 0 else (List.length matcheds)) dir matcheds) bounds), matcheds,r_vals) else (false,false,eenv,[],[]) | P_typ _ (P_aux p (l',Just(t',_,_,_))) -> vec_concat_match_plev p r_vals dir l t @@ -1159,7 +1175,7 @@ let rec exp_list mode t_level build_e build_v l_env l_mem vals exps = end and interp_main mode t_level l_env l_mem (E_aux exp (l,annot)) = - let (Env defs instrs default_dir lets regs ctors subregs aliases) = t_level in + let (Env fdefs instrs default_dir lets regs ctors subregs aliases) = t_level in let (typ,tag,ncs,effect) = match annot with | Nothing -> (T_var "fresh_v", Tag_empty, [], (Effect_aux (Effect_set []) Unknown)) | Just(t, tag, ncs, ef) -> (t,tag,ncs,ef) end in @@ -1184,6 +1200,14 @@ and interp_main mode t_level l_env l_mem (E_aux exp (l,annot)) = | V_vector start dir vs -> if start = i then (Value v,lm,le) else (Value (update_vector_start dir i 1 v),lm,le) | _ -> (Value v,lm,le) end + | Typ_app (Id_aux (Id "vector") _) + [Typ_arg_aux (Typ_arg_nexp(Nexp_aux (Nexp_var (Kid_aux (Var "length") _)) _)) _;_;_;_] -> + match (detaint v) with + | V_vector start dir vs -> + let i = (List.length vs) - 1 in + if start = i then (Value v,lm,le) else (Value (update_vector_start dir i 1 v),lm,le) + | _ -> (Value v,lm,le) end + | _ -> (Value v,lm,le) end in (match (tag,detaint v) with (*Cast is telling us to read a register*) @@ -1202,14 +1226,14 @@ and interp_main mode t_level l_env l_mem (E_aux exp (l,annot)) = | V_boxref n t -> (Value (in_mem l_mem n),l_mem,l_env) | value -> (Value value,l_mem,l_env) end | Tag_global -> - match in_env lets id with + match in_env lets name with | Just(value) -> (Value value, l_mem,l_env) | Nothing -> - (match in_env regs id with + (match in_env regs name with | Just(value) -> (Value value, l_mem,l_env) | Nothing -> (Error l ("Internal error: " ^ name ^ " unbound on Tag_global"),l_mem,l_env) end) end | Tag_enum -> - match in_env lets id with + match in_env lets name with | Just(value) -> (Value value,l_mem,l_env) | Nothing -> (Error l ("Internal error: " ^ name ^ " unbound on Tag_enum "), l_mem,l_env) end @@ -1217,14 +1241,14 @@ and interp_main mode t_level l_env l_mem (E_aux exp (l,annot)) = let regf = match in_lenv l_env id with (* Check for local treatment of a register as a value *) | V_register regform -> regform | _ -> - match in_env regs id with (* Register isn't a local value, so pull from global environment *) + match in_env regs name with (* Register isn't a local value, so pull from global environment *) | Just(V_register regform) -> regform - | _ -> Reg id annot end end in + | _ -> Reg id annot default_dir end end in (Action (Read_reg regf Nothing) (Hole_frame redex_id (E_aux (E_id redex_id) (l,intern_annot annot)) t_level l_env l_mem Top),l_mem,l_env) | Tag_alias -> - match in_env aliases id with + match in_env aliases name with | Just aspec -> interp_alias_read mode t_level l_env l_mem aspec | _ -> (Error l ("Internal error: alias not found"), l_mem,l_env) end | _ -> @@ -1393,17 +1417,17 @@ and interp_main mode t_level l_env l_mem (E_aux exp (l,annot)) = (fun value_whole lm le -> match detaint value_whole with | V_record t fexps -> - (match in_env fexps id with + (match in_env (env_from_list fexps) (get_id id) with | Just v -> (Value (retaint value_whole v),lm,l_env) | Nothing -> (Error l "Internal_error: Field not found in record",lm,le) end) - | V_register ((Reg _ annot) as reg_form) -> + | V_register ((Reg _ annot _) as reg_form) -> let id' = match annot with | Just((T_id id'),_,_,_) -> id' | Just((T_abbrev (T_id id') _),_,_,_) -> id' end in - (match in_env subregs (Id_aux (Id id') Unknown) with + (match in_env subregs id' with | Just(indexes) -> - (match in_env indexes id with + (match in_env indexes (get_id id) with | Just ir -> let sub_reg = SubReg id reg_form ir in (Action (Read_reg sub_reg Nothing) @@ -1418,20 +1442,20 @@ and interp_main mode t_level l_env l_mem (E_aux exp (l,annot)) = (fun a -> match (exp,a) with | (E_aux _ (l,Just(_,Tag_extern _,_,_)), - (Action (Read_reg ((Reg _ (Just((T_id id'),_,_,_))) as regf) Nothing) s)) -> - match in_env subregs (Id_aux (Id id') Unknown) with + (Action (Read_reg ((Reg _ (Just((T_id id'),_,_,_)) _) as regf) Nothing) s)) -> + match in_env subregs id' with | Just(indexes) -> - (match in_env indexes id with + (match in_env indexes (get_id id) with | Just ir -> (Action (Read_reg (SubReg id regf ir) Nothing) s) | _ -> Error l "Internal error, unrecognized read, no id" end) | Nothing -> Error l "Internal error, unrecognized read, no reg" end | (E_aux _ (l,Just(_,Tag_extern _,_,_)), - (Action (Read_reg ((Reg _ (Just((T_abbrev (T_id id') _),_,_,_))) as regf) Nothing) s))-> - match in_env subregs (Id_aux (Id id') Unknown) with + (Action (Read_reg ((Reg _ (Just((T_abbrev (T_id id') _),_,_,_)) _) as regf) Nothing) s))-> + match in_env subregs id' with | Just(indexes) -> - match in_env indexes id with + match in_env indexes (get_id id) with | Just ir -> (Action (Read_reg (SubReg id regf ir) Nothing) s) | _ -> Error l "Internal error, unrecognized read, no id" @@ -1714,7 +1738,7 @@ and interp_main mode t_level l_env l_mem (E_aux exp (l,annot)) = let name = get_id f in (match tag with | Tag_global -> - (match find_function defs f with + (match Map.lookup name fdefs with | Just(funcls) -> (match find_funcl funcls v with | [] -> @@ -1737,9 +1761,9 @@ and interp_main mode t_level l_env l_mem (E_aux exp (l,annot)) = interp_main mode t_level taint_env lm (E_aux (E_block lets) (l,annot)) end) | Nothing -> - (Error l (String.stringAppend "Internal error: function with empty tag unfound " name),lm,le) end) + (Error l (String.stringAppend "Internal error: function with tag global unfound " name),lm,le) end) | Tag_empty -> - (match find_function defs f with + (match Map.lookup name fdefs with | Just(funcls) -> (match find_funcl funcls v with | [] -> @@ -1758,7 +1782,7 @@ and interp_main mode t_level l_env l_mem (E_aux exp (l,annot)) = | Nothing -> (Error l (String.stringAppend "Internal error: function with empty tag unfound " name),lm,le) end) | Tag_spec -> - (match find_function defs f with + (match Map.lookup name fdefs with | Just(funcls) -> (match find_funcl funcls v with | [] -> @@ -1777,7 +1801,7 @@ and interp_main mode t_level l_env l_mem (E_aux exp (l,annot)) = | Nothing -> (Error l (String.stringAppend "Specified function must be defined before executing " name),lm,le) end) | Tag_ctor -> - (match in_ctors ctors f with + (match Map.lookup name ctors with | Just(_) -> (Value (V_ctor f typ C_Union v), lm, le) | Nothing -> (Error l (String.stringAppend "Internal error: function with ctor tag unfound " name),lm,le) end) @@ -1824,7 +1848,7 @@ and interp_main mode t_level l_env l_mem (E_aux exp (l,annot)) = (fun rv lm le -> match tag with | Tag_global -> - (match find_function defs op with + (match Map.lookup name fdefs with | Nothing -> (Error l ("Internal error, no function def for " ^ name),lm,le) | Just (funcls) -> (match find_funcl funcls (V_tuple [lv;rv]) with @@ -1842,7 +1866,7 @@ and interp_main mode t_level l_env l_mem (E_aux exp (l,annot)) = t_level l_env l_mem stack))) end)end) | Tag_empty -> - (match find_function defs op with + (match Map.lookup name fdefs with | Nothing -> (Error l ("Internal error, no function def for " ^ name),lm,le) | Just (funcls) -> (match find_funcl funcls (V_tuple [lv;rv]) with @@ -1858,7 +1882,7 @@ and interp_main mode t_level l_env l_mem (E_aux exp (l,annot)) = t_level l_env l_mem stack))) end)end) | Tag_spec -> - (match find_function defs op with + (match Map.lookup name fdefs with | Nothing -> (Error l ("No function definition found for " ^ name),lm,le) | Just (funcls) -> (match find_funcl funcls (V_tuple [lv;rv]) with @@ -1938,12 +1962,13 @@ and interp_main mode t_level l_env l_mem (E_aux exp (l,annot)) = and create_write_message_or_update mode t_level value l_env l_mem is_top_level ((LEXP_aux lexp (l,annot)):lexp tannot) : ((outcome * lmem * lenv) * maybe ((exp tannot) -> lenv -> ((lexp tannot) * lenv))) = - let (Env defs instrs default_dir lets regs ctors subregs aliases) = t_level in + let (Env fdefs instrs default_dir lets regs ctors subregs aliases) = t_level in let (typ,tag,ncs,ef) = match annot with | Nothing -> (T_var "fresh_v", Tag_empty, [], (Effect_aux (Effect_set []) Unknown)) | Just(t, tag, ncs, ef) -> (t,tag,ncs,ef) end in match lexp with | LEXP_id id -> + let name = get_id id in match tag with | Tag_empty -> match detaint (in_lenv l_env id) with @@ -1963,7 +1988,7 @@ and create_write_message_or_update mode t_level value l_env l_mem is_top_level ( else ((Value v,l_mem,l_env),Just (fun e env -> (LEXP_aux(LEXP_id id) (l,annot), env))) end | Tag_global -> - (match in_env lets id with + (match in_env lets name with | Just v -> if is_top_level then ((Error l "Writes must be to reg or registers",l_mem,l_env),Nothing) else ((Value v,l_mem,l_env),Just (fun e env -> (LEXP_aux(LEXP_id id) (l,annot), env))) @@ -1971,7 +1996,7 @@ and create_write_message_or_update mode t_level value l_env l_mem is_top_level ( end) | Tag_extern _ -> let regf = - match in_env regs id with (*pull the regform with the most specific type annotation from env *) + match in_env regs name with (*pull the regform with the most specific type annotation from env *) | Just(V_register regform) -> regform | _ -> Assert_extra.failwith "Register not known in regenv" end in let start_pos = reg_start_pos regf in @@ -1984,16 +2009,16 @@ and create_write_message_or_update mode t_level value l_env l_mem is_top_level ( else (request,Just (fun e env -> (LEXP_aux (LEXP_id id) (l,annot), env))) | Tag_alias -> let request = - (match in_env aliases id with + (match in_env aliases name with | Just (AL_aux aspec (l,_)) -> (match aspec with | AL_subreg (RI_aux (RI_id reg) (li, ((Just((T_id id),_,_,_)) as annot'))) subreg -> - (match in_env subregs (Id_aux (Id id) Unknown) with + (match in_env subregs id with | Just indexes -> - (match in_env indexes subreg with + (match in_env indexes (get_id subreg) with | Just ir -> (Action - (Write_reg (SubReg subreg (Reg reg annot') ir) Nothing + (Write_reg (SubReg subreg (Reg reg annot' default_dir) ir) Nothing (update_vector_start default_dir (get_first_index_range ir) (get_index_range_size ir) value)) (Thunk_frame (E_aux (E_lit (L_aux L_unit l)) (l, intern_annot annot)) t_level l_env l_mem Top), l_mem, l_env) @@ -2001,12 +2026,12 @@ and create_write_message_or_update mode t_level value l_env l_mem is_top_level ( | _ -> (Error l ("Internal error: alias spec has unknown register type " ^ id), l_mem, l_env) end) | AL_subreg (RI_aux (RI_id reg) (li, ((Just((T_abbrev (T_id id) _),_,_,_)) as annot'))) subreg -> - (match in_env subregs (Id_aux (Id id) Unknown) with + (match in_env subregs id with | Just indexes -> - (match in_env indexes subreg with + (match in_env indexes (get_id subreg) with | Just ir -> (Action - (Write_reg (SubReg subreg (Reg reg annot') ir) Nothing + (Write_reg (SubReg subreg (Reg reg annot' default_dir) ir) Nothing (update_vector_start default_dir (get_first_index_range ir) (get_index_range_size ir) value)) (Thunk_frame (E_aux (E_lit (L_aux L_unit l)) (l, intern_annot annot)) t_level l_env l_mem Top), l_mem, l_env) @@ -2017,7 +2042,7 @@ and create_write_message_or_update mode t_level value l_env l_mem is_top_level ( (fun v le lm -> match v with | V_lit (L_aux (L_num i) _) -> let i = natFromInteger i in - (Action (Write_reg (Reg reg annot') (Just (i,i)) + (Action (Write_reg (Reg reg annot' default_dir) (Just (i,i)) (update_vector_start default_dir i 1 value)) (Thunk_frame (E_aux (E_lit (L_aux L_unit l)) (l, intern_annot annot)) t_level l_env l_mem Top), l_mem, l_env) end) @@ -2033,7 +2058,7 @@ and create_write_message_or_update mode t_level value l_env l_mem is_top_level ( | V_lit (L_aux (L_num stop) _) -> let (start,stop) = (natFromInteger start,natFromInteger stop) in let size = if start < stop then stop - start +1 else start -stop +1 in - (Action (Write_reg (Reg reg annot') (Just (start,stop)) + (Action (Write_reg (Reg reg annot' default_dir) (Just (start,stop)) (update_vector_start default_dir start size value)) (Thunk_frame (E_aux (E_lit (L_aux L_unit l)) (l, intern_annot annot)) t_level l_env l_mem Top), @@ -2050,7 +2075,8 @@ and create_write_message_or_update mode t_level value l_env l_mem is_top_level ( | (T_app "vector" (T_args [T_arg_nexp (Ne_const b1); T_arg_nexp (Ne_const r1); _;_]), T_app "vector" (T_args [T_arg_nexp (Ne_const b2); T_arg_nexp (Ne_const r2); _;_])) -> (Action - (Write_reg (Reg reg1 annot1) Nothing (slice_vector value (natFromInteger b1) (natFromInteger r1))) + (Write_reg (Reg reg1 annot1 default_dir) Nothing + (slice_vector value (natFromInteger b1) (natFromInteger r1))) (Thunk_frame (E_aux (E_assign (LEXP_aux (LEXP_id reg2) annot2) (fst (to_exp <| mode with track_values =false|> eenv (slice_vector value (natFromInteger (r1+1)) (natFromInteger r2))))) @@ -2080,7 +2106,7 @@ and create_write_message_or_update mode t_level value l_env l_mem is_top_level ( (LEXP_aux (LEXP_memory id parms) (l,annot), env))) | Tag_global -> let name = get_id id in - (match find_function defs id with + (match Map.lookup name fdefs with | Just(funcls) -> let new_vals = match v with | V_tuple vs -> V_tuple (vs ++ [value]) @@ -2113,6 +2139,7 @@ and create_write_message_or_update mode t_level value l_env l_mem is_top_level ( ((Action a s,lm,le), Just (fun (E_aux (E_tuple es) _) env -> (LEXP_aux (LEXP_memory id es) (l,annot), env))) | e -> (e,Nothing) end | LEXP_cast typc id -> + let name = get_id id in match tag with | Tag_empty -> match detaint (in_lenv l_env id) with @@ -2135,7 +2162,7 @@ and create_write_message_or_update mode t_level value l_env l_mem is_top_level ( end | Tag_extern _ -> let regf = - match in_env regs id with (*pull the regform with the most specific type annotation from env *) + match in_env regs name with (*pull the regform with the most specific type annotation from env *) | Just(V_register regform) -> regform | _ -> Assert_extra.failwith "Register not known in regenv" end in let start_pos = reg_start_pos regf in @@ -2310,7 +2337,7 @@ and create_write_message_or_update mode t_level value l_env l_mem is_top_level ( | ((Value (V_record t fexps),lm,le),Just lexp_builder) -> let next_builder = Just (fun e env -> let (lexp,env) = (lexp_builder e env) in (LEXP_aux (LEXP_field lexp id) (l,annot), env)) in - match (in_env fexps id,is_top_level) with + match (in_env (env_from_list fexps) (get_id id),is_top_level) with | (Just (V_boxref n t),true) -> ((Value (V_lit (L_aux L_unit l)), update_mem lm n value, l_env),Nothing) | (Just (V_boxref n t),false) -> ((Value (in_mem lm n),lm,l_env),next_builder) | (Just v, true) -> ((Error l "Mutating a field access requires a reg type",lm,le),Nothing) @@ -2323,10 +2350,10 @@ and create_write_message_or_update mode t_level value l_env l_mem is_top_level ( | Read_reg _ _ -> ((Action a s,lm,le), next_builder) | Read_mem _ _ _ -> ((Action a s,lm,le), next_builder) | Call_extern _ _ -> ((Action a s,lm,le), next_builder) - | Write_reg ((Reg _ (Just(T_id id',_,_,_))) as regf) Nothing value -> - match in_env subregs (Id_aux (Id id') Unknown) with + | Write_reg ((Reg _ (Just(T_id id',_,_,_)) _) as regf) Nothing value -> + match in_env subregs id' with | Just(indexes) -> - match in_env indexes id with + match in_env indexes (get_id id) with | Just ir -> ((Action (Write_reg (SubReg id regf ir) Nothing @@ -2336,10 +2363,10 @@ and create_write_message_or_update mode t_level value l_env l_mem is_top_level ( | _ -> ((Error l "Internal error, unrecognized write, no field",lm,le),Nothing) end | Nothing -> ((Error l "Internal error, unrecognized write, no subreges",lm,le),Nothing) end - | Write_reg ((Reg _ (Just((T_abbrev(T_id id') _),_,_,_))) as regf) Nothing value -> - match in_env subregs (Id_aux (Id id') Unknown) with + | Write_reg ((Reg _ (Just((T_abbrev(T_id id') _),_,_,_)) _) as regf) Nothing value -> + match in_env subregs id' with | Just(indexes) -> - match in_env indexes id with + match in_env indexes (get_id id) with | Just ir -> ((Action (Write_reg (SubReg id regf ir) Nothing @@ -2352,7 +2379,7 @@ and create_write_message_or_update mode t_level value l_env l_mem is_top_level ( | _ -> ((Error l "Internal error, unrecognized write, no matching action",lm,le),Nothing) end | e -> e end) - end + end and interp_letbind mode t_level l_env l_mem (LB_aux lbind (l,annot)) = match lbind with @@ -2385,10 +2412,10 @@ and interp_alias_read mode t_level l_env l_mem (AL_aux alspec (l,annot)) = match alspec with | AL_subreg (RI_aux (RI_id reg) (li,((Just (t,_,_,_)) as annot'))) subreg -> let reg_ti = get_reg_typ_name t in - (match in_env subregs (Id_aux (Id reg_ti) Unknown) with + (match in_env subregs reg_ti with | Just indexes -> - (match in_env indexes subreg with - | Just ir -> (Action (Read_reg (SubReg subreg (Reg reg annot') ir) Nothing) stack, l_mem, l_env) + (match in_env indexes (get_id subreg) with + | Just ir -> (Action (Read_reg (SubReg subreg (Reg reg annot' default_dir) ir) Nothing) stack, l_mem, l_env) | _ -> (Error l "Internal error, alias spec has unknown field", l_mem, l_env) end) | _ -> (Error l (String.stringAppend "Internal error: alias spec has unknown register type " reg_ti), l_mem, l_env) end) | AL_bit (RI_aux (RI_id reg) (_,annot')) e -> @@ -2396,7 +2423,7 @@ and interp_alias_read mode t_level l_env l_mem (AL_aux alspec (l,annot)) = (fun v le lm -> match v with | V_lit (L_aux (L_num i) _) -> let i = natFromInteger i in - (Action (Read_reg (Reg reg annot') (Just (i,i))) stack, l_mem, l_env) end) + (Action (Read_reg (Reg reg annot' default_dir) (Just (i,i))) stack, l_mem, l_env) end) (fun a -> a) (*Should not currently happen as type system enforces constants*) | AL_slice (RI_aux (RI_id reg) (_,annot')) start stop -> resolve_outcome (interp_main mode t_level l_env l_mem start) @@ -2409,11 +2436,11 @@ and interp_alias_read mode t_level l_env l_mem (AL_aux alspec (l,annot)) = (match v with | V_lit (L_aux (L_num stop) _) -> let (start,stop) = (natFromInteger start,natFromInteger stop) in - (Action (Read_reg (Reg reg annot') (Just (start,stop))) stack, l_mem, l_env) end)) + (Action (Read_reg (Reg reg annot' default_dir) (Just (start,stop))) stack, l_mem, l_env) end)) (fun a -> a)) end) (fun a -> a) (*Neither action function should occur, due to above*) | AL_concat (RI_aux (RI_id reg1) (l1, annot1)) (RI_aux (RI_id reg2) annot2) -> - (Action (Read_reg (Reg reg1 annot1) Nothing) + (Action (Read_reg (Reg reg1 annot1 default_dir) Nothing) (Hole_frame (Id_aux (Id "0") Unknown) (E_aux (E_vector_append (E_aux (E_id (Id_aux (Id "0") l1)) (l1, (intern_annot annot1))) (E_aux (E_id reg2) annot2)) @@ -2432,7 +2459,7 @@ let rec eval_toplevel_let handle_action tlevel env mem lbind = | _ -> Nothing end let rec to_global_letbinds handle_action (Defs defs) t_level = - let (Env defs' instrs default_dir lets regs ctors subregs aliases) = t_level in + let (Env fdefs instrs default_dir lets regs ctors subregs aliases) = t_level in match defs with | [] -> ((Value (V_lit (L_aux L_unit Unknown)), emem, eenv),t_level) | def::defs -> @@ -2440,15 +2467,22 @@ let rec to_global_letbinds handle_action (Defs defs) t_level = | DEF_val lbind -> match eval_toplevel_let handle_action t_level eenv emem lbind with | Just le -> - to_global_letbinds handle_action (Defs defs) (Env defs' instrs default_dir (lets++le) regs ctors subregs aliases) + to_global_letbinds handle_action (Defs defs) + (Env fdefs instrs default_dir (Map.(union) lets le) regs ctors subregs aliases) | Nothing -> - to_global_letbinds handle_action (Defs defs) (Env defs' instrs default_dir lets regs ctors subregs aliases) end + to_global_letbinds handle_action (Defs defs) + (Env fdefs instrs default_dir lets regs ctors subregs aliases) end | DEF_type (TD_aux tdef _) -> match tdef with | TD_enum id ns ids _ -> - let enum_vals = map (fun eid -> (eid,V_ctor eid (T_id (get_id id)) C_Enum unitv)) ids in + let typ = T_id (get_id id) in + let enum_vals = + Map.fromList + (snd + (List.foldl (fun (c,rst) eid -> (1+c,(get_id eid,V_ctor eid typ (C_Enum c) unitv)::rst)) (0,[]) ids)) in to_global_letbinds - handle_action (Defs defs) (Env defs' instrs default_dir (lets++enum_vals) regs ctors subregs aliases) + handle_action (Defs defs) + (Env fdefs instrs default_dir (Map.(union) lets enum_vals) regs ctors subregs aliases) | _ -> to_global_letbinds handle_action (Defs defs) t_level end | _ -> to_global_letbinds handle_action (Defs defs) t_level end @@ -2465,10 +2499,12 @@ let rec extract_default_direction (Defs defs) = match defs with (*TODO Contemplate making decode and execute environment variables instead of these constants*) let to_top_env external_functions defs = let direction = (extract_default_direction defs) in - let t_level = Env defs (extract_instructions "decode" "execute" defs) + let t_level = Env (to_fdefs defs) + (extract_instructions "decode" "execute" defs) direction - [] (* empty letbind and enum values, call below will fill in any *) - (to_registers defs) (to_data_constructors defs) (to_register_fields defs) (to_aliases defs) in + Map.empty (* empty letbind and enum values, call below will fill in any *) + (to_registers direction defs) + (to_data_constructors defs) (to_register_fields defs) (to_aliases defs) in let (o,t_level) = to_global_letbinds (external_functions direction) defs t_level in match o with | (Value _,_,_) -> (Nothing,t_level) diff --git a/src/lem_interp/interp_inter_imp.lem b/src/lem_interp/interp_inter_imp.lem index da87842d..4a9964e2 100644 --- a/src/lem_interp/interp_inter_imp.lem +++ b/src/lem_interp/interp_inter_imp.lem @@ -9,13 +9,15 @@ open import Assert_extra val intern_reg_value : register_value -> Interp.value val intern_mem_value : direction -> memory_value -> Interp.value -val extern_reg_value : maybe nat -> Interp.value -> register_value +val extern_reg_value : Interp.i_direction -> maybe nat -> Interp.value -> register_value val extern_mem_value : interp_mode -> Interp.value -> (memory_value * maybe (list reg_name)) val extern_reg : Interp.reg_form -> maybe (nat * nat) -> reg_name let make_mode eager_eval tracking_values = <| Interp.eager_eval = eager_eval; Interp.track_values = tracking_values |>;; let tracking_dependencies mode = mode.Interp.track_values +let make_eager_mode mode = <| mode with Interp.eager_eval = true |>;; +let make_default_mode _ = <| Interp.eager_eval = false; Interp.track_values = false |>;; let bitl_to_ibit = function | Bitl_zero -> (Interp.V_lit (L_aux L_zero Interp_ast.Unknown)) @@ -84,6 +86,11 @@ let intern_direction = function | D_decreasing -> Interp.IDec end +let extern_direction = function + | Interp.IInc -> D_increasing + | Interp.IDec -> D_decreasing +end + let intern_opcode direction (Opcode v) = let bits = List.concatMap (fun (Byte(bits)) -> (List.map bit_to_ibit bits)) v in let direction = intern_direction direction in @@ -91,7 +98,7 @@ let intern_opcode direction (Opcode v) = let intern_reg_value v = match v with | <| rv_bits=[b] |> -> bitl_to_ibit b - | _ -> Interp.V_vector v.rv_start (intern_direction v.rv_dir) (bitls_to_ibits v.rv_bits) + | _ -> Interp.V_vector v.rv_start_internal (intern_direction v.rv_dir) (bitls_to_ibits v.rv_bits) end let intern_mem_value direction v = @@ -104,81 +111,76 @@ let intern_ifield_value direction v = let direction = intern_direction direction in Interp.V_vector (if Interp.is_inc direction then 0 else (List.length(bits) -1)) direction bits -(*let byte_list_of_integer size num = - if (num < 0) - then failwith "signed integer given to byte_list_of_integer" - else let internal_value = (Interp_lib.to_vec_inc - (Interp.V_tuple([Interp.V_lit(L_aux (L_num (size * 8)) Interp_ast.Unknown); - Interp.V_lit(L_aux (L_num num) Interp_ast.Unknown)]))) in - let num_check = Interp_lib.to_num Interp_lib.Unsigned internal_value in - match (num_check,internal_value) with - | (Interp.V_lit (L_aux (L_num n) _), Interp.V_vector _ _ bits) -> - if num = n - then (to_bytes (from_bits bits)) - else failwith "byte_list_of_integer given an integer larger than given size" - end -*) - let num_to_bits size kind num = (* num_to_bits needed in src_power_get/trans_sail.gen - rather than reengineer the generation, we include a wrapper here *) Interp_interface.bit_list_of_integer size num - -(* - match kind with - | Bitv -> Bitvector (match (Interp_lib.to_vec_inc - (Interp.V_tuple([Interp.V_lit(L_aux (L_num (integerFromNat size)) Interp_ast.Unknown); - Interp.V_lit(L_aux (L_num num) Interp_ast.Unknown)]))) with - | Interp.V_vector _ _ bits -> from_bits bits end) true 0 - | Bytev -> Bytevector (byte_list_of_integer (integerFromNat (size/8)) num) -end - -let integer_of_byte_list bytes = - let intv = intern_value (Bytevector bytes) in - match Interp_lib.to_num Interp_lib.Unsigned intv with - | Interp.V_lit (L_aux (L_num n) _) -> n - end -*) +let extern_slice (d:direction) (start:nat) ((i,j):(nat*nat)) = + match d with + | D_increasing -> (i,j) (*This is the case the thread/concurrecny model expects, so no change needed*) + | D_decreasing -> + let slice_i = start - i in + let slice_j = (i - j) + slice_i in + (slice_i,slice_j) + end let extern_reg r slice = match (r,slice) with - | (Interp.Reg (Id_aux (Id x) _) (Just(t,_,_,_)),Nothing) -> - Reg x (Interp.reg_size r) - | (Interp.Reg (Id_aux (Id x) _) (Just(t,_,_,_)),Just(i1,i2)) -> Reg_slice x (intFromNat i1, intFromNat i2) - | (Interp.SubReg (Id_aux (Id x) _) (Interp.Reg (Id_aux (Id y) _) _) (BF_aux(BF_single i) _),Nothing) -> - let i = intFromInteger i in - Reg_field y x (i,i) - | (Interp.SubReg (Id_aux (Id x) _) (Interp.Reg (Id_aux (Id y) _) _) (BF_aux(BF_range i j) _), Nothing) -> - Reg_field y x (intFromInteger i,intFromInteger j) - | (Interp.SubReg (Id_aux (Id x) _) (Interp.Reg (Id_aux (Id y) _) _) (BF_aux(BF_range i j) _), Just(i1,j1)) -> - Reg_f_slice y x (intFromInteger i,intFromInteger j) (intFromNat i1, intFromNat j1) + | (Interp.Reg (Id_aux (Id x) _) (Just(t,_,_,_)) dir,Nothing) -> + Reg x (Interp.reg_start_pos r) (Interp.reg_size r) (extern_direction dir) + | (Interp.Reg (Id_aux (Id x) _) (Just(t,_,_,_)) dir,Just(i1,i2)) -> + let start = Interp.reg_start_pos r in + let edir = extern_direction dir in + Reg_slice x start edir (extern_slice edir start (i1, i2)) + | (Interp.SubReg (Id_aux (Id x) _) ((Interp.Reg (Id_aux (Id y) _) _ dir) as main_r) (BF_aux(BF_single i) _),Nothing) -> + let i = natFromInteger i in + let start = Interp.reg_start_pos main_r in + let edir = extern_direction dir in + Reg_field y start edir x (extern_slice edir start (i,i)) + | (Interp.SubReg (Id_aux (Id x) _) ((Interp.Reg (Id_aux (Id y) _) _ dir) as main_r) (BF_aux(BF_range i j) _), Nothing) -> + let start = Interp.reg_start_pos main_r in + let edir = extern_direction dir in + Reg_field y start edir x (extern_slice edir start (natFromInteger i,natFromInteger j)) + | (Interp.SubReg (Id_aux (Id x) _) + ((Interp.Reg (Id_aux (Id y) _) _ dir) as main_r) (BF_aux(BF_range i j) _), Just(i1,j1)) -> + let start = Interp.reg_start_pos main_r in + let edir = extern_direction dir in + Reg_f_slice y start edir x (extern_slice edir start (natFromInteger i,natFromInteger j)) + (extern_slice edir start (i1, j1)) end -let rec extern_reg_value optional_start v = match v with - | Interp.V_track v regs -> extern_reg_value optional_start v - | Interp.V_vector fst dir bits -> - <| rv_bits=(bitls_from_ibits bits); - rv_dir=(if Interp.is_inc(dir) then D_increasing else D_decreasing); - rv_start=fst|> - | Interp.V_vector_sparse fst stop inc bits default -> - extern_reg_value optional_start (Interp_lib.fill_in_sparse v) +let rec extern_reg_value dir optional_start v = + let start = match optional_start with | Nothing -> 0 | Just i -> i end in + let is_inc = Interp.is_inc(dir) in + match v with + | Interp.V_track v regs -> extern_reg_value dir optional_start v + | Interp.V_vector fst dir bits -> + let is_inc = Interp.is_inc(dir) in + let width = List.length bits in + <| rv_bits=(bitls_from_ibits bits); + rv_dir=(if is_inc then D_increasing else D_decreasing); + rv_start=if is_inc then fst else (fst +1 - width); + rv_start_internal = fst; + |> + | Interp.V_vector_sparse fst stop inc bits default -> + extern_reg_value dir optional_start (Interp_lib.fill_in_sparse v) | Interp.V_lit (L_aux L_zero _) -> - let start = match optional_start with | Nothing -> 0 | Just i -> i end in - <| rv_bits=[Bitl_zero]; rv_dir=D_increasing; rv_start=start |> + <| rv_bits=[Bitl_zero]; rv_dir= if is_inc then D_increasing else D_decreasing; + rv_start= start; rv_start_internal=start |> | Interp.V_lit (L_aux L_false _) -> - let start = match optional_start with | Nothing -> 0 | Just i -> i end in - <| rv_bits=[Bitl_zero]; rv_dir=D_increasing; rv_start=start |> + <| rv_bits=[Bitl_zero]; rv_dir=if is_inc then D_increasing else D_decreasing; + rv_start=start; rv_start_internal = start |> | Interp.V_lit (L_aux L_one _) -> - let start = match optional_start with | Nothing -> 0 | Just i -> i end in - <| rv_bits=[Bitl_one]; rv_dir=D_increasing; rv_start=start |> + <| rv_bits=[Bitl_one]; rv_dir=if is_inc then D_increasing else D_decreasing; + rv_start=start; rv_start_internal = start |> | Interp.V_lit (L_aux L_true _) -> - let start = match optional_start with | Nothing -> 0 | Just i -> i end in - <| rv_bits=[Bitl_one]; rv_dir=D_increasing; rv_start=start |> + <| rv_bits=[Bitl_one]; rv_dir=if is_inc then D_increasing else D_decreasing; + rv_start=start; rv_start_internal = start |> | Interp.V_lit (L_aux L_undef _) -> - let start = match optional_start with | Nothing -> 0 | Just i -> i end in - <| rv_bits=[Bitl_undef]; rv_dir=D_increasing; rv_start=start |> + <| rv_bits=[Bitl_undef]; rv_dir=if is_inc then D_increasing else D_decreasing; + rv_start=start; rv_start_internal = start |> | Interp.V_unknown -> - let start = match optional_start with | Nothing -> 0 | Just i -> i end in - <| rv_bits=[Bitl_unknown]; rv_dir=D_increasing; rv_start=start |> + <| rv_bits=[Bitl_unknown]; rv_dir=if is_inc then D_increasing else D_decreasing; + rv_start=start; rv_start_internal = start |> end let rec extern_mem_value mode v = match v with @@ -416,14 +418,18 @@ let rec interp_to_outcome mode context thunk = | Interp.Write_reg reg_form slice value -> let optional_start = match slice with | Just (st1,st2) -> if (st1=st2) then Just st1 else Nothing | _ -> Nothing end in - Write_reg (extern_reg reg_form slice) (extern_reg_value optional_start value) (IState next_state context) + Write_reg (extern_reg reg_form slice) + (extern_reg_value internal_direction optional_start value) (IState next_state context) | Interp.Read_mem (Id_aux (Id i) _) value slice -> match List.lookup i mem_reads with | (Just (MR read_k f)) -> let (location, length, tracking) = (f mode value) in if (List.length location) = 8 - then Read_mem read_k (Address_lifted location) length tracking - (fun v -> IState (Interp.add_answer_to_stack next_state (intern_mem_value direction v)) context) + then let address_int = match (maybe_all (List.map byte_of_byte_lifted location)) with + | Just bs -> Just (integer_of_byte_list bs) + | _ -> Nothing end in + Read_mem read_k (Address_lifted location address_int) length tracking + (fun v -> IState (Interp.add_answer_to_stack next_state (intern_mem_value direction v)) context) else Error ("Memory address on read is not 64 bits") | _ -> Error ("Memory " ^ i ^ " function with read kind not found") end @@ -433,9 +439,12 @@ let rec interp_to_outcome mode context thunk = let (location, length, tracking) = (f mode loc_val) in let (value, v_tracking) = (extern_mem_value mode write_val) in if (List.length location) = 8 - then Write_mem write_k (Address_lifted location) - length tracking value v_tracking - (fun b -> + then let address_int = match (maybe_all (List.map byte_of_byte_lifted location)) with + | Just bs -> Just (integer_of_byte_list bs) + | _ -> Nothing end in + Write_mem write_k (Address_lifted location address_int) + length tracking value v_tracking + (fun b -> match return with | Nothing -> (IState (Interp.add_answer_to_stack next_state Interp.unitv) context) | Just return_bool -> return_bool (IState next_state context) b end) @@ -472,40 +481,44 @@ let interp mode (IState interp_state context) = interp_to_outcome mode context (fun _ -> Interp.resume mode interp_state Nothing) (*TODO: Only find some sub piece matches, need to look for field/slice sub pieces*) +(*TODO immediate: this will be impacted by need to change slicing *) let rec find_reg_name reg = function | [] -> Nothing | (reg_name,v)::registers -> match (reg,reg_name) with - | (Reg i size, Reg n size2) -> if i = n && size = size2 then (Just v) else find_reg_name reg registers - | (Reg_slice i (p1,p2), Reg n _) -> - if i = n then (Just (slice_reg_value v (natFromInt p1) (natFromInt p2))) else find_reg_name reg registers - | (Reg_field i f (p1,p2), Reg n _) -> - if i = n then (Just (slice_reg_value v (natFromInt p1) (natFromInt p2))) else find_reg_name reg registers - | (Reg_slice i (p1,p2), Reg_slice n (p3,p4)) -> + | (Reg i start size dir, Reg n start2 size2 dir2) -> + if i = n && size = size2 then (Just v) else find_reg_name reg registers + | (Reg_slice i _ _ (p1,p2), Reg n _ _ _) -> + if i = n then (Just (slice_reg_value v p1 p2)) else find_reg_name reg registers + | (Reg_field i _ _ f (p1,p2), Reg n _ _ _) -> + if i = n then (Just (slice_reg_value v p1 p2)) else find_reg_name reg registers + | (Reg_slice i _ _ (p1,p2), Reg_slice n _ _ (p3,p4)) -> if i=n then if p1=p3 && p2 = p4 then (Just v) - else if p1>=p3 && p2<= p4 then (Just (slice_reg_value v (natFromInt p1) (natFromInt p2))) + else if p1>=p3 && p2<= p4 then (Just (slice_reg_value v p1 p2)) else find_reg_name reg registers else find_reg_name reg registers - | (Reg_field i f _,Reg_field n fn _) -> + | (Reg_field i _ _ f _,Reg_field n _ _ fn _) -> if i=n && f = fn then (Just v) else find_reg_name reg registers - | (Reg_f_slice i f _ (p1,p2), Reg_f_slice n fn _ (p3,p4)) -> + | (Reg_f_slice i _ _ f _ (p1,p2), Reg_f_slice n _ _ fn _ (p3,p4)) -> if i=n && f=fn && p1=p3 && p2=p3 then (Just v) else find_reg_name reg registers | _ -> find_reg_name reg registers end end +(*Update slice potentially here*) let reg_size = function - | Reg i size -> size - | Reg_slice i (p1,p2) -> natFromInt (if p1 < p2 then (p2-p1 +1) else (p1-p2 +1)) - | Reg_field i f (p1,p2) -> natFromInt (if p1 < p2 then (p2-p1 +1) else (p1-p2 +1)) - | Reg_f_slice i f _ (p1,p2) -> natFromInt (if p1 < p2 then p2-p1 +1 else p1-p2+1) + | Reg i _ size _ -> size + | Reg_slice i _ _ (p1,p2) -> if p1 < p2 then (p2-p1 +1) else (p1-p2 +1) + | Reg_field i _ _ f (p1,p2) -> if p1 < p2 then (p2-p1 +1) else (p1-p2 +1) + | Reg_f_slice i _ _ f _ (p1,p2) -> if p1 < p2 then p2-p1 +1 else p1-p2+1 end let rec ie_loop mode register_values (IState interp_state context) = let (Context _ direction externs reads writes barriers) = context in let unknown_reg size = <| rv_bits = (List.replicate size Bitl_unknown); - rv_start = (if direction = D_increasing then 0 else (size-1)); + rv_start = 0; + rv_start_internal = (if direction = D_increasing then 0 else (size-1)); rv_dir = direction |> in let unknown_mem size = List.replicate size (Byte_lifted (List.replicate 8 Bitl_unknown)) in match interp mode (IState interp_state context) with @@ -538,7 +551,8 @@ let rec rr_ie_loop mode i_state = let (IState _ (Context _ direction _ _ _ _)) = i_state in let unknown_reg size = <| rv_bits = (List.replicate size Bitl_unknown); - rv_start = (if direction=D_increasing then 0 else (size-1)); + rv_start = 0; + rv_start_internal = (if direction=D_increasing then 0 else (size-1)); rv_dir = direction |> in let unknown_mem size = List.replicate size (Byte_lifted (List.replicate 8 Bitl_unknown)) in match (interp mode i_state) with diff --git a/src/lem_interp/interp_interface.lem b/src/lem_interp/interp_interface.lem index 213b7d51..830877e1 100644 --- a/src/lem_interp/interp_interface.lem +++ b/src/lem_interp/interp_interface.lem @@ -53,7 +53,14 @@ type direction = | D_increasing | D_decreasing -type register_value = <| rv_bits: list bit_lifted (* MSB first, smallest index number *); rv_dir: direction; rv_start: nat |> +type register_value = <| + rv_bits: list bit_lifted (* MSB first, smallest index number *); + rv_dir: direction; + rv_start: nat ; + rv_start_internal: nat; + (*when dir is increasing, rv_start = rv_start_internal. + Otherwise, tells interpreter how to reconstruct a proper decreasing value*) + |> type byte_lifted = Byte_lifted of list bit_lifted (* of length 8 *) @@ -61,14 +68,14 @@ type instruction_field_value = list bit type byte = Byte of list bit (* of length 8 *) (*MSB first*) -type address_lifted = Address_lifted of list byte_lifted (* of length 8 for 64bit machines*) +type address_lifted = Address_lifted of list byte_lifted (* of length 8 for 64bit machines*) * maybe integer type memory_byte = byte_lifted type memory_value = list memory_byte (* the head of the list, most-significant first, at the lowest address, of length >=1 *) (* not sure which of these is more handy yet *) -type address = Address of list byte (* of length 8 *) +type address = Address of list byte (* of length 8 *) * integer (* type address = Address of integer *) type opcode = Opcode of list byte (* of length 4 *) @@ -130,40 +137,46 @@ instance (Ord address_lifted) end (* Registers *) -(*Can be nat nat, but finding out where ppcmem doens't like that is maybe not worth the effort *) -type slice = (int * int) +type slice = (nat * nat) type reg_name = -| Reg of string * nat -(*Name of the register, accessing the entire register, and the size of this register *) +| Reg of string * nat * nat * direction +(*Name of the register, accessing the entire register, the start and size of this register, and it's direction *) -| Reg_slice of string * slice +| Reg_slice of string * nat * direction * slice (* Name of the register, accessing from the bit indexed by the first to the bit indexed by the second integer of the slice, inclusive. For -Power the first will be a smaller number than or equal to the second; -for other architectures it might be the other way round. *) +machineDef* the first is a smaller number or equal to the second, adjusted +to reflect the correct span direction in the interpreter side. *) -| Reg_field of string * string * slice -(*Name of the register and name of the field of the register +| Reg_field of string * nat * direction * string * slice +(*Name of the register, start and direction, and name of the field of the register accessed. The slice specifies where this field is in the register*) -| Reg_f_slice of string * string * slice * slice -(* The first three components are as in Reg_field; the final slice +| Reg_f_slice of string * nat * direction * string * slice * slice +(* The first four components are as in Reg_field; the final slice specifies a part of the field, indexed w.r.t. the register as a whole *) - -(* because reg_name contains slice which currently contains Big_int.big_int, the default OCaml comparison is not sufficient and we need to define explicit type classes *) let slice_eq (s1l,s1r) (s2l,s2r) = (s1l = s2l) && (s1r = s2r) let reg_nameEqual r1 r2 = match (r1,r2) with - | (Reg s1 l1, Reg s2 l2) -> s1=s2 && l1=l2 - | (Reg_slice s1 sl1, Reg_slice s2 sl2) -> s1=s2 && (slice_eq sl1 sl2) - | (Reg_field s1 f1 sl1, Reg_field s2 f2 sl2) -> s1=s2 && f1=f2 && (slice_eq sl1 sl2) - | (Reg_f_slice s1 f1 sl1 sl1', Reg_f_slice s2 f2 sl2 sl2') -> s1=s2 && f1=f2 && (slice_eq sl1 sl2) && (slice_eq sl1' sl2') + | (Reg s1 ns1 d1 l1, Reg s2 ns2 d2 l2) -> s1=s2 && ns1 = ns2 && l1=l2 && d1=d2 + | (Reg_slice s1 ns1 d1 sl1, Reg_slice s2 ns2 d2 sl2) -> s1=s2 && ns1=ns2 && d1=d2 && (slice_eq sl1 sl2) + | (Reg_field s1 ns1 d1 f1 sl1, Reg_field s2 ns2 d2 f2 sl2) -> s1=s2 && ns1=ns2 && d1=d2 && f1=f2 && (slice_eq sl1 sl2) + | (Reg_f_slice s1 ns1 d1 f1 sl1 sl1', Reg_f_slice s2 ns2 d2 f2 sl2 sl2') -> + s1=s2 && ns1=ns2 && d1=d2 && f1=f2 && (slice_eq sl1 sl2) && (slice_eq sl1' sl2') | _ -> false end +instance (Ord direction) + let compare = defaultCompare + let (<) = defaultLess + let (<=) = defaultLessEq + let (>) = defaultGreater + let (>=) = defaultGreaterEq +end + instance (Eq reg_name) let (=) = reg_nameEqual let (<>) x y = not (reg_nameEqual x y) @@ -171,15 +184,15 @@ end let reg_nameCompare r1 r2 = match (r1,r2) with - | (Reg s1 l1, Reg s2 l2) -> pairCompare compare compare (s1,l1) (s2,l2) - | (Reg_slice s1 sl1, Reg_slice s2 sl2) -> pairCompare compare compare (s1,sl1) (s2,sl2) - | (Reg_field s1 f1 sl1, Reg_field s2 f2 sl2) -> + | (Reg s1 _ _ l1, Reg s2 _ _ l2) -> pairCompare compare compare (s1,l1) (s2,l2) + | (Reg_slice s1 _ _ sl1, Reg_slice s2 _ _ sl2) -> pairCompare compare compare (s1,sl1) (s2,sl2) + | (Reg_field s1 _ _ f1 sl1, Reg_field s2 _ _ f2 sl2) -> tripleCompare compare compare compare (s1,f1,sl1) (s2,f2,sl2) - | (Reg_f_slice s1 f1 sl1 sl1', Reg_f_slice s2 f2 sl2 sl2') -> + | (Reg_f_slice s1 _ _ f1 sl1 sl1', Reg_f_slice s2 _ _ f2 sl2 sl2') -> pairCompare compare (tripleCompare compare compare compare) (s1,(f1,sl1,sl1')) (s2,(f2,sl2,sl2')) - | (Reg _ _, _) -> LT - | (Reg_slice _ _, _) -> LT - | (Reg_field _ _ _, _) -> LT + | (Reg _ _ _ _, _) -> LT + | (Reg_slice _ _ _ _, _) -> LT + | (Reg_field _ _ _ _ _, _) -> LT | (_, _) -> GT end @@ -195,6 +208,20 @@ instance (Ord reg_name) let (>=) r1 r2 = (reg_nameCompare r1 r2) <> LT end +let direction_of_reg_name r = match r with + | Reg _ _ _ d -> d + | Reg_slice _ _ d _ -> d + | Reg_field _ _ d _ _ -> d + | Reg_f_slice _ _ d _ _ _ -> d + end + +let start_of_reg_name r = match r with + | Reg _ start _ _ -> start + | Reg_slice _ start _ _ -> start + | Reg_field _ start _ _ _ -> start + | Reg_f_slice _ start _ _ _ _ -> start +end + (* Data structures for building up instructions *) type read_kind = @@ -376,20 +403,9 @@ val decode_to_instruction : context -> opcode -> instruction_or_decode_error (*Function to generate the state to run from an instruction form; is always an Instr*) val instruction_to_istate : context -> instruction -> instruction_state (*i_state_or_error*) -(* Augment an address by the given value *) -(*val add_to_address : value -> integer -> value - -(* Coerce a Bitvector value (presumed a multiple of 8 bits long) to a Bytevector value *) -val coerce_Bytevector_of_Bitvector : value -> value - -(* Coerce a Bytevector value to a Bitvector value, increasing and starting at zero *) -val coerce_Bitvector_of_Bytevector : value -> value*) - (* Slice a register value into a smaller vector, starting at first number (wrt the indices of the register value, not raw positions in its list of bits) and going to second (inclusive) according to order. *) val slice_reg_value : register_value -> nat -> nat -> register_value -(*(*append two vectors (bit x byte -> bit) *) -val append_value : value -> value -> value *) (* Big step of the interpreter, to the next request for an external action *) (* When interp_mode has eager_eval false, interpreter is (close to) small step *) @@ -410,13 +426,31 @@ val bitls_to_word8 : list bit_lifted -> word8 val integer_of_word8_list : list word8 -> integer val word8_list_of_integer : integer -> integer -> list word8 +val concretizable_bitl : bit_lifted -> bool +val concretizable_bytl : byte_lifted -> bool +val concretizable_bytls : list byte_lifted -> bool + +let concretizable_bitl = function + | Bitl_zero -> true + | Bitl_one -> true + | Bitl_undef -> false + | Bitl_unknown -> false +end + +let concretizable_bytl (Byte_lifted bs) = List.all concretizable_bitl bs +let concretizable_bytls = List.all concretizable_bytl + (* constructing values *) val register_value : bit_lifted -> direction -> nat -> nat -> register_value let register_value b dir width start_index = <| rv_bits = List.replicate width b; rv_dir = dir; (* D_increasing for Power, D_decreasing for ARM *) - rv_start = start_index; |> + rv_start_internal = start_index; + rv_start = if dir = D_increasing + then start_index + else (start_index+1) - width; (* Smaller index, as in Power, for external interaction *) + |> val register_value_zeros : direction -> nat -> nat -> register_value let register_value_zeros dir width start_index = @@ -429,9 +463,9 @@ let register_value_ones dir width start_index = val byte_lifted_unknown : byte_lifted let byte_lifted_unknown = Byte_lifted (List.replicate 8 Bitl_unknown) -val memory_value_unknown : int (*the number of bytes*) -> memory_value -let memory_value_unknown (width:int) : memory_value = - List.replicate (natFromInt width) byte_lifted_unknown +val memory_value_unknown : nat (*the number of bytes*) -> memory_value +let memory_value_unknown (width:nat) : memory_value = + List.replicate width byte_lifted_unknown (* lengths *) @@ -539,13 +573,12 @@ let byte_list_of_integer (len:nat) (a:integer):list byte = val integer_of_address : address -> integer let integer_of_address (a:address):integer = match a with - | Address bs -> integer_of_byte_list bs + | Address bs i -> i end val address_of_integer : integer -> address let address_of_integer (i:integer):address = - Address (byte_list_of_integer 8 i) - + Address (byte_list_of_integer 8 i) i (* regarding a list of int as a list of bytes in memory, MSB lowest-address first, convert to an integer *) @@ -561,28 +594,26 @@ let integer_address_of_int_list (is: list int) = val address_of_byte_list : list byte -> address let address_of_byte_list bs = if List.length bs <> 8 then failwith "address_of_byte_list given list not of length 8" else - Address bs - + Address bs (integer_of_byte_list bs) (* operations on addresses *) -val add_address_int : address -> int -> address -let add_address_int (a:address) (i:int) : address = - address_of_integer ((integer_of_address a) + (integerFromInt i)) +val add_address_nat : address -> nat -> address +let add_address_nat (a:address) (i:nat) : address = + address_of_integer ((integer_of_address a) + (integerFromNat i)) val clear_low_order_bits_of_address : address -> address let clear_low_order_bits_of_address a = match a with - | Address [b0;b1;b2;b3;b4;b5;b6;b7] -> + | Address [b0;b1;b2;b3;b4;b5;b6;b7] i -> match b7 with | Byte [bt0;bt1;bt2;bt3;bt4;bt5;bt6;bt7] -> let b7' = Byte [bt0;bt1;bt2;bt3;bt4;bt5;Bitc_zero;Bitc_zero] in - Address [b0;b1;b2;b3;b4;b5;b6;b7'] + let bytes = [b0;b1;b2;b3;b4;b5;b6;b7'] in + Address bytes (integer_of_byte_list bytes) end end - - val byte_list_of_memory_value : memory_value -> maybe (list byte) let byte_list_of_memory_value mv = maybe_all (List.map byte_of_memory_byte mv) @@ -605,29 +636,30 @@ let integer_of_register_value (rv:register_value):maybe integer = | Nothing -> Nothing | Just bs -> Just (integer_of_bit_list bs) end - -val register_value_of_integer : nat -> nat -> integer -> register_value -let register_value_of_integer (len:nat) (start:nat) (i:integer):register_value = +val register_value_of_integer : nat -> nat -> direction -> integer -> register_value +let register_value_of_integer (len:nat) (start:nat) (dir:direction) (i:integer):register_value = let bs = bit_list_of_integer len i in <| rv_bits = List.map bit_lifted_of_bit bs; - rv_dir = D_increasing; + rv_dir = dir; rv_start = start; + rv_start_internal = if dir = D_increasing then start else start + (List.length bs) - 1 |> - (* *) val opcode_of_bytes : byte -> byte -> byte -> byte -> opcode let opcode_of_bytes b0 b1 b2 b3 : opcode = Opcode [b0;b1;b2;b3] -val register_value_of_address : address -> register_value -let register_value_of_address (Address bytes) : register_value = - <| rv_bits = List.concatMap (fun (Byte bs) -> List.map bit_lifted_of_bit bs) bytes; - rv_dir = D_increasing; - rv_start = 0; |> - +val register_value_of_address : address -> direction -> register_value +let register_value_of_address (Address bytes _) dir : register_value = + let bits = List.concatMap (fun (Byte bs) -> List.map bit_lifted_of_bit bs) bytes in + <| rv_bits = bits; + rv_dir = dir; + rv_start = 0; + rv_start_internal = if dir = D_increasing then 0 else (List.length bits) - 1 + |> val address_lifted_of_register_value : register_value -> maybe address_lifted @@ -636,18 +668,22 @@ allowing Bitl_undef and Bitl_unknown *) let address_lifted_of_register_value (rv:register_value) : maybe address_lifted = if List.length rv.rv_bits <> 64 then Nothing else - Just (Address_lifted (byte_lifteds_of_bit_lifteds rv.rv_bits)) - + Just (Address_lifted (byte_lifteds_of_bit_lifteds rv.rv_bits) + (if List.all concretizable_bitl rv.rv_bits + then let (Just(bits)) = (maybe_all (List.map bit_of_bit_lifted rv.rv_bits)) in + Just (integer_of_bit_list bits) + else Nothing)) val address_of_address_lifted : address_lifted -> maybe address (* returning Nothing iff the address contains any Bitl_undef or Bitl_unknown *) let address_of_address_lifted (al:address_lifted): maybe address = match al with - | Address_lifted bls -> + | Address_lifted bls (Just i)-> match maybe_all ((List.map byte_of_byte_lifted) bls) with | Nothing -> Nothing - | Just bs -> Just (Address bs) + | Just bs -> Just (Address bs i) end + | _ -> Nothing end val address_of_register_value : register_value -> maybe address @@ -690,13 +726,13 @@ let int_of_memory_byte (mb:memory_byte) : int = val memory_value_of_address_lifted : address_lifted -> memory_value let memory_value_of_address_lifted (al:address_lifted) = match al with - | Address_lifted bs -> bs + | Address_lifted bs _ -> bs end val byte_list_of_address : address -> list byte let byte_list_of_address (a:address) : list byte = match a with - | Address bs -> bs + | Address bs _ -> bs end val byte_list_of_opcode : opcode -> list byte diff --git a/src/lem_interp/interp_utilities.lem b/src/lem_interp/interp_utilities.lem index 0a23e74c..e87600a3 100644 --- a/src/lem_interp/interp_utilities.lem +++ b/src/lem_interp/interp_utilities.lem @@ -22,6 +22,10 @@ let lit_eq (L_aux left _) (L_aux right _) = | (L_one, L_one) -> true | (L_true, L_true) -> true | (L_false, L_false) -> true + | (L_zero, L_num i) -> i = 0 + | (L_num i,L_zero) -> i = 0 + | (L_one, L_num i) -> i = 1 + | (L_num i, L_one) -> i = 1 | (L_num n, L_num m) -> n = m | (L_hex h, L_hex h') -> h = h' | (L_bin b, L_bin b') -> b = b' diff --git a/src/lem_interp/printing_functions.ml b/src/lem_interp/printing_functions.ml index 5bf3acc8..b4c5fa96 100644 --- a/src/lem_interp/printing_functions.ml +++ b/src/lem_interp/printing_functions.ml @@ -231,11 +231,20 @@ let rec bit_to_hex v = ;;*) let reg_name_to_string = function - | Reg0(s,_) -> s - | Reg_slice(s,(first,second)) -> + | Reg0(s,_,_,_) -> s + | Reg_slice(s,start,dir,(first,second)) -> + let first,second = + match dir with + | D_increasing -> (first,second) + | D_decreasing -> (start - first, start - second) in s ^ "[" ^ string_of_int first ^ (if (first = second) then "" else ".." ^ (string_of_int second)) ^ "]" - | Reg_field(s,f,_) -> s ^ "." ^ f - | Reg_f_slice(s,f,_,(first,second)) -> s ^ "." ^ f ^ "]" ^ string_of_int first ^ (if (first = second) then "" else ".." ^ (string_of_int second)) ^ "]" + | Reg_field(s,_,_,f,_) -> s ^ "." ^ f + | Reg_f_slice(s,start,dir,f,_,(first,second)) -> + let first,second = + match dir with + | D_increasing -> (first,second) + | D_decreasing -> (start - first, start - second) in + s ^ "." ^ f ^ "]" ^ string_of_int first ^ (if (first = second) then "" else ".." ^ (string_of_int second)) ^ "]" let dependencies_to_string dependencies = String.concat ", " (List.map reg_name_to_string dependencies) @@ -335,10 +344,10 @@ let rec format_events = function " Failed with message : " ^ s ^ "\n" | (E_error s)::events -> " Failed with message : " ^ s ^ " but continued on erroneously\n" - | (E_read_mem(read_kind, (Address_lifted location), length, tracking))::events -> + | (E_read_mem(read_kind, (Address_lifted(location, _)), length, tracking))::events -> " Read_mem at " ^ (memory_value_to_string location) ^ " for " ^ (string_of_int length) ^ " bytes \n" ^ (format_events events) - | (E_write_mem(write_kind,(Address_lifted location), length, tracking, value, v_tracking))::events -> + | (E_write_mem(write_kind,(Address_lifted (location,_)), length, tracking, value, v_tracking))::events -> " Write_mem at " ^ (memory_value_to_string location) ^ " writing " ^ (memory_value_to_string value) ^ " across " ^ (string_of_int length) ^ " bytes\n" ^ (format_events events) | ((E_barrier b_kind)::events) -> @@ -401,8 +410,8 @@ let local_variables_to_string (IState(stack,_)) = | LEnv(_,env) -> String.concat ", " (option_map (fun (id,value)-> match id with - | Id_aux(Id "0",_) -> None (*Let's not print out the context hole again*) - | _ -> Some (id_to_string id ^ "=" ^ val_to_string_internal mem value)) env) + | "0" -> None (*Let's not print out the context hole again*) + | _ -> Some (id ^ "=" ^ val_to_string_internal mem value)) (Pmap.bindings_list env)) let instr_parm_to_string (name, typ, value) = name ^"="^ |
