source: src/Clight/memoryInjections.ma @ 2448

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

Comitting current state of switch removal.

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