Require Import Coqlib.
Require Import Ast Events Mem Pointers Integers Values.
Record mod4 (
i:
int) :
Prop :=
{
I:
Z
;
_:
Int.unsigned i = 4 *
I
;
_: 0 <=
I <
Int.modulus / 4
}.
Definition wf_ptr (
p:
pointer) :
Prop :=
match p with
|
Ptr b i =>
mod4 i
end.
Lemma wf_ptr_aligned (
p:
pointer) :
wf_ptr p ->
pointer_chunk_aligned p Mint32.
Proof.
destruct p as (P & pi). intros [I J K]. simpl. exists I. omega. Qed.
Definition wf_val (
v:
val) :
Prop :=
match v with
|
Vint _ =>
True
|
Vptr p =>
wf_ptr p
|
Vfloat _
|
Vundef =>
False
end.
Definition wf_rmw (
rmw:
rmw_instr) :
Prop :=
match rmw with
|
rmw_ADD v |
rmw_SET v =>
False
|
rmw_CAS v v' =>
wf_val v /\
wf_val v'
end.
Lemma wf_rmw_instr_sem (
v:
val) (
rmw:
rmw_instr) :
wf_val v ->
wf_rmw rmw ->
wf_val (
rmw_instr_semantics rmw v).
Proof.
destruct rmw as [| i j |]; simpl; try now intuition.
intros V (I & J).
destruct (Val.eq_dec i Vundef). subst. inv I. simpl.
destruct (Val.eq_dec v Vundef). subst. inv V. simpl.
case (Val.eq_dec i v); trivial.
Qed.
Lemma p_dec p1 p2 :
wf_ptr p1 ->
wf_ptr p2 ->
{
p1 =
p2 } +
{
p1 <>
p2 /\
ranges_disjoint (
p1,
Int.repr 4) (
p2,
Int.repr 4) }.
Proof.
intros Hi Hj.
destruct p1 as [
b1 i1];
destruct p2 as [
b2 i2];
simpl in *.
destruct (
Z_eq_dec b1 b2).
destruct (
Int.eq_dec i1 i2).
subst.
left.
reflexivity.
right.
intuition.
inv H;
intuition.
unfold ranges_disjoint.
right.
destruct Hi as [
I HI K].
simpl in K.
destruct Hj as [
J HJ L].
simpl in L.
simpl.
repeat rewrite Zmod_small;
intuition.
assert(
Int.unsigned i1<>
Int.unsigned i2).
intro;
elim n;
apply Int.unsigned_eq;
auto.
omega.
reflexivity.
right;
split.
congruence.
left;
auto.
Qed.
Definition wf_range (
r:
arange) :
Prop :=
wf_ptr (
fst r) /\
mod4 (
snd r).
Remark wf_range_of_ptr {
p:
pointer} :
wf_ptr p ->
wf_range (
range_of_chunk p Mint32).
Proof.
intros H. split. exact H. simpl. exists 1. reflexivity. intuition. reflexivity.
Qed.
Lemma wf_range_ptr_inside {
r:
arange} {
p:
pointer} :
wf_range r ->
wf_ptr p ->
{
range_inside (
range_of_chunk p Mint32)
r } + {
ranges_disjoint r (
range_of_chunk p Mint32) }.
Proof.
destruct r as ((Blk & i) & sz). destruct p as (p & pi).
intros (B & Sz). simpl in *.
intros P.
unfold range_of_chunk, size_chunk.
case (ranges_disjoint_dec (Ptr Blk i, sz) (Ptr p pi, Int.repr 4)).
intuition.
intros K.
left.
destruct (ranges_overlapD K) as (<- & X & Y).
split. reflexivity.
destruct B as [I Hi Hi']. destruct Sz as [S Hs Hs']. rewrite Hi in *. rewrite Hs in *.
destruct P as [P Hp Hp']. rewrite Hp in *.
change (Int.unsigned (Int.repr 4)) with 4 in *.
right.
omega.
Qed.
Lemma load_store_new :
forall m p v m',
wf_ptr p ->
wf_val v ->
store_ptr Mint32 m p v =
Some m' ->
load_ptr Mint32 m'
p =
Some v.
Proof.
intros.
exploit @Mem.load_store_similar; eauto.
destruct v; simpl in *; intuition.
Qed.
Lemma load_store_old :
forall m p v m'
p',
wf_ptr p ->
wf_val v ->
wf_ptr p' ->
store_ptr Mint32 m p v =
Some m' ->
p <>
p' ->
load_ptr Mint32 m'
p' =
load_ptr Mint32 m p'.
Proof.
intros.
exploit @
Mem.load_store_other;
eauto.
destruct (
p_dec _ _ H H1);
intuition.
Qed.
Lemma store_store_ex :
forall m p1 v1 m1 p2 v2 m2,
wf_ptr p1 ->
wf_val v1 ->
wf_ptr p2 ->
wf_val v2 ->
store_ptr Mint32 m p1 v1 =
Some m1 ->
store_ptr Mint32 m1 p2 v2 =
Some m2 ->
store_ptr Mint32 m p2 v2 <>
None.
Proof.
intros m p1 v1 m1 p2 v2 m2 Hp1 Hv1 Hp2 Hv2 Hm1 Hm2.
intros H.
elim (store_chunk_allocated_noneD H).
destruct (store_chunk_allocated_someD Hm2) as ((r & s & A & B) & ?).
split. 2: assumption. exists r. exists s. split. assumption.
erewrite (store_preserves_allocated_ranges Hm1). assumption.
Qed.
Record mem_ext (
m m' :
mem) :
Prop :=
{
eq_load:
forall p,
wf_ptr p ->
load_ptr Mint32 m p =
load_ptr Mint32 m'
p
;
eq_alloc:
forall r k,
range_allocated r k m <->
range_allocated r k m'
;
eq_restr:
forall b,
mrestr m b =
mrestr m'
b
}.
Implicit Arguments eq_load [
m m'
p].
Implicit Arguments eq_alloc [
m m'].
Implicit Arguments eq_restr [
m m'].
Notation "
m ==
m'" := (
mem_ext m m') (
at level 70).
Lemma mem_eq_refl :
forall m,
m ==
m.
Proof.
constructor; intros; reflexivity. Qed.
Lemma mem_eq_sym :
forall m m',
m ==
m' ->
m' ==
m.
Proof.
intros m m'
EQ.
constructor.
intros p Hp;
symmetry;
apply (
EQ.(
eq_load)
Hp).
intros r k;
symmetry;
apply (
EQ.(
eq_alloc)
r k).
intros b;
symmetry;
apply (
EQ.(
eq_restr)
b).
Qed.
Lemma mem_eq_trans:
forall m m'
m'',
m ==
m' ->
m' ==
m'' ->
m ==
m''.
Proof.
intros m m'
m''
E F.
constructor.
intros p Hp.
transitivity (
load_ptr Mint32 m'
p);
intuition.
intros r k.
transitivity (
range_allocated r k m').
apply (
E.(
eq_alloc)
r k).
apply F.(
eq_alloc).
intros b.
transitivity (
mrestr m'
b).
apply E.(
eq_restr).
apply F.(
eq_restr).
Qed.
Lemma store_same :
forall m m'
p v m'',
wf_ptr p ->
wf_val v ->
load_ptr Mint32 m p =
Some v ->
store_ptr Mint32 m'
p v =
Some m'' ->
m ==
m' ->
m' ==
m''.
Proof.
intros m m'
p v m''
Hp Hv HL HS EQ.
constructor.
intros p'
Hp'.
destruct (
p_dec p p');
trivial.
subst.
rewrite (
EQ.(
eq_load)
Hp')
in HL.
rewrite HL.
symmetry.
eapply load_store_new;
eassumption.
eapply load_store_other;
intuition eauto.
intros r k.
eapply store_preserves_allocated_ranges.
eassumption.
intros b.
erewrite <-
restr_of_store;
eauto.
Qed.
Lemma store_ext :
forall m p v m1 m',
m ==
m' ->
wf_ptr p ->
wf_val v ->
store_ptr Mint32 m p v =
Some m1 ->
exists m1',
store_ptr Mint32 m'
p v =
Some m1' /\
m1' ==
m1.
Proof.
intros m p v m1 m'
EQ Hp Hv Hm1.
case_eq (
store_ptr Mint32 m'
p v).
intros m1'
Hm1'.
exists m1'.
split.
reflexivity.
constructor.
intros q Hq.
case (
p_dec p q Hp Hq).
intros <-.
repeat (
erewrite load_store_new;
eauto).
intros (
NE &
_).
rewrite (
load_store_old m p v m1 q);
auto.
rewrite (
load_store_old m'
p v m1'
q);
auto.
symmetry.
apply EQ.(
eq_load);
auto.
intros r k.
transitivity (
range_allocated r k m').
symmetry.
eapply store_preserves_allocated_ranges.
eassumption.
transitivity (
range_allocated r k m).
symmetry.
apply EQ.(
eq_alloc);
auto.
eapply store_preserves_allocated_ranges.
eassumption.
intros b.
erewrite (
restr_of_store Hm1);
eauto.
rewrite (
restr_of_store Hm1').
symmetry.
apply EQ.(
eq_restr).
intros K.
apply False_ind.
elim (
store_chunk_allocated_noneD K).
destruct (
store_chunk_allocated_someD Hm1)
as ((
x &
y &
A &
B) &
C).
split.
exists x;
exists y.
split.
exact A.
apply EQ.(
eq_alloc).
exact B.
exact C.
Qed.
Lemma alloc_ext :
forall m r k m1 m',
m ==
m' ->
wf_range r ->
alloc_ptr r k m =
Some m1 ->
exists m1',
alloc_ptr r k m' =
Some m1' /\
m1' ==
m1.
Proof.
intros m r k m1 m'
EQ Hr Hm1.
case_eq (
alloc_ptr r k m').
intros m1'
Hm1'.
exists m1'.
split.
reflexivity.
constructor.
intros p Hp.
pose proof (
wf_ptr_aligned _ Hp).
destruct (
wf_range_ptr_inside Hr Hp).
rewrite (
load_alloc_inside Hm1);
auto.
rewrite (
load_alloc_inside Hm1');
auto.
apply ranges_disjoint_comm in r0.
rewrite (
load_alloc_other Hm1);
auto.
rewrite (
load_alloc_other Hm1');
auto.
symmetry;
apply eq_load with (1:=
EQ).
assumption.
intros r'
k'.
rewrite (
alloc_preserves_allocated_iff Hm1).
rewrite (
alloc_preserves_allocated_iff Hm1').
pose proof (
EQ.(
eq_alloc)
r'
k').
intuition.
intros b.
rewrite (
restr_of_alloc Hm1).
rewrite (
restr_of_alloc Hm1').
symmetry;
apply EQ.(
eq_restr).
intros K.
destruct (
alloc_someD Hm1)
as (
A &
B &
C &
D).
destruct (
alloc_noneD K)
as [| [
H|(
r' &
k' &
H &
H')]].
contradiction.
elim H.
destruct r as ((
a &
b) &
c).
simpl.
rewrite <-
EQ.(
eq_restr).
exact C.
elim (
D r'
k'
H).
apply EQ.(
eq_alloc).
exact H'.
Qed.
Lemma free_ext :
forall m r k n m1 m',
m ==
m' ->
wf_range (
r,
n) ->
range_allocated (
r,
n)
k m ->
free_ptr r k m =
Some m1 ->
exists m1',
free_ptr r k m' =
Some m1' /\
m1' ==
m1.
Proof.
intros m r k n m1 m'
EQ Hr RA Hm1.
case_eq (
free_ptr r k m').
intros m1'
Hm1'.
exists m1'.
split.
reflexivity.
constructor.
intros p Hp.
destruct (
ranges_disjoint_dec (
range_of_chunk p Mint32) (
r,
n))
as [
Y|
Y].
rewrite (
load_free_other Hm1 RA Y).
erewrite (
load_free_other Hm1'). 2:
apply EQ.(
eq_alloc);
apply RA. 2:
exact Y.
symmetry.
apply EQ.(
eq_load).
assumption.
rewrite (
load_free_overlap Hm1 RA Y).
eapply load_free_overlap;
try eassumption.
apply EQ.(
eq_alloc).
assumption.
intros r'
k'.
split.
intros H;
assert (
H' :=
free_preserves_allocated_back Hm1'
_ _ H);
apply EQ.(
eq_alloc)
in H';
destruct (
free_preserves_allocated Hm1 _ _ H')
as [
Y|(
Y&->)].
assumption.
destruct r'.
unfold fst in *.
subst.
elim (
free_not_allocated Hm1'
_ _ H).
intros H;
assert (
H' :=
free_preserves_allocated_back Hm1 _ _ H);
rewrite EQ.(
eq_alloc)
in H';
destruct (
free_preserves_allocated Hm1'
_ _ H')
as [
Y|(
Y&->)].
assumption.
destruct r'.
unfold fst in *.
subst.
elim (
free_not_allocated Hm1 _ _ H).
intros b.
rewrite (
restr_of_free Hm1).
rewrite (
restr_of_free Hm1').
symmetry;
apply EQ.(
eq_restr).
intros K.
destruct (
free_someD Hm1)
as (
n' &
Hn').
rewrite EQ.(
eq_alloc)
in Hn'.
elim (
free_noneD K n'
Hn').
Qed.
Lemma store_comm :
forall m p1 v1 m1 p2 v2 m2,
p1 <>
p2 ->
wf_ptr p1 ->
wf_val v1 ->
wf_ptr p2 ->
wf_val v2 ->
store_ptr Mint32 m p1 v1 =
Some m1 ->
store_ptr Mint32 m1 p2 v2 =
Some m2 ->
forall m0,
m0 ==
m ->
forall m3,
store_ptr Mint32 m0 p2 v2 =
Some m3 ->
exists m2',
store_ptr Mint32 m3 p1 v1 =
Some m2' /\
m2' ==
m2.
Proof.
intros m p1 v1 m1 p2 v2 m2 NEQ Hp1 Hv1 Hp2 Hv2 Hm1 Hm2 m0 EQ m3 Hm3.
case_eq (
store_ptr Mint32 m3 p1 v1).
intros m'
Hm'.
exists m';
split.
reflexivity.
constructor.
intros p Hp.
case (
Ptr.eq_dec p2 p).
intros ->.
rewrite load_store_old with (4:=
Hm');
auto.
rewrite load_store_new with (3:=
Hm3);
auto.
rewrite load_store_new with (3:=
Hm2);
auto.
intros.
rewrite load_store_old with (4:=
Hm2);
auto.
case (
p_dec _ _ Hp1 Hp).
intros ->.
rewrite load_store_new with (3:=
Hm1);
auto.
rewrite load_store_new with (3:=
Hm');
auto.
intros (? &
_).
rewrite load_store_old with (4:=
Hm1);
auto.
rewrite load_store_old with (4:=
Hm');
auto.
rewrite load_store_old with (4:=
Hm3);
auto.
eapply eq_load;
eauto.
intros r k.
transitivity (
range_allocated r k m3).
symmetry.
eapply (
store_preserves_allocated_ranges Hm').
transitivity (
range_allocated r k m0).
symmetry.
eapply (
store_preserves_allocated_ranges Hm3).
transitivity (
range_allocated r k m1).
transitivity (
range_allocated r k m).
eapply eq_alloc;
eauto.
eapply (
store_preserves_allocated_ranges Hm1).
eapply (
store_preserves_allocated_ranges Hm2).
intros b.
rewrite (
restr_of_store Hm2).
rewrite (
restr_of_store Hm1).
rewrite (
restr_of_store Hm').
rewrite (
restr_of_store Hm3).
apply EQ.(
eq_restr).
intros H.
pose proof (
store_chunk_allocated_someD Hm1)
as ((
u &
u' &
U &
U') &
V).
elim (
store_chunk_allocated_noneD H).
split. 2:
assumption.
exists u.
exists u'.
split.
trivial.
apply (
store_preserves_allocated_ranges Hm3).
rewrite eq_alloc with (1:=
EQ).
assumption.
Qed.
Lemma store_alloc :
forall m p v m'
r k m'',
wf_ptr p ->
wf_val v ->
wf_range r ->
store_ptr Mint32 m p v =
Some m' ->
alloc_ptr r k m' =
Some m'' ->
forall x,
x ==
m ->
(
exists n,
alloc_ptr r k x =
Some n)
/\
(
forall n,
alloc_ptr r k x =
Some n ->
exists n',
store_ptr Mint32 n p v =
Some n' /\
n' ==
m'').
Proof.
intros m p v m'
r k m''
Hp Hv Hr HS HA x EQ.
destruct (
alloc_someD HA)
as (
Hr'' &
V &
R &
HA').
pose proof (
store_preserves_allocated_ranges HS)
as Hr'.
case_eq (
alloc_ptr r k x).
Focus 2.
intros K.
destruct (
alloc_noneD K)
as [| [
H|(
r' &
k' &
H &
H')]].
contradiction.
elim H.
destruct r as ((
a &
b) &
c).
simpl.
rewrite EQ.(
eq_restr).
rewrite <- (
restr_of_store HS).
exact R.
elim (
HA'
r'
k'
H).
apply Hr'.
apply EQ.(
eq_alloc).
exact H'.
intros x'
Hx'.
split.
exists x'.
reflexivity.
intros ?
H;
inv H.
case_eq (
store_ptr Mint32 n p v).
Focus 2.
intros K.
apply False_ind.
pose proof (
store_chunk_allocated_someD HS)
as ((
u &
u' &
U &
U') &
K').
elim (
store_chunk_allocated_noneD K).
split. 2:
assumption.
exists u.
exists u'.
split.
assumption.
apply (
alloc_preserves_allocated Hx').
rewrite EQ.(
eq_alloc).
assumption.
intros n'
Hn'.
exists n'.
split.
reflexivity.
constructor.
3:
intros b;
rewrite (
restr_of_store Hn'), (
restr_of_alloc Hx'), (
restr_of_alloc HA), (
restr_of_store HS);
apply EQ.(
eq_restr).
intros q Hq.
destruct (
p_dec q p Hq Hp)
as [->|(
Hpq &
_)].
rewrite (
load_store_new _ _ _ _ Hp Hv Hn').
rewrite (
load_alloc_other HA).
rewrite (
load_store_new _ _ _ _ Hp Hv HS).
reflexivity.
destruct (
wf_range_ptr_inside Hr Hp)
as [
H|
H]. 2:
apply ranges_disjoint_comm;
exact H.
destruct (
store_chunk_allocated_someD HS)
as ((
u &
u' &
A &
B) &
C).
elim (
HA'
u u').
2:
apply (
store_preserves_allocated_ranges HS);
assumption.
eapply overlap_inside_overlap. 2:
eapply H.
apply ranges_overlap_comm.
eapply overlap_inside_overlap. 2:
eapply A.
apply ranges_overlap_refl.
vauto.
rewrite (
load_store_old _ _ _ _ _ Hp Hv Hq Hn'). 2:
intuition.
pose proof (
wf_ptr_aligned _ Hq).
destruct (
wf_range_ptr_inside Hr Hq)
as [
K|
K].
rewrite (
load_alloc_inside HA);
auto.
rewrite (
load_alloc_inside Hx');
auto.
apply ranges_disjoint_comm in K.
rewrite (
load_alloc_other HA);
auto.
rewrite (
load_alloc_other Hx');
auto.
rewrite (
load_store_old _ _ _ _ _ Hp Hv Hq HS);
intuition.
intros ar ak.
transitivity (
range_allocated ar ak n).
symmetry.
exact (
store_preserves_allocated_ranges Hn'
ar ak).
destruct (
alloc_someD Hx')
as (
Hrx &
_ &
Rx &
HAx).
rewrite (
alloc_preserves_allocated_iff Hx').
rewrite (
alloc_preserves_allocated_iff HA).
specialize HAx with ar ak.
specialize HA'
with ar ak.
specialize Hr'
with ar ak.
pose proof (
EQ.(
eq_alloc)
ar ak).
intuition (
subst;
intuition).
Qed.
Lemma store_free :
forall m p v m'
r rx k m'',
wf_ptr p ->
wf_val v ->
wf_range (
r,
rx) ->
store_ptr Mint32 m p v =
Some m' ->
range_allocated (
r,
rx)
k m' ->
ranges_disjoint (
range_of_chunk p Mint32) (
r,
rx) ->
free_ptr r k m' =
Some m'' ->
forall x,
x ==
m ->
(
exists n,
free_ptr r k x =
Some n)
/\
(
forall n,
free_ptr r k x =
Some n ->
exists n',
store_ptr Mint32 n p v =
Some n' /\
n' ==
m'').
Proof.
intros m p v m'
r rx k m''
Hp Hv Hr Hs Ha Hd Hf x EQ.
destruct (
free_someD Hf)
as (
q &
Hq).
pose proof (
store_preserves_allocated_ranges Hs)
as Hr'.
case_eq (
free_ptr r k x).
2:
intros H;
eelim (
free_noneD H);
erewrite eq_alloc with (1:=
EQ);
apply Hr';
eassumption.
intros n'
Hn.
split.
exists n';
trivial.
intros n K;
inv K.
pose proof (
store_chunk_allocated_someD Hs)
as ((
u &
u' &
U &
U') &
V).
case_eq (
store_ptr Mint32 n p v).
Focus 2.
intros H;
elim (
store_chunk_allocated_noneD H).
split. 2:
assumption.
exists u.
exists u'.
split.
assumption.
rewrite <-
eq_alloc with (1:=
EQ)
in U'.
destruct (
free_preserves_allocated Hn u u'
U')
as [
A|(
A&
B)].
exact A.
subst.
destruct u as ((
blk &
ofs) &
usz).
unfold fst in *.
destruct (
alloc_ranges_same Ha Hq).
subst.
apply Hr'
in Hq.
rewrite eq_alloc with (1:=
EQ)
in U'.
destruct (
alloc_ranges_same U'
Hq).
subst.
clear U'.
unfold range_of_chunk in *.
assert (
Int.unsigned (
Int.repr 4) = 4)
as H4.
apply Int.unsigned_repr.
intuition.
discriminate.
destruct p as (
pb &
pi).
simpl in Hd,
U.
inv U.
inv H2.
rewrite H4 in *.
inv Hd.
congruence.
rewrite H4 in *.
destruct Hr as ((
Ofs &
B) & (
Q &
F)).
unfold snd in *.
rewrite F in *.
rewrite B in *.
simpl in V.
destruct V as (
V &
HV).
rewrite HV in *.
apply False_ind.
intuition.
intros n'
Hn'.
exists n'.
split.
reflexivity.
constructor.
intros l Hl.
destruct (
p_dec l p)
as [<-|(
X&
_)];
auto.
rewrite load_store_new with (3:=
Hn');
auto.
rewrite (
load_free_other Hf Ha);
auto.
rewrite load_store_new with (3:=
Hs);
auto.
rewrite load_store_old with (4:=
Hn');
auto.
destruct (
ranges_disjoint_dec (
range_of_chunk l Mint32) (
r,
rx))
as [
Y|
Y].
rewrite (
load_free_other Hf Ha Y).
erewrite (
load_free_other Hn). 2:
erewrite eq_alloc with (1:=
EQ);
rewrite Hr';
apply Ha. 2:
exact Y.
rewrite load_store_old with (4:=
Hs);
auto.
apply eq_load;
auto.
rewrite (
load_free_overlap Hf Ha Y).
eapply load_free_overlap;
try eassumption.
rewrite eq_alloc with (1:=
EQ).
rewrite Hr'.
assumption.
intros ar ak.
specialize Hr'
with ar ak.
pose proof (
store_preserves_allocated_ranges Hn'
ar ak).
pose proof (
free_preserves_allocated Hf ar ak).
pose proof (
free_preserves_allocated_back Hf ar ak).
pose proof (
free_preserves_allocated Hn ar ak).
pose proof (
free_preserves_allocated_back Hn ar ak).
pose proof (
store_preserves_allocated_ranges Hs ar ak).
pose proof (
EQ.(
eq_alloc)
ar ak).
destruct ar as (
ar,
ari).
pose proof (
free_not_allocated Hf ari ak).
pose proof (
free_not_allocated Hn ari ak).
unfold fst in *.
intuition (
subst;
intuition).
intros b.
pose proof (
EQ.(
eq_restr)
b).
pose proof (
restr_of_store Hs).
pose proof (
restr_of_store Hn').
pose proof (
restr_of_free Hf).
pose proof (
restr_of_free Hn).
congruence.
Qed.
Axiom emem_is_eq :
forall m m',
m ==
m' ->
m =
m'.
This is axiom is safe because we always access memory on well aligned
pointer. It could be remove if we lift every definitions that deal
with memory with == instead of =