End FRAME_PROPERTIES.
(** * Call stack invariants *)
(** This is the memory assertion that captures the contents of the stack frames mentioned in the call stacks. *)
Fixpoint stack_contents (j: meminj) (cs: list Linear.stackframe) (cs': list Mach.stackframe) : massert :=
match cs, cs' with
| nil, nil => pure True
| Linear.Stackframe f _ ls c :: cs, Mach.Stackframe fb (Vptr sp' _) ra c' :: cs' =>
frame_contents f j sp' ls (parent_locset cs) (parent_sp cs') (parent_ra cs')
** stack_contents j cs cs'
| _, _ => pure False
end.
(** [match_stacks] captures additional properties (not related to memory) of the Linear and Mach call stacks. *)
Inductive match_stacks (j: meminj):
list Linear.stackframe -> list stackframe -> signature -> Prop :=
| match_stacks_empty: forall sg,
tailcall_possible sg ->
match_stacks j nil nil sg
| match_stacks_cons: forall f sp ls c cs fb sp' ra c' cs' sg trf
(TAIL: is_tail c (Linear.fn_code f))
(FINDF: Genv.find_funct_ptr tge fb = Some (Internal trf))
(TRF: transf_function f = OK trf)
(TRC: transl_code (make_env (function_bounds f)) c = c')
(INJ: j sp = Some(sp', (fe_stack_data (make_env (function_bounds f)))))
(TY_RA: Val.has_type ra Tptr)
(AGL: agree_locs f ls (parent_locset cs))
(ARGS: forall ofs ty,
In (S Outgoing ofs ty) (regs_of_rpairs (loc_arguments sg)) ->
slot_within_bounds (function_bounds f) Outgoing ofs ty)
(STK: match_stacks j cs cs' (Linear.fn_sig f)),
match_stacks j
(Linear.Stackframe f (Vptr sp Ptrofs.zero) ls c :: cs)
(Stackframe fb (Vptr sp' Ptrofs.zero) ra c' :: cs')
sg.
(** Invariance with respect to change of memory injection. *)

Lemma stack_contents_change_meminj:
forall m j j', inject_incr j j' ->
forall cs cs' P,
m |= stack_contents j cs cs' ** P ->
m |= stack_contents j' cs cs' ** P.