You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1352 lines
45 KiB
1352 lines
45 KiB
(*
|
|
* Copyright (c) 2009 - 2013 Monoidics ltd.
|
|
* Copyright (c) 2013 - present Facebook, Inc.
|
|
* All rights reserved.
|
|
*
|
|
* 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
|
|
* of patent rights can be found in the PATENTS file in the same directory.
|
|
*)
|
|
|
|
(** The Smallfoot Intermediate Language *)
|
|
|
|
(** {2 Programs and Types} *)
|
|
|
|
(** Type to represent one @Annotation. *)
|
|
type annotation =
|
|
{ class_name: string; (* name of the annotation *)
|
|
parameters: string list; (* currently only one string parameter *) }
|
|
|
|
(** Annotation for one item: a list of annotations with visibility. *)
|
|
type item_annotation = (annotation * bool) list
|
|
|
|
(** Annotation for a method: return value and list of parameters. *)
|
|
type method_annotation =
|
|
item_annotation * item_annotation list
|
|
|
|
type func_attribute =
|
|
| FA_sentinel of int * int
|
|
|
|
(** Visibility modifiers. *)
|
|
type access = Default | Public | Private | Protected
|
|
|
|
(** Type for program variables. There are 4 kinds of variables:
|
|
1) local variables, used for local variables and formal parameters
|
|
2) callee program variables, used to handle recursion ([x | callee] is distinguished from [x])
|
|
3) global variables
|
|
4) seed variables, used to store the initial value of formal parameters
|
|
*)
|
|
type pvar
|
|
|
|
(** Unary operations *)
|
|
type unop =
|
|
| Neg (** Unary minus *)
|
|
| BNot (** Bitwise complement (~) *)
|
|
| LNot (** Logical Not (!) *)
|
|
|
|
(** Binary operations *)
|
|
type binop =
|
|
| PlusA (** arithmetic + *)
|
|
| PlusPI (** pointer + integer *)
|
|
| MinusA (** arithmetic - *)
|
|
| MinusPI (** pointer - integer *)
|
|
| MinusPP (** pointer - pointer *)
|
|
| Mult (** * *)
|
|
| Div (** / *)
|
|
| Mod (** % *)
|
|
| Shiftlt (** shift left *)
|
|
| Shiftrt (** shift right *)
|
|
|
|
| Lt (** < (arithmetic comparison) *)
|
|
| Gt (** > (arithmetic comparison) *)
|
|
| Le (** <= (arithmetic comparison) *)
|
|
| Ge (** >= (arithmetic comparison) *)
|
|
| Eq (** == (arithmetic comparison) *)
|
|
| Ne (** != (arithmetic comparison) *)
|
|
| BAnd (** bitwise and *)
|
|
| BXor (** exclusive-or *)
|
|
| BOr (** inclusive-or *)
|
|
|
|
| LAnd (** logical and. Does not always evaluate both operands. *)
|
|
| LOr (** logical or. Does not always evaluate both operands. *)
|
|
| PtrFld (** field offset via pointer to field: takes the address of a
|
|
Csu.t and a Cptr_to_fld constant to form an Lfield expression (see prop.ml) *)
|
|
|
|
(** Kinds of integers *)
|
|
type ikind =
|
|
IChar (** [char] *)
|
|
| ISChar (** [signed char] *)
|
|
| IUChar (** [unsigned char] *)
|
|
| IBool (** [bool] *)
|
|
| IInt (** [int] *)
|
|
| IUInt (** [unsigned int] *)
|
|
| IShort (** [short] *)
|
|
| IUShort (** [unsigned short] *)
|
|
| ILong (** [long] *)
|
|
| IULong (** [unsigned long] *)
|
|
| ILongLong (** [long long] (or [_int64] on Microsoft Visual C) *)
|
|
| IULongLong (** [unsigned long long] (or [unsigned _int64] on Microsoft Visual C) *)
|
|
| I128 (** [__int128_t] *)
|
|
| IU128 (** [__uint128_t] *)
|
|
|
|
(** Kinds of floating-point numbers*)
|
|
type fkind =
|
|
| FFloat (** [float] *)
|
|
| FDouble (** [double] *)
|
|
| FLongDouble (** [long double] *)
|
|
|
|
type mem_kind =
|
|
| Mmalloc (** memory allocated with malloc *)
|
|
| Mnew (** memory allocated with new *)
|
|
| Mnew_array (** memory allocated with new[] *)
|
|
| Mobjc (** memory allocated with objective-c alloc *)
|
|
|
|
(** resource that can be allocated *)
|
|
type resource =
|
|
| Rmemory of mem_kind
|
|
| Rfile
|
|
| Rignore
|
|
| Rlock
|
|
|
|
(** kind of resource action *)
|
|
type res_act_kind =
|
|
| Racquire
|
|
| Rrelease
|
|
|
|
(** kind of dangling pointers *)
|
|
type dangling_kind =
|
|
| DAuninit (** pointer is dangling because it is uninitialized *)
|
|
| DAaddr_stack_var (** pointer is dangling because it is the address of a stack variable which went out of scope *)
|
|
| DAminusone (** pointer is -1 *)
|
|
|
|
(** kind of pointer *)
|
|
type ptr_kind =
|
|
| Pk_pointer (* C/C++, Java, Objc standard/__strong pointer*)
|
|
| Pk_reference (* C++ reference *)
|
|
| Pk_objc_weak (* Obj-C __weak pointer*)
|
|
| Pk_objc_unsafe_unretained (* Obj-C __unsafe_unretained pointer *)
|
|
| Pk_objc_autoreleasing (* Obj-C __autoreleasing pointer *)
|
|
|
|
(** position in a path: proc name, node id *)
|
|
type path_pos = Procname.t * int
|
|
|
|
(** module for subtypes, to be used with Sizeof info *)
|
|
module Subtype : sig
|
|
type t
|
|
val exact : t (** denotes the current type only *)
|
|
val subtypes : t (** denotes the current type and any subtypes *)
|
|
val subtypes_cast : t
|
|
val subtypes_instof : t
|
|
val join : t -> t -> t
|
|
(** [case_analysis (c1, st1) (c2,st2) f] performs case analysis on [c1 <: c2] according
|
|
to [st1] and [st2] where f c1 c2 is true if c1 is a subtype of c2.
|
|
get_subtypes returning a pair:
|
|
- whether [st1] and [st2] admit [c1 <: c2], and in case return the updated subtype [st1]
|
|
- whether [st1] and [st2] admit [not(c1 <: c2)], and in case return
|
|
the updated subtype [st1] *)
|
|
val case_analysis : (Typename.t * t) -> (Typename.t * t) ->
|
|
(Typename.t -> Typename.t -> bool) -> (Typename.t -> bool) -> t option * t option
|
|
val check_subtype : (Typename.t -> Typename.t -> bool) -> Typename.t -> Typename.t -> bool
|
|
val subtypes_to_string : t -> string
|
|
val is_cast : t -> bool
|
|
val is_instof : t -> bool
|
|
(** equality ignoring flags in the subtype *)
|
|
val equal_modulo_flag : t -> t -> bool
|
|
end
|
|
|
|
(** module for signed and unsigned integers *)
|
|
module Int : sig
|
|
type t
|
|
val add : t -> t -> t
|
|
|
|
(** compare the value of the integers, notice this is different from const compare, which distinguished between signed and unsigned +1 *)
|
|
val compare_value : t -> t -> int
|
|
val div : t -> t -> t
|
|
val eq : t -> t -> bool
|
|
val of_int : int -> t
|
|
val of_int32 : int32 -> t
|
|
val of_int64 : int64 -> t
|
|
val geq : t -> t -> bool
|
|
val gt : t -> t -> bool
|
|
val isminusone : t -> bool
|
|
val isnegative : t -> bool
|
|
val isnull : t -> bool
|
|
val isone : t -> bool
|
|
val iszero : t -> bool
|
|
val leq : t -> t -> bool
|
|
val logand : t -> t -> t
|
|
val lognot : t -> t
|
|
val logor : t -> t -> t
|
|
val logxor : t -> t -> t
|
|
val lt : t -> t -> bool
|
|
val minus_one : t
|
|
val mul : t -> t -> t
|
|
val neg : t -> t
|
|
val neq : t -> t -> bool
|
|
val null : t (** null behaves like zero except for the function isnull *)
|
|
val one : t
|
|
val pp : Format.formatter -> t -> unit
|
|
val rem : t -> t -> t
|
|
val sub : t -> t -> t
|
|
val to_int : t -> int
|
|
val to_signed : t -> t option (** convert to signed if the value is representable *)
|
|
val to_string : t -> string
|
|
val two : t
|
|
val zero : t
|
|
end
|
|
|
|
(** Flags for a procedure call *)
|
|
type call_flags = {
|
|
cf_virtual : bool;
|
|
cf_interface : bool;
|
|
cf_noreturn : bool;
|
|
cf_is_objc_block : bool;
|
|
cf_targets : Procname.t list;
|
|
}
|
|
|
|
(** Default value for call_flags where all fields are set to false *)
|
|
val cf_default : call_flags
|
|
|
|
(** expression representing the result of decompilation *)
|
|
type dexp =
|
|
| Darray of dexp * dexp
|
|
| Dbinop of binop * dexp * dexp
|
|
| Dconst of const
|
|
| Dsizeof of typ * Subtype.t
|
|
| Dderef of dexp
|
|
| Dfcall of dexp * dexp list * Location.t * call_flags
|
|
| Darrow of dexp * Ident.fieldname
|
|
| Ddot of dexp * Ident.fieldname
|
|
| Dpvar of pvar
|
|
| Dpvaraddr of pvar
|
|
| Dunop of unop * dexp
|
|
| Dunknown
|
|
| Dretcall of dexp * dexp list * Location.t * call_flags
|
|
|
|
(** Value paths: identify an occurrence of a value in a symbolic heap
|
|
each expression represents a path, with Dpvar being the simplest one *)
|
|
and vpath =
|
|
dexp option
|
|
|
|
(** acquire/release action on a resource *)
|
|
and res_action =
|
|
{ ra_kind : res_act_kind; (** kind of action *)
|
|
ra_res : resource; (** kind of resource *)
|
|
ra_pname : Procname.t; (** name of the procedure used to acquire/release the resource *)
|
|
ra_loc : Location.t; (** location of the acquire/release *)
|
|
ra_vpath: vpath; (** vpath of the resource value *)
|
|
}
|
|
|
|
and taint_kind =
|
|
| UnverifiedSSLSocket
|
|
| SharedPreferencesData
|
|
| Unknown
|
|
|
|
and taint_info = {
|
|
taint_source : Procname.t;
|
|
taint_kind : taint_kind;
|
|
}
|
|
|
|
(** Attributes *)
|
|
and attribute =
|
|
| Aresource of res_action (** resource acquire/release *)
|
|
| Aautorelease
|
|
| Adangling of dangling_kind (** dangling pointer *)
|
|
(** undefined value obtained by calling the given procedure *)
|
|
| Aundef of Procname.t * Location.t * path_pos
|
|
| Ataint of taint_info
|
|
| Auntaint
|
|
| Alocked
|
|
| Aunlocked
|
|
(** value appeared in second argument of division at given path position *)
|
|
| Adiv0 of path_pos
|
|
(** the exp. is null because of a call to a method with exp as a null receiver *)
|
|
| Aobjc_null of exp
|
|
(** value was returned from a call to the given procedure *)
|
|
| Aretval of Procname.t
|
|
(** denotes an object registered as an observers to a notification center *)
|
|
| Aobserver
|
|
(** denotes an object unsubscribed from observers of a notification center *)
|
|
| Aunsubscribed_observer
|
|
|
|
(** Categories of attributes *)
|
|
and attribute_category =
|
|
| ACresource
|
|
| ACautorelease
|
|
| ACtaint
|
|
| AClock
|
|
| ACdiv0
|
|
| ACobjc_null
|
|
| ACundef
|
|
| ACretval
|
|
| ACobserver
|
|
|
|
(** Constants *)
|
|
and const =
|
|
| Cint of Int.t (** integer constants *)
|
|
| Cfun of Procname.t (** function names *)
|
|
| Cstr of string (** string constants *)
|
|
| Cfloat of float (** float constants *)
|
|
| Cattribute of attribute (** attribute used in disequalities to annotate a value *)
|
|
| Cexn of exp (** exception *)
|
|
| Cclass of Ident.name (** class constant *)
|
|
| Cptr_to_fld of Ident.fieldname * typ (** pointer to field constant,
|
|
and type of the surrounding Csu.t type *)
|
|
| Ctuple of exp list (** tuple of values *)
|
|
|
|
and struct_fields = (Ident.fieldname * typ * item_annotation) list
|
|
|
|
(** Type for a structured value. *)
|
|
and struct_typ = {
|
|
instance_fields : struct_fields; (** non-static fields *)
|
|
static_fields : struct_fields; (** static fields *)
|
|
csu : Csu.t; (** class/struct/union *)
|
|
struct_name : Mangled.t option; (** name *)
|
|
superclasses : Typename.t list; (** list of superclasses *)
|
|
def_methods : Procname.t list; (** methods defined *)
|
|
struct_annotations : item_annotation; (** annotations *)
|
|
}
|
|
|
|
(** Types for sil (structured) expressions. *)
|
|
and typ =
|
|
| Tvar of Typename.t (** named type *)
|
|
| Tint of ikind (** integer type *)
|
|
| Tfloat of fkind (** float type *)
|
|
| Tvoid (** void type *)
|
|
| Tfun of bool (** function type with noreturn attribute *)
|
|
| Tptr of typ * ptr_kind (** pointer type *)
|
|
| Tstruct of struct_typ (** Type for a structured value *)
|
|
| Tarray of typ * exp (** array type with fixed size *)
|
|
|
|
(** Program expressions. *)
|
|
and exp =
|
|
| Var of Ident.t (** pure variable: it is not an lvalue *)
|
|
| UnOp of unop * exp * typ option (** unary operator with type of the result if known *)
|
|
| BinOp of binop * exp * exp (** binary operator *)
|
|
| Const of const (** constants *)
|
|
| Cast of typ * exp (** type cast *)
|
|
| Lvar of pvar (** the address of a program variable *)
|
|
| Lfield of exp * Ident.fieldname * typ (** a field offset, the type is the surrounding struct type *)
|
|
| Lindex of exp * exp (** an array index offset: [exp1\[exp2\]] *)
|
|
| Sizeof of typ * Subtype.t (** a sizeof expression *)
|
|
|
|
(** Sets of types. *)
|
|
module TypSet : Set.S with type elt = typ
|
|
|
|
(** Maps with type keys. *)
|
|
module TypMap : Map.S with type key = typ
|
|
|
|
(** Sets of expressions. *)
|
|
module ExpSet : Set.S with type elt = exp
|
|
|
|
(** Maps with expression keys. *)
|
|
module ExpMap : Map.S with type key = exp
|
|
|
|
(** Hashtable with expressions as keys. *)
|
|
module ExpHash : Hashtbl.S with type key = exp
|
|
|
|
(** Convert expression lists to expression sets. *)
|
|
val elist_to_eset : exp list -> ExpSet.t
|
|
|
|
(** Kind of prune instruction *)
|
|
type if_kind =
|
|
| Ik_bexp (* boolean expressions, and exp ? exp : exp *)
|
|
| Ik_dowhile
|
|
| Ik_for
|
|
| Ik_if
|
|
| Ik_land_lor (* obtained from translation of && or || *)
|
|
| Ik_while
|
|
| Ik_switch
|
|
|
|
(** Stack operation for symbolic execution on propsets *)
|
|
type stackop =
|
|
| Push (* copy the curreny propset to the stack *)
|
|
| Swap (* swap the current propset and the top of the stack *)
|
|
| Pop (* pop the stack and combine with the current propset *)
|
|
|
|
(** An instruction. *)
|
|
type instr =
|
|
(** declaration [let x = *lexp:typ] where [typ] is the root type of [lexp] *)
|
|
| Letderef of Ident.t * exp * typ * Location.t
|
|
(** assignment [*lexp1:typ = exp2] where [typ] is the root type of [lexp1] *)
|
|
| Set of exp * typ * exp * Location.t
|
|
(** prune the state based on [exp=1], the boolean indicates whether true branch *)
|
|
| Prune of exp * Location.t * bool * if_kind
|
|
(** [Call (ret_id1..ret_idn, e_fun, arg_ts, loc, call_flags)] represents an instructions
|
|
[ret_id1..ret_idn = e_fun(arg_ts);]
|
|
where n = 0 for void return and n > 1 for struct return *)
|
|
| Call of Ident.t list * exp * (exp * typ) list * Location.t * call_flags
|
|
(** nullify stack variable, the bool parameter indicates whether to deallocate the variable *)
|
|
| Nullify of pvar * Location.t * bool
|
|
| Abstract of Location.t (** apply abstraction *)
|
|
| Remove_temps of Ident.t list * Location.t (** remove temporaries *)
|
|
| Stackop of stackop * Location.t (** operation on the stack of propsets *)
|
|
| Declare_locals of (pvar * typ) list * Location.t (** declare local variables *)
|
|
(** jump to a specific cfg node,
|
|
assuming all the possible target nodes are successors of the current node *)
|
|
| Goto_node of exp * Location.t
|
|
|
|
(** Check if an instruction is auxiliary, or if it comes from source instructions. *)
|
|
val instr_is_auxiliary : instr -> bool
|
|
|
|
(** Offset for an lvalue. *)
|
|
type offset = Off_fld of Ident.fieldname * typ | Off_index of exp
|
|
|
|
(** {2 Components of Propositions} *)
|
|
|
|
(** an atom is a pure atomic formula *)
|
|
type atom =
|
|
| Aeq of exp * exp (** equality *)
|
|
| Aneq of exp * exp (** disequality*)
|
|
|
|
(** kind of lseg or dllseg predicates *)
|
|
type lseg_kind =
|
|
| Lseg_NE (** nonempty (possibly circular) listseg *)
|
|
| Lseg_PE (** possibly empty (possibly circular) listseg *)
|
|
|
|
(** The boolean is true when the pointer was dereferenced without testing for zero. *)
|
|
type zero_flag = bool option
|
|
|
|
(** True when the value was obtained by doing case analysis on null in a procedure call. *)
|
|
type null_case_flag = bool
|
|
|
|
(** instrumentation of heap values *)
|
|
type inst =
|
|
| Iabstraction
|
|
| Iactual_precondition
|
|
| Ialloc
|
|
| Iformal of zero_flag * null_case_flag
|
|
| Iinitial
|
|
| Ilookup
|
|
| Inone
|
|
| Inullify
|
|
| Irearrange of zero_flag * null_case_flag * int * path_pos
|
|
| Itaint
|
|
| Iupdate of zero_flag * null_case_flag * int * path_pos
|
|
| Ireturn_from_call of int
|
|
|
|
val inst_abstraction : inst
|
|
val inst_actual_precondition : inst
|
|
val inst_alloc : inst
|
|
val inst_formal : inst (** for formal parameters and heap values at the beginning of the function *)
|
|
val inst_initial : inst (** for initial values *)
|
|
val inst_lookup : inst
|
|
val inst_none : inst
|
|
val inst_nullify : inst
|
|
(** the boolean indicates whether the pointer is known nonzero *)
|
|
val inst_rearrange : bool -> Location.t -> path_pos -> inst
|
|
val inst_taint : inst
|
|
val inst_update : Location.t -> path_pos -> inst
|
|
|
|
(** Get the null case flag of the inst. *)
|
|
val inst_get_null_case_flag : inst -> bool option
|
|
|
|
(** Set the null case flag of the inst. *)
|
|
val inst_set_null_case_flag : inst -> inst
|
|
|
|
(** update the location of the instrumentation *)
|
|
val inst_new_loc : Location.t -> inst -> inst
|
|
|
|
(** Update [inst_old] to [inst_new] preserving the zero flag *)
|
|
val update_inst : inst -> inst -> inst
|
|
|
|
(** join of instrumentations *)
|
|
val inst_partial_join : inst -> inst -> inst
|
|
|
|
(** meet of instrumentations *)
|
|
val inst_partial_meet : inst -> inst -> inst
|
|
|
|
(** structured expressions represent a value of structured type, such as an array or a struct. *)
|
|
type strexp =
|
|
| Eexp of exp * inst (** Base case: expression with instrumentation *)
|
|
| Estruct of (Ident.fieldname * strexp) list * inst (** C structure *)
|
|
| Earray of exp * (exp * strexp) list * inst (** Array of given size. *)
|
|
(** There are two conditions imposed / used in the array case.
|
|
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.
|
|
For instance, x |->[10 | e1: v1] implies that e1 <= 9.
|
|
Second, if two indices appear in an array, they should be different.
|
|
For instance, x |->[10 | e1: v1, e2: v2] implies that e1 != e2. *)
|
|
|
|
(** an atomic heap predicate *)
|
|
and hpred =
|
|
| Hpointsto of exp * strexp * exp
|
|
(** represents [exp|->strexp:typexp] where [typexp]
|
|
is an expression representing a type, e.h. [sizeof(t)]. *)
|
|
| Hlseg of lseg_kind * hpara * exp * exp * exp list
|
|
(** higher - order predicate for singly - linked lists.
|
|
Should ensure that exp1!= exp2 implies that exp1 is allocated.
|
|
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.*)
|
|
| Hdllseg of lseg_kind * hpara_dll * exp * exp * exp * exp * exp list
|
|
(** higher-order predicate for doubly-linked lists. *)
|
|
|
|
(** parameter for the higher-order singly-linked list predicate.
|
|
Means "lambda (root,next,svars). Exists evars. body".
|
|
Assume that root, next, svars, evars are disjoint sets of
|
|
primed identifiers, and include all the free primed identifiers in body.
|
|
body should not contain any non - primed identifiers or program
|
|
variables (i.e. pvars). *)
|
|
and hpara =
|
|
{ root: Ident.t;
|
|
next: Ident.t;
|
|
svars: Ident.t list;
|
|
evars: Ident.t list;
|
|
body: hpred list }
|
|
|
|
(** parameter for the higher-order doubly-linked list predicates.
|
|
Assume that all the free identifiers in body_dll should belong to
|
|
cell, blink, flink, svars_dll, evars_dll. *)
|
|
and hpara_dll =
|
|
{ cell: Ident.t; (** address cell *)
|
|
blink: Ident.t; (** backward link *)
|
|
flink: Ident.t; (** forward link *)
|
|
svars_dll: Ident.t list;
|
|
evars_dll: Ident.t list;
|
|
body_dll: hpred list }
|
|
|
|
(** Sets of heap predicates *)
|
|
module HpredSet : Set.S with type elt = hpred
|
|
|
|
(** {2 Compaction} *)
|
|
|
|
type sharing_env
|
|
|
|
(** Create a sharing env to store canonical representations *)
|
|
val create_sharing_env : unit -> sharing_env
|
|
|
|
(** Return a canonical representation of the exp *)
|
|
val exp_compact : sharing_env -> exp -> exp
|
|
|
|
(** Return a compact representation of the exp *)
|
|
val hpred_compact : sharing_env -> hpred -> hpred
|
|
|
|
(** {2 Type Environment} *)
|
|
|
|
type tenv (** Type for type environment. *)
|
|
|
|
(** Create a new type environment. *)
|
|
val create_tenv : unit -> tenv
|
|
|
|
(** Check if typename is found in tenv *)
|
|
val tenv_mem : tenv -> Typename.t -> bool
|
|
|
|
(** Look up a name in the global type environment. *)
|
|
val tenv_lookup : tenv -> Typename.t -> struct_typ option
|
|
|
|
(** Add a (name,typ) pair to the global type environment. *)
|
|
val tenv_add : tenv -> Typename.t -> struct_typ -> unit
|
|
|
|
(** expand a type if it is a typename by looking it up in the type environment *)
|
|
val expand_type : tenv -> typ -> typ
|
|
|
|
(** type environment used for parsing, to be set by the client of the parser module *)
|
|
val tenv_for_parsing : tenv ref
|
|
|
|
(** Load a type environment from a file *)
|
|
val load_tenv_from_file : DB.filename -> tenv option
|
|
|
|
(** Save a type environment into a file *)
|
|
val store_tenv_to_file : DB.filename -> tenv -> unit
|
|
|
|
(** iterate over a type environment *)
|
|
val tenv_iter : (Typename.t -> struct_typ -> unit) -> tenv -> unit
|
|
|
|
val tenv_fold : (Typename.t -> struct_typ -> 'a -> 'a) -> tenv -> 'a -> 'a
|
|
|
|
(** print a type environment *)
|
|
val pp_tenv : Format.formatter -> tenv -> unit
|
|
|
|
(** Return the lhs expression of a hpred *)
|
|
val hpred_get_lhs : hpred -> exp
|
|
|
|
(** Field used for objective-c reference counting *)
|
|
val objc_ref_counter_field : (Ident.fieldname * typ * item_annotation)
|
|
|
|
(** {2 Comparision And Inspection Functions} *)
|
|
|
|
val is_objc_ref_counter_field : (Ident.fieldname * typ * item_annotation) -> bool
|
|
|
|
val has_objc_ref_counter : hpred -> bool
|
|
|
|
val objc_class_annotation : (annotation * bool) list
|
|
|
|
val cpp_class_annotation : (annotation * bool) list
|
|
|
|
val is_objc_class : typ -> bool
|
|
|
|
val is_cpp_class : typ -> bool
|
|
|
|
val is_java_class : typ -> bool
|
|
|
|
val exp_is_zero : exp -> bool
|
|
|
|
val exp_is_null_literal : exp -> bool
|
|
|
|
(** return true if [exp] is the special this/self expression *)
|
|
val exp_is_this : exp -> bool
|
|
|
|
val path_pos_equal : path_pos -> path_pos -> bool
|
|
|
|
(** turn a *T into a T. fails if [typ] is not a pointer type *)
|
|
val typ_strip_ptr : typ -> typ
|
|
|
|
val zero_value_of_numerical_type : typ -> exp
|
|
|
|
val pvar_get_name : pvar -> Mangled.t
|
|
|
|
val pvar_to_string : pvar -> string
|
|
|
|
(** Turn a pvar into a seed pvar (which stores the initial value of a stack var) *)
|
|
val pvar_to_seed : pvar -> pvar
|
|
|
|
(** Check if the pvar is a callee var *)
|
|
val pvar_is_callee : pvar -> bool
|
|
|
|
(** Check if the pvar is an abducted return var or param passed by ref *)
|
|
val pvar_is_abducted : pvar -> bool
|
|
|
|
(** Check if the pvar is a local var *)
|
|
val pvar_is_local : pvar -> bool
|
|
|
|
(** Check if the pvar is a seed var *)
|
|
val pvar_is_seed : pvar -> bool
|
|
|
|
(** Check if the pvar is a global var *)
|
|
val pvar_is_global : pvar -> bool
|
|
|
|
(** Check if a pvar is the special "this" var *)
|
|
val pvar_is_this : pvar -> bool
|
|
|
|
(** Check if the pvar is a return var *)
|
|
val pvar_is_return : pvar -> bool
|
|
|
|
(** Make a static local name in objc *)
|
|
val mk_static_local_name : string -> string -> string
|
|
|
|
(** Check if a pvar is a local static in objc *)
|
|
val is_static_local_name : string -> pvar -> bool
|
|
|
|
(* A block pvar used to explain retain cycles *)
|
|
val block_pvar : pvar
|
|
|
|
(** Check if a pvar is a local pointing to a block in objc *)
|
|
val is_block_pvar : pvar -> bool
|
|
|
|
(** Check if type is a type for a block in objc *)
|
|
val is_block_type : typ -> bool
|
|
|
|
(** Compare two pvar's *)
|
|
val pvar_compare : pvar -> pvar -> int
|
|
|
|
(** Equality for pvar's *)
|
|
val pvar_equal : pvar -> pvar -> bool
|
|
|
|
(** Comparision for fieldnames. *)
|
|
val fld_compare : Ident.fieldname -> Ident.fieldname -> int
|
|
|
|
(** Equality for fieldnames. *)
|
|
val fld_equal : Ident.fieldname -> Ident.fieldname -> bool
|
|
|
|
(** Check wheter the integer kind is a char *)
|
|
val ikind_is_char : ikind -> bool
|
|
|
|
(** Check wheter the integer kind is unsigned *)
|
|
val ikind_is_unsigned : ikind -> bool
|
|
|
|
(** Convert an int64 into an Int.t given the kind: the int64 is interpreted as unsigned according to the kind *)
|
|
val int_of_int64_kind : int64 -> ikind -> Int.t
|
|
|
|
(** Comparision for ptr_kind *)
|
|
val ptr_kind_compare : ptr_kind -> ptr_kind -> int
|
|
|
|
(** Comparision for types. *)
|
|
val typ_compare : typ -> typ -> int
|
|
|
|
(** Equality for types. *)
|
|
val typ_equal : typ -> typ -> bool
|
|
|
|
(** Comparision for fieldnames * types * item annotations. *)
|
|
val fld_typ_ann_compare : Ident.fieldname * typ * item_annotation -> Ident.fieldname * typ * item_annotation -> int
|
|
|
|
val unop_equal : unop -> unop -> bool
|
|
|
|
val binop_equal : binop -> binop -> bool
|
|
|
|
(** This function returns true if the operation is injective
|
|
wrt. each argument: op(e,-) and op(-, e) is injective for all e.
|
|
The return value false means "don't know". *)
|
|
val binop_injective : binop -> bool
|
|
|
|
(** This function returns true if the operation can be inverted. *)
|
|
val binop_invertible : binop -> bool
|
|
|
|
(** This function inverts an injective binary operator
|
|
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,
|
|
the function raises an exception by calling "assert false". *)
|
|
val binop_invert : binop -> exp -> exp -> exp
|
|
|
|
(** This function returns true if 0 is the right unit of [binop].
|
|
The return value false means "don't know". *)
|
|
val binop_is_zero_runit : binop -> bool
|
|
|
|
val mem_kind_compare : mem_kind -> mem_kind -> int
|
|
|
|
val attribute_compare : attribute -> attribute -> int
|
|
|
|
val attribute_equal : attribute -> attribute -> bool
|
|
|
|
val attribute_category_compare : attribute_category -> attribute_category -> int
|
|
|
|
val attribute_category_equal : attribute_category -> attribute_category -> bool
|
|
|
|
(** Return the category to which the attribute belongs. *)
|
|
val attribute_to_category : attribute -> attribute_category
|
|
|
|
val attr_is_undef : attribute -> bool
|
|
|
|
val const_compare : const -> const -> int
|
|
|
|
val const_equal : const -> const -> bool
|
|
|
|
(** Return true if the constants have the same kind (both integers, ...) *)
|
|
val const_kind_equal : const -> const -> bool
|
|
|
|
val exp_compare : exp -> exp -> int
|
|
|
|
val exp_equal : exp -> exp -> bool
|
|
|
|
val call_flags_compare : call_flags -> call_flags -> int
|
|
|
|
val exp_typ_compare : (exp * typ) -> (exp * typ) -> int
|
|
|
|
val instr_compare : instr -> instr -> int
|
|
|
|
(** compare instructions from different procedures without considering loc's, ident's, and pvar's.
|
|
the [exp_map] param gives a mapping of names used in the procedure of [instr1] to identifiers
|
|
used in the procedure of [instr2] *)
|
|
val instr_compare_structural : instr -> instr -> exp ExpMap.t -> (int * exp ExpMap.t)
|
|
|
|
val exp_list_compare : exp list -> exp list -> int
|
|
|
|
val exp_list_equal : exp list -> exp list -> bool
|
|
|
|
val atom_compare : atom -> atom -> int
|
|
|
|
val atom_equal : atom -> atom -> bool
|
|
|
|
val strexp_compare : strexp -> strexp -> int
|
|
|
|
val strexp_equal : strexp -> strexp -> bool
|
|
|
|
val hpara_compare : hpara -> hpara -> int
|
|
|
|
val hpara_equal : hpara -> hpara -> bool
|
|
|
|
val hpara_dll_compare : hpara_dll -> hpara_dll -> int
|
|
|
|
val hpara_dll_equal : hpara_dll -> hpara_dll -> bool
|
|
|
|
val lseg_kind_compare : lseg_kind -> lseg_kind -> int
|
|
|
|
val lseg_kind_equal : lseg_kind -> lseg_kind -> bool
|
|
|
|
val hpred_compare : hpred -> hpred -> int
|
|
|
|
val hpred_equal : hpred -> hpred -> bool
|
|
|
|
val fld_strexp_compare : Ident.fieldname * strexp -> Ident.fieldname * strexp -> int
|
|
|
|
val fld_strexp_list_compare : (Ident.fieldname * strexp) list -> (Ident.fieldname * strexp) list -> int
|
|
|
|
val exp_strexp_compare : exp * strexp -> exp * strexp -> int
|
|
|
|
(** Compare function for annotations. *)
|
|
val annotation_compare : annotation -> annotation -> int
|
|
|
|
(** Compare function for annotation items. *)
|
|
val item_annotation_compare : item_annotation -> item_annotation -> int
|
|
|
|
(** Compare function for Method annotations. *)
|
|
val method_annotation_compare : method_annotation -> method_annotation -> int
|
|
|
|
(** Empty item annotation. *)
|
|
val item_annotation_empty : item_annotation
|
|
|
|
(** Empty method annotation. *)
|
|
val method_annotation_empty : method_annotation
|
|
|
|
(** Check if the item annodation is empty. *)
|
|
val item_annotation_is_empty : item_annotation -> bool
|
|
|
|
(** Check if the method annodation is empty. *)
|
|
val method_annotation_is_empty : method_annotation -> bool
|
|
|
|
(** Return the value of the FA_sentinel attribute in [attr_list] if it is found *)
|
|
val get_sentinel_func_attribute_value : func_attribute list -> (int * int) option
|
|
|
|
(** {2 Pretty Printing} *)
|
|
|
|
(** Begin change color if using diff printing, return updated printenv and change status *)
|
|
val color_pre_wrapper : printenv -> Format.formatter -> 'a -> printenv * bool
|
|
|
|
(** Close color annotation if changed *)
|
|
val color_post_wrapper : bool -> printenv -> Format.formatter -> unit
|
|
|
|
(** String representation of a unary operator. *)
|
|
val str_unop : unop -> string
|
|
|
|
(** String representation of a binary operator. *)
|
|
val str_binop : printenv -> binop -> string
|
|
|
|
(** name of the allocation function for the given memory kind *)
|
|
val mem_alloc_pname : mem_kind -> Procname.t
|
|
|
|
(** name of the deallocation function for the given memory kind *)
|
|
val mem_dealloc_pname : mem_kind -> Procname.t
|
|
|
|
(** Pretty print an annotation. *)
|
|
val pp_annotation : Format.formatter -> annotation -> unit
|
|
|
|
(** Pretty print a const. *)
|
|
val pp_const: printenv -> Format.formatter -> const -> unit
|
|
|
|
(** Pretty print an item annotation. *)
|
|
val pp_item_annotation : Format.formatter -> item_annotation -> unit
|
|
|
|
val item_annotation_to_string : item_annotation -> string
|
|
|
|
(** Pretty print a method annotation. *)
|
|
val pp_method_annotation : string -> Format.formatter -> method_annotation -> unit
|
|
|
|
(** Pretty print a type. *)
|
|
val pp_typ : printenv -> Format.formatter -> typ -> unit
|
|
|
|
(** Pretty print a type with all the details. *)
|
|
val pp_typ_full : printenv -> Format.formatter -> typ -> unit
|
|
|
|
val typ_to_string : typ -> string
|
|
|
|
(** [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_size prints the expression for the array size *)
|
|
val pp_type_decl: printenv -> (Format.formatter -> unit -> unit) ->
|
|
(printenv -> Format.formatter -> exp -> unit) ->
|
|
Format.formatter -> typ -> unit
|
|
|
|
(** Dump a type with all the details. *)
|
|
val d_typ_full : typ -> unit
|
|
|
|
(** Dump a list of types. *)
|
|
val d_typ_list : typ list -> unit
|
|
|
|
(** Pretty print a program variable. *)
|
|
val pp_pvar : printenv -> Format.formatter -> pvar -> unit
|
|
|
|
(** Pretty print a pvar which denotes a value, not an address *)
|
|
val pp_pvar_value : printenv -> Format.formatter -> pvar -> unit
|
|
|
|
(** Dump a program variable. *)
|
|
val d_pvar : pvar -> unit
|
|
|
|
(** Pretty print a list of program variables. *)
|
|
val pp_pvar_list : printenv -> Format.formatter -> pvar list -> unit
|
|
|
|
(** Dump a list of program variables. *)
|
|
val d_pvar_list : pvar list -> unit
|
|
|
|
(** convert the attribute to a string *)
|
|
val attribute_to_string : printenv -> attribute -> string
|
|
|
|
(** convert a dexp to a string *)
|
|
val dexp_to_string : dexp -> string
|
|
|
|
(** Pretty print a dexp. *)
|
|
val pp_dexp : Format.formatter -> dexp -> unit
|
|
|
|
(** Pretty print an expression. *)
|
|
val pp_exp : printenv -> Format.formatter -> exp -> unit
|
|
|
|
(** Pretty print an expression with type. *)
|
|
val pp_exp_typ : printenv -> Format.formatter -> exp * typ -> unit
|
|
|
|
(** Convert an expression to a string *)
|
|
val exp_to_string : exp -> string
|
|
|
|
(** dump an expression. *)
|
|
val d_exp : exp -> unit
|
|
|
|
(** Pretty print a type. *)
|
|
val pp_texp : printenv -> Format.formatter -> exp -> unit
|
|
|
|
(** Pretty print a type with all the details. *)
|
|
val pp_texp_full : printenv -> Format.formatter -> exp -> unit
|
|
|
|
(** Dump a type expression with all the details. *)
|
|
val d_texp_full : exp -> unit
|
|
|
|
(** Pretty print a list of expressions. *)
|
|
val pp_exp_list : printenv -> Format.formatter -> exp list -> unit
|
|
|
|
(** Dump a list of expressions. *)
|
|
val d_exp_list : exp list -> unit
|
|
|
|
(** Pretty print an offset *)
|
|
val pp_offset : printenv -> Format.formatter -> offset -> unit
|
|
|
|
(** Dump an offset *)
|
|
val d_offset : offset -> unit
|
|
|
|
(** Pretty print a list of offsets *)
|
|
val pp_offset_list : printenv -> Format.formatter -> offset list -> unit
|
|
|
|
(** Dump a list of offsets *)
|
|
val d_offset_list : offset list -> unit
|
|
|
|
(** Get the location of the instruction *)
|
|
val instr_get_loc : instr -> Location.t
|
|
|
|
(** get the expressions occurring in the instruction *)
|
|
val instr_get_exps : instr -> exp list
|
|
|
|
(** Pretty print an instruction. *)
|
|
val pp_instr : printenv -> Format.formatter -> instr -> unit
|
|
|
|
(** Dump an instruction. *)
|
|
val d_instr : instr -> unit
|
|
|
|
(** Pretty print a list of instructions. *)
|
|
val pp_instr_list : printenv -> Format.formatter -> instr list -> unit
|
|
|
|
(** Dump a list of instructions. *)
|
|
val d_instr_list : instr list -> unit
|
|
|
|
(** Pretty print a value path *)
|
|
val pp_vpath : printenv -> Format.formatter -> vpath -> unit
|
|
|
|
(** Pretty print an atom. *)
|
|
val pp_atom : printenv -> Format.formatter -> atom -> unit
|
|
|
|
(** Dump an atom. *)
|
|
val d_atom : atom -> unit
|
|
|
|
(** return a string representing the inst *)
|
|
val inst_to_string : inst -> string
|
|
|
|
(** Pretty print a strexp. *)
|
|
val pp_sexp : printenv -> Format.formatter -> strexp -> unit
|
|
|
|
(** Dump a strexp. *)
|
|
val d_sexp : strexp -> unit
|
|
|
|
(** Pretty print a strexp list. *)
|
|
val pp_sexp_list : printenv -> Format.formatter -> strexp list -> unit
|
|
|
|
(** Dump a strexp. *)
|
|
val d_sexp_list : strexp list -> unit
|
|
|
|
(** Pretty print a hpred. *)
|
|
val pp_hpred : printenv -> Format.formatter -> hpred -> unit
|
|
|
|
(** Dump a hpred. *)
|
|
val d_hpred : hpred -> unit
|
|
|
|
(** Pretty print a hpara. *)
|
|
val pp_hpara : printenv -> Format.formatter -> hpara -> unit
|
|
|
|
(** Pretty print a list of hparas. *)
|
|
val pp_hpara_list : printenv -> Format.formatter -> hpara list -> unit
|
|
|
|
(** Pretty print a hpara_dll. *)
|
|
val pp_hpara_dll : printenv -> Format.formatter -> hpara_dll -> unit
|
|
|
|
(** Pretty print a list of hpara_dlls. *)
|
|
val pp_hpara_dll_list : printenv -> Format.formatter -> hpara_dll list -> unit
|
|
|
|
(** Module Predicates records the occurrences of predicates as parameters
|
|
of (doubly -)linked lists and Epara. Provides unique numbering for predicates and an iterator. *)
|
|
module Predicates : sig
|
|
(** predicate environment *)
|
|
type env
|
|
(** create an empty predicate environment *)
|
|
val empty_env : unit -> env
|
|
(** return true if the environment is empty *)
|
|
val is_empty : env -> bool
|
|
(** return the id of the hpara *)
|
|
val get_hpara_id : env -> hpara -> int
|
|
(** return the id of the hpara_dll *)
|
|
val get_hpara_dll_id : env -> hpara_dll -> int
|
|
(** [iter env f f_dll] iterates [f] and [f_dll] on all the hpara and hpara_dll,
|
|
passing the unique id to the functions. The iterator can only be used once. *)
|
|
val iter : env -> (int -> hpara -> unit) -> (int -> hpara_dll -> unit) -> unit
|
|
(** Process one hpred, updating the predicate environment *)
|
|
val process_hpred : env -> hpred -> unit
|
|
end
|
|
|
|
(** Pretty print a hpred with optional predicate env *)
|
|
val pp_hpred_env : printenv -> Predicates.env option -> Format.formatter -> hpred -> unit
|
|
|
|
(** {2 Functions for traversing SIL data types} *)
|
|
|
|
(** This function should be used before adding a new
|
|
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.
|
|
The function faults in the re - execution mode, as an internal check of the tool. *)
|
|
val array_clean_new_index : bool -> exp -> exp
|
|
|
|
(** Change exps in strexp using [f]. *)
|
|
(** WARNING: the result might not be normalized. *)
|
|
val strexp_expmap : (exp * inst option -> exp * inst option) -> strexp -> strexp
|
|
|
|
(** Change exps in hpred by [f]. *)
|
|
(** WARNING: the result might not be normalized. *)
|
|
val hpred_expmap : (exp * inst option -> exp * inst option) -> hpred -> hpred
|
|
|
|
(** Change instrumentations in hpred using [f]. *)
|
|
val hpred_instmap : (inst -> inst) -> hpred -> hpred
|
|
|
|
(** Change exps in hpred list by [f]. *)
|
|
(** WARNING: the result might not be normalized. *)
|
|
val hpred_list_expmap : (exp * inst option -> exp * inst option) -> hpred list -> hpred list
|
|
|
|
(** Change exps in atom by [f]. *)
|
|
(** WARNING: the result might not be normalized. *)
|
|
val atom_expmap : (exp -> exp) -> atom -> atom
|
|
|
|
(** Change exps in atom list by [f]. *)
|
|
(** WARNING: the result might not be normalized. *)
|
|
val atom_list_expmap : (exp -> exp) -> atom list -> atom list
|
|
|
|
(** {2 Function for computing lexps in sigma} *)
|
|
|
|
val hpred_list_get_lexps : (exp -> bool) -> hpred list -> exp list
|
|
|
|
(** {2 Utility Functions for Expressions} *)
|
|
|
|
(** 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 *)
|
|
val texp_to_typ : typ option -> exp -> typ
|
|
|
|
(** If a struct type with field f, return the type of f.
|
|
If not, return the default type if given, otherwise raise an exception *)
|
|
val struct_typ_fld : typ option -> Ident.fieldname -> typ -> typ
|
|
|
|
(** If an array type, return the type of the element.
|
|
If not, return the default type if given, otherwise raise an exception *)
|
|
val array_typ_elem : typ option -> typ -> typ
|
|
|
|
(** Return the root of [lexp]. *)
|
|
val root_of_lexp : exp -> exp
|
|
|
|
(** Get an expression "undefined", the boolean indicates whether the undefined value goest into the footprint *)
|
|
val exp_get_undefined : bool -> exp
|
|
|
|
(** Checks whether an expression denotes a location using pointer arithmetic.
|
|
Currently, catches array - indexing expressions such as a[i] only. *)
|
|
val exp_pointer_arith : exp -> bool
|
|
|
|
(** Integer constant 0 *)
|
|
val exp_zero : exp
|
|
|
|
(** Null constant *)
|
|
val exp_null : exp
|
|
|
|
(** Integer constant 1 *)
|
|
val exp_one : exp
|
|
|
|
(** Integer constant -1 *)
|
|
val exp_minus_one : exp
|
|
|
|
(** Create integer constant *)
|
|
val exp_int : Int.t -> exp
|
|
|
|
(** Create float constant *)
|
|
val exp_float : float -> exp
|
|
|
|
(** Create integer constant corresponding to the boolean value *)
|
|
val exp_bool : bool -> exp
|
|
|
|
(** Create expresstion [e1 == e2] *)
|
|
val exp_eq : exp -> exp -> exp
|
|
|
|
(** Create expresstion [e1 != e2] *)
|
|
val exp_ne : exp -> exp -> exp
|
|
|
|
(** Create expresstion [e1 <= e2] *)
|
|
val exp_le : exp -> exp -> exp
|
|
|
|
(** Create expression [e1 < e2] *)
|
|
val exp_lt : exp -> exp -> exp
|
|
|
|
(** {2 Functions for computing program variables} *)
|
|
|
|
val exp_fpv : exp -> pvar list
|
|
|
|
val strexp_fpv : strexp -> pvar list
|
|
|
|
val atom_fpv : atom -> pvar list
|
|
|
|
val hpred_fpv : hpred -> pvar list
|
|
|
|
val hpara_fpv : hpara -> pvar list
|
|
|
|
(** {2 Functions for computing free non-program variables} *)
|
|
|
|
(** Type of free variables. These include primed, normal and footprint variables. We remember the order in which variables are added. *)
|
|
type fav
|
|
|
|
(** flag to indicate whether fav's are stored in duplicate form -- only to be used with fav_to_list *)
|
|
val fav_duplicates : bool ref
|
|
|
|
(** Pretty print a fav. *)
|
|
val pp_fav : printenv -> Format.formatter -> fav -> unit
|
|
|
|
(** Create a new [fav]. *)
|
|
val fav_new : unit -> fav
|
|
|
|
(** Emptyness check. *)
|
|
val fav_is_empty : fav -> bool
|
|
|
|
(** Check whether a predicate holds for all elements. *)
|
|
val fav_for_all : fav -> (Ident.t -> bool) -> bool
|
|
|
|
(** Check whether a predicate holds for some elements. *)
|
|
val fav_exists : fav -> (Ident.t -> bool) -> bool
|
|
|
|
(** Membership test fot [fav] *)
|
|
val fav_mem : fav -> Ident.t -> bool
|
|
|
|
(** Convert a list to a fav. *)
|
|
val fav_from_list : Ident.t list -> fav
|
|
|
|
(** Convert a [fav] to a list of identifiers while preserving the order
|
|
that identifiers were added to [fav]. *)
|
|
val fav_to_list : fav -> Ident.t list
|
|
|
|
(** Copy a [fav]. *)
|
|
val fav_copy : fav -> fav
|
|
|
|
(** Turn a xxx_fav_add function into a xxx_fav function *)
|
|
val fav_imperative_to_functional : (fav -> 'a -> unit) -> 'a -> fav
|
|
|
|
(** [fav_filter_ident fav f] only keeps [id] if [f id] is true. *)
|
|
val fav_filter_ident : fav -> (Ident.t -> bool) -> unit
|
|
|
|
(** Like [fav_filter_ident] but return a copy. *)
|
|
val fav_copy_filter_ident : fav -> (Ident.t -> bool) -> fav
|
|
|
|
(** [fav_subset_ident fav1 fav2] returns true if every ident in [fav1]
|
|
is in [fav2].*)
|
|
val fav_subset_ident : fav -> fav -> bool
|
|
|
|
(** add identifier list to fav *)
|
|
val ident_list_fav_add : Ident.t list -> fav -> unit
|
|
|
|
(** [exp_fav_add fav exp] extends [fav] with the free variables of [exp] *)
|
|
val exp_fav_add : fav -> exp -> unit
|
|
|
|
val exp_fav : exp -> fav
|
|
|
|
val exp_fav_list : exp -> Ident.t list
|
|
|
|
val ident_in_exp : Ident.t -> exp -> bool
|
|
|
|
val strexp_fav_add : fav -> strexp -> unit
|
|
|
|
val atom_fav_add : fav -> atom -> unit
|
|
|
|
val atom_fav: atom -> fav
|
|
|
|
val hpred_fav_add : fav -> hpred -> unit
|
|
|
|
val hpred_fav : hpred -> fav
|
|
|
|
(** Variables in hpara, excluding bound vars in the body *)
|
|
val hpara_shallow_av : hpara -> fav
|
|
|
|
(** Variables in hpara_dll, excluding bound vars in the body *)
|
|
val hpara_dll_shallow_av : hpara_dll -> fav
|
|
|
|
(** {2 Functions for computing all free or bound non-program variables} *)
|
|
|
|
(** Non-program variables include all of primed, normal and footprint
|
|
variables. Thus, the functions essentially compute all the
|
|
identifiers occuring in a parameter. Some variables can appear more
|
|
than once in the result. *)
|
|
|
|
val exp_av_add : fav -> exp -> unit
|
|
|
|
val strexp_av_add : fav -> strexp -> unit
|
|
|
|
val atom_av_add : fav -> atom -> unit
|
|
|
|
val hpred_av_add : fav -> hpred -> unit
|
|
|
|
val hpara_av_add : fav -> hpara -> unit
|
|
|
|
(** {2 Substitution} *)
|
|
|
|
type subst
|
|
|
|
(** Create a substitution from a list of pairs.
|
|
For all (id1, e1), (id2, e2) in the input list,
|
|
if id1 = id2, then e1 = e2. *)
|
|
val sub_of_list : (Ident.t * exp) list -> subst
|
|
|
|
(** like sub_of_list, but allow duplicate ids and only keep the first occurrence *)
|
|
val sub_of_list_duplicates : (Ident.t * exp) list -> subst
|
|
|
|
(** Convert a subst to a list of pairs. *)
|
|
val sub_to_list : subst -> (Ident.t * exp) list
|
|
|
|
(** The empty substitution. *)
|
|
val sub_empty : subst
|
|
|
|
(** Comparison for substitutions. *)
|
|
val sub_compare : subst -> subst -> int
|
|
|
|
(** Equality for substitutions. *)
|
|
val sub_equal : subst -> subst -> bool
|
|
|
|
(** Compute the common id-exp part of two inputs [subst1] and [subst2].
|
|
The first component of the output is this common part.
|
|
The second and third components are the remainder of [subst1]
|
|
and [subst2], respectively. *)
|
|
val sub_join : subst -> subst -> subst
|
|
|
|
(** Compute the common id-exp part of two inputs [subst1] and [subst2].
|
|
The first component of the output is this common part.
|
|
The second and third components are the remainder of [subst1]
|
|
and [subst2], respectively. *)
|
|
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. *)
|
|
val sub_find : (Ident.t -> bool) -> subst -> exp
|
|
|
|
(** [sub_filter filter sub] restricts the domain of [sub] to the
|
|
identifiers satisfying [filter]. *)
|
|
val sub_filter : (Ident.t -> bool) -> subst -> subst
|
|
|
|
(** [sub_filter_exp filter sub] restricts the domain of [sub] to the
|
|
identifiers satisfying [filter(id, sub(id))]. *)
|
|
val sub_filter_pair : (Ident.t * exp -> bool) -> subst -> subst
|
|
|
|
(** [sub_range_partition filter sub] partitions [sub] according to
|
|
whether range expressions satisfy [filter]. *)
|
|
val sub_range_partition : (exp -> bool) -> subst -> subst * subst
|
|
|
|
(** [sub_domain_partition filter sub] partitions [sub] according to
|
|
whether domain identifiers satisfy [filter]. *)
|
|
val sub_domain_partition : (Ident.t -> bool) -> subst -> subst * subst
|
|
|
|
(** Return the list of identifiers in the domain of the substitution. *)
|
|
val sub_domain : subst -> Ident.t list
|
|
|
|
(** Return the list of expressions in the range of the substitution. *)
|
|
val sub_range : subst -> exp list
|
|
|
|
(** [sub_range_map f sub] applies [f] to the expressions in the range of [sub]. *)
|
|
val sub_range_map : (exp -> exp) -> subst -> subst
|
|
|
|
(** [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]. *)
|
|
val sub_map : (Ident.t -> Ident.t) -> (exp -> exp) -> subst -> subst
|
|
|
|
(** Checks whether [id] belongs to the domain of [subst]. *)
|
|
val mem_sub : Ident.t -> subst -> bool
|
|
|
|
(** Extend substitution and return [None] if not possible. *)
|
|
val extend_sub : subst -> Ident.t -> exp -> subst option
|
|
|
|
(** Free auxilary variables in the domain and range of the
|
|
substitution. *)
|
|
val sub_fav_add : fav -> subst -> unit
|
|
|
|
(** Free or bound auxilary variables in the domain and range of the
|
|
substitution. *)
|
|
val sub_av_add : fav -> subst -> unit
|
|
|
|
(** Compute free pvars in a sub *)
|
|
val sub_fpv : subst -> pvar list
|
|
|
|
(** substitution functions *)
|
|
(** WARNING: these functions do not ensure that the results are normalized. *)
|
|
val exp_sub : subst -> exp -> exp
|
|
|
|
val atom_sub : subst -> atom -> atom
|
|
|
|
val instr_sub : subst -> instr -> instr
|
|
|
|
val hpred_sub : subst -> hpred -> hpred
|
|
|
|
(** {2 Functions for replacing occurrences of expressions.} *)
|
|
|
|
(** The first parameter should define a partial function.
|
|
No parts of hpara are replaced by these functions. *)
|
|
|
|
val exp_replace_exp : (exp * exp) list -> exp -> exp
|
|
|
|
val strexp_replace_exp : (exp * exp) list -> strexp -> strexp
|
|
|
|
val atom_replace_exp : (exp * exp) list -> atom -> atom
|
|
|
|
val hpred_replace_exp : (exp * exp) list -> hpred -> hpred
|
|
|
|
(** {2 Functions for constructing or destructing entities in this module} *)
|
|
|
|
|
|
(** [mk_pvar name proc_name suffix] creates a program var with the given function name and suffix *)
|
|
val mk_pvar : Mangled.t -> Procname.t -> pvar
|
|
|
|
(** [get_ret_pvar proc_name] retuns the return pvar associated with the procedure name *)
|
|
val get_ret_pvar : Procname.t -> pvar
|
|
|
|
(** [mk_pvar_callee name proc_name] creates a program var for a callee function with the given function name *)
|
|
val mk_pvar_callee : Mangled.t -> Procname.t -> pvar
|
|
|
|
(** create a global variable with the given name *)
|
|
val mk_pvar_global : Mangled.t -> pvar
|
|
|
|
(** create an abducted return variable for a call to [proc_name] at [loc] *)
|
|
val mk_pvar_abducted_ret : Procname.t -> Location.t -> pvar
|
|
|
|
val mk_pvar_abducted_ref_param : Procname.t -> pvar -> Location.t -> pvar
|
|
|
|
(** Turn an ordinary program variable into a callee program variable *)
|
|
val pvar_to_callee : Procname.t -> pvar -> pvar
|
|
|
|
(** Compute the offset list of an expression *)
|
|
val exp_get_offsets : exp -> offset list
|
|
|
|
(** Add the offset list to an expression *)
|
|
val exp_add_offsets : exp -> offset list -> exp
|
|
|
|
val sigma_to_sigma_ne : hpred list -> (atom list * hpred list) list
|
|
|
|
(** [hpara_instantiate para e1 e2 elist] instantiates [para] with [e1],
|
|
[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\]]
|
|
for some fresh [_zs'].*)
|
|
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],
|
|
[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\]]
|
|
for some fresh [_zs'].*)
|
|
val hpara_dll_instantiate : hpara_dll -> exp -> exp -> exp -> exp list -> Ident.t list * hpred list
|
|
|
|
(** Iterate over all the subtypes in the type (including the type itself) *)
|
|
val typ_iter_types : (typ -> unit) -> typ -> unit
|
|
(** Iterate over all the types (and subtypes) in the expression *)
|
|
val exp_iter_types : (typ -> unit) -> exp -> unit
|
|
(** Iterate over all the types (and subtypes) in the instruction *)
|
|
val instr_iter_types : (typ -> unit) -> instr -> unit
|
|
|
|
val custom_error : pvar
|
|
|
|
(*
|
|
(** Equality for consts. *)
|
|
val const_equal : const -> const -> bool
|
|
*)
|