package goblint
Static analysis framework for C
Install
dune-project
Dependency
Authors
Maintainers
Sources
goblint-2.6.0.tbz
sha256=20d5b7332a9f6072ab9ba86c4a53b898eaf681286c56a8805c41850bbf3ddf41
sha512=7c7685cfcd9aa866bc40e813df2bfcb3c79b3d40e615d8d6d0939c5798b9d70dd7f2ba87a741f5ba0ce891e9d254627207fb28057f1f2f6611e4e0d128fd6a71
doc/src/goblint.solver/sideWPointSelect.ml.html
Source file sideWPointSelect.ml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222
(** Strategies for widening leaf unknowns *) open Batteries open Goblint_constraint.ConstrSys open Messages module type S = functor (S:EqConstrSys) -> functor (HM:Hashtbl.S with type key = S.v) -> functor (VS:Set.S with type elt = S.v) -> sig type data (** Create data required by this widening point selection strategy. The parameters are not necessarily used by all strategies. @param is_stable This callback should return whether an unknown is stable. @param add_infl Allows the strategy to record additional influences. This is mainly intended for strategies like unstable-self, which records the influence of a side-effecting unknown x to the leaf y. *) val create_data: (S.v -> bool) -> (S.v -> S.v -> unit) -> data (** Notifies this strategy that a side-effect has occurred. This allows the strategy to adapt its internal data structure. @param data The internal state of this strategy @param x The optional source of the side-effect @param y The leaf receiving the side-effect *) val notify_side: data -> S.v option -> S.v -> unit (** Whether the destabilization of the side-effected var should record the destabilization of called variables and start variables. This information should be passed to [should_mark_wpoint] by the solver. *) val record_destabilized_vs: bool (** This strategy can decide to prevent widening. Note that, if this strategy does not veto, this does not mean that widening will necessarily be performed. Nor does a call to this function imply that the value of the leaf has grown. @param data The internal state of this strategy @param called Set of called unknowns @param old_sides Prior side-effects to leaf y @param x Optional source of the side-effect @param y Side-effected leaf y @return [true]: widening will not be applied; [false]: widening might be applied *) val veto_widen: data -> unit HM.t -> VS.t -> S.v option -> S.v -> bool (** The value of the leaf has grown. Should it be marked a widening point? Widening points are widened when their value grows, unless vetoed. Even if this function is called, leaf y might already be a widening point from an earlier side-effect. @param data The internal state of this strategy @param called Set of called unknowns @param old_sides Prior side-effects to leaf y @param x Optional source of the side-effect @param y Side-effected leaf y @param destabilized_vs Optional destabilization info, described in [record_destabilized_vs] @return [true]: mark as widening point; [false]: do not mark as widening point *) val should_mark_wpoint: data -> unit HM.t -> VS.t -> S.v option -> S.v -> bool option -> bool end (** Any side-effect after the first one will be widened which will unnecessarily lose precision. *) module Always : S = functor (S:EqConstrSys) -> functor (HM:Hashtbl.S with type key = S.v) -> functor (VS:Set.S with type elt = S.v) -> struct type data = unit let create_data _ _ = () let notify_side _ _ _ = () let record_destabilized_vs = false let veto_widen _ _ _ _ _ = false let should_mark_wpoint _ _ _ _ _ _ = true end (* On side-effect cycles, this should terminate via the outer `solver` loop. TODO check. *) (** Never widen side-effects. *) module Never : S = functor (S:EqConstrSys) -> functor (HM:Hashtbl.S with type key = S.v) -> functor (VS:Set.S with type elt = S.v) -> struct type data = unit let create_data _ _ = () let notify_side _ _ _ = () let record_destabilized_vs = false let veto_widen _ _ _ _ _ = false let should_mark_wpoint _ _ _ _ _ _ = false end (** Widening check happens by checking sides. Only widen if value increases and there has already been a side-effect from the same source *) module SidesLocal : S = functor (S:EqConstrSys) -> functor (HM:Hashtbl.S with type key = S.v) -> functor (VS:Set.S with type elt = S.v) -> struct type data = unit let create_data _ _ = () let notify_side _ _ _ = () let record_destabilized_vs = false let veto_widen state called old_sides x y = match x with | None -> false | Some x when VS.mem x old_sides -> false | _ -> true let should_mark_wpoint _ _ _ _ _ _ = true end (** If there was already a `side x y d` from the same program point and now again, make y a widening point. Different from `Sides` in that it will not distinguish between side-effects from different contexts, only the program point matters. *) module SidesPP : S = functor (S:EqConstrSys) -> functor (HM:Hashtbl.S with type key = S.v) -> functor (VS:Set.S with type elt = S.v) -> struct type data = unit let create_data _ _ = () let notify_side _ _ _ = () let record_destabilized_vs = false let veto_widen state called old_sides x y = false let should_mark_wpoint state called old_sides x y _ = match x with | Some x -> let n = S.Var.node x in VS.exists (fun v -> Node.equal (S.Var.node v) n) old_sides | None -> false (* TODO: This is consistent with the previous implementation, but if multiple side-effects come in with x = None, the leaf will never be widened. This is different from SidesLocal *) end (** If there already was a `side x y d` that changed rho[y] and now again, we make y a wpoint. x caused more than one update to y. >=3 partial context calls will be precise since sides come from different x. TODO this has 8 instead of 5 phases of `solver` for side_cycle.c *) module Sides : S = functor (S:EqConstrSys) -> functor (HM:Hashtbl.S with type key = S.v) -> functor (VS:Set.S with type elt = S.v) -> struct type data = unit let create_data _ _ = () let notify_side _ _ _ = () let record_destabilized_vs = false let veto_widen state called old_sides x y = false let should_mark_wpoint state called old_sides x y _ = match x with | Some(x) -> VS.mem x old_sides | None -> true end (* TODO: The following two don't check if a vs got destabilized which may be a problem. *) (* TODO test/remove. Check for which examples this is problematic! *) (** Side to y destabilized itself via some infl-cycle. Records influences from unknowns to globals *) module UnstableSelf : S = functor (S:EqConstrSys) -> functor (HM:Hashtbl.S with type key = S.v) -> functor (VS:Set.S with type elt = S.v) -> struct type data = { is_stable: S.v -> bool; add_infl: S.v -> S.v -> unit } let create_data is_stable add_infl = { is_stable; add_infl } let notify_side data x y = (match x with None -> () | Some x -> data.add_infl x y) let record_destabilized_vs = false let veto_widen _ _ _ _ _ = false let should_mark_wpoint state called old_sides x y _ = not (state.is_stable y) end (* TODO test/remove. *) (** Widen if any called var (not just y) is no longer stable. Expensive! *) module UnstableCalled : S = functor (S:EqConstrSys) -> functor (HM:Hashtbl.S with type key = S.v) -> functor (VS:Set.S with type elt = S.v) -> struct type data = { is_stable: S.v -> bool } let create_data is_stable _ = { is_stable } let notify_side _ _ _ = () let record_destabilized_vs = false let veto_widen state called old_sides y x = false let should_mark_wpoint state called old_sides y x _ = HM.exists (fun k _ -> not (state.is_stable k)) called (* this is very expensive since it iterates over called! see https://github.com/goblint/analyzer/issues/265#issuecomment-880748636 *) end (** Destabilized a called or start var. Problem: two partial context calls will be precise, but third call will widen the state. If this side destabilized some of the initial unknowns vs, there may be a side-cycle between vs and we should make y a wpoint *) module Cycle : S = functor (S:EqConstrSys) -> functor (HM:Hashtbl.S with type key = S.v) -> functor (VS:Set.S with type elt = S.v) -> struct type data = unit let create_data _ _ = () let notify_side _ _ _ = () let record_destabilized_vs = true let veto_widen state called old_sides x y = false let should_mark_wpoint state called old_sides x y cycle = match cycle with | Some cycle -> if tracing && cycle then trace "side_widen" "cycle: should mark wpoint %a" S.Var.pretty_trace y; cycle | None -> failwith "destabilize_vs information not provided to side_widen cycle strategy"; end let choose_impl: unit -> (module S) = fun () -> let conf = GobConfig.get_string "solvers.td3.side_widen" in match conf with | "always" -> (module Always) | "never" -> (module Never) | "sides-local" -> (module SidesLocal) | "sides" -> (module Sides) | "sides-pp" -> (module SidesPP) | "unstable-self" -> (module UnstableSelf) | "unstable-called" -> (module UnstableCalled) | "cycle" -> (module Cycle) | _ -> failwith ("Unknown value '" ^ conf ^ "' for option solvers.td3.side_widen!")
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>