(** ** Semantics of volatile stores *)
Inductive volatile_store_sem (chunk: memory_chunk) (ge: Senv.t):
list val -> mem -> trace -> val -> mem -> Prop :=
| volatile_store_sem_intro: forall b ofs m1 v t m2,
volatile_store ge chunk m1 b ofs v t m2 ->
volatile_store_sem chunk ge (Vptr b ofs :: v :: nil) m1 t Vundef m2.

(* Specifications: *)
Lemma volatile_store_preserved:
forall ge1 ge2 chunk m1 b ofs v t m2,
Senv.equiv ge1 ge2 ->
volatile_store ge1 chunk m1 b ofs v t m2 ->
volatile_store ge2 chunk m1 b ofs v t m2.
Lemma volatile_store_readonly:
forall ge chunk1 m1 b1 ofs1 v t m2,
volatile_store ge chunk1 m1 b1 ofs1 v t m2 ->
Mem.unchanged_on (loc_not_writable m1) m1 m2.
Lemma volatile_store_extends:
forall ge chunk m1 b ofs v t m2 m1' v',
volatile_store ge chunk m1 b ofs v t m2 ->
Mem.extends m1 m1' ->
Val.lessdef v v' ->
exists m2',
volatile_store ge chunk m1' b ofs v' t m2'
/\ Mem.extends m2 m2'
/\ Mem.unchanged_on (loc_out_of_bounds m1) m1' m2'.
Lemma volatile_store_inject:
forall ge1 ge2 f chunk m1 b ofs v t m2 m1' b' ofs' v',
symbols_inject f ge1 ge2 ->
volatile_store ge1 chunk m1 b ofs v t m2 ->
Val.inject f (Vptr b ofs) (Vptr b' ofs') ->
Val.inject f v v' ->
Mem.inject f m1 m1' ->
exists m2',
volatile_store ge2 chunk m1' b' ofs' v' t m2'
/\ Mem.inject f m2 m2'
/\ Mem.unchanged_on (loc_unmapped f) m1 m2
/\ Mem.unchanged_on (loc_out_of_reach f m1) m1' m2'.
Lemma volatile_store_receptive:
forall ge chunk m b ofs v t1 m1 t2,
volatile_store ge chunk m b ofs v t1 m1 -> match_traces ge t1 t2 -> t1 = t2.
Lemma volatile_store_ok:
forall chunk,
extcall_properties (volatile_store_sem chunk)
(mksignature (Tptr :: type_of_chunk chunk :: nil) None cc_default).
Lemma volatile_store_preserved:
forall ge1 ge2 chunk m1 b ofs v t m2,
Senv.equiv ge1 ge2 ->
volatile_store ge1 chunk m1 b ofs v t m2 ->
volatile_store ge2 chunk m1 b ofs v t m2.
Lemma volatile_store_readonly:
forall ge chunk1 m1 b1 ofs1 v t m2,
volatile_store ge chunk1 m1 b1 ofs1 v t m2 ->
Mem.unchanged_on (loc_not_writable m1) m1 m2.
Lemma volatile_store_extends:
forall ge chunk m1 b ofs v t m2 m1' v',
volatile_store ge chunk m1 b ofs v t m2 ->
Mem.extends m1 m1' ->
Val.lessdef v v' ->
exists m2',
volatile_store ge chunk m1' b ofs v' t m2'
/\ Mem.extends m2 m2'
/\ Mem.unchanged_on (loc_out_of_bounds m1) m1' m2'.
Lemma volatile_store_inject:
forall ge1 ge2 f chunk m1 b ofs v t m2 m1' b' ofs' v',
symbols_inject f ge1 ge2 ->
volatile_store ge1 chunk m1 b ofs v t m2 ->
Val.inject f (Vptr b ofs) (Vptr b' ofs') ->
Val.inject f v v' ->
Mem.inject f m1 m1' ->
exists m2',
volatile_store ge2 chunk m1' b' ofs' v' t m2'
/\ Mem.inject f m2 m2'
/\ Mem.unchanged_on (loc_unmapped f) m1 m2
/\ Mem.unchanged_on (loc_out_of_reach f m1) m1' m2'.
Lemma volatile_store_receptive:
forall ge chunk m b ofs v t1 m1 t2,
volatile_store ge chunk m b ofs v t1 m1 -> match_traces ge t1 t2 -> t1 = t2.
Lemma volatile_store_full:
forall f ge chunk m b ofs v t1 m1,
injection_full f m ->
volatile_store ge chunk m b ofs v t1 m1 ->
injection_full f m1.
Lemma volatile_store_ok:
forall chunk,
extcall_properties (volatile_store_sem chunk)
(mksignature (Tptr :: type_of_chunk chunk :: nil) None cc_default).