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.

68 lines
2.5 KiB

(*
* Copyright (c) 2018-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*)
open! IStd
module F = Format
(** The node in which the reaching definition x := e is defined.
A definition x :=e, declared at node N, reaches the current node
if there is a path from node N to the current node such that x is
not modified along the path **)
module Defs = AbstractDomain.FiniteSet (Procdesc.Node)
(* even though we only add singletons (defs), the set is needed for joins *)
(** Map var -> its reaching definition **)
module ReachingDefsMap = AbstractDomain.Map (Var) (Defs)
(* forward transfer function for reaching definitions *)
module TransferFunctionsReachingDefs (CFG : ProcCfg.S) = struct
module CFG = CFG
module Domain = ReachingDefsMap
type extras = ProcData.no_extras
(* for each x := e at node n, remove x's definitions and introduce x -> n *)
let exec_instr astate _ (node : CFG.Node.t) instr =
let node = CFG.Node.underlying_node node in
let strong_update_def astate var = Domain.add var (Defs.singleton node) astate in
let weak_update_def astate var =
Domain.update var
(function Some defs -> Some (Defs.add node defs) | None -> Some (Defs.singleton node))
astate
in
match instr with
| Sil.Load (lhs_id, _, _, _) when Ident.is_none lhs_id ->
(* dummy deref inserted by frontend--don't count as a read *)
astate
| Sil.Load (id, _, _, _) | Sil.Call ((id, _), _, _, _, _) ->
strong_update_def astate (Var.of_id id)
(* only strong update for assigning to a pvar *)
| Sil.Store (Lvar pvar, _, _, _) ->
strong_update_def astate (Var.of_pvar pvar)
(* by default use weak update *)
| Sil.Store (exp_lhs, _, _, _) ->
let vars = Var.get_all_vars_in_exp exp_lhs in
Sequence.fold ~init:astate ~f:weak_update_def vars
| _ ->
astate
let pp_session_name node fmt =
F.fprintf fmt "reaching defs analysis %a" CFG.Node.pp_id (CFG.Node.id node)
end
(* initialize formal parameters to have start node as reaching def *)
let init_reaching_defs_with_formals pdesc =
let start_node_defs = Defs.singleton (Procdesc.get_start_node pdesc) in
Procdesc.get_pvar_formals pdesc
|> List.fold_left ~init:ReachingDefsMap.empty ~f:(fun acc (pvar, _) ->
ReachingDefsMap.add (Var.of_pvar pvar) start_node_defs acc )
module Analyzer = AbstractInterpreter.MakeRPO (TransferFunctionsReachingDefs (ProcCfg.Normal))