Section AuxDefs.
Variable semax_external: forall {Hspec: OracleKind} (ids: list ident) (ef: external_function)
(A: rmaps.TypeTree)
(P Q: forall ts, functors.MixVariantFunctor._functor (rmaps.dependent_type_functor_rec ts (AssertTT A)) mpred),
Prop.
Inductive semax {CS: compspecs} {Espec: OracleKind} (Delta: tycontext): (environ -> mpred) -> statement -> ret_assert -> Prop :=
| semax_ifthenelse :
forall P (b: expr) c d R,
@semax CS Espec Delta (P && local (`(typed_true (typeof b)) (eval_expr b))) c R ->
@semax CS Espec Delta (P && local (`(typed_false (typeof b)) (eval_expr b))) d R ->
@semax CS Espec Delta (!! (bool_type (typeof b) = true) && tc_expr Delta (Eunop Cop.Onotbool b (Tint I32 Signed noattr)) && P) (Sifthenelse b c d) R
| semax_seq:
forall R P Q h t,
@semax CS Espec Delta P h (overridePost Q R) ->
@semax CS Espec Delta Q t R ->
@semax CS Espec Delta P (Ssequence h t) R
| semax_break: forall Q,
@semax CS Espec Delta (RA_break Q) Sbreak Q
| semax_continue: forall Q,
@semax CS Espec Delta (RA_continue Q) Scontinue Q
| semax_loop: forall Q Q' incr body R,
@semax CS Espec Delta  Q body (loop1_ret_assert Q' R) ->
@semax CS Espec Delta Q' incr (loop2_ret_assert Q R) ->
@semax CS Espec Delta Q (Sloop body incr) R
| semax_switch: forall (Q: environ->mpred) a sl R,
(forall rho, Q rho |-- tc_expr Delta a rho) ->
(forall n,
@semax CS Espec Delta
(local (`eq (eval_expr a) `(Vint n)) &&  Q)
(seq_of_labeled_statement (select_switch (Int.unsigned n) sl))
(switch_ret_assert R)) ->
@semax CS Espec Delta (!! (is_int_type (typeof a) = true) && Q) (Sswitch a sl) R
(*| semax_call_backward: forall ret a bl R, @semax CS Espec Delta (EX argsig: _, EX retsig: _, EX cc: _, EX A: _, EX P: _, EX Q: _, EX NEP: _, EX NEQ: _, EX ts: _, EX x: _, !! (Cop.classify_fun (typeof a) = Cop.fun_case_f (type_of_params argsig) retsig cc /\ (retsig = Tvoid -> ret = None) /\ tc_fn_return Delta ret retsig) && (|>((tc_expr Delta a) && (tc_exprlist Delta (snd (split argsig)) bl)))  && `(func_ptr (mk_funspec  (argsig,retsig) cc A P Q NEP NEQ)) (eval_expr a) && |>((`(P ts x: environ -> mpred) (make_args' (argsig,retsig) (eval_exprlist (snd (split argsig)) bl))) * oboxopt Delta ret (maybe_retval (Q ts x) retsig ret -* R))) (Scall ret a bl) (normal_ret_assert R)*)
| semax_call_backward: forall ret a bl R,
@semax CS Espec Delta
(EX argsig: _, EX retsig: _, EX cc: _,
EX A: _, EX P: _, EX Q: _, EX NEP: _, EX NEQ: _, EX ts: _, EX x: _,
!! (Cop.classify_fun (typeof a) =
Cop.fun_case_f (type_of_params argsig) retsig cc /\
(retsig = Tvoid -> ret = None) /\
tc_fn_return Delta ret retsig) &&
(((tc_expr Delta a) && (tc_exprlist Delta (snd (split argsig)) bl)))  &&
`(func_ptr (mk_funspec  (argsig,retsig) cc A P Q NEP NEQ)) (eval_expr a) &&
|>((`(P ts x: environ -> mpred) (make_args' (argsig,retsig) (eval_exprlist (snd (split argsig)) bl))) * oboxopt Delta ret (maybe_retval (Q ts x) retsig ret -* R)))
(Scall ret a bl)
(normal_ret_assert R)
| semax_return: forall (R: ret_assert) ret ,
@semax CS Espec Delta
( (tc_expropt Delta ret (ret_type Delta)) &&
`(RA_return R : option val -> environ -> mpred) (cast_expropt ret (ret_type Delta)) (@id environ))
(Sreturn ret)
R
| semax_set_ptr_compare_load_cast_load_backward: forall (P: environ->mpred) id e,
@semax CS Espec Delta
((|> ( (tc_expr Delta e) &&
(tc_temp_id id (typeof e) Delta e) &&
subst id (eval_expr e) P)) ||
(EX cmp: Cop.binary_operation, EX e1: expr, EX e2: expr,
EX ty: type, EX sh1: share, EX sh2: share,
!! (e = Ebinop cmp e1 e2 ty /\
sepalg.nonidentity sh1 /\ sepalg.nonidentity sh2 /\
is_comparison cmp = true /\
eqb_type (typeof e1) int_or_ptr_type = false /\
eqb_type (typeof e2) int_or_ptr_type = false /\
typecheck_tid_ptr_compare Delta id = true) &&
( |> ( (tc_expr Delta e1) &&
(tc_expr Delta e2)  &&
local (`(blocks_match cmp) (eval_expr e1) (eval_expr e2)) &&
(`(mapsto_ sh1 (typeof e1)) (eval_expr e1) * TT) &&
(`(mapsto_ sh2 (typeof e2)) (eval_expr e2) * TT) &&
subst id (eval_expr (Ebinop cmp e1 e2 ty)) P))) ||
(EX sh: share, EX t2: type, EX v2: val,
!! (typeof_temp Delta id = Some t2 /\
is_neutral_cast (typeof e) t2 = true /\
readable_share sh) &&
|> ( (tc_lvalue Delta e) &&
local (`(tc_val (typeof e) v2)) &&
(`(mapsto sh (typeof e)) (eval_lvalue e) (`v2) * TT) &&
subst id (`v2) P)) ||
(EX sh: share, EX e1: expr, EX t1: type, EX v2: val,
!! (e = Ecast e1 t1 /\
typeof_temp Delta id = Some t1 /\
cast_pointer_to_bool (typeof e1) t1 = false /\
readable_share sh) &&
|> ( (tc_lvalue Delta e1) &&
local (`(tc_val t1) (`(eval_cast (typeof e1) t1 v2))) &&
(`(mapsto sh (typeof e1)) (eval_lvalue e1) (`v2) * TT) &&
subst id (`(force_val (sem_cast (typeof e1) t1 v2))) P)))
(Sset id e) (normal_ret_assert P)
| semax_store_backward: forall e1 e2 P,
@semax CS Espec Delta
(EX sh: share, !! writable_share sh && |> ( (tc_lvalue Delta e1) &&  (tc_expr Delta (Ecast e2 (typeof e1)))  &&
((`(mapsto_ sh (typeof e1)) (eval_lvalue e1)) * (`(mapsto sh (typeof e1)) (eval_lvalue e1) (`force_val (`(sem_cast (typeof e2) (typeof e1)) (eval_expr e2))) -* P))))
(Sassign e1 e2)
(normal_ret_assert P)
| semax_skip: forall P, @semax CS Espec Delta P Sskip (normal_ret_assert P)
| semax_builtin: forall P opt ext tl el, @semax CS Espec Delta FF (Sbuiltin opt ext tl el) P
| semax_label: forall (P:environ -> mpred) (c:statement) (Q:ret_assert) l,
@semax CS Espec Delta P c Q -> @semax CS Espec Delta P (Slabel l c) Q
| semax_goto: forall P l, @semax CS Espec Delta FF (Sgoto l) P
| semax_conseq: forall P' (R': ret_assert) P c (R: ret_assert) ,
local (tc_environ Delta) && ((allp_fun_id Delta) && P) |-- |==> |> FF || P' ->
local (tc_environ Delta) && ((allp_fun_id Delta) && RA_normal R') |-- |==> |> FF || RA_normal R ->
local (tc_environ Delta) && ((allp_fun_id Delta) && RA_break R') |-- |==> |> FF || RA_break R ->
local (tc_environ Delta) && ((allp_fun_id Delta) && RA_continue R') |-- |==> |> FF || RA_continue R ->
(forall vl, local (tc_environ Delta) && ((allp_fun_id Delta) && RA_return R' vl) |-- |==> |> FF || RA_return R vl) ->
@semax CS Espec Delta P' c R' -> @semax CS Espec Delta P c R.
Definition semax_body
(V: varspecs) (G: funspecs) {C: compspecs} (f: function) (spec: ident * funspec): Prop :=
match spec with (_, mk_funspec fsig cc A P Q _ _) =>
(map snd (fst fsig) = map snd (fst (fn_funsig f))
/\ snd fsig = snd (fn_funsig f)
/\ list_norepet (map fst (fst fsig))) /\
forall Espec ts x,
@semax C Espec (func_tycontext f V G nil)
(Clight_seplog.close_precondition (map fst (fst fsig)) (map fst f.(fn_params)) (P ts x) * stackframe_of f)
f.(fn_body)
(frame_ret_assert (function_body_ret_assert (fn_return f) (Q ts x)) (stackframe_of f))
end.
Inductive semax_func: forall {Espec: OracleKind} (V: varspecs) (G: funspecs) {C: compspecs} (ge: Genv.t Clight.fundef type)(fdecs: list (ident * Clight.fundef)) (G1: funspecs), Prop :=
| semax_func_nil:   forall {Espec: OracleKind},
forall V G C ge, @semax_func Espec V G C ge nil nil
| semax_func_cons:
forall {Espec: OracleKind},
forall fs id f fsig cc A P Q NEP NEQ (V: varspecs) (G G': funspecs) {C: compspecs} ge b,
andb (id_in_list id (map (@fst _ _) G))
(andb (negb (id_in_list id (map (@fst ident Clight.fundef) fs)))
(semax_body_params_ok f)) = true ->
Forall
(fun it : ident * type =>
complete_type cenv_cs (snd it) =
true) (fn_vars f) ->
var_sizes_ok (f.(fn_vars)) ->
f.(fn_callconv) = cc ->
Genv.find_symbol ge id = Some b -> Genv.find_funct_ptr ge b = Some (Internal f) ->
semax_body V G f (id, mk_funspec fsig cc A P Q NEP NEQ)->
semax_func V G ge fs G' ->
semax_func V G ge ((id, Internal f)::fs)
((id, mk_funspec fsig cc A P Q NEP NEQ)  :: G')
| semax_func_cons_ext:
forall {Espec: OracleKind},
forall (V: varspecs) (G: funspecs) {C: compspecs} ge fs id ef argsig retsig A P Q NEP NEQ
argsig'
(G': funspecs) cc (ids: list ident) b,
ids = map fst argsig' -> (* redundant but useful for the client,
to calculate ids by reflexivity *)
argsig' = zip_with_tl ids argsig ->
ef_sig ef =
mksignature
(typlist_of_typelist (type_of_params argsig'))
(opttyp_of_type retsig) cc ->
id_in_list id (map (@fst _ _) fs) = false ->
length ids = length (typelist2list argsig) ->
(ef_inline ef = false \/ withtype_empty A) ->
(forall gx ts x (ret : option val),
(Q ts x (make_ext_rval gx ret)
&& !!step_lemmas.has_opttyp ret (opttyp_of_type retsig)
|-- !!tc_option_val retsig ret)) ->

Lemma semax_body_subsumption: forall cs V V' F F' f spec
(SF: @semax_body V F cs f spec)
(TS: tycontext_sub (func_tycontext f V F nil) (func_tycontext f V' F' nil)),
@semax_body V' F' cs f spec.