Require Import Zwf.
Require Import Axioms.
Require Import Coqlib.
Require Intv.
Require Import Maps.
Require Archi.
Require Import Integers.
Require Import IntFacts.
Require Import Values.
Require Import List Sorted Orders.
Require Import Mergesort.
Require Import Permutation.
Require Import NormaliseSpec.
Local Notation "
a #
b" := (
PMap.get b a) (
at level 1).
This module defines a greedy allocation algorithm that ensures that a
concrete memory exists for a given abstract memory.
Ltac elim_div :=
unfold Zdiv,
Zmod in *;
repeat
match goal with
|
H :
context[
Zdiv_eucl ?
X ?
Y ] |-
_ =>
generalize (
Z_div_mod_full X Y) ;
destruct (
Zdiv_eucl X Y)
| |-
context[
Zdiv_eucl ?
X ?
Y ] =>
generalize (
Z_div_mod_full X Y) ;
destruct (
Zdiv_eucl X Y)
end;
unfold Remainder.
Ltac unf_modulus :=
change (
Int.modulus)
with 4294967296
in *.
Properties of the align function.
Lemma align_plus:
forall al z,
al = 1 \/
al = 2 \/
al = 4 \/
al = 8 ->
align (
align z al) 8 =
align z 8.
Proof.
intros al z.
unfold align.
intros.
elim_div.
assert (
al <> 0)
by omega.
intuition subst;
omega.
Qed.
Lemma align_align:
forall z a (
apos:
a > 0),
align (
align z a)
a =
align z a.
Proof.
Lemma align_ge1:
forall sz al,
al > 0 ->
exists b, 0 <=
b <
al /\
align sz al =
sz +
b /\
b = (
al - 1 - (
sz - 1 -
al * ((
sz - 1) /
al))).
Proof.
intros.
generalize (
align_le sz al H).
destruct (
align_divides sz al H).
rewrite H0.
intros.
unfold align in H0.
rewrite <-
H0.
replace ((
sz+
al-1)/
al)
with (1+ ((
sz-1)/
al)).
{
replace ((1+ ((
sz-1)/
al))*
al)
with (
al + (
sz -1)/
al *
al).
{
rewrite Z.mul_comm.
replace (
al * ((
sz - 1) /
al))
with
(
al * ((
sz - 1) /
al) + (
sz-1)
mod al - (
sz-1)
mod al)
by omega.
rewrite <-
Z.div_mod by omega.
rewrite Z.mod_eq by omega.
exists (
al - 1 - (
sz - 1 -
al * ((
sz - 1) /
al))).
split;
try omega.
{
elim_div.
assert (
al <> 0)
by omega.
intuition.
}
}
rewrite Z.mul_add_distr_r.
omega.
}
{
replace (
sz +
al - 1)
with ((
sz -1) + 1*
al)
by omega.
rewrite Z_div_plus_full by omega.
omega.
}
Qed.
Lemma align_add:
forall al sz sz',
al > 0 ->
0 <=
sz <=
sz' ->
align sz al <=
align sz'
al.
Proof.
intros.
generalize (
align_ge1 sz al H)
(
align_ge1 sz'
al H).
intros [
b [
A [
B C]]] [
c [
D [
E F]]].
destruct (
zlt (
sz'-
sz)
al);
try intuition omega.
assert (
exists d, 0 <=
d <
al /\
sz' =
sz +
d).
{
clear -
H0 H l.
exists (
sz'-
sz).
intuition try omega.
}
destruct H1 as [
d [
ENC EQ]].
rewrite EQ in *.
clear EQ.
rewrite B;
rewrite E.
cut (
al * ((
sz - 1) /
al) <=
(
al * ((
sz +
d - 1) /
al)));
intros;
try omega.
apply Z.mul_le_mono_nonneg_l;
try omega.
apply Z.div_le_mono;
try omega.
Qed.
Lemma align_distr:
forall z z1,
align z 8 +
align z1 8 =
align (
align z 8 +
z1) 8.
Proof.
unfold align.
intros.
elim_div.
intuition.
Qed.
Helper functions.
Definition get_mask (
m:
PMap.t (
option nat)) (
b:
block) :
nat :=
(
match PMap.get b m with
Some m =>
m |
None =>
O
end).
Definition get_size (
bs:
PMap.t (
option (
Z*
Z))) (
b:
block) :
Z :=
match PMap.get b bs with
Some (
lo,
hi) =>
hi-
lo
|
None => 0
end.
Definition get_bounds (
bs:
PMap.t (
option (
Z*
Z))) (
b:
block) :
Z*
Z :=
match PMap.get b bs with
Some (
lo,
hi) => (
lo,
hi)
|
None => (0,0)
end.
Definition alignment_of_size (
sz:
Z) :
nat :=
(
if zlt sz 2
then O else if zlt sz 4
then 1
else if zlt sz 8
then 2
else 3)%
nat.
Fixpoint list_ints (
b:
nat) :
list nat :=
match b with
O =>
nil
|
S m =>
b ::
list_ints m
end.
Definition mk_block_list_aux (
sz:
block ->
Z) (
b:
nat) :=
map (
fun n =>
let b':=
Pos.of_nat n in
(
b',
sz b'))
(
list_ints b).
Definition size_mem_al (
al:
Z) (
lb:
list (
block*
Z)) (
b:
Z) :=
List.fold_left
(
fun acc (
bsz:
block*
Z) =>
let (
b,
sz) :=
bsz in
align (
align acc al +
Z.max 0
sz)
al
)
lb b.
Lemma size_mem_al_permut:
forall al lb lb',
al > 0 ->
Permutation lb lb' ->
forall b,
size_mem_al al lb b =
size_mem_al al lb'
b.
Proof.
Lemma size_mem_al_add:
forall l b b'
al,
al > 0 ->
0 <=
b <=
b' ->
0 <=
size_mem_al al l b <=
size_mem_al al l b'.
Proof.
Definition size_mem_aux (
t :
list (
block *
Z)) :
Z :=
size_mem_al 8
t 8.
Definition alloc_mem_al (
al:
Z) (
lb:
list (
block*
Z)) (
b :
Z * (
block ->
Z)) :=
List.fold_left
(
fun (
acc:
Z*(
block->
Z)) (
bsz:
block*
Z) =>
let (
cur,
fn) :=
acc in
let (
b,
sz) :=
bsz in
let new :=
align cur al in
(
align (
new +
Z.max 0
sz)
al,
(
fun bb =>
if peq bb b
then new
else fn bb))
)
lb b.
Definition alloc_mem_aux (
t :
list (
block *
Z)) :
Z * (
block ->
Z) :=
alloc_mem_al 8
t (8, (
fun _ => 0)).
Definition alloc_blocks (
t:
list (
block*
Z)) :
option (
block ->
int) :=
let (
sz,
m) :=
alloc_mem_aux t in
if zlt sz Int.max_unsigned
then Some (
fun b =>
Int.repr (
m b))
else None.
Lemma alloc_size_mem_al:
forall al bl zi mi z m,
alloc_mem_al al bl (
zi,
mi) = (
z,
m) ->
size_mem_al al bl zi =
z.
Proof.
induction bl; simpl; intros.
inv H; auto.
destruct a.
apply IHbl in H; auto.
Qed.
Lemma alloc_size_mem_aux:
forall bl z m,
alloc_mem_aux bl = (
z,
m) ->
size_mem_aux bl =
z.
Proof.
Remark permutation_norepet:
forall (
A:
Type) (
l l':
list A),
Permutation l l' ->
list_norepet l ->
list_norepet l'.
Proof.
induction 1;
intros.
-
constructor.
-
inv H0.
constructor;
auto.
red;
intros;
elim H3.
apply Permutation_in with l';
auto.
apply Permutation_sym;
auto.
-
inv H.
simpl in H2.
inv H3.
constructor.
simpl;
intuition.
constructor.
intuition.
auto.
-
eauto.
Qed.
Lemma size_mem_aux_alloc :
forall t p,
size_mem_aux t <=
size_mem_aux (
p::
t).
Proof.
Ltac trim H :=
match type of H with
?
A -> ?
B =>
let x:=
fresh in
assert (
x:
A); [|
specialize (
H x);
clear x]
end.
Lemma mk_block_list_aux_ext:
forall sz sz'
m
(
same_sz:
forall i,
Ple i (
Pos.of_nat m) ->
sz i =
sz'
i
),
mk_block_list_aux sz m =
mk_block_list_aux sz'
m.
Proof.
Lemma if_false:
forall {
A}
b (
a c:
A),
b =
false ->
(
if b then a else c) =
c.
Proof.
destruct b; auto. congruence.
Qed.
Lemma if_true:
forall {
A}
b (
a c:
A),
b =
true ->
(
if b then a else c) =
a.
Proof.
destruct b; auto. congruence.
Qed.
Lemma get_size_same:
forall b p t,
get_size (
PMap.set b (
Some p)
t)
b =
snd p -
fst p.
Proof.
Lemma size_mem_al_pos:
forall l b al,
al > 0 -> 0 <=
b ->
b <=
size_mem_al al l b.
Proof.
Lemma mbla_rew:
forall sz n,
mk_block_list_aux sz (
S n) =
let s :=
sz (
Pos.of_nat (
S n))
in
(
Pos.of_nat (
S n),
s) ::
mk_block_list_aux sz n.
Proof.
reflexivity.
Qed.
Lemma blocks_not_empty:
forall b sz,
forall n,
(
Pos.to_nat b <=
n)%
nat ->
(
mk_block_list_aux sz n) <>
nil.
Proof.
induction n;
intros.
xomega.
rewrite mbla_rew;
simpl.
discriminate.
Qed.
Lemma size_mem_aux_permut:
forall t t',
Permutation t t' ->
size_mem_aux t =
size_mem_aux t'.
Proof.
Lemma mbla_suppr_above:
forall sz'
sz b
(
sz_ext:
forall b',
b <>
b' ->
sz'
b' =
sz b')
n
(
sup: (
Pos.to_nat b >
n)%
nat),
(
mk_block_list_aux sz'
n) =
(
mk_block_list_aux sz n).
Proof.
induction n;
simpl;
auto.
intro sup.
assert (
b <>
Pos.of_nat (
S (
n))).
{
intro;
subst.
rewrite Nat2Pos.id in sup;
omega.
}
rewrite !
mbla_rew.
rewrite IHn by omega.
rewrite sz_ext by auto.
reflexivity.
Qed.
Lemma mbla_suppr_below:
forall sz'
sz b
(
sz_ext:
forall b',
b <>
b' ->
sz'
b' =
sz b')
n
(
inf: (
Pos.to_nat b <=
n)%
nat),
Permutation ((
b,
sz b)::(
mk_block_list_aux sz'
n))
((
b,
sz'
b)::(
mk_block_list_aux sz n)).
Proof.
Lemma size_mem_al_last:
forall szb l b o,
size_mem_al 8 (
l ++ (
b,
szb) ::
nil) (
align o 8) =
size_mem_al 8
l (
align o 8) +
align (
Z.max 0 (
szb)) 8.
Proof.
Lemma size_mem_aux_last:
forall szb l b,
size_mem_aux (
l ++ (
b,
szb) ::
nil) =
size_mem_aux l +
align (
Z.max 0 (
szb)) 8.
Proof.
Lemma size_mem_aux_first:
forall szb l b,
size_mem_aux ((
b,
szb) ::
l) =
size_mem_aux l +
align (
Z.max 0 (
szb)) 8.
Proof.
Lemma size_mem_free_eq:
forall sz'
sz n b
(
sz_ext:
forall b',
b <>
b' ->
sz'
b' =
sz b'),
size_mem_aux (
mk_block_list_aux sz n) =
size_mem_aux (
mk_block_list_aux sz'
n)
+
if le_dec (
Pos.to_nat b)
n
then align (
Z.max 0 (
sz b)) 8 -
align (
Z.max 0 (
sz'
b)) 8
else 0.
Proof.
Lemma size_mem_free_eq':
forall sz'
sz n b
(
sz_ext:
forall b',
b <>
b' ->
sz'
b' =
sz b')
(
new_sz:
sz'
b = 0),
size_mem_aux (
mk_block_list_aux sz n) =
size_mem_aux (
mk_block_list_aux sz'
n)
+
if le_dec (
Pos.to_nat b)
n
then align (
Z.max 0 (
sz b)) 8
else 0.
Proof.
Lemma Zle_add:
forall a b,
0 <=
b ->
a <=
a +
b.
Proof.
intros; omega.
Qed.
Lemma allocs_blocks_free':
forall sz'
sz n b
(
sz_ext:
forall b',
b <>
b' ->
sz'
b' =
sz b')
(
new_sz:
sz'
b = 0),
alloc_blocks (
mk_block_list_aux sz n) <>
None ->
alloc_blocks (
mk_block_list_aux sz'
n) <>
None.
Proof.
Lemma allocs_blocks_free:
forall sz'
sz n b
(
sz_ext:
forall b',
b <>
b' ->
sz'
b' =
sz b')
(
new_sz_msk: (
sz'
b =
sz b) \/
(
sz'
b = 0)),
alloc_blocks (
mk_block_list_aux sz n) <>
None ->
alloc_blocks (
mk_block_list_aux sz'
n) <>
None.
Proof.
intros.
destruct new_sz_msk as [
A|
A].
-
rewrite <-
mk_block_list_aux_ext with (
sz:=
sz);
auto.
intros;
destruct (
peq i b);
subst;
auto.
rewrite sz_ext;
auto.
-
eapply allocs_blocks_free';
eauto.
Qed.
Lemma alloc_mem_al_pos:
forall l al s m s'
m',
alloc_mem_al al l (
s,
m) = (
s',
m') ->
forall b,
~
In b (
map fst l) ->
m'
b =
m b.
Proof.
induction l; simpl; intros.
inv H; auto.
des a.
apply IHl with (b:=b) in H; auto.
rewrite H. destr.
Qed.
Lemma mbla_not_above:
forall sz n b,
(
n <
Pos.to_nat b)%
nat ->
~
In b (
map fst (
mk_block_list_aux sz n)).
Proof.
induction n.
simpl;
intros;
auto.
intros.
rewrite mbla_rew.
simpl.
destr.
subst.
rewrite Nat2Pos.id in H;
omega.
apply IHn in H1;
auto.
omega.
Qed.
Lemma compat_alloc_range_al:
forall sz n b
(
inf: (
Pos.to_nat b <=
n)%
nat)
size0 m0 size m
(
size0pos: 0 <=
size0)
(
ALLOC :
alloc_mem_al 8 (
mk_block_list_aux sz n) (
size0,
m0) =
(
size,
m)),
size0 <=
m b /\
m b +
Z.max 0 (
sz b) <=
size.
Proof.
Lemma compat_alloc_range_al':
forall l (
nr:
list_norepet (
map fst l))
size0 m0 size m
(
size0pos: 0 <=
size0)
(
ALLOC :
alloc_mem_al 8
l (
size0,
m0) = (
size,
m))
b szb
(
inf:
In (
b,
szb)
l),
size0 <=
m b /\
m b +
Z.max 0
szb <=
size.
Proof.
Lemma compat_alloc_aligned_al:
forall l size0 m0 size m b
(
i:
In b (
map fst l))
(
ALLOC :
alloc_mem_al (
two_power_nat 3)
l (
size0,
m0) =
(
size,
m)),
Z.divide 8 (
m b).
Proof.
Lemma compat_alloc_range:
forall sz n size m
(
ALLOC:
alloc_mem_aux (
mk_block_list_aux sz n) = (
size,
m)),
forall b,
(
Pos.to_nat b <=
n)%
nat ->
8 <=
m b /\
m b +
Z.max 0 (
sz b) <=
size.
Proof.
Lemma blocks_not_empty_in:
forall b sz,
forall n,
(
Pos.to_nat b <=
n)%
nat ->
In (
b,
sz b) (
mk_block_list_aux sz n).
Proof.
induction n;
intros.
xomega.
apply le_lt_or_eq in H;
destruct H.
-
rewrite mbla_rew.
simpl.
right.
apply IHn;
omega.
-
clear IHn.
rewrite mbla_rew;
simpl.
rewrite <-
H.
rewrite Pos2Nat.id.
auto.
Qed.
Lemma compat_alloc_aligned:
forall sz n size m
(
ALLOC:
alloc_mem_aux (
mk_block_list_aux sz n) = (
size,
m)),
forall b,
(
Pos.to_nat b <=
n)%
nat ->
Z.divide 8 (
m b).
Proof.
Lemma compat_alloc_overlap_al:
forall sz l b b'
s0 m0 s m
(
s0sup: 0 <=
s0)
(
ALLOC:
alloc_mem_al 8
l (
s0,
m0) = (
s,
m))
(
nr:
list_norepet (
map fst l))
(
SZb':
sz b' > 0)
(
diff:
b <>
b')
(
i1:
In (
b',
sz b')
l)
(
i0:
In (
b,
sz b)
l),
~
m b <=
m b' <
m b +
Z.max 0 (
sz b).
Proof.
Opaque mk_block_list_aux.
Lemma mbla_norepet:
forall sz n,
list_norepet (
map fst (
mk_block_list_aux sz n)).
Proof.
Lemma compat_alloc_no_overlap:
forall sz n size m
(
ALLOC:
alloc_mem_aux (
mk_block_list_aux sz n) = (
size,
m)),
forall b b',
b <>
b' ->
(
Pos.to_nat b <=
n)%
nat ->
(
Pos.to_nat b' <=
n)%
nat ->
sz b' > 0 ->
~ (
m b <=
m b' <
m b +
Z.max 0 (
sz b)).
Proof.
Lemma compat_alloc:
forall (
sz:
block ->
Z*
Z)
sz'
msk
(
MSKeq:
forall b,
msk b =
Int.not (
Int.repr (
two_power_nat (
alignment_of_size (
sz'
b)) - 1)))
(
lo0:
forall b,
fst (
sz b) <= 0)
(
SZeq:
forall b,
let (
lo,
hi) :=
sz b in sz'
b =
hi -
lo)
n al
(
SZabove:
forall b, (
Pos.to_nat b >
n)%
nat ->
sz b = (0, 0))
(
ALLOC:
alloc_blocks (
mk_block_list_aux sz'
n) =
Some al),
compat al sz msk.
Proof.
Lemma mk_block_list_aux_ext':
forall (
m :
nat) (
sz sz' :
positive ->
Z),
(
forall i :
positive,
Plt i (
Pos.of_nat m) ->
sz i =
sz'
i) ->
mk_block_list_aux sz (
pred m) =
mk_block_list_aux sz' (
pred m).
Proof.