From 85a7d54a8a06126ccc362240e12db5d114b80624 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9lio=20Brun?= <lelio.brun@isae-supaero.fr> Date: Wed, 18 May 2022 16:27:17 +0200 Subject: [PATCH] ACSL ok for main loop of stateless nodes --- src/backends/C/c_backend_main.ml | 29 +++++--- src/backends/C/c_backend_main.mli | 3 + src/backends/C/c_backend_spec.ml | 115 ++++++++++++++++++++++++------ 3 files changed, 116 insertions(+), 31 deletions(-) diff --git a/src/backends/C/c_backend_main.ml b/src/backends/C/c_backend_main.ml index 876ab82f..3f78e6aa 100644 --- a/src/backends/C/c_backend_main.ml +++ b/src/backends/C/c_backend_main.ml @@ -18,19 +18,25 @@ open C_backend_common module Mpfr = Lustrec_mpfr module type MODIFIERS_MAINSRC = sig + + val pp_import_spec_prototype : formatter -> dep_t -> unit val pp_declare_ghost_state : formatter -> ident -> unit val pp_ghost_state_parameter : formatter -> unit -> unit val pp_main_spec : formatter -> unit val pp_main_loop_invariants : ident -> machine_t list -> formatter -> machine_t -> unit + val pp_main_loop_end : + ident -> machine_t list -> formatter -> machine_t -> unit end module EmptyMod = struct + let pp_import_spec_prototype _ _ = () let pp_declare_ghost_state _ _ = () let pp_ghost_state_parameter _ _ = () let pp_main_spec _ = () let pp_main_loop_invariants _ _ _ _ = () + let pp_main_loop_end _ _ _ _ = () end module Main (Mod : MODIFIERS_MAINSRC) = struct @@ -306,7 +312,7 @@ module Main (Mod : MODIFIERS_MAINSRC) = struct /* Infinite loop */@,\ %a@[<v 2>while(1){@,\ fflush(stdout);@,\ - %a%a%a%a@]@,\ + %a%a%a%a%a@]@,\ }" (Mod.pp_main_loop_invariants main_mem machines) m @@ -337,6 +343,8 @@ module Main (Mod : MODIFIERS_MAINSRC) = struct ~pp_prologue:pp_print_cut pp_put_output) (m.mname.node_outputs, m.mstep.step_outputs) + (Mod.pp_main_loop_end main_mem machines) + m let pp_usage fmt () = fprintf @@ -457,12 +465,20 @@ module Main (Mod : MODIFIERS_MAINSRC) = struct () let pp_main_c main_fmt main_machine basename _prog machines _dependencies = + let self_dep = { + local = true; + name = basename; + content = []; + is_stateful = true (* assuming it is stateful*); + } + in fprintf main_fmt "@[<v>%a@,\ #include <stdlib.h>@,\ #include <assert.h>@,\ - %a@,\ + %a\ + %a\ @,\ %a@,\ %a\n\ @@ -470,12 +486,9 @@ module Main (Mod : MODIFIERS_MAINSRC) = struct pp_main_header () pp_import_alloc_prototype - { - local = true; - name = basename; - content = []; - is_stateful = true (* assuming it is stateful*); - } + self_dep + Mod.pp_import_spec_prototype + self_dep (* Print the svn version number and the supported C standard (C90 or C99) *) pp_print_version diff --git a/src/backends/C/c_backend_main.mli b/src/backends/C/c_backend_main.mli index e8135e8d..3dc18e6b 100644 --- a/src/backends/C/c_backend_main.mli +++ b/src/backends/C/c_backend_main.mli @@ -4,12 +4,15 @@ open Lustre_types open Machine_code_types module type MODIFIERS_MAINSRC = sig + val pp_import_spec_prototype : formatter -> dep_t -> unit val pp_declare_ghost_state : formatter -> ident -> unit val pp_ghost_state_parameter : formatter -> unit -> unit val pp_main_spec : formatter -> unit val pp_main_loop_invariants : ident -> machine_t list -> formatter -> machine_t -> unit + val pp_main_loop_end : + ident -> machine_t list -> formatter -> machine_t -> unit end module EmptyMod : MODIFIERS_MAINSRC diff --git a/src/backends/C/c_backend_spec.ml b/src/backends/C/c_backend_spec.ml index fc8ae024..3c02b2bd 100644 --- a/src/backends/C/c_backend_spec.ml +++ b/src/backends/C/c_backend_spec.ml @@ -86,7 +86,6 @@ let pp_false fmt () = pp_print_string fmt "\\false" let pp_nothing fmt () = pp_print_string fmt "\\nothing" let pp_null fmt () = pp_print_string fmt "\\null" let pp_stdout fmt () = pp_print_string fmt "stdout" -let pp_at pp_v fmt (v, l) = fprintf fmt "\\at(%a, %s)" pp_v v l let find_machine f = List.find (fun m -> m.mname.node_id = f) let instances machines m = @@ -134,7 +133,7 @@ let pp_separated pp_self pp_mem pp_ptr fmt (self, mem, paths, ptrs) = pp_mem mem (pp_comma_list ~pp_prologue:pp_print_comma (fun fmt path -> - pp_indirect pp_print_string pp_instance fmt (self, path))) + pp_indirect pp_self pp_instance fmt (self, path))) paths (pp_comma_list ~pp_prologue:pp_print_comma pp_ptr) ptrs @@ -1150,7 +1149,7 @@ module HdrMod = struct "/* k-induction predicates and lemmas */" (fun fmt m -> let c, m_c = contract_of machines m in - (pp_print_option (pp_proof_annotation m m_c) fmt c))) + pp_print_option (pp_proof_annotation m m_c) fmt c)) machines let pp_machine_decl_prefix _ _ = () @@ -1563,6 +1562,9 @@ module SrcMod = struct end module MainMod = struct + + let pp_import_spec_prototype = SrcMod.pp_import_spec_prototype + let main_mem_ghost = "main_mem_ghost" let pp_declare_ghost_state fmt name = @@ -1583,31 +1585,98 @@ module MainMod = struct fmt [ main_mem_ghost, pp_ref pp_print_string ] + let k_induction_of machines m = + match contract_of machines m with + | Some c, Some m_c -> + begin match c.mc_proof with + | Some (Kinduction k) -> + Some (m_c, k) + | _ -> None + end + | _ -> None + let pp_main_loop_invariants main_mem machines fmt m = let name = m.mname.node_id in let insts = instances machines m in - pp_acsl_cut - (fun fmt () -> - fprintf - fmt - "%a@,%a@,%a@,%a" - (pp_loop_invariant pp_mem_valid') - (name, main_mem) - (pp_loop_invariant - (pp_memory_pack_aux pp_print_string pp_print_string)) - (name, main_mem_ghost, main_mem) - (pp_loop_invariant - (pp_separated - (pp_paren pp_print_string) - pp_ref' - (pp_ref pp_var_decl))) - (main_mem, main_mem_ghost, insts, m.mstep.step_outputs) - (pp_loop_invariant - (pp_or (pp_valid_read pp_stdout) (pp_equal pp_stdout pp_null))) - ((), ((), ()))) - fmt + let m_c_k = k_induction_of machines m in + fprintf fmt "%a%a" + (pp_print_option + (fun fmt _ -> + fprintf fmt "%a@," + (pp_acsl_line (pp_ghost pp_print_string)) "int __k = 0;")) + m_c_k + (pp_acsl_cut + (fun fmt () -> + fprintf + fmt + "%a@,%a@,%a@,%a%a" + (pp_loop_invariant pp_mem_valid') + (name, main_mem) + (pp_loop_invariant + (pp_memory_pack_aux pp_print_string pp_print_string)) + (name, main_mem_ghost, main_mem) + (pp_loop_invariant + (pp_separated + (pp_paren pp_print_string) + pp_ref' + (pp_ref pp_var_decl))) + (main_mem, main_mem_ghost, insts, m.mstep.step_outputs) + (pp_loop_invariant + (pp_or (pp_valid_read pp_stdout) (pp_equal pp_stdout pp_null))) + ((), ((), ())) + (pp_print_option + (fun fmt (m_c, k) -> + fprintf fmt "@,%a@,%a" + (pp_loop_invariant (pp_gequal pp_print_string pp_print_int)) + ("__k", 0) + (pp_loop_invariant + (pp_and_l (fun fmt k' -> + pp_paren + (pp_implies + ((if k' = k then pp_gequal else pp_equal) pp_print_string pp_print_int) + (fun fmt mem -> + if k' = 0 then pp_reset_set' fmt (name, mem) + else pp_k_induction_case + (k' < k) + m + m_c + pp_print_string + (pp_comma_list ~pp_open_box:(fun fmt () -> pp_open_hovbox fmt 0) (fun fmt _ -> pp_true_c_bool fmt ())) + fmt (k', mem))) + fmt + (("__k", k'), + main_mem_ghost)))) + (List.init (k + 1) Fun.id))) + m_c_k)) () + let pp_main_loop_end _main_mem machines fmt m = + fprintf fmt "@,%a" + (pp_print_option + (fun fmt (m_c, _) -> + let stateless_c = fst (get_stateless_status m_c) in + let name_c = m_c.mname.node_id in + let mem_in_c = mk_mem_in_c m in + let mem_out_c = mk_mem_out_c m in + let pp_var_c fmt (out, vd) = + if out then pp_true_c_bool fmt () + else pp_var_decl fmt vd + in + let c_inputs = List.map (fun v -> false, v) m_c.mstep.step_inputs in + let c_outputs = List.map (fun v -> true, v) m_c.mstep.step_outputs in + fprintf fmt "%a@,%a" + (pp_acsl_line (pp_ghost pp_print_string)) + "__k++;" + (pp_acsl_line' + (pp_assert + (pp_transition_aux + stateless_c + pp_print_string + pp_print_string + pp_var_c))) + (name_c, c_inputs @ c_outputs, mem_in_c, mem_out_c))) + (k_induction_of machines m) + let pp_main_spec fmt = pp_acsl_cut (fun fmt () -> -- GitLab