From 660e007da88b9b09c8f1d2a9ba77a119c14ab646 Mon Sep 17 00:00:00 2001
From: Allan Blanchard <allan.blanchard@cea.fr>
Date: Thu, 24 Oct 2019 17:18:55 +0200
Subject: [PATCH] [Builtin] Small fix + Doc

---
 src/plugins/builtin/README.md                 | 130 +++++++++++++++
 src/plugins/builtin/basic_blocks.ml           |   6 +-
 src/plugins/builtin/basic_blocks.mli          | 155 +++++++++++++++++-
 src/plugins/builtin/options.mli               |   7 +
 .../tests/stdlib/oracle/calloc.res.oracle     |  20 +--
 .../tests/stdlib/oracle/malloc.res.oracle     |  16 +-
 .../tests/string/oracle/memcmp.res.oracle     |  10 +-
 .../tests/string/oracle/memcpy.res.oracle     |  13 +-
 .../tests/string/oracle/memmove.res.oracle    |  13 +-
 .../tests/string/oracle/memset_0.res.oracle   |  12 +-
 .../tests/string/oracle/memset_FF.res.oracle  |  12 +-
 src/plugins/builtin/transform.mli             |  12 ++
 12 files changed, 348 insertions(+), 58 deletions(-)
 create mode 100644 src/plugins/builtin/README.md

diff --git a/src/plugins/builtin/README.md b/src/plugins/builtin/README.md
new file mode 100644
index 00000000000..ffdc7099383
--- /dev/null
+++ b/src/plugins/builtin/README.md
@@ -0,0 +1,130 @@
+# Builtin plugin
+
+## Description
+
+The builtin plugin is meant to build function specialization to C functions in
+a project when the original specification (or prototype of the function) cannot
+be efficiently used by some plugins.
+
+For example, the specification of a function like `memcpy` cannot be efficiently
+used by a plugin like `WP` because it involves `void*` pointers and requires to
+deduce that bytes equality implies (typed) data equality. While for example it
+is easy to produce a typed specification for a type `int`:
+
+```c
+/*@ requires valid_dest: \valid(dest + (0 .. len-1));
+    requires valid_read_src: \valid_read(src + (0 .. len-1));
+    requires separation: \separated(dest + (0 .. len-1), src + (0 .. len-1));
+    ensures copied: ∀ ℤ j0; 0 ≤ j0 < len ⇒ *(dest + j0) ≡ *(src + j0);
+    ensures result: \result ≡ dest;
+    assigns *(dest + (0 .. len - 1)), \result;
+    assigns *(dest + (0 .. len - 1)) \from *(src + (0 .. len - 1));
+    assigns \result \from dest;
+ */
+int *memcpy_int(int *dest, int const *src, size_t len);
+```
+
+That can be easily used by WP.
+
+The role of the Builtin plugin is to find each call for which a builtin
+generator is available and if the call is well-typed according to the generator
+(for example for `memcpy` if `dest` and `src` are both pointers to integers), to
+replace this call with a call to an automatically generated specialization
+corresponding to the call.
+
+## Options
+
+- `-builtin` activate builtin replacement
+- `-builtin-fct=f,...` only replace calls in specified functions (default to all)
+- `-builtin-(no-)<function_name>` activate or deactivate a particular builtin
+  function, defaults to true.
+
+## Available builtin functions
+
+### `string.h`
+
+```c
+int memcmp(void const* s1, void const* s2, size_t len);
+```
+
+The parameters `s1` and `s2` must have the same types, except that qualifiers
+and typedefs are ignored. The type of `s1` or `s2` cannot be `void*`.
+
+```c
+void* memcpy(void * dest, void const* src, size_t len);
+```
+
+The parameters `dest` and `src` must have the same types, except that qualifiers
+and typedefs are ignored. The type of `dest` or `src` cannot be `void*`.
+
+```c
+void* memmove(void * dest, void const* src, size_t len);
+```
+
+The parameters `dest` and `src` must have the same types, except that qualifiers
+and typedefs are ignored. The type of `dest` or `src` cannot be `void*`.
+
+```c
+void* memset(void * ptr, int value, size_t len);
+```
+
+If `ptr` is of `char*` type (include signed and unsigned variants), `value` must
+be a `char`.
+
+If `ptr` is of any other pointer type (except `void*`), `value` must be a
+constant that statically evaluates to `0x00` or `0xFF`.
+
+### `stdlib.h`
+
+```c
+void* calloc(size_t num, size_t size);
+
+{
+  type* res = calloc(...) ;
+}
+```
+
+`calloc` is typed according to the variable that receives its result. It must be
+a pointer type different from `void*`. If the pointed type has a flexible array
+member, `num` is assumed to evaluate to `1` (a precondition is created for this).
+
+```c
+void free(void* ptr);
+```
+
+The type of `ptr` must be different from `void*`.
+
+
+```c
+void* malloc(size_t num, size_t size);
+
+{
+  type* res = calloc(...) ;
+}
+```
+
+`malloc` is typed according to the variable that receives its result. It must be
+a pointer type different from `void*`.
+
+## Adding a new builtin
+
+To add a new builtin, one has to register a new module implementing the
+`Builtin_builder.Generator_sig` module type to the `Transform` module. The
+lasts steps of the code should look like:
+
+```ocaml
+let () = Transform.register (module struct
+    module Hashtbl = ...
+    type override_key = ...
+
+    let function_name = "my_builtin_function"
+    let well_typed_call = ...
+    let key_from_call = ...
+    let retype_args = ...
+    let generate_prototype = ...
+    let generate_spec = ...
+    let args_for_original = ...
+  end)
+```
+
+The role and types of each function is documented in `Builtin_builder.mli`.
\ No newline at end of file
diff --git a/src/plugins/builtin/basic_blocks.ml b/src/plugins/builtin/basic_blocks.ml
index ac48f23160f..2cddd187f02 100644
--- a/src/plugins/builtin/basic_blocks.ml
+++ b/src/plugins/builtin/basic_blocks.ml
@@ -51,6 +51,7 @@ let call_function lval vi args =
   Call(lval, (Cil.evar vi), args, loc)
 
 let rec string_of_typ_aux = function
