summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorKathy Gray2014-12-11 03:59:28 +0000
committerKathy Gray2014-12-11 03:59:28 +0000
commit5a555aadcebda09a490c5855bc82c88ea8064011 (patch)
treeabd55f13563699e6ce396c11b599bb5870060e9a /src
parentccd92a34e436e890671ca66d2ad19180b89b274d (diff)
Many fixes, primarily dealing with undefined
Including: turn an undefined literal into a vector of undefined values of the correct length handle sparse vector unspecified default values as undefined literals allow global lets to call library functions
Diffstat (limited to 'src')
-rw-r--r--src/lem_interp/interp.lem97
-rw-r--r--src/lem_interp/interp_inter_imp.lem12
-rw-r--r--src/lem_interp/interp_lib.lem7
-rw-r--r--src/lem_interp/run_interp.ml2
-rw-r--r--src/pretty_print.ml4
-rw-r--r--src/type_check.ml16
6 files changed, 105 insertions, 33 deletions
diff --git a/src/lem_interp/interp.lem b/src/lem_interp/interp.lem
index efb1db7a..ce74ee77 100644
--- a/src/lem_interp/interp.lem
+++ b/src/lem_interp/interp.lem
@@ -62,7 +62,7 @@ let rec string_of_value v = match v with
| L_one -> "1"
| L_true -> "true"
| L_false -> "false"
- | L_num num -> toString(integerToString num [])
+ | L_num num -> if num = 0 then "0" else toString(integerToString num [])
| L_hex hex -> "0x" ^ hex
| L_bin bin -> "0b" ^ bin
| L_undef -> "undefined"
@@ -86,7 +86,7 @@ let rec string_of_value v = match v with
| V_unknown -> "Unknown"
| V_register _ -> "register_as_value"
| V_register_alias _ _ -> "register_as_alias"
- | V_track v _ -> (*"tainted " ^*) (string_of_value v)
+ | V_track v _ -> "tainted " ^ (string_of_value v)
end
let rec id_value_eq (i, v) (i', v') = i = i' && value_eq v v'
@@ -218,10 +218,10 @@ type outcome =
type interp_mode = <| eager_eval : bool; track_values : bool |>
(* Evaluates global let binds and prepares the context for individual expression evaluation in the current model *)
-val to_top_env : defs tannot -> (maybe outcome * top_level)
+val to_top_env : (outcome -> maybe value) -> defs tannot -> (maybe outcome * top_level)
(* interprets the exp sequentially in the presence of a set of top level definitions and returns a value, a memory request, or other external action *)
-val interp :interp_mode -> defs tannot -> exp tannot -> outcome
+val interp :interp_mode -> (outcome -> maybe value) -> defs tannot -> exp tannot -> outcome
(* Takes a paused partially evaluated expression, puts the value into the environment, and runs again *)
val resume : interp_mode -> stack -> maybe value -> outcome
@@ -1450,15 +1450,18 @@ and interp_main mode t_level l_env l_mem (E_aux exp (l,annot)) =
let slice = binary_taint (fun v1 v2 -> V_tuple[v1;v2]) i1v i2v in
let take_slice vtup vvec =
(match vtup with
- | V_tuple [V_lit (L_aux (L_num n1) ln1);V_lit (L_aux (L_num n2) ln2)] ->
- (match vvec with
- | V_vector _ _ _ -> slice_vector vvec n1 n2
- | V_vector_sparse _ _ _ _ _ -> slice_vector vvec n1 n2
- | V_unknown ->
- let inc = n1 < n2 in
- V_vector n1 inc
- (List.replicate (natFromInteger ((if inc then n1-n2 else n2-n1)+1)) V_unknown)
- | _ -> Assert_extra.failwith ("Vector slice of non-vector " ^ (string_of_value vvec)) end) end) in
+ | V_tuple [v1;v2] ->
+ (match (detaint v1, detaint v2) with
+ | (V_lit (L_aux (L_num n1) ln1),V_lit (L_aux (L_num n2) ln2)) ->
+ (match vvec with
+ | V_vector _ _ _ -> slice_vector vvec n1 n2
+ | V_vector_sparse _ _ _ _ _ -> slice_vector vvec n1 n2
+ | V_unknown ->
+ let inc = n1 < n2 in
+ V_vector n1 inc
+ (List.replicate (natFromInteger ((if inc then n1-n2 else n2-n1)+1)) V_unknown)
+ | _ -> Assert_extra.failwith ("Vector slice of non-vector " ^ (string_of_value vvec)) end) end)
+ | _ -> Assert_extra.failwith("slice not a tuple of nums " ^ (string_of_value vtup)) end) in
(Value (binary_taint take_slice slice vvec), lm,le))
(fun a ->
let rebuild v env = let (ie1,env) = to_exp mode env i1v in
@@ -2309,41 +2312,53 @@ and interp_alias_read mode t_level l_env l_mem (AL_aux alspec (l,annot)) =
(E_aux (E_id reg2) annot2))
(l,(intern_annot annot))) t_level l_env l_mem Top), l_mem,l_env) end
-let rec to_global_letbinds (Defs defs) t_level =
+let rec eval_toplevel_let handle_action tlevel env mem lbind =
+ match interp_letbind <|eager_eval=true; track_values=false;|> tlevel env mem lbind with
+ | ((Value v, lm, (LEnv _ le)),_) -> Just le
+ | ((Action a s,lm,le), Just le_builder) ->
+ (match handle_action (Action a s) with
+ | Just value ->
+ (match s with
+ | Hole_frame id exp tl lenv lmem s ->
+ eval_toplevel_let handle_action tl (add_to_env (id,value) lenv) lmem (le_builder exp) end)
+ | Nothing -> Nothing end)
+ | _ -> Nothing end
+
+let rec to_global_letbinds handle_action (Defs defs) t_level =
let (Env defs' instrs 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 ->
match def with
| DEF_val lbind ->
- match interp_letbind <|eager_eval=true; track_values=false;|> t_level eenv emem lbind with
- | ((Value v,lm,(LEnv _ le)),_) -> to_global_letbinds (Defs defs) (Env defs' instrs (lets++le) regs ctors subregs aliases)
- | ((Action a s,lm,le),_) ->
- ((Error Unknown "Top level let may not access memory, registers or (for now) external functions", lm,le),t_level)
- | (e,_) -> (e,t_level) end
+ match eval_toplevel_let handle_action t_level eenv emem lbind with
+ | Just le ->
+ to_global_letbinds handle_action (Defs defs) (Env defs' instrs (lets++le) regs ctors subregs aliases)
+ | Nothing ->
+ to_global_letbinds handle_action (Defs defs) (Env defs' instrs 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)) unitv)) ids in
- to_global_letbinds (Defs defs) (Env defs' instrs (lets++enum_vals) regs ctors subregs aliases)
- | _ -> to_global_letbinds (Defs defs) t_level end
- | _ -> to_global_letbinds (Defs defs) t_level
+ to_global_letbinds handle_action (Defs defs) (Env defs' instrs (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
end
(*TODO Contemplate making decode and execute environment variables instead of these constants*)
-let to_top_env defs =
+let to_top_env external_functions defs =
let t_level = Env defs (extract_instructions "decode" "execute" defs)
[] (* 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
- let (o,t_level) = to_global_letbinds defs t_level in
+ let (o,t_level) = to_global_letbinds external_functions defs t_level in
match o with
| (Value _,_,_) -> (Nothing,t_level)
| (o,_,_) -> (Just o,t_level)
end
-let interp mode defs exp =
- match (to_top_env defs) with
+let interp mode external_functions defs exp =
+ match (to_top_env external_functions defs) with
| (Nothing,t_level) ->
match interp_main mode t_level eenv emem exp with
| (o,_,_) -> o
@@ -2351,6 +2366,36 @@ let interp mode defs exp =
| (Just o,_) -> o (* Should do something different for action to allow global lets to call external functions *)
end
+let rec resume_with_env mode stack value =
+ match (stack,value) with
+ | (Top,_) -> (Error Unknown "Top hit without expression to evaluate",eenv)
+ | (Hole_frame id exp t_level env mem Top,Just value) ->
+ match interp_main mode t_level (add_to_env (id,value) env) mem exp with | (o,_,e) -> (o,e) end
+ | (Hole_frame id exp t_level env mem stack,Just value) ->
+ match resume_with_env mode stack (Just value) with
+ | (Value v,e) ->
+ match interp_main mode t_level (add_to_env (id,v) env) mem exp with | (o,_,e) -> (o,e) end
+ | (Action action stack,e) -> (Action action (Hole_frame id exp t_level env mem stack),e)
+ | (Error l s,e) -> (Error l s,e)
+ end
+ | (Hole_frame id exp t_level env mem stack, Nothing) ->
+ match resume_with_env mode stack Nothing with
+ | (Value v,e) ->
+ match interp_main mode t_level (add_to_env (id,v) env) mem exp with | (o,_,e) -> (o,e) end
+ | (Action action stack,e) -> (Action action (Hole_frame id exp t_level env mem stack),e)
+ | (Error l s,e) -> (Error l s,e)
+ end
+ | (Thunk_frame exp t_level env mem Top,_) ->
+ match interp_main mode t_level env mem exp with | (o,_,e) -> (o,e) end
+ | (Thunk_frame exp t_level env mem stack,value) ->
+ match resume_with_env mode stack value with
+ | (Value v,e) ->
+ match interp_main mode t_level env mem exp with | (o,_,e) -> (o,e) end
+ | (Action action stack,e) -> (Action action (Thunk_frame exp t_level env mem stack),e)
+ | (Error l s,e) -> (Error l s,e)
+ end
+ end
+
let rec resume mode stack value =
match (stack,value) with
| (Top,_) -> Error Unknown "Top hit without expression to evaluate"
diff --git a/src/lem_interp/interp_inter_imp.lem b/src/lem_interp/interp_inter_imp.lem
index 648a61bd..94f5abc6 100644
--- a/src/lem_interp/interp_inter_imp.lem
+++ b/src/lem_interp/interp_inter_imp.lem
@@ -13,7 +13,6 @@ val extern_reg_value : maybe integer -> 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 (integer * integer) -> reg_name
-let build_context defs = match Interp.to_top_env defs with (_,context) -> context end
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
@@ -377,6 +376,17 @@ let rec interp_to_value_helper arg instr thunk =
| _ -> (Nothing, Just (Internal_error "Memory or register requested in decode"))
end
+let call_external_functions outcome =
+ match outcome with
+ | Interp.Action (Interp.Call_extern i value) stack ->
+ match List.lookup i external_functions with
+ | Nothing -> Nothing
+ | Just f -> Just (f value) end
+ | _ -> Nothing end
+
+let build_context defs = match Interp.to_top_env call_external_functions defs with (_,context) -> context end
+
+
let rec find_instruction i = function
| [] -> Nothing
| Instruction_extractor.Skipped::instrs -> find_instruction i instrs
diff --git a/src/lem_interp/interp_lib.lem b/src/lem_interp/interp_lib.lem
index b72cd362..5d36149a 100644
--- a/src/lem_interp/interp_lib.lem
+++ b/src/lem_interp/interp_lib.lem
@@ -199,6 +199,8 @@ let to_vec_inc (V_tuple[v1;v2]) =
V_vector 0 true (map bool_to_bit (reverse l))
| ((V_lit(L_aux (L_num n) ln)),V_unknown) ->
V_vector 0 true (List.replicate (natFromInteger n) V_unknown)
+ | ((V_lit(L_aux (L_num n) ln)),(V_lit (L_aux L_undef _))) ->
+ V_vector 0 true (List.replicate (natFromInteger n) v2)
| (_,V_unknown) -> V_unknown
| (V_unknown,_) -> V_unknown
| _ -> Assert_extra.failwith ("to_vec_inc parameters were " ^ (string_of_value (V_tuple[v1;v2])))
@@ -213,6 +215,8 @@ let to_vec_dec (V_tuple([v1;v2])) =
V_vector (len - 1) false (map bool_to_bit (reverse l))
| ((V_lit(L_aux (L_num n) ln)),V_unknown) ->
V_vector (n-1) false (List.replicate (natFromInteger n) V_unknown)
+ | ((V_lit(L_aux (L_num n) ln)),(V_lit (L_aux L_undef _))) ->
+ V_vector (n-1) false (List.replicate (natFromInteger n) v2)
| (_,V_unknown) -> V_unknown
| (V_unknown,_) -> V_unknown
| _ -> Assert_extra.failwith ("to_vec_dec parameters were " ^ (string_of_value (V_tuple[v1;v2])))
@@ -532,7 +536,8 @@ let rec vec_concat (V_tuple [vl;vr]) =
let v_length v = retaint v (match detaint v with
| V_vector n d l -> V_lit (L_aux (L_num (integerFromNat (List.length l))) Unknown)
- | V_unknown -> V_unknown end)
+ | V_unknown -> V_unknown
+ | _ -> Assert_extra.failwith ("length given unexpected " ^ (string_of_value v)) end)
let function_map = [
("ignore", ignore_sail);
diff --git a/src/lem_interp/run_interp.ml b/src/lem_interp/run_interp.ml
index 8857f99c..a8291a78 100644
--- a/src/lem_interp/run_interp.ml
+++ b/src/lem_interp/run_interp.ml
@@ -436,7 +436,7 @@ let run
| Some m -> m in
try
Printexc.record_backtrace true;
- loop mode (reg, mem) (interp {eager_eval = eager_eval; track_values = false} test entry)
+ loop mode (reg, mem) (interp {eager_eval = eager_eval; track_values = false} (fun id -> None) test entry)
with e ->
let trace = Printexc.get_backtrace () in
debugf "%s: %s %s\n%s\n" (grey name) (red "interpretor error") (Printexc.to_string e) trace;
diff --git a/src/pretty_print.ml b/src/pretty_print.ml
index 4ea9ea63..9d7cf616 100644
--- a/src/pretty_print.ml
+++ b/src/pretty_print.ml
@@ -417,6 +417,7 @@ and pp_lem_exp ppf (E_aux(e,(l,annot))) =
| E_exit exp -> fprintf ppf "@[<0>(E_aux (E_exit %a) (%a, %a))@]" pp_lem_exp exp pp_lem_l l pp_annot annot
| E_internal_exp (l, Base((_,t),_,_,_)) ->
(match t.t with
+ | Tapp("register",[TA_typ {t=Tapp("vector",[TA_nexp _;TA_nexp r;_;_])}])
| Tapp("vector",[TA_nexp _;TA_nexp r;_;_]) ->
(match r.nexp with
| Nconst bi -> fprintf ppf "@[<0>(E_aux (E_lit (L_aux (L_num %a) %a)) (%a, %a))@]"
@@ -969,6 +970,7 @@ let doc_exp, doc_let =
(* doc_op (doc_id op) (exp l) (exp r) *)
| E_internal_exp (l, Base((_,t),_,_,_)) ->
(match t.t with
+ | Tapp("register",[TA_typ {t=Tapp("vector",[TA_nexp _;TA_nexp r;_;_])}])
| Tapp("vector",[TA_nexp _;TA_nexp r;_;_]) ->
(match r.nexp with
| Nvar v -> utf8string v
@@ -980,7 +982,7 @@ let doc_exp, doc_let =
| Nconst bi -> utf8string (Big_int.string_of_big_int bi)
| Nvar v -> utf8string v
| _ -> raise (Reporting_basic.err_unreachable l "Internal exp given implicit without var or const"))
- | _ -> raise (Reporting_basic.err_unreachable l "Internal exp given non-vector, non-implicit"))
+ | _ -> raise (Reporting_basic.err_unreachable l ("Internal exp given non-vector, non-implicit " ^ t_to_string t)))
(* XXX missing case
AAA internal_cast should never have an overload, if it's been seen it's a bug *)
diff --git a/src/type_check.ml b/src/type_check.ml
index 73b66e6e..53725a29 100644
--- a/src/type_check.ml
+++ b/src/type_check.ml
@@ -535,7 +535,16 @@ let rec check_exp envs (imp_param:nexp option) (expect_t:t) (E_aux(e,(l,annot)):
TA_nexp{nexp = Nconst (big_int_of_int (String.length s))};
TA_ord d_env.default_o ;TA_typ{t = Tid"bit"}])},[],pure_e
| L_string s -> simp_exp e l {t = Tid "string"},[],pure_e
- | L_undef -> simp_exp e l (new_t ()),[],{effect=Eset[BE_aux(BE_undef,l)]}) in
+ | L_undef ->
+ let ef = {effect=Eset[BE_aux(BE_undef,l)]} in
+ (match expect_t.t with
+ | Tapp ("vector",[TA_nexp base;TA_nexp {nexp=Nconst rise};TA_ord o;(TA_typ {t=Tid "bit"})])
+ | Tapp ("register",[TA_typ {t=Tapp ("vector",[TA_nexp base;TA_nexp {nexp=Nconst rise};
+ TA_ord o;(TA_typ {t=Tid "bit"})])}])->
+ let f = match o.order with | Oinc -> "to_vec_inc" | Odec -> "to_vec_dec" | _ -> "to_vec_inc" (*Change to follow a default?*) in
+ let tannot = (l,Base(([],expect_t),External (Some f),[],ef)) in
+ E_aux(E_app((Id_aux((Id f),l)),[(E_aux (E_internal_exp tannot, tannot));simp_exp e l bit_t]),tannot),[],ef
+ | _ -> simp_exp e l (new_t ()),[],ef)) in
let t',cs',_,e' = type_coerce (Expr l) d_env false (get_e_typ e) e expect_t in
(e',t',t_env,cs@cs',effect)
| E_cast(typ,e) ->
@@ -839,8 +848,9 @@ let rec check_exp envs (imp_param:nexp option) (expect_t:t) (E_aux(e,(l,annot)):
| (Def_val_empty,false) -> (Def_val_aux(Def_val_empty,(ld,Base(([],item_t),Emp_local,[],pure_e))),true,[],pure_e)
| (Def_val_empty,true) ->
let ef = add_effect (BE_aux(BE_unspec,l)) pure_e in
- (Def_val_aux(Def_val_dec ( (E_aux( E_lit( L_aux(L_undef, l)), (l, (Base(([],item_t),Emp_local,[],ef)))))),
- (l,Base(([],item_t),Emp_local,[],pure_e))),false,[],ef)
+ let (de,_,_,_,ef_d) = check_exp envs imp_param item_t (E_aux(E_lit (L_aux(L_undef,l)), (l,NoTyp))) in
+ (Def_val_aux(Def_val_dec de,
+ (l,Base(([],item_t),Emp_local,[],ef))),false,[],ef)
| (Def_val_dec e,_) -> let (de,t,_,cs_d,ef_d) = (check_exp envs imp_param item_t e) in
(*Check that ef_d doesn't write to memory or registers? *)
(Def_val_aux(Def_val_dec de,(ld,(Base(([],item_t),Emp_local,cs_d,ef_d)))),false,cs_d,ef_d) in