From b60c143c2742841e6122a5e9191c9422e09b392c Mon Sep 17 00:00:00 2001
From: Valentin Perrelle <valentin.perrelle@cea.fr>
Date: Sun, 2 Aug 2020 10:18:03 +0200
Subject: [PATCH] [CilBuilder] add initialization support

---
 .../ast_building/cil_builder.ml               | 118 +++++++++++++++++-
 .../ast_building/cil_builder.mli              |  44 ++++++-
 2 files changed, 155 insertions(+), 7 deletions(-)

diff --git a/src/kernel_services/ast_building/cil_builder.ml b/src/kernel_services/ast_building/cil_builder.ml
index 42bdfa12335..8af8b529e61 100644
--- a/src/kernel_services/ast_building/cil_builder.ml
+++ b/src/kernel_services/ast_building/cil_builder.ml
@@ -21,10 +21,72 @@
 (**************************************************************************)
 
 
+(* --- Types --- *)
+
+module Type =
+struct
+  type ('value,'shape) morphology =
+    | Single : ('value,'value) morphology
+    | Listed : ('value,'shape) typ -> ('value,'shape list) morphology
+
+  and ('value,'shape) typ = ('value,'shape) morphology * Cil_types.typ
+
+  open Cil_types
+
+  let typ t = Single, t
+  let void = Single, TVoid []
+  let bool = Single, TInt (IBool, [])
+  let char = Single, TInt (IChar, [])
+  let schar = Single, TInt (ISChar, [])
+  let uchar = Single, TInt (IUChar, [])
+  let int = Single, TInt (IInt, [])
+  let unit = Single, TInt (IUInt, [])
+  let short = Single, TInt (IShort, [])
+  let ushort = Single, TInt (IUShort, [])
+  let long = Single, TInt (ILong, [])
+  let ulong = Single, TInt (IULong, [])
+  let longlong = Single, TInt (ILongLong, [])
+  let ulonglong = Single, TInt (IULongLong, [])
+  let float = Single, TFloat (FFloat, [])
+  let double = Single, TFloat (FDouble, [])
+  let longdouble = Single, TFloat (FLongDouble, [])
+
+  let ptr (_,t) = Single, TPtr (t, [])
+
+  let array ?size (_,t as typ) =
+    let size = Extlib.opt_map (Cil.integer ~loc:Cil_datatype.Location.unknown) size in
+    Listed typ,
+    TArray (t, size, Cil.empty_size_cache (), [])
+
+  let attribute (s,t) name params =
+    let add_to = Cil.addAttribute (Attr (name, params)) in
+    let t = match t with
+      | TVoid l -> TVoid (add_to l)
+      | TInt (kind, l) -> TInt (kind, add_to l)
+      | TFloat (kind, l) -> TFloat (kind, add_to l)
+      | TPtr (typ, l) -> TPtr (typ, add_to l)
+      | TArray (typ, size, cache, l) -> TArray (typ, size, cache, add_to l)
+      | TFun (typ, args, variadic, l) -> TFun (typ, args, variadic, add_to l)
+      | TNamed (typeinfo, l) -> TNamed (typeinfo, add_to l)
+      | TComp (compinfo, cache, l) -> TComp (compinfo, cache, add_to l)
+      | TEnum (enuminfo, l) -> TEnum (enuminfo, add_to l)
+      | TBuiltin_va_list l -> TBuiltin_va_list (add_to l)
+    in
+    (s,t)
+
+  let const typ = attribute typ "const" []
+  let stdlib_generated typ = attribute typ "fc_stdlib_generated" []
+
+  let cil_typ (_,t) = t
+end
+
+
 (* --- C & Logic expressions builder --- *)
 
 module Exp =
 struct
+  include Type
+
   (*
     This modules exportes polymorphic variant to simulate subtyping.
     It uses regular variant internally though, instead of using only the
@@ -36,7 +98,8 @@ struct
   *)
 
   type const' =
-    | Int of Integer.t
+    | Int of int
+    | Integer of Integer.t
     | CilConstant of Cil_types.constant
   and var' =
     Cil_types.varinfo
@@ -56,11 +119,16 @@ struct
     | Range of exp' option * exp' option
     | Unop of Cil_types.unop * exp'
     | Binop of Cil_types.binop * exp' * exp'
