Timings for logical_reln_fund.v
- /home/gitlab-runner/builds/v6HyzL39/0/coq/coq/_bench/opam.OLD/ocaml-OLD/.opam-switch/build/coq-perennial.dev/./src/goose_lang/logical_reln_fund.v.timing
- /home/gitlab-runner/builds/v6HyzL39/0/coq/coq/_bench/opam.NEW/ocaml-NEW/.opam-switch/build/coq-perennial.dev/./src/goose_lang/logical_reln_fund.v.timing
From iris.proofmode Require Import tactics.
From iris.algebra Require Import auth excl.
From Perennial.algebra Require Import frac_count big_op.
From Perennial.goose_lang Require Import proofmode notation wpc_proofmode.
From Perennial.program_logic Require Import recovery_weakestpre recovery_adequacy spec_assert language_ctx.
From Perennial.goose_lang Require Import typing typed_translate adequacy refinement.
From Perennial.goose_lang Require Export recovery_adequacy spec_assert refinement_adequacy.
From Perennial.goose_lang Require Import metatheory.
From Perennial.Helpers Require Import Qextra.
From Perennial.Helpers Require List.
From Perennial.goose_lang Require Import logical_reln_defns.
Set Default Proof Using "Type".
Context {ext: ffi_syntax}.
Context {ffi: ffi_model}.
Context {ffi_semantics: ffi_semantics ext ffi}.
Context `{interp: !ffi_interp ffi}.
Context `{interp_adeq: !ffi_interp_adequacy}.
Context (impl_ty: ext_types ext).
Context {spec_ext: spec_ffi_op}.
Context {spec_ffi: spec_ffi_model}.
Context {spec_ffi_semantics: spec_ext_semantics spec_ext spec_ffi}.
Context `{spec_interp: @spec_ffi_interp spec_ffi}.
Context `{spec_adeq: !spec_ffi_interp_adequacy}.
Context (spec_ty: ext_types (@spec_ffi_op_field spec_ext)).
Notation sstate := (@state (@spec_ffi_op_field spec_ext) (spec_ffi_model_field)).
Notation sexpr := (@expr (@spec_ffi_op_field spec_ext)).
Notation sval := (@val (@spec_ffi_op_field spec_ext)).
Notation istate := (@state ext).
Notation iexpr := (@expr ext).
Notation ival := (@val ext).
Notation sty := (@ty (@val_tys _ spec_ty)).
Notation SCtx := (@Ctx (@val_tys _ spec_ty)).
Context `{hsT_model: !specTy_model spec_ty}.
Context (spec_trans: sval → ival → Prop).
Context (spec_atomic_transTy : SCtx -> sexpr -> iexpr -> sty -> sexpr -> iexpr -> sty -> Prop).
Context `{hG: !heapGS Σ} `{hRG: !refinement_heapG Σ} {hS: styG Σ}.
Lemma loc_paired_eq_iff ls l ls' l':
loc_paired ls l -∗
loc_paired ls' l' -∗
⌜ l = l' ↔ ls = ls' ⌝.
iIntros "(#Hmls&#Hml) (#Hmls'&#Hml')".
destruct (decide (ls = ls')).
iDestruct (meta_agree with "Hmls Hmls'") as %Heq.
destruct (decide (l = l')).
iDestruct (meta_agree with "Hml Hml'") as %Heq.
Lemma loc_paired_base_eq_iff ls l ls' l':
addr_offset l = addr_offset ls →
addr_offset l' = addr_offset ls' →
loc_paired (addr_base ls) (addr_base l) -∗
loc_paired (addr_base ls') (addr_base l') -∗
⌜ l = l' ↔ ls = ls' ⌝.
iIntros (??) "(#Hmls&#Hml) (#Hmls'&#Hml')".
destruct (decide (ls = ls')).
iDestruct (meta_agree with "Hmls Hmls'") as %Heq.
apply addr_base_and_offset_eq_iff; eauto; split; eauto.
destruct (decide (l = l')).
iDestruct (meta_agree with "Hml Hml'") as %Heq.
apply addr_base_and_offset_eq_iff; eauto; split; eauto.
Lemma is_loc_loc_paired ls l vTy:
is_loc ls l vTy -∗ loc_paired ls l.
Lemma is_loc_eq_iff ls l ls' l' vTy vTy':
is_loc ls l vTy -∗
is_loc ls' l' vTy' -∗
⌜ l = l' ↔ ls = ls' ⌝.
iApply (loc_paired_eq_iff with "H1 H2").
Lemma litv_loc_eq_iff (ls l ls' l': loc):
(l = l' ↔ ls = ls') →
((#l : ival) = #l' ↔ (#ls: sval) = #ls').
split; inversion 1; subst; do 2 f_equal; eapply Heq; auto.
Lemma arrayT_structRefT_promote vs v t:
val_interp (hS := hS) (arrayT t) vs v -∗
val_interp (hS := hS) (structRefT (flatten_ty t)) vs v.
rewrite val_interp_array_unfold.
iDestruct "Hv" as "[Hv|Hnull]".
iDestruct "Hv" as (l ls n idx H0lt Hnonempty (->&->&?&?&Heq1&Heq2)) "(Hsz1&Hsz1'&H1)".
iAssert (loc_paired (addr_base ls) (addr_base l)) with "[H1]" as "#Hpaired".
iDestruct "H1" as "(H&_)".
destruct (flatten_ty t); first by congruence.
iDestruct "H" as "(H&_)".
iApply is_loc_loc_paired; eauto.
assert (0 < length (flatten_ty t))%nat.
destruct (flatten_ty t); simpl in *; try congruence.
unshelve (iExists l, ls, (n * length (flatten_ty t))%nat, _, _).
destruct (flatten_ty t); simpl in *; try congruence.
iPureIntro; split_and!; eauto.
destruct (decide (0 ≤ idx ∧ idx < n)%Z) as [(Hr1&Hr2)|Hout]; last first.
assert (idx < 0 ∨ n <= idx) as [?|?] by lia.
assert (idx * length (flatten_ty t) + length (flatten_ty t) =
(idx + 1) * length (flatten_ty t)) as -> by ring.
apply Z.mul_nonpos_nonneg; lia.
apply Z.mul_le_mono_nonneg_r; lia.
iDestruct (big_sepL_elem_of _ (seq 0 n) (Z.to_nat idx) with "H1") as "H".
apply elem_of_list_In, in_seq.
assert (addr_base ls +ₗ length (flatten_ty t) * Z.to_nat idx = ls) as ->.
rewrite (addr_plus_off_decode ls); f_equal; word.
assert (addr_base l +ₗ length (flatten_ty t) * Z.to_nat idx = l) as ->.
rewrite (addr_plus_off_decode l); f_equal; word.
Lemma ctx_has_semTy_subst
e (es: sexpr) (t: sty) x v vs tx Γ:
ctx_has_semTy (hS := hS) (<[x:=tx]> Γ) es e t -∗
val_interp (hS := hS) tx vs v -∗
ctx_has_semTy (hS := hS) Γ (subst' x vs es) (subst' x v e) t.
iIntros (Γsubst Hproj) "Hsty Hspec Htrace Hctx".
destruct x as [|x] => //=.
iApply ("Hhasty" with "[] [$] [$] [$]").
rewrite -?subst_map_insert'.
iSpecialize ("Hhasty" $! (<[x := {| subst_ty := tx; subst_sval := vs; subst_ival := v |}]> Γsubst)
with "[] [$] [$] [$] [Hctx Hval]").
iPoseProof (big_sepM_insert_2 with "[Hval] [Hctx]") as "$".
rewrite ?fmap_insert //=.
Lemma structRefT_comparableTy_val_eq ts vs1 v1 vs2 v2:
val_interp (hS := hS) (structRefT ts) vs1 v1 -∗
val_interp (hS := hS) (structRefT ts) vs2 v2 -∗
⌜ v1 = v2 ↔ vs1 = vs2 ⌝.
iDestruct 1 as "[H1|Hnull1]";
iDestruct 1 as "[H2|Hnull2]".
iDestruct "H1" as (?? n1 ?? (?&?&?&?&Hoffset1)) "(Hpaired1&_)".
iDestruct "H2" as (?? n2 ?? (?&?&?&?&Hoffset2)) "(Hpaired2&_)".
iDestruct (loc_paired_base_eq_iff with "Hpaired1 Hpaired2") as %Heq; eauto.
iDestruct "Hnull2" as %(?&(Hnull2s&Hnull2)).
iDestruct "H1" as (????? (?&?&?&?&?)) "H".
split; subst; inversion 1; exfalso; (eapply plus_off_preserves_non_null; [| eassumption]; eauto).
iDestruct "Hnull1" as %(?&(Hnull1s&Hnull1)).
iDestruct "H2" as (????? (?&?&Hnnull1&Hnnull2&?)) "H".
split; subst; intros Hnulleq; symmetry in Hnulleq; inversion Hnulleq; subst; symmetry.
rewrite addr_base_of_plus //= in Hnnull2.
rewrite addr_base_of_plus //= in Hnnull1.
iDestruct "Hnull1" as %(?&(Hnull1s&Hnull1)).
iDestruct "Hnull2" as %(?&(Hnull2s&Hnull2)).
(* this is kind of round about since inversion is behaving oddly on the null offset hypothesis *)
cut (∀ (l l': loc), #l = #l' → LitLoc l = LitLoc l'); eauto.
(* this is kind of round about since inversion is behaving oddly on the null offset hypothesis *)
cut (∀ (l l': loc), (#l = (#l': @val (@spec_ffi_op_field spec_ext))) →
LitLoc l = LitLoc l'); eauto.
Lemma structRefT_unboxed_baseTy ts vs v:
val_interp (hS := hS) (structRefT ts) vs v -∗
⌜ ∃ ls l, vs = LitV ls ∧ v = LitV l ∧ lit_is_unboxed ls ∧ lit_is_unboxed l ⌝.
iDestruct 1 as "[H1|Hnull1]".
iDestruct "H1" as (?? n1 ?? (?&?&?&?&Hoffset1)) "(Hpaired1&_)".
do 2 eexists; split_and!; eauto; simpl; eauto.
iDestruct "Hnull1" as %(?&(Hnull1s&Hnull1)).
do 2 eexists; split_and!; eauto; simpl; eauto.
Lemma structRefT_unboxedTy ts vs v:
val_interp (hS := hS) (structRefT ts) vs v -∗
⌜ val_is_unboxed vs ∧ val_is_unboxed v ⌝.
iDestruct 1 as "[H1|Hnull1]".
iDestruct "H1" as (?? n1 ?? (?&?&?&?&Hoffset1)) "(Hpaired1&_)".
iDestruct "Hnull1" as %(?&(Hnull1s&Hnull1)).
Lemma unboxed_baseTy_val_unboxed_lit t vs v:
is_unboxed_baseTy t = true →
val_interp (hS := hS) t vs v -∗
⌜ ∃ ls l, vs = LitV ls ∧ v = LitV l ∧ lit_is_unboxed ls ∧ lit_is_unboxed l ⌝.
induction t => vs v; try (inversion 1; fail).
destruct t; iPureIntro; naive_solver.
iDestruct (arrayT_structRefT_promote with "H") as "H".
iApply (structRefT_unboxed_baseTy); eauto.
iApply (structRefT_unboxed_baseTy); eauto.
Lemma unboxedTy_val_unboxed t vs v:
is_unboxedTy t = true →
val_interp (hS := hS) t vs v -∗
⌜ val_is_unboxed vs ∧ val_is_unboxed v ⌝.
induction t => vs v; try (inversion 1; fail).
destruct t; iPureIntro; naive_solver.
iDestruct "H" as (?? (->&->)) "H".
iDestruct (unboxed_baseTy_val_unboxed_lit with "H") as %(?&?&?&?&?&?); subst; eauto.
iDestruct "H" as (?? (->&->)) "H".
iDestruct (unboxed_baseTy_val_unboxed_lit with "H") as %(?&?&?&?&?&?); subst; eauto.
iDestruct (arrayT_structRefT_promote with "H") as "H".
iApply (structRefT_unboxedTy); eauto.
iApply (structRefT_unboxedTy); eauto.
Lemma comparableTy_val_eq t vs1 v1 vs2 v2:
is_comparableTy t = true →
val_interp (hS := hS) t vs1 v1 -∗
val_interp (hS := hS) t vs2 v2 -∗
⌜ v1 = v2 ↔ vs1 = vs2 ⌝.
induction t => vs1 v1 vs2 v2; try (inversion 1; fail).
destruct t; iPureIntro; naive_solver.
iDestruct 1 as (?? ?? (->&->)) "(H1&H2)".
iDestruct 1 as (?? ?? (->&->)) "(H1'&H2')".
iPoseProof (IHt1 with "H1 H1'") as "%"; eauto.
iPoseProof (IHt2 with "H2 H2'") as "%"; eauto.
iDestruct 1 as "[H|H]";
iDestruct 1 as "[H'|H']";
iDestruct "H" as (?? (->&->)) "H";
iDestruct "H'" as (?? (->&->)) "H'".
iPoseProof (IHt1 with "H H'") as "%"; eauto.
split; inversion 1; subst; f_equal; naive_solver.
iPureIntro; split; inversion 1.
iPureIntro; split; inversion 1.
iPoseProof (IHt2 with "H H'") as "%"; eauto.
split; inversion 1; subst; f_equal; naive_solver.
iDestruct (arrayT_structRefT_promote with "H1") as "H1".
iDestruct (arrayT_structRefT_promote with "H2") as "H2".
iApply (structRefT_comparableTy_val_eq with "H1 H2").
apply structRefT_comparableTy_val_eq.
Global Arguments sty_val_interp {ext ffi interp spec_ext spec_ffi spec_ffi_semantics spec_interp _ specTy_model Σ _ _}.
Lemma sty_val_size:
forall τ vs v,
sty_val_interp hS τ vs v -∗
⌜ length (flatten_struct vs) = 1%nat ∧
length (flatten_struct v) = 1%nat ⌝.
by iDestruct (sty_val_flatten with "[$]") as %[-> ->].
Lemma length_flatten_well_typed vs v t:
storable t →
val_interp (hS := hS) t vs v -∗
⌜ length (flatten_ty t) = length (flatten_struct vs) ∧
length (flatten_ty t) = length (flatten_struct v) ⌝.
iInduction t as [] "IH" forall (vs v).
destruct t; iDestruct "Hval" as %Hval;
repeat destruct Hval as (?&Hval); subst; eauto.
iDestruct "Hval" as (???? (?&?)) "(H1&H2)".
destruct Hstore as (?&?).
iDestruct ("IH" with "[//] [$]") as %[Heq1 Heq2].
iDestruct ("IH1" with "[//] [$]") as %[Heq1' Heq2'].
iDestruct "Hval" as "[Hval|Hval]"; iDestruct "Hval" as (?? (?&?)) "Hval";
subst; eauto.
iDestruct "Hval" as (?????? (?&?)) "H1".
iDestruct "Hval" as "[Hval|Hnull]"; last first.
iDestruct "Hnull" as (?) "(%&%)"; subst.
iDestruct "Hval" as (?????? (?&?&?&?)) "H1".
iDestruct "Hval" as (?) "(%&%)"; subst.
iDestruct "Hval" as "[Hval|Hnull]"; last first.
iDestruct "Hnull" as (?) "(%&%)"; subst.
iDestruct "Hval" as (????? (?&?&?&?)) "H1".
iDestruct (sty_val_size with "Hval") as "(%&%)"; eauto.
Lemma flatten_well_typed vs v t i vsi vi ti:
storable t →
flatten_ty t !! i = Some ti →
flatten_struct vs !! i = Some vsi →
flatten_struct v !! i = Some vi →
val_interp (hS := hS) t vs v -∗
val_interp (hS := hS) ti vsi vi.
iIntros (Hstore Hlookup1 Hlookup2 Hlookup3) "Hval".
iInduction t as [] "IH" forall (vs v i Hlookup1 Hlookup2 Hlookup3).
destruct t; destruct i; simpl in *; inversion Hlookup1; subst; eauto;
iDestruct "Hval" as %Hval; repeat destruct Hval as (?&Hval); subst; eauto;
simpl in *; inversion Hlookup2; inversion Hlookup3; subst; eauto.
iDestruct "Hval" as (???? (?&?)) "(H1&H2)".
simpl in Hlookup1, Hlookup2, Hlookup3.
destruct Hstore as (?&?).
iDestruct (length_flatten_well_typed with "H1") as %[Hlen1 Hlens1]; first done.
iDestruct (length_flatten_well_typed with "H2") as %[Hlen2 Hlens2]; first done.
apply lookup_app_Some in Hlookup1 as [Hleft|Hright].
specialize (lookup_lt_Some _ _ _ Hleft) => Hlen.
rewrite lookup_app_l in Hlookup2; last by lia.
rewrite lookup_app_l in Hlookup3; last by lia.
destruct Hright as (?&Hright).
specialize (lookup_lt_Some _ _ _ Hright) => Hlen.
rewrite lookup_app_r in Hlookup2; last by lia.
rewrite lookup_app_r in Hlookup3; last by lia.
iDestruct "Hval" as "[Hval|Hval]"; iDestruct "Hval" as (?? (?&?)) "Hval";
subst; eauto.
destruct i; simpl in *; try inversion Hlookup1; subst; eauto.
simpl in *; inversion Hlookup2; inversion Hlookup3; subst; eauto.
destruct i; simpl in *; try inversion Hlookup1; subst; eauto.
simpl in *; inversion Hlookup2; inversion Hlookup3; subst; eauto.
iDestruct "Hval" as (?????? (->&->)) "H".
destruct i; simpl in *; try inversion Hlookup1; subst; eauto.
simpl in *; inversion Hlookup2; inversion Hlookup3; subst; eauto.
iDestruct "Hval" as "[Hval|Hnull]".
iDestruct "Hval" as (?????? (?&?&?&?)) "H1".
destruct i; simpl in *; try inversion Hlookup1; subst; eauto.
simpl in *; inversion Hlookup2; inversion Hlookup3; subst; eauto.
unshelve (iExists _, _, _, _, _, _; iSplitL ""; first done; eauto); eauto.
iDestruct "Hnull" as (?) "(%&%)"; subst.
destruct i; simpl in *; try inversion Hlookup1; subst; eauto.
simpl in *; inversion Hlookup2; inversion Hlookup3; subst; eauto.
iDestruct "Hval" as (?) "(%&%)"; subst.
destruct i; simpl in *; try inversion Hlookup1; subst; eauto.
simpl in *; inversion Hlookup2; inversion Hlookup3; subst; eauto.
iDestruct "Hval" as "[Hval|Hnull]".
iDestruct "Hval" as (????? (?&?&?&?)) "H1".
destruct i; simpl in *; try inversion Hlookup1; subst; eauto.
simpl in *; inversion Hlookup2; inversion Hlookup3; subst; eauto.
unshelve (iExists _, _, _, _, _; iSplitL ""; first done; eauto); eauto.
iDestruct "Hnull" as (?) "(%&%)"; subst.
destruct i; simpl in *; try inversion Hlookup1; subst; eauto.
simpl in *; inversion Hlookup2; inversion Hlookup3; subst; eauto.
iDestruct (sty_val_flatten with "Hval") as %[Heq1 Heq2].
destruct i; simpl in *; try inversion Hlookup1; subst; eauto.
rewrite Heq1 in Hlookup2.
rewrite Heq2 in Hlookup3.
simpl in *; inversion Hlookup2; inversion Hlookup3; subst; eauto.
Scheme expr_typing_ind := Induction for expr_transTy Sort Prop with
val_typing_ind := Induction for val_transTy Sort Prop.
Global Arguments expr_typing_ind spec_op spec_ty impl_op spec_trans
(* make it possible to supply P and P0 using `with` *)
spec_atomic_transTy P P0 : rename.
Lemma loc_paired_init l ls:
meta_token l ⊤ -∗
meta_token (hG := refinement_na_heapG) ls ⊤ ==∗
loc_paired ls l.
iMod (meta_set ⊤ l ls rlN with "[$]").
iMod (meta_set (hG := refinement_na_heapG) ⊤ ls l rlN with "[$]").
Lemma is_loc_init l ls v vs:
forall P,
l ↦ v -∗
meta_token l ⊤ -∗
ls s↦ vs -∗
meta_token (hG := refinement_na_heapG) ls ⊤ -∗
P vs v -∗
|={⊤}=> is_loc ls l P.
iIntros "Hl Hltok Hls Hlstok HP".
iMod (fc_auth_init) as (γ) "Hfc".
iMod (loc_paired_init with "[$] [$]") as "$".
iMod (inv_alloc locN ⊤ (loc_inv γ ls l P) with "[-]") as "$"; last done.
Lemma logical_reln_prepare_write t ts vs v j K (Hctx: LanguageCtx K):
{{{ spec_ctx ∗ val_interp (hS := hS) (structRefT (t :: ts)) vs v ∗ j ⤇ K (PrepareWrite vs) }}}
PrepareWrite v
{{{ RET #();
∃ (ls l: loc) mem_vs mem_v γ,
⌜ vs = #ls ∧ v = #l ⌝ ∗
inv locN (loc_inv γ ls l (val_interp (hS := hS) t)) ∗
fc_tok γ (1/2)%Qp ∗
j ⤇ K #() ∗
na_heap_mapsto_st (hG := refinement_na_heapG) WSt ls (1/2)%Qp mem_vs ∗
(∀ v' : sval, na_heap_mapsto ls 1 v' -∗ heap_mapsto ls 1 v') ∗
na_heap_mapsto_st (hG := goose_na_heapGS) WSt l 1 mem_v ∗
(∀ v' : ival, na_heap_mapsto l 1 v' -∗ heap_mapsto l 1 v')}}}.
iIntros "(#Hctx&Hvl&Hj) HΦ".
rewrite val_interp_struct_unfold.
iDestruct "Hvl" as "[Hv|Hnull]".
iDestruct "Hv" as (lv lvs n H0lt Hnonemtpy (->&->&?&?&?)) "(Hpaired&Hblock1&Hblocked2&Hloc)".
iDestruct "Hloc" as "[Hinbound|Hoob]".
iDestruct "Hinbound" as "(H&_)".
iDestruct "H" as "(Hlocinv&Hpaired')".
iDestruct "Hlocinv" as (γ) "#Hlocinv".
iInv "Hlocinv" as "Hlocinv_body" "Hclo".
iDestruct "Hlocinv_body" as (mem_vs mem_v) "H".
iDestruct "H" as "[H0readers|[Hreaders|Hwriter]]".
iDestruct "H0readers" as "(>Hfc&>Hspts&>Hpts&#Hval)".
iApply (wp_prepare_write with "[$]").
iMod (@ghost_prepare_write _ _ _ _ _ _ _ _ _ _ Hctx with "[$] Hspts Hj") as "(Hspts&Hptsclo&Hj)".
iDestruct "Hspts" as "(Hspts1&Hspts2)".
iMod (fc_auth_first_tok with "Hfc") as "(Hfc&Htok)".
iMod ("Hclo" with "[Hspts1 Hfc Hval]").
iApply fupd_mask_intro_subseteq; first by set_solver+.
iDestruct "Hreaders" as (q q' n') "(>%&>Hfc&>Hspts&Hspts_clo&>Hpts&#Hval)".
iMod (ghost_prepare_write_read_stuck with "Hctx Hspts Hj") as %[].
(* UB: writer during write *)
iDestruct "Hwriter" as "(>Hfc&>Hspts)".
iMod (ghost_prepare_write_write_stuck with "Hctx Hspts Hj") as %[].
iDestruct "Hoob" as %Hoob.
iMod (ghost_prepare_write_block_oob_stuck with "[$] [$] [$]") as %[].
iDestruct "Hnull" as %(?&->&->).
iMod (ghost_prepare_write_null_stuck with "[$] [$]") as %[].
rewrite addr_base_of_plus //=.
Lemma logical_reln_finish_store (ls l: loc) (vs vs': sval) (v v': ival) j K (Hctx: LanguageCtx K) (γ: gname):
forall vTy,
{{{ spec_ctx ∗ vTy vs v ∗ j ⤇ K (FinishStore #ls vs) ∗ fc_tok γ (1/2)%Qp ∗
inv locN (loc_inv γ ls l vTy) ∗
na_heap_mapsto_st (hG := refinement_na_heapG) WSt ls (1/2)%Qp vs' ∗
(∀ v' : sval, na_heap_mapsto ls 1 v' -∗ heap_mapsto ls 1 v') ∗
na_heap_mapsto_st (hG := goose_na_heapGS) WSt l 1 v' ∗
(∀ v' : ival, na_heap_mapsto l 1 v' -∗ heap_mapsto l 1 v')
}}}
FinishStore #l v
{{{ RET #(); j ⤇ K (of_val #()) }}}.
iIntros "(#Hctx&Hv&Hj&Htok&#Hlocinv&Hspts&Hspts_clo&Hpts&Hpts_clo) HΦ".
iInv "Hlocinv" as "Hlocinv_body" "Hclo".
iDestruct "Hlocinv_body" as (mem_vs mem_v) "H".
iDestruct "H" as "[H0readers|[Hreaders|Hwriter]]".
iDestruct "H0readers" as "(>Hfc&_&>Hpts'&_)".
iDestruct (heap_mapsto_na_acc with "Hpts'") as "(Hpts'&_)".
rewrite ?na_heap_mapsto_eq /na_heap_mapsto_def.
iDestruct (na_heap_mapsto_st_frac_valid2 with "Hpts Hpts'") as %Hval.
apply Z2Qc_inj_le in Hval.
iDestruct "Hreaders" as (q q' n') "(>%&>Hfc&>Hspts'&Hspts'_clo&>Hpts'&_)".
iDestruct (heap_mapsto_na_acc with "Hpts'") as "(Hpts'&_)".
rewrite ?na_heap_mapsto_eq /na_heap_mapsto_def.
iDestruct (na_heap_mapsto_st_frac_valid2 with "Hpts Hpts'") as %Hval.
eapply Qp.not_add_le_l, Hval.
iDestruct "Hwriter" as "(>Hfc&>Hspts')".
iDestruct (na_heap_mapsto_st_agree (hG := refinement_na_heapG) with "[Hspts Hspts']") as %Heq.
iCombine "Hspts Hspts'" as "Hspts".
wp_apply (wp_finish_store with "[$]").
iMod (ghost_finish_store with "Hctx Hspts Hspts_clo Hj") as "(?&Hj)".
iMod (fc_auth_drop_last with "[$]") as "Hfc".
iMod ("Hclo" with "[-Hj HΦ]").
iApply fupd_mask_intro_subseteq; first by set_solver+.
Lemma logical_reln_start_read t ts vs v j K (Hctx: LanguageCtx K):
{{{ spec_ctx ∗ val_interp (hS := hS) (structRefT (t :: ts)) vs v ∗ j ⤇ K (StartRead vs) }}}
StartRead v
{{{ mem_v, RET mem_v;
∃ (ls l: loc) (mem_vs: sval) γ q,
⌜ vs = #ls ∧ v = #l ∧ ls ≠ null ∧ l ≠ null ⌝ ∗
inv locN (loc_inv γ ls l (val_interp (hS := hS) t)) ∗
fc_tok γ q ∗
j ⤇ K mem_vs ∗
val_interp (hS := hS) t mem_vs mem_v ∗
na_heap_mapsto_st (hG := refinement_na_heapG) (RSt O) ls q mem_vs ∗
na_heap_mapsto_st (hG := goose_na_heapGS) (RSt 1) l q mem_v ∗
(∀ v' : ival, na_heap_mapsto l 1 v' -∗ heap_mapsto l 1 v')}}}.
iIntros "(#Hctx&Hvl&Hj) HΦ".
rewrite val_interp_struct_unfold.
iDestruct "Hvl" as "[Hv|Hnull]".
iDestruct "Hv" as (lv lvs n H0lt Hnonemtpy (->&->&?&?&?)) "(Hpaired&Hblock1&Hblocked2&Hloc)".
iDestruct "Hloc" as "[Hinbound|Hoob]".
iDestruct "Hinbound" as "(H&_)".
iDestruct "H" as "(Hlocinv&Hpaired')".
iDestruct "Hlocinv" as (γ) "#Hlocinv".
iInv "Hlocinv" as "Hlocinv_body" "Hclo".
iDestruct "Hlocinv_body" as (mem_vs mem_v) "H".
iDestruct "H" as "[H0readers|[Hreaders|Hwriter]]".
iDestruct "H0readers" as "(>Hfc&>Hspts&>Hpts&#Hval)".
iApply (wp_start_read with "[$]").
iIntros "!> (Hpts&Hpts_clo)".
iDestruct (heap_mapsto_na_acc with "Hspts") as "(Hspts&Hspts_clo)".
rewrite na_heap_mapsto_eq.
iMod (@ghost_start_read _ _ _ _ _ _ _ _ _ _ Hctx with "[$] Hspts Hj") as "(Hspts&Hj)".
replace (RSt 1) with (RSt (1 + O)%nat) by eauto.
iMod (fc_auth_first_tok with "Hfc") as "(Hfc&Htok)".
iEval (replace 1%Qp with (1/2 + 1/2)%Qp by apply Qp.half_half) in "Hpts".
iEval (replace 1%Qp with (1/2 + 1/2)%Qp by apply Qp.half_half) in "Hspts".
iDestruct (na_heap_mapsto_st_rd_frac _ 1 O with "Hpts") as "(Hpts1&Hpts2)".
iDestruct (na_heap_mapsto_st_rd_frac _ 1 O with "Hspts") as "(Hspts1&Hspts2)".
iMod ("Hclo" with "[Hpts2 Hspts1 Hfc Hval]").
iExists (1/2)%Qp, (1/2)%Qp, _.
rewrite Qp.half_half; eauto.
rewrite -na_heap_mapsto_eq.
iApply (na_mapsto_to_heap with "H").
apply addr_base_non_null; eauto.
iApply (na_mapsto_to_heap with "[Hpts2]").
apply addr_base_non_null; eauto.
rewrite na_heap_mapsto_eq /na_heap_mapsto_def.
iApply fupd_mask_intro_subseteq; first by set_solver+.
iPureIntro; split_and!; eauto;
eapply addr_base_non_null; eauto.
iDestruct "Hreaders" as (q q' n') "(>%&>Hfc&>Hspts&Hspts_clo&>Hpts&#Hval)".
iApply (wp_start_read with "[$]").
iIntros "!> (Hpts&Hpts_clo)".
rewrite na_heap_mapsto_eq.
iMod (@ghost_start_read _ _ _ _ _ _ _ _ _ _ Hctx with "[$] Hspts Hj") as "(Hspts&Hj)".
replace (S (Pos.to_nat n')) with (S (Pos.to_nat n') + 0)%nat by lia.
iMod (fc_auth_new_tok _ q q' with "Hfc") as "(Hfc&Htok)"; eauto.
specialize (Qp.div_2 q') => Hq'.
rewrite -[x in na_heap_mapsto_st _ lv x _]Hq'.
rewrite -[x in na_heap_mapsto_st (hG := refinement_na_heapG) _ _ x mem_vs]Hq'.
iDestruct (na_heap_mapsto_st_rd_frac _ 1 O with "Hpts") as "(Hpts1&Hpts2)".
iDestruct (na_heap_mapsto_st_rd_frac _ _ _ with "Hspts") as "(Hspts1&Hspts2)".
iMod ("Hclo" with "[Hpts2 Hspts1 Hfc Hval]").
iExists (q + q'/2)%Qp, (q'/2)%Qp, _.
replace (S (Pos.to_nat n')) with ((Pos.to_nat (n' + 1)))%nat by lia.
rewrite -na_heap_mapsto_eq.
iApply (na_mapsto_to_heap with "H").
apply addr_base_non_null; eauto.
iApply (na_mapsto_to_heap with "[Hpts2]").
apply addr_base_non_null; eauto.
rewrite na_heap_mapsto_eq /na_heap_mapsto_def.
iApply fupd_mask_intro_subseteq; first by set_solver+.
iPureIntro; split_and!; eauto; eapply addr_base_non_null; eauto.
rewrite -na_heap_mapsto_eq.
iApply (na_mapsto_to_heap with "H").
apply addr_base_non_null; eauto.
(* UB: writer during read *)
iDestruct "Hwriter" as "(>Hfc&>Hspts)".
iMod (ghost_start_read_write_stuck with "Hctx Hspts Hj") as %[].
iDestruct "Hoob" as %Hoob.
iMod (ghost_start_read_block_oob_stuck with "[$] [$] [$]") as %[].
iDestruct "Hnull" as %(?&->&->).
iMod (ghost_start_read_null_stuck with "[$] [$]") as %[].
rewrite addr_base_of_plus //=.
Lemma logical_reln_finish_read (ls l: loc) (vs': sval) (v': ival) j K (Hctx: LanguageCtx K) (γ: gname) q
(Hnonnull: l ≠ null):
forall vTy,
{{{ spec_ctx ∗ j ⤇ K (FinishRead #ls) ∗ fc_tok γ q ∗
inv locN (loc_inv γ ls l vTy) ∗
na_heap_mapsto_st (hG := refinement_na_heapG) (RSt O) ls q vs' ∗
na_heap_mapsto_st (hG := goose_na_heapGS) (RSt 1) l q v' ∗
(∀ v' : ival, na_heap_mapsto l 1 v' -∗ heap_mapsto l 1 v')
}}}
FinishRead #l
{{{ RET #(); j ⤇ K (of_val #()) }}}.
iIntros "(#Hctx&Hj&Htok&#Hlocinv&Hspts&Hpts&Hpts_clo) HΦ".
iInv "Hlocinv" as "Hlocinv_body" "Hclo".
iDestruct "Hlocinv_body" as (mem_vs mem_v) "H".
iDestruct "H" as "[H0readers|[Hreaders|Hwriter]]".
iDestruct "H0readers" as "(>Hfc&_&>Hpts'&_)".
iDestruct (heap_mapsto_na_acc with "Hpts'") as "(Hpts'&_)".
rewrite ?na_heap_mapsto_eq /na_heap_mapsto_def.
iDestruct (na_heap_mapsto_st_frac_valid2 with "Hpts Hpts'") as %Hval.
revert Hval; rewrite (comm _ q 1%Qp).
iDestruct "Hreaders" as (q1 q2 n') "(>Hq_sum&>Hfc&>Hspts'&Hspts'_clo&>Hpts'&Hvty)".
iDestruct "Hq_sum" as %Hq_sum.
iDestruct (heap_mapsto_na_acc with "Hpts'") as "(Hpts'&_)".
wp_apply (wp_finish_read with "[Hpts]").
iApply na_mapsto_to_heap; eauto.
iDestruct (heap_mapsto_na_acc with "Hpts") as "(Hpts&_)".
rewrite ?na_heap_mapsto_eq /na_heap_mapsto_def.
assert (n' = 1 ∨ ∃ n'', n' = 1 + n'')%positive as [H1reader|Hmore].
induction n' using Pos.peano_ind; eauto.
iDestruct (fc_auth_last_agree with "Hfc Htok") as %Hq.
iDestruct (na_heap_mapsto_st_agree with "[Hpts Hpts']") as %Heq.
iDestruct (na_heap_mapsto_st_rd_frac with "[$]") as "Hpts".
rewrite Hq_sum Nat.add_0_r.
iMod (ghost_finish_read with "Hctx Hspts' Hj") as "(Hspts'&Hj)".
iDestruct (na_heap_mapsto_st_agree (hG := refinement_na_heapG) with "[Hspts Hspts']") as %Heq.
iDestruct (na_heap_mapsto_st_rd_frac (hG := refinement_na_heapG) with "[Hspts Hspts']") as "Hspts".
iMod (fc_auth_drop_last with "[$]") as "Hfc".
iMod ("Hclo" with "[- Hj HΦ]").
iDestruct ("Hpts_clo" with "[$]") as "$".
iEval (rewrite comm Hq_sum) in "Hspts".
iApply fupd_mask_intro_subseteq; first by set_solver+.
destruct Hmore as (n''&->).
iDestruct (fc_auth_non_last_agree with "[$] [$]") as %(q'&Hq).
iDestruct (na_heap_mapsto_st_agree with "[Hpts Hpts']") as %Heq.
iDestruct (na_heap_mapsto_st_rd_frac with "[$]") as "Hpts".
replace (Pos.to_nat (1 + n'')) with (S (Pos.to_nat n'')) by lia.
iMod (ghost_finish_read with "Hctx Hspts' Hj") as "(Hspts'&Hj)".
iDestruct (na_heap_mapsto_st_agree (hG := refinement_na_heapG) with "[Hspts Hspts']") as %Heq.
iDestruct (na_heap_mapsto_st_rd_frac (hG := refinement_na_heapG) with "[Hspts Hspts']") as "Hspts".
iMod (fc_auth_drop with "[$]") as "Hfc".
iMod ("Hclo" with "[- Hj HΦ]").
rewrite -assoc {1}(comm _ q2).
iApply na_mapsto_to_heap; auto.
rewrite na_heap_mapsto_eq.
iApply fupd_mask_intro_subseteq; first by set_solver+.
iDestruct "Hwriter" as "(>Hfc&>Hspts')".
iDestruct (na_heap_mapsto_st_WSt_agree (hG := refinement_na_heapG) with "[Hspts Hspts']") as %Heq.
Existing Instances sty_inv_persistent.
Lemma val_interp_structRefT_is_loc ts vs v :
val_interp (hS:=hS) (structRefT ts) vs v -∗
⌜∃ l1 l2, vs = LitV (LitLoc l1) ∧ v = LitV (LitLoc l2)⌝.
iDestruct 1 as "[H|Hnull]".
iDestruct "H" as (?? n ?? (?&?&?&?&Hoffset)) "(Hpaired&_)".
iDestruct "Hnull" as %(?&(Hnulls&Hnull)).
Lemma is_comparableTy_is_comparable t vs v :
is_comparableTy t = true →
val_interp (hS:=hS) t vs v -∗
⌜is_comparable vs ∧ is_comparable v⌝.
induction t; simpl; intros ?? Hcompare; try congruence.
destruct t; cbn [base_ty_interp]; iPureIntro; naive_solver.
iDestruct 1 as (???? [-> ->]) "[? ?]".
apply andb_true_iff in Hcompare as [? ?].
iDestruct (IHt1 with "[$]") as %[? ?]; auto.
iDestruct (IHt2 with "[$]") as %[? ?]; auto.
apply andb_true_iff in Hcompare as [? ?].
iDestruct 1 as "[ (%&%&%Heq&?) | (%&%&%Heq&?) ]".
iDestruct (IHt1 with "[$]") as %?; auto.
iDestruct (IHt2 with "[$]") as %?; auto.
iDestruct (arrayT_structRefT_promote with "H") as "H".
iDestruct (val_interp_structRefT_is_loc with "H") as (??) "[-> ->]".
iDestruct (val_interp_structRefT_is_loc with "H") as (??) "[-> ->]".
Lemma sty_fundamental_lemma:
sty_rules_obligation spec_trans →
sty_atomic_obligation spec_atomic_transTy →
∀ Γ es e τ, expr_transTy _ _ _ spec_trans spec_atomic_transTy Γ es e τ →
⊢ ctx_has_semTy (hS := hS) Γ es e τ.
iIntros (Hrules Hatomic ???? Htyping).
induction Htyping using @expr_typing_ind with
(spec_trans := spec_trans)
(P := (λ Γ es e τ
(HTYPE: expr_transTy _ _ _ spec_trans spec_atomic_transTy Γ es e τ),
⊢ ctx_has_semTy (hS := hS) Γ es e τ))
(P0 := (λ Γ vs v τ
(HTYPE: val_transTy _ _ _ spec_trans spec_atomic_transTy Γ vs v τ),
⊢ sty_inv hS -∗ spec_ctx -∗ trace_ctx -∗ val_interp (hS := hS) τ vs v));
try (intros; iIntros (Γsubst HPROJ) "#Hinv #Hspec #Htrace #Hctx");
try (intros; iIntros "#Hinv #Hspec #Htrace").
rewrite lookup_fmap in e.
apply fmap_Some_1 in e as (t'&?&?).
iDestruct (big_sepM_lookup with "Hctx") as "H"; first eauto.
rewrite /= ?lookup_fmap H //=.
iApply wpc_value; iSplit.
iExists _; iFrame "H"; iFrame.
iPoseProof (IHHtyping1 with "[//] [$] [$] [$] [$]") as "H"; eauto.
wpc_bind (subst_map ((subst_ival <$> Γsubst)) x2).
spec_bind (subst_map ((subst_sval <$> Γsubst)) x1) as Hctx'.
iSpecialize ("H" $! j _ Hctx' with "Hj").
iApply (wpc_mono' with "[] [] H"); last auto.
iDestruct "H" as (vs2) "(Hj&Hv2)".
wpc_bind (subst_map _ f2).
iPoseProof (IHHtyping2 with "[//] [$] [$] [$] [$]") as "H"; eauto.
iSpecialize ("H" $! j (λ x, K (ectx_language.fill [AppLCtx (vs2)] x)) with "[] Hj").
apply comp_ctx; last done.
iApply (wpc_mono' with "[Hv2] [] H"); last by eauto.
iDestruct "H" as (vs1) "(Hj&Hv1)".
iDestruct "Hv1" as (?????? (Heq1&Heq2)) "#Hinterp".
iSpecialize ("Hinterp" $! _ _ with "Hv2").
iApply ("Hinterp" with "Hj").
iApply (IHHtyping with "[$] [$] [$]").
iMod (ghost_step_lifting_puredet with "[Hj]") as "(Hj&_)"; swap 1 3.
iDestruct "Hspec" as "($&?)".
apply head_prim_step_trans.
iExists _, _, _, _, _, _; iSplit; first eauto.
wpc_pures; first by eauto.
iMod (ghost_step_lifting_puredet with "[Hj]") as "(Hj&_)"; swap 1 3.
iDestruct "Hspec" as "($&?)".
(* TODO: make spec_ctx auto frame source_ctx *)
apply head_prim_step_trans.
iPoseProof (ctx_has_semTy_subst with "[] []") as "H1".
iExists _, _, _, _, _, _.
iPoseProof (ctx_has_semTy_subst with "[] Hval") as "H2".
iSpecialize ("H2" with "[//] [$] [$] [$] [$] [//] [Hj]").
do 2 (rewrite -subst_map_binder_insert' subst_map_binder_insert).
iEval (rewrite (binder_delete_commute f x)).
do 2 (rewrite -subst_map_binder_insert' subst_map_binder_insert).
iEval (rewrite {2}binder_delete_commute).
iMod (ghost_step_lifting_puredet with "[Hj]") as "(Hj&Hchild)"; swap 1 3.
iDestruct "Hspec" as "($&?)".
apply head_prim_step_trans.
iEval (simpl; rewrite right_id) in "Hchild".
iDestruct "Hchild" as (j') "Hj'".
iApply (wpc_fork with "[Hj']").
iPoseProof (IHHtyping with "[//] [$] [$] [$] [$]") as "H"; eauto.
iSpecialize ("H" $! j' (λ x, x) with "[] [$]"); first by (iPureIntro; apply language_ctx_id).
iApply (wpc_mono with "H"); eauto.
iSplit; first (iApply "Hj").
iExists _; iFrame; eauto.
iApply (Hatomic _ _ _ _ _ _ _ _ _ _ Γsubst with "[$] [$] [$] [$]").
iPoseProof (IHHtyping with "[//] [$] [$] [$] [$]") as "H"; eauto.
iPoseProof (IHHtyping1 with "[//] [$] [$] [$] [$]") as "H"; eauto.
wpc_bind (subst_map ((subst_ival <$> Γsubst)) cond').
spec_bind (_ _ cond) as Hctx'.
iSpecialize ("H" $! j _ Hctx' with "Hj").
iApply (wpc_mono' with "[] [] H"); last auto.
iDestruct "H" as (vscond) "(Hj&Hvcond)".
(* split on the value of the bool *)
iDestruct "Hvcond" as %(b&->&->).
wpc_pures; first by auto.
iMod (ghost_step_lifting_puredet _ _ K with "[Hj]") as "(Hj&Hchild)"; swap 1 3.
iDestruct "Hspec" as "($&?)".
apply head_prim_step_trans.
iApply (IHHtyping2 with "[//] [$] [$] [$] [$]").
wpc_pures; first by auto.
iMod (ghost_step_lifting_puredet with "[Hj]") as "(Hj&Hchild)"; swap 1 3.
iDestruct "Hspec" as "($&?)".
apply head_prim_step_trans.
iApply (IHHtyping3 with "[//] [$] [$] [$] [$]").
iMod (ghost_step_stuck_det with "Hj []") as %[]; swap 1 3.
iDestruct "Hspec" as "($&?)".
intros; eapply stuck_Panic.
iApply wp_ArbitraryInt; auto.
iMod (ghost_step_lifting_puredet with "[Hj]") as "(Hj&Hchild)"; swap 1 3.
iDestruct "Hspec" as "($&?)".
apply head_prim_step_trans.
repeat econstructor; eauto.
wpc_bind (subst_map _ e2).
iPoseProof (IHHtyping with "[//] [$] [$] [$] [$]") as "H".
iSpecialize ("H" $! j (λ x, K (ectx_language.fill [UnOpCtx _] x)) with "[] Hj").
apply comp_ctx; last done.
iApply (wpc_mono' with "[] [] H"); last by auto.
iDestruct "H" as (vs1) "(Hj&Hv1)".
iAssert (∃ (vres: u64), ⌜ un_op_eval ToUInt64Op v1 = Some #vres ∧
un_op_eval ToUInt64Op vs1 = Some #vres ⌝)%I with "[Hv1]" as %Hres.
destruct t; try inversion e;
destruct t; try congruence;
rewrite /val_interp//=;
iDestruct "Hv1" as (?) "(%&%)"; subst;
iPureIntro; eexists; eauto.
destruct Hres as (x&Heq1&Heq2).
iMod (ghost_step_lifting_puredet with "[Hj]") as "(Hj&Hchild)"; swap 1 3.
iDestruct "Hspec" as "($&?)".
apply head_prim_step_trans.
repeat econstructor; eauto.
wpc_bind (subst_map _ e2).
iPoseProof (IHHtyping with "[//] [$] [$] [$] [$]") as "H".
spec_bind (_ _ e1) as Hctx'.
iSpecialize ("H" $! j _ Hctx' with "Hj"); clear Hctx'.
iApply (wpc_mono' with "[] [] H"); last by auto.
iDestruct "H" as (vs1) "(Hj&Hv1)".
iAssert (∃ (vres: u32), ⌜ un_op_eval ToUInt32Op v1 = Some #vres ∧
un_op_eval ToUInt32Op vs1 = Some #vres ⌝)%I with "[Hv1]" as %Hres.
destruct t; try inversion e;
destruct t; try congruence;
rewrite /val_interp//=;
iDestruct "Hv1" as (?) "(%&%)"; subst;
iPureIntro; eexists; eauto.
destruct Hres as (x&Heq1&Heq2).
iMod (ghost_step_lifting_puredet with "[Hj]") as "(Hj&Hchild)"; swap 1 3.
iDestruct "Hspec" as "($&?)".
apply head_prim_step_trans.
repeat econstructor; eauto.
wpc_bind (subst_map _ e2).
iPoseProof (IHHtyping with "[//] [$] [$] [$] [$]") as "H".
spec_bind (_ _ e1) as Hctx'.
iSpecialize ("H" $! j _ Hctx' with "Hj"); clear Hctx'.
iApply (wpc_mono' with "[] [] H"); last by auto.
iDestruct "H" as (vs1) "(Hj&Hv1)".
iAssert (∃ (vres: u8), ⌜ un_op_eval ToUInt8Op v1 = Some #vres ∧
un_op_eval ToUInt8Op vs1 = Some #vres ⌝)%I with "[Hv1]" as %Hres.
destruct t; try inversion e;
destruct t; try congruence;
rewrite /val_interp//=;
iDestruct "Hv1" as (?) "(%&%)"; subst;
iPureIntro; eexists; eauto.
destruct Hres as (x&Heq1&Heq2).
iMod (ghost_step_lifting_puredet with "[Hj]") as "(Hj&Hchild)"; swap 1 3.
iDestruct "Hspec" as "($&?)".
apply head_prim_step_trans.
repeat econstructor; eauto.
wpc_bind (subst_map _ e2).
iPoseProof (IHHtyping with "[//] [$] [$] [$] [$]") as "H".
spec_bind (_ _ e1) as Hctx'.
iSpecialize ("H" $! j _ Hctx' with "Hj"); clear Hctx'.
iApply (wpc_mono' with "[] [] H"); last by auto.
iDestruct "H" as (vs1) "(Hj&Hv1)".
iAssert (∃ (vres: string), ⌜ un_op_eval ToStringOp v1 = Some #(LitString vres) ∧
un_op_eval ToStringOp vs1 = Some #(LitString vres) ⌝)%I with "[Hv1]" as %Hres.
destruct t; try inversion e;
destruct t; try congruence;
rewrite /val_interp//=;
iDestruct "Hv1" as (?) "(%&%)"; subst;
iPureIntro; eexists; eauto.
destruct Hres as (x&Heq1&Heq2).
iMod (ghost_step_lifting_puredet with "[Hj]") as "(Hj&Hchild)"; swap 1 3.
iDestruct "Hspec" as "($&?)".
apply head_prim_step_trans.
repeat econstructor; eauto.
destruct op; try inversion e; subst.
wpc_bind (subst_map _ e2).
iPoseProof (IHHtyping with "[//] [$] [$] [$] [$]") as "H".
spec_bind (_ _ e1) as Hctx'.
iSpecialize ("H" $! j _ Hctx' with "Hj"); clear Hctx'.
iApply (wpc_mono' with "[] [] H"); last by auto.
iDestruct "H" as (vs1) "(Hj&Hv1)".
iDestruct "Hv1" as (?) "(%&%)"; subst.
iMod (ghost_step_lifting_puredet with "[Hj]") as "(Hj&Hchild)"; swap 1 3.
iDestruct "Hspec" as "($&?)".
apply head_prim_step_trans.
repeat econstructor; eauto.
iPoseProof (IHHtyping1 with "[//] [$] [$] [$] [$]") as "H"; eauto.
wpc_bind (subst_map ((subst_ival <$> Γsubst)) e1').
spec_bind (_ _ e1) as Hctx'.
iSpecialize ("H" $! j _ Hctx' with "Hj"); clear Hctx'.
iApply (wpc_mono' with "[] [] H"); last by auto.
iDestruct "H" as (vs1) "(Hj&Hv1)".
wpc_bind (subst_map _ e2').
iPoseProof (IHHtyping2 with "[//] [$] [$] [$] [$]") as "H"; eauto.
spec_bind (_ _ e2) as Hctx'.
iSpecialize ("H" $! j _ Hctx' with "Hj"); clear Hctx'.
iApply (wpc_mono' with "[Hv1] [] H"); last by auto.
iDestruct "H" as (vs2) "(Hj&Hv2)".
iDestruct (is_comparableTy_is_comparable with "Hv1")
as %[Hcomparevs1 Hcomparev1]; auto.
iDestruct (is_comparableTy_is_comparable with "Hv2")
as %[Hcomparevs2 Hcomparev2]; auto.
iMod (ghost_step_lifting_puredet with "[Hj]") as "(Hj&Hchild)"; swap 1 3.
iDestruct "Hspec" as "($&?)".
apply head_prim_step_trans.
repeat econstructor; eauto.
rewrite /bin_op_eval /bin_op_eval_eq /=.
(* need to solve is_comparable side condition *)
iExists (bool_decide (vs1 = vs2)); eauto.
iDestruct (comparableTy_val_eq with "Hv1 Hv2") as %Heq; auto.
by apply bool_decide_ext.
wpc_bind (subst_map _ e1').
iPoseProof (IHHtyping1 with "[//] [$] [$] [$] [$]") as "H".
spec_bind (_ _ e1) as Hctx'.
iSpecialize ("H" $! j _ Hctx' with "Hj"); clear Hctx'.
iApply (wpc_mono' with "[] [] H"); last by auto.
iDestruct "H" as (vs1) "(Hj&Hv1)".
wpc_bind (subst_map _ e2').
iPoseProof (IHHtyping2 with "[//] [$] [$] [$] [$]") as "H".
spec_bind (_ _ e2) as Hctx'.
iSpecialize ("H" $! j _ Hctx' with "Hj"); clear Hctx'.
iApply (wpc_mono' with "[Hv1] [] H"); last by auto.
iDestruct "H" as (vs2) "(Hj&Hv2)".
iDestruct "Hspec" as "(#Hsrc&#Hstate)".
(* Be patient, this is handling a bunch of cases. *)
destruct op; inversion e; subst;
iDestruct "Hv1" as (?) "(%&%)"; subst;
iDestruct "Hv2" as (?) "(%&%)"; subst;
(iMod (ghost_step_lifting_puredet with "[$]") as "(Hj&Hchild)";
[ intros; eexists; apply head_prim_step_trans; repeat econstructor; eauto
| set_solver+ | wp_pures; eauto; iExists _; iFrame; eauto]).
wpc_bind (subst_map _ e1').
iPoseProof (IHHtyping1 with "[//] [$] [$] [$] [$]") as "H".
spec_bind (_ _ e1) as Hctx'.
iSpecialize ("H" $! j _ Hctx' with "Hj"); clear Hctx'.
iApply (wpc_mono' with "[] [] H"); last by auto.
iDestruct "H" as (vs1) "(Hj&Hv1)".
wpc_bind (subst_map _ e2').
iPoseProof (IHHtyping2 with "[//] [$] [$] [$] [$]") as "H".
spec_bind (_ _ e2) as Hctx'.
iSpecialize ("H" $! j _ Hctx' with "Hj"); clear Hctx'.
iApply (wpc_mono' with "[Hv1] [] H"); last by auto.
iDestruct "H" as (vs2) "(Hj&Hv2)".
iDestruct "Hspec" as "(#Hsrc&#Hstate)".
(* Be patient this is handling a bunch of cases. *)
destruct op; inversion e; subst;
iDestruct "Hv1" as (?) "(%&%)"; subst;
iDestruct "Hv2" as (?) "(%&%)"; subst;
(iMod (ghost_step_lifting_puredet with "[$]") as "(Hj&Hchild)";
[ intros; eexists; apply head_prim_step_trans; repeat econstructor; eauto
| set_solver+ | wp_pures; eauto; iExists _; iFrame; eauto]).
wpc_bind (subst_map _ e1').
iPoseProof (IHHtyping1 with "[//] [$] [$] [$] [$]") as "H".
spec_bind (_ _ e1) as Hctx'.
iSpecialize ("H" $! j _ Hctx' with "Hj"); clear Hctx'.
iApply (wpc_mono' with "[] [] H"); last by auto.
iDestruct "H" as (vs1) "(Hj&Hv1)".
wpc_bind (subst_map _ e2').
iPoseProof (IHHtyping2 with "[//] [$] [$] [$] [$]") as "H".
spec_bind (_ _ e2) as Hctx'.
iSpecialize ("H" $! j _ Hctx' with "Hj"); clear Hctx'.
iApply (wpc_mono' with "[Hv1] [] H"); last by auto.
iDestruct "H" as (vs2) "(Hj&Hv2)".
iDestruct "Hspec" as "(#Hsrc&#Hstate)".
iDestruct "Hv1" as (?) "(%&%)"; subst;
iDestruct "Hv2" as (?) "(%&%)"; subst;
(iMod (ghost_step_lifting_puredet with "[$]") as "(Hj&Hchild)";
[ intros; eexists; apply head_prim_step_trans; repeat econstructor; eauto
| set_solver+ | wp_pures; eauto; iExists _; iFrame; eauto]).
iPoseProof (IHHtyping1 with "[//] [$] [$] [$] [$]") as "H"; eauto.
wpc_bind (subst_map ((subst_ival <$> Γsubst)) e1').
spec_bind (subst_map ((subst_sval <$> Γsubst)) e1) as Hctx'.
iSpecialize ("H" $! j _ Hctx' with "Hj").
iApply (wpc_mono' with "[] [] H"); last by auto.
iDestruct "H" as (vs1) "(Hj&Hv1)".
wpc_bind (subst_map _ e2').
spec_bind (subst_map ((subst_sval <$> Γsubst)) e2) as Hctx'.
iPoseProof (IHHtyping2 with "[//] [$] [$] [$] [$]") as "H"; eauto.
iSpecialize ("H" $! j _ Hctx' with "Hj").
iApply (wpc_mono' with "[Hv1] [] H"); last by auto.
iDestruct "H" as (vs2) "(Hj&Hv2)".
spec_bind (_ ,_)%E as Hctx'.
iMod (ghost_step_lifting_puredet with "[Hj]") as "(Hj&Hchild)"; swap 1 3.
iDestruct "Hspec" as "($&?)".
apply head_prim_step_trans.
repeat econstructor; eauto.
iPoseProof (IHHtyping with "[//] [$] [$] [$] [$]") as "H"; eauto.
wpc_bind (subst_map ((subst_ival <$> Γsubst)) e').
spec_bind (subst_map ((subst_sval <$> Γsubst)) e) as Hctx'.
iSpecialize ("H" $! j _ Hctx' with "Hj").
iApply (wpc_mono' with "[] [] H"); last by auto.
iDestruct "H" as (vs) "(Hj&Hv)".
iDestruct "Hv" as (???? (->&->)) "(?&?)".
iMod (ghost_step_lifting_puredet with "[Hj]") as "(Hj&Hchild)"; swap 1 3.
iDestruct "Hspec" as "($&?)".
apply head_prim_step_trans.
repeat econstructor; eauto.
iPoseProof (IHHtyping with "[//] [$] [$] [$] [$]") as "H"; eauto.
wpc_bind (subst_map ((subst_ival <$> Γsubst)) e').
spec_bind (subst_map ((subst_sval <$> Γsubst)) e) as Hctx'.
iSpecialize ("H" $! j _ Hctx' with "Hj").
iApply (wpc_mono' with "[] [] H"); last by auto.
iDestruct "H" as (vs) "(Hj&Hv)".
iDestruct "Hv" as (???? (->&->)) "(?&?)".
iMod (ghost_step_lifting_puredet with "[Hj]") as "(Hj&Hchild)"; swap 1 3.
iDestruct "Hspec" as "($&?)".
apply head_prim_step_trans.
repeat econstructor; eauto.
iPoseProof (IHHtyping1 with "[//] [$] [$] [$] [$]") as "H1"; eauto.
iPoseProof (IHHtyping2 with "[//] [$] [$] [$] [$]") as "H2"; eauto.
wpc_bind (subst_map ((subst_ival <$> Γsubst)) ehd').
spec_bind (subst_map ((subst_sval <$> Γsubst)) ehd) as Hctx'.
iSpecialize ("H1" $! j _ Hctx' with "Hj").
iApply (wpc_mono' with "[H2] [] H1"); last by auto.
iDestruct "H" as (vs1) "(Hj&Hv1)".
wpc_bind (subst_map ((subst_ival <$> Γsubst)) etl').
spec_bind (subst_map ((subst_sval <$> Γsubst)) etl) as Hctx'.
iSpecialize ("H2" $! j _ Hctx' with "Hj").
iApply (wpc_mono' with "[Hv1] [] H2"); last by auto.
iDestruct "H" as (vs2) "(Hj&Hv2)".
spec_bind (vs1, vs2)%E as Hctx'.
iMod (ghost_step_lifting_puredet with "[Hj]") as "(Hj&_)"; swap 1 3.
iDestruct "Hspec" as "($&?)".
apply head_prim_step_trans.
repeat econstructor; eauto.
iMod (ghost_step_lifting_puredet with "[Hj]") as "(Hj&Hchild)"; swap 1 3.
iDestruct "Hspec" as "($&?)".
apply head_prim_step_trans.
repeat econstructor; eauto.
rewrite val_interp_list_unfold /listT_interp.
iDestruct "Hv2" as (lvs lv (->&->)) "H".
iExists (vs1 :: lvs), (v1 :: lv).
iPoseProof (IHHtyping1 with "[//] [$] [$] [$] [$]") as "H1"; eauto.
iPoseProof (IHHtyping2 with "[//] [$] [$] [$] [$]") as "H2"; eauto.
iPoseProof (IHHtyping3 with "[//] [$] [$] [$] [$]") as "H3"; eauto.
wpc_bind (subst_map ((subst_ival <$> Γsubst)) consfun').
spec_bind (subst_map ((subst_sval <$> Γsubst)) consfun) as Hctx'.
iSpecialize ("H3" $! j _ Hctx' with "Hj").
iApply (wpc_mono' with "[H1 H2] [] H3"); last by auto.
iDestruct "H" as (vsconsfun) "(Hj&Hvconsfun)".
wpc_bind (subst_map ((subst_ival <$> Γsubst)) nilfun').
spec_bind (subst_map ((subst_sval <$> Γsubst)) nilfun) as Hctx'.
iSpecialize ("H2" $! j _ Hctx' with "Hj").
iApply (wpc_mono' with "[H1 Hvconsfun] [] H2"); last by auto.
iDestruct "H" as (vsnilfun) "(Hj&Hvnilfun)".
wpc_bind (subst_map ((subst_ival <$> Γsubst)) el').
spec_bind (subst_map ((subst_sval <$> Γsubst)) el) as Hctx'.
iSpecialize ("H1" $! j _ Hctx' with "Hj").
iApply (wpc_mono' with "[Hvnilfun Hvconsfun] [] H1"); last by auto.
iDestruct "H" as (vsl) "(Hj&Hvsl)".
spec_bind (App _ vsl)%E as Hctx'.
iMod (ghost_step_lifting_puredet with "[Hj]") as "(Hj&_)"; swap 1 3.
iDestruct "Hspec" as "($&?)".
apply head_prim_step_trans.
repeat econstructor; eauto.
spec_bind (λ: _, _)%E as Hctx'.
iMod (ghost_step_lifting_puredet with "[Hj]") as "(Hj&_)"; swap 1 3.
iDestruct "Hspec" as "($&?)".
apply head_prim_step_trans.
repeat econstructor; eauto.
spec_bind (App _ vsnilfun)%E as Hctx'.
iMod (ghost_step_lifting_puredet with "[Hj]") as "(Hj&_)"; swap 1 3.
iDestruct "Hspec" as "($&?)".
apply head_prim_step_trans.
repeat econstructor; eauto.
spec_bind (λ: _, _)%E as Hctx'.
iMod (ghost_step_lifting_puredet with "[Hj]") as "(Hj&_)"; swap 1 3.
iDestruct "Hspec" as "($&?)".
apply head_prim_step_trans.
repeat econstructor; eauto.
spec_bind (App _ vsconsfun)%E as Hctx'.
iMod (ghost_step_lifting_puredet with "[Hj]") as "(Hj&_)"; swap 1 3.
iDestruct "Hspec" as "($&?)".
apply head_prim_step_trans.
repeat econstructor; eauto.
rewrite val_interp_list_unfold.
iDestruct "Hvsl" as (lvs lv (->&->)) "H".
destruct lvs as [|vs lvs];
destruct lv as [|v lv]; try (iDestruct "H" as %[]; done).
iMod (ghost_step_lifting_puredet with "[Hj]") as "(Hj&_)"; swap 1 3.
iDestruct "Hspec" as "($&?)".
apply head_prim_step_trans.
repeat econstructor; eauto.
spec_bind (Rec _ _ _)%E as Hctx'.
iMod (ghost_step_lifting_puredet with "[Hj]") as "(Hj&_)"; swap 1 3.
iDestruct "Hspec" as "($&?)".
apply head_prim_step_trans.
repeat econstructor; eauto.
iMod (ghost_step_lifting_puredet with "[Hj]") as "(Hj&_)"; swap 1 3.
iDestruct "Hspec" as "($&?)".
apply head_prim_step_trans.
repeat econstructor; eauto.
rewrite /val_interp -/val_interp.
iDestruct "Hvnilfun" as (f x e fs xs es (->&->)) "#Hwand".
iSpecialize ("Hwand" $! #() #() with "[] Hj").
iApply (wpc_wp _ _ _ _ True%I).
iApply (wpc_mono' with "[] [] Hwand"); last by auto.
iDestruct "H" as (vs1) "(Hj&Hv1)".
iMod (ghost_step_lifting_puredet with "[Hj]") as "(Hj&_)"; swap 1 3.
iDestruct "Hspec" as "($&?)".
apply head_prim_step_trans.
repeat econstructor; eauto.
spec_bind (Rec _ _ _)%E as Hctx'.
iMod (ghost_step_lifting_puredet with "[Hj]") as "(Hj&_)"; swap 1 3.
iDestruct "Hspec" as "($&?)".
apply head_prim_step_trans.
repeat econstructor; eauto.
iMod (ghost_step_lifting_puredet with "[Hj]") as "(Hj&_)"; swap 1 3.
iDestruct "Hspec" as "($&?)".
apply head_prim_step_trans.
repeat econstructor; eauto.
rewrite /val_interp -/val_interp.
iDestruct "Hvconsfun" as (f x e fs xs es (->&->)) "#Hwand".
iSpecialize ("Hwand" $! (v, list.val_of_list lv)%V (vs, list.val_of_list lvs)%V with "[H] Hj").
rewrite /val_interp -/val_interp.
rewrite val_interp_list_unfold /listT_interp.
iDestruct "H" as "($&H)".
iApply (wpc_wp _ _ _ _ True%I).
iApply (wpc_mono' with "[] [] Hwand"); last by auto.
iDestruct "H" as (vs1) "(Hj&Hv1)".
iPoseProof (IHHtyping with "[//] [$] [$] [$] [$]") as "H"; eauto.
wpc_bind (subst_map ((subst_ival <$> Γsubst)) e').
spec_bind (subst_map ((subst_sval <$> Γsubst)) e) as Hctx'.
iSpecialize ("H" $! j _ Hctx' with "Hj").
iApply (wpc_mono' with "[] [] H"); last by auto.
iDestruct "H" as (vs1) "(Hj&Hv1)".
iMod (ghost_step_lifting_puredet with "[Hj]") as "(Hj&Hchild)"; swap 1 3.
iDestruct "Hspec" as "($&?)".
apply head_prim_step_trans.
repeat econstructor; eauto.
iExists _, _; iFrame; eauto.
iPoseProof (IHHtyping with "[//] [$] [$] [$] [$]") as "H"; eauto.
wpc_bind (subst_map ((subst_ival <$> Γsubst)) e').
spec_bind (subst_map ((subst_sval <$> Γsubst)) e) as Hctx'.
iSpecialize ("H" $! j _ Hctx' with "Hj").
iApply (wpc_mono' with "[] [] H"); last by auto.
iDestruct "H" as (vs1) "(Hj&Hv1)".
iMod (ghost_step_lifting_puredet with "[Hj]") as "(Hj&Hchild)"; swap 1 3.
iDestruct "Hspec" as "($&?)".
apply head_prim_step_trans.
repeat econstructor; eauto.
iExists _, _; iFrame; eauto.
iPoseProof (IHHtyping1 with "[//] [$] [$] [$] [$]") as "H"; eauto.
wpc_bind (subst_map ((subst_ival <$> Γsubst)) cond').
spec_bind (subst_map ((subst_sval <$> Γsubst)) cond) as Hctx'.
iSpecialize ("H" $! j _ Hctx' with "Hj").
iApply (wpc_mono' with "[] [] H"); last by auto.
iDestruct "H" as (vs1) "(Hj&Hv1)".
iDestruct "Hv1" as "[Hleft|Hright]".
iDestruct "Hleft" as (?? (->&->)) "Hv".
iMod (ghost_step_lifting_puredet with "[Hj]") as "(Hj&Hchild)"; swap 1 3.
iDestruct "Hspec" as "($&?)".
apply head_prim_step_trans.
repeat econstructor; eauto.
wpc_bind (subst_map _ e1').
iPoseProof (IHHtyping2 with "[//] [$] [$] [$] [$]") as "H"; eauto.
spec_bind (subst_map _ e1) as Hctx'.
iSpecialize ("H" $! j _ Hctx' with "Hj").
iApply (wpc_mono' with "[Hv] [] H"); last first.
iDestruct "H" as (vs1) "(Hj&Hv1)".
iDestruct "Hv1" as (?????? (Heq1&Heq2)) "#Hinterp".
iSpecialize ("Hinterp" with "[$]").
iSpecialize ("Hinterp" $! j _ Hctx with "Hj").
iApply (wpc_mono' with "[] [] Hinterp"); last first.
iDestruct "H" as (vs'') "(Hj&Hv')".
iDestruct "Hright" as (?? (->&->)) "Hv".
iMod (ghost_step_lifting_puredet with "[Hj]") as "(Hj&Hchild)"; swap 1 3.
iDestruct "Hspec" as "($&?)".
apply head_prim_step_trans.
repeat econstructor; eauto.
wpc_bind (subst_map _ e2').
iPoseProof (IHHtyping3 with "[//] [$] [$] [$] [$]") as "H"; eauto.
spec_bind (subst_map _ e2) as Hctx'.
iSpecialize ("H" $! j _ Hctx' with "Hj").
iApply (wpc_mono' with "[Hv] [] H"); last first.
iDestruct "H" as (vs1) "(Hj&Hv1)".
iDestruct "Hv1" as (?????? (Heq1&Heq2)) "#Hinterp".
iSpecialize ("Hinterp" with "[$]").
iSpecialize ("Hinterp" $! j _ Hctx with "Hj").
iApply (wpc_mono' with "[] [] Hinterp"); last by auto.
iDestruct "H" as (vs'') "(Hj&Hv')".
wpc_bind (subst_map ((subst_ival <$> Γsubst)) n').
iPoseProof (IHHtyping1 with "[//] [$] [$] [$] [$]") as "H".
iSpecialize ("H" $! j (λ x, K (ectx_language.fill [Primitive2LCtx _ _] x)) with "[] Hj").
apply comp_ctx; last by auto.
iApply (wpc_mono' with "[] [] H"); last by auto.
iDestruct "H" as (vsn1) "(Hj&Hv1)".
wpc_bind (subst_map ((subst_ival <$> Γsubst)) v').
iPoseProof (IHHtyping2 with "[//] [$] [$] [$] [$]") as "H".
iSpecialize ("H" $! j (λ x, K (ectx_language.fill [Primitive2RCtx _ _] x)) with "[] Hj").
apply comp_ctx; last by auto.
iApply (wpc_mono' with "[Hv1] [] H"); last by auto.
iDestruct "H" as (vs2) "(Hj&Hv2)".
iDestruct "Hv1" as (nint) "(->&->)".
destruct (decide (0 < int.Z nint)) as [Hnonneg|]; last first.
iMod (ghost_allocN_non_pos_stuck with "[$] [$]") as %[].
iDestruct (length_flatten_well_typed with "Hv2") as %(Hspecsize&Hsize); first done.
iApply wp_allocN_seq_sized_meta.
destruct (flatten_ty t) as [|]; try congruence; simpl; try lia.
iIntros (l) "(%&Hsize&Hpts)".
iMod (ghost_allocN_seq_sized_meta with "[] Hj") as (ls) "(Hj&%&Hssize&Hspts)".
destruct (flatten_ty t) as [|]; try congruence; simpl; try lia.
rewrite val_interp_array_unfold /arrayT_interp.
unshelve (iExists l, ls, (int.nat nint), 0, _, _); eauto.
rewrite -Hsize -Hspecsize.
replace ((int.nat nint * length (flatten_ty t)))%Z with
(Z.of_nat (int.nat nint * length (flatten_ty t)))%nat by lia.
apply addr_base_non_null_offset; eauto; naive_solver.
apply addr_base_non_null_offset; eauto; naive_solver.
rewrite (addr_offset_0_is_base l); last naive_solver.
rewrite (addr_offset_0_is_base ls); last naive_solver.
iCombine "Hpts Hspts" as "Hpts".
iDestruct "Hv2" as "#Hv".
iApply (big_sepL_impl with "Hpts").
iIntros "!> !>" (k x Hlookup) "(Hmtoks&Hsmtoks)".
iDestruct (big_sepL2_sepL_2 with "Hmtoks Hsmtoks") as "Hmtoks"; first lia.
iApply (big_sepL2_elim_big_sepL with "[] Hmtoks").
iIntros (i vi vsi vty Hlookup1 Hlookup2 Hlookup3) "((Hpts&Hm)&(Hspts&Hsm))".
rewrite list_lookup_fmap in Hlookup3.
apply fmap_Some_1 in Hlookup3 as (sty&Hlookup3&Heq).
iDestruct (flatten_well_typed with "Hv") as "Hvali"; eauto.
iMod (is_loc_init with "Hpts Hm Hspts Hsm Hvali") as "$".
wpc_bind (subst_map ((subst_ival <$> Γsubst)) e1').
iPoseProof (IHHtyping1 with "[//] [$] [$] [$] [$]") as "H".
iSpecialize ("H" $! j (λ x, K (ectx_language.fill [BinOpLCtx _ _] x)) with "[] Hj").
apply comp_ctx; last by auto.
iApply (wpc_mono' with "[] [] H"); last by auto.
iDestruct "H" as (vsn1) "(Hj&Hv1)".
wpc_bind (subst_map ((subst_ival <$> Γsubst)) e2').
iPoseProof (IHHtyping2 with "[//] [$] [$] [$] [$]") as "H".
iSpecialize ("H" $! j (λ x, K (ectx_language.fill [BinOpRCtx _ _] x)) with "[] Hj").
apply comp_ctx; last by auto.
iApply (wpc_mono' with "[Hv1] [] H"); last by auto.
iDestruct "H" as (vs2) "(Hj&Hv2)".
iDestruct "Hv2" as (off) "H".
iDestruct "H" as %[Heq1 Heq2].
iDestruct "Hv1" as "[Hv1|Hnull]"; last first.
iDestruct "Hnull" as %(off'&Heq1'&Heq2').
iMod (ghost_step_lifting_puredet with "[Hj]") as "(Hj&_)"; swap 1 3.
iDestruct "Hspec" as "($&?)".
apply head_prim_step_trans.
repeat econstructor; eauto.
iDestruct "Hv1" as (l ls n idx Hgtzero Hnonempty Hpeq) "(Hblock1&Hblock2&Hlist)".
destruct Hpeq as (->&->&?&?&Hoff&Hoffs).
iMod (ghost_step_lifting_puredet with "[Hj]") as "(Hj&_)"; swap 1 3.
iDestruct "Hspec" as "($&?)".
apply head_prim_step_trans.
repeat econstructor; eauto.
unshelve (iExists (addr_plus_off l (ty_size t * int.Z off)),
(addr_plus_off ls (ty_size t * int.Z off)), _, (idx + int.Z off), _, _; iFrame); eauto.
rewrite ?addr_base_of_plus ?addr_offset_of_plus.
iPureIntro; split_and!; eauto.
specialize (ty_size_ge_0 t).
specialize (ty_size_ge_0 t).
iPoseProof (IHHtyping with "[//] [$] [$] [$] [$]") as "H".
iSpecialize ("H" $! j K with "[] Hj"); first auto.
iApply (wpc_mono' with "[] [] H"); last by auto.
iDestruct "H" as (vsn1) "(Hj&Hv1)".
iApply arrayT_structRefT_promote.
wpc_bind (subst_map ((subst_ival <$> Γsubst)) e1').
iPoseProof (IHHtyping with "[//] [$] [$] [$] [$]") as "H".
iSpecialize ("H" $! j (λ x, K (ectx_language.fill [BinOpLCtx _ _] x)) with "[] Hj").
apply comp_ctx; last by auto.
iApply (wpc_mono' with "[] [] H"); last by auto.
iDestruct "H" as (vsn1) "(Hj&Hv1)".
iDestruct "Hv1" as "[Hv1|Hnull]"; last first.
iDestruct "Hnull" as %(off'&Heq1'&Heq2').
iMod (ghost_step_lifting_puredet with "[Hj]") as "(Hj&_)"; swap 1 3.
iDestruct "Hspec" as "($&?)".
apply head_prim_step_trans.
repeat econstructor; eauto.
iDestruct "Hv1" as (l' ls' n Hgtzero Hnonempty Hpeq) "(Hpaired&Hblock1&Hblock2&Hlist)".
destruct Hpeq as (->&->&?&?&Hoff).
iMod (ghost_step_lifting_puredet with "[Hj]") as "(Hj&_)"; swap 1 3.
iDestruct "Hspec" as "($&?)".
apply head_prim_step_trans.
repeat econstructor; eauto.
replace (k * int.Z 1) with k by word.
unshelve (iExists (l' +ₗ k), (ls' +ₗ k), _, _, _; iFrame).
apply List.map_neq_nil, List.drop_lt.
rewrite ?addr_offset_of_plus Hoff //.
iDestruct "Hlist" as "[Hinb|Hoob]".
setoid_rewrite loc_add_assoc.
rewrite -?List.list_fmap_map fmap_drop.
iDestruct (big_sepL_drop _ _ (Z.to_nat k) with "Hinb") as "H".
iApply (big_sepL_mono with "H").
replace (Z.of_nat (Z.to_nat k + k')%nat) with (k + k'); eauto.
iDestruct "Hoob" as %Hoob.
rewrite ?addr_offset_of_plus drop_length.
wpc_bind (subst_map ((subst_ival <$> Γsubst)) l').
iPoseProof (IHHtyping with "[//] [$] [$] [$] [$]") as "H".
iSpecialize ("H" $! j (λ x, K (ectx_language.fill [Primitive1Ctx _] x)) with "[] Hj").
apply comp_ctx; last done.
iApply (wpc_mono' with "[] [] H"); last by auto.
iDestruct "H" as (vsn1) "(Hj&Hv1)".
rewrite val_interp_struct_unfold.
iDestruct "Hv1" as "[Hv|Hnull]".
iDestruct "Hv" as (lv lvs n H0lt Hnonemtpy (->&->&?&?&?)) "(Hpaired&Hblock1&Hblocked2&Hloc)".
iDestruct "Hloc" as "[Hinbound|Hoob]".
iDestruct "Hinbound" as "(H&_)".
iDestruct "H" as "(Hlocinv&Hpaired')".
iDestruct "Hlocinv" as (γ) "Hlocinv".
iInv "Hlocinv" as "Hlocinv_body" "Hclo".
iDestruct "Hlocinv_body" as (??) "H".
iDestruct "H" as "[H0readers|[Hreaders|Hwriter]]".
iDestruct "H0readers" as "(>Hfc&>Hspts&>Hpts&#Hval)".
iApply (wp_load with "[$]").
iMod (ghost_load with "[$] Hspts Hj") as "(Hspts&Hj)".
iMod ("Hclo" with "[Hpts Hspts Hfc Hval]").
iApply fupd_mask_intro_subseteq; first by set_solver+.
iDestruct "Hreaders" as (q q' n') "(>%&>Hfc&>Hspts&Hspts_clo&>Hpts&#Hval)".
iApply (wp_load with "[$]").
iMod (ghost_load_rd with "[$] Hspts Hj") as "(Hspts&Hj)".
iMod ("Hclo" with "[Hpts Hspts Hspts_clo Hfc Hval]").
iApply fupd_mask_intro_subseteq; first by set_solver+.
iDestruct "Hwriter" as "(>Hfc&>Hspts)".
iMod (ghost_load_write_stuck with "[$] [$] [$]") as %[].
iDestruct "Hoob" as %Hoob.
iMod (ghost_load_block_oob_stuck with "[$] [$] [$]") as %[].
iDestruct "Hnull" as %(?&->&->).
iMod (ghost_load_null_stuck with "[$] [$]") as %[].
rewrite addr_base_of_plus //=.
wpc_bind (subst_map ((subst_ival <$> Γsubst)) v').
iPoseProof (IHHtyping2 with "[//] [$] [$] [$] [$]") as "H".
spec_bind (subst_map _ v) as Hctx'.
iSpecialize ("H" $! j _ Hctx' with "Hj"); clear Hctx'.
iApply (wpc_mono' with "[] [] H"); last by auto.
iDestruct "H" as (vsarg) "(Hj&Hvarg)".
wpc_bind (subst_map ((subst_ival <$> Γsubst)) l').
iPoseProof (IHHtyping1 with "[//] [$] [$] [$] [$]") as "H".
spec_bind (subst_map _ l) as Hctx'.
iSpecialize ("H" $! j _ Hctx' with "Hj"); clear Hctx'.
iApply (wpc_mono' with "[Hvarg] [] H"); last by auto.
iDestruct "H" as (vsl) "(Hj&Hvl)".
wp_bind (PrepareWrite _).
(* XXX need tactic to do these pure det reductions ... *)
spec_bind (App _ vsl) as Hctx'.
iMod (ghost_step_lifting_puredet _ _ _ (App _ vsl) with "[Hj]") as "(Hj&_)"; swap 1 3.
iDestruct "Hspec" as "($&?)".
apply head_prim_step_trans.
spec_bind (Rec _ _ _) as Hctx'.
iMod (ghost_step_lifting_puredet _ _ _ (Rec _ _ _)
with "[Hj]") as "(Hj&_)"; swap 1 3.
iDestruct "Hspec" as "($&?)".
apply head_prim_step_trans.
spec_bind (App _ _) as Hctx'.
iMod (ghost_step_lifting_puredet _ _ _ _
with "[Hj]") as "(Hj&_)"; swap 1 3.
iDestruct "Hspec" as "($&?)".
apply head_prim_step_trans.
spec_bind (PrepareWrite vsl) as Hctx'.
wp_apply (logical_reln_prepare_write _ _ _ _ _ _ (Hctx') with "[Hvl Hj]").
iDestruct 1 as (lsval lval ?? γ (->&->)) "(#Hlocinv&Htok&Hj&Hspts&Hspts_clo&Hpts&Hpts_clo)".
spec_bind (Rec _ _ _) as Hctx'.
iMod (ghost_step_lifting_puredet _ _ _ (Rec _ _ _)
with "[Hj]") as "(Hj&_)"; swap 1 3.
iDestruct "Hspec" as "($&?)".
apply head_prim_step_trans.
repeat econstructor; eauto.
spec_bind (App _ _) as Hctx'.
iMod (ghost_step_lifting_puredet _ _ _ (App _ _)
with "[Hj]") as "(Hj&_)"; swap 1 3.
iDestruct "Hspec" as "($&?)".
apply head_prim_step_trans.
repeat econstructor; eauto.
wp_apply (logical_reln_finish_store with "[-]").
wpc_bind (subst_map ((subst_ival <$> Γsubst)) l').
iPoseProof (IHHtyping with "[//] [$] [$] [$] [$]") as "H".
spec_bind (subst_map _ l) as Hctx'.
iSpecialize ("H" $! j _ Hctx' with "Hj"); clear Hctx'.
iApply (wpc_mono' with "[] [] H"); last by auto.
iDestruct "H" as (vsl) "(Hj&Hvl)".
(* XXX need tactic to do these pure det reductions ... *)
spec_bind (App _ vsl) as Hctx'.
iMod (ghost_step_lifting_puredet _ _ _ (App _ vsl) with "[Hj]") as "(Hj&_)"; swap 1 3.
iDestruct "Hspec" as "($&?)".
apply head_prim_step_trans.
spec_bind (StartRead vsl) as Hctx'.
wp_apply (logical_reln_start_read _ _ _ _ _ _ (Hctx') with "[Hvl Hj]").
iDestruct 1 as (lsval lval ? γ q (->&->&?&?)) "(#Hlocinv&Htok&Hj&#Hval&Hspts&Hpts&Hpts_clo)".
spec_bind (Rec _ _ _) as Hctx'.
iMod (ghost_step_lifting_puredet _ _ _ (Rec _ _ _)
with "[Hj]") as "(Hj&_)"; swap 1 3.
iDestruct "Hspec" as "($&?)".
apply head_prim_step_trans.
repeat econstructor; eauto.
spec_bind (App _ _) as Hctx'.
iMod (ghost_step_lifting_puredet _ _ _ (App _ _)
with "[Hj]") as "(Hj&_)"; swap 1 3.
iDestruct "Hspec" as "($&?)".
apply head_prim_step_trans.
repeat econstructor; eauto.
spec_bind (FinishRead _) as Hctx'.
wp_apply (logical_reln_finish_read with "[-]").
spec_bind (Rec _ _ _) as Hctx'.
iMod (ghost_step_lifting_puredet _ _ _ (Rec _ _ _)
with "[Hj]") as "(Hj&_)"; swap 1 3.
iDestruct "Hspec" as "($&?)".
apply head_prim_step_trans.
repeat econstructor; eauto.
spec_bind (App _ _) as Hctx'.
iMod (ghost_step_lifting_puredet _ _ _ (App _ _)
with "[Hj]") as "(Hj&_)"; swap 1 3.
iDestruct "Hspec" as "($&?)".
apply head_prim_step_trans.
repeat econstructor; eauto.
wpc_bind (subst_map ((subst_ival <$> Γsubst)) l').
iPoseProof (IHHtyping1 with "[//] [$] [$] [$] [$]") as "H".
spec_bind (subst_map _ l) as Hctx'.
iSpecialize ("H" $! j _ Hctx' with "Hj").
iApply (wpc_mono' with "[] [] H"); last by auto.
iDestruct "H" as (vsl) "(Hj&Hvl)".
wpc_bind (subst_map ((subst_ival <$> Γsubst)) v1').
iPoseProof (IHHtyping2 with "[//] [$] [$] [$] [$]") as "H".
spec_bind (subst_map _ v1) as Hctx'.
iSpecialize ("H" $! j _ Hctx' with "Hj").
iApply (wpc_mono' with "[Hvl] [] H"); last by auto.
iDestruct "H" as (vs1_done) "(Hj&Hv1)".
wpc_bind (subst_map ((subst_ival <$> Γsubst)) v2').
iPoseProof (IHHtyping3 with "[//] [$] [$] [$] [$]") as "H".
spec_bind (subst_map _ v2) as Hctx'.
iSpecialize ("H" $! j _ Hctx' with "Hj").
iApply (wpc_mono' with "[Hvl Hv1] [] H"); last by auto.
iDestruct "H" as (vs2_done) "(Hj&Hvs2_done)".
rewrite val_interp_struct_unfold.
iDestruct "Hvl" as "[Hv|Hnull]".
iDestruct "Hv" as (lv lvs n H0lt Hnonemtpy (->&->&?&?&?)) "(Hpaired&Hblock1&Hblocked2&Hloc)".
iDestruct "Hloc" as "[Hinbound|Hoob]".
iDestruct "Hinbound" as "(H&_)".
iDestruct "H" as "(Hlocinv&Hpaired')".
iDestruct "Hlocinv" as (γ) "Hlocinv".
iInv "Hlocinv" as "Hlocinv_body" "Hclo".
iDestruct "Hlocinv_body" as (mem_vs mem_v) "H".
iDestruct (unboxedTy_val_unboxed with "Hv1") as %(Hsunboxed&Hunboxed).
iDestruct "H" as "[H0readers|[Hreaders|Hwriter]]".
iDestruct "H0readers" as "(>Hfc&>Hspts&>Hpts&#Hval)".
iDestruct (comparableTy_val_eq with "Hv1 Hval") as ">Heq".
apply unboxedTy_comparable.
iDestruct "Heq" as %Heq_iff.
destruct (decide (mem_v = v1_done)).
wp_apply (wp_cmpxchg_suc with "Hpts"); first eauto.
iMod (ghost_cmpxchg_suc with "[$] Hspts Hj") as "(Hspts&Hj)".
iMod ("Hclo" with "[Hpts Hspts Hfc Hval Hvs2_done]").
iApply fupd_mask_intro_subseteq; first by set_solver+.
wp_apply (wp_cmpxchg_fail with "Hpts"); first eauto.
iMod (ghost_cmpxchg_fail with "[$] Hspts Hj") as "(Hspts&Hj)".
iMod ("Hclo" with "[Hpts Hspts Hfc Hval]").
iApply fupd_mask_intro_subseteq; first by set_solver+.
iDestruct "Hreaders" as (q q' n') "(>%&>Hfc&>Hspts&Hspts_clo&>Hpts&#Hval)".
iDestruct (comparableTy_val_eq with "Hv1 Hval") as ">Heq".
apply unboxedTy_comparable.
iDestruct "Heq" as %Heq_iff.
destruct (decide (mem_v = v1_done)).
iMod (ghost_cmpxchg_suc_read_stuck with "[$] Hspts Hj") as %[].
wp_apply (wp_cmpxchg_fail with "Hpts"); first eauto.
iMod (ghost_cmpxchg_fail_rd with "[$] Hspts Hj") as "(Hspts&Hj)".
iMod ("Hclo" with "[Hpts Hspts Hfc Hval Hspts_clo]").
iApply fupd_mask_intro_subseteq; first by set_solver+.
iDestruct "Hwriter" as "(>Hfc&>Hspts)".
iMod (ghost_cmpxchg_write_stuck with "[$] [$] [$]") as %[].
iDestruct "Hoob" as %Hoob.
iMod (ghost_cmpxchg_block_oob_stuck with "[$] [$] [$]") as %[].
iDestruct "Hnull" as %(?&->&->).
iMod (ghost_cmpxchg_null_stuck with "[$] [$]") as %[].
rewrite addr_base_of_plus //=.
wpc_bind (subst_map ((subst_ival <$> Γsubst)) sel').
iPoseProof (IHHtyping with "[//] [$] [$] [$] [$]") as "H".
spec_bind (subst_map _ sel) as Hctx'.
iSpecialize ("H" $! j _ Hctx' with "Hj").
iApply (wpc_mono' with "[] [] H"); last by auto.
iDestruct "H" as (vsl) "(Hj&Hvl)".
iInv "Htrace" as (????) ">(He1&He2&Htr1&Htr2&Hor1&Hor2)" "Hclo".
iDestruct "Hvl" as (?) "(%&%)".
wp_apply (wp_input with "[$]").
iMod (ghost_input with "[$] [$] [$] [$]") as "(Hj&?&?)".
iMod ("Hclo" with "[-Hj]").
wpc_bind (subst_map ((subst_ival <$> Γsubst)) v').
iPoseProof (IHHtyping with "[//] [$] [$] [$] [$]") as "H".
spec_bind (subst_map _ v) as Hctx'.
iSpecialize ("H" $! j _ Hctx' with "Hj").
iApply (wpc_mono' with "[] [] H"); last by auto.
iDestruct "H" as (vsl) "(Hj&Hvl)".
iInv "Htrace" as (????) ">(He1&He2&Htr1&Htr2&Hor1&Hor2)" "Hclo".
iDestruct "Hvl" as (?) "(%&%)".
wp_apply (wp_output with "[$]").
iMod (ghost_output with "[$] [$] [$]") as "(Hj&?)".
iMod ("Hclo" with "[-Hj]").
iPoseProof (IHHtyping with "[//] [$] [$] [$] [$]") as "H"; eauto.
wpc_bind (subst_map ((subst_ival <$> Γsubst)) _).
iSpecialize ("H" $! j (λ x, K (ectx_language.fill [AppRCtx _] x)) with "[] Hj").
apply comp_ctx; last by auto.
iApply (wpc_mono' with "[] [] H"); last by auto.
iDestruct "H" as (vs2) "(Hj&Hv2)".
iPoseProof (Hrules with "[$] [$] [$] [] Hj") as "H"; eauto.
inversion b; subst; eauto.
iPoseProof (IHHtyping with "[$] [$] [$]") as "Hv1"; eauto.
iPoseProof (IHHtyping0 with "[$] [$] [$]") as "Hv2"; eauto.
iSplitL ""; first by eauto.
iPoseProof (IHHtyping with "[$] [$] [$]") as "Hv1"; eauto.
iPoseProof (IHHtyping0 with "[$] [$] [$]") as "Hv2"; eauto.
rewrite val_interp_list_unfold.
iDestruct "Hv2" as (l l' (->&->)) "H".
iExists (vhd :: l), (vhd' :: l').
iSplitL ""; first by eauto.
iApply (IHHtyping with "[$] [$] [$]").
iSplitR ""; first by eauto.
iApply (IHHtyping with "[$] [$] [$]").
iExists _, _, _, _, _, _.
iSplitL ""; first by eauto.
iIntros (varg vsarg) "Hvarg".
iMod (ghost_step_lifting_puredet with "[Hj]") as "(Hj&_)"; swap 1 3.
iDestruct "Hspec" as "($&?)".
apply head_prim_step_trans.
iPoseProof (ctx_has_semTy_subst with "[] []") as "H1".
iPoseProof (ctx_has_semTy_subst with "[] Hvarg") as "H2".
iSpecialize ("H2" $! ∅ with "[] [$] [$] [$] [] [//] [Hj]").
rewrite fmap_empty subst_map_empty.
rewrite fmap_empty subst_map_empty.