Inductive valid_genv {F V:Type} (ge:Genv.t F V) (m:mem) : Type :=
mk_valid_genv :
(forall b, isGlobalBlock ge b=true -> val_valid (Vptr b Ptrofs.zero) m) ->
(forall b f, Genv.find_funct_ptr ge b = Some f -> val_valid (Vptr b Ptrofs.zero) m) ->
valid_genv ge m.

(* Specifications: *)
Lemma valid_genv_alloc: forall {F V:Type} (ge:Genv.t F V) (m m1:mem) lo hi b
(ALLOC: Mem.alloc m lo hi = (m1,b)) (G: valid_genv ge m), valid_genv ge m1.
Lemma valid_genv_store: forall {F V:Type} (ge:Genv.t F V) m m1 b ofs v chunk
(STORE: Mem.store chunk m b ofs v = Some m1)
(G: valid_genv ge m), valid_genv ge m1.
Lemma valid_genv_store_zeros: forall {F V:Type} (ge:Genv.t F V) m m1 b y z
(STORE_ZERO: store_zeros m b y z = Some m1)
(G: valid_genv ge m), valid_genv ge m1.
Lemma mem_wd_store_zeros: forall m b p n m1
(STORE_ZERO: store_zeros m b p n = Some m1) (WD: mem_wd m), mem_wd m1.
Lemma valid_genv_drop: forall {F V:Type} (ge:Genv.t F V) (m m1:mem) b lo hi p
(DROP: Mem.drop_perm m b lo hi p = Some m1) (G: valid_genv ge m),
valid_genv ge m1.
Lemma mem_wd_store_init_data: forall {F V} (ge: Genv.t F V) a (b:block) (z:Z)
m1 m2 (SID:Genv.store_init_data ge m1 b z a = Some m2),
valid_genv ge m1 -> mem_wd m1 -> mem_wd m2.
Lemma valid_genv_store_init_data:
forall {F V}  (ge: Genv.t F V) a (b:block) (z:Z) m1 m2
(SID: Genv.store_init_data ge m1 b z a = Some m2),
valid_genv ge m1 -> valid_genv ge m2.
Lemma mem_wd_store_init_datalist: forall {F V} (ge: Genv.t F V) l (b:block)
(z:Z) m1 m2 (SID: Genv.store_init_data_list ge m1 b z l = Some m2),
valid_genv ge m1 -> mem_wd m1 -> mem_wd m2.
Lemma valid_genv_store_init_datalist: forall {F V} (ge: Genv.t F V) l (b:block)
(z:Z) m1 m2 (SID: Genv.store_init_data_list ge m1 b z l = Some m2),
valid_genv ge m1 -> valid_genv ge m2.
Lemma mem_wd_alloc_global: forall  {F V} (ge: Genv.t F V) a m0 m1
(GA: Genv.alloc_global ge m0 a = Some m1),
mem_wd m0 -> valid_genv ge m0 -> mem_wd m1.
Lemma valid_genv_alloc_global: forall  {F V} (ge: Genv.t F V) a m0 m1
(GA: Genv.alloc_global ge m0 a = Some m1),
valid_genv ge m0 -> valid_genv ge m1.
Lemma valid_genv_alloc_globals:
forall F V (ge: Genv.t F V) init_list m0 m
(GA: Genv.alloc_globals ge m0 init_list = Some m),
valid_genv ge m0 -> valid_genv ge m.
Lemma mem_wd_alloc_globals:
forall F V (ge: Genv.t F V) init_list m0 m
(GA: Genv.alloc_globals ge m0 init_list = Some m),
mem_wd m0 -> valid_genv ge m0 -> mem_wd m.
(*POPL-compcomp used the following lemma to prove mem_wd_load: Lemma decode_val_pointer_inv: forall chunk mvl b ofs, decode_val chunk mvl = Vptr b ofs -> chunk = Mint32 /\ mvl = inj_value Q32 (Vptr b ofs). A version of this lemma is in CompCert 2.3, Memdata.v, but missing from CompCert 2.4.  I'm not even sure it's true in CompCert 2.4.  -A.W.A.  In CompCert2.5, the proof of mem_wd_load uses the new load_ptr_is_fragment, recently added to mem_lemmas*)
Lemma mem_wd_load: forall m ch b ofs v
(LD: Mem.load ch m b ofs = Some v)
(WD : mem_wd m), val_valid v m.
Lemma mem_wd_storebytes: forall m b ofs bytes m' (WDm: mem_wd m)
(ST: Mem.storebytes m b ofs bytes = Some m')
(BytesValid: forall v, In v bytes ->
memval_inject (Mem.flat_inj (Mem.nextblock m)) v v),
mem_wd m'.
Lemma getN_aux: forall n p c B1 v B2, Mem.getN n p c = B1 ++ v::B2 ->
v = ZMap.get (p + Z.of_nat (length B1)) c.
Lemma getN_range: forall n ofs M bytes1 v bytes2,
Mem.getN n ofs M = bytes1 ++ v::bytes2 ->
(length bytes1 < n)%nat.
Lemma loadbytes_D: forall m b ofs n bytes
(LD: Mem.loadbytes m b ofs n = Some bytes),
Mem.range_perm m b ofs (ofs + n) Cur Readable /\
bytes = Mem.getN (nat_of_Z n) ofs (PMap.get b (Mem.mem_contents m)).
Lemma loadbytes_valid: forall m (WD: mem_wd m) b ofs' n bytes
(LD: Mem.loadbytes m b (Int.unsigned ofs') n = Some bytes)
v (B: In v bytes),
memval_inject (Mem.flat_inj (Mem.nextblock m)) v v.
Lemma freelist_mem_wd: forall l m m'
(M: Mem.free_list m l = Some m')
(WD: mem_wd m), mem_wd m'.