source: src/Clight/memoryInjections.ma @ 2332

Last change on this file since 2332 was 2332, checked in by garnier, 7 years ago

Some progress on switch removal. Small fix in the definition of free, in GenMem?.ma.

File size: 106.0 KB
Line 
1include "Clight/Cexec.ma".
2include "frontend_misc.ma".
3
4(* This file contains some definitions and lemmas related to memory injections.
5   Could be useful for the Clight → Cminor. Needs revision: the definitions are
6   too lax and allow inconsistent embeddings (more precisely, these embeddings do
7   not allow to prove that the semantics for pointer less-than comparisons is
8   conserved). *)
9
10(* --------------------------------------------------------------------------- *)   
11(* Some general lemmas on bitvectors (offsets /are/ bitvectors) *)
12(* --------------------------------------------------------------------------- *)
13 
14lemma add_with_carries_n_O : ∀n,bv. add_with_carries n bv (zero n) false = 〈bv,zero n〉.
15#n #bv whd in match (add_with_carries ????); elim bv //
16#n #hd #tl #Hind whd in match (fold_right2_i ????????);
17>Hind normalize
18cases n in tl;
19[ 1: #tl cases hd normalize @refl
20| 2: #n' #tl cases hd normalize @refl ]
21qed.
22
23lemma addition_n_0 : ∀n,bv. addition_n n bv (zero n) = bv.
24#n #bv whd in match (addition_n ???);
25>add_with_carries_n_O //
26qed.
27
28lemma replicate_Sn : ∀A,sz,elt.
29  replicate A (S sz) elt = elt ::: (replicate A sz elt).
30// qed.
31
32lemma zero_Sn : ∀n. zero (S n) = false ::: (zero n). // qed.
33
34lemma negation_bv_Sn : ∀n. ∀xa. ∀a : BitVector n. negation_bv … (xa ::: a) = (notb xa) ::: (negation_bv … a).
35#n #xa #a normalize @refl qed.
36
37(* useful facts on carry_of *)
38lemma carry_of_TT : ∀x. carry_of true true x = true. // qed.
39lemma carry_of_TF : ∀x. carry_of true false x = x. // qed.
40lemma carry_of_FF : ∀x. carry_of false false x = false. // qed.
41lemma carry_of_lcomm : ∀x,y,z. carry_of x y z = carry_of y x z. * * * // qed.
42lemma carry_of_rcomm : ∀x,y,z. carry_of x y z = carry_of x z y. * * * // qed.
43
44
45
46definition one_bv ≝ λn. (\fst (add_with_carries … (zero n) (zero n) true)).
47
48lemma one_bv_Sn_aux : ∀n. ∀bits,flags : BitVector (S n).
49    add_with_carries … (zero (S n)) (zero (S n)) true = 〈bits, flags〉 →
50    add_with_carries … (zero (S (S n))) (zero (S (S n))) true = 〈false ::: bits, false ::: flags〉.
51#n elim n
52[ 1: #bits #flags elim (BitVector_Sn … bits) #hd_bits * #tl_bits #Heq_bits
53     elim (BitVector_Sn … flags) #hd_flags * #tl_flags #Heq_flags
54     >(BitVector_O … tl_flags) >(BitVector_O … tl_bits)
55     normalize #Heq destruct (Heq) @refl
56| 2: #n' #Hind #bits #flags elim (BitVector_Sn … bits) #hd_bits * #tl_bits #Heq_bits
57     destruct #Hind >add_with_carries_Sn >replicate_Sn
58     whd in match (zero ?) in Hind; lapply Hind
59     elim (add_with_carries (S (S n'))
60            (false:::replicate bool (S n') false)
61            (false:::replicate bool (S n') false) true) #bits #flags #Heq destruct
62            normalize >add_with_carries_Sn in Hind;
63     elim (add_with_carries (S n') (replicate bool (S n') false)
64                    (replicate bool (S n') false) true) #flags' #bits'
65     normalize
66     cases (match bits' in Vector return λsz:ℕ.(λfoo:Vector bool sz.bool) with 
67            [VEmpty⇒true|VCons (sz:ℕ)   (cy:bool)   (tl:(Vector bool sz))⇒cy])
68     normalize #Heq destruct @refl
69] qed.     
70
71lemma one_bv_Sn : ∀n. one_bv (S (S n)) = false ::: (one_bv (S n)).
72#n lapply (one_bv_Sn_aux n)
73whd in match (one_bv ?) in ⊢ (? → (??%%));
74elim (add_with_carries (S n) (zero (S n)) (zero (S n)) true) #bits #flags
75#H lapply (H bits flags (refl ??)) #H2 >H2 @refl
76qed.
77
78lemma increment_to_addition_n_aux : ∀n. ∀a : BitVector n.
79    add_with_carries ? a (zero n) true = add_with_carries ? a (one_bv n) false.
80#n   
81elim n
82[ 1: #a >(BitVector_O … a) normalize @refl
83| 2: #n' cases n'
84     [ 1: #Hind #a elim (BitVector_Sn ? a) #xa * #tl #Heq destruct
85          >(BitVector_O … tl) normalize cases xa @refl
86     | 2: #n'' #Hind #a elim (BitVector_Sn ? a) #xa * #tl #Heq destruct
87          >one_bv_Sn >zero_Sn
88          lapply (Hind tl)
89          >add_with_carries_Sn >add_with_carries_Sn
90          #Hind >Hind elim (add_with_carries (S n'') tl (one_bv (S n'')) false) #bits #flags
91          normalize nodelta elim (BitVector_Sn … flags) #flags_hd * #flags_tl #Hflags_eq >Hflags_eq
92          normalize nodelta @refl
93] qed.         
94
95(* In order to use associativity on increment, we hide it under addition_n. *)
96lemma increment_to_addition_n : ∀n. ∀a : BitVector n. increment ? a = addition_n ? a (one_bv n).
97#n
98whd in match (increment ??) in ⊢ (∀_.??%?);
99whd in match (addition_n ???) in ⊢ (∀_.???%);
100#a lapply (increment_to_addition_n_aux n a)
101#Heq >Heq cases (add_with_carries n a (one_bv n) false) #bits #flags @refl
102qed.
103
104(* Explicit formulation of addition *)
105
106(* Explicit formulation of the last carry bit *)
107let rec ith_carry (n : nat) (a,b : BitVector n) (init : bool) on n : bool ≝
108match n return λx. BitVector x → BitVector x → bool with
109[ O ⇒ λ_,_. init
110| S x ⇒ λa',b'.
111  let hd_a ≝ head' … a' in
112  let hd_b ≝ head' … b' in
113  let tl_a ≝ tail … a' in
114  let tl_b ≝ tail … b' in
115  carry_of hd_a hd_b (ith_carry x tl_a tl_b init)
116] a b.
117
118lemma ith_carry_unfold : ∀n. ∀init. ∀a,b : BitVector (S n).
119  ith_carry ? a b init = (carry_of (head' … a) (head' … b) (ith_carry ? (tail … a) (tail … b) init)).
120#n #init #a #b @refl qed.
121
122lemma ith_carry_Sn : ∀n. ∀init. ∀xa,xb. ∀a,b : BitVector n.
123  ith_carry ? (xa ::: a) (xb ::: b) init = (carry_of xa xb (ith_carry ? a b init)). // qed.
124
125(* correction of [ith_carry] *)
126lemma ith_carry_ok : ∀n. ∀init. ∀a,b,res_ab,flags_ab : BitVector (S n).
127  〈res_ab,flags_ab〉 = add_with_carries ? a b init →
128  head' … flags_ab = ith_carry ? a b init.
129#n elim n
130[ 1: #init #a #b #res_ab #flags_ab
131     elim (BitVector_Sn … a) #hd_a * #tl_a #Heq_a
132     elim (BitVector_Sn … b) #hd_b * #tl_b #Heq_b
133     elim (BitVector_Sn … res_ab) #hd_res * #tl_res #Heq_res
134     elim (BitVector_Sn … flags_ab) #hd_flags * #tl_flags #Heq_flags
135     destruct
136     >(BitVector_O … tl_a) >(BitVector_O … tl_b)
137     cases hd_a cases hd_b cases init normalize #Heq destruct (Heq)
138     @refl
139| 2: #n' #Hind #init #a #b #res_ab #flags_ab
140     elim (BitVector_Sn … a) #hd_a * #tl_a #Heq_a
141     elim (BitVector_Sn … b) #hd_b * #tl_b #Heq_b
142     elim (BitVector_Sn … res_ab) #hd_res * #tl_res #Heq_res
143     elim (BitVector_Sn … flags_ab) #hd_flags * #tl_flags #Heq_flags
144     destruct
145     lapply (Hind … init tl_a tl_b tl_res tl_flags)
146     >add_with_carries_Sn >(ith_carry_Sn (S n'))
147     elim (add_with_carries (S n') tl_a tl_b init) #res_ab #flags_ab
148     elim (BitVector_Sn … flags_ab) #hd_flags_ab * #tl_flags_ab #Heq_flags_ab >Heq_flags_ab
149     normalize nodelta cases hd_flags_ab normalize nodelta
150     whd in match (head' ? (S n') ?); #H1 #H2
151     destruct (H2) lapply (H1 (refl ??)) whd in match (head' ???); #Heq <Heq @refl
152] qed.
153
154(* Explicit formulation of ith bit of an addition, with explicit initial carry bit. *)
155definition ith_bit ≝ λ(n : nat).λ(a,b : BitVector n).λinit.
156match n return λx. BitVector x → BitVector x → bool with
157[ O ⇒ λ_,_. init
158| S x ⇒ λa',b'.
159  let hd_a ≝ head' … a' in
160  let hd_b ≝ head' … b' in
161  let tl_a ≝ tail … a' in
162  let tl_b ≝ tail … b' in
163  xorb (xorb hd_a hd_b) (ith_carry x tl_a tl_b init)
164] a b.
165
166lemma ith_bit_unfold : ∀n. ∀init. ∀a,b : BitVector (S n).
167  ith_bit ? a b init =  xorb (xorb (head' … a) (head' … b)) (ith_carry ? (tail … a) (tail … b) init).
168#n #a #b // qed.
169
170lemma ith_bit_Sn : ∀n. ∀init. ∀xa,xb. ∀a,b : BitVector n.
171  ith_bit ? (xa ::: a) (xb ::: b) init =  xorb (xorb xa xb) (ith_carry ? a b init). // qed.
172
173(* correction of ith_bit *)
174lemma ith_bit_ok : ∀n. ∀init. ∀a,b,res_ab,flags_ab : BitVector (S n).
175  〈res_ab,flags_ab〉 = add_with_carries ? a b init →
176  head' … res_ab = ith_bit ? a b init.
177#n
178cases n
179[ 1: #init #a #b #res_ab #flags_ab
180     elim (BitVector_Sn … a) #hd_a * #tl_a #Heq_a
181     elim (BitVector_Sn … b) #hd_b * #tl_b #Heq_b
182     elim (BitVector_Sn … res_ab) #hd_res * #tl_res #Heq_res
183     elim (BitVector_Sn … flags_ab) #hd_flags * #tl_flags #Heq_flags
184     destruct
185     >(BitVector_O … tl_a) >(BitVector_O … tl_b)
186     >(BitVector_O … tl_flags) >(BitVector_O … tl_res)
187     normalize cases init cases hd_a cases hd_b normalize #Heq destruct @refl
188| 2: #n' #init #a #b #res_ab #flags_ab
189     elim (BitVector_Sn … a) #hd_a * #tl_a #Heq_a
190     elim (BitVector_Sn … b) #hd_b * #tl_b #Heq_b
191     elim (BitVector_Sn … res_ab) #hd_res * #tl_res #Heq_res
192     elim (BitVector_Sn … flags_ab) #hd_flags * #tl_flags #Heq_flags
193     destruct
194     lapply (ith_carry_ok … init tl_a tl_b tl_res tl_flags)
195     #Hcarry >add_with_carries_Sn elim (add_with_carries ? tl_a tl_b init) in Hcarry;
196     #res #flags normalize nodelta elim (BitVector_Sn … flags) #hd_flags' * #tl_flags' #Heq_flags'
197     >Heq_flags' normalize nodelta cases hd_flags' normalize nodelta #H1 #H2 destruct (H2)
198     cases hd_a cases hd_b >ith_bit_Sn whd in match (head' ???) in H1 ⊢ %;
199     <(H1 (refl ??)) @refl
200] qed.
201
202(* Transform a function from bit-vectors to bits into a vector by folding *)
203let rec bitvector_fold (n : nat) (v : BitVector n) (f : ∀sz. BitVector sz → bool) on v : BitVector n ≝
204match v with
205[ VEmpty ⇒ VEmpty ?
206| VCons sz elt tl ⇒
207  let bit ≝ f ? v in
208  bit ::: (bitvector_fold ? tl f)
209].
210
211(* Two-arguments version *)
212let rec bitvector_fold2 (n : nat) (v1, v2 : BitVector n) (f : ∀sz. BitVector sz → BitVector sz → bool) on v1 : BitVector n ≝
213match v1  with
214[ VEmpty ⇒ λ_. VEmpty ?
215| VCons sz elt tl ⇒ λv2'.
216  let bit ≝ f ? v1 v2 in
217  bit ::: (bitvector_fold2 ? tl (tail … v2') f)
218] v2.
219
220lemma bitvector_fold2_Sn : ∀n,x1,x2,v1,v2,f.
221  bitvector_fold2 (S n) (x1 ::: v1) (x2 ::: v2) f = (f ? (x1 ::: v1) (x2 ::: v2)) ::: (bitvector_fold2 … v1 v2 f). // qed.
222
223(* These functions pack all the relevant information (including carries) directly. *)
224definition addition_n_direct ≝ λn,v1,v2,init. bitvector_fold2 n v1 v2 (λn,v1,v2. ith_bit n v1 v2 init).
225
226lemma addition_n_direct_Sn : ∀n,x1,x2,v1,v2,init.
227  addition_n_direct (S n) (x1 ::: v1) (x2 ::: v2) init = (ith_bit ? (x1 ::: v1) (x2 ::: v2) init) ::: (addition_n_direct … v1 v2 init). // qed.
228 
229lemma tail_Sn : ∀n. ∀x. ∀a : BitVector n. tail … (x ::: a) = a. // qed.
230
231(* Prove the equivalence of addition_n_direct with add_with_carries *)
232lemma addition_n_direct_ok : ∀n,carry,v1,v2.
233  (\fst (add_with_carries n v1 v2 carry)) = addition_n_direct n v1 v2 carry.
234#n elim n
235[ 1: #carry #v1 #v2 >(BitVector_O … v1) >(BitVector_O … v2) normalize @refl
236| 2: #n' #Hind #carry #v1 #v2
237     elim (BitVector_Sn … v1) #hd1 * #tl1 #Heq1
238     elim (BitVector_Sn … v2) #hd2 * #tl2 #Heq2
239     lapply (Hind carry tl1 tl2)
240     lapply (ith_bit_ok ? carry v1 v2)
241     lapply (ith_carry_ok ? carry v1 v2)
242     destruct
243     #Hind >addition_n_direct_Sn
244     >ith_bit_Sn >add_with_carries_Sn
245     elim (add_with_carries n' tl1 tl2 carry) #bits #flags normalize nodelta
246     cases (match flags in Vector return λsz:ℕ.(λfoo:Vector bool sz.bool) with 
247            [VEmpty⇒carry|VCons (sz:ℕ)   (cy:bool)   (tl:(Vector bool sz))⇒cy])
248     normalize nodelta #Hcarry' lapply (Hcarry' ?? (refl ??))
249     whd in match head'; normalize nodelta
250     #H1 #H2 >H1 >H2 @refl
251] qed.
252 
253(* trivially lift associativity to our new setting *)     
254lemma associative_addition_n_direct : ∀n. ∀carry1,carry2. ∀v1,v2,v3 : BitVector n.
255  addition_n_direct ? (addition_n_direct ? v1 v2 carry1) v3 carry2 =
256  addition_n_direct ? v1 (addition_n_direct ? v2 v3 carry1) carry2.
257#n #carry1 #carry2 #v1 #v2 #v3
258<addition_n_direct_ok <addition_n_direct_ok
259<addition_n_direct_ok <addition_n_direct_ok
260lapply (associative_add_with_carries … carry1 carry2 v1 v2 v3)
261elim (add_with_carries n v2 v3 carry1) #bits #carries normalize nodelta
262elim (add_with_carries n v1 v2 carry1) #bits' #carries' normalize nodelta
263#H @(sym_eq … H)
264qed.
265
266lemma commutative_addition_n_direct : ∀n. ∀v1,v2 : BitVector n.
267  addition_n_direct ? v1 v2 false = addition_n_direct ? v2 v1 false.
268#n #v1 #v2 /by associative_addition_n, addition_n_direct_ok/
269qed.
270
271definition increment_direct ≝ λn,v. addition_n_direct n v (one_bv ?) false.
272definition twocomp_neg_direct ≝ λn,v. increment_direct n (negation_bv n v).
273
274(* fold andb on a bitvector. *)
275let rec andb_fold (n : nat) (b : BitVector n) on b : bool ≝
276match b with
277[ VEmpty ⇒ true
278| VCons sz elt tl ⇒
279  andb elt (andb_fold ? tl)
280].
281
282lemma andb_fold_Sn : ∀n. ∀x. ∀b : BitVector n. andb_fold (S n) (x ::: b) = andb x (andb_fold … n b). // qed.
283
284lemma andb_fold_inversion : ∀n. ∀elt,x. andb_fold (S n) (elt ::: x) = true → elt = true ∧ andb_fold n x = true.
285#n #elt #x cases elt normalize #H @conj destruct (H) try assumption @refl
286qed.
287
288lemma ith_increment_carry : ∀n. ∀a : BitVector (S n).
289  ith_carry … a (one_bv ?) false = andb_fold … a.
290#n elim n
291[ 1: #a elim (BitVector_Sn … a) #hd * #tl #Heq >Heq >(BitVector_O … tl)
292     cases hd normalize @refl
293| 2: #n' #Hind #a
294     elim (BitVector_Sn … a) #hd * #tl #Heq >Heq
295     lapply (Hind … tl) #Hind >one_bv_Sn
296     >ith_carry_Sn whd in match (andb_fold ??);
297     cases hd >Hind @refl
298] qed.
299
300lemma ith_increment_bit : ∀n. ∀a : BitVector (S n).
301  ith_bit … a (one_bv ?) false = xorb (head' … a) (andb_fold … (tail … a)).
302#n #a
303elim (BitVector_Sn … a) #hd * #tl #Heq >Heq
304whd in match (head' ???);
305-a cases n in tl;
306[ 1: #tl >(BitVector_O … tl) cases hd normalize try //
307| 2: #n' #tl >one_bv_Sn >ith_bit_Sn
308     >ith_increment_carry >tail_Sn
309     cases hd try //
310] qed.
311
312(* Lemma used to prove involutivity of two-complement negation *)
313lemma twocomp_neg_involutive_aux : ∀n. ∀v : BitVector (S n).
314   (andb_fold (S n) (negation_bv (S n) v) =
315    andb_fold (S n) (negation_bv (S n) (addition_n_direct (S n) (negation_bv (S n) v) (one_bv (S n)) false))).
316#n elim n
317[ 1: #v elim (BitVector_Sn … v) #hd * #tl #Heq >Heq >(BitVector_O … tl) cases hd @refl
318| 2: #n' #Hind #v elim (BitVector_Sn … v) #hd * #tl #Heq >Heq
319     lapply (Hind tl) -Hind #Hind >negation_bv_Sn >one_bv_Sn >addition_n_direct_Sn
320     >andb_fold_Sn >ith_bit_Sn >negation_bv_Sn >andb_fold_Sn <Hind
321     cases hd normalize nodelta
322     [ 1: >xorb_false >(xorb_comm false ?) >xorb_false
323     | 2: >xorb_false >(xorb_comm true ?) >xorb_true ]
324     >ith_increment_carry
325     cases (andb_fold (S n') (negation_bv (S n') tl)) @refl
326] qed.
327   
328(* Test of the 'direct' approach: proof of the involutivity of two-complement negation. *)
329lemma twocomp_neg_involutive : ∀n. ∀v : BitVector n. twocomp_neg_direct ? (twocomp_neg_direct ? v) = v.
330#n elim n
331[ 1: #v >(BitVector_O v) @refl
332| 2: #n' cases n'
333     [ 1: #Hind #v elim (BitVector_Sn … v) #hd * #tl #Heq >Heq
334          >(BitVector_O … tl) normalize cases hd @refl
335     | 2: #n'' #Hind #v elim (BitVector_Sn … v) #hd * #tl #Heq >Heq
336          lapply (Hind tl) -Hind #Hind <Hind in ⊢ (???%);
337          whd in match twocomp_neg_direct; normalize nodelta
338          whd in match increment_direct; normalize nodelta
339          >(negation_bv_Sn ? hd tl) >one_bv_Sn >(addition_n_direct_Sn ? (¬hd) false ??)
340          >ith_bit_Sn >negation_bv_Sn >addition_n_direct_Sn >ith_bit_Sn
341          generalize in match (addition_n_direct (S n'')
342                                                   (negation_bv (S n'')
343                                                   (addition_n_direct (S n'') (negation_bv (S n'') tl) (one_bv (S n'')) false))
344                                                   (one_bv (S n'')) false); #tail
345          >ith_increment_carry >ith_increment_carry
346          cases hd normalize nodelta
347          [ 1: normalize in match (xorb false false); >(xorb_comm false ?) >xorb_false >xorb_false
348          | 2: normalize in match (xorb true false); >(xorb_comm true ?) >xorb_true >xorb_false ]
349          <twocomp_neg_involutive_aux
350          cases (andb_fold (S n'') (negation_bv (S n'') tl)) @refl
351      ]
352] qed.
353
354lemma bitvector_cons_inj_inv : ∀n. ∀a,b. ∀va,vb : BitVector n. a ::: va = b ::: vb → a =b ∧ va = vb.
355#n #a #b #va #vb #H destruct (H) @conj @refl qed.
356
357lemma bitvector_cons_eq : ∀n. ∀a,b. ∀v : BitVector n. a = b → a ::: v = b ::: v. // qed.
358
359(* Injectivity of increment *)
360lemma increment_inj : ∀n. ∀a,b : BitVector n.
361  increment_direct ? a = increment_direct ? b →
362  a = b ∧ (ith_carry n a (one_bv n) false = ith_carry n b (one_bv n) false).
363#n whd in match increment_direct; normalize nodelta elim n
364[ 1: #a #b >(BitVector_O … a) >(BitVector_O … b) normalize #_ @conj //
365| 2: #n' cases n'
366   [ 1: #_ #a #b
367        elim (BitVector_Sn … a) #hd_a * #tl_a #Heq_a >Heq_a
368        elim (BitVector_Sn … b) #hd_b * #tl_b #Heq_b >Heq_b
369        >(BitVector_O … tl_a) >(BitVector_O … tl_b) cases hd_a cases hd_b
370        normalize #H @conj try //
371   | 2: #n'' #Hind #a #b
372        elim (BitVector_Sn … a) #hd_a * #tl_a #Heq_a >Heq_a
373        elim (BitVector_Sn … b) #hd_b * #tl_b #Heq_b >Heq_b
374        lapply (Hind … tl_a tl_b) -Hind #Hind
375        >one_bv_Sn >addition_n_direct_Sn >ith_bit_Sn
376        >addition_n_direct_Sn >ith_bit_Sn >xorb_false >xorb_false
377        #H elim (bitvector_cons_inj_inv … H) #Heq1 #Heq2
378        lapply (Hind Heq2) * #Heq3 #Heq4
379        cut (hd_a = hd_b)
380        [ 1: >Heq4 in Heq1; #Heq5 lapply (xorb_inj (ith_carry ? tl_b (one_bv ?) false) hd_a hd_b)
381             * #Heq6 #_ >xorb_comm in Heq6; >(xorb_comm  ? hd_b) #Heq6 >(Heq6 Heq5)
382             @refl ]
383        #Heq5 @conj [ 1: >Heq3 >Heq5 @refl ]
384        >ith_carry_Sn >ith_carry_Sn >Heq4 >Heq5 @refl
385] qed.
386
387(* Inverse of injecivity of increment, does not lose information (cf increment_inj) *)
388lemma increment_inj_inv : ∀n. ∀a,b : BitVector n.
389  a = b → increment_direct ? a = increment_direct ? b. // qed.
390
391(* A more general result. *)
392lemma addition_n_direct_inj : ∀n. ∀x,y,delta: BitVector n.
393  addition_n_direct ? x delta false = addition_n_direct ? y delta false →
394  x = y ∧ (ith_carry n x delta false = ith_carry n y delta false).
395#n elim n
396[ 1: #x #y #delta >(BitVector_O … x) >(BitVector_O … y) >(BitVector_O … delta) * @conj @refl
397| 2: #n' #Hind #x #y #delta
398     elim (BitVector_Sn … x) #hdx * #tlx #Heqx >Heqx
399     elim (BitVector_Sn … y) #hdy * #tly #Heqy >Heqy
400     elim (BitVector_Sn … delta) #hdd * #tld #Heqd >Heqd
401     >addition_n_direct_Sn >ith_bit_Sn
402     >addition_n_direct_Sn >ith_bit_Sn
403     >ith_carry_Sn >ith_carry_Sn
404     lapply (Hind … tlx tly tld) -Hind #Hind #Heq
405     elim (bitvector_cons_inj_inv … Heq) #Heq_hd #Heq_tl
406     lapply (Hind Heq_tl) -Hind * #HindA #HindB
407     >HindA >HindB >HindB in Heq_hd; #Heq_hd
408     cut (hdx = hdy)
409     [ 1: cases hdd in Heq_hd; cases (ith_carry n' tly tld false)
410          cases hdx cases hdy normalize #H try @H try @refl
411          >H try @refl ]
412     #Heq_hd >Heq_hd @conj @refl
413] qed.
414
415(* We also need it the other way around. *)
416lemma addition_n_direct_inj_inv : ∀n. ∀x,y,delta: BitVector n.
417  x ≠ y → (* ∧ (ith_carry n x delta false = ith_carry n y delta false). *)
418   addition_n_direct ? x delta false ≠ addition_n_direct ? y delta false.
419#n elim n
420[ 1: #x #y #delta >(BitVector_O … x) >(BitVector_O … y) >(BitVector_O … delta) * #H @(False_ind … (H (refl ??)))
421| 2: #n' #Hind #x #y #delta
422     elim (BitVector_Sn … x) #hdx * #tlx #Heqx >Heqx
423     elim (BitVector_Sn … y) #hdy * #tly #Heqy >Heqy
424     elim (BitVector_Sn … delta) #hdd * #tld #Heqd >Heqd
425     #Hneq
426     cut (hdx ≠ hdy ∨ tlx ≠ tly)
427     [ @(eq_bv_elim … tlx tly)
428       [ #Heq_tl >Heq_tl >Heq_tl in Hneq;
429         #Hneq cut (hdx ≠ hdy) [ % #Heq_hd >Heq_hd in Hneq; *
430                                 #H @H @refl ]
431         #H %1 @H
432       | #H %2 @H ] ]
433     -Hneq #Hneq
434     >addition_n_direct_Sn >addition_n_direct_Sn
435     >ith_bit_Sn >ith_bit_Sn cases Hneq
436     [ 1: #Hneq_hd
437          lapply (addition_n_direct_inj … tlx tly tld)         
438          @(eq_bv_elim … (addition_n_direct ? tlx tld false) (addition_n_direct ? tly tld false))
439          [ 1: #Heq -Hind #Hind elim (Hind Heq) #Heq_tl >Heq_tl #Heq_carry >Heq_carry
440               % #Habsurd elim (bitvector_cons_inj_inv … Habsurd) -Habsurd
441               lapply Hneq_hd
442               cases hdx cases hdd cases hdy cases (ith_carry ? tly tld false)
443               normalize in ⊢ (? → % → ?); #Hneq_hd #Heq_hd #_
444               try @(absurd … Heq_hd Hneq_hd)
445               elim Hneq_hd -Hneq_hd #Hneq_hd @Hneq_hd
446               try @refl try assumption try @(sym_eq … Heq_hd)
447          | 2: #Htl_not_eq #_ % #Habsurd elim (bitvector_cons_inj_inv … Habsurd) #_
448               elim Htl_not_eq -Htl_not_eq #HA #HB @HA @HB ]
449     | 2: #Htl_not_eq lapply (Hind tlx tly tld Htl_not_eq) -Hind #Hind
450          % #Habsurd elim (bitvector_cons_inj_inv … Habsurd) #_
451          elim Hind -Hind #HA #HB @HA @HB ]
452] qed.
453
454lemma carry_notb : ∀a,b,c. notb (carry_of a b c) = carry_of (notb a) (notb b) (notb c). * * * @refl qed.
455
456lemma increment_to_carry_aux : ∀n. ∀a : BitVector (S n).
457   ith_carry (S n) a (one_bv (S n)) false
458   = ith_carry (S n) a (zero (S n)) true.
459#n elim n
460[ 1: #a elim (BitVector_Sn ? a) #hd_a * #tl_a #Heq >Heq >(BitVector_O … tl_a) @refl
461| 2: #n' #Hind #a elim (BitVector_Sn ? a) #hd_a * #tl_a #Heq >Heq
462     lapply (Hind tl_a) #Hind
463     >one_bv_Sn >zero_Sn >ith_carry_Sn >ith_carry_Sn >Hind @refl
464] qed.
465
466lemma neutral_addition_n_direct_aux : ∀n. ∀v. ith_carry n v (zero n) false = false.
467#n elim n //
468#n' #Hind #v elim (BitVector_Sn … v) #hd * #tl #Heq >Heq >zero_Sn
469>ith_carry_Sn >(Hind tl) cases hd @refl.
470qed.
471
472lemma neutral_addition_n_direct : ∀n. ∀v : BitVector n.
473  addition_n_direct ? v (zero ?) false = v.
474#n elim n
475[ 1: #v >(BitVector_O … v) normalize @refl
476| 2: #n' #Hind #v elim (BitVector_Sn … v) #hd * #tl #Heq >Heq
477     lapply (Hind … tl) #H >zero_Sn >addition_n_direct_Sn
478     >ith_bit_Sn >H >xorb_false >neutral_addition_n_direct_aux
479     >xorb_false @refl
480] qed.
481
482lemma increment_to_carry_zero : ∀n. ∀a : BitVector n. addition_n_direct ? a (one_bv ?) false = addition_n_direct ? a (zero ?) true.
483#n elim n
484[ 1: #a >(BitVector_O … a) normalize @refl
485| 2: #n' cases n'
486     [ 1: #_ #a elim (BitVector_Sn … a) #hd_a * #tl_a #Heq >Heq >(BitVector_O … tl_a) cases hd_a @refl
487     | 2: #n'' #Hind #a
488          elim (BitVector_Sn … a) #hd_a * #tl_a #Heq >Heq
489          lapply (Hind tl_a) -Hind #Hind
490          >one_bv_Sn >zero_Sn >addition_n_direct_Sn >ith_bit_Sn
491          >addition_n_direct_Sn >ith_bit_Sn
492          >xorb_false >Hind @bitvector_cons_eq
493          >increment_to_carry_aux @refl
494     ]
495] qed.
496
497lemma increment_to_carry : ∀n. ∀a,b : BitVector n.
498  addition_n_direct ? a (addition_n_direct ? b (one_bv ?) false) false = addition_n_direct ? a b true.
499#n #a #b >increment_to_carry_zero <associative_addition_n_direct
500>neutral_addition_n_direct @refl
501qed.
502
503(* Prove -(a + b) = -a + -b *)
504lemma twocomp_neg_plus : ∀n. ∀a,b : BitVector n.
505  twocomp_neg_direct ? (addition_n_direct ? a b false) = addition_n_direct ? (twocomp_neg_direct … a) (twocomp_neg_direct … b) false.
506whd in match twocomp_neg_direct; normalize nodelta
507lapply increment_inj_inv
508whd in match increment_direct; normalize nodelta
509#H #n #a #b
510<associative_addition_n_direct @H
511>associative_addition_n_direct >(commutative_addition_n_direct ? (one_bv n))
512>increment_to_carry
513-H lapply b lapply a -b -a
514cases n
515[ 1: #a #b >(BitVector_O … a) >(BitVector_O … b) @refl
516| 2: #n' #a #b
517     cut (negation_bv ? (addition_n_direct ? a b false)
518           = addition_n_direct ? (negation_bv ? a) (negation_bv ? b) true ∧
519          notb (ith_carry ? a b false) = (ith_carry ? (negation_bv ? a) (negation_bv ? b) true))
520     [ -n lapply b lapply a elim n'
521     [ 1: #a #b elim (BitVector_Sn … a) #hd_a * #tl_a #Heqa >Heqa >(BitVector_O … tl_a)
522          elim (BitVector_Sn … b) #hd_b * #tl_b #Heqb >Heqb >(BitVector_O … tl_b)
523          cases hd_a cases hd_b normalize @conj @refl
524     | 2: #n #Hind #a #b
525          elim (BitVector_Sn … a) #hd_a * #tl_a #Heqa >Heqa
526          elim (BitVector_Sn … b) #hd_b * #tl_b #Heqb >Heqb
527          lapply (Hind tl_a tl_b) * #H1 #H2
528          @conj
529          [ 2: >ith_carry_Sn >negation_bv_Sn >negation_bv_Sn >ith_carry_Sn
530               >carry_notb >H2 @refl
531          | 1: >addition_n_direct_Sn >ith_bit_Sn >negation_bv_Sn
532               >negation_bv_Sn >negation_bv_Sn
533               >addition_n_direct_Sn >ith_bit_Sn >H1 @bitvector_cons_eq
534               >xorb_lneg >xorb_rneg >notb_notb
535               <xorb_rneg >H2 @refl
536          ]
537      ] ]
538      * #H1 #H2 @H1
539] qed.
540
541lemma addition_n_direct_neg : ∀n. ∀a.
542 (addition_n_direct n a (negation_bv n a) false) = replicate ?? true
543 ∧ (ith_carry n a (negation_bv n a) false = false).
544#n elim n
545[ 1: #a >(BitVector_O … a) @conj @refl
546| 2: #n' #Hind #a elim (BitVector_Sn … a) #hd * #tl #Heq >Heq
547     lapply (Hind … tl) -Hind * #HA #HB
548     @conj
549     [ 2: >negation_bv_Sn >ith_carry_Sn >HB cases hd @refl
550     | 1: >negation_bv_Sn >addition_n_direct_Sn
551          >ith_bit_Sn >HB >xorb_false >HA
552          @bitvector_cons_eq elim hd @refl
553     ]
554] qed.
555
556(* -a + a = 0 *)
557lemma bitvector_opp_direct : ∀n. ∀a : BitVector n. addition_n_direct ? a (twocomp_neg_direct ? a) false = (zero ?).
558whd in match twocomp_neg_direct;
559whd in match increment_direct;
560normalize nodelta
561#n #a <associative_addition_n_direct
562elim (addition_n_direct_neg … a) #H #_ >H
563-H -a
564cases n try //
565#n'
566cut ((addition_n_direct (S n') (replicate bool ? true) (one_bv ?) false = (zero (S n')))
567       ∧ (ith_carry ? (replicate bool (S n') true) (one_bv (S n')) false = true))
568[ elim n'
569     [ 1: @conj @refl
570     | 2: #n' * #HA #HB @conj
571          [ 1: >replicate_Sn >one_bv_Sn  >addition_n_direct_Sn
572               >ith_bit_Sn >HA >zero_Sn @bitvector_cons_eq >HB @refl
573          | 2: >replicate_Sn >one_bv_Sn >ith_carry_Sn >HB @refl ]
574     ]
575] * #H1 #H2 @H1
576qed.
577
578(* Lift back the previous result to standard operations. *)
579lemma twocomp_neg_direct_ok : ∀n. ∀v. twocomp_neg_direct ? v = two_complement_negation n v.
580#n #v whd in match twocomp_neg_direct; normalize nodelta
581whd in match increment_direct; normalize nodelta
582whd in match two_complement_negation; normalize nodelta
583>increment_to_addition_n <addition_n_direct_ok
584whd in match addition_n; normalize nodelta
585elim (add_with_carries ????) #a #b @refl
586qed.
587
588lemma two_complement_negation_plus : ∀n. ∀a,b : BitVector n.
589  two_complement_negation ? (addition_n ? a b) = addition_n ? (two_complement_negation ? a) (two_complement_negation ? b).
590#n #a #b
591lapply (twocomp_neg_plus ? a b)
592>twocomp_neg_direct_ok >twocomp_neg_direct_ok >twocomp_neg_direct_ok
593<addition_n_direct_ok <addition_n_direct_ok
594whd in match addition_n; normalize nodelta
595elim (add_with_carries n a b false) #bits #flags normalize nodelta
596elim (add_with_carries n (two_complement_negation n a) (two_complement_negation n b) false) #bits' #flags'
597normalize nodelta #H @H
598qed.
599
600lemma bitvector_opp_addition_n : ∀n. ∀a : BitVector n. addition_n ? a (two_complement_negation ? a) = (zero ?).
601#n #a lapply (bitvector_opp_direct ? a)
602>twocomp_neg_direct_ok <addition_n_direct_ok
603whd in match (addition_n ???);
604elim (add_with_carries n a (two_complement_negation n a) false) #bits #flags #H @H
605qed.
606
607lemma neutral_addition_n : ∀n. ∀a : BitVector n. addition_n ? a (zero ?) = a.
608#n #a
609lapply (neutral_addition_n_direct n a)
610<addition_n_direct_ok
611whd in match (addition_n ???);
612elim (add_with_carries n a (zero n) false) #bits #flags #H @H
613qed.
614
615lemma injective_addition_n : ∀n. ∀x,y,delta : BitVector n.
616  addition_n ? x delta = addition_n ? y delta → x = y. 
617#n #x #y #delta 
618lapply (addition_n_direct_inj … x y delta)
619<addition_n_direct_ok <addition_n_direct_ok
620whd in match addition_n; normalize nodelta
621elim (add_with_carries n x delta false) #bitsx #flagsx
622elim (add_with_carries n y delta false) #bitsy #flagsy
623normalize #H1 #H2 elim (H1 H2) #Heq #_ @Heq
624qed.
625
626lemma injective_inv_addition_n : ∀n. ∀x,y,delta : BitVector n.
627  x ≠ y → addition_n ? x delta ≠ addition_n ? y delta. 
628#n #x #y #delta 
629lapply (addition_n_direct_inj_inv … x y delta)
630<addition_n_direct_ok <addition_n_direct_ok
631whd in match addition_n; normalize nodelta
632elim (add_with_carries n x delta false) #bitsx #flagsx
633elim (add_with_carries n y delta false) #bitsy #flagsy
634normalize #H1 #H2 @(H1 H2)
635qed.
636
637
638(* --------------------------------------------------------------------------- *)   
639(* Aux lemmas that are likely to be found elsewhere. *)
640(* --------------------------------------------------------------------------- *)   
641
642lemma zlt_succ : ∀a,b. Zltb a b = true → Zltb a (Zsucc b) = true.
643#a #b #HA
644lapply (Zltb_true_to_Zlt … HA) #HA_prop
645@Zlt_to_Zltb_true /2/
646qed.
647
648lemma zlt_succ_refl : ∀a. Zltb a (Zsucc a) = true.
649#a @Zlt_to_Zltb_true /2/ qed.
650(*
651definition le_offset : offset → offset → bool.
652  λx,y. Zleb (offv x) (offv y).
653*)
654lemma not_refl_absurd : ∀A:Type[0].∀x:A. x ≠ x → False. /2/. qed.
655
656lemma eqZb_reflexive : ∀x:Z. eqZb x x = true. #x /2/. qed.
657
658(* --------------------------------------------------------------------------- *)   
659(* In the definition of injections below, we maintain a list of blocks that are
660   writeable. We need some lemmas to reason on the fact that a block cannot be
661   both writeable and not writeable, etc. *)
662(* --------------------------------------------------------------------------- *)
663
664(* When equality on A is decidable, [mem A elt l] is too. *)
665lemma mem_dec : ∀A:Type[0]. ∀eq:(∀a,b:A. a = b ∨ a ≠ b). ∀elt,l. mem A elt l ∨ ¬ (mem A elt l).
666#A #dec #elt #l elim l
667[ 1: normalize %2 /2/
668| 2: #hd #tl #Hind
669     elim (dec elt hd)
670     [ 1: #Heq >Heq %1 /2/
671     | 2: #Hneq cases Hind
672        [ 1: #Hmem %1 /2/
673        | 2: #Hnmem %2 normalize
674              % #H cases H
675              [ 1: lapply Hneq * #Hl #Eq @(Hl Eq)
676              | 2: lapply Hnmem * #Hr #Hmem @(Hr Hmem) ]
677] ] ]
678qed.
679
680lemma block_eq_dec : ∀a,b:block. a = b ∨ a ≠ b.
681#a #b @(eq_block_elim … a b) /2/ qed.
682
683lemma mem_not_mem_neq : ∀l,elt1,elt2. (mem block elt1 l) → ¬ (mem block elt2 l) → elt1 ≠ elt2.
684#l #elt1 #elt2 elim l
685[ 1: normalize #Habsurd @(False_ind … Habsurd)
686| 2: #hd #tl #Hind normalize #Hl #Hr
687   cases Hl
688   [ 1: #Heq >Heq
689        @(eq_block_elim … hd elt2)
690        [ 1: #Heq >Heq /2 by not_to_not/
691        | 2: #x @x ]
692   | 2: #Hmem1 cases (mem_dec … block_eq_dec elt2 tl)
693        [ 1: #Hmem2 % #Helt_eq cases Hr #H @H %2 @Hmem2
694        | 2: #Hmem2 @Hind //
695        ]
696   ]
697] qed.
698
699lemma neq_block_eq_block_false : ∀b1,b2:block. b1 ≠ b2 → eq_block b1 b2 = false.
700#b1 #b2 * #Hb
701@(eq_block_elim … b1 b2)
702[ 1: #Habsurd @(False_ind … (Hb Habsurd))
703| 2: // ] qed.
704
705(* --------------------------------------------------------------------------- *)   
706(* Lemmas related to freeing memory and pointer validity. *)
707(* --------------------------------------------------------------------------- *)   
708(*
709lemma nextblock_free_ok : ∀m,b. nextblock m = nextblock (free m b).
710* #contents #next #posnext * #rg #id
711normalize @refl
712qed.
713
714lemma low_bound_free_ok : ∀m,b,ptr.
715   b ≠ (pblock ptr) →
716   Zleb (low_bound (free m b) (pblock ptr)) (Z_of_unsigned_bitvector offset_size (offv (poff ptr))) =
717   Zleb (low_bound m (pblock ptr)) (Z_of_unsigned_bitvector offset_size (offv (poff ptr))).
718* #contents #next #nextpos * #brg #bid * * #prg #pid #poff normalize
719cases prg cases brg normalize nodelta try //
720@(eqZb_elim pid bid)
721[ 1,3: #Heq >Heq * #Habsurd @(False_ind … (Habsurd (refl ??)))
722| 2,4: #_ #_ @refl
723] qed.
724
725lemma high_bound_free_ok : ∀m,b,ptr.
726   b ≠ (pblock ptr) →
727   Zleb (Z_of_unsigned_bitvector offset_size (offv (poff ptr))) (high_bound (free m b) (pblock ptr)) =
728   Zleb (Z_of_unsigned_bitvector offset_size (offv (poff ptr))) (high_bound m (pblock ptr)).
729* #contents #next #nextpos * #brg #bid * * #prg #pid #poff normalize
730cases prg cases brg normalize nodelta try //
731@(eqZb_elim pid bid)
732[ 1,3: #Heq >Heq * #Habsurd @(False_ind … (Habsurd (refl ??)))
733| 2,4: #_ #_ @refl
734] qed.
735
736lemma valid_pointer_free_ok : ∀b : block. ∀m,ptr.
737   valid_pointer m ptr = true →
738   pblock ptr ≠ b →
739   valid_pointer (free m b) ptr = true.
740* #br #bid * #contents #next #posnext * * #pbr #pbid #poff
741normalize
742@(eqZb_elim pbid bid)
743[ 1: #Heqid >Heqid cases pbr cases br normalize
744     [ 1,4: #_ * #Habsurd @(False_ind … (Habsurd (refl ??))) ]
745     cases (Zltb bid next) normalize nodelta
746     [ 2,4: #Habsurd destruct (Habsurd) ]
747     //
748| 2: #Hneqid cases pbr cases br normalize try // ]
749qed.
750
751lemma valid_pointer_free_list_ok : ∀blocks : list block. ∀m,ptr.
752   valid_pointer m ptr = true →
753   ¬ mem ? (pblock ptr) blocks →
754   valid_pointer (free_list m blocks) ptr = true.
755#blocks
756elim blocks
757[ 1: #m #ptr normalize #H #_ @H
758| 2: #b #tl #Hind #m #ptr #Hvalid
759     whd in match (mem block (pblock ptr) ?);
760     >free_list_cons * #Hguard
761     @valid_pointer_free_ok
762     [ 2: % #Heq @Hguard %1 @Heq ]
763     @Hind
764     [ 1: @Hvalid
765     | 2: % #Hmem @Hguard %2 @Hmem ]
766] qed. *)
767
768lemma valid_pointer_ok_free : ∀b : block. ∀m,ptr.
769   valid_pointer m ptr = true →
770   pblock ptr ≠ b →
771   valid_pointer (free m b) ptr = true.
772* #br #bid * #contents #next #posnext * * #pbr #pbid #poff
773normalize
774@(eqZb_elim pbid bid)
775[ 1: #Heqid >Heqid cases pbr cases br normalize
776     [ 1,4: #_ * #Habsurd @(False_ind … (Habsurd (refl ??))) ]
777     cases (Zltb bid next) normalize nodelta
778     [ 2,4: #Habsurd destruct (Habsurd) ]
779     //
780| 2: #Hneqid cases pbr cases br normalize try // ]
781qed.
782
783lemma free_list_cons : ∀m,b,tl. free_list m (b :: tl) = (free (free_list m tl) b).
784#m #b #tl whd in match (free_list ??) in ⊢ (??%%);
785whd in match (free ??); @refl qed.
786
787lemma valid_pointer_free_ok : ∀b : block. ∀m,ptr.
788   valid_pointer (free m b) ptr = true →
789   pblock ptr ≠ b → (* This hypothesis is necessary to handle the cse of "valid" pointers to empty  *)
790   valid_pointer m ptr = true.
791* #br #bid * #contents #next #posnext * * #pbr #pbid #poff
792@(eqZb_elim pbid bid)
793[ 1: #Heqid >Heqid
794     cases pbr cases br normalize
795     [ 1,4: #_ * #Habsurd @(False_ind … (Habsurd (refl ??))) ]
796     cases (Zltb bid next) normalize nodelta
797     [ 2,4: #Habsurd destruct (Habsurd) ]
798     //
799| 2: #Hneqid cases pbr cases br normalize try //
800     >(eqZb_false … Hneqid) normalize nodelta try //
801qed.
802
803lemma valid_pointer_free_list_ok : ∀blocks : list block. ∀m,ptr.
804   valid_pointer (free_list m blocks) ptr = true →
805   ¬ mem ? (pblock ptr) blocks →
806   valid_pointer m ptr = true.
807#blocks
808elim blocks
809[ 1: #m #ptr normalize #H #_ @H
810| 2: #b #tl #Hind #m #ptr #Hvalid
811     whd in match (mem block (pblock ptr) ?);
812     >free_list_cons in Hvalid; #Hvalid * #Hguard
813     lapply (valid_pointer_free_ok … Hvalid) #H
814     @Hind
815     [ 2: % #Heq @Hguard %2 @Heq
816     | 1: @H % #Heq @Hguard %1 @Heq ]
817] qed.
818
819(* An alternative version without the gard on the equality of blocks. *)
820lemma valid_pointer_free_ok_alt : ∀b : block. ∀m,ptr.
821   valid_pointer (free m b) ptr = true →
822   (pblock ptr) = b ∨ (pblock ptr ≠ b ∧ valid_pointer m ptr = true).
823* #br #bid * #contents #next #posnext * * #pbr #pbid #poff
824@(eq_block_elim … (mk_block br bid) (mk_block pbr pbid))
825[ 1: #Heq #_ %1 @(sym_eq … Heq)
826| 2: cases pbr cases br normalize nodelta
827     [ 1,4: @(eqZb_elim pbid bid)
828         [ 1,3: #Heq >Heq * #H @(False_ind … (H (refl ??)))
829         | 2,4: #Hneq #_ normalize >(eqZb_false … Hneq) normalize nodelta
830                 #H %2 @conj try assumption
831                 % #Habsurd destruct (Habsurd) elim Hneq #Hneq @Hneq try @refl
832         ]
833     | *: #_ #H %2 @conj try @H % #Habsurd destruct (Habsurd) ]
834] qed.     
835
836(* Well in fact a valid pointer can be valid even after a free. Ah. *)
837(*
838lemma pointer_in_free_list_not_valid : ∀blocks,m,ptr.
839  mem ? (pblock ptr) blocks →
840  valid_pointer (free_list m blocks) ptr = false.
841*)
842(*
843#blocks elim blocks
844[ 1: #m #ptr normalize #Habsurd @(False_ind … Habsurd)
845| 2: #b #tl #Hind #m #ptr
846     whd in match (mem block (pblock ptr) ?);
847     >free_list_cons
848     *
849     [ 1: #Hptr_match whd in match (free ??);
850          whd in match (update_block ????);
851          whd in match (valid_pointer ??);
852          whd in match (low_bound ??);
853          whd in match (high_bound ??);
854          >Hptr_match >eq_block_identity normalize nodelta
855          whd in match (low ?);
856          cut (Zleb OZ (Z_of_unsigned_bitvector offset_size (offv (poff ptr))) = true)
857          [ 1: elim (offv (poff ptr)) //
858               #n' #hd #tl cases hd normalize
859               [ 1: #_ try @refl
860               | 2: #H @H ] ]
861          #H >H
862          cut (Zleb (Z_of_unsigned_bitvector offset_size (offv (poff ptr))) OZ = false)
863          [ 1: elim (offv (poff ptr)) normalize
864               #n' #hd #tl cases hd normalize
865               [ 1: normalize #_ try @refl
866               | 2: #H @H ] ]
867  valid_pointer (free_list m blocks) ptr = false.
868*)
869
870
871(* --------------------------------------------------------------------------- *)   
872(* Memory injections *)
873(* --------------------------------------------------------------------------- *)   
874
875(* An embedding is a function from blocks to (blocks × offset). *)
876definition embedding ≝ block → option (block × offset).
877
878definition offset_plus : offset → offset → offset ≝
879  λo1,o2. mk_offset (addition_n ? (offv o1) (offv o2)).
880
881lemma offset_plus_0 : ∀o. offset_plus o (mk_offset (zero ?)) = o.
882* #o
883whd in match (offset_plus ??);
884>addition_n_0 @refl
885qed.
886
887(* Translates a pointer through an embedding. *)
888definition pointer_translation : ∀p:pointer. ∀E:embedding. option pointer ≝
889λp,E.
890match p with
891[ mk_pointer pblock poff ⇒
892   match E pblock with
893   [ None ⇒ None ?
894   | Some loc ⇒
895    let 〈dest_block,dest_off〉 ≝ loc in
896    let ptr ≝ (mk_pointer dest_block (offset_plus poff dest_off)) in
897    Some ? ptr
898   ]
899].
900
901(* We parameterise the "equivalence" relation on values with an embedding. *)
902(* Front-end values. *)
903inductive value_eq (E : embedding) : val → val → Prop ≝
904| undef_eq : ∀v.
905  value_eq E Vundef v
906| vint_eq : ∀sz,i.
907  value_eq E (Vint sz i) (Vint sz i)
908| vfloat_eq : ∀f.
909  value_eq E (Vfloat f) (Vfloat f)
910| vnull_eq :
911  value_eq E Vnull Vnull
912| vptr_eq : ∀p1,p2.
913  pointer_translation p1 E = Some ? p2 →
914  value_eq E (Vptr p1) (Vptr p2).
915 
916(* [load_sim] states the fact that each successful load in [m1] is matched by a load in [m2] s.t.
917 * the values are equivalent. *)
918definition load_sim ≝
919λ(E : embedding).λ(m1 : mem).λ(m2 : mem).
920 ∀b1,off1,b2,off2,ty,v1.
921  valid_block m1 b1 →  (* We need this because it is not provable from [load_value_of_type ty m1 b1 off1] when loading by-ref *)
922  E b1 = Some ? 〈b2,off2〉 →
923  load_value_of_type ty m1 b1 off1 = Some ? v1 →
924  (∃v2. load_value_of_type ty m2 b2 (offset_plus off1 off2) = Some ? v2 ∧ value_eq E v1 v2).
925 
926definition load_sim_ptr ≝
927λ(E : embedding).λ(m1 : mem).λ(m2 : mem).
928 ∀b1,off1,b2,off2,ty,v1.
929  valid_pointer m1 (mk_pointer b1 off1) = true →  (* We need this because it is not provable from [load_value_of_type ty m1 b1 off1] when loading by-ref *)
930  pointer_translation (mk_pointer b1 off1) E = Some ? (mk_pointer b2 off2) →
931  load_value_of_type ty m1 b1 off1 = Some ? v1 →
932  (∃v2. load_value_of_type ty m2 b2 off2 = Some ? v2 ∧ value_eq E v1 v2).
933
934(* Definition of a memory injection *)
935record memory_inj (E : embedding) (m1 : mem) (m2 : mem) : Type[0] ≝
936{ (* Load simulation *)
937  mi_inj : load_sim_ptr E m1 m2;
938  (* Invalid blocks are not mapped *)
939  mi_freeblock : ∀b. ¬ (valid_block m1 b) → E b = None ?;
940  (* Valid pointers are mapped to valid pointers*)
941  mi_valid_pointers : ∀p,p'.
942                       valid_pointer m1 p = true →
943                       pointer_translation p E = Some ? p' →
944                       valid_pointer m2 p' = true;
945  (* Blocks in the codomain are valid *)
946  (* mi_incl : ∀b,b',o'. E b = Some ? 〈b',o'〉 → valid_block m2 b'; *)
947  (* Regions are preserved *)
948  mi_region : ∀b,b',o'. E b = Some ? 〈b',o'〉 → block_region b = block_region b';
949  (* Disjoint blocks are mapped to disjoint blocks. Note that our condition is stronger than compcert's.
950   * This may cause some problems if we reuse this def for the translation from Clight to Cminor, where
951   * all variables are allocated in the same block. *)
952  mi_disjoint : ∀b1,b2,b1',b2',o1',o2'.
953                b1 ≠ b2 →
954                E b1 = Some ? 〈b1',o1'〉 →
955                E b2 = Some ? 〈b2',o2'〉 →
956                b1' ≠ b2'
957}.
958
959(* Definition of a memory extension. /!\ Not equivalent to the compcert concept. /!\
960 * A memory extension is a [memory_inj] with some particular blocks designated as
961 * being writeable. *)
962
963alias id "meml" = "cic:/matita/basics/lists/list/mem.fix(0,2,1)".
964
965record memory_ext (E : embedding) (m1 : mem) (m2 : mem) : Type[0] ≝
966{ me_inj : memory_inj E m1 m2;
967  (* A list of blocks where we can write freely *)
968  me_writeable : list block;
969  (* These blocks are valid *)
970  me_writeable_valid : ∀b. meml ? b me_writeable → valid_block m2 b;
971  (* And pointers to m1 are oblivious to these blocks *)
972  me_writeable_ok : ∀p,p'.
973                     valid_pointer m1 p = true →
974                     pointer_translation p E = Some ? p' →
975                     ¬ (meml ? (pblock p') me_writeable)
976}.
977
978(* ---------------------------------------------------------------------------- *)
979(* End of the definitions on memory injections. Now, on to proving some lemmas. *)
980
981(* A particular inversion. *)
982lemma value_eq_ptr_inversion :
983  ∀E,p1,v. value_eq E (Vptr p1) v → ∃p2. v = Vptr p2 ∧ pointer_translation p1 E = Some ? p2.
984#E #p1 #v #Heq inversion Heq
985[ 1: #v #Habsurd destruct (Habsurd)
986| 2: #sz #i #Habsurd destruct (Habsurd)
987| 3: #f #Habsurd destruct (Habsurd)
988| 4:  #Habsurd destruct (Habsurd)
989| 5: #p1' #p2 #Heq #Heqv #Heqv2 #_ destruct
990     %{p2} @conj try @refl try assumption
991] qed.
992
993(* A cleaner version of inversion for [value_eq] *)
994lemma value_eq_inversion :
995  ∀E,v1,v2. ∀P : val → val → Prop. value_eq E v1 v2 →
996  (∀v. P Vundef v) →
997  (∀sz,i. P (Vint sz i) (Vint sz i)) →
998  (∀f. P (Vfloat f) (Vfloat f)) →
999  (P Vnull Vnull) →
1000  (∀p1,p2. pointer_translation p1 E = Some ? p2 → P (Vptr p1) (Vptr p2)) →
1001  P v1 v2.
1002#E #v1 #v2 #P #Heq #H1 #H2 #H3 #H4 #H5
1003inversion Heq
1004[ 1: #v #Hv1 #Hv2 #_ destruct @H1
1005| 2: #sz #i #Hv1 #Hv2 #_ destruct @H2
1006| 3: #f #Hv1 #Hv2 #_ destruct @H3
1007| 4: #Hv1 #Hv2 #_ destruct @H4
1008| 5: #p1 #p2 #Hembed #Hv1 #Hv2 #_ destruct @H5 // ] qed.
1009 
1010(* If we succeed to load something by value from a 〈b,off〉 location,
1011   [b] is a valid block. *)
1012lemma load_by_value_success_valid_block_aux :
1013  ∀ty,m,b,off,v.
1014    access_mode ty = By_value (typ_of_type ty) →
1015    load_value_of_type ty m b off = Some ? v →
1016    Zltb (block_id b) (nextblock m) = true.
1017#ty #m * #brg #bid #off #v
1018cases ty
1019[ 1: | 2: #sz #sg | 3: #fsz | 4: #ptr_ty | 5: #array_ty #array_sz | 6: #domain #codomain
1020| 7: #structname #fieldspec | 8: #unionname #fieldspec | 9: #id ]
1021whd in match (load_value_of_type ????);
1022[ 1,7,8: #_ #Habsurd destruct (Habsurd) ]
1023#Hmode
1024[ 1,2,3,6: [ 1: elim sz | 2: elim fsz ]
1025     normalize in match (typesize ?);
1026     whd in match (loadn ???);
1027     whd in match (beloadv ??);
1028     cases (Zltb bid (nextblock m)) normalize nodelta
1029     try // #Habsurd destruct (Habsurd)
1030| *: normalize in Hmode; destruct (Hmode)
1031] qed.
1032
1033(* If we succeed in loading some data from a location, then this loc is a valid pointer. *)
1034lemma load_by_value_success_valid_ptr_aux :
1035  ∀ty,m,b,off,v.
1036    access_mode ty = By_value (typ_of_type ty) →
1037    load_value_of_type ty m b off = Some ? v →
1038    Zltb (block_id b) (nextblock m) = true ∧
1039    Zleb (low_bound m b) (Z_of_unsigned_bitvector ? (offv off)) = true ∧
1040    Zltb (Z_of_unsigned_bitvector ? (offv off)) (high_bound m b) = true.
1041#ty #m * #brg #bid #off #v
1042cases ty
1043[ 1: | 2: #sz #sg | 3: #fsz | 4: #ptr_ty | 5: #array_ty #array_sz | 6: #domain #codomain
1044| 7: #structname #fieldspec | 8: #unionname #fieldspec | 9: #id ]
1045whd in match (load_value_of_type ????);
1046[ 1,7,8: #_ #Habsurd destruct (Habsurd) ]
1047#Hmode
1048[ 1,2,3,6: [ 1: elim sz | 2: elim fsz ]
1049     normalize in match (typesize ?);
1050     whd in match (loadn ???);
1051     whd in match (beloadv ??);
1052     cases (Zltb bid (nextblock m)) normalize nodelta
1053     cases (Zleb (low (blocks m (mk_block brg bid)))
1054                  (Z_of_unsigned_bitvector offset_size (offv off)))
1055     cases (Zltb (Z_of_unsigned_bitvector offset_size (offv off)) (high (blocks m (mk_block brg bid))))
1056     normalize nodelta
1057     #Heq destruct (Heq)
1058     try /3 by conj, refl/
1059| *: normalize in Hmode; destruct (Hmode)
1060] qed.
1061
1062
1063lemma valid_block_from_bool : ∀b,m. Zltb (block_id b) (nextblock m) = true → valid_block m b.
1064* #rg #id #m normalize
1065elim id /2/ qed.
1066
1067lemma valid_block_to_bool : ∀b,m. valid_block m b → Zltb (block_id b) (nextblock m) = true.
1068* #rg #id #m normalize
1069elim id /2/ qed.
1070
1071lemma load_by_value_success_valid_block :
1072  ∀ty,m,b,off,v.
1073    access_mode ty = By_value (typ_of_type ty) →
1074    load_value_of_type ty m b off = Some ? v →
1075    valid_block m b.
1076#ty #m #b #off #v #Haccess_mode #Hload
1077@valid_block_from_bool
1078elim (load_by_value_success_valid_ptr_aux ty m b off v Haccess_mode Hload) * //
1079qed.
1080
1081lemma load_by_value_success_valid_pointer :
1082  ∀ty,m,b,off,v.
1083    access_mode ty = By_value (typ_of_type ty) →
1084    load_value_of_type ty m b off = Some ? v →
1085    valid_pointer m (mk_pointer b off).
1086#ty #m #b #off #v #Haccess_mode #Hload normalize
1087elim (load_by_value_success_valid_ptr_aux ty m b off v Haccess_mode Hload)
1088* #H1 #H2 #H3 >H1 >H2 normalize nodelta
1089>Zle_to_Zleb_true try //
1090lapply (Zlt_to_Zle … (Zltb_true_to_Zlt … H3)) /2/
1091qed.
1092
1093
1094(* Making explicit the contents of memory_inj for load_value_of_type *)
1095lemma load_value_of_type_inj : ∀E,m1,m2,b1,off1,v1,b2,off2,ty.
1096    memory_inj E m1 m2 →
1097    value_eq E (Vptr (mk_pointer b1 off1)) (Vptr (mk_pointer b2 off2)) →
1098    load_value_of_type ty m1 b1 off1 = Some ? v1 →
1099    ∃v2. load_value_of_type ty m2 b2 off2 = Some ? v2 ∧ value_eq E v1 v2.
1100#E #m1 #m2 #b1 #off1 #v1 #b2 #off2 #ty #Hinj #Hvalue_eq
1101lapply (value_eq_ptr_inversion … Hvalue_eq) * #p2 * #Hp2_eq #Hembed destruct
1102lapply (refl ? (access_mode ty))
1103cases ty
1104[ 1: | 2: #sz #sg | 3: #fsz | 4: #ptr_ty | 5: #array_ty #array_sz | 6: #domain #codomain
1105| 7: #structname #fieldspec | 8: #unionname #fieldspec | 9: #id ]
1106normalize in ⊢ ((???%) → ?); #Hmode #Hyp
1107[ 1,7,8: normalize in Hyp; destruct (Hyp)
1108| 5,6: normalize in Hyp ⊢ %; destruct (Hyp) /3 by ex_intro, conj, vptr_eq/ ]
1109lapply (load_by_value_success_valid_pointer … Hmode … Hyp) #Hvalid_pointer
1110lapply (mi_inj … Hinj b1 off1 b2 off2 … Hvalid_pointer Hembed Hyp) #H @H
1111qed.     
1112
1113(* -------------------------------------- *)
1114(* Lemmas pertaining to memory allocation *)
1115
1116(* A valid block stays valid after an alloc. *)
1117lemma alloc_valid_block_conservation :
1118  ∀m,m',z1,z2,r,new_block.
1119  alloc m z1 z2 r = 〈m', new_block〉 →
1120  ∀b. valid_block m b → valid_block m' b.
1121#m #m' #z1 #z2 #r * #b' #Hregion_eq
1122elim m #contents #nextblock #Hcorrect whd in match (alloc ????);
1123#Halloc destruct (Halloc)
1124#b whd in match (valid_block ??) in ⊢ (% → %); /2/
1125qed.
1126
1127(* Allocating a new zone produces a valid block. *)
1128lemma alloc_valid_new_block :
1129  ∀m,m',z1,z2,r,new_block.
1130  alloc m z1 z2 r = 〈m', new_block〉 →
1131  valid_block m' new_block.
1132* #contents #nextblock #Hcorrect #m' #z1 #z2 #r * #new_block #Hregion_eq
1133whd in match (alloc ????); whd in match (valid_block ??);
1134#Halloc destruct (Halloc) /2/
1135qed.
1136
1137(* All data in a valid block is unchanged after an alloc. *)
1138lemma alloc_beloadv_conservation :
1139  ∀m,m',block,offset,z1,z2,r,new_block.
1140    valid_block m block →
1141    alloc m z1 z2 r = 〈m', new_block〉 →
1142    beloadv m (mk_pointer block offset) = beloadv m' (mk_pointer block offset).
1143* #contents #next #Hcorrect #m' #block #offset #z1 #z2 #r #new_block #Hvalid #Halloc
1144whd in Halloc:(??%?); destruct (Halloc)
1145whd in match (beloadv ??) in ⊢ (??%%);
1146lapply (valid_block_to_bool … Hvalid) #Hlt
1147>Hlt >(zlt_succ … Hlt)
1148normalize nodelta whd in match (update_block ?????); whd in match (eq_block ??);
1149cut (eqZb (block_id block) next = false)
1150[ lapply (Zltb_true_to_Zlt … Hlt) #Hlt' @eqZb_false /2/ ] #Hneq
1151>Hneq cases (eq_region ??) normalize nodelta  @refl
1152qed.
1153
1154(* Lift [alloc_beloadv_conservation] to loadn *)
1155lemma alloc_loadn_conservation :
1156  ∀m,m',z1,z2,r,new_block.
1157    alloc m z1 z2 r = 〈m', new_block〉 →
1158    ∀n. ∀block,offset.
1159    valid_block m block →
1160    loadn m (mk_pointer block offset) n = loadn m' (mk_pointer block offset) n.
1161#m #m' #z1 #z2 #r #new_block #Halloc #n
1162elim n try //
1163#n' #Hind #block #offset #Hvalid_block
1164whd in ⊢ (??%%);
1165>(alloc_beloadv_conservation … Hvalid_block Halloc)
1166cases (beloadv m' (mk_pointer block offset)) //
1167#bev normalize nodelta
1168whd in match (shift_pointer ???); >Hind try //
1169qed.
1170
1171(* Memory allocation preserves [memory_inj] *)
1172lemma alloc_memory_inj :
1173  ∀E:embedding.∀m1,m2,m2',z1,z2,r,new_block. ∀H:memory_inj E m1 m2.
1174  alloc m2 z1 z2 r = 〈m2', new_block〉 →
1175  memory_inj E m1 m2'.
1176#E #m1 #m2 #m2' #z1 #z2 #r * #new_block #Hregion #Hmemory_inj #Halloc
1177%
1178[ 1:
1179  whd
1180  #b1 #off1 #b2 #off2 #ty #v1 #Hvalid #Hembed #Hload
1181  elim (mi_inj E m1 m2 Hmemory_inj b1 off1 b2 off2 … ty v1 Hvalid Hembed Hload)
1182  #v2 * #Hload_eq #Hvalue_eq %{v2} @conj try //
1183  lapply (refl ? (access_mode ty))
1184  cases ty in Hload_eq;
1185  [ 1: | 2: #sz #sg | 3: #fsz | 4: #ptr_ty | 5: #array_ty #array_sz | 6: #domain #codomain
1186  | 7: #structname #fieldspec | 8: #unionname #fieldspec | 9: #id ]
1187  #Hload normalize in ⊢ ((???%) → ?); #Haccess
1188  [ 1,7,8: normalize in Hload; destruct (Hload)
1189  | 2,3,4,9: whd in match (load_value_of_type ????);
1190     whd in match (load_value_of_type ????);
1191     lapply (load_by_value_success_valid_block … Haccess Hload)
1192     #Hvalid_block
1193     whd in match (load_value_of_type ????) in Hload;
1194     <(alloc_loadn_conservation … Halloc … Hvalid_block)
1195     @Hload
1196  | 5,6: whd in match (load_value_of_type ????) in Hload ⊢ %; @Hload ]
1197| 2: @(mi_freeblock … Hmemory_inj)
1198| 3: #p #p' #Hvalid #Hptr_trans lapply (mi_valid_pointers … Hmemory_inj p p' Hvalid Hptr_trans)
1199     elim m2 in Halloc; #contentmap #nextblock #Hnextblock
1200     elim p' * #br' #bid' #o' #Halloc whd in Halloc:(??%?) ⊢ ?; destruct (Halloc)
1201     whd in match (valid_pointer ??) in ⊢ (% → %);
1202     @Zltb_elim_Type0
1203     [ 2: normalize #_ #Habsurd destruct (Habsurd) ]
1204     #Hbid' cut (Zltb bid' (Zsucc nextblock) = true) [ lapply (Zlt_to_Zltb_true … Hbid') @zlt_succ ]
1205     #Hbid_succ >Hbid_succ whd in match (low_bound ??) in ⊢ (% → %);
1206     whd in match (high_bound ??) in ⊢ (% → %);
1207     whd in match (update_block ?????);
1208     whd in match (eq_block ??);
1209     cut (eqZb bid' nextblock = false) [ 1: @eqZb_false /2 by not_to_not/ ]
1210     #Hbid_neq >Hbid_neq
1211     cases (eq_region br' r) normalize #H @H
1212| 4: @(mi_region … Hmemory_inj)
1213| 5: @(mi_disjoint … Hmemory_inj)
1214] qed.
1215
1216(* Memory allocation induces a memory extension. *)
1217lemma alloc_memory_ext :
1218  ∀E:embedding.∀m1,m2,m2',z1,z2,r,new_block. ∀H:memory_inj E m1 m2.
1219  alloc m2 z1 z2 r = 〈m2', new_block〉 →
1220  memory_ext E m1 m2'.
1221#E #m1 #m2 #m2' #z1 #z2 #r * #new_block #Hblock_region_eq #Hmemory_inj #Halloc
1222lapply (alloc_memory_inj … Hmemory_inj Halloc)
1223#Hinj' %
1224[ 1: @Hinj'
1225| 2: @[new_block]
1226| 3: #b normalize in ⊢ (%→ ?); * [ 2: #H @(False_ind … H) ]
1227      #Heq destruct (Heq) whd elim m2 in Halloc;
1228      #Hcontents #nextblock #Hnextblock
1229      whd in ⊢ ((??%?) → ?); #Heq destruct (Heq)
1230      /2/
1231| 4: * #b #o * #b' #o' #Hvalid_ptr #Hembed %
1232     normalize in ⊢ (% → ?); * [ 2: #H @H ]
1233     #Heq destruct (Heq)
1234     lapply (mi_valid_pointers … Hmemory_inj … Hvalid_ptr Hembed)
1235     whd in ⊢ (% → ?);
1236     (* contradiction because ¬ (valid_block m2 new_block)  *)
1237     elim m2 in Halloc;
1238     #contents_m2 #nextblock_m2 #Hnextblock_m2
1239     whd in ⊢ ((??%?) → ?);
1240     #Heq_alloc destruct (Heq_alloc)
1241     normalize
1242     lapply (irreflexive_Zlt nextblock_m2)
1243     @Zltb_elim_Type0
1244     [ #H * #Habsurd @(False_ind … (Habsurd H)) ] #_ #_ normalize #Habsurd destruct (Habsurd)
1245] qed.
1246
1247lemma bestorev_beloadv_conservation :
1248  ∀mA,mB,wb,wo,v.
1249    bestorev mA (mk_pointer wb wo) v = Some ? mB →
1250    ∀rb,ro. eq_block wb rb = false →
1251    beloadv mA (mk_pointer rb ro) = beloadv mB (mk_pointer rb ro).
1252#mA #mB #wb #wo #v #Hstore #rb #ro #Hblock_neq
1253whd in ⊢ (??%%);
1254elim mB in Hstore; #contentsB #nextblockB #HnextblockB
1255normalize in ⊢ (% → ?);
1256cases (Zltb (block_id wb) (nextblock mA)) normalize nodelta
1257[ 2: #Habsurd destruct (Habsurd) ]
1258cases (if Zleb (low (blocks mA wb)) (Z_of_unsigned_bitvector 16 (offv wo))
1259       then Zltb (Z_of_unsigned_bitvector 16 (offv wo)) (high (blocks mA wb)) 
1260       else false) normalize nodelta
1261[ 2: #Habsurd destruct (Habsurd) ]
1262#Heq destruct (Heq) elim rb in Hblock_neq; #rr #rid elim wb #wr #wid
1263cases rr cases wr normalize try //
1264@(eqZb_elim … rid wid)
1265[ 1,3: #Heq destruct (Heq) >(eqZb_reflexive wid) #Habsurd destruct (Habsurd) ]
1266try //
1267qed.
1268
1269(* lift [bestorev_beloadv_conservation to [loadn] *)
1270lemma bestorev_loadn_conservation :
1271  ∀mA,mB,n,wb,wo,v.
1272    bestorev mA (mk_pointer wb wo) v = Some ? mB →
1273    ∀rb,ro. eq_block wb rb = false →
1274    loadn mA (mk_pointer rb ro) n = loadn mB (mk_pointer rb ro) n.
1275#mA #mB #n
1276elim n
1277[ 1: #wb #wo #v #Hstore #rb #ro #Hblock_neq normalize @refl
1278| 2: #n' #Hind #wb #wo #v #Hstore #rb #ro #Hneq
1279     whd in ⊢ (??%%);
1280     >(bestorev_beloadv_conservation … Hstore … Hneq)
1281     >(Hind … Hstore … Hneq) @refl
1282] qed.
1283
1284(* lift [bestorev_loadn_conservation] to [load_value_of_type] *)
1285lemma bestorev_load_value_of_type_conservation :
1286  ∀mA,mB,wb,wo,v.
1287    bestorev mA (mk_pointer wb wo) v = Some ? mB →
1288    ∀rb,ro. eq_block wb rb = false →
1289    ∀ty.load_value_of_type ty mA rb ro = load_value_of_type ty mB rb ro.
1290#mA #mB #wb #wo #v #Hstore #rb #ro #Hneq #ty
1291cases ty
1292[ 1: | 2: #sz #sg | 3: #fsz | 4: #ptr_ty | 5: #array_ty #array_sz | 6: #domain #codomain
1293| 7: #structname #fieldspec | 8: #unionname #fieldspec | 9: #id ] try //
1294[ 1: elim sz | 2: elim fsz | 3: | 4: ]
1295whd in ⊢ (??%%);
1296>(bestorev_loadn_conservation … Hstore … Hneq) @refl
1297qed.
1298
1299(* Writing in the "extended" part of a memory preserves the underlying injection *)
1300lemma bestorev_memory_ext_to_load_sim :
1301  ∀E,mA,mB,mC.
1302  ∀Hext:memory_ext E mA mB.
1303  ∀wb,wo,v. meml ? wb (me_writeable … Hext) →
1304  bestorev mB (mk_pointer wb wo) v = Some ? mC →
1305  load_sim_ptr E mA mC.
1306#E #mA #mB #mC #Hext #wb #wo #v #Hwb #Hstore whd
1307#b1 #off1 #b2 #off2 #ty #v1 #Hvalid #Hembed #Hload
1308(* Show that (wb ≠ b2) by showing b2 ∉ (me_writeable ...) *)
1309lapply (me_writeable_ok … Hext (mk_pointer b1 off1) (mk_pointer b2 off2) Hvalid Hembed) #Hb2
1310lapply (mem_not_mem_neq … Hwb Hb2) #Hwb_neq_b2
1311cut ((eq_block wb b2) = false) [ @neq_block_eq_block_false @Hwb_neq_b2 ] #Heq_block_false
1312<(bestorev_load_value_of_type_conservation … Hstore … Heq_block_false)
1313@(mi_inj … (me_inj … Hext) … Hvalid  … Hembed …  Hload)
1314qed.
1315
1316(* Writing in the "extended" part of a memory preserves the whole memory injection *)
1317lemma bestorev_memory_ext_to_memory_inj :
1318  ∀E,mA,mB,mC.
1319  ∀Hext:memory_ext E mA mB.
1320  ∀wb,wo,v. meml ? wb (me_writeable … Hext) →
1321  bestorev mB (mk_pointer wb wo) v = Some ? mC →
1322  memory_inj E mA mC.
1323#E #mA * #contentsB #nextblockB #HnextblockB #mC
1324#Hext #wb #wo #v #Hwb #Hstore
1325%
1326[ 1: @(bestorev_memory_ext_to_load_sim … Hext … Hwb Hstore) ]
1327elim Hext in Hwb; * #Hinj #Hvalid #Hcodomain #Hregion #Hdisjoint #writeable #Hwriteable_valid #Hwriteable_ok
1328#Hmem
1329[ 1: @Hvalid | 3: @Hregion | 4: @Hdisjoint ] -Hvalid -Hregion -Hdisjoint
1330whd in Hstore:(??%?); lapply (Hwriteable_valid … Hmem)
1331normalize in ⊢ (% → ?); #Hlt_wb
1332#p #p' #HvalidA #Hembed lapply (Hcodomain … HvalidA Hembed) -Hcodomain
1333normalize in match (valid_pointer ??) in ⊢ (% → %);
1334>(Zlt_to_Zltb_true … Hlt_wb) in Hstore; normalize nodelta
1335cases (Zleb (low (contentsB wb)) (Z_of_unsigned_bitvector offset_size (offv wo))
1336       ∧Zltb (Z_of_unsigned_bitvector offset_size (offv wo)) (high (contentsB wb)))
1337normalize nodelta
1338[ 2: #Habsurd destruct (Habsurd) ]
1339#Heq destruct (Heq)
1340cases (Zltb (block_id (pblock p')) nextblockB) normalize nodelta
1341[ 2: #H @H ]
1342whd in match (update_block ?????);
1343cut (eq_block (pblock p') wb = false)
1344[ 2: #Heq >Heq normalize nodelta #H @H ]
1345@neq_block_eq_block_false @sym_neq
1346@(mem_not_mem_neq writeable … Hmem)
1347@(Hwriteable_ok … HvalidA Hembed)
1348qed.
1349
1350(* It even preserves memory extensions, with the same writeable blocks.  *)
1351lemma bestorev_memory_ext_to_memory_ext :
1352  ∀E,mA,mB.
1353  ∀Hext:memory_ext E mA mB.
1354  ∀wb,wo,v. meml ? wb (me_writeable … Hext) →
1355  ∀mC.bestorev mB (mk_pointer wb wo) v = Some ? mC →
1356  ΣExt:memory_ext E mA mC.(me_writeable … Hext = me_writeable … Ext).
1357#E #mA #mB #Hext #wb #wo #v #Hmem #mC #Hstore
1358%{(mk_memory_ext …
1359      (bestorev_memory_ext_to_memory_inj … Hext … Hmem … Hstore)
1360      (me_writeable … Hext)
1361      ?
1362      (me_writeable_ok … Hext)
1363 )} try @refl
1364#b #Hmemb
1365lapply (me_writeable_valid … Hext b Hmemb)
1366lapply (me_writeable_valid … Hext wb Hmem)
1367elim mB in Hstore; #contentsB #nextblockB #HnextblockB #Hstore #Hwb_valid #Hb_valid
1368lapply Hstore normalize in Hwb_valid Hb_valid ⊢ (% → ?);
1369>(Zlt_to_Zltb_true … Hwb_valid) normalize nodelta
1370cases (if Zleb (low (contentsB wb)) (Z_of_unsigned_bitvector 16 (offv wo))
1371       then Zltb (Z_of_unsigned_bitvector 16 (offv wo)) (high (contentsB wb)) 
1372       else false)
1373normalize [ 2: #Habsurd destruct (Habsurd) ]
1374#Heq destruct (Heq) @Hb_valid
1375qed.
1376
1377(* Lift [bestorev_memory_ext_to_memory_ext] to storen *)
1378lemma storen_memory_ext_to_memory_ext :
1379  ∀E,mA,l,mB,mC.
1380  ∀Hext:memory_ext E mA mB.
1381  ∀wb,wo. meml ? wb (me_writeable … Hext) →
1382  storen mB (mk_pointer wb wo) l = Some ? mC →
1383  memory_ext E mA mC.
1384#E #mA #l elim l
1385[ 1: #mB #mC #Hext #wb #wo #Hmem normalize in ⊢ (% → ?); #Heq destruct (Heq)
1386     @Hext
1387| 2: #hd #tl #Hind #mB #mC #Hext #wb #wo #Hmem
1388     whd in ⊢ ((??%?) → ?);
1389     lapply (bestorev_memory_ext_to_memory_ext … Hext … wb wo hd Hmem)
1390     cases (bestorev mB (mk_pointer wb wo) hd)
1391     normalize nodelta
1392     [ 1: #H #Habsurd destruct (Habsurd) ]
1393     #mD #H lapply (H mD (refl ??)) * #HextD #Heq #Hstore
1394     @(Hind … HextD … Hstore)
1395     <Heq @Hmem
1396] qed.     
1397
1398(* Lift [storen_memory_ext_to_memory_ext] to store_value_of_type *)
1399lemma store_value_of_type_memory_ext_to_memory_ext :
1400  ∀E,mA,mB,mC.
1401  ∀Hext:memory_ext E mA mB.
1402  ∀wb,wo. meml ? wb (me_writeable … Hext) →
1403  ∀ty,v.store_value_of_type ty mB wb wo v = Some ? mC →
1404  memory_ext E mA mC.
1405#E #mA #mB #mC #Hext #wb #wo #Hmem #ty #v
1406cases ty
1407[ 1: | 2: #sz #sg | 3: #fsz | 4: #ptr_ty | 5: #array_ty #array_sz | 6: #domain #codomain
1408| 7: #structname #fieldspec | 8: #unionname #fieldspec | 9: #id ]
1409whd in ⊢ ((??%?) → ?);
1410[ 1,5,6,7,8: #Habsurd destruct (Habsurd) ]
1411#Hstore
1412@(storen_memory_ext_to_memory_ext … Hext … Hmem … Hstore)
1413qed.
1414
1415(* Commutation results of standard binary operations with value_eq. *)
1416lemma unary_operation_value_eq :
1417  ∀E,op,v1,v2,ty.
1418   value_eq E v1 v2 →
1419   ∀r1.
1420   sem_unary_operation op v1 ty = Some ? r1 →
1421    ∃r2.sem_unary_operation op v2 ty = Some ? r2 ∧ value_eq E r1 r2.
1422#E #op #v1 #v2 #ty #Hvalue_eq #r1
1423inversion Hvalue_eq
1424[ 1: #v #Hv1 #Hv2 #_ destruct
1425     cases op normalize
1426     [ 1: cases ty [ 1: | 2: #sz #sg | 3: #fl | 4: #ty | 5: #ty #n | 6: #tl #ty | 7: #id #fl | 8: #id #fl | 9: #ty ]
1427          normalize #Habsurd destruct (Habsurd)
1428     | 3: cases ty [ 1: | 2: #sz #sg | 3: #fl | 4: #ty | 5: #ty #n | 6: #tl #ty | 7: #id #fl | 8: #id #fl | 9: #ty ]
1429          normalize #Habsurd destruct (Habsurd)
1430     | 2: #Habsurd destruct (Habsurd) ]
1431| 2: #vsz #i #Hv1 #Hv2 #_
1432     cases op
1433     [ 1: cases ty
1434          [ 1: | 2: #sz #sg | 3: #fl | 4: #ty | 5: #ty #n | 6: #tl #ty | 7: #id #fl | 8: #id #fl | 9: #ty ]
1435          whd in ⊢ ((??%?) → ?); whd in match (sem_unary_operation ???);
1436          [ 2: cases (eq_intsize sz vsz) normalize nodelta #Heq1 destruct
1437               %{(of_bool (eq_bv (bitsize_of_intsize vsz) i (zero (bitsize_of_intsize vsz))))}
1438               cases (eq_bv (bitsize_of_intsize vsz) i (zero (bitsize_of_intsize vsz))) @conj
1439               //
1440          | *: #Habsurd destruct (Habsurd) ]
1441     | 2: whd in match (sem_unary_operation ???);     
1442          #Heq1 destruct %{(Vint vsz (exclusive_disjunction_bv (bitsize_of_intsize vsz) i (mone vsz)))} @conj //
1443     | 3: whd in match (sem_unary_operation ???);
1444          cases ty
1445          [ 1: | 2: #sz #sg | 3: #fl | 4: #ty | 5: #ty #n | 6: #tl #ty | 7: #id #fl | 8: #id #fl | 9: #ty ]
1446          normalize nodelta
1447          whd in ⊢ ((??%?) → ?);
1448          [ 2: cases (eq_intsize sz vsz) normalize nodelta #Heq1 destruct
1449               %{(Vint vsz (two_complement_negation (bitsize_of_intsize vsz) i))} @conj //
1450          | *: #Habsurd destruct (Habsurd) ] ]
1451| 3: #f #Hv1 #Hv2 #_ destruct  whd in match (sem_unary_operation ???);
1452     cases op normalize nodelta
1453     [ 1: cases ty
1454          [ 1: | 2: #sz #sg | 3: #fl | 4: #ty | 5: #ty #n | 6: #tl #ty | 7: #id #fl | 8: #id #fl | 9: #ty ]
1455          whd in match (sem_notbool ??);
1456          #Heq1 destruct
1457          cases (Fcmp Ceq f Fzero) /3 by ex_intro, vint_eq, conj/
1458     | 2: normalize #Habsurd destruct (Habsurd)
1459     | 3: cases ty
1460          [ 1: | 2: #sz #sg | 3: #fl | 4: #ty | 5: #ty #n | 6: #tl #ty | 7: #id #fl | 8: #id #fl | 9: #ty ]
1461          whd in match (sem_neg ??);
1462          #Heq1 destruct /3 by ex_intro, vfloat_eq, conj/ ]
1463| 4: #Hv1 #Hv2 #_ destruct  whd in match (sem_unary_operation ???);
1464     cases op normalize nodelta
1465     [ 1: cases ty
1466          [ 1: | 2: #sz #sg | 3: #fl | 4: #ty | 5: #ty #n | 6: #tl #ty | 7: #id #fl | 8: #id #fl | 9: #ty ]
1467          whd in match (sem_notbool ??);
1468          #Heq1 destruct /3 by ex_intro, vint_eq, conj/
1469     | 2: normalize #Habsurd destruct (Habsurd)
1470     | 3: cases ty
1471          [ 1: | 2: #sz #sg | 3: #fl | 4: #ty | 5: #ty #n | 6: #tl #ty | 7: #id #fl | 8: #id #fl | 9: #ty ]
1472          whd in match (sem_neg ??);
1473          #Heq1 destruct ]
1474| 5: #p1 #p2 #Hptr_translation #Hv1 #Hv2 #_  whd in match (sem_unary_operation ???);
1475     cases op normalize nodelta
1476     [ 1: cases ty
1477          [ 1: | 2: #sz #sg | 3: #fl | 4: #ty | 5: #ty #n | 6: #tl #ty | 7: #id #fl | 8: #id #fl | 9: #ty ]
1478          whd in match (sem_notbool ??);         
1479          #Heq1 destruct /3 by ex_intro, vint_eq, conj/
1480     | 2: normalize #Habsurd destruct (Habsurd)
1481     | 3: cases ty
1482          [ 1: | 2: #sz #sg | 3: #fl | 4: #ty | 5: #ty #n | 6: #tl #ty | 7: #id #fl | 8: #id #fl | 9: #ty ]
1483          whd in match (sem_neg ??);         
1484          #Heq1 destruct ]
1485]
1486qed.
1487
1488(* value_eq lifts to addition *)
1489lemma add_value_eq :
1490  ∀E,v1,v2,v1',v2',ty1,ty2.
1491   value_eq E v1 v2 →
1492   value_eq E v1' v2' →
1493   (* memory_inj E m1 m2 →  This injection seems useless TODO *)
1494   ∀r1. (sem_add v1 ty1 v1' ty2=Some val r1→
1495           ∃r2:val.sem_add v2 ty1 v2' ty2=Some val r2∧value_eq E r1 r2).
1496#E #v1 #v2 #v1' #v2' #ty1 #ty2 #Hvalue_eq1 #Hvalue_eq2 #r1
1497@(value_eq_inversion E … Hvalue_eq1)
1498[ 1: #v | 2: #sz #i | 3: #f | 4: | 5: #p1 #p2 #Hembed ]
1499[ 1: whd in match (sem_add ????); normalize nodelta
1500     cases (classify_add ty1 ty2) normalize nodelta
1501     [ 1: #sz #sg | 2: #fsz | 3: #n #ty #sz #sg | 4: #n #sz #sg #ty | 5: #ty1' #ty2' ]
1502     #Habsurd destruct (Habsurd)
1503| 2: whd in match (sem_add ????); whd in match (sem_add ????); normalize nodelta
1504     cases (classify_add ty1 ty2) normalize nodelta     
1505     [ 1: #tsz #tsg | 2: #tfsz | 3: #tn #ty #tsz #tsg | 4: #tn #tsz #tsg #ty | 5: #ty1' #ty2' ]
1506     [ 2,3,5: #Habsurd destruct (Habsurd) ]
1507     @(value_eq_inversion E … Hvalue_eq2) normalize nodelta
1508     [ 1,6: #v' | 2,7: #sz' #i' | 3,8: #f' | 4,9: | 5,10: #p1' #p2' #Hembed' ]
1509     [ 1,2,4,5,6,7,9: #Habsurd destruct (Habsurd) ]
1510     [ 1: @intsize_eq_elim_elim
1511          [ 1: #_ #Habsurd destruct (Habsurd)
1512          | 2: #Heq destruct (Heq) normalize nodelta
1513               #Heq destruct (Heq)
1514               /3 by ex_intro, conj, vint_eq/ ]
1515     | 2: @eq_bv_elim normalize nodelta #Heq1 #Heq2 destruct
1516          /3 by ex_intro, conj, vint_eq/
1517     | 3: #Heq destruct (Heq)
1518          normalize in Hembed'; elim p1' in Hembed'; #b1' #o1' normalize nodelta #Hembed
1519          %{(Vptr (shift_pointer_n (bitsize_of_intsize sz) p2' (sizeof ty) i))} @conj try @refl
1520          @vptr_eq whd in match (pointer_translation ??);
1521          cases (E b1') in Hembed;
1522          [ 1: normalize in ⊢ (% → ?); #Habsurd destruct (Habsurd)
1523          | 2: * #block #offset normalize nodelta #Heq destruct (Heq)
1524               whd in match (shift_pointer_n ????);
1525               cut (offset_plus (shift_offset_n (bitsize_of_intsize sz) o1' (sizeof ty) i) offset =
1526                    (shift_offset_n (bitsize_of_intsize sz) (mk_offset (addition_n ? (offv o1') (offv offset))) (sizeof ty) i))
1527               [ 1: whd in match (offset_plus ??);
1528                    whd in match (shift_offset_n ????) in ⊢ (??%%);
1529                    >commutative_addition_n >associative_addition_n
1530                    <(commutative_addition_n … (offv offset) (offv o1')) @refl ]
1531               #Heq >Heq @refl ]
1532     ]
1533| 3: whd in match (sem_add ????); whd in match (sem_add ????); normalize nodelta
1534     cases (classify_add ty1 ty2) normalize nodelta     
1535     [ 1: #tsz #tsg | 2: #tfsz | 3: #tn #ty #tsz #tsg | 4: #tn #tsz #tsg #ty | 5: #ty1' #ty2' ]
1536     [ 1,3,4,5: #Habsurd destruct (Habsurd) ]
1537     @(value_eq_inversion E … Hvalue_eq2) normalize nodelta
1538     [ 1: #v' | 2: #sz' #i' | 3: #f' | 4: | 5: #p1' #p2' #Hembed' ]
1539     [ 1,2,4,5: #Habsurd destruct (Habsurd) ]
1540     #Heq destruct (Heq)
1541     /3 by ex_intro, conj, vfloat_eq/
1542| 4: whd in match (sem_add ????); whd in match (sem_add ????); normalize nodelta
1543     cases (classify_add ty1 ty2) normalize nodelta     
1544     [ 1: #tsz #tsg | 2: #tfsz | 3: #tn #ty #tsz #tsg | 4: #tn #tsz #tsg #ty | 5: #ty1' #ty2' ]
1545     [ 1,2,4,5: #Habsurd destruct (Habsurd) ]
1546     @(value_eq_inversion E … Hvalue_eq2) normalize nodelta
1547     [ 1: #v' | 2: #sz' #i' | 3: #f' | 4: | 5: #p1' #p2' #Hembed' ]
1548     [ 1,3,4,5: #Habsurd destruct (Habsurd) ]
1549     @eq_bv_elim
1550     [ 1: normalize nodelta #Heq1 #Heq2 destruct /3 by ex_intro, conj, vnull_eq/
1551     | 2: #_ normalize nodelta #Habsurd destruct (Habsurd) ]
1552| 5: whd in match (sem_add ????); whd in match (sem_add ????); normalize nodelta
1553     cases (classify_add ty1 ty2) normalize nodelta
1554     [ 1: #tsz #tsg | 2: #tfsz | 3: #tn #ty #tsz #tsg | 4: #tn #tsz #tsg #ty | 5: #ty1' #ty2' ]
1555     [ 1,2,4,5: #Habsurd destruct (Habsurd) ]
1556     @(value_eq_inversion E … Hvalue_eq2) normalize nodelta
1557     [ 1: #v' | 2: #sz' #i' | 3: #f' | 4: | 5: #p1' #p2' #Hembed' ]
1558     [ 1,3,4,5: #Habsurd destruct (Habsurd) ]
1559     #Heq destruct (Heq)
1560     %{(Vptr (shift_pointer_n (bitsize_of_intsize sz') p2 (sizeof ty) i'))} @conj try @refl
1561     @vptr_eq whd in match (pointer_translation ??) in Hembed ⊢ %;
1562     elim p1 in Hembed; #b1 #o1 normalize nodelta
1563     cases (E b1)
1564     [ 1: normalize in ⊢ (% → ?); #Habsurd destruct (Habsurd)
1565     | 2: * #block #offset normalize nodelta #Heq destruct (Heq)
1566          whd in match (shift_pointer_n ????);
1567          whd in match (shift_offset_n ????) in ⊢ (??%%);
1568          whd in match (offset_plus ??);
1569          whd in match (offset_plus ??);
1570          >commutative_addition_n >(associative_addition_n … offset_size ?)
1571          >(commutative_addition_n ? (offv offset) ?) @refl
1572     ]
1573] qed.
1574
1575lemma subtraction_delta : ∀x,y,delta.
1576  subtraction offset_size
1577    (addition_n offset_size x delta)
1578    (addition_n offset_size y delta) =
1579  subtraction offset_size x y.
1580#x #y #delta whd in match subtraction; normalize nodelta
1581(* Remove all the equal parts on each side of the equation. *)
1582<associative_addition_n
1583>two_complement_negation_plus
1584<(commutative_addition_n … (two_complement_negation ? delta))
1585>(associative_addition_n ? delta) >bitvector_opp_addition_n
1586>(commutative_addition_n ? (zero ?)) >neutral_addition_n
1587@refl
1588qed.
1589
1590(* Offset subtraction is invariant by translation *)
1591lemma sub_offset_translation :
1592 ∀n,x,y,delta. sub_offset n x y = sub_offset n (offset_plus x delta) (offset_plus y delta).
1593#n #x #y #delta
1594whd in match (sub_offset ???) in ⊢ (??%%);
1595elim x #x' elim y #y' elim delta #delta'
1596whd in match (offset_plus ??);
1597whd in match (offset_plus ??);
1598>subtraction_delta @refl
1599qed.
1600
1601(* value_eq lifts to subtraction *)
1602lemma sub_value_eq :
1603  ∀E,v1,v2,v1',v2',ty1,ty2.
1604   value_eq E v1 v2 →
1605   value_eq E v1' v2' →
1606   ∀r1. (sem_sub v1 ty1 v1' ty2=Some val r1→
1607           ∃r2:val.sem_sub v2 ty1 v2' ty2=Some val r2∧value_eq E r1 r2).
1608#E #v1 #v2 #v1' #v2' #ty1 #ty2 #Hvalue_eq1 #Hvalue_eq2 #r1
1609@(value_eq_inversion E … Hvalue_eq1)
1610[ 1: #v | 2: #sz #i | 3: #f | 4: | 5: #p1 #p2 #Hembed ]
1611[ 1: whd in match (sem_sub ????); normalize nodelta
1612     cases (classify_sub ty1 ty2) normalize nodelta
1613     [ 1: #sz #sg | 2: #fsz | 3: #n #ty #sz #sg | 4: #n #sz #sg #ty | 5: #ty1' #ty2' ]
1614     #Habsurd destruct (Habsurd)
1615| 2: whd in match (sem_sub ????); whd in match (sem_sub ????); normalize nodelta
1616     cases (classify_sub ty1 ty2) normalize nodelta     
1617     [ 1: #tsz #tsg | 2: #tfsz | 3: #tn #ty #tsz #tsg | 4: #tn #tsz #tsg #ty | 5: #ty1' #ty2' ]
1618     [ 2,3,5: #Habsurd destruct (Habsurd) ]
1619     @(value_eq_inversion E … Hvalue_eq2) normalize nodelta
1620     [ 1,6: #v' | 2,7: #sz' #i' | 3,8: #f' | 4,9: | 5,10: #p1' #p2' #Hembed' ]
1621     [ 1,2,4,5,6,7,8,9,10: #Habsurd destruct (Habsurd) ]
1622     @intsize_eq_elim_elim
1623      [ 1: #_ #Habsurd destruct (Habsurd)
1624      | 2: #Heq destruct (Heq) normalize nodelta
1625           #Heq destruct (Heq)
1626          /3 by ex_intro, conj, vint_eq/           
1627      ]
1628| 3: whd in match (sem_sub ????); whd in match (sem_sub ????); normalize nodelta
1629     cases (classify_sub ty1 ty2) normalize nodelta     
1630     [ 1: #tsz #tsg | 2: #tfsz | 3: #tn #ty #tsz #tsg | 4: #tn #tsz #tsg #ty | 5: #ty1' #ty2' ]
1631     [ 1,3,4,5: #Habsurd destruct (Habsurd) ]
1632     @(value_eq_inversion E … Hvalue_eq2) normalize nodelta
1633     [ 1: #v' | 2: #sz' #i' | 3: #f' | 4: | 5: #p1' #p2' #Hembed' ]
1634     [ 1,2,4,5: #Habsurd destruct (Habsurd) ]
1635     #Heq destruct (Heq)
1636     /3 by ex_intro, conj, vfloat_eq/
1637| 4: whd in match (sem_sub ????); whd in match (sem_sub ????); normalize nodelta
1638     cases (classify_sub ty1 ty2) normalize nodelta
1639     [ 1: #tsz #tsg | 2: #tfsz | 3: #tn #ty #tsz #tsg | 4: #tn #tsz #tsg #ty | 5: #ty1' #ty2' ]
1640     [ 1,2,5: #Habsurd destruct (Habsurd) ]
1641     @(value_eq_inversion E … Hvalue_eq2) normalize nodelta
1642     [ 1,6: #v' | 2,7: #sz' #i' | 3,8: #f' | 4,9: | 5,10: #p1' #p2' #Hembed' ]
1643     [ 1,2,4,5,6,7,9,10: #Habsurd destruct (Habsurd) ]         
1644     [ 1: @eq_bv_elim [ 1: normalize nodelta #Heq1 #Heq2 destruct /3 by ex_intro, conj, vnull_eq/
1645                      | 2: #_ normalize nodelta #Habsurd destruct (Habsurd) ]
1646     | 2: #Heq destruct (Heq) /3 by ex_intro, conj, vnull_eq/ ]
1647| 5: whd in match (sem_sub ????); whd in match (sem_sub ????); normalize nodelta
1648     cases (classify_sub ty1 ty2) normalize nodelta
1649     [ 1: #tsz #tsg | 2: #tfsz | 3: #tn #ty #tsz #tsg | 4: #tn #tsz #tsg #ty | 5: #ty1' #ty2' ]
1650     [ 1,2,5: #Habsurd destruct (Habsurd) ]
1651     @(value_eq_inversion E … Hvalue_eq2) normalize nodelta
1652     [ 1,6: #v' | 2,7: #sz' #i' | 3,8: #f' | 4,9: | 5,10: #p1' #p2' #Hembed' ]
1653     [ 1,2,4,5,6,7,8,9: #Habsurd destruct (Habsurd) ]
1654     #Heq destruct (Heq)
1655     [ 1: %{(Vptr (neg_shift_pointer_n (bitsize_of_intsize sz') p2 (sizeof ty) i'))} @conj try @refl
1656          @vptr_eq whd in match (pointer_translation ??) in Hembed ⊢ %;
1657          elim p1 in Hembed; #b1 #o1 normalize nodelta
1658          cases (E b1)
1659          [ 1: normalize in ⊢ (% → ?); #Habsurd destruct (Habsurd)
1660          | 2: * #block #offset normalize nodelta #Heq destruct (Heq)
1661               whd in match (offset_plus ??) in ⊢ (??%%);
1662               whd in match (neg_shift_pointer_n ????) in ⊢ (??%%);
1663               whd in match (neg_shift_offset_n ????) in ⊢ (??%%);
1664               whd in match (subtraction) in ⊢ (??%%); normalize nodelta
1665               generalize in match (short_multiplication ???); #mult
1666               /3 by associative_addition_n, commutative_addition_n, refl/
1667          ]
1668     | 2: lapply Heq @eq_block_elim
1669          [ 2: #_ normalize nodelta #Habsurd destruct (Habsurd)
1670          | 1: #Hpblock1_eq normalize nodelta
1671               elim p1 in Hpblock1_eq Hembed Hembed'; #b1 #off1
1672               elim p1' #b1' #off1' whd in ⊢ (% → % → ?); #Hpblock1_eq destruct (Hpblock1_eq)
1673               whd in ⊢ ((??%?) → (??%?) → ?);
1674               cases (E b1') normalize nodelta
1675               [ 1: #Habsurd destruct (Habsurd) ]
1676               * #dest_block #dest_off normalize nodelta
1677               #Heq_ptr1 #Heq_ptr2 destruct >eq_block_b_b normalize nodelta
1678               cases (eqb (sizeof tsg) O) normalize nodelta
1679               [ 1: #Habsurd destruct (Habsurd)
1680               | 2: >(sub_offset_translation 32 off1 off1' dest_off)
1681                    cases (division_u 31
1682                            (sub_offset 32 (offset_plus off1 dest_off) (offset_plus off1' dest_off))
1683                            (repr (sizeof tsg)))
1684                    [ 1: normalize nodelta #Habsurd destruct (Habsurd)
1685                    | 2: #r1' normalize nodelta #Heq2 destruct (Heq2)
1686                         /3 by ex_intro, conj, vint_eq/ ]
1687    ] ] ]
1688] qed.
1689
1690
1691lemma mul_value_eq :
1692  ∀E,v1,v2,v1',v2',ty1,ty2.
1693   value_eq E v1 v2 →
1694   value_eq E v1' v2' →
1695   ∀r1. (sem_mul v1 ty1 v1' ty2=Some val r1→
1696           ∃r2:val.sem_mul v2 ty1 v2' ty2=Some val r2∧value_eq E r1 r2).
1697#E #v1 #v2 #v1' #v2' #ty1 #ty2 #Hvalue_eq1 #Hvalue_eq2 #r1
1698@(value_eq_inversion E … Hvalue_eq1)
1699[ 1: #v | 2: #sz #i | 3: #f | 4: | 5: #p1 #p2 #Hembed ]
1700[ 1: whd in match (sem_mul ????); normalize nodelta
1701     cases (classify_aop ty1 ty2) normalize nodelta
1702     [ 1: #sz #sg | 2: #fsz | 3: #ty1' #ty2' ]
1703     #Habsurd destruct (Habsurd)
1704| 2: whd in match (sem_mul ????); whd in match (sem_mul ????); normalize nodelta
1705     cases (classify_aop ty1 ty2) normalize nodelta
1706     [ 1: #sz #sg | 2: #fsz | 3: #ty1' #ty2' ]
1707     [ 2,3: #Habsurd destruct (Habsurd) ]
1708     @(value_eq_inversion E … Hvalue_eq2) normalize nodelta
1709     [ 1: #v' | 2: #sz' #i' | 3: #f' | 4: | 5: #p1' #p2' #Hembed' ]
1710     [ 1,3,4,5: #Habsurd destruct (Habsurd) ]
1711     @intsize_eq_elim_elim
1712      [ 1: #_ #Habsurd destruct (Habsurd)
1713      | 2: #Heq destruct (Heq) normalize nodelta
1714           #Heq destruct (Heq)
1715          /3 by ex_intro, conj, vint_eq/           
1716      ]
1717| 3: whd in match (sem_mul ????); whd in match (sem_mul ????); normalize nodelta
1718     cases (classify_aop ty1 ty2) normalize nodelta
1719     [ 1: #sz #sg | 2: #fsz | 3: #ty1' #ty2' ]
1720     [ 1,3: #Habsurd destruct (Habsurd) ]
1721     @(value_eq_inversion E … Hvalue_eq2) normalize nodelta     
1722     [ 1: #v' | 2: #sz' #i' | 3: #f' | 4: | 5: #p1' #p2' #Hembed' ]
1723     [ 1,2,4,5: #Habsurd destruct (Habsurd) ]
1724     #Heq destruct (Heq)
1725     /3 by ex_intro, conj, vfloat_eq/
1726| 4: whd in match (sem_mul ????); whd in match (sem_mul ????); normalize nodelta
1727     cases (classify_aop ty1 ty2) normalize nodelta
1728     [ 1: #sz #sg | 2: #fsz | 3: #ty1' #ty2' ]
1729     #Habsurd destruct (Habsurd)
1730| 5: whd in match (sem_mul ????); whd in match (sem_mul ????); normalize nodelta
1731     cases (classify_aop ty1 ty2) normalize nodelta
1732     [ 1: #sz #sg | 2: #fsz | 3: #ty1' #ty2' ]     
1733     #Habsurd destruct (Habsurd)
1734] qed.
1735
1736lemma div_value_eq :
1737  ∀E,v1,v2,v1',v2',ty1,ty2.
1738   value_eq E v1 v2 →
1739   value_eq E v1' v2' →
1740   ∀r1. (sem_div v1 ty1 v1' ty2=Some val r1→
1741           ∃r2:val.sem_div v2 ty1 v2' ty2=Some val r2∧value_eq E r1 r2).
1742#E #v1 #v2 #v1' #v2' #ty1 #ty2 #Hvalue_eq1 #Hvalue_eq2 #r1
1743@(value_eq_inversion E … Hvalue_eq1)
1744[ 1: #v | 2: #sz #i | 3: #f | 4: | 5: #p1 #p2 #Hembed ]
1745[ 1: whd in match (sem_div ????); normalize nodelta
1746     cases (classify_aop ty1 ty2) normalize nodelta
1747     [ 1: #sz #sg | 2: #fsz | 3: #ty1' #ty2' ]
1748     #Habsurd destruct (Habsurd)
1749| 2: whd in match (sem_div ????); whd in match (sem_div ????); normalize nodelta
1750     cases (classify_aop ty1 ty2) normalize nodelta
1751     [ 1: #sz #sg | 2: #fsz | 3: #ty1' #ty2' ]
1752     [ 2,3: #Habsurd destruct (Habsurd) ]
1753     @(value_eq_inversion E … Hvalue_eq2) normalize nodelta
1754     [ 1: #v' | 2: #sz' #i' | 3: #f' | 4: | 5: #p1' #p2' #Hembed' ]
1755     [ 1,3,4,5: #Habsurd destruct (Habsurd) ]
1756     elim sg normalize nodelta
1757     @intsize_eq_elim_elim
1758     [ 1,3: #_ #Habsurd destruct (Habsurd)
1759     | 2,4: #Heq destruct (Heq) normalize nodelta
1760            @(match (division_s (bitsize_of_intsize sz') i i') with
1761              [ None ⇒ ?
1762              | Some bv' ⇒ ? ])
1763            [ 1: normalize  #Habsurd destruct (Habsurd)
1764            | 2: normalize #Heq destruct (Heq)
1765                 /3 by ex_intro, conj, vint_eq/
1766            | 3,4: elim sz' in i' i; #i' #i
1767                   normalize in match (pred_size_intsize ?);
1768                   generalize in match division_u; #division_u normalize
1769                   @(match (division_u ???) with
1770                    [ None ⇒ ?
1771                    | Some bv ⇒ ?]) normalize nodelta
1772                   #H destruct (H)
1773                  /3 by ex_intro, conj, vint_eq/ ]
1774     ]
1775| 3: whd in match (sem_div ????); whd in match (sem_div ????); normalize nodelta
1776     cases (classify_aop ty1 ty2) normalize nodelta
1777     [ 1: #sz #sg | 2: #fsz | 3: #ty1' #ty2' ]
1778     [ 1,3: #Habsurd destruct (Habsurd) ]
1779     @(value_eq_inversion E … Hvalue_eq2) normalize nodelta     
1780     [ 1: #v' | 2: #sz' #i' | 3: #f' | 4: | 5: #p1' #p2' #Hembed' ]
1781     [ 1,2,4,5: #Habsurd destruct (Habsurd) ]
1782     #Heq destruct (Heq)
1783     /3 by ex_intro, conj, vfloat_eq/
1784| 4: whd in match (sem_div ????); whd in match (sem_div ????); normalize nodelta
1785     cases (classify_aop ty1 ty2) normalize nodelta
1786     [ 1: #sz #sg | 2: #fsz | 3: #ty1' #ty2' ]
1787     #Habsurd destruct (Habsurd)
1788| 5: whd in match (sem_div ????); whd in match (sem_div ????); normalize nodelta
1789     cases (classify_aop ty1 ty2) normalize nodelta
1790     [ 1: #sz #sg | 2: #fsz | 3: #ty1' #ty2' ]     
1791     #Habsurd destruct (Habsurd)
1792] qed.
1793
1794lemma mod_value_eq :
1795  ∀E,v1,v2,v1',v2',ty1,ty2.
1796   value_eq E v1 v2 →
1797   value_eq E v1' v2' →
1798   ∀r1. (sem_mod v1 ty1 v1' ty2=Some val r1→
1799           ∃r2:val.sem_mod v2 ty1 v2' ty2=Some val r2∧value_eq E r1 r2).
1800#E #v1 #v2 #v1' #v2' #ty1 #ty2 #Hvalue_eq1 #Hvalue_eq2 #r1
1801@(value_eq_inversion E … Hvalue_eq1)
1802[ 1: #v | 2: #sz #i | 3: #f | 4: | 5: #p1 #p2 #Hembed ]
1803[ 1: whd in match (sem_mod ????); normalize nodelta
1804     cases (classify_aop ty1 ty2) normalize nodelta
1805     [ 1: #sz #sg | 2: #fsz | 3: #ty1' #ty2' ]
1806     #Habsurd destruct (Habsurd)
1807| 2: whd in match (sem_mod ????); whd in match (sem_mod ????); normalize nodelta
1808     cases (classify_aop ty1 ty2) normalize nodelta
1809     [ 1: #sz #sg | 2: #fsz | 3: #ty1' #ty2' ]
1810     [ 2,3: #Habsurd destruct (Habsurd) ]
1811     @(value_eq_inversion E … Hvalue_eq2) normalize nodelta
1812     [ 1: #v' | 2: #sz' #i' | 3: #f' | 4: | 5: #p1' #p2' #Hembed' ]
1813     [ 1,3,4,5: #Habsurd destruct (Habsurd) ]
1814     elim sg normalize nodelta
1815     @intsize_eq_elim_elim
1816     [ 1,3: #_ #Habsurd destruct (Habsurd)
1817     | 2,4: #Heq destruct (Heq) normalize nodelta
1818            @(match (modulus_s (bitsize_of_intsize sz') i i') with
1819              [ None ⇒ ?
1820              | Some bv' ⇒ ? ])
1821            [ 1: normalize  #Habsurd destruct (Habsurd)
1822            | 2: normalize #Heq destruct (Heq)
1823                 /3 by ex_intro, conj, vint_eq/
1824            | 3,4: elim sz' in i' i; #i' #i
1825                   generalize in match modulus_u; #modulus_u normalize
1826                   @(match (modulus_u ???) with
1827                    [ None ⇒ ?
1828                    | Some bv ⇒ ?]) normalize nodelta
1829                   #H destruct (H)
1830                  /3 by ex_intro, conj, vint_eq/ ]
1831     ]
1832| 3: whd in match (sem_mod ????); whd in match (sem_mod ????); normalize nodelta
1833     cases (classify_aop ty1 ty2) normalize nodelta
1834     [ 1: #sz #sg | 2: #fsz | 3: #ty1' #ty2' ]
1835     #Habsurd destruct (Habsurd)
1836| 4: whd in match (sem_mod ????); whd in match (sem_mod ????); normalize nodelta
1837     cases (classify_aop ty1 ty2) normalize nodelta
1838     [ 1: #sz #sg | 2: #fsz | 3: #ty1' #ty2' ]
1839     #Habsurd destruct (Habsurd)
1840| 5: whd in match (sem_mod ????); whd in match (sem_mod ????); normalize nodelta
1841     cases (classify_aop ty1 ty2) normalize nodelta
1842     [ 1: #sz #sg | 2: #fsz | 3: #ty1' #ty2' ]     
1843     #Habsurd destruct (Habsurd)
1844] qed.
1845
1846(* boolean ops *)
1847lemma and_value_eq :
1848  ∀E,v1,v2,v1',v2'.
1849   value_eq E v1 v2 →
1850   value_eq E v1' v2' →
1851   ∀r1. (sem_and v1 v1'=Some val r1→
1852           ∃r2:val.sem_and v2 v2'=Some val r2∧value_eq E r1 r2).
1853#E #v1 #v2 #v1' #v2' #Hvalue_eq1 #Hvalue_eq2 #r1
1854@(value_eq_inversion E … Hvalue_eq1)
1855[ 2: #sz #i
1856     @(value_eq_inversion E … Hvalue_eq2)
1857     [ 2: #sz' #i' whd in match (sem_and ??);
1858          @intsize_eq_elim_elim
1859          [ 1: #_ #Habsurd destruct (Habsurd)
1860          | 2: #Heq destruct (Heq) normalize nodelta
1861               #Heq destruct (Heq) /3 by ex_intro,conj,vint_eq/ ]
1862] ]
1863normalize in match (sem_and ??); #arg1 destruct
1864normalize in match (sem_and ??); #arg2 destruct
1865normalize in match (sem_and ??); #arg3 destruct
1866normalize in match (sem_and ??); #arg4 destruct
1867qed.
1868
1869lemma or_value_eq :
1870  ∀E,v1,v2,v1',v2'.
1871   value_eq E v1 v2 →
1872   value_eq E v1' v2' →
1873   ∀r1. (sem_or v1 v1'=Some val r1→
1874           ∃r2:val.sem_or v2 v2'=Some val r2∧value_eq E r1 r2).
1875#E #v1 #v2 #v1' #v2' #Hvalue_eq1 #Hvalue_eq2 #r1
1876@(value_eq_inversion E … Hvalue_eq1)
1877[ 2: #sz #i
1878     @(value_eq_inversion E … Hvalue_eq2)
1879     [ 2: #sz' #i' whd in match (sem_or ??);
1880          @intsize_eq_elim_elim
1881          [ 1: #_ #Habsurd destruct (Habsurd)
1882          | 2: #Heq destruct (Heq) normalize nodelta
1883               #Heq destruct (Heq) /3 by ex_intro,conj,vint_eq/ ]
1884] ]
1885normalize in match (sem_or ??); #arg1 destruct
1886normalize in match (sem_or ??); #arg2 destruct
1887normalize in match (sem_or ??); #arg3 destruct
1888normalize in match (sem_or ??); #arg4 destruct
1889qed.
1890
1891lemma xor_value_eq :
1892  ∀E,v1,v2,v1',v2'.
1893   value_eq E v1 v2 →
1894   value_eq E v1' v2' →
1895   ∀r1. (sem_xor v1 v1'=Some val r1→
1896           ∃r2:val.sem_xor v2 v2'=Some val r2∧value_eq E r1 r2).
1897#E #v1 #v2 #v1' #v2' #Hvalue_eq1 #Hvalue_eq2 #r1
1898@(value_eq_inversion E … Hvalue_eq1)
1899[ 2: #sz #i
1900     @(value_eq_inversion E … Hvalue_eq2)
1901     [ 2: #sz' #i' whd in match (sem_xor ??);
1902          @intsize_eq_elim_elim
1903          [ 1: #_ #Habsurd destruct (Habsurd)
1904          | 2: #Heq destruct (Heq) normalize nodelta
1905               #Heq destruct (Heq) /3 by ex_intro,conj,vint_eq/ ]
1906] ]
1907normalize in match (sem_xor ??); #arg1 destruct
1908normalize in match (sem_xor ??); #arg2 destruct
1909normalize in match (sem_xor ??); #arg3 destruct
1910normalize in match (sem_xor ??); #arg4 destruct
1911qed.
1912
1913lemma shl_value_eq :
1914  ∀E,v1,v2,v1',v2'.
1915   value_eq E v1 v2 →
1916   value_eq E v1' v2' →
1917   ∀r1. (sem_shl v1 v1'=Some val r1→
1918           ∃r2:val.sem_shl v2 v2'=Some val r2∧value_eq E r1 r2).
1919#E #v1 #v2 #v1' #v2' #Hvalue_eq1 #Hvalue_eq2 #r1
1920@(value_eq_inversion E … Hvalue_eq1)
1921[ 1: #v | 2: #sz #i | 3: #f | 4: | 5: #p1 #p2 #Hembed ]
1922[ 2:
1923     @(value_eq_inversion E … Hvalue_eq2)
1924     [ 1: #v' | 2: #sz' #i' | 3: #f' | 4: | 5: #p1' #p2' #Hembed' ]
1925     [ 2: whd in match (sem_shl ??);
1926          cases (lt_u ???) normalize nodelta
1927          [ 1: #Heq destruct (Heq) /3 by ex_intro,conj,vint_eq/
1928          | 2: #Habsurd destruct (Habsurd)
1929          ]
1930     | *: whd in match (sem_shl ??); #Habsurd destruct (Habsurd) ]
1931| *: whd in match (sem_shl ??); #Habsurd destruct (Habsurd) ]
1932qed.
1933
1934lemma shr_value_eq :
1935  ∀E,v1,v2,v1',v2',ty,ty'.
1936   value_eq E v1 v2 →
1937   value_eq E v1' v2' →
1938   ∀r1. (sem_shr v1 ty v1' ty'=Some val r1→
1939           ∃r2:val.sem_shr v2 ty v2' ty'=Some val r2∧value_eq E r1 r2).
1940#E #v1 #v2 #v1' #v2' #ty #ty' #Hvalue_eq1 #Hvalue_eq2 #r1
1941@(value_eq_inversion E … Hvalue_eq1)
1942[ 1: #v | 2: #sz #i | 3: #f | 4: | 5: #p1 #p2 #Hembed ]
1943whd in match (sem_shr ????); whd in match (sem_shr ????);
1944[ 1: cases (classify_aop ty ty') normalize nodelta
1945     [ 1: #sz #sg | 2: #fsz | 3: #ty1' #ty2' ]
1946     #Habsurd destruct (Habsurd)
1947| 2: cases (classify_aop ty ty') normalize nodelta
1948     [ 1: #sz #sg | 2: #fsz | 3: #ty1' #ty2' ]
1949     [ 2,3: #Habsurd destruct (Habsurd) ]
1950     @(value_eq_inversion E … Hvalue_eq2) normalize nodelta
1951     [ 1: #v' | 2: #sz' #i' | 3: #f' | 4: | 5: #p1' #p2' #Hembed' ]
1952     [ 1,3,4,5: #Habsurd destruct (Habsurd) ]
1953     elim sg normalize nodelta
1954     cases (lt_u ???) normalize nodelta #Heq destruct (Heq)
1955     /3 by ex_intro, conj, refl, vint_eq/
1956| 3: cases (classify_aop ty ty') normalize nodelta
1957     [ 1: #sz #sg | 2: #fsz | 3: #ty1' #ty2' ]
1958     #Habsurd destruct (Habsurd)
1959| 4: cases (classify_aop ty ty') normalize nodelta
1960     [ 1: #sz #sg | 2: #fsz | 3: #ty1' #ty2' ]
1961     #Habsurd destruct (Habsurd)
1962| 5: cases (classify_aop ty ty') normalize nodelta
1963     [ 1: #sz #sg | 2: #fsz | 3: #ty1' #ty2' ]
1964     #Habsurd destruct (Habsurd)
1965] qed.
1966
1967lemma eq_offset_translation : ∀delta,x,y. cmp_offset Ceq (offset_plus x delta) (offset_plus y delta) = cmp_offset Ceq x y.
1968* #delta * #x * #y
1969whd in match (offset_plus ??);
1970whd in match (offset_plus ??);
1971whd in match cmp_offset; normalize nodelta
1972whd in match eq_offset; normalize nodelta
1973@(eq_bv_elim … x y)
1974[ 1: #Heq >Heq >eq_bv_true @refl
1975| 2: #Hneq lapply (injective_inv_addition_n  … x y delta Hneq)
1976     @(eq_bv_elim … (addition_n offset_size x delta) (addition_n offset_size y delta))
1977     [ 1: #H * #H' @(False_ind … (H' H)) | 2: #_ #_ @refl ]
1978] qed.     
1979
1980lemma neq_offset_translation : ∀delta,x,y. cmp_offset Cne (offset_plus x delta) (offset_plus y delta) = cmp_offset Cne x y.
1981* #delta * #x * #y
1982whd in match (offset_plus ??);
1983whd in match (offset_plus ??);
1984whd in match cmp_offset; normalize nodelta
1985whd in match eq_offset; normalize nodelta
1986@(eq_bv_elim … x y)
1987[ 1: #Heq >Heq >eq_bv_true @refl
1988| 2: #Hneq lapply (injective_inv_addition_n  … x y delta Hneq)
1989     @(eq_bv_elim … (addition_n offset_size x delta) (addition_n offset_size y delta))
1990     [ 1: #H * #H' @(False_ind … (H' H)) | 2: #_ #_ @refl ]
1991] qed.
1992
1993
1994(* /!\ Here is the source of all sadness (op = lt) /!\ *)
1995axiom cmp_offset_translation : ∀op,delta,x,y.
1996   cmp_offset op x y = cmp_offset op (offset_plus x delta) (offset_plus y delta).
1997
1998lemma cmp_value_eq :
1999  ∀E,v1,v2,v1',v2',ty,ty',m1,m2.
2000   value_eq E v1 v2 →
2001   value_eq E v1' v2' →
2002   memory_inj E m1 m2 →   
2003   ∀op,r1. (sem_cmp op v1 ty v1' ty' m1 = Some val r1→
2004           ∃r2:val.sem_cmp op v2 ty v2' ty' m2 = Some val r2∧value_eq E r1 r2).
2005#E #v1 #v2 #v1' #v2' #ty #ty' #m1 #m2 #Hvalue_eq1 #Hvalue_eq2 #Hinj #op #r1
2006elim m1 in Hinj; #contmap1 #nextblock1 #Hnextblock1 elim m2 #contmap2 #nextblock2 #Hnextblock2 #Hinj
2007whd in match (sem_cmp ??????) in ⊢ ((??%?) → %);
2008cases (classify_cmp ty ty') normalize nodelta
2009[ 1: #tsz #tsg
2010     @(value_eq_inversion E … Hvalue_eq1) normalize nodelta
2011     [ 1: #v #Habsurd destruct (Habsurd)
2012     | 3: #f #Habsurd destruct (Habsurd)
2013     | 4: #Habsurd destruct (Habsurd)
2014     | 5: #p1 #p2 #Hembed #Habsurd destruct (Habsurd) ]
2015     #sz #i
2016     @(value_eq_inversion E … Hvalue_eq2) normalize nodelta
2017     [ 1: #v #Habsurd destruct (Habsurd)
2018     | 3: #f #Habsurd destruct (Habsurd)
2019     | 4: #Habsurd destruct (Habsurd)
2020     | 5: #p1 #p2 #Hembed #Habsurd destruct (Habsurd) ]
2021     #sz' #i' cases tsg normalize nodelta
2022     @intsize_eq_elim_elim
2023     [ 1,3: #Hneq #Habsurd destruct (Habsurd)
2024     | 2,4: #Heq destruct (Heq) normalize nodelta
2025            #Heq destruct (Heq)     
2026            [ 1: cases (cmp_int ????) whd in match (of_bool ?);
2027            | 2: cases (cmpu_int ????) whd in match (of_bool ?); ]
2028              /3 by ex_intro, conj, vint_eq/ ]
2029| 3: #fsz
2030     @(value_eq_inversion E … Hvalue_eq1) normalize nodelta
2031     [ 1: #v #Habsurd destruct (Habsurd)
2032     | 2: #sz #i #Habsurd destruct (Habsurd)
2033     | 4: #Habsurd destruct (Habsurd)
2034     | 5: #p1 #p2 #Hembed #Habsurd destruct (Habsurd) ]
2035     #f
2036     @(value_eq_inversion E … Hvalue_eq2) normalize nodelta
2037     [ 1: #v #Habsurd destruct (Habsurd)
2038     | 2: #sz #i #Habsurd destruct (Habsurd)
2039     | 4: #Habsurd destruct (Habsurd)
2040     | 5: #p1 #p2 #Hembed #Habsurd destruct (Habsurd) ]
2041     #f'
2042     #Heq destruct (Heq) cases (Fcmp op f f')
2043     /3 by ex_intro, conj, vint_eq/
2044| 4: #ty1 #ty2 #Habsurd destruct (Habsurd)
2045| 2: #optn #typ             
2046     @(value_eq_inversion E … Hvalue_eq1) normalize nodelta
2047     [ 1: #v #Habsurd destruct (Habsurd)
2048     | 2: #sz #i #Habsurd destruct (Habsurd)
2049     | 3: #f #Habsurd destruct (Habsurd)
2050     | 5: #p1 #p2 #Hembed ]
2051     @(value_eq_inversion E … Hvalue_eq2) normalize nodelta
2052     [ 1,6: #v #Habsurd destruct (Habsurd)
2053     | 2,7: #sz #i #Habsurd destruct (Habsurd)
2054     | 3,8: #f #Habsurd destruct (Habsurd)
2055     | 5,10: #p1' #p2' #Hembed' ]
2056     [ 2,3: cases op whd in match (sem_cmp_mismatch ?);
2057          #Heq destruct (Heq)
2058          [ 1,3: %{Vfalse} @conj try @refl @vint_eq
2059          | 2,4: %{Vtrue} @conj try @refl @vint_eq ]
2060     | 4: cases op whd in match (sem_cmp_match ?);
2061          #Heq destruct (Heq)
2062          [ 2,4: %{Vfalse} @conj try @refl @vint_eq
2063          | 1,3: %{Vtrue} @conj try @refl @vint_eq ] ]
2064     lapply (mi_valid_pointers … Hinj p1' p2')
2065     lapply (mi_valid_pointers … Hinj p1 p2)         
2066     cases (valid_pointer (mk_mem ???) p1')
2067     [ 2: #_ #_ >commutative_andb normalize in ⊢ (% → ?); #Habsurd destruct (Habsurd) ]
2068     cases (valid_pointer (mk_mem ???) p1)
2069     [ 2: #_ #_ normalize in ⊢ (% → ?); #Habsurd destruct (Habsurd) ]
2070     #H1 #H2 lapply (H1 (refl ??) Hembed) #Hvalid1 lapply (H2 (refl ??) Hembed') #Hvalid2
2071     >Hvalid1 >Hvalid2 normalize nodelta -H1 -H2
2072     elim p1 in Hembed; #b1 #o1
2073     elim p1' in Hembed'; #b1' #o1'
2074     whd in match (pointer_translation ??);
2075     whd in match (pointer_translation ??);
2076     @(eq_block_elim … b1 b1')
2077     [ 1: #Heq destruct (Heq)
2078          cases (E b1') normalize nodelta
2079          [ 1: #Habsurd destruct (Habsurd) ]
2080          * #eb1' #eo1' normalize nodelta
2081          #Heq1 #Heq2 #Heq3 destruct
2082          >eq_block_b_b normalize nodelta
2083          <cmp_offset_translation
2084          cases (cmp_offset ???) normalize nodelta         
2085          /3 by ex_intro, conj, vint_eq/
2086     | 2: #Hneq lapply (mi_disjoint … Hinj b1 b1')
2087          cases (E b1') [ 1: #_ normalize nodelta #Habsurd destruct (Habsurd) ]
2088          * #eb1 #eo1
2089          cases (E b1) [ 1: #_ normalize nodelta #_ #Habsurd destruct (Habsurd) ]
2090          * #eb1' #eo1' normalize nodelta #H #Heq1 #Heq2 destruct
2091          lapply (H ???? Hneq (refl ??) (refl ??))
2092          #Hneq_block >(neq_block_eq_block_false … Hneq_block) normalize nodelta
2093          elim op whd in match (sem_cmp_mismatch ?); #Heq destruct (Heq)
2094          /3 by ex_intro, conj, vint_eq/
2095     ]
2096] qed.               
2097
2098lemma binary_operation_value_eq :
2099  ∀E,op,v1,v2,v1',v2',ty1,ty2,m1,m2.
2100   value_eq E v1 v2 →
2101   value_eq E v1' v2' →
2102   memory_inj E m1 m2 →
2103   ∀r1.
2104   sem_binary_operation op v1 ty1 v1' ty2 m1 = Some ? r1 →
2105   ∃r2.sem_binary_operation op v2 ty1 v2' ty2 m2 = Some ? r2 ∧ value_eq E r1 r2.
2106#E #op #v1 #v2 #v1' #v2' #ty1 #ty2 #m1 #m2 #Hvalue_eq1 #Hvalue_eq2 #Hinj #r1
2107cases op
2108whd in match (sem_binary_operation ??????);
2109whd in match (sem_binary_operation ??????);
2110[ 1: @add_value_eq try assumption
2111| 2: @sub_value_eq try assumption
2112| 3: @mul_value_eq try assumption
2113| 4: @div_value_eq try assumption
2114| 5: @mod_value_eq try assumption
2115| 6: @and_value_eq try assumption
2116| 7: @or_value_eq try assumption
2117| 8: @xor_value_eq try assumption
2118| 9: @shl_value_eq try assumption
2119| 10: @shr_value_eq try assumption
2120| *: @cmp_value_eq try assumption
2121] qed.
2122
2123lemma cast_value_eq :
2124 ∀E,m1,m2,v1,v2. (* memory_inj E m1 m2 → *) value_eq E v1 v2 →
2125  ∀ty,cast_ty,res. exec_cast m1 v1 ty cast_ty = OK ? res →
2126  ∃res'. exec_cast m2 v2 ty cast_ty = OK ? res' ∧ value_eq E res res'.
2127#E #m1 #m2 #v1 #v2 (* #Hmemory_inj *) #Hvalue_eq #ty #cast_ty #res
2128@(value_eq_inversion … Hvalue_eq)
2129[ 1: #v normalize #Habsurd destruct (Habsurd)
2130| 2: #vsz #vi whd in match (exec_cast ????);
2131     cases ty
2132     [ 1: | 2: #sz #sg | 3: #fl | 4: #ptrty | 5: #arrayty #n | 6: #tl #retty | 7: #id #fl | 8: #id #fl | 9: #comptrty ]
2133     normalize nodelta
2134     [ 1,3,7,8,9: #Habsurd destruct (Habsurd)
2135     | 2: @intsize_eq_elim_elim
2136          [ 1: #Hneq #Habsurd destruct (Habsurd)
2137          | 2: #Heq destruct (Heq) normalize nodelta
2138               cases cast_ty
2139               [ 1: | 2: #csz #csg | 3: #cfl | 4: #cptrty | 5: #carrayty #cn
2140               | 6: #ctl #cretty | 7: #cid #cfl | 8: #cid #cfl | 9: #ccomptrty ]
2141               normalize nodelta
2142               [ 1,7,8,9: #Habsurd destruct (Habsurd)
2143               | 2: #Heq destruct (Heq) /3 by ex_intro, conj, vint_eq/
2144               | 3: #Heq destruct (Heq) /3 by ex_intro, conj, vfloat_eq/
2145               | 4,5,6: whd in match (try_cast_null ?????); normalize nodelta
2146                    @eq_bv_elim
2147                    [ 1,3,5: #Heq destruct (Heq) >eq_intsize_identity normalize nodelta
2148                         whd in match (m_bind ?????);
2149                         #Heq destruct (Heq) /3 by ex_intro, conj, vnull_eq/
2150                    | 2,4,6: #Hneq >eq_intsize_identity normalize nodelta
2151                         whd in match (m_bind ?????);
2152                         #Habsurd destruct (Habsurd) ] ]
2153          ]
2154     | 4,5,6: whd in match (try_cast_null ?????); normalize nodelta
2155          @eq_bv_elim
2156          [ 1,3,5: #Heq destruct (Heq) normalize nodelta
2157               whd in match (m_bind ?????); #Habsurd destruct (Habsurd)
2158          | 2,4,6: #Hneq normalize nodelta
2159               whd in match (m_bind ?????); #Habsurd destruct (Habsurd) ]
2160     ]
2161| 3: #f whd in match (exec_cast ????);
2162     cases ty
2163     [ 1: | 2: #sz #sg | 3: #fl | 4: #ptrty | 5: #arrayty #n
2164     | 6: #tl #retty | 7: #id #fl | 8: #id #fl | 9: #comptrty ]
2165     normalize nodelta
2166     [ 1,2,4,5,6,7,8,9: #Habsurd destruct (Habsurd) ]
2167     cases cast_ty
2168     [ 1: | 2: #csz #csg | 3: #cfl | 4: #cptrty | 5: #carrayty #cn
2169     | 6: #ctl #cretty | 7: #cid #cfl | 8: #cid #cfl | 9: #ccomptrty ]
2170     normalize nodelta
2171     [ 1,4,5,6,7,8,9: #Habsurd destruct (Habsurd) ]
2172     #Heq destruct (Heq)
2173     [ 1: /3 by ex_intro, conj, vint_eq/
2174     | 2: /3 by ex_intro, conj, vfloat_eq/ ]
2175| 4: whd in match (exec_cast ????);
2176     cases ty
2177     [ 1: | 2: #sz #sg | 3: #fl | 4: #ptrty | 5: #arrayty #n
2178     | 6: #tl #retty | 7: #id #fl | 8: #id #fl | 9: #comptrty ]
2179     normalize
2180     [ 1,2,3,7,8,9: #Habsurd destruct (Habsurd) ]
2181     cases cast_ty normalize nodelta
2182     [ 1,10,19: #Habsurd destruct (Habsurd)
2183     | 2,11,20: #csz #csg #Habsurd destruct (Habsurd)
2184     | 3,12,21: #cfl #Habsurd destruct (Habsurd)
2185     | 4,13,22: #cptrty #Heq destruct (Heq) /3 by ex_intro, conj, vnull_eq/
2186     | 5,14,23: #carrayty #cn #Heq destruct (Heq) /3 by ex_intro, conj, vnull_eq/
2187     | 6,15,24: #ctl #cretty #Heq destruct (Heq) /3 by ex_intro, conj, vnull_eq/
2188     | 7,16,25: #cid #cfl #Habsurd destruct (Habsurd)
2189     | 8,17,26: #cid #cfl #Habsurd destruct (Habsurd)
2190     | 9,18,27: #ccomptrty #Habsurd destruct (Habsurd) ]
2191| 5: #p1 #p2 #Hembed whd in match (exec_cast ????);
2192     cases ty
2193     [ 1: | 2: #sz #sg | 3: #fl | 4: #ptrty | 5: #arrayty #n
2194     | 6: #tl #retty | 7: #id #fl | 8: #id #fl | 9: #comptrty ]
2195     normalize
2196     [ 1,2,3,7,8,9: #Habsurd destruct (Habsurd) ]
2197     cases cast_ty normalize nodelta
2198     [ 1,10,19: #Habsurd destruct (Habsurd)
2199     | 2,11,20: #csz #csg #Habsurd destruct (Habsurd)
2200     | 3,12,21: #cfl #Habsurd destruct (Habsurd)
2201     | 4,13,22: #cptrty #Heq destruct (Heq) %{(Vptr p2)} @conj try @refl @vptr_eq assumption
2202     | 5,14,23: #carrayty #cn #Heq destruct (Heq)
2203                %{(Vptr p2)} @conj try @refl @vptr_eq assumption
2204     | 6,15,24: #ctl #cretty #Heq destruct (Heq)
2205                %{(Vptr p2)} @conj try @refl @vptr_eq assumption
2206     | 7,16,25: #cid #cfl #Habsurd destruct (Habsurd)
2207     | 8,17,26: #cid #cfl #Habsurd destruct (Habsurd)
2208     | 9,18,27: #ccomptrty #Habsurd destruct (Habsurd) ]
2209qed.
2210
2211lemma bool_of_val_value_eq :
2212 ∀E,v1,v2. value_eq E v1 v2 →
2213   ∀ty,b.exec_bool_of_val v1 ty = OK ? b → exec_bool_of_val v2 ty = OK ? b.
2214#E #v1 #v2 #Hvalue_eq #ty #b
2215@(value_eq_inversion … Hvalue_eq) //
2216[ 1: #v #H normalize in H; destruct (H)
2217| 2: #p1 #p2 #Hembed #H @H ] qed.
2218
2219
2220(*
2221lemma sim_related_globals : ∀ge,ge',en1,m1,en2,m2,ext.
2222  ∀E:embedding.
2223  ∀Hext:memory_ext E m1 m2.
2224  switch_removal_globals E ? fundef_switch_removal ge ge' →
2225  disjoint_extension en1 m1 en2 m2 ext E Hext →
2226  ext_fresh_for_genv ext ge →
2227  (∀e. exec_expr_sim E (exec_expr ge en1 m1 e) (exec_expr ge' en2 m2 e)) ∧
2228  (∀ed, ty. exec_lvalue_sim E (exec_lvalue' ge en1 m1 ed ty) (exec_lvalue' ge' en2 m2 ed ty)).
2229#ge #ge' #en1 #m1 #en2 #m2 #ext #E #Hext #Hrelated #Hdisjoint #Hext_fresh_for_genv
2230@expr_lvalue_ind_combined
2231[ 1: #csz #cty #i #a1
2232     whd in match (exec_expr ????); elim cty
2233     [ 1: | 2: #sz #sg | 3: #fl | 4: #ty | 5: #ty #n | 6: #tl #ty | 7: #id #fl | 8: #id #fl | 9: #ty ]
2234     normalize nodelta
2235     [ 2: cases (eq_intsize csz sz) normalize nodelta
2236          [ 1: #H destruct (H) /4 by ex_intro, conj, vint_eq/
2237          | 2: #Habsurd destruct (Habsurd) ]
2238     | 4,5,6: #_ #H destruct (H)
2239     | *: #H destruct (H) ]
2240| 2: #ty #fl #a1
2241     whd in match (exec_expr ????); #H1 destruct (H1) /4 by ex_intro, conj, vint_eq/
2242| 3: *
2243  [ 1: #sz #i | 2: #fl | 3: #var_id | 4: #e1 | 5: #e1 | 6: #op #e1 | 7: #op #e1 #e2 | 8: #cast_ty #e1
2244  | 9: #cond #iftrue #iffalse | 10: #e1 #e2 | 11: #e1 #e2 | 12: #sizeofty | 13: #e1 #field | 14: #cost #e1 ]
2245  #ty whd in ⊢ (% → ?); #Hind try @I
2246  whd in match (Plvalue ???);
2247  [ 1,2,3: whd in match (exec_expr ????); whd in match (exec_expr ????); #a1
2248       cases (exec_lvalue' ge en1 m1 ? ty) in Hind;
2249       [ 2,4,6: #error #_ normalize in ⊢ (% → ?); #Habsurd destruct (Habsurd)
2250       | 1,3,5: #b1 #H elim (H b1 (refl ??)) #b2 *
2251           elim b1 * #bl1 #o1 #tr1 elim b2 * #bl2 #o2 #tr2
2252           #Heq >Heq normalize nodelta * #Hvalue_eq #Htrace_eq
2253           whd in match (load_value_of_type' ???);
2254           whd in match (load_value_of_type' ???);
2255           lapply (load_value_of_type_inj E … (\fst a1) … ty (me_inj … Hext) Hvalue_eq)
2256           cases (load_value_of_type ty m1 bl1 o1)
2257           [ 1,3,5: #_ #Habsurd normalize in Habsurd; destruct (Habsurd)
2258           | 2,4,6: #v #Hyp normalize in ⊢ (% → ?); #Heq destruct (Heq)
2259                    elim (Hyp (refl ??)) #v2 * #Hload #Hvalue_eq >Hload
2260                    normalize /4 by ex_intro, conj/
2261  ] ] ]
2262| 4: #v #ty whd * * #b1 #o1 #tr1
2263     whd in match (exec_lvalue' ?????);
2264     whd in match (exec_lvalue' ?????);
2265     lapply (Hdisjoint v)
2266     lapply (Hext_fresh_for_genv v)
2267     cases (mem_assoc_env v ext) #Hglobal
2268     [ 1: * #vblock * * #Hlookup_en2 #Hwriteable #Hnot_in_en1
2269          >Hnot_in_en1 normalize in Hglobal ⊢ (% → ?);
2270          >(Hglobal (refl ??)) normalize
2271          #Habsurd destruct (Habsurd)
2272     | 2: normalize nodelta
2273          cases (lookup ?? en1 v) normalize nodelta
2274          [ 1: #Hlookup2 >Hlookup2 normalize nodelta
2275               lapply (rg_find_symbol … Hrelated v)
2276               cases (find_symbol ???) normalize
2277               [ 1: #_ #Habsurd destruct (Habsurd)
2278               | 2: #block cases (lookup ?? (symbols clight_fundef ge') v)
2279                    [ 1: normalize nodelta #Hfalse @(False_ind … Hfalse)
2280                    | 2: #block' normalize #Hvalue_eq #Heq destruct (Heq)
2281                         %{〈block',mk_offset (zero offset_size),[]〉} @conj try @refl
2282                         normalize /2/
2283                ] ]
2284         | 2: #block
2285              cases (lookup ?? en2 v) normalize nodelta
2286              [ 1: #Hfalse @(False_ind … Hfalse)
2287              | 2: #b * #Hvalid_block #Hvalue_eq #Heq destruct (Heq)
2288                   %{〈b, zero_offset, E0〉} @conj try @refl
2289                   normalize /2/
2290    ] ] ]
2291| 5: #e #ty whd in ⊢ (% → %);
2292     whd in match (exec_lvalue' ?????);
2293     whd in match (exec_lvalue' ?????);
2294     cases (exec_expr ge en1 m1 e)
2295     [ 1: * #v1 #tr1 #H elim (H 〈v1,tr1〉 (refl ??)) * #v1' #tr1' * #Heq >Heq normalize nodelta
2296          * elim v1 normalize nodelta
2297          [ 1: #_ #_ #a1 #Habsurd destruct (Habsurd)
2298          | 2: #sz #i #_ #_ #a1  #Habsurd destruct (Habsurd)
2299          | 3: #fl #_ #_ #a1 #Habsurd destruct (Habsurd)
2300          | 4: #_ #_ #a1 #Habsurd destruct (Habsurd)
2301          | 5: #ptr #Hvalue_eq lapply (value_eq_ptr_inversion … Hvalue_eq) * #p2 * #Hp2_eq
2302               >Hp2_eq in Hvalue_eq; elim ptr #b1 #o1 elim p2 #b2 #o2
2303               #Hvalue_eq normalize
2304               cases (E b1) [ 1: normalize in ⊢ (% → ?); #Habsurd destruct (Habsurd) ]
2305               * #b2' #o2' normalize #Heq destruct (Heq) #Htrace destruct (Htrace)
2306               * * #b1' #o1' #tr1'' #Heq2 destruct (Heq2) normalize
2307               %{〈b2,mk_offset (addition_n ? (offv o1') (offv o2')),tr1''〉} @conj try @refl
2308               normalize @conj // ]
2309     | 2: #error #_ normalize #a1 #Habsurd destruct (Habsurd) ]
2310| 6: #ty #e #ty'
2311     #Hsim @(exec_lvalue_expr_elim … Hsim)
2312     cases ty
2313     [ 1: | 2: #sz #sg | 3: #fl | 4: #ty | 5: #ty #n | 6: #tl #ty | 7: #id #fl | 8: #id #fl | 9: #ty ]
2314     * #b1 #o1 * #b2 #o2 normalize nodelta try /2 by I/
2315     #tr #H @conj try @refl try assumption
2316| 7: #ty #op #e
2317     #Hsim @(exec_expr_expr_elim … Hsim) #v1 #v2 #trace #Hvalue_eq
2318     lapply (unary_operation_value_eq E op v1 v2 (typeof e) Hvalue_eq)
2319     cases (sem_unary_operation op v1 (typeof e)) normalize nodelta
2320     [ 1: #_ @I
2321     | 2: #r1 #H elim (H r1 (refl ??)) #r1' * #Heq >Heq
2322           normalize /2/ ]
2323| 8: #ty #op #e1 #e2 #Hsim1 #Hsim2
2324     @(exec_expr_expr_elim … Hsim1) #v1 #v2 #trace #Hvalue_eq
2325     cases (exec_expr ge en1 m1 e2) in Hsim2;
2326     [ 2: #error // ]
2327     * #val #trace normalize in ⊢ (% → ?); #Hsim2
2328     elim (Hsim2 ? (refl ??)) * #val2 #trace2 * #Hexec2 * #Hvalue_eq2 #Htrace >Hexec2
2329     whd in match (m_bind ?????); whd in match (m_bind ?????);
2330     lapply (binary_operation_value_eq E op … (typeof e1) (typeof e2) ?? Hvalue_eq Hvalue_eq2 (me_inj … Hext))
2331     cases (sem_binary_operation op v1 (typeof e1) val (typeof e2) m1)
2332     [ 1: #_ // ]
2333     #opval #Hop elim (Hop ? (refl ??)) #opval' * #Hopval_eq  #Hvalue_eq_opval
2334     >Hopval_eq normalize destruct /2 by conj/
2335| 9: #ty #cast_ty #e #Hsim @(exec_expr_expr_elim … Hsim)
2336     #v1 #v2 #trace #Hvalue_eq lapply (cast_value_eq E m1 m2 … Hvalue_eq (typeof e) cast_ty)
2337     cases (exec_cast m1 v1 (typeof e) cast_ty)
2338     [ 2: #error #_ normalize @I
2339     | 1: #res #H lapply (H res (refl ??)) whd in match (m_bind ?????);
2340          * #res' * #Hexec_cast >Hexec_cast #Hvalue_eq normalize nodelta
2341          @conj // ]
2342| 10: #ty #e1 #e2 #e3 #Hsim1 #Hsim2 #Hsim3
2343     @(exec_expr_expr_elim … Hsim1) #v1 #v2 #trace #Hvalue_eq
2344     lapply (bool_of_val_value_eq E v1 v2 Hvalue_eq (typeof e1))
2345     cases (exec_bool_of_val ? (typeof e1)) #b
2346     [ 2: #_ normalize @I ]
2347     #H lapply (H ? (refl ??)) #Hexec >Hexec normalize
2348     cases b normalize nodelta
2349     [ 1: (* true branch *)
2350          cases (exec_expr ge en1 m1 e2) in Hsim2;
2351          [ 2: #error normalize #_ @I
2352          | 1: * #e2v #e2tr normalize #H elim (H ? (refl ??))
2353               * #e2v' #e2tr' * #Hexec2 >Hexec2 * #Hvalue_eq2 #Htrace_eq2 normalize
2354                    destruct @conj try // ]
2355     | 2: (* false branch *)
2356          cases (exec_expr ge en1 m1 e3) in Hsim3;
2357          [ 2: #error normalize #_ @I
2358          | 1: * #e3v #e3tr normalize #H elim (H ? (refl ??))
2359               * #e3v' #e3tr' * #Hexec3 >Hexec3 * #Hvalue_eq3 #Htrace_eq3 normalize
2360               destruct @conj // ] ]
2361| 11,12: #ty #e1 #e2 #Hsim1 #Hsim2
2362     @(exec_expr_expr_elim … Hsim1) #v1 #v1' #trace #Hvalue_eq
2363     lapply (bool_of_val_value_eq E v1 v1' Hvalue_eq (typeof e1))     
2364     cases (exec_bool_of_val v1 (typeof e1))
2365     [ 2,4:  #error #_ normalize @I ]
2366     #b cases b #H lapply (H ? (refl ??)) #Heq >Heq
2367     whd in match (m_bind ?????);
2368     whd in match (m_bind ?????);
2369     [ 2,3: normalize @conj try @refl try @vint_eq ]
2370     cases (exec_expr ge en1 m1 e2) in Hsim2;
2371     [ 2,4: #error #_ normalize @I ]
2372     * #v2 #tr2 whd in ⊢ (% → %); #H2 normalize nodelta elim (H2 ? (refl ??))
2373     * #v2' #tr2' * #Heq2 * #Hvalue_eq2 #Htrace2 >Heq2 normalize nodelta
2374     lapply (bool_of_val_value_eq E v2 v2' Hvalue_eq2 (typeof e2))
2375     cases (exec_bool_of_val v2 (typeof e2))
2376     [ 2,4: #error #_ normalize @I ]
2377     #b2 #H3 lapply (H3 ? (refl ??)) #Heq3 >Heq3 normalize nodelta
2378     destruct @conj try @conj //
2379     cases b2 whd in match (of_bool ?); @vint_eq
2380| 13: #ty #ty' cases ty
2381     [ 1: | 2: #sz #sg | 3: #fl | 4: #ty | 5: #ty #n
2382     | 6: #tl #ty | 7: #id #fl | 8: #id #fl | 9: #ty ]
2383     whd in match (exec_expr ????); whd
2384     * #v #trace #Heq destruct %{〈Vint sz (repr sz (sizeof ty')), E0〉}
2385     @conj try @refl @conj //
2386| 14: #ty #ed #aggregty #i #Hsim whd * * #b #o #tr normalize nodelta
2387    whd in match (exec_lvalue' ?????);
2388    whd in match (exec_lvalue' ge' en2 m2 (Efield (Expr ed aggregty) i) ty);
2389    whd in match (typeof ?);
2390    cases aggregty in Hsim;
2391    [ 1: | 2: #sz' #sg' | 3: #fl' | 4: #ty' | 5: #ty' #n'
2392    | 6: #tl' #ty' | 7: #id' #fl' | 8: #id' #fl' | 9: #ty' ]
2393    normalize nodelta #Hsim
2394    [ 1,2,3,4,5,6,9: #Habsurd destruct (Habsurd) ]
2395    whd in match (m_bind ?????);
2396    whd in match (m_bind ?????);
2397    whd in match (exec_lvalue ge en1 m1 (Expr ed ?));
2398    cases (exec_lvalue' ge en1 m1 ed ?) in Hsim;
2399    [ 2,4: #error #_ normalize in ⊢ (% → ?); #Habsurd destruct (Habsurd) ]
2400    * * #b1 #o1 #tr1 whd in ⊢ (% → ?); #H elim (H ? (refl ??))
2401    * * #b1' #o1' #tr1' * #Hexec normalize nodelta * #Hvalue_eq #Htrace_eq
2402    whd in match (exec_lvalue ????); >Hexec normalize nodelta
2403    [ 2: #Heq destruct (Heq) %{〈 b1',o1',tr1'〉} @conj //
2404         normalize @conj // ]
2405    cases (field_offset i fl')
2406    [ 2: #error normalize #Habsurd destruct (Habsurd) ]
2407    #offset whd in match (m_bind ?????); #Heq destruct (Heq)
2408    whd in match (m_bind ?????);
2409    %{〈b1',shift_offset (bitsize_of_intsize I32) o1' (repr I32 offset),tr1'〉} @conj
2410    destruct // normalize nodelta @conj try @refl @vptr_eq
2411    -H lapply (value_eq_ptr_inversion … Hvalue_eq) * #p2 * #Hptr_eq
2412    whd in match (pointer_translation ??);     
2413    whd in match (pointer_translation ??);
2414    cases (E b)
2415    [ 1: normalize nodelta #Habsurd destruct (Habsurd) ]
2416    * #b' #o' normalize nodelta #Heq destruct (Heq) destruct (Hptr_eq)
2417    cut (offset_plus (mk_offset (addition_n offset_size
2418                                      (offv o1)
2419                                      (sign_ext (bitsize_of_intsize I32) offset_size (repr I32 offset)))) o'
2420          = (shift_offset (bitsize_of_intsize I32) (offset_plus o1 o') (repr I32 offset)))
2421    [ whd in match (shift_offset ???) in ⊢ (???%);
2422      whd in match (offset_plus ??) in ⊢ (??%%);
2423      /3 by associative_addition_n, commutative_addition_n, refl/ ]
2424    #Heq >Heq @refl
2425| 15: #ty #l #e #Hsim
2426     @(exec_expr_expr_elim … Hsim) #v1 #v2 #trace #Hvalue_eq normalize nodelta @conj //
2427| 16: *
2428  [ 1: #sz #i | 2: #fl | 3: #var_id | 4: #e1 | 5: #e1 | 6: #op #e1 | 7: #op #e1 #e2 | 8: #cast_ty #e1
2429  | 9: #cond #iftrue #iffalse | 10: #e1 #e2 | 11: #e1 #e2 | 12: #sizeofty | 13: #e1 #field | 14: #cost #e1 ]
2430  #ty normalize in ⊢ (% → ?);
2431  [ 3,4,13: @False_ind
2432  | *: #_ normalize #a1 #Habsurd destruct (Habsurd) ]
2433] qed. *)
Note: See TracBrowser for help on using the repository browser.