Require Export VST.veric.initial_world.
Local Open Scope pred.
Obligation Tactic := idtac.
(* Definition initial_core' (ge: Genv.t fundef type) (G: funspecs) (n: nat) (loc: address) : resource := if Z.eq_dec (snd loc) 0 then match Genv.invert_symbol ge (fst loc) with | Some id => match find_id id G with | Some (mk_funspec fsig cc A P Q _ _) => PURE (FUN fsig cc) (SomeP (SpecTT A) (fun ts => fmap _ (approx n) (approx n) (packPQ P Q ts))) | None => NO Share.bot bot_unreadable end | None => NO Share.bot bot_unreadable end else NO Share.bot bot_unreadable.*)
Notation initial_core' := (initial_core' function).
(* This version starts with an empty ghost. Program Definition initial_core (ge: Genv.t fundef type) (G: funspecs) (n: nat): rmap := proj1_sig (make_rmap (initial_core' ge G n) nil n _ eq_refl). Next Obligation. intros. extensionality loc; unfold compose, initial_core'. if_tac; [ | simpl; auto]. destruct (Genv.invert_symbol ge (fst loc)); [ | simpl; auto]. destruct (find_id i G); [ | simpl; auto]. destruct f. unfold resource_fmap. f_equal. simpl. f_equal. change R.approx with approx. extensionality i0 ts b rho. rewrite fmap_app. pattern (approx n) at 7 8 9. rewrite <- approx_oo_approx. auto. Qed.*)
Notation initial_core := (@initial_core function).
(* Program Definition initial_core_ext {Z} (ora : Z) (ge: Genv.t fundef type) (G: funspecs) (n: nat): rmap := proj1_sig (make_rmap (initial_core' ge G n) (Some (ext_ghost ora, NoneP) :: nil) n _ eq_refl). Next Obligation. intros. extensionality loc; unfold compose, initial_core'. if_tac; [ | simpl; auto]. destruct (Genv.invert_symbol ge (fst loc)); [ | simpl; auto]. destruct (find_id i G); [ | simpl; auto]. destruct f. unfold resource_fmap. f_equal. simpl. f_equal. change R.approx with approx. extensionality i0 ts b rho. rewrite fmap_app. pattern (approx n) at 7 8 9. rewrite <- approx_oo_approx. auto. Qed. *)
Notation initial_core_ext := (@initial_core_ext  function).
(*Definition prog_funct (p: program) := prog_funct' (prog_defs p).*)
Notation prog_funct := (@prog_funct function).
Inductive match_fdecs: list  (ident * Clight.fundef) -> funspecs -> Prop :=
| match_fdecs_nil: match_fdecs nil nil
| match_fdecs_cons: forall i fd fspec fs G,
type_of_fundef fd = type_of_funspec fspec ->
match_fdecs fs G ->
match_fdecs ((i,fd)::fs) ((i,fspec)::G)
(* EXPERIMENT | match_fdecs_skip: forall ifd fs G, match_fdecs fs G -> match_fdecs (ifd::fs) G*)
.
(* Fixpoint match_fdecs (fdecs: list (ident * fundef)) (G: funspecs) := match fdecs, G with | _, nil => True | (i,fd)::f', (j,fspec)::G' => i=j /\ type_of_fundef fd = type_of_funspec fspec /\ match_fdecs f' G' \/ match_fdecs f' G | nil, _::_ => False end. *)
(* Definition match_fdecs (fdecs: list (ident * fundef)) (G: funspecs) := map (fun idf => (fst idf, Clight.type_of_fundef (snd idf))) fdecs = map (fun idf => (fst idf, type_of_funspec (snd idf))) G. *)
Definition initial_jm (prog: program) m (G: funspecs) (n: nat)
(H: Genv.init_mem prog = Some m)
(H1: list_norepet (prog_defs_names prog))
(H2: match_fdecs (prog_funct prog) G) : juicy_mem :=
initial_mem m (initial_core (Genv.globalenv prog) G n)
(initial_core_ok _ _ _ m H1 H2 H).
Definition initial_jm_ext {Z} (ora : Z) (prog: program) m (G: funspecs) (n: nat)
(H: Genv.init_mem prog = Some m)
(H1: list_norepet (prog_defs_names prog))
(H2: match_fdecs (prog_funct prog) G) : juicy_mem :=
initial_mem m (initial_core_ext ora (Genv.globalenv prog) G n)
(initial_core_ext_ok _ _ _ _ m H1 H2 H).

Lemma initial_jm_ext_eq : forall {Z} (ora : Z) (prog: program) m (G: funspecs) (n: nat)
(H: Genv.init_mem prog = Some m)
(H1: list_norepet (prog_defs_names prog))
(H2: match_fdecs (prog_funct prog) G),
join (m_phi (initial_jm prog m G n H H1 H2))
(set_ghost (core (m_phi (initial_jm prog m G n H H1 H2))) (Some (ext_ghost ora, NoneP) :: nil) eq_refl)
(m_phi (initial_jm_ext ora prog m G n H H1 H2)).