Open Scope logic.
Instance CompSpecs : compspecs. make_compspecs prog. Defined.
Definition Vprog : varspecs. mk_varspecs prog. Defined.
Definition t_struct_elem := Tstruct _elem noattr.
Definition t_struct_fifo := Tstruct _fifo noattr.
Instance QS: listspec _elem _next (fun sh => malloc_token Ews t_struct_elem).
Definition surely_malloc_spec :=
DECLARE _surely_malloc
WITH t:type, gv: globals
PRE [ _n OF tuint ]
PROP (0 <= sizeof t <= Int.max_unsigned;
complete_legal_cosu_type t = true;
natural_aligned natural_alignment t = true)
LOCAL (temp _n (Vint (Int.repr (sizeof t))); gvars gv)
SEP (mem_mgr gv)
POST [ tptr tvoid ] EX p:_,
PROP ()
LOCAL (temp ret_temp p)
SEP (mem_mgr gv; malloc_token Ews t p * data_at_ Ews t p).
Definition fifo_body (contents: list val) (hd tl : val) :=
(if isnil contents
then (!!(hd=nullval) && emp)
else (EX prefix: list val, EX last: val,
!!(contents = prefix++last::nil)
&&  (lseg QS Ews prefix hd tl
* malloc_token Ews t_struct_elem tl
* data_at Ews t_struct_elem (last, nullval) tl)))%logic.
Definition fifo (contents: list val) (p: val) : mpred :=
EX ht: (val*val), let (hd,tl) := ht in
!! is_pointer_or_null hd && !! is_pointer_or_null tl &&
data_at Ews t_struct_fifo (hd, tl) p * malloc_token Ews t_struct_fifo p *
fifo_body contents hd tl.
Definition fifo_new_spec :=
DECLARE _fifo_new
WITH gv: globals
PRE  [  ]
PROP() LOCAL(gvars gv) SEP (mem_mgr gv)
POST [ (tptr t_struct_fifo) ]
EX v:val, PROP() LOCAL(temp ret_temp v) SEP (mem_mgr gv; fifo nil v).
Definition fifo_put_spec :=
DECLARE _fifo_put
WITH q: val, contents: list val, p: val, last: val
PRE  [ _Q OF (tptr t_struct_fifo) , _p OF (tptr t_struct_elem) ]
PROP () LOCAL (temp _Q q; temp _p p)
SEP (fifo contents q;
malloc_token Ews t_struct_elem p;
data_at Ews t_struct_elem (last,Vundef) p)
POST [ tvoid ]
PROP() LOCAL() SEP (fifo (contents++(last :: nil)) q).
Definition fifo_empty_spec :=
DECLARE _fifo_empty
WITH q: val, contents: list val
PRE  [ _Q OF (tptr t_struct_fifo) ]
PROP() LOCAL (temp _Q q) SEP(fifo contents q)
POST [ tint ]
PROP ()
LOCAL(temp ret_temp (if isnil contents then Vtrue else Vfalse))
SEP (fifo (contents) q).
Definition fifo_get_spec :=
DECLARE _fifo_get
WITH q: val, contents: list val, first: val
PRE  [ _Q OF (tptr t_struct_fifo) ]
PROP() LOCAL (temp _Q q) SEP (fifo (first :: contents) q)
POST [ (tptr t_struct_elem) ]
EX p:val,
PROP ()
LOCAL(temp ret_temp p)
SEP (fifo contents q;
malloc_token Ews t_struct_elem p;
data_at Ews t_struct_elem (first,Vundef) p).
Definition make_elem_spec :=
DECLARE _make_elem
WITH i: int, gv: globals
PRE  [ _data OF tint ]
PROP() LOCAL(temp _data (Vint i); gvars gv) SEP(mem_mgr gv)
POST [ (tptr t_struct_elem) ]
EX p:val,
PROP()
LOCAL (temp ret_temp p)
SEP (mem_mgr gv;
malloc_token Ews t_struct_elem p;
data_at Ews t_struct_elem (Vint i, Vundef) p).
Definition main_spec :=
DECLARE _main
WITH gv: globals
PRE  [] main_pre prog tt nil gv
POST [ tint ]
PROP() LOCAL (temp ret_temp (Vint (Int.repr 1))) SEP(TT).
Definition Gprog : funspecs :=
ltac:(with_library prog
[surely_malloc_spec; fifo_new_spec; fifo_put_spec;
fifo_empty_spec; fifo_get_spec; make_elem_spec;
main_spec]).
Hint Resolve fifo_isptr : saturate_local.

Lemma body_fifo_get: semax_body Vprog Gprog f_fifo_get fifo_get_spec.