Source file TacBitwised.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
open Lang
let range a n =
let vmax = Integer.two_power_of_int n in
F.p_and (F.p_leq F.e_zero a) (F.p_lt a (F.e_zint vmax))
let bit_test x k = Cint.l_and x (F.e_int (1 lsl k))
let rec bitwise_eqs a b n =
if n >= 0 then
F.e_eq (bit_test a n) (bit_test b n) ::
bitwise_eqs a b (n-1)
else []
let bitwise_eq a b n = F.e_and (bitwise_eqs a b (n-1))
let rewrite descr u v = Tactical.rewrite [ descr , F.p_true , u , v ]
let vrange,prange = Tactical.spinner ~id:"Wp.bitwised.range"
~vmin:0 ~vmax:64 ~default:32
~title:"Bits" ~descr:"Number of bits for bitwise equality" ()
class bitcase =
object(self)
inherit Tactical.make
~id:"Wp.bitwised"
~title:"Bitwise Eq."
~descr:"Decompose Bitwise Equality"
~params:[prange]
method private process (feedback:Tactical.feedback) ~neq e a b =
if F.is_int a && F.is_int b then
let n = self#get_field vrange in
let inrange = F.p_and (range a n) (range b n) in
let bitwise = bitwise_eq a b n in
let e' = if neq then F.e_not bitwise else bitwise in
feedback#set_title "Bitwise %s. (%d bits)"
(if neq then "Neq" else "Eq") n ;
Tactical.Applicable
(fun seq ->
("range" , (fst seq , inrange)) ::
rewrite "bitwise" e e' seq)
else
Tactical.Not_applicable
method select feedback selection =
let e = Tactical.selected selection in
let open Qed.Logic in
match F.repr e with
| Eq(a,b) -> self#process feedback ~neq:false e a b
| Neq(a,b) -> self#process feedback ~neq:true e a b
| _ -> Tactical.Not_applicable
end
let tactical = Tactical.export (new bitcase)
let strategy ?(priority=1.0) selection ~nbits =
Strategy.{
priority ; tactical ; selection ;
arguments = [ arg vrange nbits ] ;
}
let is_bitwised e =
let open Qed.Logic in
match F.repr e with
| Fun(f,_) -> List.memq f Cint.f_bitwised
| _ -> false
let rec lookup push clause ~nbits ~priority p =
let open Qed.Logic in
match F.repr p with
| And ps | Or ps ->
List.iter (lookup push clause ~priority ~nbits) ps
| Imply(hs,p) ->
List.iter (lookup push clause ~priority ~nbits) (p::hs)
| Eq(x,y) | Neq(x,y) when F.is_int x && F.is_int y ->
let bx = is_bitwised x in
let by = is_bitwised y in
if bx || by then
let priority = if bx && by then priority else priority *. 0.8 in
push (strategy ~priority ~nbits Tactical.(Inside(clause,p)))
| _ -> ()
class autobitwise =
object(self)
method private nbits = Ctypes.i_bits (Ctypes.c_ptr ())
method id = "wp:bitwised"
method title =
Printf.sprintf "Auto Bitwise Eq. (%d)" self#nbits
method descr =
Printf.sprintf "Apply Bitwise Equality on wordsize bits (%d)" self#nbits
method search push (seq : Conditions.sequent) =
let goal = snd seq in
let nbits = self#nbits in
lookup push (Tactical.Goal goal) ~nbits ~priority:1.0 (F.e_prop goal) ;
Conditions.iter
(fun step ->
let p = Conditions.head step |> F.e_prop in
lookup push (Tactical.Step step) ~nbits ~priority:0.5 p
) (fst seq)
end
let () = Strategy.register (new autobitwise)