From 48142bf8e3acc717d2cb519ea3a0f6e7a344330b Mon Sep 17 00:00:00 2001 From: Thibaut Benjamin <thibaut.benjamin@cea.fr> Date: Wed, 8 Sep 2021 10:10:30 +0200 Subject: [PATCH] [e-acsl] separate files for assigns clause generation --- src/plugins/e-acsl/Makefile.in | 1 + .../e-acsl/src/code_generator/genassigns.ml | 90 +++++++++++++++++++ .../e-acsl/src/code_generator/genassigns.mli | 37 ++++++++ .../src/code_generator/logic_functions.ml | 73 +-------------- 4 files changed, 131 insertions(+), 70 deletions(-) create mode 100644 src/plugins/e-acsl/src/code_generator/genassigns.ml create mode 100644 src/plugins/e-acsl/src/code_generator/genassigns.mli diff --git a/src/plugins/e-acsl/Makefile.in b/src/plugins/e-acsl/Makefile.in index 18869a85f29..914074b0c6b 100644 --- a/src/plugins/e-acsl/Makefile.in +++ b/src/plugins/e-acsl/Makefile.in @@ -83,6 +83,7 @@ SRC_CODE_GENERATOR:= \ assert \ rational \ typed_number \ + genassigns \ logic_functions \ loops \ quantif \ diff --git a/src/plugins/e-acsl/src/code_generator/genassigns.ml b/src/plugins/e-acsl/src/code_generator/genassigns.ml new file mode 100644 index 00000000000..630786709a2 --- /dev/null +++ b/src/plugins/e-acsl/src/code_generator/genassigns.ml @@ -0,0 +1,90 @@ +(**************************************************************************) +(* *) +(* This file is part of the Frama-C's E-ACSL plug-in. *) +(* *) +(* Copyright (C) 2012-2020 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It is distributed in the hope that it will be useful, *) +(* but WITHOUT ANY WARRANTY; without even the implied warranty of *) +(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) +(* GNU Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +open Cil_types + +exception NoAssigns + +(*****************************************************************************) +(****************** Generation of function assigns ***************************) +(*****************************************************************************) + +(* If an argument contains a pointer type, then it is undecidable which assigns + clause should be generated, so skip the assigns generation in this case *) +let rec is_ptr_free typ = match Cil.unrollType typ with + | TVoid _ + | TInt (_, _) + | TFloat (_, _) -> true + | TPtr (_, _) -> false + | TArray (ty, _, _, _) -> is_ptr_free ty + | TFun (_, _, _, _) -> + (* a function cannot be an argument of a function *) + assert false + | TNamed (_, _) -> + (* The named types are unfolded with [Cil.unrolltype] *) + assert false + | TEnum (_, _) + | TBuiltin_va_list _ -> true + | TComp (cinfo, _, _) -> + match cinfo.cfields with + | None -> raise NoAssigns + | Some fields -> + List.for_all + (fun fi -> fi.fbitfield <> None || is_ptr_free fi.ftype) + fields + +(* For a GMP argument of a function, we generate an assigns from its address, + since these are the only semantically valid operations on integers. + For the argument [__e_acsl_mpz_struct * x], this function generates the + expression [*(( __e_acsl_mpz_struct * )x)] *) +let deref_gmp_arg ~loc var = + Smart_exp.lval ~loc + (Mem (Cil.mkAddrOrStartOf ~loc (Var var , NoOffset)), NoOffset) + +let rec get_assigns_from ~loc env lprofile lv = + match lprofile with + | [] -> [] + | lvar :: lvars -> + let var = Env.Logic_binding.get env lvar in + if is_ptr_free var.vtype then + Smart_exp.lval ~loc (Cil.var var) :: get_assigns_from ~loc env lvars lv + (* If the argument contains a pointer, but is an integer, then it is + necessarily a GMP type *) + else if lvar.lv_type = Linteger then + (deref_gmp_arg ~loc var) :: (get_assigns_from ~loc env lvars lv) + else begin + Options.warning ~current:true "skipping function %a when generating\ + assigns because pointers as arguments\ + is not yet supported" + Printer.pp_logic_var lv; + raise NoAssigns + end + +(* Special case when the function takes an extra argument as its result: + For the argument [__e_acsl_mpz_t *__retres_arg], this function generates the + expression [( *__retres_arg )[0]] *) +let get_gmp_integer ~loc vi = + Smart_exp.lval + ~loc + (Mem + (Smart_exp.lval ~loc (Var vi, NoOffset)), + (Index (Cil.zero ~loc, NoOffset))) diff --git a/src/plugins/e-acsl/src/code_generator/genassigns.mli b/src/plugins/e-acsl/src/code_generator/genassigns.mli new file mode 100644 index 00000000000..a770607bd2c --- /dev/null +++ b/src/plugins/e-acsl/src/code_generator/genassigns.mli @@ -0,0 +1,37 @@ +(**************************************************************************) +(* *) +(* This file is part of the Frama-C's E-ACSL plug-in. *) +(* *) +(* Copyright (C) 2012-2020 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It is distributed in the hope that it will be useful, *) +(* but WITHOUT ANY WARRANTY; without even the implied warranty of *) +(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) +(* GNU Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +exception NoAssigns + +val get_assigns_from : + loc:Cil_types.location -> + Env.t -> + Cil_types.logic_var list -> + Cil_types.logic_var -> + Cil_types.exp list +(* @returns the list of expressions that are allowed to be used to assign the + the result of a logic function *) + +val get_gmp_integer : + loc:Cil_types.location -> Cil_types.varinfo -> Cil_types.exp +(* @returns the expression that gets assigned when the result of the function is + a pointer on a GMP type *) 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 f442c14ec6c..dfb58431806 100644 --- a/src/plugins/e-acsl/src/code_generator/logic_functions.ml +++ b/src/plugins/e-acsl/src/code_generator/logic_functions.ml @@ -23,8 +23,6 @@ open Cil_types open Cil_datatype -exception NoAssigns - (**************************************************************************) (********************** Forward references ********************************) (**************************************************************************) @@ -58,71 +56,6 @@ let result_as_extra_argument = Gmp_types.Z.is_t (* TODO: to be extended to any compound type? E.g. returning a struct is not good practice... *) -(*****************************************************************************) -(****************** Generation of function assigns ***************************) -(*****************************************************************************) - -(* If an argument contains a pointer type, then it is undecidable which assigns - clause should be generated, so skip the assigns generation in this case *) -let rec is_ptr_free typ = match Cil.unrollType typ with - | TVoid _ - | TInt (_, _) - | TFloat (_, _) -> true - | TPtr (_, _) -> false - | TArray (ty, _, _, _) -> is_ptr_free ty - | TFun (_, _, _, _) -> - (* a function cannot be an argument of a function *) - assert false - | TNamed (_, _) -> - (* The named types are unfolded with [Cil.unrolltype] *) - assert false - | TEnum (_, _) - | TBuiltin_va_list _ -> true - | TComp (cinfo, _, _) -> - match cinfo.cfields with - | None -> raise NoAssigns - | Some fields -> - List.for_all - (fun fi -> fi.fbitfield <> None || is_ptr_free fi.ftype) - fields - -(* For a GMP argument of a function, we generate an assigns from its address, - since these are the only semantically valid operations on integers. - For the argument [__e_acsl_mpz_struct * x], this function generates the - expression [*(( __e_acsl_mpz_struct * )x)] *) -let deref_gmp_arg ~loc var = - Smart_exp.lval ~loc - (Mem (Cil.mkAddrOrStartOf ~loc (Var var , NoOffset)), NoOffset) - -let rec get_assigns_from ~loc env lprofile lv = - match lprofile with - | [] -> [] - | lvar :: lvars -> - let var = Env.Logic_binding.get env lvar in - if is_ptr_free var.vtype then - Smart_exp.lval ~loc (Cil.var var) :: get_assigns_from ~loc env lvars lv - (* If the argument contains a pointer, but is an integer, then it is - necessarily a GMP type *) - else if lvar.lv_type = Linteger then - (deref_gmp_arg ~loc var) :: (get_assigns_from ~loc env lvars lv) - else begin - Options.warning ~current:true "skipping function %a when generating\ - assigns because pointers as arguments\ - is not yet supported" - Printer.pp_logic_var lv; - raise NoAssigns - end - -(* Special case when the function takes an extra argument as its result: - For the argument [__e_acsl_mpz_t *__retres_arg], this function generates the - expression [( *__retres_arg )[0]] *) -let get_gmp_integer ~loc vi = - Smart_exp.lval - ~loc - (Mem - (Smart_exp.lval ~loc (Var vi, NoOffset)), - (Index (Cil.zero ~loc, NoOffset))) - (*****************************************************************************) (****************** Generation of function bodies ****************************) (*****************************************************************************) @@ -281,13 +214,13 @@ let generate_kf ~loc fname env ret_ty params_ty li = List.fold_left2 add env li.l_profile params in let assigns_from = - try Some (get_assigns_from ~loc env li.l_profile li.l_var_info) - with NoAssigns -> None + try Some (Genassigns.get_assigns_from ~loc env li.l_profile li.l_var_info) + with Genassigns.NoAssigns -> None in let assigned_var = Logic_const.new_identified_term (if res_as_extra_arg then - Logic_utils.expr_to_term (get_gmp_integer ~loc ret_vi) + Logic_utils.expr_to_term (Genassigns.get_gmp_integer ~loc ret_vi) else Logic_const.tresult fundec.svar.vtype) in -- GitLab