Skip to content

Commit 436a2ee

Browse files
committed
Add P.t as of the local constraint system unknowns.
This breaks comparing constraint systems for the backward constraint systems (for now).
1 parent e8cc8e6 commit 436a2ee

File tree

5 files changed

+107
-55
lines changed

5 files changed

+107
-55
lines changed

src/framework/analyses.ml

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,34 @@ struct
4646
let is_write_only _ = false
4747
end
4848

49+
(** Functor for locals with digests. *)
50+
module VarDigestF (C: Printable.S) (P : Printable.S) =
51+
struct
52+
type t = Node.t * C.t * P.t [@@deriving eq, ord, hash]
53+
let relift (n,x,p) = n, C.relift x, P.relift p
54+
55+
let getLocation (n,d,p) = Node.location n
56+
57+
let pretty_trace () ((n,c,p) as x) =
58+
if get_bool "dbg.trace.context" then (* Print context and digest *)
59+
dprintf "(%a, %a, %a) on %a" Node.pretty_trace n C.pretty c P.pretty p CilType.Location.pretty (getLocation x)
60+
else
61+
dprintf "%a on %a" Node.pretty_trace n CilType.Location.pretty (getLocation x)
62+
63+
let printXml f (n,c,p) =
64+
Var.printXml f n;
65+
BatPrintf.fprintf f "<context>\n";
66+
C.printXml f c;
67+
(* Print digest, for now as part of <context>; not sure how this is parsed. *)
68+
P.printXml f p;
69+
BatPrintf.fprintf f "</context>\n"
70+
71+
let var_id (n,_,_) = Var.var_id n
72+
let node (n,_,_) = n
73+
let is_write_only _ = false
74+
end
75+
76+
4977
module type SpecSysVar =
5078
sig
5179
include Printable.S
@@ -497,8 +525,8 @@ end
497525
module type ComparableSpecSys =
498526
sig
499527
module Spec: Spec
500-
module EQSys: Goblint_constraint.ConstrSys.BaseGlobConstrSys
501-
with module LVar = VarF (Spec.C)
528+
module EQSys: Goblint_constraint.ConstrSys.BaseGlobConstrSys
529+
with module LVar = VarDigestF (Spec.C) (Spec.P)
502530
(* and module GVar = GVarPretty (Spec.V) *)
503531
and module D = Spec.D
504532
(* and module G = GVarG (Spec.G) (Spec.C) *)
@@ -509,7 +537,7 @@ end
509537
module type FwdSpecSys =
510538
sig
511539
module Spec: Spec
512-
module EQSys: Goblint_constraint.ConstrSys.FwdGlobConstrSys with module LVar = VarF (Spec.C)
540+
module EQSys: Goblint_constraint.ConstrSys.FwdGlobConstrSys with module LVar = VarDigestF (Spec.C) (Spec.P)
513541
and module GVar = GVarFCNW (Spec.V) (Spec.C)
514542
and module D = Spec.D
515543
and module G = GVarL (Spec.G) (Spec.D)

src/framework/compareConstraints.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ struct
4848
Logs.info "globals:\tequal = %d\tleft = %d\tright = %d\tincomparable = %d" !eq !le !gr !uk
4949

5050
let compare_locals l1 l2 =
51-
let one_ctx (node,_) v h =
51+
let one_ctx (node,_,_) v h =
5252
PP.replace h node (try D.join v (PP.find h node) with Not_found -> v);
5353
h
5454
in

src/framework/control.ml

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ struct
117117

118118
module Slvr = (GlobSolverFromEqSolver (Goblint_solver.Selector.Make (PostSolverArg))) (EQSys) (LHT) (GHT)
119119
(* The comparator *)
120-
module CompareGlobSys = CompareConstraints.CompareGlobSys (SpecSys)
120+
(* module CompareGlobSys = CompareConstraints.CompareGlobSys (SpecSys) *)
121121

