Local Open Scope pred.
(* Scall *)
Fixpoint alloc_juicy_variables (ge: genv) (rho: env) (jm: juicy_mem) (vl: list (ident*type)) : env * juicy_mem :=
match vl with
| nil => (rho,jm)
| (id,ty)::vars => match JuicyMemOps.juicy_mem_alloc jm 0 (@sizeof ge ty) with
(m1,b1) => alloc_juicy_variables ge (PTree.set id (b1,ty) rho) m1 vars
end
end.
Definition substopt {A} (ret: option ident) (v: val) (P: environ -> A)  : environ -> A :=
match ret with
| Some id => subst id v P
| None => P
end.
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'.

Lemma stackframe_of_freeable_blocks {CS}:
forall Delta f rho ge ve,
cenv_sub (@cenv_cs CS) (genv_cenv ge) ->
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) f rho ->
stackframe_of f rho |-- freeable_blocks (blocks_of_env ge ve).