Definition int_op e :=
match e with
| Load v | Store v => tc_val tint v
| CAS r c w => tc_val tint r /\ tc_val tint c /\ tc_val tint w
end.
(* Once set, a key is never reset. *)
Definition k_R (h : list hist_el) (v : val) := !!(Forall int_op h /\
forall e, In e h -> value_of e <> vint 0 -> v = value_of e) && emp.
Definition v_R (h : list hist_el) (v : val) := emp.
Definition atomic_entry sh p := !!(field_compatible tentry [] p) && EX lkey : val, EX lval : val,
field_at sh tentry [StructField _lkey] lkey p *
atomic_loc sh lkey (field_address tentry [StructField _key] p) (vint 0) Tsh k_R *
field_at sh tentry [StructField _lvalue] lval p *
atomic_loc sh lval (field_address tentry [StructField _value] p) (vint 0) Tsh v_R.
(* Can we comprehend the per-entry histories into a broader history? *)
Definition failed_CAS k (a b : hist * hist) := exists t r, Forall (fun x => fst x < t)%nat (fst a) /\
fst b = fst a ++ [(t, CAS (Vint r) (vint 0) (vint k))] /\
r <> Int.zero /\ r <> Int.repr k /\ snd b = snd a /\
(let v := value_of_hist (fst a) in v <> vint 0 -> v = Vint r).
Definition wf_hists h l := Forall (fun x => ordered_hist (fst x) /\ ordered_hist (snd x) /\
Forall int_op (map snd (fst x)) /\ Forall int_op (map snd (snd x))) h /\ 0 <= l <= Zlength h /\
Forall (fun x => value_of_hist (fst x) <> vint 0) (sublist 0 l h) /\
Forall (fun x => value_of_hist (fst x) = vint 0) (sublist l (Zlength h) h).
Definition make_int v := match v with Vint i => Int.signed i | _ => 0 end.

(* Specifications: *)
Lemma make_int_spec : forall v, tc_val tint v -> vint (make_int v) = v.
Fixpoint make_map h :=
match h with
| [] => []
| (hk, hv) :: rest => let k := make_int (value_of_hist hk) in
if eq_dec k 0 then [] else (k, make_int (value_of_hist hv)) :: make_map rest
end.
Lemma ordered_snoc : forall h t e, ordered_hist h -> Forall (fun x => fst x < t)%nat h ->
ordered_hist (h ++ [(t, e)]).
Lemma Forall_set : forall P m k v, Forall P m -> P (k, v) -> Forall P (set m k v).
Lemma wf_make_map : forall h, wf_map (make_map h).
Lemma make_map_eq : forall h h', Forall2 (fun a b => value_of_hist (fst a) = value_of_hist (fst b) /\
value_of_hist (snd a) = value_of_hist (snd b)) h h' -> make_map h = make_map h'.
Lemma int_op_value : forall e, int_op e -> tc_val tint (value_of e).
Corollary int_op_value_of_hist : forall h, Forall int_op (map snd h) -> tc_val tint (value_of_hist h).
Lemma make_map_app : forall h1 h2 (Hnz : Forall (fun x => value_of_hist (fst x) <> vint 0) h1)
(Hint : Forall (fun x => Forall int_op (map snd (fst x))) h1),
make_map (h1 ++ h2) = make_map h1 ++ make_map h2.
Lemma make_map_drop : forall h1 h2 (Hz : Forall (fun x => value_of_hist (fst x) = vint 0) h2),
make_map (h1 ++ h2) = make_map h1.
Lemma index_of_app : forall k m1 m2, index_of (m1 ++ m2) k =
match index_of m1 k with Some i => Some i | None => option_map (Z.add (Zlength m1)) (index_of m2 k) end.
Lemma index_of_out : forall k m, Forall (fun x => fst x <> k) m -> index_of m k = None.
Lemma make_map_length : forall h (Hnz : Forall (fun x => value_of_hist (fst x) <> vint 0) h)
(Hint : Forall (fun x => Forall int_op (map snd (fst x))) h),
Zlength (make_map h) = Zlength h.
Lemma make_map_no_key : forall h k (Hout : Forall (fun x => make_int (value_of_hist (fst x)) <> k) h),
Forall (fun x => fst x <> k) (make_map h).
Lemma make_map_nil : forall h, Forall (fun x => value_of_hist (fst x) = vint 0) h -> make_map h = [].
Definition set_item_trace (h : list (hist * hist)) k v i h' := 0 <= i < Zlength h /\
Forall2 (failed_CAS k) (sublist 0 i h) (sublist 0 i h') /\
(let '(hk, hv) := Znth i h ([], []) in exists t r tv, Forall (fun x => fst x < t)%nat hk /\
Forall (fun x => fst x < tv)%nat hv /\
Znth i h' ([], []) = (hk ++ [(t, CAS r (vint 0) (vint k))], hv ++ [(tv, Store (vint v))]) /\
(r = vint 0 \/ r = vint k) /\ (let v := value_of_hist hk in v <> vint 0 -> v = r)) /\
sublist (i + 1) (Zlength h) h = sublist (i + 1) (Zlength h') h'.
Lemma set_item_trace_map : forall h k v i h' l (Hwf : wf_hists h l) (Htrace : set_item_trace h k v i h')
(Hk : k <> 0) (Hrepk : repable_signed k) (Hrepv : repable_signed v),
wf_hists h' (Z.max (i + 1) l) /\ let m' := make_map (sublist 0 i h' ++ sublist i (Zlength h) h) in
wf_map (set m' k v) /\ incl (make_map h) m' /\ make_map h' = set m' k v.