(** ** Coercing a global environment into a symbol environment *)
Definition to_senv (ge: t) : Senv.t :=
@Senv.mksenv
(find_symbol ge)
(public_symbol ge)
(invert_symbol ge)
(block_is_volatile ge)
ge.(genv_next)
ge.(genv_vars_inj)
(invert_find_symbol ge)
(find_invert_symbol ge)
(public_symbol_exists ge)
ge.(genv_symb_range)
(block_is_volatile_below ge).
(** * Construction of the initial memory state *)
Section INITMEM.
Variable ge: t.
Definition store_init_data (m: mem) (b: block) (p: Z) (id: init_data) : option mem :=
match id with
| Init_int8 n => Mem.store Mint8unsigned m b p (Vint n)
| Init_int16 n => Mem.store Mint16unsigned m b p (Vint n)
| Init_int32 n => Mem.store Mint32 m b p (Vint n)
| Init_int64 n => Mem.store Mint64 m b p (Vlong n)
| Init_float32 n => Mem.store Mfloat32 m b p (Vsingle n)
| Init_float64 n => Mem.store Mfloat64 m b p (Vfloat n)
| Init_addrof symb ofs =>
match find_symbol ge symb with
| None => None
| Some b' => Mem.store Mptr m b p (Vptr b' ofs)
end
| Init_space n => Some m
end.
Fixpoint store_init_data_list (m: mem) (b: block) (p: Z) (idl: list init_data)
{struct idl}: option mem :=
match idl with
| nil => Some m
| id :: idl' =>
match store_init_data m b p id with
| None => None
| Some m' => store_init_data_list m' b (p + init_data_size id) idl'
end
end.
Definition perm_globvar (gv: globvar V) : permission :=
if gv.(gvar_volatile) then Nonempty
else if gv.(gvar_readonly) then Readable
else Writable.
Definition alloc_global (m: mem) (idg: ident * globdef F V): option mem :=
match idg with
| (id, Gfun f) =>
let (m1, b) := Mem.alloc m 0 1 in
Mem.drop_perm m1 b 0 1 Nonempty
| (id, Gvar v) =>
let init := v.(gvar_init) in
let sz := init_data_list_size init in
let (m1, b) := Mem.alloc m 0 sz in
match store_zeros m1 b 0 sz with
| None => None
| Some m2 =>
match store_init_data_list m2 b 0 init with
| None => None
| Some m3 => Mem.drop_perm m3 b 0 sz (perm_globvar v)
end
end
end.
Fixpoint alloc_globals (m: mem) (gl: list (ident * globdef F V))
{struct gl} : option mem :=
match gl with
| nil => Some m
| g :: gl' =>
match alloc_global m g with
| None => None
| Some m' => alloc_globals m' gl'
end
end.

(* Specifications: *)
Lemma alloc_globals_app : forall gl1 gl2 m m1,
alloc_globals m gl1 = Some m1 ->
alloc_globals m1 gl2 = alloc_globals m (gl1 ++ gl2).