From c4780a6a66b6da8b4dec76193acca22ccda416f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9lio=20Brun?= <lelio.brun@isae-supaero.fr> Date: Tue, 15 Jun 2021 17:34:57 +0200 Subject: [PATCH] work on new reset functions generation --- src/backends/C/c_backend_common.ml | 74 ++++- src/backends/C/c_backend_spec.ml | 110 +++++--- src/backends/C/c_backend_src.ml | 309 ++++++++++----------- src/backends/EMF/EMF_common.ml | 3 + src/backends/Horn/horn_backend_printers.ml | 5 + src/machine_code.ml | 2 +- src/machine_code_common.ml | 7 +- src/machine_code_common.mli | 3 +- src/machine_code_types.ml | 2 + src/optimize_machine.ml | 18 +- 10 files changed, 321 insertions(+), 212 deletions(-) diff --git a/src/backends/C/c_backend_common.ml b/src/backends/C/c_backend_common.ml index bcffd9e9..49475226 100644 --- a/src/backends/C/c_backend_common.ml +++ b/src/backends/C/c_backend_common.ml @@ -298,7 +298,14 @@ let rec pp_c_const fmt c = | Const_string _ | Const_modeid _ -> assert false (* string occurs in annotations not in C *) - +let reset_flag_name = "_reset" +let pp_reset_flag ?(indirect=true) fmt self = + fprintf fmt "%s%s%s" self (if indirect then "->" else ".") reset_flag_name + +let pp_reset_assign self fmt b = + fprintf fmt "%a = %i;" + (pp_reset_flag ~indirect:true) self (if b then 1 else 0) + (* Prints a value expression [v], with internal function calls only. [pp_var] is a printer for variables (typically [pp_c_var_read]), but an offset suffix may be added for array variables @@ -329,6 +336,9 @@ let rec pp_c_val m self pp_var fmt v = pp_var fmt v | Fun (n, vl) -> pp_basic_lib_fun (Types.is_int_type v.value_type) n pp_c_val fmt vl + | ResetFlag -> + pp_reset_flag fmt self + (* Access to the value of a variable: - if it's not a scalar output, then its name is enough @@ -472,6 +482,7 @@ let rec expansion_depth v = | Array vl -> 1 + List.fold_right (fun v -> max (expansion_depth v)) vl 0 | Access (v, _) -> max 0 (expansion_depth v - 1) | Power _ -> 0 (*1 + expansion_depth v*) + | ResetFlag -> 0 and expansion_depth_cst c = match c with | Const_array cl -> @@ -604,6 +615,8 @@ let rec pp_value_suffix ?(indirect=true) m self var_type loop_vars pp_var fmt va fprintf fmt "%a%a" pp_var v pp_suffix loop_vars | _, Cst cst -> pp_c_const_suffix var_type fmt cst + | _, ResetFlag -> + pp_reset_flag fmt self | _, _ -> eprintf "internal error: C_backend_src.pp_value_suffix %a %a %a@." Types.print_ty var_type (pp_val m) value pp_suffix loop_vars; @@ -676,18 +689,18 @@ let print_dealloc_prototype fmt name = (pp_machine_memtype_name ~ghost:false) name module type MODIFIERS_GHOST_PROTO = sig - val pp_ghost_parameters: formatter -> (string * (formatter -> string -> unit)) list -> unit + val pp_ghost_parameters: ?cut:bool -> formatter -> (string * (formatter -> string -> unit)) list -> unit end module EmptyGhostProto: MODIFIERS_GHOST_PROTO = struct - let pp_ghost_parameters _ _ = () + let pp_ghost_parameters ?cut _ _ = () end module Protos (Mod: MODIFIERS_GHOST_PROTO) = struct let pp_mem_ghost name fmt mem = pp_machine_decl ~ghost:true - (fun fmt mem -> fprintf fmt "\ghost %a" pp_ptr mem) fmt + (fun fmt mem -> fprintf fmt "\\ghost %a" pp_ptr mem) fmt (name, mem) let print_clear_reset_prototype self mem fmt (name, static) = @@ -697,7 +710,7 @@ module Protos (Mod: MODIFIERS_GHOST_PROTO) = struct pp_c_decl_input_var) static (pp_machine_memtype_name ~ghost:false) name self - Mod.pp_ghost_parameters [mem, pp_mem_ghost name] + (Mod.pp_ghost_parameters ~cut:true) [mem, pp_mem_ghost name] let print_set_reset_prototype self mem fmt (name, static) = fprintf fmt "@[<v>void %a (%a%a *%s)%a@]" @@ -706,7 +719,7 @@ module Protos (Mod: MODIFIERS_GHOST_PROTO) = struct pp_c_decl_input_var) static (pp_machine_memtype_name ~ghost:false) name self - Mod.pp_ghost_parameters [mem, pp_mem_ghost name] + (Mod.pp_ghost_parameters ~cut:true) [mem, pp_mem_ghost name] let print_step_prototype self mem fmt (name, inputs, outputs) = fprintf fmt "@[<v>void %a (@[<v>%a%a%a *%s@])%a@]" @@ -717,7 +730,7 @@ module Protos (Mod: MODIFIERS_GHOST_PROTO) = struct ~pp_epilogue:pp_print_cut pp_c_decl_output_var) outputs (pp_machine_memtype_name ~ghost:false) name self - Mod.pp_ghost_parameters [mem, pp_mem_ghost name] + (Mod.pp_ghost_parameters ~cut:true) [mem, pp_mem_ghost name] let print_init_prototype self fmt (name, static) = fprintf fmt "void %a (%a%a *%s)" @@ -879,6 +892,53 @@ let pp_file_open fmt inout idx = inout idx; "f_" ^ inout ^ string_of_int idx +let pp_basic_assign pp_var fmt typ var_name value = + if Types.is_real_type typ && !Options.mpfr + then + Mpfr.pp_inject_assign pp_var fmt (var_name, value) + else + fprintf fmt "%a = %a;" + pp_var var_name + pp_var value + +(* type_directed assignment: array vs. statically sized type + - [var_type]: type of variable to be assigned + - [var_name]: name of variable to be assigned + - [value]: assigned value + - [pp_var]: printer for variables +*) +let pp_assign m self pp_var fmt (var, value) = + let depth = expansion_depth value in + let var_type = var.var_type in + let var = mk_val (Var var) var_type in + (*eprintf "pp_assign %a %a %a %d@." Types.print_ty var_type pp_val var_name pp_val value depth;*) + let loop_vars = mk_loop_variables m var_type depth in + let reordered_loop_vars = reorder_loop_variables loop_vars in + let rec aux typ fmt vars = + match vars with + | [] -> + pp_basic_assign (pp_value_suffix m self var_type loop_vars pp_var) + fmt typ var value + | (d, LVar i) :: q -> + let typ' = Types.array_element_type typ in + (*eprintf "pp_aux %a %s@." Dimension.pp_dimension d i;*) + fprintf fmt "@[<v 2>{@,int %s;@,for(%s=0;%s<%a;%s++)@,%a @]@,}" + i i i pp_c_dimension d i + (aux typ') q + | (d, LInt r) :: q -> + (*eprintf "pp_aux %a %d@." Dimension.pp_dimension d (!r);*) + let typ' = Types.array_element_type typ in + let szl = Utils.enumerate (Dimension.size_const_dimension d) in + fprintf fmt "@[<v 2>{@,%a@]@,}" + (pp_print_list (fun fmt i -> r := i; aux typ' fmt q)) szl + | _ -> assert false + in + begin + reset_loop_counter (); + (*reset_addr_counter ();*) + aux var_type fmt reordered_loop_vars; + (*eprintf "end pp_assign@.";*) + end (* Local Variables: *) (* compile-command:"make -C ../../.." *) diff --git a/src/backends/C/c_backend_spec.ml b/src/backends/C/c_backend_spec.ml index c87b1f74..16fe5e6a 100644 --- a/src/backends/C/c_backend_spec.ml +++ b/src/backends/C/c_backend_spec.ml @@ -49,6 +49,12 @@ let pp_acsl_cut pp fmt = let pp_acsl_line pp fmt = fprintf fmt "//%@ @[<h>%a@]" pp +let pp_acsl_line' pp fmt = + fprintf fmt "/*%@ @[<h>%a@] */" pp + +let pp_acsl_line_cut pp fmt = + fprintf fmt "%a@," (pp_acsl_line pp) + let pp_requires pp_req fmt = fprintf fmt "requires %a;" pp_req @@ -362,7 +368,7 @@ module PrintSpec = struct let pp_reg pp_mem fmt = function | ResetFlag -> - fprintf fmt "%t_reset" pp_mem + fprintf fmt "%t%s" pp_mem reset_flag_name | StateVar x -> fprintf fmt "%t%a" pp_mem pp_var_decl x @@ -695,7 +701,7 @@ let label_pre = "Pre" let pp_at_pre pp_p fmt p = pp_at pp_p fmt (p, label_pre) -let pp_register ?(indirect=true) ptr = +let pp_register_chain ?(indirect=true) ptr = pp_print_list ~pp_prologue:(fun fmt () -> fprintf fmt "%s->" ptr) ~pp_epilogue:(fun fmt () -> fprintf fmt "%s_reg._first" @@ -703,19 +709,24 @@ let pp_register ?(indirect=true) ptr = ~pp_sep:(fun fmt () -> pp_print_string fmt (if indirect then "->" else ".")) (fun fmt (i, _) -> pp_print_string fmt i) -let pp_reset_flag ?(indirect=true) ptr fmt mems = +let pp_reset_flag_chain ?(indirect=true) ptr fmt mems = pp_print_list ~pp_prologue:(fun fmt () -> fprintf fmt "%s->" ptr) - ~pp_epilogue:(fun fmt () -> fprintf fmt "%s_reset" - (if indirect then "->" else ".")) + ~pp_epilogue:(fun fmt () -> pp_reset_flag ~indirect fmt "") ~pp_sep:(fun fmt () -> pp_print_string fmt (if indirect then "->" else ".")) (fun fmt (i, _) -> pp_print_string fmt i) fmt mems +let pp_arrow_reset_ghost mem fmt inst = + fprintf fmt "%s_reset_ghost(%a)" Arrow.arrow_id pp_indirect' (mem, inst) + module GhostProto: MODIFIERS_GHOST_PROTO = struct - let pp_ghost_parameters fmt vs = - fprintf fmt "@;%a" - (pp_acsl (pp_ghost (pp_print_parenthesized (fun fmt (x, pp) -> pp fmt x)))) + let pp_ghost_parameters ?(cut=true) fmt vs = + fprintf fmt "%a%a" + (if cut then pp_print_cut else pp_print_nothing) () + (pp_acsl_line' + (pp_ghost + (pp_print_parenthesized (fun fmt (x, pp) -> pp fmt x)))) vs end @@ -763,33 +774,37 @@ module SrcMod = struct pp_transition_defs ~pp_epilogue:pp_print_cutcut) machines - let pp_clear_reset_spec fmt machines self mem m = + let pp_clear_reset_spec fmt self mem m = let name = m.mname.node_id in let arws, narws = List.partition (fun (_, (td, _)) -> Arrow.td_is_arrow td) m.minstances in let mk_insts = List.map (fun x -> [x]) in pp_acsl_cut (fun fmt () -> fprintf fmt - "%a@,%a@,%a@,%a@,%a@,%a@,%a@,%a@,%a@,\ + "%a@,%a@,%a@,%a@,%a@,%a@,%a@,%a@,%a@,%a@,\ @[<v 2>behavior reset:@;\ %a@,%a@]@,\ @[<v 2>behavior no_reset:@;\ - %a@,%a@]" + %a@,%a@]@,\ + complete behaviors;@,\ + disjoint behaviors;" (pp_requires pp_mem_valid') (name, self) (pp_requires (pp_separated self mem)) (mk_insts m.minstances, []) + (pp_requires (pp_memory_pack_aux pp_ptr pp_print_string)) + (name, mem, self) (pp_ensures (pp_memory_pack_aux ~i:(List.length m.mspec.mmemory_packs - 2) pp_ptr pp_print_string)) (name, mem, self) - (pp_assigns pp_indirect') [self, "_reset"] - (pp_assigns (pp_register self)) (mk_insts arws) - (pp_assigns (pp_reset_flag self)) (mk_insts narws) - (pp_assigns pp_indirect') [mem, "_reset"] - (pp_assigns (pp_register ~indirect:false mem)) (mk_insts arws) - (pp_assigns (pp_reset_flag ~indirect:false mem)) (mk_insts narws) - (pp_assumes (pp_equal pp_indirect' pp_print_int)) ((mem, "_reset"), 1) + (pp_assigns pp_reset_flag) [self] + (pp_assigns (pp_register_chain self)) (mk_insts arws) + (pp_assigns (pp_reset_flag_chain self)) (mk_insts narws) + (pp_assigns pp_reset_flag) [mem] + (pp_assigns (pp_register_chain ~indirect:false mem)) (mk_insts arws) + (pp_assigns (pp_reset_flag_chain ~indirect:false mem)) (mk_insts narws) + (pp_assumes (pp_equal pp_reset_flag pp_print_int)) (mem, 1) (pp_ensures (pp_initialization pp_ptr)) (name, mem) - (pp_assumes (pp_equal pp_indirect' pp_print_int)) ((mem, "_reset"), 0) + (pp_assumes (pp_equal pp_reset_flag pp_print_int)) (mem, 0) (pp_ensures (pp_equal pp_ptr (pp_old pp_ptr))) (mem, mem) ) fmt () @@ -800,8 +815,8 @@ module SrcMod = struct fprintf fmt "%a@,%a@,%a" (pp_ensures (pp_memory_pack_aux pp_ptr pp_print_string)) (name, mem, self) - (pp_ensures (pp_equal pp_indirect' pp_print_string)) ((mem, "_reset"), "1") - (pp_assigns (fun fmt ptr -> pp_indirect' fmt (ptr, "_reset"))) [self; mem]) + (pp_ensures (pp_equal pp_reset_flag pp_print_string)) (mem, "1") + (pp_assigns pp_reset_flag) [self; mem]) fmt () let pp_step_spec fmt machines self mem m = @@ -833,29 +848,56 @@ module SrcMod = struct (pp_assigns pp_ptr_decl) outputs (pp_assigns (pp_reg self)) m.mmemory (pp_assigns (pp_memory self)) (memories insts') - (pp_assigns (pp_register self)) insts - (pp_assigns (pp_reset_flag self)) insts'' + (pp_assigns (pp_register_chain self)) insts + (pp_assigns (pp_reset_flag_chain self)) insts'' (pp_assigns (pp_reg mem)) m.mmemory (pp_assigns (pp_memory ~indirect:false mem)) (memories insts') - (pp_assigns (pp_register ~indirect:false mem)) insts - (pp_assigns (pp_reset_flag ~indirect:false mem)) insts'' + (pp_assigns (pp_register_chain ~indirect:false mem)) insts + (pp_assigns (pp_reset_flag_chain ~indirect:false mem)) insts'' (pp_ensures (pp_transition_aux m (pp_old pp_ptr) pp_ptr pp_var_decl pp_ptr_decl)) (name, inputs, [], outputs, mem, mem) ) fmt () - let pp_step_instr_spec m self fmt instr = - fprintf fmt "@,%a" - (pp_print_list ~pp_open_box:pp_open_vbox0 - (pp_acsl (pp_assert (PrintSpec.pp_spec (InstrMode self) m)))) + let pp_ghost_instr_code m self fmt instr = match instr.instr_desc with + | MStateAssign (x, v) -> + fprintf fmt "@,%a" + (pp_acsl_line + (pp_ghost + (pp_assign m self (pp_c_var_read m)))) + (x, v) + | MResetAssign b -> + fprintf fmt "@,%a" + (pp_acsl_line + (pp_ghost + (pp_reset_assign self))) + b + | MSetReset inst -> + let td, _ = List.assoc inst m.minstances in + if Arrow.td_is_arrow td then + fprintf fmt "@,%a" + (pp_acsl_line + (pp_ghost + (pp_arrow_reset_ghost self))) + inst + | _ -> () + + let pp_step_instr_spec m self mem fmt instr = + fprintf fmt "%a%a" + (pp_ghost_instr_code m mem) instr + (pp_print_list ~pp_open_box:pp_open_vbox0 ~pp_prologue:pp_print_cut + (pp_acsl_line' (pp_assert (PrintSpec.pp_spec (InstrMode self) m)))) instr.instr_spec - let pp_ghost_set_reset_spec fmt = - fprintf fmt "@;%a@;" - (pp_acsl_line - (pp_ghost - (fun fmt mem -> fprintf fmt "%a = 1;" pp_indirect' (mem, "_reset")))) + let pp_ghost_parameter mem fmt inst = + GhostProto.pp_ghost_parameters ~cut:false fmt + (match inst with + | Some inst -> + [inst, fun fmt inst -> fprintf fmt "&%a" pp_indirect' (mem, inst)] + | None -> + [mem, pp_print_string]) + end (**************************************************************************) diff --git a/src/backends/C/c_backend_src.ml b/src/backends/C/c_backend_src.ml index 002ae1d7..e7d245cf 100644 --- a/src/backends/C/c_backend_src.ml +++ b/src/backends/C/c_backend_src.ml @@ -20,20 +20,20 @@ module type MODIFIERS_SRC = sig module GhostProto: MODIFIERS_GHOST_PROTO val pp_predicates: formatter -> machine_t list -> unit val pp_set_reset_spec: formatter -> ident -> ident -> machine_t -> unit - val pp_clear_reset_spec: formatter -> machine_t list -> ident -> ident -> machine_t -> unit + val pp_clear_reset_spec: formatter -> ident -> ident -> machine_t -> unit val pp_step_spec: formatter -> machine_t list -> ident -> ident -> machine_t -> unit - val pp_step_instr_spec: machine_t -> ident -> formatter -> instr_t -> unit - val pp_ghost_set_reset_spec: formatter -> ident -> unit + val pp_step_instr_spec: machine_t -> ident -> ident -> formatter -> instr_t -> unit + val pp_ghost_parameter: ident -> formatter -> ident option -> unit end module EmptyMod = struct module GhostProto = EmptyGhostProto let pp_predicates _ _ = () let pp_set_reset_spec _ _ _ _ = () - let pp_clear_reset_spec _ _ _ _ _ = () + let pp_clear_reset_spec _ _ _ _ = () let pp_step_spec _ _ _ _ _ = () - let pp_step_instr_spec _ _ _ _ = () - let pp_ghost_set_reset_spec _ _ = () + let pp_step_instr_spec _ _ _ _ _ = () + let pp_ghost_parameter _ _ _ = () end module Main = functor (Mod: MODIFIERS_SRC) -> struct @@ -55,7 +55,7 @@ module Main = functor (Mod: MODIFIERS_SRC) -> struct let rec static_loop_profile v = match v.value_desc with | Cst cst -> static_loop_profile_cst cst - | Var _ -> [] + | Var _ | ResetFlag -> [] | Fun (_, vl) -> List.fold_right (fun v lp -> merge_static_loop_profiles lp (static_loop_profile v)) vl [] @@ -81,54 +81,8 @@ module Main = functor (Mod: MODIFIERS_SRC) -> struct let pp_c_val m self pp_var fmt v = pp_value_suffix m self v.value_type [] pp_var fmt v - let pp_basic_assign pp_var fmt typ var_name value = - if Types.is_real_type typ && !Options.mpfr - then - Mpfr.pp_inject_assign pp_var fmt (var_name, value) - else - fprintf fmt "%a = %a;" - pp_var var_name - pp_var value - - (* type_directed assignment: array vs. statically sized type - - [var_type]: type of variable to be assigned - - [var_name]: name of variable to be assigned - - [value]: assigned value - - [pp_var]: printer for variables - *) - let pp_assign m self pp_var fmt var_type var_name value = - let depth = expansion_depth value in - (*eprintf "pp_assign %a %a %a %d@." Types.print_ty var_type pp_val var_name pp_val value depth;*) - let loop_vars = mk_loop_variables m var_type depth in - let reordered_loop_vars = reorder_loop_variables loop_vars in - let rec aux typ fmt vars = - match vars with - | [] -> - pp_basic_assign (pp_value_suffix m self var_type loop_vars pp_var) - fmt typ var_name value - | (d, LVar i) :: q -> - let typ' = Types.array_element_type typ in - (*eprintf "pp_aux %a %s@." Dimension.pp_dimension d i;*) - fprintf fmt "@[<v 2>{@,int %s;@,for(%s=0;%s<%a;%s++)@,%a @]@,}" - i i i pp_c_dimension d i - (aux typ') q - | (d, LInt r) :: q -> - (*eprintf "pp_aux %a %d@." Dimension.pp_dimension d (!r);*) - let typ' = Types.array_element_type typ in - let szl = Utils.enumerate (Dimension.size_const_dimension d) in - fprintf fmt "@[<v 2>{@,%a@]@,}" - (pp_print_list (fun fmt i -> r := i; aux typ' fmt q)) szl - | _ -> assert false - in - begin - reset_loop_counter (); - (*reset_addr_counter ();*) - aux var_type fmt reordered_loop_vars; - (*eprintf "end pp_assign@.";*) - end - - let pp_machine_ pp_machine_name fn_name m fmt ?inst self = - let name, static = + let pp_machine_ pp_machine_name fn_name m fmt ?inst self mem = + let name, is_arrow, static = match inst with | Some inst -> let node, static = try List.assoc inst m.minstances with Not_found -> @@ -136,32 +90,40 @@ module Main = functor (Mod: MODIFIERS_SRC) -> struct fn_name m.mname.node_id self inst; raise Not_found in - node_name node, static + node_name node, Arrow.td_is_arrow node, static | None -> - m.mname.node_id, [] + m.mname.node_id, false, [] in - fprintf fmt "%a(%a%s%a);" - pp_machine_name name + let is_arrow_reset = is_arrow && fn_name = "pp_machine_set_reset" in + fprintf fmt "%a(%a%s%a)%a;" + (if is_arrow_reset then + (fun fmt -> fprintf fmt "%s_reset") + else + pp_machine_name) name (pp_comma_list ~pp_eol:pp_print_comma Dimension.pp_dimension) static self (pp_print_option (fun fmt -> fprintf fmt "->%s")) inst + (if is_arrow_reset then pp_print_nothing else Mod.pp_ghost_parameter mem) + inst - let pp_machine_set_reset m self fmt inst = - pp_machine_ pp_machine_set_reset_name "pp_machine_set_reset" m fmt ~inst self + let pp_machine_set_reset m self mem fmt inst = + pp_machine_ pp_machine_set_reset_name "pp_machine_set_reset" m fmt ~inst + self mem - let pp_machine_clear_reset m self fmt = - pp_machine_ pp_machine_clear_reset_name "pp_machine_clear_reset" m fmt self + let pp_machine_clear_reset m self mem fmt = + pp_machine_ pp_machine_clear_reset_name "pp_machine_clear_reset" m fmt + self mem - let pp_machine_init m self fmt inst = - pp_machine_ pp_machine_init_name "pp_machine_init" m fmt ~inst self + let pp_machine_init m self mem fmt inst = + pp_machine_ pp_machine_init_name "pp_machine_init" m fmt ~inst self mem - let pp_machine_clear m self fmt inst = - pp_machine_ pp_machine_clear_name "pp_machine_clear" m fmt ~inst self + let pp_machine_clear m self mem fmt inst = + pp_machine_ pp_machine_clear_name "pp_machine_clear" m fmt ~inst self mem - let pp_call m self pp_read pp_write fmt i inputs outputs = + let pp_call m self mem pp_read pp_write fmt i inputs outputs = try (* stateful node instance *) let n, _ = List.assoc i m.minstances in - fprintf fmt "%a(%a%a%s->%s);" + fprintf fmt "%a(%a%a%s->%s)%a;" pp_machine_step_name (node_name n) (pp_comma_list ~pp_eol:pp_print_comma (pp_c_val m self pp_read)) inputs @@ -169,6 +131,7 @@ module Main = functor (Mod: MODIFIERS_SRC) -> struct pp_write) outputs self i + (Mod.pp_ghost_parameter mem) (Some i) with Not_found -> (* stateless node instance *) let n, _ = List.assoc i m.mcalls in fprintf fmt "%a(%a%a);" @@ -177,20 +140,21 @@ module Main = functor (Mod: MODIFIERS_SRC) -> struct (pp_c_val m self pp_read)) inputs (pp_comma_list pp_write) outputs - let pp_basic_instance_call m self = - pp_call m self (pp_c_var_read m) (pp_c_var_write m) + let pp_basic_instance_call m self mem = + pp_call m self mem (pp_c_var_read m) (pp_c_var_write m) - let pp_arrow_call m self fmt i outputs = + let pp_arrow_call m self mem fmt i outputs = match outputs with | [x] -> - fprintf fmt "%a = %a(%s->%s);" + fprintf fmt "%a = %a(%s->%s)%a;" (pp_c_var_read m) x pp_machine_step_name Arrow.arrow_id self i + (Mod.pp_ghost_parameter mem) (Some i) | _ -> assert false - let pp_instance_call m self fmt i inputs outputs = + let pp_instance_call m self mem fmt i inputs outputs = let pp_offset pp_var indices fmt var = fprintf fmt "%a%a" pp_var var @@ -208,86 +172,103 @@ module Main = functor (Mod: MODIFIERS_SRC) -> struct else let pp_read = pp_offset (pp_c_var_read m) indices in let pp_write = pp_offset (pp_c_var_write m) indices in - pp_call m self pp_read pp_write fmt i inputs outputs + pp_call m self mem pp_read pp_write fmt i inputs outputs in reset_loop_counter (); aux [] fmt (List.hd inputs).Machine_code_types.value_type - let rec pp_conditional dependencies (m: machine_t) self fmt c tl el = - fprintf fmt "@[<v 2>if (%a) {%a@]@,@[<v 2>} else {%a@]@,}" - (pp_c_val m self (pp_c_var_read m)) c - (pp_print_list ~pp_prologue:pp_print_cut - (pp_machine_instr dependencies m self)) tl - (pp_print_list ~pp_prologue:pp_print_cut - (pp_machine_instr dependencies m self)) el - - and pp_machine_instr dependencies (m: machine_t) self fmt instr = - match get_instr_desc instr with - | MNoReset _ -> () - | MSetReset inst -> - pp_machine_set_reset m self fmt inst - | MClearReset -> - fprintf fmt "%t@,%a" - (pp_machine_clear_reset m self) pp_label reset_label - | MLocalAssign (i,v) -> - pp_assign - m self (pp_c_var_read m) fmt - i.var_type (mk_val (Var i) i.var_type) v - | MStateAssign (i,v) -> - pp_assign - m self (pp_c_var_read m) fmt - i.var_type (mk_val (Var i) i.var_type) v - | MStep ([i0], i, vl) when Basic_library.is_value_internal_fun (mk_val (Fun (i, vl)) i0.var_type) -> - pp_machine_instr dependencies m self fmt - (update_instr_desc instr (MLocalAssign (i0, mk_val (Fun (i, vl)) i0.var_type))) - | MStep (il, i, vl) when !Options.mpfr && Mpfr.is_homomorphic_fun i -> - pp_instance_call m self fmt i vl il - | MStep ([i0], i, vl) when has_c_prototype i dependencies -> - fprintf fmt "%a = %s%a;" - (pp_c_val m self (pp_c_var_read m)) (mk_val (Var i0) i0.var_type) - i - (pp_print_parenthesized (pp_c_val m self (pp_c_var_read m))) vl - | MStep (il, i, vl) -> - let td, _ = List.assoc i m.minstances in - if Arrow.td_is_arrow td then - pp_arrow_call m self fmt i il - else - pp_basic_instance_call m self fmt i vl il - | MBranch (_, []) -> - eprintf "internal error: C_backend_src.pp_machine_instr %a@." - (pp_instr m) instr; - assert false - | MBranch (g, hl) -> - if let t = fst (List.hd hl) in t = tag_true || t = tag_false - then (* boolean case, needs special treatment in C because truth value is not unique *) - (* may disappear if we optimize code by replacing last branch test with default *) - let tl = try List.assoc tag_true hl with Not_found -> [] in - let el = try List.assoc tag_false hl with Not_found -> [] in - pp_conditional dependencies m self fmt g tl el - else (* enum type case *) - (*let g_typ = Typing.type_const Location.dummy_loc (Const_tag (fst (List.hd hl))) in*) - fprintf fmt "@[<v 2>switch(%a) {@,%a@,}@]" - (pp_c_val m self (pp_c_var_read m)) g - (pp_print_list ~pp_open_box:pp_open_vbox0 - (pp_machine_branch dependencies m self)) hl - | MSpec s -> - fprintf fmt "@[/*@@ %s */@]@ " s - | MComment s -> - fprintf fmt "/*%s*/@ " s - - and pp_machine_branch dependencies m self fmt (t, h) = + let rec pp_conditional dependencies m self mem fmt c tl el = + let pp_machine_instrs = + pp_print_list ~pp_open_box:pp_open_vbox0 ~pp_prologue:pp_print_cut + (pp_machine_instr dependencies m self mem) in + let pp_cond = pp_c_val m self (pp_c_var_read m) in + match tl, el with + | [], _ :: _ -> + fprintf fmt "@[<v 2>if (!%a) {%a@]@,}" + pp_cond c + pp_machine_instrs el + | _, [] -> + fprintf fmt "@[<v 2>if (%a) {%a@]@,}" + pp_cond c + pp_machine_instrs tl + | _, _ -> + fprintf fmt "@[<v 2>if (%a) {%a@]@,@[<v 2>} else {%a@]@,}" + pp_cond c + pp_machine_instrs tl + pp_machine_instrs el + + and pp_machine_instr dependencies m self mem fmt instr = + let pp_instr fmt instr = match get_instr_desc instr with + | MNoReset _ -> () + | MSetReset inst -> + pp_machine_set_reset m self mem fmt inst + | MClearReset -> + fprintf fmt "%t@,%a" + (pp_machine_clear_reset m self mem) pp_label reset_label + | MResetAssign b -> + pp_reset_assign self fmt b + | MLocalAssign (i, v) -> + pp_assign m self (pp_c_var_read m) fmt (i, v) + | MStateAssign (i, v) -> + pp_assign m self (pp_c_var_read m) fmt (i, v) + | MStep ([i0], i, vl) when Basic_library.is_value_internal_fun (mk_val (Fun (i, vl)) i0.var_type) -> + pp_machine_instr dependencies m self mem fmt + (update_instr_desc instr (MLocalAssign (i0, mk_val (Fun (i, vl)) i0.var_type))) + | MStep (il, i, vl) when !Options.mpfr && Mpfr.is_homomorphic_fun i -> + pp_instance_call m self mem fmt i vl il + | MStep ([i0], i, vl) when has_c_prototype i dependencies -> + fprintf fmt "%a = %s%a;" + (pp_c_val m self (pp_c_var_read m)) (mk_val (Var i0) i0.var_type) + i + (pp_print_parenthesized (pp_c_val m self (pp_c_var_read m))) vl + | MStep (il, i, vl) -> + let td, _ = List.assoc i m.minstances in + if Arrow.td_is_arrow td then + pp_arrow_call m self mem fmt i il + else + pp_basic_instance_call m self mem fmt i vl il + | MBranch (_, []) -> + eprintf "internal error: C_backend_src.pp_machine_instr %a@." + (pp_instr m) instr; + assert false + | MBranch (g, hl) -> + if let t = fst (List.hd hl) in t = tag_true || t = tag_false + then (* boolean case, needs special treatment in C because truth value is not unique *) + (* may disappear if we optimize code by replacing last branch test with default *) + let tl = try List.assoc tag_true hl with Not_found -> [] in + let el = try List.assoc tag_false hl with Not_found -> [] in + let no_noreset = List.filter (fun i -> match i.instr_desc with + | MNoReset _ -> false + | _ -> true) + in + pp_conditional dependencies m self mem fmt g + (no_noreset tl) (no_noreset el) + else (* enum type case *) + (*let g_typ = Typing.type_const Location.dummy_loc (Const_tag (fst (List.hd hl))) in*) + fprintf fmt "@[<v 2>switch(%a) {@,%a@,}@]" + (pp_c_val m self (pp_c_var_read m)) g + (pp_print_list ~pp_open_box:pp_open_vbox0 + (pp_machine_branch dependencies m self mem)) hl + | MSpec s -> + fprintf fmt "@[/*@@ %s */@]@ " s + | MComment s -> + fprintf fmt "/*%s*/@ " s + in + fprintf fmt "%a%a" pp_instr instr (Mod.pp_step_instr_spec m self mem) instr + + and pp_machine_branch dependencies m self mem fmt (t, h) = fprintf fmt "@[<v 2>case %a:@,%a@,break;@]" pp_c_tag t (pp_print_list ~pp_open_box:pp_open_vbox0 - (pp_machine_instr dependencies m self)) h + (pp_machine_instr dependencies m self mem)) h - let pp_machine_nospec_instr dependencies m self fmt _i instr = - pp_machine_instr dependencies m self fmt instr - - let pp_machine_step_instr dependencies m self fmt _i instr = - fprintf fmt "%a%a" - (pp_machine_instr dependencies m self) instr - (Mod.pp_step_instr_spec m self) instr + (* let pp_machine_nospec_instr dependencies m self fmt instr = + * pp_machine_instr dependencies m self fmt instr + * + * let pp_machine_step_instr dependencies m self mem fmt instr = + * fprintf fmt "%a%a" + * (pp_machine_instr dependencies m self) instr + * (Mod.pp_step_instr_spec m self mem) instr *) (********************************************************************************************) (* C file Printing functions *) @@ -414,7 +395,7 @@ module Main = functor (Mod: MODIFIERS_SRC) -> struct ?(mpfr_locals=[]) ?(pp_check=pp_print_nothing) ?(checks=[]) ?(pp_extra=pp_print_nothing) - ?(pp_instr=fun fmt _ _ -> pp_print_nothing fmt ()) ?(instrs=[]) + ?(pp_instr=fun fmt _ -> pp_print_nothing fmt ()) ?(instrs=[]) fmt = fprintf fmt "%a@[<v 2>%a {@,\ @@ -444,7 +425,7 @@ module Main = functor (Mod: MODIFIERS_SRC) -> struct (* check assertions *) (pp_print_list pp_check) checks (* instrs *) - (pp_print_list_i + (pp_print_list ~pp_open_box:pp_open_vbox0 ~pp_epilogue:pp_print_cut pp_instr) instrs @@ -478,7 +459,7 @@ module Main = functor (Mod: MODIFIERS_SRC) -> struct ~mpfr_locals:m.mstep.step_locals ~pp_check:(pp_c_check m self) ~checks:m.mstep.step_checks - ~pp_instr:(pp_machine_step_instr dependencies m self) + ~pp_instr:(pp_machine_instr dependencies m self self) ~instrs:m.mstep.step_instrs fmt else @@ -500,28 +481,30 @@ module Main = functor (Mod: MODIFIERS_SRC) -> struct ~mpfr_locals:m.mstep.step_locals ~pp_check:(pp_c_check m self) ~checks:m.mstep.step_checks - ~pp_instr:(pp_machine_step_instr dependencies m self) + ~pp_instr:(pp_machine_instr dependencies m self self) ~instrs:m.mstep.step_instrs fmt - let print_clear_reset_code machines dependencies self mem fmt m = + let print_clear_reset_code dependencies self mem fmt m = pp_print_function - ~pp_spec:(fun fmt () -> Mod.pp_clear_reset_spec fmt machines self mem m) + ~pp_spec:(fun fmt () -> Mod.pp_clear_reset_spec fmt self mem m) ~pp_prototype:(Protos.print_clear_reset_prototype self mem) ~prototype:(m.mname.node_id, m.mstatic) ~pp_local:(pp_c_decl_local_var m) ~base_locals:(const_locals m) - ~pp_instr:(pp_machine_nospec_instr dependencies m self) - ~instrs:m.minit + ~pp_instr:(pp_machine_instr dependencies m self mem) + ~instrs:[mk_branch + (mk_val ResetFlag Type_predef.type_bool) + ["true", mkinstr (MResetAssign false) :: m.minit]] fmt - let print_set_reset_code self mem fmt m = + let print_set_reset_code dependencies self mem fmt m = pp_print_function ~pp_spec:(fun fmt () -> Mod.pp_set_reset_spec fmt self mem m) ~pp_prototype:(Protos.print_set_reset_prototype self mem) ~prototype:(m.mname.node_id, m.mstatic) - ~pp_extra:(fun fmt () -> fprintf fmt "self->_reset = 1;%a" - Mod.pp_ghost_set_reset_spec mem) + ~pp_instr:(pp_machine_instr dependencies m self mem) + ~instrs:[mkinstr (MResetAssign true)] fmt let print_init_code self fmt m = @@ -541,7 +524,7 @@ module Main = functor (Mod: MODIFIERS_SRC) -> struct pp_print_list ~pp_open_box:pp_open_vbox0 ~pp_epilogue:pp_print_cut - (pp_machine_init m self) + (pp_machine_init m self self) fmt minit) fmt @@ -561,7 +544,7 @@ module Main = functor (Mod: MODIFIERS_SRC) -> struct pp_print_list ~pp_open_box:pp_open_vbox0 ~pp_epilogue:pp_print_cut - (pp_machine_clear m self) + (pp_machine_clear m self self) fmt minit) fmt @@ -582,7 +565,7 @@ module Main = functor (Mod: MODIFIERS_SRC) -> struct ~mpfr_locals:m.mstep.step_locals ~pp_check:(pp_c_check m self) ~checks:m.mstep.step_checks - ~pp_instr:(pp_machine_step_instr dependencies m self) + ~pp_instr:(pp_machine_instr dependencies m self mem) ~instrs:m.mstep.step_instrs fmt else @@ -605,7 +588,7 @@ module Main = functor (Mod: MODIFIERS_SRC) -> struct ~mpfr_locals:m.mstep.step_locals ~pp_check:(pp_c_check m self) ~checks:m.mstep.step_checks - ~pp_instr:(pp_machine_step_instr dependencies m self) + ~pp_instr:(pp_machine_instr dependencies m self mem) ~instrs:m.mstep.step_instrs fmt @@ -754,8 +737,8 @@ module Main = functor (Mod: MODIFIERS_SRC) -> struct fprintf fmt "@[<v>%a%a@,@,%a@,@,%a%a@]" print_alloc_function m (* Reset functions *) - (print_clear_reset_code machines dependencies self mem) m - (print_set_reset_code self mem) m + (print_clear_reset_code dependencies self mem) m + (print_set_reset_code dependencies self mem) m (* Step function *) (print_step_code machines dependencies self mem) m (print_mpfr_code self) m diff --git a/src/backends/EMF/EMF_common.ml b/src/backends/EMF/EMF_common.ml index 38bcb5be..d93bc214 100644 --- a/src/backends/EMF/EMF_common.ml +++ b/src/backends/EMF/EMF_common.ml @@ -316,6 +316,9 @@ let rec pp_emf_cst_or_var m fmt v = fprintf fmt "@]}" ) | Fun _ -> eprintf "Fun expression should have been normalized: %a@." (pp_val m) v ; assert false (* Invalid argument *) + | ResetFlag -> + (* TODO: handle reset flag *) + assert false and pp_emf_cst_or_var_list m = Utils.fprintf_list ~sep:",@ " (pp_emf_cst_or_var m) diff --git a/src/backends/Horn/horn_backend_printers.ml b/src/backends/Horn/horn_backend_printers.ml index 4fe13f20..de903a39 100644 --- a/src/backends/Horn/horn_backend_printers.ml +++ b/src/backends/Horn/horn_backend_printers.ml @@ -163,6 +163,9 @@ let rec pp_horn_val ?(is_lhs=false) m self pp_var fmt v = pp_var fmt (rename_machine self v) | Fun (n, vl) -> fprintf fmt "%a" (pp_basic_lib_fun n (pp_horn_val m self pp_var)) vl + | ResetFlag -> + (* TODO: handle reset flag *) + assert false (* Prints a [value] indexed by the suffix list [loop_vars] *) let rec pp_value_suffix m self pp_value fmt value = @@ -295,6 +298,8 @@ let pp_instance_call machines reset_instances m fmt i inputs outputs = let rec pp_machine_instr machines reset_instances (m: machine_t) fmt instr : ident list = match get_instr_desc instr with | MSpec _ | MComment _ -> reset_instances + (* TODO: handle reset flag *) + | MResetAssign _ -> reset_instances (* TODO: handle clear_reset *) | MClearReset -> reset_instances | MNoReset i -> (* we assign middle_mem with mem_m. And declare i as reset *) diff --git a/src/machine_code.ml b/src/machine_code.ml index b840e6b7..3b10b974 100644 --- a/src/machine_code.ml +++ b/src/machine_code.ml @@ -161,7 +161,7 @@ let rec translate_act env (y, expr) = let h, spec_h = translate_act (y, h) in (t, [h]), (t, spec_h)) hl)) in - mk_branch ~lustre_eq var_x hl, + mk_branch' ~lustre_eq var_x hl, mk_branch_tr var_x spec_hl | _ -> let e = translate_expr expr in diff --git a/src/machine_code_common.ml b/src/machine_code_common.ml index 47fa5d8c..30e1a871 100644 --- a/src/machine_code_common.ml +++ b/src/machine_code_common.ml @@ -34,6 +34,7 @@ let rec pp_val m fmt v = | Access (t, i) -> fprintf fmt "%a[%a]" pp_val t pp_val i | Power (v, n) -> fprintf fmt "(%a^%a)" pp_val v pp_val n | Fun (n, vl) -> fprintf fmt "%s%a" n (pp_print_parenthesized pp_val) vl + | ResetFlag -> fprintf fmt "RESET" module PrintSpec = struct @@ -120,6 +121,7 @@ let rec pp_instr m fmt i = begin match i.instr_desc with | MLocalAssign (i,v) -> fprintf fmt "%s := %a" i.var_id pp_val v | MStateAssign (i,v) -> fprintf fmt "{%s} := %a" i.var_id pp_val v + | MResetAssign b -> fprintf fmt "RESET := %a" pp_print_bool b | MSetReset i -> fprintf fmt "set_reset %s" i | MClearReset -> fprintf fmt "clear_reset %s" m.mname.node_id | MNoReset i -> fprintf fmt "noreset %s" i @@ -312,7 +314,10 @@ let mk_branch ?lustre_eq c br = (* (And (List.map (fun (l, instrs) -> * Imply (Equal (Val c, Tag l), And (List.map get_instr_spec instrs))) * br)) *) - (MBranch (vdecl_to_val c, br)) + (MBranch (c, br)) + +let mk_branch' ?lustre_eq v = + mk_branch ?lustre_eq (vdecl_to_val v) let mk_assign ?lustre_eq x v = mkinstr ?lustre_eq diff --git a/src/machine_code_common.mli b/src/machine_code_common.mli index 0655bc63..54466603 100644 --- a/src/machine_code_common.mli +++ b/src/machine_code_common.mli @@ -12,7 +12,8 @@ val vdecl_to_val: Lustre_types.var_decl -> Machine_code_types.value_t val vdecls_to_vals: Lustre_types.var_decl list -> Machine_code_types.value_t list val id_to_tag: Lustre_types.ident -> Machine_code_types.value_t val mk_conditional: ?lustre_eq:Lustre_types.eq -> Machine_code_types.value_t -> Machine_code_types.instr_t list -> Machine_code_types.instr_t list -> Machine_code_types.instr_t -val mk_branch: ?lustre_eq:Lustre_types.eq -> Lustre_types.var_decl -> (Lustre_types.label * Machine_code_types.instr_t list) list -> Machine_code_types.instr_t +val mk_branch: ?lustre_eq:Lustre_types.eq -> Machine_code_types.value_t -> (Lustre_types.label * Machine_code_types.instr_t list) list -> Machine_code_types.instr_t +val mk_branch': ?lustre_eq:Lustre_types.eq -> Lustre_types.var_decl -> (Lustre_types.label * Machine_code_types.instr_t list) list -> Machine_code_types.instr_t val mk_assign: ?lustre_eq:Lustre_types.eq -> Lustre_types.var_decl -> Machine_code_types.value_t -> Machine_code_types.instr_t val empty_machine: Machine_code_types.machine_t val arrow_machine: Machine_code_types.machine_t diff --git a/src/machine_code_types.ml b/src/machine_code_types.ml index 7cdfc1fe..297d25ee 100644 --- a/src/machine_code_types.ml +++ b/src/machine_code_types.ml @@ -15,6 +15,7 @@ and value_t_desc = | Array of value_t list | Access of value_t * value_t | Power of value_t * value_t + | ResetFlag type mc_formula_t = value_t formula_t @@ -28,6 +29,7 @@ type instr_t = and instr_t_desc = | MLocalAssign of var_decl * value_t | MStateAssign of var_decl * value_t + | MResetAssign of bool | MClearReset | MSetReset of ident | MNoReset of ident diff --git a/src/optimize_machine.ml b/src/optimize_machine.ml index b79835ab..fee43707 100644 --- a/src/optimize_machine.ml +++ b/src/optimize_machine.ml @@ -33,6 +33,7 @@ let rec eliminate m elim instr = | MSetReset _ | MNoReset _ | MClearReset + | MResetAssign _ | MSpec _ | MComment _ -> instr | MStep (il, i, vl) -> update_instr_desc instr (MStep(il, i, List.map e_expr vl)) @@ -58,7 +59,7 @@ and eliminate_expr m elim expr = | Array(vl) -> {expr with value_desc = Array(List.map (eliminate_expr elim) vl)} | Access(v1, v2) -> { expr with value_desc = Access(eliminate_expr elim v1, eliminate_expr elim v2)} | Power(v1, v2) -> { expr with value_desc = Power(eliminate_expr elim v1, eliminate_expr elim v2)} - | Cst _ -> expr + | Cst _ | ResetFlag -> expr let eliminate_dim elim dim = Dimension.expr_replace_expr @@ -74,9 +75,13 @@ let eliminate_dim elim dim = let unfold_expr_offset m offset expr = List.fold_left - (fun res -> (function | Index i -> mk_val (Access (res, value_of_dimension m i)) - (Types.array_element_type res.value_type) - | Field _ -> Format.eprintf "internal error: not yet implemented !"; assert false)) + (fun res -> function + | Index i -> + mk_val (Access (res, value_of_dimension m i)) + (Types.array_element_type res.value_type) + | Field _ -> + Format.eprintf "internal error: not yet implemented !"; + assert false) expr offset let rec simplify_cst_expr m offset typ cst = @@ -104,6 +109,7 @@ let simplify_expr_offset m expr = | _ , Var _ -> unfold_expr_offset m offset expr | _ , Cst cst -> simplify_cst_expr m offset expr.value_type cst | _ , Access (expr, i) -> simplify (Index (dimension_of_value i) :: offset) expr + | _ , ResetFlag -> expr | [] , _ -> expr | Index _ :: q, Power (expr, _) -> simplify q expr | Index i :: q, Array vl when Dimension.is_dimension_const i @@ -120,6 +126,7 @@ let rec simplify_instr_offset m instr = | MSetReset _ | MNoReset _ | MClearReset + | MResetAssign _ | MSpec _ | MComment _ -> instr | MStep (outputs, id, inputs) -> update_instr_desc instr (MStep (outputs, id, List.map (simplify_expr_offset m) inputs)) @@ -493,7 +500,7 @@ and instrs_remove_skip instrs cont = let rec value_replace_var fvar value = match value.value_desc with - | Cst _ -> value + | Cst _ | ResetFlag -> value | Var v -> { value with value_desc = Var (fvar v) } | Fun (id, args) -> { value with value_desc = Fun (id, List.map (value_replace_var fvar) args) } | Array vl -> { value with value_desc = Array (List.map (value_replace_var fvar) vl)} @@ -507,6 +514,7 @@ let rec instr_replace_var fvar instr cont = | MSetReset _ | MNoReset _ | MClearReset + | MResetAssign _ | MSpec _ | MComment _ -> instr_cons instr cont | MStep (il, i, vl) -> instr_cons (update_instr_desc instr (MStep (List.map fvar il, i, List.map (value_replace_var fvar) vl))) cont -- GitLab