Reviewed By: dkgi Differential Revision: D3521054 fbshipit-source-id: 3ff515bmaster
parent
cf72de9460
commit
314d022e38
@ -0,0 +1,69 @@
|
||||
(*
|
||||
* Copyright (c) 2016 - 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.
|
||||
*)
|
||||
|
||||
module F = Format
|
||||
|
||||
module Set = struct
|
||||
module APSet = PrettyPrintable.MakePPSet (struct
|
||||
type t = AccessPath.t
|
||||
let compare = AccessPath.compare
|
||||
let pp_element = AccessPath.pp
|
||||
end)
|
||||
|
||||
(** TODO (12086310): best-case behavior of some operations can be improved by adding "abstracted"
|
||||
bool recording whether an abstracted access path has been introduced *)
|
||||
type astate = APSet.t
|
||||
|
||||
let initial = APSet.empty
|
||||
|
||||
let is_bottom _ = false
|
||||
|
||||
let pp = APSet.pp
|
||||
|
||||
let normalize aps =
|
||||
APSet.filter
|
||||
(fun lhs -> not (APSet.exists (fun rhs -> lhs != rhs && AccessPath.(<=) ~lhs ~rhs) aps))
|
||||
aps
|
||||
|
||||
let add = APSet.add
|
||||
|
||||
let of_list = APSet.of_list
|
||||
|
||||
let mem ap aps =
|
||||
APSet.mem ap aps || APSet.exists (fun other_ap -> AccessPath.(<=) ~lhs:ap ~rhs:other_ap) aps
|
||||
|
||||
let mem_fuzzy ap aps =
|
||||
let has_overlap ap1 ap2 =
|
||||
AccessPath.(<=) ~lhs:ap1 ~rhs:ap2 || AccessPath.(<=) ~lhs:ap2 ~rhs:ap1 in
|
||||
APSet.mem ap aps || APSet.exists (has_overlap ap) aps
|
||||
|
||||
let (<=) ~lhs ~rhs =
|
||||
if lhs == rhs
|
||||
then true
|
||||
else
|
||||
let rhs_contains lhs_ap =
|
||||
mem lhs_ap rhs in
|
||||
APSet.subset lhs rhs || APSet.for_all rhs_contains lhs
|
||||
|
||||
let join aps1 aps2 =
|
||||
if aps1 == aps2
|
||||
then aps1
|
||||
else APSet.union aps1 aps2
|
||||
|
||||
let widen ~prev ~next ~num_iters:_ =
|
||||
if prev == next
|
||||
then prev
|
||||
else
|
||||
let abstract_access_path ap aps = match ap with
|
||||
| AccessPath.Exact exact_ap -> APSet.add (AccessPath.Abstracted exact_ap) aps
|
||||
| AccessPath.Abstracted _ -> APSet.add ap aps in
|
||||
let diff_aps = APSet.diff next prev in
|
||||
APSet.fold abstract_access_path diff_aps initial
|
||||
|> join prev
|
||||
end
|
@ -0,0 +1,36 @@
|
||||
(*
|
||||
* Copyright (c) 2016 - 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.
|
||||
*)
|
||||
|
||||
(** Generic abstract domains backed by access paths *)
|
||||
|
||||
(** add-only set of access paths. To make common operations efficient (namely, add, join, and
|
||||
widen), the set is allowed to contain elements whose concretization is redundant (e.g., x* and
|
||||
x.f). these redundancies can be eliminated by expressing the set in its canonical form via a
|
||||
call to [normalize]. however, [normalize] is quadratic in the size of the set, so it should be
|
||||
used sparingly (recommendation: only before computing a summary based on the access path set) *)
|
||||
module Set : sig
|
||||
include AbstractDomain.S
|
||||
|
||||
val of_list : AccessPath.t list -> astate
|
||||
|
||||
(** return true if \gamma({ap}) \subseteq \gamma(aps).
|
||||
note: this is worst-case linear in the size of the set *)
|
||||
val mem : AccessPath.t -> astate -> bool
|
||||
|
||||
(** more permissive version of [mem]; return true if \gamma({a}) \cap \gamma(aps) != {}.
|
||||
note: this is worst-case linear in the size of the set *)
|
||||
val mem_fuzzy : AccessPath.t -> astate -> bool
|
||||
|
||||
val add : AccessPath.t -> astate -> astate
|
||||
|
||||
(** simplify an access path set to its canonical representation by eliminating redundancies
|
||||
between (1) pairs of abstracted access_paths, and (2) exact access paths and abstracted
|
||||
access paths. warning: this is quadratic in the size of the set! use sparingly *)
|
||||
val normalize : astate -> astate
|
||||
end
|
Loading…
Reference in new issue