From 638dca648dba9c79e2bd52869645b756f58311d5 Mon Sep 17 00:00:00 2001 From: Allan Blanchard <allan.blanchard@cea.fr> Date: Fri, 27 Mar 2020 16:41:28 +0100 Subject: [PATCH] [Instantiate] Introduces globals variables table --- src/plugins/instantiate/Instantiate.mli | 11 +++ src/plugins/instantiate/Makefile.in | 4 +- src/plugins/instantiate/global_vars.ml | 40 ++++++++++ src/plugins/instantiate/global_vars.mli | 42 +++++++++++ src/plugins/instantiate/stdlib/basic_alloc.ml | 4 +- .../instantiate/tests/plugin/needs_global.i | 14 ++++ .../instantiate/tests/plugin/needs_globals.ml | 75 +++++++++++++++++++ .../plugin/oracle/needs_global.res.oracle | 34 +++++++++ src/plugins/instantiate/transform.ml | 2 + 9 files changed, 223 insertions(+), 3 deletions(-) create mode 100644 src/plugins/instantiate/global_vars.ml create mode 100644 src/plugins/instantiate/global_vars.mli create mode 100644 src/plugins/instantiate/tests/plugin/needs_global.i create mode 100644 src/plugins/instantiate/tests/plugin/needs_globals.ml create mode 100644 src/plugins/instantiate/tests/plugin/oracle/needs_global.res.oracle diff --git a/src/plugins/instantiate/Instantiate.mli b/src/plugins/instantiate/Instantiate.mli index d47de410b8f..4af9d03fc53 100644 --- a/src/plugins/instantiate/Instantiate.mli +++ b/src/plugins/instantiate/Instantiate.mli @@ -100,3 +100,14 @@ module Transform: sig *) val register: (module Instantiator_builder.Generator_sig) -> unit end + +module Global_vars:sig + (** [get t ghost storage name] searches for an existing variable [name]. If this + variable does not exists, it is created with the specified type [t], [ghost] + status and [storage]. + + The obtained varinfo does not need to be registered, it will be done by the + transformation. + *) + val get: typ -> bool -> storage -> string -> varinfo +end \ No newline at end of file diff --git a/src/plugins/instantiate/Makefile.in b/src/plugins/instantiate/Makefile.in index a8fc2764589..97c0b467e45 100644 --- a/src/plugins/instantiate/Makefile.in +++ b/src/plugins/instantiate/Makefile.in @@ -56,7 +56,9 @@ PLUGIN_EXTRA_DIRS:=\ stdlib PLUGIN_CMI := PLUGIN_CMO := \ - options basic_blocks instantiator_builder transform register \ + options basic_blocks \ + global_vars instantiator_builder \ + transform register \ $(SRC_STRING) \ $(SRC_STDLIB) diff --git a/src/plugins/instantiate/global_vars.ml b/src/plugins/instantiate/global_vars.ml new file mode 100644 index 00000000000..379443e789b --- /dev/null +++ b/src/plugins/instantiate/global_vars.ml @@ -0,0 +1,40 @@ +(**************************************************************************) +(* *) +(* This file is part of Frama-C. *) +(* *) +(* Copyright (C) 2007-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). *) +(* *) +(**************************************************************************) + +module Table = Datatype.String.Hashtbl +let table = Table.create 13 + +let get typ ghost storage name = + if Table.mem table name then Table.find table name + else begin + try Globals.Vars.find_from_astinfo name VGlobal + with Not_found -> + let vi = Cil.makeVarinfo ~ghost true false name typ in + vi.vstorage <- storage ; + Table.add table name vi ; + vi + end + +let clear () = Table.clear table + +let globals loc = + Table.fold (fun _ x l -> Cil_types.GVarDecl(x, loc) :: l) table [] diff --git a/src/plugins/instantiate/global_vars.mli b/src/plugins/instantiate/global_vars.mli new file mode 100644 index 00000000000..88b711593ce --- /dev/null +++ b/src/plugins/instantiate/global_vars.mli @@ -0,0 +1,42 @@ +(**************************************************************************) +(* *) +(* This file is part of Frama-C. *) +(* *) +(* Copyright (C) 2007-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 + +(** The purpose of this module is to create global variables when it is needed + by instantiation modules. +*) + +(** [get t ghost storage name] searches for an existing variable [name]. If this + variable does not exists, it is created with the specified type [t], [ghost] + status and [storage]. + + The obtained varinfo does not need to be registered, it will be done by the + transformation. +*) +val get: typ -> bool -> storage -> string -> varinfo + +(** Clears internal tables *) +val clear: unit -> unit + +(** Creates a list of global for the variables that have been created *) +val globals: location -> global list diff --git a/src/plugins/instantiate/stdlib/basic_alloc.ml b/src/plugins/instantiate/stdlib/basic_alloc.ml index 41679ef1d11..d2bb11bd72d 100644 --- a/src/plugins/instantiate/stdlib/basic_alloc.ml +++ b/src/plugins/instantiate/stdlib/basic_alloc.ml @@ -61,8 +61,8 @@ let isnt_allocable ?loc size = new_predicate { p with pred_name = [ "allocable" ]} let heap_status () = - let heap_status = Globals.Vars.find_from_astinfo "__fc_heap_status" VGlobal in - Basic_blocks.cvar_to_tvar (heap_status) + let vi = Global_vars.get Cil.intType true Extern "__fc_heap_status" in + Basic_blocks.cvar_to_tvar vi let assigns_result ?loc typ deps = let heap_status = new_identified_term (heap_status ()) in diff --git a/src/plugins/instantiate/tests/plugin/needs_global.i b/src/plugins/instantiate/tests/plugin/needs_global.i new file mode 100644 index 00000000000..dfd53797477 --- /dev/null +++ b/src/plugins/instantiate/tests/plugin/needs_global.i @@ -0,0 +1,14 @@ +/* run.config + OPT: -load-script tests/plugin/needs_globals.ml -instantiate -check -print +*/ + +int i ; // needed for already_one specifciation +void already_one(void* parameter) ; + +void needs_new(void* parameter) ; + +void foo(void){ + int *i ; + already_one(i); + needs_new(i); +} diff --git a/src/plugins/instantiate/tests/plugin/needs_globals.ml b/src/plugins/instantiate/tests/plugin/needs_globals.ml new file mode 100644 index 00000000000..c76373900f5 --- /dev/null +++ b/src/plugins/instantiate/tests/plugin/needs_globals.ml @@ -0,0 +1,75 @@ +let well_typed_call _ _ = function + | [ e ] -> + let t = Cil.typeOf(Cil.stripCasts e) in + not (Cil.isVoidPtrType t) && Cil.isPointerType t + | _ -> false + +let key_from_call _ _ = function + | [ e ] -> Cil.typeOf_pointed (Cil.typeOf(Cil.stripCasts e)) + | _ -> assert false + +let retype_args _ = function + | [ e ] -> [ Cil.stripCasts e ] + | _ -> assert false + +let generate_function_type t = + let params = [("x", Cil_types.TPtr(t, []), [])] in + Cil_types.TFun(Cil.voidType, Some params, false, []) + +let generate_prototype function_name t = + let fun_type = generate_function_type t in + let name = function_name ^ "_" ^ match t with + | Cil_types.TInt(_) -> "int" + | _ -> assert false (* nothing else in our test *) + in + name, fun_type + +let generate_spec needed _ _ _ = + let open Cil_types in + let open Logic_const in + let open Instantiate.Global_vars in + let vi = get Cil.floatType true Cil_types.Extern needed in + let t = tvar (Cil.cvar_to_lvar vi) in + let assigns = + Cil_types.Writes [ Logic_const.new_identified_term t, From [] ] + in { + spec_behavior = [ { + b_name = Cil.default_behavior_name ; + b_requires = [] ; + b_assumes = [] ; + b_post_cond = [] ; + b_assigns = assigns ; + b_allocation = FreeAllocAny ; + b_extended = [] + } ] ; + spec_variant = None ; + spec_terminates = None ; + spec_complete_behaviors = [] ; + spec_disjoint_behaviors = [] ; + } + +let () = Instantiate.Transform.register (module struct + module Hashtbl = Cil_datatype.Typ.Hashtbl + type override_key = Hashtbl.key + + let function_name = "already_one" + let well_typed_call = well_typed_call + let key_from_call = key_from_call + let retype_args = retype_args + let generate_prototype = generate_prototype function_name + let generate_spec = generate_spec "i" + let args_for_original _ = Extlib.id + end) + +let () = Instantiate.Transform.register (module struct + module Hashtbl = Cil_datatype.Typ.Hashtbl + type override_key = Hashtbl.key + + let function_name = "needs_new" + let well_typed_call = well_typed_call + let key_from_call = key_from_call + let retype_args = retype_args + let generate_prototype = generate_prototype function_name + let generate_spec = generate_spec "j" + let args_for_original _ = Extlib.id + end) diff --git a/src/plugins/instantiate/tests/plugin/oracle/needs_global.res.oracle b/src/plugins/instantiate/tests/plugin/oracle/needs_global.res.oracle new file mode 100644 index 00000000000..0b7e5b4ccb7 --- /dev/null +++ b/src/plugins/instantiate/tests/plugin/oracle/needs_global.res.oracle @@ -0,0 +1,34 @@ +[kernel] Parsing tests/plugin/needs_global.i (no preprocessing) +/* Generated by Frama-C */ +/*@ ghost extern float j; */ + +int i; +void already_one(void *parameter); + +void needs_new(void *parameter); + +/*@ assigns j; + assigns j \from \nothing; */ +void needs_new_int(int *x) +{ + needs_new((void *)x); + return; +} + +/*@ assigns i; + assigns i \from \nothing; */ +void already_one_int(int *x) +{ + already_one((void *)x); + return; +} + +void foo(void) +{ + int *i_0; + already_one_int(i_0); + needs_new_int(i_0); + return; +} + + diff --git a/src/plugins/instantiate/transform.ml b/src/plugins/instantiate/transform.ml index 4970a5913e2..8b0f9ece40e 100644 --- a/src/plugins/instantiate/transform.ml +++ b/src/plugins/instantiate/transform.ml @@ -38,6 +38,7 @@ let get_kfs () = Hashtbl.fold (fun k v l -> (get_kfs k v) @ l) base [] let clear () = + Global_vars.clear () ; let clear _ instantiator = let module I = (val instantiator: Instantiator) in I.clear () @@ -54,6 +55,7 @@ class transformer = object(self) method! vfile _ = let post f = + f.globals <- (Global_vars.globals (Cil.CurrentLoc.get())) @ f.globals ; Ast.mark_as_changed () ; Ast.mark_as_grown () ; f -- GitLab