+  | TVoid(_) -> "void"
   | TInt(IBool, _) -> "bool"
   | TInt(IChar, _) -> "char"
   | TInt(ISChar, _) -> "schar"
@@ -67,8 +68,9 @@ let rec string_of_typ_aux = function
   | TFloat(FDouble, _) -> "double"
   | TFloat(FLongDouble, _) -> "ldouble"
   | TPtr(t, _) -> "ptr_" ^ string_of_typ t
-  | TEnum (ei, _) -> ei.ename
-  | TComp (ci, _, _) -> ci.cname
+  | TEnum (ei, _) -> "e_" ^ ei.ename
+  | TComp (ci, _, _) when ci.cstruct -> "st_" ^ ci.cname
+  | TComp (ci, _, _) -> "un_" ^ ci.cname
   | TArray (t, Some e, _, _) ->
     "arr" ^ (string_of_exp e) ^ "_" ^ string_of_typ t
   | _ -> assert false
diff --git a/src/plugins/builtin/basic_blocks.mli b/src/plugins/builtin/basic_blocks.mli
index 890cd71cab3..b7547d10c24 100644
--- a/src/plugins/builtin/basic_blocks.mli
+++ b/src/plugins/builtin/basic_blocks.mli
@@ -22,44 +22,177 @@
 
 open Cil_types
 
+(** [string_of_typ t] returns a name generated from the given [t]. This is
+    basically the C name of the type except that:
+    - separator is ["_"],
+    - [unsigned] is ["u"]
+    - [[SIZE]] is ["arrSIZE"],
+    - [*] is ["ptr"],
+    - [enum] is ["e_"],
+    - [struct] is ["st_"],
+    - [union] is ["un_"]
+
+    For example for: [struct X ( * ) [10]], the name is ["ptr_arr10_st_X"].
+*)
+val string_of_typ: typ -> string
+
+(** Returns the type of pointed for a give logic_type *)
+val ttype_of_pointed: logic_type -> logic_type
+
+
+(** {2 C} *)
+
+(** For a type [T], returns [T*] *)
 val ptr_of: typ -> typ
+
+(** For a type [T], returns [T const] *)
 val const_of: typ -> typ
 
+(** Finds and returns [size_t] *)
 val size_t: unit -> typ
 
+(** Create a function definition from a name and a type
+    - [vdefined] is positionned to [true]
+    - formals are registered to FormalsDecl
+*)
 val prepare_definition: string -> typ -> fundec
+
+(** [call_function ret_lval vi args] creates an instruction
+    - [(ret_lval = ) vi.vname(args)].
+*)
 val call_function: lval option -> varinfo -> exp list -> instr
 
-val string_of_typ: typ -> string
 
-val ttype_of_pointed: logic_type -> logic_type
+(** {2 Terms} *)
 
+(** Builds a term from a varinfo *)
 val cvar_to_tvar: varinfo -> term
+
+(** [tunref_range ~loc ptr len] builds [*(ptr + (0 .. len-1))] *)
 val tunref_range: ?loc:location -> term -> term -> term
