diff options
| author | Alasdair Armstrong | 2019-03-21 18:54:16 +0000 |
|---|---|---|
| committer | Alasdair Armstrong | 2019-03-21 18:55:42 +0000 |
| commit | 13ad54f450a11a9c4eecdd782036e50ea2a41cd8 (patch) | |
| tree | 78adc8719e550dedb2870e6e9fcf108f206fe741 /src | |
| parent | 52382d4e8fc4edab67bf01080087fb12c88fbed4 (diff) | |
Jib: Add types to Phi functions
Add a test case to ensure variable types in l-expressions remain the
same with flow-sensitive constraints.
Diffstat (limited to 'src')
| -rw-r--r-- | src/jib/jib_compile.ml | 2 | ||||
| -rw-r--r-- | src/jib/jib_ssa.ml | 67 | ||||
| -rw-r--r-- | src/jib/jib_ssa.mli | 2 | ||||
| -rw-r--r-- | src/jib/jib_util.ml | 24 |
4 files changed, 60 insertions, 35 deletions
diff --git a/src/jib/jib_compile.ml b/src/jib/jib_compile.ml index 87e0b050..15f945e5 100644 --- a/src/jib/jib_compile.ml +++ b/src/jib/jib_compile.ml @@ -824,7 +824,7 @@ let rec compile_aexp ctx (AE_aux (aexp_aux, env, l)) = let body_gs = ngensym () in let loop_var = name loop_var in - + variable_init from_gs from_setup from_call from_cleanup @ variable_init to_gs to_setup to_call to_cleanup @ variable_init step_gs step_setup step_call step_cleanup diff --git a/src/jib/jib_ssa.ml b/src/jib/jib_ssa.ml index 470b646b..cbef761d 100644 --- a/src/jib/jib_ssa.ml +++ b/src/jib/jib_ssa.ml @@ -357,56 +357,56 @@ let dominance_frontiers graph root idom children = (**************************************************************************) type ssa_elem = - | Phi of Jib.name * Jib.name list + | Phi of Jib.name * Jib.ctyp * Jib.name list | Pi of Jib.cval list let place_phi_functions graph df = - let defsites = ref NameMap.empty in + let defsites = ref NameCTMap.empty in - let all_vars = ref NameSet.empty in + let all_vars = ref NameCTSet.empty in let rec all_decls = function - | I_aux ((I_init (_, id, _) | I_decl (_, id)), _) :: instrs -> - NameSet.add id (all_decls instrs) + | I_aux ((I_init (ctyp, id, _) | I_decl (ctyp, id)), _) :: instrs -> + NameCTSet.add (id, ctyp) (all_decls instrs) | _ :: instrs -> all_decls instrs - | [] -> NameSet.empty + | [] -> NameCTSet.empty in let orig_A n = match graph.nodes.(n) with | Some ((_, CF_block instrs), _, _) -> - let vars = List.fold_left NameSet.union NameSet.empty (List.map instr_writes instrs) in - let vars = NameSet.diff vars (all_decls instrs) in - all_vars := NameSet.union vars !all_vars; + 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; vars - | Some _ -> NameSet.empty - | None -> NameSet.empty + | Some _ -> NameCTSet.empty + | None -> NameCTSet.empty in - let phi_A = ref NameMap.empty in + let phi_A = ref NameCTMap.empty in for n = 0 to graph.next - 1 do - NameSet.iter (fun a -> - let ds = match NameMap.find_opt a !defsites with Some ds -> ds | None -> IntSet.empty in - defsites := NameMap.add a (IntSet.add n ds) !defsites + NameCTSet.iter (fun a -> + let ds = match NameCTMap.find_opt a !defsites with Some ds -> ds | None -> IntSet.empty in + defsites := NameCTMap.add a (IntSet.add n ds) !defsites ) (orig_A n) done; - NameSet.iter (fun a -> - let workset = ref (NameMap.find a !defsites) in + NameCTSet.iter (fun a -> + let workset = ref (NameCTMap.find a !defsites) in while not (IntSet.is_empty !workset) do let n = IntSet.choose !workset in workset := IntSet.remove n !workset; IntSet.iter (fun y -> - let phi_A_a = match NameMap.find_opt a !phi_A with Some set -> set | None -> IntSet.empty in + let phi_A_a = match NameCTMap.find_opt a !phi_A with Some set -> set | None -> IntSet.empty in if not (IntSet.mem y phi_A_a) then begin begin match graph.nodes.(y) with | Some ((phis, cfnode), preds, succs) -> - graph.nodes.(y) <- Some ((Phi (a, Util.list_init (IntSet.cardinal preds) (fun _ -> a)) :: phis, cfnode), preds, succs) + graph.nodes.(y) <- Some ((Phi (fst a, snd a, Util.list_init (IntSet.cardinal preds) (fun _ -> fst a)) :: phis, cfnode), preds, succs) | None -> assert false end; - phi_A := NameMap.add a (IntSet.add y phi_A_a) !phi_A; - if not (NameSet.mem a (orig_A y)) then + phi_A := NameCTMap.add a (IntSet.add y phi_A_a) !phi_A; + if not (NameCTSet.mem a (orig_A y)) then workset := IntSet.add y !workset end ) df.(n) @@ -433,7 +433,7 @@ let rename_variables graph root children = | Current_exception _ -> Current_exception i | Return _ -> Return i in - + let rec fold_frag = function | F_id id -> let i = top_stack id in @@ -498,22 +498,23 @@ let rename_variables graph root children = in let ssa_ssanode = function - | Phi (id, args) -> + | Phi (id, ctyp, args) -> let i = get_count id + 1 in counts := NameMap.add id i !counts; push_stack id i; - Phi (ssa_name i id, args) + Phi (ssa_name i id, ctyp, args) | Pi _ -> assert false (* Should not be introduced at this point *) in let fix_phi j = function - | Phi (id, ids) -> - Phi (id, List.mapi (fun k a -> - if k = j then - let i = top_stack a in - ssa_name i a - else a) - ids) + | Phi (id, ctyp, ids) -> + let fix_arg k a = + if k = j then + let i = top_stack a in + ssa_name i a + else a + in + Phi (id, ctyp, List.mapi fix_arg ids) | Pi _ -> assert false (* Should not be introduced at this point *) in @@ -604,8 +605,8 @@ let ssa instrs = (* Debugging utilities for outputing Graphviz files. *) let string_of_ssainstr = function - | Phi (id, args) -> - string_of_name id ^ " = φ(" ^ Util.string_of_list ", " string_of_name args ^ ")" + | Phi (id, ctyp, args) -> + string_of_name id ^ " : " ^ string_of_ctyp ctyp ^ " = φ(" ^ Util.string_of_list ", " string_of_name args ^ ")" | Pi cvals -> "π(" ^ Util.string_of_list ", " (fun (f, _) -> String.escaped (string_of_fragment ~zencode:false f)) cvals ^ ")" diff --git a/src/jib/jib_ssa.mli b/src/jib/jib_ssa.mli index 8cfdb198..0dba6edf 100644 --- a/src/jib/jib_ssa.mli +++ b/src/jib/jib_ssa.mli @@ -79,7 +79,7 @@ val control_flow_graph : Jib.instr list -> int * int list * ('a list * cf_node) val immediate_dominators : 'a array_graph -> int -> int array type ssa_elem = - | Phi of Jib.name * Jib.name list + | Phi of Jib.name * Jib.ctyp * Jib.name list | Pi of Jib.cval list (** Convert a list of instructions into SSA form *) diff --git a/src/jib/jib_util.ml b/src/jib/jib_util.ml index 99de19ef..3f7b14c0 100644 --- a/src/jib/jib_util.ml +++ b/src/jib/jib_util.ml @@ -648,6 +648,30 @@ let instr_deps = function | I_match_failure -> NameSet.empty, NameSet.empty | I_end -> NameSet.empty, NameSet.empty +module NameCT = struct + type t = name * ctyp + let compare (n1, ctyp1) (n2, ctyp2) = + let c = Name.compare n1 n2 in + if c = 0 then CT.compare ctyp1 ctyp2 else c +end + +module NameCTSet = Set.Make(NameCT) +module NameCTMap = Map.Make(NameCT) + +let rec clexp_typed_writes = function + | CL_id (id, ctyp) -> NameCTSet.singleton (id, ctyp) + | CL_field (clexp, _) -> clexp_typed_writes clexp + | CL_tuple (clexp, _) -> clexp_typed_writes clexp + | CL_addr clexp -> clexp_typed_writes clexp + | CL_void -> NameCTSet.empty + +let instr_typed_writes (I_aux (aux, _)) = + match aux with + | I_decl (ctyp, id) | I_reset (ctyp, id) -> NameCTSet.singleton (id, ctyp) + | I_init (ctyp, id, _) | I_reinit (ctyp, id, _) -> NameCTSet.singleton (id, ctyp) + | I_funcall (clexp, _, _, _) | I_copy (clexp, _) -> clexp_typed_writes clexp + | _ -> NameCTSet.empty + let rec map_clexp_ctyp f = function | CL_id (id, ctyp) -> CL_id (id, f ctyp) | CL_field (clexp, field) -> CL_field (map_clexp_ctyp f clexp, field) |