+  and init' =
+    | CilInit of Cil_types.init
+    | SingleInit of exp'
+    | CompoundInit of Cil_types.typ * init' list
 
   type const = [ `const of const' ]
   type var = [ `var of var' ]
   type lval = [  var | `lval of lval' ]
   type exp = [ const | lval | `exp of exp' ]
+  type init = [ exp | `init of init']
 
   (* Depolymorphize *)
 
@@ -94,11 +162,16 @@ struct
   let harden_exp_list l =
     List.map harden_exp l
 
+  let harden_init i =
+    match (i :> init) with
+    | #exp as exp -> SingleInit (harden_exp exp)
+    | `init init -> init
+
   (* Build *)
 
   let constant c = `const (CilConstant c)
-  let integer i = `const (Int i)
-  let int i = `const (Int (Integer.of_int i))
+  let integer i = `const (Integer i)
+  let int i = `const (Int i)
   let zero = int 0
   let one = int 1
   let var v = `var v
@@ -135,6 +208,14 @@ struct
   let term t = `exp (CilTerm t)
   let none = `none
   let range e1 e2 = `exp (Range (harden_exp_opt e1, harden_exp_opt e2))
+  let init i = `init (CilInit i)
+  let compound t l = `init (CompoundInit (t, List.map harden_init l))
+
+  let rec values : type a. (init, a) typ -> a -> [> init] =
+    fun (morph,typ) x ->
+    match morph with
+    | Single -> x
+    | Listed sub -> compound typ (List.map (values sub) x)
 
   exception EmptyList
 
@@ -177,7 +258,8 @@ struct
 
   let rec build_constant = function
     | CilConstant const -> const
-    | Int i -> Cil_types.(CInt64 (i, IInt, None))
+    | Int i -> build_constant (Integer (Integer.of_int i))
+    | Integer i -> Cil_types.(CInt64 (i, IInt, None))
 
   and build_lval ~loc = function
     | CilLval lval -> lval
@@ -234,6 +316,8 @@ struct
     | Const (CilConstant _) | CilExp _ | CilExpCopy _ -> raise CInLogic
     | CilTerm term -> term
     | Const (Int i) ->
+      Logic_const.tinteger ~loc i
+    | Const (Integer i) ->
       Logic_const.tint ~loc i
     | Lval lval ->
       let tlval = build_term_lval ~loc ~restyp lval in
@@ -254,6 +338,16 @@ struct
       and t2' = Extlib.opt_map (build_term ~loc ~restyp) t2 in
       Logic_const.trange ~loc (t1',t2')
 
+  let rec build_init ~loc = function
+    | CilInit init -> init
+    | SingleInit e ->
+      Cil_types.SingleInit (build_exp ~loc e)
+    | CompoundInit (typ,l) ->
+      let index i = Cil_types.(Index (Cil.integer ~loc i, NoOffset)) in
+      let initl = List.mapi (fun i sub -> index i, build_init ~loc sub) l in
+      Cil_types.CompoundInit (typ, initl)
+
+
   (* Export *)
 
   let cil_varinfo v = harden_var v
@@ -267,6 +361,7 @@ struct
   let cil_term_lval ~loc ~restyp lv =
     build_term_lval ~loc ~restyp (harden_lval lv)
   let cil_term ~loc ~restyp e = build_term ~loc ~restyp (harden_exp e)
+  let cil_init ~loc i = build_init ~loc (harden_init i)
 end
 
 
@@ -327,7 +422,7 @@ struct
   let stmts l = `stmt (Sequence (List.map (fun s -> CilStmt s) l))
   let block l = `stmt (Sequence (List.map harden_stmt l))
   let ghost s = `stmt (Ghost (harden_stmt s))
-  
+
 
   (* Convert *)
 
@@ -643,12 +738,23 @@ struct
     let fundec = get_owner () in
     Cil.setReturnType fundec typ
 
-  let local ?(ghost=false) typ name =
+  let local' ?(ghost=false) ?init typ name =
     let fundec = get_owner () and b = top () in
     let ghost = ghost || b.ghost in
     let v = Cil.makeLocalVar fundec ~insert:false ~ghost ~loc name typ in
+    begin match init with
+      | None -> ()
+      | Some init ->
+        let local_init = Cil_types.AssignInit (cil_init ~loc init) in
+        instr (Cil_types.Local_init (v, local_init, loc));
+        v.vdefined <- true
+    end;
     `var v
 
+  let local ?ghost ?init typ name =
+    let init = Extlib.opt_map (values typ) init in
+    local' ?ghost ?init (snd typ) name
+
   let local_copy ?(ghost=false) ?(suffix="_tmp") (`var vi) =
     let fundec = get_owner () and b = top () in
     let ghost = ghost || b.ghost in
diff --git a/src/kernel_services/ast_building/cil_builder.mli b/src/kernel_services/ast_building/cil_builder.mli
index 1f48a3a3bf4..af6de9843f9 100644
--- a/src/kernel_services/ast_building/cil_builder.mli
+++ b/src/kernel_services/ast_building/cil_builder.mli
@@ -27,20 +27,57 @@
 - Interface unifiée vers les smart constructors
 *)
 
+module Type :
+sig
+  type ('value,'shape) typ
+
+  val typ : Cil_types.typ -> ('v,'v) typ
+  val void : ('v,'v) typ
+  val bool : ('v,'v) typ
+  val char : ('v,'v) typ
+  val schar : ('v,'v) typ
+  val uchar : ('v,'v) typ
+  val int : ('v,'v) typ
+  val unit : ('v,'v) typ
+  val short : ('v,'v) typ
+  val ushort : ('v,'v) typ
+  val long : ('v,'v) typ
+  val ulong : ('v,'v) typ
+  val longlong : ('v,'v) typ
+  val ulonglong : ('v,'v) typ
+  val float : ('v,'v) typ
+  val double : ('v,'v) typ
+  val longdouble : ('v,'v) typ
+
+  val ptr : ('v,'s) typ -> ('v,'v) typ
+  val array : ?size:int -> ('v,'s) typ -> ('v,'s list) typ
+
+  val attribute : ('v,'s) typ -> string -> Cil_types.attrparam list
+    -> ('v,'s) typ
+  val const : ('v,'s) typ -> ('v,'s) typ
+  val stdlib_generated : ('v,'s) typ -> ('v,'s) typ
+
+  val cil_typ : ('v,'s) typ -> Cil_types.typ
+end
+
 
 (* --- C & Logic expressions builder --- *)
 
 module Exp :
 sig
+  include module type of Type
+
   type const'
   type var'
   type lval'
   type exp'
+  type init'
 
   type const = [ `const of const' ]
   type var = [ `var of var' ]
   type lval = [  var | `lval of lval' ]
   type exp = [ const | lval | `exp of exp' ]
+  type init = [ exp | `init of init']
 
   (* Build Constants *)
 
@@ -89,6 +126,9 @@ sig
   val term : Cil_types.term -> [> exp]
   val none : [> `none]
   val range :  [< exp | `none] -> [< exp | `none] -> [> exp]
+  val init : Cil_types.init -> [> init]
+  val compound : Cil_types.typ -> init list -> [> init]
+  val values : (init,'values) typ -> 'values -> init
 
   exception EmptyList
 
@@ -125,6 +165,7 @@ sig
     [< lval] -> Cil_types.term_lval
   val cil_term : loc:Cil_types.location -> restyp:Cil_types.typ ->
     [< exp] -> Cil_types.term
+  val cil_init : loc:Cil_types.location -> [< init] -> Cil_types.init
 end
 
 
@@ -194,7 +235,8 @@ sig
 
   (* Variables *)
   val return_type : Cil_types.typ -> unit
-  val local : ?ghost:bool -> Cil_types.typ -> string -> [> var]
+  val local : ?ghost:bool -> ?init:'v -> (init,'v) typ -> string -> [> var]
+  val local' : ?ghost:bool -> ?init:init -> Cil_types.typ -> string -> [> var]
   val local_copy : ?ghost:bool -> ?suffix:string -> [< var] -> [> var]
   val parameter : ?ghost:bool -> ?attributes:Cil_types.attributes ->
     Cil_types.typ -> string -> [> var]
-- 
GitLab