From 7e5d6c6f42d7972101d5faf81c2d27c85eb6ceb6 Mon Sep 17 00:00:00 2001 From: Basile Desloges <basile.desloges@cea.fr> Date: Wed, 16 Feb 2022 15:14:39 +0100 Subject: [PATCH] fixup! [eacsl] Use the label analysis to translate `\at` values --- .../e-acsl/src/code_generator/injector.ml | 1 + .../src/code_generator/translate_ats.ml | 164 +++++++++++------- .../src/code_generator/translate_ats.mli | 3 + 3 files changed, 108 insertions(+), 60 deletions(-) diff --git a/src/plugins/e-acsl/src/code_generator/injector.ml b/src/plugins/e-acsl/src/code_generator/injector.ml index 4f73a16274b..50b878a67e9 100644 --- a/src/plugins/e-acsl/src/code_generator/injector.ml +++ b/src/plugins/e-acsl/src/code_generator/injector.ml @@ -837,6 +837,7 @@ let reset_all ast = (* by default, do not run E-ACSL on the generated code *) Options.Run.off (); (* reset all the E-ACSL environments to their original states *) + Translate_ats.reset (); Logic_functions.reset (); Global_observer.reset (); Analyses.reset (); diff --git a/src/plugins/e-acsl/src/code_generator/translate_ats.ml b/src/plugins/e-acsl/src/code_generator/translate_ats.ml index db91471919e..76a12b8718f 100644 --- a/src/plugins/e-acsl/src/code_generator/translate_ats.ml +++ b/src/plugins/e-acsl/src/code_generator/translate_ats.ml @@ -250,23 +250,29 @@ let indexed_exp ~loc kf env e_at = (* Translation *) (* ************************************************************************** *) +(* Table storing the [varinfo] with the translation of a given [at_data]. *) +let translations: varinfo Error.result AtData.Hashtbl.t = + AtData.Hashtbl.create 17 + +(* [pretranslate_to_exp ~loc kf env pot] immediately translates the given + [pred_or_term] in the current environment and return the translated + expression. *) let pretranslate_to_exp ~loc kf env pot = Options.debug ~level:4 "pre-translating %a in local environment '%a'" PredOrTerm.pretty pot Typing.Function_params_ty.pretty (Env.Local_vars.get env); - let t_opt = - match pot with - | PoT_term t -> Some t - | PoT_pred _ -> None - in - let e, _ , env = + let e, env, t_opt = let adata = Assert.no_data in match pot with - | PoT_term t -> !term_to_exp_ref ~adata ~inplace:true kf env t - | PoT_pred p -> !predicate_to_exp_ref ~adata ~inplace:true kf env p + | PoT_term t -> + let e, _, env = !term_to_exp_ref ~adata ~inplace:true kf env t in + e, env, Some t + | PoT_pred p -> + let e, _, env = !predicate_to_exp_ref ~adata ~inplace:true kf env p in + e, env, None in let ty = Cil.typeOf e in - let _, var_e, env = + let var_vi, _, env = Env.new_var ~loc ~scope:Function @@ -281,7 +287,7 @@ let pretranslate_to_exp ~loc kf env pot = in [ init_set ~loc (Cil.var var_vi) var_e e ]) in - var_e, env + var_vi, env (* [pretranslate_to_exp_with_lscope ~loc ~lscope kf env pot] immediately translates the given [pred_or_term] in the current environment for each value @@ -317,7 +323,7 @@ let pretranslate_to_exp_with_lscope ~loc ~lscope kf env pot = end in let ty_ptr = TPtr(ty, []) in - let _, e_at, env = Env.new_var + let vi_at, e_at, env = Env.new_var ~loc ~name:"at" ~scope:Varname.Function @@ -428,84 +434,122 @@ let pretranslate_to_exp_with_lscope ~loc ~lscope kf env pot = (* Put block in the current env *) let env = Env.add_stmt env (Smart_stmt.block_stmt storing_loops_block) in (* Returning *) - e_at, env + vi_at, env + +(* Set holding the C labels defined in the function currently being visited. *) +let clabels_ref: Logic_label.Set.t ref = ref Logic_label.Set.empty + +(* [is_label_defined label] returns [true] if [label] is either a C label that + has been defined, a built-in label or a formal label, and return false if + [label] is a C label that has not been defined. *) +let is_label_defined label = + match label with + | StmtLabel _ when Logic_label.Set.mem label !clabels_ref -> + true + | StmtLabel _ -> + false + | BuiltinLabel _ | FormalLabel _ -> + true let for_stmt env kf stmt = + Options.debug ~level:4 "pre-translating ats for stmt %d at %a" + stmt.sid + Printer.pp_location (Stmt.loc stmt); + + (* At the start of a function, reset the set of defined C labels. *) + if Kernel_function.is_first_stmt kf stmt then + clabels_ref := Logic_label.Set.empty; + + (* If the current statement has labels, add the C label to the set. *) + begin match stmt.labels with + | [] -> () + | _ :: _ -> + clabels_ref := Logic_label.Set.add (StmtLabel (ref stmt)) !clabels_ref + end; + + (* Retrieve the set of [\at()] to translate for the given statement. *) let at_for_stmt = Error.retrieve_preprocessing - "blabla" - Labels.Translation.at_for_stmt + "labels pre-analysis" + Labels.at_for_stmt stmt Printer.pp_stmt in - Options.debug ~level:4 "pre-translating %d ats for stmt %d at %a" - (List.length at_for_stmt) - stmt.sid - Printer.pp_location (Stmt.loc stmt); + + (* Translate the [\at()]. *) let stmt_translations = PredOrTerm.Hashtbl.create 7 in - List.fold_left - (fun env ((_, _, lscope, pot, _) as at_data) -> - let e_or_err, env = - try - match PredOrTerm.Hashtbl.find_opt stmt_translations pot with - | Some e_or_err -> e_or_err, env - | None -> + AtData.Set.fold + (fun ({ lscope; pot; error } as at_data) env -> + let vi_or_err, env = + let vi_or_err = PredOrTerm.Hashtbl.find_opt stmt_translations pot in + match error, vi_or_err with + | Some exn, (Some _ | None) -> + (* If there was an error during the pre-analysis, then store it + instead of the translation. *) + Result.Error exn, env + | None, Some vi_or_err -> + (* If the same [pred_or_term] has already been translated on this + statement, return its translation. *) + vi_or_err, env + | None, None -> + (* Otherwise translate it. *) + try let loc = Stmt.loc stmt in - let e, env = + let vi, env = if Lscope.is_used lscope pot then pretranslate_to_exp_with_lscope ~loc ~lscope kf env pot else pretranslate_to_exp ~loc kf env pot in - (Result.Ok (Labels.Translation.Done e)), env - with Error.(Typing_error _ | Not_yet _) as exn -> - (Result.Error exn), env + Result.Ok vi, env + with Error.(Typing_error _ | Not_yet _) as exn -> + Result.Error exn, env in - PredOrTerm.Hashtbl.replace stmt_translations pot e_or_err; - Labels.Translation.set ~force:true at_data e_or_err; + PredOrTerm.Hashtbl.replace stmt_translations pot vi_or_err; + AtData.Hashtbl.replace translations at_data vi_or_err; env) - env at_for_stmt + env let to_exp ~loc ~adata kf env pot label = let kinstr = Env.get_kinstr env in let lscope = Env.Logic_scope.get env in - try - let e_or_err = Labels.Translation.get (kf, kinstr, lscope, pot, label) in - let e, adata, env = - match e_or_err with - | Result.Ok (Labels.Translation.Done e) -> + let at = AtData.create kf kinstr lscope pot label in + if is_label_defined label then + try + let vi_or_err = AtData.Hashtbl.find translations at in + match vi_or_err with + | Result.Ok vi -> let e, env = if Lscope.is_used lscope pot then - indexed_exp ~loc kf env e + indexed_exp ~loc kf env (Smart_exp.lval ~loc (Cil.var vi)) else - e, env + Smart_exp.lval ~loc (Cil.var vi), env in - let adata, env = + let adata, env= Assert.register_pred_or_term ~loc env pot e adata in e, adata, env - | Result.Ok Labels.Translation.Inplace -> begin - match pot with - | PoT_term t -> !term_to_exp_ref ~adata ~inplace:true kf env t - | PoT_pred p -> !predicate_to_exp_ref ~adata ~inplace:true kf env p - end - | Result.Ok Labels.Translation.Queued -> - let potstr = - match pot with PoT_term _ -> "term" | PoT_pred _ -> "predicate" - in - Options.abort ~source:(fst loc) - "%s '%a' was used before being translated.@ \ - This usually happen when using a label defined after the place@ \ - where the %s should be translated" - potstr - PredOrTerm.pretty pot - potstr | Result.Error exn -> Env.Context.save env; raise exn + with Not_found ->begin + match pot with + | PoT_term t -> !term_to_exp_ref ~adata ~inplace:true kf env t + | PoT_pred p -> !predicate_to_exp_ref ~adata ~inplace:true kf env p + end + else + let potstr = + match pot with PoT_term _ -> "Term" | PoT_pred _ -> "Predicate" in - e, adata, env - with Not_found -> - Options.fatal ~source:(fst loc) "no translation for %a" - Labels.pp_at_data (kf, kinstr, lscope, pot, label) + Options.abort ~source:(fst loc) + "%s '%a' was used before being translated.@ \ + This usually happens when using a label defined after the place@ \ + where the %s should be translated" + potstr + PredOrTerm.pretty pot + potstr + +let reset () = + AtData.Hashtbl.clear translations; + clabels_ref := Logic_label.Set.empty diff --git a/src/plugins/e-acsl/src/code_generator/translate_ats.mli b/src/plugins/e-acsl/src/code_generator/translate_ats.mli index 1fc909f3536..a975de1732c 100644 --- a/src/plugins/e-acsl/src/code_generator/translate_ats.mli +++ b/src/plugins/e-acsl/src/code_generator/translate_ats.mli @@ -46,6 +46,9 @@ val to_exp: The expression is either translated in-place or retrieved from a pre-translation phase. *) +val reset: unit -> unit +(** Clear the stored translations. *) + (*****************************************************************************) (**************************** Handling memory ********************************) (*****************************************************************************) -- GitLab