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 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'.