Skip to content

Commit 713f2a1

Browse files
authored
Merge pull request #762 from goblint/apron-box-prod
Add Apron box product lifter
2 parents df017ae + 91f333e commit 713f2a1

File tree

8 files changed

+451
-122
lines changed

8 files changed

+451
-122
lines changed

conf/traces-rel.json

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,18 @@
2626
]
2727
},
2828
"base" : {
29-
"privatization": "mutex-meet"
29+
"privatization": "mutex-meet",
30+
"invariant": {
31+
"enabled": false
32+
}
33+
},
34+
"apron": {
35+
"invariant": {
36+
"one-var": false,
37+
"local": false,
38+
"global": true,
39+
"diff-box": true
40+
}
3041
}
3142
},
3243
"sem": {
@@ -38,6 +49,9 @@
3849
},
3950
"builtin_unreachable": {
4051
"dead_code": true
52+
},
53+
"int": {
54+
"signed_overflow": "assume_none"
4155
}
4256
},
4357
"exp": {
@@ -52,5 +66,12 @@
5266
"print_tids" : true,
5367
"print_wpoints" : true,
5468
"print_protection": true
69+
},
70+
"witness": {
71+
"invariant": {
72+
"other": false,
73+
"loop-head": false,
74+
"after-lock": true
75+
}
5576
}
5677
}

src/analyses/apron/apronAnalysis.apron.ml

Lines changed: 54 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,18 @@ open ApronDomain
66

77
module M = Messages
88

9-
module SpecFunctor (AD: ApronDomain.S2) (Priv: ApronPriv.S) : Analyses.MCPSpec =
9+
module SpecFunctor (AD: ApronDomain.S3) (Priv: ApronPriv.S) : Analyses.MCPSpec =
1010
struct
1111
include Analyses.DefaultSpec
1212

1313
let name () = "apron"
1414

