(** ** Sufficient and necessary conditions for the initial memory to exist. *)

(** Alignment properties *)

Definition init_data_alignment (i: init_data) : Z :=
  match i with
  | Init_int8 n => 1
  | Init_int16 n => 2
  | Init_int32 n => 4
  | Init_int64 n => 8
  | Init_float32 n => 4
  | Init_float64 n => 4
  | Init_addrof symb ofs => if Archi.ptr64 then 8 else 4
  | Init_space n => 1
  end.

(* Specifications: *)
Lemma store_init_data_list_aligned: forall b il m p m', store_init_data_list ge m b p il = Some m' -> init_data_list_aligned p il.
Lemma store_init_data_list_free_idents: forall b i o il m p m', store_init_data_list ge m b p il = Some m' -> In (Init_addrof i o) il -> exists b', find_symbol ge i = Some b'.
Theorem init_mem_inversion: forall p m id v, init_mem p = Some m -> In (id, Gvar v) p.(prog_defs) -> init_data_list_aligned 0 v.(gvar_init) /\ forall i o, In (Init_addrof i o) v.(gvar_init) -> exists b, find_symbol (globalenv p) i = Some b.
Lemma store_zeros_exists: forall m b p n, Mem.range_perm m b p (p + n) Cur Writable -> exists m', store_zeros m b p n = Some m'.
Lemma store_init_data_list_exists: forall b il m p, Mem.range_perm m b p (p + init_data_list_size il) Cur Writable -> init_data_list_aligned p il -> (forall id ofs, In (Init_addrof id ofs) il -> exists b, find_symbol ge id = Some b) -> exists m', store_init_data_list ge m b p il = Some m'.
Lemma alloc_global_exists: forall m idg, match idg with | (id, Gfun f) => True | (id, Gvar v) => init_data_list_aligned 0 v.(gvar_init) /\ forall i o, In (Init_addrof i o) v.(gvar_init) -> exists b, find_symbol ge i = Some b end -> exists m', alloc_global ge m idg = Some m'.
Theorem init_mem_exists: forall p, (forall id v, In (id, Gvar v) (prog_defs p) -> init_data_list_aligned 0 v.(gvar_init) /\ forall i o, In (Init_addrof i o) v.(gvar_init) -> exists b, find_symbol (globalenv p) i = Some b) -> exists m, init_mem p = Some m.
Lemma store_init_data_list_aligned: forall b il m p m', store_init_data_list ge m b p il = Some m' -> init_data_list_aligned p il.
Lemma store_init_data_list_free_idents: forall b i o il m p m', store_init_data_list ge m b p il = Some m' -> In (Init_addrof i o) il -> exists b', find_symbol ge i = Some b'.
Theorem init_mem_inversion: forall p m id v, init_mem p = Some m -> In (id, Gvar v) p.(prog_defs) -> init_data_list_aligned 0 v.(gvar_init) /\ forall i o, In (Init_addrof i o) v.(gvar_init) -> exists b, find_symbol (globalenv p) i = Some b.
Lemma store_zeros_exists: forall m b p n, Mem.range_perm m b p (p + n) Cur Writable -> exists m', store_zeros m b p n = Some m'.
Lemma store_init_data_list_exists: forall b il m p, Mem.range_perm m b p (p + init_data_list_size il) Cur Writable -> init_data_list_aligned p il -> (forall id ofs, In (Init_addrof id ofs) il -> exists b, find_symbol ge id = Some b) -> exists m', store_init_data_list ge m b p il = Some m'.
Lemma alloc_global_exists: forall m idg, match idg with | (id, Gfun f) => True | (id, Gvar v) => init_data_list_aligned 0 v.(gvar_init) /\ forall i o, In (Init_addrof i o) v.(gvar_init) -> exists b, find_symbol ge i = Some b end -> exists m', alloc_global ge m idg = Some m'.
Theorem init_mem_exists: forall p, (forall id v, In (id, Gvar v) (prog_defs p) -> init_data_list_aligned 0 v.(gvar_init) /\ forall i o, In (Init_addrof i o) v.(gvar_init) -> exists b, find_symbol (globalenv p) i = Some b) -> exists m, init_mem p = Some m.