+
+(** [tplus ~loc t1 t2] builds [t1+t2] *)
 val tplus: ?loc:location -> term -> term -> term
+
+(** [tminus ~loc t1 t2] builds [t1-t2] *)
 val tminus: ?loc:location -> term -> term -> term
+
+(** [tdivide ~loc t1 t2] builds [t1/t2] *)
 val tdivide: ?loc:location -> term -> term -> term
 
+
+(** {2 Predicates} *)
+
+(** [pbounds_incl_excl ~loc low v up] builds [low <= v < up]. *)
 val pbounds_incl_excl: ?loc:location -> term -> term -> term -> predicate
-val pvalid_len_bytes: ?loc:location -> logic_label -> term -> term -> predicate
-val pvalid_read_len_bytes:
-  ?loc:location -> logic_label -> term -> term -> predicate
-val pcorrect_len_bytes: ?loc:location -> logic_type -> term -> predicate
+
+(** [plet_len_div_size ~loc ~name_ext ltyp bytes_len pred] buils a predicate:
+    - [\let name = bytes_len / sizeof(ltyp) ; < pred name >]
+
+    with [name = "__fc_<name_ext>len"]. For example, if [pred len] generates an
+    ACSL predicate:
+    - [\forall int x ; 0 <= x < len ==> p[x] == 0],
+
+    [ltyp] is [int], and [bytes_len] is 16, it generates:
+    - [\let __fc_len = bytes_len / sizeof(ltyp) ;
+       \forall int x ; 0 <= x < __fc_len ==> p[x] == 0].
+
+    Parameters:
+    - [loc] defaults to [Cil_datatype.Location.unknown]
+    - [name_ext] defaults to [""]
+    - [ltyp] must be a logic C type
+    - [bytes_len] is a value in bytes that should be divided by the [sizeof(ltyp)]
+    - if the elements contains structures they cannot have flexible array member
+*)
+val plet_len_div_size:
+  ?loc:location -> ?name_ext:string ->
+  logic_type -> term -> (term -> predicate) -> predicate
+
+(** [punfold_all_elems_eq ~loc p1 p2 len] builds a predicate:
+    - [\forall integer j1 ; 0 <= j1 < len ==> p1[j1] == p2[j1]].
+
+    If [p1[j1]] is itself an array, it recursively builds a predicate:
+    - [\forall integer j2 ; 0 <= j2 < len_of_array ==> ...].
+
+    Parameters:
+    - [p1] and [p2] must be pointers to the same type
+*)
 val punfold_all_elems_eq: ?loc:location -> term -> term -> term -> predicate
+
+(** [punfold_all_elems_pred ~loc ptr len pred] builds a predicate:
+    - [\forall integer j ; 0 <= j1 < len ==> < pred (\*(ptr + j1)) >].
+
+    If [ptr[j1]] is a compound type (array or structure), it recursively builds
+    a predicate on each element (either by introducing a new [\forall] for
+    arrays or a conjunction for structure fields).
+
+    - [ptr] must be a pointer
+    - [pred] must be applicable on simple types or pointers
+    - if the elements contains structures they cannot have flexible array member
+*)
 val punfold_all_elems_pred:
   ?loc:location -> term -> term ->
   (?loc: location -> term -> predicate) -> predicate
+
+(** [punfold_flexible_struct_pred ~loc struct bytes_len pred].
+
+    For a [struct] term of C type [struct X { ... ; Type a[]; };], it generates
+    a predicate:
+    - [\let __fc_len = (bytes_len - sizeof(struct X)) / sizeof(Type) ;
+        < pred on struct fields > &&
+        \forall integer j ; 0 <= j <= __fc_len ==> < pred on struct.a[j] >]
+
+    If met components are compound, it behaves like [punfold_all_elems_pred].
+
+    Parameters:
+    - [struct] must be a (term) structure with a flexible array member
+    - [bytes_len] is the length of the structure in bytes
+    - [pred] must be applicable on simple types or pointers
+*)
 val punfold_flexible_struct_pred:
   ?loc:location -> term -> term ->
   (?loc: location -> term -> predicate) -> predicate
 
