From 7f1bcb820fcae3b4ea36f57b2fa727298aeb6f67 Mon Sep 17 00:00:00 2001
From: Allan Blanchard <allan.blanchard@cea.fr>
Date: Tue, 24 Sep 2019 14:49:24 +0200
Subject: [PATCH] [Override Std] Simplifies spec generation

---
 src/plugins/override_std/basic_blocks.ml    | 33 +++++++++++++++++++++
 src/plugins/override_std/basic_blocks.mli   | 18 +++++++++++
 src/plugins/override_std/memcmp.ml          | 25 +++++-----------
 src/plugins/override_std/memcpy.ml          | 25 +++++-----------
 src/plugins/override_std/override_table.ml  | 10 +++++--
 src/plugins/override_std/override_table.mli |  2 +-
 6 files changed, 73 insertions(+), 40 deletions(-)

diff --git a/src/plugins/override_std/basic_blocks.ml b/src/plugins/override_std/basic_blocks.ml
index 03456bd5299..2ea6dd4db1f 100644
--- a/src/plugins/override_std/basic_blocks.ml
+++ b/src/plugins/override_std/basic_blocks.ml
@@ -138,3 +138,36 @@ let pseparated_memories ?loc p1 len1 p2 len2 =
   let b1 = tbuffer_range ?loc p1 len1 in
   let b2 = tbuffer_range ?loc p2 len2 in
   pseparated ?loc [ b1 ; b2 ]
+
+let make_behavior
+    ?(name=Cil.default_behavior_name)
+    ?(assumes=[]) ?(requires=[]) ?(ensures=[])?(assigns=WritesAny)
+    ?(alloc=FreeAllocAny) ?(extension=[])
+    () =
+  {
+    b_name = name ;
+    b_requires = requires ;
+    b_assumes = assumes ;
+    b_post_cond = ensures ;
+    b_assigns = assigns ;
+    b_allocation = alloc;
+    b_extended = extension
+  }
+
+let default_comp_disj bhvs =
+  let b_names = List.filter (fun b -> not (String.equal Cil.default_behavior_name b))
+      (List.fold_left (fun l b -> b.b_name :: l) [] bhvs)
+  in match b_names with
+  | [] -> [], []
+  | _  -> [b_names], [b_names]
+
+let make_funspec bhvs ?(termination=None)
+    ?(complete_disjoint=(default_comp_disj bhvs)) () =
+  let complete, disjoint = complete_disjoint in
+  {
+    spec_behavior = bhvs ;
+    spec_variant = None ;
+    spec_terminates = termination ;
+    spec_complete_behaviors = complete ;
+    spec_disjoint_behaviors = disjoint
+  }
diff --git a/src/plugins/override_std/basic_blocks.mli b/src/plugins/override_std/basic_blocks.mli
index 396374230ce..f0eb5ad242c 100644
--- a/src/plugins/override_std/basic_blocks.mli
+++ b/src/plugins/override_std/basic_blocks.mli
@@ -46,3 +46,21 @@ val pseparated_memories: ?loc:location -> term -> term -> term -> term -> predic
 
 val plet_len_div_size:
   ?loc:location -> logic_type -> term -> (term -> predicate) -> predicate
+
+val make_behavior:
+  ?name:string ->
+  ?assumes:identified_predicate list ->
+  ?requires:identified_predicate list ->
+  ?ensures:(termination_kind * identified_predicate) list ->
+  ?assigns:assigns ->
+  ?alloc:allocation ->
+  ?extension:acsl_extension list ->
+  unit ->
+  behavior
+
+val make_funspec:
+  behavior list ->
+  ?termination:identified_predicate option ->
+  ?complete_disjoint:(string list list * string list list) ->
+  unit ->
+  funspec
diff --git a/src/plugins/override_std/memcmp.ml b/src/plugins/override_std/memcmp.ml
index 6ed6fc00fbb..39ede274dbb 100644
--- a/src/plugins/override_std/memcmp.ml
+++ b/src/plugins/override_std/memcmp.ml
@@ -66,8 +66,11 @@ let generate_ensures loc s1 s2 len =
     { (presult_memcmp_len_bytes ~loc s1 s2 len) with pred_name = [ "equals" ] }
   ]
 
-let generate_spec loc kf c_s1 c_s2 clen =
-  Kernel.feedback "Spec for: %a" Kernel_function.pretty kf ;
+let generate_spec vi loc =
+  let (c_s1, c_s2, clen) = match Cil.getFormalsDecl vi with
+    | [ s1 ; s2 ; len ] -> s1, s2, len
+    | _ -> assert false
+  in
   let t = c_s1.vtype in
   let s1 = cvar_to_tvar c_s1 in
   let s2 = cvar_to_tvar c_s2 in
@@ -75,21 +78,7 @@ let generate_spec loc kf c_s1 c_s2 clen =
   let requires = generate_requires loc s1 s2 len in
   let assigns  = generate_assigns loc t s1 s2 len in
   let ensures  = generate_ensures loc s1 s2 len in
