source: src/Clight/toCminorCorrectness.ma @ 3178

Last change on this file since 3178 was 3178, checked in by campbell, 6 years ago

Some progress on Callstate steps in Clight to Cminor.
Note that some bogus alignment has been removed in Csyntax.

File size: 152.3 KB
Line 
1(*
2include "Clight/toCminor.ma".
3include "Clight/CexecInd.ma".
4include "common/Globalenvs.ma".
5include "Clight/memoryInjections.ma".
6include "Clight/Clight_abstract.ma".
7include "Cminor/Cminor_abstract.ma".
8*)
9include "common/Measurable.ma".
10
11(* Expr simulation. Contains important definitions for statements, too.  *)
12include "Clight/toCminorCorrectnessExpr.ma".
13
14(* When we characterise the local Clight variables, those that are stack
15   allocated are given disjoint regions of the stack. *)
16lemma characterise_vars_disjoint : ∀globals,f,vartypes,stacksize,id,n,ty.
17  characterise_vars globals f = 〈vartypes, stacksize〉 →
18  lookup ?? vartypes id = Some ? 〈Stack n,ty〉 →
19  ∀id',n',ty'. id ≠ id' →
20  lookup ?? vartypes id' = Some ? 〈Stack n',ty'〉 →
21  n' + sizeof ty' ≤ n ∨ n + sizeof ty ≤ n'.
22#globals * #ret #args #vars #body #vartypes #stacksize #id #n #ty
23whd in ⊢ (??%? → ?);
24generalize in match vartypes; -vartypes
25generalize in match stacksize; -stacksize
26elim (args@vars)
27[ #stacksize #vartypes #CHAR #L @⊥ whd in CHAR:(??%?); destruct
28  elim globals in L;
29  [ normalize #L destruct
30  | * * #id' #r #ty' #tl #IH
31    whd in match (foldr ?????);
32    #L cases (lookup_add_cases ??????? L)
33    [ * #E1 #E2 destruct
34    | @IH
35    ]
36  ]
37| * #id1 #ty1 #tl #IH #stacksize #vartypes
38  whd in match (foldr ?????);
39  (* Avoid writing out the definition again *)
40  letin ih ≝ (foldr ? (Prod ??) ?? tl) in IH ⊢ %;
41  lapply (refl ? ih) whd in match ih; -ih
42  cases (foldr ? (Prod ??) ?? tl) in ⊢ (???% → %);
43  #vartypes' #stack' #FOLD #IH
44  whd in ⊢ (??(match % with [_⇒?])? → ?);
45  cases (orb ??)
46  #CHAR whd in CHAR:(??%?); destruct
47  #L cases (lookup_add_cases ??????? L)
48  [ 1,3: * #E1 #E2 destruct
49    #id' #n' #ty' #NE >lookup_add_miss /2/
50    #L' %1 -L -IH
51    generalize in match vartypes' in FOLD L' ⊢ %; -vartypes'
52    generalize in match stack'; -stack'
53    elim tl
54    [ #stack' #vartypes2 whd in ⊢ (??%? → ?); #F destruct #L' @⊥
55      elim globals in L';
56      [ normalize #E destruct
57      | * * #id2 #r2 #ty2 #tl2 #IH whd in match (foldr ?????);
58        #L cases (lookup_add_cases ??????? L)
59        [ * #E1 #E2 destruct
60        | @IH
61        ]
62      ]
63    | * #id2 #ty2 #tl2 #IH #stack' #vartypes'
64      whd in ⊢ (??%? → ?); cases (foldr ? (Prod ??) ???) in IH ⊢ %;
65      #vartypes2 #stack2 #IH
66      whd in ⊢ (??%? → ?);
67      cases (orb ??)
68      [ #E whd in E:(??%?); destruct #L cases (lookup_add_cases ??????? L)
69        [ * #E1 #E2 destruct //
70        | #L'' lapply (IH ?? (refl ??) L'') /2/
71        ]
72      | #E whd in E:(??%?); destruct #L cases (lookup_add_cases ??????? L)
73        [ * #E1 #E2 destruct
74        | #L'' lapply (IH ?? (refl ??) L'') /2/
75        ]
76      ]
77    ]
78  | -L #L #id' #n' #ty' #NE #L'
79    cases (lookup_add_cases ??????? L')
80    [ * #E1 #E2 destruct
81      %2 -IH -L'
82      generalize in match vartypes' in FOLD L; -vartypes'
83      generalize in match stack'; -stack'
84      elim tl
85      [ #stack' #vartypes' whd in ⊢ (??%? → ?); #F destruct #L @⊥
86        elim globals in L;
87        [ normalize #E destruct
88        | * * #id1 #r1 #ty1 #tl1 #IH whd in match (foldr ?????);
89          #L cases (lookup_add_cases ??????? L)
90          [ * #E1 #E2 destruct
91          | @IH
92          ]
93        ]
94      | * #id1 #ty1 #tl1 #IH #stack' #vartypes'
95        whd in ⊢ (??%? → ?); cases (foldr ? (Prod ??) ???) in IH ⊢ %;
96        #vartypes2 #stack2 #IH
97        whd in ⊢ (??%? → ?);
98        cases (orb ??)
99        #E whd in E:(??%?); destruct
100        #L cases (lookup_add_cases ??????? L)
101        [ 1,3: * #E1 #E2 destruct //
102        | 2,4: #L' lapply (IH ?? (refl ??) L') /2/
103        ]
104      ]
105    | @(IH … (refl ??) L … NE)
106    ]
107  | -L #L #id' #n' #ty' #NE #L'
108    cases (lookup_add_cases ??????? L')
109    [ * #E1 #E2 destruct
110    | @(IH … (refl ??) L … NE)
111    ]
112  ]
113] qed.
114
115(* And everything is in the stack frame. *)
116
117lemma characterise_vars_in_range : ∀globals,f,vartypes,stacksize,id,n,ty.
118  characterise_vars globals f = 〈vartypes, stacksize〉 →
119  lookup ?? vartypes id = Some ? 〈Stack n,ty〉 →
120  n + sizeof ty ≤ stacksize.
121#globals * #ret #args #vars #body whd in match (characterise_vars ??);
122elim (args@vars)
123[ #vartypes #stacksize #id #n #ty #FOLD #L @⊥
124  whd in FOLD:(??%?); destruct elim globals in L;
125  [ #E normalize in E; destruct
126  | * * #id' #r' #ty' #tl' #IH
127    whd in match (foldr ?????); #L cases (lookup_add_cases ??????? L)
128    [ * #E1 #E2 destruct
129    | @IH
130    ]
131  ]
132| * #id' #ty' #tl #IH #vartypes #stacksize #id #n #ty
133  whd in match (foldr ?????); cases (foldr ? (Prod ??) ???) in IH ⊢ %;
134  #vartypes' #stackspace' #IH
135  whd in ⊢ (??(match % with [_⇒?])? → ?);
136  cases (orb ??) whd in ⊢ (??%? → ?);
137  #E destruct #L cases (lookup_add_cases ??????? L)
138  [ 1,3: * #E1 #E2 destruct //
139  | 2,4: #L' lapply (IH … (refl ??) L') /2/
140  ]
141] qed.
142
143
144
145(* Put knowledge that Globals are global into a more useful form than the
146   one used for the invariant. *)   
147(* XXX superfluous lemma ? Commenting it for now.
148       if not superfluous : move to toCminorCorrectnessExpr.ma, after
149       [characterise_vars_localid] *)
150(*
151lemma characterise_vars_global : ∀globals,f,vartypes,stacksize.
152  characterise_vars globals f = 〈vartypes, stacksize〉 →
153  ∀id,r,ty. lookup' vartypes id = OK ? 〈Global r,ty〉 →
154  Exists ? (λx.x = 〈〈id,r〉,ty〉) globals ∧
155  ¬ Exists ? (λx. \fst x = id) (fn_params f @ fn_vars f).
156#globals #f #vartypes #stacksize #CHAR #id #r #ty #L
157cases (characterise_vars_src … CHAR id ?)
158[ * #r' * #ty' >L
159  * #E1 destruct (E1) #EX
160  %
161  [ @EX
162  | % #EX' cases (characterise_vars_localid … CHAR EX')
163    #ty' whd in ⊢ (% → ?); >L *
164  ]
165| * #ty' whd in ⊢ (% → ?); >L *
166| whd >(opt_eq_from_res ???? L) % #E destruct
167] qed. *)
168
169(* Show how the global environments match up. *)
170
171lemma map_partial_All_to_All2 : ∀A,B,P,f,l,H,l'.
172  map_partial_All A B P f l H = OK ? l' →
173  All2 ?? (λa,b. ∃p. f a p = OK ? b) l l'.
174#A #B #P #f #l
175elim l
176[ #H #l' #MAP normalize in MAP; destruct //
177| #h #t #IH * #p #H #l'
178  whd in ⊢ (??%? → ?);
179  lapply (refl ? (f h p)) whd in match (proj1 ???);
180  cases (f h p) in ⊢ (???% → %);
181  [ #b #E #MAP cases (bind_inversion ????? MAP)
182    #tl' * #MAP' #E' normalize in E'; destruct
183    % [ %{p} @E | @IH [ @H | @MAP' ] ]
184  | #m #_ #X normalize in X; destruct
185  ]
186] qed.
187 
188
189definition clight_cminor_matching : clight_program → matching ≝
190λp.
191  let tmpuniverse ≝ universe_for_program p in
192  let fun_globals ≝ map ?? (λidf. 〈\fst idf,Code,type_of_fundef (\snd idf)〉) (prog_funct ?? p) in
193  let var_globals ≝ map ?? (λv. 〈\fst (\fst v), \snd (\fst v), \snd (\snd v)〉) (prog_vars ?? p) in
194  let globals ≝ fun_globals @ var_globals in
195  mk_matching
196    ?? (list init_data × type) (list init_data)
197    (λvs,f_clight,f_cminor. ∃H1,H2. translate_fundef tmpuniverse globals H1 f_clight H2 = OK ? f_cminor)
198    (λv,w. \fst v = w).
199
200lemma clight_to_cminor_varnames : ∀p,p'.
201  clight_to_cminor p = OK ? p' →
202  prog_var_names … p = prog_var_names … p'.
203* #vars #fns #main * #vars' #fns' #main'
204#TO cases (bind_inversion ????? TO) #fns'' * #MAP #E
205whd in E:(??%%); destruct
206-MAP normalize
207elim vars
208[ //
209| * * #id #r * #d #t #tl #IH normalize >IH //
210] qed.
211
212lemma clight_to_cminor_matches : ∀p,p'.
213  clight_to_cminor p = OK ? p' →
214  match_program (clight_cminor_matching p) p p'.
215* #vars #fns #main * #vars' #fns' #main'
216#TO cases (bind_inversion ????? TO) #fns'' * #MAP #E
217whd in E:(??%%); destruct
218%
219[ -MAP whd in match (m_V ?); whd in match (m_W ?);
220  elim vars
221  [ //
222  | * * #id #r * #init #ty #tl #IH %
223    [ % //
224    | @(All2_mp … IH) * * #a #b * #c #d * * #e #f #g * /2/
225    ]
226  ]
227| @(All2_mp … (map_partial_All_to_All2 … MAP)) -MAP
228  * #id #f * #id' #f' * #H #F cases (bind_inversion ????? F) #f'' * #TRANSF #E
229  normalize in E; destruct
230  <(clight_to_cminor_varnames … TO)
231  % whd
232  % [2: % [2: @TRANSF | skip ] | skip ]
233| %
234] qed.
235
236(* --------------------------------------------------------------------------- *)
237(* Clight to Cminor makes use of fresh symbol generators, which store the list
238 * of symbols they generate. We need to maintain as an invariant that these grow
239 * in a monotonic and consistent fashion. *)
240(* --------------------------------------------------------------------------- *)
241
242(* The two following definitions and two lemmas are duplicated from switchRemoval.ma.
243 * TODO: factorise this in frontend_misc, if they turn out not to be useless *)
244definition fresher_than_or_equal : universe SymbolTag → universe SymbolTag → Prop ≝
245λu1,u2.
246  match u1 with
247  [ mk_universe p1 ⇒
248    match u2 with
249    [ mk_universe p2 ⇒ p2 ≤ p1 ] ].
250
251definition fte ≝ fresher_than_or_equal.
252
253lemma transitive_fte : ∀u1,u2,u3. fte u1 u2 → fte u2 u3 → fte u1 u3.
254* #u1 * #u2 * #u3 normalize /2 by transitive_le/
255qed.
256
257lemma reflexive_fte : ∀u. fte u u.
258* // qed.
259
260(* Express that the [first] tmpgen generates "newer" ids than an other one. *)
261definition tmpgen_fresher_than ≝
262  λvars. λgen1, gen2 : tmpgen vars.
263    fresher_than_or_equal (tmp_universe … gen1) (tmp_universe … gen2).
264
265(* Map a predicate on all the /keys/ of an environment, i.e. on a set
266 * of identifiers. *)
267definition env_domain_P : cl_env → ∀P:(ident → Prop). Prop ≝
268 λe, P.
269  match e with
270  [ an_id_map m ⇒
271    fold ?? (λkey,elt,acc. P (an_identifier ? key) ∧ acc) m True
272  ].
273
274(* Property for an identifier to be out of the set
275 * of identifiers represented by an universe. *)
276definition ident_below_universe ≝
277  λi: ident.
278  λu: universe SymbolTag.
279  match i with
280  [ an_identifier id ⇒
281    match u with
282    [ mk_universe id_u ⇒
283      id < id_u         
284    ]   
285  ].
286
287(* Property of the domain of an environment to be disjoint of the set
288 * of identifiers represented by an universe. *) 
289definition env_below_freshgen : env → ∀vars. tmpgen vars → Prop ≝
290  λe, vars, tmpgen.
291  env_domain_P e (λid. ident_below_universe id (tmp_universe … tmpgen)).
292
293(* The property of interest for the proof. Identifiers generated from an
294 * universe above the environment are not in the said environment. *)
295lemma lookup_fails_outside_of_env :
296  ∀env, vars, ty, gen, id, gen'.
297  alloc_tmp vars ty gen = 〈id, gen'〉 →
298  env_below_freshgen env vars gen →
299  lookup ?? env id = None ?.
300@cthulhu
301qed. 
302
303(* The property of being above an environment is conserved by fresh ident
304 * generation *)
305lemma alloc_tmp_env_invariant :
306  ∀env, vars, ty, gen, id, gen'.
307  alloc_tmp vars ty gen = 〈id, gen'〉 →
308  env_below_freshgen env vars gen →
309  env_below_freshgen env vars gen'.
310@cthulhu
311qed.
312
313(* --------------------------------------------------------------------------- *)
314(* Additional invariants not contain in clight_cminor_data *)
315(* --------------------------------------------------------------------------- *)
316
317(* Fresh variable ident generator *)
318(* tmp_gen     : tmpgen alloc_type; *)
319
320(* Temporary variables generated during conversion are well-allocated. *)
321definition tmp_vars_well_allocated ≝
322   λtmpenv: list (ident × type).
323   λcm_env.
324   λcm_m.
325   λcl_m.
326   λE: embedding.
327   ∀local_variable.
328   ∀H:present ?? cm_env local_variable.
329   ∀ty. Exists ? (λx. x = 〈local_variable, ty〉) tmpenv →
330   ∀v. val_typ v (typ_of_type ty) →
331   ∃cm_m'. storev (typ_of_type ty) cm_m (lookup_present ?? cm_env local_variable H) v = Some ? cm_m' ∧
332           memory_inj E cl_m cm_m'.
333
334(* wrap the above invariant into a clight_cminor_data-eating prop *)
335(*
336definition tmp_vars_well_allocated' ≝
337   λcl_f, cl_ge, cm_ge, INV.
338   λframe_data: clight_cminor_data cl_f cl_ge cm_ge INV.
339   λtmp_gen: tmpgen (alloc_type … frame_data).
340   ∀vars_v, cl_m_v, cm_env_v, cm_m_v.
341   vars_v   = alloc_type … frame_data →
342   cl_m_v   = cl_m … frame_data →
343   cm_env_v = cm_env … frame_data →
344   cm_m_v   = cm_m … frame_data →   
345   ∀local_variable.
346   ∀H:present ?? cm_env_v local_variable.
347   ∀ty. Exists ? (λx. x = 〈local_variable, ty〉) (tmp_env … tmp_gen) →
348   ∀v. val_typ v (typ_of_type ty) →
349   ∃cm_m'. storev (typ_of_type ty) cm_m_v (lookup_present ?? cm_env_v local_variable H) v = Some ? cm_m' ∧
350           memory_inj (Em … frame_data) cl_m_v cm_m'. *)
351
352(* --------------------------------------------------------------------------- *)           
353(* A measure on Clight states that is decreasing along execution sequences     *)
354(* --------------------------------------------------------------------------- *)
355
356(* statements *)
357let rec measure_Clight_statement (s : statement) : ℕ ≝
358match s with
359[ Sskip ⇒ 0
360| Ssequence s1 s2 ⇒
361  measure_Clight_statement s1 + measure_Clight_statement s2 + 1
362| Sifthenelse e s1 s2 =>
363  measure_Clight_statement s1 + measure_Clight_statement s2 + 1
364| Swhile e s =>
365  measure_Clight_statement s + 1
366| Sdowhile e s =>
367  measure_Clight_statement s + 1
368| Sfor s1 e s2 s3 =>
369  measure_Clight_statement s1 +
370  measure_Clight_statement s2 +
371  measure_Clight_statement s3 + 1
372| Sswitch e ls =>
373  measure_Clight_ls ls + 1
374| Slabel l s =>
375  measure_Clight_statement s + 1
376| Scost cl s =>
377  measure_Clight_statement s + 1
378| _ => 1
379]
380and measure_Clight_ls (ls : labeled_statements) : ℕ :=
381match ls with
382[ LSdefault s =>
383  measure_Clight_statement s
384| LScase sz i s ls =>
385  measure_Clight_statement s +
386  measure_Clight_ls ls
387].
388
389(* continuations *)
390let rec measure_Clight_cont (cont : cl_cont) : ℕ ≝
391match cont with
392[ Kstop => 0
393| Kseq s k =>
394  measure_Clight_statement s +
395  measure_Clight_cont k + 1
396| Kwhile e s k =>
397  measure_Clight_statement s +
398  measure_Clight_cont k + 1
399| Kdowhile e s k =>
400  measure_Clight_statement s +
401  measure_Clight_cont k + 1
402| Kfor2 e s1 s2 k =>
403  measure_Clight_statement s1 +
404  measure_Clight_statement s2 +
405  measure_Clight_cont k + 1
406| Kfor3 e s1 s2 k =>
407  measure_Clight_statement s1 +
408  measure_Clight_statement s2 +
409  measure_Clight_cont k + 1
410| Kswitch k =>
411  measure_Clight_cont k + 1
412| Kcall retaddr f e k =>
413  measure_Clight_statement (fn_body f) +
414  measure_Clight_cont k + 1
415].
416
417(* Shamelessly copying Compcert. *)
418definition measure_Clight : Clight_state → ℕ × ℕ ≝
419λstate.
420match state with
421[ State f s k e m ⇒
422  〈measure_Clight_statement s + measure_Clight_cont k + 1, measure_Clight_statement s + 1〉
423| Callstate fb fd args k m ⇒ 〈0, 0〉
424| Returnstate res k m ⇒ 〈0, 0〉
425| Finalstate r ⇒ 〈0, 0〉
426].
427
428(* Stuff on lexicographic orders *)
429definition lexicographic : ∀A:Type[0]. (A → A → Prop) → A × A → A × A → Prop ≝
430λA,Ord, x, y.
431  let 〈xa, xb〉 ≝ x in
432  let 〈ya, yb〉 ≝ y in
433  Ord xa ya ∨ (xa = ya ∧ Ord xb yb).
434
435definition lex_lt ≝ lexicographic nat lt.
436
437(* --------------------------------------------------------------------------- *)
438(* Simulation relations *)
439(* --------------------------------------------------------------------------- *)
440
441definition CMcast : ∀t,t'. CMexpr t → t = t' → CMexpr t'.
442#t #t' #e #H destruct (H) @e
443qed.
444
445lemma CMcast_identity : ∀t. ∀e: CMexpr t. CMcast t t e (refl ??) = e.
446#H1 #H2 @refl qed.
447
448(* relate Clight continuations and Cminor ones. *)
449inductive clight_cminor_cont_rel :
450  ∀cl_ge, cm_ge.
451  ∀INV:  clight_cminor_inv cl_ge cm_ge.     (* stuff on global variables and functions (matching between CL and CM) *)
452  ∀cl_fd: clight_fundef.                    (* current Clight function *)
453  fundef internal_function →                (* current Cminor function *)
454  cl_env →                                  (* Clight local environment *)
455  cm_env →                                  (* Cminor local environment *)
456  mem →                                     (* Cminor memory state *)
457  ∀alloc_type:var_types.                    (* map vars to alloc type *)
458  ∀tmpenv:list (ident×type).                (* list of generated variables *)
459  (*tmpgen alloc_type →                       (* input freshgen *)
460    tmpgen alloc_type →                       (* output freshgen *) *) (* bad idea *)
461  option typ →                              (* optional target type - arg. uniform over a given function *)
462  cl_cont →                                 (* CL cont *)
463  cm_cont →                                 (* CM cont *)
464  stack →                                   (* CM stack *)
465  Prop ≝
466(* Stop continuation *)
467| ClCm_cont_stop:
468  ∀cl_ge, cm_ge, INV, cl_f, cm_f, target_type.
469  ∀cl_env, cm_env, cm_m, alloc_type, tmpenv. (*, stmt_univ, stmt_univ'.*)
470  ∀cm_stack.
471  cm_stack = SStop →
472  clight_cminor_cont_rel cl_ge cm_ge INV cl_f cm_f cl_env cm_env cm_m alloc_type tmpenv (* stmt_univ stmt_univ' *) target_type Kstop Kend cm_stack
473
474(* Seq continuation *)
475| ClCm_cont_seq:
476  ∀cl_ge, cm_ge, INV, cl_f, cm_f, target_type.
477  ∀stack.
478  ∀alloc_type.
479  ∀tmpenv.
480  ∀cl_s: statement.
481  ∀cm_s: stmt.
482  ∀cl_env: cl_env.
483  ∀cm_env: cm_env.
484  ∀cm_m: mem.
485  ∀cl_k': cl_cont.
486  ∀cm_k': cm_cont.
487  ∀stmt_univ, stmt_univ'.
488  ∀lbl_univ, lbl_univ'.
489  ∀lbls.
490  ∀flag.
491  ∀Htranslate_inv.
492  translate_statement alloc_type stmt_univ lbl_univ lbls flag target_type cl_s = OK ? «〈stmt_univ',lbl_univ',cm_s〉, Htranslate_inv» →
493  (* ---- invariant on label existence ---- *)
494  lset_inclusion ? (labels_of cm_s) (labels_of (f_body cm_f)) →
495  (* ---- invariant on fresh variables ---- *)
496  lset_inclusion ? (tmp_env alloc_type stmt_univ') tmpenv →
497  clight_cminor_cont_rel cl_ge cm_ge INV (CL_Internal cl_f) (Internal … cm_f) cl_env cm_env cm_m alloc_type tmpenv (*stmt_univ stmt_univ'*) target_type cl_k' cm_k' stack →
498  clight_cminor_cont_rel cl_ge cm_ge INV (CL_Internal cl_f) (Internal … cm_f) cl_env cm_env cm_m alloc_type tmpenv (*stmt_univ stmt_univ'*) target_type (ClKseq cl_s cl_k') (Kseq cm_s cm_k') stack
499
500(* While continuation *) 
501| ClCm_cont_while:
502  (* Inductive family parameters *)
503  ∀cl_ge, cm_ge, INV, cl_f, cm_f, target_type.
504  ∀stack.
505  ∀alloc_type.
506  ∀tmpenv.
507  ∀cl_env.
508  ∀cm_env.
509  ∀cm_m.
510  (* sub-continuations *)
511  ∀cl_k': cl_cont.
512  ∀cm_k': cm_cont.
513  (* elements of the source while statement *)
514  ∀sz,sg.
515  ∀cl_ty.
516  ∀cl_cond_desc.
517  ∀cl_body.
518  ∀Heq: ASTint sz sg = typ_of_type cl_ty.
519  (* elements of the converted while statement *)
520  ∀cm_cond: CMexpr (ASTint sz sg).
521  ∀cm_body.
522  ∀entry,exit: identifier Label.
523  (* universes used to generate fresh labels and variables *) 
524  ∀stmt_univ, stmt_univ'.
525  ∀lbl_univ, lbl_univ', lbl_univ''.
526  ∀lbls: lenv.
527  ∀Htranslate_inv.
528  (* relate CL and CM expressions *)
529  ∀Hexpr_vars:expr_vars ? cm_cond (local_id alloc_type).
530  translate_expr alloc_type (Expr cl_cond_desc cl_ty) ≃ OK ? («cm_cond, Hexpr_vars») →
531  (* Parameters and results to find_label_always *)
532  ∀sInv: stmt_inv cm_f cm_env (f_body cm_f).
533  ∀Hlabel_declared: Exists (identifier Label) (λl'.l'=entry) (labels_of (f_body cm_f)).
534  ∀Hinv.
535  (* Specify how the labels for the while-replacing gotos are produced *)
536  mklabels lbl_univ = 〈〈entry, exit〉, lbl_univ'〉 →
537  translate_statement alloc_type stmt_univ lbl_univ' lbls (ConvertTo entry exit) target_type cl_body = OK ? «〈stmt_univ',lbl_univ'',cm_body〉, Htranslate_inv» →
538  (* ---- Invariant on label existence ----  *)
539  lset_inclusion ? (labels_of cm_body) (labels_of (f_body cm_f)) →
540  (* ---- invariant on fresh variables ---- *)
541  lset_inclusion ? (tmp_env alloc_type stmt_univ') tmpenv → 
542  find_label_always entry (f_body cm_f) Kend Hlabel_declared cm_f cm_env sInv I =
543    «〈(*St_label entry*)
544          (St_seq
545            (St_ifthenelse ?? cm_cond (St_seq cm_body (St_goto entry)) St_skip)
546            (St_label exit St_skip)), cm_k'〉, Hinv» →
547  clight_cminor_cont_rel cl_ge cm_ge INV (CL_Internal cl_f) (Internal … cm_f) cl_env cm_env cm_m alloc_type tmpenv (* stmt_univ stmt_univ' *) target_type cl_k' cm_k' stack →
548  clight_cminor_cont_rel cl_ge cm_ge INV (CL_Internal cl_f) (Internal … cm_f) cl_env cm_env cm_m alloc_type tmpenv (* stmt_univ stmt_univ' *) target_type
549    (Kwhile (Expr cl_cond_desc cl_ty) cl_body cl_k')
550    (Kseq (St_goto entry) (Kseq (St_label exit St_skip) cm_k')) stack
551   
552| ClCm_cont_call_store:
553  ∀cl_ge, cm_ge, INV, (* callee fn *) cl_fd, cm_fd, (* caller *) cl_f, cm_f, target_type, target_type'.
554  ∀stack.
555  ∀alloc_type,alloc_type'.
556  ∀tmp_env,tmp_env'.
557  ∀cl_env,cl_env'.
558  ∀cm_env,cm_env'.
559  ∀cm_m.
560  (* sub-continuations *)
561  ∀cl_k': cl_cont.
562  ∀cm_k': cm_cont.
563  (* CL return addr *)
564  ∀CL_lvalue_block,CL_lvalue_offset,lhs_ty.
565  ∀CM_lvalue_ptr.
566  (* CM stack content *)
567  ∀stackptr.
568  ∀fInv.
569  ∀tmp_var, ret_var.
570  ∀Htmp_var_present.
571  ∀Hret_present.
572  ∀Hstmt_inv.
573  (* TODO: loads of invariants *)
574  clight_cminor_cont_rel cl_ge cm_ge INV (CL_Internal cl_f) (Internal … cm_f) cl_env' cm_env' cm_m alloc_type' tmp_env' (* stmt_univ stmt_univ' *) target_type' cl_k' cm_k' stack →
575  clight_cminor_cont_rel cl_ge cm_ge INV cl_fd cm_fd cl_env cm_env cm_m alloc_type tmp_env (*stmt_univ stmt_univ*) target_type
576    (Kcall (Some ? 〈CL_lvalue_block, CL_lvalue_offset, lhs_ty〉) cl_f cl_env cl_k')
577    Kend (* cm_k' is on the Cminor stack, below *)
578    (Scall (Some ? 〈ret_var,typ_of_type lhs_ty〉) cm_f stackptr
579     (update_present SymbolTag val cm_env' tmp_var Htmp_var_present (Vptr CM_lvalue_ptr)) Hret_present
580     (stmt_inv_update cm_f cm_env' (f_body cm_f) tmp_var (Vptr CM_lvalue_ptr) fInv Htmp_var_present)
581     (Kseq
582      (St_store (typ_of_type lhs_ty) (Id ASTptr tmp_var)
583       (Id (typ_of_type lhs_ty) ret_var)) cm_k') Hstmt_inv stack)
584
585| ClCm_cont_call_nostore:
586  ∀cl_ge, cm_ge, INV, (* callee *) cl_fd, cm_fd, (* caller *) cl_f, cm_f, target_type, target_type'.
587  ∀stack.
588  ∀alloc_type,alloc_type'.
589  ∀tmpenv, tmpenv'.
590  ∀cl_env,cl_env'.
591  ∀cm_env,cm_env'.
592  ∀cm_m.
593  (* sub-continuations *)
594  ∀cl_k': cl_cont.
595  ∀cm_k': cm_cont.
596  (* CM stack content *)
597  ∀cl_lhs, cm_lhs.
598  match cl_lhs with
599  [ None ⇒ match cm_lhs with [ None ⇒ True | _ ⇒ False ]
600  | Some cl_location ⇒
601    match cm_lhs with
602    [ None ⇒ False
603    | Some cm_location ⇒
604      ∃CL_lvalue_block, CL_lvalue_offset, lhs_ty, ret_var.
605       cl_location = 〈CL_lvalue_block,CL_lvalue_offset, lhs_ty〉 ∧
606       cm_location = 〈ret_var, typ_of_type lhs_ty〉
607    ]
608  ] →
609  ∀Hret_present.
610  ∀Hstmt_inv.
611  ∀stackptr.
612  ∀fInv.
613(*  ∀stmt_univ.*)
614  clight_cminor_cont_rel cl_ge cm_ge INV (CL_Internal cl_f) (Internal … cm_f) cl_env' cm_env' cm_m alloc_type' tmpenv' (* stmt_univ stmt_univ' *) target_type' cl_k' cm_k' stack →
615  clight_cminor_cont_rel cl_ge cm_ge INV cl_fd cm_fd cl_env cm_env cm_m alloc_type tmpenv (*stmt_univ stmt_univ*) target_type
616   (Kcall cl_lhs cl_f cl_env cl_k')
617   Kend
618   (Scall cm_lhs cm_f stackptr cm_env Hret_present fInv cm_k' Hstmt_inv stack).
619
620lemma translate_fundef_internal :
621  ∀ge1, ge2.
622  ∀INV: clight_cminor_inv ge1 ge2.
623  ∀u, cl_f, cm_fundef.
624  ∀H1, H2. 
625  translate_fundef u (globals ?? INV) H1 (CL_Internal cl_f) H2 = OK ? cm_fundef →
626  ∃cm_f. cm_fundef = Internal ? cm_f ∧
627         translate_function u (globals ge1 ge2 INV) cl_f H1 H2 = OK ? cm_f.
628#ge1 #ge2 #INV #u #cl_f #cm_fd #H1 #H2
629whd in ⊢ ((??%?) → ?); cases (translate_function u (globals ge1 ge2 INV) cl_f H1 H2)
630normalize nodelta
631[ 2: #er #Habsurd destruct (Habsurd)
632| 1: #cm_f #Heq destruct (Heq) %{cm_f} @conj @refl ]
633qed.
634
635lemma translate_fundef_external :
636  ∀ge1, ge2.
637  ∀INV: clight_cminor_inv ge1 ge2.
638  ∀u, id, tl, ty.
639  ∀H1, H2.
640  translate_fundef u (globals ?? INV) H1 (CL_External id tl ty) H2 =
641    OK ? (External ? (mk_external_function id (signature_of_type tl ty))).
642#ge1 #ge2 #INV #u #id #tl #ty #H1 #H2 @refl
643qed.
644
645(* Definition of the simulation relation on states. The orders of the parameters is dictated by
646 * the necessity of performing an inversion on the continuation sim relation without having to
647 * play the usual game of lapplying all previous dependent arguments.  *)
648
649inductive clight_cminor_rel : ∀cl_ge, cm_ge. clight_cminor_inv cl_ge cm_ge  → Clight_state → Cminor_state → Prop ≝
650(* --------------------------------------------------------------------------- *)
651(* normal state *)
652(* --------------------------------------------------------------------------- *)
653| CMR_normal :
654  (* Clight and Cminor global envs *)
655  ∀cl_ge, cm_ge.
656  (* Relates globals to globals and functions to functions. *)
657  ∀INV:  clight_cminor_inv cl_ge cm_ge. 
658  (* ---- Statements ---- *)
659  (* Clight statement *) 
660  ∀cl_s: statement.
661  (* Cminor statement *)
662  ∀cm_s: stmt.                                           
663  (* ---- Continuations ---- *)
664  (* Clight continuation *)
665  ∀cl_k: cl_cont.
666  (* Cminor continuation *) 
667  ∀cm_k: cm_cont.
668  (* Cminor stack *)
669  ∀cm_st: stack.
670  (* Clight enclosing function *)
671  ∀cl_f: function.
672  (* Cminor enclosing function *)
673  ∀cm_f: internal_function.
674  (* optional return type of the function *)
675  ∀rettyp.
676  (* mapping from variables to their Cminor alloc type *)                                 
677  ∀alloc_type.
678  (* Clight env/mem *)
679  ∀cl_env, cl_m.
680  (* Cminor env/mem *)
681  ∀cm_env, cm_m.
682  (* Stack pointer (block containing Cminor locals), related size *)
683  ∀stackptr, stacksize.
684  (* ---- Cminor invariants ---- *)
685  ∀fInv: stmt_inv cm_f cm_env (f_body cm_f).
686  ∀sInv: stmt_inv cm_f cm_env cm_s.
687  ∀kInv: cont_inv cm_f cm_env cm_k.
688  (* ---- relate return type variable to actual return type ---- *)
689  rettyp = opttyp_of_type (fn_return cl_f) →
690  (* ---- relate Clight and Cminor functions ---- *)
691  ∀func_univ: universe SymbolTag.
692  ∀Hfresh_globals: globals_fresh_for_univ ? (globals ?? INV) func_univ.
693  ∀Hfresh_function: fn_fresh_for_univ cl_f func_univ.
694  translate_function func_univ (globals ?? INV) cl_f Hfresh_globals Hfresh_function = OK ? cm_f →
695  (* ---- relate Clight and Cminor statements ---- *)
696  (* fresh var generators *)
697  ∀stmt_univ,stmt_univ' : tmpgen alloc_type.
698  (* fresh label generators *)
699  ∀lbl_univ,lbl_univ'   : labgen.
700  (* map old labels to new labels *)
701  ∀lbls                 : lenv.
702  (* specify where to goto when encountering a continue or a break *)
703  ∀flag                 : convert_flag.
704  (* Invariant on translation produced by [translate_statement] *)
705  ∀Htranslate_inv.
706  translate_statement alloc_type stmt_univ lbl_univ lbls flag rettyp cl_s = OK ? «〈stmt_univ',lbl_univ',cm_s〉, Htranslate_inv» →
707  (* ---- invariant on label existence ---- *)
708  lset_inclusion ? (labels_of cm_s) (labels_of (f_body cm_f)) →
709  (* ---- relate Clight continuation to Cminor continuation ---- *)
710  ∀tmpenv.
711  lset_inclusion ? (tmp_env ? stmt_univ') tmpenv →
712  clight_cminor_cont_rel cl_ge cm_ge INV (CL_Internal cl_f) (Internal … cm_f) cl_env cm_env cm_m alloc_type tmpenv (*stmt_univ stmt_univ'*) rettyp cl_k cm_k cm_st →
713  (* ---- state invariants for memory and environments ---- *)
714  (* Embedding *)
715  ∀Em: embedding.
716  (* locals are properly allocated *)
717  tmp_vars_well_allocated tmpenv cm_env cm_m cl_m Em →
718  (* specify how alloc_type is built *)
719  characterise_vars (globals ?? INV) cl_f = 〈alloc_type, stacksize〉 →
720  (* spec. Clight env at alloc time *)
721  (∃m,m'. exec_alloc_variables empty_env m (fn_params cl_f @ fn_vars cl_f) = 〈cl_env,m'〉) →
722  (* memory injection *)
723  memory_inj Em cl_m cm_m →
724  (* map CL env to CM env *)
725  memory_matching Em cl_ge cm_ge cl_m cm_m cl_env cm_env INV stackptr alloc_type →
726  (* Force embedding to compute identity on functions *)
727  (∀b. block_region b = Code → Em b = Some ? 〈b, zero_offset〉) →
728  (* Make explicit the fact that locals in CL are mapped to a single CM block *)
729  (∀b1.∀delta. Em b1=Some ? 〈stackptr,delta〉 →
730               mem block b1 (blocks_of_env cl_env)) →
731  (* The fresh name generator is compatible with the clight environment *)
732  env_below_freshgen cl_env alloc_type stmt_univ →
733  clight_cminor_rel cl_ge cm_ge INV
734    (ClState cl_f cl_s cl_k cl_env cl_m)
735    (CmState cm_f cm_s cm_env fInv sInv cm_m stackptr cm_k kInv cm_st)
736(* --------------------------------------------------------------------------- *)
737(* return state *)
738(* --------------------------------------------------------------------------- *)
739| CMR_return :
740  (* Clight and Cminor global envs *)
741  ∀cl_ge, cm_ge.
742  (* Relates globals to globals and functions to functions. *)
743  ∀INV: clight_cminor_inv cl_ge cm_ge.
744  (* ---- Continuations and functions ---- *)
745  (* Clight continuation *)
746  ∀cl_k: cl_cont.
747  (* Cminor continuation *)
748  ∀cm_k: cm_cont.
749  (* Cminor stack *)
750  ∀cm_st: stack.
751  (* Clight enclosing function *)
752  ∀cl_f: function.
753  (* Cminor enclosing function *)
754  ∀cm_f: internal_function.
755  (* mapping from variables to their Cminor alloc type *)
756  ∀alloc_type.
757  (* Clight env/mem *)
758  ∀cl_env, cl_m.
759  (* Cminor env/mem *)
760  ∀cm_env, cm_m.
761  (* Stack pointer (block containing Cminor locals), related size *)
762  ∀stackptr, stacksize.
763  (* fresh label generator *)
764  ∀stmt_univ: tmpgen alloc_type.
765  ∀tmpenv.
766  lset_inclusion ? (tmp_env ? stmt_univ) tmpenv →
767  (* ---- state invariants for memory and environments ---- *)
768  (* Embedding *)
769  ∀Em: embedding.
770  (* locals are properly allocated *)
771  tmp_vars_well_allocated tmpenv cm_env cm_m cl_m Em →
772  (* specify how alloc_type is built *)
773  characterise_vars (globals ?? INV) cl_f = 〈alloc_type, stacksize〉 →
774  (* spec. Clight env at alloc time *)
775  (∃m,m'. exec_alloc_variables empty_env m (fn_params cl_f @ fn_vars cl_f) = 〈cl_env,m'〉) →
776  (* memory injection *)
777  memory_inj Em cl_m cm_m →
778  (* map CL env to CM env *)
779  memory_matching Em cl_ge cm_ge cl_m cm_m cl_env cm_env INV stackptr alloc_type →
780  (* Force embedding to compute identity on functions *)
781  (∀b. block_region b = Code → Em b = Some ? 〈b, zero_offset〉) →
782  (* Make explicit the fact that locals in CL are mapped to a single CM block *)
783  (∀b1.∀delta. Em b1=Some ? 〈stackptr,delta〉 →
784               mem block b1 (blocks_of_env cl_env)) →
785  clight_cminor_cont_rel cl_ge cm_ge INV (CL_Internal cl_f) (Internal … cm_f) cl_env cm_env cm_m alloc_type tmpenv (*stmt_univ stmt_univ*) (None ?) cl_k cm_k cm_st →
786  clight_cminor_rel cl_ge cm_ge INV
787    (ClReturnstate Vundef cl_k cl_m)
788    (CmReturnstate (None val) cm_m cm_st)
789(* --------------------------------------------------------------------------- *)
790(* call state *)
791(* --------------------------------------------------------------------------- *)
792| CMR_call :
793  (* Clight and Cminor global envs *)
794  ∀cl_ge, cm_ge.
795  (* Relates globals to globals and functions to functions. *) 
796  ∀INV:  clight_cminor_inv cl_ge cm_ge.
797  (* ------- Continuations and functions for the current stack frame -------- *)
798  (* Clight continuation *)
799  ∀cl_k: cl_cont.
800  (* Cminor stack *)
801  ∀cm_st: stack.
802  (* Clight called fundef *)
803  ∀cl_fundef.
804  (* Cminor called fundef *)
805  ∀cm_fundef.
806  (* block of Clight and Cminor function *)
807  (* XXX why do I need that already ? *)
808  ∀fblock: block.
809  (* optional return type of the function *)
810  ∀target_type.
811  (* Clight env/mem *)
812  ∀cl_env, cl_m.
813  (* Cminor env/mem *)
814  ∀cm_env, cm_m.
815  (* specify fblock; as a consequence of these and INV we can deduce that
816     cm_fundef is the translation of cl_fundef *)
817  ∀fun_id.
818  find_funct_id clight_fundef cl_ge (Vptr (mk_pointer fblock zero_offset)) = Some ? 〈cl_fundef,fun_id〉 →
819  find_funct_id (fundef internal_function) cm_ge (Vptr (mk_pointer fblock zero_offset)) = Some ? 〈cm_fundef,fun_id〉 →
820  ∀tmpenv.
821  (*match cl_fundef with
822  [ CL_Internal _ ⇒*)
823     (* specify continuation *)
824     clight_cminor_cont_rel cl_ge cm_ge INV cl_fundef cm_fundef cl_env cm_env cm_m (empty_map …) tmpenv target_type cl_k Kend cm_st
825(*       ∨
826     (∃cl_blo, cl_off, cl_ty.         (* Clight return loscation + type *)
827      ∃cm_loc_ident, cm_return_ident. (* Cminor locals storing the lvalues *)
828      ∃sInv, fInv, kInv.              (* Invariants required by the stack construction *)
829       present ?? cm_env cm_loc_ident ∧
830       present ?? cm_env cm_return_ident ∧
831       (clight_cminor_cont_rel cl_ge cm_ge INV cl_f cm_f cl_env cm_env cm_m alloc_type target_type
832          (Kcall (Some ? 〈cl_blo, cl_off, cl_ty〉) cl_f cl_env cl_k)
833           cm_k (Scall (Some ? 〈cm_return_ident,typ_of_type cl_ty〉) cm_f stackptr cm_env sInv fInv
834                     (Kseq (St_store (typ_of_type cl_ty) (Id ? cm_loc_ident) (Id ? cm_return_ident)) cm_k)
835                      kInv cm_st))) *)
836  (*| CL_External cl_id cl_argtypes cl_rettype ⇒
837    match cm_fundef with
838    [ Internal _ ⇒ False
839    | External cm_f_ext ⇒ True ]
840(*      match cm_f_ext with
841      [ mk_external_function cm_id sig ⇒
842        cl_fun_id = cl_id ∧ cm_fun_id = cm_id ∧ cl_fun_id = cm_fun_id
843      ] *)
844  ]*) →
845  (* ---- state invariants for memory and environments ---- *)
846  (* Embedding *)
847  ∀Em: embedding.
848  (* memory injection *)
849  memory_inj Em cl_m cm_m →
850  (* Force embedding to compute identity on functions *)
851  (∀b. block_region b = Code → Em b = Some ? 〈b, zero_offset〉) →
852  ∀cl_args_values, cm_args_values.
853  All2 val val (λcl_val:val.λcm_val:val.value_eq Em cl_val cm_val) cl_args_values cm_args_values →
854  clight_cminor_rel cl_ge cm_ge INV
855   (ClCallstate fun_id cl_fundef cl_args_values cl_k cl_m)
856   (CmCallstate fun_id cm_fundef cm_args_values cm_m cm_st)
857(* --------------------------------------------------------------------------- *)
858(* special while state *)
859(* --------------------------------------------------------------------------- *)
860| CMR_while:
861 ∀cl_ge,cm_ge,INV,cl_f,cm_f.
862 ∀cl_env, cl_m, cm_env, cm_m, stackptr, stacksize.
863 ∀alloc_type.
864 ∀cl_k, cm_k. 
865 ∀sz,sg, cl_ty, cl_cond_desc.
866 ∀cl_body.
867 ∀entry_label, exit_label.
868 ∀cm_cond: CMexpr (ASTint sz sg).
869 ∀cm_body.
870 ∀cm_stack.
871 ∀rettyp.
872 ∀kInv: cont_inv cm_f cm_env cm_k.
873 ∀fInv: stmt_inv cm_f cm_env (f_body cm_f).
874 ∀sInv: stmt_inv cm_f cm_env
875           ((*St_label entry_label*)
876            (St_seq
877             (St_ifthenelse sz sg cm_cond (St_seq cm_body (St_goto entry_label)) St_skip)
878             (St_label exit_label St_skip))).
879 (* Constrain the CL type *)             
880 ∀Heq_ty: ASTint sz sg = typ_of_type cl_ty.           
881 (* ---- relate return type variable to actual return type ---- *)
882 rettyp = opttyp_of_type (fn_return cl_f) →
883 (* ---- relate Clight and Cminor functions ---- *)
884 ∀func_univ: universe SymbolTag.
885 ∀Hfresh_globals: globals_fresh_for_univ ? (globals ?? INV) func_univ.
886 ∀Hfresh_function: fn_fresh_for_univ cl_f func_univ.
887 translate_function func_univ (globals ?? INV) cl_f Hfresh_globals Hfresh_function = OK ? cm_f →
888 (* ---- relate continuations ---- *)
889 ∀stmt_univ,stmt_univ',lbl_univ,lbl_univ',lbl_univ'',lbls.
890 ∀tmpenv'.
891 lset_inclusion ? (tmp_env ? stmt_univ') tmpenv' →
892 clight_cminor_cont_rel cl_ge cm_ge INV (CL_Internal cl_f) (Internal … cm_f) cl_env cm_env cm_m alloc_type tmpenv' rettyp cl_k cm_k cm_stack →
893 (* Invariants *)
894 ∀Em: embedding.
895 tmp_vars_well_allocated tmpenv' cm_env cm_m cl_m Em →        (* locals are properly allocated *)
896 characterise_vars (globals ?? INV) cl_f = 〈alloc_type, stacksize〉 →        (* specify how alloc_type is built *)
897 (∃m,m'. exec_alloc_variables empty_env m (fn_params cl_f @ fn_vars cl_f) = 〈cl_env,m'〉) → (* spec. Clight env *)
898 memory_inj Em cl_m cm_m →                                                  (* memory injection *)
899 memory_matching Em cl_ge cm_ge cl_m cm_m cl_env cm_env INV stackptr alloc_type →  (* map CL env to CM env *)
900 (∀b. block_region b = Code → Em b = Some ? 〈b, zero_offset〉) →             (* Force embedding to compute identity on functions *)
901 (* Make explicit the fact that locals in CL are mapped to a single CM block *)
902 (∀b1.∀delta. Em b1 = Some ? 〈stackptr,delta〉 →
903              mem block b1 (blocks_of_env cl_env)) →
904 (* The fresh name generator is compatible with the clight environment *)
905 env_below_freshgen cl_env alloc_type stmt_univ →             
906 (* Expression translation and related hypotheses *)
907 ∀Hcond_tr:expr_vars ? cm_cond (local_id alloc_type).  (* invariant after converting conditional expr *)
908 (* translate_expr alloc_type (Expr cl_cond_desc cl_ty) = OK ? «CMcast ?? cm_cond Heq_ty, Hcond_tr » → *)
909 translate_expr alloc_type (Expr cl_cond_desc cl_ty) ≃ OK ? «cm_cond, Hcond_tr » →
910 (* Label consistency *)
911 Exists ? (λl':identifier Label.l'=entry_label) (labels_of (f_body cm_f)) →
912 Exists ? (λl':identifier Label.l'=exit_label) (labels_of (f_body cm_f)) → 
913 (* Statement translation *)
914 ∀Htranslate_inv.
915 mklabels lbl_univ = 〈〈entry_label, exit_label〉, lbl_univ'〉 →
916 translate_statement alloc_type stmt_univ lbl_univ' lbls
917   (ConvertTo entry_label exit_label) rettyp cl_body
918   = OK ? «〈stmt_univ',lbl_univ'',cm_body〉,Htranslate_inv» →
919 (* ---- invariant on label existence ---- *)
920 lset_inclusion ? (labels_of cm_body) (labels_of (f_body cm_f)) → 
921 (* Express the fact that the label points where it ought to *)
922 ∀Hlabel_exists.
923 ∀Hinv1, Hinv2.
924 find_label_always entry_label (f_body cm_f) Kend Hlabel_exists cm_f cm_env fInv Hinv1
925   = «〈(*St_label entry_label*)
926       (St_seq
927        (St_ifthenelse sz sg cm_cond (St_seq cm_body (St_goto entry_label))
928         St_skip)
929        (St_label exit_label St_skip)),
930      cm_k〉,
931   Hinv2» →
932 (clight_cminor_rel cl_ge cm_ge INV
933  (ClState cl_f (Swhile (Expr cl_cond_desc cl_ty) cl_body) cl_k cl_env cl_m)
934  (CmState cm_f
935   ( (*St_label entry_label*)
936    (St_seq
937     (St_ifthenelse sz sg cm_cond (St_seq cm_body (St_goto entry_label)) St_skip)
938     (St_label exit_label St_skip)))
939   cm_env fInv sInv cm_m stackptr cm_k kInv cm_stack)).
940
941   
942(*
943| CMR_call_nostore :
944 (* call to a function with no return value, or which returns in a local variable in Cminor *)
945 ∀cl_ge, cm_ge. (* cl_f, cm_f.*)
946 ∀INV: clight_cminor_inv cl_ge cm_ge.
947 ∀alloc_type, cl_env, cl_m, cm_env, cm_m, cm_stack, stackptr.
948 (* TODO: put the actual invariants on memory and etc. here *)
949 ∀func_univ: universe SymbolTag.
950 ∀cl_f, cm_f.
951 ∀Hglobals_fresh: globals_fresh_for_univ type (globals cl_ge cm_ge INV) func_univ.
952 ∀Hfundef_fresh:  fd_fresh_for_univ (CL_Internal cl_f) func_univ.
953 ∀rettyp.
954 ∀cl_k, cm_k.
955 ∀fblock.
956 rettyp = opttyp_of_type (fn_return cl_f) ∧
957 find_funct clight_fundef cl_ge (Vptr (mk_pointer fblock zero_offset)) = Some ? (CL_Internal cl_f) →
958 find_funct (fundef internal_function) cm_ge (Vptr (mk_pointer fblock zero_offset)) = Some ? (Internal ? cm_f) →
959 translate_function func_univ (globals ?? INV) cl_f Hglobals_fresh Hfundef_fresh = OK ? cm_f →
960 clight_cminor_cont_rel cl_ge cm_ge INV cl_f cm_f cl_env cm_env alloc_type rettyp cl_k cm_k cm_stack →
961 ∀fun_id.
962 ∀cl_retval, cm_retval.
963 ∀sInv, fInv, kInv.
964 ∀cl_args_values, cm_args_values.
965 All2 val val (λcl_val:val.λcm_val:val.value_eq Em cl_val cm_val) cl_args_values cm_args_values →
966 (* TODO: return_value_rel … INV frame_data cl_retval cm_retval →*)
967 clight_cminor_rel cl_ge cm_ge INV
968  (ClCallstate fun_id (CL_Internal cl_f) cl_args_values cl_k cl_m)
969  (CmCallstate fun_id (Internal ? cm_f) cm_args_values cm_m cm_stack)
970
971| CMR_call_store :
972 (* call to a function which returns to some location in memory in Cminor *)
973 ∀cl_ge, cm_ge.
974 ∀INV: clight_cminor_inv cl_ge cm_ge.
975 ∀alloc_type, cl_env, cl_m, cm_env, cm_m, cm_stack, stackptr.
976 (* TODO: put the actual invariants on memory and etc. here *)
977 ∀func_univ: universe SymbolTag.
978 ∀cl_f, cm_f.
979 ∀Hglobals_fresh: globals_fresh_for_univ type (globals cl_ge cm_ge INV) func_univ.
980 ∀Hfundef_fresh:  fd_fresh_for_univ (CL_Internal cl_f) func_univ.
981 ∀rettyp.
982 ∀cl_k, cm_k.
983 ∀fblock.
984 rettyp = opttyp_of_type (fn_return cl_f) →
985 find_funct clight_fundef cl_ge (Vptr (mk_pointer fblock zero_offset)) = Some ? (CL_Internal cl_f) →
986 find_funct (fundef internal_function) cm_ge (Vptr (mk_pointer fblock zero_offset)) = Some ? (Internal ? cm_f) →
987 translate_function func_univ (globals ?? INV) cl_f Hglobals_fresh Hfundef_fresh = OK ? cm_f →
988 clight_cminor_cont_rel cl_ge cm_ge INV cl_f cm_f cl_env cm_env alloc_type rettyp cl_k cm_k cm_stack →
989 ∀fun_id.
990 ∀cl_rettyp, cl_retval, cl_rettrace, cm_retval.
991 ∀cl_lhs, cm_lhs, Hinvariant_on_cm_lhs.
992 (* Explain where the lhs of the post-return assign comes from *)
993 exec_lvalue cl_ge cl_env cl_m cl_lhs = OK ? 〈cl_retval, cl_rettrace〉 →
994 translate_dest alloc_type cl_lhs = OK ? (MemDest ? «cm_lhs, Hinvariant_on_cm_lhs») →
995 (* TODO: Explain that the actual variable used to store the ret val is fresh and has the
996  * right type, etc *)
997 ∀cm_ret_var.
998 ∀sInv, fInv, kInv.
999 ∀cl_args_values, cm_args_values.
1000 All2 val val (λcl_val:val.λcm_val:val.value_eq Em cl_val cm_val) cl_args_values cm_args_values →
1001 (* TODO: return_value_rel … INV frame_data cl_retval cm_retval →*)
1002 ∀cm_stack.
1003 clight_cminor_rel cl_ge cm_ge INV
1004  (ClCallstate fun_id (CL_Internal cl_f)
1005    cl_args_values (Kcall (Some ? 〈cl_retval,cl_rettyp〉) cl_f cl_env cl_k) cl_m)
1006  (CmCallstate fun_id (Internal ? cm_f)
1007    cm_args_values cm_m (Scall cm_retval cm_f stackptr cm_env sInv fInv
1008                          (Kseq (St_store (typ_of_type cl_rettyp) cm_lhs
1009                                          (Id (typ_of_type cl_rettyp) cm_ret_var)) cm_k)
1010                           kInv cm_stack))
1011*)   
1012
1013definition clight_normal : Clight_state → bool ≝
1014λs. match Clight_classify s with [ cl_other ⇒ true | cl_jump ⇒ true | _ ⇒ false ].
1015
1016definition cminor_normal : Cminor_state → bool ≝
1017λs. match Cminor_classify s with [ cl_other ⇒ true | cl_jump ⇒ true | _ ⇒ false ].
1018
1019definition cl_pre : preclassified_system ≝
1020  mk_preclassified_system
1021    clight_fullexec
1022    (λg. Clight_labelled)
1023    (λg. Clight_classify)
1024    (λx,y,H. an_identifier ? one). (* XXX TODO *)
1025
1026definition cm_pre : preclassified_system ≝
1027  mk_preclassified_system
1028    Cminor_fullexec
1029    (λg. Cminor_labelled)
1030    (λg. Cminor_classify)
1031    (λx,y,H. an_identifier ? one). (* XXX TODO *)
1032
1033(* --------------------------------------------------------------------------- *)
1034(* General purpose auxilliary lemmas. *)
1035(* --------------------------------------------------------------------------- *)
1036
1037lemma invert_assert :
1038  ∀b. ∀P. assert b P → b = true ∧ P.
1039* #P whd in ⊢ (% → ?); #H
1040[ @conj try @refl @H
1041| @False_ind @H ]
1042qed.
1043
1044lemma res_to_io :
1045  ∀A,B:Type[0]. ∀C.
1046  ∀x: res A. ∀y.
1047  match x with
1048  [ OK v ⇒  Value B C ? v
1049  | Error m ⇒ Wrong … m ] = return y →
1050  x = OK ? y.
1051#A #B #C *
1052[ #x #y normalize nodelta whd in ⊢ ((???%) → ?); #Heq destruct (Heq) @refl
1053| #err #y normalize nodelta whd in ⊢ ((???%) → ?); #Heq destruct (Heq) ]
1054qed.
1055
1056lemma jmeq_absorb : ∀A:Type[0]. ∀a,b: A. ∀P:Prop. (a = b → P) → a ≃ b → P.
1057#A #a #b #P #H #Heq lapply (jmeq_to_eq ??? Heq) #Heq' @H @Heq' qed.
1058
1059(* wrap up some trivial bit of reasoning to alleviate strange destruct behaviour *)
1060lemma pair_eq_split :
1061  ∀A,B:Type[0]. ∀a1,a2:A. ∀b1,b2:B.
1062  〈a1,b1〉 = 〈a2, b2〉 →
1063  a1 = a2 ∧ b1 = b2.
1064#A #B #a1 #a2 #b1 #b2 #Heq destruct (Heq) @conj try @refl
1065qed.
1066
1067lemma ok_eq_ok_destruct :
1068  ∀A:Type[0]. ∀a,b:A. OK ? a = OK ? b → a = b.
1069#H1 #H2 #H3 #H4 destruct @refl qed.
1070
1071lemma sigma_eq_destruct  : ∀A:Type[0]. ∀a,b:A. ∀P: A → Prop. ∀Ha: P a. ∀Hb: P b.  «a, Ha» = «b,Hb» → a = b ∧ Ha ≃ Hb.
1072#A #a #b #P #Ha #Hb #Heq destruct (Heq)
1073@conj try %
1074qed.
1075
1076(* inverting find_funct and find_funct_ptr *)
1077lemma find_funct_inversion :
1078  ∀F: Type[0]. ∀ge: genv_t F. ∀v: val. ∀res: F.
1079      find_funct F ge v = Some ? res →
1080      (∃ptr. v = Vptr ptr ∧
1081            (poff ptr) = zero_offset ∧
1082            block_region (pblock ptr) = Code ∧
1083            (∃p. block_id (pblock ptr) = neg p ∧
1084                 lookup_opt … p (functions … ge) = Some ? res)).
1085#F #ge #v #res
1086cases v
1087[ | #sz #i | | #ptr ]
1088whd in ⊢ ((??%?) → ?);
1089#Heq destruct (Heq)
1090%{ptr} @conj try @conj try @conj try @refl
1091lapply Heq -Heq
1092@(eq_offset_elim … (poff ptr) zero_offset) //
1093normalize nodelta
1094[ 1,3,5: #_ #Habsurd destruct (Habsurd) ]
1095#Heq destruct (Heq)
1096whd in ⊢ ((??%?) → ?);
1097cases ptr #blo #off cases (block_region blo) normalize nodelta
1098[ 1,3: #Habsurd destruct (Habsurd) ]
1099[ // ]
1100cases (block_id blo) normalize nodelta
1101[ #Habsurd destruct (Habsurd) | #p #Habsurd destruct (Habsurd) ]
1102#p #Hlookup %{p} @conj try @refl assumption
1103qed.
1104
1105lemma find_funct_id_inversion :
1106  ∀F: Type[0]. ∀ge: genv_t F. ∀ptr. ∀f. ∀id.
1107  find_funct_id F ge ptr = Some ? 〈f, id〉 →
1108  ∃H:(find_funct F ge ptr = Some ? f).
1109     id = symbol_of_function_val' F ge ptr f H.
1110#F #ge #ptr #f #id
1111whd in match (find_funct_id ???);
1112generalize in match (refl ??);
1113generalize in ⊢
1114  (∀_:(???%).
1115    (??(match %
1116        with
1117        [ _ ⇒ λ_. ?
1118        | _ ⇒ λ_.λ_. ? ] ?)?) → ?);
1119#o cases o
1120normalize nodelta
1121[ #H #Habsurd destruct (Habsurd)
1122| #f #Hfind #Heq destruct (Heq) %{Hfind}
1123  cases (find_funct_inversion ???? Hfind) #ptr *
1124  * * #Hptr lapply Hfind -Hfind >Hptr #Hfind
1125  #Hoff #Hblock * #id * #Hblock_id #Hlookup_opt
1126  normalize nodelta @refl
1127] qed.
1128
1129(* We should be able to prove that ty = ty' with some more hypotheses, if needed. *)
1130lemma translate_dest_id_inversion :
1131  ∀var_types, e, var_id, H.
1132   translate_dest var_types e = return IdDest var_types ? var_id H →
1133   e = Expr (Evar var_id) (typeof e).
1134@cthulhu
1135(*   
1136#vars #e #var_id #ty #H
1137cases e #ed #ty'
1138cases ed
1139[ #sz #i | #id | #e1 | #e1 | #op #e1 |#op #e1 #e2 | #cast_ty #e1
1140| #cond #iftrue #iffalse | #e1 #e2 | #e1 #e2 | #sizeofty | #e1 #field | #cost #e1 ]
1141whd in ⊢ ((??%%) → ?);
1142#Heq
1143[ 1,4,5,6,7,8,9,10,11,13: destruct (Heq)
1144| 3,12: cases (bind_inversion ????? Heq) * #H1 #H2 #H3 cases H3
1145        #_ whd in ⊢ ((??%%) → ?); #Heq destruct (Heq) ]
1146lapply Heq -Heq
1147change with (bind2_eq ????? ) in ⊢ ((??%?) → ?); #Heq
1148cases (bind2_eq_inversion ?????? Heq)
1149#alloctype
1150(* * #alloctype *) * #typ' *
1151cases alloctype
1152[ #r | #n | ] normalize nodelta #Hlookup'
1153[ 1,2: whd in ⊢ ((??%%) → ?); #Heq destruct (Heq) ]
1154whd in ⊢ ((??%%) → ?); #Heq' destruct (Heq')
1155@refl*)
1156qed.
1157
1158
1159(* Note: duplicate in switchRemoval.ma *)
1160lemma fresh_elim : ∀u. ∃fv',u'. fresh SymbolTag u = 〈fv', u'〉. #u /3 by ex_intro/ qed.
1161
1162lemma fresh_elim_lab : ∀u. ∃fv',u'. fresh Label u = 〈fv', u'〉. #u /3 by ex_intro/ qed.
1163
1164
1165lemma breakup_dependent_match_on_pairs :
1166 ∀A,B,C: Type[0].
1167 ∀term: A × B.
1168 ∀F: ∀x,y. 〈x, y〉 = term → C.
1169 ∀z:C.
1170 match term
1171 return λx.x = term → ? with
1172 [ mk_Prod x y ⇒ λEq. F x y Eq ] (refl ? term) = z →
1173 ∃xa,xb,H. term = 〈xa, xb〉 ∧
1174           F xa xb H = z.
1175#A #B #C * #xa #xb #F #z normalize nodelta #H %{xa} %{xb} %{(refl ??)} @conj try @conj
1176// qed.
1177
1178(* --------------------------------------------------------------------------- *)
1179(* Extending simulation results on expressions to particular cases             *)
1180(* --------------------------------------------------------------------------- *)
1181
1182lemma translate_expr_sigma_welltyped : ∀vars, cl_expr, cm_expr.
1183  translate_expr_sigma vars cl_expr = OK ? cm_expr →
1184  dpi1 ?? (pi1 ?? cm_expr) = typ_of_type (typeof cl_expr).
1185#vars #cl_expr * * #typ #cm_expr normalize nodelta #Hexpr_vars
1186whd in ⊢ ((??%?) → ?); #H
1187cases (bind_inversion ????? H) -H * #cm_expr' #Hexpr_vars' *
1188#Htranslate_expr
1189whd in ⊢ ((??%%) → ?); #Heq destruct (Heq) @refl
1190qed.
1191
1192lemma translate_exprlist_sigma_welltyped :
1193  ∀vars, cl_exprs, cm_exprs.
1194  mmap_sigma ??? (translate_expr_sigma vars) cl_exprs = OK ? cm_exprs →
1195  All2 ?? (λcl, cm. dpi1 ?? cm = typ_of_type (typeof cl)) cl_exprs (pi1 ?? cm_exprs).
1196#vars #cl_exprs
1197elim cl_exprs
1198[ * #cm_exprs #Hall whd in ⊢ ((??%?) → ?); #Heq destruct (Heq) @I
1199| #hd #tl #Hind * #cm_exprs #Hall #H
1200  cases (bind_inversion ????? H) -H
1201  * * #cm_typ #cm_expr normalize nodelta
1202  #Hexpr_vars_cm * #Htranslate_hd
1203  lapply (translate_expr_sigma_welltyped … Htranslate_hd)
1204  #Heq_cm_typ #H
1205  cases (bind_inversion ????? H) -H
1206  #cm_tail lapply (Hind cm_tail) cases cm_tail
1207  #cm_tail_expr #Hall_tail -Hind #Hind * #Heq_cm_tail normalize nodelta
1208   whd in ⊢ ((??%%) → ?); #Heq destruct (Heq) whd @conj
1209   [ @Heq_cm_typ
1210   | @Hind assumption ]
1211] qed.
1212
1213lemma translate_dest_MemDest_simulation :
1214  ∀cl_f  : function.
1215  ∀cl_ge : genv_t clight_fundef.
1216  ∀cm_ge : genv_t (fundef internal_function).
1217  ∀INV   : clight_cminor_inv cl_ge cm_ge.
1218  ∀alloc_type. 
1219  ∀cl_env, cl_m, cm_env, cm_m, stackptr.
1220  ∀Em.
1221  ∀stacksize     : ℕ. 
1222  ∀alloc_hyp     : characterise_vars (globals ?? INV) cl_f = 〈alloc_type, stacksize〉.
1223  ∀cl_cm_env_hyp : ∃m,m'. exec_alloc_variables empty_env m (fn_params cl_f @ fn_vars cl_f) = 〈cl_env,m'〉.
1224  ∀injection     : memory_inj Em cl_m cm_m.
1225  ∀matching      : memory_matching Em cl_ge cm_ge cl_m cm_m cl_env cm_env INV stackptr alloc_type.
1226  (* decorrelate goal from input using some eqs *)
1227  ∀cl_expr. ∀cm_expr.
1228  ∀cl_block, cl_offset, trace.
1229  ∀Hyp_present. 
1230     translate_dest alloc_type cl_expr = OK ? (MemDest … cm_expr) →
1231     exec_lvalue cl_ge cl_env cl_m cl_expr = OK ? 〈〈cl_block, cl_offset〉, trace〉 →
1232     ∃cm_val. eval_expr cm_ge ASTptr cm_expr cm_env Hyp_present stackptr cm_m = OK ? 〈trace, cm_val〉 ∧
1233              value_eq Em (Vptr (mk_pointer cl_block cl_offset)) cm_val.     
1234#cl_f #cl_ge #cm_ge #INV #alloc_type
1235#cl_env #cl_m #cm_env #cm_m #stackptr #Em #stacksize #alloc_hyp #cl_env_hyp #injection #matching
1236#cl_expr * #cm_expr #Hexpr_vars #cl_block #cl_offset #trace #Hyp_present
1237whd in match (translate_dest ??); cases cl_expr #cl_desc #cl_typ normalize nodelta
1238cases cl_desc normalize nodelta
1239[ #sz #i | #id | #e1 | #e1 | #op #e1 |#op #e1 #e2 | #cast_ty #e1
1240| #cond #iftrue #iffalse | #e1 #e2 | #e1 #e2 | #sizeofty | #e1 #field | #cost #e1 ]
1241#Htranslate
1242[ 2:
1243| *: cases (bind_inversion ????? Htranslate) -Htranslate * #cm_expr' #Hexpr_vars' *
1244     #Htranslate_addr
1245     whd in ⊢ ((??%%) → ?); #Heq destruct (Heq) #Hexec_lvalue
1246     cases (eval_expr_sim cl_ge cm_ge INV cl_f alloc_type stacksize alloc_hyp … cl_env_hyp … injection … matching)
1247     #_ #Hsim
1248     @(Hsim ??? Hexpr_vars … Htranslate_addr ??? ? Hexec_lvalue) ]
1249cases (bind2_eq_inversion ?????? Htranslate) -Htranslate *
1250[ #r | #n | ]
1251* #cl_type * #Heq_lookup normalize nodelta
1252whd in ⊢ ((??%%) → ?); [3: cases (typ_eq ??) #Htyp whd in ⊢ (??%% → ?); ] #Heq destruct (Heq)
1253whd in ⊢ ((??%?) → ?);
1254@(match lookup SymbolTag block cl_env id
1255  return λx. (lookup SymbolTag block cl_env id = x) → ?
1256  with
1257  [ None ⇒ ?
1258  | Some loc ⇒ ?
1259  ] (refl ? (lookup SymbolTag block cl_env id ))) normalize nodelta
1260#Hlookup_eq
1261[ 2,4: #Heq destruct (Heq) whd in match (eval_expr ???????);
1262  [ 2: %{(Vptr (mk_pointer stackptr (shift_offset (bitsize_of_intsize I16) zero_offset (repr I16 n))))}
1263       @conj try @refl
1264       lapply (matching id)
1265       >Hlookup_eq normalize nodelta
1266       >(opt_to_res_inversion ???? Heq_lookup) normalize nodelta
1267       #Hembed %4 whd in ⊢ (??%?); >Hembed @refl
1268  | 1: whd in match (eval_constant ????);
1269       lapply (matching id)
1270       >Hlookup_eq normalize nodelta 
1271       >(opt_to_res_inversion ???? Heq_lookup) normalize nodelta
1272       @False_ind
1273  ]
1274| 1,3: #Hfind_symbol
1275  cases (bind_inversion ????? Hfind_symbol) -Hfind_symbol #block *
1276  whd in ⊢ ((??%%) → ?); #Hfind_symbol
1277  lapply (opt_to_res_inversion ???? Hfind_symbol) #Hfind_symbol_eq
1278  whd in ⊢ ((??%%) → ?); #Heq destruct (Heq)
1279  whd in match (eval_expr ???????);
1280  whd in match (eval_constant ????);
1281  lapply (matching id)
1282  [ >Hlookup_eq normalize nodelta >Hfind_symbol_eq normalize nodelta
1283    #Hembed
1284    <(eq_sym … INV id) >Hfind_symbol_eq normalize nodelta
1285     %{(Vptr
1286         (mk_pointer cl_block
1287          (shift_offset (bitsize_of_intsize I16) zero_offset (repr I16 O))))}
1288     @conj try @refl
1289     %4 whd in ⊢ (??%?); >Hembed try @refl
1290  | (* A stack variable is not in the local environment but in the global one. *)
1291    (* we have a contradiction somewhere in the context *)
1292    lapply (variable_not_in_env_but_in_vartypes_is_global ???????
1293              cl_env_hyp alloc_hyp Hlookup_eq … Heq_lookup)
1294    *  #r #Habsurd destruct (Habsurd)
1295  ]
1296] qed.
1297
1298(* lift simulation result to eval_exprlist *)
1299
1300lemma eval_exprlist_simulation :
1301  ∀cl_f.
1302  ∀cl_ge : genv_t clight_fundef.
1303  ∀cm_ge : genv_t (fundef internal_function).
1304  ∀INV   : clight_cminor_inv cl_ge cm_ge.
1305  ∀alloc_type. 
1306  ∀cl_env, cl_m, cm_env, cm_m, stackptr.
1307  ∀Em.
1308  ∀stacksize     : ℕ. 
1309  ∀alloc_hyp     : characterise_vars (globals ?? INV) cl_f = 〈alloc_type, stacksize〉.
1310  ∀cl_env_hyp : ∃m,m'. exec_alloc_variables empty_env m (fn_params cl_f @ fn_vars cl_f) = 〈cl_env,m'〉.
1311  ∀injection     : memory_inj Em cl_m cm_m.
1312  ∀matching      : memory_matching Em cl_ge cm_ge cl_m cm_m cl_env cm_env INV stackptr alloc_type.
1313  ∀cl_exprs,cm_exprs.
1314  ∀cl_results,trace.
1315  exec_exprlist cl_ge cl_env cl_m cl_exprs = OK ? 〈cl_results, trace〉 →
1316  mmap_sigma ??? (translate_expr_sigma alloc_type) cl_exprs = OK ? cm_exprs →
1317  ∀H:All ? (λx:𝚺t:typ.expr t.
1318             match x with
1319             [ mk_DPair ty e ⇒
1320                    (expr_vars ty e
1321                     (λid:ident.λty:typ.present SymbolTag val cm_env id)) ]) cm_exprs.
1322  ∃cm_results.
1323  trace_map_inv … (λe. match e return λe.
1324                         match e with
1325                         [ mk_DPair _ _ ⇒ ? ] → ?
1326                       with
1327                       [ mk_DPair ty e ⇒ λp. eval_expr cm_ge ? e cm_env p stackptr cm_m ]) cm_exprs H = OK ? 〈trace, cm_results〉 ∧
1328  All2 ?? (λcl_val, cm_val. value_eq Em cl_val cm_val) cl_results cm_results.
1329#f #cl_ge #cm_ge #INV
1330#alloc_type #cl_env #cl_m #cm_env #cm_m #stackptr #Em #stacksize #alloc_hyp #cl_env_hyp #injection #matching
1331#cl_exprs
1332elim cl_exprs
1333[ #cm_exprs #cl_results #trace
1334  whd in ⊢ ((??%?) → ?);
1335  #Heq destruct (Heq)
1336  whd in ⊢ ((??%?) → ?);
1337  #Heq destruct (Heq) #H %{[]}
1338  @conj try @refl try @I
1339| #cl_hd #cl_tl #Hind #cm_exprs #cl_results #trace
1340  #Heq cases (bind_inversion ????? Heq) -Heq
1341  * #hd_val #hd_trace * #Hexec_expr_cl
1342  #Heq cases (bind_inversion ????? Heq) -Heq 
1343  * #cl_tl_vals #cl_tl_trace * #Hexec_expr_tl
1344  whd in ⊢ ((??%%) → ?); #Heq destruct (Heq)
1345  #Htranslate
1346  lapply (translate_exprlist_sigma_welltyped … Htranslate)
1347  #Htype_eq_all #Hall
1348  cases (bind_inversion ????? Htranslate) -Htranslate
1349  * * #cmtype #cmexpr normalize nodelta
1350  #Hexpr_vars_local_cm * #Htranslate_expr_sigma #Htranslate
1351  cases (bind_inversion ????? Htranslate) -Htranslate
1352  * #cm_tail #Hexpr_vars_local_cm_tail * #Htranslate_tail
1353  normalize nodelta
1354  whd in ⊢ ((??%%) → ?); #Heq destruct (Heq)
1355  cases Htype_eq_all -Htype_eq_all #Hcm_type_eq #Htype_eq_all
1356  lapply (Hind cm_tail cl_tl_vals cl_tl_trace Hexec_expr_tl)
1357  [ assumption ] -Hind #Hind
1358  lapply (Hind Htranslate_tail (proj2 ?? Hall)) -Hind
1359  * #cm_results_tl * #Hcm_exec_tl #Hvalues_eq_tl
1360  cases (eval_expr_sim cl_ge cm_ge INV f alloc_type stacksize alloc_hyp ?? cl_env_hyp ?? Em injection stackptr matching)
1361  #Hsim #_
1362  cases (bind_inversion ????? Htranslate_expr_sigma)
1363  * #cmexpr' #Hexpr_vars_local_cm' * #Htranslate
1364  whd in ⊢ ((??%%) → ?); #Heq destruct (Heq)
1365  lapply (Hsim cl_hd cmexpr ??????) -Hsim try assumption
1366  [ @(proj1 ?? Hall) ]
1367  * #cm_val_hd * #Heval_expr_cm #Hvalue_eq     
1368  %{(cm_val_hd :: cm_results_tl)} @conj
1369  [ 2: @conj try assumption
1370  | 1: whd in ⊢ (??%?); normalize nodelta >Heval_expr_cm
1371       normalize nodelta >Hcm_exec_tl @refl
1372  ]
1373] qed.
1374
1375(* --------------------------------------------------------------------------- *)
1376(* Putting the memory injection at work.                                       *)
1377(* --------------------------------------------------------------------------- *)
1378
1379(* A) Non-interference of local variables with memory injections  *)
1380
1381(* Needed property:
1382 * A local variable allocated via the temporary variable generator should not interfere
1383 * with the memory injection. In particular, we need to show that:
1384 * 1) we can successfuly store stuff of the right type inside (where the type is specified
1385 *    at generation time, and should be in the current context)
1386 * 2) after the store, we can build a consistent memory state and more generally, a
1387 *    correct [clight_cminor_data] invariant record. Cf. toCminorCorrectnessExpr.ma
1388 *)
1389 
1390(* A.1) memory matchings survives memory injection *)
1391
1392lemma offset_plus_0' : ∀o:offset. offset_plus zero_offset o = o.
1393#o cases o #b >offset_plus_0 @refl
1394qed.
1395
1396(*
1397lemma store_value_of_type_memory_matching_to_matching : 
1398  ∀cl_ge, cm_ge, cl_en, cm_en, INV, sp, vars, cl_m, cl_m',cm_m,cm_m'.
1399  ∀E: embedding.
1400  ∀blo, blo', delta, off.
1401  E blo = Some ? 〈blo', delta〉 →
1402  ∀cl_val, cm_val, ty.
1403  value_eq E cl_val cm_val →
1404  storen cl_m (mk_pointer blo off) (fe_to_be_values ty cl_val) = Some ? cl_m' →
1405  storen cm_m (mk_pointer blo (offset_plus off delta)) (fe_to_be_values ty cm_val) = Some ? cm_m' →
1406  (lookup' vars var_id = OK (var_type×type) 〈Global r,type_of_var〉)
1407  memory_inj E cl_m' cm_m' →
1408  memory_matching E cl_ge cm_ge cl_m cm_m cl_en cm_en INV sp vars →
1409  memory_matching E cl_ge cm_ge cl_m' cm_m' cl_en cm_en INV sp vars.
1410#cl_ge #cm_ge #cl_en #cm_en #INV #sp #vars #cl_m #cl_m' #cm_m #cm_m' #E
1411#blo #blo' #delta #off #Hembed #cl_val #cm_val #ty #Hvalue_eq #Hstoren_cl #Hstoren_cm
1412#Hinj #Hmatching #id
1413lapply (Hmatching id)
1414cases (lookup ?? cl_en id) normalize nodelta
1415[ 1: #H @H
1416| 2: #bl cases (lookup ?? vars id) normalize nodelta
1417  [ 1: #H @H
1418  | 2: * #var_type #cl_type normalize nodelta
1419       cases var_type normalize nodelta
1420       [ #r #H @H
1421       | #b #H @H
1422       | #H #v lapply H -H
1423         @(eq_block_elim … bl blo)
1424         [ #Heq destruct (Heq)
1425           @(eq_offset_elim … off zero_offset)
1426           [ (* We actually load exactly where we wrote, but with a potentially different type. *)
1427             #Heq destruct (Heq) #H
1428       ]
1429  ]
1430] qed.*)
1431
1432
1433lemma alloc_tmp_in_genlist :
1434  ∀vartypes. ∀g1, g2, g3.
1435  ∀id1, ty1, id2, ty2.
1436  alloc_tmp vartypes ty1 g1 = 〈id1, g2〉 →
1437  alloc_tmp vartypes ty2 g2 = 〈id2, g3〉 →
1438  Exists (identifier SymbolTag×type)
1439   (λx:identifier SymbolTag×type.x=〈id2,ty2〉) (tmp_env ? g3).
1440#vartypes #g1 #g2 #g3
1441#id1 #ty1 #id2 #ty2 #Halloc1 #Halloc2
1442lapply (breakup_dependent_match_on_pairs ?????? Halloc1) * #id1' * #u' * #Hfg1
1443* #Hfresh_eq generalize in match (fresh_map_add ????????); #ugly
1444generalize in ⊢ ((??(????(?????%))?) → ?); #ugly2
1445#Heq destruct (Heq)
1446lapply (breakup_dependent_match_on_pairs ?????? Halloc2) * #id2' * #u'' * #Hfg2
1447* #Hfresh_eq' generalize in match (fresh_map_add ????????); #ugly'
1448generalize in ⊢ ((??(????(?????%))?) → ?); #ugly2'
1449#Heq destruct (Heq) %1 @refl
1450qed. (* this last lemma has to be refitted. *)
1451
1452lemma store_value_of_type_success_by_value :
1453   ∀ty, m, m', b, o, v.
1454   store_value_of_type ty m b o v = Some ? m' →
1455   access_mode ty = By_value (typ_of_type ty) ∧
1456   storev (typ_of_type ty) m (Vptr (mk_pointer b o)) v = Some ? m'.   
1457#ty #m #m' #b #o #v
1458cases ty
1459[ | #sz #sg | #ptr_ty | #array_ty #array_sz | #domain #codomain
1460| #structname #fieldspec | #unionname #fieldspec | #id ]
1461whd in ⊢ ((??%?) → ?);
1462[ 1,4,5,6,7: #Habsurd destruct (Habsurd) ]
1463#H @conj try @refl @H
1464qed.
1465
1466(* Some boilerplate to avoid performing a case analysis on exprs in the middle of
1467 * the proof. *)
1468lemma translate_dest_not_Evar_id :
1469  ∀vars, ed, ty.
1470  (∀id. ed ≠ Evar id) →
1471    translate_dest vars (Expr ed ty) =
1472    (do e1' ← translate_addr vars (Expr ed ty);
1473     OK ? (MemDest … e1')).
1474#vars *
1475[ #sz #i | #id | #e1 | #e1 | #op #e1 |#op #e1 #e2 | #cast_ty #e1
1476| #cond #iftrue #iffalse | #e1 #e2 | #e1 #e2 | #sizeofty | #e1 #field | #cost #e1 ]
1477#ty #H
1478[ 2: @False_ind @(absurd … (refl ??) (H ?)) ]
1479@refl
1480qed.
1481
1482lemma expr_is_Evar_id_dec :
1483  ∀ed. (∀id. ed ≠ Evar id) ∨ (∃id. ed = Evar id).
1484
1485[ #sz #i | #id | #e1 | #e1 | #op #e1 |#op #e1 #e2 | #cast_ty #e1
1486| #cond #iftrue #iffalse | #e1 #e2 | #e1 #e2 | #sizeofty | #e1 #field | #cost #e1 ]
1487[ 2: %2 %{id} @refl
1488| *: %1 #id % #Habsurd destruct (Habsurd) ]
1489qed.
1490
1491lemma mk_offset_offv_id : ∀o. mk_offset (offv o) = o.
1492* #x @refl qed.
1493
1494lemma find_funct_to_find_funct_id :
1495   ∀F, ge, ptr, fundef.
1496   ∀H:find_funct ? ge ptr = Some ? fundef.
1497   find_funct_id F ge ptr = Some ? 〈fundef, symbol_of_function_val' F ge ptr fundef H〉.
1498#F #ge #ptr #fundef #Hfind whd in match (find_funct_id ???);
1499generalize in ⊢ (??(?%)?);
1500generalize in ⊢
1501 ((???%) → (??
1502    (match %
1503(*     return λ_. (??%?) → ?*)
1504     with
1505     [ _ ⇒ λ_. ?
1506     | _ ⇒ λ_.λ_. ? ] ?)
1507  ?));
1508#o cases o normalize nodelta
1509[ #H @False_ind >Hfind in H; #Habsurd destruct (Habsurd)
1510| #f #Hfind' 
1511  cut (f = fundef)
1512  [ >Hfind in Hfind'; #Heq destruct (Heq) @refl ]
1513  #Heq destruct (Heq)
1514  @refl
1515] qed.
1516
1517lemma eval_bool_of_val_to_Cminor :
1518  ∀E. ∀ty. ∀v1,v2. ∀b.
1519    value_eq E v1 v2 →
1520    exec_bool_of_val v1 ty = return b →
1521    eval_bool_of_val v2 = return  b.
1522#E #ty #v1 #v2 #b #Hvalue_eq
1523whd in ⊢ ((??%%) → (??%%));
1524@(value_eq_inversion … Hvalue_eq) normalize nodelta
1525[ #Habsurd destruct (Habsurd) ]
1526[ #vsz #vi cases ty
1527  [ | #sz #sg | #ptr_ty | #array_ty #array_sz | #domain #codomain
1528  | #structname #fieldspec | #unionname #fieldspec | #id ] normalize nodelta
1529  [ 2: | *: #Habsurd destruct (Habsurd) ]
1530  @(intsize_eq_elim_elim … vsz sz)
1531  [ 1: #H #Habsurd destruct (Habsurd)
1532  | 2: #Heq destruct (Heq) normalize nodelta #H @H ]
1533| cases ty
1534  [ | #sz #sg | #ptr_ty | #array_ty #array_sz | #domain #codomain
1535  | #structname #fieldspec | #unionname #fieldspec | #id ] normalize nodelta
1536  #H destruct (H) @refl
1537| #p1 #p2 #Htranslate
1538  cases ty
1539  [ | #sz #sg | #ptr_ty | #array_ty #array_sz | #domain #codomain
1540  | #structname #fieldspec | #unionname #fieldspec | #id ] normalize nodelta
1541  #H destruct (H) @refl
1542] qed.
1543
1544lemma let_prod_as_inversion :
1545    ∀A,B,C: Type[0].
1546    ∀expr: A × B.
1547    ∀body: ∀a:A. ∀b:B. 〈a,b〉 = expr → res C.
1548    ∀result: C.
1549    (let 〈a,b〉 as E ≝ expr in body a b E) = return result →
1550    ∃x,y. ∃E. 〈x,y〉 = expr ∧
1551          body x y E = return result.
1552#A #B #C * #a #b #body #res normalize nodelta #Heq
1553%{a} %{b} %{(refl ??)} @conj try @refl @Heq
1554qed.
1555
1556(* move this to frontend_misc *)
1557lemma lset_inclusion_Exists : ∀A, l1, l2, P.
1558  Exists A P l1 → lset_inclusion A l1 l2 → Exists A P l2.
1559#A #l1 #l2 #P #Hexists whd in ⊢ (% → ?);
1560lapply Hexists
1561generalize in match l2;
1562elim l1
1563[ #l2 @False_ind
1564| #hd #tl #Hind #l2 *
1565  [ 2: #HA * #Hhd #Htl @Hind try assumption
1566  | 1: #H * #Hmem #_ elim l2 in Hmem;
1567       [ @False_ind
1568       | #hd2 #tl2 #Hind *
1569         [ #Heq destruct (Heq) %1 @H
1570         | #Hneq %2 @Hind @Hneq ]
1571       ]
1572  ]
1573] qed.
1574
1575axiom load_value_after_free_list_inversion :
1576  ∀ty, m, blocks, b, o, v.
1577  load_value_of_type ty (free_list m blocks) b o = Some ? v → 
1578  load_value_of_type ty m b o = Some ? v.
1579
1580(* Make explicit the contents of [exec_bind_parameters ????] *) 
1581lemma exec_alloc_bind_params_same_length :
1582  ∀e,m,m',params,vars.
1583  exec_bind_parameters e m params vars = OK ? m' →
1584  (params = [ ] ∧ vars = [ ]) ∨
1585  ∃id,ty,tl_pa,v,tl_vars,b,mi.
1586   params = 〈id,ty〉 :: tl_pa ∧
1587   vars   = v :: tl_vars ∧
1588   lookup ?? e id = Some ? b ∧
1589   store_value_of_type ty m b zero_offset v = Some ? mi ∧
1590   exec_bind_parameters e mi tl_pa tl_vars = OK ? m'.
1591#e #m #m' #params cases params
1592[ #vars whd in ⊢ ((??%?) → ?); cases vars normalize nodelta
1593  [ #Heq destruct (Heq) %1 @conj try @refl
1594  | #hd_pa #tl_pa #Habsurd destruct (Habsurd) ]
1595| * #id #ty #tl_pa #vars
1596  whd in ⊢ ((??%?) → ?);
1597  cases vars normalize nodelta
1598  [ #Habsurd destruct (Habsurd)
1599  | #hd_val #tl_val #H
1600    cases (bind_inversion ????? H) -H
1601    #blo * #HA #H
1602    cases (bind_inversion ????? H) -H
1603    #m'' * #HB #Hexec_bind %2
1604    %{id} %{ty} %{tl_pa} %{hd_val} %{tl_val} %{blo} %{m''}   
1605    @conj try @conj try @conj try @conj try @refl
1606    try @(opt_to_res_inversion ???? HA)
1607    try @(opt_to_res_inversion ???? HB)
1608    @Hexec_bind
1609  ]
1610] qed.
1611
1612(* Axiom-fest, with all the lemmas we need but won't have time to prove. Most of them are not too hard. *)
1613
1614(* The way we have of stating this is certainly not the most synthetic. The property we really need is that
1615 * stmt_univ' is fresher than stmt_univ, which sould be trivially provable by a simple induction. *)
1616axiom env_below_freshgen_preserved_by_translation :
1617    ∀cl_env, alloc_type, stmt_univ, lbl_univ, lbls, flag, rettyp, s, stmt_univ', lbl_univ', cm_s, H.
1618    env_below_freshgen cl_env alloc_type stmt_univ →
1619    translate_statement alloc_type stmt_univ lbl_univ lbls flag rettyp s = return «〈stmt_univ', lbl_univ', cm_s〉, H» →
1620    env_below_freshgen cl_env alloc_type stmt_univ'.
1621
1622axiom tmp_vars_well_allocated_preserved_by_inclusion :
1623    ∀cm_env, cm_m, cl_m, Em, tmpenv, tmpenv'.
1624    lset_inclusion ? tmpenv tmpenv' →
1625    tmp_vars_well_allocated tmpenv' cm_env cm_m cl_m Em →
1626    tmp_vars_well_allocated tmpenv cm_env cm_m cl_m Em.
1627
1628axiom translation_entails_ident_inclusion :
1629    ∀alloc_type, stmt_univ, lbl_univ, lbls, flag, rettyp, stmt_univ'.
1630    ∀cl_s, cm_s, labgen, Htrans_inv.
1631    translate_statement alloc_type stmt_univ lbl_univ lbls flag rettyp cl_s = return «〈stmt_univ',labgen,cm_s〉,Htrans_inv» →
1632    lset_inclusion ? (tmp_env … stmt_univ) (tmp_env … stmt_univ').
1633
1634(* Same remarks as above apply here too. *)
1635(*
1636lemma tmp_vars_well_allocated_preserved_by_translation :
1637    ∀cm_env, alloc_type, stmt_univ, lbl_univ, lbls, flag, rettyp, stmt_univ'.
1638    ∀Em, cm_m, cl_m, cl_s, cm_s, labgen, Htrans_inv.
1639    translate_statement alloc_type stmt_univ lbl_univ lbls flag rettyp cl_s = return «〈stmt_univ',labgen,cm_s〉,Htrans_inv» →
1640    tmp_vars_well_allocated (tmp_env alloc_type stmt_univ') cm_env cm_m cl_m Em →
1641    tmp_vars_well_allocated (tmp_env alloc_type stmt_univ) cm_env cm_m cl_m Em.
1642#cm_env #alloc_type #stmt_univ #lbl_univ #lbls #flag #rettyp #stmt_univ' #Em #cm_m #cl_m #cl_s #cm_s
1643#labgen #Htrans_inv #Htranslate_statement #H #id #Hpresent #ty #Hexists
1644@H lapply (translation_entails_ident_inclusion … Htranslate_statement)
1645#H
1646@H23*)
1647
1648axiom tmp_vars_well_allocated_conserved_by_frame_free :
1649  ∀alloc_type, tmpenv, cl_env, cm_env, cm_m, cl_m, stackptr.
1650  ∀Em, cl_ge, cm_ge, INV.
1651  ∀Hmatching:memory_matching Em cl_ge cm_ge cl_m cm_m cl_env cm_env INV stackptr alloc_type.
1652  tmp_vars_well_allocated tmpenv cm_env cm_m cl_m Em ->
1653  tmp_vars_well_allocated tmpenv cm_env (free cm_m stackptr) (free_list cl_m (blocks_of_env cl_env)) Em.
1654
1655axiom generated_id_not_in_env :
1656    ∀id, blo, tmp, ty.
1657    ∀env: cl_env.
1658    ∀alloc_type.
1659    ∀freshgen, freshgen': tmpgen alloc_type.
1660    env_below_freshgen env alloc_type freshgen →
1661    lookup ?? env id = Some ? blo →
1662    alloc_tmp alloc_type ty freshgen = 〈tmp, freshgen'〉 →
1663    tmp ≠ id.
1664
1665(* This should just be lifting a lemma from positive maps to identifier maps.
1666 * Sadly, the way things are designed requires a boring induction. *)
1667axiom update_lookup_opt_other :
1668  ∀b,a,t,H.
1669  ∀b'. b ≠ b' →
1670  lookup SymbolTag val t  b' = lookup SymbolTag val (update_present SymbolTag val t b H a) b'.
1671 
1672 
1673(* NOTE: this axiom is way more general than what we need. In practice, cm_m' is cm_m after a store. *)
1674axiom clight_cminor_cont_rel_parametric_in_mem :
1675  ∀cl_ge, cm_ge, INV, cl_f, cm_f, cl_env, cm_env, cm_m, cm_m', alloc_type, tmpenv, (*stmt_univ, stmt_univ', *) rettyp, cl_k, cm_k, cm_st.
1676  clight_cminor_cont_rel cl_ge cm_ge INV cl_f cm_f cl_env cm_env cm_m alloc_type tmpenv (*stmt_univ stmt_univ'*) rettyp cl_k cm_k cm_st →
1677  clight_cminor_cont_rel cl_ge cm_ge INV cl_f cm_f cl_env cm_env cm_m' alloc_type tmpenv (*stmt_univ stmt_univ'*) rettyp cl_k cm_k cm_st.
1678
1679(* Same remark as above. *)
1680axiom well_allocated_preserved_by_parallel_stores :
1681  ∀tmpenv, cm_env, cm_m, cm_m', cl_m, cl_m', Em.
1682
1683(* TODO: proper hypotheses (the following, commented out do not exactly fit)
1684  (storen cm_m (mk_pointer cl_blo (mk_offset (offv zero_offset))) (fe_to_be_values (typ_of_type (typeof rhs)) cm_rhs_val)
1685   =Some mem cm_mem_after_store_lhs)
1686  storev (typ_of_type ty) cl_m (Vptr (mk_pointer cl_blo zero_offset)) cl_rhs_val = Some ? cl_m') *)
1687
1688  tmp_vars_well_allocated tmpenv cm_env cm_m  cl_m  Em →
1689  tmp_vars_well_allocated tmpenv cm_env cm_m' cl_m' Em.
1690
1691(* Same remark as above. Moreover, this should be provable from memory injections. *)
1692axiom memory_matching_preserved_by_parallel_stores :
1693  ∀Em, cl_ge, cm_ge, cl_m, cl_m', cm_m, cm_m', cl_env, cm_env, INV, stackptr, alloc_type.
1694  memory_matching Em cl_ge cm_ge cl_m  cm_m  cl_env cm_env INV stackptr alloc_type →
1695  memory_matching Em cl_ge cm_ge cl_m' cm_m' cl_env cm_env INV stackptr alloc_type.
1696 
1697axiom clight_cminor_cont_rel_parametric_in_cm_env :
1698∀cl_ge, cm_ge, INV, cl_f, cm_f, cl_env, cm_env, cm_m, alloc_type, tmpenv, (*stmt_univ, stmt_univ',*) rettyp, cl_k, cm_k, cm_st, var_id, v.
1699∀Hpresent:present SymbolTag val cm_env var_id.
1700clight_cminor_cont_rel cl_ge cm_ge INV cl_f cm_f cl_env cm_env cm_m alloc_type tmpenv (*stmt_univ stmt_univ'*) rettyp cl_k cm_k cm_st ->
1701clight_cminor_cont_rel cl_ge cm_ge INV cl_f cm_f cl_env
1702  (update_present SymbolTag val cm_env var_id Hpresent v) cm_m
1703  alloc_type tmpenv (*stmt_univ stmt_univ'*) rettyp cl_k cm_k cm_st.
1704
1705axiom tmp_vars_well_allocated_preserved_by_local_store :
1706  ∀Em, cl_value, cm_value, lhs_ty, cl_m, cl_m', cm_m, cl_blo, tmpenv, cm_env, var_id.
1707  ∀Hpresent:present SymbolTag val cm_env var_id.
1708  value_eq Em cl_value cm_value →
1709  store_value_of_type' lhs_ty cl_m 〈cl_blo, zero_offset〉 cl_value = Some ? cl_m' →
1710  tmp_vars_well_allocated tmpenv cm_env cm_m cl_m Em →
1711  tmp_vars_well_allocated tmpenv
1712  (update_present ?? cm_env var_id Hpresent cm_value) cm_m
1713   cl_m' Em.
1714
1715axiom memory_inj_preserved_by_local_store :
1716∀Em, cl_ge, cm_ge, cl_m, cl_m', cm_m, cl_env, cm_env, INV, stackptr, alloc_type.
1717 memory_matching Em cl_ge cm_ge cl_m cm_m cl_env cm_env INV stackptr alloc_type ->
1718 memory_inj Em cl_m cm_m ->
1719 memory_inj Em cl_m' cm_m.
1720
1721axiom memory_matching_preserved_by_local_store :
1722  ∀Em, cl_ge, cm_ge, cl_m, cl_m', cm_m, cl_env, cm_env, INV, stackptr, alloc_type, cl_value, cm_value.
1723  ∀cl_blo, var_id, lhs_ty.
1724  ∀Hpresent:present SymbolTag val cm_env var_id. 
1725   value_eq Em cl_value cm_value →
1726   store_value_of_type' lhs_ty cl_m 〈cl_blo, zero_offset〉 cl_value = Some ? cl_m' →
1727   memory_matching Em cl_ge cm_ge cl_m cm_m cl_env cm_env INV stackptr alloc_type →
1728   memory_matching Em cl_ge cm_ge cl_m' cm_m cl_env
1729    (update_present SymbolTag val cm_env var_id Hpresent cm_value) INV stackptr alloc_type.
1730
1731lemma alloc_tmp_monotonic :
1732  ∀alloc_type, ty, univ, univ', v.
1733   alloc_tmp alloc_type ty univ = 〈v, univ'〉 →
1734   lset_inclusion ? (tmp_env ? univ) (tmp_env ? univ').
1735#alloc_type #ty #univ #univ' #v cases univ
1736#u #env #Hfresh #Hyp #Halloc
1737cases (breakup_dependent_match_on_pairs ?????? Halloc) -Halloc
1738#v * #u' * #Heq * #Heq' normalize nodelta #Heq''
1739destruct (Heq'')
1740@cons_preserves_inclusion @reflexive_lset_inclusion
1741qed.
1742
1743(* TODO: move *)
1744lemma extract_pair' : ∀A,B,C.  ∀u:A×B. ∀Q:A → B → C. ∀x.
1745((let 〈a,b〉 ≝ u in Q a b) = x) →
1746∃a,b. 〈a,b〉 = u ∧ Q a b = x.
1747#A #B #C * #a #b #Q #x normalize #E1 %{a} %{b} % try @refl @E1 qed.
1748
1749lemma pair_as_elim:
1750  ∀A,B,C: Type[0].
1751  ∀p.
1752  ∀T: ∀a:A. ∀b:B. 〈a,b〉 = p → C.
1753  ∀P: A×B → C → Prop.
1754    (∀lft, rgt. ∀E:〈lft,rgt〉 = p. P 〈lft,rgt〉 (T lft rgt E)) →
1755      P p (let 〈lft, rgt〉 as E ≝ p in T lft rgt E).
1756#A #B #C * /2/
1757qed.
1758
1759(* TODO: move *)
1760lemma alloc_low_bound : ∀m,l,h,m',b.
1761  alloc m l h = 〈m',b〉 →
1762  low_bound m' b = l.
1763* #contents #next #next_ok #l #h #m' #b #E
1764whd in E:(??%%); destruct
1765whd in ⊢ (??%?); >update_block_s
1766%
1767qed.
1768
1769lemma alloc_high_bound : ∀m,l,h,m',b.
1770  alloc m l h = 〈m',b〉 →
1771  high_bound m' b = h.
1772* #contents #next #next_ok #l #h #m' #b #E
1773whd in E:(??%%); destruct
1774whd in ⊢ (??%?); >update_block_s
1775%
1776qed.
1777
1778(* Weaker version of Zlt_to_Zle *)
1779lemma Zlt_Zle : ∀x,y:Z. x < y → x ≤ y.
1780#x #y #H
1781@(transitive_Zle … (Zsucc_le x)) @Zlt_to_Zle @H
1782qed.
1783
1784axiom unZoo : ∀off:Z.
1785  off < Z_two_power_nat 16 →
1786  Zoo (offset_of_Z off) = off.
1787
1788lemma le_to_Zle : ∀x,y:nat. le x y → Zle x y.
1789#x #y #H @(le_ind ????? H)
1790[ //
1791| #m #H1 #H2 >Zsucc_pos @(transitive_Zle … (Zsucc_le m)) assumption
1792] qed.
1793
1794lemma lt_to_Zlt : ∀x,y:nat. lt x y → Zlt x y.
1795#x #y whd in ⊢ (% → ?); #H
1796<(Zpred_Zsucc x) @Zle_to_Zlt
1797<Zsucc_pos
1798@le_to_Zle assumption
1799qed.
1800
1801lemma Zlt_Zsucc : ∀z:Z. z < Zsucc z.
1802/2/
1803qed.
1804
1805lemma Zle_Zlt_Zsucc : ∀x,y:Z. x ≤ y → x < Zsucc y.
1806/2/
1807qed.
1808
1809theorem Zle_to_Zlt_to_Zlt: ∀n,m,p:Z. n ≤ m → m < p → n < p.
1810#n #m #p #Hle #Hlt lapply (Zlt_to_Zle … Hlt)
1811@Zlt_to_Zle_to_Zlt @Zle_Zlt_Zsucc assumption
1812qed.
1813
1814
1815(* This roughly corresponds to lemma 69 of Leroy and Blazy *)
1816(*
1817lemma alloc_vars_rel : ∀vartypes, cl_m, cm_m, stacksize, cm_m1, cm_frame.
1818∀Em. memory_inj Em cl_m cm_m →
1819Z_of_nat stacksize < Z_two_power_nat 16 →
1820alloc cm_m O (Z_of_nat stacksize) = 〈cm_m1,cm_frame〉 →
1821∀L, cl_env, cl_m1.
1822exec_alloc_variables empty_env cl_m L = 〈cl_env,cl_m1〉 →
1823(∀v,ty. Exists … (λx.x = 〈v,ty〉) L → ∃c. lookup' vartypes v = return 〈c,ty〉 ∧
1824  match c with
1825  [ Local ⇒ True
1826  | Stack off ⇒
1827    le O off ∧ le (sizeof ty + off) stacksize ∧
1828    (∀v',off',t'. v≠v' → lookup' vartypes v' = return 〈Stack off',t'〉 → le (off' + sizeof t') off ∨ le (off + sizeof ty) off')
1829  | Global _ ⇒ False
1830  ]) →
1831∃Em'. memory_inj Em' cl_m1 cm_m1 ∧
1832  embedding_compatible Em Em' ∧
1833  ∀v. Exists … (λx.\fst x = v) L →
1834  ∃b,c,t. lookup … cl_env v = Some ? b ∧
1835    lookup' vartypes v = return 〈c,t〉 ∧
1836    match c with
1837    [ Local ⇒ Em' b = None ?
1838    | Stack off ⇒ Em' b = Some ? 〈cm_frame, offset_of_Z (Z_of_nat off)〉
1839    | Global _ ⇒ False
1840    ].
1841#vartypes #cl_m #cm_m #stacksize #cm_m1 #cm_frame #Em #Inj #stack_ok #cm_alloc #L
1842cut (block_implementable_bv cm_m1 cm_frame)
1843[ whd >(alloc_low_bound … cm_alloc) >(alloc_high_bound … cm_alloc) % % //
1844  cases stacksize // ] #cm_bi
1845lapply (alloc_memory_inj_m2 … Inj cm_alloc cm_bi)
1846lapply (alloc_valid_new_block … cm_alloc) #cm_frame_valid
1847cut (∀b:block. ∀delta':offset.
1848    Em b=Some (block×offset) 〈cm_frame,delta'〉 →
1849    ∀v,off,ty. lookup' vartypes v = OK ? 〈Stack off, ty〉 →
1850    high_bound cl_m b+Zoo delta'≤O+Zoo (offset_of_Z off)
1851      ∨ sizeof ty+Zoo (offset_of_Z off)≤low_bound cl_m b+Zoo delta')
1852[ #b #delta' #E @⊥ lapply (mi_nodangling … Inj … E) #V
1853  @(absurd … V) @(new_block_invalid_before_alloc … cm_alloc) ]
1854
1855generalize in match Em; -Em generalize in match empty_env; elim L
1856[ #cl_env #Em #_ #Inj #cl_env' #cl_m1 #cl_alloc
1857  whd in cl_alloc:(??%%); destruct #H
1858  %{Em} % [ % [ @Inj | // ] | #v * ]
1859| * #v #ty #tl #IH
1860  #cl_env #Em #Hexisting #Inj #cl_env' #cl_m1
1861  whd in ⊢ (??%? → ?); @pair_elim #cl_m2 #cl_b #cl_alloc #cl_alloc' #H
1862  cases (H v ty ?) [2: %1 % ] *
1863  [ #r * #L *
1864  | #off * #L * * #off_low #off_high #other
1865    lapply (alloc_memory_inj_m1_to_m2 … (offset_of_Z off) cm_frame_valid … cm_bi … cl_alloc … Inj)
1866    [ #b #delta' #NE #E @(Hexisting … E … L)
1867    | cases (alloc_properties … cm_alloc) #_ #U #i #LOW #HIGH @U
1868      [ /2/
1869      | @(transitive_Zle … HIGH) >unZoo
1870        [ <eq_plus_Zplus /2/
1871        | @(Zlt_to_Zle_to_Zlt ? (sizeof ty + off))
1872          [ <eq_plus_Zplus @lt_to_Zlt whd in ⊢ (??%); /2/
1873          | @(transitive_Zlt … stacksize) [ <eq_plus_Zplus @(lt_to_Zlt … off_high) | // ]
1874          ]
1875        ]
1876      ]
1877    | >unZoo
1878        [ <eq_plus_Zplus >(alloc_high_bound … cm_alloc)
1879*)
1880(*
1881lemma lset_inclusion_Exists :
1882  ∀A. ∀l1, l2: lset A.
1883  lset_inclusion ? l1 l2 →
1884  ∀P. Exists ? P l1 → Exists ? P l2.
1885#A #l1 elim l1
1886[ #l2 #Hincl #P @False_ind
1887| #hd #tl #Hind #l2 * #Hmem #Hincl2 #P *
1888  [ 2: #Htl @Hind assumption ]
1889  lapply P -P
1890  lapply Hincl2 -Hincl2
1891  lapply Hmem -Hmem elim l2
1892  [ @False_ind ]
1893  #hd2 #tl2 #Hind2 *
1894  [ #Heq destruct (Heq)
1895    #Hincl2 #P #H %1 @H
1896  | #Hmem #Hincl2 #P #H %2
1897    elim tl2 in Hmem;
1898    [ @False_ind
1899    | #hd2' #tl2' #Hind3 *
1900      [ #Heq destruct (Heq) %1 assumption
1901      | #Hmem' %2 @Hind3 @Hmem' ]
1902    ]
1903  ]
1904] qed.  *)
1905
1906(* --------------------------------------------------------------------------- *)
1907(* Main simulation results                                                     *)
1908(* --------------------------------------------------------------------------- *)
1909
1910(* Conjectured simulation results
1911
1912   We split these based on the start state:
1913   
1914   1. ‘normal’ states take some [S n] normal steps and simulates them by [S m]
1915      normal steps in Cminor;
1916   2. call and return steps are simulated by a call/return step plus [m] normal
1917      steps (to copy stack allocated parameters / results); and
1918   3. lone cost label steps are simulated by a lone cost label step
1919   
1920   These should allow us to maintain enough structure to identify the Cminor
1921   subtrace corresponding to a measurable Clight subtrace.
1922 *)
1923(* WIP
1924include "common/ExtraMonads.ma".
1925
1926lemma clight_cminor_call :
1927    ∀g,g'.
1928    ∀INV:clight_cminor_inv g g'.
1929    ∀s1,s1'.
1930    clight_cminor_rel g g' INV s1 s1' →
1931    Clight_classify s1 = cl_call →
1932    ∀s2,tr2,s3,tr3.
1933    step … (pcs_exec cl_pre) g s1 = Value … 〈tr2,s2〉 →   
1934    step … (pcs_exec cl_pre) g s2 = Value … 〈tr3,s3〉 →   
1935    Clight_labelled s2 →
1936    after_n_steps 1 ?? (pcs_exec cm_pre) g' s1' (λs.cminor_normal s) (λtr2',s2'.
1937      tr2 = tr2' ∧
1938      bool_to_Prop (Cminor_labelled s2') ∧
1939      ∃m.
1940      after_n_steps m ?? (pcs_exec cm_pre) g' s2' (λs.cminor_normal s) (λtr3',s3'.
1941        tr3 = tr3' ∧
1942        clight_cminor_rel g g' INV s2 s2')
1943    ).
1944#Xg #Xg' #XINV #Xs1 #Xs1' *
1945[ #g #g' #INV #cl_s #cm_s #cl_k #cm_k #cm_st #cl_f #cm_f #rettyp #alloc_type #cl_env #cl_m #cm_env #cm_m #stackptr #stacksize #fInv #sInv #kInv #Erettyp #func_univ #Hfresh_globals #Hfresh_function #Htranslate_fn #stmt_univ #stmt_univ' #lbl_univ #lbl_univ' #lbls #flag #Htranslate_inv #Htranslate_s #Hlbls_inc #tmpenv #Htmpenv #CONT #Em #HtmpEm #CHAR #ALLOC #INJ #MATCH #HEm_fn #HEm_env #Henv_below
1946  #CL whd in CL:(??%?); destruct
1947| #g #g' #INV #cl_k #cm_k #cm_st #cl_f #cm_f #alloc_type #cl_env #cl_m #cm_env #cm_m #stackptr #stacksize #stmt_univ #tmpenv #Htmpenv #Em #HEm_tmp #CHAR #ALLOC #INJ #MATCH #HEm_fn #HEm_env #CONT
1948  #CL whd in CL:(??%?); destruct
1949| #g #g' #INV #cl_k #cm_st #cl_fd #cm_fd #fblock #target_type #cl_env #cl_m #cm_env #cm_m #fid #Hfind_cl #Hfind_cm #tmpenv #CONT #Em #INJ #HEm_fn #cl_args #cm_args #Hargs
1950  #CL #s2 #tr2 #s3 #tr3 #STEP1 #STEP2 #CS2
1951 
1952  (* Note that cm_fd is the translation of cl_fd *)
1953  cases (trans_fn … INV … Hfind_cl)
1954  #func_univ * #cm_fd' * #Hglobals_fresh * #Hfundef_fresh * #Htranslate
1955  >Hfind_cm #E destruct
1956 
1957  (* Must be a CL_Internal function *)
1958  cases cl_fd in Hfundef_fresh Htranslate Hfind_cl CONT STEP1;
1959  [ #cl_f
1960  | #ext #ext_argtys #ext_retty
1961  ]
1962  #Hfundef_fresh #Htranslate #Hfind_cl #CONT #STEP1
1963  [2: cases (bindIO_inversion ??????? STEP1) -STEP1 #vs * #_ #STEP1
1964      whd in STEP1:(??%%); destruct ]
1965  -cl_fd
1966  (* and the Cminor one must be Internal *)
1967  @('bind_inversion Htranslate) #cm_f #Htranslate' #E
1968  whd in E:(??%%); destruct
1969
1970  (* Invert function translation *)
1971  (* NB: if you want to examine the proof state in here, you probably want to
1972     turn off the pretty printer - it doesn't cope well with a large proof
1973     term. *)
1974  @('bind_inversion Htranslate') * * #lbls #Ilbls #ul #Hbuild_label_env
1975  whd in ⊢ (??%? → ?);
1976  @pair_as_elim #vartypes #stacksize #Hcharacterise
1977  letin uv ≝ (mk_tmpgen ?? [ ] ??) #H
1978  @('bind_inversion H) -H #s0 #Htranslate_statement #H
1979  @('bind_inversion H) -H * * #fgens #s1 #Is #Halloc_params
1980  letin cm_params ≝ (map ??? (fn_params cl_f))
1981  whd in ⊢ (??%? → ?);
1982  letin cm_vars ≝ (map ??? (?@fn_vars cl_f)) #H
1983  @('bind_inversion H) -H #D #Hcheck_distinct_env
1984  whd in ⊢ (??%% → ?); generalize in ⊢ (??(??(???????%))? → ?);
1985  (* It's safe to use the pretty printer again. *)
1986  #cm_Sinv #H destruct
1987
1988  (* Invert Clight STEP1 *) 
1989  cases (extract_pair' ?????? STEP1) -STEP1 #cl_env * #cl_m1 * #ALLOC #STEP1
1990  cases (bindIO_inversion ??????? STEP1) -STEP1 #cl_m2 * #BIND #STEP1
1991  whd in STEP1:(??%%); destruct
1992
1993  whd whd in ⊢ (??%?);
1994  @pair_elim #cm_m1 #cm_frame #CM_ALLOC
1995
1996 (〈vartypes,stacksize〉=characterise_vars (globals g g' INV) cl_f)
1997We need to build an extended memory injection to reflect the new allocations;
1998then the bind functions put the correct local variables in;
1999then after execution the appropriate number of Cminor steps the stored values
2000match.
2001
2002Oh, and there are the locals too.
2003
2004
2005alloc_memory_inj_m2 shows that embedding is fine after the Cminor alloc
2006
2007∀Em. memory_inj Em cl_m cm_m →
2008(∀b. block_region b = Code → Em' b = Some ? 〈b,zero_offset〉) →
2009exec_alloc_variables empty_env cl_m (fn_params cl_f@fn_vars cl_f) = 〈cl_env,cl_m1〉 →
2010alloc cm_m O (f_stacksize cm_f) = 〈cm_m1,cm_frame〉 →
2011∃Em'.
2012  memory_inj Em' cl_m1 cm_m1 ∧
2013  (∀b. block_region b = Code → Em' b = Some ? 〈b,zero_offset〉) ∧
2014  (∀v,v'. value_eq Em v v' → value_eq Em' v v') ∧
2015  (∀b1.∀delta. Em' b1=Some ? 〈cm_frame,delta〉 →
2016             mem block b1 (blocks_of_env cl_env)).
2017             
2018  ∀b. Em b = Em' b ∨ (Em b = None ? ∧ ∃off. Em' b = Some ? 〈cm_frame,off〉).
2019
2020
2021translate_function func_univ (globals … INV) cl_f H1 H2 = return cm_f →
2022All2 … (λcl,cm.value_eq Em cl cm) cl_args cm_args →
2023exec_bind_parameters cl_env cl_m1 (fn_params cl_f) cl_args = return cl_m2 →
2024∃cm_en,Hcm_args_present.
2025  bind_params cm_args (f_params cm_f) = return «cm_en, Hcm_args_present» ∧
2026 
2027
2028*)
2029
2030(*
2031lemma clight_cminor_call_return :
2032  ∀g1, g2.
2033  ∀INV:clight_cminor_inv g1 g2.
2034  ∀s1,s1'.
2035  clight_cminor_rel g1 g2 INV s1 s1' →
2036  match Clight_classify s1 with
2037  [ cl_call ⇒ true
2038  | cl_return ⇒ true
2039  | _ ⇒ false ] →
2040  ∀s2,tr. step … (pcs_exec cl_pre) g1 s1 = Value … 〈tr, s2〉 →
2041  ∃m. after_n_steps m ?? (pcs_exec cm_pre) g2 s1' (λs.cminor_normal s) (λtr',s2'.
2042    tr = tr' ∧
2043    clight_cminor_rel g1 g2 INV s2 s2' ∧
2044      (m = 0 → lex_lt (measure_Clight s2) (measure_Clight s1))
2045  ).
2046#g1 #g2 #INV #s1 #s1' #Hstate_rel #Hclight_class
2047inversion Hstate_rel
2048[ 1: (* normal *)
2049  #cl_ge #cm_ge #INV' #cl_s
2050  #cm_s #cl_k #cm_k #cm_st #cl_f #cm_f #rettyp
2051  #alloc_type #cl_env #cl_m #cm_env #cm_m #stackptr #stacksize
2052  (* introduce everything *)
2053  #fInv #sInv #kInv #Htarget_type #func_univ #Hfresh_globals #Hfresh_function #Htranslate_function
2054  #stmt_univ #stmt_univ' #lbl_univ #lbl_univ' #lbls
2055  #flag  #Htrans_inv #Htrans_stmt #Hincl #HA #HB #HC
2056  #HE #HF #HG #HI #HJ #HK
2057  @(jmeq_absorb ?????) #H1 @(jmeq_absorb ?????) #H2
2058  destruct (H1 H2)
2059  @(jmeq_absorb ?????) #H3 @(jmeq_absorb ?????) #H4 @(jmeq_absorb ?????) #H5
2060  destruct (H3 H4 H5)
2061  @False_ind @Hclight_class
2062| 5:
2063  #cl_ge #cm_ge #INV' #cl_s
2064  #cm_s #cl_k #cm_k #cm_st #cl_f #cm_f #rettyp
2065  #alloc_type #cl_k #cm_k #sz #sg #cl_ty #cl_cond_desc #cl_body #entry_lab #exit_lab
2066  #cm_cond #cm_body #cm_stack #rettyp' #kInv
2067  (* introduce everything *)
2068  #fInv #sInv #kInv #Htarget_type #func_univ #Hfresh_globals #Hfresh_function #Htranslate_function
2069  #stmt_univ #stmt_univ' #lbl_univ #lbl_univ' #lbls
2070  #lbl1 #lbl2 #Em #Htmp_vars #Hcharac #Hexec #Hinj #Hmatching #Hem #Hframe #Hcond_tr
2071  #Htransl #Hex1 #Hex2 #Htransinv #Hmklabs #Htranstmt #Hincl
2072  #Hlabdecl #Hinv1 #Hinv2 #Hfindlab
2073  @(jmeq_absorb ?????) #H1 @(jmeq_absorb ?????) #H2
2074  destruct (H1 H2)
2075  @(jmeq_absorb ?????) #H3 @(jmeq_absorb ?????) #H4 @(jmeq_absorb ?????) #H5
2076  destruct (H3 H4 H5)
2077  @False_ind @Hclight_class
2078| 2:
2079  #cl_ge #cm_ge #INV' #cl_f #cm_f #cl_k #cm_k #alloc_type
2080  #cl_env #cl_m #cm_env #cm_m #cm_st #stackptr #stacksize
2081  #stmt_univ #Em #Htmp_vars_well_allocated #Halloc_hyp #Hcl_env_hyp
2082  #Hinjection #Hmatching #HEm_fn_id #Hframe_spec #Hcont_rel
2083  @(jmeq_absorb ?????) #HA @(jmeq_absorb ?????) #HB
2084  destruct (HA HB)
2085  @(jmeq_absorb ?????) #HC @(jmeq_absorb ?????) #HD @(jmeq_absorb ?????) #HE #_
2086  destruct (HC HD HE)
2087  inversion Hcont_rel
2088  [ #kcl_ge #kcm_ge #kINV #kcl_f #kcm_f #ktarget_type #kcl_env #kcm_env #kalloc_type #kstack #Hkstack
2089    @(jmeq_absorb ?????) #HA @(jmeq_absorb ?????) #HB
2090    destruct (HA HB)
2091    @(jmeq_absorb ?????) #HC @(jmeq_absorb ?????) #HD @(jmeq_absorb ?????) #HE
2092    destruct (HC HD HE)
2093    @(jmeq_absorb ?????) #HF @(jmeq_absorb ?????) #HG @(jmeq_absorb ?????) #HH
2094    @(jmeq_absorb ?????) #HI @(jmeq_absorb ?????) #HJ @(jmeq_absorb ?????) #HK @(jmeq_absorb ?????) #HL
2095    destruct (HF HG HH HI HJ HK HL) #_
2096    #s2 #tr
2097    whd in ⊢ ((??%?) → ?); #Habsurd destruct (Habsurd)
2098  | (* Kseq *)
2099    #kcl_ge #kcm_ge #kINV #kcl_f #kcm_f #ktarget_type #kstack #kalloc_type #kcl_s #kcm_s
2100    #kcl_env #kcm_env #kcl_k' #kcm_k' #kstmt_univ #kstmt_univ' #klbl_univ #klbl_univ' #klbls #kflag
2101    * * * * #kHstmt_inv #kHlabels_translated #kHtmps_preserved
2102    #kHreturn_ok #kHlabel_wf #kHeq_translate #kHlabel_inclusion #kHcont_rel #_
2103    @(jmeq_absorb ?????) #HA @(jmeq_absorb ?????) #HB
2104    destruct (HA HB)
2105    @(jmeq_absorb ?????) #HC @(jmeq_absorb ?????) #HD @(jmeq_absorb ?????) #HE
2106    destruct (HC HD HE)
2107    @(jmeq_absorb ?????) #HF @(jmeq_absorb ?????) #HG @(jmeq_absorb ?????) #HH @(jmeq_absorb ?????) #HI
2108    @(jmeq_absorb ?????) #HJ @(jmeq_absorb ?????) #HK @(jmeq_absorb ?????) #HL
2109    destruct (HF HG HH HI HJ HK HL) #_
2110    #s2 #tr
2111    whd in ⊢ ((??%?) → ?); #Habsurd destruct (Habsurd)
2112  | (* *)
2113    #kcl_ge #kcm_ge #kINV #kcl_f #kcm_f #ktarget_type #kstack #kalloc_type #kcl_env #kcm_env
2114    #kcl_k' #kcm_k' #ksz #ksg #kcl_ty #kcl_cond_desc #kcl_body #kHeq_ty #kcm_cond #kcm_body
2115    #kentry #kexit #kstmt_univ #kstmt_univ' #klbl_univ #klbl_univ' #klbl_univ''
2116    #klbls #kHtranslate_inv #kHexpr_vars #kHtranslate_expr #kfInv #kHlabel_declared
2117    #kHinv #kHmklabels #kHeq_translate #kHlabel_inclusion #kHfind_label
2118    (*     
2119    * * * * #kHentry_declared * * * *
2120    * * * #kHcond_vars_declared #Hnoise #Hnoise' #Hnoise''
2121    #kHcont_inv #kHmklabels #kHeq_translate
2122    #kHfind_label *) #kHcont_rel #_
2123    @(jmeq_absorb ?????) #HA @(jmeq_absorb ?????) #HB
2124    destruct (HA HB)
2125    @(jmeq_absorb ?????) #HC @(jmeq_absorb ?????) #HD @(jmeq_absorb ?????) #HE
2126    destruct (HC HD HE)
2127    @(jmeq_absorb ?????) #HF @(jmeq_absorb ?????) #HG @(jmeq_absorb ?????) #HH
2128    @(jmeq_absorb ?????) #HI @(jmeq_absorb ?????) #HJ @(jmeq_absorb ?????) #HK
2129    @(jmeq_absorb ?????) #HL
2130    destruct (HF HG HH HI HJ HK HL) #_
2131    #s2 #tr
2132    whd in ⊢ ((??%?) → ?); #Habsurd destruct (Habsurd)
2133  ]   
2134| 3:
2135  #cl_ge #cm_ge #INV' #alloc_type
2136  #cl_env #cl_m #cm_env #cm_m #cm_st #stackptr #func_univ
2137  #cl_f #cm_f #Hglobals_fresh #Hfundef_fresh
2138  #rettyp #cl_k #cm_k #fblock *
2139  #Hrettyp #Hfind_funct_cl #Hfind_func_cm #Htranslate_function #Hcont_rel
2140  #fun_id #cl_retval #cm_retval #sInv #fInv #kInv #cl_args #cm_args
2141  @(jmeq_absorb ?????) #HA @(jmeq_absorb ?????) #HB
2142  destruct (HA HB)
2143  @(jmeq_absorb ?????) #HC @(jmeq_absorb ?????) #HD @(jmeq_absorb ?????) #HE
2144  destruct (HC HD HE) #_
2145  #s2 #tr whd in ⊢ ((??%?) → ?);
2146  @(match (exec_alloc_variables empty_env cl_m (fn_params cl_f@fn_vars cl_f))
2147    return λx. (x = (exec_alloc_variables empty_env cl_m (fn_params cl_f@fn_vars cl_f))) → ?
2148    with
2149    [ mk_Prod new_cl_env cl_m_alloc ⇒ ?
2150    ] (refl ? (exec_alloc_variables empty_env cl_m (fn_params cl_f@fn_vars cl_f))))
2151  #Hexec_alloc_variables normalize nodelta
2152  #Hstep
2153  cases (bindIO_inversion ??????? Hstep) -Hstep
2154  #cl_m_init * #Hexec_bind_parameters
2155  whd in ⊢ ((??%%) → ?); #Heq destruct (Heq) 
2156  %{1} whd whd in ⊢ (??%?);
2157  (* Alloc big chunk of data of size (f_stacksize cm_f) *)
2158  @(match (alloc cm_m 0 (f_stacksize cm_f))
2159    return λx. (alloc cm_m 0 (f_stacksize cm_f) = x) → ?
2160    with
2161    [ mk_Prod new_cm_mem new_cm_stackptr ⇒ ?
2162    ] (refl ? (alloc cm_m 0 (f_stacksize cm_f))))
2163  #H_cm_alloc normalize nodelta
2164  (* Initialise CM /parameters/ *)
2165
2166 
2167  %{(S (times 3 (|fn_vars|)))} -Hclight_class
2168  lapply (exec_alloc_bind_params_same_length … Hexec_bind_parameters)
2169  elim cl_args in Hstate_rel Hexec_alloc;
2170  [ #Hstate_rel whd in ⊢ ((??%%) → ?);
2171
2172    whd in match (exec_bind_parameters ????);
2173
2174  exec_alloc_variables empty_env cl_m (fn_params cl_f@fn_vars cl_f) = 〈cl_env, cl_m'〉
2175   
2176 
2177  lapply (let_prod_as_inversion ?????? Hstep)
2178    @(jmeq_absorb ?????) #HF @(jmeq_absorb ?????) #HG @(jmeq_absorb ?????) #HH
2179    @(jmeq_absorb ?????) #HI @(jmeq_absorb ?????) #HJ @(jmeq_absorb ?????) #HK
2180    @(jmeq_absorb ?????) #HL
2181    destruct (HF HG HH HI HJ HK HL) #_
2182    #s2 #tr
2183 
2184 
2185  #Em #Htmp_vars_well_allocated #Halloc_hyp #Hcl_env_hyp
2186  #Hinjection #Hmatching #HEm_fn_id #Hframe_spec #Hcont_rel
2187] qed.  *)
2188
2189lemma clight_cminor_normal :
2190    ∀g1,g2.
2191    ∀INV:clight_cminor_inv g1 g2.
2192    ∀s1,s1'.
2193    clight_cminor_rel g1 g2 INV s1 s1' →
2194    clight_normal s1 →
2195    ¬ pcs_labelled cl_pre g1 s1 →
2196    ∀s2,tr. step … (pcs_exec cl_pre) g1 s1 = Value … 〈tr,s2〉 →   
2197    ∃m. after_n_steps m ?? (pcs_exec cm_pre) g2 s1' (λs.cminor_normal s) (λtr',s2'.
2198      tr = tr' ∧
2199      clight_cminor_rel g1 g2 INV s2 s2' ∧
2200      (m = 0 → lex_lt (measure_Clight s2) (measure_Clight s1))
2201    ).
2202#Xg1 #Xg2 #XINV #Xs1 #Xs1' *
2203[ 1: (* Normal state *)
2204     (* ---------------------------------------------------------------------- *)
2205#cl_ge #cm_ge #INV' #cl_s
2206(* case analysis on Clight statement *)
2207cases cl_s
2208[ 1: | 2: #lhs #rhs | 3: #retv #func #args | 4: #stm1 #stm2 | 5: #cond #iftrue #iffalse | 6: #cond #body
2209| 7: #cond #body | 8: #init #cond #step #body | 9,10: | 11: #retval | 12: #cond #switchcases | 13: #lab #body
2210| 14: #lab | 15: #cost #body ]
2211(*
2212[ 11: (* Return case *)
2213     #cm_s #cl_k #cm_k #cm_st #cl_f #cm_f #rettyp
2214     #alloc_type #cl_env #cl_m #cm_env #cm_m #stackptr #stacksize
2215     (* introduce everything *)
2216     #fInv #sInv #kInv #Htarget_type #func_univ #Hfresh_globals #Hfresh_function #Htranslate_function
2217     #stmt_univ #stmt_univ' #lbl_univ #lbl_univ' #lbls
2218     #flag #Htrans_inv #Htranslate #Hlabel_inclusion #Hcont_rel
2219     #Em #Htmp_vars_well_allocated #Halloc_hyp #Hcl_env_hyp #Hinjection #Hmatching #HEm_fn_id
2220     @(jmeq_absorb ?????) #HA @(jmeq_absorb ?????) #HB
2221     destruct (HA HB)
2222     @(jmeq_absorb ?????) #HC @(jmeq_absorb ?????) #HD @(jmeq_absorb ?????) #HE #_
2223     destruct (HC HD HE)
2224     whd in Htranslate:(??%?);
2225     cases retval in Htranslate; normalize nodelta
2226     [ cases rettyp in Htrans_inv Hcont_rel;
2227       [ 2: #opttyp normalize nodelta #Htrans_inv #_
2228            #Habsurd destruct (Habsurd)
2229       | 1: #Htrans_inv #Hcont_rel normalize nodelta #Heq destruct (Heq)
2230            #s2 #tr whd in ⊢ ((??%?) → ?);
2231            cases (fn_return cl_f)
2232            [ | #sz #sg | #ptr_ty | #array_ty #array_sz | #domain #codomain
2233            | #structname #fieldspec | #unionname #fieldspec | #id ]
2234            normalize nodelta
2235            [ 1:
2236            | *: #Habsurd destruct (Habsurd) ]
2237            whd in ⊢ ((??%?) → ?);
2238            #Heq destruct (Heq)
2239            %{1} whd @conj try @conj
2240            [ 3: #Habsurd destruct (Habsurd)
2241            | 1: @refl ]
2242            @CMR_return
2243*)     
2244[ 6: (* While *)
2245     #cm_s #cl_k #cm_k #cm_st #cl_f #cm_f #rettyp
2246     #alloc_type #cl_env #cl_m #cm_env #cm_m #stackptr #stacksize
2247     (* introduce everything *)
2248     #fInv #sInv #kInv #Htarget_type #func_univ #Hfresh_globals #Hfresh_function #Htranslate_function
2249     #stmt_univ #stmt_univ' #lbl_univ #lbl_univ' #lbls
2250     #flag * * * * #Hstmt_inv_cm cases cond #cond_desc #cond_ty
2251     (* early case analysis to avoid dependency hell *)
2252     cases cond_ty
2253     [ | #sz #sg | #ptr_ty | #array_ty #array_sz | #domain #codomain
2254     | #structname #fieldspec | #unionname #fieldspec | #id ]     
2255     #Hlabels_translated #Htmps_preserved
2256     #Hreturn_ok #Hlabel_wf #Htranslate #Hlabel_inclusion #tmpenv #Htmpenv
2257     #Hcont_rel
2258     #Em #Htmp_vars_well_allocated
2259     #Halloc_hyp #Hcl_env_hyp #Hinjection #Hmatching #HEm_fn_id
2260     #Hframe_spec #Henv_below #Hclight_normal #Hnot_labeleld
2261     lapply Htranslate -Htranslate
2262     [ 1: generalize in match (conj ????); #Hugly_inv
2263     | 2: generalize in match (conj ????); #Hugly_inv
2264     | 3: generalize in match (conj ????); #Hugly_inv
2265     | 4: generalize in match (conj ????); #Hugly_inv
2266     | 5: generalize in match (conj ????); #Hugly_inv
2267     | 6: generalize in match (conj ????); #Hugly_inv
2268     | 7: generalize in match (conj ????); #Hugly_inv
2269     | 8: generalize in match (conj ????); #Hugly_inv ]
2270     #Htranslate
2271     cases (bind_inversion ????? Htranslate) -Htranslate
2272     whd in match (typeof ?); whd in match (typ_of_type ?); *
2273     #cm_cond #Hexpr_vars_cond * #Htranslate_cond normalize nodelta
2274     [ 3,4,5,8: whd in ⊢ ((??%%) → ?); #Habsurd destruct (Habsurd) ]
2275     #Htranslate normalize nodelta
2276     lapply (let_prod_as_inversion ?????? Htranslate) -Htranslate
2277     * * #entry_label #exit_label * #lbl_univ0 * #Hmk_label_eq *
2278     #Hmk_label_eq_bis normalize nodelta #Htranslate
2279     cases (bind_inversion ????? Htranslate) -Htranslate
2280     * * * #stmt_univ0 #lbl_univ1 #cm_body
2281     #Htrans_inv * #Htrans_body normalize nodelta
2282     [ generalize in ⊢ ((??(??(????%))?) → ?);
2283       #Htrans_inv'
2284     | generalize in ⊢ ((??(??(????%))?) → ?);
2285       #Htrans_inv'
2286     | generalize in ⊢ ((??(??(????%))?) → ?);
2287       #Htrans_inv'
2288     | generalize in ⊢ ((??(??(????%))?) → ?);
2289       #Htrans_inv' ]
2290     whd in ⊢ ((???%) → ?);
2291     #Heq destruct (Heq)
2292     #s2 #tr whd in ⊢ ((??%?) → ?);
2293     #Hstep
2294     cases (bindIO_inversion ??????? Hstep) -Hstep * #cond_val #cond_trace
2295     * #Hcl_exec_cond #Hstep
2296     cases (bindIO_inversion ??????? Hstep) -Hstep
2297     #cl_cond_bool * #Hcl_bool_of_val whd in ⊢ ((??%%) → ?);
2298     cases cl_cond_bool in Hcl_bool_of_val;
2299     [ 1,3,5,7: (* cond = true: continue looping *)
2300       #Hcl_bool_of_val normalize nodelta
2301       #Heq destruct (Heq)
2302       %{4} whd whd in ⊢ (??%?); normalize nodelta
2303       [ generalize in match (proj1 ???); #Hpresent_ifthenelse
2304       | generalize in match (proj1 ???); #Hpresent_ifthenelse
2305       | generalize in match (proj1 ???); #Hpresent_ifthenelse
2306       | generalize in match (proj1 ???); #Hpresent_ifthenelse ]
2307       (* Exhibit simulation of condition evaluation *)
2308       lapply (eval_expr_sim … Halloc_hyp … Hcl_env_hyp … Hinjection … Hmatching) * #Hsim #_
2309       [ lapply (Hsim (Expr cond_desc Tvoid) … Htranslate_cond ?? Hpresent_ifthenelse Hcl_exec_cond)
2310       | lapply (Hsim (Expr cond_desc (Tint sz sg)) … Htranslate_cond ?? Hpresent_ifthenelse Hcl_exec_cond)
2311       | lapply (Hsim (Expr cond_desc (Tstruct structname fieldspec)) … Htranslate_cond ?? Hpresent_ifthenelse Hcl_exec_cond)
2312       | lapply (Hsim (Expr cond_desc (Tunion unionname fieldspec)) … Htranslate_cond ?? Hpresent_ifthenelse Hcl_exec_cond) ]
2313       * #cm_val_cond * #Hcm_eval_cond #Hvalue_eq >Hcm_eval_cond
2314       whd in match (m_bind ?????);
2315       >(eval_bool_of_val_to_Cminor … Hvalue_eq … Hcl_bool_of_val)
2316       normalize nodelta whd
2317       [ generalize in match (proj1 ???); #Hnoise'
2318         generalize in match (conj ????); #Hnoise''
2319       | generalize in match (proj1 ???); #Hnoise'
2320         generalize in match (conj ????); #Hnoise''
2321       | generalize in match (proj1 ???); #Hnoise'
2322         generalize in match (conj ????); #Hnoise''
2323       | generalize in match (proj1 ???); #Hnoise'
2324         generalize in match (conj ????); #Hnoise'' ]
2325       @conj try @conj
2326       [ 3,6,9,12: #Habsurd destruct (Habsurd)
2327       | 1,4,7,10: normalize >append_nil @refl
2328       | 2,5,8,11:
2329            cut (lset_inclusion (identifier Label) (labels_of cm_body) (labels_of (f_body cm_f)))
2330            [ 1,3,5,7:
2331              lapply Hlabel_inclusion
2332              @transitive_lset_inclusion
2333              @cons_preserves_inclusion
2334              @lset_inclusion_union %1
2335              @lset_inclusion_union %1
2336              @lset_inclusion_union %1
2337              @reflexive_lset_inclusion ]
2338            #Hlabels_of_body
2339            cut (Exists (identifier Label) (λl'.l'=entry_label) (labels_of (f_body cm_f)))
2340            [ 1,3,5,7: @(lset_inclusion_Exists ????? Hlabel_inclusion)
2341              %1 @refl ]
2342            #Hentry_exists
2343            cut (Exists (identifier Label) (λl'.l'=exit_label) (labels_of (f_body cm_f)))
2344            [ 1,3,5,7: @(lset_inclusion_Exists ????? Hlabel_inclusion)
2345              %2 @Exists_append_r %1 @refl ]
2346            #Hexit_exists
2347            @(CMR_normal … Htrans_body) try assumption
2348            @(ClCm_cont_while … (sym_eq … Hmk_label_eq) … Htrans_body) try assumption
2349            try @refl
2350            [ 1,4,7,10: @eq_to_jmeq assumption
2351            | 2,5,8,11:
2352                 @conj try assumption @conj @conj try assumption @conj @conj try assumption
2353                 try @conj try assumption try @conj try assumption
2354                 try @conj try assumption try @conj try assumption
2355            | *: (* find_label_always *)
2356                 (* TODO /!\ implement necessary invariant on label lookup *)
2357                 @cthulhu
2358            ]
2359       ]
2360     | 2,4,6,8: (* cond = false: stop looping *)
2361       #Hcl_bool_of_val normalize nodelta #Heq destruct (Heq)
2362       %{5} whd whd in ⊢ (??%?); normalize nodelta
2363       [ generalize in match (proj1 ???); #Hpresent_ifthenelse
2364       | generalize in match (proj1 ???); #Hpresent_ifthenelse
2365       | generalize in match (proj1 ???); #Hpresent_ifthenelse
2366       | generalize in match (proj1 ???); #Hpresent_ifthenelse ]
2367       (* Exhibit simulation of condition evaluation *)
2368       lapply (eval_expr_sim … Halloc_hyp … Hcl_env_hyp … Hinjection … Hmatching) * #Hsim #_
2369       [ lapply (Hsim (Expr cond_desc Tvoid) … Htranslate_cond ?? Hpresent_ifthenelse Hcl_exec_cond)
2370       | lapply (Hsim (Expr cond_desc (Tint sz sg)) … Htranslate_cond ?? Hpresent_ifthenelse Hcl_exec_cond)
2371       | lapply (Hsim (Expr cond_desc (Tstruct structname fieldspec)) … Htranslate_cond ?? Hpresent_ifthenelse Hcl_exec_cond)
2372       | lapply (Hsim (Expr cond_desc (Tunion unionname fieldspec)) … Htranslate_cond ?? Hpresent_ifthenelse Hcl_exec_cond) ]       
2373       * #cm_val_cond * #Hcm_eval_cond #Hvalue_eq >Hcm_eval_cond
2374       whd in match (m_bind ?????);
2375       >(eval_bool_of_val_to_Cminor … Hvalue_eq … Hcl_bool_of_val) normalize nodelta whd
2376       [ generalize in match (proj2 ???); #Hnoise'
2377         generalize in match (proj2 ???); #Hnoise''
2378       | generalize in match (proj2 ???); #Hnoise'
2379         generalize in match (proj2 ???); #Hnoise''
2380       | generalize in match (proj2 ???); #Hnoise'
2381         generalize in match (proj2 ???); #Hnoise''
2382       | generalize in match (proj2 ???); #Hnoise'
2383         generalize in match (proj2 ???); #Hnoise'' ]
2384       @conj try @conj try @conj
2385       [ 1,4,7,10: normalize >append_nil >append_nil @refl
2386       | 2,5,8,11:
2387          @(CMR_normal … Htranslate_function … DoNotConvert) try assumption
2388          try @refl try @(env_below_freshgen_preserved_by_translation … Henv_below Htrans_body)
2389       | *: #Habsurd destruct (Habsurd) ]
2390   ]
2391| 3: (* Call *)
2392     #cm_s #cl_k #cm_k #cm_st #cl_f #cm_f #rettyp
2393     #alloc_type #cl_env #cl_m #cm_env #cm_m #stackptr #stacksize
2394     (* introduce everything *)
2395     #fInv #sInv #kInv #Htarget_type #func_univ #Hfresh_globals #Hfresh_function #Htranslate_function
2396     #stmt_univ #stmt_univ' #lbl_univ #lbl_univ' #lbls
2397     #flag * * * * #Hstmt_inv #Hlabels_translated #Htmps_preserved #Hreturn_ok #Hlabel_wf
2398     (* generalize away ugly proof *)
2399     generalize in ⊢ (∀_:(???(??(????%))).?); #Hugly
2400     #Htranslate #Hlabel_inclusion #tmpenv #Htmpenv #Hcont_rel #Em
2401     #Htmp_vars_well_allocated
2402     #Halloc_hyp #Hcl_env_hyp #Hinjection #Hmatching #HEm_fn_id
2403     #Hframe_spec #Henv_below #Hclight_normal #Hnot_labeleld
2404     (* back to unfolding Clight execution *)
2405     cases (bind_inversion ????? Htranslate) -Htranslate *
2406     #ef #Hexpr_vars_ef * #Htranslate_ef normalize nodelta #Htranslate
2407     cases (bind_inversion ????? Htranslate) -Htranslate *
2408     #ef' #Hexpr_vars_local_ef' * #Htyp_should_eq_ef
2409     cases (typ_should_eq_inversion (typ_of_type (typeof func)) ASTptr … Htyp_should_eq_ef)
2410     -Htyp_should_eq_ef #Htyp_equality_ef
2411     #Heq_ef_ef' #Htranslate
2412     cases (bind_inversion ????? Htranslate) -Htranslate *
2413     #cm_args #Hall_variables_from_args_local *
2414     whd in ⊢ ((???%) → ?); #Hargs_spec
2415     @(match retv
2416       return λx. retv = x → ?
2417       with
2418       [ None ⇒ λHretv. ?
2419       | Some lhs ⇒ λHretv. ?
2420       ] (refl ? retv))
2421     normalize nodelta
2422     [ 2: (* return something *)
2423       #Hdest cases (bind_inversion ????? Hdest) -Hdest #dest *
2424       inversion dest normalize nodelta
2425       [ (* register dest *) #var_id #His_local @(jmeq_absorb ?????) #Hdest
2426         #Htranslate_dest whd in ⊢ ((???%) → ?); #Heq destruct (Heq)
2427         (* make explicit the nature of lhs, allowing to prove that no trace is emitted *)
2428         lapply (translate_dest_id_inversion  … Htranslate_dest) #Hlhs_eq
2429       | * #cm_expr #Hexpr_vars_cm #Hdest #Htranslate_dest #Hgensym
2430         lapply (breakup_dependent_match_on_pairs ?????? Hgensym) -Hgensym
2431         * #ret_var * #new_gensym * #Heq_alloc_tmp * #_ #Hgensym
2432         lapply (breakup_dependent_match_on_pairs ?????? Hgensym) -Hgensym
2433         * #tmp_var * #new_gensym' * #Heq_alloc_tmp' * #_
2434         generalize in ⊢ ((??(?? (????%) )?) → ?); #Hstmt_inv_after_gensym
2435         whd in ⊢ ((???%) → ?); #Heq destruct (Heq)
2436       ]
2437     | 1: (* return void *)
2438          generalize in ⊢ ((??(??(????%))?) → ?); #Hugly2
2439          whd in ⊢ ((???%) → ?); #Heq destruct (Heq) ]
2440     (* Now, execute the Clight call *)
2441     #s2 #tr #Htranslate
2442     cases (bindIO_inversion ??????? Htranslate) -Htranslate *
2443     #CL_callee_val #CL_callee_trace * #Hexec_CL_callee normalize nodelta
2444     whd in ⊢ ((???%) → ?); #Htranslate
2445     cases (bindIO_inversion ??????? Htranslate) -Htranslate *
2446     #CL_args #CL_args_trace * #Hexec_CL_args #Htranslate
2447     cases (bindIO_inversion ??????? Htranslate) -Htranslate
2448     * #CL_callee_fundef #CL_callee_id * #Hfind_funct
2449     (* We've got the CL fundef. Extract a function pointer out of it. *)
2450     lapply (opt_to_io_Value ?????? Hfind_funct) -Hfind_funct #Hfind_funct
2451     cases (find_funct_inversion ???? Hfind_funct)
2452     #CL_callee_ptr * * * #HCL_callee_eq destruct (HCL_callee_eq)
2453     (* Done. Now stash the resulting properties of this pointer in the context. *)
2454     #HCL_callee_ptr_offset_eq_zero #HCL_callee_ptr_region_eq_Code
2455     (* Some more properties, that should stay hidden. XXX we discard them, this should not hinder the proof *)     
2456     * #block_id * #Hblock_id_neg #Hlookup -Hlookup -Hblock_id_neg -block_id
2457     (* Now, break up a safety check for the type of the function and finally, execute the
2458      * CL lvalue supposed to store the result of the function call. This will yield a pointer
2459      * that will be stored in the Callstate, until the function call returns and we store te
2460      * result inside it. Of course, this does not apply to the case wich returns void. *)
2461     #Htranslate
2462     cases (bindIO_inversion ??????? Htranslate) -Htranslate #Htype_of_fundef *
2463     #Hassert_type_eq
2464     [ 1,2: (* Cases where we return something. *)
2465            #Htranslate
2466            cases (bindIO_inversion ??????? Htranslate) -Htranslate * *
2467            #CL_lvalue_block #CL_lvalue_offset #CL_lvalue_trace *
2468            whd in ⊢ ((???%) → (??%%) → ?);
2469            [ >Hlhs_eq #HCL_exec_lvalue
2470              (* The trace is empty since we execute a variable *)
2471              cut (CL_lvalue_trace = [])
2472              [ lapply (res_to_io ????? HCL_exec_lvalue)
2473                #H' whd in H':(??%?); cases (lookup ????) in H'; normalize nodelta
2474                [ 2: #b #Heq destruct (Heq) @refl
2475                | #H cases (bind_inversion ????? H) #H24 * #H27 #H28
2476                  whd in H28:(???%); destruct (H28) @refl ]
2477              ] #H destruct (H)
2478            | #HCL_exec_lvalue ]
2479     | 3: ]
2480     whd in ⊢ ((??%%) → ?); #Heq destruct (Heq)
2481     (* We have reached the final Clight state. Now execute the Cminor transalted code. *)
2482     [ 1: (* Return to a variable *)
2483          %{1} whd whd in ⊢ (??%?); normalize nodelta
2484     | 2: (* Return to memory location. Need to create a tmp CM local variable to store the
2485           * lvalue ptr (otherwise trace does not match CL). *)
2486          %{5} whd whd in ⊢ (??%?); normalize nodelta
2487          whd in match (eval_expr ???????);
2488          whd in match (m_bind ?????);
2489          (* Evalue Cminor lvalue. Need to feed some invariants to the simulation lemma, that
2490           * we bake here and now. *)
2491          cut (expr_vars ASTptr cm_expr
2492                  (λid:ident.λty:typ.present SymbolTag val cm_env id))
2493          [ cases sInv * * * * * * * #_ #H #_ #_ #_ @H ] #Hexpr_vars_cut
2494          (* Apply simulation lemma for lvalues *)
2495          lapply (translate_dest_MemDest_simulation … Htranslate_dest HCL_exec_lvalue)
2496          try assumption try @refl
2497          * #CM_lvalue * #HCM_eval_lvalue >HCM_eval_lvalue #Hvalue_eq_lvalues
2498          normalize nodelta generalize in match (proj1 ???); #Htmp_var_present
2499          (* Make explicit the fact that the CM lvalue is a pointer *)
2500          cases (value_eq_ptr_inversion … Hvalue_eq_lvalues) #CM_lvalue_ptr * #HCM_value_ptr_eq #HCM_lvalue_ptr_trans
2501          >HCM_value_ptr_eq
2502          lapply (Htmp_vars_well_allocated … tmp_var Htmp_var_present (Tpointer (typeof lhs)) ? (Vptr CM_lvalue_ptr) ?)
2503          [ 1: normalize cases CM_lvalue_ptr #b #o %3
2504          | 2: lapply (alloc_tmp_in_genlist … (sym_eq ??? Heq_alloc_tmp) (sym_eq ??? Heq_alloc_tmp'))
2505               #Hexists' @(lset_inclusion_Exists … Hexists' Htmpenv) 
2506          ]
2507          * #CM_mem_after_store * #Hstorev #Hnew_inj >Hstorev
2508          whd in match (m_bind ?????); normalize nodelta
2509          whd whd in ⊢ (??%?); normalize nodelta
2510     | 3: %{1} whd whd in ⊢ (??%?); normalize nodelta
2511     ]
2512    (* cleanup ugliness *)
2513    [ 1: generalize in match (proj2 (present ????) (expr_vars ???) (proj1 ???));
2514    | 2: generalize in match (proj2 (present ????) (expr_vars ???) (proj1 ???));
2515    | 3: generalize in match (proj2 True ??); ]
2516    #Hexpr_vars_present_ef'
2517    [ 1,3:
2518       cases (eval_expr_sim … INV' … Halloc_hyp … Hcl_env_hyp … Hinjection … Hmatching) #Hsim_expr #_
2519       cut (expr_vars (typ_of_type (typeof func)) ef
2520             (λid:ident.λty:typ.present SymbolTag val cm_env id))
2521       [ 1,3: lapply Heq_ef_ef' lapply Hexpr_vars_ef lapply ef >Htyp_equality_ef
2522                #ef #Hexpr_vars_ef @(jmeq_absorb ?????) #Heq destruct (Heq)
2523                @Hexpr_vars_present_ef' ]
2524       #Hexpr_vars_present_ef
2525       lapply (Hsim_expr … Htranslate_ef … Hexpr_vars_present_ef … Hexec_CL_callee)
2526       -Hsim_expr * #cm_func_ptr_val * #Heval_func #Hvalue_eq_func
2527       cut (eval_expr cm_ge ASTptr ef' cm_env Hexpr_vars_present_ef'
2528             stackptr cm_m = OK (trace×val) 〈CL_callee_trace,cm_func_ptr_val〉)
2529       [ 1,3:
2530         lapply Heq_ef_ef' lapply Heval_func lapply Hexpr_vars_ef lapply Hexpr_vars_local_ef'
2531         lapply Hexpr_vars_present_ef lapply ef lapply Hexpr_vars_present_ef' lapply ef'
2532         <Htyp_equality_ef #ef' #HA #ef #HB #HC #HD #HE
2533         @(jmeq_absorb ?????) #Heq destruct (Heq) @HE ]
2534       -Heval_func #Heval_func >Heval_func
2535    | 2: (* treat case 2 as special, since the type differs slightly *)
2536       letin cm_env' ≝ (update_present SymbolTag val cm_env tmp_var Htmp_var_present (Vptr CM_lvalue_ptr))
2537       cut (memory_matching Em cl_ge cm_ge cl_m cm_m cl_env cm_env' INV' stackptr alloc_type)
2538     (*  cut (memory_matching Em cl_ge cm_ge cl_m CM_mem_after_store cl_env cm_env' INV' stackptr alloc_type) *)
2539       [ (* Proving preservation of the memory matching under store in "new" cminor memory zone.
2540            Use the property that the ident [tmp_var] is not in the clight env. *)
2541         #id lapply (Hmatching id)
2542         @(match (lookup ??? id)
2543           return λx. (lookup ??? id = x) → ?
2544           with
2545           [ None ⇒ λHeq_lookup. ?
2546           | Some blo ⇒ λHeq_lookup. ?
2547           ] (refl ? (lookup ??? id)))
2548         [ 1: #H @H ] normalize nodelta         
2549         cases (lookup ??? id) normalize nodelta
2550         [ 1: #H @H ] * #var_ty #cl_ty cases var_ty normalize nodelta
2551         [ #r #H @H
2552         | #n #H @H
2553         | #H #v #Hload_value_of_type lapply (H ? Hload_value_of_type)
2554           * #v' * #Hlookup_cm #Hvalue_eq %{v'} @conj try @Hvalue_eq
2555           lapply (alloc_tmp_env_invariant ?????? (sym_eq ??? Heq_alloc_tmp) Henv_below) #Henv_below'
2556           lapply (generated_id_not_in_env ???????? Henv_below' … Heq_lookup (sym_eq ??? Heq_alloc_tmp'))
2557           #Hneq <(update_lookup_opt_other … (Vptr CM_lvalue_ptr) … cm_env … Htmp_var_present … Hneq)
2558           assumption ] ] #Hmatching'
2559       cases (eval_expr_sim … INV' … Halloc_hyp ? cm_env' Hcl_env_hyp … Hinjection stackptr Hmatching')
2560       #Hsim_expr #_
2561       generalize in match (proj2 ???); #Hall_present
2562       generalize in match (proj1 ???); #Hret_present
2563       generalize in match (proj2 ???); #Hstore_inv
2564       generalize in match (conj ????); #Hstmt_inv
2565(*       cut (eval_expr cm_ge ? ef' cm_env' ? stackptr cm_m =
2566            (eval_expr cm_ge ASTptr ef' cm_env' ? stackptr cm_m)) try assumption try @refl
2567       #Heval_expr_rewrite >Heval_expr_rewrite -Heval_expr_rewrite *)
2568       lapply (Hsim_expr … Htranslate_ef … (Vptr CL_callee_ptr) CL_callee_trace ??)
2569       try assumption
2570       [ lapply Hexpr_vars_present_ef' lapply Heq_ef_ef' lapply Hexpr_vars_ef lapply Hexpr_vars_local_ef'
2571         lapply ef >Htyp_equality_ef #ef #HA #HB @(jmeq_absorb ?????) #Heq destruct (Heq) #x @x ]
2572       * #CM_callee_ptr * #Heval_func_cm #Hvalue_eq_func
2573       (* And some more shuffling types around to match the goal *)
2574       cut (eval_expr cm_ge ? ef' cm_env' Hexpr_vars_present_ef' stackptr cm_m = OK ? 〈CL_callee_trace,CM_callee_ptr〉)
2575       [ lapply Heval_func_cm -Heval_func_cm
2576         generalize in ⊢ ((??(?????%??)?) → ?);
2577         lapply Heq_ef_ef' -Heq_ef_ef'
2578         lapply Hexpr_vars_ef -Hexpr_vars_ef
2579         lapply Hexpr_vars_local_ef' -Hexpr_vars_local_ef'
2580         lapply Hexpr_vars_present_ef'
2581         lapply ef >Htyp_equality_ef #ef0 #HA #HB #HC @(jmeq_absorb ?????)
2582         #Heq destruct (Heq) #H1 #H2 @H2 ]
2583       #Heval_cm_func >Heval_cm_func ]
2584    whd in match (m_bind ?????);
2585    lapply (trans_fn … INV' … Hfind_funct)
2586    * #tmp_u * #cminor_fundef * #Hglobals_fresh_for_tmp_u * #Hfundef_fresh_for_tmp_u *
2587    #Htranslate_fundef #Hfind_funct_cm
2588    lapply (value_eq_ptr_inversion … Hvalue_eq_func) * #cm_func_ptr * #Hcm_func_ptr
2589    whd in ⊢ ((??%?) → ?);
2590    cases CL_callee_ptr in Hfind_funct Hfind_funct_cm HCL_callee_ptr_region_eq_Code HCL_callee_ptr_offset_eq_zero;
2591    #cm_block #cm_off #Hfind_funct #Hfind_funct_cm #Hregion_is_code #Hpoff_eq_zero destruct (Hpoff_eq_zero)
2592    whd in ⊢ ((??%?) → ?);
2593    [ 1,2: >(HEm_fn_id … cm_block Hregion_is_code)
2594    | 3: >(HEm_fn_id … cm_block Hregion_is_code) ]
2595    normalize nodelta
2596    cases cm_func_ptr in Hcm_func_ptr; #cm_block' #cm_off'
2597    #Hcm_func_ptr #Heq destruct (Hcm_func_ptr Heq)
2598    [ 1,2: >addition_n_0 >mk_offset_offv_id
2599    | 3: ]
2600    >Hfind_funct_cm
2601    whd in match (opt_to_res ???); normalize nodelta
2602    (* Again, isolate cases by type similarity *)
2603    [ 1,2:
2604      cut (All (𝚺t:typ.CMexpr t)
2605            (λx:𝚺t:typ.expr t.(
2606              match x with
2607              [ mk_DPair ty e ⇒
2608               expr_vars ty e
2609                 (λid:ident
2610                  .λty0:typ.present SymbolTag val cm_env id)])) cm_args)
2611      [ 1: cases sInv * * normalize nodelta * #_ #_ #Hall #_ #_ @Hall
2612      | 3: cases sInv * * normalize nodelta * #_ #_ #Hall #_ #_ @Hall ]
2613      #Hall
2614      cases (eval_exprlist_simulation …  Halloc_hyp Hcl_env_hyp Hinjection Hmatching ???? Hexec_CL_args Hargs_spec Hall)
2615      #cm_values * #Hcm_exec_list #Hcl_cm_values_eq >Hcm_exec_list
2616    | 3:
2617      lapply (eval_exprlist_simulation …  Halloc_hyp Hcl_env_hyp Hinjection ????? Hexec_CL_args Hargs_spec ?)
2618      try assumption
2619      * #cm_values * #Hcm_exec_list #Hcl_cm_values_eq >Hcm_exec_list
2620    ]
2621    whd in match (m_bind ?????); normalize nodelta whd @conj
2622    [ 2,4,6: #Habsurd destruct (Habsurd) ]
2623    @conj
2624    [ 1,3,5: normalize try @refl >append_nil >append_nil @refl ]
2625    [ 1: generalize in match (proj1 ? (expr_vars ???) (proj1 ???)); #Hugly_pres
2626    | 2: generalize in match (proj1 ? (expr_vars ???) (proj1 ???)); #Hugly_pres
2627    | 3: ]
2628    [ 3: @(CMR_call … Hinjection … HEm_fn_id) try assumption
2629         lapply (alloc_tmp_monotonic … (sym_eq ??? Heq_alloc_tmp)) #Hincl1
2630         lapply (alloc_tmp_monotonic … (sym_eq ??? Heq_alloc_tmp')) #Hincl2
2631         lapply (transitive_lset_inclusion … Hincl1 Hincl2) #Hincl3
2632         try /2 by transitive_lset_inclusion/
2633         lapply Htranslate_fundef -Htranslate_fundef
2634         lapply Hfundef_fresh_for_tmp_u -Hfundef_fresh_for_tmp_u
2635         #Hfundef_fresh_for_tmp_u #Htranslate_fundef
2636         @ClCm_cont_call_store assumption
2637    | 1,2: (* no return or return to CM local variable *)
2638           @(CMR_call … Hinjection … HEm_fn_id) try assumption
2639           @(ClCm_cont_call_nostore … Hcont_rel) try assumption
2640           whd %{CL_lvalue_block} %{CL_lvalue_offset} %{(typeof lhs)} %{var_id}
2641           % %
2642    ]
2643| 1: (* Skip *)
2644    #cm_s #cl_k #cm_k #cm_st #cl_f #cm_f #rettyp
2645    #alloc_type #cl_env #cl_m #cm_env #cm_m #stackptr #stacksize
2646    (* introduce everything *)
2647    #fInv #sInv #kInv
2648    #Htarget_type #func_univ #Hfresh_globals #Hfresh_function #Htranslate_function
2649    #stmt_univ #stmt_univ' #lbl_univ #lbl_univ' #lbls
2650    #flag * * * * #Hstmt_inv #Hlabels_translated #Htmps_preserved
2651    #Hreturn_ok #Hlabel_wf generalize in match (conj ????); #Hugly
2652    whd in ⊢ ((??%?) → ?); #Heq_translate #Hlabel_inclusion
2653    #tmpenv #Htmpenv #Hcont_rel
2654    lapply Heq_translate -Heq_translate
2655    lapply Hugly -Hugly
2656    lapply Hlabel_wf -Hlabel_wf
2657    lapply Hreturn_ok -Hreturn_ok
2658    lapply Htmps_preserved -Htmps_preserved
2659    lapply Hlabels_translated -Hlabels_translated
2660    lapply Hstmt_inv -Hstmt_inv
2661    lapply Htranslate_function -Htranslate_function
2662    lapply Hfresh_globals -Hfresh_globals
2663    lapply Hfresh_function -Hfresh_function
2664    lapply Htarget_type -Htarget_type
2665    lapply kInv -kInv
2666    lapply sInv -sInv
2667    lapply fInv -fInv
2668    lapply stmt_univ -stmt_univ   
2669    lapply Htmpenv -Htmpenv
2670    lapply stmt_univ' -stmt_univ'
2671    lapply Hlabel_inclusion -Hlabel_inclusion
2672    (* case analysis on continuation *)
2673    inversion Hcont_rel
2674    [ (* Kstop continuation *)
2675      (* simplifying the goal using outcome of the inversion *)
2676      #kcl_ge #kcm_ge #kINV #kcl_f #kcm_f #ktarget_type #kcl_env #kcm_env #kcm_m #kalloc_type #ktmpenv #kstack #Hkstack
2677      @(jmeq_absorb ?????) #HA @(jmeq_absorb ?????) #HB
2678      destruct (HA HB)
2679      @(jmeq_absorb ?????) #HC @(jmeq_absorb ?????) #HD @(jmeq_absorb ?????) #HE
2680      destruct (HC HD HE)
2681      @(jmeq_absorb ?????) #HF @(jmeq_absorb ?????) #HG @(jmeq_absorb ?????) #HH @(jmeq_absorb ?????) #HI
2682      destruct (HF HG HH HI)
2683      @(jmeq_absorb ?????) #HJ @(jmeq_absorb ?????) #HK @(jmeq_absorb ?????) #HL @(jmeq_absorb ?????) #HM
2684       @(jmeq_absorb ?????) #HN
2685      destruct (HJ HK HL HM HN) #_
2686      (* re-introduce everything *)
2687      #Hlabel_inclusion
2688      #stmt_univ' #Htmpenv #stmt_univ #fInv #sInv #kInv #Htarget_type #Hfresh_function #Hfresh_globals
2689      #Htranslate_function #Hstmt_inv #Hlabels_translated #Htmps_preserved
2690      #Hreturn_ok #Hlabel_wf
2691      #Hugly generalize in match (conj ????); #Hugly'
2692      (* reduce statement translation function *)
2693      #Heq_translate
2694      (* In this simple case, trivial translation *)
2695      destruct (Heq_translate)
2696      #Em #Htmp_vars_well_allocated
2697      #Halloc_hyp #Hcl_env_hyp #Hinjection #Hmatching #HEm_fn_id #Hframe_spec #Henv_below
2698      #Hclight_normal #Hnot_labeleld
2699      (* unfold the clight execution *)
2700      #s2 #tr whd in ⊢ ((??%?) → ?);
2701      inversion (fn_return cl_f) normalize nodelta
2702      [ | #sz #sg | #ptr_ty | #array_ty #array_sz | #domain #codomain
2703      | #structname #fieldspec | #unionname #fieldspec | #id ]
2704      #Hfn_return whd in ⊢ ((??%?) → ?); #Heq destruct (Heq)
2705      %{1} whd @conj try @conj try @refl
2706      [ 2: #Habsurd destruct (Habsurd) ]
2707      (* Use the memory injection stuff to produce a new memory injection *)
2708      cut (memory_inj Em (free_list cl_m (blocks_of_env kcl_env)) (free kcm_m stackptr))
2709      [ @(freelist_memory_inj_m1_m2 Em cl_m kcm_m
2710            (free_list cl_m (blocks_of_env kcl_env))
2711            (free kcm_m stackptr) Hinjection (blocks_of_env kcl_env) stackptr ? (refl ??) (refl ??))
2712        assumption ]
2713      #Hinjection'
2714      @(CMR_return … Kend … Halloc_hyp Hcl_env_hyp … Hinjection') try assumption
2715      [ 2: #b lapply (Hmatching b)
2716           cases (lookup ?? kcl_env b) normalize nodelta
2717           [ 1: #H @H
2718           | 2: #b' cases (lookup ?? kalloc_type b) normalize nodelta
2719             [ 1: #H @H
2720             | 2: * #kalloc_type #ty normalize nodelta
2721                  cases kalloc_type normalize nodelta try //
2722                  #H #v #Hload_after_free @H
2723                  @(load_value_after_free_list_inversion … Hload_after_free)
2724             ]
2725           ]
2726      | 1: @(tmp_vars_well_allocated_conserved_by_frame_free … Hmatching … Htmp_vars_well_allocated)
2727      | 3: @ClCm_cont_stop @Hkstack
2728      ]
2729    | (* Kseq *)
2730      #kcl_ge #kcm_ge #kINV #kcl_f #kcm_f #ktarget_type #kstack #kalloc_type #ktmpenv #kcl_s #kcm_s
2731      #kcl_env #kcm_env #kcm_m #kcl_k' #kcm_k' #kstmt_univ #kstmt_univ' #klbl_univ #klbl_univ' #klbls #kflag
2732      * * * * #kHstmt_inv #kHlabels_translated #kHtmps_preserved
2733      #kHreturn_ok #kHlabel_wf #kHeq_translate #kHlabel_inclusion #kHident_inclusion #kHcont_rel #_
2734      @(jmeq_absorb ?????) #HA @(jmeq_absorb ?????) #HB
2735      destruct (HA HB)
2736      @(jmeq_absorb ?????) #HC @(jmeq_absorb ?????) #HD @(jmeq_absorb ?????) #HE
2737      destruct (HC HD HE)
2738      @(jmeq_absorb ?????) #HF @(jmeq_absorb ?????) #HG @(jmeq_absorb ?????) #HH @(jmeq_absorb ?????) #HI
2739      destruct (HF HG HH HI)
2740      @(jmeq_absorb ?????) #HJ @(jmeq_absorb ?????) #HK @(jmeq_absorb ?????) #HL @(jmeq_absorb ?????) #HM
2741      @(jmeq_absorb ?????) #HN
2742      destruct (HJ HK HL HM HN) #_
2743      #Hlabel_inclusion
2744      #stmt_univ' #Htmpenv #stmt_univ #fInv #sInv #kInv #Htarget_type #Hfresh_function #Hfresh_globals
2745      #Htranslate_function #Hstmt_inv #Hlabels_translated #Htmps_preserved #Hreturn_ok #Hlabel_wf
2746      #Hugly generalize in match (conj ????); #Hugly'
2747      (* In this simple case, trivial translation *)
2748      #Heq_translate destruct (Heq_translate) #Em
2749      #Htmp_vars_well_alloc
2750      #Halloc_hyp #Hcl_env_hyp #Hinjection #Hmatching #HEm_fn_id #Hframe_spec #Henv_below
2751      #Hclight_normal #Hnot_labeleld
2752      #s2 #tr whd in ⊢ ((??%?) → ?); #Heq destruct (Heq)
2753      %{1} whd @conj [ 2: #Habsurd destruct (Habsurd) ] @conj try @refl
2754      (* close simulation *)
2755      @(CMR_normal … kHeq_translate … kHcont_rel … Hinjection … Hmatching) try assumption
2756      (* TODO Invariant on env_below_freshgen *)
2757       @cthulhu
2758    | (* Kwhile continuation *)
2759      #kcl_ge #kcm_ge #kINV #kcl_f #kcm_f #ktarget_type #kstack #kalloc_type #ktmpenv #kcl_env #kcm_env #kcm_m
2760      #kcl_k' #kcm_k' #ksz #ksg #kcl_ty #kcl_cond_desc #kcl_body #kHeq_ty #kcm_cond #kcm_body
2761      #kentry #kexit #kstmt_univ #kstmt_univ' #klbl_univ #klbl_univ' #klbl_univ''
2762      #klbls #kHtranslate_inv #kHexpr_vars #kHtranslate_expr #kfInv #kHlabel_declared
2763      #kHinv #kHmklabels #kHeq_translate #kHlabel_inclusion #kHident_inclusion #kHfind_label
2764      (*     
2765      * * * * #kHentry_declared * * * *
2766      * * * #kHcond_vars_declared #Hnoise #Hnoise' #Hnoise''
2767      #kHcont_inv #kHmklabels #kHeq_translate
2768      #kHfind_label *) #kHcont_rel #_
2769      @(jmeq_absorb ?????) #HA @(jmeq_absorb ?????) #HB
2770      destruct (HA HB)
2771      @(jmeq_absorb ?????) #HC @(jmeq_absorb ?????) #HD @(jmeq_absorb ?????) #HE
2772      destruct (HC HD HE)
2773      @(jmeq_absorb ?????) #HF @(jmeq_absorb ?????) #HG @(jmeq_absorb ?????) #HH
2774      @(jmeq_absorb ?????) #HI @(jmeq_absorb ?????) #HJ @(jmeq_absorb ?????) #HK
2775      @(jmeq_absorb ?????) #HL @(jmeq_absorb ?????) #HM @(jmeq_absorb ?????) #HN
2776      destruct (HF HG HH HI HJ HK HL HM HN) #_
2777      #Hlabel_inclusion
2778      #stmt_univ' #Htmpenv #stmt_univ #fInv #sInv #kInv #Htarget_type #Hfresh_function #Hfresh_globals
2779      #Htranslate_function #Hstmt_inv #Hlabels_translated #Htmps_preserved #Hreturn_ok #Hlabel_wf
2780      #Hugly
2781      generalize in match (conj ????); #Hugly'
2782      (* In this simple case, trivial translation *)
2783      #Heq_translate destruct (Heq_translate)
2784      #Em #Htmp_vars_well_allocated
2785      #Halloc_hyp #Hcl_env_hyp #Hinjection #Hmatching
2786      #HEm_fn_id #Hframe_spec #Henv_below
2787      #Hclight_normal #Hnot_labeleld
2788      #s2 #tr
2789      whd in ⊢ ((??%?) → ?); #Heq destruct (Heq)
2790      lapply kHfind_label -kHfind_label
2791      generalize in ⊢ ((??(????%????)?) → ?); #Hlabel_exists
2792      generalize in ⊢ ((???(????%)) → ?); #Hmore_invariant
2793      #kHfind_label
2794      (* Kwhile cont case *)
2795      %{2} whd whd in ⊢ (??%?); normalize nodelta
2796      generalize in match (proj2 ???); #Hmore_noise
2797      generalize in match (proj1 ???); #Hmore_noise'
2798      >kHfind_label normalize nodelta
2799      whd @conj try @conj try @refl
2800      generalize in match (proj1 ???); #Hvars_present_in_ifthenelse
2801      generalize in match (proj2 ???); #Hcont_inv'
2802      [ 2: #Habsurd destruct (Habsurd) ]
2803      (* go to a special simulation state for while loops *)
2804      @(CMR_while … stacksize … Hcl_env_hyp … Hinjection … kHtranslate_expr … kHmklabels …  kHeq_translate)
2805      try assumption
2806      [ 1: (* TODO: lemma on Henv_below. We need to thread freshgens through cont_rel. *)
2807           @cthulhu
2808      | 2: cases Hmore_invariant * * #_ * * * * #_ #_ * #_ #_ * * #_ #H
2809           #_ #_ @H ]
2810    | 4,5: (* Continuations for Scall. TODO *)
2811      @cthulhu
2812    ]
2813| 2: (* Assign *)
2814     #cm_s #cl_k #cm_k #cm_st #cl_f #cm_f #rettyp
2815     #alloc_type #cl_env #cl_m #cm_env #cm_m #stackptr #stacksize
2816     (* introduce everything *)
2817     #fInv #sInv #kInv #Htarget_type #func_univ #Hfresh_globals #Hfresh_function #Htranslate_function
2818     #stmt_univ #stmt_univ' #lbl_univ #lbl_univ' #lbls
2819     #flag * * * * #Hstmt_inv_cm #Hlabels_translated #Htmps_preserved
2820     #Hreturn_ok #Hlabel_wf generalize in match (conj ????); #Hugly #Htranslate
2821     #Hlabel_inclusion #tmpenv #Htmpenv #Hcont_rel
2822     #Em #Htmp_vars_well_allocated
2823     #Halloc_hyp #Hcl_env_hyp #Hinjection #Hmatching #HEm_fn_id #Hframe_spec #Henv_below
2824     #Hclight_normal #Hnot_labeleld
2825     lapply Htranslate -Htranslate
2826     (* case-split on lhs in order to reduce lvalue production in Cminor *)
2827     cases lhs #lhs_ed #lhs_ty
2828     cases (expr_is_Evar_id_dec lhs_ed)
2829     [ 2: * #var_id #Hlhs_ed destruct (Hlhs_ed)
2830          #Htranslate_statement
2831          cases (bind_inversion ????? Htranslate_statement)
2832          * #cm_rhs #Hexpr_vars_rhs * #Htranslate_rhs #Htranslate_statement'
2833          cases (bind_inversion ????? Htranslate_statement') -Htranslate_statement'
2834          #lhs_dest * #Htranslate_lhs
2835          cases (bind2_eq_inversion ?????? Htranslate_lhs) -Htranslate_lhs
2836          #alloctype * #type_of_var * #Hlookup_var_success
2837          cases alloctype in Hlookup_var_success;
2838          normalize nodelta
2839          [ 1: (* Global *) #r
2840               #Hlookup_var_success whd in ⊢ ((???%) → ?); #Hlhs_dest_eq
2841               destruct (Hlhs_dest_eq) normalize nodelta
2842               generalize in match (conj ????); #Hinvariant
2843               cases (type_eq_dec ??)
2844               [ 2: #Hneq normalize nodelta whd in ⊢ ((??%%) → ?);
2845                    #Habsurd destruct (Habsurd) ]
2846               normalize nodelta whd in match (typeof ?); #Heq_cl_types
2847               whd in ⊢ ((???%) → ?); #Heq destruct (Heq)
2848               #s2 #tr whd in ⊢ ((??%?) → ?); #Hstep
2849               cases (bindIO_inversion ??????? Hstep) -Hstep
2850               * * #cl_blo #cl_off #cl_tr * whd in ⊢ ((??%?) → ?);
2851               #Hexec_lvalue #Hstep
2852               lapply (res_to_io ????? Hexec_lvalue) -Hexec_lvalue #Hexec_lvalue
2853               cases (bindIO_inversion ??????? Hstep) -Hstep
2854               * #cl_rhs_val #cl_trace * #Hexec_rhs #Hstep
2855               cases (bindIO_inversion ??????? Hstep) -Hstep
2856               #cl_mem_after_store_lhs * #Hstore
2857               whd in ⊢ ((??%%) → ?); #Heq destruct (Heq)
2858               lapply (opt_to_io_Value ?????? Hstore) -Hstore #Hstore
2859               %{1} whd whd in ⊢ (??%?); normalize nodelta
2860               generalize in match (proj1 ???); whd in ⊢ (% → ?); *
2861               whd in match (eval_expr ???????);
2862               whd in match (eval_constant ????);
2863               whd in Hexec_lvalue:(??%?);
2864               <(eq_sym … INV' var_id)
2865               lapply (Hmatching … var_id)
2866               cases (lookup ?? cl_env var_id) in Hexec_lvalue; normalize nodelta
2867               [ 1: #Heq_find_sym cases (bind_inversion ????? Heq_find_sym) -Heq_find_sym
2868                    #global_b * #Hopt_to_res lapply (opt_to_res_inversion ???? Hopt_to_res) -Hopt_to_res
2869                    #Hfind_symbol >Hfind_symbol
2870                    normalize nodelta
2871                    whd in ⊢ ((???%) → ?); #Heq destruct (Heq) #Hembed_eq
2872                    whd in match (m_bind ?????);
2873                    cases (eval_expr_sim … Halloc_hyp … Hcl_env_hyp … Hinjection … Hmatching) #Hsim_expr #_
2874                    lapply (Hsim_expr … Htranslate_rhs … (proj2 ?? (proj1 ?? (proj1 ?? sInv))) Hexec_rhs)
2875                    * #cm_rhs_val generalize in match (proj2 ???);
2876                    #Hexpr_vars_rhs * #Heval_expr_rhs #Hvalue_eq_rhs >Heval_expr_rhs
2877                    whd in match (m_bind ?????); whd in Hstore:(??%?); whd in Hstore:(??%?);
2878                    cases (store_value_of_type_success_by_value lhs_ty cl_m
2879                                    cl_mem_after_store_lhs cl_blo zero_offset cl_rhs_val Hstore)
2880                    #Haccess_mode #Hstorev
2881                    lapply (storen_parallel_aux ??? Hinjection … Hvalue_eq_rhs … Hembed_eq ??? Hstorev)
2882                    * #cm_mem_after_store_lhs * #Hstoren #Hinj whd in Hstoren:(??%?);
2883                    whd in Hstoren:(??%?); whd in match (shift_offset ???);
2884                    >sign_ext_same_size >addition_n_0
2885                    whd in match (storev ????);
2886                    lapply Hstoren whd in match (offset_plus ??);
2887                    >addition_n_0 -Hstoren
2888                    >Heq_cl_types #Hstoren >Hstoren
2889                    whd in match (opt_to_res ???); normalize nodelta
2890                    whd @conj try @conj try @refl
2891                    [ 2: #Habsurd destruct (Habsurd) ]
2892                    generalize in match (conj ????); #Hinv_vars
2893                    @CMR_normal try assumption
2894                    [ 2: @refl | *: ]
2895                    [ 3: @(memory_matching_preserved_by_parallel_stores … Hmatching)
2896                    | 2: @(well_allocated_preserved_by_parallel_stores … Htmp_vars_well_allocated)
2897                    | 1: @(clight_cminor_cont_rel_parametric_in_mem … Hcont_rel) ]
2898               | 2: #b #Heq destruct (Heq)
2899                    lapply (opt_to_res_inversion ???? Hlookup_var_success) #Hlookup_aux
2900                    >Hlookup_aux normalize nodelta @False_ind ]
2901          | 2: (* Stack *)
2902               #n #Hlookup_var_success
2903               whd in ⊢ ((???%) → ?); #Heq destruct (Heq)
2904               normalize nodelta whd in ⊢ ((???%) → ?);
2905               cases (type_eq_dec ??) normalize nodelta #Htype_eq
2906               [ 2: #Habsurd destruct (Habsurd) ]
2907               #Heq destruct (Heq) #s2 #tr #Hstep
2908               cases (bindIO_inversion ??????? Hstep)
2909               * * #cl_lvalue_block #cl_offset #cl_trace * #Hexec_lvalue
2910               lapply (res_to_io ????? Hexec_lvalue) -Hexec_lvalue
2911               whd in ⊢ ((??%?) → ?);
2912               @(match lookup ?? cl_env var_id
2913                 return λx. (lookup ?? cl_env var_id = x) → ?
2914                 with
2915                 [ None ⇒ λH. ?
2916                 | Some cl_addr ⇒ λH. ?
2917                 ] (refl ? (lookup ?? cl_env var_id)))
2918               normalize nodelta
2919               [ (* Contradiction: a stack-allocated variable was necessarily in the environment. TODO *)
2920                 @cthulhu
2921               | #Heq destruct (Heq)
2922                 lapply (Hmatching var_id) >H normalize nodelta
2923                 >(opt_to_res_inversion ???? Hlookup_var_success) normalize nodelta
2924                 #Hembedding_to_stack #Hexec_cl_rhs
2925                 cases (bindIO_inversion ??????? Hexec_cl_rhs) -Hexec_cl_rhs *
2926                 #cl_rhs_result #cl_rhs_trace * #Hcl_exec_expr_rhs #Hcl_exec_store
2927                 cases (bindIO_inversion ??????? Hcl_exec_store) -Hcl_exec_store #cl_mem_after_store
2928                 * #Hstore_value_of_type lapply (opt_to_io_Value ?????? Hstore_value_of_type)
2929                 -Hstore_value_of_type
2930                 #Hstore_value_of_type
2931                 whd in ⊢ ((??%%) → ?); #Heq destruct (Heq)
2932                 %{1} whd whd in ⊢ (??%?); normalize nodelta
2933                 whd in match (eval_expr ???????);
2934                 whd in match (eval_constant ????);
2935                 whd in match (m_bind ?????);
2936                 cases (eval_expr_sim … Halloc_hyp … Hcl_env_hyp … Hinjection … Hmatching) #Hsim_expr #_
2937                 lapply (Hsim_expr … Htranslate_rhs … (proj2 ?? (proj1 ?? (proj1 ?? sInv))) Hcl_exec_expr_rhs)
2938                 * #cm_rhs_val generalize in match (proj2 ???);
2939                 #Hexpr_vars_rhs * #Heval_expr_rhs #Hvalue_eq_rhs >Heval_expr_rhs
2940                 normalize nodelta -Hsim_expr
2941                 whd in match (shift_offset ???); >sign_ext_same_size
2942                 >commutative_addition_n >addition_n_0
2943                 whd in Hstore_value_of_type:(??%?);
2944                 cases (store_value_of_type_success_by_value ? cl_m
2945                                    cl_mem_after_store ?? cl_rhs_result Hstore_value_of_type)
2946                 whd in match (typeof ?) in ⊢ ((??%%) → (??%?) → ?);
2947                 #Haccess_mode #Hstorev -Hstore_value_of_type
2948                 lapply (storen_parallel_aux ??? Hinjection … Hvalue_eq_rhs … Hembedding_to_stack ??? Hstorev)
2949                 * #cm_mem_after_store_lhs * #Hstoren #Hinj whd in Hstoren:(??%?);
2950                 >offset_plus_0 in Hstoren; #Hstorev'
2951                 whd in match (storev ????);
2952                 lapply Htype_eq whd in match (typeof ?) in ⊢ ((??%?) → ?); #Htype_eq'
2953                 <Htype_eq' >Hstorev'
2954                 whd in match (m_bind ?????); normalize nodelta
2955                 whd @conj try @conj try @refl
2956                 [ 2: #Habsurd destruct (Habsurd) ]                 
2957                 @(CMR_normal … Halloc_hyp) try assumption
2958                 try @refl
2959                 try @(memory_matching_preserved_by_parallel_stores … Hmatching)
2960                 try @(well_allocated_preserved_by_parallel_stores … Htmp_vars_well_allocated)
2961                 @(clight_cminor_cont_rel_parametric_in_mem … Hcont_rel)
2962               ]
2963          | 3: (* Local *)
2964               #Hlookup_var_success
2965               cases (typ_eq ??) normalize nodelta #Htyp_eq
2966               whd in ⊢ ((???%) → ?);
2967               #Heq destruct (Heq) normalize nodelta -Htranslate_statement
2968               #Htranslate
2969               cases (bind_inversion ????? Htranslate) -Htranslate
2970               * #cm_expr #Hexpr_vars * #Htyp_should_eq
2971               whd in ⊢ ((??%%) → ?); #Heq destruct (Heq)
2972               cases (typ_should_eq_inversion (typ_of_type (typeof rhs)) (typ_of_type lhs_ty) … Htyp_should_eq)
2973               -Htyp_should_eq #Htyp_eq lapply Hexpr_vars_rhs lapply Hexpr_vars
2974               -Hlabel_wf -Hreturn_ok -Hlabels_translated -Hstmt_inv_cm lapply sInv               
2975               lapply cm_expr -cm_expr <Htyp_eq #cm_expr #sInv #Hexpr_vars #Hexpr_vars'
2976               @(jmeq_absorb ?????) #Heq destruct (Heq)
2977               #s2 #tr whd in ⊢ ((??%?) → ?); #Hcl_exec
2978               cases (bindIO_inversion ??????? Hcl_exec)
2979               * * #cl_blo #cl_off #cl_trace *
2980               whd in ⊢ ((???%) → ?);
2981               #Hexec_lvalue lapply (res_to_io ????? Hexec_lvalue) -Hexec_lvalue
2982               whd in ⊢ ((??%?) → ?);
2983               @(match lookup ?? cl_env var_id
2984                 return λx. (lookup ?? cl_env var_id = x) → ?
2985                 with
2986                 [ None ⇒ λH. ?
2987                 | Some cl_addr ⇒ λH. ?
2988                 ] (refl ? (lookup ?? cl_env var_id)))
2989               normalize nodelta
2990               [ (* Contradiction: a register-allocated variable was necessarily in the environment *)
2991                 (* TODO, cf Hlookup_var_success or sInv *)
2992                 @cthulhu
2993               | #Heq destruct (Heq)
2994                 lapply (Hmatching var_id) >H normalize nodelta
2995                 >(opt_to_res_inversion ???? Hlookup_var_success) normalize nodelta
2996                 #Hpresent_in_local #Hexec_cl_rhs
2997                 cases (bindIO_inversion ??????? Hexec_cl_rhs) -Hexec_cl_rhs *
2998                 #cl_rhs_result #cl_rhs_trace * #Hcl_exec_expr_rhs #Hcl_exec_store
2999                 cases (bindIO_inversion ??????? Hcl_exec_store) -Hcl_exec_store #cl_mem_after_store
3000                 * #Hstore_value_of_type lapply (opt_to_io_Value ?????? Hstore_value_of_type)
3001                 -Hstore_value_of_type #Hstore_value_of_type
3002                 whd in ⊢ ((??%%) → ?); #Heq destruct (Heq)
3003                 %{1} whd whd in ⊢ (??%?); normalize nodelta
3004                 cases (eval_expr_sim … Halloc_hyp … Hcl_env_hyp … Hinjection … Hmatching) #Hsim_expr #_
3005                 lapply (Hsim_expr … Htranslate_rhs … (proj2 ?? (proj1 ?? (proj1 ?? sInv))) Hcl_exec_expr_rhs)
3006                 * #cm_rhs_val generalize in match (proj2 ???);
3007                 #Hexpr_vars_rhs * #Heval_expr_rhs #Hvalue_eq_rhs >Heval_expr_rhs
3008                 normalize nodelta -Hsim_expr whd @conj try @conj try @refl
3009                 [ 2: #Habsurd destruct (Habsurd) ]
3010                 generalize in match (proj1 ???); #Hpresent
3011                 generalize in match (conj ????); #Hstmt_vars
3012                 @(CMR_normal … Halloc_hyp) try assumption try @refl
3013                 [ 4: @(memory_matching_preserved_by_local_store … Hvalue_eq_rhs Hstore_value_of_type Hmatching)
3014                 | 3: @(memory_inj_preserved_by_local_store … Hmatching Hinjection)
3015                 | 2: @(tmp_vars_well_allocated_preserved_by_local_store … Hvalue_eq_rhs Hstore_value_of_type Htmp_vars_well_allocated)
3016                 | 1: @(clight_cminor_cont_rel_parametric_in_cm_env … Hpresent Hcont_rel) ]
3017               ]
3018          ]
3019     | 1: #Hnot_evar #Htranslate_statement
3020          cases (bind_inversion ????? Htranslate_statement) -Htranslate_statement
3021          * #cm_rhs #Hexpr_vars_rhs * #Htranslate_rhs #Htranslate_statement'
3022          cases (bind_inversion ????? Htranslate_statement') -Htranslate_statement' #dest
3023          lapply (translate_dest_not_Evar_id alloc_type ? lhs_ty Hnot_evar)
3024          #Htranslate_dest * #Htranslate_dest'
3025          >Htranslate_dest' in Htranslate_dest; #Haux lapply (sym_eq ??? Haux) -Haux #Haux
3026          cases (bind_inversion ????? Haux) -Haux
3027          * #translated_dest #Hexpr_vars_dest * #Htranslate_addr
3028          whd in ⊢ ((??%%) → ?); #Heq destruct (Heq) normalize nodelta
3029          cases (type_eq_dec ??)
3030          [ 2: #Hneq normalize nodelta whd in ⊢ ((??%%) → ?);
3031               #Habsurd destruct (Habsurd) ]
3032          normalize nodelta whd in match (typeof ?); #Heq_cl_types
3033          whd in ⊢ ((???%) → ?); #Heq destruct (Heq)
3034          #s2 #tr whd in ⊢ ((??%?) → ?); #Hstep
3035          cases (bindIO_inversion ??????? Hstep) -Hstep
3036          * * #cl_blo #cl_off #cl_tr * whd in ⊢ ((??%?) → ?);
3037          #Hexec_lvalue #Hstep
3038          lapply (translate_dest_MemDest_simulation …
3039                     INV' ???????? Halloc_hyp Hcl_env_hyp Hinjection Hmatching ??????
3040                     Htranslate_dest' Hexec_lvalue)
3041          [ 1: @(proj1 ?? (proj1 ?? (proj1 ?? sInv))) ]
3042          * #cm_val_dest * #Heval_cm_dest #Hvalue_eq_dest
3043          %{1} whd whd in ⊢ (??%?); normalize nodelta
3044          >Heval_cm_dest
3045          whd in match (m_bind ?????);
3046          cases (bindIO_inversion ??????? Hstep) -Hstep
3047          * #val #trace * #Hexec_expr #Hstep
3048          cases (bindIO_inversion ??????? Hstep) -Hstep
3049          #cl_mem_after_store * #Hopt_store
3050          whd in ⊢ ((??%%) → ?); #Heq destruct (Heq)
3051          lapply (opt_to_io_Value ?????? Hopt_store) -Hopt_store
3052          #Hstore_value_of_type whd in Hstore_value_of_type:(??%?);
3053          cases (eval_expr_sim … Halloc_hyp … Hcl_env_hyp … Hinjection … Hmatching) #Hsim_expr #_
3054          lapply (Hsim_expr … Htranslate_rhs … (proj2 ?? (proj1 ?? (proj1 ?? sInv))) Hexec_expr)
3055          * #cm_rhs_val generalize in match (proj2 ???);
3056          #Hexpr_vars_rhs * #Heval_expr_rhs #Hvalue_eq_rhs >Heval_expr_rhs
3057          normalize nodelta -Hsim_expr
3058          cases (store_value_of_type_success_by_value ? cl_m
3059                                    cl_mem_after_store ?? val Hstore_value_of_type)
3060          whd in match (typeof ?) in ⊢ ((??%%) → (??%?) → ?);
3061          #Haccess_mode #Hstorev -Hstore_value_of_type
3062          cases (value_eq_ptr_inversion … Hvalue_eq_dest) * #cm_blo #cm_off * #Hcm_val_dest destruct (Hcm_val_dest)
3063          whd in ⊢ ((??%?) → ?); #Hembed
3064          cases (some_inversion ????? Hembed) -Hembed
3065          * #cm_blo' #cm_off' * #Hembed normalize nodelta #Heq destruct (Heq)
3066          lapply (storen_parallel_aux ??? Hinjection … Hvalue_eq_rhs … Hembed ??? Hstorev)
3067          * #cm_mem_after_store_lhs * #Hstoren #Hinj whd in Hstoren:(??%?);
3068          whd in match (storev ????);
3069          lapply Hstoren
3070          (* make the types match *)
3071          generalize in match (conj ????); #Hstmt_vars' >Heq_cl_types
3072          #Hstoren >Hstoren
3073          whd in match (m_bind ?????); normalize nodelta whd @conj try @conj try @refl
3074          [ 2: #Habsurd destruct (Habsurd) ]
3075          @(CMR_normal … Halloc_hyp) try assumption try @refl
3076          [ 3: @(memory_matching_preserved_by_parallel_stores … Hmatching)
3077          | 2: @(well_allocated_preserved_by_parallel_stores … Htmp_vars_well_allocated)
3078          | 1: @(clight_cminor_cont_rel_parametric_in_mem … Hcont_rel) ]
3079     ]
3080| 4: (* Seq *)
3081     #cm_s #cl_k #cm_k #cm_st #cl_f #cm_f #rettyp
3082     #alloc_type #cl_env #cl_m #cm_env #cm_m #stackptr #stacksize
3083     (* introduce everything *)
3084     #fInv #sInv #kInv #Htarget_type #func_univ #Hfresh_globals #Hfresh_function #Htranslate_function
3085     #stmt_univ #stmt_univ' #lbl_univ #lbl_univ' #lbls
3086     #flag * * * * #Hstmt_inv_cm #Hlabels_translated #Htmps_preserved
3087     #Hreturn_ok #Hlabel_wf generalize in match (conj ????); #Hugly #Htranslate #Hlabel_inclusion
3088     #tmpenv #Htmpenv  #Hcont_rel
3089     #Em #Htmp_vars_well_allocated
3090     #Halloc_hyp #Hcl_env_hyp #Hinjection #Hmatching #HEm_fn_id #Hframe_spec #Henv_below
3091     #Hclight_normal #Hnot_labeleld
3092     cases (bind_inversion ????? Htranslate) -Htranslate
3093     * * * #tmp_gen #labgen #cm_s1 #Htrans_inv * #Htrans_stm1 normalize nodelta
3094     #Htranslate cases (bind_inversion ????? Htranslate) -Htranslate     
3095     * * * #tmp_gen' #labgen' #cm_s2 #Htrans_inv' * #Htrans_stm2 normalize nodelta
3096     whd in ⊢ ((??%%) → ?); #Heq destruct (Heq)
3097     #s2 #tr whd in ⊢ ((??%?) → ?); #Heq destruct (Heq)
3098     %{1} whd @conj try @conj try @refl
3099     [ 2: #Habsurd destruct (Habsurd) ]
3100     @(CMR_normal … Htrans_stm1) try assumption
3101     [ 1: lapply Hlabel_inclusion
3102          @transitive_lset_inclusion @lset_inclusion_union %1
3103          @reflexive_lset_inclusion
3104     | 2: lapply (translation_entails_ident_inclusion … Htrans_stm2) #H
3105          @(transitive_lset_inclusion … (translation_entails_ident_inclusion … Htrans_stm2))
3106          assumption
3107     | 3: @(ClCm_cont_seq … Htrans_stm2)
3108          [ 1: lapply Hlabel_inclusion @transitive_lset_inclusion @lset_inclusion_union %2
3109               @reflexive_lset_inclusion
3110          | 2: assumption
3111          | 3: assumption ]
3112     ]
3113| *: (* Other statements *) @cthulhu ]
3114| 2: (* Return state *)
3115  #cl_ge #cm_ge #INV' #cl_k #cm_k #cm_st #cl_f #cm_f #alloc_type
3116  #cl_env #cl_m #cm_env #cm_mt #stackptr #stacksize
3117  #stmt_univ #tmpenv #Htmpenv #Em #Htmp_vars_wa #Hcharac #Hexec_alloc #Hinj #Hmatch #Hem_fn_id #Hframe #Hcont
3118  #Hclight_normal #Hnot_labeleld
3119  whd in Hclight_normal:%;
3120  @False_ind @Hclight_normal
3121| 3: (* Call state *)
3122  #cl_ge #cm_ge #INV' #cl_k #cm_st #cl_fundef #cm_fundef
3123  #fblock #target_type #cl_env #cl_m #cm_env #cm_m
3124  #fn_id #Hfind_cl #Hfind_cm
3125  #tmpenv #Hcont_rel
3126  #Em #Hinj #Hem_fn_id
3127  #cl_args_values #cm_args_values #Hall2
3128  #Hclight_normal #Hnot_labeleld
3129  whd in Hclight_normal:%;
3130  @False_ind @Hclight_normal
3131| 4: (* Intermediary While state *)
3132     (* ---------------------------------------------------------------------- *)
3133#cl_ge #cm_ge #INV'
3134#cl_f #cm_f #cl_env #cl_m #cm_env #cm_m #stackptr #stacksize #alloc_type
3135#cl_k #cm_k #sz #sg #cl_cond_ty #cl_cond_desc #cl_body #entry_label #exit_label #cm_cond #cm_body
3136#cm_stack #rettyp #kInv #fInv #sInv #Heq_ty #Hrettyp_eq #func_univ #Hfresh_globals #Hfresh_function
3137#Htranslate_function #Hcont_rel
3138#stmt_univ #stmt_univ' #lbl_univ #lbl_univ' #lbl_univ'' #tmpenv #Htmpenv #Hcont_rel
3139#Em #Htmp_vars_well_allocated
3140#Hcharacterise #Hcl_env_hyp #Hinjection #Hmatching #HEm_fn_id #Hframe_spec #Henv_below
3141#Hexpr_vars #Htranslate_expr #Hentry_ex #Hexit_ex #Htranslate_inv #Hmk_labels #Htranslate_statement
3142#Hlabel_inclusion #Hlabel_exists #Hinv1 #Hinv2 #Hfind_label
3143#Hclight_normal #Hnot_labeleld
3144#s2 #tr whd in ⊢ ((??%?) → ?); #Hstep
3145(* execute clight condition *)
3146cases (bindIO_inversion ??????? Hstep) -Hstep
3147* #cl_cond_val #cl_cond_trace * #Hcl_exec_cond #Hstep
3148cases (bindIO_inversion ??????? Hstep) -Hstep
3149#cl_cond_bool * #Hcl_bool_of_val whd in ⊢ ((??%%) → ?); #Heq destruct (Heq)
3150(* The numbers of steps to execute in Cminor depends on the outcome of the condition
3151   evaluation *)
3152cases cl_cond_bool in Hcl_bool_of_val;
3153[ (* cond = true: continue looping *)
3154  #Hcl_bool_of_val
3155  %{3} whd whd in ⊢ (??%?); normalize nodelta
3156  generalize in match (proj1 ???); #Hpresent_ifthenelse
3157  (* Exhibit simulation of condition evaluation *)
3158  lapply (eval_expr_sim … Hcharacterise … Hcl_env_hyp … Hinjection … Hmatching) * #Hsim #_
3159  (* The type of Hsim forces us to wrap cm_cond into a dummy cast. *)
3160  lapply (Hsim (Expr cl_cond_desc cl_cond_ty) (CMcast ?? cm_cond ?))
3161  [ >Heq_ty @refl ] -Hsim
3162  whd in match (typeof ?); #Hsim
3163  lapply (Hsim ??????)
3164  [ 2: <Heq_ty >CMcast_identity assumption
3165  | 1: assumption
3166  | 6: <Heq_ty >CMcast_identity assumption
3167  | 5: lapply Htranslate_expr lapply Hexpr_vars lapply cm_cond -cm_cond
3168       >Heq_ty #cm_cond #Hexpr_vars @(jmeq_absorb ?????) #Hsol @Hsol
3169  | *: ]
3170  * #cm_val_cond * #Hcm_eval_cond #Hvalue_eq -Hsim
3171  cut (eval_expr cm_ge (ASTint sz sg) cm_cond cm_env Hpresent_ifthenelse stackptr cm_m = OK ? 〈tr, cm_val_cond〉)
3172  [ lapply Hpresent_ifthenelse
3173    <(CMcast_identity (ASTint sz sg) cm_cond) #foo
3174    lapply Hcm_eval_cond whd in match (eq_ind_r ??????); normalize nodelta cases Heq_ty
3175    #H @H ]
3176  #Heval >Heval
3177  whd in match (m_bind ?????);
3178  >(eval_bool_of_val_to_Cminor … Hvalue_eq … Hcl_bool_of_val)
3179  normalize nodelta whd
3180  generalize in match (proj1 ???); #Hnoise'
3181  generalize in match (conj ????); #Hnoise'' @conj try @conj
3182  [ 3: #Habsurd destruct (Habsurd)
3183  | 1: normalize >append_nil @refl
3184  | 2: @(CMR_normal … Htranslate_function … Htranslate_statement) try assumption
3185       @(ClCm_cont_while … Htranslate_inv … Hmk_labels … Htranslate_statement) try assumption
3186  ]
3187| (* cond = false: stop looping *)
3188  #Hcl_bool_of_val
3189  %{4} whd whd in ⊢ (??%?); normalize nodelta
3190  generalize in match (proj1 ???); #Hpresent_ifthenelse
3191  (* Exhibit simulation of condition evaluation *)
3192  lapply (eval_expr_sim … Hcharacterise … Hcl_env_hyp … Hinjection … Hmatching) * #Hsim #_
3193  lapply (Hsim (Expr cl_cond_desc cl_cond_ty) (CMcast ?? cm_cond ?))
3194  [ >Heq_ty @refl ] -Hsim
3195  whd in match (typeof ?); #Hsim
3196  lapply (Hsim ??????)
3197  [ 2: <Heq_ty >CMcast_identity assumption
3198  | 1: assumption
3199  | 6: <Heq_ty >CMcast_identity assumption
3200  | 5: lapply Htranslate_expr lapply Hexpr_vars lapply cm_cond -cm_cond
3201       >Heq_ty #cm_cond #Hexpr_vars @(jmeq_absorb ?????) #Hsol @Hsol
3202  | *: ]
3203  * #cm_val_cond * #Hcm_eval_cond #Hvalue_eq -Hsim
3204  cut (eval_expr cm_ge (ASTint sz sg) cm_cond cm_env Hpresent_ifthenelse stackptr cm_m = OK ? 〈tr, cm_val_cond〉)
3205  [ lapply Hpresent_ifthenelse
3206    <(CMcast_identity (ASTint sz sg) cm_cond) #foo
3207    lapply Hcm_eval_cond whd in match (eq_ind_r ??????); normalize nodelta cases Heq_ty
3208    #H @H ]
3209  #Heval >Heval
3210  whd in match (m_bind ?????);
3211  >(eval_bool_of_val_to_Cminor … Hvalue_eq … Hcl_bool_of_val)
3212  normalize nodelta whd
3213  generalize in match (proj1 ???); #Hnoise'
3214  generalize in match (proj2 ???); #Hnoise''
3215  generalize in match (conj ????); #Hnoise'''
3216  whd @conj try @conj
3217  [ 3: #Habsurd destruct (Habsurd)
3218  | 1: normalize >append_nil >append_nil @refl
3219  | 2: @(CMR_normal … DoNotConvert) try assumption
3220       try @refl
3221       @(env_below_freshgen_preserved_by_translation … Htranslate_statement)
3222       assumption
3223  ]
3224]
3225
3226] qed.
3227
3228 
3229(* TODO: move to globalenvs *)
3230(* The hypotheses are a little strong - we don't need to know that the size of
3231   the initialisation data is the same. *)
3232lemma find_funct_id_match:
3233    ∀M:matching.
3234    ∀initV,initW. (∀v,w. match_var_entry M v w → size_init_data_list (initV (\snd v)) = size_init_data_list (initW (\snd w))) →
3235    ∀p: program (m_A M) (m_V M). ∀p': program (m_B M) (m_W M).
3236    ∀MATCH:match_program … M p p'.
3237    ∀v. ∀f: m_A M (prog_var_names … p). ∀id.
3238    find_funct_id … (globalenv … initV p) v = Some ? 〈f,id〉 →
3239    ∃tf : m_B M (prog_var_names … p').
3240    find_funct_id … (globalenv … initW p') v = Some ? 〈tf,id〉 ∧ match_fundef M ? f (tf⌈m_B M ? ↦ m_B M (prog_var_names … p)⌉).
3241[ 2: >(matching_vars … (mp_vars … MATCH)) % ]
3242#M #initV #initW #varsOK #p #p' #MP * [ | #sz #i | | #p ] #f #id
3243[ 1,2,3: #FF whd in FF:(??%?); destruct ]
3244#FFI cases (find_funct_id_ptr ????? FFI) #b * * #E destruct #FS #FFPI
3245cases (find_funct_ptr_id_inv ????? FFPI) #FFP #SFB
3246cases (find_funct_ptr_match M initV initW … MP ? f FFP)
3247#f' * #FFP' #MF %{f'} %
3248[ @find_funct_ptr_id_conv
3249  @(make_find_funct_ptr_id ???? id FFP' ?)
3250  whd in ⊢ (??%?); >(symbols_match … initV … MP) [ @SFB | @varsOK ]
3251| @MF
3252] qed.
3253
3254lemma clight_cminor_inv_exists : ∀p,p'.
3255  clight_to_cminor p = OK … p' →
3256  clight_cminor_inv (make_global … clight_fullexec p) (make_global … Cminor_fullexec p').
3257#p #p' #COMPILE
3258lapply (clight_to_cminor_matches … COMPILE) #MATCHES -COMPILE
3259%
3260[2: #sym lapply (find_symbol_match (clight_cminor_matching p) ????? MATCHES)
3261    [4: #H @sym_eq @H | #X #Y * #id #r #v1 #v2 * % | skip | skip ]
3262|3: #v #f #id #FF cases (find_funct_id_match … MATCHES … FF)
3263  [ #f' * #FF' whd in ⊢ (% → ?); * #H1 * #H2 #Efd
3264    % [2: %{f'} %{H1} %{H2} % [ >Efd
3265    -Efd -H1 -H2 -FF' -FF
3266    generalize in ⊢ (??(??(match % with [_⇒?]))?);
3267    >(matching_vars … (mp_vars … MATCHES)) -MATCHES
3268    #E @(streicherK ???? E) %
3269    | @FF'
3270    ]
3271   | skip
3272   ]
3273  | skip
3274  | #X #Y * #id' #r #v1 #v2 * %
3275  ]
3276| skip
3277] qed.
3278
3279(* TODO: move to common/Pointers.ma *)
3280axiom offset_plus_zero : ∀o.
3281  offset_plus o zero_offset = o.
3282
3283(* TODO: move to memory model *)
3284lemma valid_block_dec: ∀m,b. (valid_block m b) + (¬valid_block m b).
3285#m * #b
3286whd in ⊢ (?%(?%));
3287lapply (refl ? (Zltb b (nextblock m)))
3288cases (Zltb b (nextblock m)) in ⊢ (???% → ?);
3289#H
3290[ %1 @Zltb_true_to_Zlt assumption
3291| %2 @Zltb_false_to_not_Zlt assumption
3292] qed.
3293
3294definition equal_embedding : mem → block → option (block × offset) ≝
3295λm,b. match valid_block_dec m b with
3296[ inl _ ⇒ Some ? 〈b,zero_offset〉
3297| inr _ ⇒ None ?
3298].
3299
3300lemma valid_pointer_valid_block : ∀m,b,o.
3301  valid_pointer m (mk_pointer b o) →
3302  valid_block m b.
3303#m #b #o #VP
3304cases (andb_Prop_true … VP) #H
3305cases (andb_Prop_true … H) #B #_ #_
3306whd @(Zltb_true_to_Zlt … B)
3307qed.
3308
3309lemma valid_block_dec_true : ∀m,b.
3310  valid_block m b →
3311  ∃H. valid_block_dec m b = inl … H.
3312#m * #b #H whd in ⊢ (??(λ_.??%?)); whd in H;
3313generalize in ⊢ (??(λ_.??(?%)?));
3314>(Zlt_to_Zltb_true … H) in ⊢ (???% → ??(λ_.??(match % with [_⇒?|_⇒?]?)?));
3315#E % [2: % | skip ]
3316qed.
3317
3318lemma not_Zlt_to_Zltb_false : ∀x,y.
3319  ¬(Zlt x y) →
3320  Zltb x y = false.
3321#x #y #N lapply (Zltb_true_to_Zlt x y)
3322cases (Zltb x y) //
3323#H @⊥ @(absurd … (H (refl ??))) @N
3324qed.
3325
3326lemma valid_block_dec_false : ∀m,b.
3327  ¬valid_block m b →
3328  ∃H. valid_block_dec m b = inr … H.
3329#m * #b #H whd in ⊢ (??(λ_.??%?)); whd in H;
3330generalize in ⊢ (??(λ_.??(?%)?));
3331>(not_Zlt_to_Zltb_false … H) in ⊢ (???% → ??(λ_.??(match % with [_⇒?|_⇒?]?)?));
3332#E % [2: % | skip ]
3333qed.
3334
3335(* TODO: move to memoryInjections.ma? *)
3336lemma equal_value_eq : ∀m,ty,b,o,v.
3337  (∀p. load_value_of_type ty m b o = Some ? (Vptr p) → valid_pointer m p) →
3338  load_value_of_type ty m b o = Some ? v →
3339  value_eq (equal_embedding m) v v.
3340#m #ty #b #o * //
3341* #b' #o' #H1 #H2 @vptr_eq
3342whd in ⊢ (??%?); whd in match (equal_embedding ??);
3343cases (valid_block_dec_true … (valid_pointer_valid_block m b' o' ?))
3344[2: @H1 @H2 ]
3345#H3 #E >E whd in ⊢ (??%?);
3346>offset_plus_zero %
3347qed.
3348
3349lemma equal_embedding_elim : ∀m,b,b',o. ∀P:block → offset → Prop.
3350  equal_embedding m b = Some ? 〈b',o〉 →
3351  (valid_block m b → P b zero_offset) →
3352  P b' o.
3353#m * #b #b' #o #P
3354whd in ⊢ (??%? → ?);
3355cases (valid_block_dec ??) #H #E
3356whd in E:(??%%); destruct
3357/2/
3358qed.
3359
3360lemma pointer_translation_elim : ∀m,p,p'. ∀P:pointer → Prop.
3361  pointer_translation p (equal_embedding m) = Some ? p' →
3362  P p →
3363  P p'.
3364#m * #b #o * #b' #o' #P whd in ⊢ (??%? → ?);
3365whd in match (equal_embedding m b);
3366cases (valid_block_dec ??)
3367#H #E whd in E:(??%?); [ >offset_plus_zero in E; #E ] destruct
3368//
3369qed.
3370
3371lemma pointer_translation_elim' : ∀m,b,o,b',o'. ∀P:block → offset → Prop.
3372  pointer_translation (mk_pointer b o) (equal_embedding m) = Some ? (mk_pointer b' o') →
3373  P b o →
3374  P b' o'.
3375#m #b #o #b' #o' #P whd in ⊢ (??%? → ?);
3376whd in match (equal_embedding m b);
3377cases (valid_block_dec ??)
3378#H #E whd in E:(??%?); [ >offset_plus_zero in E; #E ] destruct
3379//
3380qed.
3381
3382lemma equal_memory_injection : ∀m.
3383  (∀b. valid_block m b → block_implementable_bv m b) →
3384  (∀ty,b,o,p. load_value_of_type ty m b o = Some ? (Vptr p) → valid_pointer m p) →
3385  memory_inj (equal_embedding m) m m.
3386#m #addr_ok #contents_ok %
3387[ whd #b1 #off1 #b2 #off2 #ty #v1 #Hvalid #Htrans
3388  @(pointer_translation_elim' … Htrans)
3389  #Hload
3390  %{v1} destruct %{Hload} @(equal_value_eq … Hload) @contents_ok
3391| #b #H whd in ⊢ (??%?);
3392  cases (valid_block_dec_false … H) #H' #E >E %
3393| * #b #o #p' #Hv #Ht @(pointer_translation_elim … Ht)
3394  @Hv
3395| #b #b' #off #Hem @(equal_embedding_elim … Hem) //
3396| #b #b' #o' #Hem @(equal_embedding_elim … Hem) //
3397| whd #b1 #b2 #b1' #b2' #delta1 #delta2 #NE #Hem1 #Hem2
3398  @(equal_embedding_elim … Hem1)
3399  @(equal_embedding_elim … Hem2)
3400  #_ #_ @eq_block_elim [ #E @⊥ @(absurd … E NE) | // ]
3401| #b whd whd in match (equal_embedding m b);
3402  cases (valid_block_dec m b) #H whd //
3403  % [ % @addr_ok assumption | cases (addr_ok … H) #_ * #_ #H' >Zplus_z_OZ @H' ]
3404] qed.
3405
3406axiom init_mem_good : ∀F,V,i,p,m.
3407  init_mem F V i p = OK … m →
3408  (∀b. valid_block m b → block_implementable_bv m b) ∧
3409  (∀ty,b,o,p. load_value_of_type ty m b o = Some ? (Vptr p) → valid_pointer m p).
3410
3411lemma init_clight_cminor : ∀p,p',s.
3412  make_initial_state … clight_fullexec p = OK … s →
3413  clight_to_cminor p = OK … p' →
3414  ∃INV:clight_cminor_inv (make_global … clight_fullexec p) (make_global … Cminor_fullexec p').
3415  ∃s'.
3416    make_initial_state … Cminor_fullexec p' = OK … s' ∧
3417    clight_cminor_rel (make_global … clight_fullexec p) (make_global … Cminor_fullexec p') INV s s'.
3418#p #p' #s #INIT #COMPILE
3419lapply (clight_to_cminor_matches … COMPILE) #MATCHES
3420
3421%{(clight_cminor_inv_exists … COMPILE)}
3422
3423lapply (find_funct_ptr_match (clight_cminor_matching p) (fst ??) (λx.x) … MATCHES)
3424lapply (find_symbol_match (clight_cminor_matching p) (fst ??) (λx.x) … MATCHES)
3425[ #v #w * // ]
3426lapply (init_mem_match (clight_cminor_matching p) (fst ??) (λx.x) … MATCHES)
3427[ #v #w * // ]
3428cases p in INIT COMPILE MATCHES ⊢ %; #vars #fns #main #INIT #COMPILE #MATCHES
3429cases (bind_inversion ????? INIT) -INIT #m * #INITMEM #INIT
3430cases (bind_inversion ????? INIT) -INIT #b * #FINDSYM #INIT
3431cases (bind_inversion ????? INIT) -INIT #fd * #FFP #INIT
3432whd in INIT:(??%%); destruct
3433whd in match (m_A ??); whd in match (m_B ??); whd in match (m_V ?); whd in match (m_W ?);
3434#M_initmem #M_findsym #M_ffp
3435cases (M_ffp … FFP) -M_ffp #f' * #FFP' #Mf'
3436%{(Callstate main f' [ ] m SStop)} %
3437[ whd in ⊢ (??%?); normalize in M_initmem:(??(?%%%?)(?%%%?)); >M_initmem >INITMEM
3438  whd in ⊢ (??%?); lapply (M_findsym main) <(mp_main … MATCHES)
3439  whd in match (m_A ??); whd in match (m_B ??);
3440  change with (make_global p') in match (globalenv ????); #E >E
3441  >FINDSYM
3442  whd in ⊢ (??%?); >FFP'
3443  whd in ⊢ (??%?); %
3444| @(CMR_call … b (Some ? (ASTint I32 Signed)) (empty_map …) ? (empty_map …) … (ClCm_cont_stop …))
3445  [ @find_funct_ptr_id_conv @make_find_funct_ptr_id
3446    [ @FFP
3447    | @(symbol_for_block_fn … FINDSYM FFP)
3448    ]
3449  | @find_funct_ptr_id_conv @make_find_funct_ptr_id
3450    [ @FFP'
3451    | @(symbol_for_block_fn … FFP') >M_findsym @FINDSYM
3452    ]
3453  | @([ ])
3454  | %
3455  | whd @(equal_embedding m)
3456  | cases (init_mem_good … INITMEM) #H1 #H2 @equal_memory_injection assumption
3457  | (* This is a little too concrete... and the property is true but a little
3458       strong (we always map function blocks in the embedding - even if there's
3459       no function!) *)
3460    #b #CODE cut (valid_block m b)
3461    [ cases b in CODE ⊢ %; * [2,3:#z] #CODE whd in CODE:(??%?); destruct whd
3462      lapply (nextblock_pos m) cases (nextblock m) [2,3,5,6:#z'] try * %
3463    ] #VALID
3464    whd in ⊢ (??%?); cases (valid_block_dec ??)
3465    [ //
3466    | #INVALID @⊥ @(absurd … VALID INVALID)
3467    ]
3468  | %
3469  ]
3470] qed.
3471
Note: See TracBrowser for help on using the repository browser.