Local Open Scope logic.
Fixpoint argtypes (al: list (ident * type)) : list type :=
match al with (_,t)::al' => t :: argtypes al' | nil => nil end.
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 removeopt_localdef (ret: option ident) (l: list localdef) : list localdef :=
match ret with
| Some id => remove_localdef_temp id l
| None => l
end.
(*   (HAB: forall ts : list Type, Inhabitant (functors.MixVariantFunctor._functor (rmaps.dependent_type_functor_rec ts (withtype_of_funspec fs)) mpred)) *), @semax cs Espec Delta ((*|>*)(tc_expr Delta a && tc_exprlist Delta (argtypes argsig) bl) && (|>`(Pre ts x: environ -> mpred) ( (make_args' (argsig,retsig) (eval_exprlist (argtypes argsig) bl))) * `(func_ptr' fs) (eval_expr a) * |>PROPx P (LOCALx Q (SEPx R)))) (Scall ret a bl) (normal_ret_assert (maybe_retval (Post ts x) retsig ret * PROPx P (LOCALx (removeopt_localdef ret Q) (SEPx R)))).  Lemma semax_call1: forall Espec {cs: compspecs} Delta fs A Pre Post NEPre NEPost ts x id argsig retsig cc a bl P Q R (Hsub: funspec_sub fs (mk_funspec (argsig,retsig) cc A Pre Post NEPre NEPost)), Cop.classify_fun (typeof a) = Cop.fun_case_f (type_of_params argsig) retsig cc -> match retsig with | Tvoid => False | _ => True end -> tc_fn_return Delta (Some id) retsig -> @semax cs Espec Delta ((*|>*)(tc_expr Delta a && tc_exprlist Delta (argtypes argsig) bl) && (|>`(Pre ts x: environ -> mpred) ( (make_args' (argsig,retsig) (eval_exprlist (argtypes argsig) bl))) * `(func_ptr' fs) (eval_expr a) * |>PROPx P (LOCALx Q (SEPx R)))) (Scall (Some id) a bl) (normal_ret_assert (`(Post ts x: environ -> mpred) (get_result1 id) * PROPx P (LOCALx (remove_localdef_temp id Q) (SEPx R)))).  Definition ifvoid {T} t (A B: T) := match t with Tvoid => A | _ => B end.  Lemma semax_call0: forall Espec {cs: compspecs} Delta fs A Pre Post NEPre NEPost ts x argsig retty cc a bl P Q R (Hsub: funspec_sub fs (mk_funspec (argsig,retty) cc A Pre Post NEPre NEPost)), Cop.classify_fun (typeof a) = Cop.fun_case_f (type_of_params argsig) retty cc -> @semax cs Espec Delta ((*|>*)(tc_expr Delta a && tc_exprlist Delta (argtypes argsig) bl) && (|>`(Pre ts x: environ -> mpred) ( (make_args' (argsig,retty) (eval_exprlist (argtypes argsig) bl))) * `(func_ptr' fs) (eval_expr a) * |>PROPx P (LOCALx Q (SEPx R)))) (Scall None a bl) (normal_ret_assert (ifvoid retty (`(Post ts x: environ -> mpred) (make_args nil nil)) (EX v:val, `(Post ts x: environ -> mpred) (make_args (ret_temp::nil) (v::nil))) * PROPx P (LOCALx Q (SEPx R)))).  Lemma semax_fun_id': forall id f TC Espec {cs: compspecs} Delta (PQR: environ->mpred) PostCond c (GLBL: (var_types Delta) ! id = None), (glob_specs Delta) ! id = Some f -> (glob_types Delta) ! id = Some (type_of_funspec f) -> @semax cs Espec Delta ((*|>*)TC && (local (tc_environ Delta) && (`(func_ptr' f) (eval_var id (type_of_funspec f)) * |>PQR))) c PostCond -> (*       @semax cs Espec Delta (|>(TC && PQR)) c PostCond.*)

(* TODO: Change argument order. ==> A Pre Post NEPre NEPost ts x *)
Lemma semax_call_id0:
forall Espec {cs: compspecs} Delta P Q R id bl fs argsig retty cc A ts x Pre Post NEPre NEPost
(Hsub: funspec_sub fs (mk_funspec (argsig,retty) cc A Pre Post NEPre NEPost))
(GLBL: (var_types Delta) ! id = None),
(glob_specs Delta) ! id = Some fs ->
(glob_types Delta) ! id = Some (type_of_funspec fs) ->
@semax cs Espec Delta ((*|>*) (tc_exprlist Delta (argtypes argsig) bl
&& |> (`(Pre ts x: environ -> mpred) (make_args' (argsig,retty) (eval_exprlist (argtypes argsig) bl))
* PROPx P (LOCALx Q (SEPx R)))))
(Scall None (Evar id (Tfunction (type_of_params argsig) retty cc)) bl)
(normal_ret_assert
((ifvoid retty (`(Post ts x: environ -> mpred) (make_args nil nil))
(EX v:val, `(Post ts x: environ -> mpred) (make_args (ret_temp::nil) (v::nil))))
* PROPx P (LOCALx Q (SEPx R)))).