@ -1,12 +1,12 @@
(*
(*
* Copyright ( c ) 2009 - 2013 Monoidics ltd .
* Copyright ( c ) 2009 - 2013 Monoidics ltd .
* Copyright ( c ) 2013 - present Facebook , Inc .
* Copyright ( c ) 2013 - present Facebook , Inc .
* All rights reserved .
* All rights reserved .
*
*
* This source code is licensed under the BSD style license found in the
* This source code is licensed under the BSD style license found in the
* LICENSE file in the root directory of this source tree . An additional grant
* LICENSE file in the root directory of this source tree . An additional grant
* of patent rights can be found in the PATENTS file in the same directory .
* of patent rights can be found in the PATENTS file in the same directory .
* )
* )
(* * The Smallfoot Intermediate Language *)
(* * The Smallfoot Intermediate Language *)
@ -72,10 +72,10 @@ type proc_attributes =
val copy_proc_attributes : proc_attributes -> proc_attributes
val copy_proc_attributes : proc_attributes -> proc_attributes
(* * Type for program variables. There are 4 kinds of variables:
(* * Type for program variables. There are 4 kinds of variables:
1 ) local variables , used for local variables and formal parameters
1 ) local variables , used for local variables and formal parameters
2 ) callee program variables , used to handle recursion ( [ x | callee ] is distinguished from [ x ] )
2 ) callee program variables , used to handle recursion ( [ x | callee ] is distinguished from [ x ] )
3 ) global variables
3 ) global variables
4 ) seed variables , used to store the initial value of formal parameters
4 ) seed variables , used to store the initial value of formal parameters
* )
* )
type pvar
type pvar
@ -270,7 +270,7 @@ type dexp =
| Dretcall of dexp * dexp list * location * call_flags
| Dretcall of dexp * dexp list * location * call_flags
(* * Value paths: identify an occurrence of a value in a symbolic heap
(* * Value paths: identify an occurrence of a value in a symbolic heap
each expression represents a path , with Dpvar being the simplest one * )
each expression represents a path , with Dpvar being the simplest one * )
and vpath =
and vpath =
dexp option
dexp option
@ -469,11 +469,11 @@ type strexp =
| Estruct of ( Ident . fieldname * strexp ) list * inst (* * C structure *)
| Estruct of ( Ident . fieldname * strexp ) list * inst (* * C structure *)
| Earray of exp * ( exp * strexp ) list * inst (* * Array of given size. *)
| Earray of exp * ( exp * strexp ) list * inst (* * Array of given size. *)
(* * There are two conditions imposed / used in the array case.
(* * There are two conditions imposed / used in the array case.
First , if some index and value pair appears inside an array
First , if some index and value pair appears inside an array
in a strexp , then the index is less than the size of the array .
in a strexp , then the index is less than the size of the array .
For instance , x | -> [ 10 | e1 : v1 ] implies that e1 < = 9 .
For instance , x | -> [ 10 | e1 : v1 ] implies that e1 < = 9 .
Second , if two indices appear in an array , they should be different .
Second , if two indices appear in an array , they should be different .
For instance , x | -> [ 10 | e1 : v1 , e2 : v2 ] implies that e1 != e2 . * )
For instance , x | -> [ 10 | e1 : v1 , e2 : v2 ] implies that e1 != e2 . * )
(* * an atomic heap predicate *)
(* * an atomic heap predicate *)
and hpred =
and hpred =
@ -486,14 +486,14 @@ and hpred =
This assumption is used in the rearrangement . The last [ exp list ] parameter
This assumption is used in the rearrangement . The last [ exp list ] parameter
is used to denote the shared links by all the nodes in the list . * )
is used to denote the shared links by all the nodes in the list . * )
| Hdllseg of lseg_kind * hpara_dll * exp * exp * exp * exp * exp list
| Hdllseg of lseg_kind * hpara_dll * exp * exp * exp * exp * exp list
(* * higher-order predicate for doubly-linked lists. *)
(* * higher-order predicate for doubly-linked lists. *)
(* * parameter for the higher-order singly-linked list predicate.
(* * parameter for the higher-order singly-linked list predicate.
Means " lambda (root,next,svars). Exists evars. body " .
Means " lambda (root,next,svars). Exists evars. body " .
Assume that root , next , svars , evars are disjoint sets of
Assume that root , next , svars , evars are disjoint sets of
primed identifiers , and include all the free primed identifiers in body .
primed identifiers , and include all the free primed identifiers in body .
body should not contain any non - primed identifiers or program
body should not contain any non - primed identifiers or program
variables ( i . e . pvars ) . * )
variables ( i . e . pvars ) . * )
and hpara =
and hpara =
{ root : Ident . t ;
{ root : Ident . t ;
next : Ident . t ;
next : Ident . t ;
@ -502,8 +502,8 @@ and hpara =
body : hpred list }
body : hpred list }
(* * parameter for the higher-order doubly-linked list predicates.
(* * parameter for the higher-order doubly-linked list predicates.
Assume that all the free identifiers in body_dll should belong to
Assume that all the free identifiers in body_dll should belong to
cell , blink , flink , svars_dll , evars_dll . * )
cell , blink , flink , svars_dll , evars_dll . * )
and hpara_dll =
and hpara_dll =
{ cell : Ident . t ; (* * address cell *)
{ cell : Ident . t ; (* * address cell *)
blink : Ident . t ; (* * backward link *)
blink : Ident . t ; (* * backward link *)
@ -692,21 +692,21 @@ val unop_equal : unop -> unop -> bool
val binop_equal : binop -> binop -> bool
val binop_equal : binop -> binop -> bool
(* * This function returns true if the operation is injective
(* * This function returns true if the operation is injective
wrt . each argument : op ( e , - ) and op ( - , e ) is injective for all e .
wrt . each argument : op ( e , - ) and op ( - , e ) is injective for all e .
The return value false means " don't know " . * )
The return value false means " don't know " . * )
val binop_injective : binop -> bool
val binop_injective : binop -> bool
(* * This function returns true if the operation can be inverted. *)
(* * This function returns true if the operation can be inverted. *)
val binop_invertible : binop -> bool
val binop_invertible : binop -> bool
(* * This function inverts an injective binary operator
(* * This function inverts an injective binary operator
with respect to the first argument . It returns an expression [ e' ] such that
with respect to the first argument . It returns an expression [ e' ] such that
BinOp ( [ binop ] , [ e' ] , [ exp1 ] ) = [ exp2 ] . If the [ binop ] operation is not invertible ,
BinOp ( [ binop ] , [ e' ] , [ exp1 ] ) = [ exp2 ] . If the [ binop ] operation is not invertible ,
the function raises an exception by calling " assert false " . * )
the function raises an exception by calling " assert false " . * )
val binop_invert : binop -> exp -> exp -> exp
val binop_invert : binop -> exp -> exp -> exp
(* * This function returns true if 0 is the right unit of [binop].
(* * This function returns true if 0 is the right unit of [binop].
The return value false means " don't know " . * )
The return value false means " don't know " . * )
val binop_is_zero_runit : binop -> bool
val binop_is_zero_runit : binop -> bool
val mem_kind_compare : mem_kind -> mem_kind -> int
val mem_kind_compare : mem_kind -> mem_kind -> int
@ -846,11 +846,11 @@ val pp_typ_full : printenv -> Format.formatter -> typ -> unit
val typ_to_string : typ -> string
val typ_to_string : typ -> string
(* * [pp_type_decl pe pp_base pp_size f typ] pretty prints a type declaration.
(* * [pp_type_decl pe pp_base pp_size f typ] pretty prints a type declaration.
pp_base prints the variable for a declaration , or can be skip to print only the type
pp_base prints the variable for a declaration , or can be skip to print only the type
pp_size prints the expression for the array size * )
pp_size prints the expression for the array size * )
val pp_type_decl : printenv -> ( Format . formatter -> unit -> unit ) ->
val pp_type_decl : printenv -> ( Format . formatter -> unit -> unit ) ->
( printenv -> Format . formatter -> exp -> unit ) ->
( printenv -> Format . formatter -> exp -> unit ) ->
Format . formatter -> typ -> unit
Format . formatter -> typ -> unit
(* * Dump a type with all the details. *)
(* * Dump a type with all the details. *)
val d_typ_full : typ -> unit
val d_typ_full : typ -> unit
@ -982,9 +982,9 @@ val pp_hpara_dll : printenv -> Format.formatter -> hpara_dll -> unit
val pp_hpara_dll_list : printenv -> Format . formatter -> hpara_dll list -> unit
val pp_hpara_dll_list : printenv -> Format . formatter -> hpara_dll list -> unit
(* * Module Predicates records the occurrences of predicates as parameters
(* * Module Predicates records the occurrences of predicates as parameters
of ( doubly - ) linked lists and Epara . Provides unique numbering for predicates and an iterator . * )
of ( doubly - ) linked lists and Epara . Provides unique numbering for predicates and an iterator . * )
module Predicates : sig
module Predicates : sig
(* * predicate environment *)
(* * predicate environment *)
type env
type env
(* * create an empty predicate environment *)
(* * create an empty predicate environment *)
val empty_env : unit -> env
val empty_env : unit -> env
@ -1007,9 +1007,9 @@ val pp_hpred_env : printenv -> Predicates.env option -> Format.formatter -> hpre
(* * {2 Functions for traversing SIL data types} *)
(* * {2 Functions for traversing SIL data types} *)
(* * This function should be used before adding a new
(* * This function should be used before adding a new
index to Earray . The [ exp ] is the newly created
index to Earray . The [ exp ] is the newly created
index . This function " cleans " [ exp ] according to whether it is the footprint or current part of the prop .
index . This function " cleans " [ exp ] according to whether it is the footprint or current part of the prop .
The function faults in the re - execution mode , as an internal check of the tool . * )
The function faults in the re - execution mode , as an internal check of the tool . * )
val array_clean_new_index : bool -> exp -> exp
val array_clean_new_index : bool -> exp -> exp
(* * Change exps in strexp using [f]. *)
(* * Change exps in strexp using [f]. *)
@ -1042,15 +1042,15 @@ val hpred_list_get_lexps : (exp -> bool) -> hpred list -> exp list
(* * {2 Utility Functions for Expressions} *)
(* * {2 Utility Functions for Expressions} *)
(* * Turn an expression representing a type into the type it represents
(* * Turn an expression representing a type into the type it represents
If not a sizeof , return the default type if given , otherwise raise an exception * )
If not a sizeof , return the default type if given , otherwise raise an exception * )
val texp_to_typ : typ option -> exp -> typ
val texp_to_typ : typ option -> exp -> typ
(* * If a struct type with field f, return the type of f.
(* * If a struct type with field f, return the type of f.
If not , return the default type if given , otherwise raise an exception * )
If not , return the default type if given , otherwise raise an exception * )
val struct_typ_fld : typ option -> Ident . fieldname -> typ -> typ
val struct_typ_fld : typ option -> Ident . fieldname -> typ -> typ
(* * If an array type, return the type of the element.
(* * If an array type, return the type of the element.
If not , return the default type if given , otherwise raise an exception * )
If not , return the default type if given , otherwise raise an exception * )
val array_typ_elem : typ option -> typ -> typ
val array_typ_elem : typ option -> typ -> typ
(* * Return the root of [lexp]. *)
(* * Return the root of [lexp]. *)
@ -1060,7 +1060,7 @@ val root_of_lexp : exp -> exp
val exp_get_undefined : bool -> exp
val exp_get_undefined : bool -> exp
(* * Checks whether an expression denotes a location using pointer arithmetic.
(* * Checks whether an expression denotes a location using pointer arithmetic.
Currently , catches array - indexing expressions such as a [ i ] only . * )
Currently , catches array - indexing expressions such as a [ i ] only . * )
val exp_pointer_arith : exp -> bool
val exp_pointer_arith : exp -> bool
(* * Integer constant 0 *)
(* * Integer constant 0 *)
@ -1138,7 +1138,7 @@ val fav_mem : fav -> Ident.t -> bool
val fav_from_list : Ident . t list -> fav
val fav_from_list : Ident . t list -> fav
(* * Convert a [fav] to a list of identifiers while preserving the order
(* * Convert a [fav] to a list of identifiers while preserving the order
that identifiers were added to [ fav ] . * )
that identifiers were added to [ fav ] . * )
val fav_to_list : fav -> Ident . t list
val fav_to_list : fav -> Ident . t list
(* * Copy a [fav]. *)
(* * Copy a [fav]. *)
@ -1154,7 +1154,7 @@ val fav_filter_ident : fav -> (Ident.t -> bool) -> unit
val fav_copy_filter_ident : fav -> ( Ident . t -> bool ) -> fav
val fav_copy_filter_ident : fav -> ( Ident . t -> bool ) -> fav
(* * [fav_subset_ident fav1 fav2] returns true if every ident in [fav1]
(* * [fav_subset_ident fav1 fav2] returns true if every ident in [fav1]
is in [ fav2 ] . * )
is in [ fav2 ] . * )
val fav_subset_ident : fav -> fav -> bool
val fav_subset_ident : fav -> fav -> bool
(* * add identifier list to fav *)
(* * add identifier list to fav *)
@ -1190,9 +1190,9 @@ val hpara_dll_shallow_av : hpara_dll -> fav
(* * {2 Functions for computing all free or bound non-program variables} *)
(* * {2 Functions for computing all free or bound non-program variables} *)
(* * Non-program variables include all of primed, normal and footprint
(* * Non-program variables include all of primed, normal and footprint
variables . Thus , the functions essentially compute all the
variables . Thus , the functions essentially compute all the
identifiers occuring in a parameter . Some variables can appear more
identifiers occuring in a parameter . Some variables can appear more
than once in the result . * )
than once in the result . * )
val exp_av_add : fav -> exp -> unit
val exp_av_add : fav -> exp -> unit
@ -1209,8 +1209,8 @@ val hpara_av_add : fav -> hpara -> unit
type subst
type subst
(* * Create a substitution from a list of pairs.
(* * Create a substitution from a list of pairs.
For all ( id1 , e1 ) , ( id2 , e2 ) in the input list ,
For all ( id1 , e1 ) , ( id2 , e2 ) in the input list ,
if id1 = id2 , then e1 = e2 . * )
if id1 = id2 , then e1 = e2 . * )
val sub_of_list : ( Ident . t * exp ) list -> subst
val sub_of_list : ( Ident . t * exp ) list -> subst
(* * like sub_of_list, but allow duplicate ids and only keep the first occurrence *)
(* * like sub_of_list, but allow duplicate ids and only keep the first occurrence *)
@ -1229,34 +1229,34 @@ val sub_compare : subst -> subst -> int
val sub_equal : subst -> subst -> bool
val sub_equal : subst -> subst -> bool
(* * Compute the common id-exp part of two inputs [subst1] and [subst2].
(* * Compute the common id-exp part of two inputs [subst1] and [subst2].
The first component of the output is this common part .
The first component of the output is this common part .
The second and third components are the remainder of [ subst1 ]
The second and third components are the remainder of [ subst1 ]
and [ subst2 ] , respectively . * )
and [ subst2 ] , respectively . * )
val sub_join : subst -> subst -> subst
val sub_join : subst -> subst -> subst
(* * Compute the common id-exp part of two inputs [subst1] and [subst2].
(* * Compute the common id-exp part of two inputs [subst1] and [subst2].
The first component of the output is this common part .
The first component of the output is this common part .
The second and third components are the remainder of [ subst1 ]
The second and third components are the remainder of [ subst1 ]
and [ subst2 ] , respectively . * )
and [ subst2 ] , respectively . * )
val sub_symmetric_difference : subst -> subst -> subst * subst * subst
val sub_symmetric_difference : subst -> subst -> subst * subst * subst
(* * [sub_find filter sub] returns the expression associated to the first identifier that satisfies [filter]. Raise [Not_found] if there isn't one. *)
(* * [sub_find filter sub] returns the expression associated to the first identifier that satisfies [filter]. Raise [Not_found] if there isn't one. *)
val sub_find : ( Ident . t -> bool ) -> subst -> exp
val sub_find : ( Ident . t -> bool ) -> subst -> exp
(* * [sub_filter filter sub] restricts the domain of [sub] to the
(* * [sub_filter filter sub] restricts the domain of [sub] to the
identifiers satisfying [ filter ] . * )
identifiers satisfying [ filter ] . * )
val sub_filter : ( Ident . t -> bool ) -> subst -> subst
val sub_filter : ( Ident . t -> bool ) -> subst -> subst
(* * [sub_filter_exp filter sub] restricts the domain of [sub] to the
(* * [sub_filter_exp filter sub] restricts the domain of [sub] to the
identifiers satisfying [ filter ( id , sub ( id ) ) ] . * )
identifiers satisfying [ filter ( id , sub ( id ) ) ] . * )
val sub_filter_pair : ( Ident . t * exp -> bool ) -> subst -> subst
val sub_filter_pair : ( Ident . t * exp -> bool ) -> subst -> subst
(* * [sub_range_partition filter sub] partitions [sub] according to
(* * [sub_range_partition filter sub] partitions [sub] according to
whether range expressions satisfy [ filter ] . * )
whether range expressions satisfy [ filter ] . * )
val sub_range_partition : ( exp -> bool ) -> subst -> subst * subst
val sub_range_partition : ( exp -> bool ) -> subst -> subst * subst
(* * [sub_domain_partition filter sub] partitions [sub] according to
(* * [sub_domain_partition filter sub] partitions [sub] according to
whether domain identifiers satisfy [ filter ] . * )
whether domain identifiers satisfy [ filter ] . * )
val sub_domain_partition : ( Ident . t -> bool ) -> subst -> subst * subst
val sub_domain_partition : ( Ident . t -> bool ) -> subst -> subst * subst
(* * Return the list of identifiers in the domain of the substitution. *)
(* * Return the list of identifiers in the domain of the substitution. *)
@ -1269,7 +1269,7 @@ val sub_range : subst -> exp list
val sub_range_map : ( exp -> exp ) -> subst -> subst
val sub_range_map : ( exp -> exp ) -> subst -> subst
(* * [sub_map f g sub] applies the renaming [f] to identifiers in the domain
(* * [sub_map f g sub] applies the renaming [f] to identifiers in the domain
of [ sub ] and the substitution [ g ] to the expressions in the range of [ sub ] . * )
of [ sub ] and the substitution [ g ] to the expressions in the range of [ sub ] . * )
val sub_map : ( Ident . t -> Ident . t ) -> ( exp -> exp ) -> subst -> subst
val sub_map : ( Ident . t -> Ident . t ) -> ( exp -> exp ) -> subst -> subst
(* * Checks whether [id] belongs to the domain of [subst]. *)
(* * Checks whether [id] belongs to the domain of [subst]. *)
@ -1279,11 +1279,11 @@ val mem_sub : Ident.t -> subst -> bool
val extend_sub : subst -> Ident . t -> exp -> subst option
val extend_sub : subst -> Ident . t -> exp -> subst option
(* * Free auxilary variables in the domain and range of the
(* * Free auxilary variables in the domain and range of the
substitution . * )
substitution . * )
val sub_fav_add : fav -> subst -> unit
val sub_fav_add : fav -> subst -> unit
(* * Free or bound auxilary variables in the domain and range of the
(* * Free or bound auxilary variables in the domain and range of the
substitution . * )
substitution . * )
val sub_av_add : fav -> subst -> unit
val sub_av_add : fav -> subst -> unit
(* * Compute free pvars in a sub *)
(* * Compute free pvars in a sub *)
@ -1304,7 +1304,7 @@ val hpara_sub : subst -> hpara -> hpara
(* * {2 Functions for replacing occurrences of expressions.} *)
(* * {2 Functions for replacing occurrences of expressions.} *)
(* * The first parameter should define a partial function.
(* * The first parameter should define a partial function.
No parts of hpara are replaced by these functions . * )
No parts of hpara are replaced by these functions . * )
val exp_replace_exp : ( exp * exp ) list -> exp -> exp
val exp_replace_exp : ( exp * exp ) list -> exp -> exp
@ -1348,15 +1348,15 @@ val exp_add_offsets : exp -> offset list -> exp
val sigma_to_sigma_ne : hpred list -> ( atom list * hpred list ) list
val sigma_to_sigma_ne : hpred list -> ( atom list * hpred list ) list
(* * [hpara_instantiate para e1 e2 elist] instantiates [para] with [e1],
(* * [hpara_instantiate para e1 e2 elist] instantiates [para] with [e1],
[ e2 ] and [ elist ] . If [ para = lambda ( x , y , xs ) . exists zs . b ] ,
[ e2 ] and [ elist ] . If [ para = lambda ( x , y , xs ) . exists zs . b ] ,
then the result of the instantiation is [ b \ [ e1 / x , e2 / y , elist / xs , _ zs' / zs \ ] ]
then the result of the instantiation is [ b \ [ e1 / x , e2 / y , elist / xs , _ zs' / zs \ ] ]
for some fresh [ _ zs' ] . * )
for some fresh [ _ zs' ] . * )
val hpara_instantiate : hpara -> exp -> exp -> exp list -> Ident . t list * hpred list
val hpara_instantiate : hpara -> exp -> exp -> exp list -> Ident . t list * hpred list
(* * [hpara_dll_instantiate para cell blink flink elist] instantiates [para] with [cell],
(* * [hpara_dll_instantiate para cell blink flink elist] instantiates [para] with [cell],
[ blink ] , [ flink ] , and [ elist ] . If [ para = lambda ( x , y , z , xs ) . exists zs . b ] ,
[ blink ] , [ flink ] , and [ elist ] . If [ para = lambda ( x , y , z , xs ) . exists zs . b ] ,
then the result of the instantiation is [ b \ [ cell / x , blink / y , flink / z , elist / xs , _ zs' / zs \ ] ]
then the result of the instantiation is [ b \ [ cell / x , blink / y , flink / z , elist / xs , _ zs' / zs \ ] ]
for some fresh [ _ zs' ] . * )
for some fresh [ _ zs' ] . * )
val hpara_dll_instantiate : hpara_dll -> exp -> exp -> exp -> exp list -> Ident . t list * hpred list
val hpara_dll_instantiate : hpara_dll -> exp -> exp -> exp -> exp list -> Ident . t list * hpred list
(* * Return the list of expressions that could be understood as outgoing arrows from the strexp *)
(* * Return the list of expressions that could be understood as outgoing arrows from the strexp *)