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 * 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. *)

(* Specifications: *)
Lemma match_fdecs_exists_Gfun:
forall prog G i f,
find_id i G = Some f ->
match_fdecs (prog_funct prog) G ->
exists fd,   In (i, Gfun fd) (prog_defs prog) /\
type_of_fundef fd = type_of_funspec f.
(*Specializations of stuff in initial_world: (*Partial attempt at porting add_globales_hack*)
Lemma add_globals_hack_nil:
forall gev prog_pub,
gev = Genv.add_globals (Genv.empty_genv fundef type prog_pub) (rev nil) ->
forall id, Genv.find_symbol gev id = None.
Lemma add_globals_hack_single:
forall v gev prog_pub,
gev = Genv.add_globals (Genv.empty_genv fundef type prog_pub) (cons v nil) ->
forall id b, (Genv.find_symbol gev id = Some b <-> fst v = id /\ b = 1%positive).
Lemma add_globals_hack:
forall vl gev prog_pub,
list_norepet (map fst vl) ->
gev = Genv.add_globals (Genv.empty_genv fundef type prog_pub) (rev vl) ->
(forall id b, 0 <= Zpos b - 1 < Zlength vl ->
(Genv.find_symbol gev id = Some b <->
nth_error (map (@fst _ _) vl) (length vl - Pos.to_nat b)  = Some id)).
Lemma find_symbol_globalenv:
forall (prog: program) i b,
list_norepet (prog_defs_names prog) ->
Genv.find_symbol (Genv.globalenv prog) i = Some b ->
0 < Z.pos b <= Z_of_nat (length (prog_defs prog)) /\
exists d, nth_error (prog_defs prog) (nat_of_Z (Z.pos b-1)) = Some (i,d).
Lemma initial_core_ok: forall (prog: program) G n m,
list_norepet (prog_defs_names prog) ->
match_fdecs (prog_funct prog) G ->
Genv.init_mem prog = Some m ->
initial_rmap_ok m (initial_core (Genv.globalenv prog) G n).