End MATCH_TRACES_INV.
(** An output trace is a trace composed only of output events, that is, events that do not take any result from the outside world. *)
Definition output_event (ev: event) : Prop :=
match ev with
| Event_syscall _ _ _ => False
| Event_vload _ _ _ _ => False
| Event_vstore _ _ _ _ => True
| Event_annot _ _ => True
| _ => False
end.
Fixpoint output_trace (t: trace) : Prop :=
match t with
| nil => True
| ev :: t' => output_event ev /\ output_trace t'
end.
(** * Semantics of volatile memory accesses *)
Inductive volatile_load (ge: Senv.t):
memory_chunk -> mem -> block -> ptrofs -> trace -> val -> Prop :=
| volatile_load_vol: forall chunk m b ofs id ev v,
Senv.block_is_volatile ge b = true ->
Senv.find_symbol ge id = Some b ->
eventval_match ge ev (type_of_chunk chunk) v ->
volatile_load ge chunk m b ofs
(Event_vload chunk id ofs ev :: nil)
(Val.load_result chunk v)
| volatile_load_nonvol: forall chunk m b ofs v,
Senv.block_is_volatile ge b = false ->
Mem.load chunk m b (Ptrofs.unsigned ofs) = Some v ->
volatile_load ge chunk m b ofs E0 v.
Inductive volatile_store (ge: Senv.t):
memory_chunk -> mem -> block -> ptrofs -> val -> trace -> mem -> Prop :=
| volatile_store_vol: forall chunk m b ofs id ev v,
Senv.block_is_volatile ge b = true ->
Senv.find_symbol ge id = Some b ->
eventval_match ge ev (type_of_chunk chunk) (Val.load_result chunk v) ->
volatile_store ge chunk m b ofs v
(Event_vstore chunk id ofs ev :: nil)
m
| volatile_store_nonvol: forall chunk m b ofs v m',
Senv.block_is_volatile ge b = false ->
Mem.store chunk m b (Ptrofs.unsigned ofs) v = Some m' ->
volatile_store ge chunk m b ofs v E0 m'.
(** * Semantics of external functions *)
(** For each external function, its behavior is defined by a predicate relating: - the global symbol environment - the values of the arguments passed to this function - the memory state before the call - the result value of the call - the memory state after the call - the trace generated by the call (can be empty). *)
Definition extcall_sem : Type :=
Senv.t -> list val -> mem -> trace -> val -> mem -> Prop.
(** We now specify the expected properties of this predicate. *)
Definition loc_out_of_bounds (m: mem) (b: block) (ofs: Z) : Prop :=
~Mem.perm m b ofs Max Nonempty.
Definition loc_not_writable (m: mem) (b: block) (ofs: Z) : Prop :=
~Mem.perm m b ofs Max Writable.
Definition loc_unmapped (f: meminj) (b: block) (ofs: Z): Prop :=
f b = None.
Definition loc_out_of_reach (f: meminj) (m: mem) (b: block) (ofs: Z): Prop :=
forall b0 delta,
f b0 = Some(b, delta) -> ~Mem.perm m b0 (ofs - delta) Max Nonempty.
Definition inject_separated (f f': meminj) (m1 m2: mem): Prop :=
forall b1 b2 delta,
f b1 = None -> f' b1 = Some(b2, delta) ->
~Mem.valid_block m1 b1 /\ ~Mem.valid_block m2 b2.
(*Parameter inject_delta_map: meminj -> delta_map -> delta_map -> Prop Parameter inject_access_map: meminj -> access_map -> access_map -> Prop. *)
Definition option_func {A B} (of: option (A -> B)) (a:A): option B:=
match of with
None => None
| Some f => Some (f a)
end.
Inductive inject_delta_map (f:meminj) (dm1 dm2:delta_map): Prop:=
| Build_inject_delta_mem:
( forall b b' d, f b = Some(b',d) -> forall ofs:Z,
option_func (dm1 ! b) ofs = option_func (dm2 ! b) (ofs-d)%Z) ->
inject_delta_map f dm1 dm2.
Inductive inject_delta_content (f:meminj) (dm1 dm2:delta_content): Prop:=
| Build_inject_delta_content:
( forall b b' d, f b = Some(b',d) -> forall ofs (v1: memval),
option_func (dm1 ! b) ofs = Some (Some v1) ->
exists v2, option_func (dm2 ! b) (ofs-d)%Z = Some (Some v2) /\ memval_inject f v1 v2) ->
( forall b b' d, f b = Some(b',d) -> forall ofs (v1: option memval),
option_func (dm1 ! b) ofs = Some None ->
option_func (dm2 ! b) (ofs-d)%Z = Some None) ->
( forall b b' d, f b = Some(b',d) -> forall ofs (v1: option memval),
option_func (dm1 ! b) ofs = None ->
option_func (dm2 ! b) (ofs-d)%Z = None) ->
inject_delta_content f dm1 dm2.
Inductive inject_event: meminj -> event -> event -> Prop :=
| INJ_syscall: forall f s t v, inject_event f (Event_syscall s t v) (Event_syscall s t v)
| INJ_vload : forall f mc id n v, inject_event f (Event_vload mc id n v) (Event_vload mc id n v)
| INJ_vstore : forall f mc id n v, inject_event f (Event_vstore mc id n v) (Event_vstore mc id n v)
| INJ_annot : forall f st t, inject_event f (Event_annot st t) (Event_annot st t)
| INJ_acq : forall f v dm dc v' dm' dc',
Val.inject f v v ->
inject_delta_map f dm dm' ->
inject_delta_content f dc dc' ->
inject_event f (Event_acq v dm dc) (Event_acq v' dm' dc')
| INJ_rel : forall f v dm dc v' dm' dc',
Val.inject f v v ->
inject_delta_map f dm dm' ->
inject_delta_content f dc dc' ->
inject_event f (Event_rel v dm dc) (Event_rel v' dm' dc')
| INJ_spawn : forall f v dm1 dc1 dm2 dc2 v' dm1' dc1' dm2' dc2',
Val.inject f v v ->
inject_delta_map f dm1 dm1' ->
inject_delta_map f dm2 dm2' ->
inject_delta_content f dc1 dc1' ->
inject_delta_content f dc2 dc2' ->
inject_event f (Event_spawn v dm1 dc1 dm2 dc2) (Event_spawn v' dm1' dc1' dm2' dc2').
Inductive inject_trace: meminj -> trace -> trace -> Prop :=
| injt_nil : forall f, inject_trace f nil nil
| injt_cons: forall f e t e' t',
inject_event f e e' ->
inject_trace f t t' ->
inject_trace f (cons e t) (cons e' t').
Definition injection_full (f:meminj) (m:mem):=
forall b ,
Mem.valid_block m b ->
~ f b = None.

Lemma free_full: forall f m ls lo hi m',
injection_full f m ->
Mem.free m ls lo hi = Some m' ->
injection_full f m'.