15+
module AD =
16+
struct
17+
include AD
18+
include ApronDomain.Tracked
19+
end
20+
1521
module Priv = Priv(AD)
1622
module D = ApronComponents (AD) (Priv.D)
1723
module G = Priv.G
@@ -282,7 +288,7 @@ struct
282288
| _ -> false (* remove everything else (globals, global privs) *)
283289
)
284290
in
285-
let unify_apr = ApronDomain.A.unify Man.mgr new_apr new_fun_apr in (* TODO: unify_with *)
291+
let unify_apr = AD.unify new_apr new_fun_apr in (* TODO: unify_with *)
286292
if M.tracing then M.tracel "combine" "apron unifying %a %a = %a\n" AD.pretty new_apr AD.pretty new_fun_apr AD.pretty unify_apr;
287293
let unify_st = {fun_st with apr = unify_apr} in
288294
if AD.type_tracked (Cilfacade.fundec_return_type f) then (
@@ -354,6 +360,34 @@ struct
354360
| None -> st'
355361

356362

363+
let query_invariant ctx context =
364+
let keep_local = GobConfig.get_bool "ana.apron.invariant.local" in
365+
let keep_global = GobConfig.get_bool "ana.apron.invariant.global" in
366+
367+
let apr = ctx.local.apr in
368+
(* filter variables *)
369+
let var_filter v = match V.find_metadata v with
370+
| Some (Global _) -> keep_global
371+
| Some Local -> keep_local
372+
| _ -> false
373+
in
374+
let apr = AD.keep_filter apr var_filter in
375+
376+
let one_var = GobConfig.get_bool "ana.apron.invariant.one-var" in
377+
let scope = Node.find_fundec ctx.node in
378+
379+
AD.invariant ~scope apr
380+
|> List.enum
381+
|> Enum.filter_map (fun (lincons1: Lincons1.t) ->
382+
(* filter one-vars *)
383+
if one_var || Apron.Linexpr0.get_size lincons1.lincons0.linexpr0 >= 2 then
384+
CilOfApron.cil_exp_of_lincons1 scope lincons1
385+
|> Option.filter (fun exp -> not (InvariantCil.exp_contains_tmp exp) && InvariantCil.exp_is_in_scope scope exp)
386+
else
387+
None
388+
)
389+
|> Enum.fold (fun acc x -> Invariant.(acc && of_exp x)) Invariant.none
390+
357391
let query ctx (type a) (q: a Queries.t): a Queries.result =
358392
let open Queries in
359393
let st = ctx.local in
@@ -383,8 +417,7 @@ struct
383417
let is_lt = eval_int exp in
384418
Option.default true (ID.to_bool is_lt)
385419
| Queries.Invariant context ->
386-
let scope = Node.find_fundec ctx.node in
387-
D.invariant ~scope ctx.local
420+
query_invariant ctx context
388421
| _ -> Result.top q
389422

390423

@@ -434,8 +467,19 @@ struct
434467
let sync ctx reason =
435468
(* After the solver is finished, store the results (for later comparison) *)
436469
if !GU.postsolving then begin
470+
let keep_local = GobConfig.get_bool "ana.apron.invariant.local" in
471+
let keep_global = GobConfig.get_bool "ana.apron.invariant.global" in
472+
473+
(* filter variables *)
474+
let var_filter v = match V.find_metadata v with
475+
| Some (Global _) -> keep_global
476+
| Some Local -> keep_local
477+
| _ -> false
478+
in
479+
let st = keep_filter ctx.local.apr var_filter in
480+
437481
let old_value = RH.find_default results ctx.node (AD.bot ()) in
438-
let new_value = AD.join old_value ctx.local.apr in
482+
let new_value = AD.join old_value st in
439483
RH.replace results ctx.node new_value;
440484
end;
441485
Priv.sync (Analyses.ask_of_ctx ctx) ctx.global ctx.sideg ctx.local (reason :> [`Normal | `Join | `Return | `Init | `Thread])
@@ -446,21 +490,14 @@ struct
446490
module OctApron = ApronPrecCompareUtil.OctagonD
447491
let store_data file =
448492
let convert (m: AD.t RH.t): OctApron.t RH.t =
449-
let convert_single (a: AD.t): OctApron.t =
450-
if Oct.manager_is_oct AD.Man.mgr then
451-
Oct.Abstract1.to_oct a
452-
else
453-
let generator = AD.to_lincons_array a in
454-
OctApron.of_lincons_array generator
455-
in
456-
RH.map (fun _ -> convert_single) m
493+
RH.map (fun _ -> AD.to_oct) m
457494
in
458495
let post_process m =
459496
let m = Stats.time "convert" convert m in
460497
RH.map (fun _ v -> OctApron.marshal v) m
461498
in
462499
let results = post_process results in
463-
let name = name () ^ "(domain: " ^ (AD.Man.name ()) ^ ", privatization: " ^ (Priv.name ()) ^ (if GobConfig.get_bool "ana.apron.threshold_widening" then ", th" else "" ) ^ ")" in
500+
let name = name () ^ "(domain: " ^ (AD.name ()) ^ ", privatization: " ^ (Priv.name ()) ^ (if GobConfig.get_bool "ana.apron.threshold_widening" then ", th" else "" ) ^ ")" in
464501
let results: ApronPrecCompareUtil.dump = {marshalled = results; name } in
465502
Serialize.marshal results file
466503

@@ -477,7 +514,9 @@ end
477514
let spec_module: (module MCPSpec) Lazy.t =
478515
lazy (
479516
let module Man = (val ApronDomain.get_manager ()) in
480-
let module AD = ApronDomain.D2 (Man) in
517+
let module AD = ApronDomain.D3 (Man) in
518+
let diff_box = GobConfig.get_bool "ana.apron.invariant.diff-box" in
519+
let module AD = (val if diff_box then (module ApronDomain.BoxProd (AD): ApronDomain.S3) else (module AD)) in
481520
let module Priv = (val ApronPriv.get_priv ()) in
482521
let module Spec = SpecFunctor (AD) (Priv) in
483522
(module Spec)

src/analyses/apron/apronPriv.apron.ml

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ open CommonPriv
1212

1313

1414
module type S =
15-
functor (AD: ApronDomain.S2) ->
15+
functor (AD: ApronDomain.S3) ->
1616
sig
1717
module D: Lattice.S
1818
module G: Lattice.S
@@ -46,7 +46,7 @@ module type S =
4646

4747
(** Top privatization, which doesn't track globals at all.
4848
This is unlike base's "none" privatization. which does track globals, but doesn't privatize them. *)
49-
module Top: S = functor (AD: ApronDomain.S2) ->
49+
module Top: S = functor (AD: ApronDomain.S3) ->
5050
struct
5151
module D = Lattice.Unit
5252
module G = Lattice.Unit
@@ -123,7 +123,7 @@ sig
123123
end
124124

125125
(** Protection-Based Reading. *)
126-
module ProtectionBasedPriv (Param: ProtectionBasedPrivParam): S = functor (AD: ApronDomain.S2) ->
126+
module ProtectionBasedPriv (Param: ProtectionBasedPrivParam): S = functor (AD: ApronDomain.S3) ->
127127
struct
128128
include ConfCheck.RequireMutexActivatedInit
129129
open Protection
@@ -388,7 +388,7 @@ struct
388388
let finalize () = ()
389389
end
390390

391-
module CommonPerMutex = functor(AD: ApronDomain.S2) ->
391+
module CommonPerMutex = functor(AD: ApronDomain.S3) ->
392392
struct
393393
include Protection
394394
module V = ApronDomain.V
@@ -411,7 +411,7 @@ struct
411411
end
412412

413413
(** Per-mutex meet. *)
414-
module PerMutexMeetPriv : S = functor (AD: ApronDomain.S2) ->
414+
module PerMutexMeetPriv : S = functor (AD: ApronDomain.S3) ->
415415
struct
416416
open CommonPerMutex(AD)
417417
include MutexGlobals
@@ -566,7 +566,7 @@ struct
566566
let name () = "W"
567567
end
568568

569-
module type ClusterArg = functor (AD: ApronDomain.S2) ->
569+
module type ClusterArg = functor (AD: ApronDomain.S3) ->
570570
sig
571571
module LAD: Lattice.S
572572

@@ -580,7 +580,7 @@ sig
580580
end
581581

582582
(** No clustering. *)
583-
module NoCluster:ClusterArg = functor (AD: ApronDomain.S2) ->
583+
module NoCluster:ClusterArg = functor (AD: ApronDomain.S3) ->
584584
struct
585585
module AD = AD
586586
open CommonPerMutex(AD)
@@ -663,7 +663,7 @@ end
663663

664664

665665
(** Clusters when clustering is downward-closed. *)
666-
module DownwardClosedCluster (ClusteringArg: ClusteringArg) = functor (AD: ApronDomain.S2) ->
666+
module DownwardClosedCluster (ClusteringArg: ClusteringArg) = functor (AD: ApronDomain.S3) ->
667667
struct
668668
module AD = AD
669669
open CommonPerMutex(AD)
@@ -728,7 +728,7 @@ struct
728728
end
729729

730730
(** Clusters when clustering is arbitrary (not necessarily downward-closed). *)
731-
module ArbitraryCluster (ClusteringArg: ClusteringArg): ClusterArg = functor (AD: ApronDomain.S2) ->
731+
module ArbitraryCluster (ClusteringArg: ClusteringArg): ClusterArg = functor (AD: ApronDomain.S3) ->
732732
struct
733733
module AD = AD
734734
module DCCluster = (DownwardClosedCluster(ClusteringArg))(AD)
@@ -804,7 +804,7 @@ struct
804804
end
805805

806806
(** Per-mutex meet with TIDs. *)
807-
module PerMutexMeetPrivTID (Cluster: ClusterArg): S = functor (AD: ApronDomain.S2) ->
807+
module PerMutexMeetPrivTID (Cluster: ClusterArg): S = functor (AD: ApronDomain.S3) ->
808808
struct
809809
open CommonPerMutex(AD)
810810
include MutexGlobals
@@ -1095,7 +1095,7 @@ struct
10951095
let finalize () = finalize ()
10961096
end
10971097

1098-
module TracingPriv = functor (Priv: S) -> functor (AD: ApronDomain.S2) ->
1098+
module TracingPriv = functor (Priv: S) -> functor (AD: ApronDomain.S3) ->
10991099
struct
11001100
module Priv = Priv (AD)
11011101
include Priv

src/analyses/base.ml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1128,6 +1128,12 @@ struct
11281128

11291129
cpa_invariant
11301130

1131+
let query_invariant ctx context =
1132+
if GobConfig.get_bool "ana.base.invariant.enabled" then
1133+
query_invariant ctx context
1134+
else
1135+
Invariant.none
1136+
11311137
let query ctx (type a) (q: a Q.t): a Q.result =
11321138
match q with
11331139
| Q.EvalFunvar e ->

0 commit comments

Comments
 (0)