(* * Copyright 2020, Data61, CSIRO (ABN 41 687 119 230) * * SPDX-License-Identifier: BSD-2-Clause *) theory CommonOpsLemmas imports "CommonOps" "Word_Lib.WordSetup" begin lemma fold_all_htd_updates': "ptr_retyp (p :: ('a :: c_type) ptr) = all_htd_updates TYPE('a) 1 (ptr_val p) 1" "(if P then (f :: heap_typ_desc \ heap_typ_desc) else g) s = (if P then f s else g s)" "\ n < 2 ^ word_bits \ \ ptr_retyps n p = all_htd_updates TYPE('a) 1 (ptr_val p) (of_nat n)" "\ n < 2 ^ word_bits \ \ ptr_retyps (2 ^ n) p = all_htd_updates TYPE('a) 3 (ptr_val p) (of_nat n)" "n < 2 ^ word_bits \ typ_clear_region x n = all_htd_updates TYPE(machine_word) 0 x (of_nat n)" "n < 2 ^ word_bits \ typ_region_bytes x n = all_htd_updates TYPE(machine_word) 2 x (of_nat n)" "\ n < 2 ^ word_bits \ \ ptr_arr_retyps n p = all_htd_updates TYPE('a) 4 (ptr_val p) (of_nat n)" "\ n < 2 ^ word_bits \ \ ptr_arr_retyps (2 ^ n) p = all_htd_updates TYPE('a) 5 (ptr_val p) (of_nat n)" by (simp_all add: all_htd_updates_def unat_of_nat fun_eq_iff of_nat_neq_0 word_bits_conv) lemma upcast_unat_less_2p_length: "is_up UCAST('a :: len \ 'b :: len) \ unat (x :: 'a word) < 2 ^ LENGTH('b)" by (simp add: is_up unat_pow_le_intro) (* FIXME: this is a hack that happens to work on all arches. Use arch split. *) lemma is_up_u32_word_size: "is_up UCAST(32 \ machine_word_len)" by (clarsimp simp add: is_up_def source_size target_size) lemma is_up_i32_word_size: "is_up UCAST(32 signed \ machine_word_len)" by (clarsimp simp add: is_up_def source_size target_size) lemma unat_word32_less_2p_word_bits: "unat (x :: 32 word) < 2 ^ word_bits" by (rule upcast_unat_less_2p_length[OF is_up_u32_word_size, simplified word_bits_def[symmetric]]) lemma unat_sword32_less_2p_word_bits: "unat (x :: 32 signed word) < 2 ^ word_bits" by (rule upcast_unat_less_2p_length[OF is_up_i32_word_size, simplified word_bits_def[symmetric]]) lemmas fold_all_htd_updates_intermediate = fold_all_htd_updates' fold_all_htd_updates'(3-)[OF unat_less_2p_word_bits] fold_all_htd_updates'(3-)[OF unat_word32_less_2p_word_bits] fold_all_htd_updates'(3-)[OF unat_sword32_less_2p_word_bits] lemmas fold_all_htd_updates = fold_all_htd_updates_intermediate[simplified word_bits_conv] lemma signed_div_range_check: assumes len: "size a > 1" shows "(sint a sdiv sint b = sint (a sdiv b)) = (a \ (- (2 ^ (size a - 1))) \ b \ -1)" proof - have sints: "(sint (1 :: 'a word)) = 1" "(sint (-1 :: 'a word)) = -1" "(sint (0 :: 'a word)) = 0" using len apply (simp_all add: word_size) done have abs_sint_gt_1: "b \ 0 \ b \ 1 \ b \ -1 \ abs (sint b) > 1" apply (fold word_sint.Rep_inject, simp only: sints abs_if split: if_split) apply arith done have mag: "(a \ (- (2 ^ (size a - 1))) \ (b \ -1 \ b \ 1)) \ abs (abs (sint a) div abs (sint b)) < 2 ^ (size a - 1)" using word_sint.Rep_inject[where x=a and y="- (2 ^ (size a - 1))"] word_sint.Rep_inject[where x=b and y=1] apply (simp add: word_size sint_int_min sints) apply (simp add: nonneg_mod_div) apply (cases "b = 0") apply simp apply (erule impCE) apply (rule order_le_less_trans, rule zdiv_le_dividend, simp_all) apply (cut_tac x=a in sint_range') apply (clarsimp simp add: abs_if word_size) apply (cases "a = 0", simp_all) apply (rule order_less_le_trans, rule int_div_less_self, simp_all) apply (rule abs_sint_gt_1, simp) apply (cut_tac x=a in sint_range') apply (clarsimp simp add: abs_if word_size) done show ?thesis using mag len apply (cases "b = 1") apply (case_tac "size a", simp_all)[1] apply (case_tac nat, simp_all add: sint_word_ariths word_size)[1] apply (simp add: sdiv_int_def sdiv_word_def sint_sbintrunc' sbintrunc_eq_in_range range_sbintrunc sgn_if) apply (safe, simp_all add: word_size sint_int_min) done qed lemma ptr_add_assertion_uintD: "ptr_add_assertion ptr (uint (x :: ('a :: len) word)) strong htd \ (x = 0 \ array_assertion ptr (if strong then unat (x + 1) else unat x) htd)" using unat_lt2p[where x=x] by (simp add: ptr_add_assertion_def uint_0_iff Word.unat_def[symmetric] unat_plus_if_size linorder_not_less word_size le_Suc_eq array_assertion_shrink_right del: unat_lt2p) lemma sint_uint_sless_0_if: "sint x = (if x (x = 0 \ (x array_assertion (ptr +\<^sub>p sint x) (unat (- x)) htd) \ (x \ 0 \ \ x array_assertion ptr (if strong then unat (x + 1) else unat x) htd))" using unat_lt2p[where x=x] apply (simp add: ptr_add_assertion_def word_sless_alt sint_uint_sless_0_if[THEN arg_cong[where f="\x. - x"]] sint_uint_sless_0_if[THEN arg_cong[where f=nat]] Word.unat_def[symmetric] unat_plus_if_size le_Suc_eq linorder_not_less word_size del: unat_lt2p) apply (simp add: array_assertion_shrink_right) apply (auto simp: linorder_not_less) done \ \ Some lemmas used by both SimplExport and ProveGraphRefine. \ lemmas sdiv_word_max_ineq = sdiv_word_max[folded zle_diff1_eq, simplified] lemmas signed_mult_eq_checks_all = signed_mult_eq_checks_double_size[where 'a="32" and 'b="64", simplified] signed_mult_eq_checks_double_size[where 'a="32 signed" and 'b="64 signed", simplified] signed_mult_eq_checks_double_size[where 'a="64" and 'b="128", simplified] signed_mult_eq_checks_double_size[where 'a="64 signed" and 'b="128 signed", simplified] lemmas signed_arith_ineq_checks_to_eq_all = signed_arith_ineq_checks_to_eq[where 'a="32"] signed_arith_ineq_checks_to_eq[where 'a="32", simplified word_size, simplified] signed_arith_ineq_checks_to_eq[where 'a="32 signed"] signed_arith_ineq_checks_to_eq[where 'a="32 signed", simplified word_size, simplified] signed_arith_ineq_checks_to_eq[where 'a="64"] signed_arith_ineq_checks_to_eq[where 'a="64", simplified word_size, simplified] signed_arith_ineq_checks_to_eq[where 'a="64 signed"] signed_arith_ineq_checks_to_eq[where 'a="64 signed", simplified word_size, simplified] lemmas signed_div_range_check_all = signed_div_range_check[where 'a="32", simplified word_size, simplified] signed_div_range_check[where 'a="32 signed", simplified word_size, simplified] signed_div_range_check[where 'a="64", simplified word_size, simplified] signed_div_range_check[where 'a="64 signed", simplified word_size, simplified] lemma word32_31_less: "31 < len_of TYPE (32 signed)" "31 > (0 :: nat)" "31 < len_of TYPE (32)" "31 > (0 :: nat)" by auto lemma word64_31_less: "31 < len_of TYPE (64 signed)" "31 > (0 :: nat)" "31 < len_of TYPE (64)" "31 > (0 :: nat)" by auto lemmas signed_shift_guard_to_word_all = signed_shift_guard_to_word[OF word32_31_less(1-2)] signed_shift_guard_to_word[OF word32_31_less(3-4)] signed_shift_guard_to_word[OF word64_31_less(1-2)] signed_shift_guard_to_word[OF word64_31_less(3-4)] lemmas guard_arith_simps = neg_le_iff_le signed_arith_eq_checks_to_ord signed_arith_ineq_checks_to_eq_all signed_div_range_check_all signed_mult_eq_checks_all signed_shift_guard_to_word_all sdiv_word_min[THEN eqTrueI] sdiv_word_max_ineq (* FIXME: move to word lib *) lemma small_downcasts: "unat (x :: 'a :: len word) < 2 ^ LENGTH('b :: len) \ unat (UCAST('a \ 'b) x) = unat x" apply (case_tac "LENGTH('a) \ LENGTH('b)", simp add: unat_ucast_up_simp) apply (simp add: unat_ucast unat_less_power) done (* FIXME: move to word lib *) lemma less_shift_makes_shift_cast_safe: "y < (a :: 'a :: len word) >> unat (x :: 'b :: len word) \ unat (UCAST('b \ 'a) x) = unat x" apply (prop_tac "unat x < LENGTH('a)") apply (rotate_tac) apply (erule contrapos_pp; simp add: not_less) apply (prop_tac "a >> unat x = 0") apply (rule shiftr_eq_0; simp) apply simp apply (subst small_downcasts) apply (meson le_less_trans n_less_equal_power_2 nat_less_le) apply simp done lemmas less_shift_makes_shift_cast_safe_arg_cong = arg_cong[where f="f w" for f w, OF less_shift_makes_shift_cast_safe] \ \ @{thm less_shift_makes_shift_cast_safe} allows us to remove the `ucast` in `unat (ucast x)`, but this loses potentially important type information. These rules act as "lenses" to make sure we only modify the relevant ucasts (the ones that show up in the guards of translated nontrivial shifts). \ lemmas less_shift_targeted_cast_convs = less_shift_makes_shift_cast_safe_arg_cong[where f=shiftr] less_shift_makes_shift_cast_safe_arg_cong[where f="(^)"] end