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.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.
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'.