# source:src/Clight/SimplifyCasts.ma@2332

Last change on this file since 2332 was 2219, checked in by campbell, 8 years ago

Speed up cast simplification proof checking a bit.

File size: 151.4 KB
Line
1include "Clight/Csyntax.ma".
2include "Clight/TypeComparison.ma".
3
4(* IG: used to prove preservation of the semantics. *)
5include "Clight/Cexec.ma".
6include "Clight/casts.ma".
7include "Clight/CexecSound.ma".
8
9
10(* include "ASM/AssemblyProof.ma". *) (* I had to manually copy some of the lemmas in this file, including an axiom ... *)
11
12(* Attempt to remove unnecessary integer casts in Clight programs.
13
14   This differs from the OCaml prototype by attempting to recursively determine
15   whether subexpressions can be changed rather than using a fixed size pattern.
16   As a result more complex expressions such as (char)((int)x + (int)y + (int)z)
17   where x,y and z are chars can be simplified.
18
19   A possible improvement that doesn't quite fit into this scheme would be to
20   spot that casts can be removed in expressions like (int)x == (int)y where
21   x and y have some smaller integer type.
22 *)
23
24(* Attempt to squeeze integer constant into a given type.
25
26   This might be too conservative --- if we're going to cast it anyway, can't
27   I just ignore the fact that the integer doesn't fit?
28*)
29
30(* [reduce_bits n m exp v] takes avector of size n + m + 1 and returns (if all goes well) a vector of size
31 *  m+1 (an empty vector of bits makes no sense). It proceeds by removing /all/ the [n] leading bits equal
32 * to [exp]. If it fails, it returns None. *)
33let rec reduce_bits (n,m:nat) (exp:bool) (v:BitVector (plus n (S m))) on n : option (BitVector (S m)) ≝
34match n return λn. BitVector (n+S m) → option (BitVector (S m)) with
35[ O ⇒ λv. Some ? v
36| S n' ⇒ λv. if eq_b (head' ?? v) exp then reduce_bits ?? exp (tail ?? v) else None ?
37] v.
38
39lemma reduce_bits_ok : ∀n,m.∀exp.∀v,v'. reduce_bits (S n) m exp v = Some ? v'→ reduce_bits n m exp (tail ?? v) = Some ? v'.
40#n #m #exp #v #v' #H whd in H:(??%?); lapply H -H
41cases (eq_b ? exp)
42[ 1: #H whd in H:(??%?); //
43| 2: #H normalize in H; destruct ] qed.
44
45lemma reduce_bits_trunc : ∀n,m.∀exp.∀v:(BitVector (plus n (S m))).∀v'.
46  reduce_bits n m exp v = Some ? v' → v' = truncate n (S m) v.
47#n #m elim n
48[ 1: #exp #v #v' #H normalize in v v' H; destruct normalize >vsplit_O_n //
49| 2: #n' #Hind #exp #v #v' #H >truncate_tail
50 > (Hind ??? (reduce_bits_ok ?? exp v v' H)) // ] qed.
51
52lemma reduce_bits_dec : ∀n,m.∀exp.∀v. (∃v'.reduce_bits n m exp v = Some ? v') ∨ reduce_bits n m exp v = None ?.
53#n #m #exp #v elim (reduce_bits n m exp v)
54[ 1: %2 //
55| 2: #v' %1 @(ex_intro … v') // ] qed.
56
57(* pred_bitsize_of_intsize I32 = 31, … *)
58definition pred_bitsize_of_intsize : intsize → nat ≝
59λsz. pred (bitsize_of_intsize sz).
60
61definition signed : signedness → bool ≝
62λsg. match sg with [ Unsigned ⇒ false | Signed ⇒ true ].
63
64(* [simplify_int sz sz' sg sg' i] tries to convert an integer [i] of width [sz] and signedness [sg]
65 * into an integer of size [sz'] of signedness [sg'].
66 * - It first proceeds by comparing the source and target width: if the target width is strictly superior
67 *   to the source width, the conversion fails.
68 * - If the size is equal, the argument is returned as-is.
69 * - If the target type is strictly smaller than the source, it tries to squeeze the integer to
70 *   the desired size.
71*)
72let rec simplify_int (sz,sz':intsize) (sg,sg':signedness) (i:bvint sz) : option (bvint sz') ≝
73  let bit ≝ signed sg ∧ head' … i in
74  (* [nat_compare] does more than an innocent post-doc might think. It also computes the difference between the two args.
75   * if x < y, nat_compare x y = lt(x, y-(x+1))
76   * if x = y, nat_compare x y = eq x
77   * if x > y, nat_compare x y = gt(x-(y+1), y) *)
78  match nat_compare (pred_bitsize_of_intsize sz) (pred_bitsize_of_intsize sz')
79      return λn,m,x.BitVector (S n) → option (BitVector (S m)) with
80  [ nat_lt _ _ ⇒ λi. None ?   (* refuse to make constants larger *)
81  | nat_eq _ ⇒ λi. Some ? i
82  | nat_gt x y ⇒ λi.
83      (* Here, we have [x]=31-([y]+1) and [y] ∈ {15; 7} OR [x] = 15-(7+1) and [y] = 7. I.e.: x=15,y=15 or x=23,y=7 or x=7,y=7.
84       * In [reduce_bits n m bit i], [i] is supposed to have type BitVector n + (S m). Since its type is here (S x) + (S y),
85       * we deduce that the actual arguments of [reduce_bits] are (S x) and (S y), which is consistent.
86       * If [i] is of signed type and if it is negative, then it tries to remove the (S x) first "1" bits.
87       * Otherwise, it tries to remove the (S x) first "0" bits.
88       *)
89      match reduce_bits ?? bit (i⌈BitVector (S (y+S x))↦BitVector ((S x) + (S y))⌉) with
90      [ Some i' ⇒
91        if signed sg' then
92          if eq_b bit (head' … i') then
93            Some ? i'
94          else None ?
95        else Some ? i'
96      | None ⇒ None ?
97      ]
98  ] i.
99>(commutative_plus_faster (S x)) @refl
100qed.
101
102
103lemma eq_intsize_identity : ∀id. eq_intsize id id = true.
104* normalize //
105qed.
106
107lemma sz_eq_identity : ∀s. sz_eq_dec s s = inl ?? (refl ? s).
108* normalize //
109qed.
110
111lemma type_eq_identity : ∀t. type_eq t t = true.
112#t normalize elim (type_eq_dec t t)
113[ 1: #Heq normalize //
114| 2: #H destruct elim H #Hcontr elim (Hcontr (refl ? t)) ] qed.
115
116lemma type_neq_not_identity : ∀t1, t2. t1 ≠ t2 → type_eq t1 t2 = false.
117#t1 #t2 #Hneq normalize elim (type_eq_dec t1 t2)
118[ 1: #Heq destruct elim Hneq #Hcontr elim (Hcontr (refl ? t2))
119| 2: #Hneq' normalize // ] qed.
120
121definition size_le ≝ λsz1,sz2.
122match sz1 with
123[ I8 ⇒ True
124| I16 ⇒
125  match sz2 with
126  [ I16 ⇒ True | I32 ⇒ True | _ ⇒ False ]
127| I32 ⇒
128  match sz2 with
129  [ I32 ⇒ True | _ ⇒ False ]
130].
131
132definition size_lt ≝ λsz1,sz2.
133match sz1 with
134[ I8 ⇒
135  match sz2 with
136  [ I16 ⇒ True | I32 ⇒ True | _ ⇒ False ]
137| I16 ⇒
138  match sz2 with
139  [ I32 ⇒ True | _ ⇒ False ]
140| I32 ⇒ False
141].
142
143lemma size_lt_to_le : ∀sz1,sz2. size_lt sz1 sz2 → size_le sz1 sz2.
144#sz1 #sz2 elim sz1 elim sz2 normalize // qed.
145
146lemma size_lt_dec : ∀sz1,sz2. size_lt sz1 sz2 + (¬ (size_lt sz1 sz2)).
147* * normalize /2/ /3/
148qed.
149
150lemma size_not_lt_to_ge : ∀sz1,sz2. ¬(size_lt sz1 sz2) → (sz1 = sz2) + (size_lt sz2 sz1).
151* * normalize /2/ /3/
152qed.
153
154(* This function already exists in prop, we want it in type. *)
155definition sign_eq_dect : ∀sg1,sg2:signedness. (sg1 = sg2) + (sg1 ≠ sg2).
156* * normalize // qed.
157
158lemma size_absurd : ∀a,b. size_le a b → size_lt b a → False.
159* * normalize
160#H1 #H2 try (@(False_ind … H1)) try (@(False_ind … H2)) qed.
161
162(* This defines necessary conditions for [src_expr] to be coerced to "target_ty".
163 * Again, these are /not/ sufficient conditions. See [simplify_inv] for the rest. *)
164definition necessary_conditions ≝ λsrc_sz.λsrc_sg.λtarget_sz.λtarget_sg.
165match size_lt_dec target_sz src_sz with
166[ inl Hlt ⇒ true
167| inr Hnlt ⇒
168  match sz_eq_dec target_sz src_sz with
169  [ inl Hsz_eq ⇒
170    match sign_eq_dect src_sg target_sg with
171    [ inl Hsg_eq ⇒ false
172    | inr Hsg_neq ⇒ true
173    ]
174  | inr Hsz_neq ⇒ false
175  ]
176].
177
178(* Inversion on necessary_conditions *)
179lemma necessary_conditions_spec :
180  ∀src_sz,src_sg,target_sz, target_sg. (necessary_conditions src_sz src_sg target_sz target_sg = true) →
181      ((size_lt target_sz src_sz) ∨ (src_sz = target_sz ∧ src_sg ≠ target_sg)).
182#src_sz #src_sg #target_sz #target_sg
183whd in match (necessary_conditions ????);
184cases (size_lt_dec target_sz src_sz) normalize nodelta
185[ 1: #Hlt #_ %1 //
186| 2: #Hnlt
187     cases (sz_eq_dec target_sz src_sz) normalize nodelta
188     [ 2: #_ #Hcontr destruct
189     | 1: #Heq cases (sign_eq_dect src_sg target_sg) normalize nodelta
190       [ 1: #_ #Hcontr destruct
191       | 2: #Hsg_neq #_ %2 destruct /2/ ]
192     ]
193] qed.
194
195(* Compare the results [r1,r2] of the evaluation of two expressions. If [r1] is an
196 * integer value smaller but containing the same stuff than [r2] then all is well.
197 * If the first evaluation is erroneous, we don't care about anything else. *)
198definition smaller_integer_val ≝ λsrc_sz,dst_sz,sg. λr1,r2:res(val×trace).
199match r1 with
200[ OK res1 ⇒
201  let 〈val1, tr1〉 ≝ res1 in
202  ∀v1. val1 = Vint src_sz v1 →
203  match r2 with
204  [ OK res2 ⇒
205    let 〈val2, tr2〉 ≝ res2 in
206    ∃v2. (val2 = Vint dst_sz v2 ∧
207          v2 = cast_int_int src_sz sg dst_sz v1 ∧ tr1 = tr2 ∧ size_le dst_sz src_sz)
208  | _ ⇒ False ]
209| Error errmsg1 ⇒ True
210].
211
212(* Simulation relation used for expression evaluation. *)
213inductive res_sim (A : Type[0]) (r1 : res A) (r2 : res A) : Prop ≝
214| SimOk   :  (∀a:A. r1 = OK ? a → r2 = OK ? a) → res_sim A r1 r2
215| SimFail : (∃err. r1 = Error ? err) → res_sim A r1 r2.
216
217(* Trick to reduce checking time by eliminating a load of costly automation.
218   It would be nice to do this by refactoring the type and code instead, but we
219   don't want to spend lots of time on something that already works. *)
220
221lemma SimFailNicely : ∀A,err,r2. res_sim A (Error ? err) r2.
222#A #err #r2 @SimFail %{err} %
223qed.
224
225(* Invariant of simplify_expr *)
226inductive simplify_inv (ge : genv) (en : env) (m : mem) (e1 : expr) (e2 : expr) (target_sz : intsize) (target_sg : signedness) : bool → Prop ≝
227(* Inv_eq states a standard simulation result. We enforce some needed equations on types to prove the cast cases. *)
228| Inv_eq : ∀result_flag.
229     result_flag = false →
230     typeof e1 = typeof e2 →
231     res_sim ? (exec_expr ge en m e1) (exec_expr ge en m e2) →
232     res_sim ? (exec_lvalue ge en m e1) (exec_lvalue ge en m e2) →
233     simplify_inv ge en m e1 e2 target_sz target_sg result_flag
234(* Inv_coerce_ok states that we successfuly squeezed the source expression to [target_sz]. The details are hidden in [smaller_integer_val]. *)
235| Inv_coerce_ok : ∀src_sz,src_sg.
236     (typeof e1) = (Tint src_sz src_sg) →
237     (typeof e2) = (Tint target_sz target_sg) →
238     (smaller_integer_val src_sz target_sz src_sg (exec_expr ge en m e1) (exec_expr ge en m e2)) →
239     simplify_inv ge en m e1 e2 target_sz target_sg true.
240
241(* Invariant of simplify_inside *)
242definition conservation ≝ λe,result:expr.
243∀ge,en,m. res_sim ? (exec_expr ge en m e) (exec_expr ge en m result)
244                                                    ∧ res_sim ? (exec_lvalue ge en m e) (exec_lvalue ge en m result)
245                                                    ∧ typeof e = typeof result.
246
247(* This lemma proves that simplify_int actually implements an integer cast. *)
248(* The case 4 can be merged with cases 7 and 8. *)
249
250lemma simplify_int_implements_cast : ∀sz,sz'.∀sg,sg'.∀i,i'. simplify_int sz sz' sg sg' i = Some ? i' → i' = cast_int_int sz sg sz' i.
251* *
252[ 1: #sg #sg' #i #i' #Hsimp normalize in Hsimp ⊢ %; elim sg normalize destruct //
253| 2,3,6: #sg #sg' #i #i' #Hsimp normalize in Hsimp; destruct (* ⊢ %; destruct destruct  whd in Hsimp:(??%?); destruct *)
254| 4: * * #i #i' #Hsimp whd in Hsimp:(??%?) ⊢ (??%?); normalize nodelta in Hsimp; normalize in i i' ⊢ %;
255    normalize in match (signed ?) in Hsimp;
256    normalize in match (S (plus ??)) in Hsimp;
257    normalize in match (plus 7 8) in Hsimp;
258    lapply Hsimp -Hsimp
259    cases (head' bool 15 i)
260    normalize in match (andb ??);
261    [ 1,3: elim (reduce_bits_dec 8 7 true i)
262      [ 1,3: * #v' #Heq >Heq letin Heq_trunc ≝ (reduce_bits_trunc … Heq) normalize nodelta
263        [ 1: cases (eq_b true ?) normalize #H destruct normalize @refl
264        | 2: #H destruct normalize @refl ]
265      | 2,4: #Heq >Heq normalize nodelta #H destruct ]
266    | 2,4,5,6,7,8:
267      elim (reduce_bits_dec 8 7 false i)
268      [ 1,3,5,7,9,11: * #v' #Heq >Heq normalize nodelta letin Heq_trunc ≝ (reduce_bits_trunc … Heq)
269        [ 1,3,4: cases (eq_b false ?) normalize nodelta
270         #H destruct normalize @refl
271        | 2,5,6: #H destruct normalize @refl ]
272      | 2,4,6,8,10,12: #Heq >Heq normalize nodelta #H destruct
273      ]
274    ]
275| 5,9: * * #i #i' #Hsimp whd in Hsimp:(??%?) ⊢ (??%?); destruct @refl
276| 7, 8: * * #i #i' #Hsimp whd in Hsimp:(??%?) ⊢ (??%?); normalize nodelta in Hsimp; normalize in i i' ⊢ %;
277    normalize in match (signed ?) in Hsimp;
278    normalize in match (S (plus ??)) in Hsimp;
279    normalize in match (plus 7 24) in Hsimp;
280    lapply Hsimp -Hsimp
281    cases (head' bool ? i)
282    normalize in match (andb ??);
283    [ 1,3,9,11:
284      [ 1,2: (elim (reduce_bits_dec 24 7 true i)) | 3,4: (elim (reduce_bits_dec 16 15 true i)) ]
285      [ 1,3,5,7: * #v' #Heq >Heq letin Heq_trunc ≝ (reduce_bits_trunc … Heq) normalize nodelta
286        [ 1,3: cases (eq_b true ?) normalize #H destruct normalize @refl
287        | 2,4: #H destruct normalize @refl ]
288      | 2,4,6,8: #Heq >Heq normalize nodelta #H destruct ]
289    | 2,4,5,6,7,8,10,12,13,14,15,16:
290      [ 1,2,3,4,5,6: elim (reduce_bits_dec 24 7 false i)
291      | 6,7,8,9,10,11,12: elim (reduce_bits_dec 16 15 false i) ]
292      [ 1,3,5,7,9,11,13,15,17,19,21,23:
293        * #v' #Heq >Heq normalize nodelta letin Heq_trunc ≝ (reduce_bits_trunc … Heq)
294        [ 1,3,4,7,9,10:
295          cases (eq_b false ?) normalize nodelta #H destruct normalize @refl
296        | 2,5,6,8,11,12: #H destruct normalize @refl ]
297      | 2,4,6,8,10,12,14,16,18,20,22,24: #Heq >Heq normalize nodelta #H destruct
298      ]
299    ]
300] qed.
301
303
304(* copied from AssemblyProof *)
305lemma Vector_O: ∀A. ∀v: Vector A 0. v ≃ VEmpty A.
306 #A #v generalize in match (refl … 0); cases v in ⊢ (??%? → ?%%??); //
307 #n #hd #tl #abs @⊥ destruct (abs)
308qed.
309
310lemma Vector_Sn: ∀A. ∀n.∀v:Vector A (S n).
311 ∃hd.∃tl.v ≃ VCons A n hd tl.
312 #A #n #v generalize in match (refl … (S n)); cases v in ⊢ (??%? → ??(λ_.??(λ_.?%%??)));
313 [ #abs @⊥ destruct (abs)
314 | #m #hd #tl #EQ <(injective_S … EQ) %[@hd] %[@tl] // ]
315qed.
316
317lemma vector_append_zero:
318  ∀A,m.
319  ∀v: Vector A m.
320  ∀q: Vector A 0.
321    v = q@@v.
322  #A #m #v #q
323  >(Vector_O A q) %
324qed.
325
326corollary prod_vector_zero_eq_left:
327  ∀A, n.
328  ∀q: Vector A O.
329  ∀r: Vector A n.
330    〈q, r〉 = 〈[[ ]], r〉.
331  #A #n #q #r
332  generalize in match (Vector_O A q …);
333  #hyp
334  >hyp in ⊢ (??%?);
335  %
336qed.
337
338lemma vsplit_eq : ∀A. ∀m,n. ∀v : Vector A ((S m) + n).  ∃v1:Vector A (S m). ∃v2:Vector A n. v = v1 @@ v2.
339# A #m #n elim m
340[ 1: normalize #v
341  elim (Vector_Sn ?? v) #hd * #tl #Eq
342  @(ex_intro … (hd ::: [[]])) @(ex_intro … tl)
343  >Eq normalize //
344| 2: #n' #Hind #v
345  elim (Vector_Sn ?? v) #hd * #tl #Eq
346  elim (Hind tl)
347  #tl1 * #tl2 #Eq_tl
348  @(ex_intro … (hd ::: tl1))
349  @(ex_intro … tl2)
350  destruct normalize //
351] qed.
352
353lemma vsplit_eq2 : ∀A. ∀m,n : nat. ∀v : Vector A (m + n).  ∃v1:Vector A m. ∃v2:Vector A n. v = v1 @@ v2.
354# A #m #n elim m
355[ 1: normalize #v @(ex_intro … (VEmpty ?)) @(ex_intro … v) normalize //
356| 2: #n' #Hind #v
357  elim (Vector_Sn ?? v) #hd * #tl #Eq
358  elim (Hind tl)
359  #tl1 * #tl2 #Eq_tl
360  @(ex_intro … (hd ::: tl1))
361  @(ex_intro … tl2)
362  destruct normalize //
363] qed.
364
365lemma vsplit_zero:
366  ∀A,m.
367  ∀v: Vector A m.
368    〈[[]], v〉 = vsplit A 0 m v.
369  #A #m #v
370  elim v
371  [ %
372  | #n #hd #tl #ih
373    normalize in ⊢ (???%); %
374  ]
375qed.
376
377
378lemma vsplit_zero2:
379  ∀A,m.
380  ∀v: Vector A m.
381    〈[[]], v〉 = vsplit' A 0 m v.
382  #A #m #v
383  elim v
384  [ %
385  | #n #hd #tl #ih
386    normalize in ⊢ (???%); %
387  ]
388qed.
389
390(* This is not very nice. Note that this axiom was copied verbatim from ASM/AssemblyProof.ma.
391 * TODO sync with AssemblyProof.ma, in a better world we shouldn't have to copy all of this. *)
392axiom vsplit_succ:
393  ∀A, m, n.
394  ∀l: Vector A m.
395  ∀r: Vector A n.
396  ∀v: Vector A (m + n).
397  ∀hd.
398    v = l@@r → (〈l, r〉 = vsplit ? m n v → 〈hd:::l, r〉 = vsplit ? (S m) n (hd:::v)).
399
400axiom vsplit_succ2:
401  ∀A, m, n.
402  ∀l: Vector A m.
403  ∀r: Vector A n.
404  ∀v: Vector A (m + n).
405  ∀hd.
406    v = l@@r → (〈l, r〉 = vsplit' ? m n v → 〈hd:::l, r〉 = vsplit' ? (S m) n (hd:::v)).
407
408lemma vsplit_prod2:
409  ∀A,m,n.
410  ∀p: Vector A (m + n).
411  ∀v: Vector A m.
412  ∀q: Vector A n.
413    p = v@@q → 〈v, q〉 = vsplit' A m n p.
414  #A #m
415  elim m
416  [ #n #p #v #q #hyp
417    >hyp <(vector_append_zero A n q v)
418    >(prod_vector_zero_eq_left A …)
419    @vsplit_zero2
420  | #r #ih #n #p #v #q #hyp
421    >hyp
422    cases (Vector_Sn A r v)
423    #hd #exists
424    cases exists
425    #tl #jmeq >jmeq
426    @vsplit_succ2 [1: % |2: @ih % ]
427  ]
428qed.
429
430lemma vsplit_prod:
431  ∀A,m,n.
432  ∀p: Vector A (m + n).
433  ∀v: Vector A m.
434  ∀q: Vector A n.
435    p = v@@q → 〈v, q〉 = vsplit A m n p.
436  #A #m
437  elim m
438  [ #n #p #v #q #hyp
439    >hyp <(vector_append_zero A n q v)
440    >(prod_vector_zero_eq_left A …)
441    @vsplit_zero
442  | #r #ih #n #p #v #q #hyp
443    >hyp
444    cases (Vector_Sn A r v)
445    #hd #exists
446    cases exists
447    #tl #jmeq >jmeq
448    @vsplit_succ [1: % |2: @ih % ]
449  ]
450qed.
451
452lemma cast_decompose : ∀s1, v. cast_int_int I32 s1 I8 v = (cast_int_int I16 s1 I8 (cast_int_int I32 s1 I16 v)).
453#s1 #v normalize elim s1 normalize nodelta
454normalize in v;
455elim (vsplit_eq ??? (v⌈Vector bool 32 ↦ Vector bool (16 + 16)⌉))
456[ 2,4: //
457| 1,3: #l * #r normalize nodelta #Eq1
458       <(vsplit_prod bool 16 16 … Eq1)
459       elim (vsplit_eq ??? (r⌈Vector bool 16 ↦ Vector bool (8 + 8)⌉))
460       [ 2,4: //
461       | 1,3: #lr * #rr normalize nodelta #Eq2
462              <(vsplit_prod bool 8 8 … Eq2)
463              cut (v = (l @@ lr) @@ rr)
464              [ 1,3 : destruct >(vector_associative_append ? 16 8) //
465              | 2,4: #Hrewrite destruct
466                     <(vsplit_prod bool 24 8 … Hrewrite) @refl
467              ]
468       ]
469] qed.
470
471lemma cast_idempotent : ∀s1,s2,sz1,sz2,v. size_lt sz1 sz2 → cast_int_int sz2 s1 sz1 (cast_int_int sz1 s2 sz2 v) = v.
472#s1 #s2 * * #v elim s1 elim s2
473normalize #H try @refl
474@(False_ind … H)
475qed.
476
477lemma cast_identity : ∀sz,sg,v. cast_int_int sz sg sz v = v.
478* * #v normalize // qed.
479
480lemma cast_collapse : ∀s1,s2,v. cast_int_int I32 s1 I8 (cast_int_int I16 s2 I32 v) = (cast_int_int I16 s1 I8 v).
481#s1 #s2 #v >cast_decompose >cast_idempotent
482[ 1: @refl | 2: // ]
483qed.
484
485lemma cast_composition_lt : ∀a_sz,a_sg, b_sz, b_sg, c_sz, val.
486   size_lt c_sz a_sz → size_lt c_sz b_sz →
487   (cast_int_int a_sz a_sg c_sz val =
488        cast_int_int b_sz b_sg c_sz (cast_int_int a_sz a_sg b_sz val)).
489* #a_sg * #b_sg * #val whd in match (size_lt ??); whd in match (size_lt ??);
490#Hlt1 #Hlt2
491[ 1,2,3,4,5,6,7,8,9,10,11,12,14,15,17,18,19,20,21,23,24,27:
492  @(False_ind … Hlt1) @(False_ind … Hlt2)
493| 13,25,26: >cast_identity elim a_sg elim b_sg normalize //
494| 22: normalize elim b_sg elim a_sg normalize
495      normalize in val;
496      elim (vsplit_eq ??? (val⌈Vector bool 32 ↦ Vector bool (16 + 16)⌉))
497      [ 2,4,6,8: normalize //
498      | 1,3,5,7: #left * #right normalize #Eq1
499                 <(vsplit_prod bool 16 16 … Eq1)
500                 elim (vsplit_eq ??? (right⌈Vector bool 16 ↦ Vector bool (8 + 8)⌉))
501                 [ 2,4,6,8: //
502                 | 1,3,5,7: #rightleft * #rightright normalize #Eq2
503                            <(vsplit_prod bool 8 8 … Eq2)
504                            cut (val = (left @@ rightleft) @@ rightright)
505                            [ 1,3,5,7: destruct >(vector_associative_append ? 16 8) //
506                            | 2,4,6,8: #Hrewrite destruct
507                                       <(vsplit_prod bool 24 8 … Hrewrite) @refl
508                            ]
509                 ]
510     ]
511| 16: elim b_sg elim a_sg >cast_collapse @refl
512] qed.
513
514lemma cast_composition : ∀a_sz,a_sg, b_sz, b_sg, c_sz, val.
515   size_le c_sz a_sz → size_le c_sz b_sz →
516   (cast_int_int a_sz a_sg c_sz val =
517        cast_int_int b_sz b_sg c_sz (cast_int_int a_sz a_sg b_sz val)).
518#a_sz #a_sg #b_sz #b_sg #c_sz #val #Hle_c_a #Hle_c_b
519cases (size_lt_dec c_sz a_sz)
520cases (size_lt_dec c_sz b_sz)
521[ 1: #Hltb #Hlta @(cast_composition_lt … Hlta Hltb)
522| 2: #Hnltb #Hlta
523  cases (size_not_lt_to_ge  … Hnltb)
524  [ 1: #Heq destruct >cast_identity //
525  | 2: #Hltb @(False_ind … (size_absurd ?? Hle_c_b Hltb))
526  ]
527| 3: #Hltb #Hnlta
528  cases (size_not_lt_to_ge  … Hnlta)
529  [ 1: #Heq destruct >cast_idempotent //
530  | 2: #Hlta @(False_ind … (size_absurd ?? Hle_c_a Hlta))
531  ]
532| 4: #Hnltb #Hnlta
533  cases (size_not_lt_to_ge  … Hnlta)
534  cases (size_not_lt_to_ge  … Hnltb)
535  [ 1: #Heq_b #Heq_a destruct >cast_identity >cast_identity //
536  | 2: #Hltb #Heq @(False_ind … (size_absurd ?? Hle_c_b Hltb))
537  | 3: #Eq #Hlta @(False_ind … (size_absurd ?? Hle_c_a Hlta))
538  | 4: #Hltb #Hlta @(False_ind … (size_absurd ?? Hle_c_a Hlta))
539  ]
540] qed.
541
542let rec assert_int_value (v : option val) (expected_size : intsize) : option (BitVector (bitsize_of_intsize expected_size)) ≝
543match v with
544[ None ⇒ None ?
545| Some v ⇒
546  match v with
547  [ Vint sz i ⇒
548    match sz_eq_dec sz expected_size with
549    [ inl Heq ⇒ Some ??
550    | inr _ ⇒ None ?
551    ]
552  | _ ⇒ None ?
553  ]
554].
555>Heq in i; #i @i qed.
556
557(* cast_int_int behaves as truncate (≃ vsplit) when downsizing *)
558(* ∀src_sz,target_sz,sg. ∀i. size_le target_sz src_sz → cast_int_int src_sz sg target_sz i = truncate *)
559
560lemma vsplit_to_truncate : ∀m,n,i. (\snd  (vsplit bool m n i)) = truncate  m n i.
561#m #n #i normalize // qed.
562
563(* Somme lemmas on how "simplifiable" operations behave under cast_int_int. *)
564
565lemma integer_add_cast_lt : ∀src_sz,target_sz,sg. ∀lhs_int,rhs_int. size_lt target_sz src_sz →
567                                    (cast_int_int src_sz sg target_sz lhs_int)
568                                    (cast_int_int src_sz sg target_sz rhs_int)
569                             = cast_int_int src_sz sg target_sz (addition_n (bitsize_of_intsize src_sz) lhs_int rhs_int)).
570#src_sz #target_sz #sg #lhs_int #rhs_int #Hlt
571elim src_sz in Hlt lhs_int rhs_int; elim target_sz
572[ 1,2,3,5,6,9: normalize #H @(False_ind … H)
573| *: elim sg #_
574  normalize in match (bitsize_of_intsize ?);
575  normalize in match (bitsize_of_intsize ?);
576  #lint #rint
577  normalize in match (cast_int_int ????);
578  normalize in match (cast_int_int ????);
579  whd in match (addition_n ???);
580  whd in match (addition_n ???) in ⊢ (???%);
581  >vsplit_to_truncate >vsplit_to_truncate
583  [ 1,2: normalize in match (plus 8 8); generalize in match (add_with_carries ? lint rint false);
584  | 3,4: normalize in match (plus 24 8); generalize in match (add_with_carries ? lint rint false);
585  | 5,6: normalize in match (plus 16 16); generalize in match (add_with_carries ? lint rint false);
586  ]
587  * #result #carry
588  normalize nodelta //
589qed.
590
591lemma integer_add_cast_eq : ∀src_sz,target_sz,sg. ∀lhs_int,rhs_int. target_sz = src_sz →
593                                    (cast_int_int src_sz sg target_sz lhs_int)
594                                    (cast_int_int src_sz sg target_sz rhs_int)
595                             = cast_int_int src_sz sg target_sz (addition_n (bitsize_of_intsize src_sz) lhs_int rhs_int)).
596#src_sz #target_sz #sg #lhs_int #rhs_int #Heq destruct
597>cast_identity >cast_identity >cast_identity // qed.
598
599lemma integer_add_cast_le : ∀src_sz,target_sz,sg. ∀lhs_int,rhs_int. size_le target_sz src_sz →
601                                    (cast_int_int src_sz sg target_sz lhs_int)
602                                    (cast_int_int src_sz sg target_sz rhs_int)
603                             = cast_int_int src_sz sg target_sz (addition_n (bitsize_of_intsize src_sz) lhs_int rhs_int)).
604#src_sz #target_sz #sg #lhs_int #rhs_int #Hle
605cases (sz_eq_dec target_sz src_sz)
606[ 1: #Heq @(integer_add_cast_eq … Heq)
607| 2: #Hneq cut (size_lt target_sz src_sz)
608     [ 1: elim target_sz in Hle Hneq; elim src_sz normalize //
609           #_ * #H @(H … (refl ??))
610     | 2: #Hlt @(integer_add_cast_lt … Hlt)
611     ]
612] qed.
613
614lemma truncate_eat : ∀l,n,m,v. l = n → ∃tl. truncate (S n) m v = truncate l m tl.
615#l #n #m #v #len elim (Vector_Sn … v) #hd * #tl #Heq >len
616@(ex_intro … tl)
617>Heq >Heq
618elim (vsplit_eq2 … tl) #l * #r #Eq
619normalize
620 <(vsplit_prod bool n m tl l r Eq)
621 <(vsplit_prod2 bool n m tl l r Eq)
622 normalize //
623qed.
624
625
626lemma integer_neg_trunc : ∀m,n. ∀i: BitVector (m+n). two_complement_negation n (truncate m n i) = truncate m n (two_complement_negation (m+n) i).
627#m elim m
628[ 1: #n #i normalize in i;
629     whd in match (truncate ???);
630     whd in match (truncate ???) in ⊢ (???%);
631     <vsplit_zero <vsplit_zero //
632| 2: #m' #Hind #n #i normalize in i;
633     elim (Vector_Sn … i) #hd * #tl #Heq
634     whd in match (two_complement_negation (S ?) ?);
635     >Heq in ⊢ (??%?); >truncate_tail whd in match (tail ???) in ⊢ (??%?);
636     whd in match (two_complement_negation ??) in ⊢ (??%?);
637     lapply (Hind ? tl) #H
638     whd in match (two_complement_negation ??) in H;
639     (* trying to reduce add_with_carries *)
640     normalize in match (S m'+n);
641     whd in match (zero ?) in ⊢ (???%);
642     >Heq in match (negation_bv ??) in ⊢ (???%);
643     whd in match (negation_bv ??) in ⊢ (???%);
645     normalize in ⊢ (???%);
646     cases hd normalize nodelta
647     [ 1,2: <add_with_carries_unfold  in ⊢ (???%); (* Good. Some progress. *)
648          (* try to transform the rhs of H into what we need. *)
649          whd in match (two_complement_negation ??) in H:(???%);
650          lapply H -H
651          generalize in match (add_with_carries (m'+n) (negation_bv (m'+n) tl) (zero (m'+n)) true);
652          * #Left #Right normalize nodelta
653          #H generalize in ⊢ (???(???(????(???(match % with [ _ ⇒ ? | _ ⇒  ?])))));
654          #b >(vsplit_to_truncate (S m')) >truncate_tail
655          cases b
656          normalize nodelta
657          normalize in match (tail ???); @H
658     ]
659] qed. (* This was painful. *)
660
661lemma integer_sub_cast_lt : ∀src_sz,target_sz,sg. ∀lhs_int,rhs_int. size_lt target_sz src_sz →
662                               (subtraction (bitsize_of_intsize target_sz)
663                                    (cast_int_int src_sz sg target_sz lhs_int)
664                                    (cast_int_int src_sz sg target_sz rhs_int)
665                             = cast_int_int src_sz sg target_sz (subtraction (bitsize_of_intsize src_sz) lhs_int rhs_int)).
666#src_sz #target_sz #sg #lhs_int #rhs_int #Hlt
667elim src_sz in Hlt lhs_int rhs_int; elim target_sz
668[ 1,2,3,5,6,9: normalize #H @(False_ind … H)
669| *: elim sg #_
670  normalize in match (bitsize_of_intsize ?);
671  normalize in match (bitsize_of_intsize ?);
672  #lint #rint
673  normalize in match (cast_int_int ????);
674  normalize in match (cast_int_int ????);
675  whd in match (subtraction ???);
676  whd in match (subtraction ???) in ⊢ (???%);
677  >vsplit_to_truncate >vsplit_to_truncate
679  [ 1,2: normalize in match (plus 8 8); generalize in match (add_with_carries ? lint ? false);
680  | 3,4: normalize in match (plus 24 8); generalize in match (add_with_carries ? lint ? false);
681  | 5,6: normalize in match (plus 16 16); generalize in match (add_with_carries ? lint ? false);
682  ]
683  * #result #carry
684  normalize nodelta //
685qed.
686
687lemma integer_sub_cast_eq : ∀src_sz,target_sz,sg. ∀lhs_int,rhs_int. target_sz = src_sz →
688                               (subtraction (bitsize_of_intsize target_sz)
689                                    (cast_int_int src_sz sg target_sz lhs_int)
690                                    (cast_int_int src_sz sg target_sz rhs_int)
691                             = cast_int_int src_sz sg target_sz (subtraction (bitsize_of_intsize src_sz) lhs_int rhs_int)).
692#src_sz #target_sz #sg #lhs_int #rhs_int #Heq destruct
693>cast_identity >cast_identity >cast_identity //
694qed.
695
696lemma integer_sub_cast_le : ∀src_sz,target_sz,sg. ∀lhs_int,rhs_int. size_le target_sz src_sz →
697                               (subtraction (bitsize_of_intsize target_sz)
698                                    (cast_int_int src_sz sg target_sz lhs_int)
699                                    (cast_int_int src_sz sg target_sz rhs_int)
700                             = cast_int_int src_sz sg target_sz (subtraction (bitsize_of_intsize src_sz) lhs_int rhs_int)).
701#src_sz #target_sz #sg #lhs_int #rhs_int #Hle
702cases (sz_eq_dec target_sz src_sz)
703[ 1: #Heq @(integer_sub_cast_eq … Heq)
704| 2: #Hneq cut (size_lt target_sz src_sz)
705     [ 1: elim target_sz in Hle Hneq; elim src_sz normalize //
706           #_ * #H @(H … (refl ??))
707     | 2: #Hlt @(integer_sub_cast_lt … Hlt)
708     ]
709] qed.
710
711lemma simplify_int_success_lt : ∀sz,sg,sz',sg',i,i'. (simplify_int sz sz' sg sg' i=Some (bvint sz') i') → size_le  sz' sz.
712* #sg * #sg' #i #i' #H whd in H:(??%?); try destruct normalize // qed.
713
714lemma smaller_integer_val_identity : ∀sz,sg,x.
715     smaller_integer_val sz sz sg x x.
716#sz #sg *
717[ 2: #error //
718| 1: * #val #trace whd in match (smaller_integer_val ?????);
719     #v1 #Hval %{v1} @conj try @conj try @conj //
720     elim sz //
721] qed.
722
723(* Inversion on exec_cast *)
724lemma exec_cast_inv : ∀castee_val,src_sz,src_sg,cast_sz,cast_sg,m,result.
725                         exec_cast m castee_val (Tint src_sz src_sg) (Tint cast_sz cast_sg) = OK ? result →
726                         ∃i. castee_val = Vint src_sz i ∧ result = Vint cast_sz (cast_int_int src_sz src_sg cast_sz i).
727#castee_val #src_sz #src_sg #cast_sz #cast_sg #m #result
728elim castee_val
729[ 1: | 2: #sz' #i | 3: #f | 4: | 5: #ptr ]
730[ 2: | *: whd in ⊢ ((??%?) → ?); #Habsurd destruct ]
731whd in ⊢ ((??%?) → ?);
732cases (sz_eq_dec sz' src_sz)
733[ 1: #Heq destruct >intsize_eq_elim_true normalize nodelta #Heq destruct
734     %{i}  /2/
735| 2: #Hneq >intsize_eq_elim_false; try assumption #H destruct ]
736qed.
737
738
739(* Lemmas related to the Ebinop case *)
740
742* * // qed.
743
744lemma classify_sub_int : ∀sz,sg. classify_sub (Tint sz sg) (Tint sz sg) = sub_case_ii sz sg.
745* * // qed.
746
747lemma bool_conj_inv : ∀a,b : bool. (a ∧ b) = true → a = true ∧ b = true.
748* * normalize #H @conj // qed.
749
750(* Operations where it is safe to use a smaller integer type on the assumption
751   that we would cast it down afterwards anyway. *)
752definition binop_simplifiable ≝
753λop. match op with [ Oadd ⇒ true | Osub ⇒ true | _ ⇒ false ].
754
755(* Inversion principle for integer addition *)
756lemma iadd_inv : ∀sz,sg,v1,v2,m,r. sem_binary_operation Oadd v1 (Tint sz sg) v2 (Tint sz sg) m = Some ? r →
757                                    ∃dsz,i1,i2. v1 = Vint dsz i1 ∧ v2 = Vint dsz i2 ∧ r = (Vint dsz (addition_n (bitsize_of_intsize dsz) i1 i2)).
758#sz #sg #v1 #v2 #m #r
759elim v1
760[ 1: | 2: #sz' #i | 3: #f | 4: | 5: #ptr ]
761whd in ⊢ ((??%?) → ?); normalize nodelta
763elim v2 in H;
764[ 1: | 2: #sz'' #i' | 3: #f' | 4:  | 5: #ptr' ]
765whd in ⊢ ((??%?) → ?); #H destruct
766elim (sz_eq_dec sz' sz'')
767[ 1: #Heq destruct >intsize_eq_elim_true in H; #Heq destruct %{sz''} %{i} %{i'} /3/
768| 2: #Hneq >intsize_eq_elim_false in H; try assumption #H destruct
769] qed.
770
771(* Inversion principle for integer subtraction. *)
772lemma isub_inv : ∀sz,sg,v1,v2,m,r. sem_binary_operation Osub v1 (Tint sz sg) v2 (Tint sz sg) m = Some ? r →
773                                    ∃dsz,i1,i2. v1 = Vint dsz i1 ∧ v2 = Vint dsz i2 ∧ r = (Vint dsz (subtraction ? i1 i2)).
774#sz #sg #v1 #v2 #m #r
775elim v1
776[ 1: | 2: #sz' #i | 3: #f | 4:  | 5: #ptr ]
777whd in ⊢ ((??%?) → ?); normalize nodelta
778>classify_sub_int normalize nodelta #H destruct
779elim v2 in H;
780[ 1: | 2: #sz'' #i' | 3: #f' | 4:  | 5: #ptr' ]
781whd in ⊢ ((??%?) → ?); #H destruct
782elim (sz_eq_dec sz' sz'')
783[ 1: #Heq destruct >intsize_eq_elim_true in H; #Heq destruct %{sz''} %{i} %{i'} /3/
784| 2: #Hneq >intsize_eq_elim_false in H; try assumption #H destruct
785] qed.
786
787definition is_int : val → Prop ≝
788λv.
789match v with
790[ Vint _ _ ⇒ True
791| _ ⇒ False ].
792
793(* "negative" (in the sense of ¬ Some) inversion principle for integer addition *)
794lemma neg_iadd_inv : ∀sz,sg,v1,v2,m. sem_binary_operation Oadd v1 (Tint sz sg) v2 (Tint sz sg) m = None ? →
795                                        ¬ (is_int v1) ∨ ¬ (is_int v2) ∨
796                                        ∃dsz1,dsz2,i1,i2. v1 = Vint dsz1 i1 ∧ v2 = Vint dsz2 i2 ∧ dsz1 ≠ dsz2.
797#sz #sg #v1 #v2 #m
798elim v1
799[ 1: | 2: #sz' #i | 3: #f | 4:  | 5: #ptr ]
800[ 2: | *: #_ %1 %1 % #H @H ]
801elim v2
802[ 1: | 2: #sz'' #i' | 3: #f' | 4:  | 5: #ptr' ]
803[ 2: | *: #_ %1 %2 % #H @H ]
804whd in ⊢ ((??%?) → ?); normalize nodelta
806elim (sz_eq_dec sz' sz'')
807[ 1: #Heq destruct >intsize_eq_elim_true #Habsurd destruct (Habsurd)
808| 2: #Hneq >intsize_eq_elim_false try assumption #_
809     %2 %{sz'} %{sz''} %{i} %{i'} try @conj try @conj //
810] qed.
811
812(* "negative" inversion principle for integer subtraction *)
813lemma neg_isub_inv : ∀sz,sg,v1,v2,m. sem_binary_operation Osub v1 (Tint sz sg) v2 (Tint sz sg) m = None ? →
814                                        ¬ (is_int v1) ∨ ¬ (is_int v2) ∨
815                                        ∃dsz1,dsz2,i1,i2. v1 = Vint dsz1 i1 ∧ v2 = Vint dsz2 i2 ∧ dsz1 ≠ dsz2.
816#sz #sg #v1 #v2 #m
817elim v1
818[ 1: | 2: #sz' #i | 3: #f | 4:  | 5: #ptr ]
819[ 2: | *: #_ %1 %1 % #H @H ]
820elim v2
821[ 1: | 2: #sz'' #i' | 3: #f' | 4:  | 5: #ptr' ]
822[ 2: | *: #_ %1 %2 % #H @H ]
823whd in ⊢ ((??%?) → ?); normalize nodelta
824>classify_sub_int normalize nodelta
825elim (sz_eq_dec sz' sz'')
826[ 1: #Heq destruct >intsize_eq_elim_true #Habsurd destruct (Habsurd)
827| 2: #Hneq >intsize_eq_elim_false try assumption #_
828     %2 %{sz'} %{sz''} %{i} %{i'} try @conj try @conj //
829] qed.
830
831
832lemma simplifiable_op_inconsistent : ∀op,sz,sg,v1,v2,m.
833   ¬ (is_int v1) → binop_simplifiable op = true → sem_binary_operation op v1 (Tint sz sg) v2 (Tint sz sg) m = None ?.
834#op #sz #sg #v1 #v2 #m #H
835elim op normalize in match (binop_simplifiable ?); #H destruct
836elim v1 in H;
837[ 1,6: | 2,7: #sz' #i normalize in ⊢ (% → ?); * #H @(False_ind … (H I)) | 3,8: #f | 4,9: | 5,10: #ptr ]
838#_
839whd in match (sem_binary_operation ??????); normalize nodelta
841>classify_sub_int normalize nodelta //
842qed.
843
844notation > "hvbox('let' «ident x,ident y» 'as' ident E ≝ t 'in' s)"
845 with precedence 10
846for @{ match \$t return λx.x = \$t → ? with [ mk_Sig \${ident x} \${ident y} ⇒ λ\${ident E}.\$s ] (refl ? \$t) }.
847
848notation > "hvbox('let' « 〈ident x1,ident x2〉, ident y» 'as' ident E, ident F ≝ t 'in' s)"
849 with precedence 10
850for @{ match \$t return λx.x = \$t → ? with
851       [ mk_Sig \${fresh a} \${ident y} ⇒ λ\${ident E}.
852         match \${fresh a} return λx.x = \${fresh a} → ? with
853         [ mk_Prod \${ident x1} \${ident x2} ⇒ λ\${ident F}. \$s ] (refl ? \${fresh a})
854       ] (refl ? \$t)
855      }.
856
857(* This function will make your eyes bleed. You've been warned.
858 * Implements a correct-by-construction version of Brian's original cast-removal code. Does so by
859 * threading an invariant defined in [simplify_inv], which says roughly "simplification yields either
860   what you hoped for, i.e. an integer value of the right size, OR something equivalent to the original
861   expression". [simplify_expr] is not to be called directly: simplify inside is the proper wrapper.
862 * TODO: proper doc. Some cases are simplifiable. Some type equality tests are maybe dispensable.
863 * This function is slightly more conservative than the original one, but this should be incrementally
864 * modifiable (replacing calls to simplify_inside by calls to simplify_expr, + proving correction).
865 * Also, I think that the proofs are factorizable to a great deal, but I'd rather have something
866 * more or less "modular", case-by-case wise.
867 *)
868let rec simplify_expr (e:expr) (target_sz:intsize) (target_sg:signedness)
869  : Σresult:bool×expr. ∀ge,en,m. simplify_inv ge en m e (\snd result) target_sz target_sg (\fst result) ≝
870match e return λx. x = e → ? with
871[ Expr ed ty ⇒ λHexpr_eq.
872  match ed return λx. ed = x → ? with
873  [ Econst_int cst_sz i ⇒ λHdesc_eq.
874    match ty return λx. x=ty → ? with
875    [ Tint ty_sz sg ⇒ λHexprtype_eq.
876      (* Ensure that the displayed type size [cst_sz] and actual size [sz] are equal ... *)
877      match sz_eq_dec cst_sz ty_sz with
878      [ inl Hsz_eq ⇒
879        match type_eq_dec ty (Tint target_sz target_sg) with
880        [ inl Hdonothing   ⇒ «〈true, e〉, ?»
881        | inr Hdosomething ⇒
882          (* Do the actual useful work *)
883          match simplify_int cst_sz target_sz sg target_sg i return λx. (simplify_int cst_sz target_sz sg target_sg i) = x → ? with
884          [ Some i' ⇒ λHsimpl_eq.
885            «〈true, Expr (Econst_int target_sz i') (Tint target_sz target_sg)〉, ?»
886          | None    ⇒ λ_.
887            «〈false, e〉, ?»
888          ] (refl ? (simplify_int cst_sz target_sz sg target_sg i))
889        ]
890      | inr _ ⇒ (* The expression is ill-typed. *)
891        «〈false, e〉, ?»
892      ]
893    | _ ⇒ λ_.
894      «〈false, e〉, ?»
895    ] (refl ? ty)
896  | Ederef e1 ⇒ λHdesc_eq.
897      let «e2,Hequiv» as Hsimplify ≝ simplify_inside e1 in
898      «〈false, Expr (Ederef e2) ty〉, ?»
899  | Eaddrof e1 ⇒ λHdesc_eq.
900      let «e2,Hequiv» as Hsimplify ≝ simplify_inside e1 in
901      «〈false, Expr (Eaddrof e2) ty〉, ?»
902  | Eunop op e1 ⇒ λHdesc_eq.
903     let «e2,Hequiv» as Hsimplify ≝ simplify_inside e1 in
904      «〈false, Expr (Eunop op e2) ty〉, ?»
905  | Ebinop op lhs rhs ⇒ λHdesc_eq.
906      (* Type equality is enforced to prove the equalities needed in return by the invariant. *)
907      match binop_simplifiable op
908      return λx. (binop_simplifiable op) = x → (Σresult:(bool × expr). (∀ge,en,m. simplify_inv ge en m e (\snd result) target_sz target_sg (\fst result)))
909      with
910      [ true ⇒ λHop_simplifiable_eq.
911        match assert_type_eq ty (typeof lhs) with
912        [ OK Hty_eq_lhs ⇒
913            match assert_type_eq (typeof lhs) (typeof rhs) with
914            [ OK Htylhs_eq_tyrhs ⇒
915                let «〈desired_type_lhs, lhs1〉, Hinv_lhs» as Hsimplify_lhs, Hpair_lhs ≝ simplify_expr lhs target_sz target_sg in
916                let «〈desired_type_rhs, rhs1〉, Hinv_rhs» as Hsimplify_rhs, Hpair_rhs ≝ simplify_expr rhs target_sz target_sg in
917                match desired_type_lhs ∧ desired_type_rhs
918                return  λx. (desired_type_lhs ∧ desired_type_rhs) = x → (Σresult:(bool × expr). (∀ge,en,m. simplify_inv ge en m e (\snd result) target_sz target_sg (\fst result)))
919                with
920                [ true ⇒ λHdesired_eq.
921                  «〈true, Expr (Ebinop op lhs1 rhs1) (Tint target_sz target_sg)〉, ?»
922                | false ⇒ λHdesired_eq.
923                  let «lhs1, Hequiv_lhs» as Hsimplify_lhs ≝ simplify_inside lhs in
924                  let «rhs1, Hequiv_rhs» as Hsimplify_rhs ≝ simplify_inside rhs in
925                  «〈false, Expr (Ebinop op lhs1 rhs1) ty〉, ?»
926                ] (refl ? (desired_type_lhs ∧ desired_type_rhs))
927            | Error _ ⇒
928                let «lhs1, Hequiv_lhs» as Hsimplify_lhs ≝ simplify_inside lhs in
929                let «rhs1, Hequiv_rhs» as Hsimplify_rhs ≝ simplify_inside rhs in
930                «〈false, Expr (Ebinop op lhs1 rhs1) ty〉, ?»
931            ]
932        | Error _ ⇒
933            let «lhs1, Hequiv_lhs» as Hsimplify_lhs ≝ simplify_inside lhs in
934            let «rhs1, Hequiv_rhs» as Hsimplify_rhs ≝ simplify_inside rhs in
935             «〈false, Expr (Ebinop op lhs1 rhs1) ty〉, ?»
936        ]
937      | false ⇒ λHop_simplifiable_eq.
938        let «lhs1, Hequiv_lhs» as Hsimplify_lhs ≝ simplify_inside lhs in
939        let «rhs1, Hequiv_rhs» as Hsimplify_rhs ≝ simplify_inside rhs in
940          «〈false, Expr (Ebinop op lhs1 rhs1) ty〉, ?»
941      ] (refl ? (binop_simplifiable op))
942  | Ecast cast_ty castee ⇒ λHdesc_eq.
943      match cast_ty return λx. x = cast_ty → ? with
944      [ Tint cast_sz cast_sg ⇒ λHcast_ty_eq.
945        match type_eq_dec ty cast_ty with
946        [ inl Hcast_eq ⇒
947          match necessary_conditions cast_sz cast_sg target_sz target_sg
948          return λx. x = (necessary_conditions cast_sz cast_sg target_sz target_sg) → (Σresult:(bool × expr). (∀ge,en,m. simplify_inv ge en m e (\snd result) target_sz target_sg (\fst result)))
949          with
950          [ true ⇒ λHconditions.
951              let «〈desired_type, castee1〉, Hcastee_inv» as Hsimplify1, Hpair1 ≝ simplify_expr castee target_sz target_sg in
952              match desired_type return λx. desired_type = x → Σresult:bool×expr. (∀ge,en,m. simplify_inv ge en m e (\snd result) target_sz target_sg (\fst result))
953              with
954              [ true ⇒ λHdesired_eq.
955                «〈true, castee1〉, ?»
956              | false ⇒ λHdesired_eq.
957                let «〈desired_type2, castee2〉, Hcast2» as Hsimplify2, Hpair2 ≝ simplify_expr castee cast_sz cast_sg in
958                match desired_type2 return λx. desired_type2 = x → Σresult:bool×expr. (∀ge,en,m. simplify_inv ge en m e (\snd result) target_sz target_sg (\fst result))
959                with
960                [ true ⇒ λHdesired2_eq.
961                  «〈false, castee2〉, ?»
962                | false ⇒ λHdesired2_eq.
963                  «〈false, Expr (Ecast ty castee2) cast_ty〉, ?»
964                ] (refl ? desired_type2)
965              ] (refl ? desired_type)
966          | false ⇒ λHconditions.
967              let «〈desired_type2, castee2〉, Hcast2» as Hsimplify2, Hpair2 ≝ simplify_expr castee cast_sz cast_sg in
968              match desired_type2 return λx. desired_type2 = x → Σresult:bool×expr. (∀ge,en,m. simplify_inv ge en m e (\snd result) target_sz target_sg (\fst result))
969              with
970              [ true ⇒ λHdesired2_eq.
971                «〈false, castee2〉, ?»
972              | false ⇒ λHdesired2_eq.
973                «〈false, Expr (Ecast ty castee2) cast_ty〉, ?»
974              ] (refl ? desired_type2)
975          ] (refl ? (necessary_conditions cast_sz cast_sg target_sz target_sg))
976        | inr Hcast_neq ⇒
977          (* inconsistent types ... *)
978          let «castee1, Hcastee_equiv» as Hsimplify ≝ simplify_inside castee in
979          «〈false, Expr (Ecast cast_ty castee1) ty〉, ?»
980        ]
981      | _ ⇒ λHcast_ty_eq.
982        let «castee1, Hcastee_equiv» as Hsimplify ≝ simplify_inside castee in
983        «〈false, Expr (Ecast cast_ty castee1) ty〉, ?»
984      ] (refl ? cast_ty)
985  | Econdition cond iftrue iffalse ⇒ λHdesc_eq.
986      let «cond1, Hcond_equiv» as Hsimplify ≝ simplify_inside cond in
987      match assert_type_eq ty (typeof iftrue) with
988      [ OK Hty_eq_iftrue ⇒
989          match assert_type_eq (typeof iftrue) (typeof iffalse) with
990          [ OK Hiftrue_eq_iffalse ⇒
991              let «〈desired_true, iftrue1〉, Htrue_inv» as Hsimplify_iftrue, Hpair_iftrue      ≝ simplify_expr iftrue target_sz target_sg in
992              let «〈desired_false, iffalse1〉, Hfalse_inv» as Hsimplify_iffalse, Hpair_iffalse ≝ simplify_expr iffalse target_sz target_sg in
993              match desired_true ∧ desired_false
994              return  λx. (desired_true ∧ desired_false) = x → (Σresult:(bool × expr). (∀ge,en,m. simplify_inv ge en m e (\snd result) target_sz target_sg (\fst result)))
995              with
996              [ true ⇒ λHdesired_eq.
997                «〈true, Expr (Econdition cond1 iftrue1 iffalse1) (Tint target_sz target_sg)〉, ?»
998              | false ⇒ λHdesired_eq.
999                let «iftrue1, Htrue_equiv» as Hsimplify_iftrue    ≝ simplify_inside iftrue in
1000                let «iffalse1, Hfalse_equiv» as Hsimplify_iffalse ≝ simplify_inside iffalse in
1001                «〈false, Expr (Econdition cond1 iftrue1 iffalse1) ty〉, ?»
1002              ] (refl ? (desired_true ∧ desired_false))
1003          | _ ⇒
1004            let «iftrue1, Htrue_equiv» as Hsimplify_iftrue    ≝ simplify_inside iftrue in
1005            let «iffalse1, Hfalse_equiv» as Hsimplify_iffalse ≝ simplify_inside iffalse in
1006            «〈false, Expr (Econdition cond1 iftrue1 iffalse1) ty〉, ?»
1007          ]
1008      | _ ⇒
1009        let «iftrue1, Htrue_equiv» as Hsimplify_iftrue    ≝ simplify_inside iftrue in
1010        let «iffalse1, Hfalse_equiv» as Hsimplify_iffalse ≝ simplify_inside iffalse in
1011        «〈false, Expr (Econdition cond1 iftrue1 iffalse1) ty〉, ?»
1012      ]
1013    (* Could probably do better with these, too. *)
1014  | Eandbool lhs rhs ⇒ λHdesc_eq.
1015      let «lhs1, Hlhs_equiv» as Eq1 ≝ simplify_inside lhs in
1016      let «rhs1, Hrhs_equiv» as Eq2 ≝ simplify_inside rhs in
1017      «〈false, Expr (Eandbool lhs1 rhs1) ty〉, ?»
1018  | Eorbool lhs rhs ⇒ λHdesc_eq.
1019      let «lhs1, Hlhs_equiv» as Eq1 ≝ simplify_inside lhs in
1020      let «rhs1, Hrhs_equiv» as Eq2 ≝ simplify_inside rhs in
1021      «〈false, Expr (Eorbool lhs1 rhs1) ty〉,?»
1022  (* Could also improve Esizeof *)
1023  | Efield rec_expr f ⇒ λHdesc_eq.
1024      let «rec_expr1, Hrec_expr_equiv» as Hsimplify ≝ simplify_inside rec_expr in
1025      «〈false,Expr (Efield rec_expr1 f) ty〉, ?»
1026  | Ecost l e1 ⇒ λHdesc_eq.
1027      (* The invariant requires that the toplevel [ty] type matches the type of [e1]. *)
1028      (* /!\ XXX /!\ We assume that the type of a cost-labelled expr is the type of the underlying expr. *)
1029      match type_eq_dec ty (typeof e1) with
1030      [ inl Heq ⇒
1031        let «〈desired_type, e2〉, Hinv» as Hsimplify, Hpair ≝ simplify_expr e1 target_sz target_sg in
1032        «〈desired_type, Expr (Ecost l e2) (typeof e2)〉, ?»
1033      | inr Hneq ⇒
1034        let «e2, Hexpr_equiv» as Eq ≝ simplify_inside e1 in
1035        «〈false, Expr (Ecost l e2) ty〉, ?»
1036      ]
1037  | Econst_float f ⇒ λHdesc_eq. «〈false, Expr ed ty〉, ?»
1038(* | Evar id ⇒ λHdesc_eq. «〈false, Expr ed ty〉, ?» *)
1039  (* In order for the simplification function to be less dymp, we would have to use this line, which would in fact
1040     require to alter the semantics of [load_value_of_type].  *)
1041  | Evar id        ⇒ λHdesc_eq. «〈type_eq ty (Tint target_sz target_sg), Expr ed ty〉, ?»
1042  | Esizeof t      ⇒ λHdesc_eq. «〈type_eq ty (Tint target_sz target_sg), Expr ed ty〉, ?»
1043  ] (refl ? ed)
1044] (refl ? e)
1045
1046and simplify_inside (e:expr) : Σresult:expr. conservation e result ≝
1047match e return λx. x = e → ? with
1048[ Expr ed ty ⇒ λHexpr_eq.
1049  match ed return λx. x = ed → ? with
1050  [ Ederef e1 ⇒ λHdesc_eq.
1051    let «e2, Hequiv» as Hsimplify ≝ simplify_inside e1 in
1052    «Expr (Ederef e2) ty, ?»
1053  | Eaddrof e1 ⇒ λHdesc_eq.
1054    let «e2, Hequiv» as Hsimplify ≝ simplify_inside e1 in
1055    «Expr (Eaddrof e2) ty, ?»
1056  | Eunop op e1 ⇒ λHdesc_eq.
1057    let «e2, Hequiv» as Hsimplify ≝ simplify_inside e1 in
1058    «Expr (Eunop op e2) ty, ?»
1059  | Ebinop op lhs rhs ⇒ λHdesc_eq.
1060    let «lhs1, Hequiv_lhs» as Eq_lhs ≝ simplify_inside lhs in
1061    let «rhs1, Hequiv_rhs» as Eq_rhs ≝ simplify_inside rhs in
1062    «Expr (Ebinop op lhs1 rhs1) ty, ?»
1063  | Ecast cast_ty castee ⇒ λHdesc_eq.
1064    match type_eq_dec ty cast_ty with
1065    [ inl Hcast_eq ⇒
1066       match cast_ty return λx. x = cast_ty → Σresult:expr. conservation e result
1067       with
1068       [ Tint cast_sz cast_sg ⇒ λHcast_ty_eq.
1069          let «〈success, castee1〉, Htrans_inv» as Hsimplify, Hpair ≝ simplify_expr castee cast_sz cast_sg in
1070          match success return λx. x = success → Σresult:expr. conservation e result
1071         with
1072         [ true ⇒ λHsuccess_eq.
1073           «castee1, ?»
1074         | false ⇒ λHsuccess_eq.
1075           «Expr (Ecast cast_ty castee1) ty, ?»
1076          ] (refl ? success)
1077       | _ ⇒ λHcast_ty_eq.
1078          «e, ?»
1079       ] (refl ? cast_ty)
1080    | inr Hcast_neq ⇒
1081       «e, ?»
1082    ]
1083  | Econdition cond iftrue iffalse ⇒ λHdesc_eq.
1084    let «cond1, Hequiv_cond» as Eq_cond ≝ simplify_inside cond in
1085    let «iftrue1, Hequiv_iftrue» as Eq_iftrue ≝ simplify_inside iftrue in
1086    let «iffalse1, Hequiv_iffalse» as Eq_iffalse ≝ simplify_inside iffalse in
1087    «Expr (Econdition cond1 iftrue1 iffalse1) ty, ?»
1088  | Eandbool lhs rhs ⇒ λHdesc_eq.
1089    let «lhs1, Hequiv_lhs» as Eq_lhs ≝ simplify_inside lhs in
1090    let «rhs1, Hequiv_rhs» as Eq_rhs ≝ simplify_inside rhs in
1091    «Expr (Eandbool lhs1 rhs1) ty, ?»
1092  | Eorbool lhs rhs ⇒ λHdesc_eq.
1093    let «lhs1, Hequiv_lhs» as Eq_lhs ≝ simplify_inside lhs in
1094    let «rhs1, Hequiv_rhs» as Eq_rhs ≝ simplify_inside rhs in
1095    «Expr (Eorbool lhs1 rhs1) ty, ?»
1096  | Efield rec_expr f ⇒ λHdesc_eq.
1097    let «rec_expr1, Hequiv_rec» as Eq_rec ≝ simplify_inside rec_expr in
1098    «Expr (Efield rec_expr1 f) ty, ?»
1099  | Ecost l e1 ⇒ λHdesc_eq.
1100    let «e2, Hequiv» as Eq ≝ simplify_inside e1 in
1101    «Expr (Ecost l e2) ty, ?»
1102  | _ ⇒ λHdesc_eq.
1103    «e, ?»
1104  ] (refl ? ed)
1105] (refl ? e).
1106#ge #en #m
1107[ 1,3,5,6,7,8,9,10,11,12: %1 try @refl
1108     cases (exec_expr ge en m e) #res
1109     try (@(SimOk ???) //)
1110| 2: @(Inv_coerce_ok ge en m … target_sz target_sg target_sz target_sg) destruct /by refl/
1111(*
1112     whd in match (exec_expr ????); >eq_intsize_identity whd
1113     >sz_eq_identity normalize % [ 1: @conj // | 2: elim target_sz in i; normalize #i @I ]
1114*)
1115| 4: destruct @(Inv_coerce_ok ge en m ???? ty_sz sg) / by refl/
1116     whd in match (exec_expr ????);
1117     whd in match (exec_expr ????);
1118     >eq_intsize_identity >eq_intsize_identity whd
1119     #v1 #Heq destruct (Heq) %{i'} try @conj try @conj try @conj //
1120     [ 1: @(simplify_int_implements_cast … Hsimpl_eq)
1121     | 2: @(simplify_int_success_lt … Hsimpl_eq) ]
1122| 13: %1 // >Hexpr_eq cases (exec_expr ge en m e) #res
1123      try (@(SimOk ???) //)
1124| 14: elim (type_eq_dec ty (Tint target_sz target_sg))
1125      [ 1: #Heq >Heq >type_eq_identity @(Inv_coerce_ok ??????? target_sz target_sg)
1126           destruct
1127           [ 1,2: //
1128           | 3: @smaller_integer_val_identity ]
1129      | 2: #Hneq >(type_neq_not_identity … Hneq) %1 // destruct
1130           @(SimOk ???) //
1131      ]
1132| 15: destruct %1 try @refl elim (Hequiv ge en m) * #Hexpr_sim #Hlvalue_sim #Htype_eq
1133    [ 1: (* Proving preservation of the semantics for expressions. *)
1134      cases Hexpr_sim
1135      [ 2: (* Case where the evaluation of e1 as an expression fails *)
1136        normalize * #err #Hfail >Hfail normalize nodelta @SimFailNicely
1137      | 1: (* Case where the evaluation of e1 as an expression succeeds (maybe) *)
1138        #Hsim %1 * #val #trace normalize #Hstep
1139        cut (∃ptr. (exec_expr ge en m e1 = OK ? 〈Vptr ptr, trace〉) ∧
1140                   (load_value_of_type ty m (pblock ptr) (poff ptr) = Some ? val))
1141        [ 1: lapply Hstep -Hstep
1142             cases (exec_expr ge en m e1)
1143             [ 1: * #val' #trace' normalize nodelta
1144                  cases val' normalize nodelta
1145                  [ 1,2,3,4: #H1 destruct #H2 destruct #H3 destruct
1146                  | 5: #pointer #Heq @(ex_intro … pointer) (* @(ex_intro … trace') *)
1147                       cases (load_value_of_type ty m (pblock pointer) (poff pointer)) in Heq;
1148                       normalize nodelta
1149                       [ 1: #Heq destruct | 2: #val2 #Heq destruct @conj // ]
1150                  ]
1151             | 2: normalize nodelta #errmesg #Hcontr destruct
1152             ]
1153        | 2: * #e1_ptr * #He1_eq_ptr #Hloadptr
1154             cut (∃ptr1. (exec_expr ge en m e2 = OK ? 〈Vptr ptr1, trace〉)
1155                       ∧ (load_value_of_type ty m (pblock ptr1) (poff ptr1) = Some ? val))
1156             [ 1: @(ex_intro … e1_ptr) @conj
1157                  [ 1: @Hsim // | 2: // ]
1158             | 2: * #e2_ptr * #He2_exec #Hload_e2_ptr
1159                normalize >He2_exec normalize nodelta >Hload_e2_ptr normalize nodelta @refl
1160             ]
1161        ]
1162     ]
1163   | 2: (* Proving the preservation of the semantics for lvalues. *)
1164      cases Hexpr_sim
1165      [ 2: (* Case where the evaluation of e1 as an lvalue fails *)
1166        normalize * #err #Hfail >Hfail normalize nodelta @SimFailNicely
1167      | 1: (* Case where the evaluation of e1 as an expression succeeds (maybe) *)
1168        #Hsim %1 * * #block #offset #trace normalize #Hstep
1169        cut (∃ptr. (exec_expr ge en m e1 = OK ? 〈Vptr ptr, trace〉) ∧ pblock ptr = block ∧ poff ptr = offset)
1170        [ 1: lapply Hstep -Hstep
1171             cases (exec_expr ge en m e1)
1172             [ 1: * #val' #trace' normalize nodelta
1173                  cases val' normalize nodelta
1174                  [ 1,2,3,4: #H1 destruct #H2 destruct #H3 destruct
1175                  | 5: #pointer #Heq @(ex_intro … pointer) (* @(ex_intro … trace') *)
1176                       destruct try @conj try @conj //
1177                  ]
1178             | 2: normalize nodelta #errmesg #Hcontr destruct
1179             ]
1180        | 2: * #e1_ptr * * #He1_eq_ptr #Hblock #Hoffset
1181             cut (∃ptr1. (exec_expr ge en m e2 = OK ? 〈Vptr ptr1, trace〉)  ∧ pblock ptr1 = block ∧ poff ptr1 = offset)
1182             [ 1: @(ex_intro … e1_ptr) @conj try @conj // @Hsim //
1183             | 2: * #e2_ptr * * #He2_exec #Hblock #Hoffset
1184                normalize >He2_exec normalize nodelta //
1185             ]
1186        ]
1187     ]
1188   ]
1189| 16: destruct %1 try @refl elim (Hequiv ge en m) * #Hexpr_sim #Hlvalue_sim #Htype_eq
1190    [ 1: (* Proving preservation of the semantics for expressions. *)
1191      cases Hlvalue_sim
1192      [ 2: (* Case where the evaluation of e1 as an expression fails *)
1193        * #err #Hfail whd in match (exec_expr ????); >Hfail @SimFailNicely
1194      | 1: (* Case where the evaluation of e1 as an expression succeeds (maybe) *)
1195        #Hsim %1 * #val #trace whd in match (exec_expr ????); #Hstep
1196        cut (∃block,offset,ptype. (exec_lvalue ge en m e1 = OK ? 〈block, offset, trace〉) ∧
1197                                 (ty = Tpointer ptype) ∧
1198                                  val = Vptr (mk_pointer block offset))
1199        [ 1: lapply Hstep -Hstep
1200             cases (exec_lvalue ge en m e1)
1201             [ 1: * * #block #offset #trace' normalize nodelta
1202                  cases ty
1203                  [ 2: #sz #sg | 3: #fsz | 4: #ptr_ty | 5: #array_ty #array_sz | 6: #domain #codomain
1204                  | 7: #structname #fieldspec | 8: #unionname #fieldspec | 9: #id ]
1205                  normalize nodelta try (#Heq destruct)
1206                  @(ex_intro … block) @(ex_intro … offset) @(ex_intro … ptr_ty)
1207                  try @conj try @conj destruct //
1208             | 2: normalize nodelta #errmesg #Hcontr destruct
1209             ]
1210        | 2: * #block * #offset * #ptype * * #Hexec_lvalue #Hty_eq #Hval_eq
1211             whd in match (exec_expr ????); >(Hsim … Hexec_lvalue) normalize nodelta destruct normalize nodelta
1212             //
1213        ]
1214     ]
1215    | 2: (* Proving preservation of the semantics of lvalues. *)
1216         @SimFailNicely
1217    ]
1218| 17: destruct %1 try @refl elim (Hequiv ge en m) * #Hexpr_sim #Hlvalue_sim #Htype_eq
1219      [ 1: whd in match (exec_expr ge en m (Expr ??));
1220           whd in match (exec_expr ge en m (Expr ??));
1221           cases Hexpr_sim
1222           [ 2: * #error #Hexec >Hexec normalize nodelta @SimFailNicely
1223           | 1: cases (exec_expr ge en m e1)
1224                [ 2: #error #Hexec normalize nodelta @SimFailNicely
1225                | 1: * #val #trace #Hexec
1226                     >(Hexec ? (refl ? (OK ? 〈val,trace〉)))
1227                     normalize nodelta @SimOk #a >Htype_eq #H @H
1228                ]
1229           ]
1230      | 2: @SimFailNicely
1231      ]
1232| 18: destruct elim (bool_conj_inv … Hdesired_eq) #Hdesired_lhs #Hdesired_rhs -Hdesired_eq
1233      inversion (Hinv_lhs ge en m)
1234      [ 1: #result_flag_lhs #Hresult_lhs #Htype_lhs #Hsim_expr_lhs #Hsim_lvalue_lhs #Hresult_flag_lhs_eq_true
1235           #Hinv <Hresult_flag_lhs_eq_true in Hresult_lhs; >Hdesired_lhs #Habsurd destruct
1236      | 2: #lhs_src_sz #lhs_src_sg #Htype_lhs #Htype_lhs1 #Hsmaller_lhs #Hdesired_type_lhs #_
1237           inversion (Hinv_rhs ge en m)
1238           [ 1: #result_flag_rhs #Hresult_rhs #Htype_rhs #Hsim_expr_rhs #Hsim_lvalue_rhs #Hdesired_type_rhs_eq #_
1239                <Hdesired_type_rhs_eq in Hresult_rhs; >Hdesired_rhs #Habsurd destruct
1240           | 2: #rhs_src_sz #rhs_src_sg #Htype_rhs #Htype_rhs1 #Hsmaller_rhs #Hdesired_type_rhs #_
1241                @(Inv_coerce_ok  ge en m … target_sz target_sg lhs_src_sz lhs_src_sg)
1242                [ 1: >Htype_lhs //
1243                | 2: //
1244                | 3: whd in match (exec_expr ??? (Expr ??));
1245                     whd in match (exec_expr ??? (Expr ??));
1246                     (* Tidy up the type equations *)
1247                     >Htype_lhs in Htylhs_eq_tyrhs; >Htype_rhs #Heq destruct
1248                     lapply Hsmaller_rhs lapply Hsmaller_lhs
1249                     generalize in match rhs_src_sz; #src_sz
1250                     generalize in match rhs_src_sg; #src_sg
1251                     -Hsmaller_lhs -Hsmaller_rhs -Htype_lhs -Htype_rhs -Hinv_lhs -Hinv_rhs
1252                     >Htype_lhs1 >Htype_rhs1 -Htype_lhs1 -Htype_rhs1
1253                     (* Enumerate all the cases for the evaluation of the source expressions ... *)
1254                     cases (exec_expr ge en m lhs);
1255                     try // * #val_lhs #trace_lhs normalize nodelta
1256                     cases (exec_expr ge en m rhs);
1257                     try // * #val_rhs #trace_rhs normalize nodelta
1258                     whd in match (m_bind ?????);
1259                     (* specialize to the actual simplifiable operations. *)
1260                     cases op in Hop_simplifiable_eq;
1261                     [ 1,2: | *: normalize in ⊢ (% → ?); #H destruct (H) ] #_
1262                     [ 1: lapply (iadd_inv src_sz src_sg val_lhs val_rhs m)
1263                     | 2: lapply (isub_inv src_sz src_sg val_lhs val_rhs m) ]
1264                     cases (sem_binary_operation ? val_lhs (Tint src_sz src_sg) val_rhs (Tint src_sz src_sg) m)
1265                     [ 1,3: #_ #_ #_ normalize @I ]
1266                     #src_result #Hinversion_src elim (Hinversion_src src_result (refl ? (Some ? src_result)))
1267                     #src_result_sz * #i1 * #i2 * * #Hval_lhs_eq #Hval_rhs_eq #Hsrc_result_eq
1268                     whd in match (opt_to_res ???); whd in match (m_bind ?????); normalize nodelta
1269                     >Hval_lhs_eq >Hval_rhs_eq #Hsmaller_rhs #Hsmaller_lhs
1270                     whd
1271                     #result_int #Hsrc_result >Hsrc_result in Hsrc_result_eq; #Hsrc_result_eq
1272                     lapply (sym_eq ??? Hsrc_result_eq) -Hsrc_result_eq #Hsrc_result_eq
1273                     cut (src_result_sz = src_sz) [ 1,3: destruct // ] #Hsz_eq
1274                     lapply Hsmaller_lhs lapply Hsmaller_rhs
1275                     cases (exec_expr ge en m lhs1) normalize nodelta
1276                     [ 2,4: destruct #error normalize in ⊢ (% → ?); #H @(False_ind … (H i1 (refl ? (Vint src_sz i1)))) ]
1277                     * #val_lhs1 #trace_lhs1
1278                     cases (exec_expr ge en m rhs1)
1279                     [ 2,4: destruct #error #_ normalize in ⊢ (% → ?); #H @(False_ind … (H i2 (refl ? (Vint src_sz i2)))) ]
1280                     * #val_rhs1 #trace_rhs1
1281                     whd in match (m_bind ?????); normalize nodelta
1282                     [ 1: lapply (neg_iadd_inv target_sz target_sg val_lhs1 val_rhs1 m)
1283                          lapply (iadd_inv target_sz target_sg val_lhs1 val_rhs1 m)
1284                     | 2: lapply (neg_isub_inv target_sz target_sg val_lhs1 val_rhs1 m)
1285                          lapply (isub_inv target_sz target_sg val_lhs1 val_rhs1 m) ]
1286                     cases (sem_binary_operation ? val_lhs1 (Tint target_sz target_sg) val_rhs1 (Tint target_sz target_sg) m)
1287                     [ 1,3: destruct #_ #Hneg_inversion elim (Hneg_inversion (refl ? (None ?)))
1288                            (* Proceed by case analysis on Hneg_inversion to prove the absurdity of this branch *)
1289                            *
1290                            [ 1,4: whd in ⊢ (? → % → ?); normalize nodelta
1291                                   #Habsurd #Hcounterexample elim (Hcounterexample i1 (refl ? (Vint src_sz i1)))
1292                                   #i * * * #Hlhs1_is_int >Hlhs1_is_int in Habsurd; * #Habsurd
1293                                   @(False_ind … (Habsurd I))
1294                            | 2,5: whd in ⊢ (? → ? → % → ?); normalize nodelta
1295                                   #Habsurd #_ #Hcounterexample elim (Hcounterexample i2 (refl ? (Vint src_sz i2)))
1296                                   #i * * * #Hlhs1_is_int >Hlhs1_is_int in Habsurd; * #Habsurd
1297                                   @(False_ind … (Habsurd I))
1298                            | 3,6: #dsz1 * #dsz2 * #j1 * #j2 * * #Hval_lhs1 #Hval_rhs1 #Hsz_neq
1299                                   whd in ⊢ (% → % → ?); normalize nodelta
1300                                   #Hsmaller_lhs #Hsmaller_rhs
1301                                   elim (Hsmaller_lhs … i1 (refl ? (Vint src_sz i1)))
1302                                   #li * * * #Hval_lhs1_alt #H_lhs_cast_eq #Htrace_eq_lhs #Hsize_le
1303                                   elim (Hsmaller_rhs … i2 (refl ? (Vint src_sz i2)))
1304                                   #ri * * * #Hval_rhs1_alt #H_rhs_cast_eq #Htrace_eq_rhs #_
1305                                   destruct elim Hsz_neq #Habsurd @(Habsurd (refl ? target_sz))
1306                           ]
1307                     | 2,4: destruct #result #Hinversion #_ #Hsmaller_lhs #Hsmaller_rhs normalize nodelta
1308                            elim (Hinversion result (refl ? (Some ? result)))
1309                            #result_sz * #lhs_int * #rhs_int * * #Hlhs1_eq #Hrhs1_eq #Hop_eq
1310                            elim (Hsmaller_lhs … i1 (refl ? (Vint src_sz i1)))
1311                            #li * * * #Hval_lhs1_alt #H_lhs_cast_eq #Htrace_eq_lhs #Hsize_le
1312                            elim (Hsmaller_rhs … i2 (refl ? (Vint src_sz i2)))
1313                            #ri * * * #Hval_rhs1_alt #H_rhs_cast_eq #Htrace_eq_rhs #_
1314                            destruct
1315                            [ 1: %{(addition_n (bitsize_of_intsize target_sz)
1316                                     (cast_int_int src_sz src_sg target_sz i1)
1317                                     (cast_int_int src_sz src_sg target_sz i2))}
1318                                 try @conj try @conj try @conj //
1320                            | 2: %{(subtraction (bitsize_of_intsize target_sz)
1321                                    (cast_int_int src_sz src_sg target_sz i1)
1322                                    (cast_int_int src_sz src_sg target_sz i2))}
1323                                 try @conj try @conj try @conj //
1324                                 >integer_sub_cast_le try //
1325                            ]
1326                     ] ] ] ]
1327| 19,20,21,22: destruct %1 try @refl
1328   elim (Hequiv_lhs ge en m) * #Hexpr_sim_lhs #Hlvalue_sim_lhs #Htype_eq_lhs
1329   elim (Hequiv_rhs ge en m) * #Hexpr_sim_rhs #Hlvalue_sim_rhs #Htype_eq_rhs
1330   [ 1,3,5,7:
1331      whd in match (exec_expr ????); whd in match (exec_expr ????);
1332      cases Hexpr_sim_lhs
1333      [ 2,4,6,8: * #error #Herror >Herror @SimFailNicely
1334      | *: cases (exec_expr ge en m lhs)
1335           [ 2,4,6,8: #error #_ @SimFailNicely
1336           | *: * #lval #ltrace #Hsim_lhs normalize nodelta
1337                cases Hexpr_sim_rhs
1338                [ 2,4,6,8: * #error #Herror >Herror @SimFailNicely
1339                | *: cases (exec_expr ge en m rhs)
1340                     [ 2,4,6,8: #error #_  @SimFailNicely
1341                     | *: * #rval #rtrace #Hsim_rhs
1342                          whd in match (exec_expr ??? (Expr (Ebinop ???) ?));
1343                          >(Hsim_lhs 〈lval,ltrace〉 (refl ? (OK ? 〈lval,ltrace〉)))
1344                          >(Hsim_rhs 〈rval,rtrace〉 (refl ? (OK ? 〈rval,rtrace〉)))
1345                          normalize nodelta
1346                          >Htype_eq_lhs >Htype_eq_rhs
1347                          @SimOk * #val #trace #H @H
1348                     ]
1349                ]
1350           ]
1351      ]
1352   | *: @SimFailNicely
1353   ]
1355| 23,30,31,32,33,34,35,36: %1 try @refl
1356  [ 1,4,7,10,13,16,19,22: destruct // ]
1357  elim (Hcastee_equiv ge en m) * #Hexec_sim #Hlvalue_sim #Htype_eq
1358  (* exec_expr simulation *)
1359  [ 1,3,5,7,9,11,13,15: cases Hexec_sim
1360       [ 2,4,6,8,10,12,14,16: destruct * #error #Hexec_fail whd in match (exec_expr ge en m ?);
1361            >Hexec_fail @SimFailNicely
1362       | 1,3,5,7,9,11,13,15: #Hsim @SimOk * #val #trace <Hexpr_eq >Hdesc_eq
1363            whd in match (exec_expr ge en m ?); #Hstep
1364            cut (∃v1. exec_expr ge en m castee = OK ? 〈v1,trace〉
1365                    ∧ exec_cast m v1 (typeof castee) cast_ty = OK ? val)
1366            [ 1,3,5,7,9,11,13,15:
1367                 lapply Hstep -Hstep cases (exec_expr ge en m castee)
1368                 [ 2,4,6,8,10,12,14,16: #error1 normalize nodelta #Hcontr destruct
1369                 | 1,3,5,7,9,11,13,15: * #val1 #trace1 normalize nodelta
1370                      #Hstep @(ex_intro … val1)
1371                      cases (exec_cast m val1 (typeof castee) cast_ty) in Hstep;
1372                      [ 2,4,6,8,10,12,14,16: #error #Hstep normalize in Hstep; destruct
1373                      | 1,3,5,7,9,11,13,15: #result #Hstep normalize in Hstep; destruct
1374                           @conj @refl
1375                      ]
1376                 ]
1377            | 2,4,6,8,10,12,14,16: * #v1 * #Hexec_expr #Hexec_cast
1378                 whd in match (exec_expr ge en m ?);
1379                 >(Hsim … Hexec_expr ) normalize nodelta
1380                 <Htype_eq >Hexec_cast //
1381            ]
1382      ]
1383  | 2,4,6,8,10,12,14,16: destruct  @SimFailNicely
1384  ]
1385| 24: destruct inversion (Hcastee_inv ge en m)
1386  [ 1: #result_flag #Hresult_flag #Htype_eq #Hexpr_sim #Hlvalue_sim #Hresult_flag_2
1387       <Hresult_flag_2 in Hresult_flag; #Hcontr destruct
1388  | 2: #src_sz #src_sg #Htype_castee #Htype_castee1 #Hsmaller_eval #_ #Hinv_eq
1389       @(Inv_coerce_ok ??????? cast_sz cast_sg)
1390       [ 1: // | 2: <Htype_castee1 //
1391       | 3: whd in match (exec_expr ??? (Expr ??));
1392            >Htype_castee
1393            (* Simplify the goal by culling impossible cases, using Hsmaller_val *)
1394            cases (exec_expr ge en m castee) in Hsmaller_eval;
1395            [ 2: #error //
1396            | 1: * #castee_val #castee_trace #Hsmaller normalize nodelta
1397              lapply (exec_cast_inv castee_val src_sz src_sg cast_sz cast_sg m)
1398              cases (exec_cast m castee_val (Tint src_sz src_sg) (Tint cast_sz cast_sg))
1399              [ 2: #error #_ @I
1400              | 1: #result #Hinversion elim (Hinversion result (refl ? (OK ? result)))
1401                   #castee_int * #Hcastee_val_eq #Hresult_eq
1402                   whd in match (m_bind ?????);
1403                   #result_int #Hresult_eq2
1404                   cases (exec_expr ge en m castee1) in Hsmaller;
1405                   [ 2: #error normalize in ⊢ (% → ?); #Habsurd
1406                        @(False_ind … (Habsurd castee_int Hcastee_val_eq))
1407                   | 1: * #val1 #trace1 whd in ⊢ (% → ?); normalize nodelta
1408                        #Hsmaller elim (Hsmaller castee_int Hcastee_val_eq)
1409                        #val1_int * * * #Hval1_eq #Hval1_int_eq #Hcastee_trace_eq
1410                        destruct #Hle %{(cast_int_int src_sz src_sg target_sz castee_int)}
1411                        try @conj try @conj try @conj try //
1412                        [ 1: @cast_composition ] try assumption
1413                        elim (necessary_conditions_spec … (sym_eq … Hconditions))
1414                        [ 2,4: * #Heq >Heq #_ elim target_sz //
1415                        | 1,3: #Hlt @(size_lt_to_le ?? Hlt) ]
1416 ] ] ] ] ]
1417| 25,27: destruct
1418      inversion (Hcast2 ge en m)
1419      [ 1,3: (* Impossible case.  *)
1420           #result_flag #Hresult #Htype_eq #Hsim_expr #Hsim_lvalue #Hresult_contr <Hresult_contr in Hresult;
1421           #Hcontr destruct
1422      | 2,4: (* We successfuly cast the expression to the desired type. We can thus get rid of the "cast" itself.
1423              We did not successfuly cast the subexpression to target_sz, though. *)
1424           #src_sz #src_sg #Htype_castee #Htype_castee2 #Hsmaller_eval #_ #Hinv_eq
1425           @(Inv_eq ???????) //
1426           [ 1,3: >Htype_castee2 //
1427           | 2,4: (* Prove simulation for exec_expr *)
1428               whd in match (exec_expr ??? (Expr ??));
1429               cases (exec_expr ge en m castee) in Hsmaller_eval;
1430               [ 2,4: (* erroneous evaluation of the original expression *)
1431                     #error #Hsmaller_eval @SimFailNicely
1432               | 1,3: * #val #trace normalize nodelta >Htype_castee
1433                      lapply (exec_cast_inv val src_sz src_sg cast_sz cast_sg m)
1434                      cases (exec_cast m val (Tint src_sz src_sg) (Tint cast_sz cast_sg))
1435                      [ 2,4: #error #_ #_ @SimFailNicely
1436                      | 1,3: #result #Hinversion elim (Hinversion result (refl ??))
1437                             #val_int * #Hval_eq #Hresult_eq
1438                             cases (exec_expr ge en m castee2)
1439                             [ 2,4: #error #Hsmaller_eval normalize in Hsmaller_eval; @(False_ind … (Hsmaller_eval val_int Hval_eq))
1440                             | 1,3: * #val1 #trace1 #Hsmaller elim (Hsmaller val_int Hval_eq)
1441                                    #val1_int * * * #Hval1_eq #Hcast_eq #Htrace_eq #Hle
1442                                    destruct @SimOk normalize #a #H @H ]
1443                ] ]
1444      ] ]
1445| 26,28: destruct
1446      inversion (Hcast2 ge en m)
1447      [ 2,4: (* Impossible case. *)
1448            #src_sz #src_sg #Htype_castee #Htype_castee2 #Hsmaller_eval #Habsurd #Hinv_eq
1449            (* Do some gymnastic to transform the Habsurd jmeq into a proper, 'destruct'able eq *)
1450            letin Habsurd_eq ≝ (jmeq_to_eq ??? Habsurd) lapply Habsurd_eq
1451            -Habsurd_eq -Habsurd #Habsurd destruct
1452      | 1,3: (* All our attempts at casting down the expression have failed. We still use the
1453               resulting expression, as we may have discovered and simplified unrelated casts. *)
1454            #result_flag #Hresult #Htype_eq #Hsim_expr #Hsim_lvalue #_ #Hinv
1455            @(Inv_eq ???????) //
1456                 whd in match (exec_expr ??? (Expr ??));
1457                 whd in match (exec_expr ??? (Expr ??));
1458                 cases Hsim_expr
1459                 [ 2,4: * #error #Hexec_err >Hexec_err @SimFailNicely
1460                 | 1,3: #Hexec_ok
1461                      cases (exec_expr ge en m castee) in Hexec_ok;
1462                      [ 2,4: #error #Hsim @SimFailNicely
1463                      | 1,3: * #val #trace #Hsim normalize nodelta
1464                           >Htype_eq >(Hsim 〈val,trace〉 (refl ? (OK ? 〈val,trace〉))) normalize nodelta
1465                           @SimOk #a #H @H
1466                      ]
1467                 ]
1468      ]
1469| 29: destruct elim (Hcastee_equiv ge en m) * #Hsim_expr #Hsim_lvalue #Htype_eq
1470      @(Inv_eq ???????) //
1471      whd in match (exec_expr ??? (Expr ??));
1472      whd in match (exec_expr ??? (Expr ??));
1473      cases Hsim_expr
1474           [ 2: * #error #Hexec_fail >Hexec_fail @SimFailNicely
1475           | 1: #Hexec_ok @SimOk * #val #trace
1476                cases (exec_expr ge en m castee) in Hexec_ok;
1477                [ 2: #error #Habsurd normalize in Habsurd; normalize nodelta #H destruct
1478                | 1: * #val #trace #Hexec_ok normalize nodelta
1479                     >(Hexec_ok … 〈val, trace〉 (refl ? (OK ? 〈val, trace〉)))
1480                     >Htype_eq
1481                     normalize nodelta #H @H
1482                ]
1483           ]
1484| 37: destruct elim (bool_conj_inv … Hdesired_eq) #Hdesired_true #Hdesired_false -Hdesired_eq
1485      inversion (Htrue_inv ge en m)
1486      [ 1: #result_flag_true #Hresult_true #Htype_true #Hsim_expr_true #Hsim_lvalue_true #Hresult_flag_true_eq_false
1487           #Hinv <Hresult_flag_true_eq_false in Hresult_true; >Hdesired_true #Habsurd destruct
1488      | 2: #true_src_sz #true_src_sg #Htype_eq_true #Htype_eq_true1 #Hsmaller_true #_ #Hinv_true
1489           inversion (Hfalse_inv ge en m)
1490           [ 1: #result_flag_false #Hresult_false #Htype_false #Hsim_expr_false #Hsim_lvalue_false #Hresult_flag_false_eq_false
1491                #Hinv <Hresult_flag_false_eq_false in Hresult_false; >Hdesired_false #Habsurd destruct
1492           | 2: #false_src_sz #false_src_sg #Htype_eq_false #Htype_eq_false1 #Hsmaller_false #_ #Hinv_false
1493                >Htype_eq_true @(Inv_coerce_ok ??????? true_src_sz true_src_sg)
1494                [ 1,2: //
1495                | 3: whd in match (exec_expr ????); whd in match (exec_expr ??? (Expr ??));
1496                     elim (Hcond_equiv ge en m) * #Hexec_cond_sim #_ #Htype_cond_eq
1497                     cases Hexec_cond_sim
1498                     [ 2: * #error #Herror >Herror normalize @I
1499                     | 1: cases (exec_expr ge en m cond)
1500                          [ 2: #error #_ normalize @I
1501                          | 1: * #cond_val #cond_trace #Hcond_sim
1502                               >(Hcond_sim 〈cond_val,cond_trace〉 (refl ? (OK ? 〈cond_val,cond_trace〉)))
1503                               normalize nodelta
1504                               >Htype_cond_eq
1505                               cases (exec_bool_of_val cond_val (typeof cond1)) *
1506                               [ 3,4: normalize //
1507                               | 1,2: normalize in match (m_bind ?????);
1508                                      normalize in match (m_bind ?????);
1509                                      -Hexec_cond_sim -Hcond_sim -cond_val
1510                                      [ 1: (* true branch taken *)
1511                                           cases (exec_expr ge en m iftrue) in Hsmaller_true;
1512                                           [ 2: #error #_ @I
1513                                           | 1: * #val_true_branch #trace_true_branch #Hsmaller
1514                                                #val_true_branch #Hval_true_branch lapply Hsmaller -Hsmaller
1515                                                cases (exec_expr ge en m iftrue1)
1516                                                [ 2: #error normalize in ⊢ (% → ?); #Hsmaller
1517                                                     @(False_ind … (Hsmaller val_true_branch Hval_true_branch))
1518                                                | 1: * #val_true1_branch #trace_true1_branch #Hsmaller normalize nodelta
1519                                                     elim (Hsmaller val_true_branch Hval_true_branch)
1520                                                     #val_true1_int * * * #val_true1_branch #Hval_cast_eq #Htrace_eq #Hle
1521                                                     %{val_true1_int} try @conj try @conj try @conj //
1522                                           ] ]
1523                                     | 2: (* false branch taken. Same proof as above, different arguments ... *)
1524                                           cut (false_src_sz = true_src_sz ∧ false_src_sg = true_src_sg)
1525                                           [ 1: >Htype_eq_true in Hiftrue_eq_iffalse; >Htype_eq_false #Htype_eq
1526                                                destruct (Htype_eq) @conj @refl ] * #Hsz_eq #Hsg_eq destruct
1527                                           cases (exec_expr ge en m iffalse) in Hsmaller_false;
1528                                           [ 2: #error #_ @I
1529                                           | 1: destruct * #val_false_branch #trace_false_branch #Hsmaller
1530                                                #val_false_branch #Hval_false_branch lapply Hsmaller -Hsmaller
1531                                                cases (exec_expr ge en m iffalse1)
1532                                                [ 2: #error normalize in ⊢ (% → ?); #Hsmaller
1533                                                     @(False_ind … (Hsmaller val_false_branch Hval_false_branch))
1534                                                | 1: * #val_false1_branch #trace_false1_branch #Hsmaller normalize nodelta
1535                                                     elim (Hsmaller val_false_branch Hval_false_branch)
1536                                                     #val_false1_int * * * #val_false1_branch #Hval_cast_eq #Htrace_eq #Hle
1537                                                     %{val_false1_int} try @conj try @conj try @conj //
1538                                           ] ]
1539      ] ] ] ] ] ] ]
1540| 38,39,40: destruct
1541   elim (Hcond_equiv ge en m) * #Hsim_expr_cond #Hsim_vlalue_cond #Htype_cond_eq
1542   elim (Htrue_equiv ge en m) * #Hsim_expr_true #Hsim_vlalue_true #Htype_true_eq
1543   elim (Hfalse_equiv ge en m) * #Hsim_expr_false #Hsim_vlalue_false #Htype_false_eq
1544   %1 try @refl
1545   [ 1,3,5: whd in match (exec_expr ??? (Expr ??)); whd in match (exec_expr ??? (Expr ??));
1546            cases (exec_expr ge en m cond) in Hsim_expr_cond;
1547            [ 2,4,6: #error #_ @SimFailNicely
1548            | 1,3,5: * #cond_val #cond_trace normalize nodelta
1549                cases (exec_expr ge en m cond1)
1550                [ 2,4,6: #error *
1551                         [ 1,3,5: #Hsim lapply (Hsim 〈cond_val,cond_trace〉 (refl ? (OK ? 〈cond_val,cond_trace〉)))
1552                                  #Habsurd destruct
1553                         | *: * #error #Habsurd destruct ]
1554                | 1,3,5: * #cond_val1 #cond_trace1 *
1555                         [ 2,4,6: * #error #Habsurd destruct
1556                         | 1,3,5: #Hsim lapply (Hsim 〈cond_val,cond_trace〉 (refl ? (OK ? 〈cond_val,cond_trace〉)))
1557                             #Hcond_eq normalize nodelta destruct (Hcond_eq)
1558                             >Htype_cond_eq cases (exec_bool_of_val cond_val (typeof cond1))
1559                             [ 2,4,6: #error @SimFailNicely
1560                             | 1,3,5: * (* true branch *)
1561                                [ 1,3,5:
1562                                 normalize in match (m_bind ?????);
1563                                 normalize in match (m_bind ?????);
1564                                 cases Hsim_expr_true
1565                                 [ 2,4,6: * #error #Hexec_fail >Hexec_fail @SimFailNicely
1566                                 | 1,3,5: cases (exec_expr ge en m iftrue)
1567                                     [ 2,4,6: #error #_ normalize nodelta @SimFailNicely
1568                                     | 1,3,5: * #val_true #trace_true normalize nodelta #Hsim
1569                                              >(Hsim 〈val_true,trace_true〉 (refl ? (OK ? 〈val_true,trace_true〉)))
1570                                              normalize nodelta @SimOk #a #H @H
1571                                     ]
1572                                 ]
1573                             | 2,4,6:
1574                                 normalize in match (m_bind ?????);
1575                                 normalize in match (m_bind ?????);
1576                                 cases Hsim_expr_false
1577                                 [ 2,4,6: * #error #Hexec_fail >Hexec_fail normalize nodelta @SimFailNicely
1578                                 | 1,3,5: cases (exec_expr ge en m iffalse)
1579                                     [ 2,4,6: #error #_ normalize nodelta @SimFailNicely
1580                                     | 1,3,5: * #val_false #trace_false normalize nodelta #Hsim
1581                                              >(Hsim 〈val_false,trace_false〉 (refl ? (OK ? 〈val_false,trace_false〉)))
1582                                              normalize nodelta @SimOk #a #H @H
1583                                     ]
1584                                 ]
1585                               ]
1586                             ]
1587                          ]
1588                ]
1589            ]
1590   | 2,4,6: @SimFailNicely
1591   ]
1592| 41,42: destruct
1593    elim (Hlhs_equiv ge en m) * #Hsim_expr_lhs #Hsim_lvalue_lhs #Htype_eq_lhs
1594    elim (Hrhs_equiv ge en m) * #Hsim_expr_rhs #Hsim_lvalue_rhs #Htype_eq_rhs
1595    %1 try @refl
1596    [ 1,3: whd in match (exec_expr ??? (Expr ??));
1597           whd in match (exec_expr ??? (Expr ??));
1598           cases Hsim_expr_lhs
1599           [ 2,4: * #error #Hexec_fail >Hexec_fail normalize nodelta @SimFailNicely
1600           | 1,3: cases (exec_expr ge en m lhs)
1601              [ 2,4: #error #_ @SimFailNicely
1602              | 1,3: * #lhs_val #lhs_trace #Hsim normalize nodelta
1603                     >(Hsim 〈lhs_val,lhs_trace〉 (refl ? (OK ? 〈lhs_val,lhs_trace〉)))
1604                     normalize nodelta >Htype_eq_lhs
1605                     cases (exec_bool_of_val lhs_val (typeof lhs1))
1606                       [ 2,4: #error normalize @SimFailNicely
1607                     | 1,3: *
1608                         whd in match (m_bind ?????);
1609                         whd in match (m_bind ?????);
1610                         [ 2,3: (* lhs evaluates to true *)
1611                            @SimOk #a #H @H
1612                         | 1,4: cases Hsim_expr_rhs
1613                            [ 2,4: * #error #Hexec >Hexec @SimFailNicely
1614                            | 1,3: cases (exec_expr ge en m rhs)
1615                                [ 2,4: #error #_ @SimFailNicely
1616                                | 1,3: * #rhs_val #rhs_trace -Hsim #Hsim
1617                                       >(Hsim 〈rhs_val,rhs_trace〉 (refl ? (OK ? 〈rhs_val,rhs_trace〉)))
1618                                       normalize nodelta >Htype_eq_rhs
1619                                       @SimOk #a #H @H
1620                                ]
1621                            ]
1622                         ]
1623                      ]
1624              ]
1625          ]
1626   | 2,4:  @SimFailNicely
1627   ]
1628| 43: destruct
1629      cases (type_eq_dec ty (Tint target_sz target_sg))
1630      [ 1: #Htype_eq >Htype_eq >type_eq_identity
1631           @(Inv_coerce_ok ??????? target_sz target_sg)
1632           [ 1,2: //
1633           | 3: @smaller_integer_val_identity ]
1634      | 2: #Hneq >(type_neq_not_identity … Hneq)
1635           %1 // @SimOk #a #H @H
1636      ]
1637| 44: destruct elim (Hrec_expr_equiv ge en m) * #Hsim_expr #Hsim_lvalue #Htype_eq
1638      %1 try @refl
1639      [ 1: whd in match (exec_expr ??? (Expr ??)); whd in match (exec_expr ??? (Expr ??));
1640           whd in match (exec_lvalue ????) in Hsim_lvalue;
1641           whd in match (exec_lvalue' ?????);
1642           whd in match (exec_lvalue' ?????);
1643           >Htype_eq
1644           cases (typeof rec_expr1) normalize nodelta
1645           [ 2: #sz #sg | 3: #fl | 4: #ty | 5: #ty #n | 6: #tl #ty | 7: #id #fl | 8: #id #fl | 9: #ty ]
1646           [ 1,2,3,4,5,8,9: @SimFailNicely
1647           | 6,7: cases Hsim_lvalue
1648              [ 2,4: * #error #Herror >Herror normalize in ⊢ (??%?); @SimFailNicely
1649              | 1,3: cases (exec_lvalue ge en m rec_expr)
1650                 [ 2,4: #error #_ normalize in ⊢ (??%?); @SimFailNicely
1651                 | 1,3: #a #Hsim >(Hsim a (refl ? (OK ? a)))
1652                         whd in match (m_bind ?????);
1653                         @SimOk #a #H @H
1654                 ]
1655              ]
1656           ]
1657      | 2: whd in match (exec_lvalue ??? (Expr ??)); whd in match (exec_lvalue ??? (Expr ??));
1658           >Htype_eq
1659           cases (typeof rec_expr1) normalize nodelta
1660           [ 2: #sz #sg | 3: #fl | 4: #ty | 5: #ty #n | 6: #tl #ty | 7: #id #fl | 8: #id #fl | 9: #ty ]
1661           [ 1,2,3,4,5,8,9: @SimFailNicely
1662           | 6,7: cases Hsim_lvalue
1663              [ 2,4: * #error #Herror >Herror normalize in ⊢ (??%?); @SimFailNicely
1664              | 1,3: cases (exec_lvalue ge en m rec_expr)
1665                 [ 2,4: #error #_ normalize in ⊢ (??%?); @SimFailNicely
1666                 | 1,3: #a #Hsim >(Hsim a (refl ? (OK ? a)))
1667                         whd in match (m_bind ?????);
1668                         @SimOk #a #H @H
1669                 ]
1670              ]
1671           ]
1672     ]
1673| 45: destruct
1674   inversion (Hinv ge en m)
1675   [ 2: #src_sz #src_sg #Htypeof_e1 #Htypeof_e2 #Hsmaller #Hdesired_eq #_
1676         @(Inv_coerce_ok ??????? src_sz src_sg)
1677         [ 1: >Htypeof_e1 //
1678         | 2: >Htypeof_e2 //
1679         | 3: whd in match (exec_expr ??? (Expr ??));
1680              whd in match (exec_expr ??? (Expr ??));
1681              cases (exec_expr ge en m e1) in Hsmaller;
1682              [ 2: #error normalize //
1683              | 1: * #val1 #trace1 #Hsmaller #val1_int #Hval1_eq
1684                   cases (exec_expr ge en m e2) in Hsmaller;
1685                   [ 2: #error normalize in ⊢ (% → ?); #Habsurd @(False_ind … (Habsurd val1_int Hval1_eq))
1686                   | 1: * #val2 #trace #Hsmaller elim (Hsmaller val1_int Hval1_eq)
1687                        #val2_int * * * #Hval2_eq #Hcast #Htrace #Hle normalize nodelta
1688                        %{val2_int} try @conj try @conj try @conj //
1689                   ]
1690               ]
1691         ]
1692   | 1: #result_flag #Hresult #Htype_eq #Hsim_expr #Hsim_lvalue #Hdesired_typ #_
1693        >Hresult %1 try @refl
1694        [ 1: >Htype_eq //
1695        | 2: whd in match (exec_expr ??? (Expr ??));
1696             whd in match (exec_expr ??? (Expr ??));
1697             cases Hsim_expr
1698             [ 2: * #error #Hexec_error >Hexec_error @SimFailNicely
1699             | 1: cases (exec_expr ge en m e1)
1700                  [ 2: #error #_ @SimFailNicely
1701                  | 1: #a #Hsim lapply (Hsim a (refl ? (OK ? a))) #He2_exec >He2_exec
1702                        @SimOk #a #H @H
1703                  ]
1704             ]
1705        | 3: @SimFailNicely
1706        ]
1707   ]
1708| 46: destruct elim (Hexpr_equiv ge en m) * #Hsim_expr #Hsim_lvalue #Htype_eq
1709      %1 try @refl
1710      [ 1: whd in match (exec_expr ??? (Expr ??));
1711           whd in match (exec_expr ??? (Expr ??));
1712           cases Hsim_expr
1713           [ 2: * #error #Hexec_fail >Hexec_fail @SimFailNicely
1714           | 1: cases (exec_expr ge en m e1)
1715                [ 2: #error #_ @SimFailNicely
1716                | 1: #a #Hsim lapply (Hsim a (refl ? (OK ? a))) #Hsim2 >Hsim2 @SimOk #a #H @H ]
1717           ]
1718      | 2: @SimFail /2 by ex_intro/ ]
1719(* simplify_inside cases. Amounts to propagate a simulation result, except for the /cast/ case which actually calls
1720 * simplify_expr *)
1721| 47, 48, 49: (* trivial const_int, const_float and var cases *)
1722  try @conj try @conj try @refl
1723  @SimOk #a #H @H
1724| 50: (* Deref case *) destruct
1725  elim (Hequiv ge en m) * #Hsim_expr #Hsim_lvalue #Htype_eq
1726  try @conj try @conj
1727  [ 1:
1728    whd in match (exec_expr ??? (Expr ??));
1729    whd in match (exec_expr ??? (Expr ??));
1730    whd in match (exec_lvalue' ?????);
1731    whd in match (exec_lvalue' ?????);
1732  | 2:
1733    whd in match (exec_lvalue ??? (Expr ??));
1734    whd in match (exec_lvalue ??? (Expr ??));
1735  ]
1736  [ 1,2:
1737    cases Hsim_expr
1738    [ 2,4: * #error #Hexec_fail >Hexec_fail @SimFailNicely
1739    | 1,3: cases (exec_expr ge en m e1)
1740         [ 2,4: #error #_ @SimFailNicely
1741         | 1,3: #a #Hsim lapply (Hsim a (refl ? (OK ? a))) #H >H @SimOk #a #H @H ] ]
1742  | 3: // ]
1743| 51: (* Addrof *) destruct
1744  elim (Hequiv ge en m) * #Hsim_expr #Hsim_lvalue #Htype_eq
1745  try @conj try @conj
1746  [ 1:
1747    whd in match (exec_expr ??? (Expr ??));
1748    whd in match (exec_expr ??? (Expr ??));
1749    cases Hsim_lvalue
1750    [ 2: * #error #Hlvalue_fail >Hlvalue_fail @SimFailNicely
1751    | 1: cases (exec_lvalue ge en m e1)
1752       [ 2: #error #_ @SimFailNicely
1753       | 1: #a #Hsim lapply (Hsim a (refl ? (OK ? a))) #H >H @SimOk #a #H @H ] ]
1754  | 2: @SimFailNicely
1755  | 3: // ]
1756| 52: (* Unop *) destruct
1757  elim (Hequiv ge en m) * #Hsim_expr #Hsim_lvalue #Htype_eq
1758  try @conj try @conj
1759  [ 1:
1760    whd in match (exec_expr ??? (Expr ??));
1761    whd in match (exec_expr ??? (Expr ??));
1762    cases Hsim_expr
1763    [ 2: * #error #Hexec_fail >Hexec_fail @SimFailNicely
1764    | 1: cases (exec_expr ge en m e1)
1765         [ 2: #error #_ @SimFailNicely
1766         | 1: #a #Hsim lapply (Hsim a (refl ? (OK ? a))) #H >H @SimOk
1767              >Htype_eq #a #H @H ] ]
1768  | 2: @SimFailNicely
1769  | 3: // ]
1770| 53: (* Binop *) destruct
1771  elim (Hequiv_lhs ge en m) * #Hsim_expr_lhs #Hsim_lvalue_lhs #Htype_eq_lhs
1772  elim (Hequiv_rhs ge en m) * #Hsim_expr_rhs #Hsim_lvalue_rhs #Htype_eq_rhs
1773  try @conj try @conj
1774  [ 1:
1775    whd in match (exec_expr ??? (Expr ??));
1776    whd in match (exec_expr ??? (Expr ??));
1777    cases Hsim_expr_lhs
1778    [ 2: * #error #Hexec_fail >Hexec_fail @SimFailNicely
1779    | 1: cases (exec_expr ge en m lhs)
1780         [ 2: #error #_ @SimFailNicely
1781         | 1: #lhs_value #Hsim_lhs cases Hsim_expr_rhs
1782              [ 2: * #error #Hexec_fail >Hexec_fail @SimFailNicely
1783              | 1: cases (exec_expr ge en m rhs)
1784                   [ 2: #error #_ @SimFailNicely
1785                   | 1: #rhs_value #Hsim_rhs
1786                        lapply (Hsim_lhs lhs_value (refl ? (OK ? lhs_value)))
1787                        lapply (Hsim_rhs rhs_value (refl ? (OK ? rhs_value)))
1788                        #Hrhs >Hrhs #Hlhs >Hlhs >Htype_eq_rhs >Htype_eq_lhs
1789                        @SimOk #a #H @H
1790                   ]
1791              ]
1792         ]
1793    ]
1794  | 2: @SimFailNicely
1795  | 3: //
1796  ]
1797| 54: (* Cast, fallback case *)
1798  try @conj try @conj try @refl
1799  @SimOk #a #H @H
1800| 55: (* Cast, success case *) destruct
1801  inversion (Htrans_inv ge en m)
1802  [ 1: (* contradiction *)
1803       #result_flag #Hresult_flag #Htype_eq #Hsim_epr #Hsim_lvalue #Hresult_flag_true
1804       <Hresult_flag_true in Hresult_flag; #Habsurd destruct
1805  | 2: #src_sz #src_sg #Hsrc_type_eq #Htarget_type_eq #Hsmaller #_ #_
1806       try @conj try @conj try @conj
1807       [ 1: whd in match (exec_expr ??? (Expr ??));
1808            cases (exec_expr ge en m castee) in Hsmaller;
1809            [ 2: #error #_ @SimFailNicely
1810            | 1: * #val #trace normalize nodelta >Hsrc_type_eq
1811                 lapply (exec_cast_inv val src_sz src_sg cast_sz cast_sg m)
1812                 cases (exec_cast m val ??)
1813                 [ 2: #error #_ #_ @SimFailNicely
1814                 | 1: #result #Hinversion elim (Hinversion result (refl ??))
1815                      #val_int * #Hval_eq #Hcast
1816                      cases (exec_expr ge en m castee1)
1817                      [ 2: #error #Habsurd normalize in Habsurd; @(False_ind … (Habsurd val_int Hval_eq))
1818                      | 1: * #val1 #trace1 #Hsmaller elim (Hsmaller val_int Hval_eq)
1819                           #val1_int * * * #Hval1_int #Hval18int #Htrace #Hle
1820                           @SimOk destruct normalize // ]
1821                      ]
1822             ]
1823      | 2: @SimFailNicely
1824      | 3: >Htarget_type_eq //
1825      ]
1826  ]
1827| 56: (* Cast, "failure" case *) destruct
1828  inversion (Htrans_inv ge en m)
1829  [ 2: (* contradiction *)
1830       #src_sz #src_sg #Htype_castee #Htype_castee1 #Hsmaller #Habsurd
1831       lapply (jmeq_to_eq ??? Habsurd) -Habsurd #Herror destruct
1832  | 1: #result_flag #Hresult_flag #Htype_eq #Hsim_expr #Hsim_lvalue #_ #_
1833       try @conj try @conj try @conj
1834       [ 1: whd in match (exec_expr ????);
1835            whd in match (exec_expr ??? (Expr ??));
1836            cases Hsim_expr
1837            [ 2: * #error #Hexec_fail >Hexec_fail @SimFailNicely
1838            | 1: cases (exec_expr ??? castee)
1839                 [ 2: #error #_ @SimFailNicely
1840                 | 1: #a #Hsim lapply (Hsim a (refl ? (OK ? a))) #Hexec_ok >Hexec_ok
1841                       @SimOk >Htype_eq #a #H @H ]
1842            ]
1843       | 2: @SimFailNicely
1844       | 3: //
1845       ]
1846  ]
1847| 57,58,59,60,61,62,63,64,68:
1848  try @conj try @conj try @refl
1849  @SimOk #a #H @H
1850| 65: destruct
1851  elim (Hequiv_cond ge en m) * #Hsim_exec_cond #Hsim_lvalue_cond #Htype_eq_cond
1852  elim (Hequiv_iftrue ge en m) * #Hsim_exec_true #Hsim_lvalue_true #Htype_eq_true
1853  elim (Hequiv_iffalse ge en m) * #Hsim_exec_false #Hsim_lvalue_false #Htype_eq_false
1854  try @conj try @conj
1855  [ 1: whd in match (exec_expr ??? (Expr ??));
1856       whd in match (exec_expr ??? (Expr ??));
1857       cases Hsim_exec_cond
1858       [ 2: * #error #Hexec_fail >Hexec_fail @SimFailNicely
1859       | 1: cases (exec_expr ??? cond)
1860            [ 2: #error #_ @SimFailNicely
1861            | 1: * #condb #condtrace #Hcond_sim lapply (Hcond_sim 〈condb, condtrace〉 (refl ? (OK ? 〈condb, condtrace〉)))
1862                 #Hcond_ok >Hcond_ok >Htype_eq_cond
1863                 normalize nodelta
1864                 cases (exec_bool_of_val condb (typeof cond1))
1865                 [ 2: #error @SimFailNicely
1866                 | 1: * whd in match (m_bind ?????); whd in match (m_bind ?????);
1867                      normalize nodelta
1868                      [ 1: (* true branch taken *)
1869                           cases Hsim_exec_true
1870                           [ 2: * #error #Hexec_fail >Hexec_fail @SimFailNicely
1871                           | 1: cases (exec_expr ??? iftrue)
1872                                [ 2: #error #_ @SimFailNicely
1873                                | 1: #a #Hsim lapply (Hsim a (refl ? (OK ? a))) #H >H
1874                                     @SimOk #a #H @H
1875                                ]
1876                           ]
1877                      | 2: (* false branch taken *)
1878                           cases Hsim_exec_false
1879                           [ 2: * #error #Hexec_fail >Hexec_fail @SimFailNicely
1880                           | 1: cases (exec_expr ??? iffalse)
1881                                [ 2: #error #_ @SimFailNicely
1882                                | 1: #a #Hsim lapply (Hsim a (refl ? (OK ? a))) #H >H
1883                                     @SimOk #a #H @H
1884                                ]
1885                           ]
1886                      ]
1887                ]
1888           ]
1889      ]
1890  | 2: @SimFailNicely
1891  | 3: //
1892  ]
1893| 66,67: destruct
1894  elim (Hequiv_lhs ge en m) * #Hsim_exec_lhs #Hsim_lvalue_lhs #Htype_eq_lhs
1895  elim (Hequiv_rhs ge en m) * #Hsim_exec_rhs #Hsim_lvalue_rhs #Htype_eq_rhs
1896  try @conj try @conj
1897  whd in match (exec_expr ??? (Expr ??));
1898  whd in match (exec_expr ??? (Expr ??));
1899  [ 1,4: cases Hsim_exec_lhs
1900       [ 2,4: * #error #Hexec_fail >Hexec_fail @SimFailNicely
1901       | 1,3: cases (exec_expr ??? lhs)
1902            [ 2,4: #error #_ @SimFailNicely
1903            | 1,3: #a #Hsim lapply (Hsim a (refl ? (OK ? a))) #Hlhs >Hlhs >Htype_eq_lhs
1904                   normalize nodelta elim a #lhs_val #lhs_trace
1905                   cases (exec_bool_of_val lhs_val (typeof lhs1))
1906                   [ 2,4: #error @SimFailNicely
1907                   | 1,3: * whd in match (m_bind ?????); whd in match (m_bind ?????);
1908                        [ 2,3: @SimOk //
1909                        | 1,4: cases Hsim_exec_rhs
1910                            [ 2,4: * #error #Hexec_fail >Hexec_fail @SimFailNicely
1911                            | 1,3: cases (exec_expr ??? rhs)
1912                               [ 2,4: #error #_ @SimFailNicely
1913                               | 1,3: #a #Hsim lapply (Hsim a (refl ? (OK ? a))) #Hrhs >Hrhs >Htype_eq_rhs
1914                                    @SimOk #a #H @H
1915                               ]
1916                            ]
1917                        ]
1918                   ]
1919             ]
1920        ]
1921  | 2,5: @SimFailNicely
1922  | 3,6: //
1923  ]
1924| 69: (* record field *) destruct
1925   elim (Hequiv_rec ge en m) * #Hsim_expr #Hsim_lvalue #Htype_eq
1926   try @conj try @conj
1927   whd in match (exec_expr ??? (Expr ??));
1928   whd in match (exec_expr ??? (Expr ??));
1929   whd in match (exec_lvalue' ??? (Efield rec_expr f) ty);
1930   whd in match (exec_lvalue' ??? (Efield rec_expr1 f) ty);
1931   [ 1: >Htype_eq cases (typeof rec_expr1) normalize nodelta
1932       [ 2: #sz #sg | 3: #fl | 4: #ty' | 5: #ty #n | 6: #tl #ty'
1933       | 7: #id #fl | 8: #id #fl | 9: #id ]
1934       try (@SimFailNicely)
1935       cases Hsim_lvalue
1936       [ 2,4: * #error #Hlvalue_fail >Hlvalue_fail @SimFailNicely
1937       | 1,3: cases (exec_lvalue ge en m rec_expr)
1938            [ 2,4: #error #_ @SimFailNicely
1939            | 1,3: #a #Hsim lapply (Hsim a (refl ? (OK ? a))) #Hexec >Hexec
1940                   @SimOk #a #H @H ]
1941       ]
1942   | 2: (* Note: identical to previous case. Too lazy to merge and manually shift indices. *)
1943       >Htype_eq cases (typeof rec_expr1) normalize nodelta
1944       [ 2: #sz #sg | 3: #fl | 4: #ty' | 5: #ty #n | 6: #tl #ty'
1945       | 7: #id #fl | 8: #id #fl | 9: #id ]
1946       try (@SimFailNicely)
1947       cases Hsim_lvalue
1948       [ 2,4: * #error #Hlvalue_fail >Hlvalue_fail @SimFailNicely
1949       | 1,3: cases (exec_lvalue ge en m rec_expr)
1950            [ 2,4: #error #_ @SimFailNicely
1951            | 1,3: #a #Hsim lapply (Hsim a (refl ? (OK ? a))) #Hexec >Hexec
1952                   @SimOk #a #H @H ]
1953       ]
1954   | 3: // ]
1955| 70: (* cost label *) destruct
1956   elim (Hequiv ge en m) *  #Hsim_expr #Hsim_lvalue #Htype_eq
1957   try @conj try @conj
1958   whd in match (exec_expr ??? (Expr ??));
1959   whd in match (exec_expr ??? (Expr ??));
1960   [ 1:
1961     cases Hsim_expr
1962     [ 2: * #error #Hexec >Hexec @SimFailNicely
1963     | 1: cases (exec_expr ??? e1)
1964          [ 2: #error #_ @SimFailNicely
1965          | 1: #a #Hsim lapply (Hsim a (refl ? (OK ? a))) #H >H
1966               @SimOk #a #H @H ]
1967     ]
1968   | 2: @SimFail /2 by ex_intro/
1969   | 3: //
1970   ]
1971] qed.
1972
1973(* Propagate cast simplification through statements and programs. *)
1974
1975definition simplify_e ≝ λe. pi1 … (simplify_inside e).
1976
1977let rec simplify_statement (s:statement) : statement ≝
1978match s with
1979[ Sskip ⇒ Sskip
1980| Sassign e1 e2 ⇒ Sassign (simplify_e e1) (simplify_e e2)
1981| Scall eo e es ⇒ Scall (option_map ?? simplify_e eo) (simplify_e e) (map ?? simplify_e es)
1982| Ssequence s1 s2 ⇒ Ssequence (simplify_statement s1) (simplify_statement s2)
1983| Sifthenelse e s1 s2 ⇒ Sifthenelse (simplify_e e) (simplify_statement s1) (simplify_statement s2) (* TODO: try to reduce size of e *)
1984| Swhile e s1 ⇒ Swhile (simplify_e e) (simplify_statement s1) (* TODO: try to reduce size of e *)
1985| Sdowhile e s1 ⇒ Sdowhile (simplify_e e) (simplify_statement s1) (* TODO: try to reduce size of e *)
1986| Sfor s1 e s2 s3 ⇒ Sfor (simplify_statement s1) (simplify_e e) (simplify_statement s2) (simplify_statement s3) (* TODO: reduce size of e *)
1987| Sbreak ⇒ Sbreak
1988| Scontinue ⇒ Scontinue
1989| Sreturn eo ⇒ Sreturn (option_map ?? simplify_e eo)
1990| Sswitch e ls ⇒ Sswitch (simplify_e e) (simplify_ls ls)
1991| Slabel l s1 ⇒ Slabel l (simplify_statement s1)
1992| Sgoto l ⇒ Sgoto l
1993| Scost l s1 ⇒ Scost l (simplify_statement s1)
1994]
1995and simplify_ls ls ≝
1996match ls with
1997[ LSdefault s ⇒ LSdefault (simplify_statement s)
1998| LScase sz i s ls' ⇒ LScase sz i (simplify_statement s) (simplify_ls ls')
1999].
2000
2001definition simplify_function : function → function ≝
2002λf. mk_function (fn_return f) (fn_params f) (fn_vars f) (simplify_statement (fn_body f)).
2003
2004definition simplify_fundef : clight_fundef → clight_fundef ≝
2005λf. match f with
2006  [ CL_Internal f ⇒ CL_Internal (simplify_function f)
2007  | _ ⇒ f
2008  ].
2009
2010definition simplify_program : clight_program → clight_program ≝
2011λp. transform_program … p (λ_.simplify_fundef).
2012
2013(* Simulation on statement continuations. Stolen from labelSimulation and adapted to our setting. *)
2014inductive cont_cast : cont → cont → Prop ≝
2015| cc_stop : cont_cast Kstop Kstop
2016| cc_seq : ∀s,k,k'. cont_cast k k' → cont_cast (Kseq s k) (Kseq (simplify_statement s) k')
2017| cc_while : ∀e,s,k,k'.
2018    cont_cast k k' →
2019    cont_cast (Kwhile e s k) (Kwhile (simplify_e e) (simplify_statement s) k')
2020| cc_dowhile : ∀e,s,k,k'.
2021    cont_cast k k' →
2022    cont_cast (Kdowhile e s k) (Kdowhile (simplify_e e) (simplify_statement s) k')
2023| cc_for1 : ∀e,s1,s2,k,k'.
2024    cont_cast k k' →
2025    cont_cast (Kseq (Sfor Sskip e s1 s2) k) (Kseq (Sfor Sskip (simplify_e e) (simplify_statement s1) (simplify_statement s2)) k')
2026| cc_for2 : ∀e,s1,s2,k,k'.
2027    cont_cast k k' →
2028    cont_cast (Kfor2 e s1 s2 k) (Kfor2 (simplify_e e) (simplify_statement s1) (simplify_statement s2) k')
2029| cc_for3 : ∀e,s1,s2,k,k'.
2030    cont_cast k k' →
2031    cont_cast (Kfor3 e s1 s2 k) (Kfor3 (simplify_e e) (simplify_statement s1) (simplify_statement s2) k')
2032| cc_switch : ∀k,k'.
2033    cont_cast k k' → cont_cast (Kswitch k) (Kswitch k')
2034| cc_call : ∀r,f,en,k,k'.
2035    cont_cast k k' →
2036    cont_cast (Kcall r f en k) (Kcall r (simplify_function f) en k').
2037
2038lemma call_cont_cast : ∀k,k'.
2039  cont_cast k k' →
2040  cont_cast (call_cont k) (call_cont k').
2041#k0 #k0' #K elim K /2/
2042qed.
2043
2044inductive state_cast : state → state → Prop ≝
2045| swc_state : ∀f,s,k,k',e,m.
2046  cont_cast k k' →
2047  state_cast (State f s k e m) (State (simplify_function f) (simplify_statement s ) k' e m)
2048| swc_callstate : ∀fd,args,k,k',m.
2049  cont_cast k k' → state_cast (Callstate fd args k m) (Callstate (simplify_fundef fd) args k' m)
2050| swc_returnstate : ∀res,k,k',m.
2051  cont_cast k k' → state_cast (Returnstate res k m) (Returnstate res k' m)
2052| swc_finalstate : ∀r.
2053  state_cast (Finalstate r) (Finalstate r)
2054.
2055
2056record related_globals (F:Type[0]) (t:F → F) (ge:genv_t F) (ge':genv_t F) : Prop ≝ {
2057  rg_find_symbol: ∀s.
2058    find_symbol ? ge s = find_symbol ? ge' s;
2059  rg_find_funct: ∀v,f.
2060    find_funct ? ge v = Some ? f →
2061    find_funct ? ge' v = Some ? (t f);
2062  rg_find_funct_ptr: ∀b,f.
2063    find_funct_ptr ? ge b = Some ? f →
2064    find_funct_ptr ? ge' b = Some ? (t f)
2065}.
2066
2067(* The return type of any function is invariant under cast simplification *)
2068lemma fn_return_simplify : ∀f. fn_return (simplify_function f) = fn_return f.
2069// qed.
2070
2071
2072definition expr_lvalue_ind_combined ≝
2073λP,Q,ci,cf,lv,vr,dr,ao,uo,bo,ca,cd,ab,ob,sz,fl,co,xx.
2074conj ??
2075 (expr_lvalue_ind P Q ci cf lv vr dr ao uo bo ca cd ab ob sz fl co xx)
2076 (lvalue_expr_ind P Q ci cf lv vr dr ao uo bo ca cd ab ob sz fl co xx).
2077
2078lemma simulation_transitive : ∀A,r0,r1,r2. res_sim A r0 r1 → res_sim A r1 r2 → res_sim A r0 r2.
2079#A #r0 #r1 #r2 *
2080[ 2: * #error #H >H #_ @SimFail /2 by ex_intro/
2081| 1: cases r0
2082     [ 2: #error #_ #_ @SimFail /2 by ex_intro/
2083     | 1: #elt #Hsim lapply (Hsim elt (refl ? (OK ? elt))) #H >H // ]
2084] qed.
2085
2086lemma sim_related_globals : ∀ge,ge',en,m. related_globals ? simplify_fundef ge ge' →
2087  (∀e. res_sim ? (exec_expr ge en m e) (exec_expr ge' en m e)) ∧
2088  (∀ed, ty. res_sim ? (exec_lvalue' ge en m ed ty) (exec_lvalue' ge' en m ed ty)).
2089#ge #ge' #en #m #Hrelated @expr_lvalue_ind_combined
2090[ 1: #sz #ty #i @SimOk #a normalize //
2091| 2: #ty #f @SimOk #a normalize //
2092| 3: *
2093    [ 1: #sz #i | 2: #fl | 3: #id | 4: #e1 | 5: #e1 | 6: #op #e1 | 7: #op #e1 #e2 | 8: #cast_ty #e1
2094    | 9: #cond #iftrue #iffalse | 10: #e1 #e2 | 11: #e1 #e2 | 12: #sizeofty | 13: #e1 #field | 14: #cost #e1 ]
2095    #ty #Hsim_lvalue try //
2096    whd in match (Plvalue ???);
2097    whd in match (exec_expr ????);
2098    whd in match (exec_expr ????);
2099    cases Hsim_lvalue
2100    [ 2,4,6: * #error #Hlvalue_fail >Hlvalue_fail @SimFail /2 by ex_intro/
2101    | *: cases (exec_lvalue' ge en m ? ty)
2102         [ 2,4,6: #error #_ @SimFail /2 by ex_intro/
2103         | *: #a #Hsim_lvalue lapply (Hsim_lvalue a (refl ? (OK ? a))) #Hrewrite >Hrewrite
2104              @SimOk // ]
2105    ]
2106| 4: #v #ty whd in match (exec_lvalue' ?????); whd in match (exec_lvalue' ?????);
2107     cases (lookup SymbolTag block en v) normalize nodelta
2108     [ 2: #block @SimOk //
2109     | 1: elim Hrelated #Hsymbol #_ #_ >(Hsymbol v) @SimOk //
2110     ]
2111| 5: #e #ty #Hsim_expr whd in match (exec_lvalue' ?????); whd in match (exec_lvalue' ?????);
2112     cases Hsim_expr
2113     [ 2: * #error #Hfail >Hfail @SimFail /2 by ex_intro/
2114     | 1: cases (exec_expr ge en m e)
2115          [ 2: #error #_ @SimFail /2 by ex_intro/
2116          | 1: #a #Hsim lapply (Hsim a (refl ? (OK ? a))) #Hrewrite >Hrewrite
2117                @SimOk // ]
2118     ]
2119| 6: #ty #ed #ty' #Hsim_lvalue
2120     whd in match (exec_expr ????); whd in match (exec_expr ????);
2121     whd in match (exec_lvalue ????); whd in match (exec_lvalue ????);
2122     cases Hsim_lvalue
2123     [ 2: * #error #Hlvalue_fail >Hlvalue_fail @SimFail /2 by ex_intro/
2124     | 1: cases (exec_lvalue' ge en m ed ty')
2125         [ 2: #error #_ @SimFail /2 by ex_intro/
2126         | *: #a #Hsim_lvalue lapply (Hsim_lvalue a (refl ? (OK ? a))) #Hrewrite >Hrewrite
2127              @SimOk // ]
2128    ]
2129| 7: #ty #op #e #Hsim whd in match (exec_expr ??? (Expr ??)); whd in match (exec_expr ??? (Expr ??));
2130     cases Hsim
2131     [ 2: * #error #Hfail >Hfail @SimFail /2 by ex_intro/
2132     | 1: cases (exec_expr ge en m e)
2133          [ 2: #error #_ @SimFail /2 by ex_intro/
2134          | 1: #a #Hsim lapply (Hsim a (refl ? (OK ? a))) #Hrewrite >Hrewrite
2135               @SimOk // ]
2136     ]
2137| 8: #ty #op #e1 #e2 #Hsim1 #Hsim2 whd in match (exec_expr ??? (Expr ??)); whd in match (exec_expr ??? (Expr ??));
2138     cases Hsim1
2139     [ 2: * #error #Hfail >Hfail @SimFail /2 by ex_intro/
2140     | 1: cases (exec_expr ge en m e1)
2141          [ 2: #error #_ @SimFail /2 by ex_intro/
2142          | 1: #a #Hsim lapply (Hsim a (refl ? (OK ? a))) #Hrewrite >Hrewrite
2143               cases Hsim2
2144               [ 2: * #error #Hfail >Hfail @SimFail /2 by ex_intro/
2145               | 1: cases (exec_expr ge en m e2)
2146                    [ 2: #error #_ @SimFail /2 by ex_intro/
2147                    | 1: #a #Hsim lapply (Hsim a (refl ? (OK ? a))) #Hrewrite >Hrewrite
2148                         @SimOk // ]
2149               ]
2150          ]
2151     ]
2152| 9: #ty #cast_ty #e #Hsim whd in match (exec_expr ??? (Expr ??)); whd in match (exec_expr ??? (Expr ??));
2153     cases Hsim
2154     [ 2: * #error #Hfail >Hfail @SimFail /2 by ex_intro/
2155     | 1: cases (exec_expr ge en m e)
2156          [ 2: #error #_ @SimFail /2 by ex_intro/
2157          | 1: #a #Hsim lapply (Hsim a (refl ? (OK ? a))) #Hrewrite >Hrewrite
2158               @SimOk // ]
2159     ] (* mergeable with 7 modulo intros *)
2160| 10: #ty #e1 #e2 #e3 #Hsim1 #Hsim2 #Hsim3 whd in match (exec_expr ??? (Expr ??)); whd in match (exec_expr ??? (Expr ??));
2161     cases Hsim1
2162     [ 2: * #error #Hfail >Hfail @SimFail /2 by ex_intro/
2163     | 1: cases (exec_expr ge en m e1)
2164          [ 2: #error #_ @SimFail /2 by ex_intro/
2165          | 1: #a #Hsim lapply (Hsim a (refl ? (OK ? a))) #Hrewrite >Hrewrite normalize nodelta
2166               cases (exec_bool_of_val (\fst a) (typeof e1))
2167               [ 2: #error @SimFail /2 by ex_intro/
2168               | 1: *
2169                    [ 1: (* true branch *) cases Hsim2
2170                    | 2: (* false branch *) cases Hsim3 ]
2171                    [ 2,4: * #error #Hfail >Hfail @SimFail /2 by ex_intro/
2172                    | 1: cases (exec_expr ge en m e2) | 3: cases (exec_expr ge en m e3) ]
2173                    [ 2,4: #error #_ @SimFail /2 by ex_intro/
2174                    | 1,3: #a #Hsim lapply (Hsim a (refl ? (OK ? a))) #Hrewrite >Hrewrite @SimOk // ]
2175              ]
2176          ]
2177     ]
2178| 11,12: #ty #e1 #e2 #Hsim1 #Hsim2 whd in match (exec_expr ??? (Expr ??)); whd in match (exec_expr ??? (Expr ??));
2179     cases Hsim1
2180     [ 2,4: * #error #Hfail >Hfail @SimFailNicely
2181     | 1,3: cases (exec_expr ge en m e1)
2182          [ 2,4: #error #_ @SimFailNicely
2183          | 1,3: #a #Hsim lapply (Hsim a (refl ? (OK ? a))) #Hrewrite >Hrewrite normalize nodelta
2184                 cases (exec_bool_of_val ??)
2185                 [ 2,4: #erro @SimFailNicely
2186                 | 1,3: * whd in match (m_bind ?????); whd in match (m_bind ?????);
2187                        [ 2,3: @SimOk //
2188                        | 1,4: cases Hsim2
2189                               [ 2,4: * #error #Hfail >Hfail normalize nodelta @SimFail /2 by ex_intro/
2190                               | 1,3: cases (exec_expr ge en m e2)
2191                                      [ 2,4: #error #_ @SimFail /2 by ex_intro/
2192                                      | 1,3: #a #Hsim lapply (Hsim a (refl ? (OK ? a))) #Hrewrite >Hrewrite
2193                                           @SimOk // ]
2194                               ]
2195                        ]
2196                ]
2197          ]
2198     ]
2199| 13: #ty #sizeof_ty @SimOk normalize //
2200| 14: #ty #e #ty' #field #Hsim_lvalue
2201      whd in match (exec_lvalue' ? en m (Efield ??) ty);
2202      whd in match (exec_lvalue' ge' en m (Efield ??) ty);
2203      normalize in match (typeof (Expr ??));
2204      cases ty' in Hsim_lvalue; normalize nodelta
2205      [ 2: #sz #sg | 3: #fsz | 4: #ptr_ty | 5: #array_ty #array_sz | 6: #domain #codomain
2206      | 7: #structname #fieldspec | 8: #unionname #fieldspec | 9: #id ]
2207      #Hsim_lvalue
2208      try (@SimFail /2 by ex_intro/)
2209      normalize in match (exec_lvalue ge en m ?);
2210      normalize in match (exec_lvalue ge' en m ?);
2211      cases Hsim_lvalue
2212      [ 2,4: * #error #Hfail >Hfail @SimFail /2 by ex_intro/
2213      | 1,3: cases (exec_lvalue' ge en m e ?)
2214             [ 2,4: #error #_ @SimFail /2 by ex_intro/
2215             | 1,3: #a #Hsim lapply (Hsim a (refl ? (OK ? a))) #Hrewrite >Hrewrite
2216                    @SimOk /2 by ex_intro/ ]
2217      ]
2218| 15: #ty #lab #e #Hsim
2219      whd in match (exec_expr ??? (Expr ??));
2220      whd in match (exec_expr ??? (Expr ??));
2221      cases Hsim
2222     [ 2: * #error #Hfail >Hfail @SimFail /2 by ex_intro/
2223     | 1: cases (exec_expr ge en m e)
2224          [ 2: #error #_ @SimFail /2 by ex_intro/
2225          | 1: #a #Hsim lapply (Hsim a (refl ? (OK ? a))) #Hrewrite >Hrewrite
2226               @SimOk // ]
2227     ] (* cf case 7, again *)
2228| 16: *
2229      [ 1: #sz #i | 2: #fl | 3: #id | 4: #e1 | 5: #e1 | 6: #op #e1 | 7: #op #e1 #e2 | 8: #cast_ty #e1
2230      | 9: #cond #iftrue #iffalse | 10: #e1 #e2 | 11: #e1 #e2 | 12: #sizeofty | 13: #e1 #field | 14: #cost #e1 ]
2231      #ty normalize in match (is_not_lvalue ?);
2232      [ 3,4,13: #Habsurd @(False_ind … Habsurd) ] #_
2233      @SimFailNicely
2234] qed.
2235
2236lemma related_globals_expr_simulation : ∀ge,ge',en,m.
2237  related_globals ? simplify_fundef ge ge' →
2238  ∀e. res_sim ? (exec_expr ge en m e) (exec_expr ge' en m (simplify_e e)) ∧
2239      typeof e = typeof (simplify_e e).
2240#ge #ge' #en #m #Hrelated #e whd in match (simplify_e ?);
2241cases e #ed #ty cases ed
2242[ 1: #sz #i | 2: #fl | 3: #id | 4: #e1 | 5: #e1 | 6: #op #e1 | 7: #op #e1 #e2 | 8: #cast_ty #e1
2243| 9: #cond #iftrue #iffalse | 10: #e1 #e2 | 11: #e1 #e2 | 12: #sizeofty | 13: #e1 #field | 14: #cost #e1 ]
2244elim (simplify_inside (Expr ??)) #e' #Hconservation whd in Hconservation; @conj lapply (Hconservation ge en m)
2245* * try //
2246cases (exec_expr ge en m (Expr ??))
2247try (#error #_ #_ #_ @SimFailNicely)
2248* #val #trace #Hsim_expr #Hsim_lvalue #Htype_eq
2249try @(simulation_transitive ???? Hsim_expr (proj1 ?? (sim_related_globals ge ge' en m Hrelated) ?))
2250qed.
2251
2252lemma related_globals_lvalue_simulation : ∀ge,ge',en,m.
2253  related_globals ? simplify_fundef ge ge' →
2254  ∀e. res_sim ? (exec_lvalue ge en m e) (exec_lvalue ge' en m (simplify_e e)) ∧
2255      typeof e = typeof (simplify_e e).
2256#ge #ge' #en #m #Hrelated #e whd in match (simplify_e ?);
2257cases e #ed #ty cases ed
2258[ 1: #sz #i | 2: #fl | 3: #id | 4: #e1 | 5: #e1 | 6: #op #e1 | 7: #op #e1 #e2 | 8: #cast_ty #e1
2259| 9: #cond #iftrue #iffalse | 10: #e1 #e2 | 11: #e1 #e2 | 12: #sizeofty | 13: #e1 #field | 14: #cost #e1 ]
2260elim (simplify_inside (Expr ??)) #e' #Hconservation whd in Hconservation; @conj lapply (Hconservation ge en m)
2261* * try //
2262cases (exec_lvalue ge en m (Expr ??))
2263try (#error #_ #_ #_ @SimFailNicely)
2264* #val #trace #Hsim_expr #Hsim_lvalue #Htype_eq
2265(* Having to distinguish between exec_lvalue' and exec_lvalue is /ugly/. *)
2266cases e' in Hsim_lvalue ⊢ %; #ed' #ty' whd in match (exec_lvalue ????); whd in match (exec_lvalue ????);
2267lapply (proj2 ?? (sim_related_globals ge ge' en m Hrelated) ed' ty') #Hsim_lvalue2 #Hsim_lvalue1
2268try @(simulation_transitive ???? Hsim_lvalue1 Hsim_lvalue2)
2269qed.
2270
2271lemma related_globals_exprlist_simulation : ∀ge,ge',en,m.
2272related_globals ? simplify_fundef ge ge' →
2273∀args. res_sim ? (exec_exprlist ge en m args ) (exec_exprlist ge' en m (map expr expr simplify_e args)).
2274#ge #ge' #en #m #Hrelated #args
2275elim args
2276[ 1: /3/
2277| 2: #hd #tl #Hind normalize
2278     elim (related_globals_expr_simulation ge ge' en m Hrelated hd)
2279     *
2280     [ 2: * #error #Hfail >Hfail #_ @SimFail /2 by refl, ex_intro/
2281     | 1: cases (exec_expr ge en m hd)
2282          [ 2: #error #_ #_ @SimFail /2 by refl, ex_intro/
2283          | 1: #a #Hsim lapply (Hsim a (refl ? (OK ? a))) #Heq >Heq #Htype_eq >Htype_eq
2284               cases Hind normalize
2285               [ 2: * #error #Hfail >Hfail @SimFail /2 by refl, ex_intro/
2286               | 1: cases (exec_exprlist ??? tl)
2287                    [ 2: #error #_ @SimFail /2 by refl, ex_intro/
2288                    | 1: * #values #trace #Hsim lapply (Hsim 〈values, trace〉 (refl ? (OK ? 〈values, trace〉)))
2289                         #Heq >Heq @SimOk // ]
2290               ]
2291          ]
2292     ]
2293] qed.
2294
2295lemma simplify_type_of_fundef_eq : ∀clfd. (type_of_fundef (simplify_fundef clfd)) = (type_of_fundef clfd).
2296* // qed.
2297
2298lemma simplify_typeof_eq : ∀ge:genv.∀en:env.∀m:mem. ∀func. typeof (simplify_e func) = typeof func.
2299#ge #en #m #func whd in match (simplify_e func); elim (simplify_inside func)
2300#func' #H lapply (H ge en m) * * #_ #_ //
2301qed.
2302
2303lemma simplify_fun_typeof_eq : ∀ge:genv.∀en:env.∀m:mem. ∀func. fun_typeof (simplify_e func) = fun_typeof func.
2304#ge #en #m #func whd in match (simplify_e func); whd in match (fun_typeof ?) in ⊢ (??%%);
2305>simplify_typeof_eq whd in match (simplify_e func); // qed.
2306
2307lemma simplify_is_not_skip: ∀s.s ≠ Sskip → ∃pf. is_Sskip (simplify_statement s) = inr … pf.
2308*
2309[ 1: * #Habsurd elim (Habsurd (refl ? Sskip))
2310| *: #a try #b try #c try #d try #e
2311     whd in match (simplify_statement ?);
2312     whd in match (is_Sskip ?);
2313     try /2 by refl, ex_intro/
2314] qed.
2315
2316lemma call_cont_simplify : ∀k,k'.
2317  cont_cast k k' →
2318  cont_cast (call_cont k) (call_cont k').
2319#k0 #k0' #K elim K /2/
2320qed.
2321
2322lemma simplify_ls_commute : ∀l. (simplify_statement (seq_of_labeled_statement l)) = (seq_of_labeled_statement (simplify_ls l)).
2323#l @(labeled_statements_ind … l)
2324[ 1: #default_statement //
2325| 2: #sz #i #s #tl #Hind
2326     whd in match (seq_of_labeled_statement ?) in ⊢ (??%?);
2327     whd in match (simplify_ls ?) in ⊢ (???%);
2328     whd in match (seq_of_labeled_statement ?) in ⊢ (???%);
2329     whd in match (simplify_statement ?) in ⊢ (??%?);
2330     >Hind //
2331] qed.
2332
2333lemma select_switch_commute : ∀sz,i,l.
2334 select_switch sz i (simplify_ls l) = simplify_ls (select_switch sz i l).
2335#sz #i #l @(labeled_statements_ind … l)
2336[ 1: #default_statement //
2337| 2: #sz' #i' #s #tl #Hind
2338     whd in match (simplify_ls ?) in ⊢ (??%?);
2339     whd in match (select_switch ???) in ⊢ (??%%);
2340     cases (sz_eq_dec sz sz')
2341     [ 1: #Hsz_eq destruct >intsize_eq_elim_true >intsize_eq_elim_true
2342           cases (eq_bv (bitsize_of_intsize sz') i' i) normalize nodelta
2343           whd in match (simplify_ls ?) in ⊢ (???%);
2344           [ 1: // | 2: @Hind ]
2345     | 2: #Hneq >(intsize_eq_elim_false ? sz sz' ???? Hneq) >(intsize_eq_elim_false ? sz sz' ???? Hneq)
2346          @Hind
2347     ]
2348] qed.
2349
2350lemma elim_IH_aux :
2351  ∀lab. ∀s:statement.∀k,k'. cont_cast k k' →
2352  ∀Hind:(∀k:cont.∀k':cont.
2353          cont_cast k k' →
2354          match find_label lab s k with
2355          [ None ⇒ find_label lab (simplify_statement s) k'=None (statement×cont)
2356          | Some (r:(statement×cont))⇒
2357            let 〈s',ks〉 ≝r in
2358            ∃ks':cont. find_label lab (simplify_statement s) k' = Some (statement×cont) 〈simplify_statement s',ks'〉
2359                        ∧ cont_cast ks ks']).
2360  (find_label lab s k = None ? ∧ find_label lab (simplify_statement s) k' = None ?) ∨
2361  (∃st,kst,kst'. find_label lab s k = Some ? 〈st,kst〉 ∧ find_label lab (simplify_statement s) k' = Some ? 〈simplify_statement st,kst'〉 ∧ cont_cast kst kst').
2362#lab #s #k #k' #Hcont_cast #Hind
2363lapply (Hind k k' Hcont_cast)
2364cases (find_label lab s k)
2365[ 1: normalize nodelta #Heq >Heq /3/
2366| 2: * #st #kst normalize nodelta * #kst' * #Heq #Hcont_cast' >Heq %2
2367     %{st} %{kst} %{kst'} @conj try @conj //
2368] qed.
2369
2370
2371lemma cast_find_label : ∀lab,s,k,k'.
2372  cont_cast k k' →
2373  match find_label lab s k with
2374  [ Some r ⇒
2375    let 〈s',ks〉 ≝ r in
2376    ∃ks'. find_label lab (simplify_statement s) k' = Some ? 〈simplify_statement s', ks'〉
2377    ∧ cont_cast ks ks'
2378  | None ⇒
2379    find_label lab (simplify_statement s) k' = None ?
2380  ].
2381#lab #s @(statement_ind2 ? (λls.
2382    ∀k:cont
2383    .∀k':cont
2384     .cont_cast k k'
2385      →match find_label_ls lab ls k with
2386       [None⇒
2387        find_label_ls lab (simplify_ls ls) k' = None ?
2388       |Some r ⇒
2389        let 〈s',ks〉 ≝r in
2390        ∃ks':cont
2391        .find_label_ls lab (simplify_ls ls) k'
2392         =Some (statement×cont) 〈simplify_statement s',ks'〉
2393         ∧cont_cast ks ks']
2394) … s)
2395[ 1: #k #k' #Hcont_cast
2396     whd in match (find_label ? Sskip ?); normalize nodelta @refl
2397| 2: #e1 #e2 #k #k' #Hcont_cast
2398     whd in match (find_label ? (Sassign e1 e2) ?); normalize nodelta @refl
2399| 3: #e0 #e #args #k #k' #Hcont_cast
2400     whd in match (find_label ? (Scall e0 e args) ?); normalize nodelta @refl
2401| 4: #s1 #s2 #Hind_s1 #Hind_s2 #k #k' #Hcont_cast
2402     whd in match (find_label ? (Ssequence s1 s2) ?);
2403     whd in match (find_label ? (simplify_statement (Ssequence s1 s2)) ?);
2404     elim (elim_IH_aux lab s1 (Kseq s2 k) (Kseq (simplify_statement s2) k') ? Hind_s1)
2405     [ 3: try ( @cc_seq // )
2406     | 2: * #st * #kst * #kst' * * #Hrewrite >Hrewrite #Hrewrite1 >Hrewrite1 #Hcont_cast'
2407          normalize nodelta %{kst'} /2/
2408     | 1: * #Hrewrite >Hrewrite #Hrewrite1 >Hrewrite1 normalize nodelta
2409          elim (elim_IH_aux lab s2 k k' Hcont_cast Hind_s2)
2410          [ 2: * #st * #kst * #kst' * * #Hrewrite2 >Hrewrite2 #Hrewrite3 >Hrewrite3 #Hcont_cast'
2411               normalize nodelta %{kst'} /2/
2412          | 1: * #Hrewrite >Hrewrite #Hrewrite1 >Hrewrite1 normalize nodelta //
2413     ] ]
2414| 5: #e #s1 #s2 #Hind_s1 #Hind_s2 #k #k' #Hcont_cast
2415     whd in match (find_label ???);
2416     whd in match (find_label ? (simplify_statement ?) ?);
2417     elim (elim_IH_aux lab s1 k k' Hcont_cast Hind_s1)
2418     [ 2: * #st * #kst * #kst' * * #Hrewrite >Hrewrite #Hrewrite1 >Hrewrite1 #Hcont_cast'
2419          normalize nodelta %{kst'} /2/
2420     | 1: * #Hrewrite >Hrewrite #Hrewrite1 >Hrewrite1 normalize nodelta
2421          elim (elim_IH_aux lab s2 k k' Hcont_cast Hind_s2)
2422          [ 2: * #st * #kst * #kst' * * #Hrewrite2 >Hrewrite2 #Hrewrite3 >Hrewrite3 #Hcont_cast'
2423               normalize nodelta %{kst'} /2/
2424          | 1: * #Hrewrite >Hrewrite #Hrewrite1 >Hrewrite1 normalize nodelta //
2425     ] ]
2426| 6: #e #s #Hind_s #k #k' #Hcont_cast
2427     whd in match (find_label ???);
2428     whd in match (find_label ? (simplify_statement ?) ?);
2429     elim (elim_IH_aux lab s (Kwhile e s k) (Kwhile (simplify_e e) (simplify_statement s) k') ? Hind_s)
2430     [ 2: * #st * #kst * #kst' * * #Hrewrite >Hrewrite #Hrewrite1 >Hrewrite1 #Hcont_cast'
2431          normalize nodelta %{kst'} /2/
2432     | 1: * #Hrewrite >Hrewrite #Hrewrite1 >Hrewrite1 normalize nodelta //
2433     | 3: @cc_while // ]
2434| 7: #e #s #Hind_s #k #k' #Hcont_cast
2435     whd in match (find_label ???);
2436     whd in match (find_label ? (simplify_statement ?) ?);
2437     elim (elim_IH_aux lab s (Kdowhile e s k) (Kdowhile (simplify_e e) (simplify_statement s) k') ? Hind_s)
2438     [ 2: * #st * #kst * #kst' * * #Hrewrite >Hrewrite #Hrewrite1 >Hrewrite1 #Hcont_cast'
2439          normalize nodelta %{kst'} /2/
2440     | 1: * #Hrewrite >Hrewrite #Hrewrite1 >Hrewrite1 normalize nodelta //
2441     | 3: @cc_dowhile // ]
2442| 8: #s1 #cond #s2 #s3 #Hind_s1 #Hind_s2 #Hind_s3 #k #k' #Hcont_cast
2443     whd in match (find_label ???);
2444     whd in match (find_label ? (simplify_statement ?) ?);
2445     elim (elim_IH_aux lab s1
2446               (Kseq (Sfor Sskip cond s2 s3) k)
2447               (Kseq (Sfor Sskip (simplify_e cond) (simplify_statement s2) (simplify_statement s3)) k')
2448               ? Hind_s1)
2449     [ 2: * #st * #kst * #kst' * * #Hrewrite >Hrewrite #Hrewrite1 >Hrewrite1 #Hcont_cast'
2450          normalize nodelta %{kst'} /2/
2451     | 3: @cc_for1 //
2452     | 1: * #Hrewrite >Hrewrite #Hrewrite1 >Hrewrite1 normalize nodelta
2453          elim (elim_IH_aux lab s3
2454                    (Kfor2 cond s2 s3 k)
2455                    (Kfor2 (simplify_e cond) (simplify_statement s2) (simplify_statement s3) k')
2456                      ? Hind_s3)
2457          [ 2: * #st * #kst * #kst' * * #Hrewrite >Hrewrite #Hrewrite1 >Hrewrite1 #Hcont_cast'
2458                normalize nodelta %{kst'} /2/
2459          | 3: @cc_for2 //
2460          | 1: * #Hrewrite >Hrewrite #Hrewrite1 >Hrewrite1 normalize nodelta
2461               elim (elim_IH_aux lab s2
2462                         (Kfor3 cond s2 s3 k)
2463                         (Kfor3 (simplify_e cond) (simplify_statement s2) (simplify_statement s3) k')
2464                           ? Hind_s2)
2465               [ 2: * #st * #kst * #kst' * * #Hrewrite >Hrewrite #Hrewrite1 >Hrewrite1 #Hcont_cast'
2466                    normalize nodelta %{kst'} /2/
2467               | 3: @cc_for3 //
2468               | 1: * #Hrewrite >Hrewrite #Hrewrite1 >Hrewrite1 normalize nodelta //
2469    ] ] ]
2470| 9,10: #k #k' #Hcont_cast normalize in match (find_label ???); normalize nodelta //
2471| 11: #e #k #k' #Hcont_cast normalize in match (find_label ???); normalize nodelta //
2472| 12: #e #ls #Hind #k #k' #Hcont_cast
2473     whd in match (find_label ???);
2474     whd in match (find_label ? (simplify_statement ?) ?);
2475     (* We can't elim the Hind on a list of labeled statements. We must proceed more manually. *)
2476     lapply (Hind (Kswitch k) (Kswitch k') ?)
2477     [ 1: @cc_switch //
2478     | 2: cases (find_label_ls lab ls (Kswitch k)) normalize nodelta
2479          [ 1: //
2480          | 2: * #st #kst normalize nodelta // ] ]
2481| 13: #lab' #s0 #Hind #k #k' #Hcont_cast
2482     whd in match (find_label ???);
2483     whd in match (find_label ? (simplify_statement ?) ?);
2484     cases (ident_eq lab lab') normalize nodelta
2485     [ 1: #_ %{k'} /2/
2486     | 2: #_ elim (elim_IH_aux lab s0 k k' Hcont_cast Hind)
2487          [ 2: * #st * #kst * #kst' * * #Hrewrite >Hrewrite #Hrewrite1 >Hrewrite1 #Hcont_cast'
2488                normalize nodelta %{kst'} /2/
2489          | 1: * #Heq >Heq #Heq1 >Heq1 normalize nodelta // ]
2490     ]
2491| 14: #l #k #k' #Hcont_cast //
2492| 15: #l #s0 #Hind #k #k' #Hcont_cast
2493     whd in match (find_label ???);
2494     whd in match (find_label ? (simplify_statement ?) ?);
2495     elim (elim_IH_aux lab s0 k k' Hcont_cast Hind)
2496     [ 2: * #st * #kst * #kst' * * #Hrewrite >Hrewrite #Hrewrite1 >Hrewrite1 #Hcont_cast'
2497          normalize nodelta %{kst'} /2/
2498     | 1: * #Heq >Heq #Heq1 >Heq1 normalize nodelta // ]
2499| 16: #s0 #Hind #k #k' #Hcont_cast
2500     whd in match (find_label ???);
2501     whd in match (find_label ? (simplify_statement ?) ?);
2502     elim (elim_IH_aux lab s0 k k' Hcont_cast Hind)
2503     [ 2: * #st * #kst * #kst' * * #Hrewrite >Hrewrite #Hrewrite1 >Hrewrite1 #Hcont_cast'
2504          normalize nodelta %{kst'} /2/
2505     | 1: * #Heq >Heq #Heq1 >Heq1 normalize nodelta // ]
2506| 17: #sz #i #s0 #t #Hind_s0 #Hind_ls #k #k' #Hcont_cast
2507     whd in match (simplify_ls ?);
2508     whd in match (find_label_ls ???);
2509     lapply Hind_ls
2510     @(labeled_statements_ind … t)
2511     [ 1: #default_case #Hind_ls whd in match (seq_of_labeled_statement ?);
2512          elim (elim_IH_aux lab s0
2513                  (Kseq default_case k)
2514                  (Kseq (simplify_statement default_case) k') ? Hind_s0)
2515         [ 2: * #st * #kst * #kst' * * #Hrewrite #Hrewrite1 #Hcont_cast'
2516              >Hrewrite >Hrewrite1
2517              normalize nodelta whd in match (find_label_ls ???);
2518              >Hrewrite >Hrewrite1 normalize nodelta
2519              %{kst'} /2/
2520         | 3: @cc_seq //
2521         | 1: * #Hrewrite #Hrewrite1 >Hrewrite normalize nodelta
2522              lapply (Hind_ls k k' Hcont_cast)
2523              cases (find_label_ls lab (LSdefault default_case) k)
2524              [ 1: normalize nodelta #Heq1
2525                   whd in match (simplify_ls ?);
2526                   whd in match (find_label_ls lab ??);
2527                   whd in match (seq_of_labeled_statement ?);
2528                   whd in match (find_label_ls lab ??);
2529                   >Hrewrite1 normalize nodelta @Heq1
2530              | 2: * #st #kst normalize nodelta #H
2531                   whd in match (find_label_ls lab ??);
2532                   whd in match (simplify_ls ?);
2533                   whd in match (seq_of_labeled_statement ?);
2534                   >Hrewrite1 normalize nodelta @H
2535              ]
2536         ]
2537     | 2: #sz' #i' #s' #tl' #Hind #A
2538
2539          whd in match (seq_of_labeled_statement ?);
2540          elim (elim_IH_aux lab s0
2541                   (Kseq (Ssequence s' (seq_of_labeled_statement tl')) k)
2542                   (Kseq (simplify_statement (Ssequence s' (seq_of_labeled_statement tl'))) k')
2543                   ?
2544                   Hind_s0)
2545          [ 3: @cc_seq //
2546          | 1: * #Heq #Heq2 >Heq >Heq2 normalize nodelta
2547               lapply (A k k' Hcont_cast)
2548               cases (find_label_ls lab (LScase sz' i' s' tl') k) normalize nodelta
2549               [ 1: #H whd in match (find_label_ls ???);
2550                    <simplify_ls_commute
2551                    whd in match (seq_of_labeled_statement ?);
2552                    >Heq2 normalize nodelta
2553                    assumption
2554               | 2: * #st #kst normalize nodelta #H
2555                    whd in match (find_label_ls ???);
2556                    <simplify_ls_commute >Heq2 normalize nodelta @H
2557               ]
2558          | 2: * #st * #kst * #kst' * * #Hrewrite #Hrewrite1 #Hcont_cast'
2559               >Hrewrite normalize nodelta
2560               %{kst'} @conj try //
2561               whd in match (find_label_ls ???);
2562               <simplify_ls_commute >Hrewrite1 //
2563          ]
2564    ]
2565] qed.
2566
2567lemma cast_find_label_fn : ∀lab,f,k,k',s,ks.
2568  cont_cast k k' →
2569  find_label lab (fn_body f) k = Some ? 〈s,ks〉 →
2570  ∃ks'. find_label lab (fn_body (simplify_function f)) k' = Some ? 〈simplify_statement s,ks'〉
2571        ∧ cont_cast ks ks'.
2572#lab * #rettype #args #vars #body #k #k' #s #ks #Hcont_cast #Hfind_lab
2573whd in match (simplify_function ?);
2574lapply (cast_find_label lab body ?? Hcont_cast)
2575>Hfind_lab normalize nodelta //
2576qed.
2577
2578theorem cast_correction : ∀ge, ge'.
2579  related_globals ? simplify_fundef ge ge' →
2580  ∀s1, s1', tr, s2.
2581  state_cast s1 s1' →
2582  exec_step ge s1 = Value … 〈tr,s2〉 →
2583  ∃s2'. exec_step ge' s1' = Value … 〈tr,s2'〉 ∧
2584        state_cast s2 s2'.
2585#ge #ge' #Hrelated #s1 #s1' #tr #s2 #Hs1_sim_s1' #Houtcome
2586inversion Hs1_sim_s1'
2587[ 1: (* regular state *)
2588     #f #stm #k #k' #en #m #Hcont_cast
2589     lapply (related_globals_expr_simulation ge ge' en m Hrelated) #Hsim_related
2590     lapply (related_globals_lvalue_simulation ge ge' en m Hrelated) #Hsim_lvalue_related
2591     cases stm
2592     (* Perform the intros for the statements*)
2593     [ 1: | 2: #lhs #rhs | 3: #ret #func #args | 4: #stm1 #stm2 | 5: #cond #iftrue #iffalse | 6: #cond #body
2594     | 7: #cond #body | 8: #init #cond #step #body | 9,10: | 11: #retval | 12: #cond #switchcases | 13: #lab #body
2595     | 14: #lab | 15: #cost #body ]
2596     [ 1: (* Skip *)
2597          #Heq_s1 #Heq_s1' #_ lapply Houtcome >Heq_s1
2598          whd in match (exec_step ??); whd in match (exec_step ??);
2599          inversion Hcont_cast
2600          [ 1: (* Kstop *)
2601               #Hk #Hk' #_ >fn_return_simplify cases (fn_return f) normalize nodelta
2602               [ 1: >Heq_s1 in Hs1_sim_s1'; >Heq_s1' #Hsim inversion Hsim
2603                    [ 1: #f0 #s #k0 #k0' #e #m0 #Hcont_cast0 #Hstate_eq #Hstate_eq' #_
2604                         #Eq whd in match (ret ??) in Eq; destruct (Eq)
2605                         %{(Returnstate Vundef Kstop (free_list m (blocks_of_env en)))} @conj
2606                         [ 1: // | 2: %3 %1 ]
2607                    | 2: #fd #args #k0 #k0' #m0 #Hcont_cast0 #Habsurd destruct (Habsurd)
2608                    | 3: #res #k0 #k0' #m0 #Hcont_cast #Habsurd destruct (Habsurd)
2609                    | 4: #r #Habsurd destruct (Habsurd) ]
2610               | 3,4,9: #irrelevant #Habsurd destruct
2611               | *: #irrelevant1 #irrelevant2 #Habsurd destruct ]
2612          | 2: (* Kseq stm' k' *)
2613               #stm' #k0 #k0' #Hconst_cast0 #Hind #Hk #Hk' #_ normalize nodelta #Eq
2614               whd in match (ret ??) in Eq; destruct (Eq)
2615               %{(State (simplify_function f) (simplify_statement stm') k0' en m)} @conj
2616               [ 1: // | 2: %1 // ]
2617          | 3: (* Kwhile *)
2618               #cond #body #k0 #k0' #Hconst_cast0 #Hind #Hk #Hk' #_ normalize nodelta #Eq
2619               whd in match (ret ??) in Eq; destruct (Eq)
2620               %{(State (simplify_function f) (Swhile (simplify_e cond) (simplify_statement body)) k0' en m)} @conj
2621               [ 1: // | 2: %1 // ]
2622          | 4: (* Kdowhile *)
2623               #cond #body #k0 #k0' #Hcont_cast0 #Hind #Hk #Hk' #_ normalize nodelta #Eq
2624               elim (Hsim_related cond) #Hsim_cond #Htype_cond_eq cases Hsim_cond
2625               [ 2: * #error #Hfail >Hfail in Eq; #Habsurd normalize in Habsurd; destruct
2626               | 1: cases (exec_expr ge en m cond) in Eq;
2627                    [ 2: #error whd in match (m_bind ?????) in ⊢ (% → ?); #Habsurd destruct
2628                    | 1: * #val #trace whd in match (m_bind ?????) in ⊢ (% → ?); <Htype_cond_eq
2629                         #Eq #Hsim_cond lapply (Hsim_cond 〈val,trace〉 (refl ? (OK ? 〈val,trace〉)))
2630                         #Hrewrite_cond >Hrewrite_cond whd in match (m_bind ?????);
2631                         (* case analysis on the outcome of the conditional *)
2632                         cases (exec_bool_of_val val (typeof cond)) in Eq ⊢ %;
2633                         [ 2: (* evaluation of the conditional fails *)
2634                              #error normalize in ⊢ (% → ?); #Habsurd destruct (Habsurd)
2635                         | 1: * whd in match (bindIO ??????);
2636                                whd in match (bindIO ??????);
2637                                #Eq destruct (Eq)
2638                              [ 1: %{(State (simplify_function f) (Sdowhile (simplify_e cond) (simplify_statement body)) k0' en m)}
2639                                   @conj [ 1: // | 2: %1 // ]
2640                              | 2: %{(State (simplify_function f) Sskip k0' en m)}
2641                                   @conj [ 1: // | 2: %1 // ]
2642                              ]
2643                         ]
2644                    ]
2645               ]
2646           | 5,6,7:
2647                #cond #step #body #k0 #k0' #Hcont_cast0 #Hind #Hk #Hk' #_ normalize nodelta #Eq
2648                whd in match (ret ??) in Eq ⊢ %; destruct (Eq)
2649                [ 1: %{(State (simplify_function f)
2650                              (Sfor Sskip (simplify_e cond) (simplify_statement step) (simplify_statement body))
2651                               k0' en m)} @conj
2652                     [ 1: // | 2: %1 // ]
2653                | 2: %{(State (simplify_function f)
2654                              (simplify_statement step)
2655                              (Kfor3 (simplify_e cond) (simplify_statement step) (simplify_statement body) k0')
2656                              en m)} @conj
2657                     [ 1: // | 2: %1 @cc_for3 // ]
2658                | 3: %{(State (simplify_function f)
2659                              (Sfor Sskip (simplify_e cond) (simplify_statement step)
2660                              (simplify_statement body))
2661                              k0' en m)} @conj
2662                     [ 1: // | 2: %1 // ]
2663                ]
2664           | 8: #k0 #k0' #Hcont_cast0 #Hind #Hk #Hk' #_ normalize nodelta #Eq
2665                whd in match (ret ??) in Eq ⊢ %; destruct (Eq)
2666                %{(State (simplify_function f) Sskip k0' en m)} @conj
2667                [ 1: // | 2: %1 // ]
2668           | 9: (* Call *)
2669                #r #f0 #en0 #k0 #k0' #Hcont_cast #Hind #Hk #Hk' #_ #Eq
2670                >fn_return_simplify cases (fn_return f) in Eq; normalize nodelta
2671               [ 1: #Eq whd in match (ret ??) in Eq ⊢ %; destruct (Eq)
2672                    %{(Returnstate Vundef (Kcall r (simplify_function f0) en0 k0')
2673                                  (free_list m (blocks_of_env en)))} @conj
2674                    [ 1: // | 2: %3 @cc_call // ]
2675               | 3,4,9: #irrelevant #Habsurd destruct (Habsurd)
2676               | *: #irrelevant1 #irrelevant2 #Habsurd destruct (Habsurd) ]
2677           ]
2678     | 2: (* Assign *)
2679          #Heq_s1 #Heq_s1' #_ lapply Houtcome >Heq_s1
2680          whd in match (simplify_statement ?); #Heq
2681          whd in match (exec_step ??) in Heq ⊢ %;
2682          (* Begin by making the simplify_e disappear using Hsim_related *)
2683          elim (Hsim_lvalue_related lhs) *
2684          [ 2: * #error #Hfail >Hfail in Heq; #Habsurd normalize in Habsurd; destruct (Habsurd)
2685          | 1: cases (exec_lvalue ge en m lhs) in Heq;
2686               [ 2: #error #Habsurd normalize in Habsurd; destruct (Habsurd)
2687               | 1: * * #block #offset #trace
2688                    whd in match (bindIO ??????); #Heq #Hsim #Htype_eq_lhs
2689                    lapply (Hsim 〈block, offset, trace〉 (refl ? (OK ? 〈block, offset, trace〉)))
2690                    #Hrewrite >Hrewrite -Hrewrite whd in match (bindIO ??????);
2691                    (* After [lhs], treat [rhs] *)
2692                    elim (Hsim_related rhs) *
2693                    [ 2: * #error #Hfail >Hfail in Heq; #Habsurd normalize in Habsurd; destruct (Habsurd)
2694                    | 1: cases (exec_expr ge en m rhs) in Heq;
2695                         [ 2: #error #Habsurd normalize in Habsurd; destruct (Habsurd)
2696                         | 1: * #val #trace
2697                              whd in match (bindIO ??????); #Heq #Hsim #Htype_eq_rhs
2698                              lapply (Hsim 〈val, trace〉 (refl ? (OK ? 〈val, trace〉)))
2699                              #Hrewrite >Hrewrite -Hrewrite whd in match (bindIO ??????);
2700                              <Htype_eq_lhs <Htype_eq_rhs
2701                              cases (opt_to_io ?????) in Heq;
2702                              [ 1: #o #resumption whd in match (bindIO ??????); #Habsurd destruct (Habsurd)
2703                              | 3: #error whd in match (bindIO ??????); #Habsurd destruct (Habsurd)
2704                              | 2: #mem whd in match (bindIO ??????); #Heq destruct (Heq)
2705                                   %{(State (simplify_function f) Sskip k' en mem)} @conj
2706                                   [ 1: // | 2: %1 // ]
2707                              ]
2708                         ]
2709                    ]
2710               ]
2711         ]
2712    | 3: (* Call *)
2713         #Heq_s1 #Heq_s1' #_  lapply Houtcome >Heq_s1
2714         whd in match (simplify_statement ?) in Heq ⊢ %; #Heq
2715         whd in match (exec_step ??) in Heq ⊢ %;
2716         elim (Hsim_related func) in Heq; *
2717         [ 2: * #error #Hfail >Hfail #Htype_eq #Habsurd normalize in Habsurd; destruct (Habsurd)
2718         | 1: cases (exec_expr ??? func)
2719              [ 2: #error #_ #_ #Habsurd normalize in Habsurd; destruct (Habsurd)
2720              | 1: #a #Hsim lapply (Hsim a (refl ? (OK ? a))) #Heq >Heq #Htype_eq >Htype_eq
2721                   whd in match (bindIO ??????) in ⊢ (% → %);
2722                   elim (related_globals_exprlist_simulation ge ge' en m Hrelated args)
2723                   [ 2: * #error #Hfail >Hfail #Habsurd normalize in Habsurd; destruct (Habsurd)
2724                   | 1: cases (exec_exprlist ge en m args)
2725                        [ 2: #error #_ #Habsurd normalize in Habsurd; destruct (Habsurd)
2726                        | 1: #l -Hsim #Hsim lapply (Hsim l (refl ? (OK ? l))) #Heq >Heq
2727                             whd in match (bindIO ??????) in ⊢ (% → %);
2728                             elim Hrelated #_ #Hfunct #_ lapply (Hfunct (\fst a))
2729                             cases (find_funct clight_fundef ge (\fst a));
2730                             [ 1: #_ #Habsurd normalize in Habsurd; destruct (Habsurd)
2731                             | 2: #clfd -Hsim #Hsim lapply (Hsim clfd (refl ? (Some ? clfd))) #Heq >Heq
2732                                  whd in match (bindIO ??????) in ⊢ (% → %);
2733                                  >simplify_type_of_fundef_eq >(simplify_fun_typeof_eq ge en m)
2734                                  cases (assert_type_eq (type_of_fundef clfd) (fun_typeof func))
2735                                  [ 2: #error #Habsurd normalize in Habsurd; destruct (Habsurd)
2736                                  | 1: #Htype_eq cases ret
2737                                       [ 1: whd in match (bindIO ??????) in ⊢ (% → %);
2738                                            #Eq destruct (Eq)
2739                                            %{(Callstate (simplify_fundef clfd) (\fst  l)
2740                                                         (Kcall (None (block×offset×type)) (simplify_function f) en k') m)}
2741                                            @conj
2742                                            [ 1: // | 2: %2 @cc_call // ]
2743                                       | 2: #fptr whd in match (bindIO ??????) in ⊢ (% → %);
2744                                            elim (Hsim_lvalue_related fptr) *
2745                                            [ 2: * #error #Hfail >Hfail #_
2746                                                 #Habsurd normalize in Habsurd; destruct (Habsurd)
2747                                            | 1: cases (exec_lvalue ge en m fptr)
2748                                                 [ 2: #error #_ #_ #Habsurd normalize in Habsurd; destruct (Habsurd)
2749                                                 | 1: #a #Hsim #Htype_eq_fptr >(Hsim a (refl ? (OK ? a)))
2750                                                      whd in match (bindIO ??????) in ⊢ (% → %);
2751                                                      #Heq destruct (Heq)
2752                                                      %{(Callstate (simplify_fundef clfd) (\fst  l)
2753                                                                   (Kcall (Some (block×offset×type) 〈\fst  a,typeof (simplify_e fptr)〉)
2754                                                                   (simplify_function f) en k') m)}
2755                                                      @conj [ 1: // | 2: >(simplify_typeof_eq ge en m) %2 @cc_call // ]
2756        ] ] ] ] ] ] ] ] ]
2757    | 4: #Heq_s1 #Heq_s1' #_ >Heq_s1 in Houtcome;
2758         whd in match (simplify_statement ?) in Heq ⊢ %; #Heq
2759         whd in match (exec_step ??) in Heq ⊢ %;
2760         destruct (Heq)
2761         %{(State (simplify_function f) (simplify_statement stm1) (Kseq (simplify_statement stm2) k') en m)}
2762         @conj
2763         [ 1: // | 2: %1 @cc_seq // ]
2764    | 5: #Heq_s1 #Heq_s1' #_ >Heq_s1 in Houtcome;
2765         whd in match (simplify_statement ?) in Heq ⊢ %; #Heq
2766         whd in match (exec_step ??) in Heq ⊢ %;
2767         elim (Hsim_related cond) in Heq; *
2768         [ 2: * #error #Hfail >Hfail #_ #Habsurd normalize in Habsurd; destruct (Habsurd)
2769         | 1: cases (exec_expr ge en m cond)
2770              [ 2: #error #_ #_ #Habsurd normalize in Habsurd; destruct (Habsurd)
2771              | 1: * #condval #condtrace #Hsim lapply (Hsim 〈condval, condtrace〉 (refl ? (OK ? 〈condval, condtrace〉))) #Heq >Heq
2772                   #Htype_eq_cond
2773                   whd in match (bindIO ??????) in ⊢ (% → %);
2774                   >(simplify_typeof_eq ge en m)
2775                   cases (exec_bool_of_val condval (typeof cond))
2776                   [ 2: #error #Habsurd normalize in Habsurd; destruct (Habsurd)
2777                   | 1: * whd in match (bindIO ??????) in ⊢ (% → %); #Heq normalize nodelta in Heq ⊢ %;
2778                        [ 1: destruct skip (condtrace)
2779                             %{(State (simplify_function f) (simplify_statement iftrue) k' en m)} @conj
2780                             [ 1: // | 2: <e0 %1 // ]
2781                        | 2: destruct skip (condtrace)
2782                             %{(State (simplify_function f) (simplify_statement iffalse) k' en m)} @conj
2783                             [ 1: // | 2: <e0 %1 // ]
2784                        ] ] ] ]
2785    | 6: #Heq_s1 #Heq_s1' #_ >Heq_s1 in Houtcome;
2786         whd in match (simplify_statement ?) in Heq ⊢ %; #Heq
2787         whd in match (exec_step ??) in Heq ⊢ %;
2788         elim (Hsim_related cond) in Heq; *
2789         [ 2: * #error #Hfail >Hfail #_ #Habsurd normalize in Habsurd; destruct (Habsurd)
2790         | 1: cases (exec_expr ge en m cond)
2791              [ 2: #error #_ #_ #Habsurd normalize in Habsurd; destruct (Habsurd)
2792              | 1: * #condval #condtrace #Hsim lapply (Hsim 〈condval, condtrace〉 (refl ? (OK ? 〈condval, condtrace〉))) #Heq >Heq
2793                   #Htype_eq_cond
2794                   whd in match (bindIO ??????) in ⊢ (% → %);
2795                   >(simplify_typeof_eq ge en m)
2796                   cases (exec_bool_of_val condval (typeof cond))
2797                   [ 2: #error #Habsurd normalize in Habsurd; destruct (Habsurd)
2798                   | 1: * whd in match (bindIO ??????) in ⊢ (% → %); #Heq normalize nodelta in Heq ⊢ %;
2799                        [ 1: destruct skip (condtrace)
2800                             %{(State (simplify_function f) (simplify_statement body) (Kwhile (simplify_e cond) (simplify_statement body) k') en m)}
2801                             @conj
2802                             [ 1: // | 2: <e0 %1 @cc_while // ]
2803                        | 2: destruct skip (condtrace)
2804                             %{(State (simplify_function f) Sskip k' en m)} @conj
2805                             [ 1: // | 2: <e0 %1 // ]
2806                        ] ] ] ]
2807    | 7: #Heq_s1 #Heq_s1' #_ >Heq_s1 in Houtcome;
2808         whd in match (simplify_statement ?) in Heq ⊢ %; #Heq
2809         whd in match (exec_step ??) in Heq ⊢ %;
2810         destruct (Heq)
2811         %{(State (simplify_function f) (simplify_statement body)
2812                  (Kdowhile (simplify_e cond) (simplify_statement body) k') en m)} @conj
2813         [ 1: // | 2: %1 @cc_dowhile // ]
2814    | 8: #Heq_s1 #Heq_s1' #_ >Heq_s1 in Houtcome;
2815         whd in match (simplify_statement ?) in Heq ⊢ %; #Heq
2816         whd in match (exec_step ??) in Heq ⊢ %;
2817         cases (is_Sskip init) in Heq;
2818         [ 2: #Hinit_neq_Sskip elim (simplify_is_not_skip init Hinit_neq_Sskip) #pf #Hrewrite >Hrewrite
2819              normalize nodelta
2820              whd in match (ret ??) in ⊢ (% → %);
2821              #Eq destruct (Eq)
2822              %{(State (simplify_function f) (simplify_statement init)
2823                       (Kseq (Sfor Sskip (simplify_e cond) (simplify_statement step) (simplify_statement body)) k') en m)} @conj
2824              [ 1: // | 2: %1 @cc_for1 // ]
2825         | 1: #Hinit_eq_Sskip >Hinit_eq_Sskip
2826              whd in match (simplify_statement ?);
2827              whd in match (is_Sskip ?);
2828              normalize nodelta
2829              elim (Hsim_related cond) *
2830              [ 2: * #error #Hfail #_ >Hfail #Habsurd normalize in Habsurd; destruct (Habsurd)
2831              | 1: cases (exec_expr ge en m cond)
2832                   [ 2: #error #_ #_ #Habsurd normalize in Habsurd; destruct (Habsurd)
2833                   | 1: #a #Hsim lapply (Hsim a (refl ? (OK ? a))) #Hrewrite #Htype_eq_cond >Hrewrite
2834                        whd in match (m_bind ?????); whd in match (m_bind ?????);
2835                        <Htype_eq_cond
2836                        cases (exec_bool_of_val ? (typeof cond))
2837                        [ 2: #error #Habsurd normalize in Habsurd; destruct (Habsurd)
2838                        | 1: * whd in match (bindIO ??????); whd in match (bindIO ??????);
2839                             normalize nodelta #Heq destruct (Heq)
2840                             [ 1: %{(State (simplify_function f) (simplify_statement body)
2841                                           (Kfor2 (simplify_e cond) (simplify_statement step) (simplify_statement body) k') en m)}
2842                                   @conj [ 1: // | 2: %1 @cc_for2 // ]
2843                             | 2: %{(State (simplify_function f) Sskip k' en m)} @conj
2844                                  [ 1: // | 2: %1 // ]
2845         ] ] ] ] ]
2846    | 9: #Heq_s1 #Heq_s1' #_ >Heq_s1 in Houtcome;
2847         whd in match (simplify_statement ?) in Heq ⊢ %; #Heq
2848         whd in match (exec_step ??) in Heq ⊢ %;
2849         inversion Hcont_cast in Heq; normalize nodelta
2850         [ 1: #Hk #Hk' #_
2851         | 2: #stm' #k0 #k0' #Hconst_cast0 #Hind #Hk #Hk' #_
2852         | 3: #cond #body #k0 #k0' #Hconst_cast0 #Hind #Hk #Hk' #_
2853         | 4: #cond #body #k0 #k0' #Hcont_cast0 #Hind #Hk #Hk' #_
2854         | 5,6,7: #cond #step #body #k0 #k0' #Hcont_cast0 #Hind #Hk #Hk' #_
2855         | 8: #k0 #k0' #Hcont_cast0 #Hind #Hk #Hk' #_
2856         | 9: #r #f0 #en0 #k0 #k0' #Hcont_cast #Hind #Hk #Hk' #_ ]
2857         #H whd in match (ret ??) in H ⊢ %;
2858         destruct (H)
2859         [ 1,4: %{(State (simplify_function f) Sbreak k0' en m)} @conj [ 1,3: // | 2,4: %1 // ]
2860         | 2,3,5,6: %{(State (simplify_function f) Sskip k0' en m)} @conj try // %1 // ]
2861    | 10: #Heq_s1 #Heq_s1' #_ >Heq_s1 in Houtcome;
2862         whd in match (simplify_statement ?) in Heq ⊢ %; #Heq
2863         whd in match (exec_step ??) in Heq ⊢ %;
2864         inversion Hcont_cast in Heq; normalize nodelta
2865         [ 1: #Hk #Hk' #_
2866         | 2: #stm' #k0 #k0' #Hconst_cast0 #Hind #Hk #Hk' #_
2867         | 3: #cond #body #k0 #k0' #Hconst_cast0 #Hind #Hk #Hk' #_
2868         | 4: #cond #body #k0 #k0' #Hcont_cast0 #Hind #Hk #Hk' #_
2869         | 5,6,7: #cond #step #body #k0 #k0' #Hcont_cast0 #Hind #Hk #Hk' #_
2870         | 8: #k0 #k0' #Hcont_cast0 #Hind #Hk #Hk' #_
2871         | 9: #r #f0 #en0 #k0 #k0' #Hcont_cast #Hind #Hk #Hk' #_ ]
2872         #H whd in match (ret ??) in H ⊢ %;
2873         destruct (H)
2874         [ 1,4,6: %{(State (simplify_function f) Scontinue k0' en m)} @conj try // %1 //
2875         | 2: %{(State (simplify_function f) (Swhile (simplify_e cond) (simplify_statement body)) k0' en m)}
2876              @conj try // %1 //
2877         | 3: elim (Hsim_related cond) #Hsim_cond #Htype_cond_eq elim Hsim_cond in H;
2878              [ 2: * #error #Hfail >Hfail #Habsurd normalize in Habsurd; destruct (Habsurd)
2879              | 1: cases (exec_expr ??? cond)
2880                   [ 2: #error #_ #Habsurd normalize in Habsurd; destruct (Habsurd)
2881                   | 1: #a #Hsim lapply (Hsim a (refl ? (OK ? a))) #Hrewrite >Hrewrite
2882                        whd in match (m_bind ?????) in ⊢ (% → %);
2883                        <Htype_cond_eq
2884                        cases (exec_bool_of_val ? (typeof cond))
2885                        [ 2: #error #Habsurd normalize in Habsurd; destruct (Habsurd)
2886                        | 1: * whd in match (bindIO ??????); whd in match (bindIO ??????);
2887                             normalize nodelta #Heq destruct (Heq)
2888                             [ 1: %{(State (simplify_function f) (Sdowhile (simplify_e cond) (simplify_statement body)) k0' en m)}
2889                                  @conj [ 1: // | 2: %1 // ]
2890                             | 2: %{(State (simplify_function f) Sskip k0' en m)}
2891                                  @conj [ 1: // | 2: %1 // ]
2892             ] ] ] ]
2893         | 5: %{(State (simplify_function f) (simplify_statement step)
2894                       (Kfor3 (simplify_e cond) (simplify_statement step) (simplify_statement body) k0') en m)} @conj
2895              [ 1: // | 2: %1 @cc_for3 // ]
2896         ]
2897    | 11: #Heq_s1 #Heq_s1' #_ >Heq_s1 in Houtcome;
2898          whd in match (simplify_statement ?) in Heq ⊢ %; #Heq
2899          whd in match (exec_step ??) in Heq ⊢ %;
2900          cases retval in Heq; normalize nodelta
2901          [ 1: >fn_return_simplify cases (fn_return f) normalize nodelta
2902               whd in match (ret ??) in ⊢ (% → %);
2903               [ 2: #sz #sg | 3: #fl | 4: #ty' | 5: #ty #n | 6: #tl #ty'
2904               | 7: #id #fl | 8: #id #fl | 9: #id ]
2905               #H destruct (H)
2906               %{(Returnstate Vundef (call_cont k') (free_list m (blocks_of_env en)))}
2907               @conj [ 1: // | 2: %3 @call_cont_simplify // ]
2908          | 2: #e >fn_return_simplify cases (type_eq_dec (fn_return f) Tvoid) normalize nodelta
2909               [ 1: #_ #Habsurd destruct (Habsurd)
2910               | 2: #_ elim (Hsim_related e) *
2911                    [ 2: * #error #Hfail >Hfail #_ #Habsurd normalize in Habsurd; destruct (Habsurd)
2912                    | 1: cases (exec_expr ??? e)
2913                         [ 2: #error #_ #_ #Habsurd normalize in Habsurd; destruct (Habsurd)
2914                         | 1: #a #Hsim #Htype_eq_e lapply (Hsim a (refl ? (OK ? a)))
2915                              #Hrewrite >Hrewrite
2916                              whd in match (m_bind ?????); whd in match (m_bind ?????);
2917                              #Heq destruct (Heq)
2918                              %{(Returnstate (\fst  a) (call_cont k') (free_list m (blocks_of_env en)))}
2919                              @conj [ 1: // | 2: %3 @call_cont_simplify // ]
2920         ] ] ] ]
2921    | 12: #Heq_s1 #Heq_s1' #_ >Heq_s1 in Houtcome;
2922          whd in match (simplify_statement ?) in Heq ⊢ %; #Heq
2923          whd in match (exec_step ??) in Heq ⊢ %;
2924          elim (Hsim_related cond) in Heq; *
2925          [ 2: * #error #Hfail >Hfail #_ #Habsurd normalize in Habsurd; destruct (Habsurd)
2926          | 1: cases (exec_expr ??? cond)
2927               [ 2: #error #_ #_ #Habsurd normalize in Habsurd; destruct (Habsurd)
2928               | 1: #a #Hsim #Htype_eq_cond lapply (Hsim a (refl ? (OK ? a)))
2929                    #Hrewrite >Hrewrite
2930                    whd in match (bindIO ??????); whd in match (bindIO ??????);
2931                    cases (\fst a) normalize nodelta
2932                    [ 1,3,4,5: #a destruct (a) #b destruct (b)
2933                    | 2: #sz #i whd in match (ret ??) in ⊢ (% → %); #Heq destruct (Heq)
2934                         %{(State (simplify_function f)
2935                                  (seq_of_labeled_statement (select_switch sz i (simplify_ls switchcases)))
2936                                  (Kswitch k') en m)} @conj
2937                         [ 1: //
2938                         | 2: @(labeled_statements_ind … switchcases)
2939                              [ 1: #default_s
2940                                   whd in match (simplify_ls ?);
2941                                   whd in match (select_switch sz i ?) in ⊢ (?%%);
2942                                   whd in match (seq_of_labeled_statement ?) in ⊢ (?%%);
2943                                   %1 @cc_switch //
2944                              | 2: #sz' #i' #top_case #tail #Hind
2945                                   cut ((seq_of_labeled_statement (select_switch sz i (simplify_ls (LScase sz' i' top_case tail))))
2946                                         = (simplify_statement (seq_of_labeled_statement (select_switch sz i (LScase sz' i' top_case tail)))))
2947                                   [ 1: >select_switch_commute >simplify_ls_commute @refl
2948                                   | 2: #Hrewrite >Hrewrite
2949                                        %1 @cc_switch //
2950         ] ] ] ] ] ]
2951    | 13: #Heq_s1 #Heq_s1' #_ >Heq_s1 in Houtcome;
2952          whd in match (simplify_statement ?) in Heq ⊢ %; #Heq
2953          whd in match (exec_step ??) in Heq ⊢ %;
2954          destruct (Heq)
2955          %{(State (simplify_function f) (simplify_statement body) k' en m)}
2956          @conj %1 //
2957   | 14: #Heq_s1 #Heq_s1' #_ >Heq_s1 in Houtcome;
2958          whd in match (simplify_statement ?) in Heq ⊢ %; #Heq
2959          whd in match (exec_step ??) in Heq ⊢ %;
2960          lapply (cast_find_label_fn lab f (call_cont k) (call_cont k'))
2961          cases (find_label lab (fn_body f) (call_cont k)) in Heq;
2962          normalize nodelta
2963          [ 1: #Habsurd destruct (Habsurd)
2964          | 2: * #st #kst normalize nodelta
2965               #Heq whd in match (ret ??) in Heq;
2966               #H lapply (H st kst (call_cont_simplify ???) (refl ? (Some ? 〈st,kst〉))) try //
2967               * #kst' * #Heq2 #Hcont_cast' >Heq2 normalize nodelta
2968               destruct (Heq)
2969               %{(State (simplify_function f) (simplify_statement st) kst' en m)} @conj
2970               [ 1: // | 2: %1 // ]
2971          ]
2972   | 15: #Heq_s1 #Heq_s1' #_ >Heq_s1 in Houtcome;
2973          whd in match (simplify_statement ?) in Heq ⊢ %; #Heq
2974          whd in match (exec_step ??) in Heq ⊢ %;
2975          destruct (Heq)
2976          %{(State (simplify_function f) (simplify_statement body) k' en m)}
2977          @conj
2978          [ 1: // | 2: %1 // ]
2979   ]
2980| 2: (* Call state *)
2981     #fd #args #k #k' #m #Hcont_cast #Heq_s1 #Heq_s1' #_ >Heq_s1 in Houtcome;
2982     whd in match (exec_step ??) in ⊢ (% → %);
2983     elim fd in Heq_s1'; normalize nodelta
2984     [ 1: * #rettype #args #vars #body #Heq_s1'
2985          whd in match (simplify_function ?);
2986          cases (exec_alloc_variables empty_env ??)
2987          #local_env #new_mem normalize nodelta
2988          cases (exec_bind_parameters ????)
2989          [ 2: #error #Habsurd normalize in Habsurd; destruct (Habsurd)
2990          | 1: #new_mem_init
2991               whd in match (m_bind ?????); whd in match (m_bind ?????);
2992                #Heq destruct (Heq)
2993                %{(State (mk_function rettype args vars (simplify_statement body))
2994                         (simplify_statement body) k' local_env new_mem_init)} @conj
2995                [ 1: // | 2: %1 // ]
2996          ]
2997     | 2: #id #argtypes #rettype #Heq_s1'
2998          cases (check_eventval_list args ?)
2999          [ 2: #error #Habsurd normalize in Habsurd; destruct (Habsurd)
3000          | 1: #l whd in match (m_bind ?????); whd in match (m_bind ?????);
3001          #Habsurd destruct (Habsurd) ]
3002     ]
3003| 3: (* Return state *)
3004     #res #k #k' #m #Hcont_cast #Heq_s1 #Heq_s1' #_ >Heq_s1 in Houtcome;
3005     whd in match (exec_step ??) in ⊢ (% → %);
3006     inversion Hcont_cast
3007     [ 1: #Hk #Hk' #_
3008     | 2: #stm' #k0 #k0' #Hconst_cast0 #Hind #Hk #Hk' #_
3009     | 3: #cond #body #k0 #k0' #Hconst_cast0 #Hind #Hk #Hk' #_
3010     | 4: #cond #body #k0 #k0' #Hcont_cast0 #Hind #Hk #Hk' #_
3011     | 5,6,7: #cond #step #body #k0 #k0' #Hcont_cast0 #Hind #Hk #Hk' #_
3012     | 8: #k0 #k0' #Hcont_cast0 #Hind #Hk #Hk' #_
3013     | 9: #r #f0 #en0 #k0 #k0' #Hcont_cast #Hind #Hk #Hk' #_ ]
3014     normalize nodelta
3015     [ 1: cases res normalize nodelta
3016          [ 2: * normalize nodelta #i
3017               [ 3: #Heq whd in match (ret ??) in Heq; destruct (Heq)
3018                    %{(Finalstate i)} @conj [ 1: // | 2: // ]
3019               | * : #Habsurd destruct (Habsurd) ]
3020          | *: #a try #b destruct ]
3021     | 9: elim r normalize nodelta
3022          [ 2: * * #block #offset #typ normalize nodelta
3023               cases (opt_to_io io_out io_in mem ? (store_value_of_type' ????))
3024               [ 2: #mem whd in match (m_bind ?????); whd in match (m_bind ?????);
3025                    #Heq destruct (Heq)
3026                    %{(State (simplify_function f0) Sskip k0' en0 mem)} @conj
3027                    [ 1: // | 2: %1 // ]
3028               | 1: #output #resumption
3029                    whd in match (m_bind ?????); #Habsurd destruct (Habsurd)
3030               | 3: #eror #Habsurd normalize in Habsurd; destruct (Habsurd) ]
3031          | 1: #Heq whd in match (ret ??) in Heq; destruct (Heq)
3032               %{(State (simplify_function f0) Sskip k0' en0 m)} @conj
3033               [ 1: // | 2: %1 // ]
3034          ]
3035     | *: #Habsurd destruct (Habsurd) ]
3036| 4: (* Final state *)
3037     #r #Heq_s1 #Heq_s1' #_ >Heq_s1 in Houtcome;
3038     whd in match (exec_step ??) in ⊢ (% → %);
3039     #Habsurd destruct (Habsurd)
3040] qed.
Note: See TracBrowser for help on using the repository browser.