Skip to content

Commit 570c749

Browse files
Merge pull request #1746 from arkocal/demand_constr_2
Introduce demand in constraint system
2 parents de9e04e + 600c417 commit 570c749

21 files changed

+198
-94
lines changed

src/constraint/constrSys.ml

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,13 @@ sig
8686
val postmortem: v -> v list
8787
end
8888

89+
(** A side-effecting system that supports [demand] calls *)
90+
module type DemandEqConstrSys =
91+
sig
92+
include EqConstrSys
93+
val system: v -> ((v -> d) -> (v -> d -> unit) -> (v -> unit) -> d) option
94+
end
95+
8996
(** A side-effecting system with globals. *)
9097
module type GlobConstrSys =
9198
sig
@@ -100,6 +107,21 @@ sig
100107
val postmortem: LVar.t -> LVar.t list
101108
end
102109

110+
(** A side-effecting system with globals that supports [demand] calls *)
111+
module type DemandGlobConstrSys =
112+
sig
113+
module LVar : VarType
114+
module GVar : VarType
115+
116+
module D : Lattice.S
117+
module G : Lattice.S
118+
val system: LVar.t -> ((LVar.t -> D.t) -> (LVar.t -> D.t -> unit) -> (LVar.t -> unit) -> (GVar.t -> G.t) -> (GVar.t -> G.t -> unit) -> D.t) option
119+
val iter_vars: (LVar.t -> D.t) -> (GVar.t -> G.t) -> VarQuery.t -> LVar.t VarQuery.f -> GVar.t VarQuery.f -> unit
120+
val sys_change: (LVar.t -> D.t) -> (GVar.t -> G.t) -> [`L of LVar.t | `G of GVar.t] sys_change_info
121+
val postmortem: LVar.t -> LVar.t list
122+
end
123+
124+
103125
(** [EqConstrSys] where [current_var] indicates the variable whose right-hand side is currently being evaluated. *)
104126
module CurrentVarEqConstrSys (S: EqConstrSys) =
105127
struct

src/constraint/solverTypes.ml

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,17 @@ module type GenericEqSolver =
1313
val solve : (S.v*S.d) list -> S.v list -> S.d H.t
1414
end
1515

16+
(** A solver is something that can translate a system into a solution (hash-table).
17+
These solver can handle [DemandEqConstrSys] *)
18+
module type DemandEqSolver =
19+
functor (S:DemandEqConstrSys) ->
20+
functor (H:Hashtbl.S with type key=S.v) ->
21+
sig
22+
(** The hash-map that is the first component of [solve xs vs] is a local solution for interesting variables [vs],
23+
reached from starting values [xs]. *)
24+
val solve : (S.v*S.d) list -> S.v list -> S.d H.t
25+
end
26+
1627
(** A solver is something that can translate a system into a solution (hash-table).
1728
Incremental solver has data to be marshaled. *)
1829
module type GenericEqIncrSolverBase =
@@ -44,11 +55,30 @@ module type GenericEqIncrSolver =
4455
functor (Arg: IncrSolverArg) ->
4556
GenericEqIncrSolverBase
4657

58+
module type DemandEqIncrSolverBase =
59+
functor (S: DemandEqConstrSys) ->
60+
functor (H:Hashtbl.S with type key=S.v) ->
61+
sig
62+
type marshal
63+
64+
val copy_marshal: marshal -> marshal
65+
val relift_marshal: marshal -> marshal
66+
67+
(** The hash-map that is the first component of [solve xs vs] is a local solution for interesting variables [vs],
68+
reached from starting values [xs].
69+
As a second component the solver returns data structures for incremental serialization. *)
70+
val solve : (S.v*S.d) list -> S.v list -> marshal option -> S.d H.t * marshal
71+
end
72+
73+
module type DemandEqIncrSolver =
74+
functor (Arg: IncrSolverArg) ->
75+
DemandEqIncrSolverBase
76+
4777
(** A solver is something that can translate a system into a solution (hash-table)
4878
4979
*)
50-
module type GenericGlobIncrSolver =
51-
functor (S:GlobConstrSys) ->
80+
module type DemandGlobIncrSolver =
81+
functor (S:DemandGlobConstrSys) ->
5282
functor (LH:Hashtbl.S with type key=S.LVar.t) ->
5383
functor (GH:Hashtbl.S with type key=S.GVar.t) ->
5484
sig

