(* First draft specs.  Not specifying that chunks are aligned. *)
Instance CompSpecs : compspecs. make_compspecs prog. Defined.
Definition Vprog : varspecs. mk_varspecs prog. Defined.
Local Open Scope Z.
Local Open Scope logic.
(* TODO Initially I imagined the constants would be defined as parameters (with suitable assumptions, e.g., BIGBLOCK needs to be big enough for at least one chunk of the largest size, because fill_bin unconditionally initializes the last chunk. *)
Definition WORD: Z := 4. (* sizeof(size_t) 4 for 32bit Clight; 8 in clang *)
Definition ALIGN: Z := 2.
Definition BINS: Z := 8.
Parameter BIGBLOCK: Z.
Parameter BIGBLOCK_def:
Int.repr BIGBLOCK = Int.mul (Int.shl (Int.repr 2) (Int.repr 16)) (Int.repr WORD).
Definition bin2sizeZ := fun b: Z => (Z.mul ((Z.mul (b+1) ALIGN)-1) WORD).
Definition size2binZ : Z -> Z := fun s =>
if zlt (bin2sizeZ(BINS-1)) s then -1
else (s+(Z.mul WORD (ALIGN-1))-1) / (Z.mul WORD ALIGN).
Eval compute in bin2sizeZ (BINS-1).
Example bin2sizeBINS: bin2sizeZ (BINS-1) = 60. Proof. reflexivity. Qed.
(* Hint Unfold WORD ALIGN : myDB. auto with myDB *)
(* Some sanity checks; may not be needed for code verification. *)
Definition sbrk_spec :=
(* like malloc without token; and I removed the possibility of failure to streamline the proof of fill_bin *)
DECLARE _sbrk
WITH n:Z
PRE [ 1%positive OF tuint ]
PROP (0 <= n <= Int.max_unsigned)
LOCAL (temp 1%positive (Vint (Int.repr n)))
SEP ()
POST [ tptr tvoid ] EX p:_,
PROP ()
LOCAL (temp ret_temp p)
SEP ( (* if eq_dec p nullval then emp else memory_block Tsh n p) *)
memory_block Tsh n p).
Definition bin2size_spec :=
DECLARE _bin2size
WITH b: Z
PRE [ _b OF tint ]
PROP( 0 <= b <= Int.max_signed )
LOCAL (temp _b (Vint (Int.repr b))) SEP ()
POST [ tuint ]
PROP() LOCAL(temp ret_temp (Vint (Int.repr (bin2sizeZ b)))) SEP ().
Definition size2bin_spec :=
DECLARE _size2bin
WITH s: Z
PRE [ _s OF tuint ]    (* Vlong? *)
PROP( 0 <= s <= Int.max_unsigned )
LOCAL (temp _s (Vint (Int.repr s))) SEP ()
POST [ tint ]
PROP() LOCAL(temp ret_temp (Vint (Int.repr (size2binZ s)))) SEP ().
(* malloc token, which accounts for the size field and padding. * n is the size requested * Unfolding the definition reveals the stored size value and the * actual size of the block. * Note that offset_val is in bytes, not like C pointer arith. *)
Definition malloc_token' (sh: share) (n: Z) (p: val): mpred :=
data_at Tsh tuint (offset_val (- WORD) p) (Vint (Int.repr n))
* memory_block Tsh ((bin2sizeZ(size2binZ(n)) - n)) (offset_val n p).

Lemma malloc_token'_precise:
forall sh n p, predicates_sl.precise (malloc_token' sh n p).