-  Annotations.add_requires Options.emitter kf requires ;
-  Annotations.add_assigns ~keep_empty:false Options.emitter kf assigns ;
-  Annotations.add_ensures Options.emitter kf ensures ;
-  ()
-
-let finalize_override vi loc =
-  let spec = Cil.empty_funspec () in
-  Globals.Functions.replace_by_declaration spec vi loc ;
-  let kf = Globals.Functions.get vi in
-  let (s1, s2, len) = match Cil.getFormalsDecl vi with
-    | [ s1 ; s2 ; len ] -> s1, s2, len
-    | _ -> assert false
-  in
-  generate_spec loc kf s1 s2 len ;
-  GFunDecl(spec, vi, loc)
+  make_funspec [make_behavior ~requires ~assigns ~ensures ()] ()
 
 let generate_prototype t =
   let name = function_name ^ "_" ^ (string_of_typ t) in
@@ -107,7 +96,7 @@ let generate_prototype t =
 module Table = Override_table.Make(struct
     let function_name = function_name
     let build_prototype = generate_prototype
-    let finalize = finalize_override
+    let build_spec = generate_spec
   end)
 
 let type_from_parameter x =
diff --git a/src/plugins/override_std/memcpy.ml b/src/plugins/override_std/memcpy.ml
index 125339b2713..f54cb0fd0a2 100644
--- a/src/plugins/override_std/memcpy.ml
+++ b/src/plugins/override_std/memcpy.ml
@@ -68,8 +68,11 @@ let generate_ensures loc dest src len =
     { (pcopied_len_bytes ~loc dest src len) with pred_name = [ "copied"] }
   ]
 
-let generate_spec loc kf cdest csrc clen =
-  Kernel.feedback "Spec for: %a" Kernel_function.pretty kf ;
+let generate_spec vi loc =
+  let (cdest, csrc, clen) = match Cil.getFormalsDecl vi with
+    | [ dest ; src ; len ] -> dest, src, len
+    | _ -> assert false
+  in
   let t = cdest.vtype in
   let dest = cvar_to_tvar cdest in
   let src = cvar_to_tvar csrc in
@@ -77,21 +80,7 @@ let generate_spec loc kf cdest csrc clen =
   let requires = generate_requires loc dest src len in
   let assigns  = generate_assigns loc t dest src len in
   let ensures  = generate_ensures loc dest src len in
-  Annotations.add_requires Options.emitter kf requires ;
-  Annotations.add_assigns ~keep_empty:false Options.emitter kf assigns ;
-  Annotations.add_ensures Options.emitter kf ensures ;
-  ()
-
-let finalize_override vi loc =
-  let spec = Cil.empty_funspec () in
-  Globals.Functions.replace_by_declaration spec vi loc ;
-  let kf = Globals.Functions.get vi in
-  let (dest, src, len) = match Cil.getFormalsDecl vi with
-    | [ dest ; src ; len ] -> dest, src, len
-    | _ -> assert false
-  in
-  generate_spec loc kf dest src len ;
-  GFunDecl(spec, vi, loc)
+  make_funspec [make_behavior ~requires ~assigns ~ensures ()] ()
 
 let generate_prototype t =
   let name = function_name ^ "_" ^ (string_of_typ t) in
@@ -110,7 +99,7 @@ let generate_prototype t =
 module Table = Override_table.Make(struct
     let function_name = function_name
     let build_prototype = generate_prototype
-    let finalize = finalize_override
+    let build_spec = generate_spec
   end)
 
 let type_from_parameter x =
diff --git a/src/plugins/override_std/override_table.ml b/src/plugins/override_std/override_table.ml
index bb0daaae617..d9acb213bdc 100644
--- a/src/plugins/override_std/override_table.ml
+++ b/src/plugins/override_std/override_table.ml
@@ -29,7 +29,7 @@ end
 module type Override_generator = sig
   val function_name: String.t
   val build_prototype: Cil_types.typ -> Cil_types.varinfo
-  val finalize: Cil_types.varinfo -> Cil_types.location -> Cil_types.global
+  val build_spec: Cil_types.varinfo -> Cil_types.location -> Cil_types.funspec
 end
 
 module Make_internal_table (M: Override_generator) =
@@ -51,8 +51,12 @@ module Make (Generator: Override_generator) = struct
       fct
 
   let get_globals loc =
-    let add_global _ vi l = (Generator.finalize vi loc) :: l in
-    Internal_table.fold add_global []
+    let finalize vi =
+      let spec = Generator.build_spec vi loc in
+      Globals.Functions.replace_by_declaration spec vi loc ;
+      Cil_types.GFunDecl(Cil.empty_funspec(), vi, loc)
+    in
+    Internal_table.fold (fun _ vi l -> (finalize vi) :: l) []
 
   let mark_as_computed = Internal_table.mark_as_computed
 end
diff --git a/src/plugins/override_std/override_table.mli b/src/plugins/override_std/override_table.mli
index e7d42d245a0..9be836b5d99 100644
--- a/src/plugins/override_std/override_table.mli
+++ b/src/plugins/override_std/override_table.mli
@@ -23,7 +23,7 @@
 module type Override_generator = sig
   val function_name: String.t
   val build_prototype: Cil_types.typ -> Cil_types.varinfo
-  val finalize: Cil_types.varinfo -> Cil_types.location -> Cil_types.global
+  val build_spec: Cil_types.varinfo -> Cil_types.location -> Cil_types.funspec
 end
 
 module type Table = sig
-- 
GitLab