From 15aaf8d330b6743d0e279f9d4c2c3d2c6f78b75a Mon Sep 17 00:00:00 2001 From: Julien Signoles <julien.signoles@cea.fr> Date: Fri, 27 Sep 2019 15:11:35 +0200 Subject: [PATCH] [archi] visitor rewritten up to blocks (included) --- src/plugins/e-acsl/Makefile.in | 1 - .../e-acsl/src/analyses/mmodel_analysis.ml | 52 ++- .../e-acsl/src/analyses/mmodel_analysis.mli | 12 +- .../src/code_generator/at_with_lscope.ml | 6 +- src/plugins/e-acsl/src/code_generator/env.ml | 80 ++--- src/plugins/e-acsl/src/code_generator/env.mli | 29 +- .../src/code_generator/global_observer.ml | 36 +- .../src/code_generator/global_observer.mli | 4 +- .../e-acsl/src/code_generator/injector.ml | 278 +++++++++++++++ .../e-acsl/src/code_generator/injector.mli | 2 + .../e-acsl/src/code_generator/label.ml | 27 +- .../e-acsl/src/code_generator/label.mli | 4 +- .../src/code_generator/literal_observer.ml | 11 +- .../src/code_generator/literal_observer.mli | 4 +- .../src/code_generator/logic_functions.ml | 15 +- .../src/code_generator/logic_functions.mli | 3 +- .../e-acsl/src/code_generator/loops.ml | 37 +- .../e-acsl/src/code_generator/loops.mli | 2 +- .../src/code_generator/memory_observer.ml | 3 +- .../src/code_generator/mmodel_translate.ml | 11 + .../e-acsl/src/code_generator/quantif.ml | 7 +- .../e-acsl/src/code_generator/rational.ml | 28 +- .../e-acsl/src/code_generator/rational.mli | 23 +- .../e-acsl/src/code_generator/temporal.ml | 132 ++++--- .../e-acsl/src/code_generator/temporal.mli | 11 +- .../e-acsl/src/code_generator/translate.ml | 90 ++--- .../e-acsl/src/code_generator/visit.ml | 322 ------------------ src/plugins/e-acsl/src/main.ml | 64 ++-- 28 files changed, 607 insertions(+), 687 deletions(-) diff --git a/src/plugins/e-acsl/Makefile.in b/src/plugins/e-acsl/Makefile.in index c4f3be570ff..797036119ec 100644 --- a/src/plugins/e-acsl/Makefile.in +++ b/src/plugins/e-acsl/Makefile.in @@ -79,7 +79,6 @@ SRC_CODE_GENERATOR:= \ memory_observer \ literal_observer \ global_observer \ - visit \ injector SRC_CODE_GENERATOR:=$(addprefix src/code_generator/, $(SRC_CODE_GENERATOR)) diff --git a/src/plugins/e-acsl/src/analyses/mmodel_analysis.ml b/src/plugins/e-acsl/src/analyses/mmodel_analysis.ml index b0600493ae0..70451b51a11 100644 --- a/src/plugins/e-acsl/src/analyses/mmodel_analysis.ml +++ b/src/plugins/e-acsl/src/analyses/mmodel_analysis.ml @@ -710,11 +710,7 @@ if there are memory-related annotations.@]" Env.consolidated_mem vi end -let must_model_vi bhv ?kf ?stmt vi = - let vi = match bhv with - | None -> vi - | Some bhv -> Visitor_behavior.Get_orig.varinfo bhv vi - in +let must_model_vi ?kf ?stmt vi = let _kf = match kf, stmt with | None, None | Some _, _ -> kf | None, Some stmt -> Some (Kernel_function.find_englobing_kf stmt) @@ -743,19 +739,19 @@ consolidated_must_model_vi vi false *) -let rec apply_on_vi_base_from_lval f bhv ?kf ?stmt = function - | Var vi, _ -> f bhv ?kf ?stmt vi - | Mem e, _ -> apply_on_vi_base_from_exp f bhv ?kf ?stmt e +let rec apply_on_vi_base_from_lval f ?kf ?stmt = function + | Var vi, _ -> f ?kf ?stmt vi + | Mem e, _ -> apply_on_vi_base_from_exp f ?kf ?stmt e -and apply_on_vi_base_from_exp f bhv ?kf ?stmt e = match e.enode with +and apply_on_vi_base_from_exp f ?kf ?stmt e = match e.enode with | Lval lv | AddrOf lv | StartOf lv -> - apply_on_vi_base_from_lval f bhv ?kf ?stmt lv + apply_on_vi_base_from_lval f ?kf ?stmt lv | BinOp((PlusPI | IndexPI | MinusPI), e1, _, _) -> - apply_on_vi_base_from_exp f bhv ?kf ?stmt e1 + apply_on_vi_base_from_exp f ?kf ?stmt e1 | BinOp(MinusPP, e1, e2, _) -> - apply_on_vi_base_from_exp f bhv ?kf ?stmt e1 - || apply_on_vi_base_from_exp f bhv ?kf ?stmt e2 - | Info(e, _) | CastE(_, e) -> apply_on_vi_base_from_exp f bhv ?kf ?stmt e + apply_on_vi_base_from_exp f ?kf ?stmt e1 + || apply_on_vi_base_from_exp f ?kf ?stmt e2 + | Info(e, _) | CastE(_, e) -> apply_on_vi_base_from_exp f ?kf ?stmt e | BinOp((PlusA | MinusA | Mult | Div | Mod |Shiftlt | Shiftrt | Lt | Gt | Le | Ge | Eq | Ne | BAnd | BXor | BOr | LAnd | LOr), _, _, _) | Const _ -> (* possible in case of static address *) false @@ -765,18 +761,16 @@ and apply_on_vi_base_from_exp f bhv ?kf ?stmt e = match e.enode with let must_model_lval = apply_on_vi_base_from_lval must_model_vi let must_model_exp = apply_on_vi_base_from_exp must_model_vi -let must_never_monitor_lval bhv ?kf ?stmt lv = +let must_never_monitor_lval ?kf ?stmt lv = apply_on_vi_base_from_lval - (fun _bhv ?kf:_ ?stmt:_ vi -> must_never_monitor vi) - bhv + (fun ?kf:_ ?stmt:_ vi -> must_never_monitor vi) ?kf ?stmt lv -let must_never_monitor_exp bhv ?kf ?stmt lv = +let must_never_monitor_exp ?kf ?stmt lv = apply_on_vi_base_from_exp - (fun _bhv ?kf:_ ?stmt:_ vi -> must_never_monitor vi) - bhv + (fun ?kf:_ ?stmt:_ vi -> must_never_monitor vi) ?kf ?stmt lv @@ -785,23 +779,23 @@ let must_never_monitor_exp bhv ?kf ?stmt lv = (** {1 Public API} *) (* ************************************************************************** *) -let must_model_vi ?bhv ?kf ?stmt vi = +let must_model_vi ?kf ?stmt vi = not (must_never_monitor vi) && (Options.Full_mmodel.get () - || Error.generic_handle (must_model_vi bhv ?kf ?stmt) false vi) + || Error.generic_handle (must_model_vi ?kf ?stmt) false vi) -let must_model_lval ?bhv ?kf ?stmt lv = - not (must_never_monitor_lval bhv ?kf ?stmt lv) +let must_model_lval ?kf ?stmt lv = + not (must_never_monitor_lval ?kf ?stmt lv) && (Options.Full_mmodel.get () - || Error.generic_handle (must_model_lval bhv ?kf ?stmt) false lv) + || Error.generic_handle (must_model_lval ?kf ?stmt) false lv) -let must_model_exp ?bhv ?kf ?stmt exp = - not (must_never_monitor_exp bhv ?kf ?stmt exp) +let must_model_exp ?kf ?stmt exp = + not (must_never_monitor_exp ?kf ?stmt exp) && (Options.Full_mmodel.get () - || Error.generic_handle (must_model_exp bhv ?kf ?stmt) false exp) + || Error.generic_handle (must_model_exp ?kf ?stmt) false exp) let use_model () = not (Env.is_empty ()) @@ -810,6 +804,6 @@ let use_model () = (* Local Variables: -compile-command: "make" +compile-command: "make -C ../.." End: *) diff --git a/src/plugins/e-acsl/src/analyses/mmodel_analysis.mli b/src/plugins/e-acsl/src/analyses/mmodel_analysis.mli index f091021b51c..bf50f714e48 100644 --- a/src/plugins/e-acsl/src/analyses/mmodel_analysis.mli +++ b/src/plugins/e-acsl/src/analyses/mmodel_analysis.mli @@ -31,19 +31,15 @@ val reset: unit -> unit val use_model: unit -> bool (** Is one variable monitored (at least)? *) -val must_model_vi: ?bhv:Visitor_behavior.t -> ?kf:kernel_function - -> ?stmt:stmt -> varinfo -> bool +val must_model_vi: ?kf:kernel_function -> ?stmt:stmt -> varinfo -> bool (** [must_model_vi ?kf ?stmt vi] returns [true] if the varinfo [vi] at the given [stmt] in the given function [kf] must be tracked by the memory model - library. If behavior [bhv] is specified then assume that [vi] is part - of the new project generated by the given copy behavior [bhv] *) + library. *) -val must_model_lval: ?bhv:Visitor_behavior.t -> ?kf:kernel_function - -> ?stmt:stmt -> lval -> bool +val must_model_lval: ?kf:kernel_function -> ?stmt:stmt -> lval -> bool (** Same as {!must_model_vi}, for left-values *) -val must_model_exp: ?bhv:Visitor_behavior.t -> ?kf:kernel_function - -> ?stmt:stmt -> exp -> bool +val must_model_exp: ?kf:kernel_function -> ?stmt:stmt -> exp -> bool (** Same as {!must_model_vi}, for expressions *) (* diff --git a/src/plugins/e-acsl/src/code_generator/at_with_lscope.ml b/src/plugins/e-acsl/src/code_generator/at_with_lscope.ml index 93075f36f5b..c9b710bc924 100644 --- a/src/plugins/e-acsl/src/code_generator/at_with_lscope.ml +++ b/src/plugins/e-acsl/src/code_generator/at_with_lscope.ml @@ -204,7 +204,7 @@ let index_from_sizes_and_shifts ~loc sizes_and_shifts = sum let put_block_at_label env block label = - let stmt = Label.get_stmt (Env.get_visitor env) label in + let stmt = Label.get_stmt label in let env_ref = ref env in let o = object inherit Visitor.frama_c_inplace @@ -214,8 +214,7 @@ let put_block_at_label env block label = Cil.ChangeTo stmt end in - let bhv = Env.get_behavior env in - ignore(Visitor.visitFramacStmt o (Visitor_behavior.Get.stmt bhv stmt)); + ignore (Visitor.visitFramacStmt o stmt); !env_ref let to_exp ~loc kf env pot label = @@ -244,6 +243,7 @@ let to_exp ~loc kf env pot label = ~name:"at" ~scope:Varname.Function env + kf None ty_ptr (fun vi e -> diff --git a/src/plugins/e-acsl/src/code_generator/env.ml b/src/plugins/e-acsl/src/code_generator/env.ml index ca90454b2a7..b6c1f7742c8 100644 --- a/src/plugins/e-acsl/src/code_generator/env.ml +++ b/src/plugins/e-acsl/src/code_generator/env.ml @@ -54,7 +54,6 @@ type local_env = { } type t = { - visitor: Visitor.frama_c_visitor; lscope: Lscope.t; lscope_reset: bool; annotation_kind: Misc.annotation_kind; @@ -86,21 +85,8 @@ let empty_local_env = mp_tbl = empty_mp_tbl; rte = true } -let dummy = - { visitor = new Visitor.generic_frama_c_visitor (Visitor_behavior.inplace ()); - lscope = Lscope.empty; - lscope_reset = true; - annotation_kind = Misc.Assertion; - new_global_vars = []; - global_mp_tbl = empty_mp_tbl; - env_stack = []; - var_mapping = Logic_var.Map.empty; - loop_invariants = []; - cpt = 0; } - -let empty v = - { visitor = v; - lscope = Lscope.empty; +let empty = + { lscope = Lscope.empty; lscope_reset = true; annotation_kind = Misc.Assertion; new_global_vars = []; @@ -118,19 +104,6 @@ let has_no_new_stmt env = let local, _ = top env in local.block_info = empty_block -let current_kf env = - let v = env.visitor in - match v#current_kf with - | None -> None - | Some kf -> Some (Visitor_behavior.Get.kernel_function v#behavior kf) - -let set_current_kf env kf = - let v = env.visitor in - v#set_current_kf kf - -let get_visitor env = env.visitor -let get_behavior env = env.visitor#behavior - (* ************************************************************************** *) (** {2 Loop invariants} *) (* ************************************************************************** *) @@ -163,7 +136,7 @@ let generate_rte env = (* eta-expansion required for typing generalisation *) let acc_list_rev acc l = List.fold_left (fun acc x -> x :: acc) acc l -let do_new_var ~loc ?(scope=Varname.Block) ?(name="") env t ty mk_stmts = +let do_new_var ~loc ?(scope=Varname.Block) ?(name="") env kf t ty mk_stmts = let local_env, tl_env = top env in let local_block = local_env.block_info in let is_z_t = Gmp_types.Z.is_t ty in @@ -183,8 +156,8 @@ let do_new_var ~loc ?(scope=Varname.Block) ?(name="") env t ty mk_stmts = v.vreferenced <- true; let lscope = match scope with | Varname.Global -> LGlobal - | Varname.Function -> LFunction (Extlib.the (current_kf env)) - | Varname.Block -> LLocal_block (Extlib.the (current_kf env)) + | Varname.Function -> LFunction kf + | Varname.Block -> LLocal_block kf in (* Options.feedback "new variable %a (global? %b)" Varinfo.pretty v global;*) let e = Cil.evar v in @@ -246,7 +219,7 @@ let do_new_var ~loc ?(scope=Varname.Block) ?(name="") env t ty mk_stmts = exception No_term -let new_var ~loc ?(scope=Varname.Block) ?name env t ty mk_stmts = +let new_var ~loc ?(scope=Varname.Block) ?name env kf t ty mk_stmts = let local_env, _ = top env in let memo tbl = try @@ -256,18 +229,19 @@ let new_var ~loc ?(scope=Varname.Block) ?name env t ty mk_stmts = let v, e = Term.Map.find t tbl.new_exps in if Typ.equal ty v.vtype then v, e, env else raise No_term with Not_found | No_term -> - do_new_var ~loc ~scope ?name env t ty mk_stmts + do_new_var ~loc ~scope ?name env kf t ty mk_stmts in match scope with | Varname.Global | Varname.Function -> memo env.global_mp_tbl | Varname.Block -> memo local_env.mp_tbl -let new_var_and_mpz_init ~loc ?scope ?name env t mk_stmts = +let new_var_and_mpz_init ~loc ?scope ?name env kf t mk_stmts = new_var ~loc ?scope ?name env + kf t (Gmp_types.Z.t ()) (fun v e -> Gmp.init ~loc e :: mk_stmts v e) @@ -285,7 +259,7 @@ module Logic_binding = struct let var_mapping = Logic_var.Map.add logic_v varinfos env.var_mapping in { env with var_mapping = var_mapping } - let add ?ty env logic_v = + let add ?ty env kf logic_v = let ty = match ty with | Some ty -> ty | None -> match logic_v.lv_type with @@ -303,6 +277,7 @@ module Logic_binding = struct new_var ~loc:Location.unknown env + kf ~name:logic_v.lv_name None ty @@ -336,23 +311,27 @@ module Logic_scope = struct else env end -let emitter = +let _emitter = (* [TODO ARCHI] *) Emitter.create "E_ACSL" [ Emitter.Code_annot ] ~correctness:[ Options.Gmp_only.parameter ] ~tuning:[] -let add_assert env stmt annot = match current_kf env with +(* [TODO ARCHI] to be reimplemented *) +let add_assert _env _stmt _annot = assert false +(*match current_kf env with | None -> assert false - | Some kf -> - Queue.add + | Some _kf -> +(* Queue.add (fun () -> Annotations.add_assert emitter ~kf stmt annot) env.visitor#get_filling_actions + *)*) + -let add_stmt ?(post=false) ?before env stmt = +let add_stmt ?(post=false) ?before env kf stmt = if not post then - Extlib.may (fun old -> E_acsl_label.move env.visitor ~old stmt) before; + Extlib.may (fun old -> E_acsl_label.move kf ~old stmt) before; let local_env, tl = top env in let block = local_env.block_info in let block = @@ -491,15 +470,16 @@ module Context = struct if !ctx <> [] then begin let vars = env.new_global_vars in let env = - { env with new_global_vars = - List.filter + { env with + new_global_vars = + List.filter (fun (v, scope) -> - (match scope with - | LGlobal | LFunction _ -> true - | LLocal_block _ -> false) - && List.for_all (fun (v', _) -> v != v') vars) - !ctx - @ vars } + (match scope with + | LGlobal | LFunction _ -> true + | LLocal_block _kf -> false) + && List.for_all (fun (v', _) -> v != v') vars) + !ctx + @ vars } in ctx := []; env diff --git a/src/plugins/e-acsl/src/code_generator/env.mli b/src/plugins/e-acsl/src/code_generator/env.mli index 8789e0f8d18..bfc4a75da8c 100644 --- a/src/plugins/e-acsl/src/code_generator/env.mli +++ b/src/plugins/e-acsl/src/code_generator/env.mli @@ -22,15 +22,14 @@ open Cil_types -(** Environments. +(** Environments. Environments handle all the new C constructs (variables, statements and - annotations. *) + annotations. *) type t -val dummy: t -val empty: Visitor.frama_c_visitor -> t +val empty: t val has_no_new_stmt: t -> bool (** Assume that a local context has been previously pushed. @@ -43,8 +42,8 @@ type localized_scope = val new_var: loc:location -> ?scope:Varname.scope -> ?name:string -> - t -> term option -> typ -> - (varinfo -> exp (* the var as exp *) -> stmt list) -> + t -> kernel_function -> term option -> typ -> + (varinfo -> exp (* the var as exp *) -> stmt list) -> varinfo * exp * t (** [new_var env t ty mk_stmts] extends [env] with a fresh variable of type [ty] corresponding to [t]. [scope] is the scope of the new variable (default @@ -54,14 +53,14 @@ val new_var: val new_var_and_mpz_init: loc:location -> ?scope:Varname.scope -> ?name:string -> - t -> term option -> - (varinfo -> exp (* the var as exp *) -> stmt list) -> + t -> kernel_function -> term option -> + (varinfo -> exp (* the var as exp *) -> stmt list) -> varinfo * exp * t -(** Same as [new_var], but dedicated to mpz_t variables initialized by +(** Same as [new_var], but dedicated to mpz_t variables initialized by {!Mpz.init}. *) module Logic_binding: sig - val add: ?ty:typ -> t -> logic_var -> varinfo * exp * t + val add: ?ty:typ -> t -> kernel_function -> logic_var -> varinfo * exp * t (* Add a new C binding to the list of bindings for the logic variable. *) val add_binding: t -> logic_var -> varinfo -> t @@ -80,7 +79,7 @@ val add_assert: t -> stmt -> predicate -> unit (** [add_assert env s p] associates the assertion [p] to the statement [s] in the environment [env]. *) -val add_stmt: ?post:bool -> ?before:stmt -> t -> stmt -> t +val add_stmt: ?post:bool -> ?before:stmt -> t -> kernel_function -> stmt -> t (** [add_stmt env s] extends [env] with the new statement [s]. [before] may define which stmt the new one is included before. This is to say that any labels attached to [before] are moved to [stmt]. [post] @@ -115,11 +114,6 @@ val transfer: from:t -> t -> t val get_generated_variables: t -> (varinfo * localized_scope) list (** All the new variables local to the visited function. *) -val get_visitor: t -> Visitor.generic_frama_c_visitor -val get_behavior: t -> Visitor_behavior.t -val current_kf: t -> kernel_function option -(** Kernel function currently visited in the new project. *) - module Logic_scope: sig val get: t -> Lscope.t (** Return the logic scope associated to the environment. *) @@ -141,9 +135,6 @@ module Logic_scope: sig reset at next call to [reset]. *) end -val set_current_kf: t -> kernel_function -> unit -(* Set current kf of the environment *) - (* ************************************************************************** *) (** {2 Current annotation kind} *) (* ************************************************************************** *) diff --git a/src/plugins/e-acsl/src/code_generator/global_observer.ml b/src/plugins/e-acsl/src/code_generator/global_observer.ml index 4fffa4ab20a..d4ad9545a64 100644 --- a/src/plugins/e-acsl/src/code_generator/global_observer.ml +++ b/src/plugins/e-acsl/src/code_generator/global_observer.ml @@ -38,6 +38,9 @@ let reset () = Varinfo.Hashtbl.reset tbl let is_empty () = Varinfo.Hashtbl.length tbl = 0 +(* Make a unique mapping for each global variable omitting initializers. + Initializers (used to capture literal strings) are added through + [add_initializer] below. *) let add vi = if Mmodel_analysis.must_model_vi vi then Varinfo.Hashtbl.replace tbl vi (ref []) @@ -50,12 +53,12 @@ let add_initializer vi offset init = with Not_found -> assert false -let rec literal_in_initializer env = function - | SingleInit exp -> snd (Literal_observer.exp_in_depth env exp) +let rec literal_in_initializer env kf = function + | SingleInit exp -> snd (Literal_observer.exp_in_depth env kf exp) | CompoundInit (_, l) -> - List.fold_left (fun env (_, i) -> literal_in_initializer env i) env l + List.fold_left (fun env (_, i) -> literal_in_initializer env kf i) env l -let mk_init bhv env = +let mk_init_function env = (* Create [__e_acsl_globals_init] function with definition for initialization of global variables *) let vi = @@ -82,9 +85,7 @@ let mk_init bhv env = let fct = Definition(fundec, Location.unknown) in (* Create and register [__e_acsl_globals_init] as kernel function *) - let kf = - { fundec = fct; spec = spec } - in + let kf = { fundec = fct; spec = spec } in Globals.Functions.register kf; Globals.Functions.replace_by_definition spec fundec Location.unknown; (* Now generate the statements. The generation is done only now because it @@ -95,12 +96,11 @@ let mk_init bhv env = after generating observers of **all** globals *) let env, stmts = Varinfo.Hashtbl.fold_sorted - (fun old_vi l stmts -> - let new_vi = Visitor_behavior.Get.varinfo bhv old_vi in + (fun vi l stmts -> List.fold_left (fun (env, stmts) (off, init) -> - let env = literal_in_initializer env init in - let stmt = Temporal.generate_global_init new_vi off init env in + let env = literal_in_initializer env kf init in + let stmt = Temporal.generate_global_init vi off init in env, match stmt with None -> stmts | Some stmt -> stmt :: stmts) stmts !l) @@ -110,11 +110,10 @@ let mk_init bhv env = (* allocation and initialization of globals *) let stmts = Varinfo.Hashtbl.fold_sorted - (fun old_vi _ stmts -> - let new_vi = Visitor_behavior.Get.varinfo bhv old_vi in + (fun vi _ stmts -> (* a global is both allocated and initialized *) - Misc.mk_store_stmt new_vi - :: Misc.mk_initialize ~loc:Location.unknown (Cil.var new_vi) + Misc.mk_store_stmt vi + :: Misc.mk_initialize ~loc:Location.unknown (Cil.var vi) :: stmts) tbl stmts @@ -171,11 +170,10 @@ let mk_init bhv env = blk.bstmts <- stmts; vi, fundec, env -let mk_delete bhv stmts = +let mk_delete_stmts stmts = Varinfo.Hashtbl.fold_sorted - (fun old_vi _l acc -> - let new_vi = Visitor_behavior.Get.varinfo bhv old_vi in - Misc.mk_delete_stmt new_vi :: acc) + (fun vi _l acc -> + Misc.mk_delete_stmt vi :: acc) tbl stmts diff --git a/src/plugins/e-acsl/src/code_generator/global_observer.mli b/src/plugins/e-acsl/src/code_generator/global_observer.mli index 6b1ce04936a..e0098a5ae8a 100644 --- a/src/plugins/e-acsl/src/code_generator/global_observer.mli +++ b/src/plugins/e-acsl/src/code_generator/global_observer.mli @@ -36,11 +36,11 @@ val add: varinfo -> unit val add_initializer: varinfo -> offset -> init -> unit (** add the initializer for the given observed variable *) -val mk_init: Visitor_behavior.t -> Env.t -> varinfo * fundec * Env.t +val mk_init_function: Env.t -> varinfo * fundec * Env.t (** generates a new C function containing the observers for global variable declaration and initialization *) -val mk_delete: Visitor_behavior.t -> stmt list -> stmt list +val mk_delete_stmts: stmt list -> stmt list (** generates the observers for global variable de-allocation *) (* diff --git a/src/plugins/e-acsl/src/code_generator/injector.ml b/src/plugins/e-acsl/src/code_generator/injector.ml index 6cc68db52cf..ef8f10fbf54 100644 --- a/src/plugins/e-acsl/src/code_generator/injector.ml +++ b/src/plugins/e-acsl/src/code_generator/injector.ml @@ -20,6 +20,284 @@ (* *) (**************************************************************************) +open Cil_types +open Cil_datatype + +let dkey = Options.dkey_translation + +let is_main kf = + try + let main, _ = Globals.entry_point () in + Kernel_function.equal kf main + with Globals.No_such_entry_point _s -> + false + +(* ************************************************************************** *) +(* Code *) +(* ************************************************************************** *) + +let inject_in_block _env _main kf blk = + (* [TODO ARCHI] HERE recursive call *) + let free_stmts = At_with_lscope.Free.find_all kf in + match blk.blocals, free_stmts with + | [], [] -> + () + | [], _ :: _ | _ :: _, [] | _ :: _, _ :: _ -> + let add_locals stmts = + if Functions.instrument kf then + List.fold_left + (fun acc vi -> + if Mmodel_analysis.must_model_vi ~kf vi then + Misc.mk_delete_stmt vi :: acc + else + acc) + stmts + blk.blocals + else + stmts + in + let rec insert_in_innermost_last_block blk = function + | { skind = Return _ } as ret :: ((potential_clean :: tl) as l) -> + (* keep the return (enclosed in a generated block) at the end; + preceded by clean if any *) + let init, tl = + if is_main kf && Mmodel_analysis.use_model () then + free_stmts @ [ potential_clean; ret ], tl + else + free_stmts @ [ ret ], l + in + (* now that [free] stmts for [kf] have been inserted, + there is no more need to keep the corresponding entries in the + table managing them. *) + At_with_lscope.Free.remove_all kf; + blk.bstmts <- + List.fold_left (fun acc v -> v :: acc) (add_locals init) tl + | { skind = Block b } :: _ -> + insert_in_innermost_last_block b (List.rev b.bstmts) + | l -> + blk.bstmts <- List.fold_left (fun acc v -> v :: acc) (add_locals []) l + in + insert_in_innermost_last_block blk (List.rev blk.bstmts); + if Functions.instrument kf then + blk.bstmts <- + List.fold_left + (fun acc vi -> + if Mmodel_analysis.must_model_vi vi && not vi.vdefined + then Misc.mk_store_stmt vi :: acc + else acc) + blk.bstmts + blk.blocals + +(* ************************************************************************** *) +(* Function definition *) +(* ************************************************************************** *) + +let add_generated_variables_in_function env fundec = + let vars = Env.get_generated_variables env in + let locals, blocks = + List.fold_left + (fun (local_vars, block_vars as acc) (v, scope) -> match scope with + (* TODO: [kf] assumed to be consistent. Should be asserted. *) + (* TODO: actually, is the kf as constructor parameter useful? *) + | Env.LFunction _kf -> v :: local_vars, v :: block_vars + | Env.LLocal_block _kf -> v :: local_vars, block_vars + | _ -> acc) + (fundec.slocals, fundec.sbody.blocals) + vars + in + fundec.slocals <- locals; + fundec.sbody.blocals <- blocks + +(* Memory management for \at on purely logic variables: put [malloc] stmts at + proper locations *) +let add_malloc_and_free_stmts kf fundec = + let malloc_stmts = At_with_lscope.Malloc.find_all kf in + let fstmts = malloc_stmts @ fundec.sbody.bstmts in + fundec.sbody.bstmts <- fstmts; + (* now that [malloc] stmts for [kf] have been inserted, there is no more need + to keep the corresponding entries in the table managing them. *) + At_with_lscope.Malloc.remove_all kf + +let inject_in_fundec env main fundec = + let vi = fundec.svar in + let kf = try Globals.Functions.get vi with Not_found -> assert false in + (* convert ghost variables *) + vi.vghost <- false; + List.iter (fun vi -> vi.vghost <- false) fundec.slocals; + (* update environments *) + Builtins.update vi.vname vi; + if is_main kf then Global_observer.add vi; + (* exit point computations *) + if Functions.instrument kf then Exit_points.generate fundec; + Options.feedback ~dkey ~level:2 "entering in function %a." + Kernel_function.pretty kf; + (* recursive visit *) + inject_in_block env main kf fundec.sbody; + Exit_points.clear (); + add_generated_variables_in_function env fundec; + add_malloc_and_free_stmts kf fundec; + (* setting main if necessary *) + let main = if is_main kf then Some fundec else main in + Options.feedback ~dkey ~level:2 "function %a done." + Kernel_function.pretty kf; + env, main + +(* ************************************************************************** *) +(* The whole AST *) +(* ************************************************************************** *) + +let inject_in_global (env, main) = function + (* library functions and built-ins *) + | GVarDecl(vi, _) | GVar(vi, _, _) + | GFunDecl(_, vi, _) | GFun({ svar = vi }, _) + when Misc.is_library_loc vi.vdecl || Builtins.mem vi.vname -> + Misc.register_library_function vi; + if Builtins.mem vi.vname then Builtins.update vi.vname vi; + env, main + + (* Cil built-ins and other library globals: nothing to do *) + | GVarDecl(vi, _) | GVar(vi, _, _) | GFun({ svar = vi }, _) + when Cil.is_builtin vi -> + env, main + | g when Misc.is_library_loc (Global.loc g) -> + env, main + + (* variables and functions declarations *) + | GVarDecl(vi, _) | GFunDecl(_, vi, _) -> + (* do not convert extern ghost variables, because they can't be linked, + see bts #1392 *) + if vi.vstorage <> Extern then vi.vghost <- false; + env, main + + (* variable definition *) + | GVar(vi, _initinfo, _) -> + vi.vghost <- false; + (* [TODO ARCHI] init_info *) + env, main + + (* function definition *) + | GFun(fundec, _) -> + inject_in_fundec env main fundec + + (* other globals: nothing to do *) + | GType _ + | GCompTag _ + | GCompTagDecl _ + | GEnumTag _ + | GEnumTagDecl _ + | GAsm _ + | GPragma _ + | GText _ + | GAnnot _ (* do never read annotation from sources *) + -> + env, main + +(* TODO: what about using [file.globalinit]? *) +let inject_global_initializer env file main = + Options.feedback ~dkey ~level:2 "building global initializer."; + (* [TODO ARCHI] is env really useless? *) + let vi, fundec, _env = Global_observer.mk_init_function env in + let cil_fct = GFun(fundec, Location.unknown) in + if Mmodel_analysis.use_model () then begin + match main with + | Some main -> + let exp = Cil.evar ~loc:Location.unknown vi in + (* Create [__e_acsl_globals_init();] call *) + let stmt = + Cil.mkStmtOneInstr ~valid_sid:true + (Call(None, exp, [], Location.unknown)) + in + vi.vreferenced <- true; + (* insert [__e_acsl_globals_init ();] as first statement of + [main] *) + main.sbody.bstmts <- stmt :: main.sbody.bstmts; + let new_globals = + List.fold_right + (fun g acc -> match g with + | GFun({ svar = vi }, _) + when Varinfo.equal vi main.svar -> + acc + | _ -> g :: acc) + file.globals + [ cil_fct; GFun(main, Location.unknown) ] + in + (* add the literal string varinfos as the very first + globals *) + let new_globals = + Literal_strings.fold + (fun _ vi l -> + GVar(vi, { init = None }, Location.unknown) :: l) + new_globals + in + file.globals <- new_globals + | None -> + Kernel.warning "@[no entry point specified:@ \ + you must call function `%s' and `__e_acsl_memory_clean by yourself.@]" + Global_observer.function_name; + file.globals <- file.globals @ [ cil_fct ] + end + +(* Add a call to [__e_acsl_memory_init] that initializes memory storage and + potentially records program arguments. Parameters to [__e_acsl_memory_init] + are addresses of program arguments or NULLs if [main] is declared without + arguments. *) +let inject_mmodel_initializer main = + let loc = Location.unknown in + let nulls = [ Cil.zero loc ; Cil.zero loc ] in + let handle_main main = + let args = + (* record arguments only if the second has a pointer type, so a argument + strings can be recorded. This is sufficient to capture C99 compliant + arguments and GCC extensions with environ. *) + match main.sformals with + | [] -> + (* no arguments to main given *) + nulls + | _argc :: argv :: _ when Cil.isPointerType argv.vtype -> + (* grab addresses of arguments for a call to the main initialization + function, i.e., [__e_acsl_memory_init] *) + List.map Cil.mkAddrOfVi main.sformals; + | _ :: _ -> + (* some non-standard arguments. *) + nulls + in + let ptr_size = Cil.sizeOf loc Cil.voidPtrType in + let args = args @ [ ptr_size ] in + let name = Functions.RTL.mk_api_name "memory_init" in + let init = Misc.mk_call loc name args in + main.sbody.bstmts <- init :: main.sbody.bstmts + in + Extlib.may handle_main main + +let inject_in_file file = + let env, main = + List.fold_left inject_in_global (Env.empty, None) file.globals + in + (* post-treatment *) + (* extend [main] with forward initialization and put it at end *) + if not (Global_observer.is_empty () && Literal_strings.is_empty ()) then + inject_global_initializer env file main; + file.globals <- Logic_functions.add_generated_functions file.globals; + inject_mmodel_initializer main + +let reset_all () = + Misc.reset (); + Logic_functions.reset (); + Literal_strings.reset (); + Global_observer.reset (); + Keep_status.before_translation () + +let inject () = + Options.feedback ~level:2 + "injecting annotations as code in project %a" + Project.pretty (Project.current ()); + reset_all (); + Misc.reorder_ast (); + let ast = Ast.get () in + inject_in_file ast; + (* [TODO ARCHI] not consistent with the [reset_all] strategy: *) + Typing.clear () + (* Local Variables: compile-command: "make -C ../.." diff --git a/src/plugins/e-acsl/src/code_generator/injector.mli b/src/plugins/e-acsl/src/code_generator/injector.mli index 6cc68db52cf..6c382503b25 100644 --- a/src/plugins/e-acsl/src/code_generator/injector.mli +++ b/src/plugins/e-acsl/src/code_generator/injector.mli @@ -20,6 +20,8 @@ (* *) (**************************************************************************) +val inject: unit -> unit + (* Local Variables: compile-command: "make -C ../.." diff --git a/src/plugins/e-acsl/src/code_generator/label.ml b/src/plugins/e-acsl/src/code_generator/label.ml index 4a2b857694e..f6638213b5a 100644 --- a/src/plugins/e-acsl/src/code_generator/label.ml +++ b/src/plugins/e-acsl/src/code_generator/label.ml @@ -37,14 +37,13 @@ let self = Labeled_stmts.self let new_labeled_stmt stmt = try Labeled_stmts.find stmt with Not_found -> stmt -let move (vis:Visitor.generic_frama_c_visitor) ~old new_stmt = +let move kf ~old new_stmt = let labels = old.labels in match labels with | [] -> () | _ :: _ -> old.labels <- []; new_stmt.labels <- labels @ new_stmt.labels; - let old = Visitor_behavior.Get_orig.stmt vis#behavior old in Labeled_stmts.add old new_stmt; (* update the gotos of the function jumping to one of the labels *) let o orig_stmt = object @@ -63,28 +62,30 @@ let move (vis:Visitor.generic_frama_c_visitor) ~old new_stmt = method !vexpr _ = Cil.SkipChildren method !vlval _ = Cil.SkipChildren end in - let f = Extlib.the vis#current_func in - let mv_labels s = - ignore (Visitor.visitFramacStmt (o s) (Visitor_behavior.Memo.stmt vis#behavior s)) + let mv_labels s = ignore (Visitor.visitFramacStmt (o s) s) in + let f = + try Kernel_function.get_definition kf + with Kernel_function.No_Definition -> assert false in List.iter mv_labels f.sallstmts -let get_stmt vis = function +(* [TODO ARCHI] reimplement it *) +let get_stmt = function | StmtLabel { contents = stmt } -> stmt | BuiltinLabel Here -> - (match vis#current_stmt with +(* (match vis#current_stmt with | None -> Error.not_yet "label \"Here\" in function contract" - | Some s -> s) + | Some s -> s)*) assert false | BuiltinLabel(Old | Pre) -> - (try Kernel_function.find_first_stmt (Extlib.the vis#current_kf) - with Kernel_function.No_Statement -> assert false) +(* (try Kernel_function.find_first_stmt (Extlib.the vis#current_kf) + with Kernel_function.No_Statement -> assert false)*)assert false | BuiltinLabel(Post) -> - (try Kernel_function.find_return (Extlib.the vis#current_kf) - with Kernel_function.No_Statement -> assert false) +(* (try Kernel_function.find_return (Extlib.the vis#current_kf) + with Kernel_function.No_Statement -> assert false)*) assert false | BuiltinLabel _ | FormalLabel _ -> assert false (* Local Variables: -compile-command: "make" +compile-command: "make -C ../.." End: *) diff --git a/src/plugins/e-acsl/src/code_generator/label.mli b/src/plugins/e-acsl/src/code_generator/label.mli index 994d7831f94..194e2d2589e 100644 --- a/src/plugins/e-acsl/src/code_generator/label.mli +++ b/src/plugins/e-acsl/src/code_generator/label.mli @@ -22,11 +22,11 @@ open Cil_types -val move: Visitor.generic_frama_c_visitor -> old:stmt -> stmt -> unit +val move: kernel_function -> old:stmt -> stmt -> unit (** Move all labels of the [old] stmt onto the new [stmt]. Both stmts must be in the new project. *) -val get_stmt: Visitor.generic_frama_c_visitor -> logic_label -> stmt +val get_stmt: logic_label -> stmt (** @return the statement where the logic label points to. *) val new_labeled_stmt: stmt -> stmt diff --git a/src/plugins/e-acsl/src/code_generator/literal_observer.ml b/src/plugins/e-acsl/src/code_generator/literal_observer.ml index 2be3b192a55..147f9baa6d9 100644 --- a/src/plugins/e-acsl/src/code_generator/literal_observer.ml +++ b/src/plugins/e-acsl/src/code_generator/literal_observer.ml @@ -22,7 +22,7 @@ open Cil_types -let literal loc env s = +let literal loc env kf s = try let vi = Literal_strings.find s in (* if the literal string was already created, just get it. *) @@ -35,6 +35,7 @@ let literal loc env s = ~scope:Varname.Global ~name:"literal_string" env + kf None Cil.charPtrType (fun _ _ -> [] (* done in the initializer, see {!vglob_aux} *)) @@ -42,14 +43,14 @@ let literal loc env s = Literal_strings.add s vi; exp, env -let exp env e = match e.enode with +let exp env kf e = match e.enode with (* the guard below could be optimized: if no annotation **depends on this string**, then it is not required to monitor it. (currently, the guard says: "no annotation uses the memory model" *) - | Const (CStr s) when Mmodel_analysis.use_model () -> literal e.eloc env s + | Const (CStr s) when Mmodel_analysis.use_model () -> literal e.eloc env kf s | _ -> e, env -let exp_in_depth env e = +let exp_in_depth env kf e = let env_ref = ref env in let o = object inherit Cil.genericCilVisitor (Visitor_behavior.copy (Project.current ())) @@ -58,7 +59,7 @@ let exp_in_depth env e = string**, then it is not required to monitor it. (currently, the guard says: "no annotation uses the memory model" *) | Const (CStr s) when Mmodel_analysis.use_model () -> - let e, env = literal e.eloc !env_ref s in + let e, env = literal e.eloc !env_ref kf s in env_ref := env; Cil.ChangeTo e | _ -> diff --git a/src/plugins/e-acsl/src/code_generator/literal_observer.mli b/src/plugins/e-acsl/src/code_generator/literal_observer.mli index f5cea67adfe..a196bf1d0d9 100644 --- a/src/plugins/e-acsl/src/code_generator/literal_observer.mli +++ b/src/plugins/e-acsl/src/code_generator/literal_observer.mli @@ -24,10 +24,10 @@ open Cil_types -val exp: Env.t -> exp -> exp * Env.t +val exp: Env.t -> kernel_function -> exp -> exp * Env.t (** replace the given exp by an observed variable if it is a literal string *) -val exp_in_depth: Env.t -> exp -> exp * Env.t +val exp_in_depth: Env.t -> kernel_function -> exp -> exp * Env.t (** replace any sub-expression of the given exp that is a literal string by an observed variable *) diff --git a/src/plugins/e-acsl/src/code_generator/logic_functions.ml b/src/plugins/e-acsl/src/code_generator/logic_functions.ml index 41bf5a276e0..8ac2421c992 100644 --- a/src/plugins/e-acsl/src/code_generator/logic_functions.ml +++ b/src/plugins/e-acsl/src/code_generator/logic_functions.ml @@ -177,9 +177,10 @@ let generate_kf ~loc fname env ret_ty params_ty li = in Cil.setMaxId fundec; let spec = Cil.empty_funspec () in - Queue.add + (*[TODO ARCHI] reimplement *) +(* Queue.add (fun () -> Globals.Functions.replace_by_definition spec fundec loc) - (Env.get_visitor env)#get_filling_actions; + (Env.get_visitor env)#get_filling_actions;*) (* create the kernel function itself *) let kf = { fundec = Definition(fundec, loc); spec } in (* closure generating the function's body. @@ -187,8 +188,6 @@ let generate_kf ~loc fname env ret_ty params_ty li = of recursive function calls) *) let gen_body () = let env = Env.push env in - let old_kf = Extlib.the (Env.current_kf env) in - Env.set_current_kf env kf; (* fill the typing environment with the function's parameters before generating the code (code generation invokes typing) *) let env = @@ -225,10 +224,7 @@ let generate_kf ~loc fname env ret_ty params_ty li = (fun lvi -> Interval.Env.remove lvi; ignore (Env.Logic_binding.remove env lvi)) - li.l_profile; - Env.set_current_kf - env - (Visitor_behavior.Get_orig.kernel_function (Env.get_behavior env) old_kf) + li.l_profile in vi, kf, gen_body @@ -286,7 +282,7 @@ let add_generated_functions globals = in List.rev rev_globals -let tapp_to_exp ~loc fname env t li params_ty args = +let tapp_to_exp ~loc fname env kf t li params_ty args = let ret_ty = Typing.get_typ t in let gen tbl = let vi, kf, gen_body = generate_kf fname ~loc env ret_ty params_ty li in @@ -340,6 +336,7 @@ let tapp_to_exp ~loc fname env t li params_ty args = ~loc ~name:li.l_var_info.lv_name env + kf (Some t) ret_ty (fun vi _ -> [ Cil.mkStmtOneInstr ~valid_sid:true (mkcall vi) ]) diff --git a/src/plugins/e-acsl/src/code_generator/logic_functions.mli b/src/plugins/e-acsl/src/code_generator/logic_functions.mli index 4a9a4c02ce9..8392275833a 100644 --- a/src/plugins/e-acsl/src/code_generator/logic_functions.mli +++ b/src/plugins/e-acsl/src/code_generator/logic_functions.mli @@ -38,7 +38,8 @@ val reset: unit -> unit val tapp_to_exp: loc:location -> - string -> Env.t -> term -> logic_info -> Typing.number_ty list -> exp list -> + string -> Env.t -> kernel_function -> + term -> logic_info -> Typing.number_ty list -> exp list -> varinfo * exp * Env.t val add_generated_functions: global list -> global list diff --git a/src/plugins/e-acsl/src/code_generator/loops.ml b/src/plugins/e-acsl/src/code_generator/loops.ml index 05f89c24ee7..e9849e324dc 100644 --- a/src/plugins/e-acsl/src/code_generator/loops.ml +++ b/src/plugins/e-acsl/src/code_generator/loops.ml @@ -48,25 +48,22 @@ module Loop_invariants_actions = Hook.Make(struct end) let apply_after_transformation prj = Project.on prj Loop_invariants_actions.apply () -let mv_invariants env ~old stmt = +let mv_invariants kf ~old stmt = Options.feedback ~current:true ~level:3 "keep loop invariants attached to its loop"; - match Env.current_kf env with - | None -> assert false - | Some kf -> - let filter _ ca = match ca.annot_content with - | AInvariant(_, b, _) -> b - | _ -> false - in - let l = Annotations.code_annot_emitter ~filter stmt in - if l != [] then - Loop_invariants_actions.extend - (fun () -> - List.iter - (fun (ca, e) -> - Annotations.remove_code_annot e ~kf old ca; - Annotations.add_code_annot e ~kf stmt ca) - l) + let filter _ ca = match ca.annot_content with + | AInvariant(_, b, _) -> b + | _ -> false + in + let l = Annotations.code_annot_emitter ~filter stmt in + if l != [] then + Loop_invariants_actions.extend + (fun () -> + List.iter + (fun (ca, e) -> + Annotations.remove_code_annot e ~kf old ca; + Annotations.add_code_annot e ~kf stmt ca) + l) let preserve_invariant prj env kf stmt = match stmt.skind with | Loop(_, ({ bstmts = stmts } as blk), loc, cont, break) -> @@ -219,11 +216,11 @@ let rec mk_nested_loops ~loc mk_innermost_block kf env lscope_vars = with Typing.Not_a_number -> assert false in (* loop counter corresponding to the quantified variable *) - let var_x, x, env = Env.Logic_binding.add ~ty env logic_x in + let var_x, x, env = Env.Logic_binding.add ~ty env kf logic_x in let lv_x = var var_x in let env = match ctx_one with | Typing.C_integer _ -> env - | Typing.Gmpz -> Env.add_stmt env (Gmp.init ~loc x) + | Typing.Gmpz -> Env.add_stmt env kf (Gmp.init ~loc x) | Typing.(C_float _ | Rational | Real | Nan) -> assert false in (* build the inner loops and loop body *) @@ -301,7 +298,7 @@ let rec mk_nested_loops ~loc mk_innermost_block kf env lscope_vars = [ start ; stmt ], env | Lscope.Lvs_let(lv, t) :: lscope_vars' -> let ty = Typing.get_typ t in - let vi_of_lv, exp_of_lv, env = Env.Logic_binding.add ~ty env lv in + let vi_of_lv, exp_of_lv, env = Env.Logic_binding.add ~ty env kf lv in let e, env = term_to_exp kf env t in let ty = Cil.typeOf e in let init_set = diff --git a/src/plugins/e-acsl/src/code_generator/loops.mli b/src/plugins/e-acsl/src/code_generator/loops.mli index ffe13fb4af4..a55e09d7a65 100644 --- a/src/plugins/e-acsl/src/code_generator/loops.mli +++ b/src/plugins/e-acsl/src/code_generator/loops.mli @@ -30,7 +30,7 @@ open Cil_types val apply_after_transformation: Project.t -> unit -val mv_invariants: Env.t -> old:stmt -> stmt -> unit +val mv_invariants: kernel_function -> old:stmt -> stmt -> unit (** Transfer the loop invariants from the [old] loop to the new one. Both statements must be loops. *) diff --git a/src/plugins/e-acsl/src/code_generator/memory_observer.ml b/src/plugins/e-acsl/src/code_generator/memory_observer.ml index 2004c9a510e..f3a3805994a 100644 --- a/src/plugins/e-acsl/src/code_generator/memory_observer.ml +++ b/src/plugins/e-acsl/src/code_generator/memory_observer.ml @@ -27,8 +27,7 @@ let tracking_stmt ?before fold mk_stmt env kf vars = fold (fun vi env -> if Mmodel_analysis.must_model_vi ~kf vi then - let vi = Visitor_behavior.Get.varinfo (Env.get_behavior env) vi in - Env.add_stmt ?before env (mk_stmt vi) + Env.add_stmt ?before env kf (mk_stmt vi) else env) vars diff --git a/src/plugins/e-acsl/src/code_generator/mmodel_translate.ml b/src/plugins/e-acsl/src/code_generator/mmodel_translate.ml index 036b3089c25..4d80c4d8cc2 100644 --- a/src/plugins/e-acsl/src/code_generator/mmodel_translate.ml +++ b/src/plugins/e-acsl/src/code_generator/mmodel_translate.ml @@ -121,6 +121,7 @@ let call ~loc kf name ctx env t = ~loc ~name env + kf None ctx (fun v _ -> @@ -154,6 +155,7 @@ let gmp_to_sizet ~loc kf env size p = ~loc ~name:"size" env + kf None sizet (fun vi _ -> @@ -230,6 +232,7 @@ let call_memory_block ~loc kf name ctx env ptr r p = ~loc ~name env + kf None ctx (fun v _ -> @@ -337,6 +340,7 @@ let call_with_size ~loc kf name ctx env t p = ~loc ~name env + kf None ctx (fun v _ -> @@ -374,6 +378,7 @@ let call_valid ~loc kf name ctx env t p = ~loc ~name env + kf None ctx (fun v _ -> @@ -394,3 +399,9 @@ let call_valid ~loc kf name ctx env t p = t p call_for_unsupported_constructs + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff --git a/src/plugins/e-acsl/src/code_generator/quantif.ml b/src/plugins/e-acsl/src/code_generator/quantif.ml index 4a618c5b806..2ad62b7b950 100644 --- a/src/plugins/e-acsl/src/code_generator/quantif.ml +++ b/src/plugins/e-acsl/src/code_generator/quantif.ml @@ -169,6 +169,7 @@ let convert kf env loc is_forall p bounded_vars hyps goal = ~loc ~name env + kf None intType (fun v _ -> @@ -204,7 +205,7 @@ let convert kf env loc is_forall p bounded_vars hyps goal = Loops.mk_nested_loops ~loc mk_innermost_block kf env lvs_guards in let env = - Env.add_stmt env (mkStmt ~valid_sid:true (Block (mkBlock stmts))) + Env.add_stmt env kf (mkStmt ~valid_sid:true (Block (mkBlock stmts))) in (* where to jump to go out of the loop *) let end_loop = mkEmptyStmt ~loc () in @@ -212,7 +213,7 @@ let convert kf env loc is_forall p bounded_vars hyps goal = let label = Label(label_name, loc, false) in end_loop.labels <- label :: end_loop.labels; end_loop_ref := end_loop; - let env = Env.add_stmt env end_loop in + let env = Env.add_stmt env kf end_loop in res, env end @@ -229,6 +230,6 @@ let quantif_to_exp kf env p = (* Local Variables: -compile-command: "make" +compile-command: "make -C ../.." End: *) diff --git a/src/plugins/e-acsl/src/code_generator/rational.ml b/src/plugins/e-acsl/src/code_generator/rational.ml index 427e9ef5650..8145541f8c0 100644 --- a/src/plugins/e-acsl/src/code_generator/rational.ml +++ b/src/plugins/e-acsl/src/code_generator/rational.ml @@ -30,7 +30,7 @@ let init_set ~loc lval vi_e e = [ Gmp.init ~loc vi_e ; Gmp.affect ~loc lval vi_e e ])) -let create ~loc ?name e env t_opt = +let create ~loc ?name e env kf t_opt = let ty = Cil.typeOf e in if Gmp_types.Z.is_t ty then (* GMPQ has no builtin for creating Q from Z. Hence: @@ -45,6 +45,7 @@ let create ~loc ?name e env t_opt = ~loc ?name env + kf t_opt (Gmp_types.Q.t ()) (fun vi vi_e -> @@ -138,7 +139,7 @@ let cast_to_z ~loc:_ ?name:_ e _env = assert (Gmp_types.Q.is_t (Cil.typeOf e)); Error.not_yet "reals: cast from R to Z" -let add_cast ~loc ?name e env ty = +let add_cast ~loc ?name e env kf ty = (* TODO: The best solution would actually be to directly write all the needed functions as C builtins then just call them here depending on the situation at hand. *) @@ -149,6 +150,7 @@ let add_cast ~loc ?name e env ty = ~loc ?name env + kf None Cil.doubleType (fun v _ -> @@ -182,15 +184,18 @@ let add_cast ~loc ?name e env ty = | _ -> Error.not_yet "R to <typ>" -let cmp ~loc bop e1 e2 env t_opt = +let cmp ~loc bop e1 e2 env kf t_opt = let fname = "__gmpq_cmp" in let name = Misc.name_of_binop bop in - let e1, env = create ~loc e1 env None (* TODO: t1_opt could be provided *) in - let e2, env = create ~loc e2 env None (* TODO: t2_opt could be provided *) in + (* TODO: [t1_opt] and [t2_opt] could be provided when creating [e1] and + [e2] *) + let e1, env = create ~loc e1 env kf None in + let e2, env = create ~loc e2 env kf None in let _, e, env = Env.new_var ~loc env + kf t_opt ~name Cil.intType @@ -198,12 +203,13 @@ let cmp ~loc bop e1 e2 env t_opt = in Cil.new_exp ~loc (BinOp(bop, e, Cil.zero ~loc, Cil.intType)), env -let new_var_and_init ~loc ?scope ?name env t_opt mk_stmts = +let new_var_and_init ~loc ?scope ?name env kf t_opt mk_stmts = Env.new_var ~loc ?scope ?name env + kf t_opt (Gmp_types.Q.t ()) (fun v e -> Gmp.init ~loc e :: mk_stmts v e) @@ -216,13 +222,15 @@ let name_arith_bop = function | Mod | Lt | Gt | Le | Ge | Eq | Ne | BAnd | BXor | BOr | LAnd | LOr | Shiftlt | Shiftrt | PlusPI | IndexPI | MinusPI | MinusPP -> assert false -let binop ~loc bop e1 e2 env t_opt = +let binop ~loc bop e1 e2 env kf t_opt = let name = name_arith_bop bop in - let e1, env = create ~loc e1 env None (* TODO: t1_opt could be provided *) in - let e2, env = create ~loc e2 env None (* TODO: t2_opt could be provided *) in + (* TODO: [t1_opt] and [t2_opt] could be provided when creating [e1] and + [e2] *) + let e1, env = create ~loc e1 env kf None in + let e2, env = create ~loc e2 env kf None in let mk_stmts _ e = [ Misc.mk_call ~loc name [ e; e1; e2 ] ] in let name = Misc.name_of_binop bop in - let _, e, env = new_var_and_init ~loc ~name env t_opt mk_stmts in + let _, e, env = new_var_and_init ~loc ~name env kf t_opt mk_stmts in e, env (* diff --git a/src/plugins/e-acsl/src/code_generator/rational.mli b/src/plugins/e-acsl/src/code_generator/rational.mli index c85f97de2b3..e326fb18f9b 100644 --- a/src/plugins/e-acsl/src/code_generator/rational.mli +++ b/src/plugins/e-acsl/src/code_generator/rational.mli @@ -22,12 +22,18 @@ (** Generation of rational numbers. *) +(* [TODO ARCHI]: change the call convention in the whole module *) + open Cil_types -val create: loc:location -> ?name:string -> exp -> Env.t -> term option -> +(* TODO: change the call convention *) +val create: + loc:location -> ?name:string -> exp -> Env.t -> kernel_function -> + term option -> exp * Env.t (** Create a real *) +(* TODO: change the call convention *) val init_set: loc:location -> lval -> exp -> exp -> stmt (** [init_set lval lval_as_exp exp] sets [lval] to [exp] while guranteeing that [lval] is properly initialized wrt the underlying real library. *) @@ -39,20 +45,29 @@ val normalize_str: string -> string decimal expansion. In order to make `libgmp` consider it to be a rational, it must be converted into "1/10". *) +(* TODO: change the call convention *) val cast_to_z: loc:location -> ?name:string -> exp -> Env.t -> exp * Env.t (** Assumes that the given exp is of real type and casts it into Z *) -val add_cast: loc:location -> ?name:string -> exp -> Env.t -> typ -> +(* TODO: change the call convention *) +val add_cast: + loc:location -> ?name:string -> exp -> Env.t -> kernel_function -> typ -> exp * Env.t (** Assumes that the given exp is of real type and casts it into the given typ *) -val binop: loc:location -> binop -> exp -> exp -> Env.t -> term option -> +(* TODO: change the call convention --> exp at the end *) +val binop: + loc:location -> binop -> exp -> exp -> Env.t -> kernel_function -> + term option -> exp * Env.t (** Applies [binop] to the given expressions. The optional term indicates whether the comparison has a correspondance in the logic. *) -val cmp: loc:location -> binop -> exp -> exp -> Env.t -> term option -> +(* TODO: change the call convention --> exp at the end *) +val cmp: + loc:location -> binop -> exp -> exp -> Env.t -> kernel_function -> + term option -> exp * Env.t (** Compares two expressions according to the given [binop]. The optional term indicates whether the comparison has a correspondance in the logic. *) diff --git a/src/plugins/e-acsl/src/code_generator/temporal.ml b/src/plugins/e-acsl/src/code_generator/temporal.ml index 1d27b2046c5..9e49453af8a 100644 --- a/src/plugins/e-acsl/src/code_generator/temporal.ml +++ b/src/plugins/e-acsl/src/code_generator/temporal.ml @@ -45,25 +45,6 @@ type flow = | Copy (* Copy shadow from RHS to LHS *) (* }}} *) -(* ************************************************************************** *) -(* Miscellaneous {{{ *) -(* ************************************************************************** *) - -(* Shortcuts for SA in Mmodel_analysis *) -let must_model_exp exp env = - let kf, bhv = Extlib.the (Env.current_kf env), Env.get_behavior env in - Mmodel_analysis.must_model_exp ~bhv ~kf exp - -let must_model_lval lv env = - let kf, bhv = Extlib.the (Env.current_kf env), Env.get_behavior env in - Mmodel_analysis.must_model_lval ~bhv ~kf lv - -let must_model_vi vi env = - let kf, bhv = Extlib.the (Env.current_kf env), Env.get_behavior env in - Mmodel_analysis.must_model_vi ~bhv ~kf vi - -(* }}} *) - (* ************************************************************************* *) (* Generate analysis function calls {{{ *) (* ************************************************************************** *) @@ -233,10 +214,10 @@ let mk_stmt_from_assign loc lhs rhs = (* ************************************************************************** *) (* Top-level handler for Set instructions *) -let set_instr ?(post=false) current_stmt loc lhs rhs env = - if must_model_lval lhs env then +let set_instr ?(post=false) current_stmt loc lhs rhs env kf = + if Mmodel_analysis.must_model_lval ~kf lhs then Extlib.may_map - (fun stmt -> Env.add_stmt ~before:current_stmt ~post env stmt) + (fun stmt -> Env.add_stmt ~before:current_stmt ~post env kf stmt) ~dft:env (mk_stmt_from_assign loc lhs rhs) else @@ -249,12 +230,15 @@ let set_instr ?(post=false) current_stmt loc lhs rhs env = module Function_call: sig (* Top-level handler for Call instructions *) - val instr: stmt -> lval option -> exp -> exp list -> location -> Env.t -> Env.t + val instr: + stmt -> lval option -> exp -> exp list -> location -> + Env.t -> kernel_function -> + Env.t end = struct (* Track function arguments: export referents of arguments to a global structure so they can be retrieved once that function is called *) - let save_params current_stmt loc args env = + let save_params current_stmt loc args env kf = let (env, _) = List.fold_left (fun (env, index) param -> let lv = Mem(param), NoOffset in @@ -263,9 +247,9 @@ end = struct Extlib.may_map (fun (_, rhs, flow) -> let env = - if must_model_exp param env then + if Mmodel_analysis.must_model_exp ~kf param then let stmt = Mk.save_param ~loc flow rhs index in - Env.add_stmt ~before:current_stmt ~post:false env stmt + Env.add_stmt ~before:current_stmt ~post:false env kf stmt else env in (env, index+1)) @@ -277,7 +261,7 @@ end = struct (* Update local environment with a statement tracking temporal metadata associated with assignment [ret] = [func(args)]. *) - let call_with_ret ?(alloc=false) current_stmt loc ret env = + let call_with_ret ?(alloc=false) current_stmt loc ret env kf = let rhs = Cil.new_exp ~loc (Lval ret) in let vals = assign ret rhs loc in (* Track referent numbers of assignments via function calls. @@ -308,24 +292,24 @@ end = struct else Mk.handle_return_referent ~save:false ~loc (Cil.mkAddrOf ~loc lhs) in - Env.add_stmt ~before:current_stmt ~post:true env stmt) + Env.add_stmt ~before:current_stmt ~post:true env kf stmt) ~dft:env vals (* Update local environment with a statement tracking temporal metadata associated with memcpy/memset call *) - let call_memxxx current_stmt loc args fexp env = + let call_memxxx current_stmt loc args fexp env kf = if Libc.is_memcpy fexp || Libc.is_memset fexp then let name = match fexp.enode with | Lval(Var vi, _) -> vi.vname | _ -> Options.fatal "[Temporal.call_memxxx] not a left-value" in let stmt = Misc.mk_call ~loc (RTL.mk_temporal_name name) args in - Env.add_stmt ~before:current_stmt ~post:false env stmt + Env.add_stmt ~before:current_stmt ~post:false env kf stmt else env - let instr current_stmt ret fexp args loc env = + let instr current_stmt ret fexp args loc env kf = (* Add function calls to reset_parameters and reset_return before each function call regardless. They are not really required, as if the instrumentation is correct then the right parameters will be saved @@ -335,27 +319,27 @@ end = struct be able to optimize that code out. *) let name = (RTL.mk_temporal_name "reset_parameters") in let stmt = Misc.mk_call ~loc name [] in - let env = Env.add_stmt ~before:current_stmt ~post:false env stmt in + let env = Env.add_stmt ~before:current_stmt ~post:false env kf stmt in let stmt = Mk.reset_return_referent ~loc in - let env = Env.add_stmt ~before:current_stmt ~post:false env stmt in + let env = Env.add_stmt ~before:current_stmt ~post:false env kf stmt in (* Push parameters with either a call to a function pointer or a function definition otherwise there is no point. *) let has_def = Functions.has_fundef fexp in let env = if Cil.isFunctionType (Cil.typeOf fexp) || has_def then - save_params current_stmt loc args env + save_params current_stmt loc args env kf else env in (* Handle special cases of memcpy/memset *) - let env = call_memxxx current_stmt loc args fexp env in + let env = call_memxxx current_stmt loc args fexp env kf in (* Memory allocating functions have no definitions so below expression should capture them *) let alloc = not has_def in Extlib.may_map (fun lhs -> - if must_model_lval lhs env then - call_with_ret ~alloc current_stmt loc lhs env + if Mmodel_analysis.must_model_lval ~kf lhs then + call_with_ret ~alloc current_stmt loc lhs env kf else env) ~dft:env ret @@ -367,30 +351,33 @@ end (* ************************************************************************** *) module Local_init: sig (* Top-level handler for Local_init instructions *) - val instr: stmt -> varinfo -> local_init -> location -> Env.t -> Env.t + val instr: + stmt -> varinfo -> local_init -> location -> Env.t -> kernel_function -> + Env.t end = struct - let rec handle_init current_stmt offset loc vi init env = - match init with + let rec handle_init current_stmt offset loc vi init env kf = match init with | SingleInit exp -> - set_instr ~post:true current_stmt loc (Var vi, offset) exp env + set_instr ~post:true current_stmt loc (Var vi, offset) exp env kf | CompoundInit(_, inits) -> List.fold_left (fun acc (off, init) -> - handle_init current_stmt (Cil.addOffset off offset) loc vi init acc) + let off = Cil.addOffset off offset in + handle_init current_stmt off loc vi init acc kf) env inits - let instr current_stmt vi li loc env = - if must_model_vi vi env then + let instr current_stmt vi li loc env kf = + if Mmodel_analysis.must_model_vi ~kf vi then match li with | AssignInit init -> - handle_init current_stmt NoOffset loc vi init env + handle_init current_stmt NoOffset loc vi init env kf | ConsInit(fexp, args, _) -> let ret = Some (Cil.var vi) in let fexp = Cil.evar ~loc fexp in - Function_call.instr current_stmt ret fexp args loc env - else env + Function_call.instr current_stmt ret fexp args loc env kf + else + env end (* }}} *) @@ -400,13 +387,13 @@ end (* Update local environment with a statement tracking temporal metadata associated with adding a function argument to a stack frame *) -let track_argument ?(typ) param index env = +let track_argument ?(typ) param index env kf = let typ = Extlib.opt_conv param.vtype typ in match Cil.unrollType typ with | TPtr _ | TComp _ -> let stmt = Mk.pull_param ~loc:Location.unknown param index in - Env.add_stmt ~post:false env stmt + Env.add_stmt ~post:false env kf stmt | TInt _ | TFloat _ | TEnum _ | TBuiltin_va_list _ -> env | TNamed _ -> assert false | TVoid _ |TArray _ | TFun _ -> @@ -419,20 +406,20 @@ let track_argument ?(typ) param index env = (* Update local environment [env] with statements tracking return value of a function. *) -let handle_return_stmt loc ret env = +let handle_return_stmt loc ret env kf = match ret.enode with | Lval lv -> if Cil.isPointerType (Cil.typeOfLval lv) then let exp = Cil.mkAddrOf ~loc lv in let stmt = Mk.handle_return_referent ~loc ~save:true exp in - Env.add_stmt ~post:false env stmt + Env.add_stmt ~post:false env kf stmt else env | _ -> Options.fatal "Something other than Lval in return" -let handle_return_stmt loc ret env = - if must_model_exp ret env then - handle_return_stmt loc ret env +let handle_return_stmt loc ret env kf = + if Mmodel_analysis.must_model_exp ~kf ret then + handle_return_stmt loc ret env kf else env (* }}} *) @@ -443,14 +430,18 @@ let handle_return_stmt loc ret env = (* Update local environment [env] with statements tracking instruction [instr] *) -let handle_instruction current_stmt instr env = +let handle_instruction current_stmt instr env kf = match instr with - | Set(lv, exp, loc) -> set_instr current_stmt loc lv exp env + | Set(lv, exp, loc) -> + set_instr current_stmt loc lv exp env kf | Call(ret, fexp, args, loc) -> - Function_call.instr current_stmt ret fexp args loc env - | Local_init(vi, li, loc) -> Local_init.instr current_stmt vi li loc env - | Asm _ -> Options.warning ~once:true ~current:true "@[Analysis is\ -potentially incorrect in presence of assembly code.@]"; env + Function_call.instr current_stmt ret fexp args loc env kf + | Local_init(vi, li, loc) -> + Local_init.instr current_stmt vi li loc env kf + | Asm _ -> + Options.warning ~once:true ~current:true + "@[Analysis is potentially incorrect in presence of assembly code.@]"; + env | Skip _ | Code_annot _ -> env (* }}} *) @@ -462,7 +453,7 @@ potentially incorrect in presence of assembly code.@]"; env at offset [off] return [Some stmt], where [stmt] is a statement tracking that initialization. If [init] does not need to be tracked than the return value is [None] *) -let mk_global_init ~loc vi off init env = +let mk_global_init ~loc vi off init = let exp = match init with | SingleInit e -> e (* Compound initializers should have been thrown away at this point *) @@ -484,7 +475,6 @@ let mk_global_init ~loc vi off init env = in (* The input [vi] is from the old project, so get the corresponding variable from the new one, otherwise AST integrity is violated *) - let vi = Visitor_behavior.Get.varinfo (Env.get_behavior env) vi in let lv = Var vi, off in mk_stmt_from_assign loc lv exp (* }}} *) @@ -497,33 +487,33 @@ let handle_function_parameters kf env = if is_enabled () then let env, _ = List.fold_left (fun (env, index) param -> - let param = Visitor_behavior.Get.varinfo (Env.get_behavior env) param in let env = - if Mmodel_analysis.must_model_vi ~kf param then - track_argument param index env + if Mmodel_analysis.must_model_vi ~kf param + then track_argument param index env kf else env - in env, index + 1) + in + env, index + 1) (env, 0) (Kernel_function.get_formals kf) in env else env -let handle_stmt stmt env = +let handle_stmt stmt env kf = if is_enabled () then begin match stmt.skind with - | Instr instr -> handle_instruction stmt instr env + | Instr instr -> handle_instruction stmt instr env kf | Return(ret, loc) -> Extlib.may_map - (fun ret -> handle_return_stmt loc ret env) ~dft:env ret + (fun ret -> handle_return_stmt loc ret env kf) ~dft:env ret | Goto _ | Break _ | Continue _ | If _ | Switch _ | Loop _ | Block _ | UnspecifiedSequence _ | Throw _ | TryCatch _ | TryFinally _ | TryExcept _ -> env end else env -let generate_global_init vi off init env = +let generate_global_init vi off init = if is_enabled () then - mk_global_init ~loc:vi.vdecl vi off init env + mk_global_init ~loc:vi.vdecl vi off init else None (* }}} *) diff --git a/src/plugins/e-acsl/src/code_generator/temporal.mli b/src/plugins/e-acsl/src/code_generator/temporal.mli index d996adf9d51..cf0f41843d5 100644 --- a/src/plugins/e-acsl/src/code_generator/temporal.mli +++ b/src/plugins/e-acsl/src/code_generator/temporal.mli @@ -23,23 +23,26 @@ (** Transformations to detect temporal memory errors (e.g., dereference of stale pointers). *) +open Cil_types + +(* [TODO ARCHI]: change the call convention in this module *) + val enable: bool -> unit (** Enable/disable temporal transformations *) val is_enabled: unit -> bool (** Return a boolean value indicating whether temporal analysis is enabled *) -val handle_function_parameters: Cil_types.kernel_function -> Env.t -> Env.t +val handle_function_parameters: kernel_function -> Env.t -> Env.t (** [handle_function_parameters kf env] updates the local environment [env], according to the parameters of [kf], with statements allowing to track referent numbers across function calls. *) -val handle_stmt: Cil_types.stmt -> Env.t -> Env.t +val handle_stmt: stmt -> Env.t -> kernel_function -> Env.t (** Update local environment ([Env.t]) with statements tracking temporal properties of memory blocks *) -val generate_global_init: Cil_types.varinfo -> Cil_types.offset -> - Cil_types.init -> Env.t -> Cil_types.stmt option +val generate_global_init: varinfo -> offset -> init -> stmt option (** Generate [Some s], where [s] is a statement tracking global initializer or [None] if there is no need to track it *) diff --git a/src/plugins/e-acsl/src/code_generator/translate.ml b/src/plugins/e-acsl/src/code_generator/translate.ml index b981e283a8d..9433bd739e7 100644 --- a/src/plugins/e-acsl/src/code_generator/translate.ml +++ b/src/plugins/e-acsl/src/code_generator/translate.ml @@ -69,13 +69,14 @@ type strnum = | C_number (* integers and floats included *) (* convert [e] in a way that it is compatible with the given typing context. *) -let add_cast ~loc ?name env ctx strnum t_opt e = +let add_cast ~loc ?name env kf ctx strnum t_opt e = let mk_mpz e = let _, e, env = Env.new_var ~loc ?name env + kf t_opt (Gmp_types.Z.t ()) (fun lv v -> [ Gmp.init_set ~loc (Cil.var lv) v e ]) @@ -84,7 +85,7 @@ let add_cast ~loc ?name env ctx strnum t_opt e = in let e, env = match strnum with | Str_Z -> mk_mpz e - | Str_R -> Rational.create ~loc ?name e env t_opt + | Str_R -> Rational.create ~loc ?name e env kf t_opt | C_number -> e, env in match ctx with @@ -115,8 +116,10 @@ let add_cast ~loc ?name env ctx strnum t_opt e = mk_mpz e | _, false -> if Gmp_types.Q.is_t ctx then - if Gmp_types.Q.is_t (Cil.typeOf e) then (* R --> R *) e, env - else (* C integer or Z --> R *) Rational.create ~loc ?name e env t_opt + if Gmp_types.Q.is_t (Cil.typeOf e) then (* R --> R *) + e, env + else (* C integer or Z --> R *) + Rational.create ~loc ?name e env kf t_opt else if Gmp_types.Z.is_t ty || strnum = Str_Z then (* Z --> C type or the integer is represented by a string: anyway, it fits into a C integer: convert it *) @@ -129,6 +132,7 @@ let add_cast ~loc ?name env ctx strnum t_opt e = ~loc ?name env + kf None new_ty (fun v _ -> [ Misc.mk_call ~loc ~result:(Cil.var v) fname [ e ] ]) @@ -136,7 +140,7 @@ let add_cast ~loc ?name env ctx strnum t_opt e = e, env else if Gmp_types.Q.is_t ty || strnum = Str_R then (* R --> C type or the real is represented by a string *) - Rational.add_cast ~loc ?name e env ctx + Rational.add_cast ~loc ?name e env kf ctx else (* C type --> another C type *) Cil.mkCastT ~force:false ~e ~oldt:ty ~newt:ctx, env @@ -183,7 +187,7 @@ let constant_to_exp ~loc t c = else mk_real lr.r_literal | LEnum e -> Cil.new_exp ~loc (Const (CEnum e)), C_number -let conditional_to_exp ?(name="if") loc t_opt e1 (e2, env2) (e3, env3) = +let conditional_to_exp ?(name="if") loc kf t_opt e1 (e2, env2) (e3, env3) = let env = Env.pop (Env.pop env3) in match e1.enode with | Const(CInt64(n, _, _)) when Integer.is_zero n -> @@ -200,6 +204,7 @@ let conditional_to_exp ?(name="if") loc t_opt e1 (e2, env2) (e3, env3) = ~loc ~name env + kf t_opt ty (fun v ev -> @@ -224,19 +229,14 @@ let conditional_to_exp ?(name="if") loc t_opt e1 (e2, env2) (e3, env3) = let rec thost_to_host kf env th = match th with | TVar { lv_origin = Some v } -> - let v' = Visitor_behavior.Get.varinfo (Env.get_behavior env) v in - Var v', env, v.vname + Var v, env, v.vname | TVar ({ lv_origin = None } as logic_v) -> let v' = Env.Logic_binding.get env logic_v in Var v', env, logic_v.lv_name | TResult _typ -> - let vis = Env.get_visitor env in - let kf = Extlib.the vis#current_kf in let lhost = Misc.result_lhost kf in (match lhost with - | Var v -> - let v' = Visitor_behavior.Get.varinfo (Env.get_behavior env) v in - Var v', env, "result" + | Var v -> Var v, env, "result" | _ -> assert false) | TMem t -> let e, env = term_to_exp kf env t in @@ -294,6 +294,7 @@ and context_insensitive_term_to_exp kf env t = Env.new_var_and_mpz_init ~loc env + kf ~name:vname (Some t) (fun _ ev -> [ Misc.mk_call ~loc name [ ev; e ] ]) @@ -328,11 +329,11 @@ and context_insensitive_term_to_exp kf env t = let mk_stmts _ e = [ Misc.mk_call ~loc name [ e; e1; e2 ] ] in let name = Misc.name_of_binop bop in let _, e, env = - Env.new_var_and_mpz_init ~loc ~name env (Some t) mk_stmts + Env.new_var_and_mpz_init ~loc ~name env kf (Some t) mk_stmts in e, env, C_number, "" else if Gmp_types.Q.is_t ty then - let e, env = Rational.binop ~loc bop e1 e2 env (Some t) in + let e, env = Rational.binop ~loc bop e1 e2 env kf (Some t) in e, env, C_number, "" else begin assert (Logic_typing.is_integral_type t.term_type); @@ -361,8 +362,6 @@ and context_insensitive_term_to_exp kf env t = in let mk_stmts _v e = assert (Gmp_types.Z.is_t ty); - let vis = Env.get_visitor env in - let kf = Extlib.the vis#current_kf in let cond = Misc.mk_e_acsl_guard (Env.annotation_kind env) @@ -375,10 +374,10 @@ and context_insensitive_term_to_exp kf env t = [ cond; instr ] in let name = Misc.name_of_binop bop in - let _, e, env = Env.new_var_and_mpz_init ~loc ~name env t mk_stmts in + let _, e, env = Env.new_var_and_mpz_init ~loc ~name env kf t mk_stmts in e, env, C_number, "" else if Gmp_types.Q.is_t ty then - let e, env = Rational.binop ~loc bop e1 e2 env (Some t) in + let e, env = Rational.binop ~loc bop e1 e2 env kf (Some t) in e, env, C_number, "" else begin assert (Logic_typing.is_integral_type t.term_type); @@ -399,7 +398,7 @@ and context_insensitive_term_to_exp kf env t = let env' = Env.push env1 in let res2 = term_to_exp kf (Env.push env') t2 in let e, env = - conditional_to_exp ~name:"or" loc (Some t) e1 (Cil.one loc, env') res2 + conditional_to_exp ~name:"or" loc kf (Some t) e1 (Cil.one loc, env') res2 in e, env, C_number, "" | TBinOp(LAnd, t1, t2) -> @@ -408,7 +407,8 @@ and context_insensitive_term_to_exp kf env t = let _, env2 as res2 = term_to_exp kf (Env.push env1) t2 in let env3 = Env.push env2 in let e, env = - conditional_to_exp ~name:"and" loc (Some t) e1 res2 (Cil.zero loc, env3) + conditional_to_exp + ~name:"and" loc kf (Some t) e1 res2 (Cil.zero loc, env3) in e, env, C_number, "" | TBinOp((BOr | BXor | BAnd), _, _) -> @@ -443,7 +443,7 @@ and context_insensitive_term_to_exp kf env t = | TCastE(ty, t') -> let e, env = term_to_exp kf env t' in let e, env = - add_cast ~loc ~name:"cast" env (Some ty) C_number (Some t) e + add_cast ~loc ~name:"cast" env kf (Some ty) C_number (Some t) e in e, env, C_number, "" | TLogic_coerce _ -> assert false (* handle in [term_to_exp] *) @@ -477,6 +477,7 @@ and context_insensitive_term_to_exp kf env t = ~loc ~name:(fname ^ "_app") env + kf (Some t) (Misc.cty (Extlib.the li.l_type)) (fun vi _ -> @@ -491,7 +492,7 @@ and context_insensitive_term_to_exp kf env t = let e, env = try let ty = Typing.typ_of_number_ty param_ty in - add_cast loc env (Some ty) C_number (Some targ) e + add_cast loc env kf (Some ty) C_number (Some targ) e with Typing.Not_a_number -> e, env in @@ -502,7 +503,7 @@ and context_insensitive_term_to_exp kf env t = let gen_fname = Varname.get ~scope:Varname.Global (Functions.RTL.mk_gen_name fname) in - Logic_functions.tapp_to_exp ~loc gen_fname env t li params_ty args + Logic_functions.tapp_to_exp ~loc gen_fname env kf t li params_ty args in e, env, C_number, "app" | Tapp(_, _ :: _, _) -> @@ -513,7 +514,7 @@ and context_insensitive_term_to_exp kf env t = let e1, env1 = term_to_exp kf (Env.rte env true) t1 in let (_, env2 as res2) = term_to_exp kf (Env.push env1) t2 in let res3 = term_to_exp kf (Env.push env2) t3 in - let e, env = conditional_to_exp loc (Some t) e1 res2 res3 in + let e, env = conditional_to_exp loc kf (Some t) e1 res2 res3 in e, env, C_number, "" | Tat(t, BuiltinLabel Here) -> let e, env = term_to_exp kf env t in @@ -526,7 +527,7 @@ and context_insensitive_term_to_exp kf env t = e, env, C_number, "" else let e, env = term_to_exp kf (Env.push env) t' in - let e, env, sty = at_to_exp_no_lscope env (Some t) label e in + let e, env, sty = at_to_exp_no_lscope env kf (Some t) label e in e, env, sty, "" | Tbase_addr(BuiltinLabel Here, t) -> let name = "base_addr" in @@ -580,6 +581,7 @@ and term_to_exp kf env t = ~loc:t.term_loc ?name env + kf cast sty (Some t) @@ -603,6 +605,7 @@ and comparison_to_exp let _, e, env = Env.new_var ~loc env + kf t_opt ~name Cil.intType @@ -611,12 +614,12 @@ and comparison_to_exp in Cil.new_exp ~loc (BinOp(bop, e, Cil.zero ~loc, Cil.intType)), env | Typing.Rational -> - Rational.cmp ~loc bop e1 e2 env t_opt + Rational.cmp ~loc bop e1 e2 env kf t_opt | Typing.Real -> Error.not_yet "comparison involving real numbers" -and at_to_exp_no_lscope env t_opt label e = - let stmt = E_acsl_label.get_stmt (Env.get_visitor env) label in +and at_to_exp_no_lscope env kf t_opt label e = + let stmt = E_acsl_label.get_stmt label in (* generate a new variable denoting [\at(t',label)]. That is this variable which is the resulting expression. ACSL typing rule ensures that the type of this variable is the same as @@ -628,6 +631,7 @@ and at_to_exp_no_lscope env t_opt label e = ~name:"at" ~scope:Varname.Function env + kf t_opt (Cil.typeOf e) (fun _ _ -> []) @@ -656,17 +660,15 @@ and at_to_exp_no_lscope env t_opt label e = Cil.ChangeTo stmt end in - let bhv = Env.get_behavior new_env in - let new_stmt = - Visitor.visitFramacStmt o (Visitor_behavior.Get.stmt bhv stmt) - in - Visitor_behavior.Set.stmt bhv stmt new_stmt; + let _new_stmt = Visitor.visitFramacStmt o stmt in + (* [TODO ARCHI] reimplement *) + (*Visitor_behavior.Set.stmt bhv stmt new_stmt;*) res, !env_ref, C_number and env_of_li li kf env loc = let t = Misc.term_of_li li in let ty = Typing.get_typ t in - let vi, vi_e, env = Env.Logic_binding.add ~ty env li.l_var_info in + let vi, vi_e, env = Env.Logic_binding.add ~ty env kf li.l_var_info in let e, env = term_to_exp kf env t in let stmt = match Typing.get_number_ty t with | Typing.(C_integer _ | C_float _ | Nan) -> @@ -678,7 +680,7 @@ and env_of_li li kf env loc = | Typing.Real -> Error.not_yet "real number" in - Env.add_stmt env stmt + Env.add_stmt env kf stmt (* Convert an ACSL named predicate into a corresponding C expression (if any) in the given environment. Also extend this environment which includes @@ -715,14 +717,14 @@ and named_predicate_content_to_exp ?name kf env p = named_predicate_to_exp kf (Env.push env1) p2 in let env3 = Env.push env2 in let name = match name with None -> "and" | Some n -> n in - conditional_to_exp ~name loc None e1 res2 (Cil.zero loc, env3) + conditional_to_exp ~name loc kf None e1 res2 (Cil.zero loc, env3) | Por(p1, p2) -> (* p1 || p2 <==> if p1 then true else p2 *) let e1, env1 = named_predicate_to_exp kf (Env.rte env true) p1 in let env' = Env.push env1 in let res2 = named_predicate_to_exp kf (Env.push env') p2 in let name = match name with None -> "or" | Some n -> n in - conditional_to_exp ~name loc None e1 (Cil.one loc, env') res2 + conditional_to_exp ~name loc kf None e1 (Cil.one loc, env') res2 | Pxor _ -> not_yet env "xor" | Pimplies(p1, p2) -> (* (p1 ==> p2) <==> !p1 || p2 *) @@ -748,7 +750,7 @@ and named_predicate_content_to_exp ?name kf env p = let (_, env2 as res2) = named_predicate_to_exp kf (Env.push env1) p2 in let res3 = named_predicate_to_exp kf (Env.push env2) p3 in - conditional_to_exp loc None e1 res2 res3 + conditional_to_exp loc kf None e1 res2 res3 | Plet(li, p) -> let lvs = Lscope.Lvs_let(li.l_var_info, Misc.term_of_li li) in let env = Env.Logic_scope.extend env lvs in @@ -767,7 +769,7 @@ and named_predicate_content_to_exp ?name kf env p = else begin (* convert [t'] to [e] in a separated local env *) let e, env = named_predicate_to_exp kf (Env.push env) p' in - let e, env, sty = at_to_exp_no_lscope env None label e in + let e, env, sty = at_to_exp_no_lscope env kf None label e in assert (sty = C_number); e, env end @@ -835,6 +837,7 @@ and named_predicate_to_exp ?name kf ?rte env p = ~loc:p.pred_loc ?name env + kf cast C_number None @@ -885,6 +888,7 @@ and translate_named_predicate kf env p = let env = Env.Logic_scope.reset env in Env.add_stmt env + kf (Misc.mk_e_acsl_guard ~reverse:true (Env.annotation_kind env) kf e p) let named_predicate_to_exp ?name kf env p = @@ -906,8 +910,7 @@ let () = However, it is correct to use it only in specific contexts. *) let predicate_to_exp kf p = Typing.type_named_predicate ~must_clear:true p; - let empty_env = Env.empty (new Visitor.frama_c_copy Project_skeleton.dummy) in - let e, _ = named_predicate_to_exp kf empty_env p in + let e, _ = named_predicate_to_exp kf Env.empty p in assert (Typ.equal (Cil.typeOf e) Cil.intType); e @@ -927,8 +930,7 @@ let term_to_exp typ t = in let ctx = Extlib.opt_map ctx_of_typ typ in Typing.type_term ~use_gmp_opt:true ?ctx t; - let env = Env.empty (new Visitor.frama_c_copy Project_skeleton.dummy) in - let env = Env.push env in + let env = Env.push Env.empty in let env = Env.rte env false in let e, env = try term_to_exp (Kernel_function.dummy ()) env t diff --git a/src/plugins/e-acsl/src/code_generator/visit.ml b/src/plugins/e-acsl/src/code_generator/visit.ml index d220b15715e..0083db8f3a0 100644 --- a/src/plugins/e-acsl/src/code_generator/visit.ml +++ b/src/plugins/e-acsl/src/code_generator/visit.ml @@ -21,17 +21,12 @@ (**************************************************************************) module E_acsl_label = Label -open Cil_types -open Cil_datatype - -let dkey = Options.dkey_translation (* ************************************************************************** *) (* Visitor *) (* ************************************************************************** *) (* local references to the below visitor and to [do_visit] *) -let function_env = ref Env.dummy let dft_funspec = Cil.empty_funspec () let funspec = ref dft_funspec @@ -41,194 +36,10 @@ class e_acsl_visitor prj generate = object (self) inherit Visitor.generic_frama_c_visitor (if generate then Visitor_behavior.copy prj else Visitor_behavior.inplace ()) - val mutable main_fct = None - (* fundec of the main entry point, in the new project [prj]. - [None] while the global corresponding to this fundec has not been - visited *) - val mutable is_initializer = false (* Global flag set to [true] if a currently visited node belongs to a global initializer and set to [false] otherwise *) - method private reset_env () = - function_env := Env.empty (self :> Visitor.frama_c_visitor) - - method !vfile _f = - (* copy the options used during the visit in the new project: it is the - right place to do this: it is still before visiting, but after - that the visitor internals reset all of them :-(. *) - let cur = Project.current () in - let selection = - State_selection.of_list - [ Options.Gmp_only.self; Options.Check.self; Options.Full_mmodel.self; - Kernel.SignedOverflow.self; Kernel.UnsignedOverflow.self; - Kernel.SignedDowncast.self; Kernel.UnsignedDowncast.self; - Kernel.Machdep.self ] - in - if generate then Project.copy ~selection ~src:cur prj; - Cil.DoChildrenPost - (fun f -> - (* extend [main] with forward initialization and put it at end *) - if generate then begin - if not (Global_observer.is_empty () && Literal_strings.is_empty ()) - then begin - let build_initializer () = - Options.feedback ~dkey ~level:2 "building global initializer."; - let vi, fundec, env = - Global_observer.mk_init self#behavior !function_env - in - function_env := env; - let cil_fct = GFun(fundec, Location.unknown) in - if Mmodel_analysis.use_model () then - match main_fct with - | Some main -> - let exp = Cil.evar ~loc:Location.unknown vi in - (* Create [__e_acsl_globals_init();] call *) - let stmt = - Cil.mkStmtOneInstr ~valid_sid:true - (Call(None, exp, [], Location.unknown)) - in - vi.vreferenced <- true; - (* insert [__e_acsl_globals_init ();] as first statement of - [main] *) - main.sbody.bstmts <- stmt :: main.sbody.bstmts; - let new_globals = - List.fold_right - (fun g acc -> match g with - | GFun({ svar = vi }, _) - when Varinfo.equal vi main.svar -> - acc - | _ -> g :: acc) - f.globals - [ cil_fct; GFun(main, Location.unknown) ] - in - (* add the literal string varinfos as the very first - globals *) - let new_globals = - Literal_strings.fold - (fun _ vi l -> - GVar(vi, { init = None }, Location.unknown) :: l) - new_globals - in - f.globals <- new_globals - | None -> - Kernel.warning "@[no entry point specified:@ \ -you must call function `%s' and `__e_acsl_memory_clean by yourself.@]" - Global_observer.function_name; - f.globals <- f.globals @ [ cil_fct ] - in - Project.on prj build_initializer () - end; (* must_init *) - (* Add a call to [__e_acsl_memory_init] that initializes memory - storage and potentially records program arguments. Parameters to - [__e_acsl_memory_init] are addresses of program arguments or - NULLs if [main] is declared without arguments. *) - let build_mmodel_initializer () = - let loc = Location.unknown in - let nulls = [ Cil.zero loc ; Cil.zero loc ] in - let handle_main main = - let args = - (* record arguments only if the second has a pointer type, so a - argument strings can be recorded. This is sufficient to - capture C99 compliant arguments and GCC extensions with - environ. *) - match main.sformals with - | [] -> - (* no arguments to main given *) - nulls - | _argc :: argv :: _ when Cil.isPointerType argv.vtype -> - (* grab addresses of arguments for a call to the main - initialization function, i.e., [__e_acsl_memory_init] *) - List.map Cil.mkAddrOfVi main.sformals; - | _ :: _ -> - (* some non-standard arguments. *) - nulls - in - let ptr_size = Cil.sizeOf loc Cil.voidPtrType in - let args = args @ [ ptr_size ] in - let name = Functions.RTL.mk_api_name "memory_init" in - let init = Misc.mk_call loc name args in - main.sbody.bstmts <- init :: main.sbody.bstmts - in - Extlib.may handle_main main_fct - in - Project.on - prj - (fun () -> - f.globals <- Logic_functions.add_generated_functions f.globals; - build_mmodel_initializer ()) - (); - (* reset copied states at the end to be observationally - equivalent to a standard visitor. *) - Project.clear ~selection ~project:prj (); - end; (* generate *) - f) - - method !vglob_aux = function - | GVarDecl(vi, _) | GVar(vi, _, _) - | GFunDecl(_, vi, _) | GFun({ svar = vi }, _) - when Misc.is_library_loc vi.vdecl || Builtins.mem vi.vname -> - if generate then - Cil.JustCopyPost - (fun l -> - let new_vi = Visitor_behavior.Get.varinfo self#behavior vi in - if Misc.is_library_loc vi.vdecl then - Misc.register_library_function new_vi; - if Builtins.mem vi.vname then Builtins.update vi.vname new_vi; - l) - else begin - Misc.register_library_function vi; - Cil.SkipChildren - end - | GVarDecl(vi, _) | GVar(vi, _, _) | GFun({ svar = vi }, _) - when Cil.is_builtin vi -> - if generate then Cil.JustCopy else Cil.SkipChildren - | g when Misc.is_library_loc (Global.loc g) -> - if generate then Cil.JustCopy else Cil.SkipChildren - | g -> - let unghost_vi vi = - vi.vghost <- false ; - vi.vtype <- match vi.vtype with - | TFun(res, Some l, va, attr) -> - let retype (n, t, a) = - (n, t, Cil.dropAttribute Cil.frama_c_ghost_formal a) - in - TFun(res, Some (List.map retype l), va, attr) - | _ -> - vi.vtype - in - let do_it = function - | GVar(vi, _, _) -> - unghost_vi vi - | GFun({ svar = vi } as fundec, _) -> - unghost_vi vi ; - Builtins.update vi.vname vi; - (* remember that we have to remove the main later (see method - [vfile]); do not use the [vorig_name] since both [main] and - [__e_acsl_main] have the same [vorig_name]. *) - if vi.vname = Kernel.MainFunction.get () then - main_fct <- Some fundec - | GVarDecl(vi, _) | GFunDecl(_, vi, _) -> - (* do not convert extern ghost variables, because they can't be linked, - see bts #1392 *) - if vi.vstorage <> Extern then - unghost_vi vi - | _ -> - () - in - (match g with - | GVar(vi, _, _) | GVarDecl(vi, _) | GFun({ svar = vi }, _) - (* Track function addresses but the main function that is tracked - internally via RTL *) - when vi.vorig_name <> Kernel.MainFunction.get () -> - (* Make a unique mapping for each global variable omitting initializers. - Initializers (used to capture literal strings) are added to - [global_vars] via the [vinit] visitor method (see comments below). *) - Global_observer.add (Visitor_behavior.Get_orig.varinfo self#behavior vi) - | _ -> ()); - if generate then Cil.DoChildrenPost(fun g -> List.iter do_it g; g) - else Cil.DoChildren - (* Add mappings from global variables to their initializers in [global_vars]. Note that the below function captures only [SingleInit]s. All compound initializers containing SingleInits (except for empty compound @@ -270,57 +81,6 @@ you must call function `%s' and `__e_acsl_memory_clean by yourself.@]" ()); Cil.SkipChildren - method private add_generated_variables_in_function f = - assert generate; - let vars = Env.get_generated_variables !function_env in - self#reset_env (); - let locals, blocks = - List.fold_left - (fun (local_vars, block_vars as acc) (v, scope) -> match scope with - (* TODO: [kf] assumed to be consistent. Should be asserted. *) - | Env.LFunction _kf -> v :: local_vars, v :: block_vars - | Env.LLocal_block _kf -> v :: local_vars, block_vars - | _ -> acc) - (f.slocals, f.sbody.blocals) - vars - in - f.slocals <- locals; - f.sbody.blocals <- blocks - - (* Memory management for \at on purely logic variables: - Put [malloc] stmts at proper locations *) - method private insert_malloc_and_free_stmts kf f = - let malloc_stmts = At_with_lscope.Malloc.find_all kf in - let fstmts = malloc_stmts @ f.sbody.bstmts in - f.sbody.bstmts <- fstmts; - (* Now that [malloc] stmts for [kf] have been inserted, - there is no more need to keep the corresponding entries in the - table managing them. *) - At_with_lscope.Malloc.remove_all kf - - method !vfunc f = - if generate then begin - let kf = Extlib.the self#current_kf in - if Functions.instrument kf then Exit_points.generate f; - Options.feedback ~dkey ~level:2 "entering in function %a." - Kernel_function.pretty kf; - let unghost_formal vi = - vi.vghost <- false ; - vi.vattr <- Cil.dropAttribute Cil.frama_c_ghost_formal vi.vattr - in - List.iter (fun vi -> vi.vghost <- false) f.slocals; - List.iter unghost_formal f.sformals; - Cil.DoChildrenPost - (fun f -> - Exit_points.clear (); - self#add_generated_variables_in_function f; - self#insert_malloc_and_free_stmts kf f; - Options.feedback ~dkey ~level:2 "function %a done." - Kernel_function.pretty kf; - f) - end else - Cil.DoChildren - method private is_return old_kf stmt = let old_ret = try Kernel_function.find_return old_kf @@ -672,63 +432,6 @@ you must call function `%s' and `__e_acsl_memory_clean by yourself.@]" | _ -> env) | _ -> env - method !vblock blk = - let handle_memory new_blk = - let kf = Extlib.the self#current_kf in - let free_stmts = At_with_lscope.Free.find_all kf in - match new_blk.blocals, free_stmts with - | [], [] -> - new_blk - | [], _ :: _ | _ :: _, [] | _ :: _, _ :: _ -> - let add_locals stmts = - if Functions.instrument kf then - List.fold_left - (fun acc vi -> - if Mmodel_analysis.must_model_vi ~bhv:self#behavior ~kf vi then - Misc.mk_delete_stmt vi :: acc - else - acc) - stmts - new_blk.blocals - else - stmts - in - let rec insert_in_innermost_last_block blk = function - | { skind = Return _ } as ret :: ((potential_clean :: tl) as l) -> - (* keep the return (enclosed in a generated block) at the end; - preceded by clean if any *) - let init, tl = - if self#is_main kf && Mmodel_analysis.use_model () then - free_stmts @ [ potential_clean; ret ], tl - else - free_stmts @ [ ret ], l - in - (* Now that [free] stmts for [kf] have been inserted, - there is no more need to keep the corresponding entries in the - table managing them. *) - At_with_lscope.Free.remove_all kf; - blk.bstmts <- - List.fold_left (fun acc v -> v :: acc) (add_locals init) tl - | { skind = Block b } :: _ -> - insert_in_innermost_last_block b (List.rev b.bstmts) - | l -> blk.bstmts <- - List.fold_left (fun acc v -> v :: acc) (add_locals []) l - in - insert_in_innermost_last_block new_blk (List.rev new_blk.bstmts); - if Functions.instrument kf then - new_blk.bstmts <- - List.fold_left - (fun acc vi -> - if Mmodel_analysis.must_model_vi vi && not vi.vdefined then - let vi = Visitor_behavior.Get.varinfo self#behavior vi in - Misc.mk_store_stmt vi :: acc - else acc) - new_blk.bstmts - blk.blocals; - new_blk - in - if generate then Cil.DoChildrenPost handle_memory else Cil.DoChildren - (* Processing expressions for the purpose of replacing literal strings found in the code with variables generated by E-ACSL. *) method !vexpr _ = @@ -746,33 +449,8 @@ you must call function `%s' and `__e_acsl_memory_clean by yourself.@]" end else Cil.SkipChildren - initializer - Misc.reset (); - Logic_functions.reset (); - Literal_strings.reset (); - Global_observer.reset (); - Keep_status.before_translation (); - self#reset_env () - end -let do_visit ?(prj=Project.current ()) generate = - (* The main visitor proceeds by tracking declarations belonging to the - E-ACSL runtime library and then using these declarations to generate - statements used in instrumentation. The following code reorders AST - so declarations belonging to E-ACSL library appear atop of any location - requiring instrumentation. *) - Misc.reorder_ast (); - Options.feedback ~level:2 "%s annotations in %a." - (if generate then "translating" else "checking") - Project.pretty prj; - let vis = - Extlib.try_finally ~finally:Typing.clear (new e_acsl_visitor prj) generate - in - (* explicit type annotation in order to check that no new method is - introduced by error *) - (vis : Visitor.frama_c_visitor) - (* Local Variables: compile-command: "make -C ../.." diff --git a/src/plugins/e-acsl/src/main.ml b/src/plugins/e-acsl/src/main.ml index d638cb7357f..4b0ccaabdf1 100644 --- a/src/plugins/e-acsl/src/main.ml +++ b/src/plugins/e-acsl/src/main.ml @@ -20,20 +20,7 @@ (* *) (**************************************************************************) -let check () = - Visitor.visitFramacFileSameGlobals (Visit.do_visit false) (Ast.get ()); - let t = Error.nb_untypable () in - let n = Error.nb_not_yet () in - let print msg n = - Options.result "@[%d annotation%s %s ignored,@ being %s.@]" - n - (if n > 1 then "s" else "") - (if n > 1 then "were" else "was") - msg - in - print "untypable" t; - print "unsupported" n; - n + t = 0 +let check () = assert false (* [TODO ARCHI] kill check *) let check = Dynamic.register @@ -155,39 +142,30 @@ let generate_code = Project.on prepared_prj (fun () -> let dup_prj = Dup_functions.dup () in - let cname = Project.get_name dup_prj ^ " (copy)" in let copied_prj = - Project.create_by_copy cname ~last:true ~src:dup_prj - in - let res = - Project.on - copied_prj - (fun () -> - Gmp_types.init (); - Mmodel_analysis.reset (); - let visit prj = Visit.do_visit ~prj true in - let prj = - File.create_project_from_visitor name visit - in - Loops.apply_after_transformation prj; - (* remove the RTE's results computed from E-ACSL: - they are partial and associated with the wrong - kernel function (the one of the old project). *) - let selection = - State_selection.with_dependencies !Db.RteGen.self - in - Project.clear ~selection ~project:prj (); - Resulting_projects.mark_as_computed (); - let selection = - State_selection.singleton Kernel.Files.self - in - Project.copy ~selection prj; - prj) - () + Project.create_by_copy name ~last:true ~src:dup_prj in + Project.on + copied_prj + (fun () -> + Gmp_types.init (); + Mmodel_analysis.reset (); + Injector.inject (); + (* [TODO ARCHI] remove the project as arguments *) + Loops.apply_after_transformation copied_prj; + (* remove the RTE's results computed from E-ACSL: + they are partial and associated with the wrong + kernel function (the one of the old project). *) + (* [TODO ARCHI] what if RTE was already computed? *) + let selection = + State_selection.with_dependencies !Db.RteGen.self + in + Project.clear ~selection ~project:copied_prj (); + Resulting_projects.mark_as_computed ()) + (); if Options.Debug.get () = 0 then Project.remove ~project:dup_prj (); - res) + copied_prj) () in if Options.Debug.get () = 0 then begin -- GitLab