Require Import VST.veric.juicy_base.
Require Import VST.veric.juicy_mem VST.veric.juicy_mem_lemmas VST.veric.juicy_mem_ops.
Require Import VST.veric.res_predicates.
Require Import VST.veric.extend_tc.
Require Import VST.veric.Clight_seplog.
Require Import VST.veric.Clight_assert_lemmas.
Require Import VST.veric.Clight_new.
Require Import VST.sepcomp.extspec.
Require Import VST.sepcomp.step_lemmas.
Require Import VST.veric.juicy_extspec.
Require Import VST.veric.tycontext.
Require Import VST.veric.expr2.
Require Import VST.veric.expr_lemmas.
Require Import VST.veric.semax.
Require Import VST.veric.semax_lemmas.
Require Import VST.veric.Clight_lemmas.
Require Import VST.veric.initial_world.
Require Import VST.msl.normalize.
Require Import VST.veric.semax_call.
Require Import VST.veric.Clight_initial_world.
Require Import VST.veric.initialize.
Require Import VST.veric.coqlib4.
Require Import Coq.Logic.JMeq.

Require Import Coq.Logic.JMeq.
Require Import VST.veric.ghost_PCM.

Local Open Scope pred.

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.

Section semax_prog.
Context (Espec: OracleKind).

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
(* Goal: @ex val (fun v : val => and (@eq (option val) (if ident_eq i p then @Some val (@fst val type a) else @Map.get val (make_tenv (temp_bindings (Pos.add p xH) (@map (prod val type) val (@fst val type) typed_args))) i) (@Some val v)) (tc_val' ty v)) *)
       (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
(* Goal: @ex val (fun v : val => and (@eq (option val) (if ident_eq i p then @Some val (@fst val type a) else @Map.get val (make_tenv (temp_bindings (Pos.add p xH) (@map (prod val type) val (@fst val type) typed_args))) i) (@Some val v)) (tc_val' ty v)) *)
         (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.

(* Goal: @ex val (fun v : val => and (@eq (option val) (if ident_eq i p then @Some val (@fst val type a) else @Map.get val (make_tenv (temp_bindings (Pos.add p xH) (@map (prod val type) val (@fst val type) typed_args))) i) (@Some val v)) (tc_val' ty v)) *)
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.

(* Goal: @ex val (fun v : val => and (@eq (option val) (if ident_eq i p then @Some val (@fst val type a) else @Map.get val (make_tenv (temp_bindings (Pos.add p xH) (@map (prod val type) val (@fst val type) typed_args))) i) (@Some val v)) (tc_val' ty v)) *)
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.

Lemma semax_func_nil:
   forall
(* Goal: @ex val (fun v : val => and (@eq (option val) (if ident_eq i p then @Some val (@fst val type a) else @Map.get val (make_tenv (temp_bindings (Pos.add p xH) (@map (prod val type) val (@fst val type) typed_args))) i) (@Some val v)) (tc_val' ty v)) *)
     V G {C: compspecs}, semax_func V G nil nil.
Proof.
(* Goal: forall (V : varspecs) (G : funspecs) (C : compspecs), @semax_func V G C (@nil (prod ident fundef)) (@nil (prod ident funspec)) *)
intros; split; auto.
(* Goal: @list_norepet ident (@map (prod ident fundef) ident (@fst ident fundef) (@prog_funct' (Ctypes.fundef function) type (@nil (prod ident (globdef (Ctypes.fundef function) type))))) *)
(* Goal: @list_norepet ident (@map (prod ident fundef) ident (@fst ident fundef) (@prog_funct' (Ctypes.fundef function) type (@cons (prod ident (globdef (Ctypes.fundef function) type)) a l))) *)
(* Goal: @ex block (fun b : block => @eq (option block) (@Map.get block (@Genv.find_symbol fundef type (genv_genv (globalenv prog))) id) (@Some block b)) *)
constructor.
(* Goal: forall (id : positive) (ty : type), iff (@eq (option type) (@PTree.get type id (make_tycontext_v (@nil (prod ident type)))) (@Some type ty)) (@ex block (fun v : block => @eq (option (prod block type)) (@Map.get (prod block type) (make_venv empty_env) id) (@Some (prod block type) (@pair block type v ty)))) *)
intros. rename H0 into HGG.
(* Goal: @app_pred nat ag_nat (@believe C Espec (nofunc_tycontext V G) ge (nofunc_tycontext V (@nil (prod ident funspec)))) n *)
intros b fsig cc ty P Q w ? ?.
(* Goal: @app_pred nat ag_nat (@orp nat ag_nat (believe_external Espec ge b fsig cc ty P Q) (@believe_internal C Espec ge (nofunc_tycontext V G) b fsig cc ty P Q)) w *)
hnf in H1.
(* Goal: @app_pred nat ag_nat (@orp nat ag_nat (believe_external Espec ge b fsig cc ty P Q) (@believe_internal C Espec ge (nofunc_tycontext V G) b fsig cc ty P Q)) w *)
destruct H1 as [b' [NEP [NEQ [? ?]]]].
(* Goal: @In (prod ident funspec) (@pair ident funspec id (mk_funspec f0 cc0 A a a0 P_ne Q_ne)) G *)
simpl in H1.
(* Goal: @app_pred nat ag_nat (@orp nat ag_nat (believe_external Espec ge b fsig cc ty P Q) (@believe_internal C Espec ge (nofunc_tycontext V G) b fsig cc ty P Q)) w *)
rewrite PTree.gempty in H1. inv H1.
Qed.

(* Goal: @ex val (fun v : val => and (@eq (option val) (if ident_eq i p then @Some val (@fst val type a) else @Map.get val (make_tenv (temp_bindings (Pos.add p xH) (@map (prod val type) val (@fst val type) typed_args))) i) (@Some val v)) (tc_val' ty v)) *)
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.
(* Goal: forall (id : positive) (ty : type), iff (@eq (option type) (@PTree.get type id (make_tycontext_v (@nil (prod ident type)))) (@Some type ty)) (@ex block (fun v : block => @eq (option (prod block type)) (@Map.get (prod block type) (make_venv empty_env) id) (@Some (prod block type) (@pair block type v ty)))) *)
  intros; intro; intros.
(* Goal: @In (prod ident (globdef (Ctypes.fundef function) type)) (@pair ident (globdef (Ctypes.fundef function) type) id (@Gfun (Ctypes.fundef function) type f)) (@cons (prod ident (globdef (Ctypes.fundef function) type)) (@pair ident (globdef (Ctypes.fundef function) type) i (@Gfun (Ctypes.fundef function) type f0)) l) *)
(* Goal: @In (prod ident (globdef (Ctypes.fundef function) type)) (@pair ident (globdef (Ctypes.fundef function) type) id (@Gfun (Ctypes.fundef function) type f)) (@cons (prod ident (globdef (Ctypes.fundef function) type)) (@pair ident (globdef (Ctypes.fundef function) type) i (@Gvar (Ctypes.fundef function) type v)) l) *)
  destruct H0. exists x.
(* Goal: match x in (eq _ A0) return (forall _ : forall _ : A0, @pred T agT, Prop) with | eq_refl => fun u3 : forall _ : A, @pred T agT => forall x : A, @app_pred nat ag_nat (@fash T agT (@andp T agT (@imp T agT (P x) (u3 x)) (@imp T agT (u3 x) (P x)))) a' end P' *)
  destruct x.
(* Goal: forall (id : positive) (ty : type), iff (@eq (option type) (@PTree.get type id (make_tycontext_v (@nil (prod ident type)))) (@Some type ty)) (@ex block (fun v : block => @eq (option (prod block type)) (@Map.get (prod block type) (make_venv empty_env) id) (@Some (prod block type) (@pair block type v ty)))) *)
   intros. specialize (H0 x). eapply pred_hereditary; eauto.
 Qed.

Lemma laterR_level: forall w w' : rmap, laterR w w' -> (level w > level w')%nat.
Proof.
(* Goal: forall (w w' : rmap) (_ : @necR rmap ag_rmap w w'), ge (@level rmap ag_rmap w) (@level rmap ag_rmap w') *)
induction 1.
(* Goal: ge (@level rmap ag_rmap x) (@level rmap ag_rmap y) *)
(* Goal: ge (@level rmap ag_rmap x) (@level rmap ag_rmap x) *)
(* Goal: ge (@level rmap ag_rmap x) (@level rmap ag_rmap z) *)
unfold age in H. rewrite <- ageN1 in H.
(* Goal: ge (@level rmap ag_rmap x) (@level rmap ag_rmap y) *)
(* Goal: ge (@level rmap ag_rmap x) (@level rmap ag_rmap x) *)
(* Goal: ge (@level rmap ag_rmap x) (@level rmap ag_rmap z) *)
change rmap with R.rmap; change ag_rmap with R.ag_rmap.
(* Goal: ge (@level rmap ag_rmap x) (@level rmap ag_rmap y) *)
(* Goal: ge (@level rmap ag_rmap x) (@level rmap ag_rmap x) *)
(* Goal: ge (@level rmap ag_rmap x) (@level rmap ag_rmap z) *)
rewrite (ageN_level _ _ _ H). generalize (@level _ R.ag_rmap y). intros; omega.
(* Goal: ge (@level rmap ag_rmap x) (@level rmap ag_rmap z) *)
omega.
Qed.

Lemma necR_level:  forall w w' : rmap, necR w w' -> (level w >= level w')%nat.
Proof.
(* Goal: forall (w w' : rmap) (_ : @necR rmap ag_rmap w w'), ge (@level rmap ag_rmap w) (@level rmap ag_rmap w') *)
induction 1.
(* Goal: ge (@level rmap ag_rmap x) (@level rmap ag_rmap y) *)
(* Goal: ge (@level rmap ag_rmap x) (@level rmap ag_rmap x) *)
(* Goal: ge (@level rmap ag_rmap x) (@level rmap ag_rmap z) *)
unfold age in H. rewrite <- ageN1 in H.
(* Goal: ge (@level rmap ag_rmap x) (@level rmap ag_rmap y) *)
(* Goal: ge (@level rmap ag_rmap x) (@level rmap ag_rmap x) *)
(* Goal: ge (@level rmap ag_rmap x) (@level rmap ag_rmap z) *)
change rmap with R.rmap; change ag_rmap with R.ag_rmap.
(* Goal: ge (@level rmap ag_rmap x) (@level rmap ag_rmap y) *)
(* Goal: ge (@level rmap ag_rmap x) (@level rmap ag_rmap x) *)
(* Goal: ge (@level rmap ag_rmap x) (@level rmap ag_rmap z) *)
rewrite (ageN_level _ _ _ H). generalize (@level _ R.ag_rmap y). intros; omega.
(* Goal: ge (@level rmap ag_rmap x) (@level rmap ag_rmap z) *)
omega.
(* Goal: ge (@level rmap ag_rmap x) (@level rmap ag_rmap z) *)
omega.
Qed.

Lemma HO_pred_eq_i1:
  forall A P P' m,
      approx (level m) oo  P = approx (level m) oo P' ->
    (|> HO_pred_eq A P A  P') m.
Proof.
(* Goal: forall (id : positive) (ty : type), iff (@eq (option type) (@PTree.get type id (make_tycontext_v (@nil (prod ident type)))) (@Some type ty)) (@ex block (fun v : block => @eq (option (prod block type)) (@Map.get (prod block type) (make_venv empty_env) id) (@Some (prod block type) (@pair block type v ty)))) *)
intros.
unfold HO_pred_eq.
intros ?m ?.
(* Goal: @app_pred rmap ag_rmap (pureat (SomeP (SpecTT A) (@packPQ A a a0)) (FUN f0 cc0) (@pair block Z b Z0)) (@proj1_sig rmap (fun phi : rmap => and (@eq nat (@level rmap ag_rmap phi) n) (and (@eq (forall _ : AV.address, resource) (resource_at phi) (@initial_world.initial_core' function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n)) (@eq ghost (ghost_of phi) (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) NoneP)) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds))))))) (make_rmap (@initial_world.initial_core' function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) NoneP)) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)))) n (initial_world.initial_core_ext_obligation_1 function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) (@eq_refl ghost (ghost_fmap (approx n) (approx n) (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) NoneP)) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)))))))) *)
hnf.
exists (refl_equal A).
(* Goal: forall (id : positive) (ty : type), iff (@eq (option type) (@PTree.get type id (make_tycontext_v (@nil (prod ident type)))) (@Some type ty)) (@ex block (fun v : block => @eq (option (prod block type)) (@Map.get (prod block type) (make_venv empty_env) id) (@Some (prod block type) (@pair block type v ty)))) *)
intros.
generalize (f_equal (fun f => f x) H); clear H; intro.
(* Goal: @In (prod ident (globdef (Ctypes.fundef function) type)) (@pair ident (globdef (Ctypes.fundef function) type) id (@Gfun (Ctypes.fundef function) type f)) (@cons (prod ident (globdef (Ctypes.fundef function) type)) (@pair ident (globdef (Ctypes.fundef function) type) i (@Gfun (Ctypes.fundef function) type f0)) l) *)
(* Goal: @In (prod ident (globdef (Ctypes.fundef function) type)) (@pair ident (globdef (Ctypes.fundef function) type) id (@Gfun (Ctypes.fundef function) type f)) (@cons (prod ident (globdef (Ctypes.fundef function) type)) (@pair ident (globdef (Ctypes.fundef function) type) i (@Gvar (Ctypes.fundef function) type v)) l) *)
simpl in H0.
unfold compose in *.
apply clos_trans_t1n in H0.
(* Goal: forall (id : positive) (ty : type), iff (@eq (option type) (@PTree.get type id (make_tycontext_v (@nil (prod ident type)))) (@Some type ty)) (@ex block (fun v : block => @eq (option (prod block type)) (@Map.get (prod block type) (make_venv empty_env) id) (@Some (prod block type) (@pair block type v ty)))) *)
revert H; induction H0; intros.
2 : { apply IHclos_trans_1n.
      unfold age,age1 in H. unfold ag_nat in H. unfold natAge1 in H. destruct x0; inv H.
(* Goal: False *)
(* Goal: @eq (option type) (@Some type t0) (@Some type t) *)
      clear - H1.
      assert (forall w, app_pred (approx (level (S y)) (P x)) w <-> app_pred (approx (level (S y)) (P' x)) w).
(* Goal: @ex val (fun v : val => and (@eq (option val) (if ident_eq i p then @Some val (@fst val type a) else @Map.get val (make_tenv (temp_bindings (Pos.add p xH) (@map (prod val type) val (@fst val type) typed_args))) i) (@Some val v)) (tc_val' ty v)) *)
      { intros; rewrite H1; intuition. }
      apply pred_ext; intros w ?; destruct (H w); simpl in *; intuition.
(* Goal: ge (@level rmap ag_rmap x) (@level rmap ag_rmap z) *)
      apply H0; auto. clear - H4.  unfold natLevel in *. omega.
(* Goal: ge (@level rmap ag_rmap x) (@level rmap ag_rmap z) *)
      apply H2; auto. clear - H4.  unfold natLevel in *. omega. }
unfold age,age1 in H. unfold ag_nat in H. unfold natAge1 in H. destruct x0; inv H.
intros z ?.
split; intros ? ? ?.
assert (app_pred (approx (level (S y)) (P x)) a').
(* Goal: forall _ : @ex block (fun v : block => @eq (option (prod block type)) (@Map.get (prod block type) (ve_of (construct_rho (filter_genv (globalenv prog)) empty_env (@PTree.set val xH (Vptr b Ptrofs.zero) (temp_bindings (xO xH) (@map (prod val type) val (@fst val type) typed_args))))) id) (@Some (prod block type) (@pair block type v ty))), @eq (option type) (@PTree.get type id (var_types (@Delta_types vs G C (@map (prod val type) type (@snd val type) typed_args)))) (@Some type ty) *)
simpl. split; auto. unfold natLevel.  apply necR_level in H1.
change compcert_rmaps.R.rmap with rmap in *.
change compcert_rmaps.R.ag_rmap with ag_rmap in *.
(* Goal: ge (@level rmap ag_rmap x) (@level rmap ag_rmap z) *)
omega.
rewrite H0 in H3.
simpl in H3. destruct H3; auto.
assert (app_pred (approx (level (S y)) (P' x)) a').
(* Goal: forall _ : @ex block (fun v : block => @eq (option (prod block type)) (@Map.get (prod block type) (ve_of (construct_rho (filter_genv (globalenv prog)) empty_env (@PTree.set val xH (Vptr b Ptrofs.zero) (temp_bindings (xO xH) (@map (prod val type) val (@fst val type) typed_args))))) id) (@Some (prod block type) (@pair block type v ty))), @eq (option type) (@PTree.get type id (var_types (@Delta_types vs G C (@map (prod val type) type (@snd val type) typed_args)))) (@Some type ty) *)
simpl. split; auto. unfold natLevel.  apply necR_level in H1.
change compcert_rmaps.R.rmap with rmap in *.
change compcert_rmaps.R.ag_rmap with ag_rmap in *.
(* Goal: ge (@level rmap ag_rmap x) (@level rmap ag_rmap z) *)
omega.
rewrite <- H0 in H3.
simpl in H3. destruct H3; auto.
Qed.

Lemma semax_func_cons_aux:
(* Goal: @ex val (fun v : val => and (@eq (option val) (if ident_eq i p then @Some val (@fst val type a) else @Map.get val (make_tenv (temp_bindings (Pos.add p xH) (@map (prod val type) val (@fst val type) typed_args))) i) (@Some val v)) (tc_val' ty v)) *)
  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.
Proof.
(* Goal: forall (id : positive) (ty : type), iff (@eq (option type) (@PTree.get type id (make_tycontext_v (@nil (prod ident type)))) (@Some type ty)) (@ex block (fun v : block => @eq (option (prod block type)) (@Map.get (prod block type) (make_venv empty_env) id) (@Some (prod block type) (@pair block type v ty)))) *)
intros until fs. intros H Hin Hmf; intros.
destruct H0 as [id' [NEP2 [NEQ2 [? ?]]]].
(* Goal: @In (prod ident (globdef (Ctypes.fundef function) type)) (@pair ident (globdef (Ctypes.fundef function) type) id (@Gfun (Ctypes.fundef function) type f)) (@cons (prod ident (globdef (Ctypes.fundef function) type)) (@pair ident (globdef (Ctypes.fundef function) type) i (@Gfun (Ctypes.fundef function) type f0)) l) *)
(* Goal: @In (prod ident (globdef (Ctypes.fundef function) type)) (@pair ident (globdef (Ctypes.fundef function) type) id (@Gfun (Ctypes.fundef function) type f)) (@cons (prod ident (globdef (Ctypes.fundef function) type)) (@pair ident (globdef (Ctypes.fundef function) type) i (@Gvar (Ctypes.fundef function) type v)) l) *)
simpl in H0.
(* Goal: @app_pred nat ag_nat (@prop nat ag_nat (claims ge (nofunc_tycontext V G') v fsig cc' A' P' Q')) n *)
destruct (eq_dec id id').
subst id'. rewrite PTree.gss in H0. inv H0.
apply inj_pair2 in H6. apply inj_pair2 in H7.
(* Goal: @In ident i (@map (prod ident (globvar type)) ident (@fst ident (globvar type)) vl) *)
(* Goal: iff (@eq (option type) (@PTree.get type id (make_tycontext_g vs (@cons (prod ident funspec) (@pair ident funspec i fspec) G0))) (@Some type t)) (or (@ex funspec (fun f : funspec => and (@In (prod positive funspec) (@pair positive funspec id f) (@cons (prod ident funspec) (@pair ident funspec i fspec) G0)) (@eq type t (type_of_funspec f)))) (@In (prod positive type) (@pair positive type id t) vs)) *)
subst.
(* Goal: and (@eq (option block) (@Some block loc') (@Some block loc')) (@ex funspec (fun fs : funspec => @eq (option funspec) (@PTree.get funspec i (make_tycontext_s G)) (@Some funspec fs))) *)
split; auto.
rewrite PTree.gso in H0 by auto.
(* Goal: @ex (Ctypes.fundef function) (fun _ : Ctypes.fundef function => False) *)
(* Goal: @ex (Ctypes.fundef function) (fun _ : Ctypes.fundef function => False) *)
(* Goal: @ex (Ctypes.fundef function) (fun f : Ctypes.fundef function => or (@eq (prod ident (Ctypes.fundef function)) a (@pair ident (Ctypes.fundef function) id f)) (@In (prod ident (Ctypes.fundef function)) (@pair ident (Ctypes.fundef function) id f) g)) *)
(* Goal: @ex (Ctypes.fundef function) (fun f : Ctypes.fundef function => or (@eq (prod ident (Ctypes.fundef function)) a (@pair ident (Ctypes.fundef function) id f)) (@In (prod ident (Ctypes.fundef function)) (@pair ident (Ctypes.fundef function) id f) g)) *)
elimtype False.
destruct H1 as [b' [? ?]].
symmetry in H2; inv H2.
assert (In id' (map (@fst _ _) G')).
clear - H0.
revert H0; induction G'; simpl; intros; auto.
(* Goal: iff (@eq (option type) (@PTree.get type id (@PTree.set type (@fst ident type (@pair ident type i t0)) (@snd ident type (@pair ident type i t0)) (@fold_right (PTree.t type) (prod ident type) (fun v : prod ident type => @PTree.set type (@fst ident type v) (@snd ident type v)) (PTree.empty type) vs))) (@Some type t)) (or (@eq (prod positive type) (@pair ident type i t0) (@pair positive type id t)) (@In (prod positive type) (@pair positive type id t) vs)) *)
rewrite PTree.gempty in H0; inv H0.
(* Goal: @In ident i (@map (prod ident (globvar type)) ident (@fst ident (globvar type)) vl) *)
(* Goal: iff (@eq (option type) (@PTree.get type id (make_tycontext_g vs (@cons (prod ident funspec) (@pair ident funspec i fspec) G0))) (@Some type t)) (or (@ex funspec (fun f : funspec => and (@In (prod positive funspec) (@pair positive funspec id f) (@cons (prod ident funspec) (@pair ident funspec i fspec) G0)) (@eq type t (type_of_funspec f)))) (@In (prod positive type) (@pair positive type id t) vs)) *)
destruct (eq_dec id' (fst a)). subst.
change (@ptree_set) with (@PTree.set) in H0.
(* Goal: @ex funspec (fun fs : funspec => @eq (option funspec) (@PTree.get funspec i (let (id, f) := a in @PTree.set funspec id f (make_tycontext_s G))) (@Some funspec fs)) *)
destruct a; simpl in *.
rewrite PTree.gss in H0 by auto. inv  H0.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
auto.
(* Goal: @ex funspec (fun fs : funspec => @eq (option funspec) (@PTree.get funspec i (let (id, f) := a in @PTree.set funspec id f (make_tycontext_s G))) (@Some funspec fs)) *)
destruct a; simpl in *.
destruct (eq_dec i id'). subst. rewrite PTree.gss in H0. auto.
rewrite PTree.gso in H0 by auto.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
right; apply IHG'; auto.
(* Goal: @app_pred nat ag_nat (@prop nat ag_nat (claims ge (nofunc_tycontext V G') v fsig cc' A' P' Q')) n *)
destruct (eq_dec id id').
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
2: apply (Genv.global_addresses_distinct psi n H H1); auto.
subst id'.
clear - Hin H2 Hmf.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
eapply match_fdecs_in in Hmf; eauto.
Qed.

Lemma semax_func_cons:
   forall
(* Goal: @ex val (fun v : val => and (@eq (option val) (if ident_eq i p then @Some val (@fst val type a) else @Map.get val (make_tenv (temp_bindings (Pos.add p xH) (@map (prod val type) val (@fst val type) typed_args))) i) (@Some val v)) (tc_val' ty v)) *)
         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').
Proof.
(* Goal: forall (fs : list (prod ident fundef)) (id : ident) (f : function) (cc : calling_convention) (A : TypeTree) (P Q : forall ts : list Type, _functor (dependent_type_functor_rec ts (AssertTT A)) mpred) (NEP : @super_non_expansive A P) (NEQ : @super_non_expansive A Q) (V : varspecs) (G G' : funspecs) (C : compspecs) (_ : @eq bool (andb (id_in_list id (@map (prod ident funspec) ident (@fst ident funspec) G)) (andb (negb (id_in_list id (@map (prod ident fundef) ident (@fst ident fundef) fs))) (semax_body_params_ok f))) true) (_ : @Forall (prod ident type) (fun it : prod ident type => @eq bool (complete_type (@cenv_cs C) (@snd ident type it)) true) (fn_vars f)) (_ : var_sizes_ok (@cenv_cs C) (fn_vars f)) (_ : @eq calling_convention (fn_callconv f) cc) (_ : @precondition_closed f A P) (_ : @semax_body V G C f (@pair ident funspec id (mk_funspec (fn_funsig f) cc A P Q NEP NEQ))) (_ : @semax_func V G C fs G'), @semax_func V G C (@cons (prod ident (Ctypes.fundef function)) (@pair ident (Ctypes.fundef function) id (@Internal function f)) fs) (@cons (prod ident funspec) (@pair ident funspec id (mk_funspec (fn_funsig f) cc A P Q NEP NEQ)) G') *)
intros until C.
(* Goal: forall (_ : @eq bool (andb (id_in_list id (@map (prod ident funspec) ident (@fst ident funspec) G)) (andb (negb (id_in_list id (@map (prod ident fundef) ident (@fst ident fundef) fs))) (semax_body_params_ok f))) true) (_ : @Forall (prod ident type) (fun it : prod ident type => @eq bool (complete_type (@cenv_cs C) (@snd ident type it)) true) (fn_vars f)) (_ : var_sizes_ok (@cenv_cs C) (fn_vars f)) (_ : @eq calling_convention (fn_callconv f) cc) (_ : @precondition_closed f A P) (_ : @semax_body V G C f (@pair ident funspec id (mk_funspec (fn_funsig f) cc A P Q NEP NEQ))) (_ : @semax_func V G C fs G'), @semax_func V G C (@cons (prod ident (Ctypes.fundef function)) (@pair ident (Ctypes.fundef function) id (@Internal function f)) fs) (@cons (prod ident funspec) (@pair ident funspec id (mk_funspec (fn_funsig f) cc A P Q NEP NEQ)) G') *)
intros H' COMPLETE Hvars Hcc Hpclos H3 [Hf' Hf].
(* Goal: @semax_func V G C (@cons (prod ident (Ctypes.fundef function)) (@pair ident (Ctypes.fundef function) id (@Internal function f)) fs) (@cons (prod ident funspec) (@pair ident funspec id (mk_funspec (fn_funsig f) cc A P Q NEP NEQ)) G') *)
apply andb_true_iff in H'.
(* Goal: @semax_func V G C (@cons (prod ident (Ctypes.fundef function)) (@pair ident (Ctypes.fundef function) id (@Internal function f)) fs) (@cons (prod ident funspec) (@pair ident funspec id (mk_funspec (fn_funsig f) cc A P Q NEP NEQ)) G') *)
destruct H' as [Hin H'].
(* Goal: @semax_func V G C (@cons (prod ident (Ctypes.fundef function)) (@pair ident (Ctypes.fundef function) id (@Internal function f)) fs) (@cons (prod ident funspec) (@pair ident funspec id (mk_funspec (fn_funsig f) cc A P Q NEP NEQ)) G') *)
apply andb_true_iff in H'.
(* Goal: @semax_func V G C (@cons (prod ident (Ctypes.fundef function)) (@pair ident (Ctypes.fundef function) id (@Internal function f)) fs) (@cons (prod ident funspec) (@pair ident funspec id (mk_funspec (fn_funsig f) cc A P Q NEP NEQ)) G') *)
destruct H' as [Hni H].
(* Goal: and (var_sizes_ok (genv_cenv ge) (fn_vars f)) (and (@eq funsig fsig (fn_funsig f)) (@eq calling_convention (fn_callconv f) cc')) *)
(* Goal: @app_pred nat ag_nat (@allp nat ag_nat (list Type) (fun ts : list Type => @allp nat ag_nat (_functor (dependent_type_functor_rec ts A') (@pred rmap ag_rmap)) (fun x : _functor (dependent_type_functor_rec ts A') (@pred rmap ag_rmap) => @box nat ag_nat (@laterM nat ag_nat) (@semax' C Espec (func_tycontext' f (nofunc_tycontext V G)) (fun rho : environ => @andp rmap ag_rmap (@sepcon rmap Join_rmap Perm_rmap ag_rmap Age_rmap (bind_args (fn_params f) (fn_vars f) (P' ts x) rho) (stackframe_of' (genv_cenv ge) f rho)) (funassert (func_tycontext' f (nofunc_tycontext V G)) rho)) (Ssequence (fn_body f) (Sreturn (@None expr))) (frame_ret_assert (function_body_ret_assert (fn_return f) (Q' ts x)) (stackframe_of' (genv_cenv ge) f)))))) n *)
split.
(* Goal: forall _ : @ex block (fun v : block => @eq (option (prod block type)) (@Map.get (prod block type) (ve_of (construct_rho (filter_genv (globalenv prog)) empty_env (@PTree.set val xH (Vptr b Ptrofs.zero) (temp_bindings (xO xH) (@map (prod val type) val (@fst val type) typed_args))))) id) (@Some (prod block type) (@pair block type v ty))), @eq (option type) (@PTree.get type id (var_types (@Delta_types vs G C (@map (prod val type) type (@snd val type) typed_args)))) (@Some type ty) *)
simpl. constructor 2; auto.
(* Goal: forall _ : @ex block (fun v : block => @eq (option (prod block type)) (@Map.get (prod block type) (ve_of (construct_rho (filter_genv (globalenv prog)) empty_env (@PTree.set val xH (Vptr b Ptrofs.zero) (temp_bindings (xO xH) (@map (prod val type) val (@fst val type) typed_args))))) id) (@Some (prod block type) (@pair block type v ty))), @eq (option type) (@PTree.get type id (var_types (@Delta_types vs G C (@map (prod val type) type (@snd val type) typed_args)))) (@Some type ty) *)
simpl.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
unfold type_of_function. f_equal. auto.
(* Goal: forall (ge : genv) (_ : prog_contains ge (@cons (prod ident (Ctypes.fundef function)) (@pair ident (Ctypes.fundef function) id (@Internal function f)) fs)) (_ : @eq composite_env (genv_cenv ge) (@cenv_cs C)) (n : nat), @app_pred nat ag_nat (@believe C Espec (nofunc_tycontext V G) ge (nofunc_tycontext V (@cons (prod ident funspec) (@pair ident funspec id (mk_funspec (fn_funsig f) cc A P Q NEP NEQ)) G'))) n *)
intros ge H0 HGG n.
(* Goal: @app_pred nat ag_nat (@believe C Espec (nofunc_tycontext V G) ge (nofunc_tycontext V (@cons (prod ident funspec) (@pair ident funspec id (mk_funspec (fn_funsig f) cc A P Q NEP NEQ)) G'))) n *)
assert (prog_contains ge fs).
(* Goal: prog_contains ge fs *)
(* Goal: @app_pred nat ag_nat (@believe C Espec (nofunc_tycontext V G) ge (nofunc_tycontext V (@cons (prod ident funspec) (@pair ident funspec id (mk_funspec (fn_funsig f) cc A P Q NEP NEQ)) G'))) n *)
unfold prog_contains in *.
(* Goal: forall (id : positive) (ty : type), iff (@eq (option type) (@PTree.get type id (make_tycontext_v (@nil (prod ident type)))) (@Some type ty)) (@ex block (fun v : block => @eq (option (prod block type)) (@Map.get (prod block type) (make_venv empty_env) id) (@Some (prod block type) (@pair block type v ty)))) *)
intros.
(* Goal: @ex block (fun b : block => and (@eq (option block) (@Genv.find_symbol fundef type (genv_genv ge) id0) (@Some block b)) (@eq (option fundef) (@Genv.find_funct_ptr fundef type (genv_genv ge) b) (@Some fundef f0))) *)
(* Goal: @app_pred nat ag_nat (@believe C Espec (nofunc_tycontext V G) ge (nofunc_tycontext V (@cons (prod ident funspec) (@pair ident funspec id (mk_funspec (fn_funsig f) cc A P Q NEP NEQ)) G'))) n *)
apply H0.
(* Goal: forall _ : @ex block (fun v : block => @eq (option (prod block type)) (@Map.get (prod block type) (ve_of (construct_rho (filter_genv (globalenv prog)) empty_env (@PTree.set val xH (Vptr b Ptrofs.zero) (temp_bindings (xO xH) (@map (prod val type) val (@fst val type) typed_args))))) id) (@Some (prod block type) (@pair block type v ty))), @eq (option type) (@PTree.get type id (var_types (@Delta_types vs G C (@map (prod val type) type (@snd val type) typed_args)))) (@Some type ty) *)
simpl.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
auto.
(* Goal: @app_pred nat ag_nat (@believe C Espec (nofunc_tycontext V G) ge (nofunc_tycontext V (@cons (prod ident funspec) (@pair ident funspec id (mk_funspec (fn_funsig f) cc A P Q NEP NEQ)) G'))) n *)
specialize (Hf ge H1 HGG).
(* Goal: @eq (option type) (@Some type t0) (@Some type t) *)
clear H1.
(* Goal: @app_pred nat ag_nat (@believe C Espec (nofunc_tycontext V G) ge (nofunc_tycontext V (@cons (prod ident funspec) (@pair ident funspec id (mk_funspec (fn_funsig f) cc A P Q NEP NEQ)) G'))) n *)
hnf in Hf|-*.
(* Goal: forall b : val, @app_pred nat ag_nat (@allp nat ag_nat funsig (fun fsig : funsig => @allp nat ag_nat calling_convention (fun cc0 : calling_convention => @allp nat ag_nat TypeTree (fun A0 : TypeTree => @allp nat ag_nat (forall ts : list Type, _functor (dependent_type_functor_rec ts (AssertTT A0)) (@pred rmap ag_rmap)) (fun P0 : forall ts : list Type, _functor (dependent_type_functor_rec ts (AssertTT A0)) (@pred rmap ag_rmap) => @allp nat ag_nat (forall ts : list Type, _functor (dependent_type_functor_rec ts (AssertTT A0)) (@pred rmap ag_rmap)) (fun Q0 : forall ts : list Type, _functor (dependent_type_functor_rec ts (AssertTT A0)) (@pred rmap ag_rmap) => @imp nat ag_nat (@prop nat ag_nat (claims ge (nofunc_tycontext V (@cons (prod ident funspec) (@pair ident funspec id (mk_funspec (fn_funsig f) cc A P Q NEP NEQ)) G')) b fsig cc0 A0 P0 Q0)) (@orp nat ag_nat (believe_external Espec ge b fsig cc0 A0 P0 Q0) (@believe_internal C Espec ge (nofunc_tycontext V G) b fsig cc0 A0 P0 Q0)))))))) n *)
intros v fsig cc' A' P' Q'.
(* Goal: @app_pred nat ag_nat (@imp nat ag_nat (@prop nat ag_nat (claims ge (nofunc_tycontext V (@cons (prod ident funspec) (@pair ident funspec id (mk_funspec (fn_funsig f) cc A P Q NEP NEQ)) G')) v fsig cc' A' P' Q')) (@orp nat ag_nat (believe_external Espec ge v fsig cc' A' P' Q') (@believe_internal C Espec ge (nofunc_tycontext V G) v fsig cc' A' P' Q'))) n *)
apply derives_imp.
(* Goal: @derives nat ag_nat (@prop nat ag_nat (claims ge (nofunc_tycontext V (@cons (prod ident funspec) (@pair ident funspec id (mk_funspec (fn_funsig f) cc A P Q NEP NEQ)) G')) v fsig cc' A' P' Q')) (@orp nat ag_nat (believe_external Espec ge v fsig cc' A' P' Q') (@believe_internal C Espec ge (nofunc_tycontext V G) v fsig cc' A' P' Q')) *)
clear n.
(* Goal: @derives nat ag_nat (@prop nat ag_nat (claims ge (nofunc_tycontext V (@cons (prod ident funspec) (@pair ident funspec id (mk_funspec (fn_funsig f) cc A P Q NEP NEQ)) G')) v fsig cc' A' P' Q')) (@orp nat ag_nat (believe_external Espec ge v fsig cc' A' P' Q') (@believe_internal C Espec ge (nofunc_tycontext V G) v fsig cc' A' P' Q')) *)
intros n ?.
(* Goal: @app_pred nat ag_nat (@orp nat ag_nat (believe_external Espec ge v fsig cc' A' P' Q') (@believe_internal C Espec ge (nofunc_tycontext V G) v fsig cc' A' P' Q')) n *)
subst cc.
(* Goal: @app_pred nat ag_nat (@orp nat ag_nat (believe_external Espec ge v fsig cc' A' P' Q') (@believe_internal C Espec ge (nofunc_tycontext V G) v fsig cc' A' P' Q')) n *)
specialize (H0 id (Internal f)).
(* Goal: @app_pred nat ag_nat (@orp nat ag_nat (believe_external Espec ge v fsig cc' A' P' Q') (@believe_internal C Espec ge (nofunc_tycontext V G) v fsig cc' A' P' Q')) n *)
destruct H0 as [b [? ?]]; [left; auto |].
(* Goal: @app_pred nat ag_nat (@orp nat ag_nat (believe_external Espec ge v fsig cc' A' P' Q') (@believe_internal C Espec ge (nofunc_tycontext V G) v fsig cc' A' P' Q')) n *)
rewrite <- Genv.find_funct_find_funct_ptr in H2.
(* Goal: @app_pred nat ag_nat (@orp nat ag_nat (believe_external Espec ge v fsig cc' A' P' Q') (@believe_internal C Espec ge (nofunc_tycontext V G) v fsig cc' A' P' Q')) n *)
apply negb_true_iff in Hni.
(* Goal: @app_pred nat ag_nat (@orp nat ag_nat (believe_external Espec ge v fsig cc' A' P' Q') (@believe_internal C Espec ge (nofunc_tycontext V G) v fsig cc' A' P' Q')) n *)
apply id_in_list_false in Hni.
destruct (eq_dec  (Vptr b Ptrofs.zero) v) as [?H|?H].
* (* Vptr b Ptrofs.zero = v *)
(* Goal: @app_pred nat ag_nat (@orp nat ag_nat (believe_external Espec ge v fsig cc' A' P' Q') (@believe_internal C Espec ge (nofunc_tycontext V G) v fsig cc' A' P' Q')) n *)
subst v.
(* Goal: @In ident i (@map (prod ident (globdef fundef type)) ident (@fst ident (globdef fundef type)) (@cons (prod ident (globdef fundef type)) (@pair ident (globdef fundef type) i0 (@Gvar fundef type v)) l)) *)
(* Goal: @list_disjoint ident (@map (prod ident fundef) ident (@fst ident fundef) (@prog_funct' fundef type l)) (@cons ident i (@map (prod ident (globvar type)) ident (@fst ident (globvar type)) (@prog_vars' fundef type l))) *)
right.
(* Goal: @app_pred nat ag_nat (@believe_internal C Espec ge (nofunc_tycontext V G) (Vptr b Ptrofs.zero) fsig cc' A' P' Q') n *)
exists b; exists f.
(* Goal: and (@eq (option block) (@Some block loc') (@Some block loc')) (@ex funspec (fun fs : funspec => @eq (option funspec) (@PTree.get funspec i (make_tycontext_s G)) (@Some funspec fs))) *)
split; auto.
(* Goal: @app_pred nat ag_nat (@prop nat ag_nat (and (@eq val (Vptr b Ptrofs.zero) (Vptr b Ptrofs.zero)) (and (@eq (option fundef) (@Genv.find_funct_ptr fundef type (genv_genv ge) b) (@Some (Ctypes.fundef function) (@Internal function f))) (and (@Forall (prod ident type) (fun it : prod ident type => @eq bool (complete_type (genv_cenv ge) (@snd ident type it)) true) (fn_vars f)) (and (@list_norepet ident (@app ident (@map (prod ident type) ident (@fst ident type) (fn_params f)) (@map (prod ident type) ident (@fst ident type) (fn_temps f)))) (and (@list_norepet ident (@map (prod ident type) ident (@fst ident type) (fn_vars f))) (and (var_sizes_ok (genv_cenv ge) (fn_vars f)) (and (@eq funsig fsig (fn_funsig f)) (@eq calling_convention (fn_callconv f) cc'))))))))) n *)
(* Goal: @app_pred nat ag_nat (@allp nat ag_nat (list Type) (fun ts : list Type => @allp nat ag_nat (_functor (dependent_type_functor_rec ts A') (@pred rmap ag_rmap)) (fun x : _functor (dependent_type_functor_rec ts A') (@pred rmap ag_rmap) => @box nat ag_nat (@laterM nat ag_nat) (@semax' C Espec (func_tycontext' f (nofunc_tycontext V G)) (fun rho : environ => @andp rmap ag_rmap (@sepcon rmap Join_rmap Perm_rmap ag_rmap Age_rmap (bind_args (fn_params f) (fn_vars f) (P' ts x) rho) (stackframe_of' (genv_cenv ge) f rho)) (funassert (func_tycontext' f (nofunc_tycontext V G)) rho)) (Ssequence (fn_body f) (Sreturn (@None expr))) (frame_ret_assert (function_body_ret_assert (fn_return f) (Q' ts x)) (stackframe_of' (genv_cenv ge) f)))))) n *)
apply andb_true_iff in H.
(* Goal: @app_pred nat ag_nat (@prop nat ag_nat (and (@eq val (Vptr b Ptrofs.zero) (Vptr b Ptrofs.zero)) (and (@eq (option fundef) (@Genv.find_funct_ptr fundef type (genv_genv ge) b) (@Some (Ctypes.fundef function) (@Internal function f))) (and (@Forall (prod ident type) (fun it : prod ident type => @eq bool (complete_type (genv_cenv ge) (@snd ident type it)) true) (fn_vars f)) (and (@list_norepet ident (@app ident (@map (prod ident type) ident (@fst ident type) (fn_params f)) (@map (prod ident type) ident (@fst ident type) (fn_temps f)))) (and (@list_norepet ident (@map (prod ident type) ident (@fst ident type) (fn_vars f))) (and (var_sizes_ok (genv_cenv ge) (fn_vars f)) (and (@eq funsig fsig (fn_funsig f)) (@eq calling_convention (fn_callconv f) cc'))))))))) n *)
(* Goal: @app_pred nat ag_nat (@allp nat ag_nat (list Type) (fun ts : list Type => @allp nat ag_nat (_functor (dependent_type_functor_rec ts A') (@pred rmap ag_rmap)) (fun x : _functor (dependent_type_functor_rec ts A') (@pred rmap ag_rmap) => @box nat ag_nat (@laterM nat ag_nat) (@semax' C Espec (func_tycontext' f (nofunc_tycontext V G)) (fun rho : environ => @andp rmap ag_rmap (@sepcon rmap Join_rmap Perm_rmap ag_rmap Age_rmap (bind_args (fn_params f) (fn_vars f) (P' ts x) rho) (stackframe_of' (genv_cenv ge) f rho)) (funassert (func_tycontext' f (nofunc_tycontext V G)) rho)) (Ssequence (fn_body f) (Sreturn (@None expr))) (frame_ret_assert (function_body_ret_assert (fn_return f) (Q' ts x)) (stackframe_of' (genv_cenv ge) f)))))) n *)
destruct H as [H H'].
(* Goal: @app_pred nat ag_nat (@prop nat ag_nat (and (@eq val (Vptr b Ptrofs.zero) (Vptr b Ptrofs.zero)) (and (@eq (option fundef) (@Genv.find_funct_ptr fundef type (genv_genv ge) b) (@Some (Ctypes.fundef function) (@Internal function f))) (and (@Forall (prod ident type) (fun it : prod ident type => @eq bool (complete_type (genv_cenv ge) (@snd ident type it)) true) (fn_vars f)) (and (@list_norepet ident (@app ident (@map (prod ident type) ident (@fst ident type) (fn_params f)) (@map (prod ident type) ident (@fst ident type) (fn_temps f)))) (and (@list_norepet ident (@map (prod ident type) ident (@fst ident type) (fn_vars f))) (and (var_sizes_ok (genv_cenv ge) (fn_vars f)) (and (@eq funsig fsig (fn_funsig f)) (@eq calling_convention (fn_callconv f) cc'))))))))) n *)
(* Goal: @app_pred nat ag_nat (@allp nat ag_nat (list Type) (fun ts : list Type => @allp nat ag_nat (_functor (dependent_type_functor_rec ts A') (@pred rmap ag_rmap)) (fun x : _functor (dependent_type_functor_rec ts A') (@pred rmap ag_rmap) => @box nat ag_nat (@laterM nat ag_nat) (@semax' C Espec (func_tycontext' f (nofunc_tycontext V G)) (fun rho : environ => @andp rmap ag_rmap (@sepcon rmap Join_rmap Perm_rmap ag_rmap Age_rmap (bind_args (fn_params f) (fn_vars f) (P' ts x) rho) (stackframe_of' (genv_cenv ge) f rho)) (funassert (func_tycontext' f (nofunc_tycontext V G)) rho)) (Ssequence (fn_body f) (Sreturn (@None expr))) (frame_ret_assert (function_body_ret_assert (fn_return f) (Q' ts x)) (stackframe_of' (genv_cenv ge) f)))))) n *)
apply compute_list_norepet_e in H.
(* Goal: @app_pred nat ag_nat (@prop nat ag_nat (and (@eq val (Vptr b Ptrofs.zero) (Vptr b Ptrofs.zero)) (and (@eq (option fundef) (@Genv.find_funct_ptr fundef type (genv_genv ge) b) (@Some (Ctypes.fundef function) (@Internal function f))) (and (@Forall (prod ident type) (fun it : prod ident type => @eq bool (complete_type (genv_cenv ge) (@snd ident type it)) true) (fn_vars f)) (and (@list_norepet ident (@app ident (@map (prod ident type) ident (@fst ident type) (fn_params f)) (@map (prod ident type) ident (@fst ident type) (fn_temps f)))) (and (@list_norepet ident (@map (prod ident type) ident (@fst ident type) (fn_vars f))) (and (var_sizes_ok (genv_cenv ge) (fn_vars f)) (and (@eq funsig fsig (fn_funsig f)) (@eq calling_convention (fn_callconv f) cc'))))))))) n *)
(* Goal: @app_pred nat ag_nat (@allp nat ag_nat (list Type) (fun ts : list Type => @allp nat ag_nat (_functor (dependent_type_functor_rec ts A') (@pred rmap ag_rmap)) (fun x : _functor (dependent_type_functor_rec ts A') (@pred rmap ag_rmap) => @box nat ag_nat (@laterM nat ag_nat) (@semax' C Espec (func_tycontext' f (nofunc_tycontext V G)) (fun rho : environ => @andp rmap ag_rmap (@sepcon rmap Join_rmap Perm_rmap ag_rmap Age_rmap (bind_args (fn_params f) (fn_vars f) (P' ts x) rho) (stackframe_of' (genv_cenv ge) f rho)) (funassert (func_tycontext' f (nofunc_tycontext V G)) rho)) (Ssequence (fn_body f) (Sreturn (@None expr))) (frame_ret_assert (function_body_ret_assert (fn_return f) (Q' ts x)) (stackframe_of' (genv_cenv ge) f)))))) n *)
apply compute_list_norepet_e in H'.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
split3; auto.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
rewrite Genv.find_funct_find_funct_ptr in H2; auto.
(* Goal: and (@eq (option block) (@Some block loc') (@Some block loc')) (@ex funspec (fun fs : funspec => @eq (option funspec) (@PTree.get funspec i (make_tycontext_s G)) (@Some funspec fs))) *)
split; auto.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
rewrite HGG; auto.
(* Goal: and (@eq (option block) (@Some block loc') (@Some block loc')) (@ex funspec (fun fs : funspec => @eq (option funspec) (@PTree.get funspec i (make_tycontext_s G)) (@Some funspec fs))) *)
split; auto.
(* Goal: and (@eq (option block) (@Some block loc') (@Some block loc')) (@ex funspec (fun fs : funspec => @eq (option funspec) (@PTree.get funspec i (make_tycontext_s G)) (@Some funspec fs))) *)
split; auto.
(* Goal: and (var_sizes_ok (genv_cenv ge) (fn_vars f)) (and (@eq funsig fsig (fn_funsig f)) (@eq calling_convention (fn_callconv f) cc')) *)
(* Goal: @app_pred nat ag_nat (@allp nat ag_nat (list Type) (fun ts : list Type => @allp nat ag_nat (_functor (dependent_type_functor_rec ts A') (@pred rmap ag_rmap)) (fun x : _functor (dependent_type_functor_rec ts A') (@pred rmap ag_rmap) => @box nat ag_nat (@laterM nat ag_nat) (@semax' C Espec (func_tycontext' f (nofunc_tycontext V G)) (fun rho : environ => @andp rmap ag_rmap (@sepcon rmap Join_rmap Perm_rmap ag_rmap Age_rmap (bind_args (fn_params f) (fn_vars f) (P' ts x) rho) (stackframe_of' (genv_cenv ge) f rho)) (funassert (func_tycontext' f (nofunc_tycontext V G)) rho)) (Ssequence (fn_body f) (Sreturn (@None expr))) (frame_ret_assert (function_body_ret_assert (fn_return f) (Q' ts x)) (stackframe_of' (genv_cenv ge) f)))))) n *)
split.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
rewrite HGG; auto.
(* Goal: and (@eq (option block) (@Some block loc') (@Some block loc')) (@ex funspec (fun fs : funspec => @eq (option funspec) (@PTree.get funspec i (make_tycontext_s G)) (@Some funspec fs))) *)
(* split; auto.*)
(* Goal: and (@eq funsig fsig (fn_funsig f)) (@eq calling_convention (fn_callconv f) cc') *)
(* Goal: @app_pred nat ag_nat (@allp nat ag_nat (list Type) (fun ts : list Type => @allp nat ag_nat (_functor (dependent_type_functor_rec ts A') (@pred rmap ag_rmap)) (fun x : _functor (dependent_type_functor_rec ts A') (@pred rmap ag_rmap) => @box nat ag_nat (@laterM nat ag_nat) (@semax' C Espec (func_tycontext' f (nofunc_tycontext V G)) (fun rho : environ => @andp rmap ag_rmap (@sepcon rmap Join_rmap Perm_rmap ag_rmap Age_rmap (bind_args (fn_params f) (fn_vars f) (P' ts x) rho) (stackframe_of' (genv_cenv ge) f rho)) (funassert (func_tycontext' f (nofunc_tycontext V G)) rho)) (Ssequence (fn_body f) (Sreturn (@None expr))) (frame_ret_assert (function_body_ret_assert (fn_return f) (Q' ts x)) (stackframe_of' (genv_cenv ge) f)))))) n *)
destruct H1 as [id' [NEP' [NEQ' [? [b' [? ?]]]]]].
(* Goal: and (@eq funsig fsig (fn_funsig f)) (@eq calling_convention (fn_callconv f) cc') *)
(* Goal: @app_pred nat ag_nat (@allp nat ag_nat (list Type) (fun ts : list Type => @allp nat ag_nat (_functor (dependent_type_functor_rec ts A') (@pred rmap ag_rmap)) (fun x : _functor (dependent_type_functor_rec ts A') (@pred rmap ag_rmap) => @box nat ag_nat (@laterM nat ag_nat) (@semax' C Espec (func_tycontext' f (nofunc_tycontext V G)) (fun rho : environ => @andp rmap ag_rmap (@sepcon rmap Join_rmap Perm_rmap ag_rmap Age_rmap (bind_args (fn_params f) (fn_vars f) (P' ts x) rho) (stackframe_of' (genv_cenv ge) f rho)) (funassert (func_tycontext' f (nofunc_tycontext V G)) rho)) (Ssequence (fn_body f) (Sreturn (@None expr))) (frame_ret_assert (function_body_ret_assert (fn_return f) (Q' ts x)) (stackframe_of' (genv_cenv ge) f)))))) n *)
symmetry in H5; inv H5.
(* Goal: @app_pred nat ag_nat (@prop nat ag_nat (claims ge (nofunc_tycontext V G') v fsig cc' A' P' Q')) n *)
destruct (eq_dec id id').
(* Goal: @In ident i (@map (prod ident (globvar type)) ident (@fst ident (globvar type)) vl) *)
(* Goal: iff (@eq (option type) (@PTree.get type id (make_tycontext_g vs (@cons (prod ident funspec) (@pair ident funspec i fspec) G0))) (@Some type t)) (or (@ex funspec (fun f : funspec => and (@In (prod positive funspec) (@pair positive funspec id f) (@cons (prod ident funspec) (@pair ident funspec i fspec) G0)) (@eq type t (type_of_funspec f)))) (@In (prod positive type) (@pair positive type id t) vs)) *)
subst.
(* Goal: @In (prod ident funspec) (@pair ident funspec id (mk_funspec f0 cc0 A a a0 P_ne Q_ne)) G *)
simpl in H1.
(* Goal: @app_pred nat ag_nat (@prop nat ag_nat (claims ge (nofunc_tycontext V G') v fsig cc' A' P' Q')) n *)
(* Goal: @app_pred nat ag_nat (@prop nat ag_nat (claims ge (nofunc_tycontext V G') v fsig cc' A' P' Q')) n *)
rewrite PTree.gss in H1.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
inv H1; auto.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
contradiction (Genv.global_addresses_distinct ge n0 H0 H4); auto.
(*destruct H. *)
(* Goal: @app_pred nat ag_nat (@allp nat ag_nat (list Type) (fun ts : list Type => @allp nat ag_nat (_functor (dependent_type_functor_rec ts A') (@pred rmap ag_rmap)) (fun x : _functor (dependent_type_functor_rec ts A') (@pred rmap ag_rmap) => @box nat ag_nat (@laterM nat ag_nat) (@semax' C Espec (func_tycontext' f (nofunc_tycontext V G)) (fun rho : environ => @andp rmap ag_rmap (@sepcon rmap Join_rmap Perm_rmap ag_rmap Age_rmap (bind_args (fn_params f) (fn_vars f) (P' ts x) rho) (stackframe_of' (genv_cenv ge) f rho)) (funassert (func_tycontext' f (nofunc_tycontext V G)) rho)) (Ssequence (fn_body f) (Sreturn (@None expr))) (frame_ret_assert (function_body_ret_assert (fn_return f) (Q' ts x)) (stackframe_of' (genv_cenv ge) f)))))) n *)
intros ts x.
(* Goal: @In (prod ident funspec) (@pair ident funspec id (mk_funspec f0 cc0 A a a0 P_ne Q_ne)) G *)
simpl in H1.
(* Goal: @app_pred nat ag_nat (@box nat ag_nat (@laterM nat ag_nat) (@semax' C Espec (func_tycontext' f (nofunc_tycontext V G)) (fun rho : environ => @andp rmap ag_rmap (@sepcon rmap Join_rmap Perm_rmap ag_rmap Age_rmap (bind_args (fn_params f) (fn_vars f) (P' ts x) rho) (stackframe_of' (genv_cenv ge) f rho)) (funassert (func_tycontext' f (nofunc_tycontext V G)) rho)) (Ssequence (fn_body f) (Sreturn (@None expr))) (frame_ret_assert (function_body_ret_assert (fn_return f) (Q' ts x)) (stackframe_of' (genv_cenv ge) f)))) n *)
pose proof (semax_func_cons_aux ge _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ H0 Hni Hf' H1).
(* Goal: @app_pred nat ag_nat (@box nat ag_nat (@laterM nat ag_nat) (@semax' C Espec (func_tycontext' f (nofunc_tycontext V G)) (fun rho : environ => @andp rmap ag_rmap (@sepcon rmap Join_rmap Perm_rmap ag_rmap Age_rmap (bind_args (fn_params f) (fn_vars f) (P' ts x) rho) (stackframe_of' (genv_cenv ge) f rho)) (funassert (func_tycontext' f (nofunc_tycontext V G)) rho)) (Ssequence (fn_body f) (Sreturn (@None expr))) (frame_ret_assert (function_body_ret_assert (fn_return f) (Q' ts x)) (stackframe_of' (genv_cenv ge) f)))) n *)
destruct H4 as [H4' [H4 [H4a [H4b H4c]]]].
(* Goal: @app_pred nat ag_nat (@box nat ag_nat (@laterM nat ag_nat) (@semax' C Espec (func_tycontext' f (nofunc_tycontext V G)) (fun rho : environ => @andp rmap ag_rmap (@sepcon rmap Join_rmap Perm_rmap ag_rmap Age_rmap (bind_args (fn_params f) (fn_vars f) (P' ts x) rho) (stackframe_of' (genv_cenv ge) f rho)) (funassert (func_tycontext' f (nofunc_tycontext V G)) rho)) (Ssequence (fn_body f) (Sreturn (@None expr))) (frame_ret_assert (function_body_ret_assert (fn_return f) (Q' ts x)) (stackframe_of' (genv_cenv ge) f)))) n *)
subst A' fsig cc'.
(* Goal: @app_pred nat ag_nat (@box nat ag_nat (@laterM nat ag_nat) (@semax' C Espec (func_tycontext' f (nofunc_tycontext V G)) (fun rho : environ => @andp rmap ag_rmap (@sepcon rmap Join_rmap Perm_rmap ag_rmap Age_rmap (bind_args (fn_params f) (fn_vars f) (P' ts x) rho) (stackframe_of' (genv_cenv ge) f rho)) (funassert (func_tycontext' f (nofunc_tycontext V G)) rho)) (Ssequence (fn_body f) (Sreturn (@None expr))) (frame_ret_assert (function_body_ret_assert (fn_return f) (Q' ts x)) (stackframe_of' (genv_cenv ge) f)))) n *)
apply JMeq_eq in H4b.
(* Goal: @app_pred nat ag_nat (@box nat ag_nat (@laterM nat ag_nat) (@semax' C Espec (func_tycontext' f (nofunc_tycontext V G)) (fun rho : environ => @andp rmap ag_rmap (@sepcon rmap Join_rmap Perm_rmap ag_rmap Age_rmap (bind_args (fn_params f) (fn_vars f) (P' ts x) rho) (stackframe_of' (genv_cenv ge) f rho)) (funassert (func_tycontext' f (nofunc_tycontext V G)) rho)) (Ssequence (fn_body f) (Sreturn (@None expr))) (frame_ret_assert (function_body_ret_assert (fn_return f) (Q' ts x)) (stackframe_of' (genv_cenv ge) f)))) n *)
apply JMeq_eq in H4c.
(* Goal: @app_pred nat ag_nat (@box nat ag_nat (@laterM nat ag_nat) (@semax' C Espec (func_tycontext' f (nofunc_tycontext V G)) (fun rho : environ => @andp rmap ag_rmap (@sepcon rmap Join_rmap Perm_rmap ag_rmap Age_rmap (bind_args (fn_params f) (fn_vars f) (P' ts x) rho) (stackframe_of' (genv_cenv ge) f rho)) (funassert (func_tycontext' f (nofunc_tycontext V G)) rho)) (Ssequence (fn_body f) (Sreturn (@None expr))) (frame_ret_assert (function_body_ret_assert (fn_return f) (Q' ts x)) (stackframe_of' (genv_cenv ge) f)))) n *)
subst P' Q'.
(* Goal: @app_pred nat ag_nat (@box nat ag_nat (@laterM nat ag_nat) (@semax' C Espec (func_tycontext' f (nofunc_tycontext V G)) (fun rho : environ => @andp rmap ag_rmap (@sepcon rmap Join_rmap Perm_rmap ag_rmap Age_rmap (bind_args (fn_params f) (fn_vars f) (P ts x) rho) (stackframe_of' (genv_cenv ge) f rho)) (funassert (func_tycontext' f (nofunc_tycontext V G)) rho)) (Ssequence (fn_body f) (Sreturn (@None expr))) (frame_ret_assert (function_body_ret_assert (fn_return f) (Q ts x)) (stackframe_of' (genv_cenv ge) f)))) n *)
specialize (H3 Espec ts x). 
rename H3 into H4. (* destruct H3 as [Ann H4].*)
(* Goal: @app_pred nat ag_nat (@box nat ag_nat (@laterM nat ag_nat) (@semax' C Espec (func_tycontext' f (nofunc_tycontext V G)) (fun rho : environ => @andp rmap ag_rmap (@sepcon rmap Join_rmap Perm_rmap ag_rmap Age_rmap (bind_args (fn_params f) (fn_vars f) (P ts x) rho) (stackframe_of' (genv_cenv ge) f rho)) (funassert (func_tycontext' f (nofunc_tycontext V G)) rho)) (Ssequence (fn_body f) (Sreturn (@None expr))) (frame_ret_assert (function_body_ret_assert (fn_return f) (Q ts x)) (stackframe_of' (genv_cenv ge) f)))) n *)
pose proof I.
(* Goal: @app_pred nat ag_nat (@box nat ag_nat (@laterM nat ag_nat) (@semax' C Espec (func_tycontext' f (nofunc_tycontext V G)) (fun rho : environ => @andp rmap ag_rmap (@sepcon rmap Join_rmap Perm_rmap ag_rmap Age_rmap (bind_args (fn_params f) (fn_vars f) (P ts x) rho) (stackframe_of' (genv_cenv ge) f rho)) (funassert (func_tycontext' f (nofunc_tycontext V G)) rho)) (Ssequence (fn_body f) (Sreturn (@None expr))) (frame_ret_assert (function_body_ret_assert (fn_return f) (Q ts x)) (stackframe_of' (genv_cenv ge) f)))) n *)
specialize (H4 n).
(* Goal: @app_pred nat ag_nat (@box nat ag_nat (@laterM nat ag_nat) (@semax' C Espec (func_tycontext' f (nofunc_tycontext V G)) (fun rho : environ => @andp rmap ag_rmap (@sepcon rmap Join_rmap Perm_rmap ag_rmap Age_rmap (bind_args (fn_params f) (fn_vars f) (P ts x) rho) (stackframe_of' (genv_cenv ge) f rho)) (funassert (func_tycontext' f (nofunc_tycontext V G)) rho)) (Ssequence (fn_body f) (Sreturn (@None expr))) (frame_ret_assert (function_body_ret_assert (fn_return f) (Q ts x)) (stackframe_of' (genv_cenv ge) f)))) n *)
apply now_later.
(* Goal: @app_pred nat ag_nat (@semax' C Espec (func_tycontext' f (nofunc_tycontext V G)) (fun rho : environ => @andp rmap ag_rmap (@sepcon rmap Join_rmap Perm_rmap ag_rmap Age_rmap (bind_args (fn_params f) (fn_vars f) (P ts x) rho) (stackframe_of' (genv_cenv ge) f rho)) (funassert (func_tycontext' f (nofunc_tycontext V G)) rho)) (Ssequence (fn_body f) (Sreturn (@None expr))) (frame_ret_assert (function_body_ret_assert (fn_return f) (Q ts x)) (stackframe_of' (genv_cenv ge) f))) n *)
rewrite HGG.
(* Goal: @app_pred nat ag_nat (@semax' C Espec (func_tycontext' f (nofunc_tycontext V G)) (fun rho : environ => @andp rmap ag_rmap (@sepcon rmap Join_rmap Perm_rmap ag_rmap Age_rmap (bind_args (fn_params f) (fn_vars f) (P ts x) rho) (stackframe_of' (@cenv_cs C) f rho)) (funassert (func_tycontext' f (nofunc_tycontext V G)) rho)) (Ssequence (fn_body f) (Sreturn (@None expr))) (frame_ret_assert (function_body_ret_assert (fn_return f) (Q ts x)) (stackframe_of' (@cenv_cs C) f))) n *)
clear - Hpclos H4.
rewrite semax_fold_unfold in H4|-*.
(* Goal: @app_pred nat ag_nat (@allp nat ag_nat genv (fun gx : genv => @allp nat ag_nat tycontext (fun Delta' : tycontext => @imp nat ag_nat (@prop nat ag_nat (and (tycontext_sub (func_tycontext' f (nofunc_tycontext V G)) Delta') (@eq composite_env (genv_cenv gx) (@cenv_cs C)))) (@imp nat ag_nat (@believe C Espec Delta' gx Delta') (@allp nat ag_nat cont (fun k : cont => @allp nat ag_nat assert (fun F : assert => @imp nat ag_nat (@andp nat ag_nat (@prop nat ag_nat (closed_wrt_modvars (Ssequence (fn_body f) (Sreturn (@None expr))) F)) (rguard Espec gx Delta' (frame_ret_assert (frame_ret_assert (function_body_ret_assert (fn_return f) (Q ts x)) (stackframe_of' (@cenv_cs C) f)) F) k)) (guard Espec gx Delta' (fun rho : environ => @sepcon rmap Join_rmap Perm_rmap ag_rmap Age_rmap (F rho) (@andp rmap ag_rmap (@sepcon rmap Join_rmap Perm_rmap ag_rmap Age_rmap (bind_args (fn_params f) (fn_vars f) (P ts x) rho) (stackframe_of' (@cenv_cs C) f rho)) (funassert (func_tycontext' f (nofunc_tycontext V G)) rho))) (@cons cont' (Kseq (Ssequence (fn_body f) (Sreturn (@None expr)))) k))))))))) n *)
revert n H4.
(* Goal: forall (n : nat) (_ : @app_pred nat ag_nat (@allp nat ag_nat genv (fun gx : genv => @allp nat ag_nat tycontext (fun Delta' : tycontext => @imp nat ag_nat (@prop nat ag_nat (and (tycontext_sub (func_tycontext f V G (@nil (prod ident Annotation))) Delta') (@eq composite_env (genv_cenv gx) (@cenv_cs C)))) (@imp nat ag_nat (@believe C Espec Delta' gx Delta') (@allp nat ag_nat cont (fun k : cont => @allp nat ag_nat assert (fun F : assert => @imp nat ag_nat (@andp nat ag_nat (@prop nat ag_nat (closed_wrt_modvars (Ssequence (fn_body f) (Sreturn (@None expr))) F)) (rguard Espec gx Delta' (frame_ret_assert (frame_ret_assert (function_body_ret_assert (fn_return f) (Q ts x)) (@stackframe_of C f)) F) k)) (guard Espec gx Delta' (fun rho : environ => @sepcon rmap Join_rmap Perm_rmap ag_rmap Age_rmap (F rho) (@sepcon rmap Join_rmap Perm_rmap ag_rmap Age_rmap (P ts x rho) (@stackframe_of C f rho))) (@cons cont' (Kseq (Ssequence (fn_body f) (Sreturn (@None expr)))) k))))))))) n), @app_pred nat ag_nat (@allp nat ag_nat genv (fun gx : genv => @allp nat ag_nat tycontext (fun Delta' : tycontext => @imp nat ag_nat (@prop nat ag_nat (and (tycontext_sub (func_tycontext' f (nofunc_tycontext V G)) Delta') (@eq composite_env (genv_cenv gx) (@cenv_cs C)))) (@imp nat ag_nat (@believe C Espec Delta' gx Delta') (@allp nat ag_nat cont (fun k : cont => @allp nat ag_nat assert (fun F : assert => @imp nat ag_nat (@andp nat ag_nat (@prop nat ag_nat (closed_wrt_modvars (Ssequence (fn_body f) (Sreturn (@None expr))) F)) (rguard Espec gx Delta' (frame_ret_assert (frame_ret_assert (function_body_ret_assert (fn_return f) (Q ts x)) (stackframe_of' (@cenv_cs C) f)) F) k)) (guard Espec gx Delta' (fun rho : environ => @sepcon rmap Join_rmap Perm_rmap ag_rmap Age_rmap (F rho) (@andp rmap ag_rmap (@sepcon rmap Join_rmap Perm_rmap ag_rmap Age_rmap (bind_args (fn_params f) (fn_vars f) (P ts x) rho) (stackframe_of' (@cenv_cs C) f rho)) (funassert (func_tycontext' f (nofunc_tycontext V G)) rho))) (@cons cont' (Kseq (Ssequence (fn_body f) (Sreturn (@None expr)))) k))))))))) n *)
apply allp_derives; intro gx.
(* Goal: @derives nat ag_nat (@allp nat ag_nat tycontext (fun Delta' : tycontext => @imp nat ag_nat (@prop nat ag_nat (and (tycontext_sub (func_tycontext f V G (@nil (prod ident Annotation))) Delta') (@eq composite_env (genv_cenv gx) (@cenv_cs C)))) (@imp nat ag_nat (@believe C Espec Delta' gx Delta') (@allp nat ag_nat cont (fun k : cont => @allp nat ag_nat assert (fun F : assert => @imp nat ag_nat (@andp nat ag_nat (@prop nat ag_nat (closed_wrt_modvars (Ssequence (fn_body f) (Sreturn (@None expr))) F)) (rguard Espec gx Delta' (frame_ret_assert (frame_ret_assert (function_body_ret_assert (fn_return f) (Q ts x)) (@stackframe_of C f)) F) k)) (guard Espec gx Delta' (fun rho : environ => @sepcon rmap Join_rmap Perm_rmap ag_rmap Age_rmap (F rho) (@sepcon rmap Join_rmap Perm_rmap ag_rmap Age_rmap (P ts x rho) (@stackframe_of C f rho))) (@cons cont' (Kseq (Ssequence (fn_body f) (Sreturn (@None expr)))) k)))))))) (@allp nat ag_nat tycontext (fun Delta' : tycontext => @imp nat ag_nat (@prop nat ag_nat (and (tycontext_sub (func_tycontext' f (nofunc_tycontext V G)) Delta') (@eq composite_env (genv_cenv gx) (@cenv_cs C)))) (@imp nat ag_nat (@believe C Espec Delta' gx Delta') (@allp nat ag_nat cont (fun k : cont => @allp nat ag_nat assert (fun F : assert => @imp nat ag_nat (@andp nat ag_nat (@prop nat ag_nat (closed_wrt_modvars (Ssequence (fn_body f) (Sreturn (@None expr))) F)) (rguard Espec gx Delta' (frame_ret_assert (frame_ret_assert (function_body_ret_assert (fn_return f) (Q ts x)) (stackframe_of' (@cenv_cs C) f)) F) k)) (guard Espec gx Delta' (fun rho : environ => @sepcon rmap Join_rmap Perm_rmap ag_rmap Age_rmap (F rho) (@andp rmap ag_rmap (@sepcon rmap Join_rmap Perm_rmap ag_rmap Age_rmap (bind_args (fn_params f) (fn_vars f) (P ts x) rho) (stackframe_of' (@cenv_cs C) f rho)) (funassert (func_tycontext' f (nofunc_tycontext V G)) rho))) (@cons cont' (Kseq (Ssequence (fn_body f) (Sreturn (@None expr)))) k)))))))) *)
apply allp_derives; intro Delta'.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
apply imp_derives; auto.
(* Goal: @ex val (fun v : val => and (@eq (option val) (if ident_eq i p then @Some val (@fst val type a) else @Map.get val (make_tenv (temp_bindings (Pos.add p xH) (@map (prod val type) val (@fst val type) typed_args))) i) (@Some val v)) (tc_val' ty v)) *)
(*{ unfold func_tycontext, func_tycontext'. simpl.
  apply prop_derives. intros [AA BB]; split; trivial.
  eapply tycontext_sub_trans. 2: eassumption.
(* Goal: forall _ : @ex block (fun v : block => @eq (option (prod block type)) (@Map.get (prod block type) (ve_of (construct_rho (filter_genv (globalenv prog)) empty_env (@PTree.set val xH (Vptr b Ptrofs.zero) (temp_bindings (xO xH) (@map (prod val type) val (@fst val type) typed_args))))) id) (@Some (prod block type) (@pair block type v ty))), @eq (option type) (@PTree.get type id (var_types (@Delta_types vs G C (@map (prod val type) type (@snd val type) typed_args)))) (@Some type ty) *)
  unfold make_tycontext; simpl.
(* Goal: forall (id : positive) (ty : type), iff (@eq (option type) (@PTree.get type id (make_tycontext_v (@nil (prod ident type)))) (@Some type ty)) (@ex block (fun v : block => @eq (option (prod block type)) (@Map.get (prod block type) (make_venv empty_env) id) (@Some (prod block type) (@pair block type v ty)))) *)
  repeat split; simpl; intros.
  + destruct ((make_tycontext_t (fn_params f) (fn_temps f)) ! id ); trivial.
(* Goal: iff (@eq (option type) (@PTree.get type id (@PTree.set type (@fst ident type p) (@snd ident type p) (@fold_right (PTree.t type) (prod ident type) (fun v : prod ident type => @PTree.set type (@fst ident type v) (@snd ident type v)) (PTree.empty type) vs))) (@Some type t)) (or (@eq (prod positive type) p (@pair positive type id t)) (@In (prod positive type) (@pair positive type id t) vs)) *)
    destruct p. rewrite orb_comm, orb_negb_r; split; trivial.
  + apply sub_option_refl.
  + apply sub_option_refl.
  + rewrite PTree.gempty.
(* Goal: forall _ : @ex block (fun v : block => @eq (option (prod block type)) (@Map.get (prod block type) (ve_of (construct_rho (filter_genv (globalenv prog)) empty_env (@PTree.set val xH (Vptr b Ptrofs.zero) (temp_bindings (xO xH) (@map (prod val type) val (@fst val type) typed_args))))) id) (@Some (prod block type) (@pair block type v ty))), @eq (option type) (@PTree.get type id (var_types (@Delta_types vs G C (@map (prod val type) type (@snd val type) typed_args)))) (@Some type ty) *)
    unfold Annotation_sub; simpl. destruct (PTree.get id (make_tycontext_a Ann)); trivial. destruct a; trivial.
} *)
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
apply imp_derives; auto.
(* Goal: @derives nat ag_nat (@allp nat ag_nat cont (fun k : cont => @allp nat ag_nat assert (fun F : assert => @imp nat ag_nat (@andp nat ag_nat (@prop nat ag_nat (closed_wrt_modvars (Ssequence (fn_body f) (Sreturn (@None expr))) F)) (rguard Espec gx Delta' (frame_ret_assert (frame_ret_assert (function_body_ret_assert (fn_return f) (Q ts x)) (@stackframe_of C f)) F) k)) (guard Espec gx Delta' (fun rho : environ => @sepcon rmap Join_rmap Perm_rmap ag_rmap Age_rmap (F rho) (@sepcon rmap Join_rmap Perm_rmap ag_rmap Age_rmap (P ts x rho) (@stackframe_of C f rho))) (@cons cont' (Kseq (Ssequence (fn_body f) (Sreturn (@None expr)))) k))))) (@allp nat ag_nat cont (fun k : cont => @allp nat ag_nat assert (fun F : assert => @imp nat ag_nat (@andp nat ag_nat (@prop nat ag_nat (closed_wrt_modvars (Ssequence (fn_body f) (Sreturn (@None expr))) F)) (rguard Espec gx Delta' (frame_ret_assert (frame_ret_assert (function_body_ret_assert (fn_return f) (Q ts x)) (stackframe_of' (@cenv_cs C) f)) F) k)) (guard Espec gx Delta' (fun rho : environ => @sepcon rmap Join_rmap Perm_rmap ag_rmap Age_rmap (F rho) (@andp rmap ag_rmap (@sepcon rmap Join_rmap Perm_rmap ag_rmap Age_rmap (bind_args (fn_params f) (fn_vars f) (P ts x) rho) (stackframe_of' (@cenv_cs C) f rho)) (funassert (func_tycontext' f (nofunc_tycontext V G)) rho))) (@cons cont' (Kseq (Ssequence (fn_body f) (Sreturn (@None expr)))) k))))) *)
apply allp_derives; intro k.
(* Goal: @derives nat ag_nat (@allp nat ag_nat assert (fun F : assert => @imp nat ag_nat (@andp nat ag_nat (@prop nat ag_nat (closed_wrt_modvars (Ssequence (fn_body f) (Sreturn (@None expr))) F)) (rguard Espec gx Delta' (frame_ret_assert (frame_ret_assert (function_body_ret_assert (fn_return f) (Q ts x)) (@stackframe_of C f)) F) k)) (guard Espec gx Delta' (fun rho : environ => @sepcon rmap Join_rmap Perm_rmap ag_rmap Age_rmap (F rho) (@sepcon rmap Join_rmap Perm_rmap ag_rmap Age_rmap (P ts x rho) (@stackframe_of C f rho))) (@cons cont' (Kseq (Ssequence (fn_body f) (Sreturn (@None expr)))) k)))) (@allp nat ag_nat assert (fun F : assert => @imp nat ag_nat (@andp nat ag_nat (@prop nat ag_nat (closed_wrt_modvars (Ssequence (fn_body f) (Sreturn (@None expr))) F)) (rguard Espec gx Delta' (frame_ret_assert (frame_ret_assert (function_body_ret_assert (fn_return f) (Q ts x)) (stackframe_of' (@cenv_cs C) f)) F) k)) (guard Espec gx Delta' (fun rho : environ => @sepcon rmap Join_rmap Perm_rmap ag_rmap Age_rmap (F rho) (@andp rmap ag_rmap (@sepcon rmap Join_rmap Perm_rmap ag_rmap Age_rmap (bind_args (fn_params f) (fn_vars f) (P ts x) rho) (stackframe_of' (@cenv_cs C) f rho)) (funassert (func_tycontext' f (nofunc_tycontext V G)) rho))) (@cons cont' (Kseq (Ssequence (fn_body f) (Sreturn (@None expr)))) k)))) *)
apply allp_derives; intro F.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
apply imp_derives; auto.
(* Goal: @derives nat ag_nat (guard Espec gx Delta' (fun rho : environ => @sepcon rmap Join_rmap Perm_rmap ag_rmap Age_rmap (F rho) (@sepcon rmap Join_rmap Perm_rmap ag_rmap Age_rmap (P ts x rho) (@stackframe_of C f rho))) (@cons cont' (Kseq (Ssequence (fn_body f) (Sreturn (@None expr)))) k)) (guard Espec gx Delta' (fun rho : environ => @sepcon rmap Join_rmap Perm_rmap ag_rmap Age_rmap (F rho) (@andp rmap ag_rmap (@sepcon rmap Join_rmap Perm_rmap ag_rmap Age_rmap (bind_args (fn_params f) (fn_vars f) (P ts x) rho) (stackframe_of' (@cenv_cs C) f rho)) (funassert (func_tycontext' f (nofunc_tycontext V G)) rho))) (@cons cont' (Kseq (Ssequence (fn_body f) (Sreturn (@None expr)))) k)) *)
unfold guard.
(* Goal: @derives nat ag_nat (_guard Espec gx Delta' (fun rho : environ => @sepcon rmap Join_rmap Perm_rmap ag_rmap Age_rmap (F rho) (@sepcon rmap Join_rmap Perm_rmap ag_rmap Age_rmap (P ts x rho) (@stackframe_of C f rho))) (current_function (@cons cont' (Kseq (Ssequence (fn_body f) (Sreturn (@None expr)))) k)) (@cons cont' (Kseq (Ssequence (fn_body f) (Sreturn (@None expr)))) k)) (_guard Espec gx Delta' (fun rho : environ => @sepcon rmap Join_rmap Perm_rmap ag_rmap Age_rmap (F rho) (@andp rmap ag_rmap (@sepcon rmap Join_rmap Perm_rmap ag_rmap Age_rmap (bind_args (fn_params f) (fn_vars f) (P ts x) rho) (stackframe_of' (@cenv_cs C) f rho)) (funassert (func_tycontext' f (nofunc_tycontext V G)) rho))) (current_function (@cons cont' (Kseq (Ssequence (fn_body f) (Sreturn (@None expr)))) k)) (@cons cont' (Kseq (Ssequence (fn_body f) (Sreturn (@None expr)))) k)) *)
apply allp_derives; intro tx.
(* Goal: @derives nat ag_nat (@allp nat ag_nat env (fun vx : env => let rho := construct_rho (filter_genv gx) vx tx in @fash rmap ag_rmap (@imp rmap ag_rmap (@andp rmap ag_rmap (@andp rmap ag_rmap (@prop rmap ag_rmap (guard_environ Delta' (current_function (@cons cont' (Kseq (Ssequence (fn_body f) (Sreturn (@None expr)))) k)) rho)) (@sepcon rmap Join_rmap Perm_rmap ag_rmap Age_rmap (F rho) (@sepcon rmap Join_rmap Perm_rmap ag_rmap Age_rmap (P ts x rho) (@stackframe_of C f rho)))) (funassert Delta' rho)) (assert_safe Espec gx vx tx (@cons cont' (Kseq (Ssequence (fn_body f) (Sreturn (@None expr)))) k) rho)))) (@allp nat ag_nat env (fun vx : env => let rho := construct_rho (filter_genv gx) vx tx in @fash rmap ag_rmap (@imp rmap ag_rmap (@andp rmap ag_rmap (@andp rmap ag_rmap (@prop rmap ag_rmap (guard_environ Delta' (current_function (@cons cont' (Kseq (Ssequence (fn_body f) (Sreturn (@None expr)))) k)) rho)) (@sepcon rmap Join_rmap Perm_rmap ag_rmap Age_rmap (F rho) (@andp rmap ag_rmap (@sepcon rmap Join_rmap Perm_rmap ag_rmap Age_rmap (bind_args (fn_params f) (fn_vars f) (P ts x) rho) (stackframe_of' (@cenv_cs C) f rho)) (funassert (func_tycontext' f (nofunc_tycontext V G)) rho)))) (funassert Delta' rho)) (assert_safe Espec gx vx tx (@cons cont' (Kseq (Ssequence (fn_body f) (Sreturn (@None expr)))) k) rho)))) *)
eapply allp_derives; intro vx.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
eapply subp_derives; auto.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
apply andp_derives; auto.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
apply andp_derives; auto.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
apply sepcon_derives; auto.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
apply andp_left1; auto.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
apply sepcon_derives; auto.
(* Goal: @derives rmap ag_rmap (bind_args (fn_params f) (fn_vars f) (P ts x) (construct_rho (filter_genv gx) vx tx)) (P ts x (construct_rho (filter_genv gx) vx tx)) *)
unfold bind_args.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
apply andp_left2; auto.
(* Goal: @derives rmap ag_rmap (close_precondition (fn_params f) (fn_vars f) (P ts x) (construct_rho (filter_genv gx) vx tx)) (P ts x (construct_rho (filter_genv gx) vx tx)) *)
destruct (Hpclos ts x).
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
apply close_precondition_e; auto.
* (***   Vptr b Ptrofs.zero <> v'  ********)
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
apply (Hf n v fsig cc' A' P' Q'); auto.
(* Goal: @app_pred nat ag_nat (@prop nat ag_nat (claims ge (nofunc_tycontext V G') v fsig cc' A' P' Q')) n *)
destruct H1 as [id' [NEP' [NEQ' [? ?]]]].
(* Goal: @In (prod ident funspec) (@pair ident funspec id (mk_funspec f0 cc0 A a a0 P_ne Q_ne)) G *)
simpl in H1.
(* Goal: @app_pred nat ag_nat (@prop nat ag_nat (claims ge (nofunc_tycontext V G') v fsig cc' A' P' Q')) n *)
destruct (eq_dec id id').
(* Goal: @In ident i (@map (prod ident (globvar type)) ident (@fst ident (globvar type)) vl) *)
(* Goal: iff (@eq (option type) (@PTree.get type id (make_tycontext_g vs (@cons (prod ident funspec) (@pair ident funspec i fspec) G0))) (@Some type t)) (or (@ex funspec (fun f : funspec => and (@In (prod positive funspec) (@pair positive funspec id f) (@cons (prod ident funspec) (@pair ident funspec i fspec) G0)) (@eq type t (type_of_funspec f)))) (@In (prod positive type) (@pair positive type id t) vs)) *)
subst. rewrite PTree.gss in H1.
(* Goal: @app_pred nat ag_nat (@prop nat ag_nat (claims ge (nofunc_tycontext V G') v fsig cc' A' P' Q')) n *)
(* Goal: @app_pred nat ag_nat (@prop nat ag_nat (claims ge (nofunc_tycontext V G') v fsig cc' A' P' Q')) n *)
destruct H5 as [? [? ?]]. congruence.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
rewrite PTree.gso in H1 by auto.
(* Goal: and (@eq (option block) (@Some block loc') (@Some block loc')) (@ex funspec (fun fs : funspec => @eq (option funspec) (@PTree.get funspec i (make_tycontext_s G)) (@Some funspec fs))) *)
exists id', NEP', NEQ'; split; auto.
Qed.

(* EXPERIMENT
Lemma semax_func_skip:
   forall
(* Goal: @ex val (fun v : val => and (@eq (option val) (if ident_eq i p then @Some val (@fst val type a) else @Map.get val (make_tenv (temp_bindings (Pos.add p xH) (@map (prod val type) val (@fst val type) typed_args))) i) (@Some val v)) (tc_val' ty v)) *)
        V (G: funspecs) {C: compspecs} fs idf (G': funspecs),
      semax_func V G fs G' ->
      semax_func V G (idf::fs) G'.
Proof.
(* Goal: forall (id : positive) (ty : type), iff (@eq (option type) (@PTree.get type id (make_tycontext_v (@nil (prod ident type)))) (@Some type ty)) (@ex block (fun v : block => @eq (option (prod block type)) (@Map.get (prod block type) (make_venv empty_env) id) (@Some (prod block type) (@pair block type v ty)))) *)
 intros.
 hnf in H|-*.
(* Goal: and (var_sizes_ok (genv_cenv ge) (fn_vars f)) (and (@eq funsig fsig (fn_funsig f)) (@eq calling_convention (fn_callconv f) cc')) *)
(* Goal: @app_pred nat ag_nat (@allp nat ag_nat (list Type) (fun ts : list Type => @allp nat ag_nat (_functor (dependent_type_functor_rec ts A') (@pred rmap ag_rmap)) (fun x : _functor (dependent_type_functor_rec ts A') (@pred rmap ag_rmap) => @box nat ag_nat (@laterM nat ag_nat) (@semax' C Espec (func_tycontext' f (nofunc_tycontext V G)) (fun rho : environ => @andp rmap ag_rmap (@sepcon rmap Join_rmap Perm_rmap ag_rmap Age_rmap (bind_args (fn_params f) (fn_vars f) (P' ts x) rho) (stackframe_of' (genv_cenv ge) f rho)) (funassert (func_tycontext' f (nofunc_tycontext V G)) rho)) (Ssequence (fn_body f) (Sreturn (@None expr))) (frame_ret_assert (function_body_ret_assert (fn_return f) (Q' ts x)) (stackframe_of' (genv_cenv ge) f)))))) n *)
 destruct H; split.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
 constructor 3. auto.
(* Goal: forall (id : positive) (ty : type), iff (@eq (option type) (@PTree.get type id (make_tycontext_v (@nil (prod ident type)))) (@Some type ty)) (@ex block (fun v : block => @eq (option (prod block type)) (@Map.get (prod block type) (make_venv empty_env) id) (@Some (prod block type) (@pair block type v ty)))) *)
 intros.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
 eapply H0; eauto.
 hnf in H1|-*.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
 intros; eapply H1; eauto.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
 right; auto.
Qed.
*)

Lemma semax_external_FF:
 forall Espec ids ef A n,
  @semax_external Espec ids ef A (fun _ _ _ => FF) (fun _ _ _ => FF) n.
(* Goal: forall (id : positive) (ty : type), iff (@eq (option type) (@PTree.get type id (make_tycontext_v (@nil (prod ident type)))) (@Some type ty)) (@ex block (fun v : block => @eq (option (prod block type)) (@Map.get (prod block type) (make_venv empty_env) id) (@Some (prod block type) (@pair block type v ty)))) *)
intros.
(* Goal: forall (id : positive) (ty : type), iff (@eq (option type) (@PTree.get type id (make_tycontext_v (@nil (prod ident type)))) (@Some type ty)) (@ex block (fun v : block => @eq (option (prod block type)) (@Map.get (prod block type) (make_venv empty_env) id) (@Some (prod block type) (@pair block type v ty)))) *)
hnf; intros.
(* Goal: forall _ : @ex block (fun v : block => @eq (option (prod block type)) (@Map.get (prod block type) (ve_of (construct_rho (filter_genv (globalenv prog)) empty_env (@PTree.set val xH (Vptr b Ptrofs.zero) (temp_bindings (xO xH) (@map (prod val type) val (@fst val type) typed_args))))) id) (@Some (prod block type) (@pair block type v ty))), @eq (option type) (@PTree.get type id (var_types (@Delta_types vs G C (@map (prod val type) type (@snd val type) typed_args)))) (@Some type ty) *)
simpl.
(* Goal: forall (id : positive) (ty : type), iff (@eq (option type) (@PTree.get type id (make_tycontext_v (@nil (prod ident type)))) (@Some type ty)) (@ex block (fun v : block => @eq (option (prod block type)) (@Map.get (prod block type) (make_venv empty_env) id) (@Some (prod block type) (@pair block type v ty)))) *)
intros.
(* Goal: @ex (@ext_spec_type juicy_mem external_function (@OK_ty Espec0) (JE_spec (@OK_ty Espec0) (@OK_spec Espec0)) ef) (fun b0 : @ext_spec_type juicy_mem external_function (@OK_ty Espec0) (JE_spec (@OK_ty Espec0) (@OK_spec Espec0)) ef => and (forall (b1 : @OK_ty Espec0) (a' : juicy_mem) (_ : @necR juicy_mem juicy_mem_ageable a'0 a') (_ : @joins ghost ghost_join (ghost_of (m_phi a')) (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ref (@OK_ty Espec0) b1) NoneP)) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds))))), @ext_spec_pre juicy_mem external_function (@OK_ty Espec0) (JE_spec (@OK_ty Espec0) (@OK_spec Espec0)) ef b0 (@genv_symb_injective fundef type (genv_genv b)) b3 b4 b1 a') (forall (b1 : option typ) (b3 : option val) (b4 : @OK_ty Espec0) (y : juicy_mem) (_ : ge (@level rmap ag_rmap (m_phi a'0)) (@level rmap ag_rmap (m_phi y))) (a' : juicy_mem) (_ : @necR juicy_mem juicy_mem_ageable y a') (_ : @ext_spec_post juicy_mem external_function (@OK_ty Espec0) (JE_spec (@OK_ty Espec0) (@OK_spec Espec0)) ef b0 (@genv_symb_injective fundef type (genv_genv b)) b1 b3 b4 a'), @ex rmap (fun y0 : rmap => @ex rmap (fun z : rmap => and (@join rmap Join_rmap y0 z (m_phi a')) (and False (@app_pred rmap ag_rmap b2 z)))))) *)
destruct H2 as [? [? [? [? [? ?]]]]].
(* Goal: @eq (option type) (@None type) (@Some type t) *)
contradiction.
Qed.

Lemma semax_func_cons_ext:
(* Goal: @ex val (fun v : val => and (@eq (option val) (if ident_eq i p then @Some val (@fst val type a) else @Map.get val (make_tenv (temp_bindings (Pos.add p xH) (@map (prod val type) val (@fst val type) typed_args))) i) (@Some val v)) (tc_val' ty v)) *)
   forall (V: varspecs) (G: funspecs) {C: compspecs} fs id ef argsig retsig A P Q NEP NEQ
          argsig'
          (G': funspecs) cc (ids: list ident),
      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) ->
      (forall gx ts x (ret : option val),
         (Q ts x (make_ext_rval gx ret)
            && !!has_opttyp ret (opttyp_of_type retsig)
            |-- !!tc_option_val retsig ret)) ->
      (forall n, semax_external Espec ids ef A P Q n) ->
      semax_func V G fs G' ->
      semax_func V G ((id, External ef argsig retsig cc)::fs)
           ((id, mk_funspec (argsig', retsig) cc A P Q NEP NEQ)  :: G').
Proof.
intros until ids.
intros Hids Hargsig Hef Hni Hlen Hretty H [Hf' Hf].
rewrite Hargsig in *.  clear Hids Hargsig argsig'.
(* Goal: @app_pred nat ag_nat (@orp nat ag_nat (believe_external Espec ge v fsig cc' A' P' Q') (@believe_internal C Espec ge (nofunc_tycontext V G) v fsig cc' A' P' Q')) n *)
apply id_in_list_false in Hni.
(* Goal: and (var_sizes_ok (genv_cenv ge) (fn_vars f)) (and (@eq funsig fsig (fn_funsig f)) (@eq calling_convention (fn_callconv f) cc')) *)
(* Goal: @app_pred nat ag_nat (@allp nat ag_nat (list Type) (fun ts : list Type => @allp nat ag_nat (_functor (dependent_type_functor_rec ts A') (@pred rmap ag_rmap)) (fun x : _functor (dependent_type_functor_rec ts A') (@pred rmap ag_rmap) => @box nat ag_nat (@laterM nat ag_nat) (@semax' C Espec (func_tycontext' f (nofunc_tycontext V G)) (fun rho : environ => @andp rmap ag_rmap (@sepcon rmap Join_rmap Perm_rmap ag_rmap Age_rmap (bind_args (fn_params f) (fn_vars f) (P' ts x) rho) (stackframe_of' (genv_cenv ge) f rho)) (funassert (func_tycontext' f (nofunc_tycontext V G)) rho)) (Ssequence (fn_body f) (Sreturn (@None expr))) (frame_ret_assert (function_body_ret_assert (fn_return f) (Q' ts x)) (stackframe_of' (genv_cenv ge) f)))))) n *)
split.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
hnf; simpl; f_equal; auto.
(* Goal: forall _ : @ex block (fun v : block => @eq (option (prod block type)) (@Map.get (prod block type) (ve_of (construct_rho (filter_genv (globalenv prog)) empty_env (@PTree.set val xH (Vptr b Ptrofs.zero) (temp_bindings (xO xH) (@map (prod val type) val (@fst val type) typed_args))))) id) (@Some (prod block type) (@pair block type v ty))), @eq (option type) (@PTree.get type id (var_types (@Delta_types vs G C (@map (prod val type) type (@snd val type) typed_args)))) (@Some type ty) *)
constructor 2. simpl.
(* Goal: @eq (option type) (@Some type (type_of_funspec fspec)) (@Some type t) *)
(* Goal: iff (@eq (option type) (@PTree.get type id (make_tycontext_g vs (@cons (prod ident funspec) (@pair ident funspec i fspec) G0))) (@Some type t)) (or (@ex funspec (fun f : funspec => and (@In (prod positive funspec) (@pair positive funspec id f) (@cons (prod ident funspec) (@pair ident funspec i fspec) G0)) (@eq type t (type_of_funspec f)))) (@In (prod positive type) (@pair positive type id t) vs)) *)
f_equal.
clear -Hlen.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
revert ids Hlen; induction argsig; simpl; intros; auto.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
destruct ids; auto.
(* Goal: forall _ : @ex block (fun v : block => @eq (option (prod block type)) (@Map.get (prod block type) (ve_of (construct_rho (filter_genv (globalenv prog)) empty_env (@PTree.set val xH (Vptr b Ptrofs.zero) (temp_bindings (xO xH) (@map (prod val type) val (@fst val type) typed_args))))) id) (@Some (prod block type) (@pair block type v ty))), @eq (option type) (@PTree.get type id (var_types (@Delta_types vs G C (@map (prod val type) type (@snd val type) typed_args)))) (@Some type ty) *)
destruct ids; auto. inv Hlen. simpl. f_equal; auto.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
auto.
(* Goal: forall (id : positive) (ty : type), iff (@eq (option type) (@PTree.get type id (make_tycontext_v (@nil (prod ident type)))) (@Some type ty)) (@ex block (fun v : block => @eq (option (prod block type)) (@Map.get (prod block type) (make_venv empty_env) id) (@Some (prod block type) (@pair block type v ty)))) *)
intros ge ? HGG; intros.
(* Goal: @app_pred nat ag_nat (@believe C Espec (nofunc_tycontext V G) ge (nofunc_tycontext V (@cons (prod ident funspec) (@pair ident funspec id (mk_funspec (fn_funsig f) cc A P Q NEP NEQ)) G'))) n *)
assert (prog_contains ge fs).
(* Goal: prog_contains ge fs *)
(* Goal: @app_pred nat ag_nat (@believe C Espec (nofunc_tycontext V G) ge (nofunc_tycontext V (@cons (prod ident funspec) (@pair ident funspec id (mk_funspec (fn_funsig f) cc A P Q NEP NEQ)) G'))) n *)
unfold prog_contains in *.
(* Goal: forall (id : positive) (ty : type), iff (@eq (option type) (@PTree.get type id (make_tycontext_v (@nil (prod ident type)))) (@Some type ty)) (@ex block (fun v : block => @eq (option (prod block type)) (@Map.get (prod block type) (make_venv empty_env) id) (@Some (prod block type) (@pair block type v ty)))) *)
intros.
(* Goal: @ex block (fun b : block => and (@eq (option block) (@Genv.find_symbol fundef type (genv_genv ge) id0) (@Some block b)) (@eq (option fundef) (@Genv.find_funct_ptr fundef type (genv_genv ge) b) (@Some fundef f0))) *)
(* Goal: @app_pred nat ag_nat (@believe C Espec (nofunc_tycontext V G) ge (nofunc_tycontext V (@cons (prod ident funspec) (@pair ident funspec id (mk_funspec (fn_funsig f) cc A P Q NEP NEQ)) G'))) n *)
apply H0.
(* Goal: forall _ : @ex block (fun v : block => @eq (option (prod block type)) (@Map.get (prod block type) (ve_of (construct_rho (filter_genv (globalenv prog)) empty_env (@PTree.set val xH (Vptr b Ptrofs.zero) (temp_bindings (xO xH) (@map (prod val type) val (@fst val type) typed_args))))) id) (@Some (prod block type) (@pair block type v ty))), @eq (option type) (@PTree.get type id (var_types (@Delta_types vs G C (@map (prod val type) type (@snd val type) typed_args)))) (@Some type ty) *)
simpl.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
auto.
(* Goal: @app_pred nat ag_nat (@believe C Espec (nofunc_tycontext V G) ge (nofunc_tycontext V (@cons (prod ident funspec) (@pair ident funspec id (mk_funspec (fn_funsig f) cc A P Q NEP NEQ)) G'))) n *)
specialize (Hf ge H1 HGG).
(* Goal: @eq (option type) (@Some type t0) (@Some type t) *)
clear H1.
unfold believe.
intros v' fsig' cc' A' P' Q'.
(* Goal: @app_pred nat ag_nat (@imp nat ag_nat (@prop nat ag_nat (claims ge (nofunc_tycontext V (@cons (prod ident funspec) (@pair ident funspec id (mk_funspec (fn_funsig f) cc A P Q NEP NEQ)) G')) v fsig cc' A' P' Q')) (@orp nat ag_nat (believe_external Espec ge v fsig cc' A' P' Q') (@believe_internal C Espec ge (nofunc_tycontext V G) v fsig cc' A' P' Q'))) n *)
apply derives_imp.
(* Goal: @derives nat ag_nat (@prop nat ag_nat (claims ge (nofunc_tycontext V (@cons (prod ident funspec) (@pair ident funspec id (mk_funspec (fn_funsig f) cc A P Q NEP NEQ)) G')) v fsig cc' A' P' Q')) (@orp nat ag_nat (believe_external Espec ge v fsig cc' A' P' Q') (@believe_internal C Espec ge (nofunc_tycontext V G) v fsig cc' A' P' Q')) *)
clear n.
(* Goal: @derives nat ag_nat (@prop nat ag_nat (claims ge (nofunc_tycontext V (@cons (prod ident funspec) (@pair ident funspec id (mk_funspec (fn_funsig f) cc A P Q NEP NEQ)) G')) v fsig cc' A' P' Q')) (@orp nat ag_nat (believe_external Espec ge v fsig cc' A' P' Q') (@believe_internal C Espec ge (nofunc_tycontext V G) v fsig cc' A' P' Q')) *)
intros n ?.
unfold prog_contains in H0.
generalize (H0 id (External ef argsig retsig cc)); clear H0; intro H0.
destruct H0 as [b [? ?]].
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
left; auto.
(* Goal: @app_pred nat ag_nat (@orp nat ag_nat (believe_external Espec ge v fsig cc' A' P' Q') (@believe_internal C Espec ge (nofunc_tycontext V G) v fsig cc' A' P' Q')) n *)
rewrite <- Genv.find_funct_find_funct_ptr in H2.
destruct (eq_dec  (Vptr b Ptrofs.zero) v') as [?H|?H].
subst v'.
(* Goal: @In (prod ident (globdef (Ctypes.fundef function) type)) (@pair ident (globdef (Ctypes.fundef function) type) id (@Gfun (Ctypes.fundef function) type f)) (@cons (prod ident (globdef (Ctypes.fundef function) type)) (@pair ident (globdef (Ctypes.fundef function) type) id (@Gfun (Ctypes.fundef function) type f)) l) *)
(* Goal: @In (prod ident (globdef (Ctypes.fundef function) type)) (@pair ident (globdef (Ctypes.fundef function) type) id (@Gfun (Ctypes.fundef function) type f)) (@cons (prod ident (globdef (Ctypes.fundef function) type)) (@pair ident (globdef (Ctypes.fundef function) type) i (@Gfun (Ctypes.fundef function) type f0)) l) *)
(* Goal: @In (prod ident (globdef (Ctypes.fundef function) type)) (@pair ident (globdef (Ctypes.fundef function) type) id (@Gfun (Ctypes.fundef function) type f)) (@cons (prod ident (globdef (Ctypes.fundef function) type)) (@pair ident (globdef (Ctypes.fundef function) type) i (@Gvar (Ctypes.fundef function) type v)) l) *)
left.
specialize (H n).
(* Goal: @app_pred nat ag_nat (@box nat ag_nat (@laterM nat ag_nat) (@semax' C Espec (func_tycontext' f (nofunc_tycontext V G)) (fun rho : environ => @andp rmap ag_rmap (@sepcon rmap Join_rmap Perm_rmap ag_rmap Age_rmap (bind_args (fn_params f) (fn_vars f) (P' ts x) rho) (stackframe_of' (genv_cenv ge) f rho)) (funassert (func_tycontext' f (nofunc_tycontext V G)) rho)) (Ssequence (fn_body f) (Sreturn (@None expr))) (frame_ret_assert (function_body_ret_assert (fn_return f) (Q' ts x)) (stackframe_of' (genv_cenv ge) f)))) n *)
pose proof (semax_func_cons_aux ge _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ H0 Hni Hf' H1).
destruct H3 as [H4' [H4'' [H4 [H4b H4c]]]].
subst A' fsig' cc'.
(* Goal: @app_pred nat ag_nat (@box nat ag_nat (@laterM nat ag_nat) (@semax' C Espec (func_tycontext' f (nofunc_tycontext V G)) (fun rho : environ => @andp rmap ag_rmap (@sepcon rmap Join_rmap Perm_rmap ag_rmap Age_rmap (bind_args (fn_params f) (fn_vars f) (P' ts x) rho) (stackframe_of' (genv_cenv ge) f rho)) (funassert (func_tycontext' f (nofunc_tycontext V G)) rho)) (Ssequence (fn_body f) (Sreturn (@None expr))) (frame_ret_assert (function_body_ret_assert (fn_return f) (Q' ts x)) (stackframe_of' (genv_cenv ge) f)))) n *)
apply JMeq_eq in H4b.
(* Goal: @app_pred nat ag_nat (@box nat ag_nat (@laterM nat ag_nat) (@semax' C Espec (func_tycontext' f (nofunc_tycontext V G)) (fun rho : environ => @andp rmap ag_rmap (@sepcon rmap Join_rmap Perm_rmap ag_rmap Age_rmap (bind_args (fn_params f) (fn_vars f) (P' ts x) rho) (stackframe_of' (genv_cenv ge) f rho)) (funassert (func_tycontext' f (nofunc_tycontext V G)) rho)) (Ssequence (fn_body f) (Sreturn (@None expr))) (frame_ret_assert (function_body_ret_assert (fn_return f) (Q' ts x)) (stackframe_of' (genv_cenv ge) f)))) n *)
apply JMeq_eq in H4c.
(* Goal: @app_pred nat ag_nat (@box nat ag_nat (@laterM nat ag_nat) (@semax' C Espec (func_tycontext' f (nofunc_tycontext V G)) (fun rho : environ => @andp rmap ag_rmap (@sepcon rmap Join_rmap Perm_rmap ag_rmap Age_rmap (bind_args (fn_params f) (fn_vars f) (P' ts x) rho) (stackframe_of' (genv_cenv ge) f rho)) (funassert (func_tycontext' f (nofunc_tycontext V G)) rho)) (Ssequence (fn_body f) (Sreturn (@None expr))) (frame_ret_assert (function_body_ret_assert (fn_return f) (Q' ts x)) (stackframe_of' (genv_cenv ge) f)))) n *)
subst P' Q'.
unfold believe_external.
rewrite H2.
assert (Hty: map fst (zip_with_tl ids argsig) = ids).
(* Goal: @ex val (fun v : val => and (@eq (option val) (if ident_eq i p then @Some val (@fst val type a) else @Map.get val (make_tenv (temp_bindings (Pos.add p xH) (@map (prod val type) val (@fst val type) typed_args))) i) (@Some val v)) (tc_val' ty v)) *)
{ clear -Hlen. revert argsig Hlen. induction ids; auto.
(* Goal: forall (id : positive) (ty : type), iff (@eq (option type) (@PTree.get type id (make_tycontext_v (@nil (prod ident type)))) (@Some type ty)) (@ex block (fun v : block => @eq (option (prod block type)) (@Map.get (prod block type) (make_venv empty_env) id) (@Some (prod block type) (@pair block type v ty)))) *)
  simpl; intros. destruct argsig; auto. inv Hlen.
  simpl. f_equal. auto. }
(* Goal: and (var_sizes_ok (genv_cenv ge) (fn_vars f)) (and (@eq funsig fsig (fn_funsig f)) (@eq calling_convention (fn_callconv f) cc')) *)
(* Goal: @app_pred nat ag_nat (@allp nat ag_nat (list Type) (fun ts : list Type => @allp nat ag_nat (_functor (dependent_type_functor_rec ts A') (@pred rmap ag_rmap)) (fun x : _functor (dependent_type_functor_rec ts A') (@pred rmap ag_rmap) => @box nat ag_nat (@laterM nat ag_nat) (@semax' C Espec (func_tycontext' f (nofunc_tycontext V G)) (fun rho : environ => @andp rmap ag_rmap (@sepcon rmap Join_rmap Perm_rmap ag_rmap Age_rmap (bind_args (fn_params f) (fn_vars f) (P' ts x) rho) (stackframe_of' (genv_cenv ge) f rho)) (funassert (func_tycontext' f (nofunc_tycontext V G)) rho)) (Ssequence (fn_body f) (Sreturn (@None expr))) (frame_ret_assert (function_body_ret_assert (fn_return f) (Q' ts x)) (stackframe_of' (genv_cenv ge) f)))))) n *)
rewrite fst_split. simpl map. rewrite Hty.
(* Goal: and (@eq (option block) (@Some block loc') (@Some block loc')) (@ex funspec (fun fs : funspec => @eq (option funspec) (@PTree.get funspec i (make_tycontext_s G)) (@Some funspec fs))) *)
split; auto.
(* Goal: and (@eq (option block) (@Some block loc') (@Some block loc')) (@ex funspec (fun fs : funspec => @eq (option funspec) (@PTree.get funspec i (make_tycontext_s G)) (@Some funspec fs))) *)
split; auto. split; auto.
intros ts x ret phi Hlev Hx Hnec. apply Hretty.

(* **   Vptr b Ptrofs.zero <> v'  ********)
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
apply (Hf n v' fsig' cc' A' P' Q'); auto.
(* Goal: @app_pred nat ag_nat (@prop nat ag_nat (claims ge (nofunc_tycontext V G') v fsig cc' A' P' Q')) n *)
destruct H1 as [id' [NEP' [NEQ' [? ?]]]].
(* Goal: @In (prod ident funspec) (@pair ident funspec id (mk_funspec f0 cc0 A a a0 P_ne Q_ne)) G *)
simpl in H1.
(* Goal: @app_pred nat ag_nat (@prop nat ag_nat (claims ge (nofunc_tycontext V G') v fsig cc' A' P' Q')) n *)
destruct (eq_dec id id').
(* Goal: iff (@eq (option type) (@PTree.get type id (make_tycontext_g vs G)) (@Some type t)) (or (@ex funspec (fun f : funspec => and (@In (prod positive funspec) (@pair positive funspec id f) G) (@eq type t (type_of_funspec f)))) (@In (prod positive type) (@pair positive type id t) vs)) *)
subst. rewrite PTree.gss in H1. inv H1.
(* Goal: @ex val (fun v : val => and (@eq (option val) (@PTree.get val id (PTree.empty val)) (@Some val v)) (tc_val' ty v)) *)
destruct H4 as [? [? ?]]; congruence.
(* Goal: and (@eq (option block) (@Some block loc') (@Some block loc')) (@ex funspec (fun fs : funspec => @eq (option funspec) (@PTree.get funspec i (make_tycontext_s G)) (@Some funspec fs))) *)
exists id', NEP', NEQ'; split; auto.
(* Goal: forall _ : @ex block (fun v : block => @eq (option (prod block type)) (@Map.get (prod block type) (ve_of (construct_rho (filter_genv (globalenv prog)) empty_env (@PTree.set val xH (Vptr b Ptrofs.zero) (temp_bindings (xO xH) (@map (prod val type) val (@fst val type) typed_args))))) id) (@Some (prod block type) (@pair block type v ty))), @eq (option type) (@PTree.get type id (var_types (@Delta_types vs G C (@map (prod val type) type (@snd val type) typed_args)))) (@Some type ty) *)
simpl. rewrite PTree.gso in H1 by auto; auto.
Qed.

Definition main_params (ge: genv) start : Prop :=
  exists b, exists func,
    Genv.find_symbol ge start = Some b /\
        Genv.find_funct ge (Vptr b Ptrofs.zero) = Some (Internal func) /\
        func.(fn_params) = nil.

(* Goal: @ex val (fun v : val => and (@eq (option val) (if ident_eq i p then @Some val (@fst val type a) else @Map.get val (make_tenv (temp_bindings (Pos.add p xH) (@map (prod val type) val (@fst val type) typed_args))) i) (@Some val v)) (tc_val' ty v)) *)
Lemma in_prog_funct'_in {F V}:
  forall i f (g: list (ident * globdef F V)), In (i,f) (prog_funct' g) -> In (i, Gfun f) g.
Proof.
(* Goal: forall (id : positive) (ty : type), iff (@eq (option type) (@PTree.get type id (make_tycontext_v (@nil (prod ident type)))) (@Some type ty)) (@ex block (fun v : block => @eq (option (prod block type)) (@Map.get (prod block type) (make_venv empty_env) id) (@Some (prod block type) (@pair block type v ty)))) *)
induction g; intros. inv H. simpl in *.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
destruct a; destruct g0. simpl in H. destruct H; auto. left; congruence.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
right; auto.
Qed.

Lemma in_prog_funct_in_prog_defs:
  forall i f prog, In (i,f) (prog_funct prog) -> In (i, Gfun f) (prog_defs prog).
Proof.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
 intros; apply in_prog_funct'_in; auto.
Qed.

Lemma in_prog_vars_in_prog_defs:
  forall i v prog, In (i,v) (prog_vars prog) -> In (i, Gvar v) (prog_defs prog).
Proof.
(* Goal: forall (i : ident) (v : globvar type) (prog : Ctypes.program function) (_ : @In (prod ident (globvar type)) (@pair ident (globvar type) i v) (@initial_world.prog_vars function prog)), @In (prod ident (globdef (Ctypes.fundef function) type)) (@pair ident (globdef (Ctypes.fundef function) type) i (@Gvar (Ctypes.fundef function) type v)) (@prog_defs function prog) *)
unfold prog_vars. intros ? ? ?.
(* Goal: forall (id : positive) (ty : type), iff (@eq (option type) (@PTree.get type id (make_tycontext_v (@nil (prod ident type)))) (@Some type ty)) (@ex block (fun v : block => @eq (option (prod block type)) (@Map.get (prod block type) (make_venv empty_env) id) (@Some (prod block type) (@pair block type v ty)))) *)
induction (prog_defs prog); intros. inv H. simpl in *.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
destruct a; destruct g. auto. simpl in H. destruct H; auto. left; congruence.
Qed.

Lemma find_funct_ptr_exists:
  forall (p: program) id f,
  list_norepet (prog_defs_names p) ->
  In (id, Gfun f) (prog_defs p) ->
  exists b,
     Genv.find_symbol (Genv.globalenv p) id = Some b
  /\ Genv.find_funct_ptr (Genv.globalenv p) b = Some f.
Proof.
(* Goal: forall (id : positive) (ty : type), iff (@eq (option type) (@PTree.get type id (make_tycontext_v (@nil (prod ident type)))) (@Some type ty)) (@ex block (fun v : block => @eq (option (prod block type)) (@Map.get (prod block type) (make_venv empty_env) id) (@Some (prod block type) (@pair block type v ty)))) *)
intros.
(* Goal: @ex block (fun b : block => and (@eq (option block) (@Genv.find_symbol (Ctypes.fundef function) type (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function p)) id) (@Some block b)) (@eq (option (Ctypes.fundef function)) (@Genv.find_funct_ptr (Ctypes.fundef function) type (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function p)) b) (@Some (Ctypes.fundef function) f))) *)
pose proof (prog_defmap_norepet _ _ _ H H0).
destruct (proj1 (Genv.find_def_symbol _ _ _) H1)
  as [b [? ?]].
(* Goal: and (@eq (option block) (@Some block loc') (@Some block loc')) (@ex funspec (fun fs : funspec => @eq (option funspec) (@PTree.get funspec i (make_tycontext_s G)) (@Some funspec fs))) *)
exists b; split; auto.
(* Goal: @eq (option (Ctypes.fundef function)) (@Genv.find_funct_ptr (Ctypes.fundef function) type (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function p)) b) (@Some (Ctypes.fundef function) f) *)
unfold Genv.find_funct_ptr.
(* Goal: and (@eq (option block) (@Genv.find_symbol (Ctypes.fundef function) type (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) id) (@Some block b)) (@app_pred rmap ag_rmap (func_at fs (@pair block Z b Z0)) (@initial_world.initial_core_ext function (@OK_ty Espec) ora (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n)) *)
rewrite H3.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
auto.
Qed.

Lemma funassert_initial_core:
  forall (prog: program) ve te V G n,
      list_norepet (prog_defs_names prog) ->
      match_fdecs (prog_funct prog) G ->
      app_pred (funassert (nofunc_tycontext V G) (mkEnviron (filter_genv (globalenv prog)) ve te))
                      (initial_core (Genv.globalenv prog) G n).
Proof.
(* Goal: and (var_sizes_ok (genv_cenv ge) (fn_vars f)) (and (@eq funsig fsig (fn_funsig f)) (@eq calling_convention (fn_callconv f) cc')) *)
(* Goal: @app_pred nat ag_nat (@allp nat ag_nat (list Type) (fun ts : list Type => @allp nat ag_nat (_functor (dependent_type_functor_rec ts A') (@pred rmap ag_rmap)) (fun x : _functor (dependent_type_functor_rec ts A') (@pred rmap ag_rmap) => @box nat ag_nat (@laterM nat ag_nat) (@semax' C Espec (func_tycontext' f (nofunc_tycontext V G)) (fun rho : environ => @andp rmap ag_rmap (@sepcon rmap Join_rmap Perm_rmap ag_rmap Age_rmap (bind_args (fn_params f) (fn_vars f) (P' ts x) rho) (stackframe_of' (genv_cenv ge) f rho)) (funassert (func_tycontext' f (nofunc_tycontext V G)) rho)) (Ssequence (fn_body f) (Sreturn (@None expr))) (frame_ret_assert (function_body_ret_assert (fn_return f) (Q' ts x)) (stackframe_of' (genv_cenv ge) f)))))) n *)
 intros; split.
*
(* Goal: @app_pred rmap ag_rmap (@allp rmap ag_rmap ident (fun id : ident => @allp rmap ag_rmap funspec (fun fs : funspec => @imp rmap ag_rmap (@prop rmap ag_rmap (@eq (option funspec) (@PTree.get funspec id (glob_specs (nofunc_tycontext V G))) (@Some funspec fs))) (@exp rmap ag_rmap block (fun b : block => @andp rmap ag_rmap (@prop rmap ag_rmap (@eq (option block) (@Map.get block (ge_of (mkEnviron (filter_genv (globalenv prog)) ve te)) id) (@Some block b))) (func_at fs (@pair block Z b Z0))))))) (@initial_world.initial_core_ext function (@OK_ty Espec) ora (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) *)
 intros id fs.
(* Goal: forall (id : positive) (ty : type), iff (@eq (option type) (@PTree.get type id (make_tycontext_v (@nil (prod ident type)))) (@Some type ty)) (@ex block (fun v : block => @eq (option (prod block type)) (@Map.get (prod block type) (make_venv empty_env) id) (@Some (prod block type) (@pair block type v ty)))) *)
 apply prop_imp_i; intros.
(* Goal: @app_pred rmap ag_rmap (@exp rmap ag_rmap block (fun b : block => @andp rmap ag_rmap (@prop rmap ag_rmap (@eq (option block) (@Map.get block (ge_of (mkEnviron (filter_genv (globalenv prog)) ve te)) id) (@Some block b))) (func_at fs (@pair block Z b Z0)))) (@initial_world.initial_core_ext function (@OK_ty Espec) ora (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) *)
 simpl ge_of; simpl fst; simpl snd.
(* Goal: and (@eq (option block) (@Map.get block (filter_genv (globalenv prog)) i) (@Some block loc')) (@ex funspec (fun fs : funspec => @eq (option funspec) (@PTree.get funspec i (make_tycontext_s G)) (@Some funspec fs))) *)
 unfold filter_genv, Map.get.
(* Goal: @ex val (fun v : val => and (@eq (option val) (if ident_eq i p then @Some val (@fst val type a) else @Map.get val (make_tenv (temp_bindings (Pos.add p xH) (@map (prod val type) val (@fst val type) typed_args))) i) (@Some val v)) (tc_val' ty v)) *)
 assert (exists f, In (id, f) (prog_funct prog)). {
(* Goal: @In (prod ident funspec) (@pair ident funspec id (mk_funspec f0 cc0 A a a0 P_ne Q_ne)) G *)
 simpl in H1.
(* Goal: @ex (Ctypes.fundef function) (fun f : Ctypes.fundef function => and (@In (prod ident (Ctypes.fundef function)) (@pair ident (Ctypes.fundef function) i f) (@initial_world.prog_funct function prog)) (@eq type (type_of_fundef f) (Tfunction (type_of_params (@fst (list (prod ident type)) type fsig')) (@snd (list (prod ident type)) type fsig') cc'))) *)
 forget (prog_funct prog) as g.
(* Goal: @ex (Ctypes.fundef function) (fun f : Ctypes.fundef function => @In (prod ident (Ctypes.fundef function)) (@pair ident (Ctypes.fundef function) id f) g) *)
clear - H1 H0.
revert G H1 H0; induction g; destruct G; intros; simpl in *.
(* Goal: @ex (Ctypes.fundef function) (fun _ : Ctypes.fundef function => False) *)
(* Goal: @ex (Ctypes.fundef function) (fun _ : Ctypes.fundef function => False) *)
(* Goal: @ex (Ctypes.fundef function) (fun f : Ctypes.fundef function => or (@eq (prod ident (Ctypes.fundef function)) a (@pair ident (Ctypes.fundef function) id f)) (@In (prod ident (Ctypes.fundef function)) (@pair ident (Ctypes.fundef function) id f) g)) *)
(* Goal: @ex (Ctypes.fundef function) (fun f : Ctypes.fundef function => or (@eq (prod ident (Ctypes.fundef function)) a (@pair ident (Ctypes.fundef function) id f)) (@In (prod ident (Ctypes.fundef function)) (@pair ident (Ctypes.fundef function) id f) g)) *)
elimtype False.
(* Goal: iff (@eq (option type) (@PTree.get type id (make_tycontext_g vs G)) (@Some type t)) (or (@ex funspec (fun f : funspec => and (@In (prod positive funspec) (@pair positive funspec id f) G) (@eq type t (type_of_funspec f)))) (@In (prod positive type) (@pair positive type id t) vs)) *)
rewrite PTree.gempty in H1; inv H1.
(* Goal: iff (@eq (option type) (@PTree.get type id (@PTree.set type (@fst ident type (@pair ident type i t0)) (@snd ident type (@pair ident type i t0)) (@fold_right (PTree.t type) (prod ident type) (fun v : prod ident type => @PTree.set type (@fst ident type v) (@snd ident type v)) (PTree.empty type) vs))) (@Some type t)) (or (@eq (prod positive type) (@pair ident type i t0) (@pair positive type id t)) (@In (prod positive type) (@pair positive type id t) vs)) *)
inv H0.
(* Goal: @In ident i (@map (prod ident (globvar type)) ident (@fst ident (globvar type)) vl) *)
(* Goal: iff (@eq (option type) (@PTree.get type id (make_tycontext_g vs (@cons (prod ident funspec) (@pair ident funspec i fspec) G0))) (@Some type t)) (or (@ex funspec (fun f : funspec => and (@In (prod positive funspec) (@pair positive funspec id f) (@cons (prod ident funspec) (@pair ident funspec i fspec) G0)) (@eq type t (type_of_funspec f)))) (@In (prod positive type) (@pair positive type id t) vs)) *)
destruct a; simpl in *; subst.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
destruct (eq_dec i id). subst; eauto.
(* Goal: iff (@eq (option type) (@PTree.get type id (@PTree.set type (@fst ident type (@pair ident type i t0)) (@snd ident type (@pair ident type i t0)) (@fold_right (PTree.t type) (prod ident type) (fun v : prod ident type => @PTree.set type (@fst ident type v) (@snd ident type v)) (PTree.empty type) vs))) (@Some type t)) (or (@eq (prod positive type) (@pair ident type i t0) (@pair positive type id t)) (@In (prod positive type) (@pair positive type id t) vs)) *)
 specialize (IHg nil H1). inv H0.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
(*destruct (IHg). destruct g; simpl; auto.
(* Goal: @list_norepet ident (@map (prod ident fundef) ident (@fst ident fundef) (@prog_funct' (Ctypes.fundef function) type (@nil (prod ident (globdef (Ctypes.fundef function) type))))) *)
(* Goal: @list_norepet ident (@map (prod ident fundef) ident (@fst ident fundef) (@prog_funct' (Ctypes.fundef function) type (@cons (prod ident (globdef (Ctypes.fundef function) type)) a l))) *)
(* Goal: @ex block (fun b : block => @eq (option block) (@Map.get block (@Genv.find_symbol fundef type (genv_genv (globalenv prog))) id) (@Some block b)) *)
constructor. apply match_fdecs_nil.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
eauto. *)
(* Goal: or (@eq ident (@fst ident (globdef (Ctypes.fundef function) type) a) i) (@In ident i (@map (prod ident (globdef (Ctypes.fundef function) type)) ident (@fst ident (globdef (Ctypes.fundef function) type)) l)) *)
(* Goal: @list_norepet ident (@map (prod ident fundef) ident (@fst ident fundef) (@prog_funct' (Ctypes.fundef function) type l)) *)
(* Goal: @ex block (fun b : block => @eq (option block) (@Map.get block (@Genv.find_symbol fundef type (genv_genv (globalenv prog))) id) (@Some block b)) *)
destruct a. destruct p.
(* Goal: iff (@eq (option type) (@PTree.get type id (@PTree.set type (@fst ident type (@pair ident type i t0)) (@snd ident type (@pair ident type i t0)) (@fold_right (PTree.t type) (prod ident type) (fun v : prod ident type => @PTree.set type (@fst ident type v) (@snd ident type v)) (PTree.empty type) vs))) (@Some type t)) (or (@eq (prod positive type) (@pair ident type i t0) (@pair positive type id t)) (@In (prod positive type) (@pair positive type id t) vs)) *)
 inv H0.
(* Goal: @In (prod ident funspec) (@pair ident funspec id (mk_funspec f0 cc0 A a a0 P_ne Q_ne)) G *)
 simpl in H1.
(* Goal: @In ident i (@map (prod ident (globvar type)) ident (@fst ident (globvar type)) vl) *)
(* Goal: iff (@eq (option type) (@PTree.get type id (make_tycontext_g vs (@cons (prod ident funspec) (@pair ident funspec i fspec) G0))) (@Some type t)) (or (@ex funspec (fun f : funspec => and (@In (prod positive funspec) (@pair positive funspec id f) (@cons (prod ident funspec) (@pair ident funspec i fspec) G0)) (@eq type t (type_of_funspec f)))) (@In (prod positive type) (@pair positive type id t) vs)) *)
 destruct (ident_eq i0 id). subst. eauto.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
 destruct (IHg G); auto. rewrite PTree.gso in H1; auto.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
 eauto.
(* Goal: @In (prod ident funspec) (@pair ident funspec id (mk_funspec f0 cc0 A a a0 P_ne Q_ne)) G *)
(* simpl in H1.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
 destruct (IHg ((i0,f0)::G)); auto. eauto.
*)
 }
(* Goal: @app_pred rmap ag_rmap (@exp rmap ag_rmap block (fun b : block => @andp rmap ag_rmap (@prop rmap ag_rmap (@eq (option block) (@Genv.find_symbol fundef type (genv_genv (globalenv prog)) id) (@Some block b))) (func_at fs (@pair block Z b Z0)))) (@initial_world.initial_core_ext function (@OK_ty Espec) ora (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) *)
 destruct H2 as [f ?].
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
 destruct (find_funct_ptr_exists prog id f) as [b [? ?]]; auto.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
 apply in_prog_funct_in_prog_defs; auto.
(* Goal: @app_pred rmap ag_rmap (@exp rmap ag_rmap block (fun b : block => @andp rmap ag_rmap (@prop rmap ag_rmap (@eq (option block) (@Genv.find_symbol fundef type (genv_genv (globalenv prog)) id) (@Some block b))) (func_at fs (@pair block Z b Z0)))) (@initial_world.initial_core_ext function (@OK_ty Espec) ora (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) *)
 exists b. unfold fundef.
(* Goal: forall _ : @ex block (fun v : block => @eq (option (prod block type)) (@Map.get (prod block type) (ve_of (construct_rho (filter_genv (globalenv prog)) empty_env (@PTree.set val xH (Vptr b Ptrofs.zero) (temp_bindings (xO xH) (@map (prod val type) val (@fst val type) typed_args))))) id) (@Some (prod block type) (@pair block type v ty))), @eq (option type) (@PTree.get type id (var_types (@Delta_types vs G C (@map (prod val type) type (@snd val type) typed_args)))) (@Some type ty) *)
 unfold globalenv. simpl. rewrite H3.
(* Goal: and (@eq (option block) (@Some block loc') (@Some block loc')) (@ex funspec (fun fs : funspec => @eq (option funspec) (@PTree.get funspec i (make_tycontext_s G)) (@Some funspec fs))) *)
 split; auto.
(* Goal: @app_pred rmap ag_rmap (@imp rmap ag_rmap (func_at' (mk_funspec fsig' cc' A' P' Q' NEP' NEQ') (@pair block Z loc' Z0)) (@exp rmap ag_rmap ident (fun id : ident => @andp rmap ag_rmap (@prop rmap ag_rmap (@eq (option block) (@Map.get block (ge_of (mkEnviron (filter_genv (globalenv prog)) ve te)) id) (@Some block loc'))) (@prop rmap ag_rmap (@ex funspec (fun fs : funspec => @eq (option funspec) (@PTree.get funspec id (glob_specs (nofunc_tycontext V G))) (@Some funspec fs))))))) (@initial_world.initial_core_ext function (@OK_ty Espec) ora (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) *)
 unfold func_at. destruct fs as [f0 cc0 A a a0].
(* Goal: @app_pred rmap ag_rmap (pureat (SomeP (SpecTT A) (@packPQ A a a0)) (FUN f0 cc0) (@pair block Z b Z0)) (@initial_world.initial_core function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) *)
 unfold initial_core.
(* Goal: @app_pred rmap ag_rmap (pureat (SomeP (SpecTT A) (@packPQ A a a0)) (FUN f0 cc0) (@pair block Z b Z0)) (@proj1_sig rmap (fun phi : rmap => and (@eq nat (@level rmap ag_rmap phi) n) (and (@eq (forall _ : AV.address, resource) (resource_at phi) (@initial_world.initial_core' function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n)) (@eq ghost (ghost_of phi) (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) NoneP)) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds))))))) (make_rmap (@initial_world.initial_core' function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) NoneP)) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)))) n (initial_world.initial_core_ext_obligation_1 function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) (@eq_refl ghost (ghost_fmap (approx n) (approx n) (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) NoneP)) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)))))))) *)
 hnf. rewrite resource_at_make_rmap.
(* Goal: @eq resource (@initial_world.initial_core' function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n (@pair block Z b Z0)) (PURE (FUN f0 cc0) (preds_fmap (approx (@level rmap ag_rmap (@proj1_sig rmap (fun phi : rmap => and (@eq nat (@level rmap ag_rmap phi) n) (and (@eq (forall _ : AV.address, resource) (resource_at phi) (@initial_world.initial_core' function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n)) (@eq ghost (ghost_of phi) (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) NoneP)) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds))))))) (make_rmap (@initial_world.initial_core' function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) NoneP)) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)))) n (initial_world.initial_core_ext_obligation_1 function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) (@eq_refl ghost (ghost_fmap (approx n) (approx n) (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) NoneP)) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)))))))))) (approx (@level rmap ag_rmap (@proj1_sig rmap (fun phi : rmap => and (@eq nat (@level rmap ag_rmap phi) n) (and (@eq (forall _ : AV.address, resource) (resource_at phi) (@initial_world.initial_core' function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n)) (@eq ghost (ghost_of phi) (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) NoneP)) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds))))))) (make_rmap (@initial_world.initial_core' function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) NoneP)) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)))) n (initial_world.initial_core_ext_obligation_1 function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) (@eq_refl ghost (ghost_fmap (approx n) (approx n) (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) NoneP)) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)))))))))) (SomeP (SpecTT A) (@packPQ A a a0)))) *)
 rewrite level_make_rmap.
(* Goal: @eq resource (@core resource Join_resource Sep_resource match access_at m l Cur with | Some (Freeable as p) => YES Share.top readable_share_top (VAL (contents_at m l)) NoneP | Some (Writable as p) => YES Ews (@writable_readable Ews writable_Ews) (VAL (contents_at m l)) NoneP | Some (Readable as p) => YES Ers readable_Ers (VAL (contents_at m l)) NoneP | Some (Nonempty as p) => match @initial_world.initial_core' function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n l with | NO sh n => NO extern_retainer nonreadable_extern_retainer | YES sh r k p0 => NO extern_retainer nonreadable_extern_retainer | PURE k p0 => @initial_world.initial_core' function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n l end | None => NO Share.bot bot_unreadable end) (@initial_world.initial_core' function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n l) *)
(* Goal: @eq ghost (ghost_of (@core rmap Join_rmap Sep_rmap (inflate_initial_mem m (@initial_world.initial_core_ext function (@OK_ty Espec) ora (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n)))) (ghost_of (@initial_world.initial_core function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n)) *)
 unfold initial_core'.
(* Goal: forall _ : @ex block (fun v : block => @eq (option (prod block type)) (@Map.get (prod block type) (ve_of (construct_rho (filter_genv (globalenv prog)) empty_env (@PTree.set val xH (Vptr b Ptrofs.zero) (temp_bindings (xO xH) (@map (prod val type) val (@fst val type) typed_args))))) id) (@Some (prod block type) (@pair block type v ty))), @eq (option type) (@PTree.get type id (var_types (@Delta_types vs G C (@map (prod val type) type (@snd val type) typed_args)))) (@Some type ty) *)
 simpl.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
 rewrite (Genv.find_invert_symbol (Genv.globalenv prog) id); auto.
(* Goal: @ex val (fun v : val => and (@eq (option val) (if ident_eq i p then @Some val (@fst val type a) else @Map.get val (make_tenv (temp_bindings (Pos.add p xH) (@map (prod val type) val (@fst val type) typed_args))) i) (@Some val v)) (tc_val' ty v)) *)
 assert (H9: In (id, mk_funspec f0 cc0 A a a0 P_ne Q_ne) G). {
(* Goal: False *)
(* Goal: @eq (option type) (@Some type t0) (@Some type t) *)
   clear - H1.
(* Goal: @In (prod ident funspec) (@pair ident funspec id (mk_funspec f0 cc0 A a a0 P_ne Q_ne)) G *)
    simpl in H1. unfold make_tycontext_g in H1; simpl in H1.
    induction G; simpl in *.
(* Goal: iff (@eq (option type) (@PTree.get type id (make_tycontext_g vs G)) (@Some type t)) (or (@ex funspec (fun f : funspec => and (@In (prod positive funspec) (@pair positive funspec id f) G) (@eq type t (type_of_funspec f)))) (@In (prod positive type) (@pair positive type id t) vs)) *)
    rewrite PTree.gempty in H1; inv H1.
(* Goal: @In ident i (@map (prod ident (globvar type)) ident (@fst ident (globvar type)) vl) *)
(* Goal: iff (@eq (option type) (@PTree.get type id (make_tycontext_g vs (@cons (prod ident funspec) (@pair ident funspec i fspec) G0))) (@Some type t)) (or (@ex funspec (fun f : funspec => and (@In (prod positive funspec) (@pair positive funspec id f) (@cons (prod ident funspec) (@pair ident funspec i fspec) G0)) (@eq type t (type_of_funspec f)))) (@In (prod positive type) (@pair positive type id t) vs)) *)
    destruct (ident_eq (fst a1) id); subst.
    change (@ptree_set) with (@PTree.set) in *. destruct a1; simpl in *.
(* Goal: iff (@eq (option type) (@PTree.get type id (make_tycontext_g vs G)) (@Some type t)) (or (@ex funspec (fun f : funspec => and (@In (prod positive funspec) (@pair positive funspec id f) G) (@eq type t (type_of_funspec f)))) (@In (prod positive type) (@pair positive type id t) vs)) *)
    rewrite PTree.gss in H1; inv H1. left; auto.
    change (@ptree_set) with (@PTree.set) in *. destruct a1; simpl in *. 
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
    rewrite PTree.gso in H1; auto.
 }
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
 rewrite (find_id_i _ _ _ H9); auto.
 clear - H0 H. unfold prog_defs_names, prog_funct in *.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
 eapply match_fdecs_norepet; eauto.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
 apply list_norepet_prog_funct'; auto.
*
 intros loc'  [fsig' cc' A' P' Q' NEP' NEQ'].
(* Goal: @app_pred rmap ag_rmap (@imp rmap ag_rmap (func_at' (mk_funspec fsig' cc' A' P' Q' NEP' NEQ') (@pair block Z loc' Z0)) (@exp rmap ag_rmap ident (fun id : ident => @andp rmap ag_rmap (@prop rmap ag_rmap (@eq (option block) (@Map.get block (ge_of (mkEnviron (filter_genv (globalenv prog)) ve te)) id) (@Some block loc'))) (@prop rmap ag_rmap (@ex funspec (fun fs : funspec => @eq (option funspec) (@PTree.get funspec id (glob_specs (nofunc_tycontext V G))) (@Some funspec fs))))))) (@initial_world.initial_core_ext function (@OK_ty Espec) ora (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) *)
 unfold func_at.
(* Goal: @app_pred rmap ag_rmap (@imp rmap ag_rmap (func_at' (mk_funspec fsig' cc' A' P' Q' NEP' NEQ') (@pair block Z loc' Z0)) (@exp rmap ag_rmap ident (fun id : ident => @andp rmap ag_rmap (@prop rmap ag_rmap (@eq (option block) (@Map.get block (ge_of (mkEnviron (filter_genv (globalenv prog)) ve te)) id) (@Some block loc'))) (@prop rmap ag_rmap (@ex funspec (fun fs : funspec => @eq (option funspec) (@PTree.get funspec id (glob_specs (nofunc_tycontext V G))) (@Some funspec fs))))))) (@initial_world.initial_core_ext function (@OK_ty Espec) ora (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) *)
 intros w ? ?.
(* Goal: @app_pred rmap ag_rmap (@exp rmap ag_rmap ident (fun id : ident => @andp rmap ag_rmap (@prop rmap ag_rmap (@eq (option block) (@Map.get block (ge_of (mkEnviron (filter_genv (globalenv prog)) ve te)) id) (@Some block loc'))) (@prop rmap ag_rmap (@ex funspec (fun fs : funspec => @eq (option funspec) (@PTree.get funspec id (glob_specs (nofunc_tycontext V G))) (@Some funspec fs)))))) w *)
 destruct H2 as [pp ?].
(* Goal: @app_pred rmap ag_rmap (@exp rmap ag_rmap ident (fun id : ident => @andp rmap ag_rmap (@prop rmap ag_rmap (@eq (option block) (@Map.get block (ge_of (mkEnviron (filter_genv (globalenv prog)) ve te)) id) (@Some block loc'))) (@prop rmap ag_rmap (@ex funspec (fun fs : funspec => @eq (option funspec) (@PTree.get funspec id (glob_specs (nofunc_tycontext V G))) (@Some funspec fs)))))) w *)
 hnf in H2.
(* Goal: @app_pred rmap ag_rmap (@exp rmap ag_rmap ident (fun id : ident => @andp rmap ag_rmap (@prop rmap ag_rmap (@eq (option block) (@Map.get block (ge_of (mkEnviron (filter_genv (globalenv prog)) ve te)) id) (@Some block loc'))) (@prop rmap ag_rmap (@ex funspec (fun fs : funspec => @eq (option funspec) (@PTree.get funspec id (glob_specs (nofunc_tycontext V G))) (@Some funspec fs)))))) w *)
 assert (exists pp, initial_core (Genv.globalenv prog) G n @ (loc',0) = PURE (FUN fsig' cc') pp).
(* Goal: forall (id : positive) (ty : type), iff (@eq (option type) (@PTree.get type id (make_tycontext_v (@nil (prod ident type)))) (@Some type ty)) (@ex block (fun v : block => @eq (option (prod block type)) (@Map.get (prod block type) (make_venv empty_env) id) (@Some (prod block type) (@pair block type v ty)))) *)
case_eq (initial_core (@Genv.globalenv (Ctypes.fundef function) type prog) G n @ (loc', 0)); intros.
(* Goal: @ex preds (fun pp : preds => @eq resource (NO sh n0) (PURE (FUN fsig' cc') pp)) *)
(* Goal: @ex preds (fun pp : preds => @eq resource (YES sh r k p) (PURE (FUN fsig' cc') pp)) *)
(* Goal: @ex preds (fun pp : preds => @eq resource (PURE k p) (PURE (FUN fsig' cc') pp)) *)
(* Goal: @app_pred rmap ag_rmap (@exp rmap ag_rmap ident (fun id : ident => @andp rmap ag_rmap (@prop rmap ag_rmap (@eq (option block) (@Map.get block (ge_of (mkEnviron (filter_genv (globalenv prog)) ve te)) id) (@Some block loc'))) (@prop rmap ag_rmap (@ex funspec (fun fs : funspec => @eq (option funspec) (@PTree.get funspec id (glob_specs (nofunc_tycontext V G))) (@Some funspec fs)))))) w *)
destruct (necR_NO _ _ (loc',0) sh n0 H1) as [? _].
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
rewrite H4 in H2 by auto.
(* Goal: @ex block (fun v : block => @eq (option (prod block type)) (@None (prod block type)) (@Some (prod block type) (@pair block type v ty))) *)
(* Goal: @eq (option type) (@None type) (@Some type ty) *)
inv H2.
(* Goal: @ex preds (fun pp : preds => @eq resource (YES sh r k p) (PURE (FUN fsig' cc') pp)) *)
(* Goal: @ex preds (fun pp : preds => @eq resource (PURE k p) (PURE (FUN fsig' cc') pp)) *)
(* Goal: @app_pred rmap ag_rmap (@exp rmap ag_rmap ident (fun id : ident => @andp rmap ag_rmap (@prop rmap ag_rmap (@eq (option block) (@Map.get block (ge_of (mkEnviron (filter_genv (globalenv prog)) ve te)) id) (@Some block loc'))) (@prop rmap ag_rmap (@ex funspec (fun fs : funspec => @eq (option funspec) (@PTree.get funspec id (glob_specs (nofunc_tycontext V G))) (@Some funspec fs)))))) w *)
eapply necR_YES in H1; try apply H3.
(* Goal: @ex block (fun v : block => @eq (option (prod block type)) (@None (prod block type)) (@Some (prod block type) (@pair block type v ty))) *)
(* Goal: @eq (option type) (@None type) (@Some type ty) *)
rewrite H1 in H2; inv H2.
(* Goal: @ex preds (fun pp : preds => @eq resource (PURE k p) (PURE (FUN fsig' cc') pp)) *)
(* Goal: @app_pred rmap ag_rmap (@exp rmap ag_rmap ident (fun id : ident => @andp rmap ag_rmap (@prop rmap ag_rmap (@eq (option block) (@Map.get block (ge_of (mkEnviron (filter_genv (globalenv prog)) ve te)) id) (@Some block loc'))) (@prop rmap ag_rmap (@ex funspec (fun fs : funspec => @eq (option funspec) (@PTree.get funspec id (glob_specs (nofunc_tycontext V G))) (@Some funspec fs)))))) w *)
eapply necR_PURE in H1; try apply H3.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
rewrite H1 in H2; inv H2; eauto.
(* Goal: @app_pred rmap ag_rmap (@exp rmap ag_rmap ident (fun id : ident => @andp rmap ag_rmap (@prop rmap ag_rmap (@eq (option block) (@Map.get block (ge_of (mkEnviron (filter_genv (globalenv prog)) ve te)) id) (@Some block loc'))) (@prop rmap ag_rmap (@ex funspec (fun fs : funspec => @eq (option funspec) (@PTree.get funspec id (glob_specs (nofunc_tycontext V G))) (@Some funspec fs)))))) w *)
destruct H3 as [pp' ?].
(* Goal: @app_pred rmap ag_rmap (@exp rmap ag_rmap ident (fun id : ident => @andp rmap ag_rmap (@prop rmap ag_rmap (@eq (option block) (@Map.get block (ge_of (mkEnviron (filter_genv (globalenv prog)) ve te)) id) (@Some block loc'))) (@prop rmap ag_rmap (@ex funspec (fun fs : funspec => @eq (option funspec) (@PTree.get funspec id (glob_specs (nofunc_tycontext V G))) (@Some funspec fs)))))) w *)
unfold initial_core in H3.
(* Goal: @app_pred rmap ag_rmap (@exp rmap ag_rmap ident (fun id : ident => @andp rmap ag_rmap (@prop rmap ag_rmap (@eq (option block) (@Map.get block (ge_of (mkEnviron (filter_genv (globalenv prog)) ve te)) id) (@Some block loc'))) (@prop rmap ag_rmap (@ex funspec (fun fs : funspec => @eq (option funspec) (@PTree.get funspec id (glob_specs (nofunc_tycontext V G))) (@Some funspec fs)))))) w *)
rewrite resource_at_make_rmap in H3.
(* Goal: @app_pred rmap ag_rmap (@exp rmap ag_rmap ident (fun id : ident => @andp rmap ag_rmap (@prop rmap ag_rmap (@eq (option block) (@Map.get block (ge_of (mkEnviron (filter_genv (globalenv prog)) ve te)) id) (@Some block loc'))) (@prop rmap ag_rmap (@ex funspec (fun fs : funspec => @eq (option funspec) (@PTree.get funspec id (glob_specs (nofunc_tycontext V G))) (@Some funspec fs)))))) w *)
unfold initial_core' in H3.
(* Goal: @app_pred rmap ag_rmap (@exp rmap ag_rmap ident (fun id : ident => @andp rmap ag_rmap (@prop rmap ag_rmap (@eq (option block) (@Map.get block (ge_of (mkEnviron (filter_genv (globalenv prog)) ve te)) id) (@Some block loc'))) (@prop rmap ag_rmap (@ex funspec (fun fs : funspec => @eq (option funspec) (@PTree.get funspec id (glob_specs (nofunc_tycontext V G))) (@Some funspec fs)))))) w *)
if_tac in H3; [ | inv H3].
(* Goal: forall _ : @ex block (fun v : block => @eq (option (prod block type)) (@Map.get (prod block type) (ve_of (construct_rho (filter_genv (globalenv prog)) empty_env (@PTree.set val xH (Vptr b Ptrofs.zero) (temp_bindings (xO xH) (@map (prod val type) val (@fst val type) typed_args))))) id) (@Some (prod block type) (@pair block type v ty))), @eq (option type) (@PTree.get type id (var_types (@Delta_types vs G C (@map (prod val type) type (@snd val type) typed_args)))) (@Some type ty) *)
simpl.
simpl @fst in *. 
revert H3; case_eq (@Genv.invert_symbol (Ctypes.fundef function) 
      type (@Genv.globalenv (Ctypes.fundef function) type prog) loc' ); intros;
  [ | congruence].
(* Goal: @ex ident (fun b : ident => and (@eq (option block) (@Map.get block (filter_genv (globalenv prog)) b) (@Some block loc')) (@ex funspec (fun fs : funspec => @eq (option funspec) (@PTree.get funspec b (make_tycontext_s G)) (@Some funspec fs)))) *)
revert H5; case_eq (find_id i G); intros; [| congruence].
(* Goal: @ex ident (fun b : ident => and (@eq (option block) (@Map.get block (filter_genv (globalenv prog)) b) (@Some block loc')) (@ex funspec (fun fs : funspec => @eq (option funspec) (@PTree.get funspec b (make_tycontext_s G)) (@Some funspec fs)))) *)
destruct f as [?f ?A ?a ?a]; inv H6.
(* Goal: @ex ident (fun b : ident => and (@eq (option block) (@Map.get block (filter_genv (globalenv prog)) b) (@Some block loc')) (@ex funspec (fun fs : funspec => @eq (option funspec) (@PTree.get funspec b (make_tycontext_s G)) (@Some funspec fs)))) *)
apply Genv.invert_find_symbol in H3.
(* Goal: @ex ident (fun b : ident => and (@eq (option block) (@Map.get block (filter_genv (globalenv prog)) b) (@Some block loc')) (@ex funspec (fun fs : funspec => @eq (option funspec) (@PTree.get funspec b (make_tycontext_s G)) (@Some funspec fs)))) *)
exists i.
(* Goal: and (@eq (option block) (@Map.get block (filter_genv (globalenv prog)) i) (@Some block loc')) (@ex funspec (fun fs : funspec => @eq (option funspec) (@PTree.get funspec i (make_tycontext_s G)) (@Some funspec fs))) *)
simpl ge_of. unfold filter_genv, Map.get.
(* Goal: forall _ : @ex block (fun v : block => @eq (option (prod block type)) (@Map.get (prod block type) (ve_of (construct_rho (filter_genv (globalenv prog)) empty_env (@PTree.set val xH (Vptr b Ptrofs.zero) (temp_bindings (xO xH) (@map (prod val type) val (@fst val type) typed_args))))) id) (@Some (prod block type) (@pair block type v ty))), @eq (option type) (@PTree.get type id (var_types (@Delta_types vs G C (@map (prod val type) type (@snd val type) typed_args)))) (@Some type ty) *)
unfold globalenv; simpl.
(* Goal: and (@eq (option block) (@Genv.find_symbol (Ctypes.fundef function) type (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) id) (@Some block b)) (@app_pred rmap ag_rmap (func_at fs (@pair block Z b Z0)) (@initial_world.initial_core_ext function (@OK_ty Espec) ora (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n)) *)
 unfold fundef; rewrite H3.
(* Goal: and (@eq (option block) (@Some block loc') (@Some block loc')) (@ex funspec (fun fs : funspec => @eq (option funspec) (@PTree.get funspec i (make_tycontext_s G)) (@Some funspec fs))) *)
 split; auto.
 assert (exists f, In (i,f) (prog_funct prog)
(* Goal: @ex val (fun v : val => and (@eq (option val) (if ident_eq i p then @Some val (@fst val type a) else @Map.get val (make_tenv (temp_bindings (Pos.add p xH) (@map (prod val type) val (@fst val type) typed_args))) i) (@Some val v)) (tc_val' ty v)) *)
              /\ type_of_fundef f = Tfunction (type_of_params (fst fsig')) (snd fsig') cc'). {
(* Goal: @ex (Ctypes.fundef function) (fun f : Ctypes.fundef function => and (@In (prod ident (Ctypes.fundef function)) (@pair ident (Ctypes.fundef function) i f) (@initial_world.prog_funct function prog)) (@eq type (type_of_fundef f) (Tfunction (type_of_params (@fst (list (prod ident type)) type fsig')) (@snd (list (prod ident type)) type fsig') cc'))) *)
 clear - H0 H5.
(* Goal: @ex (Ctypes.fundef function) (fun f : Ctypes.fundef function => and (@In (prod ident (Ctypes.fundef function)) (@pair ident (Ctypes.fundef function) i f) (@initial_world.prog_funct function prog)) (@eq type (type_of_fundef f) (Tfunction (type_of_params (@fst (list (prod ident type)) type fsig')) (@snd (list (prod ident type)) type fsig') cc'))) *)
 forget (prog_funct prog) as g.
(* Goal: forall (id : positive) (ty : type), iff (@eq (option type) (@PTree.get type id (make_tycontext_v (@nil (prod ident type)))) (@Some type ty)) (@ex block (fun v : block => @eq (option (prod block type)) (@Map.get (prod block type) (make_venv empty_env) id) (@Some (prod block type) (@pair block type v ty)))) *)
 revert G H0 H5; induction g; intros.
(* Goal: iff (@eq (option type) (@PTree.get type id (@PTree.set type (@fst ident type (@pair ident type i t0)) (@snd ident type (@pair ident type i t0)) (@fold_right (PTree.t type) (prod ident type) (fun v : prod ident type => @PTree.set type (@fst ident type v) (@snd ident type v)) (PTree.empty type) vs))) (@Some type t)) (or (@eq (prod positive type) (@pair ident type i t0) (@pair positive type id t)) (@In (prod positive type) (@pair positive type id t) vs)) *)
 inv H0. inv H5.
(* Goal: iff (@eq (option type) (@PTree.get type id (@PTree.set type (@fst ident type (@pair ident type i t0)) (@snd ident type (@pair ident type i t0)) (@fold_right (PTree.t type) (prod ident type) (fun v : prod ident type => @PTree.set type (@fst ident type v) (@snd ident type v)) (PTree.empty type) vs))) (@Some type t)) (or (@eq (prod positive type) (@pair ident type i t0) (@pair positive type id t)) (@In (prod positive type) (@pair positive type id t) vs)) *)
 inv H0.
(* Goal: @ex (Ctypes.fundef function) (fun f : Ctypes.fundef function => and (@In (prod ident (Ctypes.fundef function)) (@pair ident (Ctypes.fundef function) i f) (@cons (prod ident (Ctypes.fundef function)) (@pair ident fundef i0 fd) g)) (@eq type (type_of_fundef f) (Tfunction (type_of_params (@fst (list (prod ident type)) type fsig')) (@snd (list (prod ident type)) type fsig') cc'))) *)
 simpl in H5.
(* Goal: and (@eq (option block) (@Some block loc') (@Some block loc')) (@ex funspec (fun fs : funspec => @eq (option funspec) (@PTree.get funspec i (make_tycontext_s G)) (@Some funspec fs))) *)
 if_tac in H5. subst i0. inv H5. exists fd; split; auto. left; auto.
(* Goal: and (@eq (option block) (@Some block loc') (@Some block loc')) (@ex funspec (fun fs : funspec => @eq (option funspec) (@PTree.get funspec i (make_tycontext_s G)) (@Some funspec fs))) *)
 destruct (IHg G0) as [f3 [? ?]]; auto. exists f3; split; auto.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
 right; auto.
(*
 destruct (IHg _ H3 H5) as [f [H4 H4']].
(* Goal: and (@eq (option block) (@Some block loc') (@Some block loc')) (@ex funspec (fun fs : funspec => @eq (option funspec) (@PTree.get funspec i (make_tycontext_s G)) (@Some funspec fs))) *)
 exists f; split; auto. right; auto.
*)
 }
(* Goal: @ex funspec (fun fs : funspec => @eq (option funspec) (@PTree.get funspec i (make_tycontext_s G)) (@Some funspec fs)) *)
 clear H4.
(* Goal: @ex funspec (fun fs : funspec => @eq (option funspec) (@PTree.get funspec i (make_tycontext_s G)) (@Some funspec fs)) *)
 destruct H6 as [f [H4 H4']].
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
 destruct (find_funct_ptr_exists prog i f) as [b [? ?]]; auto.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
 apply in_prog_funct_in_prog_defs; auto.
 unfold fundef in *.
(* Goal: @ex funspec (fun fs : funspec => @eq (option funspec) (@PTree.get funspec i (make_tycontext_s G)) (@Some funspec fs)) *)
 inversion2 H3 H6.
(* Goal: forall (id : positive) (ty : type), iff (@eq (option type) (@PTree.get type id (make_tycontext_v (@nil (prod ident type)))) (@Some type ty)) (@ex block (fun v : block => @eq (option (prod block type)) (@Map.get (prod block type) (make_venv empty_env) id) (@Some (prod block type) (@pair block type v ty)))) *)
 case_eq (Genv.find_var_info (Genv.globalenv prog) loc'); intros.
(* Goal: @ex funspec (fun fs : funspec => @eq (option funspec) (@PTree.get funspec i (make_tycontext_s G)) (@Some funspec fs)) *)
(* Goal: @ex funspec (fun fs : funspec => @eq (option funspec) (@PTree.get funspec i (make_tycontext_s G)) (@Some funspec fs)) *)
 elimtype False; clear - H7 H6.
(* Goal: False *)
(* Goal: @ex funspec (fun fs : funspec => @eq (option funspec) (@PTree.get funspec i (make_tycontext_s G)) (@Some funspec fs)) *)
 unfold Genv.find_funct_ptr in H7.
(* Goal: False *)
(* Goal: @ex funspec (fun fs : funspec => @eq (option funspec) (@PTree.get funspec i (make_tycontext_s G)) (@Some funspec fs)) *)
 unfold Genv.find_var_info in H6.
(* Goal: @ex val (fun v : val => and (@eq (option val) (@PTree.get val id (PTree.empty val)) (@Some val v)) (tc_val' ty v)) *)
 destruct (Genv.find_def (Genv.globalenv prog) loc'); try destruct g0; congruence.
(* Goal: @ex funspec (fun fs : funspec => @eq (option funspec) (@PTree.get funspec i (make_tycontext_s G)) (@Some funspec fs)) *)
 apply find_id_e in H5. apply in_map_fst in H5.
(* Goal: @ex funspec (fun fs : funspec => @eq (option funspec) (@PTree.get funspec i (make_tycontext_s G)) (@Some funspec fs)) *)
 clear - H5.
(* Goal: @eq (option type) (@None type) (@Some type t) *)
 revert H5; induction G; simpl; intro. contradiction.
(* Goal: @In ident i (@map (prod ident (globvar type)) ident (@fst ident (globvar type)) vl) *)
(* Goal: iff (@eq (option type) (@PTree.get type id (make_tycontext_g vs (@cons (prod ident funspec) (@pair ident funspec i fspec) G0))) (@Some type t)) (or (@ex funspec (fun f : funspec => and (@In (prod positive funspec) (@pair positive funspec id f) (@cons (prod ident funspec) (@pair ident funspec i fspec) G0)) (@eq type t (type_of_funspec f)))) (@In (prod positive type) (@pair positive type id t) vs)) *)
 destruct H5. subst.
(* Goal: @ex funspec (fun fs : funspec => @eq (option funspec) (@PTree.get funspec i (let (id, f) := a in @PTree.set funspec id f (make_tycontext_s G))) (@Some funspec fs)) *)
 change (@ptree_set) with (@PTree.set) in *. destruct a; simpl in *.
(* Goal: @ex funspec (fun fs : funspec => @eq (option funspec) (@PTree.get funspec i (@PTree.set funspec i f (make_tycontext_s G))) (@Some funspec fs)) *)
(* Goal: @ex funspec (fun fs : funspec => @eq (option funspec) (@PTree.get funspec i (let (id, f) := a in @ptree_set funspec id f (make_tycontext_s G))) (@Some funspec fs)) *)
 econstructor; rewrite PTree.gss; reflexivity.
(* Goal: @ex funspec (fun fs : funspec => @eq (option funspec) (@PTree.get funspec i (let (id, f) := a in @ptree_set funspec id f (make_tycontext_s G))) (@Some funspec fs)) *)
 destruct (IHG H) as [fs ?].
(* Goal: @ex funspec (fun fs : funspec => @eq (option funspec) (@PTree.get funspec i (let (id, f) := a in @PTree.set funspec id f (make_tycontext_s G))) (@Some funspec fs)) *)
 change (@ptree_set) with (@PTree.set) in *. destruct a; simpl in *.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
 destruct (eq_dec i0 i). econstructor; subst; rewrite PTree.gss; eauto.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
 econstructor; rewrite PTree.gso by auto; eauto.
Qed.

Lemma prog_contains_prog_funct: forall prog: program,
      list_norepet (prog_defs_names prog) ->
          prog_contains (globalenv prog) (prog_funct prog).
Proof.
(* Goal: forall (id : positive) (ty : type), iff (@eq (option type) (@PTree.get type id (make_tycontext_v (@nil (prod ident type)))) (@Some type ty)) (@ex block (fun v : block => @eq (option (prod block type)) (@Map.get (prod block type) (make_venv empty_env) id) (@Some (prod block type) (@pair block type v ty)))) *)
  intros; intro; intros.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
  apply (find_funct_ptr_exists prog id f); auto.
(* Goal: @In (prod ident (globdef (Ctypes.fundef function) type)) (@pair ident (globdef (Ctypes.fundef function) type) id (@Gfun (Ctypes.fundef function) type f)) (@prog_defs function prog) *)
  unfold prog_funct in H0.
(* Goal: @In (prod ident (globdef (Ctypes.fundef function) type)) (@pair ident (globdef (Ctypes.fundef function) type) id (@Gfun (Ctypes.fundef function) type f)) (@prog_defs function prog) *)
  change (AST.prog_defs prog) with (prog_defs prog).
(* Goal: iff (@eq (option type) (@PTree.get type id (@PTree.set type (@fst ident type (@pair ident type i t0)) (@snd ident type (@pair ident type i t0)) (@fold_right (PTree.t type) (prod ident type) (fun v : prod ident type => @PTree.set type (@fst ident type v) (@snd ident type v)) (PTree.empty type) vs))) (@Some type t)) (or (@eq (prod positive type) (@pair ident type i t0) (@pair positive type id t)) (@In (prod positive type) (@pair positive type id t) vs)) *)
  induction (prog_defs prog). inv H0.
(* Goal: @In (prod ident (globdef (Ctypes.fundef function) type)) (@pair ident (globdef (Ctypes.fundef function) type) id (@Gfun (Ctypes.fundef function) type f)) (@cons (prod ident (globdef (Ctypes.fundef function) type)) (@pair ident (globdef (Ctypes.fundef function) type) i (@Gfun (Ctypes.fundef function) type f0)) l) *)
(* Goal: @In (prod ident (globdef (Ctypes.fundef function) type)) (@pair ident (globdef (Ctypes.fundef function) type) id (@Gfun (Ctypes.fundef function) type f)) (@cons (prod ident (globdef (Ctypes.fundef function) type)) (@pair ident (globdef (Ctypes.fundef function) type) i (@Gvar (Ctypes.fundef function) type v)) l) *)
   simpl in H0.  destruct a.
(* Goal: @In (prod ident (globdef (Ctypes.fundef function) type)) (@pair ident (globdef (Ctypes.fundef function) type) id (@Gfun (Ctypes.fundef function) type f)) (@cons (prod ident (globdef (Ctypes.fundef function) type)) (@pair ident (globdef (Ctypes.fundef function) type) i (@Gfun (Ctypes.fundef function) type f0)) l) *)
(* Goal: @In (prod ident (globdef (Ctypes.fundef function) type)) (@pair ident (globdef (Ctypes.fundef function) type) id (@Gfun (Ctypes.fundef function) type f)) (@cons (prod ident (globdef (Ctypes.fundef function) type)) (@pair ident (globdef (Ctypes.fundef function) type) i (@Gvar (Ctypes.fundef function) type v)) l) *)
  destruct g. simpl in H0. destruct H0. inv H0.  left. auto.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
  right; auto.  right; auto.
Qed.

Lemma funassert_initial_core_ext:
  forall (ora : OK_ty) (prog: program) ve te V G n,
      list_norepet (prog_defs_names prog) ->
      match_fdecs (prog_funct prog) G ->
      app_pred (funassert (nofunc_tycontext V G) (mkEnviron (filter_genv (globalenv prog)) ve te))
                      (initial_core_ext ora (Genv.globalenv prog) G n).
Proof.
(* Goal: and (var_sizes_ok (genv_cenv ge) (fn_vars f)) (and (@eq funsig fsig (fn_funsig f)) (@eq calling_convention (fn_callconv f) cc')) *)
(* Goal: @app_pred nat ag_nat (@allp nat ag_nat (list Type) (fun ts : list Type => @allp nat ag_nat (_functor (dependent_type_functor_rec ts A') (@pred rmap ag_rmap)) (fun x : _functor (dependent_type_functor_rec ts A') (@pred rmap ag_rmap) => @box nat ag_nat (@laterM nat ag_nat) (@semax' C Espec (func_tycontext' f (nofunc_tycontext V G)) (fun rho : environ => @andp rmap ag_rmap (@sepcon rmap Join_rmap Perm_rmap ag_rmap Age_rmap (bind_args (fn_params f) (fn_vars f) (P' ts x) rho) (stackframe_of' (genv_cenv ge) f rho)) (funassert (func_tycontext' f (nofunc_tycontext V G)) rho)) (Ssequence (fn_body f) (Sreturn (@None expr))) (frame_ret_assert (function_body_ret_assert (fn_return f) (Q' ts x)) (stackframe_of' (genv_cenv ge) f)))))) n *)
 intros; split.
*
(* Goal: @app_pred rmap ag_rmap (@allp rmap ag_rmap ident (fun id : ident => @allp rmap ag_rmap funspec (fun fs : funspec => @imp rmap ag_rmap (@prop rmap ag_rmap (@eq (option funspec) (@PTree.get funspec id (glob_specs (nofunc_tycontext V G))) (@Some funspec fs))) (@exp rmap ag_rmap block (fun b : block => @andp rmap ag_rmap (@prop rmap ag_rmap (@eq (option block) (@Map.get block (ge_of (mkEnviron (filter_genv (globalenv prog)) ve te)) id) (@Some block b))) (func_at fs (@pair block Z b Z0))))))) (@initial_world.initial_core_ext function (@OK_ty Espec) ora (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) *)
 intros id fs.
(* Goal: forall (id : positive) (ty : type), iff (@eq (option type) (@PTree.get type id (make_tycontext_v (@nil (prod ident type)))) (@Some type ty)) (@ex block (fun v : block => @eq (option (prod block type)) (@Map.get (prod block type) (make_venv empty_env) id) (@Some (prod block type) (@pair block type v ty)))) *)
 apply prop_imp_i; intros.
(* Goal: @app_pred rmap ag_rmap (@exp rmap ag_rmap block (fun b : block => @andp rmap ag_rmap (@prop rmap ag_rmap (@eq (option block) (@Map.get block (ge_of (mkEnviron (filter_genv (globalenv prog)) ve te)) id) (@Some block b))) (func_at fs (@pair block Z b Z0)))) (@initial_world.initial_core_ext function (@OK_ty Espec) ora (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) *)
 simpl ge_of; simpl fst; simpl snd.
(* Goal: and (@eq (option block) (@Map.get block (filter_genv (globalenv prog)) i) (@Some block loc')) (@ex funspec (fun fs : funspec => @eq (option funspec) (@PTree.get funspec i (make_tycontext_s G)) (@Some funspec fs))) *)
 unfold filter_genv, Map.get.
(* Goal: @ex val (fun v : val => and (@eq (option val) (if ident_eq i p then @Some val (@fst val type a) else @Map.get val (make_tenv (temp_bindings (Pos.add p xH) (@map (prod val type) val (@fst val type) typed_args))) i) (@Some val v)) (tc_val' ty v)) *)
 assert (exists f, In (id, f) (prog_funct prog)). {
(* Goal: @In (prod ident funspec) (@pair ident funspec id (mk_funspec f0 cc0 A a a0 P_ne Q_ne)) G *)
 simpl in H1.
(* Goal: @ex (Ctypes.fundef function) (fun f : Ctypes.fundef function => and (@In (prod ident (Ctypes.fundef function)) (@pair ident (Ctypes.fundef function) i f) (@initial_world.prog_funct function prog)) (@eq type (type_of_fundef f) (Tfunction (type_of_params (@fst (list (prod ident type)) type fsig')) (@snd (list (prod ident type)) type fsig') cc'))) *)
 forget (prog_funct prog) as g.
(* Goal: @ex (Ctypes.fundef function) (fun f : Ctypes.fundef function => @In (prod ident (Ctypes.fundef function)) (@pair ident (Ctypes.fundef function) id f) g) *)
clear - H1 H0.
revert G H1 H0; induction g; destruct G; intros; simpl in *.
(* Goal: @ex (Ctypes.fundef function) (fun _ : Ctypes.fundef function => False) *)
(* Goal: @ex (Ctypes.fundef function) (fun _ : Ctypes.fundef function => False) *)
(* Goal: @ex (Ctypes.fundef function) (fun f : Ctypes.fundef function => or (@eq (prod ident (Ctypes.fundef function)) a (@pair ident (Ctypes.fundef function) id f)) (@In (prod ident (Ctypes.fundef function)) (@pair ident (Ctypes.fundef function) id f) g)) *)
(* Goal: @ex (Ctypes.fundef function) (fun f : Ctypes.fundef function => or (@eq (prod ident (Ctypes.fundef function)) a (@pair ident (Ctypes.fundef function) id f)) (@In (prod ident (Ctypes.fundef function)) (@pair ident (Ctypes.fundef function) id f) g)) *)
elimtype False.
(* Goal: iff (@eq (option type) (@PTree.get type id (make_tycontext_g vs G)) (@Some type t)) (or (@ex funspec (fun f : funspec => and (@In (prod positive funspec) (@pair positive funspec id f) G) (@eq type t (type_of_funspec f)))) (@In (prod positive type) (@pair positive type id t) vs)) *)
rewrite PTree.gempty in H1; inv H1.
(* Goal: iff (@eq (option type) (@PTree.get type id (@PTree.set type (@fst ident type (@pair ident type i t0)) (@snd ident type (@pair ident type i t0)) (@fold_right (PTree.t type) (prod ident type) (fun v : prod ident type => @PTree.set type (@fst ident type v) (@snd ident type v)) (PTree.empty type) vs))) (@Some type t)) (or (@eq (prod positive type) (@pair ident type i t0) (@pair positive type id t)) (@In (prod positive type) (@pair positive type id t) vs)) *)
inv H0.
(* Goal: @In ident i (@map (prod ident (globvar type)) ident (@fst ident (globvar type)) vl) *)
(* Goal: iff (@eq (option type) (@PTree.get type id (make_tycontext_g vs (@cons (prod ident funspec) (@pair ident funspec i fspec) G0))) (@Some type t)) (or (@ex funspec (fun f : funspec => and (@In (prod positive funspec) (@pair positive funspec id f) (@cons (prod ident funspec) (@pair ident funspec i fspec) G0)) (@eq type t (type_of_funspec f)))) (@In (prod positive type) (@pair positive type id t) vs)) *)
destruct a; simpl in *; subst.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
destruct (eq_dec i id). subst; eauto.
(* Goal: iff (@eq (option type) (@PTree.get type id (@PTree.set type (@fst ident type (@pair ident type i t0)) (@snd ident type (@pair ident type i t0)) (@fold_right (PTree.t type) (prod ident type) (fun v : prod ident type => @PTree.set type (@fst ident type v) (@snd ident type v)) (PTree.empty type) vs))) (@Some type t)) (or (@eq (prod positive type) (@pair ident type i t0) (@pair positive type id t)) (@In (prod positive type) (@pair positive type id t) vs)) *)
 specialize (IHg nil H1). inv H0.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
(*destruct (IHg). destruct g; simpl; auto.
(* Goal: @list_norepet ident (@map (prod ident fundef) ident (@fst ident fundef) (@prog_funct' (Ctypes.fundef function) type (@nil (prod ident (globdef (Ctypes.fundef function) type))))) *)
(* Goal: @list_norepet ident (@map (prod ident fundef) ident (@fst ident fundef) (@prog_funct' (Ctypes.fundef function) type (@cons (prod ident (globdef (Ctypes.fundef function) type)) a l))) *)
(* Goal: @ex block (fun b : block => @eq (option block) (@Map.get block (@Genv.find_symbol fundef type (genv_genv (globalenv prog))) id) (@Some block b)) *)
constructor. apply match_fdecs_nil.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
eauto. *)
(* Goal: or (@eq ident (@fst ident (globdef (Ctypes.fundef function) type) a) i) (@In ident i (@map (prod ident (globdef (Ctypes.fundef function) type)) ident (@fst ident (globdef (Ctypes.fundef function) type)) l)) *)
(* Goal: @list_norepet ident (@map (prod ident fundef) ident (@fst ident fundef) (@prog_funct' (Ctypes.fundef function) type l)) *)
(* Goal: @ex block (fun b : block => @eq (option block) (@Map.get block (@Genv.find_symbol fundef type (genv_genv (globalenv prog))) id) (@Some block b)) *)
destruct a. destruct p.
(* Goal: iff (@eq (option type) (@PTree.get type id (@PTree.set type (@fst ident type (@pair ident type i t0)) (@snd ident type (@pair ident type i t0)) (@fold_right (PTree.t type) (prod ident type) (fun v : prod ident type => @PTree.set type (@fst ident type v) (@snd ident type v)) (PTree.empty type) vs))) (@Some type t)) (or (@eq (prod positive type) (@pair ident type i t0) (@pair positive type id t)) (@In (prod positive type) (@pair positive type id t) vs)) *)
 inv H0.
(* Goal: @In (prod ident funspec) (@pair ident funspec id (mk_funspec f0 cc0 A a a0 P_ne Q_ne)) G *)
 simpl in H1.
(* Goal: @In ident i (@map (prod ident (globvar type)) ident (@fst ident (globvar type)) vl) *)
(* Goal: iff (@eq (option type) (@PTree.get type id (make_tycontext_g vs (@cons (prod ident funspec) (@pair ident funspec i fspec) G0))) (@Some type t)) (or (@ex funspec (fun f : funspec => and (@In (prod positive funspec) (@pair positive funspec id f) (@cons (prod ident funspec) (@pair ident funspec i fspec) G0)) (@eq type t (type_of_funspec f)))) (@In (prod positive type) (@pair positive type id t) vs)) *)
 destruct (ident_eq i0 id). subst. eauto.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
 destruct (IHg G); auto. rewrite PTree.gso in H1; auto.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
 eauto.
(* Goal: @In (prod ident funspec) (@pair ident funspec id (mk_funspec f0 cc0 A a a0 P_ne Q_ne)) G *)
(* simpl in H1.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
 destruct (IHg ((i0,f0)::G)); auto. eauto.
*)
 }
(* Goal: @app_pred rmap ag_rmap (@exp rmap ag_rmap block (fun b : block => @andp rmap ag_rmap (@prop rmap ag_rmap (@eq (option block) (@Genv.find_symbol fundef type (genv_genv (globalenv prog)) id) (@Some block b))) (func_at fs (@pair block Z b Z0)))) (@initial_world.initial_core_ext function (@OK_ty Espec) ora (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) *)
 destruct H2 as [f ?].
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
 destruct (find_funct_ptr_exists prog id f) as [b [? ?]]; auto.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
 apply in_prog_funct_in_prog_defs; auto.
(* Goal: @app_pred rmap ag_rmap (@exp rmap ag_rmap block (fun b : block => @andp rmap ag_rmap (@prop rmap ag_rmap (@eq (option block) (@Genv.find_symbol fundef type (genv_genv (globalenv prog)) id) (@Some block b))) (func_at fs (@pair block Z b Z0)))) (@initial_world.initial_core_ext function (@OK_ty Espec) ora (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) *)
 exists b. unfold fundef.
(* Goal: forall _ : @ex block (fun v : block => @eq (option (prod block type)) (@Map.get (prod block type) (ve_of (construct_rho (filter_genv (globalenv prog)) empty_env (@PTree.set val xH (Vptr b Ptrofs.zero) (temp_bindings (xO xH) (@map (prod val type) val (@fst val type) typed_args))))) id) (@Some (prod block type) (@pair block type v ty))), @eq (option type) (@PTree.get type id (var_types (@Delta_types vs G C (@map (prod val type) type (@snd val type) typed_args)))) (@Some type ty) *)
 unfold globalenv. simpl. rewrite H3.
(* Goal: and (@eq (option block) (@Some block loc') (@Some block loc')) (@ex funspec (fun fs : funspec => @eq (option funspec) (@PTree.get funspec i (make_tycontext_s G)) (@Some funspec fs))) *)
 split; auto.
(* Goal: @app_pred rmap ag_rmap (@imp rmap ag_rmap (func_at' (mk_funspec fsig' cc' A' P' Q' NEP' NEQ') (@pair block Z loc' Z0)) (@exp rmap ag_rmap ident (fun id : ident => @andp rmap ag_rmap (@prop rmap ag_rmap (@eq (option block) (@Map.get block (ge_of (mkEnviron (filter_genv (globalenv prog)) ve te)) id) (@Some block loc'))) (@prop rmap ag_rmap (@ex funspec (fun fs : funspec => @eq (option funspec) (@PTree.get funspec id (glob_specs (nofunc_tycontext V G))) (@Some funspec fs))))))) (@initial_world.initial_core_ext function (@OK_ty Espec) ora (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) *)
 unfold func_at. destruct fs as [f0 cc0 A a a0].
(* Goal: @app_pred rmap ag_rmap (pureat (SomeP (SpecTT A) (@packPQ A a a0)) (FUN f0 cc0) (@pair block Z b Z0)) (@initial_world.initial_core_ext function (@OK_ty Espec) ora (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) *)
 unfold initial_core_ext.
(* Goal: @app_pred rmap ag_rmap (pureat (SomeP (SpecTT A) (@packPQ A a a0)) (FUN f0 cc0) (@pair block Z b Z0)) (@proj1_sig rmap (fun phi : rmap => and (@eq nat (@level rmap ag_rmap phi) n) (and (@eq (forall _ : AV.address, resource) (resource_at phi) (@initial_world.initial_core' function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n)) (@eq ghost (ghost_of phi) (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) NoneP)) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds))))))) (make_rmap (@initial_world.initial_core' function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) NoneP)) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)))) n (initial_world.initial_core_ext_obligation_1 function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) (@eq_refl ghost (ghost_fmap (approx n) (approx n) (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) NoneP)) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)))))))) *)
 hnf. rewrite resource_at_make_rmap.
(* Goal: @eq resource (@initial_world.initial_core' function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n (@pair block Z b Z0)) (PURE (FUN f0 cc0) (preds_fmap (approx (@level rmap ag_rmap (@proj1_sig rmap (fun phi : rmap => and (@eq nat (@level rmap ag_rmap phi) n) (and (@eq (forall _ : AV.address, resource) (resource_at phi) (@initial_world.initial_core' function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n)) (@eq ghost (ghost_of phi) (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) NoneP)) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds))))))) (make_rmap (@initial_world.initial_core' function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) NoneP)) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)))) n (initial_world.initial_core_ext_obligation_1 function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) (@eq_refl ghost (ghost_fmap (approx n) (approx n) (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) NoneP)) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)))))))))) (approx (@level rmap ag_rmap (@proj1_sig rmap (fun phi : rmap => and (@eq nat (@level rmap ag_rmap phi) n) (and (@eq (forall _ : AV.address, resource) (resource_at phi) (@initial_world.initial_core' function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n)) (@eq ghost (ghost_of phi) (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) NoneP)) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds))))))) (make_rmap (@initial_world.initial_core' function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) NoneP)) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)))) n (initial_world.initial_core_ext_obligation_1 function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) (@eq_refl ghost (ghost_fmap (approx n) (approx n) (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) NoneP)) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)))))))))) (SomeP (SpecTT A) (@packPQ A a a0)))) *)
 rewrite level_make_rmap.
(* Goal: @eq resource (@core resource Join_resource Sep_resource match access_at m l Cur with | Some (Freeable as p) => YES Share.top readable_share_top (VAL (contents_at m l)) NoneP | Some (Writable as p) => YES Ews (@writable_readable Ews writable_Ews) (VAL (contents_at m l)) NoneP | Some (Readable as p) => YES Ers readable_Ers (VAL (contents_at m l)) NoneP | Some (Nonempty as p) => match @initial_world.initial_core' function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n l with | NO sh n => NO extern_retainer nonreadable_extern_retainer | YES sh r k p0 => NO extern_retainer nonreadable_extern_retainer | PURE k p0 => @initial_world.initial_core' function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n l end | None => NO Share.bot bot_unreadable end) (@initial_world.initial_core' function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n l) *)
(* Goal: @eq ghost (ghost_of (@core rmap Join_rmap Sep_rmap (inflate_initial_mem m (@initial_world.initial_core_ext function (@OK_ty Espec) ora (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n)))) (ghost_of (@initial_world.initial_core function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n)) *)
 unfold initial_core'.
(* Goal: forall _ : @ex block (fun v : block => @eq (option (prod block type)) (@Map.get (prod block type) (ve_of (construct_rho (filter_genv (globalenv prog)) empty_env (@PTree.set val xH (Vptr b Ptrofs.zero) (temp_bindings (xO xH) (@map (prod val type) val (@fst val type) typed_args))))) id) (@Some (prod block type) (@pair block type v ty))), @eq (option type) (@PTree.get type id (var_types (@Delta_types vs G C (@map (prod val type) type (@snd val type) typed_args)))) (@Some type ty) *)
 simpl.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
 rewrite (Genv.find_invert_symbol (Genv.globalenv prog) id); auto.
(* Goal: @ex val (fun v : val => and (@eq (option val) (if ident_eq i p then @Some val (@fst val type a) else @Map.get val (make_tenv (temp_bindings (Pos.add p xH) (@map (prod val type) val (@fst val type) typed_args))) i) (@Some val v)) (tc_val' ty v)) *)
 assert (H9: In (id, mk_funspec f0 cc0 A a a0 P_ne Q_ne) G). {
(* Goal: False *)
(* Goal: @eq (option type) (@Some type t0) (@Some type t) *)
   clear - H1.
(* Goal: @In (prod ident funspec) (@pair ident funspec id (mk_funspec f0 cc0 A a a0 P_ne Q_ne)) G *)
    simpl in H1. unfold make_tycontext_g in H1; simpl in H1.
    induction G; simpl in *.
(* Goal: iff (@eq (option type) (@PTree.get type id (make_tycontext_g vs G)) (@Some type t)) (or (@ex funspec (fun f : funspec => and (@In (prod positive funspec) (@pair positive funspec id f) G) (@eq type t (type_of_funspec f)))) (@In (prod positive type) (@pair positive type id t) vs)) *)
    rewrite PTree.gempty in H1; inv H1.
(* Goal: @In ident i (@map (prod ident (globvar type)) ident (@fst ident (globvar type)) vl) *)
(* Goal: iff (@eq (option type) (@PTree.get type id (make_tycontext_g vs (@cons (prod ident funspec) (@pair ident funspec i fspec) G0))) (@Some type t)) (or (@ex funspec (fun f : funspec => and (@In (prod positive funspec) (@pair positive funspec id f) (@cons (prod ident funspec) (@pair ident funspec i fspec) G0)) (@eq type t (type_of_funspec f)))) (@In (prod positive type) (@pair positive type id t) vs)) *)
    destruct (ident_eq (fst a1) id); subst.
    change (@ptree_set) with (@PTree.set) in *. destruct a1; simpl in *.
(* Goal: iff (@eq (option type) (@PTree.get type id (make_tycontext_g vs G)) (@Some type t)) (or (@ex funspec (fun f : funspec => and (@In (prod positive funspec) (@pair positive funspec id f) G) (@eq type t (type_of_funspec f)))) (@In (prod positive type) (@pair positive type id t) vs)) *)
    rewrite PTree.gss in H1; inv H1. left; auto.
    change (@ptree_set) with (@PTree.set) in *. destruct a1; simpl in *. 
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
    rewrite PTree.gso in H1; auto.
 }
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
 rewrite (find_id_i _ _ _ H9); auto.
 clear - H0 H. unfold prog_defs_names, prog_funct in *.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
 eapply match_fdecs_norepet; eauto.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
 apply list_norepet_prog_funct'; auto.
*
 intros loc'  [fsig' cc' A' P' Q' NEP' NEQ'].
(* Goal: @app_pred rmap ag_rmap (@imp rmap ag_rmap (func_at' (mk_funspec fsig' cc' A' P' Q' NEP' NEQ') (@pair block Z loc' Z0)) (@exp rmap ag_rmap ident (fun id : ident => @andp rmap ag_rmap (@prop rmap ag_rmap (@eq (option block) (@Map.get block (ge_of (mkEnviron (filter_genv (globalenv prog)) ve te)) id) (@Some block loc'))) (@prop rmap ag_rmap (@ex funspec (fun fs : funspec => @eq (option funspec) (@PTree.get funspec id (glob_specs (nofunc_tycontext V G))) (@Some funspec fs))))))) (@initial_world.initial_core_ext function (@OK_ty Espec) ora (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) *)
 unfold func_at.
(* Goal: @app_pred rmap ag_rmap (@imp rmap ag_rmap (func_at' (mk_funspec fsig' cc' A' P' Q' NEP' NEQ') (@pair block Z loc' Z0)) (@exp rmap ag_rmap ident (fun id : ident => @andp rmap ag_rmap (@prop rmap ag_rmap (@eq (option block) (@Map.get block (ge_of (mkEnviron (filter_genv (globalenv prog)) ve te)) id) (@Some block loc'))) (@prop rmap ag_rmap (@ex funspec (fun fs : funspec => @eq (option funspec) (@PTree.get funspec id (glob_specs (nofunc_tycontext V G))) (@Some funspec fs))))))) (@initial_world.initial_core_ext function (@OK_ty Espec) ora (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) *)
 intros w ? ?.
(* Goal: @app_pred rmap ag_rmap (@exp rmap ag_rmap ident (fun id : ident => @andp rmap ag_rmap (@prop rmap ag_rmap (@eq (option block) (@Map.get block (ge_of (mkEnviron (filter_genv (globalenv prog)) ve te)) id) (@Some block loc'))) (@prop rmap ag_rmap (@ex funspec (fun fs : funspec => @eq (option funspec) (@PTree.get funspec id (glob_specs (nofunc_tycontext V G))) (@Some funspec fs)))))) w *)
 destruct H2 as [pp ?].
(* Goal: @app_pred rmap ag_rmap (@exp rmap ag_rmap ident (fun id : ident => @andp rmap ag_rmap (@prop rmap ag_rmap (@eq (option block) (@Map.get block (ge_of (mkEnviron (filter_genv (globalenv prog)) ve te)) id) (@Some block loc'))) (@prop rmap ag_rmap (@ex funspec (fun fs : funspec => @eq (option funspec) (@PTree.get funspec id (glob_specs (nofunc_tycontext V G))) (@Some funspec fs)))))) w *)
 hnf in H2.
(* Goal: @app_pred rmap ag_rmap (@exp rmap ag_rmap ident (fun id : ident => @andp rmap ag_rmap (@prop rmap ag_rmap (@eq (option block) (@Map.get block (ge_of (mkEnviron (filter_genv (globalenv prog)) ve te)) id) (@Some block loc'))) (@prop rmap ag_rmap (@ex funspec (fun fs : funspec => @eq (option funspec) (@PTree.get funspec id (glob_specs (nofunc_tycontext V G))) (@Some funspec fs)))))) w *)
 assert (exists pp, initial_core_ext ora (Genv.globalenv prog) G n @ (loc',0) = PURE (FUN fsig' cc') pp).
(* Goal: forall (id : positive) (ty : type), iff (@eq (option type) (@PTree.get type id (make_tycontext_v (@nil (prod ident type)))) (@Some type ty)) (@ex block (fun v : block => @eq (option (prod block type)) (@Map.get (prod block type) (make_venv empty_env) id) (@Some (prod block type) (@pair block type v ty)))) *)
case_eq (initial_core_ext ora (Genv.globalenv prog) G n @ (loc',0)); intros.
(* Goal: @ex preds (fun pp : preds => @eq resource (NO sh n0) (PURE (FUN fsig' cc') pp)) *)
(* Goal: @ex preds (fun pp : preds => @eq resource (YES sh r k p) (PURE (FUN fsig' cc') pp)) *)
(* Goal: @ex preds (fun pp : preds => @eq resource (PURE k p) (PURE (FUN fsig' cc') pp)) *)
(* Goal: @app_pred rmap ag_rmap (@exp rmap ag_rmap ident (fun id : ident => @andp rmap ag_rmap (@prop rmap ag_rmap (@eq (option block) (@Map.get block (ge_of (mkEnviron (filter_genv (globalenv prog)) ve te)) id) (@Some block loc'))) (@prop rmap ag_rmap (@ex funspec (fun fs : funspec => @eq (option funspec) (@PTree.get funspec id (glob_specs (nofunc_tycontext V G))) (@Some funspec fs)))))) w *)
destruct (necR_NO _ _ (loc',0) sh n0 H1) as [? _].
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
rewrite H4 in H2 by auto.
(* Goal: @ex block (fun v : block => @eq (option (prod block type)) (@None (prod block type)) (@Some (prod block type) (@pair block type v ty))) *)
(* Goal: @eq (option type) (@None type) (@Some type ty) *)
inv H2.
(* Goal: @ex preds (fun pp : preds => @eq resource (YES sh r k p) (PURE (FUN fsig' cc') pp)) *)
(* Goal: @ex preds (fun pp : preds => @eq resource (PURE k p) (PURE (FUN fsig' cc') pp)) *)
(* Goal: @app_pred rmap ag_rmap (@exp rmap ag_rmap ident (fun id : ident => @andp rmap ag_rmap (@prop rmap ag_rmap (@eq (option block) (@Map.get block (ge_of (mkEnviron (filter_genv (globalenv prog)) ve te)) id) (@Some block loc'))) (@prop rmap ag_rmap (@ex funspec (fun fs : funspec => @eq (option funspec) (@PTree.get funspec id (glob_specs (nofunc_tycontext V G))) (@Some funspec fs)))))) w *)
eapply necR_YES in H1; try apply H3.
(* Goal: @ex block (fun v : block => @eq (option (prod block type)) (@None (prod block type)) (@Some (prod block type) (@pair block type v ty))) *)
(* Goal: @eq (option type) (@None type) (@Some type ty) *)
rewrite H1 in H2; inv H2.
(* Goal: @ex preds (fun pp : preds => @eq resource (PURE k p) (PURE (FUN fsig' cc') pp)) *)
(* Goal: @app_pred rmap ag_rmap (@exp rmap ag_rmap ident (fun id : ident => @andp rmap ag_rmap (@prop rmap ag_rmap (@eq (option block) (@Map.get block (ge_of (mkEnviron (filter_genv (globalenv prog)) ve te)) id) (@Some block loc'))) (@prop rmap ag_rmap (@ex funspec (fun fs : funspec => @eq (option funspec) (@PTree.get funspec id (glob_specs (nofunc_tycontext V G))) (@Some funspec fs)))))) w *)
eapply necR_PURE in H1; try apply H3.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
rewrite H1 in H2; inv H2; eauto.
(* Goal: @app_pred rmap ag_rmap (@exp rmap ag_rmap ident (fun id : ident => @andp rmap ag_rmap (@prop rmap ag_rmap (@eq (option block) (@Map.get block (ge_of (mkEnviron (filter_genv (globalenv prog)) ve te)) id) (@Some block loc'))) (@prop rmap ag_rmap (@ex funspec (fun fs : funspec => @eq (option funspec) (@PTree.get funspec id (glob_specs (nofunc_tycontext V G))) (@Some funspec fs)))))) w *)
destruct H3 as [pp' ?].
(* Goal: @app_pred rmap ag_rmap (@exp rmap ag_rmap ident (fun id : ident => @andp rmap ag_rmap (@prop rmap ag_rmap (@eq (option block) (@Map.get block (ge_of (mkEnviron (filter_genv (globalenv prog)) ve te)) id) (@Some block loc'))) (@prop rmap ag_rmap (@ex funspec (fun fs : funspec => @eq (option funspec) (@PTree.get funspec id (glob_specs (nofunc_tycontext V G))) (@Some funspec fs)))))) w *)
unfold initial_core_ext in H3.
(* Goal: @app_pred rmap ag_rmap (@exp rmap ag_rmap ident (fun id : ident => @andp rmap ag_rmap (@prop rmap ag_rmap (@eq (option block) (@Map.get block (ge_of (mkEnviron (filter_genv (globalenv prog)) ve te)) id) (@Some block loc'))) (@prop rmap ag_rmap (@ex funspec (fun fs : funspec => @eq (option funspec) (@PTree.get funspec id (glob_specs (nofunc_tycontext V G))) (@Some funspec fs)))))) w *)
rewrite resource_at_make_rmap in H3.
(* Goal: @app_pred rmap ag_rmap (@exp rmap ag_rmap ident (fun id : ident => @andp rmap ag_rmap (@prop rmap ag_rmap (@eq (option block) (@Map.get block (ge_of (mkEnviron (filter_genv (globalenv prog)) ve te)) id) (@Some block loc'))) (@prop rmap ag_rmap (@ex funspec (fun fs : funspec => @eq (option funspec) (@PTree.get funspec id (glob_specs (nofunc_tycontext V G))) (@Some funspec fs)))))) w *)
unfold initial_core' in H3.
(* Goal: @app_pred rmap ag_rmap (@exp rmap ag_rmap ident (fun id : ident => @andp rmap ag_rmap (@prop rmap ag_rmap (@eq (option block) (@Map.get block (ge_of (mkEnviron (filter_genv (globalenv prog)) ve te)) id) (@Some block loc'))) (@prop rmap ag_rmap (@ex funspec (fun fs : funspec => @eq (option funspec) (@PTree.get funspec id (glob_specs (nofunc_tycontext V G))) (@Some funspec fs)))))) w *)
if_tac in H3; [ | inv H3].
(* Goal: forall _ : @ex block (fun v : block => @eq (option (prod block type)) (@Map.get (prod block type) (ve_of (construct_rho (filter_genv (globalenv prog)) empty_env (@PTree.set val xH (Vptr b Ptrofs.zero) (temp_bindings (xO xH) (@map (prod val type) val (@fst val type) typed_args))))) id) (@Some (prod block type) (@pair block type v ty))), @eq (option type) (@PTree.get type id (var_types (@Delta_types vs G C (@map (prod val type) type (@snd val type) typed_args)))) (@Some type ty) *)
simpl.
simpl @fst in *.
revert H3; case_eq (@Genv.invert_symbol (Ctypes.fundef function) type
              (@Genv.globalenv (Ctypes.fundef function) type prog) loc'); intros;
  [ | congruence].
(* Goal: @ex ident (fun b : ident => and (@eq (option block) (@Map.get block (filter_genv (globalenv prog)) b) (@Some block loc')) (@ex funspec (fun fs : funspec => @eq (option funspec) (@PTree.get funspec b (make_tycontext_s G)) (@Some funspec fs)))) *)
revert H5; case_eq (find_id i G); intros; [| congruence].
(* Goal: @ex ident (fun b : ident => and (@eq (option block) (@Map.get block (filter_genv (globalenv prog)) b) (@Some block loc')) (@ex funspec (fun fs : funspec => @eq (option funspec) (@PTree.get funspec b (make_tycontext_s G)) (@Some funspec fs)))) *)
destruct f as [?f ?A ?a ?a]; inv H6.
(* Goal: @ex ident (fun b : ident => and (@eq (option block) (@Map.get block (filter_genv (globalenv prog)) b) (@Some block loc')) (@ex funspec (fun fs : funspec => @eq (option funspec) (@PTree.get funspec b (make_tycontext_s G)) (@Some funspec fs)))) *)
apply Genv.invert_find_symbol in H3.
(* Goal: @ex ident (fun b : ident => and (@eq (option block) (@Map.get block (filter_genv (globalenv prog)) b) (@Some block loc')) (@ex funspec (fun fs : funspec => @eq (option funspec) (@PTree.get funspec b (make_tycontext_s G)) (@Some funspec fs)))) *)
exists i.
(* Goal: and (@eq (option block) (@Map.get block (filter_genv (globalenv prog)) i) (@Some block loc')) (@ex funspec (fun fs : funspec => @eq (option funspec) (@PTree.get funspec i (make_tycontext_s G)) (@Some funspec fs))) *)
simpl ge_of. unfold filter_genv, Map.get.
(* Goal: forall _ : @ex block (fun v : block => @eq (option (prod block type)) (@Map.get (prod block type) (ve_of (construct_rho (filter_genv (globalenv prog)) empty_env (@PTree.set val xH (Vptr b Ptrofs.zero) (temp_bindings (xO xH) (@map (prod val type) val (@fst val type) typed_args))))) id) (@Some (prod block type) (@pair block type v ty))), @eq (option type) (@PTree.get type id (var_types (@Delta_types vs G C (@map (prod val type) type (@snd val type) typed_args)))) (@Some type ty) *)
unfold globalenv; simpl.
(* Goal: and (@eq (option block) (@Genv.find_symbol (Ctypes.fundef function) type (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) id) (@Some block b)) (@app_pred rmap ag_rmap (func_at fs (@pair block Z b Z0)) (@initial_world.initial_core_ext function (@OK_ty Espec) ora (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n)) *)
 unfold fundef; rewrite H3.
(* Goal: and (@eq (option block) (@Some block loc') (@Some block loc')) (@ex funspec (fun fs : funspec => @eq (option funspec) (@PTree.get funspec i (make_tycontext_s G)) (@Some funspec fs))) *)
 split; auto.
 assert (exists f, In (i,f) (prog_funct prog)
(* Goal: @ex val (fun v : val => and (@eq (option val) (if ident_eq i p then @Some val (@fst val type a) else @Map.get val (make_tenv (temp_bindings (Pos.add p xH) (@map (prod val type) val (@fst val type) typed_args))) i) (@Some val v)) (tc_val' ty v)) *)
              /\ type_of_fundef f = Tfunction (type_of_params (fst fsig')) (snd fsig') cc'). {
(* Goal: @ex (Ctypes.fundef function) (fun f : Ctypes.fundef function => and (@In (prod ident (Ctypes.fundef function)) (@pair ident (Ctypes.fundef function) i f) (@initial_world.prog_funct function prog)) (@eq type (type_of_fundef f) (Tfunction (type_of_params (@fst (list (prod ident type)) type fsig')) (@snd (list (prod ident type)) type fsig') cc'))) *)
 clear - H0 H5.
(* Goal: @ex (Ctypes.fundef function) (fun f : Ctypes.fundef function => and (@In (prod ident (Ctypes.fundef function)) (@pair ident (Ctypes.fundef function) i f) (@initial_world.prog_funct function prog)) (@eq type (type_of_fundef f) (Tfunction (type_of_params (@fst (list (prod ident type)) type fsig')) (@snd (list (prod ident type)) type fsig') cc'))) *)
 forget (prog_funct prog) as g.
(* Goal: forall (id : positive) (ty : type), iff (@eq (option type) (@PTree.get type id (make_tycontext_v (@nil (prod ident type)))) (@Some type ty)) (@ex block (fun v : block => @eq (option (prod block type)) (@Map.get (prod block type) (make_venv empty_env) id) (@Some (prod block type) (@pair block type v ty)))) *)
 revert G H0 H5; induction g; intros.
(* Goal: iff (@eq (option type) (@PTree.get type id (@PTree.set type (@fst ident type (@pair ident type i t0)) (@snd ident type (@pair ident type i t0)) (@fold_right (PTree.t type) (prod ident type) (fun v : prod ident type => @PTree.set type (@fst ident type v) (@snd ident type v)) (PTree.empty type) vs))) (@Some type t)) (or (@eq (prod positive type) (@pair ident type i t0) (@pair positive type id t)) (@In (prod positive type) (@pair positive type id t) vs)) *)
 inv H0. inv H5.
(* Goal: iff (@eq (option type) (@PTree.get type id (@PTree.set type (@fst ident type (@pair ident type i t0)) (@snd ident type (@pair ident type i t0)) (@fold_right (PTree.t type) (prod ident type) (fun v : prod ident type => @PTree.set type (@fst ident type v) (@snd ident type v)) (PTree.empty type) vs))) (@Some type t)) (or (@eq (prod positive type) (@pair ident type i t0) (@pair positive type id t)) (@In (prod positive type) (@pair positive type id t) vs)) *)
 inv H0.
(* Goal: @ex (Ctypes.fundef function) (fun f : Ctypes.fundef function => and (@In (prod ident (Ctypes.fundef function)) (@pair ident (Ctypes.fundef function) i f) (@cons (prod ident (Ctypes.fundef function)) (@pair ident fundef i0 fd) g)) (@eq type (type_of_fundef f) (Tfunction (type_of_params (@fst (list (prod ident type)) type fsig')) (@snd (list (prod ident type)) type fsig') cc'))) *)
 simpl in H5.
(* Goal: and (@eq (option block) (@Some block loc') (@Some block loc')) (@ex funspec (fun fs : funspec => @eq (option funspec) (@PTree.get funspec i (make_tycontext_s G)) (@Some funspec fs))) *)
 if_tac in H5. subst i0. inv H5. exists fd; split; auto. left; auto.
(* Goal: and (@eq (option block) (@Some block loc') (@Some block loc')) (@ex funspec (fun fs : funspec => @eq (option funspec) (@PTree.get funspec i (make_tycontext_s G)) (@Some funspec fs))) *)
 destruct (IHg G0) as [f3 [? ?]]; auto. exists f3; split; auto.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
 right; auto.
(*
 destruct (IHg _ H3 H5) as [f [H4 H4']].
(* Goal: and (@eq (option block) (@Some block loc') (@Some block loc')) (@ex funspec (fun fs : funspec => @eq (option funspec) (@PTree.get funspec i (make_tycontext_s G)) (@Some funspec fs))) *)
 exists f; split; auto. right; auto.
*)
 }
(* Goal: @ex funspec (fun fs : funspec => @eq (option funspec) (@PTree.get funspec i (make_tycontext_s G)) (@Some funspec fs)) *)
 clear H4.
(* Goal: @ex funspec (fun fs : funspec => @eq (option funspec) (@PTree.get funspec i (make_tycontext_s G)) (@Some funspec fs)) *)
 destruct H6 as [f [H4 H4']].
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
 destruct (find_funct_ptr_exists prog i f) as [b [? ?]]; auto.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
 apply in_prog_funct_in_prog_defs; auto.
 unfold fundef in *.
(* Goal: @ex funspec (fun fs : funspec => @eq (option funspec) (@PTree.get funspec i (make_tycontext_s G)) (@Some funspec fs)) *)
 inversion2 H3 H6.
(* Goal: forall (id : positive) (ty : type), iff (@eq (option type) (@PTree.get type id (make_tycontext_v (@nil (prod ident type)))) (@Some type ty)) (@ex block (fun v : block => @eq (option (prod block type)) (@Map.get (prod block type) (make_venv empty_env) id) (@Some (prod block type) (@pair block type v ty)))) *)
 case_eq (Genv.find_var_info (Genv.globalenv prog) loc'); intros.
(* Goal: @ex funspec (fun fs : funspec => @eq (option funspec) (@PTree.get funspec i (make_tycontext_s G)) (@Some funspec fs)) *)
(* Goal: @ex funspec (fun fs : funspec => @eq (option funspec) (@PTree.get funspec i (make_tycontext_s G)) (@Some funspec fs)) *)
 elimtype False; clear - H7 H6.
(* Goal: False *)
(* Goal: @ex funspec (fun fs : funspec => @eq (option funspec) (@PTree.get funspec i (make_tycontext_s G)) (@Some funspec fs)) *)
 unfold Genv.find_funct_ptr in H7.
(* Goal: False *)
(* Goal: @ex funspec (fun fs : funspec => @eq (option funspec) (@PTree.get funspec i (make_tycontext_s G)) (@Some funspec fs)) *)
 unfold Genv.find_var_info in H6.
(* Goal: @ex val (fun v : val => and (@eq (option val) (@PTree.get val id (PTree.empty val)) (@Some val v)) (tc_val' ty v)) *)
 destruct (Genv.find_def (Genv.globalenv prog) loc'); try destruct g0; congruence.
(* Goal: @ex funspec (fun fs : funspec => @eq (option funspec) (@PTree.get funspec i (make_tycontext_s G)) (@Some funspec fs)) *)
 apply find_id_e in H5. apply in_map_fst in H5.
(* Goal: @ex funspec (fun fs : funspec => @eq (option funspec) (@PTree.get funspec i (make_tycontext_s G)) (@Some funspec fs)) *)
 clear - H5.
(* Goal: @eq (option type) (@None type) (@Some type t) *)
 revert H5; induction G; simpl; intro. contradiction.
(* Goal: @In ident i (@map (prod ident (globvar type)) ident (@fst ident (globvar type)) vl) *)
(* Goal: iff (@eq (option type) (@PTree.get type id (make_tycontext_g vs (@cons (prod ident funspec) (@pair ident funspec i fspec) G0))) (@Some type t)) (or (@ex funspec (fun f : funspec => and (@In (prod positive funspec) (@pair positive funspec id f) (@cons (prod ident funspec) (@pair ident funspec i fspec) G0)) (@eq type t (type_of_funspec f)))) (@In (prod positive type) (@pair positive type id t) vs)) *)
 destruct H5. subst.
(* Goal: @ex funspec (fun fs : funspec => @eq (option funspec) (@PTree.get funspec i (let (id, f) := a in @PTree.set funspec id f (make_tycontext_s G))) (@Some funspec fs)) *)
 change (@ptree_set) with (@PTree.set) in *. destruct a; simpl in *.
(* Goal: @ex funspec (fun fs : funspec => @eq (option funspec) (@PTree.get funspec i (@PTree.set funspec i f (make_tycontext_s G))) (@Some funspec fs)) *)
(* Goal: @ex funspec (fun fs : funspec => @eq (option funspec) (@PTree.get funspec i (let (id, f) := a in @ptree_set funspec id f (make_tycontext_s G))) (@Some funspec fs)) *)
 econstructor; rewrite PTree.gss; reflexivity.
(* Goal: @ex funspec (fun fs : funspec => @eq (option funspec) (@PTree.get funspec i (let (id, f) := a in @ptree_set funspec id f (make_tycontext_s G))) (@Some funspec fs)) *)
 destruct (IHG H) as [fs ?].
(* Goal: @ex funspec (fun fs : funspec => @eq (option funspec) (@PTree.get funspec i (let (id, f) := a in @PTree.set funspec id f (make_tycontext_s G))) (@Some funspec fs)) *)
 change (@ptree_set) with (@PTree.set) in *. destruct a; simpl in *.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
 destruct (eq_dec i0 i). econstructor; subst; rewrite PTree.gss; eauto.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
 econstructor; rewrite PTree.gso by auto; eauto.
Qed.

(* there's a place this lemma should be applied, perhaps in proof of semax_call *)
Lemma funassert_rho:
  forall G rho rho', ge_of rho = ge_of rho' -> funassert G rho |-- funassert G rho'.
(* Goal: forall (id : positive) (ty : type), iff (@eq (option type) (@PTree.get type id (make_tycontext_v (@nil (prod ident type)))) (@Some type ty)) (@ex block (fun v : block => @eq (option (prod block type)) (@Map.get (prod block type) (make_venv empty_env) id) (@Some (prod block type) (@pair block type v ty)))) *)
Proof. intros. apply funspecs_assert_rho; trivial. Qed.
(*Lenb: maybe move to seplog?*)

Lemma core_inflate_initial_mem:
  forall (m: mem) (prog: program) (G: funspecs) (n: nat)
     (INIT: Genv.init_mem prog = Some m),
    match_fdecs (prog_funct prog) G ->
      list_norepet (prog_defs_names prog) ->
   core (inflate_initial_mem m (initial_core (Genv.globalenv prog) G n)) =
         initial_core (Genv.globalenv prog) G n.
Proof.
(* Goal: forall (id : positive) (ty : type), iff (@eq (option type) (@PTree.get type id (make_tycontext_v (@nil (prod ident type)))) (@Some type ty)) (@ex block (fun v : block => @eq (option (prod block type)) (@Map.get (prod block type) (make_venv empty_env) id) (@Some (prod block type) (@pair block type v ty)))) *)
intros.
(* Goal: @eq rmap (@core rmap Join_rmap Sep_rmap (inflate_initial_mem m (@initial_world.initial_core function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n))) (@initial_world.initial_core function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) *)
assert (IOK := initial_core_ok _ _ n _ H0 H INIT).
(* Goal: @eq rmap (@core rmap Join_rmap Sep_rmap (inflate_initial_mem m (@initial_world.initial_core_ext function (@OK_ty Espec) ora (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n))) (@initial_world.initial_core function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) *)
apply rmap_ext.
(* Goal: forall _ : @ex block (fun v : block => @eq (option (prod block type)) (@Map.get (prod block type) (ve_of (construct_rho (filter_genv (globalenv prog)) empty_env (@PTree.set val xH (Vptr b Ptrofs.zero) (temp_bindings (xO xH) (@map (prod val type) val (@fst val type) typed_args))))) id) (@Some (prod block type) (@pair block type v ty))), @eq (option type) (@PTree.get type id (var_types (@Delta_types vs G C (@map (prod val type) type (@snd val type) typed_args)))) (@Some type ty) *)
  unfold inflate_initial_mem, initial_core; simpl.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
  rewrite level_core. do 2 rewrite level_make_rmap; auto.
(* Goal: forall l : AV.address, @eq resource (resource_at (@core rmap Join_rmap Sep_rmap (inflate_initial_mem m (@initial_world.initial_core_ext function (@OK_ty Espec) ora (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n))) l) (resource_at (@initial_world.initial_core function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) l) *)
(* Goal: @eq ghost (ghost_of (@core rmap Join_rmap Sep_rmap (inflate_initial_mem m (@initial_world.initial_core_ext function (@OK_ty Espec) ora (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n)))) (ghost_of (@initial_world.initial_core function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n)) *)
intro l.
(* Goal: forall _ : @ex block (fun v : block => @eq (option (prod block type)) (@Map.get (prod block type) (ve_of (construct_rho (filter_genv (globalenv prog)) empty_env (@PTree.set val xH (Vptr b Ptrofs.zero) (temp_bindings (xO xH) (@map (prod val type) val (@fst val type) typed_args))))) id) (@Some (prod block type) (@pair block type v ty))), @eq (option type) (@PTree.get type id (var_types (@Delta_types vs G C (@map (prod val type) type (@snd val type) typed_args)))) (@Some type ty) *)
unfold inflate_initial_mem, initial_core; simpl.
(* Goal: @eq resource (resource_at (@core rmap Join_rmap Sep_rmap (@proj1_sig rmap (fun phi : rmap => and (@eq nat (@level rmap ag_rmap phi) (@level rmap ag_rmap (@proj1_sig rmap (fun phi0 : rmap => and (@eq nat (@level rmap ag_rmap phi0) n) (and (@eq (forall _ : AV.address, resource) (resource_at phi0) (@initial_world.initial_core' function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n)) (@eq ghost (ghost_of phi0) (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) NoneP)) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds))))))) (make_rmap (@initial_world.initial_core' function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) NoneP)) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)))) n (initial_world.initial_core_ext_obligation_1 function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) (@eq_refl ghost (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) (SomeP (ConstType unit) (fun _ : list Type => tt)))) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds))))))))) (and (@eq (forall _ : AV.address, resource) (resource_at phi) (inflate_initial_mem' m (@proj1_sig rmap (fun phi0 : rmap => and (@eq nat (@level rmap ag_rmap phi0) n) (and (@eq (forall _ : AV.address, resource) (resource_at phi0) (@initial_world.initial_core' function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n)) (@eq ghost (ghost_of phi0) (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) NoneP)) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds))))))) (make_rmap (@initial_world.initial_core' function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) NoneP)) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)))) n (initial_world.initial_core_ext_obligation_1 function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) (@eq_refl ghost (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) (SomeP (ConstType unit) (fun _ : list Type => tt)))) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds))))))))) (@eq ghost (ghost_of phi) (ghost_of (@proj1_sig rmap (fun phi0 : rmap => and (@eq nat (@level rmap ag_rmap phi0) n) (and (@eq (forall _ : AV.address, resource) (resource_at phi0) (@initial_world.initial_core' function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n)) (@eq ghost (ghost_of phi0) (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) NoneP)) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds))))))) (make_rmap (@initial_world.initial_core' function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) NoneP)) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)))) n (initial_world.initial_core_ext_obligation_1 function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) (@eq_refl ghost (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) (SomeP (ConstType unit) (fun _ : list Type => tt)))) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds))))))))))) (make_rmap (inflate_initial_mem' m (@proj1_sig rmap (fun phi : rmap => and (@eq nat (@level rmap ag_rmap phi) n) (and (@eq (forall _ : AV.address, resource) (resource_at phi) (@initial_world.initial_core' function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n)) (@eq ghost (ghost_of phi) (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) NoneP)) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds))))))) (make_rmap (@initial_world.initial_core' function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) NoneP)) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)))) n (initial_world.initial_core_ext_obligation_1 function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) (@eq_refl ghost (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) (SomeP (ConstType unit) (fun _ : list Type => tt)))) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)))))))) (ghost_of (@proj1_sig rmap (fun phi : rmap => and (@eq nat (@level rmap ag_rmap phi) n) (and (@eq (forall _ : AV.address, resource) (resource_at phi) (@initial_world.initial_core' function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n)) (@eq ghost (ghost_of phi) (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) NoneP)) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds))))))) (make_rmap (@initial_world.initial_core' function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) NoneP)) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)))) n (initial_world.initial_core_ext_obligation_1 function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) (@eq_refl ghost (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) (SomeP (ConstType unit) (fun _ : list Type => tt)))) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)))))))) (@level rmap ag_rmap (@proj1_sig rmap (fun phi : rmap => and (@eq nat (@level rmap ag_rmap phi) n) (and (@eq (forall _ : AV.address, resource) (resource_at phi) (@initial_world.initial_core' function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n)) (@eq ghost (ghost_of phi) (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) NoneP)) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds))))))) (make_rmap (@initial_world.initial_core' function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) NoneP)) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)))) n (initial_world.initial_core_ext_obligation_1 function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) (@eq_refl ghost (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) (SomeP (ConstType unit) (fun _ : list Type => tt)))) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)))))))) (inflate_initial_mem'_fmap m (@proj1_sig rmap (fun phi : rmap => and (@eq nat (@level rmap ag_rmap phi) n) (and (@eq (forall _ : AV.address, resource) (resource_at phi) (@initial_world.initial_core' function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n)) (@eq ghost (ghost_of phi) (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) NoneP)) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds))))))) (make_rmap (@initial_world.initial_core' function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) NoneP)) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)))) n (initial_world.initial_core_ext_obligation_1 function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) (@eq_refl ghost (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) (SomeP (ConstType unit) (fun _ : list Type => tt)))) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)))))))) (ghost_of_approx (@proj1_sig rmap (fun phi : rmap => and (@eq nat (@level rmap ag_rmap phi) n) (and (@eq (forall _ : AV.address, resource) (resource_at phi) (@initial_world.initial_core' function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n)) (@eq ghost (ghost_of phi) (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) NoneP)) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds))))))) (make_rmap (@initial_world.initial_core' function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) NoneP)) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)))) n (initial_world.initial_core_ext_obligation_1 function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) (@eq_refl ghost (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) (SomeP (ConstType unit) (fun _ : list Type => tt)))) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds))))))))))) l) (resource_at (@proj1_sig rmap (fun phi : rmap => and (@eq nat (@level rmap ag_rmap phi) n) (and (@eq (forall _ : AV.address, resource) (resource_at phi) (@initial_world.initial_core' function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n)) (@eq ghost (ghost_of phi) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)))))) (make_rmap (@initial_world.initial_core' function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds))) n (initial_world.initial_core_obligation_1 function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) (@eq_refl ghost (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)))))) l) *)
(* Goal: @eq ghost (ghost_of (@core rmap Join_rmap Sep_rmap (inflate_initial_mem m (@initial_world.initial_core_ext function (@OK_ty Espec) ora (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n)))) (ghost_of (@initial_world.initial_core function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n)) *)
rewrite <- core_resource_at.
(* Goal: @eq resource (resource_at (@proj1_sig rmap (fun phi : rmap => and (@eq nat (@level rmap ag_rmap phi) n) (and (@eq (forall _ : AV.address, resource) (resource_at phi) (@initial_world.initial_core' function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n)) (@eq ghost (ghost_of phi) (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) NoneP)) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds))))))) (make_rmap (@initial_world.initial_core' function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) NoneP)) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)))) n (initial_world.initial_core_ext_obligation_1 function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) (@eq_refl ghost (ghost_fmap (approx n) (approx n) (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) NoneP)) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)))))))) (@pair block Z b Z0)) (PURE (FUN f0 cc0) (preds_fmap (approx (@level rmap ag_rmap (@proj1_sig rmap (fun phi : rmap => and (@eq nat (@level rmap ag_rmap phi) n) (and (@eq (forall _ : AV.address, resource) (resource_at phi) (@initial_world.initial_core' function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n)) (@eq ghost (ghost_of phi) (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) NoneP)) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds))))))) (make_rmap (@initial_world.initial_core' function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) NoneP)) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)))) n (initial_world.initial_core_ext_obligation_1 function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) (@eq_refl ghost (ghost_fmap (approx n) (approx n) (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) NoneP)) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)))))))))) (approx (@level rmap ag_rmap (@proj1_sig rmap (fun phi : rmap => and (@eq nat (@level rmap ag_rmap phi) n) (and (@eq (forall _ : AV.address, resource) (resource_at phi) (@initial_world.initial_core' function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n)) (@eq ghost (ghost_of phi) (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) NoneP)) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds))))))) (make_rmap (@initial_world.initial_core' function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) NoneP)) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)))) n (initial_world.initial_core_ext_obligation_1 function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) (@eq_refl ghost (ghost_fmap (approx n) (approx n) (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) NoneP)) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)))))))))) (SomeP (SpecTT A) (@packPQ A a a0)))) *)
repeat rewrite resource_at_make_rmap.
(* Goal: @eq resource (@core resource Join_resource Sep_resource (inflate_initial_mem' m (@proj1_sig rmap (fun phi : rmap => and (@eq nat (@level rmap ag_rmap phi) n) (and (@eq (forall _ : AV.address, resource) (resource_at phi) (@initial_world.initial_core' function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n)) (@eq ghost (ghost_of phi) (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) NoneP)) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds))))))) (make_rmap (@initial_world.initial_core' function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) NoneP)) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)))) n (initial_world.initial_core_ext_obligation_1 function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) (@eq_refl ghost (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) (SomeP (ConstType unit) (fun _ : list Type => tt)))) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds))))))) l)) (@initial_world.initial_core' function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n l) *)
(* Goal: @eq ghost (ghost_of (@core rmap Join_rmap Sep_rmap (inflate_initial_mem m (@initial_world.initial_core_ext function (@OK_ty Espec) ora (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n)))) (ghost_of (@initial_world.initial_core function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n)) *)
unfold inflate_initial_mem'.
(* Goal: @eq resource (resource_at (@proj1_sig rmap (fun phi : rmap => and (@eq nat (@level rmap ag_rmap phi) n) (and (@eq (forall _ : AV.address, resource) (resource_at phi) (@initial_world.initial_core' function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n)) (@eq ghost (ghost_of phi) (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) NoneP)) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds))))))) (make_rmap (@initial_world.initial_core' function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) NoneP)) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)))) n (initial_world.initial_core_ext_obligation_1 function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) (@eq_refl ghost (ghost_fmap (approx n) (approx n) (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) NoneP)) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)))))))) (@pair block Z b Z0)) (PURE (FUN f0 cc0) (preds_fmap (approx (@level rmap ag_rmap (@proj1_sig rmap (fun phi : rmap => and (@eq nat (@level rmap ag_rmap phi) n) (and (@eq (forall _ : AV.address, resource) (resource_at phi) (@initial_world.initial_core' function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n)) (@eq ghost (ghost_of phi) (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) NoneP)) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds))))))) (make_rmap (@initial_world.initial_core' function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) NoneP)) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)))) n (initial_world.initial_core_ext_obligation_1 function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) (@eq_refl ghost (ghost_fmap (approx n) (approx n) (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) NoneP)) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)))))))))) (approx (@level rmap ag_rmap (@proj1_sig rmap (fun phi : rmap => and (@eq nat (@level rmap ag_rmap phi) n) (and (@eq (forall _ : AV.address, resource) (resource_at phi) (@initial_world.initial_core' function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n)) (@eq ghost (ghost_of phi) (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) NoneP)) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds))))))) (make_rmap (@initial_world.initial_core' function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) NoneP)) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)))) n (initial_world.initial_core_ext_obligation_1 function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) (@eq_refl ghost (ghost_fmap (approx n) (approx n) (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) NoneP)) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)))))))))) (SomeP (SpecTT A) (@packPQ A a a0)))) *)
repeat rewrite resource_at_make_rmap.
(* Goal: @eq resource (@core resource Join_resource Sep_resource match access_at m l Cur with | Some (Freeable as p) => YES Share.top readable_share_top (VAL (contents_at m l)) NoneP | Some (Writable as p) => YES Ews (@writable_readable Ews writable_Ews) (VAL (contents_at m l)) NoneP | Some (Readable as p) => YES Ers readable_Ers (VAL (contents_at m l)) NoneP | Some (Nonempty as p) => match @initial_world.initial_core' function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n l with | NO sh n => NO extern_retainer nonreadable_extern_retainer | YES sh r k p0 => NO extern_retainer nonreadable_extern_retainer | PURE k p0 => @initial_world.initial_core' function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n l end | None => NO Share.bot bot_unreadable end) (@initial_world.initial_core' function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n l) *)
(* Goal: @eq ghost (ghost_of (@core rmap Join_rmap Sep_rmap (inflate_initial_mem m (@initial_world.initial_core_ext function (@OK_ty Espec) ora (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n)))) (ghost_of (@initial_world.initial_core function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n)) *)
unfold initial_core'.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
case_eq (@Genv.invert_symbol (Ctypes.fundef function) type (@Genv.globalenv (Ctypes.fundef function) type prog) (@fst block Z l) ); intros; auto.
(* Goal: @eq resource (@core resource Join_resource Sep_resource match access_at m l Cur with | Some (Freeable as p) => YES Share.top readable_share_top (VAL (contents_at m l)) NoneP | Some (Writable as p) => YES Ews (@writable_readable Ews writable_Ews) (VAL (contents_at m l)) NoneP | Some (Readable as p) => YES Ers readable_Ers (VAL (contents_at m l)) NoneP | Some (Nonempty as p) => match (if Z.eq_dec (@snd block Z l) Z0 then match find_id i G with | Some (mk_funspec fsig cc A P Q P_ne Q_ne as f) => PURE (FUN fsig cc) (SomeP (SpecTT A) (fun ts : list Type => @fmap (dependent_type_functor_rec ts (SpecTT A)) (@pred rmap ag_rmap) (@pred rmap ag_rmap) (approx n) (approx n) (@packPQ A P Q ts))) | None => NO Share.bot bot_unreadable end else NO Share.bot bot_unreadable) with | NO sh n => NO extern_retainer nonreadable_extern_retainer | YES sh r k p0 => NO extern_retainer nonreadable_extern_retainer | PURE k p0 => if Z.eq_dec (@snd block Z l) Z0 then match find_id i G with | Some (mk_funspec fsig cc A P Q P_ne Q_ne as f) => PURE (FUN fsig cc) (SomeP (SpecTT A) (fun ts : list Type => @fmap (dependent_type_functor_rec ts (SpecTT A)) (@pred rmap ag_rmap) (@pred rmap ag_rmap) (approx n) (approx n) (@packPQ A P Q ts))) | None => NO Share.bot bot_unreadable end else NO Share.bot bot_unreadable end | None => NO Share.bot bot_unreadable end) (if Z.eq_dec (@snd block Z l) Z0 then match find_id i G with | Some (mk_funspec fsig cc A P Q P_ne Q_ne as f) => PURE (FUN fsig cc) (SomeP (SpecTT A) (fun ts : list Type => @fmap (dependent_type_functor_rec ts (SpecTT A)) (@pred rmap ag_rmap) (@pred rmap ag_rmap) (approx n) (approx n) (@packPQ A P Q ts))) | None => NO Share.bot bot_unreadable end else NO Share.bot bot_unreadable) *)
(* Goal: @eq resource (@core resource Join_resource Sep_resource match access_at m l Cur with | Some (Freeable as p) => YES Share.top readable_share_top (VAL (contents_at m l)) NoneP | Some (Writable as p) => YES Ews (@writable_readable Ews writable_Ews) (VAL (contents_at m l)) NoneP | Some (Readable as p) => YES Ers readable_Ers (VAL (contents_at m l)) NoneP | Some (Nonempty as p) => match (if Z.eq_dec (@snd block Z l) Z0 then NO Share.bot bot_unreadable else NO Share.bot bot_unreadable) with | NO sh n => NO extern_retainer nonreadable_extern_retainer | YES sh r k p0 => NO extern_retainer nonreadable_extern_retainer | PURE k p0 => if Z.eq_dec (@snd block Z l) Z0 then NO Share.bot bot_unreadable else NO Share.bot bot_unreadable end | None => NO Share.bot bot_unreadable end) (if Z.eq_dec (@snd block Z l) Z0 then NO Share.bot bot_unreadable else NO Share.bot bot_unreadable) *)
(* Goal: @eq ghost (ghost_of (@core rmap Join_rmap Sep_rmap (inflate_initial_mem m (@initial_world.initial_core_ext function (@OK_ty Espec) ora (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n)))) (ghost_of (@initial_world.initial_core function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n)) *)
rename i into id.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
case_eq (find_id id G); intros; auto.
(* Goal: @eq resource (@core resource Join_resource Sep_resource match access_at m l Cur with | Some (Freeable as p) => YES Share.top readable_share_top (VAL (contents_at m l)) NoneP | Some (Writable as p) => YES Ews (@writable_readable Ews writable_Ews) (VAL (contents_at m l)) NoneP | Some (Readable as p) => YES Ers readable_Ers (VAL (contents_at m l)) NoneP | Some (Nonempty as p) => match (if Z.eq_dec (@snd block Z l) Z0 then match f with | mk_funspec fsig cc A P Q P_ne Q_ne => PURE (FUN fsig cc) (SomeP (SpecTT A) (fun ts : list Type => @fmap (dependent_type_functor_rec ts (SpecTT A)) (@pred rmap ag_rmap) (@pred rmap ag_rmap) (approx n) (approx n) (@packPQ A P Q ts))) end else NO Share.bot bot_unreadable) with | NO sh n => NO extern_retainer nonreadable_extern_retainer | YES sh r k p0 => NO extern_retainer nonreadable_extern_retainer | PURE k p0 => if Z.eq_dec (@snd block Z l) Z0 then match f with | mk_funspec fsig cc A P Q P_ne Q_ne => PURE (FUN fsig cc) (SomeP (SpecTT A) (fun ts : list Type => @fmap (dependent_type_functor_rec ts (SpecTT A)) (@pred rmap ag_rmap) (@pred rmap ag_rmap) (approx n) (approx n) (@packPQ A P Q ts))) end else NO Share.bot bot_unreadable end | None => NO Share.bot bot_unreadable end) (if Z.eq_dec (@snd block Z l) Z0 then match f with | mk_funspec fsig cc A P Q P_ne Q_ne => PURE (FUN fsig cc) (SomeP (SpecTT A) (fun ts : list Type => @fmap (dependent_type_functor_rec ts (SpecTT A)) (@pred rmap ag_rmap) (@pred rmap ag_rmap) (approx n) (approx n) (@packPQ A P Q ts))) end else NO Share.bot bot_unreadable) *)
(* Goal: @eq resource (@core resource Join_resource Sep_resource match access_at m l Cur with | Some (Freeable as p) => YES Share.top readable_share_top (VAL (contents_at m l)) NoneP | Some (Writable as p) => YES Ews (@writable_readable Ews writable_Ews) (VAL (contents_at m l)) NoneP | Some (Readable as p) => YES Ers readable_Ers (VAL (contents_at m l)) NoneP | Some (Nonempty as p) => match (if Z.eq_dec (@snd block Z l) Z0 then NO Share.bot bot_unreadable else NO Share.bot bot_unreadable) with | NO sh n => NO extern_retainer nonreadable_extern_retainer | YES sh r k p0 => NO extern_retainer nonreadable_extern_retainer | PURE k p0 => if Z.eq_dec (@snd block Z l) Z0 then NO Share.bot bot_unreadable else NO Share.bot bot_unreadable end | None => NO Share.bot bot_unreadable end) (if Z.eq_dec (@snd block Z l) Z0 then NO Share.bot bot_unreadable else NO Share.bot bot_unreadable) *)
(* Goal: @eq resource (@core resource Join_resource Sep_resource match access_at m l Cur with | Some (Freeable as p) => YES Share.top readable_share_top (VAL (contents_at m l)) NoneP | Some (Writable as p) => YES Ews (@writable_readable Ews writable_Ews) (VAL (contents_at m l)) NoneP | Some (Readable as p) => YES Ers readable_Ers (VAL (contents_at m l)) NoneP | Some (Nonempty as p) => match (if Z.eq_dec (@snd block Z l) Z0 then NO Share.bot bot_unreadable else NO Share.bot bot_unreadable) with | NO sh n => NO extern_retainer nonreadable_extern_retainer | YES sh r k p0 => NO extern_retainer nonreadable_extern_retainer | PURE k p0 => if Z.eq_dec (@snd block Z l) Z0 then NO Share.bot bot_unreadable else NO Share.bot bot_unreadable end | None => NO Share.bot bot_unreadable end) (if Z.eq_dec (@snd block Z l) Z0 then NO Share.bot bot_unreadable else NO Share.bot bot_unreadable) *)
(* Goal: @eq ghost (ghost_of (@core rmap Join_rmap Sep_rmap (inflate_initial_mem m (@initial_world.initial_core_ext function (@OK_ty Espec) ora (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n)))) (ghost_of (@initial_world.initial_core function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n)) *)
rename f into fs.
(* Goal: @eq resource (@core resource Join_resource Sep_resource match access_at m l Cur with | Some (Freeable as p) => YES Share.top readable_share_top (VAL (contents_at m l)) NoneP | Some (Writable as p) => YES Ews (@writable_readable Ews writable_Ews) (VAL (contents_at m l)) NoneP | Some (Readable as p) => YES Ers readable_Ers (VAL (contents_at m l)) NoneP | Some (Nonempty as p) => match (if Z.eq_dec (@snd block Z l) Z0 then match fs with | mk_funspec fsig cc A P Q P_ne Q_ne => PURE (FUN fsig cc) (SomeP (SpecTT A) (fun ts : list Type => @fmap (dependent_type_functor_rec ts (SpecTT A)) (@pred rmap ag_rmap) (@pred rmap ag_rmap) (approx n) (approx n) (@packPQ A P Q ts))) end else NO Share.bot bot_unreadable) with | NO sh n => NO extern_retainer nonreadable_extern_retainer | YES sh r k p0 => NO extern_retainer nonreadable_extern_retainer | PURE k p0 => if Z.eq_dec (@snd block Z l) Z0 then match fs with | mk_funspec fsig cc A P Q P_ne Q_ne => PURE (FUN fsig cc) (SomeP (SpecTT A) (fun ts : list Type => @fmap (dependent_type_functor_rec ts (SpecTT A)) (@pred rmap ag_rmap) (@pred rmap ag_rmap) (approx n) (approx n) (@packPQ A P Q ts))) end else NO Share.bot bot_unreadable end | None => NO Share.bot bot_unreadable end) (if Z.eq_dec (@snd block Z l) Z0 then match fs with | mk_funspec fsig cc A P Q P_ne Q_ne => PURE (FUN fsig cc) (SomeP (SpecTT A) (fun ts : list Type => @fmap (dependent_type_functor_rec ts (SpecTT A)) (@pred rmap ag_rmap) (@pred rmap ag_rmap) (approx n) (approx n) (@packPQ A P Q ts))) end else NO Share.bot bot_unreadable) *)
(* Goal: @eq resource (@core resource Join_resource Sep_resource match access_at m l Cur with | Some (Freeable as p) => YES Share.top readable_share_top (VAL (contents_at m l)) NoneP | Some (Writable as p) => YES Ews (@writable_readable Ews writable_Ews) (VAL (contents_at m l)) NoneP | Some (Readable as p) => YES Ers readable_Ers (VAL (contents_at m l)) NoneP | Some (Nonempty as p) => match (if Z.eq_dec (@snd block Z l) Z0 then NO Share.bot bot_unreadable else NO Share.bot bot_unreadable) with | NO sh n => NO extern_retainer nonreadable_extern_retainer | YES sh r k p0 => NO extern_retainer nonreadable_extern_retainer | PURE k p0 => if Z.eq_dec (@snd block Z l) Z0 then NO Share.bot bot_unreadable else NO Share.bot bot_unreadable end | None => NO Share.bot bot_unreadable end) (if Z.eq_dec (@snd block Z l) Z0 then NO Share.bot bot_unreadable else NO Share.bot bot_unreadable) *)
(* Goal: @eq resource (@core resource Join_resource Sep_resource match access_at m l Cur with | Some (Freeable as p) => YES Share.top readable_share_top (VAL (contents_at m l)) NoneP | Some (Writable as p) => YES Ews (@writable_readable Ews writable_Ews) (VAL (contents_at m l)) NoneP | Some (Readable as p) => YES Ers readable_Ers (VAL (contents_at m l)) NoneP | Some (Nonempty as p) => match (if Z.eq_dec (@snd block Z l) Z0 then NO Share.bot bot_unreadable else NO Share.bot bot_unreadable) with | NO sh n => NO extern_retainer nonreadable_extern_retainer | YES sh r k p0 => NO extern_retainer nonreadable_extern_retainer | PURE k p0 => if Z.eq_dec (@snd block Z l) Z0 then NO Share.bot bot_unreadable else NO Share.bot bot_unreadable end | None => NO Share.bot bot_unreadable end) (if Z.eq_dec (@snd block Z l) Z0 then NO Share.bot bot_unreadable else NO Share.bot bot_unreadable) *)
(* Goal: @eq ghost (ghost_of (@core rmap Join_rmap Sep_rmap (inflate_initial_mem m (@initial_world.initial_core_ext function (@OK_ty Espec) ora (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n)))) (ghost_of (@initial_world.initial_core function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n)) *)
assert (exists f, In (id,f) (prog_funct prog)).
(* Goal: @ex (Ctypes.fundef function) (fun f : Ctypes.fundef function => @In (prod ident (Ctypes.fundef function)) (@pair ident (Ctypes.fundef function) id f) (@initial_world.prog_funct function prog)) *)
(* Goal: @eq resource (@core resource Join_resource Sep_resource match access_at m l Cur with | Some (Freeable as p) => YES Share.top readable_share_top (VAL (contents_at m l)) NoneP | Some (Writable as p) => YES Ews (@writable_readable Ews writable_Ews) (VAL (contents_at m l)) NoneP | Some (Readable as p) => YES Ers readable_Ers (VAL (contents_at m l)) NoneP | Some (Nonempty as p) => match (if Z.eq_dec (@snd block Z l) Z0 then match fs with | mk_funspec fsig cc A P Q P_ne Q_ne => PURE (FUN fsig cc) (SomeP (SpecTT A) (fun ts : list Type => @fmap (dependent_type_functor_rec ts (SpecTT A)) (@pred rmap ag_rmap) (@pred rmap ag_rmap) (approx n) (approx n) (@packPQ A P Q ts))) end else NO Share.bot bot_unreadable) with | NO sh n => NO extern_retainer nonreadable_extern_retainer | YES sh r k p0 => NO extern_retainer nonreadable_extern_retainer | PURE k p0 => if Z.eq_dec (@snd block Z l) Z0 then match fs with | mk_funspec fsig cc A P Q P_ne Q_ne => PURE (FUN fsig cc) (SomeP (SpecTT A) (fun ts : list Type => @fmap (dependent_type_functor_rec ts (SpecTT A)) (@pred rmap ag_rmap) (@pred rmap ag_rmap) (approx n) (approx n) (@packPQ A P Q ts))) end else NO Share.bot bot_unreadable end | None => NO Share.bot bot_unreadable end) (if Z.eq_dec (@snd block Z l) Z0 then match fs with | mk_funspec fsig cc A P Q P_ne Q_ne => PURE (FUN fsig cc) (SomeP (SpecTT A) (fun ts : list Type => @fmap (dependent_type_functor_rec ts (SpecTT A)) (@pred rmap ag_rmap) (@pred rmap ag_rmap) (approx n) (approx n) (@packPQ A P Q ts))) end else NO Share.bot bot_unreadable) *)
(* Goal: @eq resource (@core resource Join_resource Sep_resource match access_at m l Cur with | Some (Freeable as p) => YES Share.top readable_share_top (VAL (contents_at m l)) NoneP | Some (Writable as p) => YES Ews (@writable_readable Ews writable_Ews) (VAL (contents_at m l)) NoneP | Some (Readable as p) => YES Ers readable_Ers (VAL (contents_at m l)) NoneP | Some (Nonempty as p) => match (if Z.eq_dec (@snd block Z l) Z0 then NO Share.bot bot_unreadable else NO Share.bot bot_unreadable) with | NO sh n => NO extern_retainer nonreadable_extern_retainer | YES sh r k p0 => NO extern_retainer nonreadable_extern_retainer | PURE k p0 => if Z.eq_dec (@snd block Z l) Z0 then NO Share.bot bot_unreadable else NO Share.bot bot_unreadable end | None => NO Share.bot bot_unreadable end) (if Z.eq_dec (@snd block Z l) Z0 then NO Share.bot bot_unreadable else NO Share.bot bot_unreadable) *)
(* Goal: @eq resource (@core resource Join_resource Sep_resource match access_at m l Cur with | Some (Freeable as p) => YES Share.top readable_share_top (VAL (contents_at m l)) NoneP | Some (Writable as p) => YES Ews (@writable_readable Ews writable_Ews) (VAL (contents_at m l)) NoneP | Some (Readable as p) => YES Ers readable_Ers (VAL (contents_at m l)) NoneP | Some (Nonempty as p) => match (if Z.eq_dec (@snd block Z l) Z0 then NO Share.bot bot_unreadable else NO Share.bot bot_unreadable) with | NO sh n => NO extern_retainer nonreadable_extern_retainer | YES sh r k p0 => NO extern_retainer nonreadable_extern_retainer | PURE k p0 => if Z.eq_dec (@snd block Z l) Z0 then NO Share.bot bot_unreadable else NO Share.bot bot_unreadable end | None => NO Share.bot bot_unreadable end) (if Z.eq_dec (@snd block Z l) Z0 then NO Share.bot bot_unreadable else NO Share.bot bot_unreadable) *)
(* Goal: @eq ghost (ghost_of (@core rmap Join_rmap Sep_rmap (inflate_initial_mem m (@initial_world.initial_core_ext function (@OK_ty Espec) ora (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n)))) (ghost_of (@initial_world.initial_core function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n)) *)
apply find_id_e in H2.
(* Goal: @ex (Ctypes.fundef function) (fun f : Ctypes.fundef function => @In (prod ident (Ctypes.fundef function)) (@pair ident (Ctypes.fundef function) id f) (@initial_world.prog_funct function prog)) *)
(* Goal: @eq resource (@core resource Join_resource Sep_resource match access_at m l Cur with | Some (Freeable as p) => YES Share.top readable_share_top (VAL (contents_at m l)) NoneP | Some (Writable as p) => YES Ews (@writable_readable Ews writable_Ews) (VAL (contents_at m l)) NoneP | Some (Readable as p) => YES Ers readable_Ers (VAL (contents_at m l)) NoneP | Some (Nonempty as p) => match (if Z.eq_dec (@snd block Z l) Z0 then match fs with | mk_funspec fsig cc A P Q P_ne Q_ne => PURE (FUN fsig cc) (SomeP (SpecTT A) (fun ts : list Type => @fmap (dependent_type_functor_rec ts (SpecTT A)) (@pred rmap ag_rmap) (@pred rmap ag_rmap) (approx n) (approx n) (@packPQ A P Q ts))) end else NO Share.bot bot_unreadable) with | NO sh n => NO extern_retainer nonreadable_extern_retainer | YES sh r k p0 => NO extern_retainer nonreadable_extern_retainer | PURE k p0 => if Z.eq_dec (@snd block Z l) Z0 then match fs with | mk_funspec fsig cc A P Q P_ne Q_ne => PURE (FUN fsig cc) (SomeP (SpecTT A) (fun ts : list Type => @fmap (dependent_type_functor_rec ts (SpecTT A)) (@pred rmap ag_rmap) (@pred rmap ag_rmap) (approx n) (approx n) (@packPQ A P Q ts))) end else NO Share.bot bot_unreadable end | None => NO Share.bot bot_unreadable end) (if Z.eq_dec (@snd block Z l) Z0 then match fs with | mk_funspec fsig cc A P Q P_ne Q_ne => PURE (FUN fsig cc) (SomeP (SpecTT A) (fun ts : list Type => @fmap (dependent_type_functor_rec ts (SpecTT A)) (@pred rmap ag_rmap) (@pred rmap ag_rmap) (approx n) (approx n) (@packPQ A P Q ts))) end else NO Share.bot bot_unreadable) *)
(* Goal: @eq resource (@core resource Join_resource Sep_resource match access_at m l Cur with | Some (Freeable as p) => YES Share.top readable_share_top (VAL (contents_at m l)) NoneP | Some (Writable as p) => YES Ews (@writable_readable Ews writable_Ews) (VAL (contents_at m l)) NoneP | Some (Readable as p) => YES Ers readable_Ers (VAL (contents_at m l)) NoneP | Some (Nonempty as p) => match (if Z.eq_dec (@snd block Z l) Z0 then NO Share.bot bot_unreadable else NO Share.bot bot_unreadable) with | NO sh n => NO extern_retainer nonreadable_extern_retainer | YES sh r k p0 => NO extern_retainer nonreadable_extern_retainer | PURE k p0 => if Z.eq_dec (@snd block Z l) Z0 then NO Share.bot bot_unreadable else NO Share.bot bot_unreadable end | None => NO Share.bot bot_unreadable end) (if Z.eq_dec (@snd block Z l) Z0 then NO Share.bot bot_unreadable else NO Share.bot bot_unreadable) *)
(* Goal: @eq resource (@core resource Join_resource Sep_resource match access_at m l Cur with | Some (Freeable as p) => YES Share.top readable_share_top (VAL (contents_at m l)) NoneP | Some (Writable as p) => YES Ews (@writable_readable Ews writable_Ews) (VAL (contents_at m l)) NoneP | Some (Readable as p) => YES Ers readable_Ers (VAL (contents_at m l)) NoneP | Some (Nonempty as p) => match (if Z.eq_dec (@snd block Z l) Z0 then NO Share.bot bot_unreadable else NO Share.bot bot_unreadable) with | NO sh n => NO extern_retainer nonreadable_extern_retainer | YES sh r k p0 => NO extern_retainer nonreadable_extern_retainer | PURE k p0 => if Z.eq_dec (@snd block Z l) Z0 then NO Share.bot bot_unreadable else NO Share.bot bot_unreadable end | None => NO Share.bot bot_unreadable end) (if Z.eq_dec (@snd block Z l) Z0 then NO Share.bot bot_unreadable else NO Share.bot bot_unreadable) *)
(* Goal: @eq ghost (ghost_of (@core rmap Join_rmap Sep_rmap (inflate_initial_mem m (@initial_world.initial_core_ext function (@OK_ty Espec) ora (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n)))) (ghost_of (@initial_world.initial_core function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n)) *)
apply in_map_fst in H2.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
eapply match_fdecs_in in H2; eauto.
(* Goal: @ex (Ctypes.fundef function) (fun f : Ctypes.fundef function => @In (prod ident (Ctypes.fundef function)) (@pair ident (Ctypes.fundef function) id f) (@initial_world.prog_funct function prog)) *)
(* Goal: @eq resource (@core resource Join_resource Sep_resource match access_at m l Cur with | Some (Freeable as p) => YES Share.top readable_share_top (VAL (contents_at m l)) NoneP | Some (Writable as p) => YES Ews (@writable_readable Ews writable_Ews) (VAL (contents_at m l)) NoneP | Some (Readable as p) => YES Ers readable_Ers (VAL (contents_at m l)) NoneP | Some (Nonempty as p) => match (if Z.eq_dec (@snd block Z l) Z0 then match fs with | mk_funspec fsig cc A P Q P_ne Q_ne => PURE (FUN fsig cc) (SomeP (SpecTT A) (fun ts : list Type => @fmap (dependent_type_functor_rec ts (SpecTT A)) (@pred rmap ag_rmap) (@pred rmap ag_rmap) (approx n) (approx n) (@packPQ A P Q ts))) end else NO Share.bot bot_unreadable) with | NO sh n => NO extern_retainer nonreadable_extern_retainer | YES sh r k p0 => NO extern_retainer nonreadable_extern_retainer | PURE k p0 => if Z.eq_dec (@snd block Z l) Z0 then match fs with | mk_funspec fsig cc A P Q P_ne Q_ne => PURE (FUN fsig cc) (SomeP (SpecTT A) (fun ts : list Type => @fmap (dependent_type_functor_rec ts (SpecTT A)) (@pred rmap ag_rmap) (@pred rmap ag_rmap) (approx n) (approx n) (@packPQ A P Q ts))) end else NO Share.bot bot_unreadable end | None => NO Share.bot bot_unreadable end) (if Z.eq_dec (@snd block Z l) Z0 then match fs with | mk_funspec fsig cc A P Q P_ne Q_ne => PURE (FUN fsig cc) (SomeP (SpecTT A) (fun ts : list Type => @fmap (dependent_type_functor_rec ts (SpecTT A)) (@pred rmap ag_rmap) (@pred rmap ag_rmap) (approx n) (approx n) (@packPQ A P Q ts))) end else NO Share.bot bot_unreadable) *)
(* Goal: @eq resource (@core resource Join_resource Sep_resource match access_at m l Cur with | Some (Freeable as p) => YES Share.top readable_share_top (VAL (contents_at m l)) NoneP | Some (Writable as p) => YES Ews (@writable_readable Ews writable_Ews) (VAL (contents_at m l)) NoneP | Some (Readable as p) => YES Ers readable_Ers (VAL (contents_at m l)) NoneP | Some (Nonempty as p) => match (if Z.eq_dec (@snd block Z l) Z0 then NO Share.bot bot_unreadable else NO Share.bot bot_unreadable) with | NO sh n => NO extern_retainer nonreadable_extern_retainer | YES sh r k p0 => NO extern_retainer nonreadable_extern_retainer | PURE k p0 => if Z.eq_dec (@snd block Z l) Z0 then NO Share.bot bot_unreadable else NO Share.bot bot_unreadable end | None => NO Share.bot bot_unreadable end) (if Z.eq_dec (@snd block Z l) Z0 then NO Share.bot bot_unreadable else NO Share.bot bot_unreadable) *)
(* Goal: @eq resource (@core resource Join_resource Sep_resource match access_at m l Cur with | Some (Freeable as p) => YES Share.top readable_share_top (VAL (contents_at m l)) NoneP | Some (Writable as p) => YES Ews (@writable_readable Ews writable_Ews) (VAL (contents_at m l)) NoneP | Some (Readable as p) => YES Ers readable_Ers (VAL (contents_at m l)) NoneP | Some (Nonempty as p) => match (if Z.eq_dec (@snd block Z l) Z0 then NO Share.bot bot_unreadable else NO Share.bot bot_unreadable) with | NO sh n => NO extern_retainer nonreadable_extern_retainer | YES sh r k p0 => NO extern_retainer nonreadable_extern_retainer | PURE k p0 => if Z.eq_dec (@snd block Z l) Z0 then NO Share.bot bot_unreadable else NO Share.bot bot_unreadable end | None => NO Share.bot bot_unreadable end) (if Z.eq_dec (@snd block Z l) Z0 then NO Share.bot bot_unreadable else NO Share.bot bot_unreadable) *)
(* Goal: @eq ghost (ghost_of (@core rmap Join_rmap Sep_rmap (inflate_initial_mem m (@initial_world.initial_core_ext function (@OK_ty Espec) ora (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n)))) (ghost_of (@initial_world.initial_core function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n)) *)
apply in_map_iff in H2.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
destruct H2 as [[i' f] [? ?]]. subst id; exists f; auto.
(* Goal: @eq resource (@core resource Join_resource Sep_resource match access_at m l Cur with | Some (Freeable as p) => YES Share.top readable_share_top (VAL (contents_at m l)) NoneP | Some (Writable as p) => YES Ews (@writable_readable Ews writable_Ews) (VAL (contents_at m l)) NoneP | Some (Readable as p) => YES Ers readable_Ers (VAL (contents_at m l)) NoneP | Some (Nonempty as p) => match (if Z.eq_dec (@snd block Z l) Z0 then match fs with | mk_funspec fsig cc A P Q P_ne Q_ne => PURE (FUN fsig cc) (SomeP (SpecTT A) (fun ts : list Type => @fmap (dependent_type_functor_rec ts (SpecTT A)) (@pred rmap ag_rmap) (@pred rmap ag_rmap) (approx n) (approx n) (@packPQ A P Q ts))) end else NO Share.bot bot_unreadable) with | NO sh n => NO extern_retainer nonreadable_extern_retainer | YES sh r k p0 => NO extern_retainer nonreadable_extern_retainer | PURE k p0 => if Z.eq_dec (@snd block Z l) Z0 then match fs with | mk_funspec fsig cc A P Q P_ne Q_ne => PURE (FUN fsig cc) (SomeP (SpecTT A) (fun ts : list Type => @fmap (dependent_type_functor_rec ts (SpecTT A)) (@pred rmap ag_rmap) (@pred rmap ag_rmap) (approx n) (approx n) (@packPQ A P Q ts))) end else NO Share.bot bot_unreadable end | None => NO Share.bot bot_unreadable end) (if Z.eq_dec (@snd block Z l) Z0 then match fs with | mk_funspec fsig cc A P Q P_ne Q_ne => PURE (FUN fsig cc) (SomeP (SpecTT A) (fun ts : list Type => @fmap (dependent_type_functor_rec ts (SpecTT A)) (@pred rmap ag_rmap) (@pred rmap ag_rmap) (approx n) (approx n) (@packPQ A P Q ts))) end else NO Share.bot bot_unreadable) *)
(* Goal: @eq resource (@core resource Join_resource Sep_resource match access_at m l Cur with | Some (Freeable as p) => YES Share.top readable_share_top (VAL (contents_at m l)) NoneP | Some (Writable as p) => YES Ews (@writable_readable Ews writable_Ews) (VAL (contents_at m l)) NoneP | Some (Readable as p) => YES Ers readable_Ers (VAL (contents_at m l)) NoneP | Some (Nonempty as p) => match (if Z.eq_dec (@snd block Z l) Z0 then NO Share.bot bot_unreadable else NO Share.bot bot_unreadable) with | NO sh n => NO extern_retainer nonreadable_extern_retainer | YES sh r k p0 => NO extern_retainer nonreadable_extern_retainer | PURE k p0 => if Z.eq_dec (@snd block Z l) Z0 then NO Share.bot bot_unreadable else NO Share.bot bot_unreadable end | None => NO Share.bot bot_unreadable end) (if Z.eq_dec (@snd block Z l) Z0 then NO Share.bot bot_unreadable else NO Share.bot bot_unreadable) *)
(* Goal: @eq resource (@core resource Join_resource Sep_resource match access_at m l Cur with | Some (Freeable as p) => YES Share.top readable_share_top (VAL (contents_at m l)) NoneP | Some (Writable as p) => YES Ews (@writable_readable Ews writable_Ews) (VAL (contents_at m l)) NoneP | Some (Readable as p) => YES Ers readable_Ers (VAL (contents_at m l)) NoneP | Some (Nonempty as p) => match (if Z.eq_dec (@snd block Z l) Z0 then NO Share.bot bot_unreadable else NO Share.bot bot_unreadable) with | NO sh n => NO extern_retainer nonreadable_extern_retainer | YES sh r k p0 => NO extern_retainer nonreadable_extern_retainer | PURE k p0 => if Z.eq_dec (@snd block Z l) Z0 then NO Share.bot bot_unreadable else NO Share.bot bot_unreadable end | None => NO Share.bot bot_unreadable end) (if Z.eq_dec (@snd block Z l) Z0 then NO Share.bot bot_unreadable else NO Share.bot bot_unreadable) *)
(* Goal: @eq ghost (ghost_of (@core rmap Join_rmap Sep_rmap (inflate_initial_mem m (@initial_world.initial_core_ext function (@OK_ty Espec) ora (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n)))) (ghost_of (@initial_world.initial_core function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n)) *)
destruct H3 as [f ?].
(* Goal: @eq resource (@core resource Join_resource Sep_resource match access_at m l Cur with | Some (Freeable as p) => YES Share.top readable_share_top (VAL (contents_at m l)) NoneP | Some (Writable as p) => YES Ews (@writable_readable Ews writable_Ews) (VAL (contents_at m l)) NoneP | Some (Readable as p) => YES Ers readable_Ers (VAL (contents_at m l)) NoneP | Some (Nonempty as p) => match (if Z.eq_dec (@snd block Z l) Z0 then match fs with | mk_funspec fsig cc A P Q P_ne Q_ne => PURE (FUN fsig cc) (SomeP (SpecTT A) (fun ts : list Type => @fmap (dependent_type_functor_rec ts (SpecTT A)) (@pred rmap ag_rmap) (@pred rmap ag_rmap) (approx n) (approx n) (@packPQ A P Q ts))) end else NO Share.bot bot_unreadable) with | NO sh n => NO extern_retainer nonreadable_extern_retainer | YES sh r k p0 => NO extern_retainer nonreadable_extern_retainer | PURE k p0 => if Z.eq_dec (@snd block Z l) Z0 then match fs with | mk_funspec fsig cc A P Q P_ne Q_ne => PURE (FUN fsig cc) (SomeP (SpecTT A) (fun ts : list Type => @fmap (dependent_type_functor_rec ts (SpecTT A)) (@pred rmap ag_rmap) (@pred rmap ag_rmap) (approx n) (approx n) (@packPQ A P Q ts))) end else NO Share.bot bot_unreadable end | None => NO Share.bot bot_unreadable end) (if Z.eq_dec (@snd block Z l) Z0 then match fs with | mk_funspec fsig cc A P Q P_ne Q_ne => PURE (FUN fsig cc) (SomeP (SpecTT A) (fun ts : list Type => @fmap (dependent_type_functor_rec ts (SpecTT A)) (@pred rmap ag_rmap) (@pred rmap ag_rmap) (approx n) (approx n) (@packPQ A P Q ts))) end else NO Share.bot bot_unreadable) *)
(* Goal: @eq resource (@core resource Join_resource Sep_resource match access_at m l Cur with | Some (Freeable as p) => YES Share.top readable_share_top (VAL (contents_at m l)) NoneP | Some (Writable as p) => YES Ews (@writable_readable Ews writable_Ews) (VAL (contents_at m l)) NoneP | Some (Readable as p) => YES Ers readable_Ers (VAL (contents_at m l)) NoneP | Some (Nonempty as p) => match (if Z.eq_dec (@snd block Z l) Z0 then NO Share.bot bot_unreadable else NO Share.bot bot_unreadable) with | NO sh n => NO extern_retainer nonreadable_extern_retainer | YES sh r k p0 => NO extern_retainer nonreadable_extern_retainer | PURE k p0 => if Z.eq_dec (@snd block Z l) Z0 then NO Share.bot bot_unreadable else NO Share.bot bot_unreadable end | None => NO Share.bot bot_unreadable end) (if Z.eq_dec (@snd block Z l) Z0 then NO Share.bot bot_unreadable else NO Share.bot bot_unreadable) *)
(* Goal: @eq resource (@core resource Join_resource Sep_resource match access_at m l Cur with | Some (Freeable as p) => YES Share.top readable_share_top (VAL (contents_at m l)) NoneP | Some (Writable as p) => YES Ews (@writable_readable Ews writable_Ews) (VAL (contents_at m l)) NoneP | Some (Readable as p) => YES Ers readable_Ers (VAL (contents_at m l)) NoneP | Some (Nonempty as p) => match (if Z.eq_dec (@snd block Z l) Z0 then NO Share.bot bot_unreadable else NO Share.bot bot_unreadable) with | NO sh n => NO extern_retainer nonreadable_extern_retainer | YES sh r k p0 => NO extern_retainer nonreadable_extern_retainer | PURE k p0 => if Z.eq_dec (@snd block Z l) Z0 then NO Share.bot bot_unreadable else NO Share.bot bot_unreadable end | None => NO Share.bot bot_unreadable end) (if Z.eq_dec (@snd block Z l) Z0 then NO Share.bot bot_unreadable else NO Share.bot bot_unreadable) *)
(* Goal: @eq ghost (ghost_of (@core rmap Join_rmap Sep_rmap (inflate_initial_mem m (@initial_world.initial_core_ext function (@OK_ty Espec) ora (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n)))) (ghost_of (@initial_world.initial_core function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n)) *)
apply Genv.invert_find_symbol in H1.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
destruct (find_funct_ptr_exists prog id f) as [b [? ?]]; auto.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
apply in_prog_funct_in_prog_defs; auto.
(* Goal: @eq resource (@core resource Join_resource Sep_resource match access_at m l Cur with | Some (Freeable as p) => YES Share.top readable_share_top (VAL (contents_at m l)) NoneP | Some (Writable as p) => YES Ews (@writable_readable Ews writable_Ews) (VAL (contents_at m l)) NoneP | Some (Readable as p) => YES Ers readable_Ers (VAL (contents_at m l)) NoneP | Some (Nonempty as p) => match (if Z.eq_dec (@snd block Z l) Z0 then match fs with | mk_funspec fsig cc A P Q P_ne Q_ne => PURE (FUN fsig cc) (SomeP (SpecTT A) (fun ts : list Type => @fmap (dependent_type_functor_rec ts (SpecTT A)) (@pred rmap ag_rmap) (@pred rmap ag_rmap) (approx n) (approx n) (@packPQ A P Q ts))) end else NO Share.bot bot_unreadable) with | NO sh n => NO extern_retainer nonreadable_extern_retainer | YES sh r k p0 => NO extern_retainer nonreadable_extern_retainer | PURE k p0 => if Z.eq_dec (@snd block Z l) Z0 then match fs with | mk_funspec fsig cc A P Q P_ne Q_ne => PURE (FUN fsig cc) (SomeP (SpecTT A) (fun ts : list Type => @fmap (dependent_type_functor_rec ts (SpecTT A)) (@pred rmap ag_rmap) (@pred rmap ag_rmap) (approx n) (approx n) (@packPQ A P Q ts))) end else NO Share.bot bot_unreadable end | None => NO Share.bot bot_unreadable end) (if Z.eq_dec (@snd block Z l) Z0 then match fs with | mk_funspec fsig cc A P Q P_ne Q_ne => PURE (FUN fsig cc) (SomeP (SpecTT A) (fun ts : list Type => @fmap (dependent_type_functor_rec ts (SpecTT A)) (@pred rmap ag_rmap) (@pred rmap ag_rmap) (approx n) (approx n) (@packPQ A P Q ts))) end else NO Share.bot bot_unreadable) *)
(* Goal: @eq resource (@core resource Join_resource Sep_resource match access_at m l Cur with | Some (Freeable as p) => YES Share.top readable_share_top (VAL (contents_at m l)) NoneP | Some (Writable as p) => YES Ews (@writable_readable Ews writable_Ews) (VAL (contents_at m l)) NoneP | Some (Readable as p) => YES Ers readable_Ers (VAL (contents_at m l)) NoneP | Some (Nonempty as p) => match (if Z.eq_dec (@snd block Z l) Z0 then NO Share.bot bot_unreadable else NO Share.bot bot_unreadable) with | NO sh n => NO extern_retainer nonreadable_extern_retainer | YES sh r k p0 => NO extern_retainer nonreadable_extern_retainer | PURE k p0 => if Z.eq_dec (@snd block Z l) Z0 then NO Share.bot bot_unreadable else NO Share.bot bot_unreadable end | None => NO Share.bot bot_unreadable end) (if Z.eq_dec (@snd block Z l) Z0 then NO Share.bot bot_unreadable else NO Share.bot bot_unreadable) *)
(* Goal: @eq resource (@core resource Join_resource Sep_resource match access_at m l Cur with | Some (Freeable as p) => YES Share.top readable_share_top (VAL (contents_at m l)) NoneP | Some (Writable as p) => YES Ews (@writable_readable Ews writable_Ews) (VAL (contents_at m l)) NoneP | Some (Readable as p) => YES Ers readable_Ers (VAL (contents_at m l)) NoneP | Some (Nonempty as p) => match (if Z.eq_dec (@snd block Z l) Z0 then NO Share.bot bot_unreadable else NO Share.bot bot_unreadable) with | NO sh n => NO extern_retainer nonreadable_extern_retainer | YES sh r k p0 => NO extern_retainer nonreadable_extern_retainer | PURE k p0 => if Z.eq_dec (@snd block Z l) Z0 then NO Share.bot bot_unreadable else NO Share.bot bot_unreadable end | None => NO Share.bot bot_unreadable end) (if Z.eq_dec (@snd block Z l) Z0 then NO Share.bot bot_unreadable else NO Share.bot bot_unreadable) *)
(* Goal: @eq ghost (ghost_of (@core rmap Join_rmap Sep_rmap (inflate_initial_mem m (@initial_world.initial_core_ext function (@OK_ty Espec) ora (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n)))) (ghost_of (@initial_world.initial_core function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n)) *)
inversion2 H1 H4.
+ if_tac.
 - destruct (IOK l) as [_ ?].
(* Goal: @eq resource (@core resource Join_resource Sep_resource match access_at m l Cur with | Some (Freeable as p) => YES Share.top readable_share_top (VAL (contents_at m l)) NoneP | Some (Writable as p) => YES Ews (@writable_readable Ews writable_Ews) (VAL (contents_at m l)) NoneP | Some (Readable as p) => YES Ers readable_Ers (VAL (contents_at m l)) NoneP | Some (Nonempty as p) => match match fs with | mk_funspec fsig cc A P Q P_ne Q_ne => PURE (FUN fsig cc) (SomeP (SpecTT A) (fun ts : list Type => @fmap (dependent_type_functor_rec ts (SpecTT A)) (@pred rmap ag_rmap) (@pred rmap ag_rmap) (approx n) (approx n) (@packPQ A P Q ts))) end with | NO sh n => NO extern_retainer nonreadable_extern_retainer | YES sh r k p0 => NO extern_retainer nonreadable_extern_retainer | PURE k p0 => match fs with | mk_funspec fsig cc A P Q P_ne Q_ne => PURE (FUN fsig cc) (SomeP (SpecTT A) (fun ts : list Type => @fmap (dependent_type_functor_rec ts (SpecTT A)) (@pred rmap ag_rmap) (@pred rmap ag_rmap) (approx n) (approx n) (@packPQ A P Q ts))) end end | None => NO Share.bot bot_unreadable end) match fs with | mk_funspec fsig cc A P Q P_ne Q_ne => PURE (FUN fsig cc) (SomeP (SpecTT A) (fun ts : list Type => @fmap (dependent_type_functor_rec ts (SpecTT A)) (@pred rmap ag_rmap) (@pred rmap ag_rmap) (approx n) (approx n) (@packPQ A P Q ts))) end *)
   unfold initial_core in H6. rewrite resource_at_make_rmap in H6.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
   unfold initial_core' in H6. rewrite if_true in H6 by auto.
(* Goal: @eq resource (@core resource Join_resource Sep_resource match access_at m l Cur with | Some (Freeable as p) => YES Share.top readable_share_top (VAL (contents_at m l)) NoneP | Some (Writable as p) => YES Ews (@writable_readable Ews writable_Ews) (VAL (contents_at m l)) NoneP | Some (Readable as p) => YES Ers readable_Ers (VAL (contents_at m l)) NoneP | Some (Nonempty as p) => match match fs with | mk_funspec fsig cc A P Q P_ne Q_ne => PURE (FUN fsig cc) (SomeP (SpecTT A) (fun ts : list Type => @fmap (dependent_type_functor_rec ts (SpecTT A)) (@pred rmap ag_rmap) (@pred rmap ag_rmap) (approx n) (approx n) (@packPQ A P Q ts))) end with | NO sh n => NO extern_retainer nonreadable_extern_retainer | YES sh r k p0 => NO extern_retainer nonreadable_extern_retainer | PURE k p0 => match fs with | mk_funspec fsig cc A P Q P_ne Q_ne => PURE (FUN fsig cc) (SomeP (SpecTT A) (fun ts : list Type => @fmap (dependent_type_functor_rec ts (SpecTT A)) (@pred rmap ag_rmap) (@pred rmap ag_rmap) (approx n) (approx n) (@packPQ A P Q ts))) end end | None => NO Share.bot bot_unreadable end) match fs with | mk_funspec fsig cc A P Q P_ne Q_ne => PURE (FUN fsig cc) (SomeP (SpecTT A) (fun ts : list Type => @fmap (dependent_type_functor_rec ts (SpecTT A)) (@pred rmap ag_rmap) (@pred rmap ag_rmap) (approx n) (approx n) (@packPQ A P Q ts))) end *)
   apply Genv.find_invert_symbol in H1.
   unfold fundef in *; rewrite H1 in *.
   rewrite H2 in *. destruct fs.
(* Goal: @eq resource (@core resource Join_resource Sep_resource match access_at m l Cur with | Some (Freeable as p) => YES Share.top readable_share_top (VAL (contents_at m l)) NoneP | Some (Writable as p) => YES Ews (@writable_readable Ews writable_Ews) (VAL (contents_at m l)) NoneP | Some (Readable as p) => YES Ers readable_Ers (VAL (contents_at m l)) NoneP | Some (Nonempty as p) => PURE (FUN f0 c) (SomeP (SpecTT A) (fun ts : list Type => @fmap (dependent_type_functor_rec ts (SpecTT A)) (@pred rmap ag_rmap) (@pred rmap ag_rmap) (approx n) (approx n) (@packPQ A P Q ts))) | None => NO Share.bot bot_unreadable end) (PURE (FUN f0 c) (SomeP (SpecTT A) (fun ts : list Type => @fmap (dependent_type_functor_rec ts (SpecTT A)) (@pred rmap ag_rmap) (@pred rmap ag_rmap) (approx n) (approx n) (@packPQ A P Q ts)))) *)
   destruct H6 as [? [? ?]]. rewrite H7.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
   rewrite core_PURE; auto.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
 - destruct (access_at m l); try destruct p; try rewrite core_YES; try rewrite core_NO; auto.
+ (*unfold fundef in *. rewrite H1,H2 in *.*)
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
   if_tac;  destruct (access_at m l); try destruct p; try rewrite core_YES; try rewrite core_NO; auto.
+ (*unfold fundef in *; rewrite H1 in *.*)
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
  if_tac;   destruct (access_at m l); try destruct p; try rewrite core_YES; try rewrite core_NO; auto.
+ rewrite ghost_of_core.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
  unfold inflate_initial_mem, initial_core; rewrite !ghost_of_make_rmap, ghost_core; auto.
Qed.

Lemma core_inflate_initial_mem':
  forall (ora : OK_ty) (m: mem) (prog: program) (G: funspecs) (n: nat)
     (INIT: Genv.init_mem prog = Some m),
    match_fdecs (prog_funct prog) G ->
      list_norepet (prog_defs_names prog) ->
   core (inflate_initial_mem m (initial_core_ext ora (Genv.globalenv prog) G n)) =
         initial_core (Genv.globalenv prog) G n.
Proof.
(* Goal: forall (id : positive) (ty : type), iff (@eq (option type) (@PTree.get type id (make_tycontext_v (@nil (prod ident type)))) (@Some type ty)) (@ex block (fun v : block => @eq (option (prod block type)) (@Map.get (prod block type) (make_venv empty_env) id) (@Some (prod block type) (@pair block type v ty)))) *)
intros.
(* Goal: @eq rmap (@core rmap Join_rmap Sep_rmap (inflate_initial_mem m (@initial_world.initial_core_ext function (@OK_ty Espec) ora (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n))) (@initial_world.initial_core function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) *)
assert (IOK := initial_core_ext_ok ora _ _ n _ H0 H INIT).
(* Goal: @eq rmap (@core rmap Join_rmap Sep_rmap (inflate_initial_mem m (@initial_world.initial_core_ext function (@OK_ty Espec) ora (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n))) (@initial_world.initial_core function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) *)
apply rmap_ext.
(* Goal: forall _ : @ex block (fun v : block => @eq (option (prod block type)) (@Map.get (prod block type) (ve_of (construct_rho (filter_genv (globalenv prog)) empty_env (@PTree.set val xH (Vptr b Ptrofs.zero) (temp_bindings (xO xH) (@map (prod val type) val (@fst val type) typed_args))))) id) (@Some (prod block type) (@pair block type v ty))), @eq (option type) (@PTree.get type id (var_types (@Delta_types vs G C (@map (prod val type) type (@snd val type) typed_args)))) (@Some type ty) *)
  unfold inflate_initial_mem, initial_core, initial_core_ext; simpl.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
  rewrite level_core. rewrite !level_make_rmap; auto.
(* Goal: forall l : AV.address, @eq resource (resource_at (@core rmap Join_rmap Sep_rmap (inflate_initial_mem m (@initial_world.initial_core_ext function (@OK_ty Espec) ora (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n))) l) (resource_at (@initial_world.initial_core function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) l) *)
(* Goal: @eq ghost (ghost_of (@core rmap Join_rmap Sep_rmap (inflate_initial_mem m (@initial_world.initial_core_ext function (@OK_ty Espec) ora (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n)))) (ghost_of (@initial_world.initial_core function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n)) *)
intro l.
(* Goal: forall _ : @ex block (fun v : block => @eq (option (prod block type)) (@Map.get (prod block type) (ve_of (construct_rho (filter_genv (globalenv prog)) empty_env (@PTree.set val xH (Vptr b Ptrofs.zero) (temp_bindings (xO xH) (@map (prod val type) val (@fst val type) typed_args))))) id) (@Some (prod block type) (@pair block type v ty))), @eq (option type) (@PTree.get type id (var_types (@Delta_types vs G C (@map (prod val type) type (@snd val type) typed_args)))) (@Some type ty) *)
unfold inflate_initial_mem, initial_core, initial_core_ext; simpl.
(* Goal: @eq resource (resource_at (@core rmap Join_rmap Sep_rmap (@proj1_sig rmap (fun phi : rmap => and (@eq nat (@level rmap ag_rmap phi) (@level rmap ag_rmap (@proj1_sig rmap (fun phi0 : rmap => and (@eq nat (@level rmap ag_rmap phi0) n) (and (@eq (forall _ : AV.address, resource) (resource_at phi0) (@initial_world.initial_core' function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n)) (@eq ghost (ghost_of phi0) (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) NoneP)) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds))))))) (make_rmap (@initial_world.initial_core' function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) NoneP)) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)))) n (initial_world.initial_core_ext_obligation_1 function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) (@eq_refl ghost (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) (SomeP (ConstType unit) (fun _ : list Type => tt)))) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds))))))))) (and (@eq (forall _ : AV.address, resource) (resource_at phi) (inflate_initial_mem' m (@proj1_sig rmap (fun phi0 : rmap => and (@eq nat (@level rmap ag_rmap phi0) n) (and (@eq (forall _ : AV.address, resource) (resource_at phi0) (@initial_world.initial_core' function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n)) (@eq ghost (ghost_of phi0) (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) NoneP)) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds))))))) (make_rmap (@initial_world.initial_core' function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) NoneP)) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)))) n (initial_world.initial_core_ext_obligation_1 function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) (@eq_refl ghost (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) (SomeP (ConstType unit) (fun _ : list Type => tt)))) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds))))))))) (@eq ghost (ghost_of phi) (ghost_of (@proj1_sig rmap (fun phi0 : rmap => and (@eq nat (@level rmap ag_rmap phi0) n) (and (@eq (forall _ : AV.address, resource) (resource_at phi0) (@initial_world.initial_core' function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n)) (@eq ghost (ghost_of phi0) (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) NoneP)) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds))))))) (make_rmap (@initial_world.initial_core' function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) NoneP)) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)))) n (initial_world.initial_core_ext_obligation_1 function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) (@eq_refl ghost (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) (SomeP (ConstType unit) (fun _ : list Type => tt)))) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds))))))))))) (make_rmap (inflate_initial_mem' m (@proj1_sig rmap (fun phi : rmap => and (@eq nat (@level rmap ag_rmap phi) n) (and (@eq (forall _ : AV.address, resource) (resource_at phi) (@initial_world.initial_core' function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n)) (@eq ghost (ghost_of phi) (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) NoneP)) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds))))))) (make_rmap (@initial_world.initial_core' function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) NoneP)) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)))) n (initial_world.initial_core_ext_obligation_1 function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) (@eq_refl ghost (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) (SomeP (ConstType unit) (fun _ : list Type => tt)))) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)))))))) (ghost_of (@proj1_sig rmap (fun phi : rmap => and (@eq nat (@level rmap ag_rmap phi) n) (and (@eq (forall _ : AV.address, resource) (resource_at phi) (@initial_world.initial_core' function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n)) (@eq ghost (ghost_of phi) (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) NoneP)) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds))))))) (make_rmap (@initial_world.initial_core' function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) NoneP)) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)))) n (initial_world.initial_core_ext_obligation_1 function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) (@eq_refl ghost (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) (SomeP (ConstType unit) (fun _ : list Type => tt)))) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)))))))) (@level rmap ag_rmap (@proj1_sig rmap (fun phi : rmap => and (@eq nat (@level rmap ag_rmap phi) n) (and (@eq (forall _ : AV.address, resource) (resource_at phi) (@initial_world.initial_core' function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n)) (@eq ghost (ghost_of phi) (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) NoneP)) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds))))))) (make_rmap (@initial_world.initial_core' function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) NoneP)) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)))) n (initial_world.initial_core_ext_obligation_1 function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) (@eq_refl ghost (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) (SomeP (ConstType unit) (fun _ : list Type => tt)))) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)))))))) (inflate_initial_mem'_fmap m (@proj1_sig rmap (fun phi : rmap => and (@eq nat (@level rmap ag_rmap phi) n) (and (@eq (forall _ : AV.address, resource) (resource_at phi) (@initial_world.initial_core' function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n)) (@eq ghost (ghost_of phi) (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) NoneP)) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds))))))) (make_rmap (@initial_world.initial_core' function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) NoneP)) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)))) n (initial_world.initial_core_ext_obligation_1 function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) (@eq_refl ghost (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) (SomeP (ConstType unit) (fun _ : list Type => tt)))) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)))))))) (ghost_of_approx (@proj1_sig rmap (fun phi : rmap => and (@eq nat (@level rmap ag_rmap phi) n) (and (@eq (forall _ : AV.address, resource) (resource_at phi) (@initial_world.initial_core' function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n)) (@eq ghost (ghost_of phi) (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) NoneP)) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds))))))) (make_rmap (@initial_world.initial_core' function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) NoneP)) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)))) n (initial_world.initial_core_ext_obligation_1 function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) (@eq_refl ghost (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) (SomeP (ConstType unit) (fun _ : list Type => tt)))) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds))))))))))) l) (resource_at (@proj1_sig rmap (fun phi : rmap => and (@eq nat (@level rmap ag_rmap phi) n) (and (@eq (forall _ : AV.address, resource) (resource_at phi) (@initial_world.initial_core' function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n)) (@eq ghost (ghost_of phi) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)))))) (make_rmap (@initial_world.initial_core' function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds))) n (initial_world.initial_core_obligation_1 function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) (@eq_refl ghost (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)))))) l) *)
(* Goal: @eq ghost (ghost_of (@core rmap Join_rmap Sep_rmap (inflate_initial_mem m (@initial_world.initial_core_ext function (@OK_ty Espec) ora (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n)))) (ghost_of (@initial_world.initial_core function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n)) *)
rewrite <- core_resource_at.
(* Goal: @eq resource (resource_at (@proj1_sig rmap (fun phi : rmap => and (@eq nat (@level rmap ag_rmap phi) n) (and (@eq (forall _ : AV.address, resource) (resource_at phi) (@initial_world.initial_core' function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n)) (@eq ghost (ghost_of phi) (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) NoneP)) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds))))))) (make_rmap (@initial_world.initial_core' function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) NoneP)) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)))) n (initial_world.initial_core_ext_obligation_1 function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) (@eq_refl ghost (ghost_fmap (approx n) (approx n) (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) NoneP)) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)))))))) (@pair block Z b Z0)) (PURE (FUN f0 cc0) (preds_fmap (approx (@level rmap ag_rmap (@proj1_sig rmap (fun phi : rmap => and (@eq nat (@level rmap ag_rmap phi) n) (and (@eq (forall _ : AV.address, resource) (resource_at phi) (@initial_world.initial_core' function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n)) (@eq ghost (ghost_of phi) (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) NoneP)) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds))))))) (make_rmap (@initial_world.initial_core' function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) NoneP)) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)))) n (initial_world.initial_core_ext_obligation_1 function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) (@eq_refl ghost (ghost_fmap (approx n) (approx n) (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) NoneP)) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)))))))))) (approx (@level rmap ag_rmap (@proj1_sig rmap (fun phi : rmap => and (@eq nat (@level rmap ag_rmap phi) n) (and (@eq (forall _ : AV.address, resource) (resource_at phi) (@initial_world.initial_core' function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n)) (@eq ghost (ghost_of phi) (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) NoneP)) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds))))))) (make_rmap (@initial_world.initial_core' function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) NoneP)) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)))) n (initial_world.initial_core_ext_obligation_1 function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) (@eq_refl ghost (ghost_fmap (approx n) (approx n) (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) NoneP)) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)))))))))) (SomeP (SpecTT A) (@packPQ A a a0)))) *)
repeat rewrite resource_at_make_rmap.
(* Goal: @eq resource (@core resource Join_resource Sep_resource (inflate_initial_mem' m (@proj1_sig rmap (fun phi : rmap => and (@eq nat (@level rmap ag_rmap phi) n) (and (@eq (forall _ : AV.address, resource) (resource_at phi) (@initial_world.initial_core' function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n)) (@eq ghost (ghost_of phi) (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) NoneP)) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds))))))) (make_rmap (@initial_world.initial_core' function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) NoneP)) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)))) n (initial_world.initial_core_ext_obligation_1 function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) (@eq_refl ghost (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) (SomeP (ConstType unit) (fun _ : list Type => tt)))) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds))))))) l)) (@initial_world.initial_core' function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n l) *)
(* Goal: @eq ghost (ghost_of (@core rmap Join_rmap Sep_rmap (inflate_initial_mem m (@initial_world.initial_core_ext function (@OK_ty Espec) ora (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n)))) (ghost_of (@initial_world.initial_core function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n)) *)
unfold inflate_initial_mem'.
(* Goal: @eq resource (resource_at (@proj1_sig rmap (fun phi : rmap => and (@eq nat (@level rmap ag_rmap phi) n) (and (@eq (forall _ : AV.address, resource) (resource_at phi) (@initial_world.initial_core' function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n)) (@eq ghost (ghost_of phi) (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) NoneP)) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds))))))) (make_rmap (@initial_world.initial_core' function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) NoneP)) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)))) n (initial_world.initial_core_ext_obligation_1 function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) (@eq_refl ghost (ghost_fmap (approx n) (approx n) (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) NoneP)) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)))))))) (@pair block Z b Z0)) (PURE (FUN f0 cc0) (preds_fmap (approx (@level rmap ag_rmap (@proj1_sig rmap (fun phi : rmap => and (@eq nat (@level rmap ag_rmap phi) n) (and (@eq (forall _ : AV.address, resource) (resource_at phi) (@initial_world.initial_core' function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n)) (@eq ghost (ghost_of phi) (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) NoneP)) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds))))))) (make_rmap (@initial_world.initial_core' function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) NoneP)) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)))) n (initial_world.initial_core_ext_obligation_1 function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) (@eq_refl ghost (ghost_fmap (approx n) (approx n) (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) NoneP)) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)))))))))) (approx (@level rmap ag_rmap (@proj1_sig rmap (fun phi : rmap => and (@eq nat (@level rmap ag_rmap phi) n) (and (@eq (forall _ : AV.address, resource) (resource_at phi) (@initial_world.initial_core' function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n)) (@eq ghost (ghost_of phi) (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) NoneP)) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds))))))) (make_rmap (@initial_world.initial_core' function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) NoneP)) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)))) n (initial_world.initial_core_ext_obligation_1 function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) (@eq_refl ghost (ghost_fmap (approx n) (approx n) (@cons (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)) (@Some (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds) (@pair (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds (@ext_ghost (@OK_ty Espec) ora) NoneP)) (@nil (option (prod (@sigT ghost.Ghost (fun g : ghost.Ghost => @sig (@ghost.G g) (fun a : @ghost.G g => @ghost.valid g a))) preds)))))))))) (SomeP (SpecTT A) (@packPQ A a a0)))) *)
repeat rewrite resource_at_make_rmap.
(* Goal: @eq resource (@core resource Join_resource Sep_resource match access_at m l Cur with | Some (Freeable as p) => YES Share.top readable_share_top (VAL (contents_at m l)) NoneP | Some (Writable as p) => YES Ews (@writable_readable Ews writable_Ews) (VAL (contents_at m l)) NoneP | Some (Readable as p) => YES Ers readable_Ers (VAL (contents_at m l)) NoneP | Some (Nonempty as p) => match @initial_world.initial_core' function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n l with | NO sh n => NO extern_retainer nonreadable_extern_retainer | YES sh r k p0 => NO extern_retainer nonreadable_extern_retainer | PURE k p0 => @initial_world.initial_core' function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n l end | None => NO Share.bot bot_unreadable end) (@initial_world.initial_core' function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n l) *)
(* Goal: @eq ghost (ghost_of (@core rmap Join_rmap Sep_rmap (inflate_initial_mem m (@initial_world.initial_core_ext function (@OK_ty Espec) ora (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n)))) (ghost_of (@initial_world.initial_core function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n)) *)
unfold initial_core'.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
case_eq (Genv.invert_symbol (Genv.globalenv prog) (fst l)); intros; auto.
(* Goal: @eq resource (@core resource Join_resource Sep_resource match access_at m l Cur with | Some (Freeable as p) => YES Share.top readable_share_top (VAL (contents_at m l)) NoneP | Some (Writable as p) => YES Ews (@writable_readable Ews writable_Ews) (VAL (contents_at m l)) NoneP | Some (Readable as p) => YES Ers readable_Ers (VAL (contents_at m l)) NoneP | Some (Nonempty as p) => match (if Z.eq_dec (@snd block Z l) Z0 then match find_id i G with | Some (mk_funspec fsig cc A P Q P_ne Q_ne as f) => PURE (FUN fsig cc) (SomeP (SpecTT A) (fun ts : list Type => @fmap (dependent_type_functor_rec ts (SpecTT A)) (@pred rmap ag_rmap) (@pred rmap ag_rmap) (approx n) (approx n) (@packPQ A P Q ts))) | None => NO Share.bot bot_unreadable end else NO Share.bot bot_unreadable) with | NO sh n => NO extern_retainer nonreadable_extern_retainer | YES sh r k p0 => NO extern_retainer nonreadable_extern_retainer | PURE k p0 => if Z.eq_dec (@snd block Z l) Z0 then match find_id i G with | Some (mk_funspec fsig cc A P Q P_ne Q_ne as f) => PURE (FUN fsig cc) (SomeP (SpecTT A) (fun ts : list Type => @fmap (dependent_type_functor_rec ts (SpecTT A)) (@pred rmap ag_rmap) (@pred rmap ag_rmap) (approx n) (approx n) (@packPQ A P Q ts))) | None => NO Share.bot bot_unreadable end else NO Share.bot bot_unreadable end | None => NO Share.bot bot_unreadable end) (if Z.eq_dec (@snd block Z l) Z0 then match find_id i G with | Some (mk_funspec fsig cc A P Q P_ne Q_ne as f) => PURE (FUN fsig cc) (SomeP (SpecTT A) (fun ts : list Type => @fmap (dependent_type_functor_rec ts (SpecTT A)) (@pred rmap ag_rmap) (@pred rmap ag_rmap) (approx n) (approx n) (@packPQ A P Q ts))) | None => NO Share.bot bot_unreadable end else NO Share.bot bot_unreadable) *)
(* Goal: @eq resource (@core resource Join_resource Sep_resource match access_at m l Cur with | Some (Freeable as p) => YES Share.top readable_share_top (VAL (contents_at m l)) NoneP | Some (Writable as p) => YES Ews (@writable_readable Ews writable_Ews) (VAL (contents_at m l)) NoneP | Some (Readable as p) => YES Ers readable_Ers (VAL (contents_at m l)) NoneP | Some (Nonempty as p) => match (if Z.eq_dec (@snd block Z l) Z0 then NO Share.bot bot_unreadable else NO Share.bot bot_unreadable) with | NO sh n => NO extern_retainer nonreadable_extern_retainer | YES sh r k p0 => NO extern_retainer nonreadable_extern_retainer | PURE k p0 => if Z.eq_dec (@snd block Z l) Z0 then NO Share.bot bot_unreadable else NO Share.bot bot_unreadable end | None => NO Share.bot bot_unreadable end) (if Z.eq_dec (@snd block Z l) Z0 then NO Share.bot bot_unreadable else NO Share.bot bot_unreadable) *)
(* Goal: @eq ghost (ghost_of (@core rmap Join_rmap Sep_rmap (inflate_initial_mem m (@initial_world.initial_core_ext function (@OK_ty Espec) ora (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n)))) (ghost_of (@initial_world.initial_core function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n)) *)
rename i into id.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
case_eq (find_id id G); intros; auto.
(* Goal: @eq resource (@core resource Join_resource Sep_resource match access_at m l Cur with | Some (Freeable as p) => YES Share.top readable_share_top (VAL (contents_at m l)) NoneP | Some (Writable as p) => YES Ews (@writable_readable Ews writable_Ews) (VAL (contents_at m l)) NoneP | Some (Readable as p) => YES Ers readable_Ers (VAL (contents_at m l)) NoneP | Some (Nonempty as p) => match (if Z.eq_dec (@snd block Z l) Z0 then match f with | mk_funspec fsig cc A P Q P_ne Q_ne => PURE (FUN fsig cc) (SomeP (SpecTT A) (fun ts : list Type => @fmap (dependent_type_functor_rec ts (SpecTT A)) (@pred rmap ag_rmap) (@pred rmap ag_rmap) (approx n) (approx n) (@packPQ A P Q ts))) end else NO Share.bot bot_unreadable) with | NO sh n => NO extern_retainer nonreadable_extern_retainer | YES sh r k p0 => NO extern_retainer nonreadable_extern_retainer | PURE k p0 => if Z.eq_dec (@snd block Z l) Z0 then match f with | mk_funspec fsig cc A P Q P_ne Q_ne => PURE (FUN fsig cc) (SomeP (SpecTT A) (fun ts : list Type => @fmap (dependent_type_functor_rec ts (SpecTT A)) (@pred rmap ag_rmap) (@pred rmap ag_rmap) (approx n) (approx n) (@packPQ A P Q ts))) end else NO Share.bot bot_unreadable end | None => NO Share.bot bot_unreadable end) (if Z.eq_dec (@snd block Z l) Z0 then match f with | mk_funspec fsig cc A P Q P_ne Q_ne => PURE (FUN fsig cc) (SomeP (SpecTT A) (fun ts : list Type => @fmap (dependent_type_functor_rec ts (SpecTT A)) (@pred rmap ag_rmap) (@pred rmap ag_rmap) (approx n) (approx n) (@packPQ A P Q ts))) end else NO Share.bot bot_unreadable) *)
(* Goal: @eq resource (@core resource Join_resource Sep_resource match access_at m l Cur with | Some (Freeable as p) => YES Share.top readable_share_top (VAL (contents_at m l)) NoneP | Some (Writable as p) => YES Ews (@writable_readable Ews writable_Ews) (VAL (contents_at m l)) NoneP | Some (Readable as p) => YES Ers readable_Ers (VAL (contents_at m l)) NoneP | Some (Nonempty as p) => match (if Z.eq_dec (@snd block Z l) Z0 then NO Share.bot bot_unreadable else NO Share.bot bot_unreadable) with | NO sh n => NO extern_retainer nonreadable_extern_retainer | YES sh r k p0 => NO extern_retainer nonreadable_extern_retainer | PURE k p0 => if Z.eq_dec (@snd block Z l) Z0 then NO Share.bot bot_unreadable else NO Share.bot bot_unreadable end | None => NO Share.bot bot_unreadable end) (if Z.eq_dec (@snd block Z l) Z0 then NO Share.bot bot_unreadable else NO Share.bot bot_unreadable) *)
(* Goal: @eq resource (@core resource Join_resource Sep_resource match access_at m l Cur with | Some (Freeable as p) => YES Share.top readable_share_top (VAL (contents_at m l)) NoneP | Some (Writable as p) => YES Ews (@writable_readable Ews writable_Ews) (VAL (contents_at m l)) NoneP | Some (Readable as p) => YES Ers readable_Ers (VAL (contents_at m l)) NoneP | Some (Nonempty as p) => match (if Z.eq_dec (@snd block Z l) Z0 then NO Share.bot bot_unreadable else NO Share.bot bot_unreadable) with | NO sh n => NO extern_retainer nonreadable_extern_retainer | YES sh r k p0 => NO extern_retainer nonreadable_extern_retainer | PURE k p0 => if Z.eq_dec (@snd block Z l) Z0 then NO Share.bot bot_unreadable else NO Share.bot bot_unreadable end | None => NO Share.bot bot_unreadable end) (if Z.eq_dec (@snd block Z l) Z0 then NO Share.bot bot_unreadable else NO Share.bot bot_unreadable) *)
(* Goal: @eq ghost (ghost_of (@core rmap Join_rmap Sep_rmap (inflate_initial_mem m (@initial_world.initial_core_ext function (@OK_ty Espec) ora (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n)))) (ghost_of (@initial_world.initial_core function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n)) *)
rename f into fs.
(* Goal: @eq resource (@core resource Join_resource Sep_resource match access_at m l Cur with | Some (Freeable as p) => YES Share.top readable_share_top (VAL (contents_at m l)) NoneP | Some (Writable as p) => YES Ews (@writable_readable Ews writable_Ews) (VAL (contents_at m l)) NoneP | Some (Readable as p) => YES Ers readable_Ers (VAL (contents_at m l)) NoneP | Some (Nonempty as p) => match (if Z.eq_dec (@snd block Z l) Z0 then match fs with | mk_funspec fsig cc A P Q P_ne Q_ne => PURE (FUN fsig cc) (SomeP (SpecTT A) (fun ts : list Type => @fmap (dependent_type_functor_rec ts (SpecTT A)) (@pred rmap ag_rmap) (@pred rmap ag_rmap) (approx n) (approx n) (@packPQ A P Q ts))) end else NO Share.bot bot_unreadable) with | NO sh n => NO extern_retainer nonreadable_extern_retainer | YES sh r k p0 => NO extern_retainer nonreadable_extern_retainer | PURE k p0 => if Z.eq_dec (@snd block Z l) Z0 then match fs with | mk_funspec fsig cc A P Q P_ne Q_ne => PURE (FUN fsig cc) (SomeP (SpecTT A) (fun ts : list Type => @fmap (dependent_type_functor_rec ts (SpecTT A)) (@pred rmap ag_rmap) (@pred rmap ag_rmap) (approx n) (approx n) (@packPQ A P Q ts))) end else NO Share.bot bot_unreadable end | None => NO Share.bot bot_unreadable end) (if Z.eq_dec (@snd block Z l) Z0 then match fs with | mk_funspec fsig cc A P Q P_ne Q_ne => PURE (FUN fsig cc) (SomeP (SpecTT A) (fun ts : list Type => @fmap (dependent_type_functor_rec ts (SpecTT A)) (@pred rmap ag_rmap) (@pred rmap ag_rmap) (approx n) (approx n) (@packPQ A P Q ts))) end else NO Share.bot bot_unreadable) *)
(* Goal: @eq resource (@core resource Join_resource Sep_resource match access_at m l Cur with | Some (Freeable as p) => YES Share.top readable_share_top (VAL (contents_at m l)) NoneP | Some (Writable as p) => YES Ews (@writable_readable Ews writable_Ews) (VAL (contents_at m l)) NoneP | Some (Readable as p) => YES Ers readable_Ers (VAL (contents_at m l)) NoneP | Some (Nonempty as p) => match (if Z.eq_dec (@snd block Z l) Z0 then NO Share.bot bot_unreadable else NO Share.bot bot_unreadable) with | NO sh n => NO extern_retainer nonreadable_extern_retainer | YES sh r k p0 => NO extern_retainer nonreadable_extern_retainer | PURE k p0 => if Z.eq_dec (@snd block Z l) Z0 then NO Share.bot bot_unreadable else NO Share.bot bot_unreadable end | None => NO Share.bot bot_unreadable end) (if Z.eq_dec (@snd block Z l) Z0 then NO Share.bot bot_unreadable else NO Share.bot bot_unreadable) *)
(* Goal: @eq resource (@core resource Join_resource Sep_resource match access_at m l Cur with | Some (Freeable as p) => YES Share.top readable_share_top (VAL (contents_at m l)) NoneP | Some (Writable as p) => YES Ews (@writable_readable Ews writable_Ews) (VAL (contents_at m l)) NoneP | Some (Readable as p) => YES Ers readable_Ers (VAL (contents_at m l)) NoneP | Some (Nonempty as p) => match (if Z.eq_dec (@snd block Z l) Z0 then NO Share.bot bot_unreadable else NO Share.bot bot_unreadable) with | NO sh n => NO extern_retainer nonreadable_extern_retainer | YES sh r k p0 => NO extern_retainer nonreadable_extern_retainer | PURE k p0 => if Z.eq_dec (@snd block Z l) Z0 then NO Share.bot bot_unreadable else NO Share.bot bot_unreadable end | None => NO Share.bot bot_unreadable end) (if Z.eq_dec (@snd block Z l) Z0 then NO Share.bot bot_unreadable else NO Share.bot bot_unreadable) *)
(* Goal: @eq ghost (ghost_of (@core rmap Join_rmap Sep_rmap (inflate_initial_mem m (@initial_world.initial_core_ext function (@OK_ty Espec) ora (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n)))) (ghost_of (@initial_world.initial_core function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n)) *)
assert (exists f, In (id,f) (prog_funct prog)).
(* Goal: @ex (Ctypes.fundef function) (fun f : Ctypes.fundef function => @In (prod ident (Ctypes.fundef function)) (@pair ident (Ctypes.fundef function) id f) (@initial_world.prog_funct function prog)) *)
(* Goal: @eq resource (@core resource Join_resource Sep_resource match access_at m l Cur with | Some (Freeable as p) => YES Share.top readable_share_top (VAL (contents_at m l)) NoneP | Some (Writable as p) => YES Ews (@writable_readable Ews writable_Ews) (VAL (contents_at m l)) NoneP | Some (Readable as p) => YES Ers readable_Ers (VAL (contents_at m l)) NoneP | Some (Nonempty as p) => match (if Z.eq_dec (@snd block Z l) Z0 then match fs with | mk_funspec fsig cc A P Q P_ne Q_ne => PURE (FUN fsig cc) (SomeP (SpecTT A) (fun ts : list Type => @fmap (dependent_type_functor_rec ts (SpecTT A)) (@pred rmap ag_rmap) (@pred rmap ag_rmap) (approx n) (approx n) (@packPQ A P Q ts))) end else NO Share.bot bot_unreadable) with | NO sh n => NO extern_retainer nonreadable_extern_retainer | YES sh r k p0 => NO extern_retainer nonreadable_extern_retainer | PURE k p0 => if Z.eq_dec (@snd block Z l) Z0 then match fs with | mk_funspec fsig cc A P Q P_ne Q_ne => PURE (FUN fsig cc) (SomeP (SpecTT A) (fun ts : list Type => @fmap (dependent_type_functor_rec ts (SpecTT A)) (@pred rmap ag_rmap) (@pred rmap ag_rmap) (approx n) (approx n) (@packPQ A P Q ts))) end else NO Share.bot bot_unreadable end | None => NO Share.bot bot_unreadable end) (if Z.eq_dec (@snd block Z l) Z0 then match fs with | mk_funspec fsig cc A P Q P_ne Q_ne => PURE (FUN fsig cc) (SomeP (SpecTT A) (fun ts : list Type => @fmap (dependent_type_functor_rec ts (SpecTT A)) (@pred rmap ag_rmap) (@pred rmap ag_rmap) (approx n) (approx n) (@packPQ A P Q ts))) end else NO Share.bot bot_unreadable) *)
(* Goal: @eq resource (@core resource Join_resource Sep_resource match access_at m l Cur with | Some (Freeable as p) => YES Share.top readable_share_top (VAL (contents_at m l)) NoneP | Some (Writable as p) => YES Ews (@writable_readable Ews writable_Ews) (VAL (contents_at m l)) NoneP | Some (Readable as p) => YES Ers readable_Ers (VAL (contents_at m l)) NoneP | Some (Nonempty as p) => match (if Z.eq_dec (@snd block Z l) Z0 then NO Share.bot bot_unreadable else NO Share.bot bot_unreadable) with | NO sh n => NO extern_retainer nonreadable_extern_retainer | YES sh r k p0 => NO extern_retainer nonreadable_extern_retainer | PURE k p0 => if Z.eq_dec (@snd block Z l) Z0 then NO Share.bot bot_unreadable else NO Share.bot bot_unreadable end | None => NO Share.bot bot_unreadable end) (if Z.eq_dec (@snd block Z l) Z0 then NO Share.bot bot_unreadable else NO Share.bot bot_unreadable) *)
(* Goal: @eq resource (@core resource Join_resource Sep_resource match access_at m l Cur with | Some (Freeable as p) => YES Share.top readable_share_top (VAL (contents_at m l)) NoneP | Some (Writable as p) => YES Ews (@writable_readable Ews writable_Ews) (VAL (contents_at m l)) NoneP | Some (Readable as p) => YES Ers readable_Ers (VAL (contents_at m l)) NoneP | Some (Nonempty as p) => match (if Z.eq_dec (@snd block Z l) Z0 then NO Share.bot bot_unreadable else NO Share.bot bot_unreadable) with | NO sh n => NO extern_retainer nonreadable_extern_retainer | YES sh r k p0 => NO extern_retainer nonreadable_extern_retainer | PURE k p0 => if Z.eq_dec (@snd block Z l) Z0 then NO Share.bot bot_unreadable else NO Share.bot bot_unreadable end | None => NO Share.bot bot_unreadable end) (if Z.eq_dec (@snd block Z l) Z0 then NO Share.bot bot_unreadable else NO Share.bot bot_unreadable) *)
(* Goal: @eq ghost (ghost_of (@core rmap Join_rmap Sep_rmap (inflate_initial_mem m (@initial_world.initial_core_ext function (@OK_ty Espec) ora (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n)))) (ghost_of (@initial_world.initial_core function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n)) *)
apply find_id_e in H2.
(* Goal: @ex (Ctypes.fundef function) (fun f : Ctypes.fundef function => @In (prod ident (Ctypes.fundef function)) (@pair ident (Ctypes.fundef function) id f) (@initial_world.prog_funct function prog)) *)
(* Goal: @eq resource (@core resource Join_resource Sep_resource match access_at m l Cur with | Some (Freeable as p) => YES Share.top readable_share_top (VAL (contents_at m l)) NoneP | Some (Writable as p) => YES Ews (@writable_readable Ews writable_Ews) (VAL (contents_at m l)) NoneP | Some (Readable as p) => YES Ers readable_Ers (VAL (contents_at m l)) NoneP | Some (Nonempty as p) => match (if Z.eq_dec (@snd block Z l) Z0 then match fs with | mk_funspec fsig cc A P Q P_ne Q_ne => PURE (FUN fsig cc) (SomeP (SpecTT A) (fun ts : list Type => @fmap (dependent_type_functor_rec ts (SpecTT A)) (@pred rmap ag_rmap) (@pred rmap ag_rmap) (approx n) (approx n) (@packPQ A P Q ts))) end else NO Share.bot bot_unreadable) with | NO sh n => NO extern_retainer nonreadable_extern_retainer | YES sh r k p0 => NO extern_retainer nonreadable_extern_retainer | PURE k p0 => if Z.eq_dec (@snd block Z l) Z0 then match fs with | mk_funspec fsig cc A P Q P_ne Q_ne => PURE (FUN fsig cc) (SomeP (SpecTT A) (fun ts : list Type => @fmap (dependent_type_functor_rec ts (SpecTT A)) (@pred rmap ag_rmap) (@pred rmap ag_rmap) (approx n) (approx n) (@packPQ A P Q ts))) end else NO Share.bot bot_unreadable end | None => NO Share.bot bot_unreadable end) (if Z.eq_dec (@snd block Z l) Z0 then match fs with | mk_funspec fsig cc A P Q P_ne Q_ne => PURE (FUN fsig cc) (SomeP (SpecTT A) (fun ts : list Type => @fmap (dependent_type_functor_rec ts (SpecTT A)) (@pred rmap ag_rmap) (@pred rmap ag_rmap) (approx n) (approx n) (@packPQ A P Q ts))) end else NO Share.bot bot_unreadable) *)
(* Goal: @eq resource (@core resource Join_resource Sep_resource match access_at m l Cur with | Some (Freeable as p) => YES Share.top readable_share_top (VAL (contents_at m l)) NoneP | Some (Writable as p) => YES Ews (@writable_readable Ews writable_Ews) (VAL (contents_at m l)) NoneP | Some (Readable as p) => YES Ers readable_Ers (VAL (contents_at m l)) NoneP | Some (Nonempty as p) => match (if Z.eq_dec (@snd block Z l) Z0 then NO Share.bot bot_unreadable else NO Share.bot bot_unreadable) with | NO sh n => NO extern_retainer nonreadable_extern_retainer | YES sh r k p0 => NO extern_retainer nonreadable_extern_retainer | PURE k p0 => if Z.eq_dec (@snd block Z l) Z0 then NO Share.bot bot_unreadable else NO Share.bot bot_unreadable end | None => NO Share.bot bot_unreadable end) (if Z.eq_dec (@snd block Z l) Z0 then NO Share.bot bot_unreadable else NO Share.bot bot_unreadable) *)
(* Goal: @eq resource (@core resource Join_resource Sep_resource match access_at m l Cur with | Some (Freeable as p) => YES Share.top readable_share_top (VAL (contents_at m l)) NoneP | Some (Writable as p) => YES Ews (@writable_readable Ews writable_Ews) (VAL (contents_at m l)) NoneP | Some (Readable as p) => YES Ers readable_Ers (VAL (contents_at m l)) NoneP | Some (Nonempty as p) => match (if Z.eq_dec (@snd block Z l) Z0 then NO Share.bot bot_unreadable else NO Share.bot bot_unreadable) with | NO sh n => NO extern_retainer nonreadable_extern_retainer | YES sh r k p0 => NO extern_retainer nonreadable_extern_retainer | PURE k p0 => if Z.eq_dec (@snd block Z l) Z0 then NO Share.bot bot_unreadable else NO Share.bot bot_unreadable end | None => NO Share.bot bot_unreadable end) (if Z.eq_dec (@snd block Z l) Z0 then NO Share.bot bot_unreadable else NO Share.bot bot_unreadable) *)
(* Goal: @eq ghost (ghost_of (@core rmap Join_rmap Sep_rmap (inflate_initial_mem m (@initial_world.initial_core_ext function (@OK_ty Espec) ora (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n)))) (ghost_of (@initial_world.initial_core function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n)) *)
apply in_map_fst in H2.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
eapply match_fdecs_in in H2; eauto.
(* Goal: @ex (Ctypes.fundef function) (fun f : Ctypes.fundef function => @In (prod ident (Ctypes.fundef function)) (@pair ident (Ctypes.fundef function) id f) (@initial_world.prog_funct function prog)) *)
(* Goal: @eq resource (@core resource Join_resource Sep_resource match access_at m l Cur with | Some (Freeable as p) => YES Share.top readable_share_top (VAL (contents_at m l)) NoneP | Some (Writable as p) => YES Ews (@writable_readable Ews writable_Ews) (VAL (contents_at m l)) NoneP | Some (Readable as p) => YES Ers readable_Ers (VAL (contents_at m l)) NoneP | Some (Nonempty as p) => match (if Z.eq_dec (@snd block Z l) Z0 then match fs with | mk_funspec fsig cc A P Q P_ne Q_ne => PURE (FUN fsig cc) (SomeP (SpecTT A) (fun ts : list Type => @fmap (dependent_type_functor_rec ts (SpecTT A)) (@pred rmap ag_rmap) (@pred rmap ag_rmap) (approx n) (approx n) (@packPQ A P Q ts))) end else NO Share.bot bot_unreadable) with | NO sh n => NO extern_retainer nonreadable_extern_retainer | YES sh r k p0 => NO extern_retainer nonreadable_extern_retainer | PURE k p0 => if Z.eq_dec (@snd block Z l) Z0 then match fs with | mk_funspec fsig cc A P Q P_ne Q_ne => PURE (FUN fsig cc) (SomeP (SpecTT A) (fun ts : list Type => @fmap (dependent_type_functor_rec ts (SpecTT A)) (@pred rmap ag_rmap) (@pred rmap ag_rmap) (approx n) (approx n) (@packPQ A P Q ts))) end else NO Share.bot bot_unreadable end | None => NO Share.bot bot_unreadable end) (if Z.eq_dec (@snd block Z l) Z0 then match fs with | mk_funspec fsig cc A P Q P_ne Q_ne => PURE (FUN fsig cc) (SomeP (SpecTT A) (fun ts : list Type => @fmap (dependent_type_functor_rec ts (SpecTT A)) (@pred rmap ag_rmap) (@pred rmap ag_rmap) (approx n) (approx n) (@packPQ A P Q ts))) end else NO Share.bot bot_unreadable) *)
(* Goal: @eq resource (@core resource Join_resource Sep_resource match access_at m l Cur with | Some (Freeable as p) => YES Share.top readable_share_top (VAL (contents_at m l)) NoneP | Some (Writable as p) => YES Ews (@writable_readable Ews writable_Ews) (VAL (contents_at m l)) NoneP | Some (Readable as p) => YES Ers readable_Ers (VAL (contents_at m l)) NoneP | Some (Nonempty as p) => match (if Z.eq_dec (@snd block Z l) Z0 then NO Share.bot bot_unreadable else NO Share.bot bot_unreadable) with | NO sh n => NO extern_retainer nonreadable_extern_retainer | YES sh r k p0 => NO extern_retainer nonreadable_extern_retainer | PURE k p0 => if Z.eq_dec (@snd block Z l) Z0 then NO Share.bot bot_unreadable else NO Share.bot bot_unreadable end | None => NO Share.bot bot_unreadable end) (if Z.eq_dec (@snd block Z l) Z0 then NO Share.bot bot_unreadable else NO Share.bot bot_unreadable) *)
(* Goal: @eq resource (@core resource Join_resource Sep_resource match access_at m l Cur with | Some (Freeable as p) => YES Share.top readable_share_top (VAL (contents_at m l)) NoneP | Some (Writable as p) => YES Ews (@writable_readable Ews writable_Ews) (VAL (contents_at m l)) NoneP | Some (Readable as p) => YES Ers readable_Ers (VAL (contents_at m l)) NoneP | Some (Nonempty as p) => match (if Z.eq_dec (@snd block Z l) Z0 then NO Share.bot bot_unreadable else NO Share.bot bot_unreadable) with | NO sh n => NO extern_retainer nonreadable_extern_retainer | YES sh r k p0 => NO extern_retainer nonreadable_extern_retainer | PURE k p0 => if Z.eq_dec (@snd block Z l) Z0 then NO Share.bot bot_unreadable else NO Share.bot bot_unreadable end | None => NO Share.bot bot_unreadable end) (if Z.eq_dec (@snd block Z l) Z0 then NO Share.bot bot_unreadable else NO Share.bot bot_unreadable) *)
(* Goal: @eq ghost (ghost_of (@core rmap Join_rmap Sep_rmap (inflate_initial_mem m (@initial_world.initial_core_ext function (@OK_ty Espec) ora (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n)))) (ghost_of (@initial_world.initial_core function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n)) *)
apply in_map_iff in H2.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
destruct H2 as [[i' f] [? ?]]. subst id; exists f; auto.
(* Goal: @eq resource (@core resource Join_resource Sep_resource match access_at m l Cur with | Some (Freeable as p) => YES Share.top readable_share_top (VAL (contents_at m l)) NoneP | Some (Writable as p) => YES Ews (@writable_readable Ews writable_Ews) (VAL (contents_at m l)) NoneP | Some (Readable as p) => YES Ers readable_Ers (VAL (contents_at m l)) NoneP | Some (Nonempty as p) => match (if Z.eq_dec (@snd block Z l) Z0 then match fs with | mk_funspec fsig cc A P Q P_ne Q_ne => PURE (FUN fsig cc) (SomeP (SpecTT A) (fun ts : list Type => @fmap (dependent_type_functor_rec ts (SpecTT A)) (@pred rmap ag_rmap) (@pred rmap ag_rmap) (approx n) (approx n) (@packPQ A P Q ts))) end else NO Share.bot bot_unreadable) with | NO sh n => NO extern_retainer nonreadable_extern_retainer | YES sh r k p0 => NO extern_retainer nonreadable_extern_retainer | PURE k p0 => if Z.eq_dec (@snd block Z l) Z0 then match fs with | mk_funspec fsig cc A P Q P_ne Q_ne => PURE (FUN fsig cc) (SomeP (SpecTT A) (fun ts : list Type => @fmap (dependent_type_functor_rec ts (SpecTT A)) (@pred rmap ag_rmap) (@pred rmap ag_rmap) (approx n) (approx n) (@packPQ A P Q ts))) end else NO Share.bot bot_unreadable end | None => NO Share.bot bot_unreadable end) (if Z.eq_dec (@snd block Z l) Z0 then match fs with | mk_funspec fsig cc A P Q P_ne Q_ne => PURE (FUN fsig cc) (SomeP (SpecTT A) (fun ts : list Type => @fmap (dependent_type_functor_rec ts (SpecTT A)) (@pred rmap ag_rmap) (@pred rmap ag_rmap) (approx n) (approx n) (@packPQ A P Q ts))) end else NO Share.bot bot_unreadable) *)
(* Goal: @eq resource (@core resource Join_resource Sep_resource match access_at m l Cur with | Some (Freeable as p) => YES Share.top readable_share_top (VAL (contents_at m l)) NoneP | Some (Writable as p) => YES Ews (@writable_readable Ews writable_Ews) (VAL (contents_at m l)) NoneP | Some (Readable as p) => YES Ers readable_Ers (VAL (contents_at m l)) NoneP | Some (Nonempty as p) => match (if Z.eq_dec (@snd block Z l) Z0 then NO Share.bot bot_unreadable else NO Share.bot bot_unreadable) with | NO sh n => NO extern_retainer nonreadable_extern_retainer | YES sh r k p0 => NO extern_retainer nonreadable_extern_retainer | PURE k p0 => if Z.eq_dec (@snd block Z l) Z0 then NO Share.bot bot_unreadable else NO Share.bot bot_unreadable end | None => NO Share.bot bot_unreadable end) (if Z.eq_dec (@snd block Z l) Z0 then NO Share.bot bot_unreadable else NO Share.bot bot_unreadable) *)
(* Goal: @eq resource (@core resource Join_resource Sep_resource match access_at m l Cur with | Some (Freeable as p) => YES Share.top readable_share_top (VAL (contents_at m l)) NoneP | Some (Writable as p) => YES Ews (@writable_readable Ews writable_Ews) (VAL (contents_at m l)) NoneP | Some (Readable as p) => YES Ers readable_Ers (VAL (contents_at m l)) NoneP | Some (Nonempty as p) => match (if Z.eq_dec (@snd block Z l) Z0 then NO Share.bot bot_unreadable else NO Share.bot bot_unreadable) with | NO sh n => NO extern_retainer nonreadable_extern_retainer | YES sh r k p0 => NO extern_retainer nonreadable_extern_retainer | PURE k p0 => if Z.eq_dec (@snd block Z l) Z0 then NO Share.bot bot_unreadable else NO Share.bot bot_unreadable end | None => NO Share.bot bot_unreadable end) (if Z.eq_dec (@snd block Z l) Z0 then NO Share.bot bot_unreadable else NO Share.bot bot_unreadable) *)
(* Goal: @eq ghost (ghost_of (@core rmap Join_rmap Sep_rmap (inflate_initial_mem m (@initial_world.initial_core_ext function (@OK_ty Espec) ora (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n)))) (ghost_of (@initial_world.initial_core function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n)) *)
destruct H3 as [f ?].
(* Goal: @eq resource (@core resource Join_resource Sep_resource match access_at m l Cur with | Some (Freeable as p) => YES Share.top readable_share_top (VAL (contents_at m l)) NoneP | Some (Writable as p) => YES Ews (@writable_readable Ews writable_Ews) (VAL (contents_at m l)) NoneP | Some (Readable as p) => YES Ers readable_Ers (VAL (contents_at m l)) NoneP | Some (Nonempty as p) => match (if Z.eq_dec (@snd block Z l) Z0 then match fs with | mk_funspec fsig cc A P Q P_ne Q_ne => PURE (FUN fsig cc) (SomeP (SpecTT A) (fun ts : list Type => @fmap (dependent_type_functor_rec ts (SpecTT A)) (@pred rmap ag_rmap) (@pred rmap ag_rmap) (approx n) (approx n) (@packPQ A P Q ts))) end else NO Share.bot bot_unreadable) with | NO sh n => NO extern_retainer nonreadable_extern_retainer | YES sh r k p0 => NO extern_retainer nonreadable_extern_retainer | PURE k p0 => if Z.eq_dec (@snd block Z l) Z0 then match fs with | mk_funspec fsig cc A P Q P_ne Q_ne => PURE (FUN fsig cc) (SomeP (SpecTT A) (fun ts : list Type => @fmap (dependent_type_functor_rec ts (SpecTT A)) (@pred rmap ag_rmap) (@pred rmap ag_rmap) (approx n) (approx n) (@packPQ A P Q ts))) end else NO Share.bot bot_unreadable end | None => NO Share.bot bot_unreadable end) (if Z.eq_dec (@snd block Z l) Z0 then match fs with | mk_funspec fsig cc A P Q P_ne Q_ne => PURE (FUN fsig cc) (SomeP (SpecTT A) (fun ts : list Type => @fmap (dependent_type_functor_rec ts (SpecTT A)) (@pred rmap ag_rmap) (@pred rmap ag_rmap) (approx n) (approx n) (@packPQ A P Q ts))) end else NO Share.bot bot_unreadable) *)
(* Goal: @eq resource (@core resource Join_resource Sep_resource match access_at m l Cur with | Some (Freeable as p) => YES Share.top readable_share_top (VAL (contents_at m l)) NoneP | Some (Writable as p) => YES Ews (@writable_readable Ews writable_Ews) (VAL (contents_at m l)) NoneP | Some (Readable as p) => YES Ers readable_Ers (VAL (contents_at m l)) NoneP | Some (Nonempty as p) => match (if Z.eq_dec (@snd block Z l) Z0 then NO Share.bot bot_unreadable else NO Share.bot bot_unreadable) with | NO sh n => NO extern_retainer nonreadable_extern_retainer | YES sh r k p0 => NO extern_retainer nonreadable_extern_retainer | PURE k p0 => if Z.eq_dec (@snd block Z l) Z0 then NO Share.bot bot_unreadable else NO Share.bot bot_unreadable end | None => NO Share.bot bot_unreadable end) (if Z.eq_dec (@snd block Z l) Z0 then NO Share.bot bot_unreadable else NO Share.bot bot_unreadable) *)
(* Goal: @eq resource (@core resource Join_resource Sep_resource match access_at m l Cur with | Some (Freeable as p) => YES Share.top readable_share_top (VAL (contents_at m l)) NoneP | Some (Writable as p) => YES Ews (@writable_readable Ews writable_Ews) (VAL (contents_at m l)) NoneP | Some (Readable as p) => YES Ers readable_Ers (VAL (contents_at m l)) NoneP | Some (Nonempty as p) => match (if Z.eq_dec (@snd block Z l) Z0 then NO Share.bot bot_unreadable else NO Share.bot bot_unreadable) with | NO sh n => NO extern_retainer nonreadable_extern_retainer | YES sh r k p0 => NO extern_retainer nonreadable_extern_retainer | PURE k p0 => if Z.eq_dec (@snd block Z l) Z0 then NO Share.bot bot_unreadable else NO Share.bot bot_unreadable end | None => NO Share.bot bot_unreadable end) (if Z.eq_dec (@snd block Z l) Z0 then NO Share.bot bot_unreadable else NO Share.bot bot_unreadable) *)
(* Goal: @eq ghost (ghost_of (@core rmap Join_rmap Sep_rmap (inflate_initial_mem m (@initial_world.initial_core_ext function (@OK_ty Espec) ora (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n)))) (ghost_of (@initial_world.initial_core function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n)) *)
apply Genv.invert_find_symbol in H1.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
destruct (find_funct_ptr_exists prog id f) as [b [? ?]]; auto.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
apply in_prog_funct_in_prog_defs; auto.
(* Goal: @eq resource (@core resource Join_resource Sep_resource match access_at m l Cur with | Some (Freeable as p) => YES Share.top readable_share_top (VAL (contents_at m l)) NoneP | Some (Writable as p) => YES Ews (@writable_readable Ews writable_Ews) (VAL (contents_at m l)) NoneP | Some (Readable as p) => YES Ers readable_Ers (VAL (contents_at m l)) NoneP | Some (Nonempty as p) => match (if Z.eq_dec (@snd block Z l) Z0 then match fs with | mk_funspec fsig cc A P Q P_ne Q_ne => PURE (FUN fsig cc) (SomeP (SpecTT A) (fun ts : list Type => @fmap (dependent_type_functor_rec ts (SpecTT A)) (@pred rmap ag_rmap) (@pred rmap ag_rmap) (approx n) (approx n) (@packPQ A P Q ts))) end else NO Share.bot bot_unreadable) with | NO sh n => NO extern_retainer nonreadable_extern_retainer | YES sh r k p0 => NO extern_retainer nonreadable_extern_retainer | PURE k p0 => if Z.eq_dec (@snd block Z l) Z0 then match fs with | mk_funspec fsig cc A P Q P_ne Q_ne => PURE (FUN fsig cc) (SomeP (SpecTT A) (fun ts : list Type => @fmap (dependent_type_functor_rec ts (SpecTT A)) (@pred rmap ag_rmap) (@pred rmap ag_rmap) (approx n) (approx n) (@packPQ A P Q ts))) end else NO Share.bot bot_unreadable end | None => NO Share.bot bot_unreadable end) (if Z.eq_dec (@snd block Z l) Z0 then match fs with | mk_funspec fsig cc A P Q P_ne Q_ne => PURE (FUN fsig cc) (SomeP (SpecTT A) (fun ts : list Type => @fmap (dependent_type_functor_rec ts (SpecTT A)) (@pred rmap ag_rmap) (@pred rmap ag_rmap) (approx n) (approx n) (@packPQ A P Q ts))) end else NO Share.bot bot_unreadable) *)
(* Goal: @eq resource (@core resource Join_resource Sep_resource match access_at m l Cur with | Some (Freeable as p) => YES Share.top readable_share_top (VAL (contents_at m l)) NoneP | Some (Writable as p) => YES Ews (@writable_readable Ews writable_Ews) (VAL (contents_at m l)) NoneP | Some (Readable as p) => YES Ers readable_Ers (VAL (contents_at m l)) NoneP | Some (Nonempty as p) => match (if Z.eq_dec (@snd block Z l) Z0 then NO Share.bot bot_unreadable else NO Share.bot bot_unreadable) with | NO sh n => NO extern_retainer nonreadable_extern_retainer | YES sh r k p0 => NO extern_retainer nonreadable_extern_retainer | PURE k p0 => if Z.eq_dec (@snd block Z l) Z0 then NO Share.bot bot_unreadable else NO Share.bot bot_unreadable end | None => NO Share.bot bot_unreadable end) (if Z.eq_dec (@snd block Z l) Z0 then NO Share.bot bot_unreadable else NO Share.bot bot_unreadable) *)
(* Goal: @eq resource (@core resource Join_resource Sep_resource match access_at m l Cur with | Some (Freeable as p) => YES Share.top readable_share_top (VAL (contents_at m l)) NoneP | Some (Writable as p) => YES Ews (@writable_readable Ews writable_Ews) (VAL (contents_at m l)) NoneP | Some (Readable as p) => YES Ers readable_Ers (VAL (contents_at m l)) NoneP | Some (Nonempty as p) => match (if Z.eq_dec (@snd block Z l) Z0 then NO Share.bot bot_unreadable else NO Share.bot bot_unreadable) with | NO sh n => NO extern_retainer nonreadable_extern_retainer | YES sh r k p0 => NO extern_retainer nonreadable_extern_retainer | PURE k p0 => if Z.eq_dec (@snd block Z l) Z0 then NO Share.bot bot_unreadable else NO Share.bot bot_unreadable end | None => NO Share.bot bot_unreadable end) (if Z.eq_dec (@snd block Z l) Z0 then NO Share.bot bot_unreadable else NO Share.bot bot_unreadable) *)
(* Goal: @eq ghost (ghost_of (@core rmap Join_rmap Sep_rmap (inflate_initial_mem m (@initial_world.initial_core_ext function (@OK_ty Espec) ora (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n)))) (ghost_of (@initial_world.initial_core function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n)) *)
inversion2 H1 H4.
+ if_tac.
  - destruct (IOK l) as [_ ?].
(* Goal: @eq resource (@core resource Join_resource Sep_resource match access_at m l Cur with | Some (Freeable as p) => YES Share.top readable_share_top (VAL (contents_at m l)) NoneP | Some (Writable as p) => YES Ews (@writable_readable Ews writable_Ews) (VAL (contents_at m l)) NoneP | Some (Readable as p) => YES Ers readable_Ers (VAL (contents_at m l)) NoneP | Some (Nonempty as p) => match match fs with | mk_funspec fsig cc A P Q P_ne Q_ne => PURE (FUN fsig cc) (SomeP (SpecTT A) (fun ts : list Type => @fmap (dependent_type_functor_rec ts (SpecTT A)) (@pred rmap ag_rmap) (@pred rmap ag_rmap) (approx n) (approx n) (@packPQ A P Q ts))) end with | NO sh n => NO extern_retainer nonreadable_extern_retainer | YES sh r k p0 => NO extern_retainer nonreadable_extern_retainer | PURE k p0 => match fs with | mk_funspec fsig cc A P Q P_ne Q_ne => PURE (FUN fsig cc) (SomeP (SpecTT A) (fun ts : list Type => @fmap (dependent_type_functor_rec ts (SpecTT A)) (@pred rmap ag_rmap) (@pred rmap ag_rmap) (approx n) (approx n) (@packPQ A P Q ts))) end end | None => NO Share.bot bot_unreadable end) match fs with | mk_funspec fsig cc A P Q P_ne Q_ne => PURE (FUN fsig cc) (SomeP (SpecTT A) (fun ts : list Type => @fmap (dependent_type_functor_rec ts (SpecTT A)) (@pred rmap ag_rmap) (@pred rmap ag_rmap) (approx n) (approx n) (@packPQ A P Q ts))) end *)
   unfold initial_core_ext in H6. rewrite resource_at_make_rmap in H6.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
   unfold initial_core' in H6. rewrite if_true in H6 by auto.
(* Goal: @eq resource (@core resource Join_resource Sep_resource match access_at m l Cur with | Some (Freeable as p) => YES Share.top readable_share_top (VAL (contents_at m l)) NoneP | Some (Writable as p) => YES Ews (@writable_readable Ews writable_Ews) (VAL (contents_at m l)) NoneP | Some (Readable as p) => YES Ers readable_Ers (VAL (contents_at m l)) NoneP | Some (Nonempty as p) => match match fs with | mk_funspec fsig cc A P Q P_ne Q_ne => PURE (FUN fsig cc) (SomeP (SpecTT A) (fun ts : list Type => @fmap (dependent_type_functor_rec ts (SpecTT A)) (@pred rmap ag_rmap) (@pred rmap ag_rmap) (approx n) (approx n) (@packPQ A P Q ts))) end with | NO sh n => NO extern_retainer nonreadable_extern_retainer | YES sh r k p0 => NO extern_retainer nonreadable_extern_retainer | PURE k p0 => match fs with | mk_funspec fsig cc A P Q P_ne Q_ne => PURE (FUN fsig cc) (SomeP (SpecTT A) (fun ts : list Type => @fmap (dependent_type_functor_rec ts (SpecTT A)) (@pred rmap ag_rmap) (@pred rmap ag_rmap) (approx n) (approx n) (@packPQ A P Q ts))) end end | None => NO Share.bot bot_unreadable end) match fs with | mk_funspec fsig cc A P Q P_ne Q_ne => PURE (FUN fsig cc) (SomeP (SpecTT A) (fun ts : list Type => @fmap (dependent_type_functor_rec ts (SpecTT A)) (@pred rmap ag_rmap) (@pred rmap ag_rmap) (approx n) (approx n) (@packPQ A P Q ts))) end *)
   apply Genv.find_invert_symbol in H1.
   unfold fundef in *; rewrite H1 in *.
   rewrite H2 in *. destruct fs.
(* Goal: @eq resource (@core resource Join_resource Sep_resource match access_at m l Cur with | Some (Freeable as p) => YES Share.top readable_share_top (VAL (contents_at m l)) NoneP | Some (Writable as p) => YES Ews (@writable_readable Ews writable_Ews) (VAL (contents_at m l)) NoneP | Some (Readable as p) => YES Ers readable_Ers (VAL (contents_at m l)) NoneP | Some (Nonempty as p) => PURE (FUN f0 c) (SomeP (SpecTT A) (fun ts : list Type => @fmap (dependent_type_functor_rec ts (SpecTT A)) (@pred rmap ag_rmap) (@pred rmap ag_rmap) (approx n) (approx n) (@packPQ A P Q ts))) | None => NO Share.bot bot_unreadable end) (PURE (FUN f0 c) (SomeP (SpecTT A) (fun ts : list Type => @fmap (dependent_type_functor_rec ts (SpecTT A)) (@pred rmap ag_rmap) (@pred rmap ag_rmap) (approx n) (approx n) (@packPQ A P Q ts)))) *)
   destruct H6 as [? [? ?]]. rewrite H7.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
   rewrite core_PURE; auto.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
  - destruct (access_at m l); try destruct p; try rewrite core_YES; try rewrite core_NO; auto.
+ (*unfold fundef in *; rewrite H1,H2 in *.*)
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
  if_tac;  destruct (access_at m l); try destruct p; try rewrite core_YES; try rewrite core_NO; auto.
+ (*unfold fundef in *; rewrite H1 in *.*)
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
  if_tac;   destruct (access_at m l); try destruct p; try rewrite core_YES; try rewrite core_NO; auto.
+ rewrite ghost_of_core.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
  unfold inflate_initial_mem, initial_core; rewrite !ghost_of_make_rmap, ghost_core; auto.
Qed.

(* Goal: @ex val (fun v : val => and (@eq (option val) (if ident_eq i p then @Some val (@fst val type a) else @Map.get val (make_tenv (temp_bindings (Pos.add p xH) (@map (prod val type) val (@fst val type) typed_args))) i) (@Some val v)) (tc_val' ty v)) *)
Definition Delta1 V G {C: compspecs}: tycontext :=
  make_tycontext ((1%positive,(Tfunction Tnil Tvoid cc_default))::nil) nil nil Tvoid V G nil.

Lemma match_globvars_in':
  forall i t vl vs,
  match_globvars vl vs = true ->
  In (i,t) vs ->
  exists g, In (i,g) vl /\ gvar_info g = t.
Proof.
(* Goal: forall (id : positive) (ty : type), iff (@eq (option type) (@PTree.get type id (make_tycontext_v (@nil (prod ident type)))) (@Some type ty)) (@ex block (fun v : block => @eq (option (prod block type)) (@Map.get (prod block type) (make_venv empty_env) id) (@Some (prod block type) (@pair block type v ty)))) *)
 induction vl; destruct vs; intros. inv H0.
(* Goal: @list_norepet ident (@map (prod ident fundef) ident (@fst ident fundef) (@prog_funct' (Ctypes.fundef function) type (@cons (prod ident (globdef (Ctypes.fundef function) type)) a l))) *)
(* Goal: @ex block (fun b : block => @eq (option block) (@Map.get block (@Genv.find_symbol fundef type (genv_genv (globalenv prog))) id) (@Some block b)) *)
 destruct p; inv H.
(* Goal: iff (@eq (option type) (@PTree.get type id (@PTree.set type (@fst ident type (@pair ident type i t0)) (@snd ident type (@pair ident type i t0)) (@fold_right (PTree.t type) (prod ident type) (fun v : prod ident type => @PTree.set type (@fst ident type v) (@snd ident type v)) (PTree.empty type) vs))) (@Some type t)) (or (@eq (prod positive type) (@pair ident type i t0) (@pair positive type id t)) (@In (prod positive type) (@pair positive type id t) vs)) *)
 inv H0. destruct p, H0. inv H0.  simpl in *.
(* Goal: or (@eq ident (@fst ident (globdef (Ctypes.fundef function) type) a) i) (@In ident i (@map (prod ident (globdef (Ctypes.fundef function) type)) ident (@fst ident (globdef (Ctypes.fundef function) type)) l)) *)
(* Goal: @list_norepet ident (@map (prod ident fundef) ident (@fst ident fundef) (@prog_funct' (Ctypes.fundef function) type l)) *)
(* Goal: @ex block (fun b : block => @eq (option block) (@Map.get block (@Genv.find_symbol fundef type (genv_genv (globalenv prog))) id) (@Some block b)) *)
 destruct a.
(* Goal: @eq (option type) (@Some type t0) (@Some type t) *)
 pose proof (eqb_ident_spec i i0); destruct (eqb_ident i i0).
 assert (i=i0) by (rewrite <- H0; auto). subst i0; clear H0.
(* Goal: @ex (globvar type) (fun g0 : globvar type => and (@In (prod ident (globvar type)) (@pair ident (globvar type) i g0) (@cons (prod ident (globvar type)) (@pair ident (globvar type) i1 g) vl)) (@eq type (@gvar_info type g0) t)) *)
(* Goal: @ex (globvar type) (fun g0 : globvar type => and (@In (prod ident (globvar type)) (@pair ident (globvar type) i g0) (@cons (prod ident (globvar type)) (@pair ident (globvar type) i1 g) vl)) (@eq type (@gvar_info type g0) t)) *)
 apply andb_true_iff in H; destruct H.
(* Goal: @ex (globvar type) (fun g0 : globvar type => and (or (@eq (prod ident (globvar type)) (@pair ident (globvar type) i g) (@pair ident (globvar type) i g0)) (@In (prod ident (globvar type)) (@pair ident (globvar type) i g0) vl)) (@eq type (@gvar_info type g0) t)) *)
(* Goal: @ex (globvar type) (fun g0 : globvar type => and (or (@eq (prod ident (globvar type)) (@pair ident (globvar type) i0 g) (@pair ident (globvar type) i g0)) (@In (prod ident (globvar type)) (@pair ident (globvar type) i g0) vl)) (@eq type (@gvar_info type g0) t)) *)
(* Goal: @ex (globvar type) (fun g : globvar type => and (@In (prod ident (globvar type)) (@pair ident (globvar type) i g) (@cons (prod ident (globvar type)) a vl)) (@eq type (@gvar_info type g) t)) *)
 apply eqb_type_true in H. subst t.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
 exists g; split3; auto.
(* Goal: and (@eq (option block) (@Some block loc') (@Some block loc')) (@ex funspec (fun fs : funspec => @eq (option funspec) (@PTree.get funspec i (make_tycontext_s G)) (@Some funspec fs))) *)
 destruct (IHvl _ H) as [g' [? ?]]. left; auto. exists g'; split; auto.
(* Goal: @ex (globvar type) (fun g : globvar type => and (@In (prod ident (globvar type)) (@pair ident (globvar type) i g) (@cons (prod ident (globvar type)) a vl)) (@eq type (@gvar_info type g) t)) *)
 simpl in H. destruct a.
(* Goal: @ex (globvar type) (fun g0 : globvar type => and (@In (prod ident (globvar type)) (@pair ident (globvar type) i g0) (@cons (prod ident (globvar type)) (@pair ident (globvar type) i1 g) vl)) (@eq type (@gvar_info type g0) t)) *)
 pose proof (eqb_ident_spec i0 i1); destruct (eqb_ident i0 i1).
(* Goal: @ex (globvar type) (fun g0 : globvar type => and (@In (prod ident (globvar type)) (@pair ident (globvar type) i g0) (@cons (prod ident (globvar type)) (@pair ident (globvar type) i1 g) vl)) (@eq type (@gvar_info type g0) t)) *)
(* Goal: @ex (globvar type) (fun g0 : globvar type => and (@In (prod ident (globvar type)) (@pair ident (globvar type) i g0) (@cons (prod ident (globvar type)) (@pair ident (globvar type) i1 g) vl)) (@eq type (@gvar_info type g0) t)) *)
 apply andb_true_iff in H; destruct H.
(* Goal: and (@eq (option block) (@Some block loc') (@Some block loc')) (@ex funspec (fun fs : funspec => @eq (option funspec) (@PTree.get funspec i (make_tycontext_s G)) (@Some funspec fs))) *)
 destruct (IHvl _ H2) as [g' [? ?]]; auto. exists g'; split; auto.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
 right; auto.
(* Goal: and (@eq (option block) (@Some block loc') (@Some block loc')) (@ex funspec (fun fs : funspec => @eq (option funspec) (@PTree.get funspec i (make_tycontext_s G)) (@Some funspec fs))) *)
 apply IHvl in H. destruct H as [g' [? ?]]. exists g'; split; auto.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
 right; auto.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
 right; auto.
Qed.

Lemma match_globvars_in:
  forall i vl vs, match_globvars vl vs = true -> In i  (map (@fst _ _) vs) -> In i (map (@fst _ _) vl).
Proof.
(* Goal: forall (id : positive) (ty : type), iff (@eq (option type) (@PTree.get type id (make_tycontext_v (@nil (prod ident type)))) (@Some type ty)) (@ex block (fun v : block => @eq (option (prod block type)) (@Map.get (prod block type) (make_venv empty_env) id) (@Some (prod block type) (@pair block type v ty)))) *)
 intros.
(* Goal: @In ident i (@map (prod ident (globvar type)) ident (@fst ident (globvar type)) vl) *)
 apply list_in_map_inv in H0. destruct H0 as [t [? ?]]. subst i.
(* Goal: @In ident (@fst ident type t) (@map (prod ident (globvar type)) ident (@fst ident (globvar type)) vl) *)
 destruct t as [i t].
 destruct  (match_globvars_in' _ _ _ _ H H1) as [g [? ?]].
(* Goal: forall _ : @ex block (fun v : block => @eq (option (prod block type)) (@Map.get (prod block type) (ve_of (construct_rho (filter_genv (globalenv prog)) empty_env (@PTree.set val xH (Vptr b Ptrofs.zero) (temp_bindings (xO xH) (@map (prod val type) val (@fst val type) typed_args))))) id) (@Some (prod block type) (@pair block type v ty))), @eq (option type) (@PTree.get type id (var_types (@Delta_types vs G C (@map (prod val type) type (@snd val type) typed_args)))) (@Some type ty) *)
 simpl. apply in_map_fst with g; auto.
Qed.

Lemma match_globvars_norepet:
  forall vl vs,
   list_norepet (map (@fst _ _) vl) ->
   match_globvars vl vs = true ->
   list_norepet (map (@fst _ _) vs).
Proof.
(* Goal: forall (id : positive) (ty : type), iff (@eq (option type) (@PTree.get type id (make_tycontext_v (@nil (prod ident type)))) (@Some type ty)) (@ex block (fun v : block => @eq (option (prod block type)) (@Map.get (prod block type) (make_venv empty_env) id) (@Some (prod block type) (@pair block type v ty)))) *)
induction vl; destruct vs; simpl; intros.
(* Goal: @list_norepet ident (@map (prod ident fundef) ident (@fst ident fundef) (@prog_funct' (Ctypes.fundef function) type (@nil (prod ident (globdef (Ctypes.fundef function) type))))) *)
(* Goal: @list_norepet ident (@map (prod ident fundef) ident (@fst ident fundef) (@prog_funct' (Ctypes.fundef function) type (@cons (prod ident (globdef (Ctypes.fundef function) type)) a l))) *)
(* Goal: @ex block (fun b : block => @eq (option block) (@Map.get block (@Genv.find_symbol fundef type (genv_genv (globalenv prog))) id) (@Some block b)) *)
constructor. destruct p. inv H0.
(* Goal: @list_norepet ident (@map (prod ident fundef) ident (@fst ident fundef) (@prog_funct' (Ctypes.fundef function) type (@nil (prod ident (globdef (Ctypes.fundef function) type))))) *)
(* Goal: @list_norepet ident (@map (prod ident fundef) ident (@fst ident fundef) (@prog_funct' (Ctypes.fundef function) type (@cons (prod ident (globdef (Ctypes.fundef function) type)) a l))) *)
(* Goal: @ex block (fun b : block => @eq (option block) (@Map.get block (@Genv.find_symbol fundef type (genv_genv (globalenv prog))) id) (@Some block b)) *)
constructor.
(* Goal: or (@eq ident (@fst ident (globdef (Ctypes.fundef function) type) a) i) (@In ident i (@map (prod ident (globdef (Ctypes.fundef function) type)) ident (@fst ident (globdef (Ctypes.fundef function) type)) l)) *)
(* Goal: @list_norepet ident (@map (prod ident fundef) ident (@fst ident fundef) (@prog_funct' (Ctypes.fundef function) type l)) *)
(* Goal: @ex block (fun b : block => @eq (option block) (@Map.get block (@Genv.find_symbol fundef type (genv_genv (globalenv prog))) id) (@Some block b)) *)
destruct p; destruct a.
simpl in *.
(* Goal: @list_norepet ident (@map (prod ident fundef) ident (@fst ident fundef) (@prog_funct' (Ctypes.fundef function) type (@cons (prod ident (globdef (Ctypes.fundef function) type)) a l))) *)
(* Goal: @ex block (fun b : block => @eq (option block) (@Map.get block (@Genv.find_symbol fundef type (genv_genv (globalenv prog))) id) (@Some block b)) *)
inv H.
(* Goal: @eq (option type) (@Some type t0) (@Some type t) *)
 pose proof (eqb_ident_spec i i0); destruct (eqb_ident i i0).
(* Goal: @list_norepet ident (@cons ident i (@map (prod ident type) ident (@fst ident type) vs)) *)
(* Goal: @list_norepet ident (@cons ident i (@map (prod ident type) ident (@fst ident type) vs)) *)
 assert (i=i0) by (apply H; auto); subst i0; clear H.
(* Goal: @In (prod ident (globdef (Ctypes.fundef function) type)) (@pair ident (globdef (Ctypes.fundef function) type) id (@Gfun (Ctypes.fundef function) type f)) (@cons (prod ident (globdef (Ctypes.fundef function) type)) (@pair ident (globdef (Ctypes.fundef function) type) i (@Gfun (Ctypes.fundef function) type f0)) l) *)
(* Goal: @In (prod ident (globdef (Ctypes.fundef function) type)) (@pair ident (globdef (Ctypes.fundef function) type) id (@Gfun (Ctypes.fundef function) type f)) (@cons (prod ident (globdef (Ctypes.fundef function) type)) (@pair ident (globdef (Ctypes.fundef function) type) i (@Gvar (Ctypes.fundef function) type v)) l) *)
 apply andb_true_iff in H0; destruct H0.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
 constructor; auto.
(* Goal: not (@In ident i (@map (prod ident type) ident (@fst ident type) vs)) *)
(* Goal: @list_norepet ident (@cons ident i (@map (prod ident type) ident (@fst ident type) vs)) *)
 contradict H3.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
 eapply match_globvars_in; eauto.
(* Goal: iff (@eq (option type) (@PTree.get type id (make_tycontext_g vs G)) (@Some type t)) (or (@ex funspec (fun f : funspec => and (@In (prod positive funspec) (@pair positive funspec id f) G) (@eq type t (type_of_funspec f)))) (@In (prod positive type) (@pair positive type id t) vs)) *)
 assert (i<>i0). intro; subst; destruct H. specialize (H1 (eq_refl _)); inv H1.
(* Goal: @list_norepet ident (@cons ident i (@map (prod ident type) ident (@fst ident type) vs)) *)
 clear H.
(* Goal: @list_norepet ident (@cons ident i (@map (prod ident type) ident (@fst ident type) vs)) *)
 specialize (IHvl ((i,t)::vs) H4 H0).
(* Goal: @list_norepet ident (@cons ident i (@map (prod ident type) ident (@fst ident type) vs)) *)
 inv IHvl.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
 constructor; auto.
Qed.

Lemma make_tycontext_g_denote:
  forall id t l vs G,
    list_norepet (map fst l) ->
    match_globvars (prog_vars' l) vs = true ->
    match_fdecs (prog_funct' l) G ->
   ((make_tycontext_g vs G) ! id = Some t <->
    ((exists f, In (id,f) G /\ t = type_of_funspec f) \/ In (id,t) vs)).
Proof.
(* Goal: forall (id : positive) (ty : type), iff (@eq (option type) (@PTree.get type id (make_tycontext_v (@nil (prod ident type)))) (@Some type ty)) (@ex block (fun v : block => @eq (option (prod block type)) (@Map.get (prod block type) (make_venv empty_env) id) (@Some (prod block type) (@pair block type v ty)))) *)
  intros.
(* Goal: @ex val (fun v : val => and (@eq (option val) (if ident_eq i p then @Some val (@fst val type a) else @Map.get val (make_tenv (temp_bindings (Pos.add p xH) (@map (prod val type) val (@fst val type) typed_args))) i) (@Some val v)) (tc_val' ty v)) *)
  assert (list_norepet (map (@fst _ _) (prog_funct' l) ++  (map (@fst _ _) (prog_vars' l)))). {
   clear - H.
(* Goal: @list_norepet ident (@map (prod ident fundef) ident (@fst ident fundef) (@prog_funct' (Ctypes.fundef function) type (@nil (prod ident (globdef (Ctypes.fundef function) type))))) *)
(* Goal: @list_norepet ident (@map (prod ident fundef) ident (@fst ident fundef) (@prog_funct' (Ctypes.fundef function) type (@cons (prod ident (globdef (Ctypes.fundef function) type)) a l))) *)
(* Goal: @ex block (fun b : block => @eq (option block) (@Map.get block (@Genv.find_symbol fundef type (genv_genv (globalenv prog))) id) (@Some block b)) *)
  induction l; simpl. constructor.
  destruct a; destruct g; simpl in *; inv H.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
  constructor; auto.
  clear - H2; contradict H2.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
   induction l. inv H2. destruct a; destruct g; simpl in *. destruct H2; auto.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
   apply in_app in H2. destruct H2. right; apply IHl. apply in_app; auto.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
   destruct H; auto. right; apply IHl; apply in_app; auto.
(* Goal: @list_norepet ident (@app ident (@map (prod ident fundef) ident (@fst ident fundef) (@prog_funct' fundef type l)) (@cons ident i (@map (prod ident (globvar type)) ident (@fst ident (globvar type)) (@prog_vars' fundef type l)))) *)
   specialize (IHl H3).
(* Goal: @list_norepet ident (@app ident (@map (prod ident fundef) ident (@fst ident fundef) (@prog_funct' fundef type l)) (@cons ident i (@map (prod ident (globvar type)) ident (@fst ident (globvar type)) (@prog_vars' fundef type l)))) *)
   apply list_norepet_app in IHl. destruct IHl as [? [? ?]].
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
   apply list_norepet_app; split3; auto.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
   constructor; auto.
  clear - H2; contradict H2.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
   induction l. inv H2. destruct a; destruct g. simpl in H2. constructor 2; auto.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
   simpl in H2. destruct H2. subst; left; auto. right. auto.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
  apply list_disjoint_cons_r; auto.
  clear - H2; contradict H2.
(* Goal: @In ident i (@map (prod ident (globdef fundef type)) ident (@fst ident (globdef fundef type)) (@cons (prod ident (globdef fundef type)) a l)) *)
   induction l. inv H2. destruct a; destruct g. simpl in H2.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
  destruct H2. subst; left; auto. right; auto.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
  simpl in *. right; auto.
}
(* Goal: iff (@eq (option type) (@PTree.get type id (make_tycontext_g vs G)) (@Some type t)) (or (@ex funspec (fun f : funspec => and (@In (prod positive funspec) (@pair positive funspec id f) G) (@eq type t (type_of_funspec f)))) (@In (prod positive type) (@pair positive type id t) vs)) *)
 forget (prog_vars' l) as vl.
(* Goal: iff (@eq (option type) (@PTree.get type id (make_tycontext_g vs G)) (@Some type t)) (or (@ex funspec (fun f : funspec => and (@In (prod positive funspec) (@pair positive funspec id f) G) (@eq type t (type_of_funspec f)))) (@In (prod positive type) (@pair positive type id t) vs)) *)
 forget (prog_funct' l) as fl.
(* Goal: iff (@eq (option type) (@PTree.get type id (make_tycontext_g vs G)) (@Some type t)) (or (@ex funspec (fun f : funspec => and (@In (prod positive funspec) (@pair positive funspec id f) G) (@eq type t (type_of_funspec f)))) (@In (prod positive type) (@pair positive type id t) vs)) *)
 clear l H.
(* Goal: forall (id : positive) (ty : type), iff (@eq (option type) (@PTree.get type id (make_tycontext_v (@nil (prod ident type)))) (@Some type ty)) (@ex block (fun v : block => @eq (option (prod block type)) (@Map.get (prod block type) (make_venv empty_env) id) (@Some (prod block type) (@pair block type v ty)))) *)
 revert G H2 H1; induction fl; intros.
* (* fl = nil *)
(* Goal: iff (@eq (option type) (@PTree.get type id (make_tycontext_g vs G)) (@Some type t)) (or (@ex funspec (fun f : funspec => and (@In (prod positive funspec) (@pair positive funspec id f) G) (@eq type t (type_of_funspec f)))) (@In (prod positive type) (@pair positive type id t) vs)) *)
 destruct G; inv H1.
(* Goal: not (@In ident i (@map (prod ident fundef) ident (@fst ident fundef) (@prog_funct' (Ctypes.fundef function) type l))) *)
(* Goal: @list_norepet ident (@map (prod ident fundef) ident (@fst ident fundef) (@prog_funct' (Ctypes.fundef function) type l)) *)
(* Goal: @ex block (fun b : block => @eq (option block) (@Map.get block (@Genv.find_symbol fundef type (genv_genv (globalenv prog))) id) (@Some block b)) *)
 simpl in H2.
 apply iff_trans with (In (id, t) vs );
  [ | clear; intuition; destruct H0 as [? [? ?]]; contradiction].
(* Goal: forall (id : positive) (ty : type), iff (@eq (option type) (@PTree.get type id (make_tycontext_v (@nil (prod ident type)))) (@Some type ty)) (@ex block (fun v : block => @eq (option (prod block type)) (@Map.get (prod block type) (make_venv empty_env) id) (@Some (prod block type) (@pair block type v ty)))) *)
 revert vs H0; induction vl; destruct vs; simpl in *; intros.
+(* fl = nil /\ vl = nil /\ vs = nil*)
(* Goal: forall _ : @ex block (fun v : block => @eq (option (prod block type)) (@PTree.get (prod block type) id (PTree.empty (prod block type))) (@Some (prod block type) (@pair block type v ty))), @eq (option type) (@PTree.get type id (PTree.empty type)) (@Some type ty) *)
 rewrite PTree.gempty.
(* Goal: forall (id : positive) (ty : type), iff (@eq (option type) (@PTree.get type id (make_tycontext_v (@nil (prod ident type)))) (@Some type ty)) (@ex block (fun v : block => @eq (option (prod block type)) (@Map.get (prod block type) (make_venv empty_env) id) (@Some (prod block type) (@pair block type v ty)))) *)
 split; intros. discriminate. contradiction.
+ (* fl = nil /\ vl = nil /\ vs<>nil *)
(* Goal: iff (@eq (option type) (@PTree.get type id (@PTree.set type (@fst ident type p) (@snd ident type p) (@fold_right (PTree.t type) (prod ident type) (fun v : prod ident type => @PTree.set type (@fst ident type v) (@snd ident type v)) (PTree.empty type) vs))) (@Some type t)) (or (@eq (prod positive type) p (@pair positive type id t)) (@In (prod positive type) (@pair positive type id t) vs)) *)
 clear H2.
(* Goal: iff (@eq (option type) (@PTree.get type id (@PTree.set type (@fst ident type (@pair ident type i t0)) (@snd ident type (@pair ident type i t0)) (@fold_right (PTree.t type) (prod ident type) (fun v : prod ident type => @PTree.set type (@fst ident type v) (@snd ident type v)) (PTree.empty type) vs))) (@Some type t)) (or (@eq (prod positive type) (@pair ident type i t0) (@pair positive type id t)) (@In (prod positive type) (@pair positive type id t) vs)) *)
 destruct p. inv H0.
+ (* fl = nil /\ vl inductive case /\ vs = nil  *)
(* Goal: forall _ : @ex block (fun v : block => @eq (option (prod block type)) (@PTree.get (prod block type) id (PTree.empty (prod block type))) (@Some (prod block type) (@pair block type v ty))), @eq (option type) (@PTree.get type id (PTree.empty type)) (@Some type ty) *)
 clear H0. rewrite PTree.gempty.
(* Goal: @ex val (fun v : val => and (@eq (option val) (@PTree.get val id (PTree.empty val)) (@Some val v)) (tc_val' ty v)) *)
   clear. intuition congruence.
 + (* fl = nil /\ vl inductive case /\ vs <> nil *)
   destruct p. destruct a. simpl in *. inv H2.
(* Goal: iff (@eq (option type) (@PTree.get type id (@PTree.set type i t0 (@fold_right (PTree.t type) (prod ident type) (fun v : prod ident type => @PTree.set type (@fst ident type v) (@snd ident type v)) (PTree.empty type) vs))) (@Some type t)) (or (@eq (prod positive type) (@pair ident type i t0) (@pair positive type id t)) (@In (prod positive type) (@pair positive type id t) vs)) *)
  specialize (IHvl H4).
(* Goal: iff (@eq (option type) (@PTree.get type id (make_tycontext_g vs (@cons (prod ident funspec) (@pair ident funspec i fspec) G0))) (@Some type t)) (or (@ex funspec (fun f : funspec => and (@In (prod positive funspec) (@pair positive funspec id f) (@cons (prod ident funspec) (@pair ident funspec i fspec) G0)) (@eq type t (type_of_funspec f)))) (@In (prod positive type) (@pair positive type id t) vs)) *)
  destruct (ident_eq id i).
 - subst id.
(* Goal: @list_norepet ident (@map (prod ident fundef) ident (@fst ident fundef) (@prog_funct' (Ctypes.fundef function) type (@cons (prod ident (globdef (Ctypes.fundef function) type)) a l))) *)
(* Goal: @ex block (fun b : block => @eq (option block) (@Map.get block (@Genv.find_symbol fundef type (genv_genv (globalenv prog))) id) (@Some block b)) *)
  rewrite PTree.gss. split; intro. inv H.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
  auto.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
 destruct H. inv H. auto.
(* Goal: @eq (option type) (@Some type t0) (@Some type t) *)
 pose proof (eqb_ident_spec i i0); destruct (eqb_ident i i0).
(* Goal: @eq (option type) (@Some type t0) (@Some type t) *)
 assert (i=i0) by (rewrite <- H1; auto). subst i0; clear H1.
(* Goal: @In (prod ident (globdef (Ctypes.fundef function) type)) (@pair ident (globdef (Ctypes.fundef function) type) id (@Gfun (Ctypes.fundef function) type f)) (@cons (prod ident (globdef (Ctypes.fundef function) type)) (@pair ident (globdef (Ctypes.fundef function) type) i (@Gfun (Ctypes.fundef function) type f0)) l) *)
(* Goal: @In (prod ident (globdef (Ctypes.fundef function) type)) (@pair ident (globdef (Ctypes.fundef function) type) id (@Gfun (Ctypes.fundef function) type f)) (@cons (prod ident (globdef (Ctypes.fundef function) type)) (@pair ident (globdef (Ctypes.fundef function) type) i (@Gvar (Ctypes.fundef function) type v)) l) *)
  apply andb_true_iff in H0; destruct H0.
(* Goal: @eq type (type_of_funspec fspec) t *)
(* Goal: iff (@eq (option type) (@PTree.get type id (make_tycontext_g vs (@cons (prod ident funspec) (@pair ident funspec i fspec) G0))) (@Some type t)) (or (@ex funspec (fun f : funspec => and (@In (prod positive funspec) (@pair positive funspec id f) (@cons (prod ident funspec) (@pair ident funspec i fspec) G0)) (@eq type t (type_of_funspec f)))) (@In (prod positive type) (@pair positive type id t) vs)) *)
 contradiction H3.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
 eapply match_globvars_in; eauto. apply in_map_fst with t. auto.
(* Goal: False *)
(* Goal: @eq (option type) (@Some type t0) (@Some type t) *)
 assert (i<>i0). intro; subst. clear - H1. destruct H1. specialize (H0 (eq_refl _)); inv H0.
(* Goal: @eq (option type) (@Some type t0) (@Some type t) *)
 clear H1.
(* Goal: @eq (option type) (@Some type t0) (@Some type t) *)
 pose proof (match_globvars_norepet _ _ H4 H0).
(* Goal: iff (@eq (option type) (@PTree.get type id (make_tycontext_g vs G)) (@Some type t)) (or (@ex funspec (fun f : funspec => and (@In (prod positive funspec) (@pair positive funspec id f) G) (@eq type t (type_of_funspec f)))) (@In (prod positive type) (@pair positive type id t) vs)) *)
 inv H1. contradiction H7. apply in_map_fst with t; auto.
 - (* id <> i *)
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
 rewrite PTree.gso by auto.
(* Goal: iff (@eq (option type) (@PTree.get type id (@fold_right (PTree.t type) (prod ident type) (fun v : prod ident type => @PTree.set type (@fst ident type v) (@snd ident type v)) (PTree.empty type) vs)) (@Some type t)) (or (@eq (prod positive type) (@pair ident type i t0) (@pair positive type id t)) (@In (prod positive type) (@pair positive type id t) vs)) *)
 pose proof (eqb_ident_spec i i0).
(* Goal: iff (@eq (option type) (@PTree.get type id (@fold_right (PTree.t type) (prod ident type) (fun v : prod ident type => @PTree.set type (@fst ident type v) (@snd ident type v)) (PTree.empty type) vs)) (@Some type t)) (or (@eq (prod positive type) (@pair ident type i t0) (@pair positive type id t)) (@In (prod positive type) (@pair positive type id t) vs)) *)
 destruct (ident_eq i i0).
(* Goal: @In ident i (@map (prod ident (globvar type)) ident (@fst ident (globvar type)) vl) *)
(* Goal: iff (@eq (option type) (@PTree.get type id (make_tycontext_g vs (@cons (prod ident funspec) (@pair ident funspec i fspec) G0))) (@Some type t)) (or (@ex funspec (fun f : funspec => and (@In (prod positive funspec) (@pair positive funspec id f) (@cons (prod ident funspec) (@pair ident funspec i fspec) G0)) (@eq type t (type_of_funspec f)))) (@In (prod positive type) (@pair positive type id t) vs)) *)
 subst. destruct H. rewrite H1 in H0 by auto.
(* Goal: @In (prod ident (globdef (Ctypes.fundef function) type)) (@pair ident (globdef (Ctypes.fundef function) type) id (@Gfun (Ctypes.fundef function) type f)) (@cons (prod ident (globdef (Ctypes.fundef function) type)) (@pair ident (globdef (Ctypes.fundef function) type) i (@Gfun (Ctypes.fundef function) type f0)) l) *)
(* Goal: @In (prod ident (globdef (Ctypes.fundef function) type)) (@pair ident (globdef (Ctypes.fundef function) type) id (@Gfun (Ctypes.fundef function) type f)) (@cons (prod ident (globdef (Ctypes.fundef function) type)) (@pair ident (globdef (Ctypes.fundef function) type) i (@Gvar (Ctypes.fundef function) type v)) l) *)
 rewrite andb_true_iff in H0; destruct H0.
(* Goal: iff (@eq (option type) (@PTree.get type id (@fold_right (PTree.t type) (prod ident type) (fun v : prod ident type => @PTree.set type (@fst ident type v) (@snd ident type v)) (PTree.empty type) vs)) (@Some type t)) (or (@eq (prod positive type) (@pair ident type i0 t0) (@pair positive type id t)) (@In (prod positive type) (@pair positive type id t) vs)) *)
(* Goal: iff (@eq (option type) (@PTree.get type id (@fold_right (PTree.t type) (prod ident type) (fun v : prod ident type => @PTree.set type (@fst ident type v) (@snd ident type v)) (PTree.empty type) vs)) (@Some type t)) (or (@eq (prod positive type) (@pair ident type i t0) (@pair positive type id t)) (@In (prod positive type) (@pair positive type id t) vs)) *)
 apply eqb_type_true in H0. subst t0.
(* Goal: iff (@eq (option type) (@PTree.get type id (@fold_right (PTree.t type) (prod ident type) (fun v : prod ident type => @PTree.set type (@fst ident type v) (@snd ident type v)) (PTree.empty type) vs)) (@Some type t)) (or (@eq (prod positive type) (@pair ident type i0 (@gvar_info type g)) (@pair positive type id t)) (@In (prod positive type) (@pair positive type id t) vs)) *)
(* Goal: iff (@eq (option type) (@PTree.get type id (@fold_right (PTree.t type) (prod ident type) (fun v : prod ident type => @PTree.set type (@fst ident type v) (@snd ident type v)) (PTree.empty type) vs)) (@Some type t)) (or (@eq (prod positive type) (@pair ident type i t0) (@pair positive type id t)) (@In (prod positive type) (@pair positive type id t) vs)) *)
 clear H H1.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
 rewrite IHvl; auto.
(* Goal: @ex val (fun v : val => and (@eq (option val) (@PTree.get val id (PTree.empty val)) (@Some val v)) (tc_val' ty v)) *)
 clear - n; intuition. inv H0; congruence.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
 destruct (eqb_ident i i0). contradict n0; apply H; auto.
(* Goal: iff (@eq (option type) (@PTree.get type id (@fold_right (PTree.t type) (prod ident type) (fun v : prod ident type => @PTree.set type (@fst ident type v) (@snd ident type v)) (PTree.empty type) vs)) (@Some type t)) (or (@eq (prod positive type) (@pair ident type i t0) (@pair positive type id t)) (@In (prod positive type) (@pair positive type id t) vs)) *)
 eapply iff_trans; [ | apply (IHvl ((i,t0)::vs))]; clear IHvl.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
 simpl;  rewrite PTree.gso by auto. apply iff_refl.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
 auto.
*
(* Goal: iff (@eq (option type) (@PTree.get type id (make_tycontext_g vs G)) (@Some type t)) (or (@ex funspec (fun f : funspec => and (@In (prod positive funspec) (@pair positive funspec id f) G) (@eq type t (type_of_funspec f)))) (@In (prod positive type) (@pair positive type id t) vs)) *)
 inv H1.
 +
(* Goal: @ex block (fun v : block => @eq (option (prod block type)) (@None (prod block type)) (@Some (prod block type) (@pair block type v ty))) *)
(* Goal: @eq (option type) (@None type) (@Some type ty) *)
   inv H2.
(* Goal: iff (@eq (option type) (@PTree.get type id (make_tycontext_g vs (@cons (prod ident funspec) (@pair ident funspec i fspec) G0))) (@Some type t)) (or (@ex funspec (fun f : funspec => and (@In (prod positive funspec) (@pair positive funspec id f) (@cons (prod ident funspec) (@pair ident funspec i fspec) G0)) (@eq type t (type_of_funspec f)))) (@In (prod positive type) (@pair positive type id t) vs)) *)
   specialize (IHfl _ H5 H6).
(* Goal: @In ident i (@map (prod ident (globvar type)) ident (@fst ident (globvar type)) vl) *)
(* Goal: iff (@eq (option type) (@PTree.get type id (make_tycontext_g vs (@cons (prod ident funspec) (@pair ident funspec i fspec) G0))) (@Some type t)) (or (@ex funspec (fun f : funspec => and (@In (prod positive funspec) (@pair positive funspec id f) (@cons (prod ident funspec) (@pair ident funspec i fspec) G0)) (@eq type t (type_of_funspec f)))) (@In (prod positive type) (@pair positive type id t) vs)) *)
   destruct (ident_eq id i). subst.
(* Goal: iff (@eq (option type) (@PTree.get type i (@PTree.set type i t0 (@fold_right (PTree.t type) (prod ident type) (fun v : prod ident type => @PTree.set type (@fst ident type v) (@snd ident type v)) (PTree.empty type) vs))) (@Some type t)) (or (@eq (prod positive type) (@pair ident type i t0) (@pair positive type i t)) (@In (prod positive type) (@pair positive type i t) vs)) *)
  simpl; rewrite PTree.gss.
(* Goal: iff (@eq (option type) (@Some type (type_of_funspec fspec)) (@Some type t)) (or (@ex funspec (fun f : funspec => and (or (@eq (prod positive funspec) (@pair ident funspec i fspec) (@pair positive funspec i f)) (@In (prod positive funspec) (@pair positive funspec i f) G0)) (@eq type t (type_of_funspec f)))) (@In (prod positive type) (@pair positive type i t) vs)) *)
(* Goal: iff (@eq (option type) (@PTree.get type id (make_tycontext_g vs (@cons (prod ident funspec) (@pair ident funspec i fspec) G0))) (@Some type t)) (or (@ex funspec (fun f : funspec => and (@In (prod positive funspec) (@pair positive funspec id f) (@cons (prod ident funspec) (@pair ident funspec i fspec) G0)) (@eq type t (type_of_funspec f)))) (@In (prod positive type) (@pair positive type id t) vs)) *)
  split; intro.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
  left; exists fspec.  inv H; auto.
(* Goal: @eq (option type) (@Some type (type_of_funspec fspec)) (@Some type t) *)
(* Goal: iff (@eq (option type) (@PTree.get type id (make_tycontext_g vs (@cons (prod ident funspec) (@pair ident funspec i fspec) G0))) (@Some type t)) (or (@ex funspec (fun f : funspec => and (@In (prod positive funspec) (@pair positive funspec id f) (@cons (prod ident funspec) (@pair ident funspec i fspec) G0)) (@eq type t (type_of_funspec f)))) (@In (prod positive type) (@pair positive type id t) vs)) *)
  f_equal.
(* Goal: @eq type (type_of_funspec fspec) t *)
(* Goal: iff (@eq (option type) (@PTree.get type id (make_tycontext_g vs (@cons (prod ident funspec) (@pair ident funspec i fspec) G0))) (@Some type t)) (or (@ex funspec (fun f : funspec => and (@In (prod positive funspec) (@pair positive funspec id f) (@cons (prod ident funspec) (@pair ident funspec i fspec) G0)) (@eq type t (type_of_funspec f)))) (@In (prod positive type) (@pair positive type id t) vs)) *)
  destruct H as [[f [? ?]]| ?].
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
  destruct H. inv H. auto.
  elimtype False; clear - H3 H H6.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
  apply H3; apply in_app_iff. left; eapply match_fdecs_in; eauto.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
  apply in_map_fst in H; auto.
(* Goal: @In ident i (@map (prod ident (globdef fundef type)) ident (@fst ident (globdef fundef type)) (@cons (prod ident (globdef fundef type)) (@pair ident (globdef fundef type) i0 (@Gvar fundef type v)) l)) *)
(* Goal: @list_disjoint ident (@map (prod ident fundef) ident (@fst ident fundef) (@prog_funct' fundef type l)) (@cons ident i (@map (prod ident (globvar type)) ident (@fst ident (globvar type)) (@prog_vars' fundef type l))) *)
  contradiction H3. apply in_app_iff; right.
(* Goal: @In ident i (@map (prod ident (globvar type)) ident (@fst ident (globvar type)) vl) *)
(* Goal: iff (@eq (option type) (@PTree.get type id (make_tycontext_g vs (@cons (prod ident funspec) (@pair ident funspec i fspec) G0))) (@Some type t)) (or (@ex funspec (fun f : funspec => and (@In (prod positive funspec) (@pair positive funspec id f) (@cons (prod ident funspec) (@pair ident funspec i fspec) G0)) (@eq type t (type_of_funspec f)))) (@In (prod positive type) (@pair positive type id t) vs)) *)
  subst.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
  eapply match_globvars_in; eauto.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
  apply in_map_fst in H; auto.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
  simpl; rewrite PTree.gso; auto.
(* Goal: iff (@eq (option type) (@PTree.get type id (make_tycontext_g vs G0)) (@Some type t)) (or (@ex funspec (fun f : funspec => and (or (@eq (prod positive funspec) (@pair ident funspec i fspec) (@pair positive funspec id f)) (@In (prod positive funspec) (@pair positive funspec id f) G0)) (@eq type t (type_of_funspec f)))) (@In (prod positive type) (@pair positive type id t) vs)) *)
  rewrite IHfl. clear IHfl.
(* Goal: @In ident i (@map (prod ident (globvar type)) ident (@fst ident (globvar type)) vl) *)
(* Goal: iff (@eq (option type) (@PTree.get type id (make_tycontext_g vs (@cons (prod ident funspec) (@pair ident funspec i fspec) G0))) (@Some type t)) (or (@ex funspec (fun f : funspec => and (@In (prod positive funspec) (@pair positive funspec id f) (@cons (prod ident funspec) (@pair ident funspec i fspec) G0)) (@eq type t (type_of_funspec f)))) (@In (prod positive type) (@pair positive type id t) vs)) *)
  split; intros [[f [? ?]]| ?]; subst.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
  left; eauto. right; eauto.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
  left; eauto. destruct H. congruence.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
  exists f; eauto.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
  right; eauto.
(*+
(* Goal: @ex block (fun v : block => @eq (option (prod block type)) (@None (prod block type)) (@Some (prod block type) (@pair block type v ty))) *)
(* Goal: @eq (option type) (@None type) (@Some type ty) *)
  simpl in H2; inv H2.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
  apply (IHfl G); auto.
*)
Qed.

Lemma tc_ge_denote_initial:
  forall vs G (prog: program),
list_norepet (prog_defs_names prog) ->
match_globvars (prog_vars prog) vs = true->
match_fdecs (prog_funct prog) G ->
typecheck_glob_environ (filter_genv (globalenv prog)) (make_tycontext_g vs G).
Proof.
(* Goal: forall (id : positive) (ty : type), iff (@eq (option type) (@PTree.get type id (make_tycontext_v (@nil (prod ident type)))) (@Some type ty)) (@ex block (fun v : block => @eq (option (prod block type)) (@Map.get (prod block type) (make_venv empty_env) id) (@Some (prod block type) (@pair block type v ty)))) *)
intros.
(* Goal: forall (id : positive) (ty : type), iff (@eq (option type) (@PTree.get type id (make_tycontext_v (@nil (prod ident type)))) (@Some type ty)) (@ex block (fun v : block => @eq (option (prod block type)) (@Map.get (prod block type) (make_venv empty_env) id) (@Some (prod block type) (@pair block type v ty)))) *)
hnf; intros.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
rewrite make_tycontext_g_denote in H2; eauto.
(* Goal: @ex block (fun b : block => @eq (option block) (@Map.get block (filter_genv (globalenv prog)) id) (@Some block b)) *)
destruct H2 as [[f [? ?]]|?].
*
(* Goal: @ex block (fun b : block => @eq (option block) (@Map.get block (filter_genv (globalenv prog)) id) (@Some block b)) *)
subst t.
(* Goal: @ex block (fun b : block => @eq (option block) (@Map.get block (filter_genv (globalenv prog)) id) (@Some block b)) *)
unfold filter_genv.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
destruct (match_fdecs_exists_Gfun prog G id f) as [fd [? H20]]; auto.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
apply find_id_i; auto.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
eapply match_fdecs_norepet; eauto.
(* Goal: @list_norepet ident (@map (prod ident fundef) ident (@fst ident fundef) (@initial_world.prog_funct function prog)) *)
(* Goal: @ex block (fun b : block => @eq (option block) (@Map.get block (@Genv.find_symbol fundef type (genv_genv (globalenv prog))) id) (@Some block b)) *)
unfold prog_defs_names in H.
clear - H.
(* Goal: @list_norepet ident (@map (prod ident fundef) ident (@fst ident fundef) (@initial_world.prog_funct function prog)) *)
(* Goal: @ex block (fun b : block => @eq (option block) (@Map.get block (@Genv.find_symbol fundef type (genv_genv (globalenv prog))) id) (@Some block b)) *)
unfold prog_funct.
(* Goal: @list_norepet ident (@map (prod ident fundef) ident (@fst ident fundef) (@prog_funct' (Ctypes.fundef function) type (@prog_defs function prog))) *)
(* Goal: @ex block (fun b : block => @eq (option block) (@Map.get block (@Genv.find_symbol fundef type (genv_genv (globalenv prog))) id) (@Some block b)) *)
change (AST.prog_defs prog) with (prog_defs prog) in H.
(* Goal: @list_norepet ident (@map (prod ident fundef) ident (@fst ident fundef) (@prog_funct' (Ctypes.fundef function) type (@nil (prod ident (globdef (Ctypes.fundef function) type))))) *)
(* Goal: @list_norepet ident (@map (prod ident fundef) ident (@fst ident fundef) (@prog_funct' (Ctypes.fundef function) type (@cons (prod ident (globdef (Ctypes.fundef function) type)) a l))) *)
(* Goal: @ex block (fun b : block => @eq (option block) (@Map.get block (@Genv.find_symbol fundef type (genv_genv (globalenv prog))) id) (@Some block b)) *)
induction (prog_defs prog). constructor.
(* Goal: forall _ : @ex block (fun v : block => @eq (option (prod block type)) (@Map.get (prod block type) (ve_of (construct_rho (filter_genv (globalenv prog)) empty_env (@PTree.set val xH (Vptr b Ptrofs.zero) (temp_bindings (xO xH) (@map (prod val type) val (@fst val type) typed_args))))) id) (@Some (prod block type) (@pair block type v ty))), @eq (option type) (@PTree.get type id (var_types (@Delta_types vs G C (@map (prod val type) type (@snd val type) typed_args)))) (@Some type ty) *)
inv H. destruct a; simpl.  destruct g.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
simpl map. constructor; auto. simpl in H2.
(* Goal: not (@In ident i (@map (prod ident fundef) ident (@fst ident fundef) (@prog_funct' (Ctypes.fundef function) type l))) *)
(* Goal: @list_norepet ident (@map (prod ident fundef) ident (@fst ident fundef) (@prog_funct' (Ctypes.fundef function) type l)) *)
(* Goal: @ex block (fun b : block => @eq (option block) (@Map.get block (@Genv.find_symbol fundef type (genv_genv (globalenv prog))) id) (@Some block b)) *)
contradict H2.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
clear - H2. induction l; simpl; auto.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
destruct a. destruct g; simpl in *. destruct H2; auto. right; auto.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
apply IHl; auto.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
destruct (find_funct_ptr_exists prog id fd) as [b [? ?]]; auto.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
exists b; auto.
*
(* Goal: @ex block (fun b : block => @eq (option block) (@Map.get block (filter_genv (globalenv prog)) id) (@Some block b)) *)
 unfold filter_genv.
(* Goal: @ex block (fun b : block => @eq (option block) (@Map.get block (@Genv.find_symbol fundef type (genv_genv (globalenv prog))) id) (@Some block b)) *)
 destruct (match_globvars_in' _ _ _ _ H0 H2) as [g [? ?]].
(* Goal: @ex block (fun b : block => @eq (option block) (@Map.get block (@Genv.find_symbol fundef type (genv_genv (globalenv prog))) id) (@Some block b)) *)
 apply in_prog_vars_in_prog_defs in H3.
(* Goal: @ex block (fun b : block => @eq (option block) (@Map.get block (@Genv.find_symbol fundef type (genv_genv (globalenv prog))) id) (@Some block b)) *)
 pose proof (prog_defmap_norepet _ _ _ H H3).
destruct (proj1 (Genv.find_def_symbol _ _ _) H5)
  as [b [? ?]].
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
 exists b; auto.
Qed.

Lemma semax_prog_typecheck_aux:
(* Goal: @ex val (fun v : val => and (@eq (option val) (if ident_eq i p then @Some val (@fst val type a) else @Map.get val (make_tenv (temp_bindings (Pos.add p xH) (@map (prod val type) val (@fst val type) typed_args))) i) (@Some val v)) (tc_val' ty v)) *)
  forall vs G {C: compspecs} (prog: program) b,
   list_norepet (prog_defs_names prog) ->
   match_globvars (prog_vars prog) vs = true ->
   match_fdecs (prog_funct prog) G ->
   typecheck_environ
      (Delta1 vs G) (construct_rho (filter_genv (globalenv prog)) empty_env
        (PTree.set 1 (Vptr b Ptrofs.zero) (PTree.empty val))) .
Proof.
(* Goal: forall (id : positive) (ty : type), iff (@eq (option type) (@PTree.get type id (make_tycontext_v (@nil (prod ident type)))) (@Some type ty)) (@ex block (fun v : block => @eq (option (prod block type)) (@Map.get (prod block type) (make_venv empty_env) id) (@Some (prod block type) (@pair block type v ty)))) *)
unfold Delta1; intros.
(* Goal: typecheck_environ (make_tycontext (@cons (prod positive type) (@pair positive type xH (Tfunction Tnil Tvoid cc_default)) (@nil (prod positive type))) (@nil (prod ident type)) (@nil (prod ident type)) Tvoid vs G (@nil (prod ident Annotation))) (construct_rho (filter_genv (globalenv prog)) empty_env (@PTree.set val xH (Vptr b Ptrofs.zero) (PTree.empty val))) *)
unfold construct_rho.
(* Goal: typecheck_environ (make_tycontext (@cons (prod positive type) (@pair positive type xH (Tfunction Tnil Tvoid cc_default)) (@nil (prod positive type))) (@nil (prod ident type)) (@nil (prod ident type)) Tvoid vs G (@nil (prod ident Annotation))) (mkEnviron (filter_genv (globalenv prog)) (make_venv empty_env) (make_tenv (@PTree.set val xH (Vptr b Ptrofs.zero) (PTree.empty val)))) *)
unfold make_tycontext.
(* Goal: typecheck_environ (mk_tycontext (make_tycontext_t (@cons (prod positive type) (@pair positive type xH (Tfunction Tnil Tvoid cc_default)) (@nil (prod positive type))) (@nil (prod ident type))) (make_tycontext_v (@nil (prod ident type))) Tvoid (make_tycontext_g vs G) (make_tycontext_s G) (make_tycontext_a (@nil (prod ident Annotation)))) (mkEnviron (filter_genv (globalenv prog)) (make_venv empty_env) (make_tenv (@PTree.set val xH (Vptr b Ptrofs.zero) (PTree.empty val)))) *)
unfold typecheck_environ.
(* Goal: and (typecheck_temp_environ (te_of (mkEnviron (filter_genv (globalenv prog)) (make_venv empty_env) (make_tenv (@PTree.set val xH (Vptr b Ptrofs.zero) (PTree.empty val))))) (temp_types (mk_tycontext (make_tycontext_t (@cons (prod positive type) (@pair positive type xH (Tfunction Tnil Tvoid cc_default)) (@nil (prod positive type))) (@nil (prod ident type))) (make_tycontext_v (@nil (prod ident type))) Tvoid (make_tycontext_g vs G) (make_tycontext_s G) (make_tycontext_a (@nil (prod ident Annotation)))))) (and (typecheck_var_environ (ve_of (mkEnviron (filter_genv (globalenv prog)) (make_venv empty_env) (make_tenv (@PTree.set val xH (Vptr b Ptrofs.zero) (PTree.empty val))))) (var_types (mk_tycontext (make_tycontext_t (@cons (prod positive type) (@pair positive type xH (Tfunction Tnil Tvoid cc_default)) (@nil (prod positive type))) (@nil (prod ident type))) (make_tycontext_v (@nil (prod ident type))) Tvoid (make_tycontext_g vs G) (make_tycontext_s G) (make_tycontext_a (@nil (prod ident Annotation)))))) (typecheck_glob_environ (ge_of (mkEnviron (filter_genv (globalenv prog)) (make_venv empty_env) (make_tenv (@PTree.set val xH (Vptr b Ptrofs.zero) (PTree.empty val))))) (glob_types (mk_tycontext (make_tycontext_t (@cons (prod positive type) (@pair positive type xH (Tfunction Tnil Tvoid cc_default)) (@nil (prod positive type))) (@nil (prod ident type))) (make_tycontext_v (@nil (prod ident type))) Tvoid (make_tycontext_g vs G) (make_tycontext_s G) (make_tycontext_a (@nil (prod ident Annotation))))))) *)
unfold ve_of, ge_of, te_of.
(* Goal: and (typecheck_temp_environ (make_tenv (@PTree.set val xH (Vptr b Ptrofs.zero) (PTree.empty val))) (temp_types (mk_tycontext (make_tycontext_t (@cons (prod positive type) (@pair positive type xH (Tfunction Tnil Tvoid cc_default)) (@nil (prod positive type))) (@nil (prod ident type))) (make_tycontext_v (@nil (prod ident type))) Tvoid (make_tycontext_g vs G) (make_tycontext_s G) (make_tycontext_a (@nil (prod ident Annotation)))))) (and (typecheck_var_environ (make_venv empty_env) (var_types (mk_tycontext (make_tycontext_t (@cons (prod positive type) (@pair positive type xH (Tfunction Tnil Tvoid cc_default)) (@nil (prod positive type))) (@nil (prod ident type))) (make_tycontext_v (@nil (prod ident type))) Tvoid (make_tycontext_g vs G) (make_tycontext_s G) (make_tycontext_a (@nil (prod ident Annotation)))))) (typecheck_glob_environ (filter_genv (globalenv prog)) (glob_types (mk_tycontext (make_tycontext_t (@cons (prod positive type) (@pair positive type xH (Tfunction Tnil Tvoid cc_default)) (@nil (prod positive type))) (@nil (prod ident type))) (make_tycontext_v (@nil (prod ident type))) Tvoid (make_tycontext_g vs G) (make_tycontext_s G) (make_tycontext_a (@nil (prod ident Annotation))))))) *)
split3.
*
(* Goal: typecheck_temp_environ (make_tenv (@PTree.set val xH (Vptr b Ptrofs.zero) (PTree.empty val))) (temp_types (mk_tycontext (make_tycontext_t (@cons (prod positive type) (@pair positive type xH (Tfunction Tnil Tvoid cc_default)) (@nil (prod positive type))) (@nil (prod ident type))) (make_tycontext_v (@nil (prod ident type))) Tvoid (make_tycontext_g vs G) (make_tycontext_s G) (make_tycontext_a (@nil (prod ident Annotation))))) *)
unfold temp_types. unfold fst.
(* Goal: typecheck_temp_environ (make_tenv (@PTree.set val xH (Vptr b Ptrofs.zero) (PTree.empty val))) (make_tycontext_t (@cons (prod positive type) (@pair positive type xH (Tfunction Tnil Tvoid cc_default)) (@nil (prod positive type))) (@nil (prod ident type))) *)
unfold make_tycontext_t.
(* Goal: @In ident i (@map (prod ident (globdef fundef type)) ident (@fst ident (globdef fundef type)) (@cons (prod ident (globdef fundef type)) (@pair ident (globdef fundef type) i0 (@Gvar fundef type v)) l)) *)
(* Goal: @list_disjoint ident (@map (prod ident fundef) ident (@fst ident fundef) (@prog_funct' fundef type l)) (@cons ident i (@map (prod ident (globvar type)) ident (@fst ident (globvar type)) (@prog_vars' fundef type l))) *)
unfold fold_right. unfold snd, fst.
(* Goal: typecheck_temp_environ (make_tenv (@PTree.set val xH (Vptr b Ptrofs.zero) (PTree.empty val))) (@PTree.set type xH (Tfunction Tnil Tvoid cc_default) (PTree.empty type)) *)
unfold typecheck_temp_environ.
(* Goal: forall (id : positive) (ty : type) (_ : @eq (option type) (@PTree.get type id (@PTree.set type xH (Tfunction Tnil Tvoid cc_default) (PTree.empty type))) (@Some type ty)), @ex val (fun v : val => and (@eq (option val) (@Map.get val (make_tenv (@PTree.set val xH (Vptr b Ptrofs.zero) (PTree.empty val))) id) (@Some val v)) (tc_val' ty v)) *)
unfold make_tenv.
(* Goal: forall (id : positive) (ty : type) (_ : @eq (option type) (@PTree.get type id (@PTree.set type xH (Tfunction Tnil Tvoid cc_default) (PTree.empty type))) (@Some type ty)), @ex val (fun v : val => and (@eq (option val) (@Map.get val (fun id0 : positive => @PTree.get val id0 (@PTree.set val xH (Vptr b Ptrofs.zero) (PTree.empty val))) id) (@Some val v)) (tc_val' ty v)) *)
unfold Map.get.
(* Goal: forall (id : positive) (ty : type), iff (@eq (option type) (@PTree.get type id (make_tycontext_v (@nil (prod ident type)))) (@Some type ty)) (@ex block (fun v : block => @eq (option (prod block type)) (@Map.get (prod block type) (make_venv empty_env) id) (@Some (prod block type) (@pair block type v ty)))) *)
intros.
rewrite PTree.gsspec in *. if_tac. inv H2.
(* Goal: and (@eq (option block) (@Some block loc') (@Some block loc')) (@ex funspec (fun fs : funspec => @eq (option funspec) (@PTree.get funspec i (make_tycontext_s G)) (@Some funspec fs))) *)
+ exists (Vptr b Ptrofs.zero); split; auto. apply tc_val_tc_val'. simpl; auto.
(* Goal: @ex val (fun v : val => and (@eq (option val) (@PTree.get val id (PTree.empty val)) (@Some val v)) (tc_val' ty v)) *)
+ rewrite PTree.gempty in H2. congruence.
*
(* Goal: typecheck_var_environ (make_venv empty_env) (var_types (mk_tycontext (make_tycontext_t (@cons (prod positive type) (@pair positive type xH (Tfunction Tnil Tvoid cc_default)) (@nil (prod positive type))) (@nil (prod ident type))) (make_tycontext_v (@nil (prod ident type))) Tvoid (make_tycontext_g vs G) (make_tycontext_s G) (make_tycontext_a (@nil (prod ident Annotation))))) *)
unfold var_types.
(* Goal: forall (id : positive) (ty : type), iff (@eq (option type) (@PTree.get type id (make_tycontext_v (@nil (prod ident type)))) (@Some type ty)) (@ex block (fun v : block => @eq (option (prod block type)) (@Map.get (prod block type) (make_venv empty_env) id) (@Some (prod block type) (@pair block type v ty)))) *)
unfold typecheck_var_environ. intros.
(* Goal: forall _ : @ex block (fun v : block => @eq (option (prod block type)) (@Map.get (prod block type) (ve_of (construct_rho (filter_genv (globalenv prog)) empty_env (@PTree.set val xH (Vptr b Ptrofs.zero) (temp_bindings (xO xH) (@map (prod val type) val (@fst val type) typed_args))))) id) (@Some (prod block type) (@pair block type v ty))), @eq (option type) (@PTree.get type id (var_types (@Delta_types vs G C (@map (prod val type) type (@snd val type) typed_args)))) (@Some type ty) *)
unfold make_tycontext_v. simpl.
(* Goal: forall _ : @ex block (fun v : block => @eq (option (prod block type)) (@PTree.get (prod block type) id (PTree.empty (prod block type))) (@Some (prod block type) (@pair block type v ty))), @eq (option type) (@PTree.get type id (PTree.empty type)) (@Some type ty) *)
rewrite PTree.gempty.
(* Goal: iff (@eq (option type) (@None type) (@Some type ty)) (@ex block (fun v : block => @eq (option (prod block type)) (@Map.get (prod block type) (make_venv empty_env) id) (@Some (prod block type) (@pair block type v ty)))) *)
unfold Map.get, make_venv, empty_env.
(* Goal: forall _ : @ex block (fun v : block => @eq (option (prod block type)) (@PTree.get (prod block type) id (PTree.empty (prod block type))) (@Some (prod block type) (@pair block type v ty))), @eq (option type) (@PTree.get type id (PTree.empty type)) (@Some type ty) *)
rewrite PTree.gempty.
(* Goal: @ex block (fun v : block => @eq (option (prod block type)) (@None (prod block type)) (@Some (prod block type) (@pair block type v ty))) *)
(* Goal: @eq (option type) (@None type) (@Some type ty) *)
intuition. inv H2. destruct H2; inv H2.
*
(* Goal: typecheck_glob_environ (filter_genv (globalenv prog)) (glob_types (mk_tycontext (make_tycontext_t (@cons (prod positive type) (@pair positive type xH (Tfunction Tnil Tvoid cc_default)) (@nil (prod positive type))) (@nil (prod ident type))) (make_tycontext_v (@nil (prod ident type))) Tvoid (make_tycontext_g vs G) (make_tycontext_s G) (make_tycontext_a (@nil (prod ident Annotation))))) *)
unfold glob_types. unfold make_tycontext_t, snd.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
eapply tc_ge_denote_initial; eauto.
Qed.

(* Goal: @ex val (fun v : val => and (@eq (option val) (if ident_eq i p then @Some val (@fst val type a) else @Map.get val (make_tenv (temp_bindings (Pos.add p xH) (@map (prod val type) val (@fst val type) typed_args))) i) (@Some val v)) (tc_val' ty v)) *)
Lemma in_map_sig {A B} (E:forall b b' : B, {b=b'}+{b<>b'}) y (f : A -> B) l : In y (map f l) -> {x : A | f x = y /\ In x l }.
Proof.
(* Goal: forall _ : @In B y (@map A B f l), @sig A (fun x : A => and (@eq B (f x) y) (@In A x l)) *)
  induction l; intros HI.
  - inversion HI.
  - simpl in HI.
(* Goal: @sig A (fun x : A => and (@eq B (f x) y) (@In A x (@cons A a l))) *)
    destruct (E (f a) y).
    + exists a; intuition.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
    + destruct IHl. tauto. exists x; intuition.
Qed.

Lemma find_symbol_funct_ptr_ex_sig V ge id f :
  (exists b : block,
      Genv.find_symbol ge id = Some b /\
      Genv.find_funct_ptr ge b = Some f) ->
(* Goal: @ex val (fun v : val => and (@eq (option val) (if ident_eq i p then @Some val (@fst val type a) else @Map.get val (make_tenv (temp_bindings (Pos.add p xH) (@map (prod val type) val (@fst val type) typed_args))) i) (@Some val v)) (tc_val' ty v)) *)
  {b : block |
   Genv.find_symbol ge id = Some b /\
   @Genv.find_funct_ptr (Ctypes.fundef function) V ge b = Some f}.
Proof.
  intros Ex.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
  apply (decidable_countable_ex_sig Pos.of_nat); auto.
  now intro; eexists; symmetry; apply Pos2Nat.id.
  intros p.
(* Goal: @ex val (fun v : val => and (@eq (option val) (if ident_eq i p then @Some val (@fst val type a) else @Map.get val (make_tenv (temp_bindings (Pos.add p xH) (@map (prod val type) val (@fst val type) typed_args))) i) (@Some val v)) (tc_val' ty v)) *)
  assert (group : forall {A} {B} (a a':A) (b b':B), (a = a' /\ b = b') <-> ((a, b) = (a', b')))
    by (intros;split; [ intros [<- <-]; reflexivity | intros E; injection E; auto]).
(* Goal: @ex val (fun v : val => and (@eq (option val) (if ident_eq i p then @Some val (@fst val type a) else @Map.get val (make_tenv (temp_bindings (Pos.add p xH) (@map (prod val type) val (@fst val type) typed_args))) i) (@Some val v)) (tc_val' ty v)) *)
  assert (sumbool_iff_left : forall (A A' B : Prop), (A -> A') -> {A}+{B} -> {A'}+{B}) by tauto.
(* Goal: @ex val (fun v : val => and (@eq (option val) (if ident_eq i p then @Some val (@fst val type a) else @Map.get val (make_tenv (temp_bindings (Pos.add p xH) (@map (prod val type) val (@fst val type) typed_args))) i) (@Some val v)) (tc_val' ty v)) *)
  assert (sumbool_iff_right : forall (A B B' : Prop), (B -> B') -> {A}+{B} -> {A}+{B'}) by tauto.
(* Goal: @In (prod ident (globdef (Ctypes.fundef function) type)) (@pair ident (globdef (Ctypes.fundef function) type) id (@Gfun (Ctypes.fundef function) type f)) (@cons (prod ident (globdef (Ctypes.fundef function) type)) (@pair ident (globdef (Ctypes.fundef function) type) id (@Gfun (Ctypes.fundef function) type f)) l) *)
(* Goal: @In (prod ident (globdef (Ctypes.fundef function) type)) (@pair ident (globdef (Ctypes.fundef function) type) id (@Gfun (Ctypes.fundef function) type f)) (@cons (prod ident (globdef (Ctypes.fundef function) type)) (@pair ident (globdef (Ctypes.fundef function) type) i (@Gfun (Ctypes.fundef function) type f0)) l) *)
(* Goal: @In (prod ident (globdef (Ctypes.fundef function) type)) (@pair ident (globdef (Ctypes.fundef function) type) id (@Gfun (Ctypes.fundef function) type f)) (@cons (prod ident (globdef (Ctypes.fundef function) type)) (@pair ident (globdef (Ctypes.fundef function) type) i (@Gvar (Ctypes.fundef function) type v)) l) *)
  eapply sumbool_iff_left. apply group.
(* Goal: @In ident i (@map (prod ident (globdef fundef type)) ident (@fst ident (globdef fundef type)) (@cons (prod ident (globdef fundef type)) (@pair ident (globdef fundef type) i0 (@Gvar fundef type v)) l)) *)
(* Goal: @list_disjoint ident (@map (prod ident fundef) ident (@fst ident fundef) (@prog_funct' fundef type l)) (@cons ident i (@map (prod ident (globvar type)) ident (@fst ident (globvar type)) (@prog_vars' fundef type l))) *)
  eapply sumbool_iff_right. rewrite group. apply (fun x => x).
  pose proof type_eq.
  pose proof eq_dec_statement.
  repeat (hnf; decide equality; auto).
Qed.

Lemma initial_jm_funassert V (prog : Clight.program) m G n H H1 H2 :
  (funassert (nofunc_tycontext V G) (empty_environ (globalenv prog)))
    (m_phi (initial_jm prog m G n H H1 H2)).
Proof.
(* Goal: @app_pred rmap ag_rmap (funassert (nofunc_tycontext V G) (empty_environ (globalenv prog))) (m_phi (initial_jm prog m G n H H1 H2)) *)
  unfold initial_jm.
  assert (FA: app_pred (funassert (nofunc_tycontext V G) (empty_environ (globalenv prog)))
    (initial_world.initial_core (Genv.globalenv prog) G n)
         ).
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
  apply funassert_initial_core; auto.
(* Goal: @app_pred rmap ag_rmap (funassert (nofunc_tycontext V G) (empty_environ (globalenv prog))) (m_phi (initial_mem m (@initial_world.initial_core_ext function (@OK_ty Espec) ora (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) (@initial_core_ext_ok (@OK_ty Espec) ora prog G n m H1 H2 H))) *)
  revert FA.
(* Goal: forall _ : @app_pred rmap ag_rmap (funassert (nofunc_tycontext V G) (empty_environ (globalenv prog))) (@initial_world.initial_core_ext function (@OK_ty Espec) ora (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n), @app_pred rmap ag_rmap (funassert (nofunc_tycontext V G) (empty_environ (globalenv prog))) (m_phi (initial_mem m (@initial_world.initial_core_ext function (@OK_ty Espec) ora (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) (@initial_core_ext_ok (@OK_ty Espec) ora prog G n m H1 H2 H))) *)
  pose proof corable_funassert (nofunc_tycontext V G) (empty_environ (globalenv prog)) as CO.
(* Goal: forall _ : @app_pred rmap ag_rmap (funassert (nofunc_tycontext V G) (empty_environ (globalenv prog))) (@initial_world.initial_core_ext function (@OK_ty Espec) ora (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n), @app_pred rmap ag_rmap (funassert (nofunc_tycontext V G) (empty_environ (globalenv prog))) (m_phi (initial_mem m (@initial_world.initial_core_ext function (@OK_ty Espec) ora (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) (@initial_core_ext_ok (@OK_ty Espec) ora prog G n m H1 H2 H))) *)
  rewrite corable_spec in CO. apply CO.
(* Goal: @eq rmap (@core rmap Join_rmap Sep_rmap (@initial_world.initial_core_ext function (@OK_ty Espec) ora (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n)) (@core rmap Join_rmap Sep_rmap (m_phi (initial_mem m (@initial_world.initial_core_ext function (@OK_ty Espec) ora (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) (@initial_core_ext_ok (@OK_ty Espec) ora prog G n m H1 H2 H)))) *)
  pose proof initial_mem_core as E.
  unfold juicy_mem_core in *. erewrite E; try reflexivity.
Qed.

Lemma initial_jm_ext_funassert (ora : OK_ty) V (prog : Clight.program) m G n H H1 H2 :
  (funassert (nofunc_tycontext V G) (empty_environ (globalenv prog)))
    (m_phi (initial_jm_ext ora prog m G n H H1 H2)).
Proof.
(* Goal: @app_pred rmap ag_rmap (funassert (nofunc_tycontext V G) (empty_environ (globalenv prog))) (m_phi (@initial_jm_ext (@OK_ty Espec) ora prog m G n H H1 H2)) *)
  unfold initial_jm_ext.
  assert (FA: app_pred (funassert (nofunc_tycontext V G) (empty_environ (globalenv prog)))
    (initial_world.initial_core_ext ora (Genv.globalenv prog) G n)
         ).
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
  apply funassert_initial_core_ext; auto.
(* Goal: @app_pred rmap ag_rmap (funassert (nofunc_tycontext V G) (empty_environ (globalenv prog))) (m_phi (initial_mem m (@initial_world.initial_core_ext function (@OK_ty Espec) ora (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) (@initial_core_ext_ok (@OK_ty Espec) ora prog G n m H1 H2 H))) *)
  revert FA. 
(* Goal: forall _ : @app_pred rmap ag_rmap (funassert (nofunc_tycontext V G) (empty_environ (globalenv prog))) (@initial_world.initial_core_ext function (@OK_ty Espec) ora (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n), @app_pred rmap ag_rmap (funassert (nofunc_tycontext V G) (empty_environ (globalenv prog))) (m_phi (initial_mem m (@initial_world.initial_core_ext function (@OK_ty Espec) ora (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) (@initial_core_ext_ok (@OK_ty Espec) ora prog G n m H1 H2 H))) *)
  pose proof corable_funassert (nofunc_tycontext V G) (empty_environ (globalenv prog)) as CO.
(* Goal: forall _ : @app_pred rmap ag_rmap (funassert (nofunc_tycontext V G) (empty_environ (globalenv prog))) (@initial_world.initial_core_ext function (@OK_ty Espec) ora (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n), @app_pred rmap ag_rmap (funassert (nofunc_tycontext V G) (empty_environ (globalenv prog))) (m_phi (initial_mem m (@initial_world.initial_core_ext function (@OK_ty Espec) ora (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) (@initial_core_ext_ok (@OK_ty Espec) ora prog G n m H1 H2 H))) *)
  rewrite corable_spec in CO. apply CO.
(* Goal: @eq rmap (@core rmap Join_rmap Sep_rmap (@initial_world.initial_core_ext function (@OK_ty Espec) ora (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n)) (@core rmap Join_rmap Sep_rmap (m_phi (initial_mem m (@initial_world.initial_core_ext function (@OK_ty Espec) ora (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) (@initial_core_ext_ok (@OK_ty Espec) ora prog G n m H1 H2 H)))) *)
  pose proof initial_mem_core as E.
  unfold juicy_mem_core in *. erewrite E; try reflexivity.
Qed.

(* Goal: @ex val (fun v : val => and (@eq (option val) (if ident_eq i p then @Some val (@fst val type a) else @Map.get val (make_tenv (temp_bindings (Pos.add p xH) (@map (prod val type) val (@fst val type) typed_args))) i) (@Some val v)) (tc_val' ty v)) *)
Lemma semax_prog_rule' {CS: compspecs} :
  forall V G prog m h,
     @semax_prog CS prog V G ->
     Genv.init_mem prog = Some m ->
(* Goal: @ex val (fun v : val => and (@eq (option val) (if ident_eq i p then @Some val (@fst val type a) else @Map.get val (make_tenv (temp_bindings (Pos.add p xH) (@map (prod val type) val (@fst val type) typed_args))) i) (@Some val v)) (tc_val' ty v)) *)
     { b : block & { q : corestate &
       (Genv.find_symbol (globalenv prog) (prog_main prog) = Some b) *
       (forall jm, m_dry jm = m -> exists jm', semantics.initial_core (juicy_core_sem (cl_core_sem (globalenv prog))) h
                    jm q jm' (Vptr b Ptrofs.zero) nil) *
       forall n z,
(* Goal: @ex val (fun v : val => and (@eq (option val) (if ident_eq i p then @Some val (@fst val type a) else @Map.get val (make_tenv (temp_bindings (Pos.add p xH) (@map (prod val type) val (@fst val type) typed_args))) i) (@Some val v)) (tc_val' ty v)) *)
         { jm |
           m_dry jm = m /\ level jm = n /\
           nth_error (ghost_of (m_phi jm)) 0 = Some (Some (ext_ghost z, NoneP)) /\
           jsafeN (@OK_spec Espec) (globalenv prog) n z q jm /\
           no_locks (m_phi jm) /\
           matchfunspecs (globalenv prog) G (m_phi jm) /\
           (funassert (nofunc_tycontext V G) (empty_environ (globalenv prog))) (m_phi jm)
     } } }%type.
Proof.
  intros until m.
(* Goal: forall (id : positive) (ty : type), iff (@eq (option type) (@PTree.get type id (make_tycontext_v (@nil (prod ident type)))) (@Some type ty)) (@ex block (fun v : block => @eq (option (prod block type)) (@Map.get (prod block type) (make_venv empty_env) id) (@Some (prod block type) (@pair block type v ty)))) *)
  pose proof I; intros.
  destruct H0 as [? [AL [HGG [[? ?] [GV ?]]]]].
(* Goal: @eq (option type) (@None type) (@Some type t) *)
  destruct (find_id (prog_main prog) G) as [fspec|] eqn:Hfind; try contradiction.
(* Goal: @ex val (fun v : val => and (@eq (option val) (if ident_eq i p then @Some val (@fst val type a) else @Map.get val (make_tenv (temp_bindings (Pos.add p xH) (@map (prod val type) val (@fst val type) typed_args))) i) (@Some val v)) (tc_val' ty v)) *)
  assert (H4': exists post, In (prog_main prog, main_spec' prog post) G /\ fspec = main_spec' prog post). {
    destruct (find_id (prog_main prog) G) eqn:?.
    apply find_id_e in Heqo. destruct H4 as [post ?]. exists post.
(* Goal: and (@eq (option block) (@Some block loc') (@Some block loc')) (@ex funspec (fun fs : funspec => @eq (option funspec) (@PTree.get funspec i (make_tycontext_s G)) (@Some funspec fs))) *)
    subst. split; auto. inv Hfind. auto. inv Hfind.
  } clear H4. rename H4' into H4.
(* Goal: @ex val (fun v : val => and (@eq (option val) (if ident_eq i p then @Some val (@fst val type a) else @Map.get val (make_tenv (temp_bindings (Pos.add p xH) (@map (prod val type) val (@fst val type) typed_args))) i) (@Some val v)) (tc_val' ty v)) *)
  assert ({ f | In (prog_main prog, f) (prog_funct prog)}).
  forget (prog_main prog) as id.
(* Goal: @ex val (fun v : val => and (@eq (option val) (if ident_eq i p then @Some val (@fst val type a) else @Map.get val (make_tenv (temp_bindings (Pos.add p xH) (@map (prod val type) val (@fst val type) typed_args))) i) (@Some val v)) (tc_val' ty v)) *)
  assert (H4': In id (map fst G)). {
  destruct H4 as [? [H4 _]].
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
  apply in_map_fst in H4. auto.
  }
  pose proof (match_fdecs_in _ _ _ H4' H2).
  apply in_map_sig in H5. 2:decide equality.
(* Goal: @In ident i (@map (prod ident (globvar type)) ident (@fst ident (globvar type)) vl) *)
(* Goal: iff (@eq (option type) (@PTree.get type id (make_tycontext_g vs (@cons (prod ident funspec) (@pair ident funspec i fspec) G0))) (@Some type t)) (or (@ex funspec (fun f : funspec => and (@In (prod positive funspec) (@pair positive funspec id f) (@cons (prod ident funspec) (@pair ident funspec i fspec) G0)) (@eq type t (type_of_funspec f)))) (@In (prod positive type) (@pair positive type id t) vs)) *)
  destruct H5 as [[? ?] [? ?]]; subst.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
  eauto.
  destruct H5 as [f ?].
  apply compute_list_norepet_e in H0.
  assert (indefs: In (prog_main prog, Gfun f) (AST.prog_defs prog))
    by (apply in_prog_funct_in_prog_defs; auto).
  pose proof (find_funct_ptr_exists prog (prog_main prog) f) as EXx.
  (* Genv.find_funct_ptr_exists is a Prop existential, we use constructive epsilon and
     decidability on a countable set to transform it to a Type existential *)
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
  apply find_symbol_funct_ptr_ex_sig in EXx; auto.

(* Goal: @app_pred nat ag_nat (@box nat ag_nat (@laterM nat ag_nat) (@semax' C Espec (func_tycontext' f (nofunc_tycontext V G)) (fun rho : environ => @andp rmap ag_rmap (@sepcon rmap Join_rmap Perm_rmap ag_rmap Age_rmap (bind_args (fn_params f) (fn_vars f) (P ts x) rho) (stackframe_of' (genv_cenv ge) f rho)) (funassert (func_tycontext' f (nofunc_tycontext V G)) rho)) (Ssequence (fn_body f) (Sreturn (@None expr))) (frame_ret_assert (function_body_ret_assert (fn_return f) (Q ts x)) (stackframe_of' (genv_cenv ge) f)))) n *)
  pose proof I.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
  destruct EXx as [b [? ?]]; auto.
(* Goal: @ex val (fun v : val => and (@eq (option val) (if ident_eq i p then @Some val (@fst val type a) else @Map.get val (make_tenv (temp_bindings (Pos.add p xH) (@map (prod val type) val (@fst val type) typed_args))) i) (@Some val v)) (tc_val' ty v)) *)
  assert (E: type_of_fundef f = Tfunction Tnil tint cc_default). {
     destruct H4 as [post [? ?]].
      destruct (match_fdecs_exists_Gfun
                  prog G (prog_main prog)
                  (main_spec' prog post))
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
        as (fd, (Ifd, sametypes)); auto.
(* Goal: @ex val (fun v : val => and (@eq (option val) (if ident_eq i p then @Some val (@fst val type a) else @Map.get val (make_tenv (temp_bindings (Pos.add p xH) (@map (prod val type) val (@fst val type) typed_args))) i) (@Some val v)) (tc_val' ty v)) *)
      {
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
        apply find_id_i; auto.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
        eapply match_fdecs_norepet; eauto.
        clear -H0; revert H0.
        apply sublist_norepet.
        unfold prog_funct, prog_funct', prog_defs_names.
        replace (AST.prog_defs prog) with (prog_defs prog) by reflexivity.
        generalize (prog_defs prog); intros l; induction l as [|(i,[g|]) l];
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
          constructor; auto.
      }
      assert (fd = f).
      cut (Gfun fd = @Gfun _ type f); [ intros E; injection E; auto | ].
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
      apply (list_norepet_In_In (prog_main prog) _ _ (prog_defs prog)); auto.
      subst fd.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
      auto.
    }
(* Goal: @app_pred rmap ag_rmap (@exp rmap ag_rmap block (fun b : block => @andp rmap ag_rmap (@prop rmap ag_rmap (@eq (option block) (@Genv.find_symbol fundef type (genv_genv (globalenv prog)) id) (@Some block b))) (func_at fs (@pair block Z b Z0)))) (@initial_world.initial_core_ext function (@OK_ty Espec) ora (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) *)
  exists b.
  unfold semantics.initial_core, juicy_core_sem.
  unfold j_initial_core, semantics.initial_core, cl_core_sem, cl_initial_core.
  eexists.
  unfold fundef in *.
  change (Genv.globalenv prog) with (genv_genv (globalenv prog)) in *.
  rewrite H6, H7.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
  rewrite if_true by auto.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
  repeat split; eauto.
(* Goal: @ex val (fun v : val => and (@eq (option val) (if ident_eq i p then @Some val (@fst val type a) else @Map.get val (make_tenv (temp_bindings (Pos.add p xH) (@map (prod val type) val (@fst val type) typed_args))) i) (@Some val v)) (tc_val' ty v)) *)
  {
(* Goal: forall (id : positive) (ty : type), iff (@eq (option type) (@PTree.get type id (make_tycontext_v (@nil (prod ident type)))) (@Some type ty)) (@ex block (fun v : block => @eq (option (prod block type)) (@Map.get (prod block type) (make_venv empty_env) id) (@Some (prod block type) (@pair block type v ty)))) *)
    intros. eexists; split. reflexivity.
    rewrite E.  
    repeat split; eauto; try solve [constructor].
  }
  intros n z.
  exists (initial_jm_ext z _ _ _ n H1 H0 H2).
(* Goal: and (var_sizes_ok (genv_cenv ge) (fn_vars f)) (and (@eq funsig fsig (fn_funsig f)) (@eq calling_convention (fn_callconv f) cc')) *)
(* Goal: @app_pred nat ag_nat (@allp nat ag_nat (list Type) (fun ts : list Type => @allp nat ag_nat (_functor (dependent_type_functor_rec ts A') (@pred rmap ag_rmap)) (fun x : _functor (dependent_type_functor_rec ts A') (@pred rmap ag_rmap) => @box nat ag_nat (@laterM nat ag_nat) (@semax' C Espec (func_tycontext' f (nofunc_tycontext V G)) (fun rho : environ => @andp rmap ag_rmap (@sepcon rmap Join_rmap Perm_rmap ag_rmap Age_rmap (bind_args (fn_params f) (fn_vars f) (P' ts x) rho) (stackframe_of' (genv_cenv ge) f rho)) (funassert (func_tycontext' f (nofunc_tycontext V G)) rho)) (Ssequence (fn_body f) (Sreturn (@None expr))) (frame_ret_assert (function_body_ret_assert (fn_return f) (Q' ts x)) (stackframe_of' (genv_cenv ge) f)))))) n *)
  repeat split.
(* Goal: forall _ : @ex block (fun v : block => @eq (option (prod block type)) (@Map.get (prod block type) (ve_of (construct_rho (filter_genv (globalenv prog)) empty_env (@PTree.set val xH (Vptr b Ptrofs.zero) (temp_bindings (xO xH) (@map (prod val type) val (@fst val type) typed_args))))) id) (@Some (prod block type) (@pair block type v ty))), @eq (option type) (@PTree.get type id (var_types (@Delta_types vs G C (@map (prod val type) type (@snd val type) typed_args)))) (@Some type ty) *)
  - simpl.
    rewrite inflate_initial_mem_level.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
    unfold initial_core_ext. rewrite level_make_rmap; auto.

(* Goal: forall _ : @ex block (fun v : block => @eq (option (prod block type)) (@Map.get (prod block type) (ve_of (construct_rho (filter_genv (globalenv prog)) empty_env (@PTree.set val xH (Vptr b Ptrofs.zero) (temp_bindings (xO xH) (@map (prod val type) val (@fst val type) typed_args))))) id) (@Some (prod block type) (@pair block type v ty))), @eq (option type) (@PTree.get type id (var_types (@Delta_types vs G C (@map (prod val type) type (@snd val type) typed_args)))) (@Some type ty) *)
  - unfold initial_jm_ext; simpl.
    unfold inflate_initial_mem; rewrite ghost_of_make_rmap.
    unfold initial_core_ext; rewrite ghost_of_make_rmap.
    reflexivity.

  - specialize (H3 (globalenv prog) (prog_contains_prog_funct _ H0)).
    destruct H4 as [post [? ?]].
    unfold temp_bindings. simpl length. simpl typed_params. simpl type_of_params.
    pattern n at 1; replace n with (level (m_phi (initial_jm_ext z prog m G n H1 H0 H2))).
    pose (rho1 := mkEnviron (filter_genv (globalenv prog)) (Map.empty (block * type))
                           (Map.set 1 (Vptr b Ptrofs.zero) (Map.empty val))).
    pose (post' := fun rho => TT * EX rv:val, post nil (globals_of_env rho1) (env_set (globals_only rho) ret_temp rv)).
    eapply (semax_call_aux (Delta1 V G) (ConstType (ident->val))
              _ post _ (const_super_non_expansive _ _) (const_super_non_expansive _ _)
              nil (globals_of_env rho1) (fun _ => TT) (fun _ => TT)
              None (nil, tint) cc_default _ _ (normal_ret_assert post') _ _ _ _
              (construct_rho (filter_genv (globalenv prog)) empty_env
                 (PTree.set 1 (Vptr b Ptrofs.zero) (PTree.empty val)))
              _ _ b (prog_main prog));
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
      try apply H3; try eassumption; auto.
(* Goal: forall _ : @ex block (fun v : block => @eq (option (prod block type)) (@Map.get (prod block type) (ve_of (construct_rho (filter_genv (globalenv prog)) empty_env (@PTree.set val xH (Vptr b Ptrofs.zero) (temp_bindings (xO xH) (@map (prod val type) val (@fst val type) typed_args))))) id) (@Some (prod block type) (@pair block type v ty))), @eq (option type) (@PTree.get type id (var_types (@Delta_types vs G C (@map (prod val type) type (@snd val type) typed_args)))) (@Some type ty) *)
    + simpl.
        unfold inflate_initial_mem; rewrite ghost_of_make_rmap.
        unfold initial_core_ext; rewrite ghost_of_make_rmap.
(* Goal: @list_norepet ident (@map (prod ident fundef) ident (@fst ident fundef) (@prog_funct' (Ctypes.fundef function) type (@nil (prod ident (globdef (Ctypes.fundef function) type))))) *)
(* Goal: @list_norepet ident (@map (prod ident fundef) ident (@fst ident fundef) (@prog_funct' (Ctypes.fundef function) type (@cons (prod ident (globdef (Ctypes.fundef function) type)) a l))) *)
(* Goal: @ex block (fun b : block => @eq (option block) (@Map.get block (@Genv.find_symbol fundef type (genv_genv (globalenv prog))) id) (@Some block b)) *)
        exists (Some (ext_both z, NoneP) :: nil); repeat constructor.
(* Goal: forall _ : @ex block (fun v : block => @eq (option (prod block type)) (@Map.get (prod block type) (ve_of (construct_rho (filter_genv (globalenv prog)) empty_env (@PTree.set val xH (Vptr b Ptrofs.zero) (temp_bindings (xO xH) (@map (prod val type) val (@fst val type) typed_args))))) id) (@Some (prod block type) (@pair block type v ty))), @eq (option type) (@PTree.get type id (var_types (@Delta_types vs G C (@map (prod val type) type (@snd val type) typed_args)))) (@Some type ty) *)
    + simpl.
      exists (Vptr b Ptrofs.zero).
(* Goal: and (@eq (option block) (@Some block loc') (@Some block loc')) (@ex funspec (fun fs : funspec => @eq (option funspec) (@PTree.get funspec i (make_tycontext_s G)) (@Some funspec fs))) *)
      split; auto.
    + simpl snd.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
      replace (params_of_fundef f) with (@nil type). simpl; auto. clear -E.
      destruct f as [[? ? [ | [] ]] | e [|] ? c] ; compute in *; congruence.
    + clear - GV H2 H0.
(* Goal: and (var_sizes_ok (genv_cenv ge) (fn_vars f)) (and (@eq funsig fsig (fn_funsig f)) (@eq calling_convention (fn_callconv f) cc')) *)
(* Goal: @app_pred nat ag_nat (@allp nat ag_nat (list Type) (fun ts : list Type => @allp nat ag_nat (_functor (dependent_type_functor_rec ts A') (@pred rmap ag_rmap)) (fun x : _functor (dependent_type_functor_rec ts A') (@pred rmap ag_rmap) => @box nat ag_nat (@laterM nat ag_nat) (@semax' C Espec (func_tycontext' f (nofunc_tycontext V G)) (fun rho : environ => @andp rmap ag_rmap (@sepcon rmap Join_rmap Perm_rmap ag_rmap Age_rmap (bind_args (fn_params f) (fn_vars f) (P' ts x) rho) (stackframe_of' (genv_cenv ge) f rho)) (funassert (func_tycontext' f (nofunc_tycontext V G)) rho)) (Ssequence (fn_body f) (Sreturn (@None expr))) (frame_ret_assert (function_body_ret_assert (fn_return f) (Q' ts x)) (stackframe_of' (genv_cenv ge) f)))))) n *)
      split.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
      eapply semax_prog_typecheck_aux; eauto.
(* Goal: forall _ : @ex block (fun v : block => @eq (option (prod block type)) (@Map.get (prod block type) (ve_of (construct_rho (filter_genv (globalenv prog)) empty_env (@PTree.set val xH (Vptr b Ptrofs.zero) (temp_bindings (xO xH) (@map (prod val type) val (@fst val type) typed_args))))) id) (@Some (prod block type) (@pair block type v ty))), @eq (option type) (@PTree.get type id (var_types (@Delta_types vs G C (@map (prod val type) type (@snd val type) typed_args)))) (@Some type ty) *)
      simpl.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
      auto.
    + hnf; intros; intuition.
    + hnf; intros; intuition.
(* Goal: forall _ : @ex block (fun v : block => @eq (option (prod block type)) (@Map.get (prod block type) (ve_of (construct_rho (filter_genv (globalenv prog)) empty_env (@PTree.set val xH (Vptr b Ptrofs.zero) (temp_bindings (xO xH) (@map (prod val type) val (@fst val type) typed_args))))) id) (@Some (prod block type) (@pair block type v ty))), @eq (option type) (@PTree.get type id (var_types (@Delta_types vs G C (@map (prod val type) type (@snd val type) typed_args)))) (@Some type ty) *)
      unfold normal_ret_assert; simpl.
      extensionality rho'.
      normalize.
      unfold post'.
      apply pred_ext.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
           normalize. intro rv. do 2 apply exp_right with rv; auto.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
           normalize. intro rv. apply exp_right with rv; auto. 
    + rewrite (corable_funassert _ _).
      simpl m_phi.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
      rewrite core_inflate_initial_mem'; auto.
      do 3 (pose proof I).
      replace (funassert (Delta1 V G)) with
      (funassert (@nofunc_tycontext V G)).
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
      unfold rho1; apply funassert_initial_core; auto.
      apply same_glob_funassert.
      reflexivity.
    + intros ek vl tx' vx'.
      cbv zeta. rewrite proj_frame_ret_assert. simpl seplog.sepcon.
      subst post'. cbv beta.
      destruct ek; simpl proj_ret_assert; normalize.
      apply derives_subp.
      normalize. intro rv.
(* Goal: forall _ : @ex block (fun v : block => @eq (option (prod block type)) (@Map.get (prod block type) (ve_of (construct_rho (filter_genv (globalenv prog)) empty_env (@PTree.set val xH (Vptr b Ptrofs.zero) (temp_bindings (xO xH) (@map (prod val type) val (@fst val type) typed_args))))) id) (@Some (prod block type) (@pair block type v ty))), @eq (option type) (@PTree.get type id (var_types (@Delta_types vs G C (@map (prod val type) type (@snd val type) typed_args)))) (@Some type ty) *)
      simpl.
      eapply derives_trans, own.bupd_intro.
      intros ? ? ? ? Hora _ ?.
      destruct H9 as [[? [H10' [H11 ?]]] ?].
      hnf in H10', H11.
      destruct H9.
      subst a.
      change Clight_new.true_expr with true_expr.
      change (level (m_phi jm)) with (level jm).
      apply safe_loop_skip.
    + unfold glob_types, Delta1. simpl @snd.
      forget (prog_main prog) as main.
      instantiate (1:= post).
      instantiate (1:= main_pre prog).
(* Goal: @ex val (fun v : val => and (@eq (option val) (if ident_eq i p then @Some val (@fst val type a) else @Map.get val (make_tenv (temp_bindings (Pos.add p xH) (@map (prod val type) val (@fst val type) typed_args))) i) (@Some val v)) (tc_val' ty v)) *)
      assert (H8': list_norepet (map (@fst _ _) (prog_funct prog))). {
      clear - H0.
(* Goal: @list_norepet ident (@map (prod ident fundef) ident (@fst ident fundef) (@initial_world.prog_funct function prog)) *)
(* Goal: @ex block (fun b : block => @eq (option block) (@Map.get block (@Genv.find_symbol fundef type (genv_genv (globalenv prog))) id) (@Some block b)) *)
      unfold prog_defs_names in H0. unfold prog_funct.
      change (AST.prog_defs prog) with (prog_defs prog) in H0.
(* Goal: iff (@eq (option type) (@PTree.get type id (@PTree.set type (@fst ident type (@pair ident type i t0)) (@snd ident type (@pair ident type i t0)) (@fold_right (PTree.t type) (prod ident type) (fun v : prod ident type => @PTree.set type (@fst ident type v) (@snd ident type v)) (PTree.empty type) vs))) (@Some type t)) (or (@eq (prod positive type) (@pair ident type i t0) (@pair positive type id t)) (@In (prod positive type) (@pair positive type id t) vs)) *)
      induction (prog_defs prog); auto. inv H0.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
      destruct a; destruct g; simpl; auto. constructor; auto.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
      clear - H2; simpl in H2; contradict H2; induction l; simpl in *; auto.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
      destruct a; destruct g; simpl in *; auto. destruct H2; auto.
      }
      forget (prog_funct prog) as fs.
      clear - H4 H8' H2. rename H8' into H8.
      fold (main_spec prog).
      forget (main_spec prog) as fd.
(* Goal: @ex block (fun v : block => @eq (option (prod block type)) (@None (prod block type)) (@Some (prod block type) (@pair block type v ty))) *)
(* Goal: @eq (option type) (@None type) (@Some type ty) *)
      revert G H2 H4 H8; induction fs; intros; inv H2.
      contradiction H4.
      simpl in *.
(* Goal: @In ident i (@map (prod ident (globvar type)) ident (@fst ident (globvar type)) vl) *)
(* Goal: iff (@eq (option type) (@PTree.get type id (make_tycontext_g vs (@cons (prod ident funspec) (@pair ident funspec i fspec) G0))) (@Some type t)) (or (@ex funspec (fun f : funspec => and (@In (prod positive funspec) (@pair positive funspec id f) (@cons (prod ident funspec) (@pair ident funspec i fspec) G0)) (@eq type t (type_of_funspec f)))) (@In (prod positive type) (@pair positive type id t) vs)) *)
      destruct (ident_eq i main). subst. rewrite PTree.gss.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
      destruct H4. inv H; auto.
      inv H8.
(* Goal: @eq type (type_of_funspec fspec) t *)
(* Goal: iff (@eq (option type) (@PTree.get type id (make_tycontext_g vs (@cons (prod ident funspec) (@pair ident funspec i fspec) G0))) (@Some type t)) (or (@ex funspec (fun f : funspec => and (@In (prod positive funspec) (@pair positive funspec id f) (@cons (prod ident funspec) (@pair ident funspec i fspec) G0)) (@eq type t (type_of_funspec f)))) (@In (prod positive type) (@pair positive type id t) vs)) *)
      contradiction H3.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
      eapply match_fdecs_in; eauto.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
      apply in_map_fst in H; auto.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
      rewrite PTree.gso by auto.
(* Goal: @ex val (fun v : val => and (@eq (option val) (@PTree.get val id (PTree.empty val)) (@Some val v)) (tc_val' ty v)) *)
      destruct H4; try congruence.
      inv H8.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
      eapply IHfs; eauto.
(* Goal: forall (id : positive) (ty : type), iff (@eq (option type) (@PTree.get type id (make_tycontext_v (@nil (prod ident type)))) (@Some type ty)) (@ex block (fun v : block => @eq (option (prod block type)) (@Map.get (prod block type) (make_venv empty_env) id) (@Some (prod block type) (@pair block type v ty)))) *)
    + intros.
      intros ? ?.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
      split; apply derives_imp; auto.
    + unfold main_pre.
(* Goal: @app_pred nat ag_nat (@box nat ag_nat (@laterM nat ag_nat) (@semax' C Espec (func_tycontext' f (nofunc_tycontext V G)) (fun rho : environ => @andp rmap ag_rmap (@sepcon rmap Join_rmap Perm_rmap ag_rmap Age_rmap (bind_args (fn_params f) (fn_vars f) (P ts x) rho) (stackframe_of' (genv_cenv ge) f rho)) (funassert (func_tycontext' f (nofunc_tycontext V G)) rho)) (Ssequence (fn_body f) (Sreturn (@None expr))) (frame_ret_assert (function_body_ret_assert (fn_return f) (Q ts x)) (stackframe_of' (genv_cenv ge) f)))) n *)
      apply now_later.
      rewrite TT_sepcon_TT.
      rewrite sepcon_comm.
      eexists; eexists; split; [apply initial_jm_ext_eq|].
(* Goal: and (@eq (option block) (@Some block loc') (@Some block loc')) (@ex funspec (fun fs : funspec => @eq (option funspec) (@PTree.get funspec i (make_tycontext_s G)) (@Some funspec fs))) *)
      split; auto.
     match goal with |- app_pred (globvars2pred (globals_of_env ?A) _ ?B) _ => 
       change (globals_of_env A) with (globals_of_env B)
      end.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
      apply global_initializers; auto.
(* Goal: forall _ : @ex block (fun v : block => @eq (option (prod block type)) (@Map.get (prod block type) (ve_of (construct_rho (filter_genv (globalenv prog)) empty_env (@PTree.set val xH (Vptr b Ptrofs.zero) (temp_bindings (xO xH) (@map (prod val type) val (@fst val type) typed_args))))) id) (@Some (prod block type) (@pair block type v ty))), @eq (option type) (@PTree.get type id (var_types (@Delta_types vs G C (@map (prod val type) type (@snd val type) typed_args)))) (@Some type ty) *)
    + simpl.
      rewrite inflate_initial_mem_level.
(* Goal: @app_pred rmap ag_rmap (pureat (SomeP (SpecTT A) (@packPQ A a a0)) (FUN f0 cc0) (@pair block Z b Z0)) (@initial_world.initial_core function (@Genv.globalenv (Ctypes.fundef function) type (@program_of_program function prog)) G n) *)
      unfold initial_core.
      apply level_make_rmap.
  - apply initial_jm_ext_without_locks.
  - apply initial_jm_ext_matchfunspecs. 
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
  -  destruct (initial_jm_ext_funassert z V prog m G n H1 H0 H2). auto.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
  -  destruct (initial_jm_ext_funassert z V prog m G n H1 H0 H2). auto.
Qed.

(* This version works if we don't need to know anything about the external state. *)
(* Goal: @ex val (fun v : val => and (@eq (option val) (if ident_eq i p then @Some val (@fst val type a) else @Map.get val (make_tenv (temp_bindings (Pos.add p xH) (@map (prod val type) val (@fst val type) typed_args))) i) (@Some val v)) (tc_val' ty v)) *)
Lemma semax_prog_rule {CS: compspecs} :
  OK_ty = unit -> 
  forall V G prog m h,
     @semax_prog CS prog V G ->
     Genv.init_mem prog = Some m ->
(* Goal: @ex val (fun v : val => and (@eq (option val) (if ident_eq i p then @Some val (@fst val type a) else @Map.get val (make_tenv (temp_bindings (Pos.add p xH) (@map (prod val type) val (@fst val type) typed_args))) i) (@Some val v)) (tc_val' ty v)) *)
     { b : block & { q : corestate &
       (Genv.find_symbol (globalenv prog) (prog_main prog) = Some b) *
       (forall jm, m_dry jm = m -> exists jm', semantics.initial_core (juicy_core_sem (cl_core_sem (globalenv prog))) h
                    jm q jm' (Vptr b Ptrofs.zero) nil) *
       forall n,
(* Goal: @ex val (fun v : val => and (@eq (option val) (if ident_eq i p then @Some val (@fst val type a) else @Map.get val (make_tenv (temp_bindings (Pos.add p xH) (@map (prod val type) val (@fst val type) typed_args))) i) (@Some val v)) (tc_val' ty v)) *)
         { jm |
           m_dry jm = m /\ level jm = n /\
           (forall z, jsafeN (@OK_spec Espec) (globalenv prog) n z q jm) /\
           no_locks (m_phi jm) /\
           matchfunspecs (globalenv prog) G (m_phi jm) /\
           (funassert (nofunc_tycontext V G) (empty_environ (globalenv prog))) (m_phi jm)
     } } }%type.
Proof.
(* Goal: forall (id : positive) (ty : type), iff (@eq (option type) (@PTree.get type id (make_tycontext_v (@nil (prod ident type)))) (@Some type ty)) (@ex block (fun v : block => @eq (option (prod block type)) (@Map.get (prod block type) (make_venv empty_env) id) (@Some (prod block type) (@pair block type v ty)))) *)
  intro OKunit; intros.
(* Goal: @sigT block (fun b : block => @sigT corestate (fun q : corestate => prod (prod (@eq (option block) (@Genv.find_symbol fundef type (genv_genv (globalenv prog)) (@prog_main function prog)) (@Some block b)) (forall (jm : juicy_mem) (_ : @eq mem (m_dry jm) m), @ex juicy_mem (fun jm' : juicy_mem => @semantics.initial_core corestate juicy_mem (@juicy_core_sem corestate (cl_core_sem (globalenv prog))) h jm q jm' (Vptr b Ptrofs.zero) (@nil val)))) (forall n : nat, @sig juicy_mem (fun jm : juicy_mem => and (@eq mem (m_dry jm) m) (and (@eq nat (@level juicy_mem juicy_mem_ageable jm) n) (and (forall z : @OK_ty Espec, @jsafeN (@OK_ty Espec) (@OK_spec Espec) (globalenv prog) n z q jm) (and (no_locks (m_phi jm)) (and (matchfunspecs (globalenv prog) G (m_phi jm)) (@app_pred rmap ag_rmap (funassert (nofunc_tycontext V G) (empty_environ (globalenv prog))) (m_phi jm)))))))))) *)
  destruct (semax_prog_rule' V G prog m h H H0) as [b [q [[?H ?H] ?H]]].
(* Goal: @sigT block (fun b : block => @sigT corestate (fun q : corestate => prod (prod (@eq (option block) (@Genv.find_symbol fundef type (genv_genv (globalenv prog)) (@prog_main function prog)) (@Some block b)) (forall (jm : juicy_mem) (_ : @eq mem (m_dry jm) m), @ex juicy_mem (fun jm' : juicy_mem => @semantics.initial_core corestate juicy_mem (@juicy_core_sem corestate (cl_core_sem (globalenv prog))) h jm q jm' (Vptr b Ptrofs.zero) (@nil val)))) (forall n : nat, @sig juicy_mem (fun jm : juicy_mem => and (@eq mem (m_dry jm) m) (and (@eq nat (@level juicy_mem juicy_mem_ageable jm) n) (and (forall z : @OK_ty Espec, @jsafeN (@OK_ty Espec) (@OK_spec Espec) (globalenv prog) n z q jm) (and (no_locks (m_phi jm)) (and (matchfunspecs (globalenv prog) G (m_phi jm)) (@app_pred rmap ag_rmap (funassert (nofunc_tycontext V G) (empty_environ (globalenv prog))) (m_phi jm)))))))))) *)
  clear H H0.
  destruct Espec. simpl in *.
(* Goal: and (@eq (option block) (@Some block loc') (@Some block loc')) (@ex funspec (fun fs : funspec => @eq (option funspec) (@PTree.get funspec i (make_tycontext_s G)) (@Some funspec fs))) *)
  exists b, q; split; auto.
(* Goal: forall n : nat, @sig juicy_mem (fun jm : juicy_mem => and (@eq mem (m_dry jm) m) (and (@eq nat (@level rmap ag_rmap (m_phi jm)) n) (and (forall z : OK_ty, @jsafeN OK_ty OK_spec (globalenv prog) n z q jm) (and (no_locks (m_phi jm)) (and (matchfunspecs (globalenv prog) G (m_phi jm)) (and (forall (b : ident) (b0 : funspec) (a' : rmap) (_ : @necR rmap ag_rmap (m_phi jm) a') (_ : @eq (option funspec) (@PTree.get funspec b (make_tycontext_s G)) (@Some funspec b0)), @ex block (fun b1 : block => and (@eq (option block) (@Map.get block (filter_genv (globalenv prog)) b) (@Some block b1)) (@app_pred rmap ag_rmap (func_at b0 (@pair block Z b1 Z0)) a'))) (forall (b : block) (b0 : funspec) (a' : rmap) (_ : @necR rmap ag_rmap (m_phi jm) a') (_ : @app_pred rmap ag_rmap (func_at' b0 (@pair block Z b Z0)) a'), @ex ident (fun b1 : ident => and (@eq (option block) (@Map.get block (filter_genv (globalenv prog)) b1) (@Some block b)) (@ex funspec (fun fs : funspec => @eq (option funspec) (@PTree.get funspec b1 (make_tycontext_s G)) (@Some funspec fs))))))))))) *)
  clear H1 H2.
(* Goal: forall n : nat, @sig juicy_mem (fun jm : juicy_mem => and (@eq mem (m_dry jm) m) (and (@eq nat (@level rmap ag_rmap (m_phi jm)) n) (and (forall z : OK_ty, @jsafeN OK_ty OK_spec (globalenv prog) n z q jm) (and (no_locks (m_phi jm)) (and (matchfunspecs (globalenv prog) G (m_phi jm)) (and (forall (b : ident) (b0 : funspec) (a' : rmap) (_ : @necR rmap ag_rmap (m_phi jm) a') (_ : @eq (option funspec) (@PTree.get funspec b (make_tycontext_s G)) (@Some funspec b0)), @ex block (fun b1 : block => and (@eq (option block) (@Map.get block (filter_genv (globalenv prog)) b) (@Some block b1)) (@app_pred rmap ag_rmap (func_at b0 (@pair block Z b1 Z0)) a'))) (forall (b : block) (b0 : funspec) (a' : rmap) (_ : @necR rmap ag_rmap (m_phi jm) a') (_ : @app_pred rmap ag_rmap (func_at' b0 (@pair block Z b Z0)) a'), @ex ident (fun b1 : ident => and (@eq (option block) (@Map.get block (filter_genv (globalenv prog)) b1) (@Some block b)) (@ex funspec (fun fs : funspec => @eq (option funspec) (@PTree.get funspec b1 (make_tycontext_s G)) (@Some funspec fs))))))))))) *)
  intros n. specialize (H3 n).
(* Goal: @sig juicy_mem (fun jm : juicy_mem => and (@eq mem (m_dry jm) m) (and (@eq nat (@level rmap ag_rmap (m_phi jm)) n) (and (forall z : OK_ty, @jsafeN OK_ty OK_spec (globalenv prog) n z q jm) (and (no_locks (m_phi jm)) (and (matchfunspecs (globalenv prog) G (m_phi jm)) (and (forall (b : ident) (b0 : funspec) (a' : rmap) (_ : @necR rmap ag_rmap (m_phi jm) a') (_ : @eq (option funspec) (@PTree.get funspec b (make_tycontext_s G)) (@Some funspec b0)), @ex block (fun b1 : block => and (@eq (option block) (@Map.get block (filter_genv (globalenv prog)) b) (@Some block b1)) (@app_pred rmap ag_rmap (func_at b0 (@pair block Z b1 Z0)) a'))) (forall (b : block) (b0 : funspec) (a' : rmap) (_ : @necR rmap ag_rmap (m_phi jm) a') (_ : @app_pred rmap ag_rmap (func_at' b0 (@pair block Z b Z0)) a'), @ex ident (fun b1 : ident => and (@eq (option block) (@Map.get block (filter_genv (globalenv prog)) b1) (@Some block b)) (@ex funspec (fun fs : funspec => @eq (option funspec) (@PTree.get funspec b1 (make_tycontext_s G)) (@Some funspec fs))))))))))) *)
  subst OK_ty. specialize (H3 tt).
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
 destruct H3 as [jm [? [? ?]]]; exists jm; split3; auto.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
 destruct H1 as [? [? [? [? ?]]]]. split3; auto.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
 intro. destruct z. auto.
Qed.

(* Goal: @ex val (fun v : val => and (@eq (option val) (if ident_eq i p then @Some val (@fst val type a) else @Map.get val (make_tenv (temp_bindings (Pos.add p xH) (@map (prod val type) val (@fst val type) typed_args))) i) (@Some val v)) (tc_val' ty v)) *)
Definition Delta_types V G {C: compspecs} (tys : list type) : tycontext :=
  make_tycontext
    (params_of_types
       1 ((Tfunction (type_of_params (params_of_types 2 tys)) Tvoid cc_default) :: tys))
    nil nil Tvoid V G nil.

Lemma semax_prog_typecheck_aux_types:
(* Goal: @ex val (fun v : val => and (@eq (option val) (if ident_eq i p then @Some val (@fst val type a) else @Map.get val (make_tenv (temp_bindings (Pos.add p xH) (@map (prod val type) val (@fst val type) typed_args))) i) (@Some val v)) (tc_val' ty v)) *)
  forall vs G {C: compspecs} (prog: program) b (typed_args : list (val * type)),
   list_norepet (prog_defs_names prog) ->
   match_globvars (prog_vars prog) vs = true ->
   match_fdecs (prog_funct prog) G ->
   Forall (fun x => tc_val (snd x) (fst x)) typed_args ->
   typecheck_environ
     (Delta_types vs G (map snd typed_args))
     (construct_rho
        (filter_genv (globalenv prog)) empty_env
        (PTree.set 1 (Vptr b Ptrofs.zero)
                   (temp_bindings 2 (map fst typed_args)))).
Proof.
(* Goal: forall (vs : varspecs) (G : funspecs) (C : compspecs) (prog : program) (b : block) (typed_args : list (prod val type)) (_ : @list_norepet ident (@prog_defs_names (Ctypes.fundef function) type (@program_of_program function prog))) (_ : @eq bool (match_globvars (@initial_world.prog_vars function prog) vs) true) (_ : match_fdecs (@initial_world.prog_funct function prog) G) (_ : @Forall (prod val type) (fun x : prod val type => tc_val (@snd val type x) (@fst val type x)) typed_args), typecheck_environ (@Delta_types vs G C (@map (prod val type) type (@snd val type) typed_args)) (construct_rho (filter_genv (globalenv prog)) empty_env (@PTree.set val xH (Vptr b Ptrofs.zero) (temp_bindings (xO xH) (@map (prod val type) val (@fst val type) typed_args)))) *)
  intros vs G C prog b typed_args NR MG MF TYP.
(* Goal: and (var_sizes_ok (genv_cenv ge) (fn_vars f)) (and (@eq funsig fsig (fn_funsig f)) (@eq calling_convention (fn_callconv f) cc')) *)
(* Goal: @app_pred nat ag_nat (@allp nat ag_nat (list Type) (fun ts : list Type => @allp nat ag_nat (_functor (dependent_type_functor_rec ts A') (@pred rmap ag_rmap)) (fun x : _functor (dependent_type_functor_rec ts A') (@pred rmap ag_rmap) => @box nat ag_nat (@laterM nat ag_nat) (@semax' C Espec (func_tycontext' f (nofunc_tycontext V G)) (fun rho : environ => @andp rmap ag_rmap (@sepcon rmap Join_rmap Perm_rmap ag_rmap Age_rmap (bind_args (fn_params f) (fn_vars f) (P' ts x) rho) (stackframe_of' (genv_cenv ge) f rho)) (funassert (func_tycontext' f (nofunc_tycontext V G)) rho)) (Ssequence (fn_body f) (Sreturn (@None expr))) (frame_ret_assert (function_body_ret_assert (fn_return f) (Q' ts x)) (stackframe_of' (genv_cenv ge) f)))))) n *)
  repeat split.
  - unfold te_of, construct_rho.
(* Goal: typecheck_temp_environ (make_tenv (@PTree.set val xH (Vptr b Ptrofs.zero) (temp_bindings (xO xH) (@map (prod val type) val (@fst val type) typed_args)))) (temp_types (@Delta_types vs G C (@map (prod val type) type (@snd val type) typed_args))) *)
    intros i ty.
(* Goal: forall _ : @eq (option type) (@PTree.get type i (temp_types (@Delta_types vs G C (@map (prod val type) type (@snd val type) typed_args)))) (@Some type ty), @ex val (fun v : val => and (@eq (option val) (@Map.get val (make_tenv (@PTree.set val xH (Vptr b Ptrofs.zero) (temp_bindings (xO xH) (@map (prod val type) val (@fst val type) typed_args)))) i) (@Some val v)) (tc_val' ty v)) *)
    unfold make_tycontext, temp_types.
(* Goal: forall _ : @eq (option type) (@PTree.get type i match @Delta_types vs G C (@map (prod val type) type (@snd val type) typed_args) with | mk_tycontext a tyc_vars tyc_ret tyc_globty tyc_globsp tyc_annot => a end) (@Some type ty), @ex val (fun v : val => and (@eq (option val) (@Map.get val (make_tenv (@PTree.set val xH (Vptr b Ptrofs.zero) (temp_bindings (xO xH) (@map (prod val type) val (@fst val type) typed_args)))) i) (@Some val v)) (tc_val' ty v)) *)
    intros Found.
    assert (make_tycontext_t_cons1 : forall i i' t l1 l2, (make_tycontext_t ((i, t) :: l1) l2) ! i' =
      if peq i' i then Some t else (make_tycontext_t l1 l2) ! i')
    by (clear; intros i i' t l1 l2; simpl; rewrite PTree.gsspec; reflexivity).
(* Goal: @ex val (fun v : val => and (@eq (option val) (@Map.get val (make_tenv (@PTree.set val xH (Vptr b Ptrofs.zero) (temp_bindings (xO xH) (@map (prod val type) val (@fst val type) typed_args)))) i) (@Some val v)) (tc_val' ty v)) *)
    unfold Delta_types, make_tycontext in Found.
(* Goal: @ex val (fun v : val => and (@eq (option val) (@Map.get val (make_tenv (@PTree.set val xH (Vptr b Ptrofs.zero) (temp_bindings (xO xH) (@map (prod val type) val (@fst val type) typed_args)))) i) (@Some val v)) (tc_val' ty v)) *)
    simpl params_of_types in Found.
(* Goal: @ex val (fun v : val => and (@eq (option val) (@Map.get val (make_tenv (temp_bindings p (@map (prod val type) val (@fst val type) (@cons (prod val type) a typed_args)))) i) (@Some val v)) (tc_val' ty v)) *)
    rewrite make_tycontext_t_cons1 in Found.
    rewrite <-map_ptree_rel, Map.gsspec.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
    if_tac; if_tac in Found; subst; try tauto.
    + injection Found as <-.
(* Goal: and (@eq (option block) (@Some block loc') (@Some block loc')) (@ex funspec (fun fs : funspec => @eq (option funspec) (@PTree.get funspec i (make_tycontext_s G)) (@Some funspec fs))) *)
      exists (Vptr b Ptrofs.zero); split; auto.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
      apply tc_val_tc_val'; simpl; auto.
    + revert Found; generalize (2%positive).
(* Goal: forall (p : positive) (_ : @eq (option type) (@PTree.get type i (make_tycontext_t (params_of_types p (@map (prod val type) type (@snd val type) typed_args)) (@nil (prod ident type)))) (@Some type ty)), @ex val (fun v : val => and (@eq (option val) (@Map.get val (make_tenv (temp_bindings p (@map (prod val type) val (@fst val type) typed_args))) i) (@Some val v)) (tc_val' ty v)) *)
      induction typed_args; intros p Found.
      * rewrite PTree.gempty in Found.
(* Goal: @ex val (fun v : val => and (@eq (option val) (@Map.get val (make_tenv (temp_bindings p (@map (prod val type) val (@fst val type) (@nil (prod val type))))) i) (@Some val v)) (tc_val' ty v)) *)
        discriminate.
      * simpl (params_of_types _ _ ) in Found.
(* Goal: @ex val (fun v : val => and (@eq (option val) (@Map.get val (make_tenv (temp_bindings p (@map (prod val type) val (@fst val type) (@cons (prod val type) a typed_args)))) i) (@Some val v)) (tc_val' ty v)) *)
        rewrite make_tycontext_t_cons1 in Found.
(* Goal: @ex val (fun v : val => and (@eq (option val) (@Map.get val (make_tenv (temp_bindings p (@map (prod val type) val (@fst val type) (@cons (prod val type) a typed_args)))) i) (@Some val v)) (tc_val' ty v)) *)
        simpl (map _ _).
        change (exists v : val, Map.get (make_tenv (PTree.set p (fst a) (temp_bindings (p+1)
          (map fst typed_args)))) i = Some v /\ tc_val' ty v).
        rewrite <-map_ptree_rel, Map.gsspec.
(* Goal: @ex val (fun v : val => and (@eq (option val) (if ident_eq i p then @Some val (@fst val type a) else @Map.get val (make_tenv (temp_bindings (Pos.add p xH) (@map (prod val type) val (@fst val type) typed_args))) i) (@Some val v)) (tc_val' ty v)) *)
        inversion TYP.
(* Goal: @ex val (fun v : val => and (@eq (option val) (if ident_eq i p then @Some val (@fst val type a) else @Map.get val (make_tenv (temp_bindings (Pos.add p xH) (@map (prod val type) val (@fst val type) typed_args))) i) (@Some val v)) (tc_val' ty v)) *)
        { if_tac; if_tac in Found; subst; try tauto.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
          - injection Found as <-. apply tc_val_tc_val' in H3; eauto.
          - apply IHtyped_args; auto. }
(* Goal: forall _ : @ex block (fun v : block => @eq (option (prod block type)) (@Map.get (prod block type) (ve_of (construct_rho (filter_genv (globalenv prog)) empty_env (@PTree.set val xH (Vptr b Ptrofs.zero) (temp_bindings (xO xH) (@map (prod val type) val (@fst val type) typed_args))))) id) (@Some (prod block type) (@pair block type v ty))), @eq (option type) (@PTree.get type id (var_types (@Delta_types vs G C (@map (prod val type) type (@snd val type) typed_args)))) (@Some type ty) *)
  - simpl.
(* Goal: forall _ : @ex block (fun v : block => @eq (option (prod block type)) (@PTree.get (prod block type) id (PTree.empty (prod block type))) (@Some (prod block type) (@pair block type v ty))), @eq (option type) (@PTree.get type id (PTree.empty type)) (@Some type ty) *)
    rewrite PTree.gempty.
(* Goal: @ex val (fun v : val => and (@eq (option val) (@Map.get val (make_tenv (temp_bindings p (@map (prod val type) val (@fst val type) (@nil (prod val type))))) i) (@Some val v)) (tc_val' ty v)) *)
    intro; discriminate.
(* Goal: forall _ : @ex block (fun v : block => @eq (option (prod block type)) (@Map.get (prod block type) (ve_of (construct_rho (filter_genv (globalenv prog)) empty_env (@PTree.set val xH (Vptr b Ptrofs.zero) (temp_bindings (xO xH) (@map (prod val type) val (@fst val type) typed_args))))) id) (@Some (prod block type) (@pair block type v ty))), @eq (option type) (@PTree.get type id (var_types (@Delta_types vs G C (@map (prod val type) type (@snd val type) typed_args)))) (@Some type ty) *)
  - simpl.
(* Goal: forall _ : @ex block (fun v : block => @eq (option (prod block type)) (@Map.get (prod block type) (make_venv empty_env) id) (@Some (prod block type) (@pair block type v ty))), @eq (option type) (@PTree.get type id (PTree.empty type)) (@Some type ty) *)
    unfold make_venv, Map.get, empty_env.
(* Goal: forall _ : @ex block (fun v : block => @eq (option (prod block type)) (@PTree.get (prod block type) id (PTree.empty (prod block type))) (@Some (prod block type) (@pair block type v ty))), @eq (option type) (@PTree.get type id (PTree.empty type)) (@Some type ty) *)
    rewrite PTree.gempty.
(* Goal: @ex val (fun v : val => and (@eq (option val) (@Map.get val (make_tenv (temp_bindings p (@map (prod val type) val (@fst val type) (@nil (prod val type))))) i) (@Some val v)) (tc_val' ty v)) *)
    intros [? ?]; discriminate.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
  - eapply tc_ge_denote_initial; eauto.
Qed.

Lemma find_id_maketycontext_s G id : (make_tycontext_s G) ! id = find_id id G.
Proof.
(* Goal: forall _ : @ex block (fun v : block => @eq (option (prod block type)) (@Map.get (prod block type) (ve_of (construct_rho (filter_genv (globalenv prog)) empty_env (@PTree.set val xH (Vptr b Ptrofs.zero) (temp_bindings (xO xH) (@map (prod val type) val (@fst val type) typed_args))))) id) (@Some (prod block type) (@pair block type v ty))), @eq (option type) (@PTree.get type id (var_types (@Delta_types vs G C (@map (prod val type) type (@snd val type) typed_args)))) (@Some type ty) *)
  induction G as [|(i,t) G]; simpl.
  - destruct id; reflexivity.
  - rewrite PTree.gsspec.
(* Goal: @ex val (fun v : val => and (@eq (option val) (@PTree.get val id (PTree.empty val)) (@Some val v)) (tc_val' ty v)) *)
    do 2 if_tac; congruence.
Qed.

(* Goal: @ex val (fun v : val => and (@eq (option val) (if ident_eq i p then @Some val (@fst val type a) else @Map.get val (make_tenv (temp_bindings (Pos.add p xH) (@map (prod val type) val (@fst val type) typed_args))) i) (@Some val v)) (tc_val' ty v)) *)
Lemma semax_prog_entry_point {CS: compspecs} V G prog b id_fun id_arg arg A 
   (P Q: forall ts : list Type, (dependent_type_functor_rec ts (AssertTT A)) mpred)
   NEP NEQ h:
  @semax_prog CS prog V G ->
  Genv.find_symbol (globalenv prog) id_fun = Some b ->
  find_id id_fun G =
    Some (mk_funspec ((id_arg, Tpointer Tvoid noattr) :: nil, tptr Tvoid)
                     cc_default A P Q NEP NEQ) ->
  is_pointer_or_null arg ->
  (* initial environment *)
  let rho0 : environ :=
      construct_rho
        (filter_genv (globalenv prog)) empty_env
        (PTree.set 1 (Vptr b Ptrofs.zero)
                   (PTree.set id_arg arg (PTree.empty val))) in

  (* initial environment without the function => to check jm |= P a *)
  let rho1 : environ :=
      construct_rho
        (filter_genv (globalenv prog)) empty_env
        ((* PTree.set 1 (Vptr b Ptrofs.zero) *)
          (PTree.set id_arg arg (PTree.empty val))) in

(* Goal: @ex val (fun v : val => and (@eq (option val) (if ident_eq i p then @Some val (@fst val type a) else @Map.get val (make_tenv (temp_bindings (Pos.add p xH) (@map (prod val type) val (@fst val type) typed_args))) i) (@Some val v)) (tc_val' ty v)) *)
  { q : corestate |
    (forall jm, Val.inject (Mem.flat_inj (nextblock (m_dry jm))) arg arg ->
      exists jm', semantics.initial_core
      (juicy_core_sem (cl_core_sem (globalenv prog))) h
      jm q jm' (Vptr b Ptrofs.zero) (arg :: nil)) /\

    forall (jm : juicy_mem) ts a,
      app_pred (P ts a rho1) (m_phi jm) ->
(*      (forall rho, app_pred (! (Q ts a rho >=> !!False)) (m_phi jm)) ->*)
      app_pred (funassert (Delta_types V G (Tpointer Tvoid noattr::nil)) rho0) (m_phi jm) ->
      forall z, app_pred (ext_compat z) (m_phi jm) -> jsafeN (@OK_spec Espec) (globalenv prog) (level jm) z q jm }.
Proof.
  intros SP Findb id_in_G arg_p.
  destruct ((fun x => x) SP) as (_ & _ & _ & (MatchFdecs & Believe) & _).
  specialize (Believe (globalenv prog)).
  spec Believe. now apply prog_contains_prog_funct, compute_list_norepet_e, SP.
  spec Believe. now symmetry; apply SP.

  pose proof Believe as Believe_.
  specialize (Believe 5%nat).
  unfold claims in *.
  unfold nofunc_tycontext in *.
  simpl glob_specs in Believe.
  rewrite <-find_id_maketycontext_s in id_in_G.

  specialize (Believe (Vptr b Ptrofs.zero)
                      ((id_arg, Tpointer Tvoid noattr) :: nil, tptr Tvoid)
                      cc_default A P Q _ (necR_refl _)).
  spec Believe.
(* Goal: @ex val (fun v : val => and (@eq (option val) (if ident_eq i p then @Some val (@fst val type a) else @Map.get val (make_tenv (temp_bindings (Pos.add p xH) (@map (prod val type) val (@fst val type) typed_args))) i) (@Some val v)) (tc_val' ty v)) *)
  { exists id_fun, NEP, NEQ. split; auto. exists b; split; auto. }
  simpl (semantics.initial_core _). unfold j_initial_core.
  simpl (semantics.initial_core _). unfold cl_initial_core.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
  if_tac [_|?]. 2:tauto.

  destruct (Genv.find_funct_ptr (globalenv prog) b) as [f|] eqn:Eb; swap 1 2.
(* Goal: @ex val (fun v : val => and (@eq (option val) (if ident_eq i p then @Some val (@fst val type a) else @Map.get val (make_tenv (temp_bindings (Pos.add p xH) (@map (prod val type) val (@fst val type) typed_args))) i) (@Some val v)) (tc_val' ty v)) *)
  { exfalso.
    destruct Believe as [H | (b' & fu & (? & WOB & ASD) & WOBk)].
    unfold believe_external in *.
    unfold Genv.find_funct in *.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
    if_tac [_|?] in H. rewrite Eb in H. auto. tauto.
(* Goal: @ex val (fun v : val => and (@eq (option val) (@PTree.get val id (PTree.empty val)) (@Some val v)) (tc_val' ty v)) *)
    assert (b' = b) by congruence. subst b'. congruence.
  }
(* Goal: @ex val (fun v : val => and (@eq (option val) (if ident_eq i p then @Some val (@fst val type a) else @Map.get val (make_tenv (temp_bindings (Pos.add p xH) (@map (prod val type) val (@fst val type) typed_args))) i) (@Some val v)) (tc_val' ty v)) *)
  assert (Ef : type_of_fundef f = Tfunction (Tcons (Tpointer Tvoid noattr) Tnil) (tptr Tvoid) cc_default). {
    (* I think this can be proved using believe_internal / believe_external ? *)
    destruct Believe as [BE|BI].
    - unfold believe_external in *.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
      simpl in BE. if_tac [_|?] in BE. 2:tauto.
      replace (Genv.find_funct_ptr (globalenv prog)) with
      (Genv.find_funct_ptr (Genv.globalenv prog)) in *
        by reflexivity.
      unfold fundef in BE.
      rewrite Eb in BE.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
      destruct f as [ | ef sigargs sigret c'']. tauto.
(* Goal: forall _ : @ex block (fun v : block => @eq (option (prod block type)) (@Map.get (prod block type) (ve_of (construct_rho (filter_genv (globalenv prog)) empty_env (@PTree.set val xH (Vptr b Ptrofs.zero) (temp_bindings (xO xH) (@map (prod val type) val (@fst val type) typed_args))))) id) (@Some (prod block type) (@pair block type v ty))), @eq (option type) (@PTree.get type id (var_types (@Delta_types vs G C (@map (prod val type) type (@snd val type) typed_args)))) (@Some type ty) *)
      simpl.
(* Goal: @eq (option type) (@Some type (type_of_funspec fspec)) (@Some type t) *)
(* Goal: iff (@eq (option type) (@PTree.get type id (make_tycontext_g vs (@cons (prod ident funspec) (@pair ident funspec i fspec) G0))) (@Some type t)) (or (@ex funspec (fun f : funspec => and (@In (prod positive funspec) (@pair positive funspec id f) (@cons (prod ident funspec) (@pair ident funspec i fspec) G0)) (@eq type t (type_of_funspec f)))) (@In (prod positive type) (@pair positive type id t) vs)) *)
      destruct BE as [((Es & -> & ASD & LEN) & ?) _]. injection Es as Es <-. f_equal.
      destruct sigargs as [ | ? [ | ]]; simpl in Es.
(* Goal: @ex val (fun v : val => and (@eq (option val) (@PTree.get val id (PTree.empty val)) (@Some val v)) (tc_val' ty v)) *)
      + congruence.
(* Goal: @ex val (fun v : val => and (@eq (option val) (@PTree.get val id (PTree.empty val)) (@Some val v)) (tc_val' ty v)) *)
      + congruence.
      + (* in believe_external, zip_with_tl throws away arguments if they are not named *)
        simpl in LEN. disc.

    - destruct BI as (b' & fu & (? & WOB & ? & ? & ? & ? & wob & ?) & WOBk).
      unfold fn_funsig in *. injection wob as Hpar Hret.
(* Goal: @ex val (fun v : val => and (@eq (option val) (@PTree.get val id (PTree.empty val)) (@Some val v)) (tc_val' ty v)) *)
      assert (b' = b) by congruence. subst b'.
(* Goal: @ex val (fun v : val => and (@eq (option val) (@PTree.get val id (PTree.empty val)) (@Some val v)) (tc_val' ty v)) *)
      assert (f = Internal fu) by congruence. subst f.
(* Goal: forall _ : @ex block (fun v : block => @eq (option (prod block type)) (@Map.get (prod block type) (ve_of (construct_rho (filter_genv (globalenv prog)) empty_env (@PTree.set val xH (Vptr b Ptrofs.zero) (temp_bindings (xO xH) (@map (prod val type) val (@fst val type) typed_args))))) id) (@Some (prod block type) (@pair block type v ty))), @eq (option type) (@PTree.get type id (var_types (@Delta_types vs G C (@map (prod val type) type (@snd val type) typed_args)))) (@Some type ty) *)
      simpl.
(* Goal: @eq type (type_of_function f) (Tfunction (type_of_params (fn_params f)) (fn_return f) cc) *)
(* Goal: forall (ge : genv) (_ : prog_contains ge (@cons (prod ident (Ctypes.fundef function)) (@pair ident (Ctypes.fundef function) id (@Internal function f)) fs)) (_ : @eq composite_env (genv_cenv ge) (@cenv_cs C)) (n : nat), @app_pred nat ag_nat (@believe C Espec (nofunc_tycontext V G) ge (nofunc_tycontext V (@cons (prod ident funspec) (@pair ident funspec id (mk_funspec (fn_funsig f) cc A P Q NEP NEQ)) G'))) n *)
      unfold type_of_function.
      destruct fu as [? ? [ | [] [ | [] ]] ? ?]; simpl in *; congruence.
  }
  rewrite Ef.
(* Goal: and (var_sizes_ok (genv_cenv ge) (fn_vars f)) (and (@eq funsig fsig (fn_funsig f)) (@eq calling_convention (fn_callconv f) cc')) *)
(* Goal: @app_pred nat ag_nat (@allp nat ag_nat (list Type) (fun ts : list Type => @allp nat ag_nat (_functor (dependent_type_functor_rec ts A') (@pred rmap ag_rmap)) (fun x : _functor (dependent_type_functor_rec ts A') (@pred rmap ag_rmap) => @box nat ag_nat (@laterM nat ag_nat) (@semax' C Espec (func_tycontext' f (nofunc_tycontext V G)) (fun rho : environ => @andp rmap ag_rmap (@sepcon rmap Join_rmap Perm_rmap ag_rmap Age_rmap (bind_args (fn_params f) (fn_vars f) (P' ts x) rho) (stackframe_of' (genv_cenv ge) f rho)) (funassert (func_tycontext' f (nofunc_tycontext V G)) rho)) (Ssequence (fn_body f) (Sreturn (@None expr))) (frame_ret_assert (function_body_ret_assert (fn_return f) (Q' ts x)) (stackframe_of' (genv_cenv ge) f)))))) n *)
  eexists. split.
(* Goal: forall (id : positive) (ty : type), iff (@eq (option type) (@PTree.get type id (make_tycontext_v (@nil (prod ident type)))) (@Some type ty)) (@ex block (fun v : block => @eq (option (prod block type)) (@Map.get (prod block type) (make_venv empty_env) id) (@Some (prod block type) (@pair block type v ty)))) *)
  intros. eexists; repeat split; eauto.
(* Goal: @list_norepet ident (@map (prod ident fundef) ident (@fst ident fundef) (@prog_funct' (Ctypes.fundef function) type (@nil (prod ident (globdef (Ctypes.fundef function) type))))) *)
(* Goal: @list_norepet ident (@map (prod ident fundef) ident (@fst ident fundef) (@prog_funct' (Ctypes.fundef function) type (@cons (prod ident (globdef (Ctypes.fundef function) type)) a l))) *)
(* Goal: @ex block (fun b : block => @eq (option block) (@Map.get block (@Genv.find_symbol fundef type (genv_genv (globalenv prog))) id) (@Some block b)) *)
  repeat constructor.
(* Goal: @ex val (fun v : val => and (@eq (option val) (if ident_eq i p then @Some val (@fst val type a) else @Map.get val (make_tenv (temp_bindings (Pos.add p xH) (@map (prod val type) val (@fst val type) typed_args))) i) (@Some val v)) (tc_val' ty v)) *)
  {clear - arg_p.
(* Goal: @eq (option type) (@None type) (@Some type t) *)
   destruct arg; try contradiction.
   first [apply val_casted_long_ptr |  apply val_casted_int_ptr]; reflexivity.
   apply val_casted_ptr_ptr. }
(* Goal: @ex val (fun v : val => and (@eq (option val) (if ident_eq i p then @Some val (@fst val type a) else @Map.get val (make_tenv (temp_bindings (Pos.add p xH) (@map (prod val type) val (@fst val type) typed_args))) i) (@Some val v)) (tc_val' ty v)) *)
  { clear - arg_p. destruct arg; try contradiction; simpl in *.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
      unfold Tptr. destruct Archi.ptr64; try contradiction; auto.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
      unfold Tptr. destruct Archi.ptr64; auto.
  }
(* Goal: @ex val (fun v : val => and (@eq (option val) (if ident_eq i p then @Some val (@fst val type a) else @Map.get val (make_tenv (temp_bindings (Pos.add p xH) (@map (prod val type) val (@fst val type) typed_args))) i) (@Some val v)) (tc_val' ty v)) *)
  { unfold arg_well_formed. constructor; auto. } 

  intros jm ts a m_sat_Pa m_funassert.

  assert (Pf : params_of_fundef f = Tpointer Tvoid noattr :: nil).
(* Goal: @ex val (fun v : val => and (@eq (option val) (if ident_eq i p then @Some val (@fst val type a) else @Map.get val (make_tenv (temp_bindings (Pos.add p xH) (@map (prod val type) val (@fst val type) typed_args))) i) (@Some val v)) (tc_val' ty v)) *)
  { clear -Ef.
    destruct f as [f|f]. simpl in *.
    unfold type_of_function in *.
    destruct f as [? ? [ | [] [ | [] ]] ? ?]; simpl in *; congruence.
    simpl in *. injection Ef; intros; subst. reflexivity. }

  pose (rho3 :=
          construct_rho
            (filter_genv (globalenv prog)) empty_env
            (PTree.set 1 (Vptr b Ptrofs.zero)
                       (temp_bindings 2 (map fst ((arg, Tpointer Tvoid noattr) :: nil))))).
(* Goal: @app_pred nat ag_nat (@box nat ag_nat (@laterM nat ag_nat) (@semax' C Espec (func_tycontext' f (nofunc_tycontext V G)) (fun rho : environ => @andp rmap ag_rmap (@sepcon rmap Join_rmap Perm_rmap ag_rmap Age_rmap (bind_args (fn_params f) (fn_vars f) (P ts x) rho) (stackframe_of' (genv_cenv ge) f rho)) (funassert (func_tycontext' f (nofunc_tycontext V G)) rho)) (Ssequence (fn_body f) (Sreturn (@None expr))) (frame_ret_assert (function_body_ret_assert (fn_return f) (Q ts x)) (stackframe_of' (genv_cenv ge) f)))) n *)
  pose proof I.
  intros z Hz.
  evar (R : environ -> mpred).
  eapply
    (semax_call_aux
       (Delta_types V G (Tpointer Tvoid noattr::nil)) A P
       (fun _ _ => Q ts a) Q NEP NEQ
       ts a (fun _ => emp) (fun _ => emp)
       None ((id_arg, Tpointer Tvoid noattr)::nil, tptr Tvoid) cc_default _ _
       (normal_ret_assert R)
       _ _ _ _ rho3
       _ _ b id_fun);
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
    try apply H3; try eassumption; auto.

  (* tc_expr *)

(* Goal: forall _ : @ex block (fun v : block => @eq (option (prod block type)) (@Map.get (prod block type) (ve_of (construct_rho (filter_genv (globalenv prog)) empty_env (@PTree.set val xH (Vptr b Ptrofs.zero) (temp_bindings (xO xH) (@map (prod val type) val (@fst val type) typed_args))))) id) (@Some (prod block type) (@pair block type v ty))), @eq (option type) (@PTree.get type id (var_types (@Delta_types vs G C (@map (prod val type) type (@snd val type) typed_args)))) (@Some type ty) *)
  simpl. exists (Vptr b Ptrofs.zero); auto.

  (* tc_exprlist *)
(* Goal: forall _ : @ex block (fun v : block => @eq (option (prod block type)) (@Map.get (prod block type) (ve_of (construct_rho (filter_genv (globalenv prog)) empty_env (@PTree.set val xH (Vptr b Ptrofs.zero) (temp_bindings (xO xH) (@map (prod val type) val (@fst val type) typed_args))))) id) (@Some (prod block type) (@pair block type v ty))), @eq (option type) (@PTree.get type id (var_types (@Delta_types vs G C (@map (prod val type) type (@snd val type) typed_args)))) (@Some type ty) *)
  rewrite Pf. simpl. exists arg; simpl; auto.

  (* guard_environ *)
  split; try apply I.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
  eapply semax_prog_typecheck_aux_types; eauto.
  apply compute_list_norepet_e. apply SP. apply SP.

  (* closed_wrt_modvars *)
(* Goal: forall z : unit, @jsafeN unit OK_spec (globalenv prog) n z q jm *)
  intro.
  reflexivity.

  (* equality of normal_ret_assert *)
  unfold R.
(* Goal: forall _ : @ex block (fun v : block => @eq (option (prod block type)) (@Map.get (prod block type) (ve_of (construct_rho (filter_genv (globalenv prog)) empty_env (@PTree.set val xH (Vptr b Ptrofs.zero) (temp_bindings (xO xH) (@map (prod val type) val (@fst val type) typed_args))))) id) (@Some (prod block type) (@pair block type v ty))), @eq (option type) (@PTree.get type id (var_types (@Delta_types vs G C (@map (prod val type) type (@snd val type) typed_args)))) (@Some type ty) *)
  unfold normal_ret_assert; simpl.
  extensionality rho'.
  normalize.
  reflexivity.

  (* globalenv prog = cenv_cs *)
  destruct SP as [? [AL [HGG [[H2 H3] [GV _]]]]].
(* Goal: @app_pred nat ag_nat (@semax' C Espec (func_tycontext' f (nofunc_tycontext V G)) (fun rho : environ => @andp rmap ag_rmap (@sepcon rmap Join_rmap Perm_rmap ag_rmap Age_rmap (bind_args (fn_params f) (fn_vars f) (P ts x) rho) (stackframe_of' (genv_cenv ge) f rho)) (funassert (func_tycontext' f (nofunc_tycontext V G)) rho)) (Ssequence (fn_body f) (Sreturn (@None expr))) (frame_ret_assert (function_body_ret_assert (fn_return f) (Q ts x)) (stackframe_of' (genv_cenv ge) f))) n *)
  rewrite HGG. reflexivity.

  (* safety: we conclude as we add an infinite loop at the end *)
  intros ek ret te env phi lev phi' necr [[Guard FrameRA] FunAssert].
  apply own.bupd_intro; intros ora jm0 Hora Heq <-.
  rewrite proj_frame_ret_assert in FrameRA. simpl seplog.sepcon in FrameRA.
  destruct ek; simpl proj_ret_assert in FrameRA;
   try solve [elimtype False; clear - FrameRA; destruct FrameRA as [? [? [? [[? ?] ?]]]]; contradiction];
   try solve [elimtype False; clear - FrameRA; destruct FrameRA as [? [? [? [? ?]]]]; contradiction].
   apply safe_loop_skip.
  (* equivalence between Q and Q' *)
  intros vl; split; apply derives_imp; apply derives_refl'; reflexivity.

  (* precondition *)
  refine (derives_e _ _ _ _ m_sat_Pa).
  normalize.
  eapply derives_trans; [|apply now_later].
(* Goal: @eq (option type) (@Some type (type_of_funspec fspec)) (@Some type t) *)
(* Goal: iff (@eq (option type) (@PTree.get type id (make_tycontext_g vs (@cons (prod ident funspec) (@pair ident funspec i fspec) G0))) (@Some type t)) (or (@ex funspec (fun f : funspec => and (@In (prod positive funspec) (@pair positive funspec id f) (@cons (prod ident funspec) (@pair ident funspec i fspec) G0)) (@eq type t (type_of_funspec f)))) (@In (prod positive type) (@pair positive type id t) vs)) *)
  apply derives_refl'; f_equal.
  rewrite Pf.
(* Goal: forall _ : @ex block (fun v : block => @eq (option (prod block type)) (@Map.get (prod block type) (ve_of (construct_rho (filter_genv (globalenv prog)) empty_env (@PTree.set val xH (Vptr b Ptrofs.zero) (temp_bindings (xO xH) (@map (prod val type) val (@fst val type) typed_args))))) id) (@Some (prod block type) (@pair block type v ty))), @eq (option type) (@PTree.get type id (var_types (@Delta_types vs G C (@map (prod val type) type (@snd val type) typed_args)))) (@Some type ty) *)
  simpl.
  unfold globals_only, env_set, construct_rho.
(* Goal: forall _ : @ex block (fun v : block => @eq (option (prod block type)) (@Map.get (prod block type) (ve_of (construct_rho (filter_genv (globalenv prog)) empty_env (@PTree.set val xH (Vptr b Ptrofs.zero) (temp_bindings (xO xH) (@map (prod val type) val (@fst val type) typed_args))))) id) (@Some (prod block type) (@pair block type v ty))), @eq (option type) (@PTree.get type id (var_types (@Delta_types vs G C (@map (prod val type) type (@snd val type) typed_args)))) (@Some type ty) *)
  simpl.
(* Goal: @eq (option type) (@Some type (type_of_funspec fspec)) (@Some type t) *)
(* Goal: iff (@eq (option type) (@PTree.get type id (make_tycontext_g vs (@cons (prod ident funspec) (@pair ident funspec i fspec) G0))) (@Some type t)) (or (@ex funspec (fun f : funspec => and (@In (prod positive funspec) (@pair positive funspec id f) (@cons (prod ident funspec) (@pair ident funspec i fspec) G0)) (@eq type t (type_of_funspec f)))) (@In (prod positive type) (@pair positive type id t) vs)) *)
  f_equal.
  extensionality i; destruct i; reflexivity.
  unfold make_tenv, force_val, sem_cast_pointer, eval_id.
  extensionality i.
(* Goal: @eq (option funspec) (@PTree.get funspec id (@ptree_set funspec i t (make_tycontext_s G))) (if @eq_dec ident EqDec_ident id i then @Some funspec t else find_id id G) *)
  rewrite PTree.gsspec.
  unfold Map.set.
(* Goal: @In ident i (@map (prod ident (globvar type)) ident (@fst ident (globvar type)) vl) *)
(* Goal: iff (@eq (option type) (@PTree.get type id (make_tycontext_g vs (@cons (prod ident funspec) (@pair ident funspec i fspec) G0))) (@Some type t)) (or (@ex funspec (fun f : funspec => and (@In (prod positive funspec) (@pair positive funspec id f) (@cons (prod ident funspec) (@pair ident funspec i fspec) G0)) (@eq type t (type_of_funspec f)))) (@In (prod positive type) (@pair positive type id t) vs)) *)
  if_tac; if_tac; try congruence; subst.
(* Goal: forall _ : @ex block (fun v : block => @eq (option (prod block type)) (@Map.get (prod block type) (ve_of (construct_rho (filter_genv (globalenv prog)) empty_env (@PTree.set val xH (Vptr b Ptrofs.zero) (temp_bindings (xO xH) (@map (prod val type) val (@fst val type) typed_args))))) id) (@Some (prod block type) (@pair block type v ty))), @eq (option type) (@PTree.get type id (var_types (@Delta_types vs G C (@map (prod val type) type (@snd val type) typed_args)))) (@Some type ty) *)
  unfold liftx, lift; simpl.
(* Goal: @jsafeN unit OK_spec (globalenv prog) n tt q jm *)
  now destruct arg; inversion arg_p; auto.
  now destruct i; reflexivity.
Qed.

End semax_prog.
