1 | include "joint/joint_semantics.ma". |
---|
2 | include alias "common/Identifiers.ma". |
---|
3 | include "utilities/hide.ma". |
---|
4 | include "ASM/BitVectorTrie.ma". |
---|
5 | include "joint/TranslateUtils.ma". |
---|
6 | include "common/ExtraMonads.ma". |
---|
7 | include "common/extraGlobalenvs.ma". |
---|
8 | |
---|
9 | definition reg_store ≝ λreg,v,locals.add RegisterTag beval locals reg v. |
---|
10 | |
---|
11 | definition reg_retrieve : register_env beval → register → res beval ≝ |
---|
12 | λlocals,reg. opt_to_res … [MSG BadRegister; CTX ? reg] (lookup … locals reg). |
---|
13 | |
---|
14 | record hw_register_env : Type[0] ≝ |
---|
15 | { reg_env : BitVectorTrie beval 6 |
---|
16 | ; other_bit : bebit |
---|
17 | }. |
---|
18 | |
---|
19 | include alias "ASM/BitVectorTrie.ma". |
---|
20 | |
---|
21 | definition hwreg_retrieve: hw_register_env → Register → beval ≝ |
---|
22 | λenv,r. lookup … (bitvector_of_register r) (reg_env env) BVundef. |
---|
23 | |
---|
24 | definition hwreg_store: Register → beval → hw_register_env → hw_register_env ≝ |
---|
25 | λr,v,env.mk_hw_register_env (insert … (bitvector_of_register r) v (reg_env env)) |
---|
26 | (other_bit env). |
---|
27 | |
---|
28 | definition hwreg_set_other : bebit → hw_register_env → hw_register_env ≝ |
---|
29 | λv,env.mk_hw_register_env (reg_env env) v. |
---|
30 | |
---|
31 | definition hwreg_retrieve_sp : hw_register_env → res xpointer ≝ |
---|
32 | λenv. |
---|
33 | let spl ≝ hwreg_retrieve env RegisterSPL in |
---|
34 | let sph ≝ hwreg_retrieve env RegisterSPH in |
---|
35 | ! ptr ← pointer_of_address 〈spl, sph〉 ; |
---|
36 | match ptype ptr return λx.ptype ptr = x → res xpointer with |
---|
37 | [ XData ⇒ λprf.return «ptr, prf» |
---|
38 | | _ ⇒ λ_.Error … [MSG BadPointer] |
---|
39 | ] (refl …). |
---|
40 | |
---|
41 | definition hwreg_store_sp : hw_register_env → xpointer → hw_register_env ≝ |
---|
42 | λenv,sp. |
---|
43 | let 〈spl, sph〉 ≝ beval_pair_of_pointer sp in |
---|
44 | hwreg_store RegisterSPH sph (hwreg_store RegisterSPL spl env). |
---|
45 | |
---|
46 | definition init_hw_register_env: xpointer → hw_register_env ≝ |
---|
47 | hwreg_store_sp (mk_hw_register_env (Stub …) BBundef). |
---|
48 | |
---|
49 | (*** Store/retrieve on pseudo-registers ***) |
---|
50 | include alias "common/Identifiers.ma". |
---|
51 | |
---|
52 | unification hint 0 ≔ X ⊢ register_env X ≡ identifier_map RegisterTag X. |
---|
53 | |
---|
54 | (******************************** GRAPHS **************************************) |
---|
55 | |
---|
56 | record sem_graph_params : Type[1] ≝ |
---|
57 | { sgp_pars : uns_params |
---|
58 | ; sgp_sup : ∀F.sem_unserialized_params sgp_pars F |
---|
59 | ; graph_pre_main_generator : |
---|
60 | ∀p : joint_program (mk_graph_params sgp_pars). |
---|
61 | joint_closed_internal_function (mk_graph_params sgp_pars) (prog_names … p) |
---|
62 | }. |
---|
63 | |
---|
64 | |
---|
65 | definition sem_graph_params_to_graph_params : |
---|
66 | ∀pars : sem_graph_params.graph_params ≝ |
---|
67 | λpars.mk_graph_params (sgp_pars pars). |
---|
68 | |
---|
69 | coercion graph_params_from_sem_graph_params nocomposites : |
---|
70 | ∀pars : sem_graph_params. |
---|
71 | graph_params ≝ sem_graph_params_to_graph_params |
---|
72 | on _pars : sem_graph_params to graph_params. |
---|
73 | |
---|
74 | definition sem_graph_params_to_sem_params : |
---|
75 | ∀pars : sem_graph_params. |
---|
76 | sem_params ≝ |
---|
77 | λpars. |
---|
78 | mk_sem_params |
---|
79 | (mk_serialized_params |
---|
80 | (pars : graph_params) |
---|
81 | (sgp_sup pars ?) |
---|
82 | (word_of_identifier ?) |
---|
83 | (an_identifier ?) |
---|
84 | ? (refl …)) |
---|
85 | (graph_pre_main_generator pars). |
---|
86 | * #p % qed. |
---|
87 | |
---|
88 | coercion sem_params_from_sem_graph_params : |
---|
89 | ∀pars : sem_graph_params. |
---|
90 | sem_params ≝ sem_graph_params_to_sem_params |
---|
91 | on _pars : sem_graph_params to sem_params. |
---|
92 | |
---|
93 | |
---|
94 | (******************************** LINEAR **************************************) |
---|
95 | |
---|
96 | lemma succ_pos_of_nat_of_pos : ∀p.succ_pos_of_nat (nat_of_pos p) = succ p. |
---|
97 | @pos_elim [%] |
---|
98 | #p #IH >nat_possucc whd in ⊢ (??%?); >IH % qed. |
---|
99 | |
---|
100 | record sem_lin_params : Type[1] ≝ |
---|
101 | { slp_pars : uns_params |
---|
102 | ; slp_sup : ∀F.sem_unserialized_params slp_pars F |
---|
103 | ; lin_pre_main_generator : |
---|
104 | ∀p : joint_program (mk_lin_params slp_pars). |
---|
105 | joint_closed_internal_function (mk_lin_params slp_pars) (prog_names … p) |
---|
106 | }. |
---|
107 | |
---|
108 | definition sem_lin_params_to_lin_params : |
---|
109 | ∀pars : sem_lin_params.lin_params ≝ |
---|
110 | λpars.mk_lin_params (slp_pars pars). |
---|
111 | |
---|
112 | coercion lin_params_from_sem_lin_params nocomposites : |
---|
113 | ∀pars : sem_lin_params. |
---|
114 | lin_params ≝ sem_lin_params_to_lin_params |
---|
115 | on _pars : sem_lin_params to lin_params. |
---|
116 | |
---|
117 | definition sem_lin_params_to_sem_params : |
---|
118 | ∀pars : sem_lin_params. |
---|
119 | sem_params ≝ |
---|
120 | λpars. |
---|
121 | mk_sem_params |
---|
122 | (mk_serialized_params |
---|
123 | (pars : lin_params) |
---|
124 | (slp_sup pars ?) |
---|
125 | succ_pos_of_nat |
---|
126 | (λp.pred (nat_of_pos p)) |
---|
127 | ??) |
---|
128 | (lin_pre_main_generator pars). |
---|
129 | [ @pos_cases [%] #p >nat_possucc @succ_pos_of_nat_of_pos |
---|
130 | | #n >nat_succ_pos % |
---|
131 | ] qed. |
---|
132 | |
---|
133 | coercion sem_params_from_sem_lin_params : |
---|
134 | ∀pars : sem_lin_params. |
---|
135 | sem_params ≝ sem_lin_params_to_sem_params |
---|
136 | on _pars : sem_lin_params to sem_params. |
---|
137 | |
---|
138 | (* TODO move elsewhere *) |
---|
139 | lemma lookup_opt_pm_set_elim : ∀A.∀P : option A → Prop.∀p,q,o,m. |
---|
140 | (p = q → P o) → |
---|
141 | (p ≠ q → P (lookup_opt A p m)) → |
---|
142 | P (lookup_opt A p (pm_set A q o m)). |
---|
143 | #A #P #p #q |
---|
144 | @(eqb_elim p q) #H #o #m #H1 #H2 |
---|
145 | [ >H >lookup_opt_pm_set_hit @H1 @H |
---|
146 | | >lookup_opt_pm_set_miss [ @H2 ] @H |
---|
147 | ] |
---|
148 | qed. |
---|
149 | |
---|
150 | lemma lookup_add_elim : ∀tag,A.∀P : option A → Prop.∀m,i,j,x. |
---|
151 | (i = j → P (Some ? x)) → |
---|
152 | (i ≠ j → P (lookup tag A m j)) → |
---|
153 | P (lookup tag A (add tag A m i x) j). |
---|
154 | #tag #A #P * #m * #p * #q #x |
---|
155 | #H1 #H2 whd in ⊢ (?%); normalize nodelta whd in match insert; normalize nodelta |
---|
156 | @lookup_opt_pm_set_elim #H destruct |
---|
157 | [ @H1 % | @H2 % #EQ destruct cases H #H @H % ] |
---|
158 | qed. |
---|
159 | |
---|
160 | lemma fetch_statement_eq : ∀p:sem_params.∀g. |
---|
161 | ∀ge : genv p g.∀ptr : program_counter. |
---|
162 | ∀i,fn,s. |
---|
163 | fetch_internal_function … ge (pc_block ptr) = OK … 〈i, fn〉 → |
---|
164 | let pt ≝ point_of_pc … ptr in |
---|
165 | stmt_at … (joint_if_code … fn) pt = Some ? s → |
---|
166 | fetch_statement … ge ptr = OK … 〈i, fn, s〉. |
---|
167 | #p #g #ge #ptr #i #f #s #EQ1 #EQ2 |
---|
168 | whd in match fetch_statement; normalize nodelta >EQ1 >m_return_bind |
---|
169 | >EQ2 % |
---|
170 | qed. |
---|
171 | |
---|
172 | lemma fetch_statement_inv : ∀p:sem_params.∀g. |
---|
173 | ∀ge : genv p g.∀ptr : program_counter. |
---|
174 | ∀i,fn,s. |
---|
175 | fetch_statement … ge ptr = OK … 〈i, fn, s〉 → |
---|
176 | fetch_internal_function … ge (pc_block ptr) = OK … 〈i, fn〉 ∧ |
---|
177 | let pt ≝ point_of_pc p ptr in |
---|
178 | stmt_at … (joint_if_code … fn) pt = Some ? s. |
---|
179 | #p #g #ge #ptr #i #fn #s #H |
---|
180 | elim (bind_inversion ????? H) * #i #f' * #EQ1 -H #H |
---|
181 | elim (bind_inversion ????? H) #s' * -H #H |
---|
182 | lapply (opt_eq_from_res ???? H) -H #EQ2 |
---|
183 | whd in ⊢ (??%%→?); #EQ destruct(EQ) %{EQ1 EQ2} |
---|
184 | qed. |
---|
185 | |
---|
186 | definition pm_P : ∀A,B.∀P : A → B → Prop.positive_map A → positive_map B → Prop ≝ |
---|
187 | λA,B,P,mA,mB. |
---|
188 | ∀p. |
---|
189 | match lookup_opt … p mA with |
---|
190 | [ Some a ⇒ |
---|
191 | match lookup_opt … p mB with |
---|
192 | [ Some b ⇒ P a b |
---|
193 | | _ ⇒ False |
---|
194 | ] |
---|
195 | | _ ⇒ match lookup_opt … p mB with |
---|
196 | [ Some _ ⇒ False |
---|
197 | | _ ⇒ True |
---|
198 | ] |
---|
199 | ]. |
---|
200 | |
---|
201 | definition match_funct_map : |
---|
202 | ∀M : matching. |
---|
203 | ∀vars.positive_map (m_A M vars) → positive_map (m_B M vars) → Prop ≝ |
---|
204 | λM,vars.pm_P … (match_fundef M ?). |
---|
205 | |
---|
206 | lemma pm_P_insert : |
---|
207 | ∀A,B,P. |
---|
208 | ∀p,a1,a2,m1,m2.P a1 a2 → pm_P A B P m1 m2 → |
---|
209 | pm_P … P (insert … p a1 m1) (insert … p a2 m2). |
---|
210 | #A #B #P #p #a1 #a2 #m1 #m2 #Pa1a2 #Pm1m2 |
---|
211 | #p' |
---|
212 | @(eqb_elim p' p) #H destruct |
---|
213 | [ >lookup_opt_insert_hit >lookup_opt_insert_hit @Pa1a2 |
---|
214 | | >(lookup_opt_insert_miss … a1 … H) >(lookup_opt_insert_miss … a2 … H) |
---|
215 | @Pm1m2 |
---|
216 | ] |
---|
217 | qed. |
---|
218 | |
---|
219 | lemma pm_P_set_None : |
---|
220 | ∀A,B,P. |
---|
221 | ∀p,m1,m2.pm_P A B P m1 m2 → |
---|
222 | pm_P … P (pm_set … p (None ?) m1) (pm_set … p (None ?) m2). |
---|
223 | #A #B #P #p #m1 #m2 #Pm1m2 |
---|
224 | #p' |
---|
225 | @(eqb_elim p' p) #H destruct |
---|
226 | [ >lookup_opt_pm_set_hit >lookup_opt_pm_set_hit % |
---|
227 | | >(lookup_opt_pm_set_miss … H) >(lookup_opt_pm_set_miss … H) |
---|
228 | @Pm1m2 |
---|
229 | ] |
---|
230 | qed. |
---|
231 | |
---|
232 | record match_genv_t (M : matching) |
---|
233 | (vars : list ident) |
---|
234 | (ge1 : genv_t (m_A M vars)) (ge2 : genv_t (m_B M vars)) : Prop ≝ |
---|
235 | { symbols_eq : symbols … ge1 = symbols … ge2 |
---|
236 | ; nextfunction_eq : nextfunction … ge1 = nextfunction … ge2 |
---|
237 | ; functions_match : pm_P ?? (match_fundef M ?) (functions … ge1) (functions … ge2) |
---|
238 | }. |
---|
239 | |
---|
240 | lemma add_globals_match : |
---|
241 | ∀M : matching.∀initV,initW. |
---|
242 | ∀vars1,vars2. |
---|
243 | ∀vars. |
---|
244 | (* let vars1' ≝ map … (λx.\fst (\fst x)) vars1 in |
---|
245 | let vars2' ≝ map … (λx.\fst (\fst x)) vars2 in *) |
---|
246 | ∀env_mem1 : genv_t (m_A M vars) × mem. |
---|
247 | ∀env_mem2 : genv_t (m_B M vars) × mem. |
---|
248 | All2 (ident×region×(m_V M)) (ident×region×(m_W M)) |
---|
249 | (match_var_entry M) vars1 vars2 → |
---|
250 | nextblock … (\snd env_mem1) = nextblock … (\snd env_mem2) → |
---|
251 | match_genv_t M vars |
---|
252 | (\fst env_mem1) (\fst env_mem2) → |
---|
253 | match_genv_t M vars |
---|
254 | (\fst (add_globals … initV env_mem1 vars1)) |
---|
255 | (\fst (add_globals … initW env_mem2 vars2)). |
---|
256 | #M #init1 #init2 #vars1 |
---|
257 | elim vars1 -vars1 [2: ** #id1 #r1 #v1 #tl1 #IH ] |
---|
258 | * [2,4: ** #id2 #r2 #v2 #tl2 ] |
---|
259 | #vars * #env1 #mem1 * #env2 #mem2 * |
---|
260 | [2: #_ #H @H ] |
---|
261 | #H inversion H #id' #r' #v1' #v2' #P #EQ1 #EQ2 #_ destruct -H #H |
---|
262 | #EQnxtbl #G @(IH tl2 … H) |
---|
263 | cases mem1 in EQnxtbl; -mem1 #mem1 #nbl1 #prf1 |
---|
264 | cases mem2 -mem2 #mem2 #nbl2 #prf2 #EQ destruct |
---|
265 | [ % ] |
---|
266 | normalize nodelta % |
---|
267 | whd in match add_symbol; |
---|
268 | whd in match drop_fn; normalize nodelta |
---|
269 | [ >(symbols_eq … G) % |
---|
270 | | @(nextfunction_eq … G) |
---|
271 | | >(symbols_eq … G) cases (lookup ? block ??) normalize nodelta |
---|
272 | [2: ** [2,3: #p] normalize nodelta ] |
---|
273 | try @pm_P_set_None |
---|
274 | @(functions_match … G) |
---|
275 | ] |
---|
276 | qed. |
---|
277 | |
---|
278 | lemma add_functs_match : |
---|
279 | ∀M : matching. |
---|
280 | ∀vars. |
---|
281 | ∀functs1,functs2. |
---|
282 | (* let vars1' ≝ map … (λx.\fst (\fst x)) vars1 in |
---|
283 | let vars2' ≝ map … (λx.\fst (\fst x)) vars2 in *) |
---|
284 | ∀env1 : genv_t (m_A M vars). |
---|
285 | ∀env2 : genv_t (m_B M vars). |
---|
286 | All2 … |
---|
287 | (match_funct_entry M vars vars) functs1 functs2 → |
---|
288 | match_genv_t M vars env1 env2 → |
---|
289 | match_genv_t M vars |
---|
290 | (add_functs … env1 functs1) |
---|
291 | (add_functs … env2 functs2). |
---|
292 | #M #vars #functs1 elim functs1 -functs1 [2: * #id1 #f1 #tl1 #IH ] |
---|
293 | * [2,4: * #id2 #f2 #tl2 ] |
---|
294 | #env1 #env2 * |
---|
295 | [2: #H @H ] |
---|
296 | #H |
---|
297 | cut (id1 = id2 ∧ match_fundef M … f1 f2) |
---|
298 | [ @(match_funct_entry_inv M ??????? H) #v #i #f1 #f2 #H %{H} % ] |
---|
299 | * #EQ destruct #Pf1f2 #Ptl1tl2 #G |
---|
300 | lapply (IH … Ptl1tl2 G) -G #G |
---|
301 | % |
---|
302 | whd in |
---|
303 | match (add_functs ?? (? :: tl1)); |
---|
304 | whd in |
---|
305 | match (add_functs ?? (? :: tl2)); |
---|
306 | change with (add_functs ?? tl1) in match (foldr ???? tl1); |
---|
307 | change with (add_functs ?? tl2) in match (foldr ???? tl2); |
---|
308 | whd in match drop_fn; normalize nodelta |
---|
309 | [ >(nextfunction_eq … G) >(symbols_eq … G) % |
---|
310 | | >(nextfunction_eq … G) % |
---|
311 | | >(symbols_eq … G) cases (lookup ? block ??) normalize nodelta |
---|
312 | [2: ** [2,3: #p] normalize nodelta ] |
---|
313 | >(nextfunction_eq … G) |
---|
314 | @(pm_P_insert … Pf1f2) |
---|
315 | try @pm_P_set_None @(functions_match … G) |
---|
316 | ] |
---|
317 | qed. |
---|
318 | |
---|
319 | lemma globalenv_match: |
---|
320 | ∀M:matching.∀initV,initW. |
---|
321 | (∀v,w. match_var_entry M v w → |
---|
322 | size_init_data_list (initV (\snd v)) = size_init_data_list (initW (\snd w))) → |
---|
323 | ∀p: program (m_A M) (m_V M). ∀p': program (m_B M) (m_W M). |
---|
324 | ∀MATCH:match_program … M p p'. |
---|
325 | match_genv_t M ? (globalenv … initV p) |
---|
326 | (globalenv … initW p' ⌈prog_var_names … p' ↦ prog_var_names … p⌉). |
---|
327 | [2: @sym_eq @(matching_vars … (mp_vars … MATCH)) ] |
---|
328 | * #A #B #V #W #Pf #Pv #iV #iW #init_eq |
---|
329 | * #vars1 #functs1 #main1 |
---|
330 | * #vars2 #functs2 #main2 |
---|
331 | * |
---|
332 | whd in match prog_var_names; |
---|
333 | normalize nodelta; |
---|
334 | #Mvars #Mfns #EQmain destruct |
---|
335 | lapply (sym_eq ????) |
---|
336 | #E |
---|
337 | lapply Mfns lapply functs2 -functs2 |
---|
338 | whd in match globalenv; whd in match globalenv_allocmem; |
---|
339 | whd in match prog_var_names in E ⊢ %; |
---|
340 | normalize nodelta in E ⊢ %; |
---|
341 | >E normalize nodelta #functs2 #Mfns |
---|
342 | @add_globals_match [ assumption | % ] |
---|
343 | @add_functs_match [ assumption ] |
---|
344 | % try % #p % |
---|
345 | qed. |
---|
346 | |
---|
347 | lemma symbols_transf: |
---|
348 | ∀A,B,V,init.∀prog_in : program A V. |
---|
349 | ∀trans : ∀vars.A vars → B vars. |
---|
350 | let prog_out ≝ transform_program … prog_in trans in |
---|
351 | symbols … (globalenv … init prog_out) = symbols … (globalenv … init prog_in). |
---|
352 | #A #B #V #iV #p #tf whd |
---|
353 | lapply (transform_program_match … tf p) |
---|
354 | #MATCH |
---|
355 | >(symbols_eq … (globalenv_match … MATCH)) |
---|
356 | [2: @iV |3: #v #w * // ] |
---|
357 | lapply (sym_eq ????) |
---|
358 | whd in match (prog_var_names ???); whd in match (prog_vars B ??); |
---|
359 | #E >(K ?? E) normalize nodelta % |
---|
360 | qed. |
---|
361 | |
---|
362 | lemma functions_transf: |
---|
363 | ∀A,B,V,init.∀prog_in : program A V. |
---|
364 | ∀trans : ∀vars.A vars → B vars. |
---|
365 | let prog_out ≝ transform_program … prog_in trans in |
---|
366 | ∀p.lookup_opt … p (functions … (globalenv … init prog_out)) = |
---|
367 | option_map ?? (trans ?) (lookup_opt … p (functions … (globalenv … init prog_in))). |
---|
368 | #A #B #V #iV #p #tf #n |
---|
369 | lapply (transform_program_match … tf p) |
---|
370 | #MATCH |
---|
371 | whd in match globalenv; whd in match globalenv_allocmem; |
---|
372 | normalize nodelta |
---|
373 | lapply (functions_match … (globalenv_match … MATCH) n) |
---|
374 | [ @iV | @iV | #v #w * // ] |
---|
375 | lapply (sym_eq ????) |
---|
376 | whd in match (prog_var_names ???); whd in match (prog_vars B ??); |
---|
377 | #E >(K ?? E) normalize nodelta |
---|
378 | cases (lookup_opt ???) [2: #x ] normalize nodelta |
---|
379 | cases (lookup_opt ???) [2,4: #y ] normalize nodelta |
---|
380 | [ #EQ <EQ % |*: * % ] |
---|
381 | qed. |
---|
382 | |
---|
383 | lemma symbol_for_block_transf : |
---|
384 | ∀A,B,V,init.∀prog_in : program A V. |
---|
385 | ∀trans : ∀vars.A vars → B vars. |
---|
386 | let prog_out ≝ transform_program … prog_in trans in |
---|
387 | ∀bl. |
---|
388 | symbol_for_block … (globalenv … init prog_out) bl = |
---|
389 | symbol_for_block … (globalenv … init prog_in) bl. |
---|
390 | #A #B #V #iV #p #tf whd |
---|
391 | #bl |
---|
392 | whd in match symbol_for_block; normalize nodelta |
---|
393 | >(symbols_transf … tf) % |
---|
394 | qed. |
---|
395 | |
---|
396 | include alias "common/Pointers.ma". |
---|
397 | |
---|
398 | (* TODO move *) |
---|
399 | lemma Exists_mp : ∀A,P,Q,l.(∀x.P x → Q x) → Exists A P l → Exists A Q l. |
---|
400 | #A #P #Q #l #H elim l -l [2: #hd #tl #IH] * #G whd /3 by or_introl, or_intror/ qed. |
---|
401 | |
---|
402 | definition joint_globalenv : |
---|
403 | ∀p : sem_params.∀pr:joint_program p. |
---|
404 | (ident → option ℕ) → genv p (prog_names … pr) ≝ |
---|
405 | λp,prog,stacksizes. |
---|
406 | let genv ≝ globalenv … (λx.x) prog in |
---|
407 | let pc_from_lbl ≝ λbl.λfn : joint_closed_internal_function p ?.λlbl. |
---|
408 | ! pt ← point_of_label … (joint_if_code … fn) lbl ; |
---|
409 | return mk_program_counter bl (offset_of_point … p pt) in |
---|
410 | mk_genv_gen ?? genv ? stacksizes (pre_main_generator … p prog) pc_from_lbl. |
---|
411 | #s #H |
---|
412 | cases (find_symbol_exists ?? (λx.x) … prog s ?) |
---|
413 | [ #bl #EQ >EQ % #ABS destruct ] |
---|
414 | cases (Exists_append … H) -H #H |
---|
415 | [ @Exists_append_r | @Exists_append_l ] |
---|
416 | [ @(Exists_mp … H) @sym_eq ] |
---|
417 | cases prog in H; #functs * #vars #functs' #main #init_cost |
---|
418 | whd in match prog_funct_names; normalize nodelta #EQ |
---|
419 | >map_ext_eq [ >EQ @Exists_mp @sym_eq | // ] skip |
---|
420 | qed. |
---|
421 | |
---|
422 | lemma opt_to_res_bind : ∀X,Y,m,f,e.opt_to_res Y e (! x ← m ; f x) = |
---|
423 | ! x ← opt_to_res X e m ; opt_to_res Y e (f x). |
---|
424 | #X #Y * [2: #x] #f #e % qed. |
---|
425 | |
---|
426 | lemma fetch_function_transf: |
---|
427 | ∀src,dst : sem_params.∀prog_in : joint_program src. |
---|
428 | ∀stacksizes,trans. |
---|
429 | let prog_out ≝ transform_joint_program src dst trans prog_in in |
---|
430 | ∀bl. |
---|
431 | fetch_function … (joint_globalenv … prog_out stacksizes) bl = |
---|
432 | if eqZb (block_id bl) (-1) then |
---|
433 | return 〈pre_main_id, Internal ? (pre_main_generator … dst prog_out)〉 |
---|
434 | else |
---|
435 | ! 〈id, f〉 ← fetch_function … (joint_globalenv … prog_in stacksizes) bl ; |
---|
436 | return 〈id, transf_fundef ?? (trans ?) f〉. |
---|
437 | #src #dst #p #sizes #tf whd |
---|
438 | lapply (transform_program_match … (λvars.transf_fundef … (tf ?)) p) |
---|
439 | #MATCH |
---|
440 | whd in match fetch_function; |
---|
441 | whd in match joint_globalenv; normalize nodelta |
---|
442 | #bl @eqZb_elim #Hbl normalize nodelta [ % ] |
---|
443 | whd in match transform_joint_program; |
---|
444 | whd in match prog_names; normalize nodelta |
---|
445 | >symbol_for_block_transf |
---|
446 | >opt_to_res_bind >opt_to_res_bind in ⊢ (???%); >m_bind_bind |
---|
447 | @m_bind_ext_eq #id |
---|
448 | whd in match find_funct_ptr; normalize nodelta |
---|
449 | cases bl -bl ** [2,3: #p] normalize nodelta #_ try % |
---|
450 | lapply (functions_match … (globalenv_match … MATCH) p) try @(λx.x) |
---|
451 | [#v #w * //] |
---|
452 | lapply (sym_eq ????) |
---|
453 | whd in match prog_var_names; normalize nodelta |
---|
454 | #E >(K ?? E) -E normalize nodelta |
---|
455 | cases (lookup_opt ???) [2: #x ] normalize nodelta |
---|
456 | cases (lookup_opt ???) [2,4: #y ] normalize nodelta |
---|
457 | * % |
---|
458 | qed. |
---|
459 | |
---|
460 | lemma fetch_internal_function_transf : |
---|
461 | ∀src,dst : sem_params.∀prog_in : joint_program src. |
---|
462 | ∀stacksizes,trans. |
---|
463 | let prog_out ≝ transform_joint_program src dst trans prog_in in |
---|
464 | ∀bl. |
---|
465 | fetch_internal_function … (joint_globalenv … prog_out stacksizes) bl = |
---|
466 | if eqZb (block_id bl) (-1) then |
---|
467 | return 〈pre_main_id, pre_main_generator … dst prog_out〉 |
---|
468 | else |
---|
469 | ! 〈i, f〉 ← fetch_internal_function … (joint_globalenv … prog_in stacksizes) bl ; |
---|
470 | return 〈i, trans … f〉. |
---|
471 | #src #dst #p #sizes #tf whd |
---|
472 | #bl whd in match fetch_internal_function; normalize nodelta |
---|
473 | >(fetch_function_transf … p) |
---|
474 | @eqZb_elim #Hbl [%] normalize nodelta >m_bind_bind >m_bind_bind |
---|
475 | @m_bind_ext_eq * #id * #f % |
---|
476 | qed. |
---|
477 | |
---|
478 | include alias "utilities/binary/positive.ma". |
---|
479 | |
---|
480 | lemma pm_map_add_ind : ∀A.∀P : positive_map A → Prop. |
---|
481 | (∀m.(∀p.lookup_opt A p m = None ?) → P m) → |
---|
482 | (∀m,p,v.P m → lookup_opt A p m = None ? → P (insert A p v m)) → |
---|
483 | ∀m.P m. |
---|
484 | #A #P #H1 #H2 #m lapply H2 lapply H1 lapply P -P elim m -m |
---|
485 | [ #P #H1 #_ @H1 #p % ] |
---|
486 | #o #l #r #IHl #IHr #P #H1 #H2 |
---|
487 | @IHl #l' |
---|
488 | [ #empty_l' @IHr #r' |
---|
489 | [ #empty_r' cases o [ @H1 * try #p normalize // ] |
---|
490 | #v change with (P (insert ? one v (pm_node ? (None ?) ??))) |
---|
491 | @H2 [ @H1 * try #p normalize // | % ] |
---|
492 | ] |
---|
493 | ] |
---|
494 | #p #v #H #G |
---|
495 | [ change with (P (insert ? (p1 p) v (pm_node ? ???))) |
---|
496 | | change with (P (insert ? (p0 p) v (pm_node ? ???))) |
---|
497 | ] @H2 assumption |
---|
498 | qed. |
---|
499 | |
---|
500 | include alias "basics/logic.ma". |
---|
501 | include alias "common/PositiveMap.ma". |
---|
502 | |
---|
503 | lemma swap_neg : ∀A,B : Prop.(A → B) → ¬B → ¬A. |
---|
504 | #A #B #impl * #Bf % #At @Bf @impl @At qed-. |
---|
505 | |
---|
506 | definition b_graph_transform_program_props ≝ |
---|
507 | λsrc,dst : sem_graph_params. |
---|
508 | λstacksizes. |
---|
509 | λdata,prog_in. |
---|
510 | λinit_regs : block → list register. |
---|
511 | λf_lbls : block → label → list label. |
---|
512 | λf_regs : block → label → list register. |
---|
513 | let prog_out ≝ b_graph_transform_program src dst data prog_in in |
---|
514 | let src_genv ≝ joint_globalenv src prog_in stacksizes in |
---|
515 | let dst_genv ≝ joint_globalenv dst prog_out stacksizes in |
---|
516 | ∀bl,def_in. |
---|
517 | find_funct_ptr … src_genv bl = return (Internal ? def_in) → |
---|
518 | ∃init_data,def_out. |
---|
519 | find_funct_ptr … dst_genv bl = return (Internal ? def_out) ∧ |
---|
520 | bind_new_instantiates … init_data (data … def_in) (init_regs bl) ∧ |
---|
521 | b_graph_translate_props src dst ? init_data |
---|
522 | def_in def_out (f_lbls bl) (f_regs bl). |
---|
523 | |
---|
524 | lemma make_b_graph_transform_program_props : |
---|
525 | ∀src,dst:sem_graph_params. |
---|
526 | ∀stacksizes. |
---|
527 | ∀data : ∀globals.joint_closed_internal_function src globals → |
---|
528 | bound_b_graph_translate_data src dst globals. |
---|
529 | ∀prog_in : joint_program src. |
---|
530 | let prog_out ≝ b_graph_transform_program … data prog_in in |
---|
531 | let src_genv ≝ joint_globalenv src prog_in stacksizes in |
---|
532 | let dst_genv ≝ joint_globalenv dst prog_out stacksizes in |
---|
533 | ∃init_regs : block → list register. |
---|
534 | ∃f_lbls : block → label → list label. |
---|
535 | ∃f_regs : block → label → list register. |
---|
536 | b_graph_transform_program_props src dst stacksizes data prog_in init_regs f_lbls f_regs. |
---|
537 | cases daemon (* TOREDO |
---|
538 | #src #dst #data #prog_in |
---|
539 | whd in match b_graph_transform_program_props; normalize nodelta |
---|
540 | whd in match joint_globalenv; normalize nodelta |
---|
541 | letin prog_out ≝ (b_graph_transform_program … data prog_in) |
---|
542 | letin src_genv ≝ (globalenv … (λx.x) prog_in) |
---|
543 | letin dst_genv ≝ (globalenv … (λx.x) prog_out) |
---|
544 | cut (∀p.lookup_opt ? p (functions ? dst_genv) = |
---|
545 | option_map ?? (transf_fundef … (λf.b_graph_translate … (data … f) f)) |
---|
546 | (lookup_opt ? p (functions ? src_genv))) |
---|
547 | [ @functions_transf ] |
---|
548 | cut (symbols ? dst_genv = symbols ? src_genv) |
---|
549 | [ @symbols_transf ] |
---|
550 | cases dst_genv #functs2 #nextf2 #symbols2 #H2 |
---|
551 | cases src_genv #functs1 #nextf1 #symbols1 #H1 #EQ destruct |
---|
552 | lapply H2 lapply H1 lapply functs2 |
---|
553 | @(pm_map_add_ind … functs1) -functs1 -functs2 #functs1 |
---|
554 | [ #functs1_empty | #p #f #IH #p_not_in ] |
---|
555 | #functs2 #H1 #H2 #transf |
---|
556 | [ %{(λ_.[ ])} %{(λ_.λ_.[])} %{(λ_.λ_.[])} |
---|
557 | #bl #def_in #ABS1 #ABS2 @⊥ lapply ABS2 -ABS2 lapply ABS1 -ABS1 |
---|
558 | whd in match find_funct_ptr; |
---|
559 | whd in match find_symbol; |
---|
560 | normalize nodelta |
---|
561 | cases bl; * normalize nodelta |
---|
562 | [2,3: #p ] |
---|
563 | [1,3: #_ whd in ⊢ (???%→?); #EQ destruct ] |
---|
564 | >lookup_add_hit |
---|
565 | #H >lookup_opt_insert_miss |
---|
566 | [2: @(swap_neg … H) #EQ >EQ % ] |
---|
567 | whd in match drop_fn; normalize nodelta |
---|
568 | cases (lookup … symbols1 pre_main_id) |
---|
569 | normalize nodelta |
---|
570 | [ >functs1_empty | ** [2,3: #p' ] normalize nodelta |
---|
571 | [1,3: >functs1_empty |
---|
572 | | @lookup_opt_pm_set_elim #H destruct |
---|
573 | [2: >functs1_empty ] |
---|
574 | ] |
---|
575 | ] whd in ⊢ (???%→?); #EQ destruct |
---|
576 | ] |
---|
577 | cases (IH (pm_set … p (None ?) functs2) ???) |
---|
578 | [|*: @hide_prf |
---|
579 | [ #b #G @(H1 b ?) @(swap_neg … G) -G |
---|
580 | whd in match insert; normalize nodelta |
---|
581 | @lookup_opt_pm_set_elim |
---|
582 | [ #EQ #ABS destruct ] |
---|
583 | #NEQ #H @H |
---|
584 | | #b #G @(H2 b ?) @(swap_neg … G) -G |
---|
585 | @lookup_opt_pm_set_elim |
---|
586 | [ #_ #_ % ] |
---|
587 | #_ #H @H |
---|
588 | | #b @lookup_opt_pm_set_elim |
---|
589 | [ #EQ destruct >p_not_in % ] |
---|
590 | #NEQ >transf |
---|
591 | >(lookup_opt_insert_miss ? f b p … NEQ) % |
---|
592 | ] |
---|
593 | ] |
---|
594 | #init_regs * #f_lbls * #f_regs #props |
---|
595 | -IH cases f in H1 transf; -f #f #H1 #transf |
---|
596 | [ (* internal *) |
---|
597 | letin upd ≝ (λA : Type[0].λf : block → A. |
---|
598 | λid.λv,id'. |
---|
599 | if eq_block id id' then v else f id') |
---|
600 | cases (pi2 ?? (b_graph_translate … (data … f) f)) |
---|
601 | #loc_data * #loc_init_regs * #loc_f_lbls * #loc_f_regs * |
---|
602 | #inst_loc_data #loc_props |
---|
603 | letin bl ≝ (mk_block (neg p)) |
---|
604 | %{(upd … init_regs bl loc_init_regs)} |
---|
605 | %{(upd … f_lbls bl loc_f_lbls)} |
---|
606 | %{(upd … f_regs bl loc_f_regs)} |
---|
607 | | (* external, nothing changes *) |
---|
608 | %{init_regs} |
---|
609 | %{f_lbls} |
---|
610 | %{f_regs} |
---|
611 | ] |
---|
612 | * #p' #def_in |
---|
613 | whd in match find_funct_ptr; normalize nodelta |
---|
614 | whd in match (block_region (mk_block p')); |
---|
615 | cases p' -p' [2,3,5,6: #p' ] normalize nodelta |
---|
616 | [1,3,5,6: #_ #ABS normalize in ABS; destruct] |
---|
617 | whd in match find_symbol; |
---|
618 | whd in match insert; normalize nodelta |
---|
619 | #bl_prf |
---|
620 | @lookup_opt_pm_set_elim #pp' destruct |
---|
621 | [1,3: whd in ⊢ (??%%→?); #EQ destruct(EQ) |
---|
622 | [ %{loc_data} % |
---|
623 | [2: % [ % ] |
---|
624 | [ >lookup_opt_insert_hit % |
---|
625 | |*: >eq_block_b_b assumption |
---|
626 | ] |
---|
627 | |] |
---|
628 | |*: >(lookup_opt_insert_miss ???? functs1 … pp') |
---|
629 | [ @eq_block_elim [ #EQ destruct cases (absurd ?? pp') % ] #_ normalize nodelta] |
---|
630 | #EQ lapply (props (mk_block (neg p')) def_in EQ) |
---|
631 | whd in match find_funct_ptr; normalize nodelta |
---|
632 | >(lookup_opt_pm_set_miss … functs2 … pp') #H @H |
---|
633 | ] *) |
---|
634 | qed. |
---|
635 | |
---|
636 | lemma if_elim' : ∀A : Type[0].∀P : A → Prop.∀b : bool.∀c1,c2 : A. |
---|
637 | (b → P c1) → (¬(bool_to_Prop b) → P c2) → P (if b then c1 else c2). |
---|
638 | #A #P * /3 by Prop_notb/ qed. |
---|
639 | |
---|
640 | lemma b_graph_transform_program_fetch_internal_function : |
---|
641 | ∀src,dst:sem_graph_params. |
---|
642 | ∀stacksizes. |
---|
643 | ∀data : ∀globals.joint_closed_internal_function src globals → |
---|
644 | bound_b_graph_translate_data src dst globals. |
---|
645 | ∀prog_in : joint_program src. |
---|
646 | ∀init_regs : block → list register. |
---|
647 | ∀f_lbls : block → label → list label. |
---|
648 | ∀f_regs : block → label → list register. |
---|
649 | b_graph_transform_program_props … stacksizes data prog_in init_regs f_lbls f_regs → |
---|
650 | let prog_out ≝ b_graph_transform_program … data prog_in in |
---|
651 | let src_genv ≝ joint_globalenv src prog_in stacksizes in |
---|
652 | let dst_genv ≝ joint_globalenv dst prog_out stacksizes in |
---|
653 | ∀bl : Σbl.block_region … bl = Code.∀id,def_in. |
---|
654 | if eqZb (block_id … bl) (-1) then |
---|
655 | (fetch_internal_function … dst_genv bl = |
---|
656 | return 〈pre_main_id, pre_main_generator … dst prog_out〉) |
---|
657 | else |
---|
658 | (fetch_internal_function … src_genv bl = return 〈id, def_in〉 → |
---|
659 | ∃init_data,def_out. |
---|
660 | fetch_internal_function … dst_genv bl = return 〈id, def_out〉 ∧ |
---|
661 | bind_new_instantiates … init_data (data … def_in) (init_regs bl) ∧ |
---|
662 | b_graph_translate_props src dst ? init_data |
---|
663 | def_in def_out (f_lbls bl) (f_regs bl)). |
---|
664 | #src #dst #stacksizes #data #prog_in |
---|
665 | #init_regs #f_lbls #f_regs #props |
---|
666 | #bl #id #def_in |
---|
667 | @if_elim' #Hbl |
---|
668 | [ whd in match fetch_internal_function; whd in match fetch_function; |
---|
669 | normalize nodelta >Hbl % ] |
---|
670 | #H @('bind_inversion H) * #id' * #def_in' -H |
---|
671 | normalize nodelta [2: #_ whd in ⊢ (??%%→?); #ABS destruct ] |
---|
672 | whd in match fetch_function; normalize nodelta |
---|
673 | >Hbl normalize nodelta |
---|
674 | #H @('bind_inversion (opt_eq_from_res … H)) -H #id'' #EQ1 |
---|
675 | #H @('bind_inversion H) -H #def_in'' #H |
---|
676 | whd in ⊢ (??%%→??%%→?); #EQ2 #EQ3 destruct |
---|
677 | cases (props … H) |
---|
678 | #loc_data * #def_out ** #H1 #H2 #H3 |
---|
679 | %{loc_data} %{def_out} |
---|
680 | %{H3} %{H2} |
---|
681 | whd in match fetch_internal_function; |
---|
682 | whd in match fetch_function; normalize nodelta |
---|
683 | >Hbl normalize nodelta |
---|
684 | whd in match joint_globalenv; normalize nodelta |
---|
685 | whd in match prog_names; normalize nodelta |
---|
686 | >symbol_for_block_transf >EQ1 >m_return_bind |
---|
687 | >H1 % |
---|
688 | qed. |
---|
689 | |
---|
690 | lemma b_graph_transform_program_fetch_statement : |
---|
691 | ∀src,dst:sem_graph_params.∀stacksizes. |
---|
692 | ∀data : ∀globals.joint_closed_internal_function src globals → |
---|
693 | bound_b_graph_translate_data src dst globals. |
---|
694 | ∀prog_in : joint_program src. |
---|
695 | ∀init_regs : block → list register. |
---|
696 | ∀f_lbls : block → label → list label. |
---|
697 | ∀f_regs : block → label → list register. |
---|
698 | b_graph_transform_program_props … stacksizes data prog_in init_regs f_lbls f_regs → |
---|
699 | let prog_out ≝ b_graph_transform_program … data prog_in in |
---|
700 | let src_genv ≝ joint_globalenv src prog_in stacksizes in |
---|
701 | let dst_genv ≝ joint_globalenv dst prog_out stacksizes in |
---|
702 | ∀pc,id,def_in,s. |
---|
703 | if eqZb (block_id … (pc_block … pc)) (-1) then |
---|
704 | (fetch_internal_function … dst_genv (pc_block … pc) = |
---|
705 | return 〈pre_main_id, pre_main_generator … dst prog_out〉) |
---|
706 | else |
---|
707 | (fetch_statement … src_genv pc = return 〈id, def_in, s〉 → |
---|
708 | ∃init_data,def_out. |
---|
709 | let bl ≝ pc_block pc in |
---|
710 | fetch_internal_function … dst_genv bl = return 〈id, def_out〉 ∧ |
---|
711 | bind_new_instantiates … init_data (data … def_in) (init_regs bl) ∧ |
---|
712 | let l ≝ point_of_pc dst pc in |
---|
713 | let lbls ≝ f_lbls bl l in let regs ≝ f_regs bl l in |
---|
714 | match s with |
---|
715 | [ sequential s' nxt ⇒ |
---|
716 | let block ≝ |
---|
717 | if not_emptyb … (added_prologue … init_data) ∧ |
---|
718 | eq_identifier … (joint_if_entry … def_in) l then |
---|
719 | bret … [ ] |
---|
720 | else |
---|
721 | f_step … init_data l s' in |
---|
722 | l ~❨block, l::lbls, regs❩~> nxt in joint_if_code … def_out |
---|
723 | | final s' ⇒ |
---|
724 | l ~❨f_fin … init_data l s', l::lbls, regs❩~> it in joint_if_code … def_out |
---|
725 | | FCOND abs _ _ _ ⇒ Ⓧabs |
---|
726 | ]). |
---|
727 | #src #dst #stacksizes #data #prog_in |
---|
728 | #init_regs #f_lbls #f_regs #props |
---|
729 | #pc #id #def_in #s |
---|
730 | lapply (b_graph_transform_program_fetch_internal_function … props |
---|
731 | (pc_block … pc) id def_in) |
---|
732 | @if_elim' #Hbl >Hbl normalize nodelta [ #H @H ] #G |
---|
733 | #H @('bind_inversion H) * #id' #def_in' -H |
---|
734 | #EQfif |
---|
735 | #H @('bind_inversion H) -H #s |
---|
736 | #H lapply (opt_eq_from_res ???? H) -H |
---|
737 | #EQstmt_at whd in ⊢ (??%%→?); #EQ destruct |
---|
738 | cases (G … EQfif) |
---|
739 | #a * #b ** #H1 #H2 #H3 %{a} %{b} % |
---|
740 | [ %{H1 H2} |
---|
741 | | @(multi_fetch_ok … H3 … EQstmt_at) |
---|
742 | ] |
---|
743 | qed. |
---|
744 | |
---|
745 | lemma b_graph_transform_program_fetch_statement_plus : |
---|
746 | ∀src,dst:sem_graph_params.∀stacksizes. |
---|
747 | ∀data : ∀globals.joint_closed_internal_function src globals → |
---|
748 | bound_b_graph_translate_data src dst globals. |
---|
749 | ∀prog_in : joint_program src. |
---|
750 | ∀init_regs : block → list register. |
---|
751 | ∀f_lbls : block → label → list label. |
---|
752 | ∀f_regs : block → label → list register. |
---|
753 | b_graph_transform_program_props … stacksizes data prog_in init_regs f_lbls f_regs → |
---|
754 | let prog_out ≝ b_graph_transform_program … data prog_in in |
---|
755 | let src_genv ≝ joint_globalenv src prog_in stacksizes in |
---|
756 | let dst_genv ≝ joint_globalenv dst prog_out stacksizes in |
---|
757 | ∀pc,id,def_in,s. |
---|
758 | if eqZb (block_id … (pc_block … pc)) (-1) then |
---|
759 | (fetch_internal_function … dst_genv (pc_block … pc) = |
---|
760 | return 〈pre_main_id, pre_main_generator … dst prog_out〉) |
---|
761 | else |
---|
762 | (fetch_statement … src_genv pc = return 〈id, def_in, s〉 → |
---|
763 | ∃init_data,def_out. |
---|
764 | let bl ≝ pc_block pc in |
---|
765 | fetch_internal_function … dst_genv bl = return 〈id, def_out〉 ∧ |
---|
766 | bind_new_instantiates … init_data (data … def_in) (init_regs bl) ∧ |
---|
767 | let l ≝ point_of_pc dst pc in |
---|
768 | let lbls ≝ f_lbls bl l in |
---|
769 | let regs ≝ f_regs bl l in |
---|
770 | partial_partition … (f_lbls bl) ∧ |
---|
771 | partial_partition … (f_regs bl) ∧ |
---|
772 | (∀l.All … |
---|
773 | (λlbl.¬fresh_for_univ … lbl (joint_if_luniverse … def_in) ∧ |
---|
774 | fresh_for_univ … lbl (joint_if_luniverse … def_out)) (f_lbls bl l)) ∧ |
---|
775 | (∀l.All … |
---|
776 | (λreg.¬fresh_for_univ … reg (joint_if_runiverse … def_in) ∧ |
---|
777 | fresh_for_univ … reg (joint_if_runiverse … def_out)) (f_regs bl l)) ∧ |
---|
778 | match s with |
---|
779 | [ sequential s' nxt ⇒ |
---|
780 | let block ≝ |
---|
781 | if not_emptyb … (added_prologue … init_data) ∧ |
---|
782 | eq_identifier … (joint_if_entry … def_in) l then |
---|
783 | bret … [ ] |
---|
784 | else |
---|
785 | f_step … init_data l s' in |
---|
786 | l ~❨block, l::lbls, regs❩~> nxt in joint_if_code … def_out |
---|
787 | | final s' ⇒ |
---|
788 | l ~❨f_fin … init_data l s', l::lbls, regs❩~> it in joint_if_code … def_out |
---|
789 | | FCOND abs _ _ _ ⇒ Ⓧabs |
---|
790 | ]). |
---|
791 | #src #dst #stacksizes #data #prog_in |
---|
792 | #init_regs #f_lbls #f_regs #props |
---|
793 | #pc #id #def_in #s |
---|
794 | lapply (b_graph_transform_program_fetch_internal_function … props … (pc_block … pc) id def_in) |
---|
795 | @if_elim' #Hbl >Hbl normalize nodelta |
---|
796 | [ #H @H ] #G |
---|
797 | #H @('bind_inversion H) * #id' #def_in' -H |
---|
798 | #EQfif |
---|
799 | #H @('bind_inversion H) -H #s |
---|
800 | #H lapply (opt_eq_from_res ???? H) -H |
---|
801 | #EQstmt_at whd in ⊢ (??%%→?); #EQ destruct |
---|
802 | cases (G … EQfif) |
---|
803 | #a * #b ** #H1 #H2 #H3 %{a} %{b} % |
---|
804 | [ %{H1 H2} |
---|
805 | | %{(multi_fetch_ok … H3 … EQstmt_at)} |
---|
806 | %{(freshness_regs … H3)} |
---|
807 | %{(freshness_lbls … H3)} |
---|
808 | %{(partition_regs … H3)} |
---|
809 | @(partition_lbls … H3) |
---|
810 | ] |
---|
811 | qed. |
---|