Instance Inhabitant_share : Inhabitant share := Share.bot. (* TODO: remove this, it's already in sublist.v *)
Instance Inhabitant_mpred : Inhabitant mpred := @FF mpred Nveric. (* TODO: remove this, it's already in sublist.v *)

(* Specifications: *)
Lemma join_shares_nth : forall shs sh1 sh i, sepalg_list.list_join sh1 shs sh -> 0 <= i < Zlength shs ->
exists sh', sepalg_list.list_join (Znth i shs) (remove_Znth i shs) sh' /\ sepalg.join sh1 sh' sh.
Lemma list_join_comm : forall (l1 l2 : list share) a b, sepalg_list.list_join a (l1 ++ l2) b ->
sepalg_list.list_join a (l2 ++ l1) b.
(* Split a share into an arbitrary number of subshares. *)
Lemma split_shares : forall n sh, readable_share sh ->
exists sh1 shs, Zlength shs = Z.of_nat n /\ readable_share sh1 /\ Forall readable_share shs /\
sepalg_list.list_join sh1 shs sh.
Lemma data_at_shares_join : forall {cs} sh t v p shs sh1 (Hsplit : sepalg_list.list_join sh1 shs sh),
@data_at cs sh1 t v p * fold_right sepcon emp (map (fun sh => data_at sh t v p) shs) =
data_at sh t v p.
(* These lemmas should probably be in veric. *)
Lemma exp_comm : forall {A B} P,
(EX x : A, EX y : B, P x y) = EX y : B, EX x : A, P x y.
Lemma mapsto_value_eq: forall sh1 sh2 t p v1 v2, readable_share sh1 -> readable_share sh2 ->
v1 <> Vundef -> v2 <> Vundef -> mapsto sh1 t p v1 * mapsto sh2 t p v2 |-- !!(v1 = v2).
Lemma mapsto_value_cohere: forall sh1 sh2 t p v1 v2, readable_share sh1 ->
mapsto sh1 t p v1 * mapsto sh2 t p v2 |-- mapsto sh1 t p v1 * mapsto sh2 t p v1.
Lemma struct_pred_value_cohere : forall {cs : compspecs} m sh1 sh2 p t f off v1 v2
(Hsh1 : readable_share sh1) (Hsh2 : readable_share sh2)
(IH : Forall (fun it : ident * type => forall v1 v2 (p : val),
readable_share sh1 -> readable_share sh2 ->
data_at_rec sh1 (t it) v1 p * data_at_rec sh2 (t it) v2 p |--
data_at_rec sh1 (t it) v1 p * data_at_rec sh2 (t it) v1 p) m),
struct_pred m (fun (it : ident * type) v =>
withspacer sh1 (f it + sizeof (t it)) (off it) (at_offset (data_at_rec sh1 (t it) v) (f it))) v1 p *
struct_pred m (fun (it : ident * type) v =>
withspacer sh2 (f it + sizeof (t it)) (off it) (at_offset (data_at_rec sh2 (t it) v) (f it))) v2 p |--
struct_pred m (fun (it : ident * type) v =>
withspacer sh1 (f it + sizeof (t it)) (off it) (at_offset (data_at_rec sh1 (t it) v) (f it))) v1 p *
struct_pred m (fun (it : ident * type) v =>
withspacer sh2 (f it + sizeof (t it)) (off it) (at_offset (data_at_rec sh2 (t it) v) (f it))) v1 p.
Lemma data_at_value_cohere : forall {cs : compspecs} sh1 sh2 t v1 v2 p, readable_share sh1 ->
type_is_by_value t = true -> type_is_volatile t = false ->
data_at sh1 t v1 p * data_at sh2 t v2 p |--
data_at sh1 t v1 p * data_at sh2 t v1 p.
Lemma data_at_array_value_cohere : forall {cs : compspecs} sh1 sh2 t z a v1 v2 p, readable_share sh1 ->
type_is_by_value t = true -> type_is_volatile t = false ->
data_at sh1 (Tarray t z a) v1 p * data_at sh2 (Tarray t z a) v2 p |--
data_at sh1 (Tarray t z a) v1 p * data_at sh2 (Tarray t z a) v1 p.
(* This isn't true if the type contains any unions, since in fact the type of the data could be different. Lemma data_at_rec_value_cohere : forall {cs : compspecs} sh1 sh2 t v1 v2 p, readable_share sh1 -> readable_share sh2 -> data_at_rec sh1 t v1 p * data_at_rec sh2 t v2 p |-- data_at_rec sh1 t v1 p * data_at_rec sh2 t v1 p.  Corollary field_at_value_cohere : forall {cs : compspecs} sh1 sh2 t gfs v1 v2 p, readable_share sh1 -> field_at sh1 t gfs v1 p * field_at sh2 t gfs v2 p |-- field_at sh1 t gfs v1 p * field_at sh2 t gfs v1 p.  Corollary data_at_value_cohere : forall {cs : compspecs} sh1 sh2 t v1 v2 p, readable_share sh1 -> data_at sh1 t v1 p * data_at sh2 t v2 p |-- data_at sh1 t v1 p * data_at sh2 t v1 p.  Corollary data_at__cohere : forall {cs : compspecs} sh1 sh2 t v p, readable_share sh1 -> data_at sh1 t v p * data_at_ sh2 t p = data_at sh1 t v p * data_at sh2 t v p.  Lemma data_at__shares_join : forall {cs} sh t v p shs sh1 (Hsplit : sepalg_list.list_join sh1 shs sh) (Hreadable1 : readable_share sh1) (Hreadable : Forall readable_share shs), @data_at cs sh1 t v p * fold_right sepcon emp (map (fun sh => data_at_ sh t p) shs) |-- data_at sh t v p.  Lemma extract_nth_sepcon : forall l i, 0 <= i < Zlength l -> fold_right sepcon emp l = Znth i l * fold_right sepcon emp (upd_Znth i l emp).  Lemma replace_nth_sepcon : forall P l i, P * fold_right sepcon emp (upd_Znth i l emp) = fold_right sepcon emp (upd_Znth i l P).  Lemma sepcon_derives_prop : forall P Q R, P |-- !!R -> P * Q |-- !!R.  Lemma sepcon_map : forall {A} P Q (l : list A), fold_right sepcon emp (map (fun x => P x * Q x) l) = fold_right sepcon emp (map P l) * fold_right sepcon emp (map Q l).  Lemma sepcon_list_derives : forall l1 l2 (Hlen : Zlength l1 = Zlength l2) (Heq : forall i, 0 <= i < Zlength l1 -> Znth i l1 |-- Znth i l2), fold_right sepcon emp l1 |-- fold_right sepcon emp l2.  Lemma sepcon_rotate : forall lP m n, 0 <= n - m < Zlength lP -> fold_right sepcon emp lP = fold_right sepcon emp (rotate lP m n).  (* wand lemmas *)
Lemma wand_eq : forall P Q R, P = Q * R -> P = Q * (Q -* P).
Lemma wand_twice : forall P Q R, P -* Q -* R = P * Q -* R.
Lemma sepcon_In : forall l P, In P l -> exists Q, fold_right sepcon emp l = P * Q.
Lemma extract_wand_sepcon : forall l P, In P l ->
fold_right sepcon emp l = P * (P -* fold_right sepcon emp l).
Lemma wand_sepcon_map : forall {A} (R : A -> mpred) l P Q
(HR : forall i, In i l -> R i = P i * Q i),
fold_right sepcon emp (map R l) = fold_right sepcon emp (map P l) *
(fold_right sepcon emp (map P l) -* fold_right sepcon emp (map R l)).
Lemma wand_frame : forall P Q R, P -* Q |-- P * R -* Q * R.
Lemma semax_extract_later_prop'':
forall {CS : compspecs} {Espec: OracleKind},
forall (Delta : tycontext) (PP : Prop) P Q R c post P1 P2,
P2 |-- !!PP ->
(PP -> semax Delta (PROPx P (LOCALx Q (SEPx (P1 && |>P2 :: R)))) c post) ->
semax Delta (PROPx P (LOCALx Q (SEPx (P1 && |>P2 :: R)))) c post.
Lemma field_at_array_inbounds : forall {cs : compspecs} sh t z a i v p,
field_at sh (Tarray t z a) [ArraySubsc i] v p |-- !!(0 <= i < z).
Lemma valid_pointer_isptr : forall v, valid_pointer v |-- !!(is_pointer_or_null v).
Hint Resolve valid_pointer_isptr : saturate_local.
Lemma approx_imp : forall n P Q, compcert_rmaps.RML.R.approx n (predicates_hered.imp P Q) =
compcert_rmaps.RML.R.approx n (predicates_hered.imp (compcert_rmaps.RML.R.approx n P)
(compcert_rmaps.RML.R.approx n Q)).