122122
(* Triple of the function, context, and the local value. *)
123123
module RT = AnalysisResult.ResultType2 (Spec)
@@ -552,7 +552,8 @@ struct
552552
(Splitter.split_solution vh', vh')
553553
) (d1, d2)
554554
in
555-
555+
(* TODO: Fix the implementation of CompareConstraints below *)
556+
(*
556557
if get_bool "dbg.compare_runs.globsys" then
557558
CompareGlobSys.compare (d1, d2) r1 r2;
558559
@@ -566,7 +567,7 @@ struct
566567
567568
let module CompareNode = CompareConstraints.CompareNode (Spec.C) (EQSys.D) (LHT) in
568569
if get_bool "dbg.compare_runs.node" then
569-
CompareNode.compare (d1, d2) (fst r1) (fst r2);
570+
CompareNode.compare (d1, d2) (fst r1) (fst r2); *)
570571

571572
r1 (* return the result of the first run for further options -- maybe better to exit early since compare_runs is its own mode. Only excluded verify below since it's on by default. *)
572573
| _ -> failwith "Currently only two runs can be compared!";
@@ -619,19 +620,21 @@ struct
619620
in
620621

621622
if get_string "comparesolver" <> "" then (
622-
let compare_with (module S2 : DemandEqIncrSolver) =
623-
let module PostSolverArg2 =
624-
struct
623+
failwith "Comparison not implemented for backward constraint systems."
624+
(** TODO: Fix implementation below *)
625+
(* let compare_with (module S2 : DemandEqIncrSolver) =
626+
let module PostSolverArg2 =
627+
struct
625628
include PostSolverArg
626629
let should_warn = false (* we already warn from main solver *)
627630
let should_save_run = false (* we already save main solver *)
628-
end
629-
in
630-
let module S2' = (GlobSolverFromEqSolver (S2 (PostSolverArg2))) (EQSys) (LHT) (GHT) in
631-
let (r2, _) = S2'.solve entrystates entrystates_global startvars' None in (* TODO: has incremental data? *)
632-
CompareGlobSys.compare (get_string "solver", get_string "comparesolver") (lh,gh) (r2)
633-
in
634-
compare_with (Goblint_solver.Selector.choose_solver (get_string "comparesolver"))
631+
end
632+
in
633+
let module S2' = (GlobSolverFromEqSolver (S2 (PostSolverArg2))) (EQSys) (LHT) (GHT) in
634+
let (r2, _) = S2'.solve entrystates entrystates_global startvars' None in (* TODO: has incremental data? *)
635+
CompareGlobSys.compare (get_string "solver", get_string "comparesolver") (lh,gh) (r2)
636+
in
637+
compare_with (Goblint_solver.Selector.choose_solver (get_string "comparesolver")) *)
635638
);
636639

637640
(* Most warnings happen before during postsolver, but some happen later (e.g. in finalize), so enable this for the rest (if required by option). *)

src/framework/fwdConstraints.ml

Lines changed: 35 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -19,18 +19,18 @@ end
1919
(** The main point of this file---generating a [FwdGlobConstrSys] from a [Spec]. *)
2020
module FromSpec (S:Spec) (Cfg:CfgForward) (I: Increment)
2121
: sig
22-
include FwdGlobConstrSys with module LVar = VarF (S.C)
22+
include FwdGlobConstrSys with module LVar = VarDigestF (S.C) (S.P)
2323
and module GVar = GVarFCNW (S.V)(S.C)
2424
and module D = S.D
2525
and module G = GVarL (S.G) (S.D)
2626
end
2727
=
2828
struct
29-
type lv = MyCFG.node * S.C.t
29+
type lv = MyCFG.node * S.C.t * S.P.t
3030
(* type gv = varinfo *)
3131
type ld = S.D.t
3232
(* type gd = S.G.t *)
33-
module LVar = VarF (S.C)
33+
module LVar = VarDigestF (S.C) (S.P)
3434
module GVar = GVarFCNW (S.V)(S.C)
3535
module D = S.D
3636
module G = GVarL (S.G) (S.D)
@@ -45,17 +45,17 @@ struct
4545
S.sync man (`JoinCall f)
4646
| _ -> S.sync man `Join
4747

48-
let common_man' var edge target_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 =
48+
let common_man' (var: node * Obj.t * Obj.t) edge target_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 =
4949
let r = ref [] in
5050
let spawns = ref [] in
5151
(* now watch this ... *)
5252
let rec man =
5353
{ ask = (fun (type a) (q: a Queries.t) -> S.query man q)
5454
; emit = (fun _ -> failwith "emit outside MCP")
5555
; node = target_node
56-
; prev_node = fst var
57-
; control_context = (fun () -> snd var |> Obj.obj)
58-
; context = (fun () -> snd var |> Obj.obj)
56+
; prev_node = Tuple3.first var
57+
; control_context = (fun () -> Tuple3.second var |> Obj.obj)
58+
; context = (fun () -> Tuple3.second var |> Obj.obj)
5959
; edge = edge
6060
; local = pval
6161
; global = (fun g -> G.spec (getg (GVar.spec g)))
@@ -72,7 +72,9 @@ struct
7272
match Cilfacade.find_varinfo_fundec f with
7373
| fd ->
7474
let c = S.context man fd d in
75-
sidel (FunctionEntry fd, c) d
75+
(* Derive digest from abstract state *)
76+
let p = S.P.of_elt d in
77+
sidel (FunctionEntry fd, c, p) d
7678
| exception Not_found ->
7779
(* unknown function *)
7880
M.error ~category:Imprecise ~tags:[Category Unsound] "Created a thread from unknown function %s" f.vname;
@@ -167,7 +169,7 @@ struct
167169
let d = S.branch man e tv in (* Force transfer function to be evaluated before dereferencing in common_join argument. *)
168170
common_join man d !r !spawns
169171

170-
let tf_normal_call man lv e (f:fundec) args getl sidel getg sideg =
172+
let tf_normal_call man lv e (f:fundec) args getl (sidel : lv -> ld -> unit) getg sideg =
171173
let combine (cd, fc, fd) =
172174
if M.tracing then M.traceli "combine" "local: %a" S.D.pretty cd;
173175
if M.tracing then M.trace "combine" "function: %a" S.D.pretty fd;
@@ -222,7 +224,13 @@ struct
222224
in
223225
let paths = S.enter man lv f args in
224226
let paths = List.map (fun (c,v) -> (c, S.context man f v, v)) paths in
225-
List.iter (fun (c,fc,v) -> if not (S.D.is_bot v) then sidel (FunctionEntry f, fc) v) paths;
227+
let sidel_entries (c,fc,v) =
228+
if not (S.D.is_bot v) then begin
229+
let p = S.P.of_elt v in
230+
sidel (FunctionEntry f, fc, p) v
231+
end
232+
in
233+
List.iter sidel_entries paths;
226234
let paths = List.map (fun (c,fc,v) ->
227235
let endvar = (GVar.return (f,fc)) in
228236
(c, fc, if S.D.is_bot v then v else G.return @@ getg endvar)) paths in
@@ -323,33 +331,33 @@ struct
323331
let d = S.skip man in (* Force transfer function to be evaluated before dereferencing in common_join argument. *)
324332
common_join man d !r !spawns
325333

326-
let tf ((n,c) as var) getl sidel getg sideg target_node edge d =
334+
let tf ((n,c,p) as var) getl sidel getg sideg target_node edge d =
327335
begin match edge with
328336
| Assign (lv,rv) ->
329337
let r = tf_assign var edge target_node lv rv getl sidel getg sideg d in
330-
sidel (target_node, Obj.obj c) r
338+
sidel (target_node, Obj.obj c, Obj.obj p) r
331339
| VDecl (v) ->
332340
let r = tf_vdecl var edge target_node v getl sidel getg sideg d in
333-
sidel (target_node, Obj.obj c) r
341+
sidel (target_node, Obj.obj c, Obj.obj p) r
334342
| Proc (r,f,ars) ->
335343
let r = tf_proc var edge target_node r f ars getl sidel getg sideg d in
336-
sidel (target_node, Obj.obj c) r
344+
sidel (target_node, Obj.obj c, Obj.obj p) r
337345
| Entry f ->
338346
let r = tf_entry var edge target_node f getl sidel getg sideg d in
339-
sidel (target_node, Obj.obj c) r
347+
sidel (target_node, Obj.obj c, Obj.obj p) r
340348
| Ret (r,fd) ->
341349
let r = tf_ret var edge target_node r fd getl sidel getg sideg d in
342-
sidel (target_node, Obj.obj c) r;
350+
sidel (target_node, Obj.obj c, Obj.obj p) r;
343351
sideg (GVar.return (fd,Obj.obj c)) (G.create_return r)
344-
| Test (p,b) ->
345-
let r = tf_test var edge target_node p b getl sidel getg sideg d in
346-
sidel (target_node, Obj.obj c) r
352+
| Test (e,b) ->
353+
let r = tf_test var edge target_node e b getl sidel getg sideg d in
354+
sidel (target_node, Obj.obj c, Obj.obj p) r
347355
| ASM (_, _, _) ->
348356
let r = tf_asm var edge target_node getl sidel getg sideg d in
349-
sidel (target_node, Obj.obj c) r
357+
sidel (target_node, Obj.obj c, Obj.obj p) r
350358
| Skip ->
351359
let r = tf_skip var edge target_node getl sidel getg sideg d in
352-
sidel (target_node, Obj.obj c) r
360+
sidel (target_node, Obj.obj c, Obj.obj p) r
353361
end
354362

355363
type Goblint_backtrace.mark += TfLocation of location
@@ -372,13 +380,13 @@ struct
372380
tf var getl sidel getg sideg target_node edge d
373381
)
374382

375-
let tf_fwd value (v,c) (edges, u) getl sidel getg sideg:unit =
383+
let tf_fwd value (v,c,p) (edges, u) getl sidel getg sideg:unit =
376384
let pval = value in
377385
let _, locs = List.fold_right (fun (f,e) (t,xs) -> f, (f,t)::xs) edges (Node.location v,[]) in
378-
let es = List.map (tf (v,Obj.repr c) getl sidel getg sideg u) edges in
386+
let es = List.map (tf (v,Obj.repr c, Obj.repr p) getl sidel getg sideg u) edges in
379387
List.iter2 (fun e l -> e pval l) es locs
380388

381-
let tf value (v,c) (e,u) getl sidel getg sideg =
389+
let tf value (v,c,p) (e,u) getl sidel getg sideg =
382390
let old_node = !current_node in
383391
let old_fd = Option.map Node.find_fundec old_node |? Cil.dummyFunDec in
384392
let new_fd = Node.find_fundec v in
@@ -393,12 +401,12 @@ struct
393401
if not (CilType.Fundec.equal old_fd new_fd) then
394402
Timing.Program.exit new_fd.svar.vname
395403
) (fun () ->
396-
tf_fwd value (v,c) (e,u) getl sidel getg sideg
404+
tf_fwd value (v,c,p) (e,u) getl sidel getg sideg
397405
)
398406

399-
let system (v,c) =
407+
let system (v,c,p) =
400408
let tf value getl sidel getg sideg =
401-
let tf' eu = tf value (v,c) eu getl sidel getg sideg in
409+
let tf' eu = tf value (v,c,p) eu getl sidel getg sideg in
402410
let xs = Cfg.next v in
403411
List.iter (fun eu -> tf' eu) xs
404412
in

src/framework/fwdControl.ml

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,8 @@ struct
225225
let res = Result.create 113 in
226226

227227
(* Adding the state at each system variable to the final result *)
228-
let add_local_var (n,es) state =
228+
(* TODO: Consider digest in result? *)
229+
let add_local_var (n,es,_) state =
229230
(* Not using Node.location here to have updated locations in incremental analysis.
230231
See: https://github.com/goblint/analyzer/issues/290#issuecomment-881258091. *)
231232
let loc = UpdateCil.getLoc n in
@@ -445,8 +446,8 @@ struct
445446
in
446447
let prestartstate = Spec.startstate MyCFG.dummy_func.svar in (* like in do_extern_inits *)
447448
let othervars = List.map (enter_with (otherstate prestartstate)) otherfuns in
448-
let startvars = List.concat (startvars @ exitvars @ othervars) in
449-
if startvars = [] then
449+
let startfuns = List.concat (startvars @ exitvars @ othervars) in
450+
if startfuns = [] then
450451
failwith "BUG: Empty set of start variables; may happen if enter_func of any analysis returns an empty list.";
451452

452453
AnalysisState.global_initialization := false;
@@ -466,9 +467,21 @@ struct
466467
; sideg = (fun g d -> sideg (EQSys.GVar.spec g) (EQSys.G.create_spec d))
467468
}
468469
in
469-
let startvars' = List.map (fun (n,e) -> (MyCFG.FunctionEntry n, Spec.context (man e) n e)) startvars in
470+
let startvars' =
471+
let to_startvar (n,e) =
472+
let context = Spec.context (man e) n e in
473+
let digest = Spec.P.of_elt e in
474+
(MyCFG.FunctionEntry n, context, digest)
475+
in
476+
List.map to_startvar startfuns in
470477

471-
let entrystates = List.map (fun (n,e) -> (MyCFG.FunctionEntry n, Spec.context (man e) n e), e) startvars in
478+
let entrystates =
479+
let to_entrystate (n,e) =
480+
let context = Spec.context (man e) n e in
481+
let digest = Spec.P.of_elt e in
482+
((MyCFG.FunctionEntry n, context, digest), e)
483+
in
484+
List.map to_entrystate startfuns in
472485
let entrystates_global = GHT.to_list gh in
473486

474487
let uncalled_dead = ref 0 in
@@ -481,9 +494,9 @@ struct
481494
let gobview = get_bool "gobview" in
482495
let save_run_str = let o = get_string "save_run" in if o = "" then (if gobview then "run" else "") else o in
483496
let solve = if (get_string "solver" = "bu") then BuSolver.solve else
484-
if (get_string "solver" = "wbu") then WBuSolver.solve else FwdSolver.solve in
485-
let check = if (get_string "solver" = "bu") then BuSolver.check else
486-
if (get_string "solver" = "wbu") then WBuSolver.check else FwdSolver.check in
497+
if (get_string "solver" = "wbu") then WBuSolver.solve else FwdSolver.solve in
498+
let check = if (get_string "solver" = "bu") then BuSolver.check else
499+
if (get_string "solver" = "wbu") then WBuSolver.check else FwdSolver.check in
487500
let _ = solve entrystates entrystates_global startvars' in
488501

489502
AnalysisState.should_warn := true; (* reset for postsolver *)
@@ -496,7 +509,7 @@ struct
496509
(* Most warnings happen before during postsolver, but some happen later (e.g. in finalize), so enable this for the rest (if required by option). *)
497510
AnalysisState.should_warn := PostSolverArg.should_warn;
498511
let insrt k _ s = match k with
499-
| (MyCFG.FunctionEntry fn,_) -> Set.Int.add fn.svar.vid s
512+
| (MyCFG.FunctionEntry fn,_,_) -> Set.Int.add fn.svar.vid s
500513
| _ -> s
501514
in
502515
(* set of ids of called functions *)
@@ -541,10 +554,10 @@ struct
541554
let lh2, gh2 = LHT.of_seq rho, GHT.of_seq tau in
542555
CompareGlobSys.compare (get_string "solver", get_string "comparesolver") (lh,gh) (lh2, gh2)
543556
in
544-
let solve = if (get_string "comparesolver" = "bu") then BuSolver.solve else
557+
let solve = if (get_string "comparesolver" = "bu") then BuSolver.solve else
545558
(if (get_string "comparesolver" = "fwd") then FwdSolver.solve else WBuSolver.solve) in
546559

547-
let check = if (get_string "comparesolver" = "bu") then BuSolver.check else
560+
let check = if (get_string "comparesolver" = "bu") then BuSolver.check else
548561
(if (get_string "comparesolver" = "fwd") then FwdSolver.check else WBuSolver.check) in
549562
compare_with solve check;
550563
);

0 commit comments

Comments
 (0)