(** Preservation of [match_callstack] by freeing all blocks allocated for local variables at function entry (on the C#minor side) and simultaneously freeing the Cminor stack data block. *)

(* Specifications: *)
Lemma in_blocks_of_env:
forall e id b sz,
e!id = Some(b, sz) -> In (b, 0, sz) (blocks_of_env e).
Lemma in_blocks_of_env_inv:
forall b lo hi e,
In (b, lo, hi) (blocks_of_env e) ->
exists id, e!id = Some(b, hi) /\ lo = 0.
Lemma match_callstack_freelist:
forall f cenv tf e le te sp lo hi cs m m' tm,
Mem.inject f m tm ->
Mem.free_list m (blocks_of_env e) = Some m' ->
match_callstack f m tm (Frame cenv tf e le te sp lo hi :: cs) (Mem.nextblock m) (Mem.nextblock tm) ->
exists tm',
Mem.free tm sp 0 tf.(fn_stackspace) = Some tm'
/\ match_callstack f m' tm' cs (Mem.nextblock m') (Mem.nextblock tm')
/\ Mem.inject f m' tm'.
Lemma in_blocks_of_env:
forall e id b sz,
e!id = Some(b, sz) -> In (b, 0, sz) (blocks_of_env e).
Lemma in_blocks_of_env_inv:
forall b lo hi e,
In (b, lo, hi) (blocks_of_env e) ->
exists id, e!id = Some(b, hi) /\ lo = 0.
Lemma match_callstack_freelist:
forall f cenv tf e le te sp lo hi cs m m' tm,
Mem.inject f m tm ->
Mem.free_list m (blocks_of_env e) = Some m' ->
match_callstack f m tm (Frame cenv tf e le te sp lo hi :: cs) (Mem.nextblock m) (Mem.nextblock tm) ->
exists tm',
Mem.free tm sp 0 tf.(fn_stackspace) = Some tm'
/\ match_callstack f m' tm' cs (Mem.nextblock m') (Mem.nextblock tm')
/\ Mem.inject f m' tm'.