src/constraint/translators.ml

Lines changed: 43 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,35 @@ open Batteries
33
open ConstrSys
44
open SolverTypes
55

6+
(** Translate a [DemandConstrSys] into a [EqConstrSys] *)
7+
module EqConstrSysFromDemandConstrSys (S: DemandEqConstrSys)
8+
: EqConstrSys with type v = S.v
9+
and type d = S.d
10+
and module Var = S.Var
11+
and module Dom = S.Dom =
12+
struct
13+
type v = S.v
14+
type d = S.d
15+
module Var = S.Var
16+
module Dom = S.Dom
17+
18+
let system (x: v) =
19+
match S.system x with
20+
| None -> None
21+
| Some f ->
22+
let f' get set = f get set (ignore % get) in
23+
Some f'
24+
25+
let sys_change = S.sys_change
26+
let postmortem = S.postmortem
27+
end
628

7-
(** Translate a [GlobConstrSys] into a [EqConstrSys] *)
8-
module EqConstrSysFromGlobConstrSys (S:GlobConstrSys)
9-
: EqConstrSys with type v = Var2(S.LVar)(S.GVar).t
10-
and type d = Lattice.Lift2(S.G)(S.D).t
11-
and module Var = Var2(S.LVar)(S.GVar)
12-
and module Dom = Lattice.Lift2(S.G)(S.D)
29+
(** Translate a [DemandGlobConstrSys] into a [DemandEqConstrSys] *)
30+
module EqConstrSysFromGlobConstrSys (S:DemandGlobConstrSys)
31+
: DemandEqConstrSys with type v = Var2(S.LVar)(S.GVar).t
32+
and type d = Lattice.Lift2(S.G)(S.D).t
33+
and module Var = Var2(S.LVar)(S.GVar)
34+
and module Dom = Lattice.Lift2(S.G)(S.D)
1335
=
1436
struct
1537
module Var = Var2(S.LVar)(S.GVar)
@@ -39,8 +61,8 @@ struct
3961
let l, g = (fun x -> `L x), (fun x -> `G x)
4062
let lD, gD = (fun x -> `Lifted2 x), (fun x -> `Lifted1 x)
4163

42-
let conv f get set =
43-
f (getL % get % l) (fun x v -> set (l x) (lD v))
64+
let conv f get set demand =
65+
f (getL % get % l) (fun x v -> set (l x) (lD v)) (fun x -> ignore @@ getL @@ get @@ l x)
4466
(getG % get % g) (fun x v -> set (g x) (gD v))
4567
|> lD
4668

@@ -57,7 +79,7 @@ struct
5779
end
5880

5981
(** Splits a [EqConstrSys] solution into a [GlobConstrSys] solution with given [Hashtbl.S] for the [EqConstrSys]. *)
60-
module GlobConstrSolFromEqConstrSolBase (S: GlobConstrSys) (LH: Hashtbl.S with type key = S.LVar.t) (GH: Hashtbl.S with type key = S.GVar.t) (VH: Hashtbl.S with type key = Var2 (S.LVar) (S.GVar).t) =
82+
module GlobConstrSolFromEqConstrSolBase (S: DemandGlobConstrSys) (LH: Hashtbl.S with type key = S.LVar.t) (GH: Hashtbl.S with type key = S.GVar.t) (VH: Hashtbl.S with type key = Var2 (S.LVar) (S.GVar).t) =
6183
struct
6284
let split_solution hm =
6385
let l' = LH.create 113 in
@@ -86,17 +108,25 @@ struct
86108
end
87109

88110
(** Splits a [EqConstrSys] solution into a [GlobConstrSys] solution. *)
89-
module GlobConstrSolFromEqConstrSol (S: GlobConstrSys) (LH: Hashtbl.S with type key = S.LVar.t) (GH: Hashtbl.S with type key = S.GVar.t) =
111+
module GlobConstrSolFromEqConstrSol (S: DemandGlobConstrSys) (LH: Hashtbl.S with type key = S.LVar.t) (GH: Hashtbl.S with type key = S.GVar.t) =
90112
struct
91113
module S2 = EqConstrSysFromGlobConstrSys (S)
92114
module VH = Hashtbl.Make (S2.Var)
93115

94116
include GlobConstrSolFromEqConstrSolBase (S) (LH) (GH) (VH)
95117
end
96118

