(** [contains_callee_saves j sp pos rl ls] is a memory assertion that holds if block [sp], starting at offset [pos], contains the values of the callee-save registers [rl] as given by the location map [ls], up to the memory injection [j].  The memory layout of the registers in [rl] is the same as that implemented by [save_callee_save_rec]. *)
Fixpoint contains_callee_saves (j: meminj) (sp: block) (pos: Z) (rl: list mreg) (ls: locset) : massert :=
match rl with
| nil => pure True
| r :: rl =>
let ty := mreg_type r in
let sz := AST.typesize ty in
let pos1 := align pos sz in
contains (chunk_of_type ty) sp pos1 (fun v => Val.inject j (ls (R r)) v)
** contains_callee_saves j sp (pos1 + sz) rl ls
end.

Lemma contains_callee_saves_exten:
forall j sp ls ls' rl pos,
(forall r, In r rl -> ls' (R r) = ls (R r)) ->
massert_eqv (contains_callee_saves j sp pos rl ls)
(contains_callee_saves j sp pos rl ls').