Require Import Coqlib.
Require Import Errors.
Require Import AST.
Require Import Maps.
Require Import Integers.
Require Import Floats.
Require Import Values.
Require Import Globalenvs.
Require Import Values_symbolictype.
Require Import Values_symbolic.
Require Import Normalise.
Require Import NormaliseSpec.
Require Import ExprEval.
Require Import Memory.
Require Import Psatz.
Require Import MemRel Align Tactics.
Require Import Permutation MemReserve BlockAppears ListUtils.
Opaque two_power_nat.
Opaque minus Z.mul.
Local Opaque Pos.of_nat.
Hint Resolve two_power_nat_pos.
Lemma npow_inj :
forall x y,
Z.of_nat (
NPeano.pow x y) = (
Z.of_nat x ^
Z.of_nat y)%
Z.
Proof.
Section NAT_RANGE'.
Nat ranges
We define ranges lo,lo+n.
Fixpoint nat_range'
lo n :
list nat :=
match n with
O =>
lo ::
nil
|
S m =>
lo ::
nat_range' (
S lo)
m
end.
Lemma nat_range'
_range:
forall n lo b,
(
In b (
nat_range'
lo n) ->
(
lo <=
b <=
lo +
n)%
nat).
Proof.
induction n;
simpl;
intros.
des H.
lia.
des (
eq_nat_dec lo b).
lia.
des H.
apply IHn in i.
lia.
Qed.
Lemma range_nat_range':
forall n lo b,
(
lo <=
b <=
lo +
n)%
nat ->
In b (
nat_range'
lo n).
Proof.
induction n;
simpl;
intros.
des H.
lia.
des (
eq_nat_dec lo b).
clear Heqs.
right.
apply IHn.
lia.
Qed.
Lemma lnr_nat_range':
forall n lo,
list_norepet (
nat_range'
lo n).
Proof.
induction n; simpl; intros.
repeat constructor. destr.
constructor. intro IN. apply nat_range'_range in IN. lia.
eauto.
Qed.
End NAT_RANGE'.
Section NAT_RANGE.
Nat ranges
We define ranges lo,hi.
Definition nat_range lo hi :
list nat :=
if le_dec lo hi then nat_range'
lo (
hi-
lo)%
nat else nil.
Lemma nat_range_rew:
forall lo hi,
nat_range lo hi =
if le_dec lo hi
then lo ::
nat_range (
S lo)
hi
else nil.
Proof.
intros.
unfold nat_range.
destr.
destr.
des hi.
lia.
rewrite <-
minus_Sn_m.
simpl.
f_equal.
lia.
replace hi with lo by lia.
rewrite minus_diag.
reflexivity.
Qed.
Special case for n,n = n
Lemma nat_range_same:
forall n,
nat_range n n =
n ::
nil.
Proof.
Lemma length_nat_range:
forall m n,
(
n <=
m)%
nat ->
length (
nat_range n m)%
nat =
S (
m -
n)%
nat.
Proof.
unfold nat_range.
intros m n.
intros.
destr.
generalize (
m -
n)%
nat.
intro n0;
clear.
revert n;
induction n0;
simpl;
intros;
eauto.
Qed.
Lemma nat_range_range:
forall lo hi b,
(
In b (
nat_range lo hi) ->
(
lo <=
b <=
hi)%
nat).
Proof.
unfold nat_range.
intros.
destr_in H.
apply nat_range'
_range in H.
lia.
Qed.
Lemma range_nat_range_range:
forall lo hi b,
(
lo <=
b <=
hi)%
nat ->
In b (
nat_range lo hi).
Proof.
unfold nat_range.
intros.
destr.
apply range_nat_range'.
lia.
lia.
Qed.
Lemma lnr_nat_range:
forall lo hi,
list_norepet (
nat_range lo hi).
Proof.
unfold nat_range.
intros.
destr.
apply lnr_nat_range'.
constructor.
Qed.
End NAT_RANGE.
Section BOX_RANGE.
Box ranges
The "box range" of a block b of size z in a concrete memory cm is
given by box_range cm (b,z) is the list of boxes that b spans over in
cm.
Definition box_range cm (
bz :
block *
Z) :=
let (
b,
sz) :=
bz in
if zlt 0
sz
then nat_range (
Z.to_nat (
Int.unsigned (
cm b) / 8))
(
Z.to_nat ((
Int.unsigned (
cm b) +
sz - 1) / 8))
else nil.
Lemma lnr_box_range:
forall cm a,
list_norepet (
box_range cm a).
Proof.
This alternate version of box range uses the memory m to get the block
size instead of having the size given directly as argument.
Definition box_range'
m cm b :=
let sz := (
Mem.size_block m b)
in
box_range cm (
b,
sz).
Lemma box_range'
_eq:
forall cm m,
map (
box_range cm) (
Mem.mk_block_list m) =
map (
box_range'
m cm) (
map fst (
Mem.mk_block_list m)).
Proof.
End BOX_RANGE.
Definition nb_boxes_used_cm m (
cm :
block ->
int) :
nat :=
length
(
remove_dbl eq_nat_dec (
concat (
map (
box_range cm) (
Mem.mk_block_list m)))).
Section MK_BLOCK_LIST.
Lemma in_bl:
forall m b1 z1
(
i:
In (
b1,
z1) (
Mem.mk_block_list m)),
(
Pos.to_nat b1 <=
pred (
Pos.to_nat (
Mem.nextblock m)))%
nat.
Proof.
Lemma lnr_mbl:
forall m,
list_norepet (
map fst (
Mem.mk_block_list m)).
Proof.
Lemma in_bound_in_mk_block_list:
forall m b z,
In (
b,
z) (
Mem.mk_block_list m) ->
0 <
z ->
in_bound (
Int.unsigned Int.zero) (
Mem.bounds_of_block m b).
Proof.
End MK_BLOCK_LIST.
Lemma box_span_mu:
(
Mem.box_span Int.max_unsigned - 2)%
nat =
Z.to_nat Mem.nb_boxes_max.
Proof.
Section CANON_CM.
Lemma alloc_compat' :
forall m l,
Mem.is_block_list (
Mem.mem_blocksize m) (
pred (
Pos.to_nat (
Mem.nextblock m)))
l ->
{
al :
block ->
nat |
Mem.mk_cm l (
Mem.nb_extra m) =
Some al /\
Mem.compat_m m Mem.M31 (
Mem.box_alloc_to_cm al) }.
Proof.
Definition canon_cm (
m:
mem) :
block ->
int.
Proof.
Lemma canon_cm_mulMA:
forall m b,
exists k,
Int.unsigned (
canon_cm m b) =
two_power_nat MA *
k.
Proof.
Lemma canon_cm_mul8:
forall m b,
exists k,
Int.unsigned (
canon_cm m b) = 8 *
k.
Proof.
Lemma canon_cm_mul_mask:
forall m b,
exists k,
Int.unsigned (
canon_cm m b) =
two_power_nat (
Mem.mask m b) *
k.
Proof.
The meaning of the following lemma is the following: given an address x
aligned on m bits, and a size s compatible with the m-alignment and no
larger than 8 bytes, all the range x,x+s-1 fits inside the same 8-byte
box.
Lemma add_small_div_Z:
forall k s m,
0 <=
k ->
(
m <=
MA)%
nat ->
(
alignment_of_size s <=
m)%
nat ->
0 <
s <= 8 ->
two_power_nat m *
k / 8 = (
two_power_nat m *
k +
s - 1) / 8.
Proof.
Lemma int_and_two_p_m1_mul:
forall i n,
(
n <=
MA)%
nat ->
Int.and i (
Int.not (
Int.repr (
two_power_nat n - 1))) =
i ->
exists k,
i =
Int.mul (
Int.repr (
two_power_nat n))
k.
Proof.
intros;
eapply int_and_two_p_m1_mul';
eauto.
transitivity 12.
generalize (
MA_bound).
lia.
vm_compute;
congruence.
Qed.
Lemma int_and_two_p_m1_mul_Z:
forall i n,
(
n <=
MA)%
nat ->
Int.and i (
Int.not (
Int.repr (
two_power_nat n - 1))) =
i ->
exists k,
Int.unsigned i = (
two_power_nat n) *
k.
Proof.
intros.
eapply int_and_two_p_m1_mul_Z';
eauto.
generalize (
MA_bound);
lia.
Qed.
Lemma int_and_two_p_m1_mul_Z_inv:
forall i n k,
(
n <=
MA)%
nat ->
Int.unsigned i = (
two_power_nat n) *
k ->
Int.and i (
Int.not (
Int.repr (
two_power_nat n - 1))) =
i.
Proof.
Lemma add_small_div:
forall x s m,
Int.and x (
Int.not (
Int.repr (
two_power_nat m - 1))) =
x ->
(
m <=
MA)%
nat ->
(
alignment_of_size s <=
m)%
nat ->
0 <
s <= 8 ->
Int.unsigned x / 8 = (
Int.unsigned x +
s - 1) / 8.
Proof.
Lemma canon_cm_box_range:
forall cm m b z,
Mem.compat_m m Mem.M32 cm ->
0 <
z ->
z =
Mem.size_block m b ->
length (
box_range cm (
b,
z)) =
length (
box_range (
canon_cm m) (
b,
z)).
Proof.
Lemma canon_cm_box_range':
forall cm m b z,
Mem.compat_m m Mem.M32 cm ->
z =
Mem.size_block m b ->
length (
box_range cm (
b,
z)) =
length (
box_range (
canon_cm m) (
b,
z)).
Proof.
Lemma box_over_approx:
forall z (
l0 : 0 <
z),
(
z - 1) /
two_power_nat 3 <
two_power_nat (
MA - 3) *
Z.of_nat (
Mem.box_span z).
Proof.
Lemma rng_contrad:
forall z b b0 y
(
l : 0 <
z)
(
LEY1 : (
Z.to_nat (
two_power_nat (
MA - 3) * (
Z.of_nat b + 1)) <=
y)%
nat)
(
YLE2 : (
y <=
Z.to_nat (
two_power_nat (
MA - 3) * (
Z.of_nat b0 + 1) + (
z - 1) /
two_power_nat 3))%
nat)
(
l2 : (
b0 +
Mem.box_span z <=
b)%
nat),
False.
Proof.
Lemma box_alloc_rew:
forall (
thr :
nat) (
m :
Mem.mem') (
ba :
block ->
nat),
(
thr <
Z.to_nat Mem.nb_boxes_max)%
nat ->
Mem.make_box_allocation (
Mem.mk_block_list m) = (
thr,
ba) ->
forall (
b :
block) (
o :
int),
in_bound (
Int.unsigned o) (
Mem.bounds_of_block m b) ->
Int.unsigned (
Mem.box_alloc_to_cm ba b) =
two_power_nat MA * (
Z.of_nat (
ba b) + 1).
Proof.
Lemma lnr_box_alloc_to_cm:
forall m n x
(
LT :
Z.of_nat (
n +
Mem.nb_extra m) <
Mem.nb_boxes_max)
(
MBO :
Mem.make_box_allocation (
Mem.mk_block_list m) = (
n,
x)),
forall l :
list (
block *
Z),
(
forall x0 :
block *
Z,
In x0 l ->
In x0 (
Mem.mk_block_list m)) ->
list_norepet (
map fst l) ->
list_norepet (
concat (
map (
box_range (
Mem.box_alloc_to_cm x))
l)).
Proof.
Lemma lnr_canon:
forall m,
list_norepet (
concat (
map (
box_range (
canon_cm m)) (
Mem.mk_block_list m))).
Proof.
Lemma canon_cm_more_boxes:
forall cm m,
Mem.compat_m m Mem.M32 cm ->
(
nb_boxes_used_cm m cm <=
nb_boxes_used_cm m (
canon_cm m))%
nat.
Proof.
End CANON_CM.
Lemma length_box_range_canon_cm:
forall m b z, 0 <
z ->
length (
box_range (
canon_cm m) (
b,
z)) = (
S (
Z.to_nat ((
z - 1)/ 8))).
Proof.
Definition boxes cm l :=
map (
box_range cm)
l.
Definition num_boxes {
A} (
bl:
list (
list A)) :=
length (
concat bl).
Definition box_span m cm x :=
length (
box_range'
m cm x).
Lemma nb_boxes_used_cm_nb_boxes_used_m:
forall m,
(
nb_boxes_used_cm m (
canon_cm m) <=
Mem.nb_boxes_used_m m *
NPeano.pow 2 (
MA-3))%
nat.
Proof.
Definition has_free_boxes m cm N :=
(
nb_boxes_used_cm m cm +
N <
Z.to_nat Mem.nb_boxes_max *
NPeano.pow 2 (
MA-3))%
nat.
Definition nb_boxes8_max := (
Z.to_nat Mem.nb_boxes_max *
NPeano.pow 2 (
MA - 3))%
nat.
Section GET_FREE_BOXES.
Definition get_free_boxes m cm :=
fold_left
(
fun (
acc:
list nat)
b =>
filter (
fun x =>
negb (
in_dec eq_nat_dec x (
box_range'
m cm b)))
acc)
(
map fst (
Mem.mk_block_list m))
(
list_ints nb_boxes8_max).
Lemma in_gfb:
forall x m cm ,
In x (
get_free_boxes m cm) ->
In x (
list_ints nb_boxes8_max) /\
Forall (
fun y =>
negb (
in_dec eq_nat_dec x (
box_range'
m cm y)) =
true) (
map fst (
Mem.mk_block_list m)).
Proof.
Lemma align_two_power_nat:
forall m n,
(1 <=
m)%
nat ->
(
m <=
n)%
nat ->
align (
two_power_nat n - 1) (
two_power_nat m) =
two_power_nat n.
Proof.
Lemma align_max_unsigned:
align (
Int.max_unsigned) (
two_power_nat MA) =
Int.max_unsigned + 1.
Proof.
Lemma valid_box_repr:
forall x (
i: (0 <
x <=
nb_boxes8_max)%
nat)
o (
RNGO: 0 <=
o < 8),
0 < 8 *
Z.of_nat x +
o <
Int.max_unsigned.
Proof.
Lemma valid_box_repr_le:
forall x (
i: (0 <
x <=
nb_boxes8_max)%
nat)
o (
RNGO: 0 <=
o < 8),
0 <= 8 *
Z.of_nat x +
o <=
Int.max_unsigned.
Proof.
Lemma in_gfb':
forall x m cm ,
Mem.compat_m m Mem.M32 cm ->
In x (
get_free_boxes m cm) ->
(0 <
x <=
nb_boxes8_max)%
nat /\
forall b o o',
Mem.in_bound_m (
Int.unsigned o)
m b ->
0 <=
Int.unsigned o' < 8 ->
Int.unsigned (
Int.add (
cm b)
o) <>
Int.unsigned (
Int.add (
Int.repr (8 *
Z.of_nat x))
o').
Proof.
Lemma lnr_gfb:
forall m cm,
list_norepet (
get_free_boxes m cm).
Proof.
Lemma in_gfb_addrspace:
forall x m cm ,
In x (
get_free_boxes m cm) ->
forall o, 0 <=
Int.unsigned o < 8 -> 0 < (8 *
Z.of_nat x) +
Int.unsigned o <
Int.max_unsigned.
Proof.
Lemma get_free_boxes_filter:
forall m cm,
Permutation
(
get_free_boxes m cm)
(
filter
(
fun box =>
negb
(
existsb
(
fun b =>
in_dec eq_nat_dec box (
box_range'
m cm b))
(
map fst (
Mem.mk_block_list m))))
(
list_ints nb_boxes8_max)).
Proof.
Lemma get_used_boxes_filter:
forall m cm (
COMP:
Mem.compat_m m Mem.M32 cm),
Permutation (
remove_dbl eq_nat_dec (
concat (
map (
box_range cm) (
Mem.mk_block_list m))))
(
filter (
fun x :
nat =>
existsb (
fun b :
block =>
in_dec eq_nat_dec x (
box_range'
m cm b)) (
map fst (
Mem.mk_block_list m)))
(
list_ints nb_boxes8_max ++
O ::
nat_range (
S nb_boxes8_max) (
Z.to_nat (
Int.max_unsigned / 8)))).
Proof.
Lemma length_get_free_boxes:
forall m cm,
Mem.compat_m m Mem.M32 cm ->
(
Z.to_nat Mem.nb_boxes_max *
NPeano.pow 2 (
MA - 3) <=
length (
get_free_boxes m cm) +
nb_boxes_used_cm m cm)%
nat.
Proof.
Lemma has_free_boxes_correct:
forall m cm n,
Mem.compat_m m Mem.M32 cm ->
has_free_boxes m cm n ->
exists l,
(
length l >=
n)%
nat /\
list_norepet l /\
Forall (
fun z :
Z =>
forall b o o',
Mem.in_bound_m (
Int.unsigned o)
m b ->
0 <=
Int.unsigned o' < 8 ->
Int.unsigned (
Int.add (
cm b)
o) <>
Int.unsigned (
Int.add (
Int.repr z)
o'))
l /\
Forall (
fun z =>
forall o, 0 <=
Int.unsigned o < 8 -> 0 <
z +
Int.unsigned o <
Int.max_unsigned)
l /\
Forall (
fun z =>
exists k,
z = 8 *
k)
l.
Proof.
End GET_FREE_BOXES.