From 7fd646af75e377f53e084a4dd98e454f5b80dc2e Mon Sep 17 00:00:00 2001
From: Johannes Hostert <jhostert@ethz.ch>
Date: Thu, 14 Nov 2024 23:18:32 +0100
Subject: [PATCH] add insert read example

---
 _CoqProject                                   |   1 +
 .../examples/protected/shared_insert_read.v   | 174 ++++++++++++++++++
 2 files changed, 175 insertions(+)
 create mode 100644 theories/tree_borrows/examples/protected/shared_insert_read.v

diff --git a/_CoqProject b/_CoqProject
index 431e6908..89aa4ad8 100644
--- a/_CoqProject
+++ b/_CoqProject
@@ -195,6 +195,7 @@ theories/tree_borrows/examples/protected/mutable_reorder_read_down.v
 theories/tree_borrows/examples/protected/mutable_reorder_read_up.v
 theories/tree_borrows/examples/protected/shared_reorder_read_down_escaped.v
 theories/tree_borrows/examples/protected/shared_reorder_read_up_escaped.v
+theories/tree_borrows/examples/protected/shared_insert_read.v
 theories/tree_borrows/examples/protected/mutable_reorder_write_down_activated.v
 theories/tree_borrows/examples/protected/mutable_reorder_write_up_activated.v
 theories/tree_borrows/examples/protected/mutable_reorder_write_up_activated_paper.v
