Library encode_decode
From mathcomp Require Import ssreflect ssrfun ssrbool eqtype ssrnat seq.
Require Import ssrZ ZArith_ext seq_ext machine_int multi_int.
Import MachineInt.
Require Import mips_bipl mapstos.
Import mips_bipl.expr_m.
Import mips_bipl.assert_m.
Local Open Scope machine_int_scope.
Local Open Scope heap_scope.
Local Open Scope mips_assert_scope.
Require Import ssrZ ZArith_ext seq_ext machine_int multi_int.
Import MachineInt.
Require Import mips_bipl mapstos.
Import mips_bipl.expr_m.
Import mips_bipl.assert_m.
Local Open Scope machine_int_scope.
Local Open Scope heap_scope.
Local Open Scope mips_assert_scope.
construct a heap from a list of int 32's
Definition list2heap (a : nat) (l : list (int 32)) : heap.t :=
map_prop_m.mk_finmap (zip (iota a (size l)) l).
Lemma dom_list2heap l x : heap.dom (list2heap x l) = iota x (size l).
Proof.
rewrite /list2heap -heap.elts_dom map_prop_m.elts_mk_finmap; last first.
rewrite unzip1_zip /= ?size_iota //; by apply ordset.ordered_iota.
by rewrite -/(unzip1 _) unzip1_zip // size_iota.
Qed.
Lemma cdom_list2heap l x : heap.cdom (list2heap x l) = l.
Proof.
rewrite /list2heap -heap.elts_cdom map_prop_m.elts_mk_finmap; last first.
rewrite unzip1_zip /= ?size_iota //; by apply ordset.ordered_iota.
by rewrite -/(unzip2 _) unzip2_zip // size_iota.
Qed.
Lemma disj_list2heap l n h : disj (iota n (size l)) (heap.dom h) -> list2heap n l # h.
Proof. move=> ?; by rewrite heap.disjE; apply/seq_ext.disP; rewrite dom_list2heap. Qed.
Local Open Scope zarith_ext_scope.
Local Open Scope mips_expr_scope.
Lemma mapstos_list2heap : forall l n e s, u2Z ( [ e ]e_ s ) = 4 * Z_of_nat n ->
u2Z ( [ e ]e_ s ) + 4 * (Z_of_nat (size l) - 1) < Zbeta 1 ->
(e |--> l) s (list2heap n l).
Proof.
elim=> [n e s e_mod e_fit | hd tl IH v n0 s Hv Hn /=].
- split; last by [].
apply Zdivide_mod.
exists (Z_of_nat n); by rewrite mulZC.
- destruct tl as [|i tl].
+ rewrite /list2heap /= heap.unionhe.
exists (heap.sing v hd), heap.emp; split; first by apply heap.disjhe.
split; first by rewrite heap.unionhe.
split; first by exists v.
split; last by [].
apply u2Z_add_mod => //.
apply Zdivide_mod.
exists (Z_of_nat v); by rewrite mulZC.
+ rewrite [i :: _]lock /list2heap /= -lock.
apply assert_m.con_cons.
* apply heap.disj_sym, disj_list2heap.
apply/disP; by rewrite heap.dom_sing dis_seq_singl.
* by exists v.
* apply (mapstos_ext (int_e ([ n0 ]e_s `+ four32)) s) => //.
apply IH.
- rewrite u2Z_add_Z2u //; last first.
rewrite (_ : Z_of_nat _ - 1 = 1 + Z_of_nat (size tl)) in Hn; last first.
rewrite [size _]/=; omegaz.
rewrite -Zbeta1E; lia.
rewrite Z_S Hv; ring.
- rewrite u2Z_add_Z2u //; last first.
rewrite !Z_S in Hn; rewrite -Zbeta1E; lia.
rewrite (_ : Z_of_nat _ - 1 = Z_of_nat (size (i :: tl))) in Hn; last by rewrite [size _]/=; omegaz.
lia.
Qed.
Lemma mapstos_inv_list2heap : forall l e s h, (e |--> l) s h ->
u2Z ( [ e ]e_ s) + 4 * Z_of_nat (size l) < Zbeta 1 ->
h = list2heap '|u2Z ( [ e ]e_ s `>> 2)| l.
Proof.
elim=> [e s h Hmem Hfit /= | hd tl IH e s h].
- rewrite /= in Hmem.
by case: Hmem.
- rewrite [assert_m.mapstos _ _]/=.
case=> h1 [h2 [Hdisj [Hunion [Hmem1 Hmem2]]]] Hinmem.
case: Hmem1 => loc [H1 H2].
rewrite /= in H2 *.
have -> : '|u2Z ( [ e ]e_ s `>> 2)| = loc.
rewrite (@shrl_2 _ (Z_of_nat loc)) // Z2uK //.
by rewrite Zabs_nat_Z_of_nat.
split; first by apply Zle_0_nat.
move: (max_u2Z ( [ e ]e_ s)).
rewrite H1 (_ : 2 ^^ 32 = 2 ^^ 30 * 4) // mulZC => X.
apply Zmult_gt_0_lt_reg_r in X => //; lia.
rewrite /list2heap /=.
have <- : '|u2Z ([ e ]e_ s `+ four32 `>> 2)| = S loc.
move: (@u2Z_shrl _ ([ e ]e_ s `+ four32) 2 refl_equal) => // X.
rewrite [_ ^^ _]/= (@u2Z_rem'' _ _ _ (1 + Z_of_nat loc)) in X; last first.
rewrite u2Z_add_Z2u // H1.
+ rewrite [_ ^^ _]/=; ring.
+ rewrite Z_S in Hinmem; rewrite -Zbeta1E; lia.
rewrite addZ0 u2Z_add_Z2u // in X; last first.
rewrite Z_S in Hinmem; rewrite -Zbeta1E; lia.
have -> : u2Z (eval e s `+ four32 `>> 2) = 1 + Z_of_nat loc by lia.
rewrite Zabs_nat_Zplus //; last exact/Zle_0_nat.
by rewrite Zabs_nat_Z_of_nat.
move: {IH}(IH _ _ _ Hmem2).
rewrite /list2heap.
move=> <- //; last first.
rewrite [eval _ _]/= u2Z_add_Z2u //.
+ rewrite [size _]/= Z_S in Hinmem; lia.
+ rewrite Z_S in Hinmem; rewrite -Zbeta1E; lia.
by rewrite -H2.
Qed.
Lemma inv_list2heap P l e s h : (P ** e |--> l) s h ->
u2Z ([e ]e_ s) + 4 * Z_of_nat (size l) < Zbeta 1 ->
@seq_ext.inc heap.l
(iota '|u2Z ([ e ]e_ s) / 4| (size l))
(heap.dom h).
Proof.
move=> Hmem Hfit.
case: Hmem => h1 [h2 [h1dh2 [h1Uh2 [Hh1 Hh2]]]].
apply mapstos_inv_list2heap in Hh2 => //.
rewrite h1Uh2.
set d := iota _ _.
rewrite (_ : d = heap.dom h2).
apply/seq_ext.incP => i Hi.
apply/seq_ext.inP.
rewrite heap.unionC //.
apply heap.in_dom_union_L.
by apply/seq_ext.inP.
by rewrite /d Hh2 dom_list2heap u2Z_shrl'.
Qed.
Lemma mapstos_inv_proj_list2heap P l e s h : (P ** e |--> l) s h ->
u2Z ( [ e ]e_ s) + 4 * Z_of_nat (size l) < Zbeta 1 ->
heap.proj h (iota '|(u2Z ([ e ]e_ s) / 4)| (size l)) =
list2heap '|u2Z ( [ e ]e_ s `>> 2)| l.
Proof.
move=> HP Hfit.
case: HP => h1 [h2 [h1dh2 [h1Uh2 [Hh1 Hh2]]]].
apply mapstos_inv_list2heap in Hh2 => //.
rewrite h1Uh2.
set d2 := iota _ _.
have -> : d2 = heap.dom h2 by rewrite /d2 Hh2 dom_list2heap u2Z_shrl'.
rewrite heap.proj_union_R_dom; last exact/heap.disj_sym.
by rewrite heap.proj_itself.
Qed.
Local Close Scope zarith_ext_scope.
extract a list of contiguous int 32's from a heap
Definition heap2list (b : heap.l) (n : nat) (h : heap.t) : list heap.v :=
heap.cdom (heap.proj h (seq.iota b n)).
Lemma len_heap2list : forall (n : nat) (a : heap.l) h,
List.incl (iota a n : list heap.l) (heap.dom h) -> size (heap2list a n h) = n.
Proof.
move=> n a h H.
have {}H : seq_ext.inc (seq.iota a n : seq.seq ssrnat.nat_eqType) (heap.dom h).
by apply/seq_ext.incP.
apply heap.dom_proj_exact in H; last first.
by apply ordset.ordered_iota.
by rewrite /heap2list heap.size_cdom_dom H seq.size_iota.
Qed.
Lemma heap2list2heap : forall n z l, size l = n -> heap2list z n (list2heap z l) = l.
Proof.
elim => [z [] //= _ | n IH z [|h t] // [len_t] ].
- by rewrite /heap2list heap.proj_emp heap.cdom_emp.
- rewrite /heap2list /list2heap /= heap.proj_union_sing; last first.
by rewrite seq.in_cons eqxx.
rewrite heap.cdom_union_sing /=.
+ congr cons.
rewrite heap.dom_proj_cons.
* exact: IH.
* by rewrite dom_list2heap // mem_iota ltnn.
+ apply order.lt_lb => m.
case/heap.in_dom_proj_inter => Hm1 Hm2.
rewrite dom_list2heap // in Hm1.
rewrite /heap.ltl /order.NatOrder.ltA /ltn /=.
move: Hm1.
by rewrite mem_iota => /andP[].
Qed.
Lemma heap2list_list2heap_union n z l h : size l = n ->
list2heap z l # h ->
heap2list z n (list2heap z l \U h) = heap2list z n (list2heap z l).
Proof.
move=> Hn Hdisj.
rewrite /heap2list.
move: (dom_list2heap l z).
rewrite Hn => <-.
by rewrite heap.proj_union_L_dom // heap.proj_itself.
Qed.