Fixpoint freelist_no_overlap (l: list (block * Z * Z)) : Prop :=
match l with
| nil => True
| (b, lo, hi) :: l' =>
freelist_no_overlap l' /\
(forall b' lo' hi', In (b', lo', hi') l' ->
b' <> b \/ hi' <= lo \/ hi <= lo')
end.

(* Specifications: *)
Lemma can_free_list:
forall l m,
(forall b lo hi, In (b, lo, hi) l -> Mem.range_perm m b lo hi Cur Freeable) ->
freelist_no_overlap l ->
exists m', Mem.free_list m l = Some m'.
Lemma blocks_of_env_no_overlap:
forall (ge: genv) j cenv e le m lo hi te tle tlo thi tm,
match_envs j cenv e le m lo hi te tle tlo thi ->
Mem.inject j m tm ->
(forall id b ty,
e!id = Some(b, ty) -> Mem.range_perm m b 0 (sizeof ge ty) Cur Freeable) ->
forall l,
list_norepet (List.map fst l) ->
(forall id bty, In (id, bty) l -> te!id = Some bty) ->
freelist_no_overlap (List.map (block_of_binding ge) l).
Lemma free_list_right_inject:
forall j m1 l m2 m2',
Mem.inject j m1 m2 ->
Mem.free_list m2 l = Some m2' ->
(forall b1 b2 delta lo hi ofs k p,
j b1 = Some(b2, delta) -> In (b2, lo, hi) l ->
Mem.perm m1 b1 ofs k p -> lo <= ofs + delta < hi -> False) ->
Mem.inject j m1 m2'.
Lemma blocks_of_env_translated:
forall e, blocks_of_env tge e = blocks_of_env ge e.
Theorem match_envs_free_blocks:
forall j cenv e le m lo hi te tle tlo thi m' tm,
match_envs j cenv e le m lo hi te tle tlo thi ->
Mem.inject j m tm ->
Mem.free_list m (blocks_of_env ge e) = Some m' ->
exists tm',
Mem.free_list tm (blocks_of_env tge te) = Some tm'
/\ Mem.inject j m' tm'.