Definition init_mem (p: program F V) :=
  alloc_globals (globalenv p) Mem.empty p.(prog_defs).

(* Specifications: *)
Lemma init_mem_genv_next: forall p m, init_mem p = Some m -> genv_next (globalenv p) = Mem.nextblock m.
Theorem find_symbol_not_fresh: forall p id b m, init_mem p = Some m -> find_symbol (globalenv p) id = Some b -> Mem.valid_block m b.
Theorem find_def_not_fresh: forall p b g m, init_mem p = Some m -> find_def (globalenv p) b = Some g -> Mem.valid_block m b.
Theorem find_funct_ptr_not_fresh: forall p b f m, init_mem p = Some m -> find_funct_ptr (globalenv p) b = Some f -> Mem.valid_block m b.
Theorem find_var_info_not_fresh: forall p b gv m, init_mem p = Some m -> find_var_info (globalenv p) b = Some gv -> Mem.valid_block m b.
Lemma init_mem_characterization_gen: forall p m, init_mem p = Some m -> globals_initialized (globalenv p) (globalenv p) m.
Theorem init_mem_characterization: forall p b gv m, find_var_info (globalenv p) b = Some gv -> init_mem p = Some m -> Mem.range_perm m b 0 (init_data_list_size gv.(gvar_init)) Cur (perm_globvar gv) /\ (forall ofs k p, Mem.perm m b ofs k p -> 0 <= ofs < init_data_list_size gv.(gvar_init) /\ perm_order (perm_globvar gv) p) /\ (gv.(gvar_volatile) = false -> load_store_init_data (globalenv p) m b 0 gv.(gvar_init)) /\ (gv.(gvar_volatile) = false -> Mem.loadbytes m b 0 (init_data_list_size gv.(gvar_init)) = Some (bytes_of_init_data_list (globalenv p) gv.(gvar_init))).
Theorem init_mem_characterization_2: forall p b fd m, find_funct_ptr (globalenv p) b = Some fd -> init_mem p = Some m -> Mem.perm m b 0 Cur Nonempty /\ (forall ofs k p, Mem.perm m b ofs k p -> ofs = 0 /\ p = Nonempty).
Lemma store_zeros_neutral: forall m b p n m', Mem.inject_neutral thr m -> Plt b thr -> store_zeros m b p n = Some m' -> Mem.inject_neutral thr m'.
Lemma store_init_data_neutral: forall m b p id m', Mem.inject_neutral thr m -> Plt b thr -> store_init_data ge m b p id = Some m' -> Mem.inject_neutral thr m'.
Lemma store_init_data_list_neutral: forall b idl m p m', Mem.inject_neutral thr m -> Plt b thr -> store_init_data_list ge m b p idl = Some m' -> Mem.inject_neutral thr m'.
Lemma alloc_global_neutral: forall idg m m', alloc_global ge m idg = Some m' -> Mem.inject_neutral thr m -> Plt (Mem.nextblock m) thr -> Mem.inject_neutral thr m'.
Lemma init_mem_genv_next: forall p m, init_mem p = Some m -> genv_next (globalenv p) = Mem.nextblock m.
Theorem find_symbol_not_fresh: forall p id b m, init_mem p = Some m -> find_symbol (globalenv p) id = Some b -> Mem.valid_block m b.
Theorem find_def_not_fresh: forall p b g m, init_mem p = Some m -> find_def (globalenv p) b = Some g -> Mem.valid_block m b.
Theorem find_funct_ptr_not_fresh: forall p b f m, init_mem p = Some m -> find_funct_ptr (globalenv p) b = Some f -> Mem.valid_block m b.
Theorem find_var_info_not_fresh: forall p b gv m, init_mem p = Some m -> find_var_info (globalenv p) b = Some gv -> Mem.valid_block m b.
Lemma init_mem_characterization_gen: forall p m, init_mem p = Some m -> globals_initialized (globalenv p) (globalenv p) m.
Theorem init_mem_characterization: forall p b gv m, find_var_info (globalenv p) b = Some gv -> init_mem p = Some m -> Mem.range_perm m b 0 (init_data_list_size gv.(gvar_init)) Cur (perm_globvar gv) /\ (forall ofs k p, Mem.perm m b ofs k p -> 0 <= ofs < init_data_list_size gv.(gvar_init) /\ perm_order (perm_globvar gv) p) /\ (gv.(gvar_volatile) = false -> load_store_init_data (globalenv p) m b 0 gv.(gvar_init)) /\ (gv.(gvar_volatile) = false -> Mem.loadbytes m b 0 (init_data_list_size gv.(gvar_init)) = Some (bytes_of_init_data_list (globalenv p) gv.(gvar_init))).
Theorem init_mem_characterization_2: forall p b fd m, find_funct_ptr (globalenv p) b = Some fd -> init_mem p = Some m -> Mem.perm m b 0 Cur Nonempty /\ (forall ofs k p, Mem.perm m b ofs k p -> ofs = 0 /\ p = Nonempty).
Lemma store_zeros_neutral: forall m b p n m', Mem.inject_neutral thr m -> Plt b thr -> store_zeros m b p n = Some m' -> Mem.inject_neutral thr m'.
Lemma store_init_data_neutral: forall m b p id m', Mem.inject_neutral thr m -> Plt b thr -> store_init_data ge m b p id = Some m' -> Mem.inject_neutral thr m'.
Lemma store_init_data_list_neutral: forall b idl m p m', Mem.inject_neutral thr m -> Plt b thr -> store_init_data_list ge m b p idl = Some m' -> Mem.inject_neutral thr m'.
Lemma alloc_global_neutral: forall idg m m', alloc_global ge m idg = Some m' -> Mem.inject_neutral thr m -> Plt (Mem.nextblock m) thr -> Mem.inject_neutral thr m'.