+(** [pvalid_len_bytes ~loc label ptr bytes_len] generates a predicate
+    - [\valid{label}(ptr + (0 .. (len_bytes/sizeof(\*ptr))))].
+
+    Parameters:
+    - [ptr] must be a term of pointer type.
+*)
+val pvalid_len_bytes: ?loc:location -> logic_label -> term -> term -> predicate
+
+(** [pvalid_read_len_bytes ~loc label ptr bytes_len] generates a predicate
+  - [\valid_read{label}(ptr + (0 .. (len_bytes/sizeof(\*ptr))))].
+
+  Parameters:
+  - [ptr] must be a term of pointer type.
+ *)
+val pvalid_read_len_bytes:
+  ?loc:location -> logic_label -> term -> term -> predicate
+
+(** [pcorrect_len_bytes ~loc ltyp bytes_len] returns a predicate
+    [bytes_len % sizeof(ltyp) == 0].
+*)
+val pcorrect_len_bytes: ?loc:location -> logic_type -> term -> predicate
+
+(** [pseparated_memories ~loc p1 len1 p2 len2] returns a predicate:
+    - [\separated(p1 + (0 .. len1), p2 + (0 .. len2))]
+
+    Parameters:
+    - [p1] and [p2] must be of pointer type
+*)
 val pseparated_memories:
   ?loc:location -> term -> term -> term -> term -> predicate
 
-val plet_len_div_size:
-  ?loc:location -> ?name_ext:string ->
-  logic_type -> term -> (term -> predicate) -> predicate
+(** {2 Specification} *)
 
+(** Builds a behavior from its components. If a component is missing,
+  it defaults to:
+  - [name]: [Cil.default_behavior_name]
+  - [requires], [ensures], [extension]: [[]]
+  - [assigns]: = [WritesAny]
+  - [alloc]: [FreeAllocAny]
+*)
 val make_behavior:
   ?name:string ->
   ?assumes:identified_predicate list ->
@@ -71,6 +204,10 @@ val make_behavior:
   unit ->
   behavior
 
+(** Builds a funspec from a list of behaviors.
+    - [termination] defaults to [None]
+    - [complete_disjoint] default to all disjoint, all complete
+*)
 val make_funspec:
   behavior list ->
   ?termination:identified_predicate option ->
diff --git a/src/plugins/builtin/options.mli b/src/plugins/builtin/options.mli
index 3ff7f8a32bc..8086aca2afe 100644
--- a/src/plugins/builtin/options.mli
+++ b/src/plugins/builtin/options.mli
@@ -22,9 +22,16 @@
 
 include Plugin.General_services
 
+(** Builtin transformtion enabled *)
 module Enabled : Parameter_sig.Bool
+
+(** Set of kernel function provided for transformation *)
 module Kfs : Parameter_sig.Kernel_function_set
 
+(** Used by [Builtin_builder] to generate builtin options. For a given builtin,
+    the module generate an option "-builtin-(no-)<function_name>" that defaults
+    to true.
+*)
 module NewBuiltin
     (B : sig val function_name: string end) : Parameter_sig.Bool
 
