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.

(* Specifications: *)
Lemma derives_refl' {A: Type}  `{ageable A}:
forall P Q: pred A, P=Q -> P |-- Q.
Lemma same_glob_funassert':
forall Delta1 Delta2 rho rho',
(forall id, (glob_specs Delta1) ! id = (glob_specs Delta2) ! id) ->
ge_of rho = ge_of rho' ->
funassert Delta1 rho = funassert Delta2 rho'.
Lemma semax_call_external:
forall (Delta : tycontext) (A : TypeTree)
(P Q Q' : forall ts, dependent_type_functor_rec ts (AssertTT A) mpred)
(ts: list Type) (x : dependent_type_functor_rec ts A mpred)
(F : environ -> pred rmap) (F0 : assert)
(ret : option ident) (params : list (ident * type)) (retty : type) cc
(a : expr) (bl : list expr) (R : ret_assert) (psi : genv) (vx : env)
(tx : temp_env) (k : cont) (rho : environ) (ora : OK_ty) (jm : juicy_mem)
(b : block)
(Hora : juicy_mem_op (ext_compat ora) jm)
(TC0 : Cop.classify_fun (typeof a) =
Cop.fun_case_f (type_of_params params) retty cc)
(TCret : tc_fn_return Delta ret retty)
(TC1 : (|> tc_expr Delta a rho) (m_phi jm))
(TC2 : (|> tc_exprlist Delta (map snd params) bl rho) (m_phi jm))
(TC3 : guard_environ Delta (current_function k) rho)
(TC5 : retty = Tvoid -> ret = None)
(H : closed_wrt_modvars (Scall ret a bl) F0)
(HR : RA_normal R =
(fun rho0 : environ =>
EX  old : val,
substopt ret old F rho0 * maybe_retval (Q ts x) retty ret rho0))
(HGG:  genv_cenv psi = cenv_cs)
(H0 : rho = construct_rho (filter_genv psi) vx tx)
(H3 : eval_expr a rho = Vptr b Ptrofs.zero)
(H4 : (funassert Delta rho) (m_phi jm))
(H1 : (rguard Espec psi Delta
(frame_ret_assert R F0) k) (level (m_phi jm)))
(H11 : forall vl : environ, (!|>(Q' ts x vl <=> Q ts x vl)) (m_phi jm))
(H14 : (|>(F0 rho * F rho *
P ts x
(make_args (map fst params)
(eval_exprlist (map snd params) bl rho) rho))) (m_phi jm))
(n : nat)
(H2 : level (m_phi jm) = S n)
(H15 : (believe_external Espec psi (Vptr b Ptrofs.zero) (params, retty) cc A P Q')
(level (m_phi jm))),
exists (c' : corestate) (m' : juicy_mem),
jstep (cl_core_sem psi) (State vx tx (Kseq (Scall ret a bl) :: k)) jm c' m' /\
jm_bupd ora (jsafeN OK_spec psi n ora c') m'.
Lemma alloc_juicy_variables_age:
forall {ge rho jm jm1 vl rho' jm' jm1'},
age jm jm1 -> age jm' jm1' ->
alloc_juicy_variables ge rho jm vl = (rho', jm') ->
alloc_juicy_variables ge rho jm1 vl = (rho', jm1').
Lemma alloc_juicy_variables_resource_decay:
forall ge rho jm vl rho' jm',
alloc_juicy_variables ge rho jm vl = (rho', jm') ->
resource_decay (nextblock (m_dry jm)) (m_phi jm) (m_phi jm') /\
(nextblock (m_dry jm) <= nextblock (m_dry jm'))%positive.
Lemma make_args_close_precondition:
forall params args ge ve te m tx ve' te' m' P vars,
list_norepet (map fst params) ->
bind_parameter_temps params args tx = Some te' ->
alloc_juicy_variables ge empty_env m vars = (ve', m') ->
P (make_args (map fst params) args (construct_rho (filter_genv ge) ve te))
|-- close_precondition params vars P (construct_rho (filter_genv ge) ve' te').
Lemma juicy_mem_alloc_block:
forall jm n jm2 b F,
juicy_mem_alloc jm 0 n = (jm2, b) ->
app_pred F (m_phi jm)  ->
0 <= n < Ptrofs.modulus ->
app_pred (F * memory_block Share.top n (Vptr b Ptrofs.zero)) (m_phi jm2).
Lemma alloc_juicy_variables_lem2:
forall jm f (ge: genv) ve te jm' (F: pred rmap)
(HGG:  genv_cenv ge = cenv_cs)
(COMPLETE: Forall (fun it => complete_type cenv_cs (snd it) = true) (fn_vars f))
(Hsize: Forall (fun var => @sizeof ge (snd var) <= Ptrofs.max_unsigned) (fn_vars f)),
list_norepet (map fst (fn_vars f)) ->
alloc_juicy_variables ge empty_env jm (fn_vars f) = (ve, jm') ->
app_pred F (m_phi jm) ->
app_pred (F * stackframe_of f (construct_rho (filter_genv ge) ve te)) (m_phi jm').
Lemma free_list_juicy_mem_ghost: forall m l m', free_list_juicy_mem m l m' ->
ghost_of (m_phi m') = ghost_of (m_phi m).
Lemma alloc_juicy_variables_ghost: forall l ge rho jm,
ghost_of (m_phi (snd (alloc_juicy_variables ge rho jm l))) = ghost_of (m_phi jm).
Lemma semax_call_aux:
forall (Delta : tycontext)
(A : TypeTree)
(P Q Q' : forall ts, 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) (fsig0 : funsig) cc (a : expr)
(bl : list expr) (R : ret_assert) (psi : genv) (vx:env) (tx:Clight.temp_env) (k : cont) (rho : environ)
(ora : OK_ty) (jm : juicy_mem) (b : block) (id : ident)
(Hora : juicy_mem_op (ext_compat ora) jm),
Cop.classify_fun (typeof a) =
Cop.fun_case_f (type_of_params (fst fsig0)) (snd fsig0) cc ->
tc_fn_return Delta ret (snd fsig0) ->
(|>tc_expr Delta a rho) (m_phi jm) ->
(|>tc_exprlist Delta (snd (split (fst fsig0))) bl rho) (m_phi jm) ->
guard_environ Delta (current_function k) rho ->
(snd fsig0 =Tvoid -> ret=None) ->
closed_wrt_modvars (Scall ret a bl) F0 ->
RA_normal R = (fun rho0 : environ => EX old:val, substopt ret old F rho0 * maybe_retval (Q ts x) (snd fsig0) ret rho0) ->
genv_cenv psi = cenv_cs ->
rho = construct_rho (filter_genv psi) vx tx ->
eval_expr a rho = Vptr b Ptrofs.zero ->
(funassert Delta rho) (m_phi jm) ->
(rguard Espec psi Delta (frame_ret_assert R F0) k) (level (m_phi jm)) ->
(believe Espec Delta psi Delta) (level (m_phi jm)) ->
(glob_specs Delta)!id = Some (mk_funspec fsig0 cc A P Q' NEP NEQ') ->
Genv.find_symbol psi id = Some b ->
(forall vl : environ, (!|>(Q' ts x vl <=> Q ts x vl)) (m_phi jm)) ->
(|>(F0 rho * F rho *
P ts x (make_args (map (@fst  _ _) (fst fsig0))
(eval_exprlist (snd (split (fst fsig0))) bl rho) rho)
)) (m_phi jm) ->
jsafeN (@OK_spec Espec) psi (level (m_phi jm)) ora
(State (vx) (tx) (Kseq (Scall ret a bl) :: k)) jm.