(* * Copyright 2020, Data61, CSIRO (ABN 41 687 119 230) * * SPDX-License-Identifier: BSD-2-Clause *) theory GlobalsSwap imports "Lib.Lib" "CParser.CTranslation" "CParser.PackedTypes" begin datatype 'g global_data = GlobalData "string" "nat" "addr \ bool" "'g \ word8 list" "word8 list \ 'g \ 'g" | ConstGlobalData "string" "nat" "addr \ bool" "word8 list" "word8 list \ bool" | AddressedGlobalData "string" "nat" "addr \ bool" (* in each case the symbol name, length in bytes, tag and constraint on address. for active globals a getter/setter, for const globals a sample value and a way to check a value *) definition is_const_global_data :: "'g global_data \ bool" where "is_const_global_data gd = (case gd of ConstGlobalData nm m ok v chk \ True | _ \ False)" definition is_addressed_global_data :: "'g global_data \ bool" where "is_addressed_global_data gd = (case gd of AddressedGlobalData _ _ _ \ True | _ \ False)" definition is_global_data :: "'g global_data \ bool" where "is_global_data gd = (case gd of GlobalData _ _ _ _ _ \ True | _ \ False)" definition "global_data_region symtab gd = (case gd of GlobalData name m b g s \ {symtab name ..+ m} | ConstGlobalData name m b v chk \ {symtab name ..+ m} | AddressedGlobalData name m b \ {})" definition "global_data_ok symtab gd = (case gd of GlobalData nm _ ok _ _ \ ok (symtab nm) | ConstGlobalData nm _ ok _ _ \ ok (symtab nm) | AddressedGlobalData nm _ ok \ ok (symtab nm))" definition global_data :: "string \ ('g \ ('a :: packed_type)) \ (('a \ 'a) \ 'g \ 'g) \ 'g global_data" where "global_data name getter updator = GlobalData name (size_of TYPE('a)) (\addr. c_guard (Ptr addr :: 'a ptr)) (to_bytes_p o getter) (updator o K o from_bytes)" type_synonym 'g hrs_update = "(heap_raw_state \ heap_raw_state) \ 'g \ 'g" definition global_swap :: "('g \ heap_raw_state) \ 'g hrs_update \ (string \ addr) \ 'g global_data \ 'g \ 'g" where "global_swap g_hrs g_hrs_upd symtab gd \ (case gd of GlobalData name len n g p \ \gs. g_hrs_upd (\_. hrs_mem_update (heap_update_list (symtab name) (take len (g (g_hrs_upd (K undefined) gs)))) (g_hrs gs)) (p (heap_list (hrs_mem (g_hrs gs)) len (symtab name)) (g_hrs_upd (K undefined) gs)) | _ \ id)" definition globals_swap :: "('g \ heap_raw_state) \ 'g hrs_update \ (string \ addr) \ 'g global_data list \ 'g \ 'g" where "globals_swap g_hrs g_hrs_upd symtab gds = foldr (global_swap g_hrs g_hrs_upd symtab) gds" lemma foldr_does_nothing_to_xf: "\ \x s. x \ set xs \ xf (f x s) = xf s \ \ xf (foldr f xs s) = xf s" by (induct xs, simp_all) lemma intvl_empty2: "({p ..+ n} = {}) = (n = 0)" by (auto simp add: intvl_def) lemma heap_update_list_commute: "{p ..+ length xs} \ {q ..+ length ys} = {} \ heap_update_list p xs (heap_update_list q ys hp) = heap_update_list q ys (heap_update_list p xs hp)" apply (cases "length xs < addr_card") apply (cases "length ys < addr_card") apply (rule ext, simp add: heap_update_list_value) apply blast apply (simp_all add: addr_card intvl_overflow intvl_empty2) done lemma heap_update_commute: "\d,g \\<^sub>t p; d,g' \\<^sub>t q; \ TYPE('a) <\<^sub>\ TYPE('b); \ field_of_t q p; wf_fd (typ_info_t TYPE('a)); wf_fd (typ_info_t TYPE('b)) \ \ heap_update p v (heap_update q (u :: 'b :: c_type) h) = heap_update q u (heap_update p (v :: 'a :: c_type) h)" apply (drule(3) h_t_valid_neq_disjoint) apply (simp add: heap_update_def) apply (simp add: heap_update_list_commute heap_list_update_disjoint_same to_bytes_def length_fa_ti size_of_def Int_commute) done definition global_data_swappable :: "'g global_data \ 'g global_data \ bool" where "global_data_swappable gd gd' \ case (gd, gd') of (GlobalData _ _ _ g s, GlobalData _ _ _ g' s') \ (\v v' gs. s v (s' v' gs) = s' v' (s v gs)) \ (\v gs. g (s' v gs) = g gs) \ (\v gs. g' (s v gs) = g' gs) | _ \ True" definition global_data_valid :: "('g \ heap_raw_state) \ 'g hrs_update \ 'g global_data \ bool" where "global_data_valid g_hrs g_hrs_upd gd \ (case gd of GlobalData _ l _ g s \ (\gs. length (g gs) = l) \ (\v v' gs. s v (s v' gs) = s v gs) \ (\gs. s (g gs) gs = gs) \ (\v gs. length v = l \ g (s v gs) = v) \ (\v f gs. (s v (g_hrs_upd f gs)) = g_hrs_upd f (s v gs)) \ (\v gs. g_hrs (s v gs) = g_hrs gs) \ (\f gs. g (g_hrs_upd f gs) = g gs) \ l < addr_card | _ \ True)" definition "global_acc_valid g_hrs g_hrs_upd \ (\f s. g_hrs (g_hrs_upd f s) = f (g_hrs s)) \ (\f f' s. g_hrs_upd f (g_hrs_upd f' s) = g_hrs_upd (f o f') s) \ (\s. g_hrs_upd (\_. g_hrs s) s = s)" lemma global_swap_swap: "\ global_data_region symtab gd \ global_data_region symtab gd' = {}; global_acc_valid g_hrs g_hrs_upd; global_data_swappable gd gd'; global_data_valid g_hrs g_hrs_upd gd; global_data_valid g_hrs g_hrs_upd gd' \ \ global_swap g_hrs g_hrs_upd symtab gd (global_swap g_hrs g_hrs_upd symtab gd' gs) = global_swap g_hrs g_hrs_upd symtab gd' (global_swap g_hrs g_hrs_upd symtab gd gs)" apply (clarsimp simp add: global_swap_def hrs_mem_update global_data_swappable_def global_data_valid_def global_acc_valid_def o_def split: global_data.split_asm) apply (clarsimp simp: global_data_region_def K_def) apply (simp add: heap_list_update_disjoint_same Int_commute) apply (simp add: hrs_mem_update_def split_def) apply (subst heap_update_list_commute, simp_all) done lemma heap_update_list_double_id: "\ heap_list hp n ptr = xs; length xs' = length xs; length xs < addr_card \ \ heap_update_list ptr xs (heap_update_list ptr xs' hp) = hp" apply (rule ext, simp add: heap_update_list_value') apply (clarsimp simp: heap_list_nth intvl_def) done lemma global_swap_cancel: "\ global_acc_valid g_hrs g_hrs_upd; global_data_valid g_hrs g_hrs_upd gd \ \ global_swap g_hrs g_hrs_upd symtab gd (global_swap g_hrs g_hrs_upd symtab gd gs) = gs" apply (insert heap_list_update[where v="case gd of GlobalData _ _ _ g _ \ g gs"]) apply (clarsimp simp: global_swap_def hrs_mem_update global_data_valid_def global_acc_valid_def split: global_data.split) apply (simp add: hrs_mem_update_def split_def o_def) apply (simp add: heap_update_list_double_id hrs_mem_def) done lemma foldr_update_commutes: "\ \x s. x \ set xs \ f (g x s) = g x (f s) \ \ f (foldr g xs s) = foldr g xs (f s)" by (induct xs, simp_all) definition "globals_list_valid symtab g_hrs g_hrs_upd xs = (distinct_prop global_data_swappable xs \ (\x \ set xs. global_data_valid g_hrs g_hrs_upd x) \ (\x \ set xs. global_data_ok symtab x))" lemma global_data_swappable_sym: "global_data_swappable x y = global_data_swappable y x" by (auto simp add: global_data_swappable_def split: global_data.split) lemma hrs_htd_globals_swap: "\ global_acc_valid g_hrs g_hrs_upd; \x \ set xs. global_data_valid g_hrs g_hrs_upd x \ \ hrs_htd (g_hrs (globals_swap g_hrs g_hrs_upd symtab xs gs)) = hrs_htd (g_hrs gs)" unfolding globals_swap_def apply (rule foldr_does_nothing_to_xf) apply (simp add: global_swap_def global_acc_valid_def split: global_data.split prod.split bool.split) done lemmas foldr_hrs_htd_global_swap = hrs_htd_globals_swap[unfolded globals_swap_def] definition globals_list_distinct :: "addr set \ (string \ addr) \ 'g global_data list \ bool" where "globals_list_distinct D symtab gds = distinct_prop (\S T. S \ T = {}) (D # map (global_data_region symtab) gds)" lemma globals_swap_twice_helper: "\ globals_list_valid symtab g_hrs g_hrs_upd xs; global_acc_valid g_hrs g_hrs_upd; globals_list_distinct D symtab xs \ \ globals_swap g_hrs g_hrs_upd symtab xs (globals_swap g_hrs g_hrs_upd symtab xs gs) = gs" apply (simp add: globals_swap_def) apply (clarsimp simp: foldr_hrs_htd_global_swap globals_list_valid_def) apply (induct xs) apply simp apply (clarsimp simp: globals_list_distinct_def) apply (subst foldr_update_commutes[where f="global_swap g_hrs g_hrs_upd symtab v" for v]) apply (rule global_swap_swap, auto)[1] apply (simp add: global_swap_cancel foldr_hrs_htd_global_swap) done lemma disjoint_int_intvl_min: "\ S \ {p ..+ n} = {} \ \ S \ {p ..+ min m n} = {}" using intvl_start_le[where x="min m n" and y=n] by auto lemma ptr_set_disjoint_footprint: "(s_footprint (p :: ('a :: c_type) ptr) \ (S \ UNIV) = {}) \ ({ptr_val p ..+ size_of TYPE('a)} \ S = {})" by (auto simp add: s_footprint_intvl[symmetric]) lemma disjoint_heap_list_globals_swap_filter: "\ global_acc_valid g_hrs g_hrs_upd; globals_list_distinct D symtab (filter is_global_data xs); {p ..+ n} \ D \ \ heap_list (hrs_mem (g_hrs (globals_swap g_hrs g_hrs_upd symtab xs gs))) n p = heap_list (hrs_mem (g_hrs gs)) n p" apply (clarsimp simp: globals_swap_def) apply (rule foldr_does_nothing_to_xf) apply (clarsimp simp: global_swap_def hrs_mem_update global_acc_valid_def globals_list_distinct_def split: global_data.split) apply (subst heap_list_update_disjoint_same, simp_all) apply (drule spec, drule mp, erule conjI, simp add: is_global_data_def) apply (simp add: Int_commute global_data_region_def) apply (rule disjoint_int_intvl_min) apply blast done lemma disjoint_h_val_globals_swap_filter: "\ global_acc_valid g_hrs g_hrs_upd; globals_list_distinct D symtab (filter is_global_data xs); s_footprint p \ D \ UNIV \ \ h_val (hrs_mem (g_hrs (globals_swap g_hrs g_hrs_upd symtab xs gs))) p = h_val (hrs_mem (g_hrs gs)) p" apply (clarsimp simp: h_val_def) apply (subst disjoint_heap_list_globals_swap_filter[where g_hrs=g_hrs], assumption+) apply (auto simp: s_footprint_intvl[symmetric])[1] apply simp done lemma distinct_prop_filter: "distinct_prop P (filter Q xs) = distinct_prop (\x y. Q x \ Q y \ P x y) xs" by (induct xs, auto) lemma distinct_prop_weaken: "\ distinct_prop P xs; \x y. P x y \ Q x y \ \ distinct_prop Q xs" by (induct xs, simp_all) lemma globals_list_distinct_filter: "globals_list_distinct D symtab xs \ globals_list_distinct D symtab (filter P xs)" by (clarsimp simp: globals_list_distinct_def distinct_prop_map distinct_prop_filter elim!: distinct_prop_weaken) lemmas disjoint_h_val_globals_swap = disjoint_h_val_globals_swap_filter[OF _ globals_list_distinct_filter] lemma disjoint_heap_update_globals_swap_filter: "\ global_acc_valid g_hrs g_hrs_upd; globals_list_distinct D symtab (filter is_global_data xs); s_footprint (p :: ('a :: wf_type) ptr) \ D \ UNIV \ \ g_hrs_upd (hrs_mem_update (heap_update p v)) (globals_swap g_hrs g_hrs_upd symtab xs gs) = globals_swap g_hrs g_hrs_upd symtab xs (g_hrs_upd (hrs_mem_update (heap_update p v)) gs)" apply (clarsimp simp: globals_swap_def global_acc_valid_def) apply (rule foldr_update_commutes) apply (clarsimp simp: global_swap_def hrs_mem_update h_val_def heap_update_def o_def K_def globals_list_distinct_def split: global_data.split) apply (drule spec, drule mp, erule conjI, simp add: is_global_data_def) apply (rule_tac f="g_hrs_upd" in arg_cong2[rotated]) apply (subst heap_list_update_disjoint_same, simp_all) apply (rule ptr_set_disjoint_footprint) apply (simp add: global_data_region_def) apply blast apply (clarsimp simp: hrs_mem_update_def split_def) apply (subst heap_update_list_commute) apply (simp add: to_bytes_def length_fa_ti size_of_def global_data_region_def) apply (intro disjoint_int_intvl_min ptr_set_disjoint_footprint[unfolded size_of_def]) apply blast apply (subst heap_list_update_disjoint_same, simp_all add: global_data_region_def) apply (simp add: Int_commute) apply (intro disjoint_int_intvl_min ptr_set_disjoint_footprint) apply blast done lemmas disjoint_heap_update_globals_swap = disjoint_heap_update_globals_swap_filter[OF _ globals_list_distinct_filter] lemma to_bytes_p_from_bytes: "length xs = size_of TYPE ('a :: packed_type) \ to_bytes_p (from_bytes xs :: 'a) = xs" by (simp add: to_bytes_p_def to_bytes_def from_bytes_def update_ti_t_def size_of_def field_access_update_same td_fafu_idem) lemma to_bytes_p_inj: "inj (to_bytes_p :: ('a :: packed_type) \ _)" apply (rule inj_onI) apply (drule_tac f=from_bytes in arg_cong) apply (simp add: to_bytes_p_def) apply (subst(asm) CTypes.inv | simp)+ done lemma global_data_valid: "global_data_valid g_hrs g_hrs_upd (global_data p (g :: 'g \ ('a :: packed_type)) s) = ( (\v v' gs. s (\_. v) (s (\_. v') gs) = s (\_. v) gs) \ (\gs. s (\_. g gs) gs = gs) \ (\v f gs. s (\_. v) (g_hrs_upd f gs) = g_hrs_upd f (s (\_. v) gs)) \ (\f gs. g (g_hrs_upd f gs) = g gs) \ (\v gs. g_hrs (s (\_. v) gs) = g_hrs gs) \ (\v gs. g (s (\_. v) gs) = v))" proof - have all_to_xs: "\P. (\(v :: 'a). P v) = (\xs. P (from_bytes xs))" apply (safe, simp_all) apply (drule_tac x="to_bytes_p v" in spec) apply (simp add: to_bytes_p_from_bytes) done show ?thesis apply (simp add: global_data_valid_def global_data_def) apply (simp add: all_to_xs order_less_imp_le[OF max_size] inj_eq[OF to_bytes_p_inj] conj_comms K_def) apply (safe, simp_all add: to_bytes_p_from_bytes) apply (drule_tac x="to_bytes_p (from_bytes xs :: 'a)" in spec, drule mp) apply simp apply (simp add: inj_eq[OF to_bytes_p_inj]) done qed lemma globals_swap_reorder_append: "\ globals_list_valid symtab g_hrs g_hrs_upd (xs @ ys); global_acc_valid g_hrs g_hrs_upd; globals_list_distinct D symtab (xs @ ys) \ \ globals_swap g_hrs g_hrs_upd symtab (xs @ ys) = globals_swap g_hrs g_hrs_upd symtab (ys @ xs)" apply (induct xs) apply simp apply (rule ext) apply (clarsimp simp: globals_swap_def foldr_hrs_htd_global_swap fun_eq_iff) apply (drule meta_mp, simp add: globals_list_valid_def) apply (clarsimp simp: globals_list_distinct_def) apply (rule foldr_update_commutes) apply (clarsimp simp: ball_Un globals_list_valid_def) apply (rule global_swap_swap, simp_all) done lemma globals_swap_reorder_append_n: "\ globals_list_valid symtab g_hrs g_hrs_upd xs; global_acc_valid g_hrs g_hrs_upd; globals_list_distinct D symtab xs \ \ globals_swap g_hrs g_hrs_upd symtab xs = globals_swap g_hrs g_hrs_upd symtab (drop n xs @ take n xs)" using globals_swap_reorder_append [where xs="take n xs" and ys="drop n xs"] by simp lemma heap_update_list_overwrite: "\ length xs = length ys; length ys < addr_card \ \ heap_update_list w xs (heap_update_list w ys hp) = heap_update_list w xs hp" by (rule ext, simp add: heap_update_list_value) lemma heap_list_update_eq: "\ n = length v; n \ addr_card \ \ heap_list (heap_update_list p v h) n p = v" by (simp add: heap_list_update) lemma globals_swap_absorb_update: "\ global_acc_valid g_hrs g_hrs_upd; \s. v (g_hrs s) = v'; length v' = m; globals_list_valid symtab g_hrs g_hrs_upd (GlobalData nm m ok g s # xs); globals_list_distinct D symtab (GlobalData nm m ok g s # xs) \ \ s v' (globals_swap g_hrs g_hrs_upd symtab (GlobalData nm m ok g s # xs) gs) = globals_swap g_hrs g_hrs_upd symtab (GlobalData nm m ok g s # xs) (g_hrs_upd (\hrs. hrs_mem_update (heap_update_list (symtab nm) (v hrs)) hrs) gs)" apply (induct xs) apply (simp add: globals_swap_def global_acc_valid_def) apply (simp add: global_swap_def global_data_def hrs_mem_update) apply (simp add: globals_list_valid_def global_data_valid_def K_def o_def) apply (simp add: hrs_mem_def hrs_mem_update_def split_def heap_update_def h_val_def heap_update_list_overwrite heap_list_update_eq order_less_imp_le del: SepCode.inv_p) apply (drule meta_mp, simp add: globals_list_valid_def globals_list_distinct_def)+ apply (rename_tac x xs) apply (subgoal_tac "\gs. globals_swap g_hrs g_hrs_upd symtab (GlobalData nm m ok g s # x # xs) gs = global_swap g_hrs g_hrs_upd symtab x (globals_swap g_hrs g_hrs_upd symtab (GlobalData nm m ok g s # xs) gs)") apply (subgoal_tac "\gs. s v' (global_swap g_hrs g_hrs_upd symtab x gs) = global_swap g_hrs g_hrs_upd symtab x (s v' gs)") apply (simp add: global_acc_valid_def) apply (clarsimp simp: globals_list_valid_def global_data_swappable_def global_data_def global_swap_def K_def global_data_valid_def order_less_imp_le simp del: SepCode.inv_p split: global_data.split_asm prod.split bool.split) apply (clarsimp simp: globals_swap_def globals_list_distinct_def global_data_def globals_list_valid_def) apply (rule global_swap_swap, simp+) done lemma append_2nd_simp_backward: "xs @ y # ys = (xs @ [y]) @ ys" by simp lemma globals_swap_access_mem_raw: "\ global_acc_valid g_hrs g_hrs_upd; globals_list_valid symtab g_hrs g_hrs_upd xs; globals_list_distinct D symtab xs; GlobalData nm m ok g s \ set xs; size_of TYPE('a) = m \ \ h_val (hrs_mem (g_hrs gs)) (Ptr (symtab nm) :: ('a :: c_type) ptr) = from_bytes (g (globals_swap g_hrs g_hrs_upd symtab xs gs))" apply (clarsimp simp: in_set_conv_decomp) apply (subst append_2nd_simp_backward) apply (subst globals_swap_reorder_append, simp+) apply (simp add: globals_swap_def del: foldr_append split del: if_split) apply (subgoal_tac "global_data_valid g_hrs g_hrs_upd (GlobalData nm (size_of TYPE('a)) ok g s)") apply (subst append_assoc[symmetric], subst foldr_append) apply (subst foldr_does_nothing_to_xf[where xf=g]) apply (subgoal_tac "global_data_swappable (GlobalData nm (size_of TYPE('a)) ok g s) x") apply (clarsimp simp: global_data_swappable_def global_data_def global_swap_def global_data_valid_def split: global_data.split_asm prod.split bool.split) apply (simp add: globals_list_valid_def distinct_prop_append) apply (auto simp: global_data_swappable_sym)[1] apply (simp add: global_data_valid_def) apply (simp add: global_data_def global_swap_def h_val_def K_def ) apply (simp_all add: globals_list_valid_def) done lemma globals_swap_access_mem: "\ global_data nm g u \ set xs; global_acc_valid g_hrs g_hrs_upd; globals_list_valid symtab g_hrs g_hrs_upd xs; globals_list_distinct D symtab xs \ \ g (globals_swap g_hrs g_hrs_upd symtab xs gs) = h_val (hrs_mem (g_hrs gs)) (Ptr (symtab nm))" by (simp add: global_data_def globals_swap_access_mem_raw) lemma globals_swap_access_mem2: "\ global_data nm g u \ set xs; global_acc_valid g_hrs g_hrs_upd; globals_list_valid symtab g_hrs g_hrs_upd xs; globals_list_distinct D symtab xs \ \ g gs = h_val (hrs_mem (g_hrs (globals_swap g_hrs g_hrs_upd symtab xs gs))) (Ptr (symtab nm))" using globals_swap_twice_helper globals_swap_access_mem by metis lemma globals_swap_update_mem_raw: "\ global_acc_valid g_hrs g_hrs_upd; \hmem. (v hmem) = v'; length v' = m; globals_list_valid symtab g_hrs g_hrs_upd xs; globals_list_distinct D symtab xs; GlobalData nm m ok g st \ set xs \ \ globals_swap g_hrs g_hrs_upd symtab xs (g_hrs_upd (hrs_mem_update (\hmem. heap_update_list (symtab nm) (v hmem) hmem)) gs) = st v' (globals_swap g_hrs g_hrs_upd symtab xs gs)" apply (clarsimp simp: in_set_conv_decomp) apply (subst globals_swap_reorder_append, simp+)+ apply (rule globals_swap_absorb_update[symmetric, where D=D], simp_all) apply (simp add: globals_list_valid_def distinct_prop_append) apply (insert global_data_swappable_sym) apply blast apply (simp add: globals_list_distinct_def ball_Un distinct_prop_append) apply blast done lemma to_bytes_p_from_bytes_eq: "\ from_bytes ys = (v :: 'a :: packed_type); length ys = size_of TYPE('a) \ \ to_bytes_p v = ys" by (clarsimp simp: to_bytes_p_from_bytes) lemma globals_swap_update_mem: "\ global_data nm g u \ set xs; global_acc_valid g_hrs g_hrs_upd; globals_list_valid symtab g_hrs g_hrs_upd xs; globals_list_distinct D symtab xs \ \ u (\_. v) (globals_swap g_hrs g_hrs_upd symtab xs gs) = globals_swap g_hrs g_hrs_upd symtab xs (g_hrs_upd (hrs_mem_update (\hrs. heap_update (Ptr (symtab nm)) v hrs)) gs)" unfolding global_data_def apply (simp add: heap_update_def) apply (subst globals_swap_update_mem_raw[where v'="to_bytes_p v", rotated -1], assumption, simp_all add: K_def o_def) apply clarsimp apply (rule to_bytes_p_from_bytes_eq[symmetric], simp+) done lemma globals_swap_update_mem2: assumes prems: "global_data nm g u \ set xs" "global_acc_valid g_hrs g_hrs_upd" "globals_list_valid symtab g_hrs g_hrs_upd xs" "globals_list_distinct D symtab xs" shows "globals_swap g_hrs g_hrs_upd symtab xs (u (\_. v) gs) = g_hrs_upd (hrs_mem_update (\hrs. heap_update (Ptr (symtab nm)) v hrs)) (globals_swap g_hrs g_hrs_upd symtab xs gs)" using prems globals_swap_twice_helper globals_swap_update_mem by metis lemma globals_swap_hrs_htd_update: "\ global_acc_valid g_hrs g_hrs_upd; globals_list_valid symtab g_hrs g_hrs_upd xs \ \ g_hrs_upd (hrs_htd_update ufn) (globals_swap g_hrs g_hrs_upd symtab xs gs) = globals_swap g_hrs g_hrs_upd symtab xs (g_hrs_upd (hrs_htd_update ufn) gs)" apply (clarsimp simp: globals_swap_def hrs_htd_update global_acc_valid_def) apply (rule foldr_update_commutes) apply (clarsimp simp: globals_list_valid_def, drule(1) bspec) apply (simp add: global_swap_def o_def global_data_valid_def hrs_htd_update split: global_data.split_asm prod.split bool.split) apply (simp add: hrs_htd_update_def hrs_mem_update_def split_def) done definition const_global_data :: "string \ ('a :: c_type) \ 'g global_data" where "const_global_data name v = ConstGlobalData name (size_of TYPE('a)) (\addr. c_guard (Ptr addr :: 'a ptr)) (to_bytes_p v) (\xs. from_bytes xs = v)" definition addressed_global_data :: "string \ ('a :: c_type) itself \ 'g global_data" where "addressed_global_data name tp = AddressedGlobalData name (size_of tp) (\addr. c_guard (Ptr addr :: 'a ptr))" lemma is_global_data_simps[simp]: "is_global_data (global_data nm g s)" "\ is_global_data (const_global_data nm v)" "\ is_global_data (addressed_global_data nm tp)" by (simp_all add: global_data_def const_global_data_def is_global_data_def addressed_global_data_def) lemma is_const_global_data_simps[simp]: "is_const_global_data (const_global_data nm v)" "\ is_const_global_data (global_data nm g s)" "\ is_const_global_data (addressed_global_data nm tp)" by (simp_all add: global_data_def const_global_data_def is_const_global_data_def addressed_global_data_def) lemma distinct_prop_swappable_optimisation: "distinct_prop global_data_swappable (filter is_global_data gs) \ distinct_prop (\x y. global_data_swappable x y) gs" apply (simp add: distinct_prop_filter is_global_data_def global_data_swappable_def) apply (erule distinct_prop_weaken) apply (simp split: global_data.splits) done lemma globals_list_valid_optimisation: "distinct_prop global_data_swappable (filter is_global_data gs) \ \g \ set gs. global_data_valid g_hrs g_hrs_upd g \ \g \ set gs. global_data_ok symtab g \ globals_list_valid symtab g_hrs g_hrs_upd gs" using globals_list_valid_def distinct_prop_swappable_optimisation by blast definition const_globals_in_memory :: "(string \ addr) \ 'g global_data list \ heap_mem \ bool" where "const_globals_in_memory symtab xs hmem = (\gd \ set xs. case gd of ConstGlobalData nm l ok v chk \ chk (heap_list hmem l (symtab nm)) | _ \ True)" lemma const_globals_in_memory_h_val_eq: "const_globals_in_memory symtab (const_global_data nm v # xs) hmem = (h_val hmem (Ptr (symtab nm)) = v \ const_globals_in_memory symtab xs hmem)" by (simp add: const_globals_in_memory_def const_global_data_def h_val_def) lemma const_globals_in_memory_other_eqs: "const_globals_in_memory symtab (global_data nm g s # xs) hmem = const_globals_in_memory symtab xs hmem" "const_globals_in_memory symtab (addressed_global_data nm tp # xs) hmem = const_globals_in_memory symtab xs hmem" "const_globals_in_memory symtab [] hmem" by (auto simp add: const_globals_in_memory_def global_data_def addressed_global_data_def) lemmas const_globals_in_memory_eqs = const_globals_in_memory_h_val_eq const_globals_in_memory_other_eqs lemma const_globals_in_memory_h_val: "\ const_global_data nm v \ set xs; const_globals_in_memory symtab xs hmem \ \ h_val hmem (Ptr (symtab nm)) = v" apply (simp add: const_globals_in_memory_def const_global_data_def) apply (drule (1) bspec) apply (clarsimp simp: h_val_def) done lemma const_globals_in_memory_heap_update_list: "\ const_globals_in_memory symtab xs hmem; globals_list_distinct D symtab (filter is_const_global_data xs); {p ..+ length ys} \ D \ \ const_globals_in_memory symtab xs (heap_update_list p ys hmem)" apply (clarsimp simp: const_globals_in_memory_def globals_list_distinct_def split: global_data.split) apply (drule(1) bspec) apply (drule spec, drule mp, erule conjI, simp add: is_const_global_data_def) apply (simp add: global_data_region_def) apply (subst heap_list_update_disjoint_same) apply blast apply simp done definition htd_safe :: "addr set \ heap_typ_desc \ bool" where "htd_safe D htd = (dom_s htd \ D \ UNIV)" lemma const_globals_in_memory_heap_update: "\ const_globals_in_memory symtab gs hmem; globals_list_distinct D symtab gs; ptr_safe (p :: ('a :: wf_type) ptr) htd; htd_safe D htd \ \ const_globals_in_memory symtab gs (heap_update p val hmem)" apply (simp add: split_def heap_update_def) apply (erule const_globals_in_memory_heap_update_list, erule globals_list_distinct_filter) apply (clarsimp simp: ptr_safe_def htd_safe_def s_footprint_intvl[symmetric]) apply blast done lemma distinct_prop_memD: "\ x \ set zs; y \ set zs; distinct_prop P zs \ \ x = y \ P x y \ P y x" by (induct zs, auto) lemma const_globals_in_memory_heap_update_global: "\ const_globals_in_memory symtab gs hmem; global_data nm (getter :: 'g \ 'a) setter \ set gs; globals_list_distinct D symtab gs \ \ const_globals_in_memory symtab gs (heap_update (Ptr (symtab nm)) (v :: 'a :: packed_type) hmem)" apply (simp add: heap_update_def split_def) apply (erule const_globals_in_memory_heap_update_list[OF _ _ order_refl]) apply (clarsimp simp: globals_list_distinct_def distinct_prop_map distinct_prop_filter) apply (simp add: distinct_prop_weaken) apply clarsimp apply (drule(2) distinct_prop_memD) apply (auto simp: global_data_region_def global_data_def is_const_global_data_def) done lemma const_globals_in_memory_after_swap: "global_acc_valid t_hrs_' t_hrs_'_update \ globals_list_distinct D symbol_table gxs \ const_globals_in_memory symbol_table gxs (hrs_mem (t_hrs_' (globals_swap t_hrs_' t_hrs_'_update symbol_table gxs gs))) = const_globals_in_memory symbol_table gxs (hrs_mem (t_hrs_' gs))" apply (simp add: const_globals_in_memory_def) apply (rule ball_cong, simp_all) apply (clarsimp split: global_data.split) apply (subst disjoint_heap_list_globals_swap_filter[OF _ _ order_refl], assumption+, simp_all) apply (clarsimp simp: globals_list_distinct_def distinct_prop_map distinct_prop_filter distinct_prop_weaken) apply (drule(2) distinct_prop_memD) apply (clarsimp simp: is_global_data_def ball_Un distinct_prop_append global_data_region_def Int_commute split: global_data.split_asm) done ML \ structure DefineGlobalsList = struct fun dest_conjs t = (t RS @{thm conjunct1}) :: dest_conjs (t RS @{thm conjunct2}) handle THM _ => [t] fun define_globals_list (mungedb:CalculateState.mungedb) globloc globty thy = let open CalculateState NameGeneration val sT = @{typ string} val gdT = Type (@{type_name global_data}, [globty]) val ctxt = Named_Target.begin (globloc, Position.none) thy fun glob (_, _, _, Local _) = error "define_globals_list: Local" | glob (nm, typ, _, UntouchedGlobal) = let val cname = NameGeneration.untouched_global_name nm val init = Syntax.read_term ctxt (MString.dest cname) in Const (@{const_name "const_global_data"}, sT --> typ --> gdT) $ HOLogic.mk_string (MString.dest nm) $ init end | glob (nm, typ, _, NSGlobal) = let (* FIXME: _' hackery (or more generally, hackery) *) val acc = (Sign.intern_const thy (global_rcd_name ^ "." ^ MString.dest nm ^ "_'"), globty --> typ) val upd = (Sign.intern_const thy (global_rcd_name ^ "." ^ MString.dest nm ^ "_'" ^ Record.updateN), (typ --> typ) --> globty --> globty) in Const (@{const_name "global_data"}, sT --> snd acc --> snd upd --> gdT) $ HOLogic.mk_string (MString.dest nm) $ Const acc $ Const upd end | glob (nm, typ, _, AddressedGlobal) = Const (@{const_name "addressed_global_data"}, sT --> Term.itselfT typ --> gdT) $ HOLogic.mk_string (MString.dest nm) $ Logic.mk_type typ val naming = Binding.name o NameGeneration.global_data_name val globs = CNameTab.dest mungedb |> map snd |> filter (fn v => case #4 v of Local _ => false | _ => true) |> map (fn g => (g |> #1 |> MString.dest |> naming, glob g)) val (xs, ctxt) = fold_map (fn (nm, tm) => Local_Theory.define ((nm, NoSyn), ((Thm.def_binding nm, []), tm))) globs ctxt val gdTs = HOLogic.mk_list gdT (map fst xs) val ((gdl, (_, gdl_def)), ctxt) = Local_Theory.define ((@{binding global_data_list}, NoSyn), ((@{binding global_data_list_def}, []), gdTs)) ctxt val (_, ctxt) = Local_Theory.note ((@{binding "global_data_defs"}, []), map (snd #> snd) xs) ctxt val lT = HOLogic.listT gdT val setT = HOLogic.mk_setT gdT val setC = Const (@{const_name set}, lT --> setT) val thm = Goal.prove ctxt [] [] (HOLogic.mk_Trueprop (Const (@{const_name less_eq}, setT --> setT --> HOLogic.boolT) $ (setC $ gdTs) $ (setC $ gdl))) (K (simp_tac (put_simpset HOL_basic_ss ctxt addsimps @{thms order_refl} addsimps [gdl_def]) 1)) val mems = simplify (put_simpset HOL_basic_ss ctxt addsimps @{thms set_simps insert_subset empty_subsetI simp_thms}) thm |> dest_conjs val (_, ctxt) = Local_Theory.note ((@{binding "global_data_mems"}, []), mems) ctxt in Local_Theory.exit_global ctxt end fun define_globals_list_i s globty thy = let val {base = localename,...} = OS.Path.splitBaseExt (OS.Path.file s) val globloc = suffix HPInter.globalsN localename in define_globals_list (CalculateState.get_mungedb thy s |> the) globloc globty thy end end \ lemma globals_list_distinct_filter_member: "x \ set xs \ globals_list_distinct D symtab xs \ \ P x \ globals_list_distinct (global_data_region symtab x) symtab (filter P xs)" apply (clarsimp simp: globals_list_distinct_def) apply (rule conjI) apply (clarsimp simp: in_set_conv_decomp[where x="x"] distinct_prop_append) apply auto[1] apply (simp add: distinct_prop_map distinct_prop_filter) apply (erule distinct_prop_weaken, simp) done lemma s_footprint_intvl_subset: "s_footprint (p :: 'a ptr) \ {ptr_val p ..+ size_of TYPE ('a :: c_type)} \ UNIV" by (auto simp: s_footprint_def s_footprint_untyped_def intvl_def size_of_def) lemma h_val_globals_swap_in_const_global: "\ global_acc_valid g_hrs g_hrs_upd; globals_list_distinct D symtab xs; const_global_data s (v :: 'a :: c_type) \ set xs; unat offs + size_of TYPE('b) \ size_of TYPE('a) \ \ h_val (hrs_mem (g_hrs (globals_swap g_hrs g_hrs_upd symtab xs gs))) (Ptr (symtab s + offs) :: ('b :: c_type) ptr) = h_val (hrs_mem (g_hrs gs)) (Ptr (symtab s + offs))" apply (erule disjoint_h_val_globals_swap_filter, erule(1) globals_list_distinct_filter_member) apply simp apply (rule order_trans, rule s_footprint_intvl_subset) apply (simp add: global_data_region_def const_global_data_def Times_subset_cancel2) apply (erule intvl_sub_offset) done lemmas h_val_globals_swap_in_const_global_both = h_val_globals_swap_in_const_global h_val_globals_swap_in_const_global[where offs=0, simplified] lemma const_globals_in_memory_to_h_val_with_swap: "\ global_acc_valid g_hrs g_hrs_upd; globals_list_distinct D symtab xs; const_global_data nm v \ set xs; const_globals_in_memory symtab xs (hrs_mem (g_hrs gs)) \ \ v = h_val (hrs_mem (g_hrs (globals_swap g_hrs g_hrs_upd symtab xs gs))) (Ptr (symtab nm))" apply (subst disjoint_h_val_globals_swap_filter, assumption, erule(1) globals_list_distinct_filter_member) apply simp apply (simp add: global_data_region_def const_global_data_def) apply (rule order_trans, rule s_footprint_intvl_subset) apply simp apply (erule(1) const_globals_in_memory_h_val[symmetric]) done text \This alternative ptr_safe definition will apply to all global pointers given globals_list_distinct etc. It supports the same nonoverlapping properties with h_t_valid as h_t_valid itself.\ definition ptr_inverse_safe :: "('a :: mem_type) ptr \ heap_typ_desc \ bool" where "ptr_inverse_safe p htd = (c_guard p \ (fst ` s_footprint p \ fst ` dom_s htd = {}))" lemma global_data_implies_ptr_inverse_safe: "\ global_data nm (accr :: 'a \ ('b :: packed_type)) updr \ set glist; globals_list_distinct D symtab glist; globals_list_valid symtab t_hrs t_hrs_upd glist; htd_safe D htd \ \ ptr_inverse_safe (Ptr (symtab nm) :: 'b ptr) htd" apply (clarsimp simp add: ptr_inverse_safe_def globals_list_valid_def htd_safe_def globals_list_distinct_def) apply (drule(1) bspec)+ apply (simp add: global_data_region_def global_data_ok_def global_data_def) apply (auto dest!: s_footprint_intvl_subset[THEN subsetD]) done ML \ fun add_globals_swap_rewrites member_thms ctxt = let fun cpat pat = Thm.cterm_of ctxt (Proof_Context.read_term_pattern ctxt pat) val gav = Proof_Context.get_thm ctxt "global_acc_valid" val glv = Proof_Context.get_thm ctxt "globals_list_valid" val gld = Proof_Context.get_thm ctxt "globals_list_distinct" val acc = [Thm.trivial (cpat "PROP ?P"), gav, glv, gld] MRS @{thm globals_swap_access_mem2} val upd = [Thm.trivial (cpat "PROP ?P"), gav, glv, gld] MRS @{thm globals_swap_update_mem2} val cg_with_swap = [gav, gld] MRS @{thm const_globals_in_memory_to_h_val_with_swap} val pinv_safe = [Thm.trivial (cpat "PROP ?P"), gld, glv] MRS @{thm global_data_implies_ptr_inverse_safe} val empty_ctxt = put_simpset HOL_basic_ss ctxt fun unfold_mem thm = let val (x, _) = HOLogic.dest_mem (HOLogic.dest_Trueprop (Thm.concl_of thm)) val (s, _) = dest_Const (head_of x) in if s = @{const_name global_data} orelse s = @{const_name const_global_data} orelse s = @{const_name addressed_global_data} then thm else simplify (empty_ctxt addsimps [Proof_Context.get_thm ctxt (s ^ "_def")]) thm end val member_thms = map unfold_mem member_thms val globals_swap_rewrites = member_thms RL [acc, upd] val const_globals_rewrites = member_thms RL @{thms const_globals_in_memory_h_val[symmetric]} val const_globals_swap_rewrites = member_thms RL [cg_with_swap] val pinv_safe_intros = member_thms RL [pinv_safe] in ctxt |> Local_Theory.note ((@{binding "globals_swap_rewrites"}, []), globals_swap_rewrites) |> snd |> Local_Theory.note ((@{binding "const_globals_rewrites"}, []), const_globals_rewrites) |> snd |> Local_Theory.note ((@{binding "const_globals_rewrites_with_swap"}, []), const_globals_swap_rewrites) |> snd |> Local_Theory.note ((@{binding "pointer_inverse_safe_global_rules"}, []), pinv_safe_intros) |> snd end \ end