diff --git a/src/plugins/builtin/tests/stdlib/oracle/calloc.res.oracle b/src/plugins/builtin/tests/stdlib/oracle/calloc.res.oracle
index e116acefd06..aad87a80a21 100644
--- a/src/plugins/builtin/tests/stdlib/oracle/calloc.res.oracle
+++ b/src/plugins/builtin/tests/stdlib/oracle/calloc.res.oracle
@@ -49,7 +49,7 @@ struct Flex {
     complete behaviors no_allocation, allocation;
     disjoint behaviors no_allocation, allocation;
  */
-struct Flex *calloc_Flex(size_t num, size_t size)
+struct Flex *calloc_st_Flex(size_t num, size_t size)
 {
   struct Flex *__retres;
   __retres = (struct Flex *)calloc(num,size);
@@ -170,7 +170,7 @@ char *calloc_char(size_t num, size_t size)
     complete behaviors no_allocation, allocation;
     disjoint behaviors no_allocation, allocation;
  */
-struct X *calloc_X(size_t num, size_t size)
+struct X *calloc_st_X(size_t num, size_t size)
 {
   struct X *__retres;
   __retres = (struct X *)calloc(num,size);
@@ -256,12 +256,12 @@ int main(void)
   int __retres;
   int *pi = calloc_int((unsigned int)10,sizeof(int));
   float *pf = calloc_float((unsigned int)10,sizeof(float));
-  struct X *px = calloc_X((unsigned int)10,sizeof(struct X));
+  struct X *px = calloc_st_X((unsigned int)10,sizeof(struct X));
   char *pc = calloc_char((unsigned int)10,sizeof(char));
   int (*pa)[10] = calloc_arr10_int((unsigned int)10,sizeof(int [10]));
   struct Flex *f =
-    calloc_Flex((unsigned int)1,
-                sizeof(struct Flex) + (unsigned int)3 * sizeof(int));
+    calloc_st_Flex((unsigned int)1,
+                   sizeof(struct Flex) + (unsigned int)3 * sizeof(int));
   void *v = calloc((unsigned int)10,sizeof(char));
   __retres = 0;
   return __retres;
@@ -320,7 +320,7 @@ struct Flex {
     complete behaviors no_allocation, allocation;
     disjoint behaviors no_allocation, allocation;
  */
-struct Flex *calloc_Flex(size_t num, size_t size)
+struct Flex *calloc_st_Flex(size_t num, size_t size)
 {
   struct Flex *__retres;
   __retres = (struct Flex *)calloc(num,size);
@@ -444,7 +444,7 @@ char *calloc_char(size_t num, size_t size)
     complete behaviors no_allocation, allocation;
     disjoint behaviors no_allocation, allocation;
  */
-struct X *calloc_X(size_t num, size_t size)
+struct X *calloc_st_X(size_t num, size_t size)
 {
   struct X *__retres;
   __retres = (struct X *)calloc(num,size);
@@ -532,12 +532,12 @@ int main(void)
   int __retres;
   int *pi = calloc_int((unsigned int)10,sizeof(int));
   float *pf = calloc_float((unsigned int)10,sizeof(float));
-  struct X *px = calloc_X((unsigned int)10,sizeof(struct X));
+  struct X *px = calloc_st_X((unsigned int)10,sizeof(struct X));
   char *pc = calloc_char((unsigned int)10,sizeof(char));
   int (*pa)[10] = calloc_arr10_int((unsigned int)10,sizeof(int [10]));
   struct Flex *f =
-    calloc_Flex((unsigned int)1,
-                sizeof(struct Flex) + (unsigned int)3 * sizeof(int));
+    calloc_st_Flex((unsigned int)1,
+                   sizeof(struct Flex) + (unsigned int)3 * sizeof(int));
   void *v = calloc((unsigned int)10,sizeof(char));
   __retres = 0;
   return __retres;
diff --git a/src/plugins/builtin/tests/stdlib/oracle/malloc.res.oracle b/src/plugins/builtin/tests/stdlib/oracle/malloc.res.oracle
index c552df1af72..a43a99fddf6 100644
--- a/src/plugins/builtin/tests/stdlib/oracle/malloc.res.oracle
+++ b/src/plugins/builtin/tests/stdlib/oracle/malloc.res.oracle
@@ -35,7 +35,7 @@ struct Flex {
     complete behaviors no_allocation, allocation;
     disjoint behaviors no_allocation, allocation;
  */
-struct Flex *malloc_Flex(size_t size)
+struct Flex *malloc_st_Flex(size_t size)
 {
   struct Flex *__retres;
   __retres = (struct Flex *)malloc(size);
@@ -128,7 +128,7 @@ char *malloc_char(size_t size)
     complete behaviors no_allocation, allocation;
     disjoint behaviors no_allocation, allocation;
  */
-struct X *malloc_X(size_t size)
+struct X *malloc_st_X(size_t size)
 {
   struct X *__retres;
   __retres = (struct X *)malloc(size);
@@ -202,11 +202,11 @@ int main(void)
   int __retres;
   int *pi = malloc_int(sizeof(int) * (unsigned int)10);
   float *pf = malloc_float(sizeof(float) * (unsigned int)10);
-  struct X *px = malloc_X(sizeof(struct X) * (unsigned int)10);
+  struct X *px = malloc_st_X(sizeof(struct X) * (unsigned int)10);
   char *pc = malloc_char((unsigned int)10);
   int (*pa)[10] = malloc_arr10_int(sizeof(int [10]) * (unsigned int)10);
   struct Flex *f =
-    malloc_Flex(sizeof(struct Flex) + (unsigned int)3 * sizeof(int));
+    malloc_st_Flex(sizeof(struct Flex) + (unsigned int)3 * sizeof(int));
   void *v = malloc(sizeof(char) * (unsigned int)10);
   __retres = 0;
   return __retres;
@@ -252,7 +252,7 @@ struct Flex {
     complete behaviors no_allocation, allocation;
     disjoint behaviors no_allocation, allocation;
  */
-struct Flex *malloc_Flex(size_t size)
+struct Flex *malloc_st_Flex(size_t size)
 {
   struct Flex *__retres;
   __retres = (struct Flex *)malloc(size);
@@ -345,7 +345,7 @@ char *malloc_char(size_t size)
     complete behaviors no_allocation, allocation;
     disjoint behaviors no_allocation, allocation;
  */
-struct X *malloc_X(size_t size)
+struct X *malloc_st_X(size_t size)
 {
   struct X *__retres;
   __retres = (struct X *)malloc(size);
@@ -419,11 +419,11 @@ int main(void)
   int __retres;
   int *pi = malloc_int(sizeof(int) * (unsigned int)10);
   float *pf = malloc_float(sizeof(float) * (unsigned int)10);
-  struct X *px = malloc_X(sizeof(struct X) * (unsigned int)10);
+  struct X *px = malloc_st_X(sizeof(struct X) * (unsigned int)10);
   char *pc = malloc_char((unsigned int)10);
   int (*pa)[10] = malloc_arr10_int(sizeof(int [10]) * (unsigned int)10);
   struct Flex *f =
-    malloc_Flex(sizeof(struct Flex) + (unsigned int)3 * sizeof(int));
+    malloc_st_Flex(sizeof(struct Flex) + (unsigned int)3 * sizeof(int));
   void *v = malloc(sizeof(char) * (unsigned int)10);
   __retres = 0;
   return __retres;
diff --git a/src/plugins/builtin/tests/string/oracle/memcmp.res.oracle b/src/plugins/builtin/tests/string/oracle/memcmp.res.oracle
index 1e239406f5d..7b39a351f64 100644
--- a/src/plugins/builtin/tests/string/oracle/memcmp.res.oracle
+++ b/src/plugins/builtin/tests/string/oracle/memcmp.res.oracle
@@ -64,7 +64,7 @@ int with_named(named * /*[10]*/ s1, named * /*[10]*/ s2)
       \from (indirect: *(s1 + (0 .. len - 1))),
             (indirect: *(s2 + (0 .. len - 1)));
  */
-int memcmp_X(struct X const *s1, struct X const *s2, size_t len)
+int memcmp_st_X(struct X const *s1, struct X const *s2, size_t len)
 {
   int __retres;
   __retres = memcmp((void const *)s1,(void const *)s2,len);
@@ -74,7 +74,7 @@ int memcmp_X(struct X const *s1, struct X const *s2, size_t len)
 int structure(struct X * /*[10]*/ s1, struct X * /*[10]*/ s2)
 {
   int tmp;
-  tmp = memcmp_X(s1,s2,(unsigned int)10 * sizeof(struct X));
+  tmp = memcmp_st_X(s1,s2,(unsigned int)10 * sizeof(struct X));
   return tmp;
 }
 
@@ -233,7 +233,7 @@ int with_named(named *s1, named *s2)
       \from (indirect: *(s1 + (0 .. len - 1))),
             (indirect: *(s2 + (0 .. len - 1)));
  */
-int memcmp_X(struct X const *s1, struct X const *s2, size_t len)
+int memcmp_st_X(struct X const *s1, struct X const *s2, size_t len)
 {
   int __retres;
   __retres = memcmp((void const *)s1,(void const *)s2,len);
@@ -243,8 +243,8 @@ int memcmp_X(struct X const *s1, struct X const *s2, size_t len)
 int structure(struct X *s1, struct X *s2)
 {
   int tmp;
-  tmp = memcmp_X((struct X const *)s1,(struct X const *)s2,
-                 (unsigned int)10 * sizeof(struct X));
+  tmp = memcmp_st_X((struct X const *)s1,(struct X const *)s2,
+                    (unsigned int)10 * sizeof(struct X));
   return tmp;
 }
 
diff --git a/src/plugins/builtin/tests/string/oracle/memcpy.res.oracle b/src/plugins/builtin/tests/string/oracle/memcpy.res.oracle
index b0d5a8eaba6..ced9071c356 100644
--- a/src/plugins/builtin/tests/string/oracle/memcpy.res.oracle
+++ b/src/plugins/builtin/tests/string/oracle/memcpy.res.oracle
@@ -69,7 +69,7 @@ void with_named(named * /*[10]*/ src, named * /*[10]*/ dest)
     assigns *(dest + (0 .. len - 1)) \from *(src + (0 .. len - 1));
     assigns \result \from dest;
  */
-struct X *memcpy_X(struct X *dest, struct X const *src, size_t len)
+struct X *memcpy_st_X(struct X *dest, struct X const *src, size_t len)
 {
   struct X *__retres;
   __retres = (struct X *)memcpy((void *)dest,(void const *)src,len);
@@ -78,8 +78,8 @@ struct X *memcpy_X(struct X *dest, struct X const *src, size_t len)
 
 void structure(struct X * /*[10]*/ src, struct X * /*[10]*/ dest)
 {
-  struct X *res = memcpy_X(dest,src,(unsigned int)10 * sizeof(struct X));
-  memcpy_X(src,res,(unsigned int)10 * sizeof(struct X));
+  struct X *res = memcpy_st_X(dest,src,(unsigned int)10 * sizeof(struct X));
+  memcpy_st_X(src,res,(unsigned int)10 * sizeof(struct X));
   return;
 }
 
@@ -249,7 +249,7 @@ void with_named(named *src, named *dest)
     assigns *(dest + (0 .. len - 1)) \from *(src + (0 .. len - 1));
     assigns \result \from dest;
  */
-struct X *memcpy_X(struct X *dest, struct X const *src, size_t len)
+struct X *memcpy_st_X(struct X *dest, struct X const *src, size_t len)
 {
   struct X *__retres;
   __retres = (struct X *)memcpy((void *)dest,(void const *)src,len);
@@ -259,8 +259,9 @@ struct X *memcpy_X(struct X *dest, struct X const *src, size_t len)
 void structure(struct X *src, struct X *dest)
 {
   struct X *res =
-    memcpy_X(dest,(struct X const *)src,(unsigned int)10 * sizeof(struct X));
-  memcpy_X(src,(struct X const *)res,(unsigned int)10 * sizeof(struct X));
+    memcpy_st_X(dest,(struct X const *)src,
+                (unsigned int)10 * sizeof(struct X));
+  memcpy_st_X(src,(struct X const *)res,(unsigned int)10 * sizeof(struct X));
   return;
 }
 
diff --git a/src/plugins/builtin/tests/string/oracle/memmove.res.oracle b/src/plugins/builtin/tests/string/oracle/memmove.res.oracle
index 75ff285878b..7b7122fb41a 100644
--- a/src/plugins/builtin/tests/string/oracle/memmove.res.oracle
+++ b/src/plugins/builtin/tests/string/oracle/memmove.res.oracle
@@ -61,7 +61,7 @@ void with_named(named * /*[10]*/ src, named * /*[10]*/ dest)
     assigns *(dest + (0 .. len - 1)) \from *(src + (0 .. len - 1));
     assigns \result \from dest;
  */
-struct X *memmove_X(struct X *dest, struct X const *src, size_t len)
+struct X *memmove_st_X(struct X *dest, struct X const *src, size_t len)
 {
   struct X *__retres;
   __retres = (struct X *)memmove((void *)dest,(void const *)src,len);
@@ -70,8 +70,8 @@ struct X *memmove_X(struct X *dest, struct X const *src, size_t len)
 
 void structure(struct X * /*[10]*/ src, struct X * /*[10]*/ dest)
 {
-  struct X *res = memmove_X(dest,src,(unsigned int)10 * sizeof(struct X));
-  memmove_X(src,res,(unsigned int)10 * sizeof(struct X));
+  struct X *res = memmove_st_X(dest,src,(unsigned int)10 * sizeof(struct X));
+  memmove_st_X(src,res,(unsigned int)10 * sizeof(struct X));
   return;
 }
 
@@ -225,7 +225,7 @@ void with_named(named *src, named *dest)
     assigns *(dest + (0 .. len - 1)) \from *(src + (0 .. len - 1));
     assigns \result \from dest;
  */
-struct X *memmove_X(struct X *dest, struct X const *src, size_t len)
+struct X *memmove_st_X(struct X *dest, struct X const *src, size_t len)
 {
   struct X *__retres;
   __retres = (struct X *)memmove((void *)dest,(void const *)src,len);
@@ -235,8 +235,9 @@ struct X *memmove_X(struct X *dest, struct X const *src, size_t len)
 void structure(struct X *src, struct X *dest)
 {
   struct X *res =
-    memmove_X(dest,(struct X const *)src,(unsigned int)10 * sizeof(struct X));
-  memmove_X(src,(struct X const *)res,(unsigned int)10 * sizeof(struct X));
+    memmove_st_X(dest,(struct X const *)src,
+                 (unsigned int)10 * sizeof(struct X));
+  memmove_st_X(src,(struct X const *)res,(unsigned int)10 * sizeof(struct X));
   return;
 }
 
diff --git a/src/plugins/builtin/tests/string/oracle/memset_0.res.oracle b/src/plugins/builtin/tests/string/oracle/memset_0.res.oracle
index ecaeedab7db..ba939b95fc5 100644
--- a/src/plugins/builtin/tests/string/oracle/memset_0.res.oracle
+++ b/src/plugins/builtin/tests/string/oracle/memset_0.res.oracle
@@ -157,7 +157,7 @@ void with_named(named * /*[10]*/ dest)
     assigns *(ptr + (0 .. num - 1)) \from \nothing;
     assigns \result \from ptr;
  */
-struct X *memset_X_0(struct X *ptr, size_t num)
+struct X *memset_st_X_0(struct X *ptr, size_t num)
 {
   struct X *__retres;
   __retres = (struct X *)memset((void *)ptr,0,num);
@@ -166,8 +166,8 @@ struct X *memset_X_0(struct X *ptr, size_t num)
 
 void structure(struct X * /*[10]*/ dest)
 {
-  struct X *res = memset_X_0(dest,(unsigned int)10 * sizeof(struct X));
-  memset_X_0(res,(unsigned int)10 * sizeof(struct X));
+  struct X *res = memset_st_X_0(dest,(unsigned int)10 * sizeof(struct X));
+  memset_st_X_0(res,(unsigned int)10 * sizeof(struct X));
   return;
 }
 
@@ -418,7 +418,7 @@ void with_named(named *dest)
     assigns *(ptr + (0 .. num - 1)) \from \nothing;
     assigns \result \from ptr;
  */
-struct X *memset_X_0(struct X *ptr, size_t num)
+struct X *memset_st_X_0(struct X *ptr, size_t num)
 {
   struct X *__retres;
   __retres = (struct X *)memset((void *)ptr,0,num);
@@ -427,8 +427,8 @@ struct X *memset_X_0(struct X *ptr, size_t num)
 
 void structure(struct X *dest)
 {
-  struct X *res = memset_X_0(dest,(unsigned int)10 * sizeof(struct X));
-  memset_X_0(res,(unsigned int)10 * sizeof(struct X));
+  struct X *res = memset_st_X_0(dest,(unsigned int)10 * sizeof(struct X));
+  memset_st_X_0(res,(unsigned int)10 * sizeof(struct X));
   return;
 }
 
diff --git a/src/plugins/builtin/tests/string/oracle/memset_FF.res.oracle b/src/plugins/builtin/tests/string/oracle/memset_FF.res.oracle
index a50c0bf600c..1115c29a5ac 100644
--- a/src/plugins/builtin/tests/string/oracle/memset_FF.res.oracle
+++ b/src/plugins/builtin/tests/string/oracle/memset_FF.res.oracle
@@ -295,7 +295,7 @@ void with_named(named * /*[10]*/ dest)
     assigns *(ptr + (0 .. num - 1)) \from \nothing;
     assigns \result \from ptr;
  */
-struct X *memset_X_FF(struct X *ptr, size_t num)
+struct X *memset_st_X_FF(struct X *ptr, size_t num)
 {
   struct X *__retres;
   __retres = (struct X *)memset((void *)ptr,255,num);
@@ -304,8 +304,8 @@ struct X *memset_X_FF(struct X *ptr, size_t num)
 
 void structure(struct X * /*[10]*/ dest)
 {
-  struct X *res = memset_X_FF(dest,(unsigned int)10 * sizeof(struct X));
-  memset_X_FF(res,(unsigned int)10 * sizeof(struct X));
+  struct X *res = memset_st_X_FF(dest,(unsigned int)10 * sizeof(struct X));
+  memset_st_X_FF(res,(unsigned int)10 * sizeof(struct X));
   return;
 }
 
@@ -704,7 +704,7 @@ void with_named(named *dest)
     assigns *(ptr + (0 .. num - 1)) \from \nothing;
     assigns \result \from ptr;
  */
-struct X *memset_X_FF(struct X *ptr, size_t num)
+struct X *memset_st_X_FF(struct X *ptr, size_t num)
 {
   struct X *__retres;
   __retres = (struct X *)memset((void *)ptr,255,num);
@@ -713,8 +713,8 @@ struct X *memset_X_FF(struct X *ptr, size_t num)
 
 void structure(struct X *dest)
 {
-  struct X *res = memset_X_FF(dest,(unsigned int)10 * sizeof(struct X));
-  memset_X_FF(res,(unsigned int)10 * sizeof(struct X));
+  struct X *res = memset_st_X_FF(dest,(unsigned int)10 * sizeof(struct X));
+  memset_st_X_FF(res,(unsigned int)10 * sizeof(struct X));
   return;
 }
 
diff --git a/src/plugins/builtin/transform.mli b/src/plugins/builtin/transform.mli
index 10e265d8719..72800ee3426 100644
--- a/src/plugins/builtin/transform.mli
+++ b/src/plugins/builtin/transform.mli
@@ -20,5 +20,17 @@
 (*                                                                        *)
 (**************************************************************************)
 
+(** Module for AST transformation *)
+
+(** Registers a new [Builtin] to the visitor from the [Generator_sig] module
+    of this builtin. Each new builtin function generator should call this
+    globally.
+*)
 val register: (module Builtin_builder.Generator_sig) -> unit
+
+(** In all selected functions of the given file, for all function call, if there
+    exists a builtin module for this function, and the call is well-typed,
+    replaces it with a call to the generated override function and inserted the
+    generated function in the AST.
+*)
 val transform: Cil_types.file -> unit
-- 
GitLab