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'.
Definition maybe_retval (Q: environ -> mpred) retty ret :=
match ret with
| Some id => fun rho => Q (get_result1 id rho)
| None =>
match retty with
| Tvoid => (fun rho => Q (globals_only rho))
| _ => fun rho => EX v: val, Q (make_args (ret_temp::nil) (v::nil) rho)
end
end.
Definition tc_fn_return (Delta: tycontext) (ret: option ident) (t: type) :=
match ret with
| None => True
| Some i => match (temp_types Delta) ! i with Some t' => t=t' | _ => False end
end.
Definition thisvar (ret: option ident) (i : ident) : Prop :=
match ret with None => False | Some x => x=i end.

Lemma semax_call_external: forall
(CS : compspecs) (Espec : OracleKind) (Delta : tycontext)
(A : TypeTree)
(P Q : forall ts : list Type,  (dependent_type_functor_rec ts (AssertTT A)) mpred)
(NEP : super_non_expansive P) (NEQ' : super_non_expansive Q)
(ts : list Type)
(x : (dependent_type_functor_rec ts A) mpred)
(F : environ -> pred rmap) (F0 : assert)
(ret : option ident) (curf : function) (fsig : funsig) (cc : calling_convention)
(R : ret_assert) (psi : genv) (vx : env) (tx : temp_env)
(k : cont) (rho : environ) (ora : OK_ty) (b : block) (jm : juicy_mem)
(Hora : (ext_compat ora) (m_phi jm))
(TCret : tc_fn_return Delta ret (snd fsig))
(TC3 : guard_environ Delta curf rho)
(TC5 : snd fsig = Tvoid -> ret = None)
(H : closed_wrt_vars (thisvar ret) F0)
(HGG : cenv_sub cenv_cs psi)
(H0 : rho = construct_rho (filter_genv psi) vx tx)
(H1 : (rguard Espec psi Delta curf (frame_ret_assert R F0) k) (level (m_phi jm)))
(H4 : (funassert Delta rho) (m_phi jm))
(Prog_OK : (believe Espec Delta psi Delta) (level jm))
(args : list val)
(H14 : (F0 rho * F rho *
P ts x (make_args (map fst (fst fsig)) args rho))%pred
(m_phi jm))
(H5 : (believe_external Espec psi (Vptr b Ptrofs.zero) fsig cc A P Q) (S (level jm)))
(ff : Clight.fundef)
(H16 : Genv.find_funct psi (Vptr b Ptrofs.zero) = Some ff)
(H16' : type_of_fundef ff =
Tfunction (type_of_params (fst fsig)) (snd fsig) cc)
(TC8 : tc_vals (snd (split (fst fsig))) args)
(Hargs : Datatypes.length (fst fsig) = Datatypes.length args),
let ctl := Kcall ret curf vx tx k : cont in
forall (HR : (ALL rho' : environ,
|> ! ((EX old : val,
substopt ret old F rho' *
maybe_retval (Q ts x) (snd fsig) ret rho') >=>
RA_normal R rho')) (m_phi jm)),
jsafeN OK_spec psi (level jm) ora (Callstate ff args ctl) jm.