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
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))
|