97-
(** Transforms a [GenericEqIncrSolver] into a [GenericGlobIncrSolver]. *)
98-
module GlobSolverFromEqSolver (Sol:GenericEqIncrSolverBase)
99-
= functor (S:GlobConstrSys) ->
119+
120+
module DemandEqIncrSolverFromGenericEqIncrSolver (Sol: GenericEqIncrSolver): DemandEqIncrSolver =
121+
functor (Arg: IncrSolverArg) ->
122+
functor (S: DemandEqConstrSys) ->
123+
functor (H: Hashtbl.S with type key = S.v) ->
124+
Sol (Arg) (EqConstrSysFromDemandConstrSys (S)) (H)
125+
126+
127+
(** Transforms a [DemandEqIncrSolver] into a [DemandGlobIncrSolver]. *)
128+
module GlobSolverFromEqSolver (Sol:DemandEqIncrSolverBase)
129+
= functor (S:DemandGlobConstrSys) ->
100130
functor (LH:Hashtbl.S with type key=S.LVar.t) ->
101131
functor (GH:Hashtbl.S with type key=S.GVar.t) ->
102132
struct

src/framework/analyses.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -424,7 +424,7 @@ end
424424
module type SpecSys =
425425
sig
426426
module Spec: Spec
427-
module EQSys: Goblint_constraint.ConstrSys.GlobConstrSys with module LVar = VarF (Spec.C)
427+
module EQSys: Goblint_constraint.ConstrSys.DemandGlobConstrSys with module LVar = VarF (Spec.C)
428428
and module GVar = GVarF (Spec.V)
429429
and module D = Spec.D
430430
and module G = GVarG (Spec.G) (Spec.C)

src/framework/constraints.ml

Lines changed: 35 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,13 @@ sig
1515
end
1616

1717

18-
(** The main point of this file---generating a [GlobConstrSys] from a [Spec]. *)
18+
(** The main point of this file---generating a [DemandGlobConstrSys] from a [Spec]. *)
1919
module FromSpec (S:Spec) (Cfg:CfgBackward) (I: Increment)
2020
: sig
21-
include GlobConstrSys with module LVar = VarF (S.C)
22-
and module GVar = GVarF (S.V)
23-
and module D = S.D
24-
and module G = GVarG (S.G) (S.C)
21+
include DemandGlobConstrSys with module LVar = VarF (S.C)
22+
and module GVar = GVarF (S.V)
23+
and module D = S.D
24+
and module G = GVarG (S.G) (S.C)
2525
end
2626
=
2727
struct
@@ -50,7 +50,7 @@ struct
5050
if !AnalysisState.postsolving then
5151
sideg (GVar.contexts f) (G.create_contexts (G.CSet.singleton c))
5252

53-
let common_man var edge prev_node pval (getl:lv -> ld) sidel getg sideg : (D.t, S.G.t, S.C.t, S.V.t) man * D.t list ref * (lval option * varinfo * exp list * D.t * bool) list ref =
53+
let common_man var edge prev_node pval (getl:lv -> ld) sidel demandl getg sideg : (D.t, S.G.t, S.C.t, S.V.t) man * D.t list ref * (lval option * varinfo * exp list * D.t * bool) list ref =
5454
let r = ref [] in
5555
let spawns = ref [] in
5656
(* now watch this ... *)
@@ -78,7 +78,7 @@ struct
7878
| fd ->
7979
let c = S.context man fd d in
8080
sidel (FunctionEntry fd, c) d;
81-
ignore (getl (Function fd, c))
81+
demandl (Function fd, c)
8282
| exception Not_found ->
8383
(* unknown function *)
8484
M.error ~category:Imprecise ~tags:[Category Unsound] "Created a thread from unknown function %s" f.vname;
@@ -131,13 +131,13 @@ struct
131131

132132
let common_joins man ds splits spawns = common_join man (bigsqcup ds) splits spawns
133133

134-
let tf_assign var edge prev_node lv e getl sidel getg sideg d =
135-
let man, r, spawns = common_man var edge prev_node d getl sidel getg sideg in
134+
let tf_assign var edge prev_node lv e getl sidel demandl getg sideg d =
135+
let man, r, spawns = common_man var edge prev_node d getl sidel demandl getg sideg in
136136
let d = S.assign man lv e in (* Force transfer function to be evaluated before dereferencing in common_join argument. *)
137137
common_join man d !r !spawns
138138

