include "compiler.ma". include "ASM/Interpret2.ma". include "Clight/labelSimulation.ma". theorem correct : ∀observe,input_program,output. (* ∀lobject_code,labelled,cost_map. *) compile observe input_program = return output → not_wrong … (exec_inf … clight_fullexec input_program) → sim_with_labels (exec_inf … clight_fullexec input_program) (exec_inf … clight_fullexec (c_labelled_clight … output)) ∧ True (* TODO *). #observe #input_program #output #COMPILE #NOT_WRONG cases (bind_inversion ????? COMPILE) -COMPILE * * #init_cost #labelled' #rtlabs_program * #FRONTEND #COMPILE cases (bind_inversion ????? COMPILE) -COMPILE #lobject_code' * #ASSEMBLER #COMPILE whd in COMPILE:(??%%); destruct cases (bind_inversion ????? FRONTEND) -FRONTEND #cminor_program * #CMINOR #FRONTEND whd in FRONTEND:(??%%); destruct % [ (* Needs switch removal too, now @labelling_sim @NOT_WRONG *) cases daemon | @I ] qed. include "Clight/Clight_classified_system.ma". (* From measurable on Clight, we will end up with an RTLabs flat trace where we know that there are some m' and n' such that the prefix in Clight matches the prefix in RTLabs given by m', the next n steps in Clight are equivalent to the n' steps in RTLabs, and we have a suitable "will_return" for RTLabs for those n' steps so that we can build a corresponding structured trace. "Equivalent" here means, in particular, that the observables will be the same, and those observables will include the stack space costs. *) definition in_execution_prefix : execution_prefix Clight_state → costlabel → Prop ≝ λx,l. Exists … (λtrs. Exists … (λev. ev = EVcost l) (\fst trs)) x. let rec foldl_exists_aux (A,B:Type[0]) (l,l':list B) (f:A → ∀b:B. Exists … (λx.x=b) l → A) (a:A) on l' : (∀b. Exists … (λx.x=b) l' → Exists … (λx.x=b) l) → A ≝ match l' return λl'. (∀b. Exists … (λx.x=b) l' → Exists … (λx.x=b) l) → A with [ nil ⇒ λ_. a | cons h t ⇒ λH. foldl_exists_aux A B l t f (f a h (H …)) ? ]. [ %1 % | #b #H' @H %2 @H' ] qed. definition foldl_exists : ∀A,B:Type[0]. ∀l:list B. (A → ∀b:B. Exists … (λx. x = b ) l → A) → A → A ≝ λA,B,l,f,a. foldl_exists_aux A B l l f a (λb,H. H). lemma Exists_lift : ∀A,P,Q,l. (∀x. P x → Q x) → Exists A P l → Exists A Q l. #A #P #Q #l elim l [ // | #h #t #IH #H * [ #H' %1 @H @H' | #H' %2 @IH /2/ ] ] qed. definition measure_clock : ∀x:execution_prefix Clight_state. ((Σl:costlabel.in_execution_prefix x l)→ℕ) → nat ≝ λx,costmap. foldl_exists … x (λclock,trs,H. foldl_exists … (\fst trs) (λclock,ev. match ev return λev. Exists … (λx. x=ev) ? → nat with [ EVcost l ⇒ λH'. clock + costmap «l,?» | _ ⇒ λ_. clock ]) clock) 0. whd @(Exists_lift … H) * #tr1 #s1 #E destruct @(Exists_lift … H') #ev1 #E @E qed. definition clight_clock_after : ∀p:clight_program. nat → ((Σl:costlabel.in_clight_program p l)→ℕ) → option nat ≝ λp,n,costmap. let x ≝ exec_inf … clight_fullexec p in match split_trace … x n with [ Some traces ⇒ Some ? (measure_clock (\fst traces) (λl.costmap «l,?»)) | None ⇒ None ? ]. cases daemon qed. include "common/AssocList.ma". definition lookup_stack_cost : stack_cost_model → ident → nat ≝ λstack_cost,id. match assoc_list_lookup ?? id (eq_identifier …) stack_cost with [ None ⇒ 0 | Some n ⇒ n ]. definition simulates ≝ λp: compiler_output. let initial_status ≝ initialise_status … (load_code_memory (oc (c_labelled_object_code … p))) in ∀m1,m2. measurable Clight_pcs (c_labelled_clight … p) m1 m2 (lookup_stack_cost (c_stack_cost … p)) (c_max_stack … p) → ∀c1,c2. clight_clock_after (c_labelled_clight … p) m1 (c_clight_cost_map … p) = Some ? c1 → clight_clock_after (c_labelled_clight … p) m2 (c_clight_cost_map … p) = Some ? c2 → ∃n1,n2. observables Clight_pcs (c_labelled_clight … p) m1 m2 = observables (OC_preclassified_system (c_labelled_object_code … p)) (c_labelled_object_code … p) n1 n2 ∧ minus c2 c1 = clock … (execute n2 ? initial_status) - clock … (execute n1 ? initial_status). include "common/ExtraMonads.ma". theorem correct' : ∀observe. ∀input_program,output. compile observe input_program = return output → not_wrong … (exec_inf … clight_fullexec input_program) → sim_with_labels (exec_inf … clight_fullexec input_program) (exec_inf … clight_fullexec (c_labelled_clight … output)) ∧ simulates output. #observe #p_in #out #H @('bind_inversion H) -H ** #init_cost #labelled #p_rtlabs #EQ_front_end #H @('bind_inversion H) -H ** #p_asm #stack_costs #globals_size #H @('bind_inversion H) -H #p_asm' #H lapply (opt_eq_from_res ???? H) #EQ_lin_to_asm whd in ⊢ (??%%→?); #EQ lapply (sym_eq ??? EQ) -EQ #EQ destruct(EQ) #H @('bind_inversion H) -H #p_loc #EQ_assembler whd in ⊢ (??%%→?); #EQ lapply (sym_eq ??? EQ) -EQ #EQ destruct(EQ) #NOT_WRONG % [ cases daemon (* TODO *) | #m1 #m2 #m1_m2_meas #c1 #c2 #c1_prf #c2_prf cut (∀n,s1,s2,obs1,obs2. exec_with_observables_n n (RTLabs_init_state p_rtlabs) = return 〈obs1, s1〉 → ∀tlr : trace_label_return (RTLabs_status p_rtlabs) s1 s2. tlr_observables … tlr (function_of … s1) = obs2 → (* maybe instead of function_of the called id can rather be obtained from execution? *) ∃m,p,s_fin. observables (OC_preclassified_system (c_labelled_object_code … p)) (c_labelled_object_code … p) m p = return 〈obs1, obs2〉) (* start of old simulates (* [nth_state_of_with_stack state stack_cost stack_bound exec n] returns [Some s] iff after [n] steps of [exec] we have reached [s] without exceeding the [stack_bound] according to the [stack_cost] function. *) axiom nth_state_of_with_stack : ∀state. (state → nat) → nat → execution state io_out io_in → nat → option state. axiom nth_state_of : ∀state. execution state io_out io_in → nat → option state. let cl_trace ≝ exec_inf … clight_fullexec labelled in let asm_trace ≝ exec_inf … ASM_fullexec object_code in not_wrong ? cl_trace → ∀n,s. nth_state_of_with_stack ? stack_cost stack_bound cl_trace n = Some ? s → 𝚺m,s'. nth_state_of ? asm_trace m = Some ? s' ∧ s ≃ s' *) (* TODO ∀input_program. ! 〈object_code,costlabel_map,labelled,cost_map〉 ← compile input_program exec_inf … clight_fullexec input_program ≃l exec_inf … clight_fullexec labelled ∧ exec_inf … clight_fullexec labelled ≈ exec_inf … ASM_fullexec object_code (* Should we be lifting labels in some way here? *) ∧ ∀i,f : clight_status. Clight_labelled i → Clight_labelled f → ∀mx,time. let trace ≝ exec_inf_aux … clight_fullexec labelled i in will_return O O mx time f trace → mx < max_allowed_stack → ∃!i',f'. i ≃ i' ∧ f ≃ f' ∧ i' 8051~> f' ∧ time = clock f' - clock i'. ∀s,flat. let ge ≝ (globalenvs … labelled) in subtrace_of (exec_inf … RTLabs_fullexec labelled) flat → RTLabs_cost s = true → ∀WR : will_return ge 0 s flat. let structured_trace_rtlabs ≝ make_label_return' ge 0 s flat ??? WR in let labels_rtlabs ≝ flat_label_trace … flat WR in ∃!initial,final,structured_trace_asm. structured_trace_rtlabs ≈ structured_trace_asm ∧ clock … code_memory … final = clock … code_memory … initial + (Σ_{i < |labels_rtlabs|} (cost_map (match nth i labels_rtlabs with [ Some k ⇒ k | None ⇒ 0 ])). What is ≃l? Must show that "labelled" does everything that "input_program" does, without getting lost in some non-terminating loop part way. *)