Instance CompSpecs : compspecs. make_compspecs prog. Defined.
Definition Vprog : varspecs. mk_varspecs prog. Defined.
(* This program, and its verification, are described in Chapter 29 of _Program Logics for Certified Compilers_, by Appel et al., 2014 *)
Local Open Scope Z.
Local Open Scope logic.
(*   mf_assert msgfmt sh buf len data  := the [data] is formatted into a message at most [len] bytes,  stored starting at address [buf] with share [sh] *)
Record message_format (t: type) : Type :=
mf_build {
mf_size: Z;
mf_data_assert: forall (data: reptype t), Prop;
mf_assert: forall (sh: share) (buf: val) (len: Z) (data: reptype t), mpred;
mf_size_range:  0 <= mf_size <= Int.max_signed;
mf_bufprop: forall sh buf len data,
mf_assert sh buf len data |--
!!(0 <= len <= mf_size) && memory_block sh len buf;
mf_restbuf := fun (sh: share) (buf: val) (len: Z) =>
memory_block sh (mf_size-len) (offset_val len buf)
}.
Arguments mf_build {t}.
Arguments mf_size {t}.
Arguments mf_data_assert {t}.
Arguments mf_assert {t}.
Arguments mf_bufprop {t}.
Arguments mf_size_range {t}.
Arguments mf_restbuf {t}.
Definition t_struct_intpair := Tstruct _intpair noattr.
Definition t_struct_message := Tstruct _message noattr.
Program Definition intpair_message: message_format t_struct_intpair :=
mf_build 8 (fun data => is_int I32 Signed (fst data) /\ is_int I32 Signed (snd data))
(fun sh buf len data => !!(len=8/\ is_int I32 Signed (fst data) /\ is_int I32 Signed (snd data))
&& data_at sh (tarray tint 2) [fst data; snd data] buf)
_ _.
Next Obligation.
compute; split; congruence.
Qed.
Next Obligation.
entailer!.
change 8 with (sizeof (tarray tint 2)).
apply data_at_memory_block.
Qed.
Definition serialize_spec {t: type} (format: message_format t) :=
WITH data: reptype t, p: val, buf: val, sh: share, sh': share
PRE [ _p OF (tptr tvoid), _buf OF (tptr tuchar) ]
PROP (readable_share sh; writable_share sh';
mf_data_assert format data;
align_compatible tint buf)
LOCAL (temp _p p; temp _buf buf)
SEP (data_at sh t data p;
memory_block sh' (mf_size format) buf)
POST [ tint ]
EX len: Z,
PROP() LOCAL (temp ret_temp (Vint (Int.repr len)))
SEP( data_at sh t data p;
mf_assert format sh' buf len data;
mf_restbuf format sh' buf len).
Definition deserialize_spec {t: type} (format: message_format t) :=
WITH data: reptype t, p: val, buf: val, sh: share, sh': share, len: Z
PRE [ _p OF (tptr tvoid), _buf OF (tptr tuchar), _length OF tint ]
PROP (readable_share sh'; writable_share sh;
0 <= len <= mf_size format)
LOCAL (temp _p p;
temp _buf buf;
temp _length (Vint (Int.repr len)))
SEP (mf_assert format sh' buf len data;
data_at_ sh t p)
POST [ tvoid ]
PROP (mf_data_assert format data)  LOCAL ()
SEP (mf_assert format sh' buf len data;
data_at sh t data p).
Definition intpair_serialize_spec :=
DECLARE _intpair_serialize (serialize_spec intpair_message).
Definition intpair_deserialize_spec :=
DECLARE _intpair_deserialize (deserialize_spec intpair_message).
Definition main_spec :=
DECLARE _main
WITH gv: globals
PRE  [] main_pre prog tt nil gv
POST [ tint ] main_post prog nil gv.
Definition message (sh: share) {t: type} (format: message_format t) (m: val) : mpred :=
EX fg: val*val,
func_ptr' (serialize_spec format) (fst fg) *
func_ptr' (deserialize_spec format) (snd fg) *
data_at sh t_struct_message (Vint (Int.repr (mf_size format)), (fst fg, snd fg)) m.
Definition Gprog : funspecs :=   ltac:(with_library prog [
intpair_serialize_spec; intpair_deserialize_spec; main_spec]).

Lemma body_intpair_serialize: semax_body Vprog Gprog f_intpair_serialize intpair_serialize_spec.