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.

(* Specifications: *)
Lemma fst_split {T1 T2}: forall vl: list (T1*T2), fst (split vl) = map fst vl.
Lemma snd_split {T1 T2}: forall vl: list (T1*T2), snd (split vl) = map snd vl.
Lemma eval_exprlist_relate:
forall (Delta : tycontext) (fsig0 : funsig)
(bl : list expr) (psi : genv) (vx : env) (tx : temp_env)
(rho : environ) m,
denote_tc_assert (typecheck_exprlist Delta (snd (split (fst fsig0))) bl) rho (m_phi m) ->
typecheck_environ Delta rho ->
genv_cenv psi = cenv_cs ->
rho = construct_rho (filter_genv psi) vx tx ->
forall f : function,
fsig0 = fn_funsig f ->
Clight.eval_exprlist psi vx tx (m_dry m) bl
(type_of_params (fn_params f))
(eval_exprlist (snd (split (fst fsig0))) bl rho).
Lemma bind_parameter_temps_excludes :
forall l1 l2 t id t1,
~In id (map fst l1) ->
(bind_parameter_temps l1 l2 t) = Some t1 ->
t1 ! id = t ! id.
Lemma pass_params_ni :
forall  l2
(te' : temp_env) (id : positive) te l,
bind_parameter_temps l2 l (te) = Some te' ->
(In id (map fst l2) -> False) ->
Map.get (make_tenv te') id = te ! id.
Lemma bind_exists_te : forall l1 l2 t1 t2 te,
bind_parameter_temps l1 l2 t1 = Some te ->
exists te2, bind_parameter_temps l1 l2 t2 = Some te2.
Lemma smaller_temps_exists2 : forall l1 l2 t1 t2 te te2 i,
bind_parameter_temps l1 l2 t1 = Some te ->
bind_parameter_temps l1 l2 t2 = Some te2 ->
t1 ! i = t2 ! i ->
te ! i = te2 ! i.
Lemma smaller_temps_exists' : forall l l1 te te' id i t,
bind_parameter_temps l l1 (PTree.set id Vundef t)=  Some te ->
i <> id ->
(bind_parameter_temps l l1 t = Some te') -> te' ! i = te ! i.
Lemma smaller_temps_exists'' : forall l l1 te id i t,
bind_parameter_temps l l1 (PTree.set id Vundef t)=  Some te ->
i <> id ->
exists te', (bind_parameter_temps l l1 t = Some te').
Lemma smaller_temps_exists : forall l l1 te id i t,
bind_parameter_temps l l1 (PTree.set id Vundef t)=  Some te ->
i <> id ->
exists te', (bind_parameter_temps l l1 t = Some te' /\ te' ! i = te ! i).
Lemma alloc_vars_lookup :
forall ge id m1 l ve m2 e ,
list_norepet (map fst l) ->
(forall i, In i (map fst l) -> e ! i = None) ->
Clight.alloc_variables ge (e) m1 l ve m2 ->
(exists v, e ! id = Some v) ->
ve ! id = e ! id.
Lemma alloc_vars_lemma : forall ge id l m1 m2 ve ve'
(SD : forall i, In i (map fst l) -> ve ! i = None),
list_norepet (map fst l) ->
Clight.alloc_variables ge ve m1 l ve' m2 ->
(In id (map fst l) ->
exists v, ve' ! id = Some v).
Lemma semax_call_typecheck_environ:
forall (Delta : tycontext) (bl : list expr) (psi : genv) (vx : env) (tx : temp_env)
(jm : juicy_mem) (b : block) (f : function)
(H17 : list_norepet (map fst (fn_params f) ++ map fst (fn_temps f)))
(H17' : list_norepet (map fst (fn_vars f)))
(H16 : Genv.find_funct_ptr psi b = Some (Internal f))
(ve' : env) (jm' : juicy_mem) (te' : temp_env)
(H15 : alloc_variables psi empty_env (m_dry jm) (fn_vars f) ve' (m_dry jm'))
(TC3 : typecheck_temp_environ (make_tenv tx) (temp_types Delta))
(TC4 : typecheck_var_environ (make_venv vx) (var_types Delta))
(TC5 : typecheck_glob_environ (filter_genv psi) (glob_types Delta))
(H : forall (b : ident) (b0 : funspec) (a' : rmap),
necR (m_phi jm') a' ->
(glob_specs Delta) ! b = Some b0 ->
exists b1 : block,
filter_genv psi b = Some b1 /\
func_at b0 (b1,0) a')
(H1: forall (b : block) (b0 : funspec) (a' : rmap),
necR (m_phi jm') a' ->
(func_at' b0 (b, 0)) a' ->
exists (b1 : ident),
filter_genv psi b1 = Some b /\
(exists fs : funspec, (glob_specs Delta) ! b1 = Some fs))
(l : list ident) (l0 : list type)
(Heqp : (l, l0) = split (fn_params f))
(TC2 : denote_tc_assert (typecheck_exprlist Delta l0 bl)
(mkEnviron (filter_genv psi) (make_venv vx) (make_tenv tx)) (m_phi jm)) (**)
(H21 : bind_parameter_temps (fn_params f)
(eval_exprlist l0 bl
(mkEnviron (filter_genv psi) (make_venv vx) (make_tenv tx)))
(create_undef_temps (fn_temps f)) = Some te')
(TE : typecheck_environ
Delta (mkEnviron (filter_genv psi) (make_venv vx) (make_tenv tx))),
typecheck_environ
(mk_tycontext
(make_tycontext_t (fn_params f) (fn_temps f))
(make_tycontext_v (fn_vars f))
(fn_return f)  (glob_types Delta) (glob_specs Delta) (annotations Delta))
(mkEnviron (filter_genv psi) (make_venv ve') (make_tenv te')).