Fixpoint match_globvars (gvs: list (ident * globvar type)) (V: varspecs) : bool :=
 match V with
 | nil => true
 | (id,t)::V' => match gvs with
                       | nil => false
                       | (j,g)::gvs' => if eqb_ident id j
                                              then andb (eqb_type t (gvar_info g)) (match_globvars gvs' V')
                                              else match_globvars gvs' V
                      end
  end.Definition prog_contains (ge: genv) (fdecs : list (ident * 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 _ cc A P Q _ _) =>
    forall Espec ts x, 
      semax Espec (func_tycontext f V G nil)
          (fun rho => P ts x rho * stackframe_of f rho)
           (Ssequence f.(fn_body) (Sreturn None))
          (frame_ret_assert (function_body_ret_assert (fn_return f) (Q ts x)) (stackframe_of f))
 end.Definition semax_func
         (V: varspecs) (G: funspecs) {C: compspecs} (fdecs: list (ident * fundef)) (G1: funspecs) : Prop :=
   match_fdecs fdecs G1 /\
  forall ge, prog_contains ge fdecs ->
          genv_cenv ge = cenv_cs ->
          forall n, believe Espec (nofunc_tycontext V G) ge (nofunc_tycontext V G1) n.Definition main_pre (prog: program) : list Type -> (ident->val) -> assert :=
(fun nil gv => globvars2pred gv (prog_vars prog)).Definition main_pre_ext (prog: program) (ora: OK_ty) : 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' (prog: program) 
    (post: list Type -> (ident->val) -> environ ->pred rmap): funspec :=
  mk_funspec (nil, tint) cc_default
     (ConstType (ident->val)) (main_pre prog) post
       (const_super_non_expansive _ _) (const_super_non_expansive _ _).Definition main_spec (prog: program): funspec :=
  mk_funspec (nil, tint) cc_default
     (ConstType (ident->val)) (main_pre prog) (main_post prog)
       (const_super_non_expansive _ _) (const_super_non_expansive _ _).Definition main_spec_ext' (prog: program) (ora: OK_ty)
    (post: list Type -> (ident->val) -> environ ->pred rmap): funspec :=
  mk_funspec (nil, tint) cc_default
     (ConstType (ident->val)) (main_pre_ext 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_ext 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 semax_prog {C: compspecs}
           (prog: program)  (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 /\
  match_globvars (prog_vars prog) V = true /\
  match find_id prog.(prog_main) G with
  | Some s => exists post, s = main_spec' prog post
  | None => False
  end.Definition semax_prog_ext {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 /\
  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.

(* Specifications: *)
Lemma semax_func_nil: forall V G {C: compspecs}, semax_func V G nil nil.
Lemma laterR_level: forall w w' : rmap, laterR w w' -> (level w > level w')%nat.
Lemma necR_level: forall w w' : rmap, necR w w' -> (level w >= level w')%nat.
Lemma semax_func_cons_aux: forall (psi: genv) id fsig1 cc1 A1 P1 Q1 NEP1 NEQ1 fsig2 cc2 A2 P2 Q2 (V: varspecs) (G': funspecs) {C: compspecs} b fs, Genv.find_symbol psi id = Some b -> ~ In id (map (fst (A:=ident) (B:=fundef)) fs) -> match_fdecs fs G' -> claims psi (nofunc_tycontext V ((id, mk_funspec fsig1 cc1 A1 P1 Q1 NEP1 NEQ1) :: G')) (Vptr b Ptrofs.zero) fsig2 cc2 A2 P2 Q2 -> fsig1=fsig2 /\ cc1 = cc2 /\ A1=A2 /\ JMeq P1 P2 /\ JMeq Q1 Q2.
Lemma semax_func_cons: forall fs id f cc (A: TypeTree) P Q NEP NEQ (V: varspecs) (G G': funspecs) {C: compspecs}, andb (id_in_list id (map (@fst _ _) G)) (andb (negb (id_in_list id (map (@fst ident 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 -> precondition_closed f P -> semax_body V G f (id, mk_funspec (fn_funsig f) cc A P Q NEP NEQ) -> semax_func V G fs G' -> semax_func V G ((id, Internal f)::fs) ((id, mk_funspec (fn_funsig f) cc A P Q NEP NEQ) :: G').
Lemma semax_external_FF: forall Espec ids ef A n, @semax_external Espec ids ef A (fun _ _ _ => FF) (fun _ _ _ => FF) n.