diff --git a/theories/tree_borrows/examples/protected/shared_insert_read.v b/theories/tree_borrows/examples/protected/shared_insert_read.v
new file mode 100644
index 00000000..80ecf513
--- /dev/null
+++ b/theories/tree_borrows/examples/protected/shared_insert_read.v
@@ -0,0 +1,174 @@
+(** This file has been adapted from the Stacked Borrows development, available at 
+  https://gitlab.mpi-sws.org/FP/stacked-borrows
+*)
+
+From simuliris.simulation Require Import lifting.
+From simuliris.tree_borrows Require Import proofmode lang adequacy examples.lib.
+From iris.prelude Require Import options.
+
+
+
+(** Moving read of shared ref up across code that *may* use that ref. *)
+
+(** This is a variant using protectors.
+  See delete_read_pubic_escaped_unprotected.v for the original optimization without protectors and with deferred UB.
+ *)
+
+(* Assuming x : & i32 *)
+
+Definition prot_shared_insert_read_unopt : expr :=
+    let: "c" := InitCall in
+
+    (* "x" is the local variable that stores the pointer value "i" *)
+    let: "x" := new_place sizeof_scalar "i" in
+
+    (* retag_place reborrows the pointer value stored in "x" (which is "i"),
+      then updates "x" with the new pointer value.
+      Using a protector here.
+    *)
+    retag_place "x" ShrRef TyFrz sizeof_scalar FnEntry "c";;
+
+    (* The unknown code is represented by a call to an unknown function "f" *)
+    let: "tst" := Call #[ScFnPtr "f"] (#[]) in
+    (* if tst is negative, if so read from x, otherwise return tst *)
+    let: "result" := if: "tst" ≤ (#[0])%V
+                     then Copy *{sizeof_scalar} "x"
+                     else "tst" in
+
+    (* Free the local variable *)
+    Free "x" ;;
+
+    (* Finally, return the read value *)
+    EndCall "c";;
+    "result"
+  .
+
+Definition prot_shared_insert_read_opt : expr :=
+    let: "c" := InitCall in
+    let: "x" := new_place sizeof_scalar "i" in
+    retag_place "x" ShrRef TyFrz sizeof_scalar FnEntry "c";;
+    let: "tst" := Call #[ScFnPtr "f"] (#[]) in
+    let: "v" := Copy *{sizeof_scalar} "x" in
+    let: "result" := if: "tst" ≤ (#[0])%V then "v" else "tst" in
+    Free "x" ;;
+    EndCall "c";;
+    "result"
+  .
+
+Lemma prot_shared_insert_read `{sborGS Σ} :
+  ⊢ log_rel prot_shared_insert_read_opt prot_shared_insert_read_unopt.
+Proof.
+  log_rel.
+  iIntros "%r_t %r_s #Hrel !# %Ï€ _".
+  sim_pures.
+  sim_apply InitCall InitCall sim_init_call "". iIntros (c) "Hcall". iApply sim_expr_base. sim_pures.
+
+  (* new place *)
+  simpl. source_bind (new_place _ _).
+  iApply source_red_safe_reach.
+  { intros. rewrite subst_result. eapply new_place_safe_reach. }
+  simpl. iIntros "(%v_s & -> & %Hsize)". destruct v_s as [|v_s [|?]]; try done.
+  iPoseProof (rrel_value_source with "Hrel") as (v_t) "(-> & #Hv)".
+  iPoseProof (value_rel_length with "Hv") as "%Hlen". destruct v_t as [|v_t [|?]]; try done.
+  iApply source_red_base. iModIntro. to_sim.
+  sim_apply (new_place _ _) (new_place _ _) sim_new_place_local "%t %l % % Htag Ht Hs"; first done.
+  sim_pures.
+
+  target_apply (Copy _) (target_copy_local with "Htag Ht") "Ht Htag". 2: done. 1: rewrite read_range_heaplet_to_list // Z.sub_diag /= //.
+  source_apply (Copy _) (source_copy_local with "Htag Hs") "Hs Htag". 2: done. 1: rewrite read_range_heaplet_to_list // Z.sub_diag /= //.
+
+  (* do the retag *)
+  sim_bind (Retag _ _ _ _ _ _) (Retag _ _ _ _ _ _).
+  iApply sim_safe_implies.
+  iIntros ((_ & ot & i & [= ->] & _)).
+  iPoseProof (value_rel_singleton_source with "Hv") as (sc_t [= ->]) "Hscrel".
+  iPoseProof (sc_rel_ptr_source with "Hscrel") as ([= ->]) "Htagged".
+  iApply (sim_retag_fnentry with "Hscrel Hcall"). 1: by cbv.
+  iIntros (t_i v_t v_s _ Hlen_t Hlen_s) "Hcall #Hvrel #Htag_i Hi_t Hi_s".
+  destruct v_t as [|v_t []]; try done.
+  destruct v_s as [|v_s []]; try done. iSimpl in "Hcall".
+  iApply sim_expr_base.
+  target_apply (Write _ _) (target_write_local with "Htag Ht") "Ht Htag".
+  2-3: done. 1: rewrite /write_range bool_decide_true. 2: simpl; lia. 1: rewrite Z.sub_diag /= //.
+  source_apply (Write _ _) (source_write_local with "Htag Hs") "Hs Htag".
+  2: done. 1: rewrite /write_range bool_decide_true. 2: simpl; lia. 1: rewrite Z.sub_diag /= //.
+  sim_pures.
+
+  (* do the call *)
+  sim_pures.
+  sim_apply (Call _ _) (Call _ _) (sim_call _ (ValR []) (ValR [])) "".
+  { iApply big_sepL2_nil. done. }
+  iIntros (r_t r_s) "#Hfres". sim_pures.
+
+  (* do the target load *)
+  target_apply (Copy (Place _ _ _)) (target_copy_local with "Htag Ht") "Ht Htag". 2: done.
+  1: rewrite read_range_heaplet_to_list // Z.sub_diag /= //.
+  target_pures. target_bind (Copy _).
+  iApply (target_copy_protected with "Hcall Htag_i Hi_t"). 1: done.
+  2: simpl; lia. 1: rewrite read_range_heaplet_to_list // Z.sub_diag /= //.
+  2: by rewrite lookup_insert.
+  { intros off Hoff. simpl in *. rewrite /range'_contains /sizeof_scalar /= in Hoff. assert (off = i.2)%nat as -> by lia. rewrite /shift_loc /= Z.add_0_r /call_set_in lookup_insert /=. by eexists. }
+  iIntros "Hi_t _ Hcall". target_finish.
+  sim_pures. simpl. rewrite !subst_result.
+
+  source_bind (BinOp _ _ _).
+  Search BinOp.
+  iApply source_red_safe_implies. 1: eapply (safe_implies_le r_s (ValR [ScInt 0]%V)%V).
+  iIntros ((zres_s & z2 & -> & [= <-])).
+  destruct r_t as [[|zres_t []]|]; simpl; try done.
+  2: { iExFalso. iPoseProof (big_sepL2_length with "Hfres") as "%HH". done. }
+  iEval (rewrite /value_rel /= /sc_rel) in "Hfres". iDestruct "Hfres" as "[Hfres _]".
+  destruct zres_t; try done. iPure "Hfres" as ->.
+  sim_pures. target_pures. sim_pures.
+  destruct (bool_decide (zres_s ≤ 0%nat)%Z).
+  - simpl. target_case; first done. source_case; first done. sim_pures.
+    (* do the source load *)
+    source_apply (Copy (Place _ _ _)) (source_copy_local with "Htag Hs") "Hs Htag". 2: done.
+    1: rewrite read_range_heaplet_to_list // Z.sub_diag /= //.
+    source_pures. source_bind (Copy _).
+    iApply (source_copy_protected with "Hcall Htag_i Hi_s"). 1: done.
+    2: simpl; lia. 1: rewrite read_range_heaplet_to_list // Z.sub_diag /= //.
+    2: by rewrite lookup_insert.
+    { intros off Hoff. simpl in *. rewrite /range'_contains /sizeof_scalar /= in Hoff. assert (off = i.2)%nat as -> by lia. rewrite /shift_loc /= Z.add_0_r /call_set_in lookup_insert /=. by eexists. }
+    iIntros "Hi_s _ Hcall". source_finish.
+    sim_pures.
+
+    (* cleanup: remove the protector ghost state, make the external locations public, free the local locations*)
+    sim_apply (Free _) (Free _) (sim_free_local with "Htag Ht Hs") "Htag"; [done..|]. sim_pures.
+    iApply (sim_protected_unprotect_public with "Hcall Htag_i"). 1: by rewrite lookup_insert.
+    iIntros "Hc". iEval (rewrite delete_insert) in "Hc".
+    sim_apply (EndCall _) (EndCall _) (sim_endcall_own with "Hc") "".
+    sim_pures.
+    sim_val. iModIntro. iSplit; first done. done.
+  - simpl. target_case; first done. source_case; first done. sim_pures.
+
+    (* cleanup: remove the protector ghost state, make the external locations public, free the local locations*)
+    sim_apply (Free _) (Free _) (sim_free_local with "Htag Ht Hs") "Htag"; [done..|]. sim_pures.
+    iApply (sim_protected_unprotect_public with "Hcall Htag_i"). 1: by rewrite lookup_insert.
+    iIntros "Hc". iEval (rewrite delete_insert) in "Hc".
+    sim_apply (EndCall _) (EndCall _) (sim_endcall_own with "Hc") "".
+    sim_pures.
+    sim_val. iModIntro. iSplit; first done.
+Qed.
+
+
+Section closed.
+  (** Obtain a closed proof of [ctx_ref]. *)
+  Lemma prot_shared_insert_read_ctx : ctx_ref prot_shared_insert_read_opt prot_shared_insert_read_unopt.
+  Proof.
+    set Σ := #[sborΣ].
+    apply (log_rel_adequacy Σ)=>?.
+    apply prot_shared_insert_read.
+  Qed.
+End closed.
+
+Check prot_shared_insert_read_ctx.
+Print Assumptions prot_shared_insert_read_ctx.
+(* 
+prot_shared_insert_read_ctx
+     : ctx_ref prot_shared_insert_read_opt prot_shared_insert_read_unopt
+Axioms:
+IndefiniteDescription.constructive_indefinite_description : ∀ (A : Type) (P : A → Prop), (∃ x : A, P x) → {x : A | P x}
+Classical_Prop.classic : ∀ P : Prop, P ∨ ¬ P
+*)
+
-- 
GitLab