Section semax_prog.
Context (Espec: OracleKind).
Definition prog_contains (ge: genv) (fdecs : list (ident * Clight.fundef)) : Prop :=
forall id f, In (id,f) fdecs ->
exists b, Genv.find_symbol ge id = Some b /\ Genv.find_funct_ptr ge b = Some f.
Definition entry_tempenv (te: temp_env) (f: function) (vl: list val) :=
length vl = length f.(fn_params) /\
forall id v, PTree.get id te = Some v ->
In (id,v)
(combine (map (@fst _ _) f.(fn_params)) vl
++ map (fun tv => (fst tv, Vundef)) f.(fn_temps)).
Definition semax_body_params_ok f : bool :=
andb
(compute_list_norepet (map (@fst _ _) (fn_params f) ++ map (@fst _ _) (fn_temps f)))
(compute_list_norepet (map (@fst _ _) (fn_vars f))).
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 Espec (func_tycontext f V G nil)
(fun rho => close_precondition (map fst (fst fsig)) (map fst f.(fn_params)) (P ts x) rho * stackframe_of f rho)
f.(fn_body)
(frame_ret_assert (function_body_ret_assert (fn_return f) (Q ts x)) (stackframe_of f))
end.
Definition genv_contains (ge: Genv.t Clight.fundef type) (fdecs : list (ident * Clight.fundef)) : Prop :=
forall id f, In (id,f) fdecs ->
exists b, Genv.find_symbol ge id = Some b /\ Genv.find_funct_ptr ge b = Some f.
Definition main_pre {Z} (prog: program) (ora: Z) : list Type -> (ident->val) -> assert :=
(fun nil gv rho => globvars2pred gv (prog_vars prog) rho * has_ext ora).
Definition Tint32s := Tint I32 Signed noattr.
Definition main_post (prog: program) : list Type -> (ident->val) -> assert :=
(fun nil _ _ => TT).
Definition main_spec_ext' {Z} (prog: program) (ora: Z)
(post: list Type -> (ident->val) -> environ ->pred rmap): funspec :=
mk_funspec (nil, tint) cc_default
(ConstType (ident->val)) (main_pre prog ora) post
(const_super_non_expansive _ _) (const_super_non_expansive _ _).
Definition main_spec_ext (prog: program) (ora: OK_ty): funspec :=
mk_funspec (nil, tint) cc_default
(ConstType (ident->val)) (main_pre prog ora) (main_post prog)
(const_super_non_expansive _ _) (const_super_non_expansive _ _).
Definition is_Internal (prog : program) (f : ident) :=
match Genv.find_symbol (Genv.globalenv prog) f with
None => false
| Some b =>
match Genv.find_funct_ptr (Genv.globalenv prog) b with
| None => false
| Some f =>
match f with
| External _ _ _ _ => false
| Internal _ => true
end
end
end.
Definition postcondition_allows_exit retty :=
forall
v  ora (jm : juicy_mem),
tc_option_val retty v ->
app_pred (ext_compat ora) (m_phi jm) ->
ext_spec_exit OK_spec v ora jm.
Definition semax_prog {C: compspecs}
(prog: program) (ora: OK_ty) (V: varspecs) (G: funspecs) : Prop :=
compute_list_norepet (prog_defs_names prog) = true  /\
all_initializers_aligned prog /\
cenv_cs = prog_comp_env prog /\
(*  @semax_func V G C (prog_funct prog) G /\*)
@semax_func V G C (Genv.globalenv prog) (prog_funct prog) G /\
match_globvars (prog_vars prog) V = true /\
match find_id prog.(prog_main) G with
| Some s => exists post,
s = main_spec_ext' prog ora post
| None => False
end.
Program Definition HO_pred_eq {T}{agT: ageable T}
(A: Type) (P: A -> pred T) (A': Type) (P': A' -> pred T) : pred nat :=
fun v => exists H: A=A',
match H in (_ = A) return (A -> pred T) -> Prop with
| refl_equal => fun (u3: A -> pred T) =>
forall x: A, (P x <=> u3 x) v
end P'.
Next Obligation.
try (intros; intro; intros).
destruct H0. exists x.
destruct x.
intros. specialize (H0 x). eapply pred_hereditary; eauto.
Qed.

Lemma semax_func_cons: forall
fs id f fsig cc (A: TypeTree) 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 cenv_cs (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').