Skip to content

Commit 5a264ad

Browse files
committed
NF
1 parent ec017f9 commit 5a264ad

File tree

2 files changed

+708
-560
lines changed

2 files changed

+708
-560
lines changed

src/lib/reasoners/bitv_rel.ml

Lines changed: 113 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -437,8 +437,81 @@ module Interval_domain = struct
437437
) (point Z.zero) (Shostak.Bitv.embed r)
438438
end
439439

440+
let normal_form_bv bv =
441+
let rec loop cte mask r_sz acc = function
442+
| [] -> List.rev acc, (cte, mask, r_sz)
443+
| { Bitv.bv = Bitv.Cte n ; sz } :: bv' ->
444+
let cte = Z.(cte lsl sz lor n) in
445+
let mask = Z.(mask lsl sz lor (extract minus_one 0 sz)) in
446+
let acc =
447+
match acc with
448+
| [] -> []
449+
| _ -> { Bitv.bv = Bitv.Cte Z.zero ; sz } :: acc
450+
in
451+
loop cte mask (r_sz + sz) acc bv'
452+
| x :: bv' ->
453+
let cte = Z.(cte lsl x.sz) in
454+
let mask = Z.(mask lsl x.sz) in
455+
loop cte mask (r_sz + x.sz) (x :: acc) bv'
456+
in loop Z.zero Z.zero 0 [] bv
457+
458+
let normal_form_r r =
459+
let bv, ofs = normal_form_bv (Shostak.Bitv.embed r) in
460+
match bv with
461+
| [] -> None, ofs
462+
| bv -> Some (Shostak.Bitv.is_mine bv), ofs
463+
464+
module NF = struct
465+
type expr = X.r
466+
467+
type var = X.r
468+
469+
type ofs = Z.t * Z.t * int
470+
471+
let pp_ofs ppf (cte, mask, sz) =
472+
Fmt.pf ppf "%s & %s [%d]"
473+
(Z.format "%b" cte) (Z.format "%b" mask) sz
474+
475+
let ofs_sub (cte1, mask1, sz1) (cte2, mask2, sz2) =
476+
assert (sz1 = sz2);
477+
assert (Z.equal (Z.logand mask2 (Z.lognot mask1)) Z.zero);
478+
assert (Z.equal (Z.logand mask2 cte1) cte2);
479+
let cte = Z.sub cte1 cte2 in
480+
assert (Z.equal cte (Z.logand cte1 (Z.lognot mask2)));
481+
let sz = Z.numbits (Z.extract (Z.lognot mask2) 0 sz1) in
482+
(Z.extract cte 0 sz, Z.extract mask1 0 sz, sz)
483+
484+
let decompose = normal_form_r
485+
end
486+
487+
module IDD = struct
488+
type var = X.r
489+
490+
type ofs = Z.t * Z.t * int
491+
492+
let default_domain r =
493+
Interval_domain.map_leaves (fun r ->
494+
Interval_domain.unknown (X.type_info r)
495+
) r
496+
497+
type domain = Interval_domain.t
498+
499+
let constant (cte, _, _) =
500+
Intervals.Int.of_bounds (Closed cte) (Closed cte)
501+
502+
let add_offset (cte, _, _) d =
503+
Intervals.Int.add d (Intervals.Int.of_bounds (Closed cte) (Closed cte))
504+
505+
let sub_offset _ (cte, _, _) d =
506+
Intervals.Int.sub d (Intervals.Int.of_bounds (Closed cte) (Closed cte))
507+
end
508+
440509
module Interval_domains =
441-
Rel_utils.Domains_make(Interval_domain)(Rel_utils.Explained(Constraint))
510+
Rel_utils.Domains_make
511+
(Interval_domain)
512+
(Rel_utils.Explained(Constraint))
513+
(IDD)
514+
(NF)
442515

443516
module Interval_domains_uf =
444517
Rel_utils.UfDomainMap(Interval_domain)(Interval_domains)
@@ -499,8 +572,44 @@ module Domain : Rel_utils.Domain with type t = Bitlist.t = struct
499572
invalid_arg "unknown"
500573
end
501574

575+
module BDD = struct
576+
type var = X.r
577+
578+
type ofs = Z.t * Z.t * int
579+
580+
type domain = Bitlist.t
581+
582+
let default_domain r =
583+
Domain.map_leaves (fun r ->
584+
Domain.unknown (X.type_info r)
585+
) r
586+
587+
let widen sz d =
588+
let width = Bitlist.width d in
589+
assert (width <= sz);
590+
if width = sz then d else
591+
Bitlist.concat (Bitlist.exact (sz - width) Z.zero Explanation.empty) d
592+
593+
let constant (cte, _, sz) =
594+
Bitlist.exact sz cte Explanation.empty
595+
596+
let add_offset (cte, mask, sz) d =
597+
assert (sz > 0);
598+
let d = widen sz d in
599+
let mask = Bitlist.exact sz mask Explanation.empty in
600+
let cte = Bitlist.exact sz cte Explanation.empty in
601+
Bitlist.logor d (Bitlist.logand cte mask)
602+
603+
let sub_offset r (_cte, mask, sz) d =
604+
let r_sz = match X.type_info r with Tbitv n -> n | _ -> assert false in
605+
assert (sz > 0);
606+
assert (Bitlist.width d = sz);
607+
let mask = Bitlist.exact sz mask Explanation.empty in
608+
Bitlist.extract (Bitlist.logand d (Bitlist.lognot mask)) 0 (r_sz - 1)
609+
end
610+
502611
module Domains =
503-
Rel_utils.Domains_make(Domain)(Rel_utils.Explained(Constraint))
612+
Rel_utils.Domains_make(Domain)(Rel_utils.Explained(Constraint))(BDD)(NF)
504613
module Domains_uf =
505614
Rel_utils.UfDomainMap(Domain)(Domains)
506615

@@ -1218,7 +1327,7 @@ let propagate_bitlist queue dom =
12181327
let update r d = update ~ex:Explanation.empty (handle dom r) d
12191328
in
12201329
if X.is_a_leaf r then
1221-
Domains.Variables.iter_parents r (fun p ->
1330+
Domains.VS.iter_parents r (fun p ->
12221331
if X.is_a_leaf p then
12231332
assert (X.equal r p)
12241333
else
@@ -1243,7 +1352,7 @@ let propagate_intervals queue dom =
12431352
let update r d = update ~ex:Explanation.empty (handle dom r) d
12441353
in
12451354
if X.is_a_leaf r then
1246-
Interval_domains_uf.Variables.iter_parents r (fun p ->
1355+
Interval_domains.VS.iter_parents r (fun p ->
12471356
if X.is_a_leaf p then
12481357
assert (X.equal r p)
12491358
else
@@ -1391,18 +1500,6 @@ let rec propagate_all uf eqs bdom idom =
13911500
else
13921501
eqs, bdom, idom
13931502

1394-
module Watch = struct
1395-
type t = int
1396-
1397-
let pp ppf n = Fmt.pf ppf "w%d" n
1398-
1399-
let equal = Int.equal
1400-
1401-
let compare = Int.compare
1402-
1403-
let hash : int -> int = Hashtbl.hash
1404-
end
1405-
14061503
type t =
14071504
{ delayed : Rel_utils.Delayed.t
14081505
; terms : SX.t

0 commit comments

Comments
 (0)