Definition freeable_blocks: list (block * BinInt.Z * BinInt.Z) -> mpred :=
fold_right (fun (bb: block*BinInt.Z * BinInt.Z) a =>
match bb with (b,lo,hi) =>
sepcon (VALspec_range (hi-lo) Share.top (b,lo)) a
end)
emp.
Inductive free_list_juicy_mem:
forall  (jm: juicy_mem) (bl: list (block * BinInt.Z * BinInt.Z))
(jm': juicy_mem), Prop :=
| FLJM_nil: forall jm, free_list_juicy_mem jm nil jm
| FLJM_cons: forall jm b lo hi bl jm2 jm'
(H: free (m_dry jm) b lo hi = Some (m_dry jm2))
(H0 : forall ofs : Z,
lo <= ofs < hi ->
perm_of_res (m_phi jm @ (b, ofs)) = Some Freeable),
free_juicy_mem jm (m_dry jm2) b lo hi H = jm2 ->
free_list_juicy_mem jm2 bl jm' ->
free_list_juicy_mem jm ((b,lo,hi)::bl) jm'.

(* Specifications: *)
Lemma perm_of_res_val : forall r, perm_of_res r = Some Freeable ->
exists v pp, r = YES Share.top readable_share_top (VAL v) pp.
Lemma free_list_juicy_mem_i:
forall jm bl m' F,
free_list (m_dry jm) bl = Some m' ->
app_pred (freeable_blocks bl * F) (m_phi jm) ->
exists jm', free_list_juicy_mem jm bl jm'
/\ m_dry jm' = m'
/\ level jm = level jm'.
Lemma free_juicy_mem_ext:
forall jm1 jm2 b lo hi m1 m2 H1 H2,
jm1=jm2 -> m1=m2 ->
free_juicy_mem jm1 m1 b lo hi H1 = free_juicy_mem jm2 m2 b lo hi H2.
Lemma free_list_juicy_mem_lem:
forall P jm bl jm',
free_list_juicy_mem jm bl jm' ->
app_pred (freeable_blocks bl * P) (m_phi jm) ->
app_pred P (m_phi jm').
Lemma xelements_app:
forall A (rho: PTree.t A) i al bl,
PTree.xelements rho i al ++ bl = PTree.xelements rho i (al++bl).
Lemma PTree_elements_remove: forall {A} (T: PTree.tree A) i e,
In e (PTree.elements (PTree.remove i T)) ->
In e (PTree.elements T) /\ fst e <> i.
Lemma stackframe_of_freeable_blocks:
forall Delta f rho ge ve,
genv_cenv ge = cenv_cs ->
Forall (fun it => complete_type cenv_cs (snd it) = true) (fn_vars f) ->
list_norepet (map fst (fn_vars f)) ->
ve_of rho = make_venv ve ->
guard_environ (func_tycontext' f Delta) (Some f) rho ->
stackframe_of f rho |-- freeable_blocks (blocks_of_env ge ve).