(** [contains_locations j sp pos bound sl ls] is a separation logic assertion that holds if the memory area at block [sp], offset [pos], size [4 * bound], reflects the values of the stack locations of kind [sl] given by the location map [ls], up to the memory injection [j].  Two such [contains_locations] assertions will be used later, one to reason about the values of [Local] slots, the other about the values of [Outgoing] slots. *)
Program Definition contains_locations (j: meminj) (sp: block) (pos bound: Z) (sl: slot) (ls: locset) : massert := {|
m_pred := fun m =>
(8 | pos) /\ 0 <= pos /\ pos + 4 * bound <= Ptrofs.modulus /\
Mem.range_perm m sp pos (pos + 4 * bound) Cur Freeable /\
forall ofs ty, 0 <= ofs -> ofs + typesize ty <= bound -> (typealign ty | ofs) ->
exists v, Mem.load (chunk_of_type ty) m sp (pos + 4 * ofs) = Some v
/\ Val.inject j (ls (S sl ofs ty)) v;
m_footprint := fun b ofs =>
b = sp /\ pos <= ofs < pos + 4 * bound
|}.
Next Obligation.
intuition auto.
- red; intros. eapply Mem.perm_unchanged_on; eauto. simpl; auto.
- exploit H4; eauto. intros (v & A & B). exists v; split; auto.
eapply Mem.load_unchanged_on; eauto.
simpl; intros. rewrite size_type_chunk, typesize_typesize in H8.
split; auto. omega.
Qed.
Next Obligation.
eauto with mem.
Qed.
Remark valid_access_location:
forall m sp pos bound ofs ty p,
(8 | pos) ->
Mem.range_perm m sp pos (pos + 4 * bound) Cur Freeable ->
0 <= ofs -> ofs + typesize ty <= bound -> (typealign ty | ofs) ->
Mem.valid_access m (chunk_of_type ty) sp (pos + 4 * ofs) p.

Lemma contains_locations_exten:
forall ls ls' j sp pos bound sl,
(forall ofs ty, Val.lessdef (ls' (S sl ofs ty)) (ls (S sl ofs ty))) ->
massert_imp (contains_locations j sp pos bound sl ls)
(contains_locations j sp pos bound sl ls').