summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/jib/jib_smt.ml35
-rw-r--r--src/jib/jib_ssa.ml118
-rw-r--r--src/jib/jib_ssa.mli13
3 files changed, 112 insertions, 54 deletions
diff --git a/src/jib/jib_smt.ml b/src/jib/jib_smt.ml
index 350f50d9..de5feca1 100644
--- a/src/jib/jib_smt.ml
+++ b/src/jib/jib_smt.ml
@@ -1343,6 +1343,19 @@ let rmw_modify smt = function
end
| _ -> assert false
+let smt_terminator ctx =
+ let open Jib_ssa in
+ function
+ | T_end id ->
+ add_event ctx Return (Var (zencode_name id));
+ []
+
+ | T_match_failure ->
+ add_pathcond_event ctx Match;
+ []
+
+ | T_undefined _ | T_goto _ | T_jump _ | T_label _ | T_none -> []
+
(* For a basic block (contained in a control-flow node / cfnode), we
turn the instructions into a sequence of define-const and
declare-const expressions. Because we are working with a SSA graph,
@@ -1421,21 +1434,11 @@ let smt_instr ctx =
end;
[declare_const ctx id ctyp]
- | I_aux (I_end id, _) ->
- add_event ctx Return (Var (zencode_name id));
- []
-
| I_aux (I_clear _, _) -> []
- | I_aux (I_match_failure, _) ->
- add_pathcond_event ctx Match;
- []
-
- | I_aux (I_undefined ctyp, _) -> []
-
- (* I_jump and I_goto will only appear as terminators for basic blocks. *)
- | I_aux ((I_jump _ | I_goto _), _) -> []
-
+ (* Should only appear as terminators for basic blocks. *)
+ | I_aux ((I_jump _ | I_goto _ | I_end _ | I_match_failure | I_undefined _), (_, l)) ->
+ Reporting.unreachable l __POS__ "SMT: Instruction should only appear as block terminator"
| instr ->
failwith ("Cannot translate: " ^ Pretty_print_sail.to_string (pp_instr instr))
@@ -1451,9 +1454,11 @@ let smt_cfnode all_cdefs ctx ssanodes =
| _ -> declare_const ctx id ctyp
in
smt_reg_decs @ List.map smt_start (NameMap.bindings inits)
- | CF_block instrs ->
+ | CF_block (instrs, terminator) ->
let ctx = { ctx with pathcond = get_pathcond ctx ssanodes } in
- List.concat (List.map (smt_instr ctx) instrs)
+ let smt_instrs = List.map (smt_instr ctx) instrs in
+ let smt_term = smt_terminator ctx terminator in
+ List.concat (smt_instrs @ [smt_term])
(* We can ignore any non basic-block/start control-flow nodes *)
| _ -> []
diff --git a/src/jib/jib_ssa.ml b/src/jib/jib_ssa.ml
index a4a77f9d..dfacf90a 100644
--- a/src/jib/jib_ssa.ml
+++ b/src/jib/jib_ssa.ml
@@ -53,6 +53,7 @@ open Jib
open Jib_util
module IntSet = Set.Make(struct type t = int let compare = compare end)
+module IntMap = Map.Make(struct type t = int let compare = compare end)
(**************************************************************************)
(* 1. Mutable graph type *)
@@ -60,12 +61,16 @@ module IntSet = Set.Make(struct type t = int let compare = compare end)
type 'a array_graph = {
mutable next : int;
- mutable nodes : ('a * IntSet.t * IntSet.t) option array
+ mutable nodes : ('a * IntSet.t * IntSet.t) option array;
+ mutable next_cond : int;
+ mutable conds : cval IntMap.t
}
let make ~initial_size () = {
next = 0;
- nodes = Array.make initial_size None
+ nodes = Array.make initial_size None;
+ next_cond = 1;
+ conds = IntMap.empty
}
let get_vertex graph n = graph.nodes.(n)
@@ -77,6 +82,12 @@ let iter_graph f graph =
| None -> ()
done
+let add_cond cval graph =
+ let n = graph.next_cond in
+ graph.conds <- IntMap.add n cval graph.conds;
+ graph.next_cond <- n + 1;
+ n
+
(** Add a vertex to a graph, returning the node index *)
let add_vertex data graph =
let n = graph.next in
@@ -187,12 +198,32 @@ let prune visited graph =
(* 2. Mutable control flow graph *)
(**************************************************************************)
+type terminator =
+ | T_undefined of ctyp
+ | T_match_failure
+ | T_end of name
+ | T_goto of string
+ | T_jump of int * string
+ | T_label of string
+ | T_none
+
type cf_node =
| CF_label of string
- | CF_block of instr list
- | CF_guard of cval
+ | CF_block of instr list * terminator
+ | CF_guard of int
| CF_start of ctyp NameMap.t
+let to_terminator graph = function
+ | I_label label -> T_label label
+ | I_goto label -> T_goto label
+ | I_jump (cval, label) ->
+ let n = add_cond cval graph in
+ T_jump (n, label)
+ | I_end name -> T_end name
+ | I_match_failure -> T_match_failure
+ | I_undefined ctyp -> T_undefined ctyp
+ | _ -> assert false
+
(* For now we only generate CFGs for flat lists of instructions *)
let control_flow_graph instrs =
let module StringMap = Map.Make(String) in
@@ -209,46 +240,42 @@ let control_flow_graph instrs =
let cf_split (I_aux (aux, _)) =
match aux with
- | I_block _ | I_label _ | I_goto _ | I_jump _ | I_if _ | I_end _ | I_match_failure | I_undefined _ -> true
+ | I_label _ | I_goto _ | I_jump _ | I_end _ | I_match_failure | I_undefined _ -> true
| _ -> false
in
let rec cfg preds instrs =
let before, after = instr_split_at cf_split instrs in
- let last = match after with
- | I_aux (I_label _, _) :: _ -> []
- | instr :: _ -> [instr]
- | _ -> []
+ let terminator, after = match after with
+ | I_aux (instr, _) :: after -> to_terminator graph instr, after
+ | [] -> T_none, []
in
- let preds = match before @ last with
- | [] -> preds
- | instrs ->
- let n = add_vertex ([], CF_block instrs) graph in
+ let preds = match before, terminator with
+ | [], (T_none | T_label _) -> preds
+ | instrs, _ ->
+ let n = add_vertex ([], CF_block (instrs, terminator)) graph in
List.iter (fun p -> add_edge p n graph) preds;
[n]
in
- match after with
- | I_aux ((I_end _ | I_match_failure | I_undefined _), _) :: after ->
+ match terminator with
+ | T_end _ | T_match_failure | T_undefined _ ->
cfg [] after
- | I_aux (I_goto label, _) :: after ->
+ | T_goto label ->
List.iter (fun p -> add_edge p (StringMap.find label !labels) graph) preds;
cfg [] after
- | I_aux (I_jump (cval, label), _) :: after ->
- let t = add_vertex ([], CF_guard cval) graph in
- let f = add_vertex ([], CF_guard (V_call (Bnot, [cval]))) graph in
+ | T_jump (cond, label) ->
+ let t = add_vertex ([], CF_guard cond) graph in
+ let f = add_vertex ([], CF_guard (- cond)) graph in
List.iter (fun p -> add_edge p t graph; add_edge p f graph) preds;
add_edge t (StringMap.find label !labels) graph;
cfg [f] after
- | I_aux (I_label label, _) :: after ->
+ | T_label label ->
cfg (StringMap.find label !labels :: preds) after
- | I_aux (_, (_, l)) :: after ->
- Reporting.unreachable l __POS__ "Could not add instruction to control-flow graph"
-
- | [] -> preds
+ | T_none -> preds
in
let start = add_vertex ([], CF_start NameMap.empty) graph in
@@ -422,7 +449,7 @@ let place_phi_functions graph df =
let orig_A n =
match graph.nodes.(n) with
- | Some ((_, CF_block instrs), _, _) ->
+ | Some ((_, CF_block (instrs, _)), _, _) ->
let vars = List.fold_left NameCTSet.union NameCTSet.empty (List.map instr_typed_writes instrs) in
let vars = NameCTSet.diff vars (all_decls instrs) in
all_vars := NameCTSet.union vars !all_vars;
@@ -542,21 +569,32 @@ let rename_variables graph root children =
counts := NameMap.add id i !counts;
push_stack id i;
I_init (ctyp, ssa_name i id, cval)
- | I_jump (cval, label) ->
- I_jump (fold_cval cval, label)
- | I_end id ->
- let i = top_stack id in
- I_end (ssa_name i id)
| instr -> instr
in
I_aux (aux, annot)
in
+ let ssa_terminator = function
+ | T_jump (cond, label) ->
+ begin match IntMap.find_opt cond graph.conds with
+ | Some cval ->
+ graph.conds <- IntMap.add cond (fold_cval cval) graph.conds;
+ T_jump (cond, label)
+ | None -> assert false
+ end
+ | T_end id ->
+ let i = top_stack id in
+ T_end (ssa_name i id)
+ | terminator -> terminator
+ in
+
let ssa_cfnode = function
| CF_start inits -> CF_start inits
- | CF_block instrs -> CF_block (List.map ssa_instr instrs)
+ | CF_block (instrs, terminator) ->
+ let instrs = List.map ssa_instr instrs in
+ CF_block (instrs, ssa_terminator terminator)
| CF_label label -> CF_label label
- | CF_guard cval -> CF_guard (fold_cval cval)
+ | CF_guard cond -> CF_guard cond
in
let ssa_ssanode = function
@@ -612,13 +650,19 @@ let rename_variables graph root children =
let place_pi_functions graph start idom children =
let get_guard = function
- | CF_guard guard -> [guard]
+ | CF_guard cond ->
+ begin match IntMap.find_opt (abs cond) graph.conds with
+ | Some guard when cond > 0 -> [guard]
+ | Some guard -> [V_call (Bnot, [guard])]
+ | None -> assert false
+ end
| _ -> []
in
let get_pi_contents ssanodes =
List.concat (List.map (function Pi guards -> guards | _ -> []) ssanodes)
in
+ (*
let rec between_dom p n =
if n = p then
[]
@@ -634,13 +678,13 @@ let place_pi_functions graph start idom children =
| _, pred -> pred
end
| None -> assert false
- in
+ in *)
let rec go n =
begin match graph.nodes.(n) with
| Some ((ssa, cfnode), preds, succs) ->
let p = idom.(n) in
- let bd = between_dom p n in
+ let bd = [] (* between_dom p n *) in
if p <> -1 then
begin match graph.nodes.(p) with
| Some ((dom_ssa, _), _, _) ->
@@ -699,9 +743,9 @@ let string_of_phis = function
let string_of_node = function
| (phis, CF_label label) -> string_of_phis phis ^ label
- | (phis, CF_block instrs) -> string_of_phis phis ^ Util.string_of_list "\\l" (fun instr -> String.escaped (Pretty_print_sail.to_string (pp_instr ~short:true instr))) instrs
+ | (phis, CF_block (instrs, terminator)) -> string_of_phis phis ^ Util.string_of_list "\\l" (fun instr -> String.escaped (Pretty_print_sail.to_string (pp_instr ~short:true instr))) instrs
| (phis, CF_start inits) -> string_of_phis phis ^ "START"
- | (phis, CF_guard cval) -> string_of_phis phis ^ (String.escaped (Pretty_print_sail.to_string (pp_cval cval)))
+ | (phis, CF_guard cval) -> string_of_phis phis ^ string_of_int cval
let vertex_color = function
| (_, CF_start _) -> "peachpuff"
diff --git a/src/jib/jib_ssa.mli b/src/jib/jib_ssa.mli
index 759e1ccb..72cf1a1e 100644
--- a/src/jib/jib_ssa.mli
+++ b/src/jib/jib_ssa.mli
@@ -77,10 +77,19 @@ exception Not_a_DAG of int
val topsort : 'a array_graph -> int list
+type terminator =
+ | T_undefined of Jib.ctyp
+ | T_match_failure
+ | T_end of Jib.name
+ | T_goto of string
+ | T_jump of int * string
+ | T_label of string
+ | T_none
+
type cf_node =
| CF_label of string
- | CF_block of Jib.instr list
- | CF_guard of Jib.cval
+ | CF_block of Jib.instr list * terminator
+ | CF_guard of int
| CF_start of Jib.ctyp NameMap.t
val control_flow_graph : Jib.instr list -> int * int list * ('a list * cf_node) array_graph