139-
let tf_vdecl var edge prev_node v getl sidel getg sideg d =
140-
let man, r, spawns = common_man var edge prev_node d getl sidel getg sideg in
139+
let tf_vdecl var edge prev_node v getl sidel demandl getg sideg d =
140+
let man, r, spawns = common_man var edge prev_node d getl sidel demandl getg sideg in
141141
let d = S.vdecl man v in (* Force transfer function to be evaluated before dereferencing in common_join argument. *)
142142
common_join man d !r !spawns
143143

@@ -152,8 +152,8 @@ struct
152152
let nval = S.sync { man with local = spawning_return } `Return in
153153
nval
154154

155-
let tf_ret var edge prev_node ret fd getl sidel getg sideg d =
156-
let man, r, spawns = common_man var edge prev_node d getl sidel getg sideg in
155+
let tf_ret var edge prev_node ret fd getl sidel demandl getg sideg d =
156+
let man, r, spawns = common_man var edge prev_node d getl sidel demandl getg sideg in
157157
let d = (* Force transfer function to be evaluated before dereferencing in common_join argument. *)
158158
if (CilType.Fundec.equal fd MyCFG.dummy_func ||
159159
List.mem fd.svar.vname (get_string_list "mainfun")) &&
@@ -163,21 +163,21 @@ struct
163163
in
164164
common_join man d !r !spawns
165165

166-
let tf_entry var edge prev_node fd getl sidel getg sideg d =
166+
let tf_entry var edge prev_node fd getl sidel demandl getg sideg d =
167167
(* Side effect function context here instead of at sidel to FunctionEntry,
168168
because otherwise context for main functions (entrystates) will be missing or pruned during postsolving. *)
169169
let c: unit -> S.C.t = snd var |> Obj.obj in
170170
side_context sideg fd (c ());
171-
let man, r, spawns = common_man var edge prev_node d getl sidel getg sideg in
171+
let man, r, spawns = common_man var edge prev_node d getl sidel demandl getg sideg in
172172
let d = S.body man fd in (* Force transfer function to be evaluated before dereferencing in common_join argument. *)
173173
common_join man d !r !spawns
174174

175-
let tf_test var edge prev_node e tv getl sidel getg sideg d =
176-
let man, r, spawns = common_man var edge prev_node d getl sidel getg sideg in
175+
let tf_test var edge prev_node e tv getl sidel demandl getg sideg d =
176+
let man, r, spawns = common_man var edge prev_node d getl sidel demandl getg sideg in
177177
let d = S.branch man e tv in (* Force transfer function to be evaluated before dereferencing in common_join argument. *)
178178
common_join man d !r !spawns
179179

180-
let tf_normal_call man lv e (f:fundec) args getl sidel getg sideg =
180+
let tf_normal_call man lv e (f:fundec) args getl sidel demandl getg sideg =
181181
let combine (cd, fc, fd) =
182182
if M.tracing then M.traceli "combine" "local: %a" S.D.pretty cd;
183183
if M.tracing then M.trace "combine" "function: %a" S.D.pretty fd;
@@ -245,8 +245,8 @@ struct
245245

246246
let tf_special_call man lv f args = S.special man lv f args
247247

248-
let tf_proc var edge prev_node lv e args getl sidel getg sideg d =
249-
let man, r, spawns = common_man var edge prev_node d getl sidel getg sideg in
248+
let tf_proc var edge prev_node lv e args getl sidel demandl getg sideg d =
249+
let man, r, spawns = common_man var edge prev_node d getl sidel demandl getg sideg in
250250
let functions =
251251
match e with
252252
| Lval (Var v, NoOffset) ->
@@ -271,7 +271,7 @@ struct
271271
M.info ~category:Analyzer "Using special for defined function %s" f.vname;
272272
tf_special_call man lv f args
273273
| fd ->
274-
tf_normal_call man lv e fd args getl sidel getg sideg
274+
tf_normal_call man lv e fd args getl sidel demandl getg sideg
275275
| exception Not_found ->
276276
tf_special_call man lv f args)
277277
end
@@ -292,17 +292,17 @@ struct
292292
end else
293293
common_joins man funs !r !spawns
294294

295-
let tf_asm var edge prev_node getl sidel getg sideg d =
296-
let man, r, spawns = common_man var edge prev_node d getl sidel getg sideg in
295+
let tf_asm var edge prev_node getl sidel demandl getg sideg d =
296+
let man, r, spawns = common_man var edge prev_node d getl sidel demandl getg sideg in
297297
let d = S.asm man in (* Force transfer function to be evaluated before dereferencing in common_join argument. *)
298298
common_join man d !r !spawns
299299

300-
let tf_skip var edge prev_node getl sidel getg sideg d =
301-
let man, r, spawns = common_man var edge prev_node d getl sidel getg sideg in
300+
let tf_skip var edge prev_node getl sidel demandl getg sideg d =
301+
let man, r, spawns = common_man var edge prev_node d getl sidel demandl getg sideg in
302302
let d = S.skip man in (* Force transfer function to be evaluated before dereferencing in common_join argument. *)
303303
common_join man d !r !spawns
304304

305-
let tf var getl sidel getg sideg prev_node edge d =
305+
let tf var getl sidel demandl getg sideg prev_node edge d =
306306
begin match edge with
307307
| Assign (lv,rv) -> tf_assign var edge prev_node lv rv
308308
| VDecl (v) -> tf_vdecl var edge prev_node v
@@ -312,7 +312,7 @@ struct
312312
| Test (p,b) -> tf_test var edge prev_node p b
313313
| ASM (_, _, _) -> tf_asm var edge prev_node (* TODO: use ASM fields for something? *)
314314
| Skip -> tf_skip var edge prev_node
315-
end getl sidel getg sideg d
315+
end getl sidel demandl getg sideg d
316316

317317
type Goblint_backtrace.mark += TfLocation of location
318318

@@ -322,7 +322,7 @@ struct
322322
| _ -> None (* for other marks *)
323323
)
324324

325-
let tf var getl sidel getg sideg prev_node (_,edge) d (f,t) =
325+
let tf var getl sidel demandl getg sideg prev_node (_,edge) d (f,t) =
326326
let old_loc = !Goblint_tracing.current_loc in
327327
let old_loc2 = !Goblint_tracing.next_loc in
328328
Goblint_tracing.current_loc := f;
@@ -331,16 +331,16 @@ struct
331331
Goblint_tracing.current_loc := old_loc;
332332
Goblint_tracing.next_loc := old_loc2
333333
) (fun () ->
334-
let d = tf var getl sidel getg sideg prev_node edge d in
334+
let d = tf var getl sidel demandl getg sideg prev_node edge d in
335335
d
336336
)
337337

338-
let tf (v,c) (edges, u) getl sidel getg sideg =
338+
let tf (v,c) (edges, u) getl sidel demandl getg sideg =
339339
let pval = getl (u,c) in
340340
let _, locs = List.fold_right (fun (f,e) (t,xs) -> f, (f,t)::xs) edges (Node.location v,[]) in
341-
List.fold_left2 (|>) pval (List.map (tf (v,Obj.repr (fun () -> c)) getl sidel getg sideg u) edges) locs
341+
List.fold_left2 (|>) pval (List.map (tf (v,Obj.repr (fun () -> c)) getl sidel demandl getg sideg u) edges) locs
342342

343-
let tf (v,c) (e,u) getl sidel getg sideg =
343+
let tf (v,c) (e,u) getl sidel demandl getg sideg =
344344
let old_node = !current_node in
345345
let old_fd = Option.map Node.find_fundec old_node |? Cil.dummyFunDec in
346346
let new_fd = Node.find_fundec v in
@@ -355,7 +355,7 @@ struct
355355
if not (CilType.Fundec.equal old_fd new_fd) then
356356
Timing.Program.exit new_fd.svar.vname
357357
) (fun () ->
358-
let d = tf (v,c) (e,u) getl sidel getg sideg in
358+
let d = tf (v,c) (e,u) getl sidel demandl getg sideg in
359359
d
360360
)
361361

@@ -364,8 +364,8 @@ struct
364364
| FunctionEntry _ ->
365365
None
366366
| _ ->
367-
let tf getl sidel getg sideg =
368-
let tf' eu = tf (v,c) eu getl sidel getg sideg in
367+
let tf getl sidel demandl getg sideg =
368+
let tf' eu = tf (v,c) eu getl sidel demandl getg sideg in
369369

370370
match NodeH.find_option CfgTools.node_scc_global v with
371371
| Some scc when NodeH.mem scc.prev v && NodeH.length scc.prev = 1 ->

0 commit comments

Comments
 (0)