summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/jib/jib_compile.ml17
-rw-r--r--src/jib/jib_compile.mli4
-rw-r--r--src/jib/jib_smt.ml77
-rw-r--r--src/jib/jib_ssa.ml17
-rw-r--r--src/jib/jib_util.ml1
-rw-r--r--src/smtlib.ml10
-rw-r--r--src/value2.lem1
7 files changed, 98 insertions, 29 deletions
diff --git a/src/jib/jib_compile.ml b/src/jib/jib_compile.ml
index ad60d224..f8cb3bcd 100644
--- a/src/jib/jib_compile.ml
+++ b/src/jib/jib_compile.ml
@@ -160,7 +160,8 @@ type ctx =
optimize_anf : ctx -> typ aexp -> typ aexp;
specialize_calls : bool;
ignore_64 : bool;
- struct_value : bool
+ struct_value : bool;
+ use_real : bool;
}
let initial_ctx ~convert_typ:convert_typ ~optimize_anf:optimize_anf env =
@@ -176,7 +177,8 @@ let initial_ctx ~convert_typ:convert_typ ~optimize_anf:optimize_anf env =
optimize_anf = optimize_anf;
specialize_calls = false;
ignore_64 = false;
- struct_value = false
+ struct_value = false;
+ use_real = false;
}
let ctyp_of_typ ctx typ = ctx.convert_typ ctx typ
@@ -232,10 +234,13 @@ let rec compile_aval l ctx = function
| AV_lit (L_aux (L_false, _), _) -> [], V_lit (VL_bool false, CT_bool), []
| AV_lit (L_aux (L_real str, _), _) ->
- let gs = ngensym () in
- [iinit CT_real gs (V_lit (VL_string str, CT_string))],
- V_id (gs, CT_real),
- [iclear CT_real gs]
+ if ctx.use_real then
+ [], V_lit (VL_real str, CT_real), []
+ else
+ let gs = ngensym () in
+ [iinit CT_real gs (V_lit (VL_string str, CT_string))],
+ V_id (gs, CT_real),
+ [iclear CT_real gs]
| AV_lit (L_aux (L_unit, _), _) -> [], V_lit (VL_unit, CT_unit), []
diff --git a/src/jib/jib_compile.mli b/src/jib/jib_compile.mli
index b882f2f9..70a0b322 100644
--- a/src/jib/jib_compile.mli
+++ b/src/jib/jib_compile.mli
@@ -96,7 +96,9 @@ type ctx =
be ignored. *)
ignore_64 : bool;
(** If false (default) we won't generate any V_struct values *)
- struct_value : bool
+ struct_value : bool;
+ (** Allow real literals *)
+ use_real : bool;
}
val initial_ctx :
diff --git a/src/jib/jib_smt.ml b/src/jib/jib_smt.ml
index 99938365..c03b8934 100644
--- a/src/jib/jib_smt.ml
+++ b/src/jib/jib_smt.ml
@@ -92,6 +92,9 @@ type ctx = {
the global path conditional of the containing block in the
control flow graph *)
pathcond : smt_exp;
+ (* Set if we need to use strings *)
+ use_string : bool ref;
+ use_real : bool ref
}
(* These give the default bounds for various SMT types, stored in the
@@ -114,6 +117,8 @@ let initial_ctx () = {
ast = Defs [];
events = ref EventMap.empty;
pathcond = Bool_lit true;
+ use_string = ref false;
+ use_real = ref false;
}
let event_stack ctx ev =
@@ -162,7 +167,12 @@ let rec smt_ctyp ctx = function
ctx.tuple_sizes := IntSet.add (List.length ctyps) !(ctx.tuple_sizes);
Tuple (List.map (smt_ctyp ctx) ctyps)
| CT_vector (_, ctyp) -> Array (Bitvec !vector_index, smt_ctyp ctx ctyp)
- | CT_string -> Bitvec 64
+ | CT_string ->
+ ctx.use_string := true;
+ String
+ | CT_real ->
+ ctx.use_real := true;
+ Real
| CT_ref ctyp ->
begin match CTMap.find_opt ctyp ctx.register_map with
| Some regs -> Bitvec (required_width (Big_int.of_int (List.length regs)))
@@ -231,8 +241,16 @@ let smt_value ctx vl ctyp =
| VL_bit Sail2_values.B0, CT_bit -> Bin "0"
| VL_bit Sail2_values.B1, CT_bit -> Bin "1"
| VL_unit, _ -> Var "unit"
- | VL_string _, _ -> Var "unit" (* FIXME: String support *)
- | vl, _ -> failwith ("Cannot translate literal to SMT " ^ string_of_value vl)
+ | VL_string str, _ ->
+ ctx.use_string := true;
+ String_lit (String.escaped str)
+ | VL_real str, _ ->
+ ctx.use_real := true;
+ if str.[0] = '-' then
+ Fn ("-", [Real_lit (String.sub str 1 (String.length str - 1))])
+ else
+ Real_lit str
+ | vl, _ -> failwith ("Cannot translate literal to SMT: " ^ string_of_value vl)
let zencode_ctor ctor_id unifiers =
match unifiers with
@@ -883,9 +901,18 @@ let builtin_compare_bits fn ctx v1 v2 ret_ctyp =
| _ -> builtin_type_error ctx fn [v1; v2] (Some ret_ctyp)
+(* ***** Real number operations: lib/real.sail ***** *)
+
+let builtin_sqrt_real ctx root v =
+ ctx.use_real := true;
+ let smt = smt_cval ctx v in
+ [Declare_const (root, Real);
+ Assert (Fn ("and", [Fn ("=", [smt; Fn ("*", [Var root; Var root])]);
+ Fn (">=", [Var root; Real_lit "0.0"])]))]
+
let smt_builtin ctx name args ret_ctyp =
match name, args, ret_ctyp with
- | "eq_bits", [v1; v2], _ -> Fn ("=", [smt_cval ctx v1; smt_cval ctx v2])
+ | "eq_bits", [v1; v2], CT_bool -> Fn ("=", [smt_cval ctx v1; smt_cval ctx v2])
| "eq_anything", [v1; v2], CT_bool -> Fn ("=", [smt_cval ctx v1; smt_cval ctx v2])
(* lib/flow.sail *)
@@ -954,6 +981,23 @@ let smt_builtin ctx name args ret_ctyp =
| "get_slice_int", [v1; v2; v3], ret_ctyp -> builtin_get_slice_int ctx v1 v2 v3 ret_ctyp
| "set_slice", [v1; v2; v3; v4; v5], ret_ctyp -> builtin_set_slice_bits ctx v1 v2 v3 v4 v5 ret_ctyp
+ (* string builtins *)
+ | "concat_str", [v1; v2], CT_string -> ctx.use_string := true; Fn ("str.++", [smt_cval ctx v1; smt_cval ctx v2])
+ | "eq_string", [v1; v2], CT_bool -> ctx.use_string := true; Fn ("=", [smt_cval ctx v1; smt_cval ctx v2])
+
+ (* lib/real.sail *)
+ (* Note that sqrt_real is special and is handled by smt_instr. *)
+ | "eq_real", [v1; v2], CT_bool -> ctx.use_real := true; Fn ("=", [smt_cval ctx v1; smt_cval ctx v2])
+ | "neg_real", [v], CT_real -> ctx.use_real := true; Fn ("-", [smt_cval ctx v])
+ | "add_real", [v1; v2], CT_real -> ctx.use_real := true; Fn ("+", [smt_cval ctx v1; smt_cval ctx v2])
+ | "sub_real", [v1; v2], CT_real -> ctx.use_real := true; Fn ("-", [smt_cval ctx v1; smt_cval ctx v2])
+ | "mult_real", [v1; v2], CT_real -> ctx.use_real := true; Fn ("*", [smt_cval ctx v1; smt_cval ctx v2])
+ | "div_real", [v1; v2], CT_real -> ctx.use_real := true; Fn ("/", [smt_cval ctx v1; smt_cval ctx v2])
+ | "lt_real", [v1; v2], CT_bool -> ctx.use_real := true; Fn ("<", [smt_cval ctx v1; smt_cval ctx v2])
+ | "gt_real", [v1; v2], CT_bool -> ctx.use_real := true; Fn (">", [smt_cval ctx v1; smt_cval ctx v2])
+ | "lteq_real", [v1; v2], CT_bool -> ctx.use_real := true; Fn ("<=", [smt_cval ctx v1; smt_cval ctx v2])
+ | "gteq_real", [v1; v2], CT_bool -> ctx.use_real := true; Fn (">=", [smt_cval ctx v1; smt_cval ctx v2])
+
| _ -> failwith ("Unknown builtin " ^ name ^ " " ^ Util.string_of_list ", " string_of_ctyp (List.map cval_ctyp args) ^ " -> " ^ string_of_ctyp ret_ctyp)
let rec smt_conversion ctx from_ctyp to_ctyp x =
@@ -1288,8 +1332,15 @@ let smt_instr ctx =
| I_aux (I_funcall (CL_id (id, ret_ctyp), extern, function_id, args), (_, l)) ->
if Env.is_extern function_id ctx.tc_env "c" && not extern then
let name = Env.get_extern function_id ctx.tc_env "c" in
- let value = smt_builtin ctx name args ret_ctyp in
- [define_const ctx id ret_ctyp value]
+ if name = "sqrt_real" then
+ begin match args with
+ | [v] -> builtin_sqrt_real ctx (zencode_name id) v
+ | _ ->
+ Reporting.unreachable l __POS__ "Bad arguments for sqrt_real"
+ end
+ else
+ let value = smt_builtin ctx name args ret_ctyp in
+ [define_const ctx id ret_ctyp value]
else if extern && string_of_id function_id = "internal_vector_init" then
[declare_const ctx id ret_ctyp]
else if extern && string_of_id function_id = "internal_vector_update" then
@@ -1360,6 +1411,10 @@ let smt_instr ctx =
| I_aux (I_undefined ctyp, _) -> []
+ (* I_jump and I_goto will only appear as terminators for basic blocks. *)
+ | I_aux ((I_jump _ | I_goto _), _) -> []
+
+
| instr ->
failwith ("Cannot translate: " ^ Pretty_print_sail.to_string (pp_instr instr))
@@ -1404,7 +1459,7 @@ let optimize_smt stack =
| Some n -> Hashtbl.replace uses var (n + 1)
| None -> Hashtbl.add uses var 1
end
- | Hex _ | Bin _ | Bool_lit _ -> ()
+ | Hex _ | Bin _ | Bool_lit _ | String_lit _ | Real_lit _ -> ()
| Fn (f, exps) ->
List.iter uses_in_exp exps
| Ite (cond, t, e) ->
@@ -1613,7 +1668,11 @@ let smt_cdef props lets name_file ctx all_cdefs = function
let out_chan = open_out fname in
if prop_type = "counterexample" then
output_string out_chan "(set-option :produce-models true)\n";
- output_string out_chan "(set-logic QF_AUFBVDT)\n";
+
+ if !(ctx.use_string) || !(ctx.use_real) then
+ output_string out_chan "(set-logic ALL)\n"
+ else
+ output_string out_chan "(set-logic QF_AUFBVDT)\n";
List.iter (fun def -> output_string out_chan (string_of_smt_def def); output_string out_chan "\n") (smt_header ctx all_cdefs);
@@ -1679,7 +1738,7 @@ let generate_smt props name_file env ast =
env
in
let t = Profile.start () in
- let cdefs, ctx = compile_ast { ctx with specialize_calls = true; ignore_64 = true; struct_value = true } ast in
+ let cdefs, ctx = compile_ast { ctx with specialize_calls = true; ignore_64 = true; struct_value = true; use_real = true } ast in
Profile.finish "Compiling to Jib IR" t;
cdefs
in
diff --git a/src/jib/jib_ssa.ml b/src/jib/jib_ssa.ml
index c8027ee5..9a9a3361 100644
--- a/src/jib/jib_ssa.ml
+++ b/src/jib/jib_ssa.ml
@@ -125,7 +125,7 @@ let reachable roots graph =
IntSet.iter reachable' roots; !visited
exception Not_a_DAG of int;;
-
+
let topsort graph =
let marked = ref IntSet.empty in
let temp_marked = ref IntSet.empty in
@@ -193,6 +193,7 @@ type cf_node =
| CF_guard of cval
| CF_start of ctyp NameMap.t
+(* For now we only generate CFGs for flat lists of instructions *)
let control_flow_graph instrs =
let module StringMap = Map.Make(String) in
let labels = ref StringMap.empty in
@@ -215,7 +216,7 @@ let control_flow_graph instrs =
let rec cfg preds instrs =
let before, after = instr_split_at cf_split instrs in
let last = match after with
- | I_aux ((I_label _ | I_goto _ | I_jump _), _) :: _ -> []
+ | I_aux (I_label _, _) :: _ -> []
| instr :: _ -> [instr]
| _ -> []
in
@@ -227,11 +228,6 @@ let control_flow_graph instrs =
[n]
in
match after with
- | I_aux (I_if (cond, then_instrs, else_instrs, _), _) :: after ->
- let t = cfg preds then_instrs in
- let e = cfg preds else_instrs in
- cfg (t @ e) after
-
| I_aux ((I_end _ | I_match_failure | I_undefined _), _) :: after ->
cfg [] after
@@ -249,11 +245,8 @@ let control_flow_graph instrs =
| I_aux (I_label label, _) :: after ->
cfg (StringMap.find label !labels :: preds) after
- | I_aux (I_block instrs, _) :: after ->
- let m = cfg preds instrs in
- cfg m after
-
- | _ :: after -> assert false
+ | I_aux (_, (_, l)) :: after ->
+ Reporting.unreachable l __POS__ "Could not add instruction to control-flow graph"
| [] -> preds
in
diff --git a/src/jib/jib_util.ml b/src/jib/jib_util.ml
index c98c325c..378f5fae 100644
--- a/src/jib/jib_util.ml
+++ b/src/jib/jib_util.ml
@@ -259,6 +259,7 @@ let string_of_value = function
| VL_bit Sail2_values.B0 -> "UINT64_C(0)"
| VL_bit Sail2_values.B1 -> "UINT64_C(1)"
| VL_bit Sail2_values.BU -> failwith "Undefined bit found in value"
+ | VL_real str -> str
| VL_string str -> "\"" ^ str ^ "\""
let string_of_name ?deref_current_exception:(dce=true) ?zencode:(zencode=true) =
diff --git a/src/smtlib.ml b/src/smtlib.ml
index 72421b8a..7f485447 100644
--- a/src/smtlib.ml
+++ b/src/smtlib.ml
@@ -54,6 +54,8 @@ open Ast_util
type smt_typ =
| Bitvec of int
| Bool
+ | String
+ | Real
| Datatype of string * (string * (string * smt_typ) list) list
| Tuple of smt_typ list
| Array of smt_typ * smt_typ
@@ -89,6 +91,8 @@ type smt_exp =
| Bool_lit of bool
| Hex of string
| Bin of string
+ | Real_lit of string
+ | String_lit of string
| Var of string
| Fn of string * smt_exp list
| Ite of smt_exp * smt_exp * smt_exp
@@ -145,7 +149,7 @@ let rec simp_smt_exp vars = function
| Some exp -> simp_smt_exp vars exp
| None -> Var v
end
- | (Hex _ | Bin _ | Bool_lit _ as exp) -> exp
+ | (Hex _ | Bin _ | Bool_lit _ | String_lit _ | Real_lit _ as exp) -> exp
| Fn (f, exps) ->
let exps = List.map (simp_smt_exp vars) exps in
simp_fn (Fn (f, exps))
@@ -184,6 +188,8 @@ let rec pp_smt_exp =
let open PPrint in
function
| Bool_lit b -> string (string_of_bool b)
+ | Real_lit str -> string str
+ | String_lit str -> string ("\"" ^ str ^ "\"")
| Hex str -> string ("#x" ^ str)
| Bin str -> string ("#b" ^ str)
| Var str -> string str
@@ -201,6 +207,8 @@ let rec pp_smt_typ =
let open PPrint in
function
| Bool -> string "Bool"
+ | String -> string "String"
+ | Real -> string "Real"
| Bitvec n -> string (Printf.sprintf "(_ BitVec %d)" n)
| Datatype (name, _) -> string name
| Tuple tys -> pp_sfun ("Tup" ^ string_of_int (List.length tys)) (List.map pp_smt_typ tys)
diff --git a/src/value2.lem b/src/value2.lem
index 0e65e91f..0afaa2d1 100644
--- a/src/value2.lem
+++ b/src/value2.lem
@@ -59,4 +59,5 @@ type vl =
| VL_unit
| VL_int of integer
| VL_string of string
+ | VL_real of string
| VL_null (* Used for unitialized values and null pointers in C compilation *)