(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
(* Require Import VST.floyd.proofauto.
   TEMPORARILY replace "floyd.proofauto"
   with all the imports in the list below.
   This reduces makefile-based recompilation
   when changing things in (e.g.) forward.v
*)
Require Import VST.floyd.base2.
Require Import VST.floyd.client_lemmas.
Require Import VST.floyd.closed_lemmas.
Require Import VST.floyd.nested_pred_lemmas.
Require Import VST.floyd.nested_field_lemmas.
Require Import VST.floyd.efield_lemmas.
Require Import VST.floyd.mapsto_memory_block.
Require Import VST.floyd.reptype_lemmas.
Require VST.floyd.aggregate_pred. Import VST.floyd.aggregate_pred.aggregate_pred.
Require Import VST.floyd.data_at_rec_lemmas.
Require Import VST.floyd.field_at.
Require Import VST.floyd.nested_loadstore.
(*Require Import VST.floyd.unfold_data_at.*)
Require Import VST.floyd.entailer.
(*  End TEMPORARILY *)

Lemma int64_eq_e: forall i j, Int64.eq i j = true -> i=j.
(* Goal: forall (v' : @elemtype cs list_structid list_link list_token ls) (ash bsh psh : share) (p : val) (v : @elemtype cs list_structid list_link list_token ls) (_ : @sepalg.join share Share.Join_ba ash bsh psh) (_ : not (readable_share ash)) (_ : readable_share bsh), @eq mpred (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls ash v' p) (@list_cell cs list_structid list_link list_token ls bsh v p)) (@list_cell cs list_structid list_link list_token ls psh v p) *)
Proof. intros. pose proof (Int64.eq_spec i j); rewrite H in H0; auto. Qed.

Lemma ptrofs_eq_e: forall i j, Ptrofs.eq i j = true -> i=j.
(* Goal: forall (v' : @elemtype cs list_structid list_link list_token ls) (ash bsh psh : share) (p : val) (v : @elemtype cs list_structid list_link list_token ls) (_ : @sepalg.join share Share.Join_ba ash bsh psh) (_ : not (readable_share ash)) (_ : readable_share bsh), @eq mpred (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls ash v' p) (@list_cell cs list_structid list_link list_token ls bsh v p)) (@list_cell cs list_structid list_link list_token ls psh v p) *)
Proof. intros. pose proof (Ptrofs.eq_spec i j); rewrite H in H0; auto. Qed.

Lemma allp_andp1  {A}{ND: NatDed A}:  forall B (any: B) (p: B -> A) q, andp (allp p) q = (allp (fun x => andp (p x) q)).
Proof.
(* Goal: forall (v' : @elemtype cs list_structid list_link list_token ls) (ash bsh psh : share) (p : val) (v : @elemtype cs list_structid list_link list_token ls) (_ : @sepalg.join share Share.Join_ba ash bsh psh) (_ : not (readable_share ash)) (_ : readable_share bsh), @eq mpred (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls ash v' p) (@list_cell cs list_structid list_link list_token ls bsh v p)) (@list_cell cs list_structid list_link list_token ls psh v p) *)
 intros. apply pred_ext.
(* Goal: @derives A ND (@allp A ND B (fun x : B => @andp A ND (p x) q)) (@allp A ND B p) *)
(* Goal: @derives A ND (@allp A ND B (fun x : B => @andp A ND (p x) q)) q *)
 apply allp_right; intro x.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@andp mpred Nveric (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) (@emp mpred Nveric Sveric))) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
(* Goal: @derives mpred Nveric (lseg_cons ls dsh psh (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) p q) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@orp mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) p q)) *)
 apply andp_derives; auto. apply allp_left with x; auto.
(* Goal: @derives A ND (@allp A ND B (fun x : B => @andp A ND (p x) q)) (@allp A ND B p) *)
(* Goal: @derives A ND (@allp A ND B (fun x : B => @andp A ND (p x) q)) q *)
 apply andp_right. apply allp_right; intro x. apply allp_left with x. apply andp_left1; auto.
(* Goal: @derives A ND (@allp A ND B (fun x : B => @andp A ND (p x) q)) q *)
 apply allp_left with any. apply andp_left2; auto.
Qed.

Lemma allp_andp2  {A}{ND: NatDed A}:  forall B (any: B) p (q: B -> A),
     andp p (allp q) = (allp (fun x => andp p (q x))).
Proof.
(* Goal: forall (v' : @elemtype cs list_structid list_link list_token ls) (ash bsh psh : share) (p : val) (v : @elemtype cs list_structid list_link list_token ls) (_ : @sepalg.join share Share.Join_ba ash bsh psh) (_ : not (readable_share ash)) (_ : readable_share bsh), @eq mpred (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls ash v' p) (@list_cell cs list_structid list_link list_token ls bsh v p)) (@list_cell cs list_structid list_link list_token ls psh v p) *)
intros. rewrite andp_comm. rewrite allp_andp1; auto.
(* Goal: @eq mpred (@prop mpred Nveric (ptr_eq v v)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) *)
(* Goal: @eq mpred (let (p, h) := p in @andp mpred Nveric (@prop mpred Nveric (and (@eq val p v) (not (ptr_eq v v)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh v)) (@list_cell cs list_structid list_link list_token ls dsh h v)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) v)) (lseg ls dsh psh l tail v)))) (@andp mpred Nveric (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) p l) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) (@emp mpred Nveric Sveric)) *)
f_equal. extensionality x. rewrite andp_comm; auto.
Qed.

Lemma valid_pointer_offset_val_zero:
  forall p, valid_pointer (offset_val 0 p) = valid_pointer p.
Proof.
Admitted.

Local Open Scope logic.

Class listspec {cs: compspecs} (list_structid: ident) (list_link: ident) (token: share -> val -> mpred):=
  mk_listspec {
   list_fields: members;
   list_struct := Tstruct list_structid noattr;
   list_members_eq: list_fields = co_members (get_co list_structid);
   list_struct_complete_legal_cosu: complete_legal_cosu_type list_struct = true; (* TODO: maybe this line not useful? *)
   list_link_type: nested_field_type list_struct (StructField list_link :: nil) = Tpointer list_struct noattr;
   list_token := token
}.

Section LIST1.
Context {cs: compspecs}.
Context  {list_structid: ident} {list_link: ident} {list_token: share -> val -> mpred}.

Fixpoint all_but_link (f: members) : members :=
 match f with
 | nil => nil
 | cons it f' => if ident_eq (fst it) list_link
                               then f'
                               else cons it (all_but_link f')
 end.

Lemma list_link_size_in_range (ls: listspec list_structid list_link list_token):
  0 < sizeof (nested_field_type list_struct (StructField list_link :: nil)) < Ptrofs.modulus.
Proof.
(* Goal: and (Z.lt Z0 (@sizeof (@cenv_cs cs) (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))))) (Z.lt (@sizeof (@cenv_cs cs) (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)))) Ptrofs.modulus) *)
  rewrite list_link_type.
(* Goal: and (Z.lt Z0 (@sizeof (@cenv_cs cs) (Tpointer (@list_struct cs list_structid list_link list_token ls) noattr))) (Z.lt (@sizeof (@cenv_cs cs) (Tpointer (@list_struct cs list_structid list_link list_token ls) noattr)) Ptrofs.modulus) *)
  unfold sizeof.
(* Goal: and (Z.lt Z0 (if Archi.ptr64 then Zpos (xO (xO (xO xH))) else Zpos (xO (xO xH)))) (Z.lt (if Archi.ptr64 then Zpos (xO (xO (xO xH))) else Zpos (xO (xO xH))) Ptrofs.modulus) *)
  destruct Archi.ptr64 eqn:Hp.
(* Goal: and (Z.lt Z0 (Zpos (xO (xO (xO xH))))) (Z.lt (Zpos (xO (xO (xO xH)))) Ptrofs.modulus) *)
(* Goal: and (Z.lt Z0 (Zpos (xO (xO xH)))) (Z.lt (Zpos (xO (xO xH))) Ptrofs.modulus) *)
  rewrite Ptrofs.modulus_eq64 by auto; computable.
(* Goal: and (Z.lt Z0 (Zpos (xO (xO xH)))) (Z.lt (Zpos (xO (xO xH))) Ptrofs.modulus) *)
  rewrite Ptrofs.modulus_eq32 by auto; computable.
Qed.

Definition elemtype (ls: listspec list_structid list_link list_token) :=
  compact_prod
  (map (fun it => reptype (field_type (fst it) list_fields)) (all_but_link list_fields)).

Definition field_type'  (F: members) (it: ident * type) :=
   reptype (field_type (fst it) F).

Definition add_link_back' {F f: members}
  (v: compact_prod (map (field_type' F) (all_but_link f))) :
  compact_prod (map (field_type' F) f).
(* Goal: compact_prod (@map (prod ident type) Type (field_type' F) f) *)
  induction f as [| it0 f].
  + exact tt.
  +  destruct f as [| it1 f0].
    - exact (default_val _).
    - change (all_but_link (it0 :: it1 :: f0))
       with (if ident_eq (fst it0) list_link
                               then it1::f0
                               else cons it0 (all_but_link (it1::f0)))
       in v.
(* Goal: compact_prod (@map (prod ident type) Type (field_type' F) (@cons (prod ident type) it0 (@cons (prod ident type) it1 f0))) *)
       change (reptype (field_type (fst it0) F) * compact_prod (map (field_type' F) (it1::f0)))%type.
(* Goal: prod (@reptype cs (field_type (@fst ident type it0) F)) (compact_prod (@map (prod ident type) Type (field_type' F) (@cons (prod ident type) it1 f0))) *)
       destruct (ident_eq (fst it0) list_link).
(* Goal: prod (@reptype cs (field_type (@fst ident type it0) F)) (compact_prod (@map (prod ident type) Type (field_type' F) (@cons (prod ident type) it1 f0))) *)
(* Goal: prod (@reptype cs (field_type (@fst ident type it0) F)) (compact_prod (@map (prod ident type) Type (field_type' F) (@cons (prod ident type) it1 f0))) *)
       exact (default_val _, v).
(* Goal: prod (@reptype cs (field_type (@fst ident type it0) F)) (compact_prod (@map (prod ident type) Type (field_type' F) (@cons (prod ident type) it1 f0))) *)
       destruct (all_but_link (it1 :: f0)) eqn:?.
(* Goal: prod (@reptype cs (field_type (@fst ident type it0) F)) (compact_prod (@map (prod ident type) Type (field_type' F) (@cons (prod ident type) it1 f0))) *)
(* Goal: prod (@reptype cs (field_type (@fst ident type it0) F)) (compact_prod (@map (prod ident type) Type (field_type' F) (@cons (prod ident type) it1 f0))) *)
       simpl in Heqm.
(* Goal: prod (@reptype cs (field_type (@fst ident type it0) F)) (compact_prod (@map (prod ident type) Type (field_type' F) (@cons (prod ident type) it1 f0))) *)
(* Goal: prod (@reptype cs (field_type (@fst ident type it0) F)) (compact_prod (@map (prod ident type) Type (field_type' F) (@cons (prod ident type) it1 f0))) *)
       destruct (ident_eq (fst it1) list_link); [ | discriminate Heqm].
(* Goal: prod (@reptype cs (field_type (@fst ident type it0) F)) (compact_prod (@map (prod ident type) Type (field_type' F) (@cons (prod ident type) it1 f0))) *)
(* Goal: prod (@reptype cs (field_type (@fst ident type it0) F)) (compact_prod (@map (prod ident type) Type (field_type' F) (@cons (prod ident type) it1 f0))) *)
        subst f0.
(* Goal: prod (@reptype cs (field_type (@fst ident type it0) F)) (compact_prod (@map (prod ident type) Type (field_type' F) (@cons (prod ident type) it1 (@nil (prod ident type))))) *)
(* Goal: prod (@reptype cs (field_type (@fst ident type it0) F)) (compact_prod (@map (prod ident type) Type (field_type' F) (@cons (prod ident type) it1 f0))) *)
        exact (v, default_val _).
(* Goal: prod (@reptype cs (field_type (@fst ident type it0) F)) (compact_prod (@map (prod ident type) Type (field_type' F) (@cons (prod ident type) it1 f0))) *)
        exact (fst v, IHf (snd v)).
Defined.

Definition add_link_back
 (F f : members)
  (v : compact_prod
         (map (fun it : ident * type => reptype (field_type (fst it) F))
            (all_but_link f)))
  : compact_prod (map (fun it => reptype (field_type (fst it) F)) f)
  :=
list_rect
  (fun f0 : list (ident * type) =>
   compact_prod (map (field_type' F) (all_but_link f0)) ->
   compact_prod (map (field_type' F) f0))
  (fun _ : compact_prod (map (field_type' F) (all_but_link nil)) => tt)
  (fun (it0 : ident * type) (f0 : list (ident * type))
     (IHf : compact_prod (map (field_type' F) (all_but_link f0)) ->
            compact_prod (map (field_type' F) f0))
     (v0 : compact_prod (map (field_type' F) (all_but_link (it0 :: f0)))) =>
   match
     f0 as l
     return
       (compact_prod (map (field_type' F) (all_but_link (it0 :: l))) ->
        (compact_prod (map (field_type' F) (all_but_link l)) ->
         compact_prod (map (field_type' F) l)) ->
        compact_prod (map (field_type' F) (it0 :: l)))
   with
   | nil =>
       fun
         (_ : compact_prod (map (field_type' F) (all_but_link (it0 :: nil))))
         (_ : compact_prod (map (field_type' F) (all_but_link nil)) ->
              compact_prod (map (field_type' F) nil)) =>
       default_val (field_type (fst it0) F)
   | it1 :: f1 =>
       fun
         (v1 : compact_prod
                 (map (field_type' F) (all_but_link (it0 :: it1 :: f1))))
         (IHf0 : compact_prod
                   (map (field_type' F) (all_but_link (it1 :: f1))) ->
                 compact_prod (map (field_type' F) (it1 :: f1))) =>
       (if ident_eq (fst it0) list_link as s0
         return
           (compact_prod
              (map (field_type' F)
                 (if s0 then it1 :: f1 else it0 :: all_but_link (it1 :: f1))) ->
            reptype (field_type (fst it0) F) *
            compact_prod (map (field_type' F) (it1 :: f1)))
        then
         fun v2 : compact_prod (map (field_type' F) (it1 :: f1)) =>
         (default_val (field_type (fst it0) F), v2)
        else
         fun
           v2 : compact_prod
                  (map (field_type' F) (it0 :: all_but_link (it1 :: f1))) =>
         match
           all_but_link (it1 :: f1) as l
           return
             (all_but_link (it1 :: f1) = l ->
              compact_prod (map (field_type' F) (it0 :: l)) ->
              (compact_prod (map (field_type' F) l) ->
               compact_prod (map (field_type' F) (it1 :: f1))) ->
              reptype (field_type (fst it0) F) *
              compact_prod (map (field_type' F) (it1 :: f1)))
         with
         | nil =>
             fun (Heqm0 : all_but_link (it1 :: f1) = nil)
               (v3 : compact_prod (map (field_type' F) (it0 :: nil)))
               (IHf1 : compact_prod (map (field_type' F) nil) ->
                       compact_prod (map (field_type' F) (it1 :: f1))) =>
             let s0 := ident_eq (fst it1) list_link in
             (if s0
               return
                 ((if s0 then f1 else it1 :: all_but_link f1) = nil ->
                  reptype (field_type (fst it0) F) *
                  compact_prod (map (field_type' F) (it1 :: f1)))
              then
               fun Heqm1 : f1 = nil =>
               eq_rect_r
                 (fun f2 : members =>
                  (compact_prod (map (field_type' F) nil) ->
                   compact_prod (map (field_type' F) (it1 :: f2))) ->
                  reptype (field_type (fst it0) F) *
                  compact_prod (map (field_type' F) (it1 :: f2)))
                 (fun
                    _ : compact_prod (map (field_type' F) nil) ->
                        compact_prod (map (field_type' F) (it1 :: nil)) =>
                  (v3, default_val (field_type (fst it1) F)))
                 Heqm1 IHf1
              else
               fun Heqm1 : it1 :: all_but_link f1 = nil =>
                 False_rect
                   (reptype (field_type (fst it0) F) *
                    compact_prod (map (field_type' F) (it1 :: f1)))
                 (eq_rect (it1 :: all_but_link f1)
                    (fun e : members =>
                     match e with
                     | nil => False
                     | _ :: _ => True
                     end) I nil Heqm1)) Heqm0
         | p :: m0 =>
             fun (_ : all_but_link (it1 :: f1) = p :: m0)
               (v3 : compact_prod (map (field_type' F) (it0 :: p :: m0)))
               (IHf1 : compact_prod (map (field_type' F) (p :: m0)) ->
                       compact_prod (map (field_type' F) (it1 :: f1))) =>
             (fst v3, IHf1 (snd v3))
         end eq_refl v2 IHf0) v1
   end v0 IHf) f v.

(*
Definition add_link_back {ls: listspec list_structid list_link} {f F: members}
  (v: compact_prod (map (fun it => reptype (field_type (fst it) F)) (all_but_link f))) :
  compact_prod (map (fun it => reptype (field_type (fst it) F)) f).
  unfold all_but_link in v.
  induction f as [| [i0 t0] f].
  + exact tt.
  + simpl in *; destruct f as [| [i1 t1] f0] eqn:?; [| destruct (ident_eq i0 list_link)].
    - exact (default_val _).
    - exact (default_val _, v).
    - fold (all_but_link ((i1, t1) :: f0)) in IHf, v.
      destruct (all_but_link ((i1, t1) :: f0)) eqn:?.
(* Goal: prod (@reptype cs (field_type (@fst ident type it0) F)) (compact_prod (@map (prod ident type) Type (field_type' F) (@cons (prod ident type) it1 f0))) *)
(* Goal: prod (@reptype cs (field_type (@fst ident type it0) F)) (compact_prod (@map (prod ident type) Type (field_type' F) (@cons (prod ident type) it1 f0))) *)
      * simpl in Heqm.
        if_tac in Heqm; [| congruence].
(* Goal: prod (@reptype cs (field_type (@fst ident type it0) F)) (compact_prod (@map (prod ident type) Type (field_type' F) (@cons (prod ident type) it1 f0))) *)
(* Goal: prod (@reptype cs (field_type (@fst ident type it0) F)) (compact_prod (@map (prod ident type) Type (field_type' F) (@cons (prod ident type) it1 f0))) *)
        subst f0.
(* Goal: prod (@reptype cs (field_type (@fst ident type it0) F)) (compact_prod (@map (prod ident type) Type (field_type' F) (@cons (prod ident type) it1 (@nil (prod ident type))))) *)
(* Goal: prod (@reptype cs (field_type (@fst ident type it0) F)) (compact_prod (@map (prod ident type) Type (field_type' F) (@cons (prod ident type) it1 f0))) *)
        exact (v, default_val _).
(* Goal: prod (@reptype cs (field_type (@fst ident type it0) F)) (compact_prod (@map (prod ident type) Type (field_type' F) (@cons (prod ident type) it1 f0))) *)
      * exact (fst v, IHf (snd v)).
Defined.
*)

Definition list_data {ls: listspec list_structid list_link list_token} (v: elemtype ls): reptype list_struct.
(* Goal: @reptype cs (@list_struct cs list_structid list_link list_token ls) *)
  unfold list_struct.
(* Goal: @reptype cs (Tstruct list_structid noattr) *)
  pose (add_link_back _ _ v: reptype_structlist _).
(* Goal: @reptype cs (Tstruct list_structid noattr) *)
  rewrite list_members_eq in r.
(* Goal: @reptype cs (Tstruct list_structid noattr) *)
  exact (@fold_reptype _ (Tstruct _ _) r).
Defined.

Definition list_cell' (ls: listspec list_structid list_link list_token) sh v p :=
  (field_at_ sh list_struct (StructField list_link :: nil) p) -* (data_at sh list_struct (list_data v) p).

Definition list_cell (ls: listspec list_structid list_link list_token) (sh: Share.t)
   (v: elemtype ls) (p: val) : mpred :=
   !! field_compatible list_struct nil p &&
   struct_pred (all_but_link list_fields)
              (fun it v => withspacer sh
                (field_offset cenv_cs (fst it) list_fields + sizeof (field_type (fst it) list_fields))
                (field_offset_next cenv_cs (fst it) list_fields (co_sizeof (get_co list_structid)))
                (at_offset (data_at_rec sh (field_type (fst it) list_fields) v) (field_offset cenv_cs (fst it) list_fields)))
     v p.

Lemma struct_pred_type_changable:
  forall m m' A F v v' p p',
  m=m' ->
  JMeq v v' ->
  (forall it v, F it v p = F it v p') ->
  @struct_pred m A F v p = @struct_pred m' A F v' p'.
Proof.
(* Goal: forall (v' : @elemtype cs list_structid list_link list_token ls) (ash bsh psh : share) (p : val) (v : @elemtype cs list_structid list_link list_token ls) (_ : @sepalg.join share Share.Join_ba ash bsh psh) (_ : not (readable_share ash)) (_ : readable_share bsh), @eq mpred (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls ash v' p) (@list_cell cs list_structid list_link list_token ls bsh v p)) (@list_cell cs list_structid list_link list_token ls psh v p) *)
intros.
(* Goal: @eq mpred (@struct_pred m A F v p) (@struct_pred m' A F v' p') *)
subst m'. apply JMeq_eq in H0. subst v'.
(* Goal: @eq mpred (@struct_pred m A F v p) (@struct_pred m A F v p') *)
induction m. reflexivity.
(* Goal: @eq mpred (@struct_pred (@cons (prod ident type) a m) A F v p) (@struct_pred (@cons (prod ident type) a m) A F v p') *)
destruct m.
(* Goal: @eq mpred (@struct_pred (@cons (prod ident type) a (@nil (prod ident type))) A F v p) (@struct_pred (@cons (prod ident type) a (@nil (prod ident type))) A F v p') *)
(* Goal: @eq mpred (@struct_pred (@cons (prod ident type) a (@cons (prod ident type) p0 m)) A F v p) (@struct_pred (@cons (prod ident type) a (@cons (prod ident type) p0 m)) A F v p') *)
destruct a; simpl.
(* Goal: @eq mpred (F (@pair ident type i t) v p) (F (@pair ident type i t) v p') *)
(* Goal: @eq mpred (@struct_pred (@cons (prod ident type) a (@cons (prod ident type) p0 m)) A F v p) (@struct_pred (@cons (prod ident type) a (@cons (prod ident type) p0 m)) A F v p') *)
apply H1.
(* Goal: @eq mpred (@struct_pred (@cons (prod ident type) a (@cons (prod ident type) p0 m)) A F v p) (@struct_pred (@cons (prod ident type) a (@cons (prod ident type) p0 m)) A F v p') *)
rewrite !struct_pred_cons2.
(* Goal: @eq mpred (@prop mpred Nveric (ptr_eq v v)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) *)
(* Goal: @eq mpred (let (p, h) := p in @andp mpred Nveric (@prop mpred Nveric (and (@eq val p v) (not (ptr_eq v v)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh v)) (@list_cell cs list_structid list_link list_token ls dsh h v)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) v)) (lseg ls dsh psh l tail v)))) (@andp mpred Nveric (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) p l) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) (@emp mpred Nveric Sveric)) *)
f_equal.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
auto.
(* Goal: @eq mpred (@struct_pred (@cons (prod ident type) p0 m) A F (@snd (A a) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m with | nil => A p0 | cons T l => prod (A p0) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => prod t (compact_prod T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m)) end v) p) (@struct_pred (@cons (prod ident type) p0 m) A F (@snd (A a) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m with | nil => A p0 | cons T l => prod (A p0) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => prod t (compact_prod T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m)) end v) p') *)
apply IHm.
Qed.

Lemma list_cell_link_join:
  forall (LS: listspec list_structid list_link list_token) sh v p,
   list_cell LS sh v p
   * spacer sh  (field_offset cenv_cs list_link list_fields +
                        sizeof (field_type list_link list_fields))
                        (field_offset_next cenv_cs list_link list_fields
                        (co_sizeof (get_co list_structid)))
           (offset_val 0 p)
   * field_at_ sh list_struct (StructField list_link :: nil) p
     = data_at sh list_struct (list_data v) p.
Proof.
(* Goal: forall (v' : @elemtype cs list_structid list_link list_token ls) (ash bsh psh : share) (p : val) (v : @elemtype cs list_structid list_link list_token ls) (_ : @sepalg.join share Share.Join_ba ash bsh psh) (_ : not (readable_share ash)) (_ : readable_share bsh), @eq mpred (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls ash v' p) (@list_cell cs list_structid list_link list_token ls bsh v p)) (@list_cell cs list_structid list_link list_token ls psh v p) *)
unfold list_cell, data_at_, data_at, field_at_, field_at; intros.
destruct (field_compatible_dec list_struct nil p);
  [ | solve [apply pred_ext; normalize]].
Admitted.
(*
rewrite <- !gather_prop_left.
rewrite !(prop_true_andp _ _ f).
rewrite (prop_true_andp (field_compatible list_struct (StructField list_link :: nil) p))
   by admit.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
normalize.
apply andp_prop_ext.
admit.
intro HV.
clear HV.
change  (nested_field_type list_struct nil) with list_struct.
rewrite (data_at_rec_ind sh list_struct
          (@fold_reptype cs (Tstruct list_structid noattr)
            (@eq_rect members
               (@list_fields cs list_structid list_link LS)
               (fun m : members => @reptype_structlist cs m)
               (@add_link_back
                  (@list_fields cs list_structid list_link LS)
                  (@list_fields cs list_structid list_link LS) v)
               (co_members (@get_co cs list_structid))
               (@list_members_eq cs list_structid list_link LS)))).
(* Goal: @derives mpred Nveric (valid_pointer Vundef) (valid_pointer p) *)
simpl.
forget (co_sizeof (get_co list_structid)) as sz.
assert (FT: field_type list_link list_fields = tptr list_struct).
  admit.
pose (P m := fun (it : ident * type) (v0 : reptype (field_type (fst it) m)) =>
   withspacer sh
     (field_offset cenv_cs (fst it) m +
      sizeof (field_type (fst it) m))
     (field_offset_next cenv_cs (fst it) m sz)
     (at_offset (data_at_rec sh (field_type (fst it) m) v0)
        (field_offset cenv_cs (fst it) m))).
fold (P list_fields).
fold (P (co_members (get_co list_structid))).
transitivity
  (at_offset
  (struct_pred (co_members (get_co list_structid))
     (P (co_members (get_co list_structid)))
     (
           (eq_rect list_fields (fun m : members => reptype_structlist m)
              (add_link_back _ _ v) (co_members (get_co list_structid))
              list_members_eq))) (nested_field_offset list_struct nil) p);
 [ | f_equal; f_equal; rewrite unfold_fold_reptype; reflexivity ].
unfold at_offset.
rewrite (data_at_rec_type_changable sh
                      (nested_field_type list_struct (StructField list_link :: nil))
                      (tptr list_struct)
                      (default_val _) Vundef
                      list_link_type)
  by (rewrite by_value_default_val; try reflexivity;
       rewrite list_link_type; reflexivity).
set (ofs := Int.repr (nested_field_offset list_struct (StructField list_link :: nil))).
assert (Hofs: ofs = Int.repr (field_offset cenv_cs list_link list_fields)). {
  unfold ofs.
  clear.
(* Goal: @eq mpred (@prop mpred Nveric (ptr_eq v v)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) *)
(* Goal: @eq mpred (let (p, h) := p in @andp mpred Nveric (@prop mpred Nveric (and (@eq val p v) (not (ptr_eq v v)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh v)) (@list_cell cs list_structid list_link list_token ls dsh h v)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) v)) (lseg ls dsh psh l tail v)))) (@andp mpred Nveric (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) p l) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) (@emp mpred Nveric Sveric)) *)
  f_equal.
(* Goal: @reptype cs (@list_struct cs list_structid list_link list_token ls) *)
  unfold list_struct.
  pose proof list_link_type.
  unfold nested_field_offset.
(* Goal: @derives mpred Nveric (valid_pointer Vundef) (valid_pointer p) *)
  simpl. rewrite list_members_eq.
(* Goal: False *)
  unfold list_struct, nested_field_type in H; simpl in H.
  destruct (compute_in_members list_link (co_members (get_co list_structid))); inv H.
(* Goal: @eq mpred (@struct_pred (@nil (prod ident type)) A F v p) (@struct_pred (@nil (prod ident type)) A F v p') *)
(* Goal: @eq mpred (@struct_pred (@cons (prod ident type) a m) A F v p) (@struct_pred (@cons (prod ident type) a m) A F v p') *)
  reflexivity.
  }
revert v; unfold elemtype.
fold (field_type' list_fields).
pose (m := list_fields).
pose (m' := co_members (get_co list_structid)).
set (H := list_members_eq).
clearbody H.
revert H.
change (forall (H: m=m')
  (v : compact_prod (map (field_type' list_fields) (all_but_link m))),
struct_pred (all_but_link m) (P list_fields) v p  *
spacer sh
  (field_offset cenv_cs list_link list_fields +
   sizeof (field_type list_link list_fields))
  (field_offset_next cenv_cs list_link list_fields sz)
  p*
data_at_rec sh (tptr list_struct) Vundef
  (offset_val ofs p) =
struct_pred m'
  (P m')
  (eq_rect m reptype_structlist
     (add_link_back list_fields m v) m' H)
  (offset_val (Int.repr 0) p)).
assert  (MNR := get_co_members_no_replicate list_structid).
fold m' in MNR.
revert MNR.
clearbody m'.
(* Goal: forall (v' : @elemtype cs list_structid list_link list_token ls) (ash bsh psh : share) (p : val) (v : @elemtype cs list_structid list_link list_token ls) (_ : @sepalg.join share Share.Join_ba ash bsh psh) (_ : not (readable_share ash)) (_ : readable_share bsh), @eq mpred (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls ash v' p) (@list_cell cs list_structid list_link list_token ls bsh v p)) (@list_cell cs list_structid list_link list_token ls psh v p) *)
intros.
(* Goal: @eq mpred (@struct_pred m A F v p) (@struct_pred m' A F v' p') *)
subst m'.
rewrite <- eq_rect_eq.
assert (In list_link (map fst m)). {
 unfold m.
 rewrite list_members_eq.
 pose proof list_link_type.
 unfold nested_field_type in H.
 unfold list_struct in H. unfold nested_field_rec in H.
 destruct (compute_in_members list_link (co_members (get_co list_structid)))
    eqn:?; inv H.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
 apply compute_in_members_true_iff; auto.
}
change (struct_pred (all_but_link m) (P list_fields) v p  *
spacer sh
  (field_offset cenv_cs list_link list_fields +
   sizeof (field_type list_link list_fields))
  (field_offset_next cenv_cs list_link list_fields sz)
  p*
data_at_rec sh (tptr list_struct) Vundef (offset_val ofs p) =
struct_pred m (P list_fields)
  (add_link_back list_fields m v)
  (offset_val (Int.repr 0) p)).
revert MNR H v; clearbody m.
induction m; intros; [inv H | ].
(* Goal: False *)
 simpl in H.
 assert (H': In list_link (map fst m) -> fst a <> list_link).
  clear - MNR. unfold members_no_replicate in MNR.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh (@fst val (@elemtype cs list_structid list_link list_token ls) (@pair val (@elemtype cs list_structid list_link list_token ls) p h))) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) (@pair val (@elemtype cs list_structid list_link list_token ls) p h)) (@fst val (@elemtype cs list_structid list_link list_token ls) (@pair val (@elemtype cs list_structid list_link list_token ls) p h)))) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) (@fst val (@elemtype cs list_structid list_link list_token ls) (@pair val (@elemtype cs list_structid list_link list_token ls) p h)))) (lseg ls dsh psh r y z)) (@orp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (and (ptr_eq (@fst val (@elemtype cs list_structid list_link list_token ls) (@pair val (@elemtype cs list_structid list_link list_token ls) p h)) z) (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) p h) r) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) p h) r) (@fst val (@elemtype cs list_structid list_link list_token ls) (@pair val (@elemtype cs list_structid list_link list_token ls) p h)) z)) *)
    intros; simpl in *.  destruct (id_in_list (fst a) (map fst m)) eqn:?. inv MNR.
(* Goal: @derives mpred Nveric (@emp mpred Nveric Sveric) (lseg_cons ls dsh psh s v v2) *)
(* Goal: @derives mpred Nveric (lseg_cons ls dsh psh s v v2) (@orp mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq v v2)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) s (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh s v v2)) *)
    apply id_in_list_false in Heqb. intro. congruence.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tl')) (list_token dsh nullval)) (@list_cell cs list_structid list_link list_token ls dsh x nullval)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tl') nullval)) (@emp mpred Nveric Sveric)) (@FF mpred Nveric) *)
 destruct H.
* (* list_link is the first field *)
clear H'.
(* Goal: False *)
destruct a. simpl in H. subst i.
(* Goal: @eq mpred (@struct_pred (@cons (prod ident type) a m) A F v p) (@struct_pred (@cons (prod ident type) a m) A F v p') *)
destruct m.
(* Goal: @derives mpred Nveric (valid_pointer Vundef) (valid_pointer p) *)
Opaque field_offset. Opaque field_type. simpl.
Transparent field_offset. Transparent field_type.
assert ((if ident_eq list_link list_link then nil else (list_link, t) :: nil) = nil)
  by (rewrite if_true; auto).
simpl in v.
assert (exists v' : compact_prod (map (field_type' list_fields) nil), JMeq v' v).  {
  revert H v.
  clear.
  pose (j := if ident_eq list_link list_link
             then @nil (ident * type) else (list_link, t) :: @nil (ident * type)).
  change (j = nil ->
   forall
     v : compact_prod (map (field_type' list_fields) j),
    exists v' : compact_prod (map (field_type' list_fields) nil), JMeq v' v).
  clearbody j.
(* Goal: @eq mpred (@struct_pred (@nil (prod ident type)) A F v p) (@struct_pred (@nil (prod ident type)) A F v p') *)
(* Goal: @eq mpred (@struct_pred (@cons (prod ident type) a m) A F v p) (@struct_pred (@cons (prod ident type) a m) A F v p') *)
  intros; subst. exists v; reflexivity.
}
destruct H0 as [v' ?].
replace (struct_pred
  (if ident_eq list_link list_link then nil else (list_link, t) :: nil)
  (P list_fields) v p) with
  (struct_pred nil (P list_fields) v' p).
Focus 2.
(* Goal: @eq mpred (@struct_pred (@nil (prod ident type)) A F v p) (@struct_pred (@nil (prod ident type)) A F v p') *)
(* Goal: @eq mpred (@struct_pred (@cons (prod ident type) a m) A F v p) (@struct_pred (@cons (prod ident type) a m) A F v p') *)
if_tac; [ | congruence]. reflexivity.
(* Goal: @derives mpred Nveric (valid_pointer Vundef) (valid_pointer p) *)
Opaque field_offset. Opaque field_type. simpl.
Transparent field_offset. Transparent field_type.
rewrite emp_sepcon.
clear v' H0 H v IHm.
unfold P.
rewrite withspacer_spacer.
unfold at_offset. simpl @fst.
(* Goal: @eq mpred (@prop mpred Nveric (ptr_eq v v)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) *)
(* Goal: @eq mpred (let (p, h) := p in @andp mpred Nveric (@prop mpred Nveric (and (@eq val p v) (not (ptr_eq v v)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh v)) (@list_cell cs list_structid list_link list_token ls dsh h v)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) v)) (lseg ls dsh psh l tail v)))) (@andp mpred Nveric (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) p l) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) (@emp mpred Nveric Sveric)) *)
f_equal.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
rewrite isptr_offset_val_zero by auto.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
auto.
rewrite offset_offset_val, Int.add_zero_l.
rewrite Hofs.
apply equal_f.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
apply data_at_rec_type_changable; auto.
(* Goal: @eq mpred (@struct_pred (@nil (prod ident type)) A F v p) (@struct_pred (@nil (prod ident type)) A F v p') *)
(* Goal: @eq mpred (@struct_pred (@cons (prod ident type) a m) A F v p) (@struct_pred (@cons (prod ident type) a m) A F v p') *)
rewrite FT. reflexivity.
assert (all_but_link ((list_link,t)::p0::m) = p0::m).
(* Goal: @eq mpred (@struct_pred (@nil (prod ident type)) A F v p) (@struct_pred (@nil (prod ident type)) A F v p') *)
(* Goal: @eq mpred (@struct_pred (@cons (prod ident type) a m) A F v p) (@struct_pred (@cons (prod ident type) a m) A F v p') *)
simpl. rewrite if_true by auto; reflexivity.
assert (all_but_link (p0::m) = p0::m). {
   clear - MNR H.
   admit. (* easy enough *)
}
rewrite struct_pred_cons2.
unfold P at 2.
rewrite withspacer_spacer.
rewrite Hofs. unfold at_offset.
rewrite offset_offset_val, Int.add_zero_l.
change (fst (list_link, t)) with list_link.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
rewrite isptr_offset_val_zero by auto.
pull_right (spacer sh
  (field_offset cenv_cs list_link list_fields +
   sizeof (field_type list_link list_fields))
  (field_offset_next cenv_cs list_link list_fields sz) p).
(* Goal: @eq mpred (@prop mpred Nveric (ptr_eq v v)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) *)
(* Goal: @eq mpred (let (p, h) := p in @andp mpred Nveric (@prop mpred Nveric (and (@eq val p v) (not (ptr_eq v v)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh v)) (@list_cell cs list_structid list_link list_token ls dsh h v)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) v)) (lseg ls dsh psh l tail v)))) (@andp mpred Nveric (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) p l) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) (@emp mpred Nveric Sveric)) *)
f_equal.
rewrite sepcon_comm.
(* Goal: @eq mpred (@prop mpred Nveric (ptr_eq v v)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) *)
(* Goal: @eq mpred (let (p, h) := p in @andp mpred Nveric (@prop mpred Nveric (and (@eq val p v) (not (ptr_eq v v)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh v)) (@list_cell cs list_structid list_link list_token ls dsh h v)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) v)) (lseg ls dsh psh l tail v)))) (@andp mpred Nveric (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) p l) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) (@emp mpred Nveric Sveric)) *)
f_equal.
apply equal_f.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
apply data_at_rec_type_changable; auto.
apply JMeq_trans with (B:= reptype (field_type list_link list_fields)) (y:= default_val (field_type list_link list_fields)).
(* Goal: @eq mpred (@struct_pred (@nil (prod ident type)) A F v p) (@struct_pred (@nil (prod ident type)) A F v p') *)
(* Goal: @eq mpred (@struct_pred (@cons (prod ident type) a m) A F v p) (@struct_pred (@cons (prod ident type) a m) A F v p') *)
rewrite FT. reflexivity.
match goal with |- JMeq ?A ?B => replace A with B end.
apply JMeq_refl.
clear.
revert v.
unfold all_but_link.
unfold add_link_back.
unfold list_rect at 1.
simpl @fst.
(* Goal: ptr_neq (Vptr b i) (if Archi.ptr64 then Vlong Int64.zero else Vint Int.zero) *)
destruct (ident_eq list_link list_link); [ | elimtype False; congruence]; intro.
(* Goal: @eq mpred (@struct_pred (@nil (prod ident type)) A F v p) (@struct_pred (@nil (prod ident type)) A F v p') *)
(* Goal: @eq mpred (@struct_pred (@cons (prod ident type) a m) A F v p) (@struct_pred (@cons (prod ident type) a m) A F v p') *)
simpl. reflexivity.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
 apply struct_pred_type_changable; auto.
 clear.
 revert v.
(* Goal: @derives mpred Nveric (valid_pointer Vundef) (valid_pointer p) *)
 simpl.
(* Goal: ptr_neq (Vptr b i) (if Archi.ptr64 then Vlong Int64.zero else Vint Int.zero) *)
 destruct (ident_eq list_link list_link); [ | elimtype False; congruence]; intro.
(* Goal: @eq mpred (@struct_pred (@nil (prod ident type)) A F v p) (@struct_pred (@nil (prod ident type)) A F v p') *)
(* Goal: @eq mpred (@struct_pred (@cons (prod ident type) a m) A F v p) (@struct_pred (@cons (prod ident type) a m) A F v p') *)
 simpl. reflexivity.
* (* list link is not the first field *)
 specialize (H' H).
destruct m; [inv H | ].
 rewrite struct_pred_cons2.
 assert (all_but_link (a :: p0 :: m) = a :: all_but_link (p0::m)). {
  clear - MNR H. forget (p0::m) as m'. clear p0 m.
  induction m'. inv H.
  unfold all_but_link; fold all_but_link.
  unfold members_no_replicate in *.
  rewrite map_cons in MNR.
  unfold compute_list_norepet in MNR.
  fold compute_list_norepet in MNR.
  destruct (id_in_list (fst a) (map fst (a0 :: m'))) eqn:?; [discriminate | ].
  simpl in Heqb. rewrite orb_false_iff in Heqb. destruct Heqb.
  apply Pos.eqb_neq in H0.
  apply id_in_list_false in H1.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tl')) (list_token dsh nullval)) (@list_cell cs list_structid list_link list_token ls dsh x nullval)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tl') nullval)) (@emp mpred Nveric Sveric)) (@FF mpred Nveric) *)
  simpl in H. destruct H.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
  rewrite H in *. rewrite if_false by auto. auto.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
  rewrite if_false by congruence. auto.
}
 unfold members_no_replicate in *.
 simpl in MNR.
(* Goal: @eq val p q *)
 destruct ((fst a =? fst p0)%positive || id_in_list (fst a) (map fst m))%bool eqn:?; try discriminate.
 rewrite orb_false_iff in Heqb. destruct Heqb.
  apply Pos.eqb_neq in H1.
  apply id_in_list_false in H2.
  specialize (IHm MNR H).
 destruct p0 as [i t].
(* simpl in v'. *)
  simpl in H1. clear MNR H.
 destruct (ident_eq i list_link).
 + subst i.
  assert (exists v' : compact_prod (map (field_type' list_fields) (a :: m)),
                JMeq v v'). {
   revert v; clear - H0.
   replace (all_but_link ((list_link, t) :: m)) with m in H0
     by (simpl; rewrite if_true by auto; auto).
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
   rewrite H0. eexists; eauto.
 }
 destruct H as [v' H3].
 simpl in v'.
(* Goal: @eq mpred (@struct_pred (@cons (prod ident type) a m) A F v p) (@struct_pred (@cons (prod ident type) a m) A F v p') *)
 destruct m.
 -
  simpl in v'.
  assert (exists v'': compact_prod
                  (map (field_type' list_fields)
                     (all_but_link ((list_link, t) :: nil))), JMeq v'' tt). {
(* Goal: @eq mpred (@struct_pred (@nil (prod ident type)) A F v p) (@struct_pred (@nil (prod ident type)) A F v p') *)
(* Goal: @eq mpred (@struct_pred (@cons (prod ident type) a m) A F v p) (@struct_pred (@cons (prod ident type) a m) A F v p') *)
  clear. simpl. rewrite if_true by auto. exists tt; reflexivity.
 }
 destruct H as [v'' H4].
 specialize (IHm v'').
 replace (struct_pred (all_but_link ((list_link, t) :: nil)) (P list_fields) v'' p) with
    (struct_pred nil (P list_fields) tt p) in IHm
  by (apply struct_pred_type_changable; auto; simpl; rewrite if_true; auto).
  change (struct_pred nil (P list_fields) tt p) with emp in IHm.
  rewrite emp_sepcon in IHm.
(* Goal: @derives mpred Nveric P (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh v1) (@list_cell cs list_structid list_link list_token ls dsh h v1)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) p) v1)) (lseg ls dsh psh tail p v2)) *)
  rewrite sepcon_assoc. rewrite IHm; clear IHm.
(* Goal: @eq mpred (@prop mpred Nveric (ptr_eq v v)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) *)
(* Goal: @eq mpred (let (p, h) := p in @andp mpred Nveric (@prop mpred Nveric (and (@eq val p v) (not (ptr_eq v v)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh v)) (@list_cell cs list_structid list_link list_token ls dsh h v)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) v)) (lseg ls dsh psh l tail v)))) (@andp mpred Nveric (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) p l) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) (@emp mpred Nveric Sveric)) *)
  f_equal.
  assert (exists v4: compact_prod
                  (map (field_type' list_fields) (a::nil)), JMeq v4 v). {
  clear - H1. revert v. simpl. rewrite if_false by auto. rewrite if_true by auto.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
  eexists; eauto.
 }
 destruct H as [v4 H5].
  transitivity (struct_pred (a :: nil) (P list_fields) v4 (offset_val (Int.repr 0) p)).
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
 apply struct_pred_type_changable; auto.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
 simpl. rewrite if_false by auto; rewrite if_true by auto. auto.
 admit. (* see proof above *)
 destruct a as [i' t'].
 unfold struct_pred at 1.
  unfold list_rect.
(* Goal: @eq mpred (@prop mpred Nveric (ptr_eq v v)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) *)
(* Goal: @eq mpred (let (p, h) := p in @andp mpred Nveric (@prop mpred Nveric (and (@eq val p v) (not (ptr_eq v v)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh v)) (@list_cell cs list_structid list_link list_token ls dsh h v)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) v)) (lseg ls dsh psh l tail v)))) (@andp mpred Nveric (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) p l) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) (@emp mpred Nveric Sveric)) *)
  f_equal.
  clear - H1 H5. simpl in H1.
  admit.  (* tedious *)
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
  apply struct_pred_type_changable; auto.
  clear - H1 H4 H3.
  simpl in v'.
  admit.  (* tedious *)
  -
  simpl map at 1 in v'. cbv beta iota in v'.
  destruct v' as [va vr].
  assert (exists vr' : compact_prod
              (map (field_type' list_fields)
                 (all_but_link ((list_link, t) :: p0 :: m))),
                JMeq vr vr'). {
  clear - H1; simpl in H1.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
  simpl. rewrite if_true by auto. exists vr; eauto.
  } destruct H as [vr' H4].
   specialize (IHm vr').
  replace (struct_pred (all_but_link (a :: (list_link, t) :: p0 :: m)) (P list_fields) v p)
       with (P list_fields a
                (fst (add_link_back list_fields (a :: (list_link, t) :: p0 :: m) v))
                 (offset_val (Int.repr 0) p) *
                struct_pred (all_but_link ((list_link, t) :: p0 :: m)) (P list_fields) vr' p).
(* Goal: @eq mpred (@prop mpred Nveric (ptr_eq v v)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) *)
(* Goal: @eq mpred (let (p, h) := p in @andp mpred Nveric (@prop mpred Nveric (and (@eq val p v) (not (ptr_eq v v)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh v)) (@list_cell cs list_structid list_link list_token ls dsh h v)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) v)) (lseg ls dsh psh l tail v)))) (@andp mpred Nveric (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) p l) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) (@emp mpred Nveric Sveric)) *)
  rewrite !sepcon_assoc. f_equal.
  rewrite <- sepcon_assoc.
  rewrite IHm.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
  apply struct_pred_type_changable; auto.
  clear - H3 H4 H1.
  admit.  (* tedious *)
  clear - H3 H4 H1 H0.
  transitivity (P list_fields a va p *
                    struct_pred (all_but_link ((list_link, t) :: p0 :: m)) (P list_fields) vr' p).
(* Goal: @eq mpred (@prop mpred Nveric (ptr_eq v v)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) *)
(* Goal: @eq mpred (let (p, h) := p in @andp mpred Nveric (@prop mpred Nveric (and (@eq val p v) (not (ptr_eq v v)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh v)) (@list_cell cs list_structid list_link list_token ls dsh h v)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) v)) (lseg ls dsh psh l tail v)))) (@andp mpred Nveric (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) p l) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) (@emp mpred Nveric Sveric)) *)
  f_equal.
(* Goal: @eq mpred (@prop mpred Nveric (ptr_eq v v)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) *)
(* Goal: @eq mpred (let (p, h) := p in @andp mpred Nveric (@prop mpred Nveric (and (@eq val p v) (not (ptr_eq v v)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh v)) (@list_cell cs list_structid list_link list_token ls dsh h v)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) v)) (lseg ls dsh psh l tail v)))) (@andp mpred Nveric (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) p l) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) (@emp mpred Nveric Sveric)) *)
  unfold P; rewrite !withspacer_spacer; f_equal. rewrite <- spacer_offset_zero. auto.
  unfold at_offset. rewrite offset_offset_val. rewrite Int.add_zero_l.
(* Goal: @eq mpred (@prop mpred Nveric (ptr_eq v v)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) *)
(* Goal: @eq mpred (let (p, h) := p in @andp mpred Nveric (@prop mpred Nveric (and (@eq val p v) (not (ptr_eq v v)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh v)) (@list_cell cs list_structid list_link list_token ls dsh h v)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) v)) (lseg ls dsh psh l tail v)))) (@andp mpred Nveric (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) p l) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) (@emp mpred Nveric Sveric)) *)
  f_equal.
  admit.  (* tedious *)
  assert (exists v6: compact_prod (map (field_type' list_fields) (a :: p0 :: m)),
                JMeq v v6). {
    clear - H1 H0.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
    simpl all_but_link at 2 in H0. rewrite if_true in H0 by auto.
(* Goal: forall (v' : @elemtype cs list_structid list_link list_token ls) (ash bsh psh : share) (p : val) (v : @elemtype cs list_structid list_link list_token ls) (_ : @sepalg.join share Share.Join_ba ash bsh psh) (_ : not (readable_share ash)) (_ : readable_share bsh), @eq mpred (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls ash v' p) (@list_cell cs list_structid list_link list_token ls bsh v p)) (@list_cell cs list_structid list_link list_token ls psh v p) *)
 revert v; rewrite H0. intros. exists v; auto.
 } destruct H as [v6 H].
  transitivity (struct_pred (a :: p0 :: m) (P list_fields) v6 p).
(* Goal: @eq mpred (@prop mpred Nveric (ptr_eq v v)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) *)
(* Goal: @eq mpred (let (p, h) := p in @andp mpred Nveric (@prop mpred Nveric (and (@eq val p v) (not (ptr_eq v v)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh v)) (@list_cell cs list_structid list_link list_token ls dsh h v)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) v)) (lseg ls dsh psh l tail v)))) (@andp mpred Nveric (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) p l) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) (@emp mpred Nveric Sveric)) *)
  rewrite struct_pred_cons2. f_equal.
(* Goal: @eq mpred (@prop mpred Nveric (ptr_eq v v)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) *)
(* Goal: @eq mpred (let (p, h) := p in @andp mpred Nveric (@prop mpred Nveric (and (@eq val p v) (not (ptr_eq v v)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh v)) (@list_cell cs list_structid list_link list_token ls dsh h v)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) v)) (lseg ls dsh psh l tail v)))) (@andp mpred Nveric (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) p l) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) (@emp mpred Nveric Sveric)) *)
  unfold P; rewrite !withspacer_spacer; f_equal.
  unfold at_offset.
(* Goal: @eq mpred (@prop mpred Nveric (ptr_eq v v)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) *)
(* Goal: @eq mpred (let (p, h) := p in @andp mpred Nveric (@prop mpred Nveric (and (@eq val p v) (not (ptr_eq v v)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh v)) (@list_cell cs list_structid list_link list_token ls dsh h v)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) v)) (lseg ls dsh psh l tail v)))) (@andp mpred Nveric (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) p l) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) (@emp mpred Nveric Sveric)) *)
  f_equal. rewrite H in H3. clear - H3. apply JMeq_eq in H3. subst; reflexivity.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
  apply struct_pred_type_changable; auto.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
  simpl. rewrite if_true by auto. auto.
  rewrite H in H3.
  clear - H3 H4.
  eapply JMeq_trans. apply JMeq_sym. apply H4.
  destruct v6.
  clear - H3. simpl.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
  apply JMeq_eq in H3. inv H3; auto.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
  apply struct_pred_type_changable; auto.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
  simpl. rewrite if_false by auto. rewrite if_true by auto. auto.
 +
   assert (all_but_link ((i,t)::m) = (i,t)::all_but_link m).
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
   simpl. rewrite if_false by auto; auto.
   assert (exists v' :
      (field_type' list_fields a * compact_prod (map (field_type' list_fields) (all_but_link ((i, t) :: m)))), JMeq v v'). {
     clear - H H0 v. revert v; rewrite H0. rewrite H.
(* Goal: forall (v' : @elemtype cs list_structid list_link list_token ls) (ash bsh psh : share) (p : val) (v : @elemtype cs list_structid list_link list_token ls) (_ : @sepalg.join share Share.Join_ba ash bsh psh) (_ : not (readable_share ash)) (_ : readable_share bsh), @eq mpred (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls ash v' p) (@list_cell cs list_structid list_link list_token ls bsh v p)) (@list_cell cs list_structid list_link list_token ls psh v p) *)
   simpl. intros. exists v; reflexivity.
 } destruct H3 as [v' Hv'].
  destruct v' as [v1 vr].
  specialize (IHm vr).
  replace (struct_pred (all_but_link (a :: (i, t) :: m)) (P list_fields) v p)
     with (P list_fields a (fst (add_link_back list_fields (a :: (i, t) :: m) v))
                   (offset_val (Int.repr 0) p) *
              struct_pred (all_but_link ((i, t) :: m)) (P list_fields) vr p).
(* Goal: @eq mpred (@prop mpred Nveric (ptr_eq v v)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) *)
(* Goal: @eq mpred (let (p, h) := p in @andp mpred Nveric (@prop mpred Nveric (and (@eq val p v) (not (ptr_eq v v)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh v)) (@list_cell cs list_structid list_link list_token ls dsh h v)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) v)) (lseg ls dsh psh l tail v)))) (@andp mpred Nveric (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) p l) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) (@emp mpred Nveric Sveric)) *)
  rewrite !sepcon_assoc. f_equal.
  rewrite <- sepcon_assoc.
  rewrite IHm. clear IHm.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
  apply struct_pred_type_changable; auto.
  admit.  (* tedious *)
  assert (exists v'': compact_prod
      (field_type' list_fields a :: field_type' list_fields (i,t) :: map (field_type' list_fields) (all_but_link m)),
    JMeq v v''). {
    clear - H H0. revert v; rewrite H0. rewrite H. intros; exists v. reflexivity.
  } destruct H3 as [v'' Hv''].
  transitivity (struct_pred (a :: (i,t) :: all_but_link m) (P list_fields) v'' p).
  rewrite struct_pred_cons2.
(* Goal: @eq mpred (@prop mpred Nveric (ptr_eq v v)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) *)
(* Goal: @eq mpred (let (p, h) := p in @andp mpred Nveric (@prop mpred Nveric (and (@eq val p v) (not (ptr_eq v v)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh v)) (@list_cell cs list_structid list_link list_token ls dsh h v)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) v)) (lseg ls dsh psh l tail v)))) (@andp mpred Nveric (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) p l) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) (@emp mpred Nveric Sveric)) *)
  f_equal.
  admit.  (* tedious *)
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
  apply struct_pred_type_changable; auto.
  clear - Hv' Hv''. rewrite Hv'' in Hv'. simpl in v''. destruct v''.
  clear - Hv'.
  admit.  (* tedious *)
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
  apply struct_pred_type_changable; auto.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
  rewrite H0. rewrite H. auto.
Qed.
*)
Lemma list_cell_link_join_nospacer:
  forall (LS: listspec list_structid list_link list_token) sh v p,
   field_offset cenv_cs list_link list_fields +
                        sizeof (field_type list_link list_fields) =
   field_offset_next cenv_cs list_link list_fields
                        (co_sizeof (get_co list_structid)) ->
   list_cell LS sh v p * field_at_ sh list_struct (StructField list_link :: nil) p
     = data_at sh list_struct (list_data v) p.
Proof.
(* Goal: forall (v' : @elemtype cs list_structid list_link list_token ls) (ash bsh psh : share) (p : val) (v : @elemtype cs list_structid list_link list_token ls) (_ : @sepalg.join share Share.Join_ba ash bsh psh) (_ : not (readable_share ash)) (_ : readable_share bsh), @eq mpred (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls ash v' p) (@list_cell cs list_structid list_link list_token ls bsh v p)) (@list_cell cs list_structid list_link list_token ls psh v p) *)
intros.
rewrite <- list_cell_link_join.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
unfold spacer. rewrite if_true. rewrite sepcon_emp. auto.
(* Goal: @eq Z (Z.sub (field_offset_next (@cenv_cs cs) list_link (@list_fields cs list_structid list_link list_token LS) (co_sizeof (@get_co cs list_structid))) (Z.add (field_offset (@cenv_cs cs) list_link (@list_fields cs list_structid list_link list_token LS)) (@sizeof (@cenv_cs cs) (field_type list_link (@list_fields cs list_structid list_link list_token LS))))) Z0 *)
omega.
Qed.

End LIST1.

Module LsegGeneral.

Section LIST2.
Context {cs: compspecs}.
Context  {list_structid: ident} {list_link: ident} {list_token: share -> val -> mpred}.

Fixpoint lseg (ls: listspec list_structid list_link list_token) (dsh psh: share)
            (contents: list (val * elemtype ls)) (x z: val) : mpred :=
 match contents with
 | (p,h)::hs => !! (p=x /\ ~ptr_eq x z) &&
              EX y:val,  !! is_pointer_or_null y &&
              list_token dsh x * list_cell ls dsh h x
              * field_at psh list_struct (StructField list_link ::nil)
                  (valinject (nested_field_type list_struct (StructField list_link :: nil)) y) x
              * lseg ls dsh psh hs y z
 | nil => !! (ptr_eq x z) && emp
 end.

Lemma lseg_unfold (ls: listspec list_structid list_link list_token): forall dsh psh contents v1 v2,
    lseg ls dsh psh contents v1 v2 =
     match contents with
     | (p,h)::t => !! (p=v1 /\ ~ ptr_eq v1 v2) && EX tail: val,
                      !! is_pointer_or_null tail &&
                      list_token dsh v1 * list_cell ls dsh h v1
                      * field_at psh list_struct (StructField list_link :: nil)
                          (valinject (nested_field_type list_struct (StructField list_link :: nil)) tail) v1
                      * lseg ls dsh psh t tail v2
     | nil => !! (ptr_eq v1 v2) && emp
     end.
Proof.
(* Goal: forall (v' : @elemtype cs list_structid list_link list_token ls) (ash bsh psh : share) (p : val) (v : @elemtype cs list_structid list_link list_token ls) (_ : @sepalg.join share Share.Join_ba ash bsh psh) (_ : not (readable_share ash)) (_ : readable_share bsh), @eq mpred (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls ash v' p) (@list_cell cs list_structid list_link list_token ls bsh v p)) (@list_cell cs list_structid list_link list_token ls psh v p) *)
 intros.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
 destruct contents as [ | [? ?] ?]; simpl; auto.
Qed.

Lemma lseg_eq (ls: listspec list_structid list_link list_token):
  forall dsh psh l v ,
  is_pointer_or_null v ->
    lseg ls dsh psh l v v = !!(l=nil) && emp.
Proof.
(* Goal: forall (v' : @elemtype cs list_structid list_link list_token ls) (ash bsh psh : share) (p : val) (v : @elemtype cs list_structid list_link list_token ls) (_ : @sepalg.join share Share.Join_ba ash bsh psh) (_ : not (readable_share ash)) (_ : readable_share bsh), @eq mpred (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls ash v' p) (@list_cell cs list_structid list_link list_token ls bsh v p)) (@list_cell cs list_structid list_link list_token ls psh v p) *)
intros.
(* Goal: @eq mpred (lseg ls dsh psh l v v) (@andp mpred Nveric (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) l (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) (@emp mpred Nveric Sveric)) *)
rewrite (lseg_unfold ls dsh psh l v v).
(* Goal: @eq mpred match l with | nil => @andp mpred Nveric (@prop mpred Nveric (ptr_eq v v)) (@emp mpred Nveric Sveric) | cons (pair p h as p0) t => @andp mpred Nveric (@prop mpred Nveric (and (@eq val p v) (not (ptr_eq v v)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh v)) (@list_cell cs list_structid list_link list_token ls dsh h v)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) v)) (lseg ls dsh psh t tail v))) end (@andp mpred Nveric (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) l (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) (@emp mpred Nveric Sveric)) *)
destruct l.
(* Goal: @eq mpred (@prop mpred Nveric (ptr_eq v v)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) *)
(* Goal: @eq mpred (let (p, h) := p in @andp mpred Nveric (@prop mpred Nveric (and (@eq val p v) (not (ptr_eq v v)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh v)) (@list_cell cs list_structid list_link list_token ls dsh h v)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) v)) (lseg ls dsh psh l tail v)))) (@andp mpred Nveric (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) p l) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) (@emp mpred Nveric Sveric)) *)
f_equal. f_equal.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
apply prop_ext; split; intro; auto.
(* Goal: ptr_eq v v *)
(* Goal: @eq mpred (let (p, h) := p in @andp mpred Nveric (@prop mpred Nveric (and (@eq val p v) (not (ptr_eq v v)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh v)) (@list_cell cs list_structid list_link list_token ls dsh h v)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) v)) (lseg ls dsh psh l tail v)))) (@andp mpred Nveric (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) p l) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) (@emp mpred Nveric Sveric)) *)
unfold ptr_eq.
(* Goal: match v with | Vundef => False | Vint n1 => match v with | Vundef => False | Vint n2 => and (@eq bool Archi.ptr64 false) (and (@eq bool (Int.cmpu Ceq n1 n2) true) (@eq bool (Int.cmpu Ceq n1 (Int.repr Z0)) true)) | Vlong i => False | Vfloat f => False | Vsingle f => False | Vptr b i => False end | Vlong n1 => match v with | Vundef => False | Vint i => False | Vlong n2 => and (@eq bool Archi.ptr64 true) (and (@eq bool (Int64.cmpu Ceq n1 n2) true) (@eq bool (Int64.cmpu Ceq n1 (Int64.repr Z0)) true)) | Vfloat f => False | Vsingle f => False | Vptr b i => False end | Vfloat f => False | Vsingle f => False | Vptr b1 ofs1 => match v with | Vundef => False | Vint i => False | Vlong i => False | Vfloat f => False | Vsingle f => False | Vptr b2 ofs2 => and (@eq block b1 b2) (@eq bool (Ptrofs.cmpu Ceq ofs1 ofs2) true) end end *)
(* Goal: @eq mpred (let (p, h) := p in @andp mpred Nveric (@prop mpred Nveric (and (@eq val p v) (not (ptr_eq v v)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh v)) (@list_cell cs list_structid list_link list_token ls dsh h v)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) v)) (lseg ls dsh psh l tail v)))) (@andp mpred Nveric (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) p l) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) (@emp mpred Nveric Sveric)) *)
unfold is_pointer_or_null in H.
destruct Archi.ptr64 eqn:Hp;
destruct v; inv H; auto;
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
unfold Ptrofs.cmpu; rewrite Ptrofs.eq_true; auto.
(* Goal: @derives mpred Nveric (@orp mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) p l) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) p l) x z)) (let (p, h) := p in @andp mpred Nveric (@prop mpred Nveric (and (@eq val p x) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh h x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) x)) (lseg ls dsh psh l tail z)))) *)
destruct p.
apply pred_ext;
(* Goal: ptr_neq (Vptr b i) (if Archi.ptr64 then Vlong Int64.zero else Vint Int.zero) *)
apply derives_extract_prop; intro.
(* Goal: @derives mpred Nveric (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh v)) (@list_cell cs list_structid list_link list_token ls dsh e v)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) v)) (lseg ls dsh psh l tail v))) (@andp mpred Nveric (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) v0 e) l) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) (@emp mpred Nveric Sveric)) *)
(* Goal: @derives mpred Nveric (@emp mpred Nveric Sveric) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val v0 v) (not (ptr_eq v v)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh v)) (@list_cell cs list_structid list_link list_token ls dsh e v)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) v)) (lseg ls dsh psh l tail v)))) *)
destruct H0.
(* Goal: @derives mpred Nveric (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh v)) (@list_cell cs list_structid list_link list_token ls dsh e v)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) v)) (lseg ls dsh psh l tail v))) (@andp mpred Nveric (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) v0 e) l) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) (@emp mpred Nveric Sveric)) *)
(* Goal: @derives mpred Nveric (@emp mpred Nveric Sveric) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val v0 v) (not (ptr_eq v v)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh v)) (@list_cell cs list_structid list_link list_token ls dsh e v)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) v)) (lseg ls dsh psh l tail v)))) *)
contradiction H1.
(* Goal: ptr_eq v v *)
(* Goal: @derives mpred Nveric (@emp mpred Nveric Sveric) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val v0 v) (not (ptr_eq v v)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh v)) (@list_cell cs list_structid list_link list_token ls dsh e v)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) v)) (lseg ls dsh psh l tail v)))) *)
destruct v; inv H; try split; auto; apply Ptrofs.eq_true.
(* Goal: @derives mpred Nveric (@emp mpred Nveric Sveric) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) *)
(* Goal: @derives mpred Nveric (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) x z) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) *)
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) (@orp mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) x z)) *)
inv H0.
Qed.

Definition lseg_cons (ls: listspec list_structid list_link list_token) dsh psh (l: list (val * elemtype ls)) (x z: val) : mpred :=
        !! (~ ptr_eq x z) &&
       EX h:(elemtype ls), EX r:list (val * elemtype ls), EX y:val,
             !!(l=(x,h)::r  /\ is_pointer_or_null y) &&
             list_token dsh x * list_cell ls dsh h x *
             field_at psh list_struct (StructField list_link :: nil) (valinject (nested_field_type list_struct (StructField list_link :: nil)) y) x *
             lseg ls dsh psh r y z.

Lemma lseg_unroll (ls: listspec list_structid list_link list_token): forall dsh psh l x z ,
    lseg ls dsh psh l x z =
      (!! (ptr_eq x z) && !! (l=nil) && emp) || lseg_cons ls dsh psh l x z.
Proof.
(* Goal: forall (v' : @elemtype cs list_structid list_link list_token ls) (ash bsh psh : share) (p : val) (v : @elemtype cs list_structid list_link list_token ls) (_ : @sepalg.join share Share.Join_ba ash bsh psh) (_ : not (readable_share ash)) (_ : readable_share bsh), @eq mpred (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls ash v' p) (@list_cell cs list_structid list_link list_token ls bsh v p)) (@list_cell cs list_structid list_link list_token ls psh v p) *)
intros.
(* Goal: @eq mpred (lseg ls dsh psh l x z) (@orp mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) l (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh l x z)) *)
rewrite lseg_unfold at 1.
(* Goal: @eq mpred match l with | nil => @andp mpred Nveric (@prop mpred Nveric (ptr_eq v v)) (@emp mpred Nveric Sveric) | cons (pair p h as p0) t => @andp mpred Nveric (@prop mpred Nveric (and (@eq val p v) (not (ptr_eq v v)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh v)) (@list_cell cs list_structid list_link list_token ls dsh h v)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) v)) (lseg ls dsh psh t tail v))) end (@andp mpred Nveric (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) l (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) (@emp mpred Nveric Sveric)) *)
apply pred_ext; destruct l.
(* Goal: forall (v' : @elemtype cs list_structid list_link list_token ls) (ash bsh psh : share) (p : val) (v : @elemtype cs list_structid list_link list_token ls) (_ : @sepalg.join share Share.Join_ba ash bsh psh) (_ : not (readable_share ash)) (_ : readable_share bsh), @eq mpred (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls ash v' p) (@list_cell cs list_structid list_link list_token ls bsh v p)) (@list_cell cs list_structid list_link list_token ls psh v p) *)
apply derives_extract_prop; intros.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
rewrite prop_true_andp by auto.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
rewrite prop_true_andp by auto.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
apply orp_right1; auto.
(* Goal: @derives mpred Nveric (@orp mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) p l) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) p l) x z)) (let (p, h) := p in @andp mpred Nveric (@prop mpred Nveric (and (@eq val p x) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh h x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) x)) (lseg ls dsh psh l tail z)))) *)
destruct p.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh p) (@list_cell cs list_structid list_link list_token ls dsh h p)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) p)) (lseg ls dsh psh r y z)) (@orp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (and (ptr_eq p z) (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) p h) r) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) p h) r) p z)) *)
apply orp_right2.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh p) (@list_cell cs list_structid list_link list_token ls dsh h p)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) p)) (lseg ls dsh psh r y z)) (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) p h) r) p z) *)
unfold lseg_cons.
(* Goal: forall (v' : @elemtype cs list_structid list_link list_token ls) (ash bsh psh : share) (p : val) (v : @elemtype cs list_structid list_link list_token ls) (_ : @sepalg.join share Share.Join_ba ash bsh psh) (_ : not (readable_share ash)) (_ : readable_share bsh), @eq mpred (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls ash v' p) (@list_cell cs list_structid list_link list_token ls bsh v p)) (@list_cell cs list_structid list_link list_token ls psh v p) *)
apply derives_extract_prop; intros.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tl')) (list_token dsh nullval)) (@list_cell cs list_structid list_link list_token ls dsh x nullval)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tl') nullval)) (@emp mpred Nveric Sveric)) (@FF mpred Nveric) *)
destruct H.
(* Goal: @derives mpred Nveric (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh e x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) x)) (lseg ls dsh psh l tail z))) (@andp mpred Nveric (@prop mpred Nveric (not (ptr_eq x z))) (@exp mpred Nveric (@elemtype cs list_structid list_link list_token ls) (fun h : @elemtype cs list_structid list_link list_token ls => @exp mpred Nveric (list (prod val (@elemtype cs list_structid list_link list_token ls))) (fun r : list (prod val (@elemtype cs list_structid list_link list_token ls)) => @exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) v e) l) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) x h) r)) (is_pointer_or_null y))) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh h x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))))) *)
(* Goal: @derives mpred Nveric (@orp mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) x z)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@emp mpred Nveric Sveric)) *)
(* Goal: @derives mpred Nveric (@orp mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) p l) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) p l) x z)) (let (p, h) := p in @andp mpred Nveric (@prop mpred Nveric (and (@eq val p x) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh h x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) x)) (lseg ls dsh psh l tail z)))) *)
apply exp_left; intro tail.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
normalize.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh x) (@list_cell cs list_structid list_link list_token ls dsh e x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) x)) (lseg ls dsh psh l tail z)) (@exp mpred Nveric (@elemtype cs list_structid list_link list_token ls) (fun x0 : @elemtype cs list_structid list_link list_token ls => @andp mpred Nveric (@TT mpred Nveric) (@exp mpred Nveric (list (prod val (@elemtype cs list_structid list_link list_token ls))) (fun r : list (prod val (@elemtype cs list_structid list_link list_token ls)) => @exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) v e) l) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) x x0) r)) (is_pointer_or_null y))) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh x0 x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))))) *)
(* Goal: @derives mpred Nveric (@orp mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) x z)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@emp mpred Nveric Sveric)) *)
(* Goal: @derives mpred Nveric (@orp mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) p l) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) p l) x z)) (let (p, h) := p in @andp mpred Nveric (@prop mpred Nveric (and (@eq val p x) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh h x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) x)) (lseg ls dsh psh l tail z)))) *)
apply exp_right with e. rewrite TT_andp.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh x) (@list_cell cs list_structid list_link list_token ls dsh e x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) x)) (lseg ls dsh psh l tail z)) (@exp mpred Nveric (list (prod val (@elemtype cs list_structid list_link list_token ls))) (fun r : list (prod val (@elemtype cs list_structid list_link list_token ls)) => @exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) v e) l) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) x e) r)) (is_pointer_or_null y))) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh e x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) *)
(* Goal: @derives mpred Nveric (@orp mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) x z)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@emp mpred Nveric Sveric)) *)
(* Goal: @derives mpred Nveric (@orp mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) p l) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) p l) x z)) (let (p, h) := p in @andp mpred Nveric (@prop mpred Nveric (and (@eq val p x) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh h x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) x)) (lseg ls dsh psh l tail z)))) *)
apply exp_right with l.
(* Goal: @derives mpred Nveric P (@exp mpred Nveric (list (prod val (@elemtype cs list_structid list_link list_token ls))) (fun r : list (prod val (@elemtype cs list_structid list_link list_token ls)) => @exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) v1 h) tail) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) v1 h) r)) (is_pointer_or_null y))) (list_token dsh v1)) (@list_cell cs list_structid list_link list_token ls dsh h v1)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) v1)) (lseg ls dsh psh r y v2)))) *)
apply exp_right with tail.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) s (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) v h) r)) (is_pointer_or_null y))) (list_token dsh v)) (@list_cell cs list_structid list_link list_token ls dsh h v)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) v)) (lseg ls dsh psh r y v2)) (fold_right_sepcon R)) (@exp mpred Nveric (prod (prod (prod (@elemtype cs list_structid list_link list_token ls) (list (prod val (@elemtype cs list_structid list_link list_token ls)))) val) val) (fun x : prod (prod (prod (@elemtype cs list_structid list_link list_token ls) (list (prod val (@elemtype cs list_structid list_link list_token ls)))) val) val => (let (p0, p) := x in let (p1, y) := p0 in let (h, r) := p1 in fun x0 : environ => @andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) s (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) p h) r)) (is_pointer_or_null y))) (@prop mpred Nveric (@eq val p v))) (@andp mpred Nveric (@prop mpred Nveric (@fold_right Prop Prop and True P)) (@andp mpred Nveric (@prop mpred Nveric (@fold_right (forall _ : environ, Prop) (forall _ : environ, Prop) (fun (x1 x2 : forall _ : environ, Prop) (x3 : environ) => and (x1 x3) (x2 x3)) (fun _ : environ => True) (@map localdef (forall _ : environ, Prop) locald_denote Q) x0)) (@sepcon mpred Nveric Sveric (list_token dsh v) (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls dsh h v) (@sepcon mpred Nveric Sveric (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) v) (@sepcon mpred Nveric Sveric (lseg ls dsh psh r y v2) (fold_right_sepcon R)))))))) rho)) *)
repeat rewrite sepcon_andp_prop'.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh x) (@list_cell cs list_structid list_link list_token ls dsh e x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) x)) (lseg ls dsh psh l tail z)) (@andp mpred Nveric (@prop mpred Nveric (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) v e) l) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) x e) l)) (is_pointer_or_null tail))) (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh x) (@list_cell cs list_structid list_link list_token ls dsh e x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) x)) (lseg ls dsh psh l tail z))) *)
(* Goal: @derives mpred Nveric (@orp mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) x z)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@emp mpred Nveric Sveric)) *)
(* Goal: @derives mpred Nveric (@orp mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) p l) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) p l) x z)) (let (p, h) := p in @andp mpred Nveric (@prop mpred Nveric (and (@eq val p x) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh h x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) x)) (lseg ls dsh psh l tail z)))) *)
apply andp_right.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
apply prop_right; split; auto.
(* Goal: and True (iff (@eq val (Vptr b0 i) (Vptr b0 i0)) (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) *)
(* Goal: @derives mpred Nveric (let (p0, h) := p0 in @andp mpred Nveric (@prop mpred Nveric (and (@eq val p0 p) (not (ptr_eq p q)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh p)) (@list_cell cs list_structid list_link list_token ls dsh h p)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) p)) (lseg ls dsh psh contents tail q)))) (@prop mpred Nveric (and (is_pointer_or_null p) (iff (@eq val p q) (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) p0 contents) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))))) *)
subst.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
auto.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
subst. auto.
(* Goal: @derives mpred Nveric (@orp mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) x z)) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) *)
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) (@orp mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) x z)) *)
apply orp_left.
rewrite andp_assoc;
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq v v2)) (@andp mpred Nveric (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) s (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) (@emp mpred Nveric Sveric))) (lseg_cons ls dsh psh s v v2) *)
(* Goal: @derives mpred Nveric (lseg_cons ls dsh psh s v v2) (@orp mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq v v2)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) s (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh s v v2)) *)
do 2 (apply derives_extract_prop; intro).
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
 rewrite prop_true_andp by auto. auto.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh p) (@list_cell cs list_structid list_link list_token ls dsh h p)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) p)) (lseg ls dsh psh r y z)) (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) p h) r) p z) *)
unfold lseg_cons.
(* Goal: forall (v' : @elemtype cs list_structid list_link list_token ls) (ash bsh psh : share) (p : val) (v : @elemtype cs list_structid list_link list_token ls) (_ : @sepalg.join share Share.Join_ba ash bsh psh) (_ : not (readable_share ash)) (_ : readable_share bsh), @eq mpred (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls ash v' p) (@list_cell cs list_structid list_link list_token ls bsh v p)) (@list_cell cs list_structid list_link list_token ls psh v p) *)
apply derives_extract_prop; intros.
(* Goal: @derives mpred Nveric (@exp mpred Nveric (@elemtype cs list_structid list_link list_token ls) (fun h : @elemtype cs list_structid list_link list_token ls => @exp mpred Nveric (list (prod val (@elemtype cs list_structid list_link list_token ls))) (fun r : list (prod val (@elemtype cs list_structid list_link list_token ls)) => @exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) v e) l) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) x h) r)) (is_pointer_or_null y))) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh h x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z))))) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val v x) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh e x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) x)) (lseg ls dsh psh l tail z)))) *)
apply exp_left; intro h.
(* Goal: @derives mpred Nveric (@exp mpred Nveric (list (prod val (@elemtype cs list_structid list_link list_token ls))) (fun r : list (prod val (@elemtype cs list_structid list_link list_token ls)) => @exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) v e) l) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) x h) r)) (is_pointer_or_null y))) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh h x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val v x) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh e x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) x)) (lseg ls dsh psh l tail z)))) *)
apply exp_left; intro r.
(* Goal: @derives mpred Nveric (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) v e) l) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) x h) r)) (is_pointer_or_null y))) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh h x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z))) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val v x) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh e x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) x)) (lseg ls dsh psh l tail z)))) *)
apply exp_left; intro y.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) v e) l) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) x h) r)) (is_pointer_or_null y))) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh h x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val v x) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh e x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) x)) (lseg ls dsh psh l tail z)))) *)
do 3 rewrite sepcon_andp_prop'.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) s (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) v h) r)) (is_pointer_or_null y))) (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh v) (@list_cell cs list_structid list_link list_token ls dsh h v)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) v)) (lseg ls dsh psh r y v2)) (fold_right_sepcon R))) (@exp mpred Nveric (prod (prod (prod (@elemtype cs list_structid list_link list_token ls) (list (prod val (@elemtype cs list_structid list_link list_token ls)))) val) val) (fun x : prod (prod (prod (@elemtype cs list_structid list_link list_token ls) (list (prod val (@elemtype cs list_structid list_link list_token ls)))) val) val => (let (p0, p) := x in let (p1, y) := p0 in let (h, r) := p1 in fun x0 : environ => @andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) s (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) p h) r)) (is_pointer_or_null y))) (@prop mpred Nveric (@eq val p v))) (@andp mpred Nveric (@prop mpred Nveric (@fold_right Prop Prop and True P)) (@andp mpred Nveric (@prop mpred Nveric (@fold_right (forall _ : environ, Prop) (forall _ : environ, Prop) (fun (x1 x2 : forall _ : environ, Prop) (x3 : environ) => and (x1 x3) (x2 x3)) (fun _ : environ => True) (@map localdef (forall _ : environ, Prop) locald_denote Q) x0)) (@sepcon mpred Nveric Sveric (list_token dsh v) (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls dsh h v) (@sepcon mpred Nveric Sveric (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) v) (@sepcon mpred Nveric Sveric (lseg ls dsh psh r y v2) (fold_right_sepcon R)))))))) rho)) *)
apply derives_extract_prop; intros [? ?].
(* Goal: @derives mpred Nveric (@emp mpred Nveric Sveric) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) *)
(* Goal: @derives mpred Nveric (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) x z) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) *)
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) (@orp mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) x z)) *)
inv H0.
(* Goal: @derives mpred Nveric (@orp mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) p l) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) p l) x z)) (let (p, h) := p in @andp mpred Nveric (@prop mpred Nveric (and (@eq val p x) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh h x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) x)) (lseg ls dsh psh l tail z)))) *)
destruct p.
(* Goal: @derives mpred Nveric (@orp mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) x z)) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) *)
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) (@orp mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) x z)) *)
apply orp_left.
rewrite andp_assoc;
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq v v2)) (@andp mpred Nveric (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) s (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) (@emp mpred Nveric Sveric))) (lseg_cons ls dsh psh s v v2) *)
(* Goal: @derives mpred Nveric (lseg_cons ls dsh psh s v v2) (@orp mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq v v2)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) s (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh s v v2)) *)
do 2 (apply derives_extract_prop; intro).
(* Goal: @derives mpred Nveric (@emp mpred Nveric Sveric) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) *)
(* Goal: @derives mpred Nveric (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) x z) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) *)
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) (@orp mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) x z)) *)
inv H0.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh p) (@list_cell cs list_structid list_link list_token ls dsh h p)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) p)) (lseg ls dsh psh r y z)) (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) p h) r) p z) *)
unfold lseg_cons.
(* Goal: forall (v' : @elemtype cs list_structid list_link list_token ls) (ash bsh psh : share) (p : val) (v : @elemtype cs list_structid list_link list_token ls) (_ : @sepalg.join share Share.Join_ba ash bsh psh) (_ : not (readable_share ash)) (_ : readable_share bsh), @eq mpred (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls ash v' p) (@list_cell cs list_structid list_link list_token ls bsh v p)) (@list_cell cs list_structid list_link list_token ls psh v p) *)
apply derives_extract_prop; intros.
(* Goal: @derives mpred Nveric (@exp mpred Nveric (@elemtype cs list_structid list_link list_token ls) (fun h : @elemtype cs list_structid list_link list_token ls => @exp mpred Nveric (list (prod val (@elemtype cs list_structid list_link list_token ls))) (fun r : list (prod val (@elemtype cs list_structid list_link list_token ls)) => @exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) v e) l) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) x h) r)) (is_pointer_or_null y))) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh h x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z))))) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val v x) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh e x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) x)) (lseg ls dsh psh l tail z)))) *)
apply exp_left; intro h.
(* Goal: @derives mpred Nveric (@exp mpred Nveric (list (prod val (@elemtype cs list_structid list_link list_token ls))) (fun r : list (prod val (@elemtype cs list_structid list_link list_token ls)) => @exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) v e) l) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) x h) r)) (is_pointer_or_null y))) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh h x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val v x) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh e x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) x)) (lseg ls dsh psh l tail z)))) *)
apply exp_left; intro r.
(* Goal: @derives mpred Nveric (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) v e) l) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) x h) r)) (is_pointer_or_null y))) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh h x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z))) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val v x) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh e x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) x)) (lseg ls dsh psh l tail z)))) *)
apply exp_left; intro y.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) v e) l) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) x h) r)) (is_pointer_or_null y))) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh h x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val v x) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh e x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) x)) (lseg ls dsh psh l tail z)))) *)
do 3 rewrite sepcon_andp_prop'.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) s (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) v h) r)) (is_pointer_or_null y))) (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh v) (@list_cell cs list_structid list_link list_token ls dsh h v)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) v)) (lseg ls dsh psh r y v2)) (fold_right_sepcon R))) (@exp mpred Nveric (prod (prod (prod (@elemtype cs list_structid list_link list_token ls) (list (prod val (@elemtype cs list_structid list_link list_token ls)))) val) val) (fun x : prod (prod (prod (@elemtype cs list_structid list_link list_token ls) (list (prod val (@elemtype cs list_structid list_link list_token ls)))) val) val => (let (p0, p) := x in let (p1, y) := p0 in let (h, r) := p1 in fun x0 : environ => @andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) s (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) p h) r)) (is_pointer_or_null y))) (@prop mpred Nveric (@eq val p v))) (@andp mpred Nveric (@prop mpred Nveric (@fold_right Prop Prop and True P)) (@andp mpred Nveric (@prop mpred Nveric (@fold_right (forall _ : environ, Prop) (forall _ : environ, Prop) (fun (x1 x2 : forall _ : environ, Prop) (x3 : environ) => and (x1 x3) (x2 x3)) (fun _ : environ => True) (@map localdef (forall _ : environ, Prop) locald_denote Q) x0)) (@sepcon mpred Nveric Sveric (list_token dsh v) (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls dsh h v) (@sepcon mpred Nveric Sveric (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) v) (@sepcon mpred Nveric Sveric (lseg ls dsh psh r y v2) (fold_right_sepcon R)))))))) rho)) *)
apply derives_extract_prop; intros [? ?].
(* Goal: @derives mpred Nveric (@emp mpred Nveric Sveric) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) *)
(* Goal: @derives mpred Nveric (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) x z) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) *)
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) (@orp mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) x z)) *)
symmetry in H0; inv H0.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
 rewrite prop_true_andp by auto.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh p) (@list_cell cs list_structid list_link list_token ls dsh h p)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) p)) (lseg ls dsh psh r y z)) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) p h) r) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) p h) r)) (is_pointer_or_null y))) (list_token dsh p)) (@list_cell cs list_structid list_link list_token ls dsh h p)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) p)) (lseg ls dsh psh r y z))) *)
apply exp_right with y.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
normalize.
Qed.

Lemma lseg_unroll_nonempty1 (ls: listspec list_structid list_link list_token):
   forall p P dsh psh h tail v1 v2,
    ~ ptr_eq v1 v2 ->
    is_pointer_or_null p ->
    P |-- list_token dsh v1 * list_cell ls dsh h v1 *
             (field_at psh list_struct (StructField list_link :: nil)
                   (valinject (nested_field_type list_struct (StructField list_link :: nil)) p) v1 *
               lseg ls dsh psh tail p v2) ->
    P |-- lseg ls dsh psh ((v1,h)::tail) v1 v2.
(* Goal: forall (v' : @elemtype cs list_structid list_link list_token ls) (ash bsh psh : share) (p : val) (v : @elemtype cs list_structid list_link list_token ls) (_ : @sepalg.join share Share.Join_ba ash bsh psh) (_ : not (readable_share ash)) (_ : readable_share bsh), @eq mpred (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls ash v' p) (@list_cell cs list_structid list_link list_token ls bsh v p)) (@list_cell cs list_structid list_link list_token ls psh v p) *)
Proof. intros. rewrite lseg_unroll. apply orp_right2. unfold lseg_cons.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
  rewrite prop_true_andp by auto.
(* Goal: @derives mpred Nveric P (@exp mpred Nveric (list (prod val (@elemtype cs list_structid list_link list_token ls))) (fun r : list (prod val (@elemtype cs list_structid list_link list_token ls)) => @exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) v1 h) tail) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) v1 h) r)) (is_pointer_or_null y))) (list_token dsh v1)) (@list_cell cs list_structid list_link list_token ls dsh h v1)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) v1)) (lseg ls dsh psh r y v2)))) *)
  apply exp_right with h. apply exp_right with tail. apply exp_right with p.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
    rewrite prop_true_andp by auto.
(* Goal: @derives mpred Nveric P (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh v1) (@list_cell cs list_structid list_link list_token ls dsh h v1)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) p) v1)) (lseg ls dsh psh tail p v2)) *)
 rewrite sepcon_assoc.
(* Goal: @derives mpred Nveric P (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh v1) (@list_cell cs list_structid list_link list_token ls dsh h v1)) (@sepcon mpred Nveric Sveric (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) p) v1) (lseg ls dsh psh tail p v2))) *)
 eapply derives_trans; [ apply H1 | ].
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
 apply sepcon_derives; auto.
Qed.

Lemma lseg_neq (ls: listspec list_structid list_link list_token):
  forall dsh psh s v v2,
    ptr_neq v v2 ->
     lseg ls dsh psh s v v2 = lseg_cons ls dsh psh s v v2.
(* Goal: forall (v' : @elemtype cs list_structid list_link list_token ls) (ash bsh psh : share) (p : val) (v : @elemtype cs list_structid list_link list_token ls) (_ : @sepalg.join share Share.Join_ba ash bsh psh) (_ : not (readable_share ash)) (_ : readable_share bsh), @eq mpred (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls ash v' p) (@list_cell cs list_structid list_link list_token ls bsh v p)) (@list_cell cs list_structid list_link list_token ls psh v p) *)
intros. rewrite lseg_unroll.
(* Goal: @eq mpred (@orp mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) x z)) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) *)
apply pred_ext. apply orp_left; auto.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) *)
(* Goal: @derives mpred Nveric (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) x z) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) *)
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) (@orp mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) x z)) *)
rewrite andp_assoc.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq v v2)) (@andp mpred Nveric (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) s (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) (@emp mpred Nveric Sveric))) (lseg_cons ls dsh psh s v v2) *)
(* Goal: @derives mpred Nveric (lseg_cons ls dsh psh s v v2) (@orp mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq v v2)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) s (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh s v v2)) *)
do 2 (apply derives_extract_prop; intro).
(* Goal: @derives mpred Nveric (@emp mpred Nveric Sveric) (lseg_cons ls dsh psh s v v2) *)
(* Goal: @derives mpred Nveric (lseg_cons ls dsh psh s v v2) (@orp mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq v v2)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) s (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh s v v2)) *)
congruence.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
apply orp_right2. auto.
Qed.

Lemma lseg_nonnull (ls: listspec list_structid list_link list_token):
  forall dsh psh s v,
      typed_true (tptr list_struct) v ->
     lseg ls dsh psh s v nullval = lseg_cons ls dsh psh s v nullval.
Proof.
(* Goal: forall (v' : @elemtype cs list_structid list_link list_token ls) (ash bsh psh : share) (p : val) (v : @elemtype cs list_structid list_link list_token ls) (_ : @sepalg.join share Share.Join_ba ash bsh psh) (_ : not (readable_share ash)) (_ : readable_share bsh), @eq mpred (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls ash v' p) (@list_cell cs list_structid list_link list_token ls bsh v p)) (@list_cell cs list_structid list_link list_token ls psh v p) *)
intros. unfold nullval.
(* Goal: @eq mpred (lseg ls dsh psh s v (if Archi.ptr64 then Vlong Int64.zero else Vint Int.zero)) (lseg_cons ls dsh psh s v (if Archi.ptr64 then Vlong Int64.zero else Vint Int.zero)) *)
apply lseg_neq.
(* Goal: @derives mpred Nveric (@emp mpred Nveric Sveric) (lseg_cons ls dsh psh s v v2) *)
(* Goal: @derives mpred Nveric (lseg_cons ls dsh psh s v v2) (@orp mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq v v2)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) s (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh s v v2)) *)
destruct v; inv H; intuition; try congruence.
(* Goal: ptr_neq (Vptr b i) (if Archi.ptr64 then Vlong Int64.zero else Vint Int.zero) *)
intro. apply ptr_eq_e in H.
(* Goal: False *)
(* Goal: ptr_neq (Vptr b i) (if Archi.ptr64 then Vlong Int64.zero else Vint Int.zero) *)
destruct Archi.ptr64 eqn:Hp; inv H.
(* Goal: False *)
(* Goal: ptr_neq (Vptr b i) (if Archi.ptr64 then Vlong Int64.zero else Vint Int.zero) *)
inv H1.
(* Goal: ptr_neq (Vptr b i) (if Archi.ptr64 then Vlong Int64.zero else Vint Int.zero) *)
intro. simpl in H.
(* Goal: @derives mpred Nveric (@emp mpred Nveric Sveric) (lseg_cons ls dsh psh s v v2) *)
(* Goal: @derives mpred Nveric (lseg_cons ls dsh psh s v v2) (@orp mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq v v2)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) s (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh s v v2)) *)
destruct Archi.ptr64; congruence.
Qed.

Lemma unfold_lseg_neq (ls: listspec list_structid list_link list_token):
   forall P Q1 Q R (v v2: val) dsh psh (s: list (val * elemtype ls)),
      PROPx P (LOCALx (Q1::Q) (SEPx (lseg ls dsh psh s v v2 :: R))) |--
                        !! (ptr_neq v v2) ->
      PROPx P (LOCALx (Q1::Q) (SEPx (lseg ls dsh psh s v v2 :: R))) |--
     EX hryp: elemtype ls * list (val * elemtype ls) * val * val,
      match hryp with (h,r,y,p) =>
       !! (s=(p,h)::r /\ is_pointer_or_null y) &&
       !! (p=v) &&
      PROPx P (LOCALx Q
        (SEPx (list_token dsh v :: list_cell ls dsh h v::
                  field_at psh list_struct (StructField list_link :: nil) (valinject (nested_field_type list_struct (StructField list_link :: nil)) y) v ::
                  lseg ls dsh psh r y v2 ::
                  R)))
        end.
Proof.
(* Goal: forall (v' : @elemtype cs list_structid list_link list_token ls) (ash bsh psh : share) (p : val) (v : @elemtype cs list_structid list_link list_token ls) (_ : @sepalg.join share Share.Join_ba ash bsh psh) (_ : not (readable_share ash)) (_ : readable_share bsh), @eq mpred (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls ash v' p) (@list_cell cs list_structid list_link list_token ls bsh v p)) (@list_cell cs list_structid list_link list_token ls psh v p) *)
intros.
apply derives_trans with
(PROPx P (LOCALx (Q1::Q) (SEPx (lseg_cons ls dsh psh s v v2 :: R)))).
apply derives_trans with
(!! ptr_neq v v2 && PROPx P (LOCALx (Q1::Q) (SEPx (lseg ls dsh psh s v v2 :: R)))).
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
apply andp_right; auto.
(* Goal: @derives (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (@andp (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (@prop (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (ptr_neq v v2)) (PROPx P (LOCALx (@cons localdef Q1 Q) (SEPx (@cons mpred (lseg ls dsh psh s v v2) R))))) (PROPx P (LOCALx (@cons localdef Q1 Q) (SEPx (@cons mpred (lseg_cons ls dsh psh s v v2) R)))) *)
(* Goal: @derives (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (PROPx P (LOCALx (@cons localdef Q1 Q) (SEPx (@cons mpred (lseg_cons ls dsh psh s v v2) R)))) (@exp (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (prod (prod (prod (@elemtype cs list_structid list_link list_token ls) (list (prod val (@elemtype cs list_structid list_link list_token ls)))) val) val) (fun hryp : prod (prod (prod (@elemtype cs list_structid list_link list_token ls) (list (prod val (@elemtype cs list_structid list_link list_token ls)))) val) val => let (p0, p) := hryp in let (p1, y) := p0 in let (h, r) := p1 in @andp (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (@andp (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (@prop (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) s (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) p h) r)) (is_pointer_or_null y))) (@prop (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (@eq val p v))) (PROPx P (LOCALx Q (SEPx (@cons mpred (list_token dsh v) (@cons mpred (@list_cell cs list_structid list_link list_token ls dsh h v) (@cons mpred (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) v) (@cons mpred (lseg ls dsh psh r y v2) R))))))))) *)
intro rho; unfold PROPx,LOCALx,SEPx,local,tc_expr,tc_lvalue; unfold_lift; simpl.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_neq v v2)) (@andp mpred Nveric (@prop mpred Nveric (@fold_right Prop Prop and True P)) (@andp mpred Nveric (@lift1 Prop mpred (@prop mpred Nveric) (fun x : environ => and (locald_denote Q1 x) (@fold_right (forall _ : environ, Prop) (forall _ : environ, Prop) (fun (x0 x1 : forall _ : environ, Prop) (x2 : environ) => and (x0 x2) (x1 x2)) (fun _ : environ => True) (@map localdef (forall _ : environ, Prop) locald_denote Q) x)) rho) (@sepcon mpred Nveric Sveric (lseg ls dsh psh s v v2) (fold_right_sepcon R))))) (@andp mpred Nveric (@prop mpred Nveric (@fold_right Prop Prop and True P)) (@andp mpred Nveric (@lift1 Prop mpred (@prop mpred Nveric) (fun x : environ => and (locald_denote Q1 x) (@fold_right (forall _ : environ, Prop) (forall _ : environ, Prop) (fun (x0 x1 : forall _ : environ, Prop) (x2 : environ) => and (x0 x2) (x1 x2)) (fun _ : environ => True) (@map localdef (forall _ : environ, Prop) locald_denote Q) x)) rho) (@sepcon mpred Nveric Sveric (lseg_cons ls dsh psh s v v2) (fold_right_sepcon R)))) *)
(* Goal: @derives (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (PROPx P (LOCALx (@cons localdef Q1 Q) (SEPx (@cons mpred (lseg_cons ls dsh psh s v v2) R)))) (@exp (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (prod (prod (prod (@elemtype cs list_structid list_link list_token ls) (list (prod val (@elemtype cs list_structid list_link list_token ls)))) val) val) (fun hryp : prod (prod (prod (@elemtype cs list_structid list_link list_token ls) (list (prod val (@elemtype cs list_structid list_link list_token ls)))) val) val => let (p0, p) := hryp in let (p1, y) := p0 in let (h, r) := p1 in @andp (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (@andp (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (@prop (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) s (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) p h) r)) (is_pointer_or_null y))) (@prop (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (@eq val p v))) (PROPx P (LOCALx Q (SEPx (@cons mpred (list_token dsh v) (@cons mpred (@list_cell cs list_structid list_link list_token ls dsh h v) (@cons mpred (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) v) (@cons mpred (lseg ls dsh psh r y v2) R))))))))) *)
unfold lift1; simpl.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_neq v v2)) (@andp mpred Nveric (@prop mpred Nveric (@fold_right Prop Prop and True P)) (@andp mpred Nveric (@prop mpred Nveric (and (locald_denote Q1 rho) (@fold_right (forall _ : environ, Prop) (forall _ : environ, Prop) (fun (x x0 : forall _ : environ, Prop) (x1 : environ) => and (x x1) (x0 x1)) (fun _ : environ => True) (@map localdef (forall _ : environ, Prop) locald_denote Q) rho))) (@sepcon mpred Nveric Sveric (lseg ls dsh psh s v v2) (fold_right_sepcon R))))) (@andp mpred Nveric (@prop mpred Nveric (@fold_right Prop Prop and True P)) (@andp mpred Nveric (@prop mpred Nveric (and (locald_denote Q1 rho) (@fold_right (forall _ : environ, Prop) (forall _ : environ, Prop) (fun (x x0 : forall _ : environ, Prop) (x1 : environ) => and (x x1) (x0 x1)) (fun _ : environ => True) (@map localdef (forall _ : environ, Prop) locald_denote Q) rho))) (@sepcon mpred Nveric Sveric (lseg_cons ls dsh psh s v v2) (fold_right_sepcon R)))) *)
(* Goal: @derives (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (PROPx P (LOCALx (@cons localdef Q1 Q) (SEPx (@cons mpred (lseg_cons ls dsh psh s v v2) R)))) (@exp (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (prod (prod (prod (@elemtype cs list_structid list_link list_token ls) (list (prod val (@elemtype cs list_structid list_link list_token ls)))) val) val) (fun hryp : prod (prod (prod (@elemtype cs list_structid list_link list_token ls) (list (prod val (@elemtype cs list_structid list_link list_token ls)))) val) val => let (p0, p) := hryp in let (p1, y) := p0 in let (h, r) := p1 in @andp (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (@andp (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (@prop (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) s (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) p h) r)) (is_pointer_or_null y))) (@prop (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (@eq val p v))) (PROPx P (LOCALx Q (SEPx (@cons mpred (list_token dsh v) (@cons mpred (@list_cell cs list_structid list_link list_token ls dsh h v) (@cons mpred (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) v) (@cons mpred (lseg ls dsh psh r y v2) R))))))))) *)
 repeat (apply derives_extract_prop; intro).
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
 rewrite prop_true_andp by auto.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
 rewrite prop_true_andp by auto.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
apply sepcon_derives; auto.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
rewrite lseg_neq; auto.
(* Goal: @derives (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (PROPx P (LOCALx (@cons localdef Q1 Q) (SEPx (@cons mpred (lseg_cons ls dsh psh s v v2) R)))) (@exp (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (prod (prod (prod (@elemtype cs list_structid list_link list_token ls) (list (prod val (@elemtype cs list_structid list_link list_token ls)))) val) val) (fun hryp : prod (prod (prod (@elemtype cs list_structid list_link list_token ls) (list (prod val (@elemtype cs list_structid list_link list_token ls)))) val) val => let (p0, p) := hryp in let (p1, y) := p0 in let (h, r) := p1 in @andp (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (@andp (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (@prop (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) s (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) p h) r)) (is_pointer_or_null y))) (@prop (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (@eq val p v))) (PROPx P (LOCALx Q (SEPx (@cons mpred (list_token dsh v) (@cons mpred (@list_cell cs list_structid list_link list_token ls dsh h v) (@cons mpred (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) v) (@cons mpred (lseg ls dsh psh r y v2) R))))))))) *)
intro rho; unfold PROPx,LOCALx,SEPx,local,tc_expr,tc_lvalue,lift2,lift1,lift0; simpl.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@fold_right Prop Prop and True P)) (@andp mpred Nveric (@prop mpred Nveric (@liftx (Tarrow Prop (Tarrow Prop (LiftEnviron Prop))) and (locald_denote Q1) (@fold_right (forall _ : environ, Prop) (forall _ : environ, Prop) (@liftx (Tarrow Prop (Tarrow Prop (LiftEnviron Prop))) and) (@liftx (LiftEnviron Prop) True) (@map localdef (forall _ : environ, Prop) locald_denote Q)) rho)) (@sepcon mpred Nveric Sveric (lseg_cons ls dsh psh s v v2) (fold_right_sepcon R)))) (@exp mpred Nveric (prod (prod (prod (@elemtype cs list_structid list_link list_token ls) (list (prod val (@elemtype cs list_structid list_link list_token ls)))) val) val) (fun x : prod (prod (prod (@elemtype cs list_structid list_link list_token ls) (list (prod val (@elemtype cs list_structid list_link list_token ls)))) val) val => (let (p0, p) := x in let (p1, y) := p0 in let (h, r) := p1 in fun x0 : environ => @andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) s (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) p h) r)) (is_pointer_or_null y))) (@prop mpred Nveric (@eq val p v))) (@andp mpred Nveric (@prop mpred Nveric (@fold_right Prop Prop and True P)) (@andp mpred Nveric (@prop mpred Nveric (@fold_right (forall _ : environ, Prop) (forall _ : environ, Prop) (@liftx (Tarrow Prop (Tarrow Prop (LiftEnviron Prop))) and) (@liftx (LiftEnviron Prop) True) (@map localdef (forall _ : environ, Prop) locald_denote Q) x0)) (@sepcon mpred Nveric Sveric (list_token dsh v) (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls dsh h v) (@sepcon mpred Nveric Sveric (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) v) (@sepcon mpred Nveric Sveric (lseg ls dsh psh r y v2) (fold_right_sepcon R)))))))) rho)) *)
 unfold_lift.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh p) (@list_cell cs list_structid list_link list_token ls dsh h p)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) p)) (lseg ls dsh psh r y z)) (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) p h) r) p z) *)
 unfold lseg_cons. simpl.
(* Goal: ptr_neq (Vptr b i) (if Archi.ptr64 then Vlong Int64.zero else Vint Int.zero) *)
 apply derives_extract_prop; intro.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) s (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) v h) r)) (is_pointer_or_null y))) (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh v) (@list_cell cs list_structid list_link list_token ls dsh h v)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) v)) (lseg ls dsh psh r y v2)) (fold_right_sepcon R))) (@exp mpred Nveric (prod (prod (prod (@elemtype cs list_structid list_link list_token ls) (list (prod val (@elemtype cs list_structid list_link list_token ls)))) val) val) (fun x : prod (prod (prod (@elemtype cs list_structid list_link list_token ls) (list (prod val (@elemtype cs list_structid list_link list_token ls)))) val) val => (let (p0, p) := x in let (p1, y) := p0 in let (h, r) := p1 in fun x0 : environ => @andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) s (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) p h) r)) (is_pointer_or_null y))) (@prop mpred Nveric (@eq val p v))) (@andp mpred Nveric (@prop mpred Nveric (@fold_right Prop Prop and True P)) (@andp mpred Nveric (@prop mpred Nveric (@fold_right (forall _ : environ, Prop) (forall _ : environ, Prop) (fun (x1 x2 : forall _ : environ, Prop) (x3 : environ) => and (x1 x3) (x2 x3)) (fun _ : environ => True) (@map localdef (forall _ : environ, Prop) locald_denote Q) x0)) (@sepcon mpred Nveric Sveric (list_token dsh v) (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls dsh h v) (@sepcon mpred Nveric Sveric (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) v) (@sepcon mpred Nveric Sveric (lseg ls dsh psh r y v2) (fold_right_sepcon R)))))))) rho)) *)
 apply derives_extract_prop; intros [? ?].
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (not (ptr_eq v v2))) (@exp mpred Nveric (@elemtype cs list_structid list_link list_token ls) (fun h : @elemtype cs list_structid list_link list_token ls => @exp mpred Nveric (list (prod val (@elemtype cs list_structid list_link list_token ls))) (fun r : list (prod val (@elemtype cs list_structid list_link list_token ls)) => @exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) s (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) v h) r)) (is_pointer_or_null y))) (list_token dsh v)) (@list_cell cs list_structid list_link list_token ls dsh h v)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) v)) (lseg ls dsh psh r y v2)))))) (fold_right_sepcon R)) (@exp mpred Nveric (prod (prod (prod (@elemtype cs list_structid list_link list_token ls) (list (prod val (@elemtype cs list_structid list_link list_token ls)))) val) val) (fun x : prod (prod (prod (@elemtype cs list_structid list_link list_token ls) (list (prod val (@elemtype cs list_structid list_link list_token ls)))) val) val => (let (p0, p) := x in let (p1, y) := p0 in let (h, r) := p1 in fun x0 : environ => @andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) s (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) p h) r)) (is_pointer_or_null y))) (@prop mpred Nveric (@eq val p v))) (@andp mpred Nveric (@prop mpred Nveric (@fold_right Prop Prop and True P)) (@andp mpred Nveric (@prop mpred Nveric (@fold_right (forall _ : environ, Prop) (forall _ : environ, Prop) (fun (x1 x2 : forall _ : environ, Prop) (x3 : environ) => and (x1 x3) (x2 x3)) (fun _ : environ => True) (@map localdef (forall _ : environ, Prop) locald_denote Q) x0)) (@sepcon mpred Nveric Sveric (list_token dsh v) (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls dsh h v) (@sepcon mpred Nveric Sveric (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) v) (@sepcon mpred Nveric Sveric (lseg ls dsh psh r y v2) (fold_right_sepcon R)))))))) rho)) *)
 rewrite sepcon_andp_prop'.
(* Goal: ptr_neq (Vptr b i) (if Archi.ptr64 then Vlong Int64.zero else Vint Int.zero) *)
 apply derives_extract_prop; intro.
(* Goal: @derives mpred Nveric (@exp mpred Nveric (@elemtype cs list_structid list_link list_token ls) (fun h : @elemtype cs list_structid list_link list_token ls => @exp mpred Nveric (list (prod val (@elemtype cs list_structid list_link list_token ls))) (fun r : list (prod val (@elemtype cs list_structid list_link list_token ls)) => @exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) v e) l) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) x h) r)) (is_pointer_or_null y))) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh h x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z))))) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val v x) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh e x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) x)) (lseg ls dsh psh l tail z)))) *)
 rewrite exp_sepcon1; apply exp_left; intro h.
(* Goal: @derives mpred Nveric (@exp mpred Nveric (list (prod val (@elemtype cs list_structid list_link list_token ls))) (fun r : list (prod val (@elemtype cs list_structid list_link list_token ls)) => @exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) v e) l) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) x h) r)) (is_pointer_or_null y))) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh h x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val v x) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh e x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) x)) (lseg ls dsh psh l tail z)))) *)
 rewrite exp_sepcon1; apply exp_left; intro r.
(* Goal: @derives mpred Nveric (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) v e) l) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) x h) r)) (is_pointer_or_null y))) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh h x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z))) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val v x) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh e x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) x)) (lseg ls dsh psh l tail z)))) *)
 rewrite exp_sepcon1; apply exp_left; intro y.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) s (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) v h) r)) (is_pointer_or_null y))) (list_token dsh v)) (@list_cell cs list_structid list_link list_token ls dsh h v)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) v)) (lseg ls dsh psh r y v2)) (fold_right_sepcon R)) (@exp mpred Nveric (prod (prod (prod (@elemtype cs list_structid list_link list_token ls) (list (prod val (@elemtype cs list_structid list_link list_token ls)))) val) val) (fun x : prod (prod (prod (@elemtype cs list_structid list_link list_token ls) (list (prod val (@elemtype cs list_structid list_link list_token ls)))) val) val => (let (p0, p) := x in let (p1, y) := p0 in let (h, r) := p1 in fun x0 : environ => @andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) s (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) p h) r)) (is_pointer_or_null y))) (@prop mpred Nveric (@eq val p v))) (@andp mpred Nveric (@prop mpred Nveric (@fold_right Prop Prop and True P)) (@andp mpred Nveric (@prop mpred Nveric (@fold_right (forall _ : environ, Prop) (forall _ : environ, Prop) (fun (x1 x2 : forall _ : environ, Prop) (x3 : environ) => and (x1 x3) (x2 x3)) (fun _ : environ => True) (@map localdef (forall _ : environ, Prop) locald_denote Q) x0)) (@sepcon mpred Nveric Sveric (list_token dsh v) (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls dsh h v) (@sepcon mpred Nveric Sveric (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) v) (@sepcon mpred Nveric Sveric (lseg ls dsh psh r y v2) (fold_right_sepcon R)))))))) rho)) *)
 repeat rewrite sepcon_andp_prop'.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) s (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) v h) r)) (is_pointer_or_null y))) (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh v) (@list_cell cs list_structid list_link list_token ls dsh h v)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) v)) (lseg ls dsh psh r y v2)) (fold_right_sepcon R))) (@exp mpred Nveric (prod (prod (prod (@elemtype cs list_structid list_link list_token ls) (list (prod val (@elemtype cs list_structid list_link list_token ls)))) val) val) (fun x : prod (prod (prod (@elemtype cs list_structid list_link list_token ls) (list (prod val (@elemtype cs list_structid list_link list_token ls)))) val) val => (let (p0, p) := x in let (p1, y) := p0 in let (h, r) := p1 in fun x0 : environ => @andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) s (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) p h) r)) (is_pointer_or_null y))) (@prop mpred Nveric (@eq val p v))) (@andp mpred Nveric (@prop mpred Nveric (@fold_right Prop Prop and True P)) (@andp mpred Nveric (@prop mpred Nveric (@fold_right (forall _ : environ, Prop) (forall _ : environ, Prop) (fun (x1 x2 : forall _ : environ, Prop) (x3 : environ) => and (x1 x3) (x2 x3)) (fun _ : environ => True) (@map localdef (forall _ : environ, Prop) locald_denote Q) x0)) (@sepcon mpred Nveric Sveric (list_token dsh v) (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls dsh h v) (@sepcon mpred Nveric Sveric (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) v) (@sepcon mpred Nveric Sveric (lseg ls dsh psh r y v2) (fold_right_sepcon R)))))))) rho)) *)
 apply derives_extract_prop; intros [? ?].
(* Goal: and True (iff (@eq val (Vptr b0 i) (Vptr b0 i0)) (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) *)
(* Goal: @derives mpred Nveric (let (p0, h) := p0 in @andp mpred Nveric (@prop mpred Nveric (and (@eq val p0 p) (not (ptr_eq p q)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh p)) (@list_cell cs list_structid list_link list_token ls dsh h p)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) p)) (lseg ls dsh psh contents tail q)))) (@prop mpred Nveric (and (is_pointer_or_null p) (iff (@eq val p q) (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) p0 contents) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))))) *)
 subst.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh v) (@list_cell cs list_structid list_link list_token ls dsh h v)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) v)) (lseg ls dsh psh r y v2)) (fold_right_sepcon R)) (@exp mpred Nveric (prod (prod (prod (@elemtype cs list_structid list_link list_token ls) (list (prod val (@elemtype cs list_structid list_link list_token ls)))) val) val) (fun x : prod (prod (prod (@elemtype cs list_structid list_link list_token ls) (list (prod val (@elemtype cs list_structid list_link list_token ls)))) val) val => (let (p0, p) := x in let (p1, y) := p0 in let (h0, r0) := p1 in fun x0 : environ => @andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) v h) r) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) p h0) r0)) (is_pointer_or_null y))) (@prop mpred Nveric (@eq val p v))) (@andp mpred Nveric (@prop mpred Nveric (@fold_right Prop Prop and True P)) (@andp mpred Nveric (@prop mpred Nveric (@fold_right (forall _ : environ, Prop) (forall _ : environ, Prop) (fun (x1 x2 : forall _ : environ, Prop) (x3 : environ) => and (x1 x3) (x2 x3)) (fun _ : environ => True) (@map localdef (forall _ : environ, Prop) locald_denote Q) x0)) (@sepcon mpred Nveric Sveric (list_token dsh v) (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls dsh h0 v) (@sepcon mpred Nveric Sveric (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) v) (@sepcon mpred Nveric Sveric (lseg ls dsh psh r0 y v2) (fold_right_sepcon R)))))))) rho)) *)
 apply exp_right with (h,r,y, v).
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
 repeat rewrite prop_true_andp by auto.
(* Goal: @derives mpred Nveric P (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh v1) (@list_cell cs list_structid list_link list_token ls dsh h v1)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) p) v1)) (lseg ls dsh psh tail p v2)) *)
 repeat rewrite sepcon_assoc.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
 auto.
Qed.

Lemma unfold_lseg_cons (ls: listspec list_structid list_link list_token):
   forall P Q1 Q R e dsh psh s,
      PROPx P (LOCALx (Q1::Q) (SEPx (lseg ls dsh psh s e nullval :: R))) |--
                        !! (typed_true (tptr list_struct) e) ->
      PROPx P (LOCALx (Q1::Q) (SEPx (lseg ls dsh psh s e nullval :: R))) |--
     EX hryp: elemtype ls * list (val * elemtype ls) * val * val,
      match hryp with (h,r,y,p) =>
       !! (s=(p,h)::r /\ is_pointer_or_null y) &&
       !! (p=e)&&
      PROPx P (LOCALx Q
        (SEPx (list_token dsh e :: list_cell ls dsh h e ::
                  field_at psh list_struct (StructField list_link :: nil) (valinject (nested_field_type list_struct (StructField list_link :: nil)) y) e ::
                  lseg ls dsh psh r y nullval ::
                  R)))
        end.
Proof.
(* Goal: forall (v' : @elemtype cs list_structid list_link list_token ls) (ash bsh psh : share) (p : val) (v : @elemtype cs list_structid list_link list_token ls) (_ : @sepalg.join share Share.Join_ba ash bsh psh) (_ : not (readable_share ash)) (_ : readable_share bsh), @eq mpred (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls ash v' p) (@list_cell cs list_structid list_link list_token ls bsh v p)) (@list_cell cs list_structid list_link list_token ls psh v p) *)
intros. apply unfold_lseg_neq.
eapply derives_trans.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
apply H. normalize.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@fold_right Prop Prop and True P)) (@andp mpred Nveric (@prop mpred Nveric (@liftx (Tarrow Prop (Tarrow Prop (LiftEnviron Prop))) and (locald_denote Q1) (@fold_right (forall _ : environ, Prop) (forall _ : environ, Prop) (@liftx (Tarrow Prop (Tarrow Prop (LiftEnviron Prop))) and) (@liftx (LiftEnviron Prop) True) (@map localdef (forall _ : environ, Prop) locald_denote Q)) rho)) (@sepcon mpred Nveric Sveric (lseg_cons ls dsh psh s v v2) (fold_right_sepcon R)))) (@exp mpred Nveric (prod (prod (prod (@elemtype cs list_structid list_link list_token ls) (list (prod val (@elemtype cs list_structid list_link list_token ls)))) val) val) (fun x : prod (prod (prod (@elemtype cs list_structid list_link list_token ls) (list (prod val (@elemtype cs list_structid list_link list_token ls)))) val) val => (let (p0, p) := x in let (p1, y) := p0 in let (h, r) := p1 in fun x0 : environ => @andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) s (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) p h) r)) (is_pointer_or_null y))) (@prop mpred Nveric (@eq val p v))) (@andp mpred Nveric (@prop mpred Nveric (@fold_right Prop Prop and True P)) (@andp mpred Nveric (@prop mpred Nveric (@fold_right (forall _ : environ, Prop) (forall _ : environ, Prop) (@liftx (Tarrow Prop (Tarrow Prop (LiftEnviron Prop))) and) (@liftx (LiftEnviron Prop) True) (@map localdef (forall _ : environ, Prop) locald_denote Q) x0)) (@sepcon mpred Nveric Sveric (list_token dsh v) (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls dsh h v) (@sepcon mpred Nveric Sveric (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) v) (@sepcon mpred Nveric Sveric (lseg ls dsh psh r y v2) (fold_right_sepcon R)))))))) rho)) *)
unfold local. super_unfold_lift.
(* Goal: @eq mpred (lseg ls dsh psh s v nullval) (lseg_cons ls dsh psh s v nullval) *)
unfold nullval.
(* Goal: ptr_neq (Vptr b i) (if Archi.ptr64 then Vlong Int64.zero else Vint Int.zero) *)
intro.
(* Goal: and True (iff (@eq val (Vptr b0 i) (Vptr b0 i0)) (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) *)
(* Goal: @derives mpred Nveric (let (p0, h) := p0 in @andp mpred Nveric (@prop mpred Nveric (and (@eq val p0 p) (not (ptr_eq p q)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh p)) (@list_cell cs list_structid list_link list_token ls dsh h p)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) p)) (lseg ls dsh psh contents tail q)))) (@prop mpred Nveric (and (is_pointer_or_null p) (iff (@eq val p q) (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) p0 contents) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))))) *)
apply ptr_eq_e in H1. subst.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
normalize.
Qed.

Lemma semax_lseg_neq (ls: listspec list_structid list_link list_token):
  forall (Espec: OracleKind)
      Delta P Q dsh psh s v v2 R c Post,
    ~ (ptr_eq v v2) ->
  (forall (h: elemtype ls) (r: list (val * elemtype ls)) (y: val),
    s=(v,h)::r -> is_pointer_or_null y ->
    semax Delta
        (PROPx P (LOCALx Q
        (SEPx (list_token dsh v :: list_cell ls dsh h v ::
                  field_at psh list_struct (StructField list_link :: nil)
                      (valinject (nested_field_type list_struct (StructField list_link :: nil)) y) v ::
                  lseg ls dsh psh r y v2 ::
                  R)))) c Post) ->
   semax Delta
       (PROPx P (LOCALx Q (SEPx (lseg ls dsh psh s v v2 :: R))))
       c Post.
Proof.
(* Goal: forall (v' : @elemtype cs list_structid list_link list_token ls) (ash bsh psh : share) (p : val) (v : @elemtype cs list_structid list_link list_token ls) (_ : @sepalg.join share Share.Join_ba ash bsh psh) (_ : not (readable_share ash)) (_ : readable_share bsh), @eq mpred (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls ash v' p) (@list_cell cs list_structid list_link list_token ls bsh v p)) (@list_cell cs list_structid list_link list_token ls psh v p) *)
intros.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
rewrite lseg_neq by auto.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh p) (@list_cell cs list_structid list_link list_token ls dsh h p)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) p)) (lseg ls dsh psh r y z)) (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) p h) r) p z) *)
unfold lseg_cons.
apply semax_pre0 with
 (EX h: elemtype ls, EX r: list (val * elemtype ls), EX y: val,
  !!(s = (v, h) :: r /\ is_pointer_or_null y) &&
    PROPx P (LOCALx Q (SEPx (list_token dsh v :: list_cell ls dsh h v ::
       field_at psh list_struct (StructField list_link :: nil)
                   (valinject
                      (nested_field_type list_struct
                         (StructField list_link :: nil)) y) v ::
        lseg ls dsh psh r y v2 :: R)))).
(* Goal: @derives (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (PROPx P (LOCALx Q (SEPx (@cons mpred (@andp mpred Nveric (@prop mpred Nveric (not (ptr_eq v v2))) (@exp mpred Nveric (@elemtype cs list_structid list_link list_token ls) (fun h : @elemtype cs list_structid list_link list_token ls => @exp mpred Nveric (list (prod val (@elemtype cs list_structid list_link list_token ls))) (fun r : list (prod val (@elemtype cs list_structid list_link list_token ls)) => @exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) s (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) v h) r)) (is_pointer_or_null y))) (list_token dsh v)) (@list_cell cs list_structid list_link list_token ls dsh h v)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) v)) (lseg ls dsh psh r y v2)))))) R)))) (@exp (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (@elemtype cs list_structid list_link list_token ls) (fun h : @elemtype cs list_structid list_link list_token ls => @exp (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (list (prod val (@elemtype cs list_structid list_link list_token ls))) (fun r : list (prod val (@elemtype cs list_structid list_link list_token ls)) => @exp (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) val (fun y : val => @andp (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (@prop (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) s (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) v h) r)) (is_pointer_or_null y))) (PROPx P (LOCALx Q (SEPx (@cons mpred (list_token dsh v) (@cons mpred (@list_cell cs list_structid list_link list_token ls dsh h v) (@cons mpred (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) v) (@cons mpred (lseg ls dsh psh r y v2) R))))))))))) *)
(* Goal: semax cs Espec Delta (@exp (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (@elemtype cs list_structid list_link list_token ls) (fun h : @elemtype cs list_structid list_link list_token ls => @exp (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (list (prod val (@elemtype cs list_structid list_link list_token ls))) (fun r : list (prod val (@elemtype cs list_structid list_link list_token ls)) => @exp (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) val (fun y : val => @andp (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (@prop (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) s (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) v h) r)) (is_pointer_or_null y))) (PROPx P (LOCALx Q (SEPx (@cons mpred (list_token dsh v) (@cons mpred (@list_cell cs list_structid list_link list_token ls dsh h v) (@cons mpred (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) v) (@cons mpred (lseg ls dsh psh r y v2) R))))))))))) c Post *)
go_lowerx; entailer.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh v) (@list_cell cs list_structid list_link list_token ls dsh h v)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) v)) (lseg ls dsh psh r y v2)) (fold_right_sepcon R)) (@exp mpred Nveric (@elemtype cs list_structid list_link list_token ls) (fun x : @elemtype cs list_structid list_link list_token ls => @exp mpred Nveric (list (prod val (@elemtype cs list_structid list_link list_token ls))) (fun x0 : list (prod val (@elemtype cs list_structid list_link list_token ls)) => @exp mpred Nveric val (fun x1 : val => @andp mpred Nveric (@prop mpred Nveric (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) v h) r) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) v x) x0)) (is_pointer_or_null x1))) (@andp mpred Nveric (@TT mpred Nveric) (@andp mpred Nveric (@TT mpred Nveric) (@sepcon mpred Nveric Sveric (list_token dsh v) (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls dsh x v) (@sepcon mpred Nveric Sveric (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) x1) v) (@sepcon mpred Nveric Sveric (lseg ls dsh psh x0 x1 v2) (fold_right_sepcon R))))))))))) *)
(* Goal: semax cs Espec Delta (@exp (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (@elemtype cs list_structid list_link list_token ls) (fun h : @elemtype cs list_structid list_link list_token ls => @exp (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (list (prod val (@elemtype cs list_structid list_link list_token ls))) (fun r : list (prod val (@elemtype cs list_structid list_link list_token ls)) => @exp (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) val (fun y : val => @andp (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (@prop (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) s (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) v h) r)) (is_pointer_or_null y))) (PROPx P (LOCALx Q (SEPx (@cons mpred (list_token dsh v) (@cons mpred (@list_cell cs list_structid list_link list_token ls dsh h v) (@cons mpred (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) v) (@cons mpred (lseg ls dsh psh r y v2) R))))))))))) c Post *)
Exists h r y.
rewrite <- ?sepcon_assoc.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
normalize.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
  autorewrite with subst norm1 norm2; normalize.
(* Goal: semax cs Espec Delta (@exp (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (@elemtype cs list_structid list_link list_token ls) (fun h : @elemtype cs list_structid list_link list_token ls => @exp (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (list (prod val (@elemtype cs list_structid list_link list_token ls))) (fun r : list (prod val (@elemtype cs list_structid list_link list_token ls)) => @exp (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) val (fun y : val => @andp (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (@prop (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) s (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) v h) r)) (is_pointer_or_null y))) (PROPx P (LOCALx Q (SEPx (@cons mpred (list_token dsh v) (@cons mpred (@list_cell cs list_structid list_link list_token ls dsh h v) (@cons mpred (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) v) (@cons mpred (lseg ls dsh psh r y v2) R))))))))))) c Post *)
Intros h r y.
(* Goal: semax cs Espec Delta (@andp (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (@prop (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) s (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) v h) r)) (is_pointer_or_null y))) (PROPx P (LOCALx Q (SEPx (@cons mpred (list_token dsh v) (@cons mpred (@list_cell cs list_structid list_link list_token ls dsh h v) (@cons mpred (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) v) (@cons mpred (lseg ls dsh psh r y v2) R)))))))) c Post *)
apply semax_extract_prop; intros [? ?].
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
eapply H0; eauto.
Qed.


Lemma semax_lseg_nonnull (ls: listspec list_structid list_link list_token):
  forall (Espec: OracleKind)
      Delta P Q dsh psh s v R c Post,
   ENTAIL Delta, PROPx P (LOCALx Q
            (SEPx (lseg ls dsh psh s v nullval :: R))) |--
                        !!(typed_true (tptr list_struct) v)  ->
  (forall (h: elemtype ls) (r: list (val * elemtype ls)) (y: val),
    s=(v,h)::r -> is_pointer_or_null y ->
    semax Delta
        (PROPx P (LOCALx Q
        (SEPx (list_token dsh v :: list_cell ls dsh h v ::
                  field_at psh list_struct (StructField list_link :: nil) (valinject (nested_field_type list_struct (StructField list_link :: nil)) y) v ::
                  lseg ls dsh psh r y nullval ::
                  R)))) c Post) ->
   semax Delta
       (PROPx P (LOCALx Q (SEPx (lseg ls dsh psh s v nullval :: R))))
       c Post.
Proof.
(* Goal: forall (v' : @elemtype cs list_structid list_link list_token ls) (ash bsh psh : share) (p : val) (v : @elemtype cs list_structid list_link list_token ls) (_ : @sepalg.join share Share.Join_ba ash bsh psh) (_ : not (readable_share ash)) (_ : readable_share bsh), @eq mpred (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls ash v' p) (@list_cell cs list_structid list_link list_token ls bsh v p)) (@list_cell cs list_structid list_link list_token ls psh v p) *)
intros.
(* Goal: semax cs Espec Delta (PROPx P (LOCALx Q (SEPx (@cons mpred (lseg ls dsh psh s v nullval) R)))) c Post *)
assert_PROP (~ ptr_eq v nullval).
(* Goal: @derives (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (@andp (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (local (tc_environ Delta)) (PROPx P (LOCALx Q (SEPx (@cons mpred (lseg ls dsh psh s v nullval) R))))) (@prop (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (not (ptr_eq v nullval))) *)
(* Goal: semax cs Espec Delta (PROPx P (LOCALx Q (SEPx (@cons mpred (lseg ls dsh psh s v nullval) R)))) c Post *)
eapply derives_trans; [apply H |].
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
normalize.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
apply semax_lseg_neq; auto.
Qed.

Lemma lseg_nil_eq (ls: listspec list_structid list_link list_token):
    forall dsh psh p q, lseg ls dsh psh nil p q = !! (ptr_eq p q) && emp.
(* Goal: forall (v' : @elemtype cs list_structid list_link list_token ls) (ash bsh psh : share) (p : val) (v : @elemtype cs list_structid list_link list_token ls) (_ : @sepalg.join share Share.Join_ba ash bsh psh) (_ : not (readable_share ash)) (_ : readable_share bsh), @eq mpred (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls ash v' p) (@list_cell cs list_structid list_link list_token ls bsh v p)) (@list_cell cs list_structid list_link list_token ls psh v p) *)
Proof. intros.
(* Goal: @eq mpred (lseg ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) x z) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) *)
 rewrite lseg_unroll.
(* Goal: @eq mpred (@orp mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) x z)) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) *)
 apply pred_ext.
(* Goal: @derives mpred Nveric (@orp mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) x z)) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) *)
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) (@orp mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) x z)) *)
 apply orp_left.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) *)
(* Goal: @derives mpred Nveric (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) x z) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) *)
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) (@orp mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) x z)) *)
 rewrite andp_assoc.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@andp mpred Nveric (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) (@emp mpred Nveric Sveric))) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
(* Goal: @derives mpred Nveric (lseg_cons ls dsh psh (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) p q) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@orp mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) p q)) *)
 apply andp_derives; auto.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
rewrite prop_true_andp by auto. auto.
(* Goal: @derives mpred Nveric (@emp mpred Nveric Sveric) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) *)
(* Goal: @derives mpred Nveric (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) x z) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) *)
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) (@orp mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) x z)) *)
 unfold lseg_cons. normalize. inv H0.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) *)
(* Goal: @derives mpred Nveric (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) x z) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) *)
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) (@orp mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) x z)) *)
 apply orp_right1.  rewrite andp_assoc.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
 rewrite (prop_true_andp (_ = _)) by auto. auto.
Qed.

Lemma lseg_cons_eq (ls: listspec list_structid list_link list_token):
     forall dsh psh h r x z ,
    lseg ls dsh psh (h::r) x z =
        !!(x = fst h /\ ~ ptr_eq x z) &&
         (EX  y : val,
          !!(is_pointer_or_null y) &&
   list_token dsh x * list_cell ls dsh (snd h) x * field_at psh list_struct (StructField list_link :: nil) (valinject (nested_field_type list_struct (StructField list_link :: nil)) y) x *
   lseg ls dsh psh r y z).
Proof.
(* Goal: forall (v' : @elemtype cs list_structid list_link list_token ls) (ash bsh psh : share) (p : val) (v : @elemtype cs list_structid list_link list_token ls) (_ : @sepalg.join share Share.Join_ba ash bsh psh) (_ : not (readable_share ash)) (_ : readable_share bsh), @eq mpred (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls ash v' p) (@list_cell cs list_structid list_link list_token ls bsh v p)) (@list_cell cs list_structid list_link list_token ls psh v p) *)
 intros. rewrite lseg_unroll.
(* Goal: @eq mpred (@orp mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) x z)) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) *)
 apply pred_ext.
(* Goal: @derives mpred Nveric (@orp mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) x z)) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) *)
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) (@orp mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) x z)) *)
 apply orp_left.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) *)
(* Goal: @derives mpred Nveric (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) x z) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) *)
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) (@orp mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) x z)) *)
 rewrite andp_assoc.
(* Goal: ptr_neq (Vptr b i) (if Archi.ptr64 then Vlong Int64.zero else Vint Int.zero) *)
 apply derives_extract_prop; intro.
(* Goal: ptr_neq (Vptr b i) (if Archi.ptr64 then Vlong Int64.zero else Vint Int.zero) *)
 apply derives_extract_prop; intro.
(* Goal: @derives mpred Nveric (@emp mpred Nveric Sveric) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) *)
(* Goal: @derives mpred Nveric (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) x z) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) *)
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) (@orp mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) x z)) *)
 inv H0.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh p) (@list_cell cs list_structid list_link list_token ls dsh h p)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) p)) (lseg ls dsh psh r y z)) (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) p h) r) p z) *)
 unfold lseg_cons.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
 normalize.
(* Goal: @derives mpred Nveric (@emp mpred Nveric Sveric) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) *)
(* Goal: @derives mpred Nveric (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) x z) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) *)
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) (@orp mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) x z)) *)
 symmetry in H0; inv H0.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
 apply exp_right with y. normalize.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
  autorewrite with subst norm1 norm2; normalize.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
 normalize. destruct h as [p h]. simpl in *.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh p) (@list_cell cs list_structid list_link list_token ls dsh h p)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) p)) (lseg ls dsh psh r y z)) (@orp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (and (ptr_eq p z) (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) p h) r) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) p h) r) p z)) *)
 apply orp_right2.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh p) (@list_cell cs list_structid list_link list_token ls dsh h p)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) p)) (lseg ls dsh psh r y z)) (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) p h) r) p z) *)
 unfold lseg_cons.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
 rewrite prop_true_andp by auto.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh p) (@list_cell cs list_structid list_link list_token ls dsh h p)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) p)) (lseg ls dsh psh r y z)) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) p h) r) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) p h) r)) (is_pointer_or_null y))) (list_token dsh p)) (@list_cell cs list_structid list_link list_token ls dsh h p)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) p)) (lseg ls dsh psh r y z))) *)
 apply exp_right with h. apply exp_right with r.  apply exp_right with y.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
 normalize.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
  autorewrite with subst norm1 norm2; normalize.
Qed.

Definition lseg_cons_right (ls: listspec list_structid list_link list_token)
           dsh psh (l: list (val * elemtype ls)) (x z: val) : mpred :=
        !! (~ ptr_eq x z) &&
       EX h:(elemtype ls), EX r:list (val * elemtype ls), EX y:val,
             !!(l=r++(y,h)::nil /\ is_pointer_or_null y)  &&
                       list_token dsh y * list_cell ls dsh h y *
             field_at psh list_struct (StructField list_link :: nil) (valinject (nested_field_type list_struct (StructField list_link :: nil)) z) y *
             lseg ls dsh psh r x y.

Lemma lseg_cons_right_neq (ls: listspec list_structid list_link list_token): forall dsh psh l x h y w z,
             sepalg.nonidentity psh ->
             list_token dsh y * list_cell ls dsh h y * field_at psh list_struct (StructField list_link :: nil) (valinject (nested_field_type list_struct (StructField list_link :: nil)) z) y *
             lseg ls dsh psh l x y * field_at psh list_struct (StructField list_link :: nil) (valinject (nested_field_type list_struct (StructField list_link :: nil)) w) z
   |--   lseg ls dsh psh (l++(y,h)::nil) x z * field_at psh list_struct (StructField list_link :: nil) (valinject (nested_field_type list_struct (StructField list_link :: nil)) w) z.
Proof.
(* Goal: forall (v' : @elemtype cs list_structid list_link list_token ls) (ash bsh psh : share) (p : val) (v : @elemtype cs list_structid list_link list_token ls) (_ : @sepalg.join share Share.Join_ba ash bsh psh) (_ : not (readable_share ash)) (_ : readable_share bsh), @eq mpred (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls ash v' p) (@list_cell cs list_structid list_link list_token ls bsh v p)) (@list_cell cs list_structid list_link list_token ls psh v p) *)
intros. rename H into SH.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh y) (@list_cell cs list_structid list_link list_token ls dsh h y)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) z) y)) (lseg ls dsh psh l x y)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) w) z)) (@sepcon mpred Nveric Sveric (lseg ls dsh psh (@app (prod val (@elemtype cs list_structid list_link list_token ls)) l (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) y h) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) x z) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) w) z)) *)
assert (SZ: 0 < sizeof (nested_field_type list_struct (DOT list_link))).
(* Goal: Z.lt Z0 (@sizeof (@cenv_cs cs) (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)))) *)
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh y) (@list_cell cs list_structid list_link list_token ls dsh h y)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) z) y)) (lseg ls dsh psh l x y)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) w) z)) (@sepcon mpred Nveric Sveric (lseg ls dsh psh (@app (prod val (@elemtype cs list_structid list_link list_token ls)) l (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) y h) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) x z) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) w) z)) *)
  rewrite list_link_type; simpl; destruct Archi.ptr64; computable.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh y) (@list_cell cs list_structid list_link list_token ls dsh h y)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) z) y)) (lseg ls dsh psh l x y)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) w) z)) (@sepcon mpred Nveric Sveric (lseg ls dsh psh (@app (prod val (@elemtype cs list_structid list_link list_token ls)) l (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) y h) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) x z) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) w) z)) *)
rewrite (field_at_isptr _ _ _ _ z).
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
normalize.
(* Goal: forall (v' : @elemtype cs list_structid list_link list_token ls) (ash bsh psh : share) (p : val) (v : @elemtype cs list_structid list_link list_token ls) (_ : @sepalg.join share Share.Join_ba ash bsh psh) (_ : not (readable_share ash)) (_ : readable_share bsh), @eq mpred (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls ash v' p) (@list_cell cs list_structid list_link list_token ls bsh v p)) (@list_cell cs list_structid list_link list_token ls psh v p) *)
revert x; induction l; simpl; intros.
*
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
normalize.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
  autorewrite with subst norm1 norm2; normalize.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh y) (@list_cell cs list_structid list_link list_token ls dsh h y)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) z) y)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) w) z)) (@exp mpred Nveric val (fun x : val => @andp mpred Nveric (@prop mpred Nveric (not (ptr_eq y z))) (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null x)) (list_token dsh y)) (@list_cell cs list_structid list_link list_token ls dsh h y)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) x) y)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@emp mpred Nveric Sveric))) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) w) z)))) *)
 apply exp_right with z.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh y) (@list_cell cs list_structid list_link list_token ls dsh h y)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) z) y)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) w) z)) (@andp mpred Nveric (@prop mpred Nveric (not (ptr_eq y z))) (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null z)) (list_token dsh y)) (@list_cell cs list_structid list_link list_token ls dsh h y)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) z) y)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq z z)) (@emp mpred Nveric Sveric))) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) w) z))) *)
 entailer!.
*
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh y) (@list_cell cs list_structid list_link list_token ls dsh h y)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) z) y)) (let (p, h) := a in @andp mpred Nveric (@prop mpred Nveric (and (@eq val p x) (not (ptr_eq x y)))) (@exp mpred Nveric val (fun y0 : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y0)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh h x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y0) x)) (lseg ls dsh psh l y0 y))))) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) w) z)) (@sepcon mpred Nveric Sveric (let (p, h0) := a in @andp mpred Nveric (@prop mpred Nveric (and (@eq val p x) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y0 : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y0)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh h0 x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y0) x)) (lseg ls dsh psh (@app (prod val (@elemtype cs list_structid list_link list_token ls)) l (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) y h) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) y0 z)))) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) w) z)) *)
destruct a as [v el].
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
normalize.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh y) (@list_cell cs list_structid list_link list_token ls dsh h y)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) z) y)) (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh x) (@list_cell cs list_structid list_link list_token ls dsh el x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) x0) x)) (lseg ls dsh psh l x0 y))) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) w) z)) (@exp mpred Nveric val (fun x0 : val => @andp mpred Nveric (@prop mpred Nveric (and (@eq val x x) (not (ptr_eq x z)))) (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null x0)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh el x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) x0) x)) (lseg ls dsh psh (@app (prod val (@elemtype cs list_structid list_link list_token ls)) l (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) y h) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) x0 z)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) w) z)))) *)
apply exp_right with x0.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
normalize.
rewrite <- ?sepcon_assoc.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
  autorewrite with subst norm1 norm2; normalize.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh y) (@list_cell cs list_structid list_link list_token ls dsh h y)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) z) y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh el x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) x0) x)) (lseg ls dsh psh l x0 y)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) w) z)) (@andp mpred Nveric (@prop mpred Nveric (and (not (ptr_eq x z)) (is_pointer_or_null x0))) (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh x) (@list_cell cs list_structid list_link list_token ls dsh el x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) x0) x)) (lseg ls dsh psh (@app (prod val (@elemtype cs list_structid list_link list_token ls)) l (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) y h) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) x0 z)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) w) z))) *)
specialize (IHl x0).
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh y) (@list_cell cs list_structid list_link list_token ls dsh h y)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) z) y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh el x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) x0) x)) (lseg ls dsh psh l x0 y)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) w) z)) (@andp mpred Nveric (@prop mpred Nveric (and (not (ptr_eq x z)) (is_pointer_or_null x0))) (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh x) (@list_cell cs list_structid list_link list_token ls dsh el x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) x0) x)) (lseg ls dsh psh (@app (prod val (@elemtype cs list_structid list_link list_token ls)) l (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) y h) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) x0 z)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) w) z))) *)
entailer.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh y) (@list_cell cs list_structid list_link list_token ls dsh h y)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) z) y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh el x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) x0) x)) (lseg ls dsh psh l x0 y)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) w) z)) (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh x) (@list_cell cs list_structid list_link list_token ls dsh el x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) x0) x)) (lseg ls dsh psh (@app (prod val (@elemtype cs list_structid list_link list_token ls)) l (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) y h) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) x0 z)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) w) z)) *)
pull_right (list_cell ls dsh el x).
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
apply sepcon_derives; auto.
pull_right (field_at psh list_struct (StructField list_link :: nil)
      (valinject
         (nested_field_type list_struct (StructField list_link :: nil)) x0)
      x).
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh y) (@list_cell cs list_structid list_link list_token ls dsh h y)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) z) y)) (list_token dsh x)) (lseg ls dsh psh l x0 y)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) w) z)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) x0) x)) (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh x) (lseg ls dsh psh (@app (prod val (@elemtype cs list_structid list_link list_token ls)) l (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) y h) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) x0 z)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) w) z)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) x0) x)) *)
pull_right (list_token dsh x).
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
apply sepcon_derives; auto.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
apply sepcon_derives; auto.
Qed.

Lemma lseg_cons_right_null (ls: listspec list_structid list_link list_token): forall dsh psh l x h y,
             list_token dsh y * list_cell ls dsh h y * field_at psh list_struct (StructField list_link :: nil) (valinject (nested_field_type list_struct (StructField list_link :: nil)) nullval) y *
             lseg ls dsh psh l x y
   |--   lseg ls dsh psh (l++(y,h)::nil) x nullval.
Proof.
(* Goal: forall (v' : @elemtype cs list_structid list_link list_token ls) (ash bsh psh : share) (p : val) (v : @elemtype cs list_structid list_link list_token ls) (_ : @sepalg.join share Share.Join_ba ash bsh psh) (_ : not (readable_share ash)) (_ : readable_share bsh), @eq mpred (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls ash v' p) (@list_cell cs list_structid list_link list_token ls bsh v p)) (@list_cell cs list_structid list_link list_token ls psh v p) *)
intros.
(* Goal: forall (v' : @elemtype cs list_structid list_link list_token ls) (ash bsh psh : share) (p : val) (v : @elemtype cs list_structid list_link list_token ls) (_ : @sepalg.join share Share.Join_ba ash bsh psh) (_ : not (readable_share ash)) (_ : readable_share bsh), @eq mpred (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls ash v' p) (@list_cell cs list_structid list_link list_token ls bsh v p)) (@list_cell cs list_structid list_link list_token ls psh v p) *)
revert x; induction l; simpl; intros.
*
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
normalize.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
  autorewrite with subst norm1 norm2; normalize.
apply exp_right with nullval.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh x) (@list_cell cs list_structid list_link list_token ls dsh e x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) x)) (lseg ls dsh psh l tail z)) (@andp mpred Nveric (@prop mpred Nveric (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) v e) l) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) x e) l)) (is_pointer_or_null tail))) (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh x) (@list_cell cs list_structid list_link list_token ls dsh e x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) x)) (lseg ls dsh psh l tail z))) *)
(* Goal: @derives mpred Nveric (@orp mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) x z)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@emp mpred Nveric Sveric)) *)
(* Goal: @derives mpred Nveric (@orp mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) p l) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) p l) x z)) (let (p, h) := p in @andp mpred Nveric (@prop mpred Nveric (and (@eq val p x) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh h x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) x)) (lseg ls dsh psh l tail z)))) *)
apply andp_right.
(* Goal: ptr_neq (Vptr b i) (if Archi.ptr64 then Vlong Int64.zero else Vint Int.zero) *)
apply not_prop_right; intro.
(* Goal: False *)
(* Goal: ptr_neq (Vptr b i) (if Archi.ptr64 then Vlong Int64.zero else Vint Int.zero) *)
apply ptr_eq_e in H. subst y.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh y) (@list_cell cs list_structid list_link list_token ls dsh h y)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) z) y)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) w) z)) (@andp mpred Nveric (@prop mpred Nveric (not (ptr_eq y z))) (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null z)) (list_token dsh y)) (@list_cell cs list_structid list_link list_token ls dsh h y)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) z) y)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq z z)) (@emp mpred Nveric Sveric))) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) w) z))) *)
entailer!.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tl')) (list_token dsh nullval)) (@list_cell cs list_structid list_link list_token ls dsh x nullval)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tl') nullval)) (@emp mpred Nveric Sveric)) (@FF mpred Nveric) *)
destruct H. contradiction H.
(* Goal: @eq mpred (@struct_pred (@nil (prod ident type)) A F v p) (@struct_pred (@nil (prod ident type)) A F v p') *)
(* Goal: @eq mpred (@struct_pred (@cons (prod ident type) a m) A F v p) (@struct_pred (@cons (prod ident type) a m) A F v p') *)
rewrite prop_true_andp by reflexivity.
rewrite prop_true_andp
  by (unfold nullval; destruct Archi.ptr64 eqn:Hp; simpl; auto).
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
normalize.
*
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh y) (@list_cell cs list_structid list_link list_token ls dsh h y)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) z) y)) (let (p, h) := a in @andp mpred Nveric (@prop mpred Nveric (and (@eq val p x) (not (ptr_eq x y)))) (@exp mpred Nveric val (fun y0 : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y0)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh h x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y0) x)) (lseg ls dsh psh l y0 y))))) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) w) z)) (@sepcon mpred Nveric Sveric (let (p, h0) := a in @andp mpred Nveric (@prop mpred Nveric (and (@eq val p x) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y0 : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y0)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh h0 x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y0) x)) (lseg ls dsh psh (@app (prod val (@elemtype cs list_structid list_link list_token ls)) l (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) y h) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) y0 z)))) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) w) z)) *)
destruct a as [v el].
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
normalize.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh y) (@list_cell cs list_structid list_link list_token ls dsh h y)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) z) y)) (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh x) (@list_cell cs list_structid list_link list_token ls dsh el x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) x0) x)) (lseg ls dsh psh l x0 y))) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) w) z)) (@exp mpred Nveric val (fun x0 : val => @andp mpred Nveric (@prop mpred Nveric (and (@eq val x x) (not (ptr_eq x z)))) (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null x0)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh el x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) x0) x)) (lseg ls dsh psh (@app (prod val (@elemtype cs list_structid list_link list_token ls)) l (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) y h) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) x0 z)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) w) z)))) *)
apply exp_right with x0.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
normalize.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
  autorewrite with subst norm1 norm2; normalize.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh y) (@list_cell cs list_structid list_link list_token ls dsh h y)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) z) y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh el x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) x0) x)) (lseg ls dsh psh l x0 y)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) w) z)) (@andp mpred Nveric (@prop mpred Nveric (and (not (ptr_eq x z)) (is_pointer_or_null x0))) (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh x) (@list_cell cs list_structid list_link list_token ls dsh el x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) x0) x)) (lseg ls dsh psh (@app (prod val (@elemtype cs list_structid list_link list_token ls)) l (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) y h) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) x0 z)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) w) z))) *)
specialize (IHl x0).
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh x) (@list_cell cs list_structid list_link list_token ls dsh e x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) x)) (lseg ls dsh psh l tail z)) (@andp mpred Nveric (@prop mpred Nveric (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) v e) l) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) x e) l)) (is_pointer_or_null tail))) (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh x) (@list_cell cs list_structid list_link list_token ls dsh e x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) x)) (lseg ls dsh psh l tail z))) *)
(* Goal: @derives mpred Nveric (@orp mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) x z)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@emp mpred Nveric Sveric)) *)
(* Goal: @derives mpred Nveric (@orp mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) p l) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) p l) x z)) (let (p, h) := p in @andp mpred Nveric (@prop mpred Nveric (and (@eq val p x) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh h x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) x)) (lseg ls dsh psh l tail z)))) *)
apply andp_right.
rewrite prop_and.
apply andp_right; [ | apply prop_right; auto].
(* Goal: ptr_neq (Vptr b i) (if Archi.ptr64 then Vlong Int64.zero else Vint Int.zero) *)
apply not_prop_right; intro.
apply ptr_eq_e in H0. subst x.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh y) (@list_cell cs list_structid list_link list_token ls dsh h y)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) z) y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh el x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) x0) x)) (lseg ls dsh psh l x0 y)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) w) z)) (@andp mpred Nveric (@prop mpred Nveric (and (not (ptr_eq x z)) (is_pointer_or_null x0))) (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh x) (@list_cell cs list_structid list_link list_token ls dsh el x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) x0) x)) (lseg ls dsh psh (@app (prod val (@elemtype cs list_structid list_link list_token ls)) l (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) y h) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) x0 z)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) w) z))) *)
entailer.
destruct H2; contradiction H2.
eapply derives_trans.
2: apply sepcon_derives; [ | eassumption]; apply derives_refl.
clear IHl.
cancel.
Qed.


Lemma lseg_cons_right_list (ls: listspec list_structid list_link list_token): forall dsh psh l l' x h y z,
    sepalg.nonidentity psh ->
             list_token dsh y * list_cell ls dsh h y
           * field_at psh list_struct (StructField list_link :: nil) (valinject (nested_field_type list_struct (StructField list_link :: nil)) z) y
           * lseg ls dsh psh l x y
           * lseg ls dsh psh l' z nullval
   |--   lseg ls dsh psh (l++(y,h)::nil) x z * lseg ls dsh psh l' z nullval.
Proof.
(* Goal: forall (v' : @elemtype cs list_structid list_link list_token ls) (ash bsh psh : share) (p : val) (v : @elemtype cs list_structid list_link list_token ls) (_ : @sepalg.join share Share.Join_ba ash bsh psh) (_ : not (readable_share ash)) (_ : readable_share bsh), @eq mpred (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls ash v' p) (@list_cell cs list_structid list_link list_token ls bsh v p)) (@list_cell cs list_structid list_link list_token ls psh v p) *)
intros.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh y) (@list_cell cs list_structid list_link list_token ls dsh h y)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) z) y)) (lseg ls dsh psh l x y)) (lseg ls dsh psh l' z nullval)) (@sepcon mpred Nveric Sveric (lseg ls dsh psh (@app (prod val (@elemtype cs list_structid list_link list_token ls)) l (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) y h) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) x z) (lseg ls dsh psh l' z nullval)) *)
destruct l'.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh y) (@list_cell cs list_structid list_link list_token ls dsh h y)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) z) y)) (lseg ls dsh psh l x y)) (lseg ls dsh psh (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) z nullval)) (@sepcon mpred Nveric Sveric (lseg ls dsh psh (@app (prod val (@elemtype cs list_structid list_link list_token ls)) l (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) y h) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) x z) (lseg ls dsh psh (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) z nullval)) *)
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh y) (@list_cell cs list_structid list_link list_token ls dsh h y)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) z) y)) (lseg ls dsh psh l x y)) (lseg ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) p l') z nullval)) (@sepcon mpred Nveric Sveric (lseg ls dsh psh (@app (prod val (@elemtype cs list_structid list_link list_token ls)) l (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) y h) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) x z) (lseg ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) p l') z nullval)) *)
rewrite lseg_nil_eq.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
normalize.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh y) (@list_cell cs list_structid list_link list_token ls dsh h y)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) nullval) y)) (lseg ls dsh psh l x y)) (lseg ls dsh psh (@app (prod val (@elemtype cs list_structid list_link list_token ls)) l (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) y h) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) x nullval) *)
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh y) (@list_cell cs list_structid list_link list_token ls dsh h y)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) z) y)) (lseg ls dsh psh l x y)) (lseg ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) p l') z nullval)) (@sepcon mpred Nveric Sveric (lseg ls dsh psh (@app (prod val (@elemtype cs list_structid list_link list_token ls)) l (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) y h) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) x z) (lseg ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) p l') z nullval)) *)
apply lseg_cons_right_null.
(* Goal: @eq mpred (lseg ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) x' h) r) x z) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x x') (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (lseg_cell ls dsh psh h x y) (lseg ls dsh psh r y z)))) *)
rewrite lseg_cons_eq.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh y) (@list_cell cs list_structid list_link list_token ls dsh h y)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) z) y)) (lseg ls dsh psh l x y)) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val z (@fst val (@elemtype cs list_structid list_link list_token ls) p)) (not (ptr_eq z nullval)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh z)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) p) z)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) z)) (lseg ls dsh psh l' y nullval))))) (@sepcon mpred Nveric Sveric (lseg ls dsh psh (@app (prod val (@elemtype cs list_structid list_link list_token ls)) l (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) y h) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) x z) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val z (@fst val (@elemtype cs list_structid list_link list_token ls) p)) (not (ptr_eq z nullval)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh z)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) p) z)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) z)) (lseg ls dsh psh l' y nullval))))) *)
Intros u. Exists u. subst z.
rewrite <- ?sepcon_assoc.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
rewrite !prop_true_andp by auto.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
normalize.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
apply sepcon_derives; auto.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh y) (@list_cell cs list_structid list_link list_token ls dsh h y)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) (@fst val (@elemtype cs list_structid list_link list_token ls) p)) y)) (lseg ls dsh psh l x y)) (list_token dsh (@fst val (@elemtype cs list_structid list_link list_token ls) p))) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) p) (@fst val (@elemtype cs list_structid list_link list_token ls) p))) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) u) (@fst val (@elemtype cs list_structid list_link list_token ls) p))) (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (lseg ls dsh psh (@app (prod val (@elemtype cs list_structid list_link list_token ls)) l (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) y h) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) x (@fst val (@elemtype cs list_structid list_link list_token ls) p)) (list_token dsh (@fst val (@elemtype cs list_structid list_link list_token ls) p))) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) p) (@fst val (@elemtype cs list_structid list_link list_token ls) p))) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) u) (@fst val (@elemtype cs list_structid list_link list_token ls) p))) *)
pull_right (list_cell ls dsh (snd p) (fst p)).
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh y) (@list_cell cs list_structid list_link list_token ls dsh h y)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) (@fst val (@elemtype cs list_structid list_link list_token ls) p)) y)) (lseg ls dsh psh l x y)) (list_token dsh (@fst val (@elemtype cs list_structid list_link list_token ls) p))) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) u) (@fst val (@elemtype cs list_structid list_link list_token ls) p))) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) p) (@fst val (@elemtype cs list_structid list_link list_token ls) p))) (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (lseg ls dsh psh (@app (prod val (@elemtype cs list_structid list_link list_token ls)) l (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) y h) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) x (@fst val (@elemtype cs list_structid list_link list_token ls) p)) (list_token dsh (@fst val (@elemtype cs list_structid list_link list_token ls) p))) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) u) (@fst val (@elemtype cs list_structid list_link list_token ls) p))) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) p) (@fst val (@elemtype cs list_structid list_link list_token ls) p))) *)
pull_right (list_token dsh (fst p)).
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
apply sepcon_derives; auto.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
apply sepcon_derives; auto.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
apply lseg_cons_right_neq; auto.
Qed.

Lemma lseg_unroll_right (ls: listspec list_structid list_link list_token): forall sh sh' l x z ,
    lseg ls sh sh' l x z = (!! (ptr_eq x z) && !! (l=nil) && emp) || lseg_cons_right ls sh sh' l x z.
Abort.  (* not likely true *)


Lemma lseg_local_facts:
  forall ls dsh psh contents p q,
     lseg ls dsh psh contents p q |--
     !! (is_pointer_or_null p /\ (p=q <-> contents=nil)).
Proof.
(* Goal: forall (v' : @elemtype cs list_structid list_link list_token ls) (ash bsh psh : share) (p : val) (v : @elemtype cs list_structid list_link list_token ls) (_ : @sepalg.join share Share.Join_ba ash bsh psh) (_ : not (readable_share ash)) (_ : readable_share bsh), @eq mpred (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls ash v' p) (@list_cell cs list_structid list_link list_token ls bsh v p)) (@list_cell cs list_structid list_link list_token ls psh v p) *)
intros.
(* Goal: @derives mpred Nveric (lseg ls dsh psh contents p q) (@prop mpred Nveric (and (is_pointer_or_null p) (iff (@eq val p q) (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) contents (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))))) *)
rewrite lseg_unfold.
(* Goal: @derives mpred Nveric match contents with | nil => @andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric) | cons (pair p1 h as p0) t => @andp mpred Nveric (@prop mpred Nveric (and (@eq val p1 p) (not (ptr_eq p q)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh p)) (@list_cell cs list_structid list_link list_token ls dsh h p)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) p)) (lseg ls dsh psh t tail q))) end (@prop mpred Nveric (and (is_pointer_or_null p) (iff (@eq val p q) (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) contents (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))))) *)
destruct contents.
(* Goal: ptr_neq (Vptr b i) (if Archi.ptr64 then Vlong Int64.zero else Vint Int.zero) *)
apply derives_extract_prop; intro.
(* Goal: @derives mpred Nveric (@emp mpred Nveric Sveric) (@prop mpred Nveric (and (is_pointer_or_null p) (iff (@eq val p q) (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))))) *)
(* Goal: @derives mpred Nveric (let (p0, h) := p0 in @andp mpred Nveric (@prop mpred Nveric (and (@eq val p0 p) (not (ptr_eq p q)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh p)) (@list_cell cs list_structid list_link list_token ls dsh h p)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) p)) (lseg ls dsh psh contents tail q)))) (@prop mpred Nveric (and (is_pointer_or_null p) (iff (@eq val p q) (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) p0 contents) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))))) *)
unfold ptr_eq in H.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh p) (@list_cell cs list_structid list_link list_token ls dsh e p)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) p)) (lseg ls dsh psh contents tail q)) (@prop mpred Nveric (iff (@eq val p q) (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) p e) contents) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) *)
apply prop_right.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
destruct p; try contradiction; simpl; auto.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
destruct q; try contradiction; auto.
(* Goal: and (if Archi.ptr64 then False else @eq Int.int i Int.zero) (iff (@eq val (Vint i) (Vint i0)) (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) *)
(* Goal: and (if Archi.ptr64 then @eq Int64.int i Int64.zero else False) (iff (@eq val (Vlong i) q) (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) *)
(* Goal: and True (iff (@eq val (Vptr b i) q) (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) *)
(* Goal: @derives mpred Nveric (let (p0, h) := p0 in @andp mpred Nveric (@prop mpred Nveric (and (@eq val p0 p) (not (ptr_eq p q)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh p)) (@list_cell cs list_structid list_link list_token ls dsh h p)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) p)) (lseg ls dsh psh contents tail q)))) (@prop mpred Nveric (and (is_pointer_or_null p) (iff (@eq val p q) (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) p0 contents) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))))) *)
unfold Int.cmpu in H.
(* Goal: and (if Archi.ptr64 then @eq Int64.int i Int64.zero else False) (iff (@eq val (Vlong i) (Vlong i0)) (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) *)
(* Goal: and True (iff (@eq val (Vptr b i) q) (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) *)
(* Goal: @derives mpred Nveric (let (p0, h) := p0 in @andp mpred Nveric (@prop mpred Nveric (and (@eq val p0 p) (not (ptr_eq p q)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh p)) (@list_cell cs list_structid list_link list_token ls dsh h p)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) p)) (lseg ls dsh psh contents tail q)))) (@prop mpred Nveric (and (is_pointer_or_null p) (iff (@eq val p q) (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) p0 contents) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))))) *)
destruct H as [? [? ?]].
(* Goal: and (if Archi.ptr64 then False else @eq Int.int i Int.zero) (iff (@eq val (Vint i) (Vint i0)) (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) *)
(* Goal: and (if Archi.ptr64 then @eq Int64.int i Int64.zero else False) (iff (@eq val (Vlong i) q) (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) *)
(* Goal: and True (iff (@eq val (Vptr b i) q) (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) *)
(* Goal: @derives mpred Nveric (let (p0, h) := p0 in @andp mpred Nveric (@prop mpred Nveric (and (@eq val p0 p) (not (ptr_eq p q)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh p)) (@list_cell cs list_structid list_link list_token ls dsh h p)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) p)) (lseg ls dsh psh contents tail q)))) (@prop mpred Nveric (and (is_pointer_or_null p) (iff (@eq val p q) (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) p0 contents) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))))) *)
apply int_eq_e in H0.
(* Goal: and True (iff (@eq val (Vptr b0 i) (Vptr b0 i0)) (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) *)
(* Goal: @derives mpred Nveric (let (p0, h) := p0 in @andp mpred Nveric (@prop mpred Nveric (and (@eq val p0 p) (not (ptr_eq p q)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh p)) (@list_cell cs list_structid list_link list_token ls dsh h p)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) p)) (lseg ls dsh psh contents tail q)))) (@prop mpred Nveric (and (is_pointer_or_null p) (iff (@eq val p q) (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) p0 contents) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))))) *)
apply int_eq_e in H1. subst. rewrite H.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
split; auto; split; auto.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
destruct q; try contradiction; auto.
(* Goal: and (if Archi.ptr64 then @eq Int64.int i Int64.zero else False) (iff (@eq val (Vlong i) (Vlong i0)) (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) *)
(* Goal: and True (iff (@eq val (Vptr b i) q) (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) *)
(* Goal: @derives mpred Nveric (let (p0, h) := p0 in @andp mpred Nveric (@prop mpred Nveric (and (@eq val p0 p) (not (ptr_eq p q)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh p)) (@list_cell cs list_structid list_link list_token ls dsh h p)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) p)) (lseg ls dsh psh contents tail q)))) (@prop mpred Nveric (and (is_pointer_or_null p) (iff (@eq val p q) (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) p0 contents) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))))) *)
unfold Int64.cmpu in H.
(* Goal: and (if Archi.ptr64 then @eq Int64.int i Int64.zero else False) (iff (@eq val (Vlong i) (Vlong i0)) (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) *)
(* Goal: and True (iff (@eq val (Vptr b i) q) (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) *)
(* Goal: @derives mpred Nveric (let (p0, h) := p0 in @andp mpred Nveric (@prop mpred Nveric (and (@eq val p0 p) (not (ptr_eq p q)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh p)) (@list_cell cs list_structid list_link list_token ls dsh h p)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) p)) (lseg ls dsh psh contents tail q)))) (@prop mpred Nveric (and (is_pointer_or_null p) (iff (@eq val p q) (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) p0 contents) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))))) *)
destruct H as [? [? ?]].
(* Goal: and (if Archi.ptr64 then @eq Int64.int i Int64.zero else False) (iff (@eq val (Vlong i) (Vlong i0)) (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) *)
(* Goal: and True (iff (@eq val (Vptr b i) q) (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) *)
(* Goal: @derives mpred Nveric (let (p0, h) := p0 in @andp mpred Nveric (@prop mpred Nveric (and (@eq val p0 p) (not (ptr_eq p q)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh p)) (@list_cell cs list_structid list_link list_token ls dsh h p)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) p)) (lseg ls dsh psh contents tail q)))) (@prop mpred Nveric (and (is_pointer_or_null p) (iff (@eq val p q) (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) p0 contents) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))))) *)
apply int64_eq_e in H0.
(* Goal: and True (iff (@eq val (Vptr b0 i) (Vptr b0 i0)) (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) *)
(* Goal: @derives mpred Nveric (let (p0, h) := p0 in @andp mpred Nveric (@prop mpred Nveric (and (@eq val p0 p) (not (ptr_eq p q)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh p)) (@list_cell cs list_structid list_link list_token ls dsh h p)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) p)) (lseg ls dsh psh contents tail q)))) (@prop mpred Nveric (and (is_pointer_or_null p) (iff (@eq val p q) (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) p0 contents) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))))) *)
apply int64_eq_e in H1. subst. rewrite H.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
split3; auto.
(* Goal: and True (iff (@eq val (Vptr b i) q) (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) *)
(* Goal: @derives mpred Nveric (let (p0, h) := p0 in @andp mpred Nveric (@prop mpred Nveric (and (@eq val p0 p) (not (ptr_eq p q)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh p)) (@list_cell cs list_structid list_link list_token ls dsh h p)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) p)) (lseg ls dsh psh contents tail q)))) (@prop mpred Nveric (and (is_pointer_or_null p) (iff (@eq val p q) (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) p0 contents) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))))) *)
destruct q; try contradiction.
(* Goal: and True (iff (@eq val (Vptr b0 i) (Vptr b0 i0)) (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) *)
(* Goal: @derives mpred Nveric (let (p0, h) := p0 in @andp mpred Nveric (@prop mpred Nveric (and (@eq val p0 p) (not (ptr_eq p q)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh p)) (@list_cell cs list_structid list_link list_token ls dsh h p)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) p)) (lseg ls dsh psh contents tail q)))) (@prop mpred Nveric (and (is_pointer_or_null p) (iff (@eq val p q) (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) p0 contents) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))))) *)
destruct H; subst.
(* Goal: and True (iff (@eq val (Vptr b0 i) (Vptr b0 i0)) (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) *)
(* Goal: @derives mpred Nveric (let (p0, h) := p0 in @andp mpred Nveric (@prop mpred Nveric (and (@eq val p0 p) (not (ptr_eq p q)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh p)) (@list_cell cs list_structid list_link list_token ls dsh h p)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) p)) (lseg ls dsh psh contents tail q)))) (@prop mpred Nveric (and (is_pointer_or_null p) (iff (@eq val p q) (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) p0 contents) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))))) *)
unfold Ptrofs.cmpu in H0.
(* Goal: and True (iff (@eq val (Vptr b0 i) (Vptr b0 i0)) (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) *)
(* Goal: @derives mpred Nveric (let (p0, h) := p0 in @andp mpred Nveric (@prop mpred Nveric (and (@eq val p0 p) (not (ptr_eq p q)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh p)) (@list_cell cs list_structid list_link list_token ls dsh h p)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) p)) (lseg ls dsh psh contents tail q)))) (@prop mpred Nveric (and (is_pointer_or_null p) (iff (@eq val p q) (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) p0 contents) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))))) *)
apply ptrofs_eq_e in H0.
(* Goal: and True (iff (@eq val (Vptr b0 i) (Vptr b0 i0)) (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) *)
(* Goal: @derives mpred Nveric (let (p0, h) := p0 in @andp mpred Nveric (@prop mpred Nveric (and (@eq val p0 p) (not (ptr_eq p q)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh p)) (@list_cell cs list_structid list_link list_token ls dsh h p)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) p)) (lseg ls dsh psh contents tail q)))) (@prop mpred Nveric (and (is_pointer_or_null p) (iff (@eq val p q) (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) p0 contents) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))))) *)
subst. intuition.
(* Goal: @derives mpred Nveric (let (p0, h) := p0 in @andp mpred Nveric (@prop mpred Nveric (and (@eq val p0 p) (not (ptr_eq p q)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh p)) (@list_cell cs list_structid list_link list_token ls dsh h p)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) p)) (lseg ls dsh psh contents tail q)))) (@prop mpred Nveric (and (is_pointer_or_null p) (iff (@eq val p q) (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) p0 contents) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))))) *)
destruct p0.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
normalize.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh p) (@list_cell cs list_structid list_link list_token ls dsh e p)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) p)) (lseg ls dsh psh contents tail q)) (@prop mpred Nveric (and (is_pointer_or_null p) (iff (@eq val p q) (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) p e) contents) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))))) *)
rewrite field_at_isptr.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
normalize.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
  autorewrite with subst norm1 norm2; normalize.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh p) (@list_cell cs list_structid list_link list_token ls dsh e p)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) p)) (lseg ls dsh psh contents tail q)) (@prop mpred Nveric (iff (@eq val p q) (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) p e) contents) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) *)
apply prop_right.
(* Goal: iff (@eq val p q) (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) p e) contents) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))) *)
split. intro; subst q.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
contradiction H. normalize.
(* Goal: forall (v' : @elemtype cs list_structid list_link list_token ls) (ash bsh psh : share) (p : val) (v : @elemtype cs list_structid list_link list_token ls) (_ : @sepalg.join share Share.Join_ba ash bsh psh) (_ : not (readable_share ash)) (_ : readable_share bsh), @eq mpred (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls ash v' p) (@list_cell cs list_structid list_link list_token ls bsh v p)) (@list_cell cs list_structid list_link list_token ls psh v p) *)
intros. discriminate.
Qed.

Definition lseg_cell  (ls: listspec list_structid list_link list_token)
    (dsh psh : share)
    (v: elemtype ls) (x y: val) :=
   !!is_pointer_or_null y && list_token dsh x * list_cell ls dsh v x * field_at psh list_struct (StructField list_link :: nil) (valinject (nested_field_type list_struct (StructField list_link :: nil)) y) x.

Lemma lseg_cons_eq2: forall
  (ls : listspec list_structid list_link list_token) (dsh psh : share) (h : elemtype ls)
   (r : list (val * elemtype ls))
  (x x' z : val), lseg ls dsh psh ((x',h) :: r) x z =
  !!(x=x' /\ ~ ptr_eq x z) && (EX  y : val, lseg_cell ls dsh psh h x y * lseg ls dsh psh r y z).
Proof.
(* Goal: forall (v' : @elemtype cs list_structid list_link list_token ls) (ash bsh psh : share) (p : val) (v : @elemtype cs list_structid list_link list_token ls) (_ : @sepalg.join share Share.Join_ba ash bsh psh) (_ : not (readable_share ash)) (_ : readable_share bsh), @eq mpred (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls ash v' p) (@list_cell cs list_structid list_link list_token ls bsh v p)) (@list_cell cs list_structid list_link list_token ls psh v p) *)
  intros.
  rewrite -> lseg_cons_eq.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (lseg_cell ls dsh psh x nullval tl') (@emp mpred Nveric Sveric)) (@FF mpred Nveric) *)
  unfold lseg_cell.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
 normalize.
Qed.

Lemma list_append: forall {dsh psh: share}
  {ls : listspec list_structid list_link list_token} (hd mid tl:val) ct1 ct2 P,
  (forall x tl', lseg_cell ls dsh psh x tl tl' * P tl |-- FF) ->
  (lseg ls dsh psh ct1 hd mid) * lseg ls dsh psh ct2 mid tl * P tl|--
  (lseg ls dsh psh (ct1 ++ ct2) hd tl) * P tl.
Proof.
(* Goal: forall (v' : @elemtype cs list_structid list_link list_token ls) (ash bsh psh : share) (p : val) (v : @elemtype cs list_structid list_link list_token ls) (_ : @sepalg.join share Share.Join_ba ash bsh psh) (_ : not (readable_share ash)) (_ : readable_share bsh), @eq mpred (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls ash v' p) (@list_cell cs list_structid list_link list_token ls bsh v p)) (@list_cell cs list_structid list_link list_token ls psh v p) *)
  intros.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
  revert hd; induction ct1; simpl; intros; auto.
  *
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
  normalize.
  *
  destruct a  as [v a].
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
  normalize.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
  autorewrite with subst norm1 norm2; normalize.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh p) (@list_cell cs list_structid list_link list_token ls dsh h p)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) p)) (lseg ls dsh psh r y z)) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) p h) r) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) p h) r)) (is_pointer_or_null y))) (list_token dsh p)) (@list_cell cs list_structid list_link list_token ls dsh h p)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) p)) (lseg ls dsh psh r y z))) *)
  apply exp_right with y.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh x) (@list_cell cs list_structid list_link list_token ls dsh e x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) x)) (lseg ls dsh psh l tail z)) (@andp mpred Nveric (@prop mpred Nveric (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) v e) l) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) x e) l)) (is_pointer_or_null tail))) (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh x) (@list_cell cs list_structid list_link list_token ls dsh e x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) x)) (lseg ls dsh psh l tail z))) *)
(* Goal: @derives mpred Nveric (@orp mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) x z)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@emp mpred Nveric Sveric)) *)
(* Goal: @derives mpred Nveric (@orp mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) p l) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) p l) x z)) (let (p, h) := p in @andp mpred Nveric (@prop mpred Nveric (and (@eq val p x) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh h x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) x)) (lseg ls dsh psh l tail z)))) *)
  apply andp_right.
(* Goal: ptr_neq (Vptr b i) (if Archi.ptr64 then Vlong Int64.zero else Vint Int.zero) *)
  apply not_prop_right; intro. apply ptr_eq_e in H1; subst hd.
  clear IHct1.
  unfold lseg_cell in H.
  specialize (H a y).
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
  rewrite prop_true_andp in H by auto.
  apply derives_trans with
        (lseg ls dsh psh ct1 y mid * lseg ls dsh psh ct2 mid tl * FF).
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
 cancel. auto.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
  rewrite sepcon_FF; auto.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
  normalize.
  specialize (IHct1 y). clear H.
(* Goal: @derives mpred Nveric P (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh v1) (@list_cell cs list_structid list_link list_token ls dsh h v1)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) p) v1)) (lseg ls dsh psh tail p v2)) *)
   do 2 rewrite sepcon_assoc.
  eapply derives_trans.
 apply sepcon_derives.
  apply derives_refl.
  rewrite <- !sepcon_assoc; eassumption.
  cancel.
Qed.

Lemma list_append_null:
  forall
   (ls: listspec list_structid list_link list_token)
   (dsh psh: share)
   (hd mid: val) ct1 ct2,
   lseg ls dsh psh ct1 hd mid * lseg ls dsh psh ct2 mid nullval |--
   lseg ls dsh psh (ct1++ct2) hd nullval.
Proof.
(* Goal: forall (v' : @elemtype cs list_structid list_link list_token ls) (ash bsh psh : share) (p : val) (v : @elemtype cs list_structid list_link list_token ls) (_ : @sepalg.join share Share.Join_ba ash bsh psh) (_ : not (readable_share ash)) (_ : readable_share bsh), @eq mpred (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls ash v' p) (@list_cell cs list_structid list_link list_token ls bsh v p)) (@list_cell cs list_structid list_link list_token ls psh v p) *)
intros.
 rewrite <- sepcon_emp.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (lseg ls dsh psh ct1 hd mid) (lseg ls dsh psh ct2 mid nullval)) (@sepcon mpred Nveric Sveric (lseg ls dsh psh (@app (prod val (@elemtype cs list_structid list_link list_token ls)) ct1 ct2) hd nullval) (@emp mpred Nveric Sveric)) *)
 eapply derives_trans; [ | apply (list_append hd mid nullval ct1 ct2 (fun _ => emp))].
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
 normalize.
(* Goal: forall (v' : @elemtype cs list_structid list_link list_token ls) (ash bsh psh : share) (p : val) (v : @elemtype cs list_structid list_link list_token ls) (_ : @sepalg.join share Share.Join_ba ash bsh psh) (_ : not (readable_share ash)) (_ : readable_share bsh), @eq mpred (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls ash v' p) (@list_cell cs list_structid list_link list_token ls bsh v p)) (@list_cell cs list_structid list_link list_token ls psh v p) *)
 intros.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tl')) (list_token dsh nullval)) (@list_cell cs list_structid list_link list_token ls dsh x nullval)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tl') nullval)) (@emp mpred Nveric Sveric)) (@FF mpred Nveric) *)
  unfold lseg_cell. simpl. saturate_local. destruct H. contradiction H.
Qed.

Lemma sizeof_list_struct_pos (LS: listspec list_structid list_link list_token) :
   sizeof list_struct > 0.
Admitted.

End LIST2.

Hint Rewrite @lseg_nil_eq : norm.

Hint Rewrite @lseg_eq using reflexivity: norm.

(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tl')) (list_token dsh nullval)) (@list_cell cs list_structid list_link list_token ls dsh x nullval)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tl') nullval)) (@emp mpred Nveric Sveric)) (@FF mpred Nveric) *)
Hint Resolve @lseg_local_facts : saturate_local.
End LsegGeneral.

Module LsegSpecial.

Section LIST.
Context {cs: compspecs}.
Context  {list_structid: ident} {list_link: ident} {list_token: share -> val -> mpred}.

Definition lseg (ls: listspec list_structid list_link list_token) (sh: share)
   (contents: list (elemtype ls)) (x y: val) : mpred :=
    EX al:list (val*elemtype ls),
          !! (contents = map snd al) &&
             LsegGeneral.lseg ls sh sh al x y.

Lemma lseg_unfold (ls: listspec list_structid list_link list_token): forall sh contents v1 v2,
    lseg ls sh contents v1 v2 =
     match contents with
     | h::t => !! (~ ptr_eq v1 v2) && EX tail: val,
                      !! is_pointer_or_null tail &&
                      list_token sh v1 * list_cell ls sh h v1
                      * field_at sh list_struct (StructField list_link :: nil)
                          (valinject (nested_field_type list_struct (StructField list_link :: nil)) tail) v1
                      *  lseg ls sh t tail v2
     | nil => !! (ptr_eq v1 v2) && emp
     end.
Proof.
(* Goal: forall (v' : @elemtype cs list_structid list_link list_token ls) (ash bsh psh : share) (p : val) (v : @elemtype cs list_structid list_link list_token ls) (_ : @sepalg.join share Share.Join_ba ash bsh psh) (_ : not (readable_share ash)) (_ : readable_share bsh), @eq mpred (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls ash v' p) (@list_cell cs list_structid list_link list_token ls bsh v p)) (@list_cell cs list_structid list_link list_token ls psh v p) *)
 intros.
 unfold lseg.
(* Goal: forall (v' : @elemtype cs list_structid list_link list_token ls) (ash bsh psh : share) (p : val) (v : @elemtype cs list_structid list_link list_token ls) (_ : @sepalg.join share Share.Join_ba ash bsh psh) (_ : not (readable_share ash)) (_ : readable_share bsh), @eq mpred (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls ash v' p) (@list_cell cs list_structid list_link list_token ls bsh v p)) (@list_cell cs list_structid list_link list_token ls psh v p) *)
 revert v1; induction contents; intros.
(* Goal: @eq mpred (@orp mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) x z)) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) *)
 apply pred_ext.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
 normalize. destruct al; inv H.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
 rewrite LsegGeneral.lseg_nil_eq; auto.
 apply exp_right with nil.
(* Goal: ptr_neq (Vptr b i) (if Archi.ptr64 then Vlong Int64.zero else Vint Int.zero) *)
 apply derives_extract_prop; intro.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
 normalize.
(* Goal: @eq mpred (@orp mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) x z)) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) *)
 apply pred_ext.
 apply exp_left; intros [ | [v1' a'] al].
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
 normalize. inv H.
(* Goal: ptr_neq (Vptr b i) (if Archi.ptr64 then Vlong Int64.zero else Vint Int.zero) *)
 apply derives_extract_prop; intro.
 symmetry in H; inv H.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
 rewrite LsegGeneral.lseg_cons_eq; auto.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) s (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) v h) r)) (is_pointer_or_null y))) (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh v) (@list_cell cs list_structid list_link list_token ls dsh h v)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) v)) (lseg ls dsh psh r y v2)) (fold_right_sepcon R))) (@exp mpred Nveric (prod (prod (prod (@elemtype cs list_structid list_link list_token ls) (list (prod val (@elemtype cs list_structid list_link list_token ls)))) val) val) (fun x : prod (prod (prod (@elemtype cs list_structid list_link list_token ls) (list (prod val (@elemtype cs list_structid list_link list_token ls)))) val) val => (let (p0, p) := x in let (p1, y) := p0 in let (h, r) := p1 in fun x0 : environ => @andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) s (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) p h) r)) (is_pointer_or_null y))) (@prop mpred Nveric (@eq val p v))) (@andp mpred Nveric (@prop mpred Nveric (@fold_right Prop Prop and True P)) (@andp mpred Nveric (@prop mpred Nveric (@fold_right (forall _ : environ, Prop) (forall _ : environ, Prop) (fun (x1 x2 : forall _ : environ, Prop) (x3 : environ) => and (x1 x3) (x2 x3)) (fun _ : environ => True) (@map localdef (forall _ : environ, Prop) locald_denote Q) x0)) (@sepcon mpred Nveric Sveric (list_token dsh v) (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls dsh h v) (@sepcon mpred Nveric Sveric (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) v) (@sepcon mpred Nveric Sveric (lseg ls dsh psh r y v2) (fold_right_sepcon R)))))))) rho)) *)
 apply derives_extract_prop; intros [? ?].
 simpl in H;  subst v1'.
(* Goal: @derives mpred Nveric (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) v e) l) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) x h) r)) (is_pointer_or_null y))) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh h x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z))) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val v x) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh e x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) x)) (lseg ls dsh psh l tail z)))) *)
 apply exp_left; intro y.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
 normalize. apply exp_right with y. normalize.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
 repeat apply sepcon_derives; auto.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
 apply exp_right with al; normalize.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
 normalize.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
 apply exp_right with ((v1,a)::al); normalize.
(* Goal: @derives mpred Nveric (valid_pointer Vundef) (valid_pointer p) *)
 simpl.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
 normalize. apply exp_right with tail. normalize.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
  autorewrite with subst norm1 norm2; normalize.
Qed.

Lemma lseg_eq (ls: listspec list_structid list_link list_token):
  forall sh l v ,
  is_pointer_or_null v ->
    lseg ls sh l v v = !!(l=nil) && emp.
Proof.
(* Goal: forall (v' : @elemtype cs list_structid list_link list_token ls) (ash bsh psh : share) (p : val) (v : @elemtype cs list_structid list_link list_token ls) (_ : @sepalg.join share Share.Join_ba ash bsh psh) (_ : not (readable_share ash)) (_ : readable_share bsh), @eq mpred (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls ash v' p) (@list_cell cs list_structid list_link list_token ls bsh v p)) (@list_cell cs list_structid list_link list_token ls psh v p) *)
intros.
unfold lseg.
(* Goal: @eq mpred (@orp mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) x z)) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) *)
apply pred_ext.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
normalize.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
rewrite LsegGeneral.lseg_eq by auto. normalize.
apply exp_right with nil.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
normalize.
Qed.

Definition lseg_cons (ls: listspec list_structid list_link list_token) sh (l: list (elemtype ls)) (x z: val) : mpred :=
        !! (~ ptr_eq x z) &&
       EX h:(elemtype ls), EX r:list (elemtype ls), EX y:val,
             !!(l=h::r  /\ is_pointer_or_null y) &&
             list_token sh x * list_cell ls sh h x *
             field_at sh list_struct (StructField list_link :: nil) (valinject (nested_field_type list_struct (StructField list_link :: nil)) y) x *
              lseg ls sh r y z.

Lemma lseg_unroll (ls: listspec list_structid list_link list_token): forall sh l x z ,
    lseg ls sh l x z =
      (!! (ptr_eq x z) && !! (l=nil) && emp) || lseg_cons ls sh l x z.
Proof.
(* Goal: forall (v' : @elemtype cs list_structid list_link list_token ls) (ash bsh psh : share) (p : val) (v : @elemtype cs list_structid list_link list_token ls) (_ : @sepalg.join share Share.Join_ba ash bsh psh) (_ : not (readable_share ash)) (_ : readable_share bsh), @eq mpred (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls ash v' p) (@list_cell cs list_structid list_link list_token ls bsh v p)) (@list_cell cs list_structid list_link list_token ls psh v p) *)
intros.
unfold lseg, lseg_cons.
(* Goal: @eq mpred (@orp mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) x z)) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) *)
apply pred_ext.
*
(* Goal: forall (v' : @elemtype cs list_structid list_link list_token ls) (ash bsh psh : share) (p : val) (v : @elemtype cs list_structid list_link list_token ls) (_ : @sepalg.join share Share.Join_ba ash bsh psh) (_ : not (readable_share ash)) (_ : readable_share bsh), @eq mpred (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls ash v' p) (@list_cell cs list_structid list_link list_token ls bsh v p)) (@list_cell cs list_structid list_link list_token ls psh v p) *)
apply exp_left; intros.
(* Goal: ptr_neq (Vptr b i) (if Archi.ptr64 then Vlong Int64.zero else Vint Int.zero) *)
apply derives_extract_prop; intro.
rewrite LsegGeneral.lseg_unroll.
apply orp_left; [apply orp_right1 | apply orp_right2].
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_neq v v2)) (@andp mpred Nveric (@prop mpred Nveric (@fold_right Prop Prop and True P)) (@andp mpred Nveric (@prop mpred Nveric (and (locald_denote Q1 rho) (@fold_right (forall _ : environ, Prop) (forall _ : environ, Prop) (fun (x x0 : forall _ : environ, Prop) (x1 : environ) => and (x x1) (x0 x1)) (fun _ : environ => True) (@map localdef (forall _ : environ, Prop) locald_denote Q) rho))) (@sepcon mpred Nveric Sveric (lseg ls dsh psh s v v2) (fold_right_sepcon R))))) (@andp mpred Nveric (@prop mpred Nveric (@fold_right Prop Prop and True P)) (@andp mpred Nveric (@prop mpred Nveric (and (locald_denote Q1 rho) (@fold_right (forall _ : environ, Prop) (forall _ : environ, Prop) (fun (x x0 : forall _ : environ, Prop) (x1 : environ) => and (x x1) (x0 x1)) (fun _ : environ => True) (@map localdef (forall _ : environ, Prop) locald_denote Q) rho))) (@sepcon mpred Nveric Sveric (lseg_cons ls dsh psh s v v2) (fold_right_sepcon R)))) *)
(* Goal: @derives (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (PROPx P (LOCALx (@cons localdef Q1 Q) (SEPx (@cons mpred (lseg_cons ls dsh psh s v v2) R)))) (@exp (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (prod (prod (prod (@elemtype cs list_structid list_link list_token ls) (list (prod val (@elemtype cs list_structid list_link list_token ls)))) val) val) (fun hryp : prod (prod (prod (@elemtype cs list_structid list_link list_token ls) (list (prod val (@elemtype cs list_structid list_link list_token ls)))) val) val => let (p0, p) := hryp in let (p1, y) := p0 in let (h, r) := p1 in @andp (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (@andp (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (@prop (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) s (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) p h) r)) (is_pointer_or_null y))) (@prop (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (@eq val p v))) (PROPx P (LOCALx Q (SEPx (@cons mpred (list_token dsh v) (@cons mpred (@list_cell cs list_structid list_link list_token ls dsh h v) (@cons mpred (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) v) (@cons mpred (lseg ls dsh psh r y v2) R))))))))) *)
rewrite andp_assoc; repeat (apply derives_extract_prop; intro).
(* Goal: and True (iff (@eq val (Vptr b0 i) (Vptr b0 i0)) (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) *)
(* Goal: @derives mpred Nveric (let (p0, h) := p0 in @andp mpred Nveric (@prop mpred Nveric (and (@eq val p0 p) (not (ptr_eq p q)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh p)) (@list_cell cs list_structid list_link list_token ls dsh h p)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) p)) (lseg ls dsh psh contents tail q)))) (@prop mpred Nveric (and (is_pointer_or_null p) (iff (@eq val p q) (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) p0 contents) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))))) *)
subst. simpl.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
normalize.
unfold LsegGeneral.lseg_cons.
(* Goal: ptr_neq (Vptr b i) (if Archi.ptr64 then Vlong Int64.zero else Vint Int.zero) *)
apply derives_extract_prop; intro.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
rewrite prop_true_andp by auto.
apply exp_derives; intro h.
apply exp_left; intro r; apply exp_right with (map snd r).
apply exp_derives; intro y.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
normalize.
subst l.
unfold lseg.
cancel.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
apply exp_right with r; normalize.
*
(* Goal: @derives mpred Nveric (@orp mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) x z)) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) *)
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) (@orp mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) x z)) *)
apply orp_left.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_neq v v2)) (@andp mpred Nveric (@prop mpred Nveric (@fold_right Prop Prop and True P)) (@andp mpred Nveric (@prop mpred Nveric (and (locald_denote Q1 rho) (@fold_right (forall _ : environ, Prop) (forall _ : environ, Prop) (fun (x x0 : forall _ : environ, Prop) (x1 : environ) => and (x x1) (x0 x1)) (fun _ : environ => True) (@map localdef (forall _ : environ, Prop) locald_denote Q) rho))) (@sepcon mpred Nveric Sveric (lseg ls dsh psh s v v2) (fold_right_sepcon R))))) (@andp mpred Nveric (@prop mpred Nveric (@fold_right Prop Prop and True P)) (@andp mpred Nveric (@prop mpred Nveric (and (locald_denote Q1 rho) (@fold_right (forall _ : environ, Prop) (forall _ : environ, Prop) (fun (x x0 : forall _ : environ, Prop) (x1 : environ) => and (x x1) (x0 x1)) (fun _ : environ => True) (@map localdef (forall _ : environ, Prop) locald_denote Q) rho))) (@sepcon mpred Nveric Sveric (lseg_cons ls dsh psh s v v2) (fold_right_sepcon R)))) *)
(* Goal: @derives (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (PROPx P (LOCALx (@cons localdef Q1 Q) (SEPx (@cons mpred (lseg_cons ls dsh psh s v v2) R)))) (@exp (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (prod (prod (prod (@elemtype cs list_structid list_link list_token ls) (list (prod val (@elemtype cs list_structid list_link list_token ls)))) val) val) (fun hryp : prod (prod (prod (@elemtype cs list_structid list_link list_token ls) (list (prod val (@elemtype cs list_structid list_link list_token ls)))) val) val => let (p0, p) := hryp in let (p1, y) := p0 in let (h, r) := p1 in @andp (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (@andp (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (@prop (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) s (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) p h) r)) (is_pointer_or_null y))) (@prop (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (@eq val p v))) (PROPx P (LOCALx Q (SEPx (@cons mpred (list_token dsh v) (@cons mpred (@list_cell cs list_structid list_link list_token ls dsh h v) (@cons mpred (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) v) (@cons mpred (lseg ls dsh psh r y v2) R))))))))) *)
rewrite andp_assoc; repeat (apply derives_extract_prop; intro).
(* Goal: and True (iff (@eq val (Vptr b0 i) (Vptr b0 i0)) (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) *)
(* Goal: @derives mpred Nveric (let (p0, h) := p0 in @andp mpred Nveric (@prop mpred Nveric (and (@eq val p0 p) (not (ptr_eq p q)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh p)) (@list_cell cs list_structid list_link list_token ls dsh h p)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) p)) (lseg ls dsh psh contents tail q)))) (@prop mpred Nveric (and (is_pointer_or_null p) (iff (@eq val p q) (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) p0 contents) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))))) *)
subst.
apply exp_right with nil.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
simpl. normalize.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
  autorewrite with subst norm1 norm2; normalize.
(* Goal: ptr_neq (Vptr b i) (if Archi.ptr64 then Vlong Int64.zero else Vint Int.zero) *)
apply derives_extract_prop; intro.
(* Goal: @derives mpred Nveric (@exp mpred Nveric (@elemtype cs list_structid list_link list_token ls) (fun h : @elemtype cs list_structid list_link list_token ls => @exp mpred Nveric (list (prod val (@elemtype cs list_structid list_link list_token ls))) (fun r : list (prod val (@elemtype cs list_structid list_link list_token ls)) => @exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) v e) l) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) x h) r)) (is_pointer_or_null y))) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh h x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z))))) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val v x) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh e x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) x)) (lseg ls dsh psh l tail z)))) *)
apply exp_left; intro h.
(* Goal: @derives mpred Nveric (@exp mpred Nveric (list (prod val (@elemtype cs list_structid list_link list_token ls))) (fun r : list (prod val (@elemtype cs list_structid list_link list_token ls)) => @exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) v e) l) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) x h) r)) (is_pointer_or_null y))) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh h x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val v x) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh e x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) x)) (lseg ls dsh psh l tail z)))) *)
apply exp_left; intro r.
(* Goal: @derives mpred Nveric (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) v e) l) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) x h) r)) (is_pointer_or_null y))) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh h x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z))) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val v x) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh e x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) x)) (lseg ls dsh psh l tail z)))) *)
apply exp_left; intro y.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
normalize.
unfold lseg.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
normalize.
apply exp_right with ((x,h)::al).
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
normalize.
(* Goal: @derives mpred Nveric (valid_pointer Vundef) (valid_pointer p) *)
simpl.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
normalize.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh p) (@list_cell cs list_structid list_link list_token ls dsh h p)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) p)) (lseg ls dsh psh r y z)) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) p h) r) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) p h) r)) (is_pointer_or_null y))) (list_token dsh p)) (@list_cell cs list_structid list_link list_token ls dsh h p)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) p)) (lseg ls dsh psh r y z))) *)
apply exp_right with y.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
normalize.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
  autorewrite with subst norm1 norm2; normalize.
Qed.

Lemma lseg_unroll_nonempty1 (ls: listspec list_structid list_link list_token):
   forall p P sh h (tail: list (elemtype ls)) v1 v2,
    ~ ptr_eq v1 v2 ->
    is_pointer_or_null p ->
    P |-- list_token sh v1 * list_cell ls sh h v1 *
             (field_at sh list_struct (StructField list_link :: nil)
                   (valinject (nested_field_type list_struct (StructField list_link :: nil)) p) v1 *
               lseg ls sh tail p v2) ->
    P |-- lseg ls sh (h::tail) v1 v2.
(* Goal: forall (v' : @elemtype cs list_structid list_link list_token ls) (ash bsh psh : share) (p : val) (v : @elemtype cs list_structid list_link list_token ls) (_ : @sepalg.join share Share.Join_ba ash bsh psh) (_ : not (readable_share ash)) (_ : readable_share bsh), @eq mpred (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls ash v' p) (@list_cell cs list_structid list_link list_token ls bsh v p)) (@list_cell cs list_structid list_link list_token ls psh v p) *)
Proof. intros. rewrite lseg_unroll. apply orp_right2. unfold lseg_cons.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
  rewrite prop_true_andp by auto.
(* Goal: @derives mpred Nveric P (@exp mpred Nveric (list (prod val (@elemtype cs list_structid list_link list_token ls))) (fun r : list (prod val (@elemtype cs list_structid list_link list_token ls)) => @exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) v1 h) tail) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) v1 h) r)) (is_pointer_or_null y))) (list_token dsh v1)) (@list_cell cs list_structid list_link list_token ls dsh h v1)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) v1)) (lseg ls dsh psh r y v2)))) *)
  apply exp_right with h. apply exp_right with tail. apply exp_right with p.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
    rewrite prop_true_andp by auto.
(* Goal: @derives mpred Nveric P (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh v1) (@list_cell cs list_structid list_link list_token ls dsh h v1)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) p) v1)) (lseg ls dsh psh tail p v2)) *)
 rewrite sepcon_assoc.
(* Goal: @derives mpred Nveric P (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh v1) (@list_cell cs list_structid list_link list_token ls dsh h v1)) (@sepcon mpred Nveric Sveric (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) p) v1) (lseg ls dsh psh tail p v2))) *)
 eapply derives_trans; [ apply H1 | ].
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
 apply sepcon_derives; auto.
Qed.

Lemma lseg_neq (ls: listspec list_structid list_link list_token):
  forall sh s v v2,
    ptr_neq v v2 ->
     lseg ls sh s v v2 = lseg_cons ls sh s v v2.
(* Goal: forall (v' : @elemtype cs list_structid list_link list_token ls) (ash bsh psh : share) (p : val) (v : @elemtype cs list_structid list_link list_token ls) (_ : @sepalg.join share Share.Join_ba ash bsh psh) (_ : not (readable_share ash)) (_ : readable_share bsh), @eq mpred (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls ash v' p) (@list_cell cs list_structid list_link list_token ls bsh v p)) (@list_cell cs list_structid list_link list_token ls psh v p) *)
intros. rewrite lseg_unroll.
(* Goal: @eq mpred (@orp mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) x z)) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) *)
apply pred_ext. apply orp_left; auto.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) *)
(* Goal: @derives mpred Nveric (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) x z) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) *)
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) (@orp mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) x z)) *)
rewrite andp_assoc.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq v v2)) (@andp mpred Nveric (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) s (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) (@emp mpred Nveric Sveric))) (lseg_cons ls dsh psh s v v2) *)
(* Goal: @derives mpred Nveric (lseg_cons ls dsh psh s v v2) (@orp mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq v v2)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) s (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh s v v2)) *)
do 2 (apply derives_extract_prop; intro).
(* Goal: @derives mpred Nveric (@emp mpred Nveric Sveric) (lseg_cons ls dsh psh s v v2) *)
(* Goal: @derives mpred Nveric (lseg_cons ls dsh psh s v v2) (@orp mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq v v2)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) s (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh s v v2)) *)
congruence.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
apply orp_right2. auto.
Qed.

Lemma lseg_nonnull (ls: listspec list_structid list_link list_token):
  forall sh s v,
      typed_true (tptr list_struct) v ->
     lseg ls sh s v nullval = lseg_cons ls sh s v nullval.
Proof.
(* Goal: forall (v' : @elemtype cs list_structid list_link list_token ls) (ash bsh psh : share) (p : val) (v : @elemtype cs list_structid list_link list_token ls) (_ : @sepalg.join share Share.Join_ba ash bsh psh) (_ : not (readable_share ash)) (_ : readable_share bsh), @eq mpred (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls ash v' p) (@list_cell cs list_structid list_link list_token ls bsh v p)) (@list_cell cs list_structid list_link list_token ls psh v p) *)
intros. unfold nullval.
(* Goal: @eq mpred (lseg ls dsh psh s v (if Archi.ptr64 then Vlong Int64.zero else Vint Int.zero)) (lseg_cons ls dsh psh s v (if Archi.ptr64 then Vlong Int64.zero else Vint Int.zero)) *)
apply lseg_neq.
unfold typed_true, strict_bool_val in H.
(* Goal: False *)
simpl in H.
(* Goal: and (Z.lt Z0 (if Archi.ptr64 then Zpos (xO (xO (xO xH))) else Zpos (xO (xO xH)))) (Z.lt (if Archi.ptr64 then Zpos (xO (xO (xO xH))) else Zpos (xO (xO xH))) Ptrofs.modulus) *)
destruct Archi.ptr64 eqn:Hp.
*
destruct v; inv H. 
(* Goal: False *)
(* Goal: ptr_neq (Vptr b i) (if Archi.ptr64 then Vlong Int64.zero else Vint Int.zero) *)
destruct (Int64.eq i Int64.zero); inv H1.
intro; apply ptr_eq_e in H; inv H.
*
destruct v; inv H.
(* Goal: False *)
(* Goal: ptr_neq (Vptr b i) (if Archi.ptr64 then Vlong Int64.zero else Vint Int.zero) *)
destruct (Int.eq i Int.zero); inv H1.
intro; apply ptr_eq_e in H; inv H.
Qed.

Lemma unfold_lseg_neq (ls: listspec list_structid list_link list_token):
   forall P Q1 Q R (v v2: val) sh (s: list (elemtype ls)),
      PROPx P (LOCALx (Q1::Q) (SEPx (lseg ls sh s v v2 :: R))) |--
                        !! (ptr_neq v v2) ->
      PROPx P (LOCALx (Q1::Q) (SEPx (lseg ls sh s v v2 :: R))) |--
     EX hryp: elemtype ls * list (elemtype ls) * val,
      match hryp with (h,r,y) =>
       !! (s=h::r /\ is_pointer_or_null y) &&
      PROPx P (LOCALx Q
        (SEPx (list_token sh v :: list_cell ls sh h v::
                  field_at sh list_struct (StructField list_link :: nil) (valinject (nested_field_type list_struct (StructField list_link :: nil)) y) v ::
                   lseg ls sh r y v2 ::
                  R)))
        end.
Proof.
(* Goal: forall (v' : @elemtype cs list_structid list_link list_token ls) (ash bsh psh : share) (p : val) (v : @elemtype cs list_structid list_link list_token ls) (_ : @sepalg.join share Share.Join_ba ash bsh psh) (_ : not (readable_share ash)) (_ : readable_share bsh), @eq mpred (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls ash v' p) (@list_cell cs list_structid list_link list_token ls bsh v p)) (@list_cell cs list_structid list_link list_token ls psh v p) *)
intros.
apply derives_trans with
(PROPx P (LOCALx (Q1::Q) (SEPx (lseg_cons ls sh s v v2 :: R)))).
apply derives_trans with
(!! (ptr_neq v v2) && PROPx P (LOCALx (Q1::Q) (SEPx (lseg ls sh s v v2 :: R)))).
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
apply andp_right; auto.
(* Goal: @derives (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (@andp (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (@prop (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (ptr_neq v v2)) (PROPx P (LOCALx (@cons localdef Q1 Q) (SEPx (@cons mpred (lseg ls dsh psh s v v2) R))))) (PROPx P (LOCALx (@cons localdef Q1 Q) (SEPx (@cons mpred (lseg_cons ls dsh psh s v v2) R)))) *)
(* Goal: @derives (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (PROPx P (LOCALx (@cons localdef Q1 Q) (SEPx (@cons mpred (lseg_cons ls dsh psh s v v2) R)))) (@exp (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (prod (prod (prod (@elemtype cs list_structid list_link list_token ls) (list (prod val (@elemtype cs list_structid list_link list_token ls)))) val) val) (fun hryp : prod (prod (prod (@elemtype cs list_structid list_link list_token ls) (list (prod val (@elemtype cs list_structid list_link list_token ls)))) val) val => let (p0, p) := hryp in let (p1, y) := p0 in let (h, r) := p1 in @andp (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (@andp (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (@prop (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) s (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) p h) r)) (is_pointer_or_null y))) (@prop (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (@eq val p v))) (PROPx P (LOCALx Q (SEPx (@cons mpred (list_token dsh v) (@cons mpred (@list_cell cs list_structid list_link list_token ls dsh h v) (@cons mpred (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) v) (@cons mpred (lseg ls dsh psh r y v2) R))))))))) *)
intro rho; unfold PROPx,LOCALx,SEPx,local,tc_expr,tc_lvalue; unfold_lift; simpl.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_neq v v2)) (@andp mpred Nveric (@prop mpred Nveric (@fold_right Prop Prop and True P)) (@andp mpred Nveric (@lift1 Prop mpred (@prop mpred Nveric) (fun x : environ => and (locald_denote Q1 x) (@fold_right (forall _ : environ, Prop) (forall _ : environ, Prop) (fun (x0 x1 : forall _ : environ, Prop) (x2 : environ) => and (x0 x2) (x1 x2)) (fun _ : environ => True) (@map localdef (forall _ : environ, Prop) locald_denote Q) x)) rho) (@sepcon mpred Nveric Sveric (lseg ls dsh psh s v v2) (fold_right_sepcon R))))) (@andp mpred Nveric (@prop mpred Nveric (@fold_right Prop Prop and True P)) (@andp mpred Nveric (@lift1 Prop mpred (@prop mpred Nveric) (fun x : environ => and (locald_denote Q1 x) (@fold_right (forall _ : environ, Prop) (forall _ : environ, Prop) (fun (x0 x1 : forall _ : environ, Prop) (x2 : environ) => and (x0 x2) (x1 x2)) (fun _ : environ => True) (@map localdef (forall _ : environ, Prop) locald_denote Q) x)) rho) (@sepcon mpred Nveric Sveric (lseg_cons ls dsh psh s v v2) (fold_right_sepcon R)))) *)
(* Goal: @derives (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (PROPx P (LOCALx (@cons localdef Q1 Q) (SEPx (@cons mpred (lseg_cons ls dsh psh s v v2) R)))) (@exp (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (prod (prod (prod (@elemtype cs list_structid list_link list_token ls) (list (prod val (@elemtype cs list_structid list_link list_token ls)))) val) val) (fun hryp : prod (prod (prod (@elemtype cs list_structid list_link list_token ls) (list (prod val (@elemtype cs list_structid list_link list_token ls)))) val) val => let (p0, p) := hryp in let (p1, y) := p0 in let (h, r) := p1 in @andp (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (@andp (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (@prop (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) s (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) p h) r)) (is_pointer_or_null y))) (@prop (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (@eq val p v))) (PROPx P (LOCALx Q (SEPx (@cons mpred (list_token dsh v) (@cons mpred (@list_cell cs list_structid list_link list_token ls dsh h v) (@cons mpred (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) v) (@cons mpred (lseg ls dsh psh r y v2) R))))))))) *)
unfold lift1; simpl.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_neq v v2)) (@andp mpred Nveric (@prop mpred Nveric (@fold_right Prop Prop and True P)) (@andp mpred Nveric (@prop mpred Nveric (and (locald_denote Q1 rho) (@fold_right (forall _ : environ, Prop) (forall _ : environ, Prop) (fun (x x0 : forall _ : environ, Prop) (x1 : environ) => and (x x1) (x0 x1)) (fun _ : environ => True) (@map localdef (forall _ : environ, Prop) locald_denote Q) rho))) (@sepcon mpred Nveric Sveric (lseg ls dsh psh s v v2) (fold_right_sepcon R))))) (@andp mpred Nveric (@prop mpred Nveric (@fold_right Prop Prop and True P)) (@andp mpred Nveric (@prop mpred Nveric (and (locald_denote Q1 rho) (@fold_right (forall _ : environ, Prop) (forall _ : environ, Prop) (fun (x x0 : forall _ : environ, Prop) (x1 : environ) => and (x x1) (x0 x1)) (fun _ : environ => True) (@map localdef (forall _ : environ, Prop) locald_denote Q) rho))) (@sepcon mpred Nveric Sveric (lseg_cons ls dsh psh s v v2) (fold_right_sepcon R)))) *)
(* Goal: @derives (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (PROPx P (LOCALx (@cons localdef Q1 Q) (SEPx (@cons mpred (lseg_cons ls dsh psh s v v2) R)))) (@exp (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (prod (prod (prod (@elemtype cs list_structid list_link list_token ls) (list (prod val (@elemtype cs list_structid list_link list_token ls)))) val) val) (fun hryp : prod (prod (prod (@elemtype cs list_structid list_link list_token ls) (list (prod val (@elemtype cs list_structid list_link list_token ls)))) val) val => let (p0, p) := hryp in let (p1, y) := p0 in let (h, r) := p1 in @andp (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (@andp (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (@prop (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) s (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) p h) r)) (is_pointer_or_null y))) (@prop (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (@eq val p v))) (PROPx P (LOCALx Q (SEPx (@cons mpred (list_token dsh v) (@cons mpred (@list_cell cs list_structid list_link list_token ls dsh h v) (@cons mpred (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) v) (@cons mpred (lseg ls dsh psh r y v2) R))))))))) *)
 repeat (apply derives_extract_prop; intro).
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
 rewrite prop_true_andp by auto.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
 rewrite prop_true_andp by auto.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
apply sepcon_derives; auto.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
rewrite lseg_neq; auto.
(* Goal: @derives (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (PROPx P (LOCALx (@cons localdef Q1 Q) (SEPx (@cons mpred (lseg_cons ls dsh psh s v v2) R)))) (@exp (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (prod (prod (prod (@elemtype cs list_structid list_link list_token ls) (list (prod val (@elemtype cs list_structid list_link list_token ls)))) val) val) (fun hryp : prod (prod (prod (@elemtype cs list_structid list_link list_token ls) (list (prod val (@elemtype cs list_structid list_link list_token ls)))) val) val => let (p0, p) := hryp in let (p1, y) := p0 in let (h, r) := p1 in @andp (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (@andp (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (@prop (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) s (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) p h) r)) (is_pointer_or_null y))) (@prop (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (@eq val p v))) (PROPx P (LOCALx Q (SEPx (@cons mpred (list_token dsh v) (@cons mpred (@list_cell cs list_structid list_link list_token ls dsh h v) (@cons mpred (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) v) (@cons mpred (lseg ls dsh psh r y v2) R))))))))) *)
intro rho; unfold PROPx,LOCALx,SEPx,local,tc_expr,tc_lvalue,lift2,lift1,lift0; simpl.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@fold_right Prop Prop and True P)) (@andp mpred Nveric (@prop mpred Nveric (@liftx (Tarrow Prop (Tarrow Prop (LiftEnviron Prop))) and (locald_denote Q1) (@fold_right (forall _ : environ, Prop) (forall _ : environ, Prop) (@liftx (Tarrow Prop (Tarrow Prop (LiftEnviron Prop))) and) (@liftx (LiftEnviron Prop) True) (@map localdef (forall _ : environ, Prop) locald_denote Q)) rho)) (@sepcon mpred Nveric Sveric (lseg_cons ls dsh psh s v v2) (fold_right_sepcon R)))) (@exp mpred Nveric (prod (prod (prod (@elemtype cs list_structid list_link list_token ls) (list (prod val (@elemtype cs list_structid list_link list_token ls)))) val) val) (fun x : prod (prod (prod (@elemtype cs list_structid list_link list_token ls) (list (prod val (@elemtype cs list_structid list_link list_token ls)))) val) val => (let (p0, p) := x in let (p1, y) := p0 in let (h, r) := p1 in fun x0 : environ => @andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) s (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) p h) r)) (is_pointer_or_null y))) (@prop mpred Nveric (@eq val p v))) (@andp mpred Nveric (@prop mpred Nveric (@fold_right Prop Prop and True P)) (@andp mpred Nveric (@prop mpred Nveric (@fold_right (forall _ : environ, Prop) (forall _ : environ, Prop) (@liftx (Tarrow Prop (Tarrow Prop (LiftEnviron Prop))) and) (@liftx (LiftEnviron Prop) True) (@map localdef (forall _ : environ, Prop) locald_denote Q) x0)) (@sepcon mpred Nveric Sveric (list_token dsh v) (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls dsh h v) (@sepcon mpred Nveric Sveric (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) v) (@sepcon mpred Nveric Sveric (lseg ls dsh psh r y v2) (fold_right_sepcon R)))))))) rho)) *)
 unfold_lift.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh p) (@list_cell cs list_structid list_link list_token ls dsh h p)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) p)) (lseg ls dsh psh r y z)) (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) p h) r) p z) *)
 unfold lseg_cons. simpl.
(* Goal: ptr_neq (Vptr b i) (if Archi.ptr64 then Vlong Int64.zero else Vint Int.zero) *)
 apply derives_extract_prop; intro.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) s (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) v h) r)) (is_pointer_or_null y))) (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh v) (@list_cell cs list_structid list_link list_token ls dsh h v)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) v)) (lseg ls dsh psh r y v2)) (fold_right_sepcon R))) (@exp mpred Nveric (prod (prod (prod (@elemtype cs list_structid list_link list_token ls) (list (prod val (@elemtype cs list_structid list_link list_token ls)))) val) val) (fun x : prod (prod (prod (@elemtype cs list_structid list_link list_token ls) (list (prod val (@elemtype cs list_structid list_link list_token ls)))) val) val => (let (p0, p) := x in let (p1, y) := p0 in let (h, r) := p1 in fun x0 : environ => @andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) s (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) p h) r)) (is_pointer_or_null y))) (@prop mpred Nveric (@eq val p v))) (@andp mpred Nveric (@prop mpred Nveric (@fold_right Prop Prop and True P)) (@andp mpred Nveric (@prop mpred Nveric (@fold_right (forall _ : environ, Prop) (forall _ : environ, Prop) (fun (x1 x2 : forall _ : environ, Prop) (x3 : environ) => and (x1 x3) (x2 x3)) (fun _ : environ => True) (@map localdef (forall _ : environ, Prop) locald_denote Q) x0)) (@sepcon mpred Nveric Sveric (list_token dsh v) (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls dsh h v) (@sepcon mpred Nveric Sveric (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) v) (@sepcon mpred Nveric Sveric (lseg ls dsh psh r y v2) (fold_right_sepcon R)))))))) rho)) *)
 apply derives_extract_prop; intros [? ?].
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (not (ptr_eq v v2))) (@exp mpred Nveric (@elemtype cs list_structid list_link list_token ls) (fun h : @elemtype cs list_structid list_link list_token ls => @exp mpred Nveric (list (prod val (@elemtype cs list_structid list_link list_token ls))) (fun r : list (prod val (@elemtype cs list_structid list_link list_token ls)) => @exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) s (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) v h) r)) (is_pointer_or_null y))) (list_token dsh v)) (@list_cell cs list_structid list_link list_token ls dsh h v)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) v)) (lseg ls dsh psh r y v2)))))) (fold_right_sepcon R)) (@exp mpred Nveric (prod (prod (prod (@elemtype cs list_structid list_link list_token ls) (list (prod val (@elemtype cs list_structid list_link list_token ls)))) val) val) (fun x : prod (prod (prod (@elemtype cs list_structid list_link list_token ls) (list (prod val (@elemtype cs list_structid list_link list_token ls)))) val) val => (let (p0, p) := x in let (p1, y) := p0 in let (h, r) := p1 in fun x0 : environ => @andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) s (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) p h) r)) (is_pointer_or_null y))) (@prop mpred Nveric (@eq val p v))) (@andp mpred Nveric (@prop mpred Nveric (@fold_right Prop Prop and True P)) (@andp mpred Nveric (@prop mpred Nveric (@fold_right (forall _ : environ, Prop) (forall _ : environ, Prop) (fun (x1 x2 : forall _ : environ, Prop) (x3 : environ) => and (x1 x3) (x2 x3)) (fun _ : environ => True) (@map localdef (forall _ : environ, Prop) locald_denote Q) x0)) (@sepcon mpred Nveric Sveric (list_token dsh v) (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls dsh h v) (@sepcon mpred Nveric Sveric (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) v) (@sepcon mpred Nveric Sveric (lseg ls dsh psh r y v2) (fold_right_sepcon R)))))))) rho)) *)
 rewrite sepcon_andp_prop'.
(* Goal: ptr_neq (Vptr b i) (if Archi.ptr64 then Vlong Int64.zero else Vint Int.zero) *)
 apply derives_extract_prop; intro.
(* Goal: @derives mpred Nveric (@exp mpred Nveric (@elemtype cs list_structid list_link list_token ls) (fun h : @elemtype cs list_structid list_link list_token ls => @exp mpred Nveric (list (prod val (@elemtype cs list_structid list_link list_token ls))) (fun r : list (prod val (@elemtype cs list_structid list_link list_token ls)) => @exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) v e) l) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) x h) r)) (is_pointer_or_null y))) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh h x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z))))) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val v x) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh e x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) x)) (lseg ls dsh psh l tail z)))) *)
 rewrite exp_sepcon1; apply exp_left; intro h.
(* Goal: @derives mpred Nveric (@exp mpred Nveric (list (prod val (@elemtype cs list_structid list_link list_token ls))) (fun r : list (prod val (@elemtype cs list_structid list_link list_token ls)) => @exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) v e) l) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) x h) r)) (is_pointer_or_null y))) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh h x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val v x) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh e x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) x)) (lseg ls dsh psh l tail z)))) *)
 rewrite exp_sepcon1; apply exp_left; intro r.
(* Goal: @derives mpred Nveric (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) v e) l) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) x h) r)) (is_pointer_or_null y))) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh h x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z))) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val v x) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh e x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) x)) (lseg ls dsh psh l tail z)))) *)
 rewrite exp_sepcon1; apply exp_left; intro y.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) s (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) v h) r)) (is_pointer_or_null y))) (list_token dsh v)) (@list_cell cs list_structid list_link list_token ls dsh h v)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) v)) (lseg ls dsh psh r y v2)) (fold_right_sepcon R)) (@exp mpred Nveric (prod (prod (prod (@elemtype cs list_structid list_link list_token ls) (list (prod val (@elemtype cs list_structid list_link list_token ls)))) val) val) (fun x : prod (prod (prod (@elemtype cs list_structid list_link list_token ls) (list (prod val (@elemtype cs list_structid list_link list_token ls)))) val) val => (let (p0, p) := x in let (p1, y) := p0 in let (h, r) := p1 in fun x0 : environ => @andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) s (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) p h) r)) (is_pointer_or_null y))) (@prop mpred Nveric (@eq val p v))) (@andp mpred Nveric (@prop mpred Nveric (@fold_right Prop Prop and True P)) (@andp mpred Nveric (@prop mpred Nveric (@fold_right (forall _ : environ, Prop) (forall _ : environ, Prop) (fun (x1 x2 : forall _ : environ, Prop) (x3 : environ) => and (x1 x3) (x2 x3)) (fun _ : environ => True) (@map localdef (forall _ : environ, Prop) locald_denote Q) x0)) (@sepcon mpred Nveric Sveric (list_token dsh v) (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls dsh h v) (@sepcon mpred Nveric Sveric (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) v) (@sepcon mpred Nveric Sveric (lseg ls dsh psh r y v2) (fold_right_sepcon R)))))))) rho)) *)
 repeat rewrite sepcon_andp_prop'.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) s (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) v h) r)) (is_pointer_or_null y))) (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh v) (@list_cell cs list_structid list_link list_token ls dsh h v)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) v)) (lseg ls dsh psh r y v2)) (fold_right_sepcon R))) (@exp mpred Nveric (prod (prod (prod (@elemtype cs list_structid list_link list_token ls) (list (prod val (@elemtype cs list_structid list_link list_token ls)))) val) val) (fun x : prod (prod (prod (@elemtype cs list_structid list_link list_token ls) (list (prod val (@elemtype cs list_structid list_link list_token ls)))) val) val => (let (p0, p) := x in let (p1, y) := p0 in let (h, r) := p1 in fun x0 : environ => @andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) s (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) p h) r)) (is_pointer_or_null y))) (@prop mpred Nveric (@eq val p v))) (@andp mpred Nveric (@prop mpred Nveric (@fold_right Prop Prop and True P)) (@andp mpred Nveric (@prop mpred Nveric (@fold_right (forall _ : environ, Prop) (forall _ : environ, Prop) (fun (x1 x2 : forall _ : environ, Prop) (x3 : environ) => and (x1 x3) (x2 x3)) (fun _ : environ => True) (@map localdef (forall _ : environ, Prop) locald_denote Q) x0)) (@sepcon mpred Nveric Sveric (list_token dsh v) (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls dsh h v) (@sepcon mpred Nveric Sveric (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) v) (@sepcon mpred Nveric Sveric (lseg ls dsh psh r y v2) (fold_right_sepcon R)))))))) rho)) *)
 apply derives_extract_prop; intros [? ?].
(* Goal: and True (iff (@eq val (Vptr b0 i) (Vptr b0 i0)) (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) *)
(* Goal: @derives mpred Nveric (let (p0, h) := p0 in @andp mpred Nveric (@prop mpred Nveric (and (@eq val p0 p) (not (ptr_eq p q)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh p)) (@list_cell cs list_structid list_link list_token ls dsh h p)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) p)) (lseg ls dsh psh contents tail q)))) (@prop mpred Nveric (and (is_pointer_or_null p) (iff (@eq val p q) (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) p0 contents) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))))) *)
 subst.
 apply exp_right with (h,r,y).
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
 repeat rewrite prop_true_andp by auto.
(* Goal: @derives mpred Nveric P (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh v1) (@list_cell cs list_structid list_link list_token ls dsh h v1)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) p) v1)) (lseg ls dsh psh tail p v2)) *)
 repeat rewrite sepcon_assoc.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
 auto.
Qed.

Lemma unfold_lseg_cons (ls: listspec list_structid list_link list_token):
   forall P Q1 Q R e sh s,
      PROPx P (LOCALx (Q1::Q) (SEPx (lseg ls sh s e nullval :: R))) |--
                        !!(typed_true (tptr list_struct) e) ->
      PROPx P (LOCALx (Q1::Q) (SEPx (lseg ls sh s e nullval :: R))) |--
     EX hryp: elemtype ls * list (elemtype ls) * val,
      match hryp with (h,r,y) =>
       !! (s=h::r /\ is_pointer_or_null y) &&
      PROPx P (LOCALx Q
        (SEPx (list_token sh e :: list_cell ls sh h e ::
                  field_at sh list_struct (StructField list_link :: nil) (valinject (nested_field_type list_struct (StructField list_link :: nil)) y) e ::
                   lseg ls sh r y nullval ::
                  R)))
        end.
Proof.
(* Goal: forall (v' : @elemtype cs list_structid list_link list_token ls) (ash bsh psh : share) (p : val) (v : @elemtype cs list_structid list_link list_token ls) (_ : @sepalg.join share Share.Join_ba ash bsh psh) (_ : not (readable_share ash)) (_ : readable_share bsh), @eq mpred (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls ash v' p) (@list_cell cs list_structid list_link list_token ls bsh v p)) (@list_cell cs list_structid list_link list_token ls psh v p) *)
intros. apply unfold_lseg_neq.
eapply derives_trans.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
apply H. normalize.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@fold_right Prop Prop and True P)) (@andp mpred Nveric (@prop mpred Nveric (@liftx (Tarrow Prop (Tarrow Prop (LiftEnviron Prop))) and (locald_denote Q1) (@fold_right (forall _ : environ, Prop) (forall _ : environ, Prop) (@liftx (Tarrow Prop (Tarrow Prop (LiftEnviron Prop))) and) (@liftx (LiftEnviron Prop) True) (@map localdef (forall _ : environ, Prop) locald_denote Q)) rho)) (@sepcon mpred Nveric Sveric (lseg_cons ls dsh psh s v v2) (fold_right_sepcon R)))) (@exp mpred Nveric (prod (prod (prod (@elemtype cs list_structid list_link list_token ls) (list (prod val (@elemtype cs list_structid list_link list_token ls)))) val) val) (fun x : prod (prod (prod (@elemtype cs list_structid list_link list_token ls) (list (prod val (@elemtype cs list_structid list_link list_token ls)))) val) val => (let (p0, p) := x in let (p1, y) := p0 in let (h, r) := p1 in fun x0 : environ => @andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) s (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) p h) r)) (is_pointer_or_null y))) (@prop mpred Nveric (@eq val p v))) (@andp mpred Nveric (@prop mpred Nveric (@fold_right Prop Prop and True P)) (@andp mpred Nveric (@prop mpred Nveric (@fold_right (forall _ : environ, Prop) (forall _ : environ, Prop) (@liftx (Tarrow Prop (Tarrow Prop (LiftEnviron Prop))) and) (@liftx (LiftEnviron Prop) True) (@map localdef (forall _ : environ, Prop) locald_denote Q) x0)) (@sepcon mpred Nveric Sveric (list_token dsh v) (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls dsh h v) (@sepcon mpred Nveric Sveric (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) v) (@sepcon mpred Nveric Sveric (lseg ls dsh psh r y v2) (fold_right_sepcon R)))))))) rho)) *)
unfold local. super_unfold_lift.
(* Goal: @eq mpred (lseg ls dsh psh s v nullval) (lseg_cons ls dsh psh s v nullval) *)
unfold nullval.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
destruct e; inv H0; try congruence; auto.
(* Goal: ptr_neq (Vptr b i) (if Archi.ptr64 then Vlong Int64.zero else Vint Int.zero) *)
intro. apply ptr_eq_e in H0.
(* Goal: @derives mpred Nveric (@emp mpred Nveric Sveric) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) *)
(* Goal: @derives mpred Nveric (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) x z) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) *)
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) (@orp mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) x z)) *)
destruct Archi.ptr64; inv H0.
Qed.

Lemma semax_lseg_neq (ls: listspec list_structid list_link list_token):
  forall (Espec: OracleKind)
      Delta P Q sh s v v2 R c Post,
    ~ (ptr_eq v v2) ->
  (forall (h: elemtype ls) (r: list (elemtype ls)) (y: val),
    s=h::r -> is_pointer_or_null y ->
    semax Delta
        (PROPx P (LOCALx Q
        (SEPx (list_token sh v :: list_cell ls sh h v ::
                  field_at sh list_struct (StructField list_link :: nil)
                      (valinject (nested_field_type list_struct (StructField list_link :: nil)) y) v ::
                   lseg ls sh r y v2 ::
                  R)))) c Post) ->
   semax Delta
       (PROPx P (LOCALx Q (SEPx (lseg ls sh s v v2 :: R))))
       c Post.
Proof.
(* Goal: forall (v' : @elemtype cs list_structid list_link list_token ls) (ash bsh psh : share) (p : val) (v : @elemtype cs list_structid list_link list_token ls) (_ : @sepalg.join share Share.Join_ba ash bsh psh) (_ : not (readable_share ash)) (_ : readable_share bsh), @eq mpred (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls ash v' p) (@list_cell cs list_structid list_link list_token ls bsh v p)) (@list_cell cs list_structid list_link list_token ls psh v p) *)
intros.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
rewrite lseg_neq by auto.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh p) (@list_cell cs list_structid list_link list_token ls dsh h p)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) p)) (lseg ls dsh psh r y z)) (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) p h) r) p z) *)
unfold lseg_cons.
apply semax_pre0 with
 (EX h: elemtype ls, EX r: list (elemtype ls), EX y: val,
  !!(s = h :: r /\ is_pointer_or_null y) &&
    PROPx P (LOCALx Q (SEPx (list_token sh v :: list_cell ls sh h v ::
       field_at sh list_struct (StructField list_link :: nil)
                   (valinject
                      (nested_field_type list_struct
                         (StructField list_link :: nil)) y) v ::
        lseg ls sh r y v2 :: R)))).
(* Goal: @derives (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (PROPx P (LOCALx Q (SEPx (@cons mpred (@andp mpred Nveric (@prop mpred Nveric (not (ptr_eq v v2))) (@exp mpred Nveric (@elemtype cs list_structid list_link list_token ls) (fun h : @elemtype cs list_structid list_link list_token ls => @exp mpred Nveric (list (prod val (@elemtype cs list_structid list_link list_token ls))) (fun r : list (prod val (@elemtype cs list_structid list_link list_token ls)) => @exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) s (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) v h) r)) (is_pointer_or_null y))) (list_token dsh v)) (@list_cell cs list_structid list_link list_token ls dsh h v)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) v)) (lseg ls dsh psh r y v2)))))) R)))) (@exp (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (@elemtype cs list_structid list_link list_token ls) (fun h : @elemtype cs list_structid list_link list_token ls => @exp (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (list (prod val (@elemtype cs list_structid list_link list_token ls))) (fun r : list (prod val (@elemtype cs list_structid list_link list_token ls)) => @exp (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) val (fun y : val => @andp (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (@prop (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) s (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) v h) r)) (is_pointer_or_null y))) (PROPx P (LOCALx Q (SEPx (@cons mpred (list_token dsh v) (@cons mpred (@list_cell cs list_structid list_link list_token ls dsh h v) (@cons mpred (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) v) (@cons mpred (lseg ls dsh psh r y v2) R))))))))))) *)
(* Goal: semax cs Espec Delta (@exp (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (@elemtype cs list_structid list_link list_token ls) (fun h : @elemtype cs list_structid list_link list_token ls => @exp (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (list (prod val (@elemtype cs list_structid list_link list_token ls))) (fun r : list (prod val (@elemtype cs list_structid list_link list_token ls)) => @exp (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) val (fun y : val => @andp (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (@prop (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) s (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) v h) r)) (is_pointer_or_null y))) (PROPx P (LOCALx Q (SEPx (@cons mpred (list_token dsh v) (@cons mpred (@list_cell cs list_structid list_link list_token ls dsh h v) (@cons mpred (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) v) (@cons mpred (lseg ls dsh psh r y v2) R))))))))))) c Post *)
go_lowerx; entailer.  (* Intros h r y should work here, but doesn't. *)
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh v) (@list_cell cs list_structid list_link list_token ls dsh h v)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) v)) (lseg ls dsh psh r y v2)) (fold_right_sepcon R)) (@exp mpred Nveric (@elemtype cs list_structid list_link list_token ls) (fun x : @elemtype cs list_structid list_link list_token ls => @exp mpred Nveric (list (prod val (@elemtype cs list_structid list_link list_token ls))) (fun x0 : list (prod val (@elemtype cs list_structid list_link list_token ls)) => @exp mpred Nveric val (fun x1 : val => @andp mpred Nveric (@prop mpred Nveric (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) v h) r) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) v x) x0)) (is_pointer_or_null x1))) (@andp mpred Nveric (@TT mpred Nveric) (@andp mpred Nveric (@TT mpred Nveric) (@sepcon mpred Nveric Sveric (list_token dsh v) (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls dsh x v) (@sepcon mpred Nveric Sveric (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) x1) v) (@sepcon mpred Nveric Sveric (lseg ls dsh psh x0 x1 v2) (fold_right_sepcon R))))))))))) *)
(* Goal: semax cs Espec Delta (@exp (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (@elemtype cs list_structid list_link list_token ls) (fun h : @elemtype cs list_structid list_link list_token ls => @exp (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (list (prod val (@elemtype cs list_structid list_link list_token ls))) (fun r : list (prod val (@elemtype cs list_structid list_link list_token ls)) => @exp (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) val (fun y : val => @andp (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (@prop (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) s (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) v h) r)) (is_pointer_or_null y))) (PROPx P (LOCALx Q (SEPx (@cons mpred (list_token dsh v) (@cons mpred (@list_cell cs list_structid list_link list_token ls dsh h v) (@cons mpred (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) v) (@cons mpred (lseg ls dsh psh r y v2) R))))))))))) c Post *)
Exists h r y.
rewrite <- ?sepcon_assoc.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
normalize.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
  autorewrite with subst norm1 norm2; normalize.
(* Goal: semax cs Espec Delta (@exp (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (@elemtype cs list_structid list_link list_token ls) (fun h : @elemtype cs list_structid list_link list_token ls => @exp (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (list (prod val (@elemtype cs list_structid list_link list_token ls))) (fun r : list (prod val (@elemtype cs list_structid list_link list_token ls)) => @exp (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) val (fun y : val => @andp (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (@prop (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) s (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) v h) r)) (is_pointer_or_null y))) (PROPx P (LOCALx Q (SEPx (@cons mpred (list_token dsh v) (@cons mpred (@list_cell cs list_structid list_link list_token ls dsh h v) (@cons mpred (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) v) (@cons mpred (lseg ls dsh psh r y v2) R))))))))))) c Post *)
Intros h r y.
(* Goal: semax cs Espec Delta (@andp (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (@prop (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) s (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) v h) r)) (is_pointer_or_null y))) (PROPx P (LOCALx Q (SEPx (@cons mpred (list_token dsh v) (@cons mpred (@list_cell cs list_structid list_link list_token ls dsh h v) (@cons mpred (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) v) (@cons mpred (lseg ls dsh psh r y v2) R)))))))) c Post *)
apply semax_extract_prop; intros [? ?].
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
eapply H0; eauto.
Qed.


Lemma semax_lseg_nonnull (ls: listspec list_structid list_link list_token):
  forall (Espec: OracleKind)
      Delta P Q sh s v R c Post,
      ENTAIL Delta, PROPx P (LOCALx Q
            (SEPx (lseg ls sh s v nullval :: R))) |--
                        !!(typed_true (tptr list_struct) v)  ->
  (forall (h: elemtype ls) (r: list (elemtype ls)) (y: val),
    s=h::r -> is_pointer_or_null y ->
    semax Delta
        (PROPx P (LOCALx Q
        (SEPx (list_token sh v :: list_cell ls sh h v ::
                  field_at sh list_struct (StructField list_link :: nil) (valinject (nested_field_type list_struct (StructField list_link :: nil)) y) v ::
                   lseg ls sh r y nullval ::
                  R)))) c Post) ->
   semax Delta
       (PROPx P (LOCALx Q (SEPx (lseg ls sh s v nullval :: R))))
       c Post.
Proof.
(* Goal: forall (v' : @elemtype cs list_structid list_link list_token ls) (ash bsh psh : share) (p : val) (v : @elemtype cs list_structid list_link list_token ls) (_ : @sepalg.join share Share.Join_ba ash bsh psh) (_ : not (readable_share ash)) (_ : readable_share bsh), @eq mpred (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls ash v' p) (@list_cell cs list_structid list_link list_token ls bsh v p)) (@list_cell cs list_structid list_link list_token ls psh v p) *)
intros.
(* Goal: semax cs Espec Delta (PROPx P (LOCALx Q (SEPx (@cons mpred (lseg ls dsh psh s v nullval) R)))) c Post *)
assert_PROP (~ ptr_eq v nullval).
(* Goal: @derives (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (@andp (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (local (tc_environ Delta)) (PROPx P (LOCALx Q (SEPx (@cons mpred (lseg ls dsh psh s v nullval) R))))) (@prop (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (not (ptr_eq v nullval))) *)
(* Goal: semax cs Espec Delta (PROPx P (LOCALx Q (SEPx (@cons mpred (lseg ls dsh psh s v nullval) R)))) c Post *)
eapply derives_trans; [apply H |].
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
normalize.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
apply semax_lseg_neq; auto.
Qed.

Lemma lseg_nil_eq (ls: listspec list_structid list_link list_token):
    forall sh p q, lseg ls sh nil p q = !! (ptr_eq p q) && emp.
(* Goal: forall (v' : @elemtype cs list_structid list_link list_token ls) (ash bsh psh : share) (p : val) (v : @elemtype cs list_structid list_link list_token ls) (_ : @sepalg.join share Share.Join_ba ash bsh psh) (_ : not (readable_share ash)) (_ : readable_share bsh), @eq mpred (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls ash v' p) (@list_cell cs list_structid list_link list_token ls bsh v p)) (@list_cell cs list_structid list_link list_token ls psh v p) *)
Proof. intros.
(* Goal: @eq mpred (lseg ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) x z) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) *)
 rewrite lseg_unroll.
(* Goal: @eq mpred (@orp mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) x z)) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) *)
 apply pred_ext.
(* Goal: @derives mpred Nveric (@orp mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) x z)) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) *)
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) (@orp mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) x z)) *)
 apply orp_left.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) *)
(* Goal: @derives mpred Nveric (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) x z) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) *)
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) (@orp mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) x z)) *)
 rewrite andp_assoc.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@andp mpred Nveric (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) (@emp mpred Nveric Sveric))) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
(* Goal: @derives mpred Nveric (lseg_cons ls dsh psh (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) p q) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@orp mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) p q)) *)
 apply andp_derives; auto.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
rewrite prop_true_andp by auto. auto.
(* Goal: @derives mpred Nveric (@emp mpred Nveric Sveric) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) *)
(* Goal: @derives mpred Nveric (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) x z) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) *)
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) (@orp mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) x z)) *)
 unfold lseg_cons. normalize. inv H0.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) *)
(* Goal: @derives mpred Nveric (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) x z) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) *)
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) (@orp mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) x z)) *)
 apply orp_right1.  rewrite andp_assoc.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
 rewrite (prop_true_andp (_ = _)) by auto. auto.
Qed.

Lemma lseg_cons_eq (ls: listspec list_structid list_link list_token):
     forall sh h r x z ,
    lseg ls sh (h::r) x z =
        !!(~ ptr_eq x z) &&
         (EX  y : val,
          !!(is_pointer_or_null y) &&
   list_token sh x * list_cell ls sh h x * field_at sh list_struct (StructField list_link :: nil) (valinject (nested_field_type list_struct (StructField list_link :: nil)) y) x *
   lseg ls sh r y z).
Proof.
(* Goal: forall (v' : @elemtype cs list_structid list_link list_token ls) (ash bsh psh : share) (p : val) (v : @elemtype cs list_structid list_link list_token ls) (_ : @sepalg.join share Share.Join_ba ash bsh psh) (_ : not (readable_share ash)) (_ : readable_share bsh), @eq mpred (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls ash v' p) (@list_cell cs list_structid list_link list_token ls bsh v p)) (@list_cell cs list_structid list_link list_token ls psh v p) *)
 intros. rewrite lseg_unroll.
(* Goal: @eq mpred (@orp mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) x z)) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) *)
 apply pred_ext.
(* Goal: @derives mpred Nveric (@orp mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) x z)) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) *)
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) (@orp mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) x z)) *)
 apply orp_left.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) *)
(* Goal: @derives mpred Nveric (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) x z) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) *)
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) (@orp mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) x z)) *)
 rewrite andp_assoc.
(* Goal: ptr_neq (Vptr b i) (if Archi.ptr64 then Vlong Int64.zero else Vint Int.zero) *)
 apply derives_extract_prop; intro.
(* Goal: ptr_neq (Vptr b i) (if Archi.ptr64 then Vlong Int64.zero else Vint Int.zero) *)
 apply derives_extract_prop; intro.
(* Goal: @derives mpred Nveric (@emp mpred Nveric Sveric) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) *)
(* Goal: @derives mpred Nveric (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) x z) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) *)
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) (@orp mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) x z)) *)
 inv H0.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh p) (@list_cell cs list_structid list_link list_token ls dsh h p)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) p)) (lseg ls dsh psh r y z)) (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) p h) r) p z) *)
 unfold lseg_cons.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
 normalize.
(* Goal: @derives mpred Nveric (@emp mpred Nveric Sveric) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) *)
(* Goal: @derives mpred Nveric (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) x z) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) *)
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) (@orp mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) x z)) *)
 symmetry in H0; inv H0.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
 apply exp_right with y. normalize.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh p) (@list_cell cs list_structid list_link list_token ls dsh h p)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) p)) (lseg ls dsh psh r y z)) (@orp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (and (ptr_eq p z) (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) p h) r) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) p h) r) p z)) *)
 apply orp_right2.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh p) (@list_cell cs list_structid list_link list_token ls dsh h p)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) p)) (lseg ls dsh psh r y z)) (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) p h) r) p z) *)
 unfold lseg_cons.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@andp mpred Nveric (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) (@emp mpred Nveric Sveric))) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
(* Goal: @derives mpred Nveric (lseg_cons ls dsh psh (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) p q) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@orp mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) p q)) *)
 apply andp_derives; auto.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh p) (@list_cell cs list_structid list_link list_token ls dsh h p)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) p)) (lseg ls dsh psh r y z)) (@exp mpred Nveric (@elemtype cs list_structid list_link list_token ls) (fun h0 : @elemtype cs list_structid list_link list_token ls => @exp mpred Nveric (list (prod val (@elemtype cs list_structid list_link list_token ls))) (fun r0 : list (prod val (@elemtype cs list_structid list_link list_token ls)) => @exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) p h) r) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) p h0) r0)) (is_pointer_or_null y))) (list_token dsh p)) (@list_cell cs list_structid list_link list_token ls dsh h0 p)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) p)) (lseg ls dsh psh r0 y z))))) *)
 apply exp_right with h. apply exp_right with r.  apply exp_derives; intro y.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
 normalize.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
  autorewrite with subst norm1 norm2; normalize.
Qed.

Definition lseg_cons_right (ls: listspec list_structid list_link list_token)
           sh (l: list (elemtype ls)) (x z: val) : mpred :=
        !! (~ ptr_eq x z) &&
       EX h:(elemtype ls), EX r:list (elemtype ls), EX y:val,
             !!(l=r++(h::nil) /\ is_pointer_or_null y)  &&
                       list_token sh y * list_cell ls sh h y *
             field_at sh list_struct (StructField list_link :: nil) (valinject (nested_field_type list_struct (StructField list_link :: nil)) z) y *
              lseg ls sh r x y.

Lemma lseg_cons_right_neq (ls: listspec list_structid list_link list_token): forall sh l x h y w z,
       sepalg.nonidentity sh ->
             list_token sh y * list_cell ls sh h y * field_at sh list_struct (StructField list_link :: nil) (valinject (nested_field_type list_struct (StructField list_link :: nil)) z) y *
             lseg ls sh l x y * field_at sh list_struct (StructField list_link :: nil) (valinject (nested_field_type list_struct (StructField list_link :: nil)) w) z
   |--   lseg ls sh (l++h::nil) x z * field_at sh list_struct (StructField list_link :: nil) (valinject (nested_field_type list_struct (StructField list_link :: nil)) w) z.
Proof.
(* Goal: forall (v' : @elemtype cs list_structid list_link list_token ls) (ash bsh psh : share) (p : val) (v : @elemtype cs list_structid list_link list_token ls) (_ : @sepalg.join share Share.Join_ba ash bsh psh) (_ : not (readable_share ash)) (_ : readable_share bsh), @eq mpred (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls ash v' p) (@list_cell cs list_structid list_link list_token ls bsh v p)) (@list_cell cs list_structid list_link list_token ls psh v p) *)
intros.
unfold lseg.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
normalize.
apply exp_right with (al ++ (y,h)::nil).
rewrite prop_true_andp by (rewrite map_app; reflexivity).
eapply derives_trans; [ | apply LsegGeneral.lseg_cons_right_neq; auto].
cancel.
Qed.

Lemma lseg_cons_right_null (ls: listspec list_structid list_link list_token): forall sh l x h y,
             list_token sh y * list_cell ls sh h y * field_at sh list_struct (StructField list_link :: nil) (valinject (nested_field_type list_struct (StructField list_link :: nil)) nullval) y *
             lseg ls sh l x y
   |--   lseg ls sh (l++h::nil) x nullval.
Proof.
(* Goal: forall (v' : @elemtype cs list_structid list_link list_token ls) (ash bsh psh : share) (p : val) (v : @elemtype cs list_structid list_link list_token ls) (_ : @sepalg.join share Share.Join_ba ash bsh psh) (_ : not (readable_share ash)) (_ : readable_share bsh), @eq mpred (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls ash v' p) (@list_cell cs list_structid list_link list_token ls bsh v p)) (@list_cell cs list_structid list_link list_token ls psh v p) *)
intros.
unfold lseg.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
normalize.
apply exp_right with (al ++ (y,h)::nil).
rewrite prop_true_andp by (rewrite map_app; reflexivity).
eapply derives_trans; [ | apply LsegGeneral.lseg_cons_right_null].
cancel.
Qed.


Lemma lseg_cons_right_list (ls: listspec list_structid list_link list_token): forall sh l l' x h y z,
              sepalg.nonidentity sh ->
             list_token sh y * list_cell ls sh h y * field_at sh list_struct (StructField list_link :: nil) (valinject (nested_field_type list_struct (StructField list_link :: nil)) z) y *
             lseg ls sh l x y * lseg ls sh l' z nullval
   |--   lseg ls sh (l++h::nil) x z * lseg ls sh l' z nullval.
Proof.
(* Goal: forall (v' : @elemtype cs list_structid list_link list_token ls) (ash bsh psh : share) (p : val) (v : @elemtype cs list_structid list_link list_token ls) (_ : @sepalg.join share Share.Join_ba ash bsh psh) (_ : not (readable_share ash)) (_ : readable_share bsh), @eq mpred (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls ash v' p) (@list_cell cs list_structid list_link list_token ls bsh v p)) (@list_cell cs list_structid list_link list_token ls psh v p) *)
intros.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh y) (@list_cell cs list_structid list_link list_token ls dsh h y)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) z) y)) (lseg ls dsh psh l x y)) (lseg ls dsh psh l' z nullval)) (@sepcon mpred Nveric Sveric (lseg ls dsh psh (@app (prod val (@elemtype cs list_structid list_link list_token ls)) l (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) y h) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) x z) (lseg ls dsh psh l' z nullval)) *)
destruct l'.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh y) (@list_cell cs list_structid list_link list_token ls dsh h y)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) z) y)) (lseg ls dsh psh l x y)) (lseg ls dsh psh (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) z nullval)) (@sepcon mpred Nveric Sveric (lseg ls dsh psh (@app (prod val (@elemtype cs list_structid list_link list_token ls)) l (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) y h) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) x z) (lseg ls dsh psh (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) z nullval)) *)
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh y) (@list_cell cs list_structid list_link list_token ls dsh h y)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) z) y)) (lseg ls dsh psh l x y)) (lseg ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) p l') z nullval)) (@sepcon mpred Nveric Sveric (lseg ls dsh psh (@app (prod val (@elemtype cs list_structid list_link list_token ls)) l (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) y h) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) x z) (lseg ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) p l') z nullval)) *)
rewrite lseg_nil_eq.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
normalize.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh y) (@list_cell cs list_structid list_link list_token ls dsh h y)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) nullval) y)) (lseg ls dsh psh l x y)) (lseg ls dsh psh (@app (prod val (@elemtype cs list_structid list_link list_token ls)) l (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) y h) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) x nullval) *)
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh y) (@list_cell cs list_structid list_link list_token ls dsh h y)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) z) y)) (lseg ls dsh psh l x y)) (lseg ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) p l') z nullval)) (@sepcon mpred Nveric Sveric (lseg ls dsh psh (@app (prod val (@elemtype cs list_structid list_link list_token ls)) l (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) y h) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) x z) (lseg ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) p l') z nullval)) *)
apply lseg_cons_right_null.
(* Goal: @eq mpred (lseg ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) x' h) r) x z) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x x') (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (lseg_cell ls dsh psh h x y) (lseg ls dsh psh r y z)))) *)
rewrite lseg_cons_eq.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh y) (@list_cell cs list_structid list_link list_token ls dsh h y)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) z) y)) (lseg ls dsh psh l x y)) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val z (@fst val (@elemtype cs list_structid list_link list_token ls) p)) (not (ptr_eq z nullval)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh z)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) p) z)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) z)) (lseg ls dsh psh l' y nullval))))) (@sepcon mpred Nveric Sveric (lseg ls dsh psh (@app (prod val (@elemtype cs list_structid list_link list_token ls)) l (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) y h) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) x z) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val z (@fst val (@elemtype cs list_structid list_link list_token ls) p)) (not (ptr_eq z nullval)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh z)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) p) z)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) z)) (lseg ls dsh psh l' y nullval))))) *)
Intros u.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh y) (@list_cell cs list_structid list_link list_token ls dsh h y)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) z) y)) (lseg ls dsh psh l x y)) (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh z) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) p) z)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) u) z)) (lseg ls dsh psh l' u nullval))) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val z (@fst val (@elemtype cs list_structid list_link list_token ls) p)) (not (ptr_eq z nullval)))) (@sepcon mpred Nveric Sveric (lseg ls dsh psh (@app (prod val (@elemtype cs list_structid list_link list_token ls)) l (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) y h) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) x z) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh z)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) p) z)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) z)) (lseg ls dsh psh l' y nullval))))) *)
Exists u.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
rewrite !prop_true_andp by auto.
rewrite <- !sepcon_assoc.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
apply sepcon_derives; auto.
pull_right (list_cell ls sh e z).
pull_right (list_token sh z).
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
apply sepcon_derives; auto.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
apply sepcon_derives; auto.
apply lseg_cons_right_neq.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
auto.
Qed.

Lemma lseg_unroll_right (ls: listspec list_structid list_link list_token): forall sh l x z ,
    lseg ls sh l x z = (!! (ptr_eq x z) && !! (l=nil) && emp) || lseg_cons_right ls sh l x z.
Abort.  (* not likely true *)

Lemma lseg_local_facts:
  forall ls sh contents p q,
     lseg ls sh contents p q |--
     !! (is_pointer_or_null p /\ (p=q <-> contents=nil)).
Proof.
(* Goal: forall (v' : @elemtype cs list_structid list_link list_token ls) (ash bsh psh : share) (p : val) (v : @elemtype cs list_structid list_link list_token ls) (_ : @sepalg.join share Share.Join_ba ash bsh psh) (_ : not (readable_share ash)) (_ : readable_share bsh), @eq mpred (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls ash v' p) (@list_cell cs list_structid list_link list_token ls bsh v p)) (@list_cell cs list_structid list_link list_token ls psh v p) *)
intros.
unfold lseg.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
normalize.
eapply derives_trans; [apply LsegGeneral.lseg_local_facts |].
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
normalize.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
split; auto.
(* Goal: and (if Archi.ptr64 then @eq Int64.int (Int64.repr Z0) Int64.zero else False) (iff (@eq val (Vlong (Int64.repr Z0)) (Vlong (Int64.repr Z0))) (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) *)
(* Goal: and True (iff (@eq val (Vptr b i) q) (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) *)
(* Goal: @derives mpred Nveric (let (p0, h) := p0 in @andp mpred Nveric (@prop mpred Nveric (and (@eq val p0 p) (not (ptr_eq p q)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh p)) (@list_cell cs list_structid list_link list_token ls dsh h p)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) p)) (lseg ls dsh psh contents tail q)))) (@prop mpred Nveric (and (is_pointer_or_null p) (iff (@eq val p q) (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) p0 contents) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))))) *)
rewrite H.
clear.
(* Goal: @derives mpred Nveric (@emp mpred Nveric Sveric) (lseg_cons ls dsh psh s v v2) *)
(* Goal: @derives mpred Nveric (lseg_cons ls dsh psh s v v2) (@orp mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq v v2)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) s (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh s v v2)) *)
destruct al; simpl; intuition; try congruence.
Qed.

Definition lseg_cell (ls: listspec list_structid list_link list_token)
    (sh : share)
    (v: elemtype ls) (x y: val) :=
   !!is_pointer_or_null y && list_token sh x * list_cell ls sh v x * field_at sh list_struct (StructField list_link :: nil) (valinject (nested_field_type list_struct (StructField list_link :: nil)) y) x.

Lemma lseg_cons_eq2: forall
  (ls : listspec list_structid list_link list_token) (sh : share) (h : elemtype ls)
   (r : list (elemtype ls))
  (x z : val), lseg ls sh (h :: r) x z =
  !!(~ ptr_eq x z) && (EX  y : val, lseg_cell ls sh h x y * lseg ls sh r y z).
Proof.
(* Goal: forall (v' : @elemtype cs list_structid list_link list_token ls) (ash bsh psh : share) (p : val) (v : @elemtype cs list_structid list_link list_token ls) (_ : @sepalg.join share Share.Join_ba ash bsh psh) (_ : not (readable_share ash)) (_ : readable_share bsh), @eq mpred (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls ash v' p) (@list_cell cs list_structid list_link list_token ls bsh v p)) (@list_cell cs list_structid list_link list_token ls psh v p) *)
  intros.
  rewrite -> lseg_cons_eq.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (lseg_cell ls dsh psh x nullval tl') (@emp mpred Nveric Sveric)) (@FF mpred Nveric) *)
  unfold lseg_cell.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
 normalize.
Qed.

Lemma list_append: forall {sh: share}
  {ls : listspec list_structid list_link list_token} (hd mid tl:val) ct1 ct2 P,
  (forall x tl', lseg_cell ls sh x tl tl' * P tl |-- FF) ->
  (lseg ls sh ct1 hd mid) * lseg ls sh ct2 mid tl * P tl|--
  (lseg ls sh (ct1 ++ ct2) hd tl) * P tl.
Proof.
(* Goal: forall (v' : @elemtype cs list_structid list_link list_token ls) (ash bsh psh : share) (p : val) (v : @elemtype cs list_structid list_link list_token ls) (_ : @sepalg.join share Share.Join_ba ash bsh psh) (_ : not (readable_share ash)) (_ : readable_share bsh), @eq mpred (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls ash v' p) (@list_cell cs list_structid list_link list_token ls bsh v p)) (@list_cell cs list_structid list_link list_token ls psh v p) *)
  intros.
  unfold lseg.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
 normalize.
 eapply derives_trans.
 apply LsegGeneral.list_append.
(* Goal: forall (v' : @elemtype cs list_structid list_link list_token ls) (ash bsh psh : share) (p : val) (v : @elemtype cs list_structid list_link list_token ls) (_ : @sepalg.join share Share.Join_ba ash bsh psh) (_ : not (readable_share ash)) (_ : readable_share bsh), @eq mpred (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls ash v' p) (@list_cell cs list_structid list_link list_token ls bsh v p)) (@list_cell cs list_structid list_link list_token ls psh v p) *)
 intros.
 eapply derives_trans; [ | apply (H x0 tl')].
 unfold lseg_cell, LsegGeneral.lseg_cell.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh y) (@list_cell cs list_structid list_link list_token ls dsh h y)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) z) y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh el x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) x0) x)) (lseg ls dsh psh l x0 y)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) w) z)) (@andp mpred Nveric (@prop mpred Nveric (and (not (ptr_eq x z)) (is_pointer_or_null x0))) (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh x) (@list_cell cs list_structid list_link list_token ls dsh el x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) x0) x)) (lseg ls dsh psh (@app (prod val (@elemtype cs list_structid list_link list_token ls)) l (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) y h) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) x0 z)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) w) z))) *)
 entailer.
 apply exp_right with (x++al).
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
 rewrite prop_true_andp; auto.
(* Goal: @eq mpred (@struct_pred (@nil (prod ident type)) A F v p) (@struct_pred (@nil (prod ident type)) A F v p') *)
(* Goal: @eq mpred (@struct_pred (@cons (prod ident type) a m) A F v p) (@struct_pred (@cons (prod ident type) a m) A F v p') *)
 rewrite map_app; reflexivity.
Qed.

Lemma list_append_null:
  forall
   (ls: listspec list_structid list_link list_token)
   (sh: share)
   (hd mid: val) ct1 ct2,
   lseg ls sh ct1 hd mid * lseg ls sh ct2 mid nullval |--
   lseg ls sh (ct1++ct2) hd nullval.
Proof.
(* Goal: forall (v' : @elemtype cs list_structid list_link list_token ls) (ash bsh psh : share) (p : val) (v : @elemtype cs list_structid list_link list_token ls) (_ : @sepalg.join share Share.Join_ba ash bsh psh) (_ : not (readable_share ash)) (_ : readable_share bsh), @eq mpred (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls ash v' p) (@list_cell cs list_structid list_link list_token ls bsh v p)) (@list_cell cs list_structid list_link list_token ls psh v p) *)
intros.
 rewrite <- sepcon_emp.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (lseg ls dsh psh ct1 hd mid) (lseg ls dsh psh ct2 mid nullval)) (@sepcon mpred Nveric Sveric (lseg ls dsh psh (@app (prod val (@elemtype cs list_structid list_link list_token ls)) ct1 ct2) hd nullval) (@emp mpred Nveric Sveric)) *)
 eapply derives_trans; [ | apply (list_append hd mid nullval ct1 ct2 (fun _ => emp))].
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
 normalize.
(* Goal: forall (v' : @elemtype cs list_structid list_link list_token ls) (ash bsh psh : share) (p : val) (v : @elemtype cs list_structid list_link list_token ls) (_ : @sepalg.join share Share.Join_ba ash bsh psh) (_ : not (readable_share ash)) (_ : readable_share bsh), @eq mpred (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls ash v' p) (@list_cell cs list_structid list_link list_token ls bsh v p)) (@list_cell cs list_structid list_link list_token ls psh v p) *)
 intros.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tl')) (list_token dsh nullval)) (@list_cell cs list_structid list_link list_token ls dsh x nullval)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tl') nullval)) (@emp mpred Nveric Sveric)) (@FF mpred Nveric) *)
  unfold lseg_cell. simpl. saturate_local. destruct H. contradiction H.
Qed.

Lemma list_cell_valid_pointer:
  forall (LS: listspec list_structid list_link list_token) (sh: Share.t) v p,
   sepalg.nonidentity sh ->
   field_offset cenv_cs list_link list_fields + sizeof (field_type list_link list_fields)
   = field_offset_next cenv_cs list_link list_fields  (co_sizeof (get_co list_structid)) ->
   list_cell LS sh v p * field_at_ sh list_struct (StructField list_link::nil) p
  |-- valid_pointer p.
Proof.
(* Goal: forall (LS : @listspec cs list_structid list_link list_token) (sh : Share.t) (v : @elemtype cs list_structid list_link list_token LS) (p : val) (_ : @sepalg.nonidentity Share.t Share.Join_ba pa_share sh) (_ : @eq Z (Z.add (field_offset (@cenv_cs cs) list_link (@list_fields cs list_structid list_link list_token LS)) (@sizeof (@cenv_cs cs) (field_type list_link (@list_fields cs list_structid list_link list_token LS)))) (field_offset_next (@cenv_cs cs) list_link (@list_fields cs list_structid list_link list_token LS) (co_sizeof (@get_co cs list_structid)))), @derives mpred Nveric (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token LS sh v p) (@field_at_ cs sh (@list_struct cs list_structid list_link list_token LS) (@cons gfield (StructField list_link) (@nil gfield)) p)) (valid_pointer p) *)
  intros ? ? ? ? NON_ID ?.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
 rewrite list_cell_link_join_nospacer; auto.
(* Goal: @derives mpred Nveric (@data_at cs sh (@list_struct cs list_structid list_link list_token LS) (@list_data cs list_structid list_link list_token LS v) p) (valid_pointer p) *)
 unfold data_at_, field_at_, data_at.
(* Goal: @derives mpred Nveric (@field_at cs sh (@list_struct cs list_structid list_link list_token LS) (@nil gfield) (@list_data cs list_structid list_link list_token LS v) p) (valid_pointer p) *)
 eapply derives_trans; [ apply field_at_valid_ptr; auto | ].
(* Goal: Z.gt (@sizeof (@cenv_cs cs) (@nested_field_type cs (@list_struct cs list_structid list_link list_token LS) (@nil gfield))) Z0 *)
(* Goal: @derives mpred Nveric (valid_pointer (@field_address cs (@list_struct cs list_structid list_link list_token LS) (@nil gfield) p)) (valid_pointer p) *)
 change (nested_field_type list_struct nil) with list_struct.
(* Goal: Z.gt (@sizeof (@cenv_cs cs) (@list_struct cs list_structid list_link list_token LS)) Z0 *)
(* Goal: @derives mpred Nveric (valid_pointer (@field_address cs (@list_struct cs list_structid list_link list_token LS) (@nil gfield) p)) (valid_pointer p) *)
 apply LsegGeneral.sizeof_list_struct_pos.
(* Goal: @derives mpred Nveric (valid_pointer (@field_address cs (@list_struct cs list_structid list_link list_token LS) (@nil gfield) p)) (valid_pointer p) *)
 unfold field_address.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
 if_tac; auto.
(* Goal: @derives mpred Nveric (valid_pointer (offset_val (@nested_field_offset cs (@list_struct cs list_structid list_link list_token LS) (@nil gfield)) p)) (valid_pointer p) *)
(* Goal: @derives mpred Nveric (valid_pointer Vundef) (valid_pointer p) *)
 change (Int.repr (nested_field_offset list_struct nil)) with Int.zero.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
  rewrite valid_pointer_offset_val_zero; auto.
(* Goal: @derives mpred Nveric (valid_pointer Vundef) (valid_pointer p) *)
 simpl.
(* Goal: @derives mpred Nveric (@predicates_hered.FF compcert_rmaps.RML.R.rmap compcert_rmaps.RML.R.ag_rmap) (valid_pointer p) *)
 change predicates_hered.FF with FF. apply FF_left.
Qed.

Lemma lseg_valid_pointer:
  forall (ls : listspec list_structid list_link list_token) sh contents p q R,
   sepalg.nonidentity sh ->
   field_offset cenv_cs list_link list_fields + sizeof (field_type list_link list_fields)
   = field_offset_next cenv_cs list_link list_fields  (co_sizeof (get_co list_structid)) ->
    R |-- valid_pointer q ->
    R * lseg ls sh contents p q |-- valid_pointer p.
Proof.
intros ? ? ? ? ? ? NON_ID ? ?.
(* Goal: @derives mpred Nveric match contents with | nil => @andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric) | cons (pair p1 h as p0) t => @andp mpred Nveric (@prop mpred Nveric (and (@eq val p1 p) (not (ptr_eq p q)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh p)) (@list_cell cs list_structid list_link list_token ls dsh h p)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) p)) (lseg ls dsh psh t tail q))) end (@prop mpred Nveric (and (is_pointer_or_null p) (iff (@eq val p q) (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) contents (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))))) *)
destruct contents.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
rewrite lseg_nil_eq. normalize.
(* Goal: @derives mpred Nveric (valid_pointer Vundef) (valid_pointer p) *)
unfold lseg; simpl.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
normalize.
(* Goal: False *)
(* Goal: ptr_neq (Vptr b i) (if Archi.ptr64 then Vlong Int64.zero else Vint Int.zero) *)
destruct al; inv H1.
rewrite LsegGeneral.lseg_cons_eq.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
normalize.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh (@fst val (@elemtype cs list_structid list_link list_token ls) (@pair val (@elemtype cs list_structid list_link list_token ls) p h))) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) (@pair val (@elemtype cs list_structid list_link list_token ls) p h)) (@fst val (@elemtype cs list_structid list_link list_token ls) (@pair val (@elemtype cs list_structid list_link list_token ls) p h)))) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) (@fst val (@elemtype cs list_structid list_link list_token ls) (@pair val (@elemtype cs list_structid list_link list_token ls) p h)))) (lseg ls dsh psh r y z)) (@orp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (and (ptr_eq (@fst val (@elemtype cs list_structid list_link list_token ls) (@pair val (@elemtype cs list_structid list_link list_token ls) p h)) z) (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) p h) r) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) p h) r) (@fst val (@elemtype cs list_structid list_link list_token ls) (@pair val (@elemtype cs list_structid list_link list_token ls) p h)) z)) *)
destruct p0 as [p z]; simpl in *.
apply sepcon_valid_pointer2.
apply sepcon_valid_pointer1.
(* Goal: @derives mpred Nveric P (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh v1) (@list_cell cs list_structid list_link list_token ls dsh h v1)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) p) v1)) (lseg ls dsh psh tail p v2)) *)
rewrite sepcon_assoc.
apply sepcon_valid_pointer2.
eapply derives_trans; [ | eapply list_cell_valid_pointer; eauto].
apply sepcon_derives ; [ apply derives_refl | ].
cancel.
Qed.

End LIST.

Hint Rewrite @lseg_nil_eq : norm.
Hint Rewrite @lseg_eq using reflexivity: norm.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tl')) (list_token dsh nullval)) (@list_cell cs list_structid list_link list_token ls dsh x nullval)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tl') nullval)) (@emp mpred Nveric Sveric)) (@FF mpred Nveric) *)
Hint Resolve @lseg_local_facts : saturate_local.

Ltac resolve_lseg_valid_pointer :=
match goal with
 | |- ?Q |-- valid_pointer ?p =>
   match Q with context [lseg ?A ?B ?C p ?q] =>
   repeat rewrite <- sepcon_assoc;
   pull_right (lseg A B C p q);
   apply lseg_valid_pointer; [auto | reflexivity | ];
   auto 50 with valid_pointer
   end
 end.

Hint Extern 10 (_ |-- valid_pointer _) =>
   resolve_lseg_valid_pointer : valid_pointer.

Lemma list_cell_local_facts:
  forall {cs: compspecs} {list_structid list_link: ident}{list_token}
    (ls: listspec list_structid list_link list_token) sh v p,
   list_cell ls sh v p |-- !! field_compatible list_struct nil p.
Proof.
(* Goal: forall (v' : @elemtype cs list_structid list_link list_token ls) (ash bsh psh : share) (p : val) (v : @elemtype cs list_structid list_link list_token ls) (_ : @sepalg.join share Share.Join_ba ash bsh psh) (_ : not (readable_share ash)) (_ : readable_share bsh), @eq mpred (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls ash v' p) (@list_cell cs list_structid list_link list_token ls bsh v p)) (@list_cell cs list_structid list_link list_token ls psh v p) *)
intros.
(* Goal: @derives mpred Nveric (@list_cell cs list_structid list_link list_token0 ls sh v p) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
unfold list_cell.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
normalize.
Qed.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tl')) (list_token dsh nullval)) (@list_cell cs list_structid list_link list_token ls dsh x nullval)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tl') nullval)) (@emp mpred Nveric Sveric)) (@FF mpred Nveric) *)
Hint Resolve list_cell_local_facts : saturate_local.

End LsegSpecial.

Module Links.

Section LIST2.
Context {cs: compspecs}.
Context  {list_structid: ident} {list_link: ident}{list_token: share -> val -> mpred}.

Definition vund  (ls: listspec list_structid list_link list_token) : elemtype ls :=
 compact_prod_gen
      (fun it => default_val (field_type (fst it) list_fields)) (@all_but_link list_link  list_fields).

Definition lseg (ls: listspec list_structid list_link list_token) (dsh psh: share)
            (contents: list val) (x z: val) : mpred :=
  LsegGeneral.lseg ls dsh psh (map (fun v => (v, vund ls)) contents) x z.

Lemma nonreadable_list_cell_eq:
  forall (ls: listspec list_structid list_link list_token) sh v v' p,
    ~ readable_share sh ->
   list_cell ls sh v p = list_cell ls sh v' p.
Proof.
(* Goal: forall (v' : @elemtype cs list_structid list_link list_token ls) (ash bsh psh : share) (p : val) (v : @elemtype cs list_structid list_link list_token ls) (_ : @sepalg.join share Share.Join_ba ash bsh psh) (_ : not (readable_share ash)) (_ : readable_share bsh), @eq mpred (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls ash v' p) (@list_cell cs list_structid list_link list_token ls bsh v p)) (@list_cell cs list_structid list_link list_token ls psh v p) *)
unfold list_cell; intros.
 destruct (field_compatible_dec list_struct nil p);
    [ | solve [ apply pred_ext; normalize ]].
(* Goal: @eq mpred (@prop mpred Nveric (ptr_eq v v)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) *)
(* Goal: @eq mpred (let (p, h) := p in @andp mpred Nveric (@prop mpred Nveric (and (@eq val p v) (not (ptr_eq v v)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh v)) (@list_cell cs list_structid list_link list_token ls dsh h v)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) v)) (lseg ls dsh psh l tail v)))) (@andp mpred Nveric (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) p l) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) (@emp mpred Nveric Sveric)) *)
 f_equal.
 revert v v'; unfold elemtype.
(* Goal: forall (v' : @elemtype cs list_structid list_link list_token ls) (ash bsh psh : share) (p : val) (v : @elemtype cs list_structid list_link list_token ls) (_ : @sepalg.join share Share.Join_ba ash bsh psh) (_ : not (readable_share ash)) (_ : readable_share bsh), @eq mpred (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls ash v' p) (@list_cell cs list_structid list_link list_token ls bsh v p)) (@list_cell cs list_structid list_link list_token ls psh v p) *)
 induction (all_but_link list_fields); intros.
(* Goal: @eq mpred (@struct_pred (@nil (prod ident type)) A F v p) (@struct_pred (@nil (prod ident type)) A F v p') *)
(* Goal: @eq mpred (@struct_pred (@cons (prod ident type) a m) A F v p) (@struct_pred (@cons (prod ident type) a m) A F v p') *)
 reflexivity.
 destruct a as [i t].
 assert (field_compatible (field_type i list_fields) nil
  (offset_val (field_offset cenv_cs i list_fields) p))
    by  admit.  (* need to adjust the induction hypothesis to prove this *)
 destruct m as [ | [i' t']].
 + Opaque field_type field_offset.
(* Goal: @derives mpred Nveric (valid_pointer Vundef) (valid_pointer p) *)
 clear IHm; simpl.
 Transparent field_type field_offset.
 rewrite !withspacer_spacer.
(* Goal: @eq mpred (@prop mpred Nveric (ptr_eq v v)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) *)
(* Goal: @eq mpred (let (p, h) := p in @andp mpred Nveric (@prop mpred Nveric (and (@eq val p v) (not (ptr_eq v v)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh v)) (@list_cell cs list_structid list_link list_token ls dsh h v)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) v)) (lseg ls dsh psh l tail v)))) (@andp mpred Nveric (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) p l) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) (@emp mpred Nveric Sveric)) *)
 f_equal.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
 admit. (* apply nonreadable_data_at_rec_eq; auto. *) (* list_cell should be defined by field_at instead of data_at_rec. *)
 +
(* Goal: @eq mpred (@struct_pred (@cons (prod ident type) a (@cons (prod ident type) p0 m)) A F v p) (@struct_pred (@cons (prod ident type) a (@cons (prod ident type) p0 m)) A F v p') *)
 rewrite !struct_pred_cons2.
 rewrite !withspacer_spacer.
(* Goal: @eq mpred (@prop mpred Nveric (ptr_eq v v)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) *)
(* Goal: @eq mpred (let (p, h) := p in @andp mpred Nveric (@prop mpred Nveric (and (@eq val p v) (not (ptr_eq v v)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh v)) (@list_cell cs list_structid list_link list_token ls dsh h v)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) v)) (lseg ls dsh psh l tail v)))) (@andp mpred Nveric (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) p l) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) (@emp mpred Nveric Sveric)) *)
 f_equal. f_equal.

 - admit. (* unfold at_offset. apply nonreadable_data_at_rec_eq; auto.*)
 - apply IHm.
Admitted.

Lemma cell_share_join:
  forall (ls: listspec list_structid list_link list_token) ash bsh psh p v,
   sepalg.join ash bsh psh ->
   list_cell ls ash v p * list_cell ls bsh v p = list_cell ls psh v p.
Proof.
(* Goal: forall (v' : @elemtype cs list_structid list_link list_token ls) (ash bsh psh : share) (p : val) (v : @elemtype cs list_structid list_link list_token ls) (_ : @sepalg.join share Share.Join_ba ash bsh psh) (_ : not (readable_share ash)) (_ : readable_share bsh), @eq mpred (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls ash v' p) (@list_cell cs list_structid list_link list_token ls bsh v p)) (@list_cell cs list_structid list_link list_token ls psh v p) *)
 intros.
(* Goal: @derives mpred Nveric (@list_cell cs list_structid list_link list_token0 ls sh v p) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
 unfold list_cell.
 destruct (field_compatible_dec list_struct nil p);
    [ | solve [ apply pred_ext; normalize ]].
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
 normalize.
(* Goal: @eq mpred (@prop mpred Nveric (ptr_eq v v)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) *)
(* Goal: @eq mpred (let (p, h) := p in @andp mpred Nveric (@prop mpred Nveric (and (@eq val p v) (not (ptr_eq v v)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh v)) (@list_cell cs list_structid list_link list_token ls dsh h v)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) v)) (lseg ls dsh psh l tail v)))) (@andp mpred Nveric (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) p l) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) (@emp mpred Nveric Sveric)) *)
 f_equal.
 revert v; unfold elemtype.
(* Goal: forall (v' : @elemtype cs list_structid list_link list_token ls) (ash bsh psh : share) (p : val) (v : @elemtype cs list_structid list_link list_token ls) (_ : @sepalg.join share Share.Join_ba ash bsh psh) (_ : not (readable_share ash)) (_ : readable_share bsh), @eq mpred (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls ash v' p) (@list_cell cs list_structid list_link list_token ls bsh v p)) (@list_cell cs list_structid list_link list_token ls psh v p) *)
 induction (all_but_link list_fields); intros.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
 simpl. rewrite emp_sepcon; auto.
 destruct a as [i t].
 assert (field_compatible (field_type i list_fields) nil
  (offset_val (field_offset cenv_cs i list_fields) p))
    by  admit.  (* need to adjust the induction hypothesis to prove this *)
 destruct m as [ | [i' t']].
 +
(* Goal: @derives mpred Nveric (valid_pointer Vundef) (valid_pointer p) *)
 clear IHm; simpl. rewrite !withspacer_spacer.
 rewrite <- sepcon_assoc.
 match goal with |- ?A * ?B * ?C * ?D = _ =>
    pull_left C; pull_left A
 end.
(* Goal: @eq mpred (@prop mpred Nveric (ptr_eq v v)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) *)
(* Goal: @eq mpred (let (p, h) := p in @andp mpred Nveric (@prop mpred Nveric (and (@eq val p v) (not (ptr_eq v v)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh v)) (@list_cell cs list_structid list_link list_token ls dsh h v)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) v)) (lseg ls dsh psh l tail v)))) (@andp mpred Nveric (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) p l) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) (@emp mpred Nveric Sveric)) *)
 rewrite sepcon_assoc. f_equal.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
 unfold spacer. if_tac. rewrite emp_sepcon; auto.
 unfold at_offset.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
 apply memory_block_share_join; auto.
 unfold at_offset.
 assert (isptr p) by (auto with field_compatible).
 destruct p; try inversion H1.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
 apply data_at_rec_share_join; auto.
 +
(* Goal: @eq mpred (@struct_pred (@cons (prod ident type) a (@cons (prod ident type) p0 m)) A F v p) (@struct_pred (@cons (prod ident type) a (@cons (prod ident type) p0 m)) A F v p') *)
 rewrite !struct_pred_cons2.
 rewrite !withspacer_spacer.
 match goal with |- (?A * ?B * ?C) * (?A' * ?B' * ?C') = _ =>
   transitivity ((A * A') * (B * B') * (C * C'))
 end.
 rewrite <- ! sepcon_assoc.
 repeat match goal with |- _ * ?A = _ => pull_right A; f_equal end.
(* Goal: @eq mpred (@prop mpred Nveric (ptr_eq v v)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) *)
(* Goal: @eq mpred (let (p, h) := p in @andp mpred Nveric (@prop mpred Nveric (and (@eq val p v) (not (ptr_eq v v)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh v)) (@list_cell cs list_structid list_link list_token ls dsh h v)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) v)) (lseg ls dsh psh l tail v)))) (@andp mpred Nveric (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) p l) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) (@emp mpred Nveric Sveric)) *)
 f_equal. f_equal.
(* Goal: @eq mpred (@sepcon mpred Nveric Sveric (list_cell LS sh v p) (@field_at_ cs sh (@list_struct cs list_structid list_link list_token LS) (@cons gfield (StructField list_link) (@nil gfield)) p)) (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_cell LS sh v p) (spacer sh (Z.add (field_offset (@cenv_cs cs) list_link (@list_fields cs list_structid list_link list_token LS)) (@sizeof (@cenv_cs cs) (field_type list_link (@list_fields cs list_structid list_link list_token LS)))) (field_offset_next (@cenv_cs cs) list_link (@list_fields cs list_structid list_link list_token LS) (co_sizeof (@get_co cs list_structid))) (offset_val Z0 p))) (@field_at_ cs sh (@list_struct cs list_structid list_link list_token LS) (@cons gfield (StructField list_link) (@nil gfield)) p)) *)
 unfold spacer. if_tac. apply sepcon_emp.
 unfold at_offset.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
 apply memory_block_share_join; auto.
 unfold at_offset.
 assert (isptr p) by (auto with field_compatible).
 destruct p; try inversion H1.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
 apply data_at_rec_share_join; auto.
(* Goal: @eq mpred (@struct_pred (@cons (prod ident type) p0 m) A F (@snd (A a) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m with | nil => A p0 | cons T l => prod (A p0) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => prod t (compact_prod T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m)) end v) p) (@struct_pred (@cons (prod ident type) p0 m) A F (@snd (A a) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m with | nil => A p0 | cons T l => prod (A p0) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => prod t (compact_prod T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m)) end v) p') *)
 apply IHm.
Admitted.

Lemma join_cell_link (ls: listspec list_structid list_link list_token):
  forall v' ash bsh psh p v,
   sepalg.join ash bsh psh ->
  ~ (readable_share ash) ->
    readable_share bsh ->
   list_cell ls ash v' p * list_cell ls bsh v p = list_cell ls psh v p.
 Proof.
(* Goal: forall (v' : @elemtype cs list_structid list_link list_token ls) (ash bsh psh : share) (p : val) (v : @elemtype cs list_structid list_link list_token ls) (_ : @sepalg.join share Share.Join_ba ash bsh psh) (_ : not (readable_share ash)) (_ : readable_share bsh), @eq mpred (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls ash v' p) (@list_cell cs list_structid list_link list_token ls bsh v p)) (@list_cell cs list_structid list_link list_token ls psh v p) *)
 intros.
(* Goal: @eq mpred (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls ash v' p) (@list_cell cs list_structid list_link list_token ls bsh v p)) (@list_cell cs list_structid list_link list_token ls psh v p) *)
 rewrite (nonreadable_list_cell_eq _ _ v' v _ H0).
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
 apply cell_share_join; auto.
Qed.

Lemma lseg_unfold (ls: listspec list_structid list_link list_token): forall dsh psh contents v1 v2,
    lseg ls dsh psh contents v1 v2 =
     match contents with
     | p::t => !! (p=v1 /\ ~ ptr_eq v1 v2) && EX tail: val,
                      !! is_pointer_or_null tail &&
                      list_token dsh v1 * list_cell ls dsh (vund ls) v1
                      * field_at psh list_struct (StructField list_link :: nil)
                          (valinject (nested_field_type list_struct (StructField list_link :: nil)) tail) v1
                      * lseg ls dsh psh t tail v2
     | nil => !! (ptr_eq v1 v2) && emp
     end.
Proof.
(* Goal: forall (v' : @elemtype cs list_structid list_link list_token ls) (ash bsh psh : share) (p : val) (v : @elemtype cs list_structid list_link list_token ls) (_ : @sepalg.join share Share.Join_ba ash bsh psh) (_ : not (readable_share ash)) (_ : readable_share bsh), @eq mpred (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls ash v' p) (@list_cell cs list_structid list_link list_token ls bsh v p)) (@list_cell cs list_structid list_link list_token ls psh v p) *)
 intros.
 unfold lseg.
 rewrite LsegGeneral.lseg_unfold.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
 revert v1; induction contents; simpl; intros; auto.
Qed.

Lemma lseg_eq (ls: listspec list_structid list_link list_token):
  forall dsh psh l v ,
  is_pointer_or_null v ->
    lseg ls dsh psh l v v = !!(l=nil) && emp.
Proof.
(* Goal: forall (v' : @elemtype cs list_structid list_link list_token ls) (ash bsh psh : share) (p : val) (v : @elemtype cs list_structid list_link list_token ls) (_ : @sepalg.join share Share.Join_ba ash bsh psh) (_ : not (readable_share ash)) (_ : readable_share bsh), @eq mpred (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls ash v' p) (@list_cell cs list_structid list_link list_token ls bsh v p)) (@list_cell cs list_structid list_link list_token ls psh v p) *)
intros.
(* Goal: @eq mpred (lseg ls dsh psh l v v) (@andp mpred Nveric (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) l (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) (@emp mpred Nveric Sveric)) *)
rewrite (lseg_unfold ls dsh psh l v v).
(* Goal: @eq mpred match l with | nil => @andp mpred Nveric (@prop mpred Nveric (ptr_eq v v)) (@emp mpred Nveric Sveric) | cons (pair p h as p0) t => @andp mpred Nveric (@prop mpred Nveric (and (@eq val p v) (not (ptr_eq v v)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh v)) (@list_cell cs list_structid list_link list_token ls dsh h v)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) v)) (lseg ls dsh psh t tail v))) end (@andp mpred Nveric (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) l (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) (@emp mpred Nveric Sveric)) *)
destruct l.
(* Goal: @eq mpred (@prop mpred Nveric (ptr_eq v v)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) *)
(* Goal: @eq mpred (let (p, h) := p in @andp mpred Nveric (@prop mpred Nveric (and (@eq val p v) (not (ptr_eq v v)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh v)) (@list_cell cs list_structid list_link list_token ls dsh h v)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) v)) (lseg ls dsh psh l tail v)))) (@andp mpred Nveric (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) p l) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) (@emp mpred Nveric Sveric)) *)
f_equal. f_equal.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
apply prop_ext; split; intro; auto.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
normalize.
apply pred_ext;
(* Goal: ptr_neq (Vptr b i) (if Archi.ptr64 then Vlong Int64.zero else Vint Int.zero) *)
apply derives_extract_prop; intro.
(* Goal: @derives mpred Nveric (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh v)) (@list_cell cs list_structid list_link list_token ls dsh e v)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) v)) (lseg ls dsh psh l tail v))) (@andp mpred Nveric (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) v0 e) l) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) (@emp mpred Nveric Sveric)) *)
(* Goal: @derives mpred Nveric (@emp mpred Nveric Sveric) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val v0 v) (not (ptr_eq v v)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh v)) (@list_cell cs list_structid list_link list_token ls dsh e v)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) v)) (lseg ls dsh psh l tail v)))) *)
destruct H0.
(* Goal: @derives mpred Nveric (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh v)) (@list_cell cs list_structid list_link list_token ls dsh e v)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) v)) (lseg ls dsh psh l tail v))) (@andp mpred Nveric (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) v0 e) l) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) (@emp mpred Nveric Sveric)) *)
(* Goal: @derives mpred Nveric (@emp mpred Nveric Sveric) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val v0 v) (not (ptr_eq v v)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh v)) (@list_cell cs list_structid list_link list_token ls dsh e v)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) v)) (lseg ls dsh psh l tail v)))) *)
contradiction H1.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
destruct v; inv H; try split; auto.
unfold Ptrofs.cmpu. apply Ptrofs.eq_true.
(* Goal: @derives mpred Nveric (@emp mpred Nveric Sveric) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) *)
(* Goal: @derives mpred Nveric (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) x z) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) *)
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) (@orp mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) x z)) *)
inv H0.
Qed.

Definition lseg_cons (ls: listspec list_structid list_link list_token) dsh psh
           (l: list val) (x z: val) : mpred :=
        !! (~ ptr_eq x z) &&
       EX h:(elemtype ls), EX r:list val, EX y:val,
             !!(l=x::r  /\ is_pointer_or_null y) &&
             list_token dsh x * list_cell ls dsh h x *
             field_at psh list_struct (StructField list_link :: nil) (valinject (nested_field_type list_struct (StructField list_link :: nil)) y) x *
             lseg ls dsh psh r y z.

Lemma lseg_unroll (ls: listspec list_structid list_link list_token): forall dsh psh l x z ,
    ~ (readable_share dsh) ->
    lseg ls dsh psh l x z =
      (!! (ptr_eq x z) && !! (l=nil) && emp) || lseg_cons ls dsh psh l x z.
Proof.
(* Goal: forall (v' : @elemtype cs list_structid list_link list_token ls) (ash bsh psh : share) (p : val) (v : @elemtype cs list_structid list_link list_token ls) (_ : @sepalg.join share Share.Join_ba ash bsh psh) (_ : not (readable_share ash)) (_ : readable_share bsh), @eq mpred (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls ash v' p) (@list_cell cs list_structid list_link list_token ls bsh v p)) (@list_cell cs list_structid list_link list_token ls psh v p) *)
intros.
rename H into NR.
(* Goal: @eq mpred (lseg ls dsh psh l x z) (@orp mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) l (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh l x z)) *)
rewrite lseg_unfold at 1.
(* Goal: @eq mpred match l with | nil => @andp mpred Nveric (@prop mpred Nveric (ptr_eq v v)) (@emp mpred Nveric Sveric) | cons (pair p h as p0) t => @andp mpred Nveric (@prop mpred Nveric (and (@eq val p v) (not (ptr_eq v v)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh v)) (@list_cell cs list_structid list_link list_token ls dsh h v)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) v)) (lseg ls dsh psh t tail v))) end (@andp mpred Nveric (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) l (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) (@emp mpred Nveric Sveric)) *)
apply pred_ext; destruct l.
(* Goal: forall (v' : @elemtype cs list_structid list_link list_token ls) (ash bsh psh : share) (p : val) (v : @elemtype cs list_structid list_link list_token ls) (_ : @sepalg.join share Share.Join_ba ash bsh psh) (_ : not (readable_share ash)) (_ : readable_share bsh), @eq mpred (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls ash v' p) (@list_cell cs list_structid list_link list_token ls bsh v p)) (@list_cell cs list_structid list_link list_token ls psh v p) *)
apply derives_extract_prop; intros.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
rewrite prop_true_andp by auto.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
rewrite prop_true_andp by auto.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
apply orp_right1; auto.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh p) (@list_cell cs list_structid list_link list_token ls dsh h p)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) p)) (lseg ls dsh psh r y z)) (@orp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (and (ptr_eq p z) (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) p h) r) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) p h) r) p z)) *)
apply orp_right2.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh p) (@list_cell cs list_structid list_link list_token ls dsh h p)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) p)) (lseg ls dsh psh r y z)) (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) p h) r) p z) *)
unfold lseg_cons.
(* Goal: forall (v' : @elemtype cs list_structid list_link list_token ls) (ash bsh psh : share) (p : val) (v : @elemtype cs list_structid list_link list_token ls) (_ : @sepalg.join share Share.Join_ba ash bsh psh) (_ : not (readable_share ash)) (_ : readable_share bsh), @eq mpred (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls ash v' p) (@list_cell cs list_structid list_link list_token ls bsh v p)) (@list_cell cs list_structid list_link list_token ls psh v p) *)
apply derives_extract_prop; intros.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tl')) (list_token dsh nullval)) (@list_cell cs list_structid list_link list_token ls dsh x nullval)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tl') nullval)) (@emp mpred Nveric Sveric)) (@FF mpred Nveric) *)
destruct H.
subst x.
(* Goal: @derives mpred Nveric (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh e x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) x)) (lseg ls dsh psh l tail z))) (@andp mpred Nveric (@prop mpred Nveric (not (ptr_eq x z))) (@exp mpred Nveric (@elemtype cs list_structid list_link list_token ls) (fun h : @elemtype cs list_structid list_link list_token ls => @exp mpred Nveric (list (prod val (@elemtype cs list_structid list_link list_token ls))) (fun r : list (prod val (@elemtype cs list_structid list_link list_token ls)) => @exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) v e) l) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) x h) r)) (is_pointer_or_null y))) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh h x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))))) *)
(* Goal: @derives mpred Nveric (@orp mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) x z)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@emp mpred Nveric Sveric)) *)
(* Goal: @derives mpred Nveric (@orp mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) p l) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) p l) x z)) (let (p, h) := p in @andp mpred Nveric (@prop mpred Nveric (and (@eq val p x) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh h x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) x)) (lseg ls dsh psh l tail z)))) *)
apply exp_left; intro tail.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
rewrite (prop_true_andp (~ptr_eq v z)) by auto.
apply exp_right with (vund ls).
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh x) (@list_cell cs list_structid list_link list_token ls dsh e x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) x)) (lseg ls dsh psh l tail z)) (@exp mpred Nveric (list (prod val (@elemtype cs list_structid list_link list_token ls))) (fun r : list (prod val (@elemtype cs list_structid list_link list_token ls)) => @exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) v e) l) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) x e) r)) (is_pointer_or_null y))) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh e x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) *)
(* Goal: @derives mpred Nveric (@orp mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) x z)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@emp mpred Nveric Sveric)) *)
(* Goal: @derives mpred Nveric (@orp mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) p l) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) p l) x z)) (let (p, h) := p in @andp mpred Nveric (@prop mpred Nveric (and (@eq val p x) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh h x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) x)) (lseg ls dsh psh l tail z)))) *)
apply exp_right with l.
(* Goal: @derives mpred Nveric P (@exp mpred Nveric (list (prod val (@elemtype cs list_structid list_link list_token ls))) (fun r : list (prod val (@elemtype cs list_structid list_link list_token ls)) => @exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) v1 h) tail) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) v1 h) r)) (is_pointer_or_null y))) (list_token dsh v1)) (@list_cell cs list_structid list_link list_token ls dsh h v1)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) v1)) (lseg ls dsh psh r y v2)))) *)
apply exp_right with tail.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
normalize.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
  autorewrite with subst norm1 norm2; normalize.
(* Goal: @derives mpred Nveric (@orp mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) x z)) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) *)
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) (@orp mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) x z)) *)
apply orp_left.
rewrite andp_assoc;
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq v v2)) (@andp mpred Nveric (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) s (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) (@emp mpred Nveric Sveric))) (lseg_cons ls dsh psh s v v2) *)
(* Goal: @derives mpred Nveric (lseg_cons ls dsh psh s v v2) (@orp mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq v v2)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) s (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh s v v2)) *)
do 2 (apply derives_extract_prop; intro).
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
 rewrite prop_true_andp by auto. auto.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh p) (@list_cell cs list_structid list_link list_token ls dsh h p)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) p)) (lseg ls dsh psh r y z)) (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) p h) r) p z) *)
unfold lseg_cons.
(* Goal: forall (v' : @elemtype cs list_structid list_link list_token ls) (ash bsh psh : share) (p : val) (v : @elemtype cs list_structid list_link list_token ls) (_ : @sepalg.join share Share.Join_ba ash bsh psh) (_ : not (readable_share ash)) (_ : readable_share bsh), @eq mpred (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls ash v' p) (@list_cell cs list_structid list_link list_token ls bsh v p)) (@list_cell cs list_structid list_link list_token ls psh v p) *)
apply derives_extract_prop; intros.
(* Goal: @derives mpred Nveric (@exp mpred Nveric (@elemtype cs list_structid list_link list_token ls) (fun h : @elemtype cs list_structid list_link list_token ls => @exp mpred Nveric (list (prod val (@elemtype cs list_structid list_link list_token ls))) (fun r : list (prod val (@elemtype cs list_structid list_link list_token ls)) => @exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) v e) l) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) x h) r)) (is_pointer_or_null y))) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh h x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z))))) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val v x) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh e x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) x)) (lseg ls dsh psh l tail z)))) *)
apply exp_left; intro h.
(* Goal: @derives mpred Nveric (@exp mpred Nveric (list (prod val (@elemtype cs list_structid list_link list_token ls))) (fun r : list (prod val (@elemtype cs list_structid list_link list_token ls)) => @exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) v e) l) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) x h) r)) (is_pointer_or_null y))) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh h x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val v x) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh e x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) x)) (lseg ls dsh psh l tail z)))) *)
apply exp_left; intro r.
(* Goal: @derives mpred Nveric (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) v e) l) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) x h) r)) (is_pointer_or_null y))) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh h x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z))) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val v x) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh e x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) x)) (lseg ls dsh psh l tail z)))) *)
apply exp_left; intro y.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) v e) l) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) x h) r)) (is_pointer_or_null y))) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh h x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val v x) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh e x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) x)) (lseg ls dsh psh l tail z)))) *)
do 3 rewrite sepcon_andp_prop'.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) s (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) v h) r)) (is_pointer_or_null y))) (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh v) (@list_cell cs list_structid list_link list_token ls dsh h v)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) v)) (lseg ls dsh psh r y v2)) (fold_right_sepcon R))) (@exp mpred Nveric (prod (prod (prod (@elemtype cs list_structid list_link list_token ls) (list (prod val (@elemtype cs list_structid list_link list_token ls)))) val) val) (fun x : prod (prod (prod (@elemtype cs list_structid list_link list_token ls) (list (prod val (@elemtype cs list_structid list_link list_token ls)))) val) val => (let (p0, p) := x in let (p1, y) := p0 in let (h, r) := p1 in fun x0 : environ => @andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) s (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) p h) r)) (is_pointer_or_null y))) (@prop mpred Nveric (@eq val p v))) (@andp mpred Nveric (@prop mpred Nveric (@fold_right Prop Prop and True P)) (@andp mpred Nveric (@prop mpred Nveric (@fold_right (forall _ : environ, Prop) (forall _ : environ, Prop) (fun (x1 x2 : forall _ : environ, Prop) (x3 : environ) => and (x1 x3) (x2 x3)) (fun _ : environ => True) (@map localdef (forall _ : environ, Prop) locald_denote Q) x0)) (@sepcon mpred Nveric Sveric (list_token dsh v) (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls dsh h v) (@sepcon mpred Nveric Sveric (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) v) (@sepcon mpred Nveric Sveric (lseg ls dsh psh r y v2) (fold_right_sepcon R)))))))) rho)) *)
apply derives_extract_prop; intros [? ?].
(* Goal: @derives mpred Nveric (@emp mpred Nveric Sveric) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) *)
(* Goal: @derives mpred Nveric (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) x z) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) *)
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) (@orp mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) x z)) *)
inv H0.
(* Goal: @derives mpred Nveric (@orp mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) x z)) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) *)
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) (@orp mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) x z)) *)
apply orp_left.
rewrite andp_assoc;
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq v v2)) (@andp mpred Nveric (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) s (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) (@emp mpred Nveric Sveric))) (lseg_cons ls dsh psh s v v2) *)
(* Goal: @derives mpred Nveric (lseg_cons ls dsh psh s v v2) (@orp mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq v v2)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) s (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh s v v2)) *)
do 2 (apply derives_extract_prop; intro).
(* Goal: @derives mpred Nveric (@emp mpred Nveric Sveric) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) *)
(* Goal: @derives mpred Nveric (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) x z) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) *)
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) (@orp mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) x z)) *)
inv H0.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh p) (@list_cell cs list_structid list_link list_token ls dsh h p)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) p)) (lseg ls dsh psh r y z)) (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) p h) r) p z) *)
unfold lseg_cons.
(* Goal: forall (v' : @elemtype cs list_structid list_link list_token ls) (ash bsh psh : share) (p : val) (v : @elemtype cs list_structid list_link list_token ls) (_ : @sepalg.join share Share.Join_ba ash bsh psh) (_ : not (readable_share ash)) (_ : readable_share bsh), @eq mpred (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls ash v' p) (@list_cell cs list_structid list_link list_token ls bsh v p)) (@list_cell cs list_structid list_link list_token ls psh v p) *)
apply derives_extract_prop; intros.
(* Goal: @derives mpred Nveric (@exp mpred Nveric (@elemtype cs list_structid list_link list_token ls) (fun h : @elemtype cs list_structid list_link list_token ls => @exp mpred Nveric (list (prod val (@elemtype cs list_structid list_link list_token ls))) (fun r : list (prod val (@elemtype cs list_structid list_link list_token ls)) => @exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) v e) l) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) x h) r)) (is_pointer_or_null y))) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh h x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z))))) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val v x) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh e x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) x)) (lseg ls dsh psh l tail z)))) *)
apply exp_left; intro h.
(* Goal: @derives mpred Nveric (@exp mpred Nveric (list (prod val (@elemtype cs list_structid list_link list_token ls))) (fun r : list (prod val (@elemtype cs list_structid list_link list_token ls)) => @exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) v e) l) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) x h) r)) (is_pointer_or_null y))) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh h x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val v x) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh e x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) x)) (lseg ls dsh psh l tail z)))) *)
apply exp_left; intro r.
(* Goal: @derives mpred Nveric (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) v e) l) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) x h) r)) (is_pointer_or_null y))) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh h x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z))) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val v x) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh e x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) x)) (lseg ls dsh psh l tail z)))) *)
apply exp_left; intro y.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) v e) l) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) x h) r)) (is_pointer_or_null y))) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh h x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val v x) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh e x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) x)) (lseg ls dsh psh l tail z)))) *)
do 3 rewrite sepcon_andp_prop'.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) s (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) v h) r)) (is_pointer_or_null y))) (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh v) (@list_cell cs list_structid list_link list_token ls dsh h v)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) v)) (lseg ls dsh psh r y v2)) (fold_right_sepcon R))) (@exp mpred Nveric (prod (prod (prod (@elemtype cs list_structid list_link list_token ls) (list (prod val (@elemtype cs list_structid list_link list_token ls)))) val) val) (fun x : prod (prod (prod (@elemtype cs list_structid list_link list_token ls) (list (prod val (@elemtype cs list_structid list_link list_token ls)))) val) val => (let (p0, p) := x in let (p1, y) := p0 in let (h, r) := p1 in fun x0 : environ => @andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) s (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) p h) r)) (is_pointer_or_null y))) (@prop mpred Nveric (@eq val p v))) (@andp mpred Nveric (@prop mpred Nveric (@fold_right Prop Prop and True P)) (@andp mpred Nveric (@prop mpred Nveric (@fold_right (forall _ : environ, Prop) (forall _ : environ, Prop) (fun (x1 x2 : forall _ : environ, Prop) (x3 : environ) => and (x1 x3) (x2 x3)) (fun _ : environ => True) (@map localdef (forall _ : environ, Prop) locald_denote Q) x0)) (@sepcon mpred Nveric Sveric (list_token dsh v) (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls dsh h v) (@sepcon mpred Nveric Sveric (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) v) (@sepcon mpred Nveric Sveric (lseg ls dsh psh r y v2) (fold_right_sepcon R)))))))) rho)) *)
apply derives_extract_prop; intros [? ?].
(* Goal: @derives mpred Nveric (@emp mpred Nveric Sveric) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) *)
(* Goal: @derives mpred Nveric (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) x z) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) *)
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) (@orp mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) x z)) *)
symmetry in H0; inv H0.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
 rewrite prop_true_andp by auto.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh p) (@list_cell cs list_structid list_link list_token ls dsh h p)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) p)) (lseg ls dsh psh r y z)) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) p h) r) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) p h) r)) (is_pointer_or_null y))) (list_token dsh p)) (@list_cell cs list_structid list_link list_token ls dsh h p)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) p)) (lseg ls dsh psh r y z))) *)
apply exp_right with y.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
normalize.
repeat (apply sepcon_derives; auto).
clear - NR.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
apply derives_refl'; apply nonreadable_list_cell_eq; auto.
Qed.

Lemma lseg_unroll_nonempty1 (ls: listspec list_structid list_link list_token):
   forall p P dsh psh h tail v1 v2,
    ~ (readable_share dsh) ->
    ~ ptr_eq v1 v2 ->
    is_pointer_or_null p ->
    P |-- list_token dsh v1 * list_cell ls dsh h v1 *
             (field_at psh list_struct (StructField list_link :: nil)
                   (valinject (nested_field_type list_struct (StructField list_link :: nil)) p) v1 *
               lseg ls dsh psh tail p v2) ->
    P |-- lseg ls dsh psh (v1::tail) v1 v2.
(* Goal: forall (v' : @elemtype cs list_structid list_link list_token ls) (ash bsh psh : share) (p : val) (v : @elemtype cs list_structid list_link list_token ls) (_ : @sepalg.join share Share.Join_ba ash bsh psh) (_ : not (readable_share ash)) (_ : readable_share bsh), @eq mpred (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls ash v' p) (@list_cell cs list_structid list_link list_token ls bsh v p)) (@list_cell cs list_structid list_link list_token ls psh v p) *)
Proof. intros. rewrite lseg_unroll by auto. apply orp_right2. unfold lseg_cons.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
  rewrite prop_true_andp by auto.
(* Goal: @derives mpred Nveric P (@exp mpred Nveric (list (prod val (@elemtype cs list_structid list_link list_token ls))) (fun r : list (prod val (@elemtype cs list_structid list_link list_token ls)) => @exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) v1 h) tail) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) v1 h) r)) (is_pointer_or_null y))) (list_token dsh v1)) (@list_cell cs list_structid list_link list_token ls dsh h v1)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) v1)) (lseg ls dsh psh r y v2)))) *)
  apply exp_right with h. apply exp_right with tail. apply exp_right with p.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
    rewrite prop_true_andp by auto.
(* Goal: @derives mpred Nveric P (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh v1) (@list_cell cs list_structid list_link list_token ls dsh h v1)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) p) v1)) (lseg ls dsh psh tail p v2)) *)
 rewrite sepcon_assoc.
 eapply derives_trans; [ eassumption | ].
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
 apply sepcon_derives; auto.
Qed.

Lemma lseg_neq (ls: listspec list_structid list_link list_token):
  forall dsh psh s v v2,
    ~ (readable_share dsh) ->
    ptr_neq v v2 ->
     lseg ls dsh psh s v v2 = lseg_cons ls dsh psh s v v2.
(* Goal: forall (v' : @elemtype cs list_structid list_link list_token ls) (ash bsh psh : share) (p : val) (v : @elemtype cs list_structid list_link list_token ls) (_ : @sepalg.join share Share.Join_ba ash bsh psh) (_ : not (readable_share ash)) (_ : readable_share bsh), @eq mpred (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls ash v' p) (@list_cell cs list_structid list_link list_token ls bsh v p)) (@list_cell cs list_structid list_link list_token ls psh v p) *)
intros. rewrite lseg_unroll by auto.
(* Goal: @eq mpred (@orp mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) x z)) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) *)
apply pred_ext. apply orp_left; auto.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) *)
(* Goal: @derives mpred Nveric (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) x z) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) *)
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) (@orp mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) x z)) *)
rewrite andp_assoc.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq v v2)) (@andp mpred Nveric (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) s (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) (@emp mpred Nveric Sveric))) (lseg_cons ls dsh psh s v v2) *)
(* Goal: @derives mpred Nveric (lseg_cons ls dsh psh s v v2) (@orp mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq v v2)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) s (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh s v v2)) *)
do 2 (apply derives_extract_prop; intro).
(* Goal: @derives mpred Nveric (@emp mpred Nveric Sveric) (lseg_cons ls dsh psh s v v2) *)
(* Goal: @derives mpred Nveric (lseg_cons ls dsh psh s v v2) (@orp mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq v v2)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) s (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh s v v2)) *)
congruence.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
apply orp_right2. auto.
Qed.

Lemma lseg_nonnull (ls: listspec list_structid list_link list_token):
  forall dsh psh s v,
    ~ (readable_share dsh) ->
      typed_true (tptr list_struct) v ->
     lseg ls dsh psh s v nullval = lseg_cons ls dsh psh s v nullval.
Proof.
(* Goal: forall (v' : @elemtype cs list_structid list_link list_token ls) (ash bsh psh : share) (p : val) (v : @elemtype cs list_structid list_link list_token ls) (_ : @sepalg.join share Share.Join_ba ash bsh psh) (_ : not (readable_share ash)) (_ : readable_share bsh), @eq mpred (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls ash v' p) (@list_cell cs list_structid list_link list_token ls bsh v p)) (@list_cell cs list_structid list_link list_token ls psh v p) *)
intros. unfold nullval.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
apply lseg_neq; auto.
unfold typed_true, strict_bool_val in H0; simpl in H0.
destruct Archi.ptr64 eqn:?;
  destruct v; inv H0;
  first [ revert H2; simple_if_tac; discriminate | intro Hx; inv Hx]. 
Qed.

Lemma unfold_lseg_neq (ls: listspec list_structid list_link list_token):
   forall P Q1 Q R (v v2: val) dsh psh (s: list val),
    ~ (readable_share dsh) ->
      PROPx P (LOCALx (Q1::Q) (SEPx (lseg ls dsh psh s v v2 :: R))) |--
                        !! (ptr_neq v v2) ->
      PROPx P (LOCALx (Q1::Q) (SEPx (lseg ls dsh psh s v v2 :: R))) |--
     EX hryp: elemtype ls * list val * val * val,
      match hryp with (h,r,y,p) =>
       !! (s=p::r /\ is_pointer_or_null y) &&
       !! (p=v) &&
      PROPx P (LOCALx Q
        (SEPx (list_token dsh v :: list_cell ls dsh h v::
                  field_at psh list_struct (StructField list_link :: nil) (valinject (nested_field_type list_struct (StructField list_link :: nil)) y) v ::
                  lseg ls dsh psh r y v2 ::
                  R)))
        end.
Proof.
(* Goal: forall (v' : @elemtype cs list_structid list_link list_token ls) (ash bsh psh : share) (p : val) (v : @elemtype cs list_structid list_link list_token ls) (_ : @sepalg.join share Share.Join_ba ash bsh psh) (_ : not (readable_share ash)) (_ : readable_share bsh), @eq mpred (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls ash v' p) (@list_cell cs list_structid list_link list_token ls bsh v p)) (@list_cell cs list_structid list_link list_token ls psh v p) *)
intros.
apply derives_trans with
(PROPx P (LOCALx (Q1::Q) (SEPx (lseg_cons ls dsh psh s v v2 :: R)))).
apply derives_trans with
(!! (ptr_neq v v2) && PROPx P (LOCALx (Q1::Q) (SEPx (lseg ls dsh psh s v v2 :: R)))).
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
apply andp_right; auto.
(* Goal: @derives (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (@andp (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (@prop (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (ptr_neq v v2)) (PROPx P (LOCALx (@cons localdef Q1 Q) (SEPx (@cons mpred (lseg ls dsh psh s v v2) R))))) (PROPx P (LOCALx (@cons localdef Q1 Q) (SEPx (@cons mpred (lseg_cons ls dsh psh s v v2) R)))) *)
(* Goal: @derives (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (PROPx P (LOCALx (@cons localdef Q1 Q) (SEPx (@cons mpred (lseg_cons ls dsh psh s v v2) R)))) (@exp (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (prod (prod (prod (@elemtype cs list_structid list_link list_token ls) (list (prod val (@elemtype cs list_structid list_link list_token ls)))) val) val) (fun hryp : prod (prod (prod (@elemtype cs list_structid list_link list_token ls) (list (prod val (@elemtype cs list_structid list_link list_token ls)))) val) val => let (p0, p) := hryp in let (p1, y) := p0 in let (h, r) := p1 in @andp (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (@andp (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (@prop (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) s (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) p h) r)) (is_pointer_or_null y))) (@prop (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (@eq val p v))) (PROPx P (LOCALx Q (SEPx (@cons mpred (list_token dsh v) (@cons mpred (@list_cell cs list_structid list_link list_token ls dsh h v) (@cons mpred (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) v) (@cons mpred (lseg ls dsh psh r y v2) R))))))))) *)
intro rho; unfold PROPx,LOCALx,SEPx,local,tc_expr,tc_lvalue; unfold_lift; simpl.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_neq v v2)) (@andp mpred Nveric (@prop mpred Nveric (@fold_right Prop Prop and True P)) (@andp mpred Nveric (@lift1 Prop mpred (@prop mpred Nveric) (fun x : environ => and (locald_denote Q1 x) (@fold_right (forall _ : environ, Prop) (forall _ : environ, Prop) (fun (x0 x1 : forall _ : environ, Prop) (x2 : environ) => and (x0 x2) (x1 x2)) (fun _ : environ => True) (@map localdef (forall _ : environ, Prop) locald_denote Q) x)) rho) (@sepcon mpred Nveric Sveric (lseg ls dsh psh s v v2) (fold_right_sepcon R))))) (@andp mpred Nveric (@prop mpred Nveric (@fold_right Prop Prop and True P)) (@andp mpred Nveric (@lift1 Prop mpred (@prop mpred Nveric) (fun x : environ => and (locald_denote Q1 x) (@fold_right (forall _ : environ, Prop) (forall _ : environ, Prop) (fun (x0 x1 : forall _ : environ, Prop) (x2 : environ) => and (x0 x2) (x1 x2)) (fun _ : environ => True) (@map localdef (forall _ : environ, Prop) locald_denote Q) x)) rho) (@sepcon mpred Nveric Sveric (lseg_cons ls dsh psh s v v2) (fold_right_sepcon R)))) *)
(* Goal: @derives (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (PROPx P (LOCALx (@cons localdef Q1 Q) (SEPx (@cons mpred (lseg_cons ls dsh psh s v v2) R)))) (@exp (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (prod (prod (prod (@elemtype cs list_structid list_link list_token ls) (list (prod val (@elemtype cs list_structid list_link list_token ls)))) val) val) (fun hryp : prod (prod (prod (@elemtype cs list_structid list_link list_token ls) (list (prod val (@elemtype cs list_structid list_link list_token ls)))) val) val => let (p0, p) := hryp in let (p1, y) := p0 in let (h, r) := p1 in @andp (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (@andp (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (@prop (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) s (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) p h) r)) (is_pointer_or_null y))) (@prop (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (@eq val p v))) (PROPx P (LOCALx Q (SEPx (@cons mpred (list_token dsh v) (@cons mpred (@list_cell cs list_structid list_link list_token ls dsh h v) (@cons mpred (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) v) (@cons mpred (lseg ls dsh psh r y v2) R))))))))) *)
unfold lift1; simpl.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_neq v v2)) (@andp mpred Nveric (@prop mpred Nveric (@fold_right Prop Prop and True P)) (@andp mpred Nveric (@prop mpred Nveric (and (locald_denote Q1 rho) (@fold_right (forall _ : environ, Prop) (forall _ : environ, Prop) (fun (x x0 : forall _ : environ, Prop) (x1 : environ) => and (x x1) (x0 x1)) (fun _ : environ => True) (@map localdef (forall _ : environ, Prop) locald_denote Q) rho))) (@sepcon mpred Nveric Sveric (lseg ls dsh psh s v v2) (fold_right_sepcon R))))) (@andp mpred Nveric (@prop mpred Nveric (@fold_right Prop Prop and True P)) (@andp mpred Nveric (@prop mpred Nveric (and (locald_denote Q1 rho) (@fold_right (forall _ : environ, Prop) (forall _ : environ, Prop) (fun (x x0 : forall _ : environ, Prop) (x1 : environ) => and (x x1) (x0 x1)) (fun _ : environ => True) (@map localdef (forall _ : environ, Prop) locald_denote Q) rho))) (@sepcon mpred Nveric Sveric (lseg_cons ls dsh psh s v v2) (fold_right_sepcon R)))) *)
(* Goal: @derives (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (PROPx P (LOCALx (@cons localdef Q1 Q) (SEPx (@cons mpred (lseg_cons ls dsh psh s v v2) R)))) (@exp (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (prod (prod (prod (@elemtype cs list_structid list_link list_token ls) (list (prod val (@elemtype cs list_structid list_link list_token ls)))) val) val) (fun hryp : prod (prod (prod (@elemtype cs list_structid list_link list_token ls) (list (prod val (@elemtype cs list_structid list_link list_token ls)))) val) val => let (p0, p) := hryp in let (p1, y) := p0 in let (h, r) := p1 in @andp (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (@andp (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (@prop (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) s (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) p h) r)) (is_pointer_or_null y))) (@prop (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (@eq val p v))) (PROPx P (LOCALx Q (SEPx (@cons mpred (list_token dsh v) (@cons mpred (@list_cell cs list_structid list_link list_token ls dsh h v) (@cons mpred (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) v) (@cons mpred (lseg ls dsh psh r y v2) R))))))))) *)
 repeat (apply derives_extract_prop; intro).
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
 rewrite prop_true_andp by auto.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
 rewrite prop_true_andp by auto.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
apply sepcon_derives; auto.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
rewrite lseg_neq; auto.
(* Goal: @derives (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (PROPx P (LOCALx (@cons localdef Q1 Q) (SEPx (@cons mpred (lseg_cons ls dsh psh s v v2) R)))) (@exp (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (prod (prod (prod (@elemtype cs list_structid list_link list_token ls) (list (prod val (@elemtype cs list_structid list_link list_token ls)))) val) val) (fun hryp : prod (prod (prod (@elemtype cs list_structid list_link list_token ls) (list (prod val (@elemtype cs list_structid list_link list_token ls)))) val) val => let (p0, p) := hryp in let (p1, y) := p0 in let (h, r) := p1 in @andp (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (@andp (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (@prop (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) s (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) p h) r)) (is_pointer_or_null y))) (@prop (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (@eq val p v))) (PROPx P (LOCALx Q (SEPx (@cons mpred (list_token dsh v) (@cons mpred (@list_cell cs list_structid list_link list_token ls dsh h v) (@cons mpred (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) v) (@cons mpred (lseg ls dsh psh r y v2) R))))))))) *)
intro rho; unfold PROPx,LOCALx,SEPx,local,tc_expr,tc_lvalue,lift2,lift1,lift0; simpl.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@fold_right Prop Prop and True P)) (@andp mpred Nveric (@prop mpred Nveric (@liftx (Tarrow Prop (Tarrow Prop (LiftEnviron Prop))) and (locald_denote Q1) (@fold_right (forall _ : environ, Prop) (forall _ : environ, Prop) (@liftx (Tarrow Prop (Tarrow Prop (LiftEnviron Prop))) and) (@liftx (LiftEnviron Prop) True) (@map localdef (forall _ : environ, Prop) locald_denote Q)) rho)) (@sepcon mpred Nveric Sveric (lseg_cons ls dsh psh s v v2) (fold_right_sepcon R)))) (@exp mpred Nveric (prod (prod (prod (@elemtype cs list_structid list_link list_token ls) (list (prod val (@elemtype cs list_structid list_link list_token ls)))) val) val) (fun x : prod (prod (prod (@elemtype cs list_structid list_link list_token ls) (list (prod val (@elemtype cs list_structid list_link list_token ls)))) val) val => (let (p0, p) := x in let (p1, y) := p0 in let (h, r) := p1 in fun x0 : environ => @andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) s (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) p h) r)) (is_pointer_or_null y))) (@prop mpred Nveric (@eq val p v))) (@andp mpred Nveric (@prop mpred Nveric (@fold_right Prop Prop and True P)) (@andp mpred Nveric (@prop mpred Nveric (@fold_right (forall _ : environ, Prop) (forall _ : environ, Prop) (@liftx (Tarrow Prop (Tarrow Prop (LiftEnviron Prop))) and) (@liftx (LiftEnviron Prop) True) (@map localdef (forall _ : environ, Prop) locald_denote Q) x0)) (@sepcon mpred Nveric Sveric (list_token dsh v) (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls dsh h v) (@sepcon mpred Nveric Sveric (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) v) (@sepcon mpred Nveric Sveric (lseg ls dsh psh r y v2) (fold_right_sepcon R)))))))) rho)) *)
 unfold_lift.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh p) (@list_cell cs list_structid list_link list_token ls dsh h p)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) p)) (lseg ls dsh psh r y z)) (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) p h) r) p z) *)
 unfold lseg_cons. simpl.
(* Goal: ptr_neq (Vptr b i) (if Archi.ptr64 then Vlong Int64.zero else Vint Int.zero) *)
 apply derives_extract_prop; intro.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) s (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) v h) r)) (is_pointer_or_null y))) (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh v) (@list_cell cs list_structid list_link list_token ls dsh h v)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) v)) (lseg ls dsh psh r y v2)) (fold_right_sepcon R))) (@exp mpred Nveric (prod (prod (prod (@elemtype cs list_structid list_link list_token ls) (list (prod val (@elemtype cs list_structid list_link list_token ls)))) val) val) (fun x : prod (prod (prod (@elemtype cs list_structid list_link list_token ls) (list (prod val (@elemtype cs list_structid list_link list_token ls)))) val) val => (let (p0, p) := x in let (p1, y) := p0 in let (h, r) := p1 in fun x0 : environ => @andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) s (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) p h) r)) (is_pointer_or_null y))) (@prop mpred Nveric (@eq val p v))) (@andp mpred Nveric (@prop mpred Nveric (@fold_right Prop Prop and True P)) (@andp mpred Nveric (@prop mpred Nveric (@fold_right (forall _ : environ, Prop) (forall _ : environ, Prop) (fun (x1 x2 : forall _ : environ, Prop) (x3 : environ) => and (x1 x3) (x2 x3)) (fun _ : environ => True) (@map localdef (forall _ : environ, Prop) locald_denote Q) x0)) (@sepcon mpred Nveric Sveric (list_token dsh v) (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls dsh h v) (@sepcon mpred Nveric Sveric (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) v) (@sepcon mpred Nveric Sveric (lseg ls dsh psh r y v2) (fold_right_sepcon R)))))))) rho)) *)
 apply derives_extract_prop; intros [? ?].
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (not (ptr_eq v v2))) (@exp mpred Nveric (@elemtype cs list_structid list_link list_token ls) (fun h : @elemtype cs list_structid list_link list_token ls => @exp mpred Nveric (list (prod val (@elemtype cs list_structid list_link list_token ls))) (fun r : list (prod val (@elemtype cs list_structid list_link list_token ls)) => @exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) s (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) v h) r)) (is_pointer_or_null y))) (list_token dsh v)) (@list_cell cs list_structid list_link list_token ls dsh h v)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) v)) (lseg ls dsh psh r y v2)))))) (fold_right_sepcon R)) (@exp mpred Nveric (prod (prod (prod (@elemtype cs list_structid list_link list_token ls) (list (prod val (@elemtype cs list_structid list_link list_token ls)))) val) val) (fun x : prod (prod (prod (@elemtype cs list_structid list_link list_token ls) (list (prod val (@elemtype cs list_structid list_link list_token ls)))) val) val => (let (p0, p) := x in let (p1, y) := p0 in let (h, r) := p1 in fun x0 : environ => @andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) s (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) p h) r)) (is_pointer_or_null y))) (@prop mpred Nveric (@eq val p v))) (@andp mpred Nveric (@prop mpred Nveric (@fold_right Prop Prop and True P)) (@andp mpred Nveric (@prop mpred Nveric (@fold_right (forall _ : environ, Prop) (forall _ : environ, Prop) (fun (x1 x2 : forall _ : environ, Prop) (x3 : environ) => and (x1 x3) (x2 x3)) (fun _ : environ => True) (@map localdef (forall _ : environ, Prop) locald_denote Q) x0)) (@sepcon mpred Nveric Sveric (list_token dsh v) (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls dsh h v) (@sepcon mpred Nveric Sveric (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) v) (@sepcon mpred Nveric Sveric (lseg ls dsh psh r y v2) (fold_right_sepcon R)))))))) rho)) *)
 rewrite sepcon_andp_prop'.
(* Goal: ptr_neq (Vptr b i) (if Archi.ptr64 then Vlong Int64.zero else Vint Int.zero) *)
 apply derives_extract_prop; intro.
(* Goal: @derives mpred Nveric (@exp mpred Nveric (@elemtype cs list_structid list_link list_token ls) (fun h : @elemtype cs list_structid list_link list_token ls => @exp mpred Nveric (list (prod val (@elemtype cs list_structid list_link list_token ls))) (fun r : list (prod val (@elemtype cs list_structid list_link list_token ls)) => @exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) v e) l) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) x h) r)) (is_pointer_or_null y))) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh h x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z))))) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val v x) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh e x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) x)) (lseg ls dsh psh l tail z)))) *)
 rewrite exp_sepcon1; apply exp_left; intro h.
(* Goal: @derives mpred Nveric (@exp mpred Nveric (list (prod val (@elemtype cs list_structid list_link list_token ls))) (fun r : list (prod val (@elemtype cs list_structid list_link list_token ls)) => @exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) v e) l) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) x h) r)) (is_pointer_or_null y))) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh h x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val v x) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh e x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) x)) (lseg ls dsh psh l tail z)))) *)
 rewrite exp_sepcon1; apply exp_left; intro r.
(* Goal: @derives mpred Nveric (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) v e) l) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) x h) r)) (is_pointer_or_null y))) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh h x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z))) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val v x) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh e x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) x)) (lseg ls dsh psh l tail z)))) *)
 rewrite exp_sepcon1; apply exp_left; intro y.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) s (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) v h) r)) (is_pointer_or_null y))) (list_token dsh v)) (@list_cell cs list_structid list_link list_token ls dsh h v)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) v)) (lseg ls dsh psh r y v2)) (fold_right_sepcon R)) (@exp mpred Nveric (prod (prod (prod (@elemtype cs list_structid list_link list_token ls) (list (prod val (@elemtype cs list_structid list_link list_token ls)))) val) val) (fun x : prod (prod (prod (@elemtype cs list_structid list_link list_token ls) (list (prod val (@elemtype cs list_structid list_link list_token ls)))) val) val => (let (p0, p) := x in let (p1, y) := p0 in let (h, r) := p1 in fun x0 : environ => @andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) s (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) p h) r)) (is_pointer_or_null y))) (@prop mpred Nveric (@eq val p v))) (@andp mpred Nveric (@prop mpred Nveric (@fold_right Prop Prop and True P)) (@andp mpred Nveric (@prop mpred Nveric (@fold_right (forall _ : environ, Prop) (forall _ : environ, Prop) (fun (x1 x2 : forall _ : environ, Prop) (x3 : environ) => and (x1 x3) (x2 x3)) (fun _ : environ => True) (@map localdef (forall _ : environ, Prop) locald_denote Q) x0)) (@sepcon mpred Nveric Sveric (list_token dsh v) (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls dsh h v) (@sepcon mpred Nveric Sveric (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) v) (@sepcon mpred Nveric Sveric (lseg ls dsh psh r y v2) (fold_right_sepcon R)))))))) rho)) *)
 repeat rewrite sepcon_andp_prop'.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) s (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) v h) r)) (is_pointer_or_null y))) (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh v) (@list_cell cs list_structid list_link list_token ls dsh h v)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) v)) (lseg ls dsh psh r y v2)) (fold_right_sepcon R))) (@exp mpred Nveric (prod (prod (prod (@elemtype cs list_structid list_link list_token ls) (list (prod val (@elemtype cs list_structid list_link list_token ls)))) val) val) (fun x : prod (prod (prod (@elemtype cs list_structid list_link list_token ls) (list (prod val (@elemtype cs list_structid list_link list_token ls)))) val) val => (let (p0, p) := x in let (p1, y) := p0 in let (h, r) := p1 in fun x0 : environ => @andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) s (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) p h) r)) (is_pointer_or_null y))) (@prop mpred Nveric (@eq val p v))) (@andp mpred Nveric (@prop mpred Nveric (@fold_right Prop Prop and True P)) (@andp mpred Nveric (@prop mpred Nveric (@fold_right (forall _ : environ, Prop) (forall _ : environ, Prop) (fun (x1 x2 : forall _ : environ, Prop) (x3 : environ) => and (x1 x3) (x2 x3)) (fun _ : environ => True) (@map localdef (forall _ : environ, Prop) locald_denote Q) x0)) (@sepcon mpred Nveric Sveric (list_token dsh v) (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls dsh h v) (@sepcon mpred Nveric Sveric (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) v) (@sepcon mpred Nveric Sveric (lseg ls dsh psh r y v2) (fold_right_sepcon R)))))))) rho)) *)
 apply derives_extract_prop; intros [? ?].
(* Goal: and True (iff (@eq val (Vptr b0 i) (Vptr b0 i0)) (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) *)
(* Goal: @derives mpred Nveric (let (p0, h) := p0 in @andp mpred Nveric (@prop mpred Nveric (and (@eq val p0 p) (not (ptr_eq p q)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh p)) (@list_cell cs list_structid list_link list_token ls dsh h p)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) p)) (lseg ls dsh psh contents tail q)))) (@prop mpred Nveric (and (is_pointer_or_null p) (iff (@eq val p q) (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) p0 contents) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))))) *)
 subst.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh v) (@list_cell cs list_structid list_link list_token ls dsh h v)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) v)) (lseg ls dsh psh r y v2)) (fold_right_sepcon R)) (@exp mpred Nveric (prod (prod (prod (@elemtype cs list_structid list_link list_token ls) (list (prod val (@elemtype cs list_structid list_link list_token ls)))) val) val) (fun x : prod (prod (prod (@elemtype cs list_structid list_link list_token ls) (list (prod val (@elemtype cs list_structid list_link list_token ls)))) val) val => (let (p0, p) := x in let (p1, y) := p0 in let (h0, r0) := p1 in fun x0 : environ => @andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) v h) r) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) p h0) r0)) (is_pointer_or_null y))) (@prop mpred Nveric (@eq val p v))) (@andp mpred Nveric (@prop mpred Nveric (@fold_right Prop Prop and True P)) (@andp mpred Nveric (@prop mpred Nveric (@fold_right (forall _ : environ, Prop) (forall _ : environ, Prop) (fun (x1 x2 : forall _ : environ, Prop) (x3 : environ) => and (x1 x3) (x2 x3)) (fun _ : environ => True) (@map localdef (forall _ : environ, Prop) locald_denote Q) x0)) (@sepcon mpred Nveric Sveric (list_token dsh v) (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls dsh h0 v) (@sepcon mpred Nveric Sveric (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) v) (@sepcon mpred Nveric Sveric (lseg ls dsh psh r0 y v2) (fold_right_sepcon R)))))))) rho)) *)
 apply exp_right with (h,r,y, v).
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
 repeat rewrite prop_true_andp by auto.
(* Goal: @derives mpred Nveric P (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh v1) (@list_cell cs list_structid list_link list_token ls dsh h v1)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) p) v1)) (lseg ls dsh psh tail p v2)) *)
 repeat rewrite sepcon_assoc.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
 auto.
Qed.

Lemma unfold_lseg_cons (ls: listspec list_structid list_link list_token):
   forall P Q1 Q R e dsh psh s,
    ~ (readable_share dsh) ->
      PROPx P (LOCALx (Q1::Q) (SEPx (lseg ls dsh psh s e nullval :: R))) |--
                        !! (typed_true (tptr list_struct) e) ->
      PROPx P (LOCALx (Q1::Q) (SEPx (lseg ls dsh psh s e nullval :: R))) |--
     EX hryp: elemtype ls * list val * val * val,
      match hryp with (h,r,y,p) =>
       !! (s=p::r /\ is_pointer_or_null y) &&
       !! (p = e) &&
      PROPx P (LOCALx Q
        (SEPx (list_token dsh e :: list_cell ls dsh h e ::
                  field_at psh list_struct (StructField list_link :: nil) (valinject (nested_field_type list_struct (StructField list_link :: nil)) y) e ::
                  lseg ls dsh psh r y nullval ::
                  R)))
        end.
Proof.
(* Goal: forall (v' : @elemtype cs list_structid list_link list_token ls) (ash bsh psh : share) (p : val) (v : @elemtype cs list_structid list_link list_token ls) (_ : @sepalg.join share Share.Join_ba ash bsh psh) (_ : not (readable_share ash)) (_ : readable_share bsh), @eq mpred (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls ash v' p) (@list_cell cs list_structid list_link list_token ls bsh v p)) (@list_cell cs list_structid list_link list_token ls psh v p) *)
intros. apply unfold_lseg_neq; auto.
eapply derives_trans.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
apply H0. normalize.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@fold_right Prop Prop and True P)) (@andp mpred Nveric (@prop mpred Nveric (@liftx (Tarrow Prop (Tarrow Prop (LiftEnviron Prop))) and (locald_denote Q1) (@fold_right (forall _ : environ, Prop) (forall _ : environ, Prop) (@liftx (Tarrow Prop (Tarrow Prop (LiftEnviron Prop))) and) (@liftx (LiftEnviron Prop) True) (@map localdef (forall _ : environ, Prop) locald_denote Q)) rho)) (@sepcon mpred Nveric Sveric (lseg_cons ls dsh psh s v v2) (fold_right_sepcon R)))) (@exp mpred Nveric (prod (prod (prod (@elemtype cs list_structid list_link list_token ls) (list (prod val (@elemtype cs list_structid list_link list_token ls)))) val) val) (fun x : prod (prod (prod (@elemtype cs list_structid list_link list_token ls) (list (prod val (@elemtype cs list_structid list_link list_token ls)))) val) val => (let (p0, p) := x in let (p1, y) := p0 in let (h, r) := p1 in fun x0 : environ => @andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) s (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) p h) r)) (is_pointer_or_null y))) (@prop mpred Nveric (@eq val p v))) (@andp mpred Nveric (@prop mpred Nveric (@fold_right Prop Prop and True P)) (@andp mpred Nveric (@prop mpred Nveric (@fold_right (forall _ : environ, Prop) (forall _ : environ, Prop) (@liftx (Tarrow Prop (Tarrow Prop (LiftEnviron Prop))) and) (@liftx (LiftEnviron Prop) True) (@map localdef (forall _ : environ, Prop) locald_denote Q) x0)) (@sepcon mpred Nveric Sveric (list_token dsh v) (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls dsh h v) (@sepcon mpred Nveric Sveric (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) v) (@sepcon mpred Nveric Sveric (lseg ls dsh psh r y v2) (fold_right_sepcon R)))))))) rho)) *)
unfold local. super_unfold_lift.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
unfold nullval. destruct e; inv H1; try congruence; auto.
(* Goal: ptr_neq (Vptr b i) (if Archi.ptr64 then Vlong Int64.zero else Vint Int.zero) *)
intro. apply ptr_eq_e in H1.
(* Goal: False *)
(* Goal: ptr_neq (Vptr b i) (if Archi.ptr64 then Vlong Int64.zero else Vint Int.zero) *)
destruct Archi.ptr64; inv H1.
Qed.

Lemma semax_lseg_neq (ls: listspec list_structid list_link list_token):
  forall (Espec: OracleKind)
      Delta P Q dsh psh s v v2 R c Post,
    ~ (readable_share dsh) ->
    ~ (ptr_eq v v2) ->
  (forall (h: elemtype ls) (r: list val) (y: val),
    s=v::r -> is_pointer_or_null y ->
    semax Delta
        (PROPx P (LOCALx Q
        (SEPx (list_token dsh v :: list_cell ls dsh h v ::
                  field_at psh list_struct (StructField list_link :: nil)
                      (valinject (nested_field_type list_struct (StructField list_link :: nil)) y) v ::
                  lseg ls dsh psh r y v2 ::
                  R)))) c Post) ->
   semax Delta
       (PROPx P (LOCALx Q (SEPx (lseg ls dsh psh s v v2 :: R))))
       c Post.
Proof.
(* Goal: forall (v' : @elemtype cs list_structid list_link list_token ls) (ash bsh psh : share) (p : val) (v : @elemtype cs list_structid list_link list_token ls) (_ : @sepalg.join share Share.Join_ba ash bsh psh) (_ : not (readable_share ash)) (_ : readable_share bsh), @eq mpred (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls ash v' p) (@list_cell cs list_structid list_link list_token ls bsh v p)) (@list_cell cs list_structid list_link list_token ls psh v p) *)
intros.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
rewrite lseg_neq by auto.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh p) (@list_cell cs list_structid list_link list_token ls dsh h p)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) p)) (lseg ls dsh psh r y z)) (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) p h) r) p z) *)
unfold lseg_cons.
apply semax_pre0 with
 (EX h: elemtype ls, EX r: list val, EX y: val,
  !!(s = v :: r /\ is_pointer_or_null y) &&
    PROPx P (LOCALx Q (SEPx (list_token dsh v :: list_cell ls dsh h v ::
       field_at psh list_struct (StructField list_link :: nil)
                   (valinject
                      (nested_field_type list_struct
                         (StructField list_link :: nil)) y) v ::
        lseg ls dsh psh r y v2 :: R)))).
(* Goal: @derives (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (PROPx P (LOCALx Q (SEPx (@cons mpred (@andp mpred Nveric (@prop mpred Nveric (not (ptr_eq v v2))) (@exp mpred Nveric (@elemtype cs list_structid list_link list_token ls) (fun h : @elemtype cs list_structid list_link list_token ls => @exp mpred Nveric (list (prod val (@elemtype cs list_structid list_link list_token ls))) (fun r : list (prod val (@elemtype cs list_structid list_link list_token ls)) => @exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) s (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) v h) r)) (is_pointer_or_null y))) (list_token dsh v)) (@list_cell cs list_structid list_link list_token ls dsh h v)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) v)) (lseg ls dsh psh r y v2)))))) R)))) (@exp (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (@elemtype cs list_structid list_link list_token ls) (fun h : @elemtype cs list_structid list_link list_token ls => @exp (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (list (prod val (@elemtype cs list_structid list_link list_token ls))) (fun r : list (prod val (@elemtype cs list_structid list_link list_token ls)) => @exp (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) val (fun y : val => @andp (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (@prop (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) s (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) v h) r)) (is_pointer_or_null y))) (PROPx P (LOCALx Q (SEPx (@cons mpred (list_token dsh v) (@cons mpred (@list_cell cs list_structid list_link list_token ls dsh h v) (@cons mpred (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) v) (@cons mpred (lseg ls dsh psh r y v2) R))))))))))) *)
(* Goal: semax cs Espec Delta (@exp (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (@elemtype cs list_structid list_link list_token ls) (fun h : @elemtype cs list_structid list_link list_token ls => @exp (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (list (prod val (@elemtype cs list_structid list_link list_token ls))) (fun r : list (prod val (@elemtype cs list_structid list_link list_token ls)) => @exp (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) val (fun y : val => @andp (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (@prop (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) s (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) v h) r)) (is_pointer_or_null y))) (PROPx P (LOCALx Q (SEPx (@cons mpred (list_token dsh v) (@cons mpred (@list_cell cs list_structid list_link list_token ls dsh h v) (@cons mpred (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) v) (@cons mpred (lseg ls dsh psh r y v2) R))))))))))) c Post *)
go_lowerx; entailer.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh v) (@list_cell cs list_structid list_link list_token ls dsh h v)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) v)) (lseg ls dsh psh r y v2)) (fold_right_sepcon R)) (@exp mpred Nveric (@elemtype cs list_structid list_link list_token ls) (fun x : @elemtype cs list_structid list_link list_token ls => @exp mpred Nveric (list (prod val (@elemtype cs list_structid list_link list_token ls))) (fun x0 : list (prod val (@elemtype cs list_structid list_link list_token ls)) => @exp mpred Nveric val (fun x1 : val => @andp mpred Nveric (@prop mpred Nveric (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) v h) r) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) v x) x0)) (is_pointer_or_null x1))) (@andp mpred Nveric (@TT mpred Nveric) (@andp mpred Nveric (@TT mpred Nveric) (@sepcon mpred Nveric Sveric (list_token dsh v) (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls dsh x v) (@sepcon mpred Nveric Sveric (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) x1) v) (@sepcon mpred Nveric Sveric (lseg ls dsh psh x0 x1 v2) (fold_right_sepcon R))))))))))) *)
(* Goal: semax cs Espec Delta (@exp (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (@elemtype cs list_structid list_link list_token ls) (fun h : @elemtype cs list_structid list_link list_token ls => @exp (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (list (prod val (@elemtype cs list_structid list_link list_token ls))) (fun r : list (prod val (@elemtype cs list_structid list_link list_token ls)) => @exp (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) val (fun y : val => @andp (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (@prop (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) s (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) v h) r)) (is_pointer_or_null y))) (PROPx P (LOCALx Q (SEPx (@cons mpred (list_token dsh v) (@cons mpred (@list_cell cs list_structid list_link list_token ls dsh h v) (@cons mpred (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) v) (@cons mpred (lseg ls dsh psh r y v2) R))))))))))) c Post *)
Exists h r y.
rewrite <- ?sepcon_assoc.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
normalize.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
  autorewrite with subst norm1 norm2; normalize.
(* Goal: semax cs Espec Delta (@exp (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (@elemtype cs list_structid list_link list_token ls) (fun h : @elemtype cs list_structid list_link list_token ls => @exp (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (list (prod val (@elemtype cs list_structid list_link list_token ls))) (fun r : list (prod val (@elemtype cs list_structid list_link list_token ls)) => @exp (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) val (fun y : val => @andp (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (@prop (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) s (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) v h) r)) (is_pointer_or_null y))) (PROPx P (LOCALx Q (SEPx (@cons mpred (list_token dsh v) (@cons mpred (@list_cell cs list_structid list_link list_token ls dsh h v) (@cons mpred (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) v) (@cons mpred (lseg ls dsh psh r y v2) R))))))))))) c Post *)
Intros h r y.
(* Goal: semax cs Espec Delta (@andp (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (@prop (forall _ : environ, mpred) (@LiftNatDed' mpred Nveric) (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) s (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) v h) r)) (is_pointer_or_null y))) (PROPx P (LOCALx Q (SEPx (@cons mpred (list_token dsh v) (@cons mpred (@list_cell cs list_structid list_link list_token ls dsh h v) (@cons mpred (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) v) (@cons mpred (lseg ls dsh psh r y v2) R)))))))) c Post *)
apply semax_extract_prop; intros [? ?].
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
eauto.
Qed.


Lemma semax_lseg_nonnull (ls: listspec list_structid list_link list_token):
  forall (Espec: OracleKind)
      Delta P Q dsh psh s v R c Post,
    ~ (readable_share dsh) ->
   ENTAIL Delta, PROPx P (LOCALx Q
            (SEPx (lseg ls dsh psh s v nullval :: R))) |--
                        !!(typed_true (tptr list_struct) v)  ->
  (forall (h: elemtype ls) (r: list val) (y: val),
    s=v::r -> is_pointer_or_null y ->
    semax Delta
        (PROPx P (LOCALx Q
        (SEPx (list_token dsh v :: list_cell ls dsh h v ::
                  field_at psh list_struct (StructField list_link :: nil) (valinject (nested_field_type list_struct (StructField list_link :: nil)) y) v ::
                  lseg ls dsh psh r y nullval ::
                  R)))) c Post) ->
   semax Delta
       (PROPx P (LOCALx Q (SEPx (lseg ls dsh psh s v nullval :: R))))
       c Post.
Proof.
(* Goal: forall (v' : @elemtype cs list_structid list_link list_token ls) (ash bsh psh : share) (p : val) (v : @elemtype cs list_structid list_link list_token ls) (_ : @sepalg.join share Share.Join_ba ash bsh psh) (_ : not (readable_share ash)) (_ : readable_share bsh), @eq mpred (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls ash v' p) (@list_cell cs list_structid list_link list_token ls bsh v p)) (@list_cell cs list_structid list_link list_token ls psh v p) *)
intros.
(* Goal: semax cs Espec Delta (PROPx P (LOCALx Q (SEPx (@cons mpred (lseg ls dsh psh s v nullval) R)))) c Post *)
assert_PROP (~ ptr_eq v nullval).
eapply derives_trans; [eapply H0 |].
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
normalize.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
apply semax_lseg_neq; auto.
Qed.

Lemma lseg_nil_eq (ls: listspec list_structid list_link list_token):
    forall dsh psh p q,
   lseg ls dsh psh nil p q = !! (ptr_eq p q) && emp.
(* Goal: forall (v' : @elemtype cs list_structid list_link list_token ls) (ash bsh psh : share) (p : val) (v : @elemtype cs list_structid list_link list_token ls) (_ : @sepalg.join share Share.Join_ba ash bsh psh) (_ : not (readable_share ash)) (_ : readable_share bsh), @eq mpred (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls ash v' p) (@list_cell cs list_structid list_link list_token ls bsh v p)) (@list_cell cs list_structid list_link list_token ls psh v p) *)
Proof. intros.
(* Goal: @eq mpred (@struct_pred (@nil (prod ident type)) A F v p) (@struct_pred (@nil (prod ident type)) A F v p') *)
(* Goal: @eq mpred (@struct_pred (@cons (prod ident type) a m) A F v p) (@struct_pred (@cons (prod ident type) a m) A F v p') *)
 reflexivity.
Qed.

Lemma lseg_cons_eq (ls: listspec list_structid list_link list_token):
     forall dsh psh h r x z ,
     ~ (readable_share dsh) ->
    lseg ls dsh psh (h::r) x z =
        !!(x = h /\ ~ ptr_eq x z) &&
         (EX  y : val,
          !!(is_pointer_or_null y) &&
   list_token dsh x * list_cell ls dsh (vund ls) x * field_at psh list_struct (StructField list_link :: nil) (valinject (nested_field_type list_struct (StructField list_link :: nil)) y) x *
   lseg ls dsh psh r y z).
Proof.
(* Goal: forall (v' : @elemtype cs list_structid list_link list_token ls) (ash bsh psh : share) (p : val) (v : @elemtype cs list_structid list_link list_token ls) (_ : @sepalg.join share Share.Join_ba ash bsh psh) (_ : not (readable_share ash)) (_ : readable_share bsh), @eq mpred (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls ash v' p) (@list_cell cs list_structid list_link list_token ls bsh v p)) (@list_cell cs list_structid list_link list_token ls psh v p) *)
 intros. rewrite lseg_unroll by auto.
(* Goal: @eq mpred (@orp mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) x z)) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) *)
 apply pred_ext.
(* Goal: @derives mpred Nveric (@orp mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) x z)) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) *)
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) (@orp mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) x z)) *)
 apply orp_left.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) *)
(* Goal: @derives mpred Nveric (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) x z) (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) *)
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq val x (@fst val (@elemtype cs list_structid list_link list_token ls) h)) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh (@snd val (@elemtype cs list_structid list_link list_token ls) h) x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) x)) (lseg ls dsh psh r y z)))) (@orp mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) h r) x z)) *)
 rewrite andp_assoc.
(* Goal: ptr_neq (Vptr b i) (if Archi.ptr64 then Vlong Int64.zero else Vint Int.zero) *)
 apply derives_extract_prop; intro.
(* Goal: ptr_neq (Vptr b i) (if Archi.ptr64 then Vlong Int64.zero else Vint Int.zero) *)
 apply derives_extract_prop; intro.
(* Goal: False *)
(* Goal: ptr_neq (Vptr b i) (if Archi.ptr64 then Vlong Int64.zero else Vint Int.zero) *)
 inv H1.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh p) (@list_cell cs list_structid list_link list_token ls dsh h p)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) p)) (lseg ls dsh psh r y z)) (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) p h) r) p z) *)
 unfold lseg_cons.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
 normalize.
(* Goal: False *)
(* Goal: ptr_neq (Vptr b i) (if Archi.ptr64 then Vlong Int64.zero else Vint Int.zero) *)
 symmetry in H1; inv H1.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
 apply exp_right with y. normalize.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
  autorewrite with subst norm1 norm2; normalize.
 repeat (apply sepcon_derives; auto).
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
 apply derives_refl'; apply nonreadable_list_cell_eq; auto.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh p) (@list_cell cs list_structid list_link list_token ls dsh h p)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) p)) (lseg ls dsh psh r y z)) (@orp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (and (ptr_eq p z) (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) p h) r) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) p h) r) p z)) *)
 apply orp_right2.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
 normalize.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh p) (@list_cell cs list_structid list_link list_token ls dsh h p)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) p)) (lseg ls dsh psh r y z)) (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) p h) r) p z) *)
 unfold lseg_cons.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
 rewrite prop_true_andp by auto.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh p) (@list_cell cs list_structid list_link list_token ls dsh h p)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) p)) (lseg ls dsh psh r y z)) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) p h) r) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) p h) r)) (is_pointer_or_null y))) (list_token dsh p)) (@list_cell cs list_structid list_link list_token ls dsh h p)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) p)) (lseg ls dsh psh r y z))) *)
 apply exp_right with (vund ls). apply exp_right with r.  apply exp_right with y.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
 normalize.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
  autorewrite with subst norm1 norm2; normalize.
Qed.

Definition lseg_cons_right (ls: listspec list_structid list_link list_token)
           dsh psh (l: list val) (x z: val) : mpred :=
        !! (~ ptr_eq x z) &&
       EX r:list val , EX y:val,
             !!(l=r++y::nil /\ is_pointer_or_null y)  &&
                       list_cell ls dsh (vund ls) y *
             field_at psh list_struct (StructField list_link :: nil) (valinject (nested_field_type list_struct (StructField list_link :: nil)) z) y *
             lseg ls dsh psh r x y.

Lemma lseg_cons_right_neq (ls: listspec list_structid list_link list_token):
      forall dsh psh l x h y w z,
     sepalg.nonidentity psh ->
     ~ (readable_share dsh) ->
             list_token dsh y * list_cell ls dsh h y * field_at psh list_struct (StructField list_link :: nil) (valinject (nested_field_type list_struct (StructField list_link :: nil)) z) y *
             lseg ls dsh psh l x y * field_at psh list_struct (StructField list_link :: nil) (valinject (nested_field_type list_struct (StructField list_link :: nil)) w) z
   |--   lseg ls dsh psh (l++y::nil) x z * field_at psh list_struct (StructField list_link :: nil) (valinject (nested_field_type list_struct (StructField list_link :: nil)) w) z.
Proof.
(* Goal: forall (v' : @elemtype cs list_structid list_link list_token ls) (ash bsh psh : share) (p : val) (v : @elemtype cs list_structid list_link list_token ls) (_ : @sepalg.join share Share.Join_ba ash bsh psh) (_ : not (readable_share ash)) (_ : readable_share bsh), @eq mpred (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls ash v' p) (@list_cell cs list_structid list_link list_token ls bsh v p)) (@list_cell cs list_structid list_link list_token ls psh v p) *)
intros. rename H into SH. rename H0 into NR.
assert (SZ: 0 < sizeof (nested_field_type list_struct (DOT list_link)))
  by (rewrite list_link_type; simpl; destruct Archi.ptr64; computable).
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh y) (@list_cell cs list_structid list_link list_token ls dsh h y)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) z) y)) (lseg ls dsh psh l x y)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) w) z)) (@sepcon mpred Nveric Sveric (lseg ls dsh psh (@app (prod val (@elemtype cs list_structid list_link list_token ls)) l (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) y h) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) x z) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) w) z)) *)
rewrite (field_at_isptr _ _ _ _ z).
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
normalize.
(* Goal: forall (v' : @elemtype cs list_structid list_link list_token ls) (ash bsh psh : share) (p : val) (v : @elemtype cs list_structid list_link list_token ls) (_ : @sepalg.join share Share.Join_ba ash bsh psh) (_ : not (readable_share ash)) (_ : readable_share bsh), @eq mpred (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls ash v' p) (@list_cell cs list_structid list_link list_token ls bsh v p)) (@list_cell cs list_structid list_link list_token ls psh v p) *)
revert x; induction l; simpl; intros.
*
unfold lseg.
(* Goal: @derives mpred Nveric (valid_pointer Vundef) (valid_pointer p) *)
simpl.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
normalize.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
  autorewrite with subst norm1 norm2; normalize.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh y) (@list_cell cs list_structid list_link list_token ls dsh h y)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) z) y)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) w) z)) (@exp mpred Nveric val (fun x : val => @andp mpred Nveric (@prop mpred Nveric (not (ptr_eq y z))) (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null x)) (list_token dsh y)) (@list_cell cs list_structid list_link list_token ls dsh h y)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) x) y)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@emp mpred Nveric Sveric))) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) w) z)))) *)
apply exp_right with z.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh y) (@list_cell cs list_structid list_link list_token ls dsh h y)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) z) y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh el x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) x0) x)) (lseg ls dsh psh l x0 y)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) w) z)) (@andp mpred Nveric (@prop mpred Nveric (and (not (ptr_eq x z)) (is_pointer_or_null x0))) (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh x) (@list_cell cs list_structid list_link list_token ls dsh el x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) x0) x)) (lseg ls dsh psh (@app (prod val (@elemtype cs list_structid list_link list_token ls)) l (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) y h) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) x0 z)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) w) z))) *)
entailer.
(* Goal: @eq mpred (@prop mpred Nveric (ptr_eq v v)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) *)
(* Goal: @eq mpred (let (p, h) := p in @andp mpred Nveric (@prop mpred Nveric (and (@eq val p v) (not (ptr_eq v v)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh v)) (@list_cell cs list_structid list_link list_token ls dsh h v)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) v)) (lseg ls dsh psh l tail v)))) (@andp mpred Nveric (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) p l) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) (@emp mpred Nveric Sveric)) *)
 apply derives_refl';  f_equal. f_equal. f_equal.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
 apply (nonreadable_list_cell_eq); auto.
*
(* Goal: @derives mpred Nveric (valid_pointer Vundef) (valid_pointer p) *)
unfold lseg; simpl.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
normalize.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh y) (@list_cell cs list_structid list_link list_token ls dsh h y)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) z) y)) (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh x) (@list_cell cs list_structid list_link list_token ls dsh el x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) x0) x)) (lseg ls dsh psh l x0 y))) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) w) z)) (@exp mpred Nveric val (fun x0 : val => @andp mpred Nveric (@prop mpred Nveric (and (@eq val x x) (not (ptr_eq x z)))) (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null x0)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh el x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) x0) x)) (lseg ls dsh psh (@app (prod val (@elemtype cs list_structid list_link list_token ls)) l (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) y h) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) x0 z)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) w) z)))) *)
apply exp_right with x0.
rewrite <- ?sepcon_assoc.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
normalize.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
  autorewrite with subst norm1 norm2; normalize.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh y) (@list_cell cs list_structid list_link list_token ls dsh h y)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) z) y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh el x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) x0) x)) (lseg ls dsh psh l x0 y)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) w) z)) (@andp mpred Nveric (@prop mpred Nveric (and (not (ptr_eq x z)) (is_pointer_or_null x0))) (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh x) (@list_cell cs list_structid list_link list_token ls dsh el x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) x0) x)) (lseg ls dsh psh (@app (prod val (@elemtype cs list_structid list_link list_token ls)) l (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) y h) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) x0 z)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) w) z))) *)
specialize (IHl x0).
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh y) (@list_cell cs list_structid list_link list_token ls dsh h y)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) z) y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh el x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) x0) x)) (lseg ls dsh psh l x0 y)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) w) z)) (@andp mpred Nveric (@prop mpred Nveric (and (not (ptr_eq x z)) (is_pointer_or_null x0))) (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh x) (@list_cell cs list_structid list_link list_token ls dsh el x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) x0) x)) (lseg ls dsh psh (@app (prod val (@elemtype cs list_structid list_link list_token ls)) l (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) y h) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) x0 z)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) w) z))) *)
entailer.
pull_right (list_token dsh x); pull_right (list_cell ls dsh (vund ls) x).
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
apply sepcon_derives; auto.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
apply sepcon_derives; auto.
pull_right (field_at psh list_struct (StructField list_link :: nil)
      (valinject
         (nested_field_type list_struct (StructField list_link :: nil)) x0)
      x).
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
apply sepcon_derives; auto.
Qed.

Lemma lseg_cons_right_null (ls: listspec list_structid list_link list_token): forall dsh psh l x h y,
     ~ (readable_share dsh) ->
             list_token dsh y * list_cell ls dsh h y * field_at psh list_struct (StructField list_link :: nil) (valinject (nested_field_type list_struct (StructField list_link :: nil)) nullval) y *
             lseg ls dsh psh l x y
   |--   lseg ls dsh psh (l++y::nil) x nullval.
Proof.
(* Goal: forall (v' : @elemtype cs list_structid list_link list_token ls) (ash bsh psh : share) (p : val) (v : @elemtype cs list_structid list_link list_token ls) (_ : @sepalg.join share Share.Join_ba ash bsh psh) (_ : not (readable_share ash)) (_ : readable_share bsh), @eq mpred (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls ash v' p) (@list_cell cs list_structid list_link list_token ls bsh v p)) (@list_cell cs list_structid list_link list_token ls psh v p) *)
intros. rename H into NR.
unfold lseg.
(* Goal: forall (v' : @elemtype cs list_structid list_link list_token ls) (ash bsh psh : share) (p : val) (v : @elemtype cs list_structid list_link list_token ls) (_ : @sepalg.join share Share.Join_ba ash bsh psh) (_ : not (readable_share ash)) (_ : readable_share bsh), @eq mpred (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls ash v' p) (@list_cell cs list_structid list_link list_token ls bsh v p)) (@list_cell cs list_structid list_link list_token ls psh v p) *)
revert x; induction l; simpl; intros.
*
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
normalize.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
  autorewrite with subst norm1 norm2; normalize.
apply exp_right with nullval.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh x) (@list_cell cs list_structid list_link list_token ls dsh e x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) x)) (lseg ls dsh psh l tail z)) (@andp mpred Nveric (@prop mpred Nveric (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) v e) l) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) x e) l)) (is_pointer_or_null tail))) (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh x) (@list_cell cs list_structid list_link list_token ls dsh e x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) x)) (lseg ls dsh psh l tail z))) *)
(* Goal: @derives mpred Nveric (@orp mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) x z)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@emp mpred Nveric Sveric)) *)
(* Goal: @derives mpred Nveric (@orp mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) p l) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) p l) x z)) (let (p, h) := p in @andp mpred Nveric (@prop mpred Nveric (and (@eq val p x) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh h x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) x)) (lseg ls dsh psh l tail z)))) *)
apply andp_right.
(* Goal: ptr_neq (Vptr b i) (if Archi.ptr64 then Vlong Int64.zero else Vint Int.zero) *)
apply not_prop_right; intro.
(* Goal: False *)
(* Goal: ptr_neq (Vptr b i) (if Archi.ptr64 then Vlong Int64.zero else Vint Int.zero) *)
apply ptr_eq_e in H. subst y.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh y) (@list_cell cs list_structid list_link list_token ls dsh h y)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) z) y)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) w) z)) (@andp mpred Nveric (@prop mpred Nveric (not (ptr_eq y z))) (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null z)) (list_token dsh y)) (@list_cell cs list_structid list_link list_token ls dsh h y)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) z) y)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq z z)) (@emp mpred Nveric Sveric))) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) w) z))) *)
entailer!.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tl')) (list_token dsh nullval)) (@list_cell cs list_structid list_link list_token ls dsh x nullval)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tl') nullval)) (@emp mpred Nveric Sveric)) (@FF mpred Nveric) *)
destruct H. contradiction H.
(* Goal: @eq mpred (@struct_pred (@nil (prod ident type)) A F v p) (@struct_pred (@nil (prod ident type)) A F v p') *)
(* Goal: @eq mpred (@struct_pred (@cons (prod ident type) a m) A F v p) (@struct_pred (@cons (prod ident type) a m) A F v p') *)
rewrite prop_true_andp by reflexivity.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
rewrite prop_true_andp by normalize.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
normalize.
(* Goal: @eq mpred (@prop mpred Nveric (ptr_eq v v)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) *)
(* Goal: @eq mpred (let (p, h) := p in @andp mpred Nveric (@prop mpred Nveric (and (@eq val p v) (not (ptr_eq v v)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh v)) (@list_cell cs list_structid list_link list_token ls dsh h v)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) v)) (lseg ls dsh psh l tail v)))) (@andp mpred Nveric (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) p l) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) (@emp mpred Nveric Sveric)) *)
apply derives_refl'; f_equal. f_equal.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
apply nonreadable_list_cell_eq; auto.
*
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
normalize.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh y) (@list_cell cs list_structid list_link list_token ls dsh h y)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) z) y)) (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh x) (@list_cell cs list_structid list_link list_token ls dsh el x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) x0) x)) (lseg ls dsh psh l x0 y))) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) w) z)) (@exp mpred Nveric val (fun x0 : val => @andp mpred Nveric (@prop mpred Nveric (and (@eq val x x) (not (ptr_eq x z)))) (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null x0)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh el x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) x0) x)) (lseg ls dsh psh (@app (prod val (@elemtype cs list_structid list_link list_token ls)) l (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) y h) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) x0 z)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) w) z)))) *)
apply exp_right with x0.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
normalize.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
  autorewrite with subst norm1 norm2; normalize.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh y) (@list_cell cs list_structid list_link list_token ls dsh h y)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) z) y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh el x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) x0) x)) (lseg ls dsh psh l x0 y)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) w) z)) (@andp mpred Nveric (@prop mpred Nveric (and (not (ptr_eq x z)) (is_pointer_or_null x0))) (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh x) (@list_cell cs list_structid list_link list_token ls dsh el x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) x0) x)) (lseg ls dsh psh (@app (prod val (@elemtype cs list_structid list_link list_token ls)) l (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) y h) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) x0 z)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) w) z))) *)
specialize (IHl x0).
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh x) (@list_cell cs list_structid list_link list_token ls dsh e x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) x)) (lseg ls dsh psh l tail z)) (@andp mpred Nveric (@prop mpred Nveric (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) v e) l) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) x e) l)) (is_pointer_or_null tail))) (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh x) (@list_cell cs list_structid list_link list_token ls dsh e x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) x)) (lseg ls dsh psh l tail z))) *)
(* Goal: @derives mpred Nveric (@orp mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) x z)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@emp mpred Nveric Sveric)) *)
(* Goal: @derives mpred Nveric (@orp mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) p l) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) p l) x z)) (let (p, h) := p in @andp mpred Nveric (@prop mpred Nveric (and (@eq val p x) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh h x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) x)) (lseg ls dsh psh l tail z)))) *)
apply andp_right.
rewrite prop_and.
apply andp_right; [ | apply prop_right; auto].
(* Goal: ptr_neq (Vptr b i) (if Archi.ptr64 then Vlong Int64.zero else Vint Int.zero) *)
apply not_prop_right; intro.
apply ptr_eq_e in H0. subst x.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh y) (@list_cell cs list_structid list_link list_token ls dsh h y)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) z) y)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh el x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) x0) x)) (lseg ls dsh psh l x0 y)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) w) z)) (@andp mpred Nveric (@prop mpred Nveric (and (not (ptr_eq x z)) (is_pointer_or_null x0))) (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh x) (@list_cell cs list_structid list_link list_token ls dsh el x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) x0) x)) (lseg ls dsh psh (@app (prod val (@elemtype cs list_structid list_link list_token ls)) l (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) y h) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) x0 z)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) w) z))) *)
entailer.
destruct H3; contradiction H3.
eapply derives_trans.
2: apply sepcon_derives; [ | eassumption]; apply derives_refl.
clear IHl.
cancel.
Qed.


Lemma lseg_cons_right_list (ls: listspec list_structid list_link list_token):
      forall dsh psh l l' x h y z,
     sepalg.nonidentity psh ->
     ~ (readable_share dsh) ->
             list_token dsh y * list_cell ls dsh h y * field_at psh list_struct (StructField list_link :: nil) (valinject (nested_field_type list_struct (StructField list_link :: nil)) z) y *
             lseg ls dsh psh l x y * lseg ls dsh psh l' z nullval
   |--   lseg ls dsh psh (l++y::nil) x z * lseg ls dsh psh l' z nullval.
Proof.
(* Goal: forall (v' : @elemtype cs list_structid list_link list_token ls) (ash bsh psh : share) (p : val) (v : @elemtype cs list_structid list_link list_token ls) (_ : @sepalg.join share Share.Join_ba ash bsh psh) (_ : not (readable_share ash)) (_ : readable_share bsh), @eq mpred (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls ash v' p) (@list_cell cs list_structid list_link list_token ls bsh v p)) (@list_cell cs list_structid list_link list_token ls psh v p) *)
intros.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh y) (@list_cell cs list_structid list_link list_token ls dsh h y)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) z) y)) (lseg ls dsh psh l x y)) (lseg ls dsh psh l' z nullval)) (@sepcon mpred Nveric Sveric (lseg ls dsh psh (@app (prod val (@elemtype cs list_structid list_link list_token ls)) l (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) y h) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) x z) (lseg ls dsh psh l' z nullval)) *)
destruct l'.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh y) (@list_cell cs list_structid list_link list_token ls dsh h y)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) z) y)) (lseg ls dsh psh l x y)) (lseg ls dsh psh (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) z nullval)) (@sepcon mpred Nveric Sveric (lseg ls dsh psh (@app (prod val (@elemtype cs list_structid list_link list_token ls)) l (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) y h) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) x z) (lseg ls dsh psh (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) z nullval)) *)
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh y) (@list_cell cs list_structid list_link list_token ls dsh h y)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) z) y)) (lseg ls dsh psh l x y)) (lseg ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) p l') z nullval)) (@sepcon mpred Nveric Sveric (lseg ls dsh psh (@app (prod val (@elemtype cs list_structid list_link list_token ls)) l (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) y h) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) x z) (lseg ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) p l') z nullval)) *)
rewrite lseg_nil_eq.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
normalize.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
apply lseg_cons_right_null; auto.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
rewrite lseg_cons_eq; auto.
(* Goal: and True (iff (@eq val (Vptr b0 i) (Vptr b0 i0)) (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) *)
(* Goal: @derives mpred Nveric (let (p0, h) := p0 in @andp mpred Nveric (@prop mpred Nveric (and (@eq val p0 p) (not (ptr_eq p q)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh p)) (@list_cell cs list_structid list_link list_token ls dsh h p)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) p)) (lseg ls dsh psh contents tail q)))) (@prop mpred Nveric (and (is_pointer_or_null p) (iff (@eq val p q) (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) p0 contents) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))))) *)
Intros u. Exists u. subst.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
rewrite !prop_true_andp by auto.
rewrite <- !sepcon_assoc.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
apply sepcon_derives; auto.
pull_right (list_cell ls dsh (vund ls) v).
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
apply sepcon_derives; auto.
pull_right (list_token dsh v).
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
apply sepcon_derives; auto.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
apply lseg_cons_right_neq; auto.
Qed.

Lemma lseg_unroll_right (ls: listspec list_structid list_link list_token): forall sh sh' l x z ,
    lseg ls sh sh' l x z = (!! (ptr_eq x z) && !! (l=nil) && emp) || lseg_cons_right ls sh sh' l x z.
Abort.  (* not likely true *)

Lemma lseg_local_facts:
  forall ls dsh psh contents p q,
     lseg ls dsh psh contents p q |--
     !! (is_pointer_or_null p /\ (p=q <-> contents=nil)).
Proof.
(* Goal: forall (v' : @elemtype cs list_structid list_link list_token ls) (ash bsh psh : share) (p : val) (v : @elemtype cs list_structid list_link list_token ls) (_ : @sepalg.join share Share.Join_ba ash bsh psh) (_ : not (readable_share ash)) (_ : readable_share bsh), @eq mpred (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls ash v' p) (@list_cell cs list_structid list_link list_token ls bsh v p)) (@list_cell cs list_structid list_link list_token ls psh v p) *)
intros.
(* Goal: @derives mpred Nveric (lseg ls dsh psh contents p q) (@prop mpred Nveric (and (is_pointer_or_null p) (iff (@eq val p q) (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) contents (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))))) *)
rewrite lseg_unfold.
(* Goal: @derives mpred Nveric match contents with | nil => @andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric) | cons (pair p1 h as p0) t => @andp mpred Nveric (@prop mpred Nveric (and (@eq val p1 p) (not (ptr_eq p q)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh p)) (@list_cell cs list_structid list_link list_token ls dsh h p)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) p)) (lseg ls dsh psh t tail q))) end (@prop mpred Nveric (and (is_pointer_or_null p) (iff (@eq val p q) (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) contents (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))))) *)
destruct contents.
(* Goal: ptr_neq (Vptr b i) (if Archi.ptr64 then Vlong Int64.zero else Vint Int.zero) *)
apply derives_extract_prop; intro.
(* Goal: @derives mpred Nveric (@emp mpred Nveric Sveric) (@prop mpred Nveric (and (is_pointer_or_null p) (iff (@eq val p q) (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))))) *)
(* Goal: @derives mpred Nveric (let (p0, h) := p0 in @andp mpred Nveric (@prop mpred Nveric (and (@eq val p0 p) (not (ptr_eq p q)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh p)) (@list_cell cs list_structid list_link list_token ls dsh h p)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) p)) (lseg ls dsh psh contents tail q)))) (@prop mpred Nveric (and (is_pointer_or_null p) (iff (@eq val p q) (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) p0 contents) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))))) *)
unfold ptr_eq in H.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh p) (@list_cell cs list_structid list_link list_token ls dsh e p)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) p)) (lseg ls dsh psh contents tail q)) (@prop mpred Nveric (iff (@eq val p q) (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) p e) contents) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) *)
apply prop_right.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
destruct p; try contradiction; simpl; auto.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
destruct q; try contradiction; auto.
(* Goal: and (if Archi.ptr64 then @eq Int64.int i Int64.zero else False) (iff (@eq val (Vlong i) (Vlong i0)) (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) *)
(* Goal: and True (iff (@eq val (Vptr b i) q) (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) *)
(* Goal: @derives mpred Nveric (let (p0, h) := p0 in @andp mpred Nveric (@prop mpred Nveric (and (@eq val p0 p) (not (ptr_eq p q)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh p)) (@list_cell cs list_structid list_link list_token ls dsh h p)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) p)) (lseg ls dsh psh contents tail q)))) (@prop mpred Nveric (and (is_pointer_or_null p) (iff (@eq val p q) (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) p0 contents) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))))) *)
destruct H as [? [? ?]]. rewrite H.
unfold Int.cmpu in *.
(* Goal: and (if Archi.ptr64 then False else @eq Int.int i Int.zero) (iff (@eq val (Vint i) (Vint i0)) (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) *)
(* Goal: and (if Archi.ptr64 then @eq Int64.int i Int64.zero else False) (iff (@eq val (Vlong i) q) (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) *)
(* Goal: and True (iff (@eq val (Vptr b i) q) (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) *)
(* Goal: @derives mpred Nveric (let (p0, h) := p0 in @andp mpred Nveric (@prop mpred Nveric (and (@eq val p0 p) (not (ptr_eq p q)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh p)) (@list_cell cs list_structid list_link list_token ls dsh h p)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) p)) (lseg ls dsh psh contents tail q)))) (@prop mpred Nveric (and (is_pointer_or_null p) (iff (@eq val p q) (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) p0 contents) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))))) *)
apply int_eq_e in H0.
(* Goal: and True (iff (@eq val (Vptr b0 i) (Vptr b0 i0)) (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) *)
(* Goal: @derives mpred Nveric (let (p0, h) := p0 in @andp mpred Nveric (@prop mpred Nveric (and (@eq val p0 p) (not (ptr_eq p q)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh p)) (@list_cell cs list_structid list_link list_token ls dsh h p)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) p)) (lseg ls dsh psh contents tail q)))) (@prop mpred Nveric (and (is_pointer_or_null p) (iff (@eq val p q) (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) p0 contents) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))))) *)
apply int_eq_e in H1. subst.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
split; auto; split; auto.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
destruct q; try contradiction; auto.
(* Goal: and (if Archi.ptr64 then @eq Int64.int i Int64.zero else False) (iff (@eq val (Vlong i) (Vlong i0)) (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) *)
(* Goal: and True (iff (@eq val (Vptr b i) q) (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) *)
(* Goal: @derives mpred Nveric (let (p0, h) := p0 in @andp mpred Nveric (@prop mpred Nveric (and (@eq val p0 p) (not (ptr_eq p q)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh p)) (@list_cell cs list_structid list_link list_token ls dsh h p)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) p)) (lseg ls dsh psh contents tail q)))) (@prop mpred Nveric (and (is_pointer_or_null p) (iff (@eq val p q) (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) p0 contents) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))))) *)
destruct H as [? [? ?]]. rewrite H.
unfold Int64.cmpu in *.
(* Goal: and (if Archi.ptr64 then @eq Int64.int i Int64.zero else False) (iff (@eq val (Vlong i) (Vlong i0)) (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) *)
(* Goal: and True (iff (@eq val (Vptr b i) q) (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) *)
(* Goal: @derives mpred Nveric (let (p0, h) := p0 in @andp mpred Nveric (@prop mpred Nveric (and (@eq val p0 p) (not (ptr_eq p q)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh p)) (@list_cell cs list_structid list_link list_token ls dsh h p)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) p)) (lseg ls dsh psh contents tail q)))) (@prop mpred Nveric (and (is_pointer_or_null p) (iff (@eq val p q) (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) p0 contents) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))))) *)
apply int64_eq_e in H0.
(* Goal: and True (iff (@eq val (Vptr b0 i) (Vptr b0 i0)) (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) *)
(* Goal: @derives mpred Nveric (let (p0, h) := p0 in @andp mpred Nveric (@prop mpred Nveric (and (@eq val p0 p) (not (ptr_eq p q)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh p)) (@list_cell cs list_structid list_link list_token ls dsh h p)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) p)) (lseg ls dsh psh contents tail q)))) (@prop mpred Nveric (and (is_pointer_or_null p) (iff (@eq val p q) (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) p0 contents) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))))) *)
apply int64_eq_e in H1. subst.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
split; auto; split; auto.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
destruct q; try contradiction; auto.
(* Goal: and True (iff (@eq val (Vptr b0 i) (Vptr b0 i0)) (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) *)
(* Goal: @derives mpred Nveric (let (p0, h) := p0 in @andp mpred Nveric (@prop mpred Nveric (and (@eq val p0 p) (not (ptr_eq p q)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh p)) (@list_cell cs list_structid list_link list_token ls dsh h p)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) p)) (lseg ls dsh psh contents tail q)))) (@prop mpred Nveric (and (is_pointer_or_null p) (iff (@eq val p q) (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) p0 contents) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))))) *)
destruct H; subst.
unfold Ptrofs.cmpu in *.
(* Goal: and True (iff (@eq val (Vptr b0 i) (Vptr b0 i0)) (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) *)
(* Goal: @derives mpred Nveric (let (p0, h) := p0 in @andp mpred Nveric (@prop mpred Nveric (and (@eq val p0 p) (not (ptr_eq p q)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh p)) (@list_cell cs list_structid list_link list_token ls dsh h p)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) p)) (lseg ls dsh psh contents tail q)))) (@prop mpred Nveric (and (is_pointer_or_null p) (iff (@eq val p q) (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) p0 contents) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))))) *)
apply ptrofs_eq_e in H0. subst.
(* Goal: and True (iff (@eq val (Vptr b0 i0) (Vptr b0 i0)) (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) *)
(* Goal: @derives mpred Nveric (let (p0, h) := p0 in @andp mpred Nveric (@prop mpred Nveric (and (@eq val p0 p) (not (ptr_eq p q)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh p)) (@list_cell cs list_structid list_link list_token ls dsh h p)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) p)) (lseg ls dsh psh contents tail q)))) (@prop mpred Nveric (and (is_pointer_or_null p) (iff (@eq val p q) (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) p0 contents) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))))) *)
intuition.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
normalize.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh p) (@list_cell cs list_structid list_link list_token ls dsh e p)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) p)) (lseg ls dsh psh contents tail q)) (@prop mpred Nveric (and (is_pointer_or_null p) (iff (@eq val p q) (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) p e) contents) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))))) *)
rewrite field_at_isptr.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
normalize.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
  autorewrite with subst norm1 norm2; normalize.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh p) (@list_cell cs list_structid list_link list_token ls dsh e p)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) p)) (lseg ls dsh psh contents tail q)) (@prop mpred Nveric (iff (@eq val p q) (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) p e) contents) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) *)
apply prop_right.
(* Goal: iff (@eq val p q) (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) p e) contents) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))) *)
split. intro; subst q.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
contradiction H. normalize.
(* Goal: forall (v' : @elemtype cs list_structid list_link list_token ls) (ash bsh psh : share) (p : val) (v : @elemtype cs list_structid list_link list_token ls) (_ : @sepalg.join share Share.Join_ba ash bsh psh) (_ : not (readable_share ash)) (_ : readable_share bsh), @eq mpred (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls ash v' p) (@list_cell cs list_structid list_link list_token ls bsh v p)) (@list_cell cs list_structid list_link list_token ls psh v p) *)
intros. discriminate.
Qed.

Definition lseg_cell  (ls: listspec list_structid list_link list_token)
    (dsh psh : share)
    (v: elemtype ls) (x y: val) :=
   !!is_pointer_or_null y && list_token dsh x * list_cell ls dsh v x * field_at psh list_struct (StructField list_link :: nil) (valinject (nested_field_type list_struct (StructField list_link :: nil)) y) x.

Lemma lseg_cons_eq2: forall
  (ls : listspec list_structid list_link list_token) (dsh psh : share) (h : elemtype ls)
   (r : list val )  (x z : val),
     ~ (readable_share dsh) ->
  lseg ls dsh psh (x :: r) x z =
  !!(~ ptr_eq x z) && (EX  y : val, lseg_cell ls dsh psh h x y * lseg ls dsh psh r y z).
Proof.
(* Goal: forall (v' : @elemtype cs list_structid list_link list_token ls) (ash bsh psh : share) (p : val) (v : @elemtype cs list_structid list_link list_token ls) (_ : @sepalg.join share Share.Join_ba ash bsh psh) (_ : not (readable_share ash)) (_ : readable_share bsh), @eq mpred (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls ash v' p) (@list_cell cs list_structid list_link list_token ls bsh v p)) (@list_cell cs list_structid list_link list_token ls psh v p) *)
  intros.
  rewrite -> lseg_cons_eq by auto.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (lseg_cell ls dsh psh x nullval tl') (@emp mpred Nveric Sveric)) (@FF mpred Nveric) *)
  unfold lseg_cell.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
 normalize.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
  autorewrite with subst norm1 norm2; normalize.
(* Goal: @eq mpred (@prop mpred Nveric (ptr_eq v v)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) *)
(* Goal: @eq mpred (let (p, h) := p in @andp mpred Nveric (@prop mpred Nveric (and (@eq val p v) (not (ptr_eq v v)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh v)) (@list_cell cs list_structid list_link list_token ls dsh h v)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) v)) (lseg ls dsh psh l tail v)))) (@andp mpred Nveric (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) p l) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) (@emp mpred Nveric Sveric)) *)
 f_equal. extensionality y.
(* Goal: @eq mpred (@prop mpred Nveric (ptr_eq v v)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) *)
(* Goal: @eq mpred (let (p, h) := p in @andp mpred Nveric (@prop mpred Nveric (and (@eq val p v) (not (ptr_eq v v)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh v)) (@list_cell cs list_structid list_link list_token ls dsh h v)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) v)) (lseg ls dsh psh l tail v)))) (@andp mpred Nveric (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) p l) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))) (@emp mpred Nveric Sveric)) *)
 f_equal. f_equal. f_equal. f_equal.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
 apply nonreadable_list_cell_eq; auto.
Qed.

Lemma list_append: forall {dsh psh: share}
  {ls : listspec list_structid list_link list_token} (hd mid tl:val) ct1 ct2 P,
  (forall tl', lseg_cell ls dsh psh (vund ls) tl tl' * P tl |-- FF) ->
  (lseg ls dsh psh ct1 hd mid) * lseg ls dsh psh ct2 mid tl * P tl|--
  (lseg ls dsh psh (ct1 ++ ct2) hd tl) * P tl.
Proof.
(* Goal: forall (v' : @elemtype cs list_structid list_link list_token ls) (ash bsh psh : share) (p : val) (v : @elemtype cs list_structid list_link list_token ls) (_ : @sepalg.join share Share.Join_ba ash bsh psh) (_ : not (readable_share ash)) (_ : readable_share bsh), @eq mpred (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls ash v' p) (@list_cell cs list_structid list_link list_token ls bsh v p)) (@list_cell cs list_structid list_link list_token ls psh v p) *)
 intros.
 unfold lseg.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
 revert hd; induction ct1; simpl; intros; auto.
*
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
 normalize.
*
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
 normalize.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
 progress (autorewrite with subst norm1 norm2); normalize.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh p) (@list_cell cs list_structid list_link list_token ls dsh h p)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) p)) (lseg ls dsh psh r y z)) (@exp mpred Nveric val (fun y : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) p h) r) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) p h) r)) (is_pointer_or_null y))) (list_token dsh p)) (@list_cell cs list_structid list_link list_token ls dsh h p)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) y) p)) (lseg ls dsh psh r y z))) *)
 apply exp_right with y.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh x) (@list_cell cs list_structid list_link list_token ls dsh e x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) x)) (lseg ls dsh psh l tail z)) (@andp mpred Nveric (@prop mpred Nveric (and (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) v e) l) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) (@pair val (@elemtype cs list_structid list_link list_token ls) x e) l)) (is_pointer_or_null tail))) (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh x) (@list_cell cs list_structid list_link list_token ls dsh e x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) x)) (lseg ls dsh psh l tail z))) *)
(* Goal: @derives mpred Nveric (@orp mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh (@nil (prod val (@elemtype cs list_structid list_link list_token ls))) x z)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@emp mpred Nveric Sveric)) *)
(* Goal: @derives mpred Nveric (@orp mpred Nveric (@andp mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq x z)) (@prop mpred Nveric (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) p l) (@nil (prod val (@elemtype cs list_structid list_link list_token ls)))))) (@emp mpred Nveric Sveric)) (lseg_cons ls dsh psh (@cons (prod val (@elemtype cs list_structid list_link list_token ls)) p l) x z)) (let (p, h) := p in @andp mpred Nveric (@prop mpred Nveric (and (@eq val p x) (not (ptr_eq x z)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh x)) (@list_cell cs list_structid list_link list_token ls dsh h x)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) x)) (lseg ls dsh psh l tail z)))) *)
 apply andp_right.
 +
(* Goal: ptr_neq (Vptr b i) (if Archi.ptr64 then Vlong Int64.zero else Vint Int.zero) *)
  apply not_prop_right; intro. apply ptr_eq_e in H1; subst hd.
  clear IHct1.
  specialize (H y).
  unfold lseg_cell in H.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
  rewrite prop_true_andp in H by auto.
  change (LsegGeneral.lseg ls dsh psh (map (fun v : val => (v, vund ls)) ct1))
    with (lseg ls dsh psh ct1).
  change (LsegGeneral.lseg ls dsh psh (map (fun v : val => (v, vund ls)) ct2))
    with (lseg ls dsh psh ct2).
  apply derives_trans with
        (lseg ls dsh psh ct1 y mid * lseg ls dsh psh ct2 mid tl * FF).
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
  cancel. auto.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
  rewrite sepcon_FF; auto.
 +
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
  normalize.
  specialize (IHct1 y). clear H.
(* Goal: @derives mpred Nveric P (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (list_token dsh v1) (@list_cell cs list_structid list_link list_token ls dsh h v1)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) p) v1)) (lseg ls dsh psh tail p v2)) *)
   do 2 rewrite sepcon_assoc.
  eapply derives_trans.
 apply sepcon_derives.
  apply derives_refl.
  rewrite <- !sepcon_assoc; eassumption.
  cancel.
Qed.

Lemma list_append_null:
  forall
   (ls: listspec list_structid list_link list_token)
   (dsh psh: share)
   (hd mid: val) ct1 ct2,
   lseg ls dsh psh ct1 hd mid * lseg ls dsh psh ct2 mid nullval |--
   lseg ls dsh psh (ct1++ct2) hd nullval.
Proof.
(* Goal: forall (v' : @elemtype cs list_structid list_link list_token ls) (ash bsh psh : share) (p : val) (v : @elemtype cs list_structid list_link list_token ls) (_ : @sepalg.join share Share.Join_ba ash bsh psh) (_ : not (readable_share ash)) (_ : readable_share bsh), @eq mpred (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls ash v' p) (@list_cell cs list_structid list_link list_token ls bsh v p)) (@list_cell cs list_structid list_link list_token ls psh v p) *)
intros.
 rewrite <- sepcon_emp.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (lseg ls dsh psh ct1 hd mid) (lseg ls dsh psh ct2 mid nullval)) (@sepcon mpred Nveric Sveric (lseg ls dsh psh (@app (prod val (@elemtype cs list_structid list_link list_token ls)) ct1 ct2) hd nullval) (@emp mpred Nveric Sveric)) *)
 eapply derives_trans; [ | apply (list_append hd mid nullval ct1 ct2 (fun _ => emp))].
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
 normalize.
(* Goal: forall (v' : @elemtype cs list_structid list_link list_token ls) (ash bsh psh : share) (p : val) (v : @elemtype cs list_structid list_link list_token ls) (_ : @sepalg.join share Share.Join_ba ash bsh psh) (_ : not (readable_share ash)) (_ : readable_share bsh), @eq mpred (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls ash v' p) (@list_cell cs list_structid list_link list_token ls bsh v p)) (@list_cell cs list_structid list_link list_token ls psh v p) *)
 intros.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tl')) (list_token dsh nullval)) (@list_cell cs list_structid list_link list_token ls dsh x nullval)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tl') nullval)) (@emp mpred Nveric Sveric)) (@FF mpred Nveric) *)
  unfold lseg_cell. simpl. saturate_local. destruct H. contradiction H.
Qed.

Lemma list_cell_valid_pointer:
  forall (LS: listspec list_structid list_link list_token) (dsh psh: Share.t) v p,
   sepalg.nonidentity dsh ->
   sepalg.join_sub dsh psh ->
   field_offset cenv_cs list_link list_fields + sizeof (field_type list_link list_fields)
   = field_offset_next cenv_cs list_link list_fields  (co_sizeof (get_co list_structid)) ->
   list_cell LS dsh v p * field_at_ psh list_struct (StructField list_link::nil) p
  |-- valid_pointer p.
Proof.
  intros ? ? ? ? ? NON_ID ? ?.
 destruct H as [bsh ?].
 rewrite <- (field_at__share_join _ _ _ _ _ _ H).
 rewrite <- sepcon_assoc.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
 rewrite list_cell_link_join_nospacer; auto.
 apply sepcon_valid_pointer1.
(* Goal: @derives mpred Nveric (@data_at cs sh (@list_struct cs list_structid list_link list_token LS) (@list_data cs list_structid list_link list_token LS v) p) (valid_pointer p) *)
 unfold data_at_, field_at_, data_at.
(* Goal: @derives mpred Nveric (@field_at cs sh (@list_struct cs list_structid list_link list_token LS) (@nil gfield) (@list_data cs list_structid list_link list_token LS v) p) (valid_pointer p) *)
 eapply derives_trans; [ apply field_at_valid_ptr; auto | ].
(* Goal: Z.gt (@sizeof (@cenv_cs cs) (@nested_field_type cs (@list_struct cs list_structid list_link list_token LS) (@nil gfield))) Z0 *)
(* Goal: @derives mpred Nveric (valid_pointer (@field_address cs (@list_struct cs list_structid list_link list_token LS) (@nil gfield) p)) (valid_pointer p) *)
 change (nested_field_type list_struct nil) with list_struct.
(* Goal: Z.gt (@sizeof (@cenv_cs cs) (@list_struct cs list_structid list_link list_token LS)) Z0 *)
(* Goal: @derives mpred Nveric (valid_pointer (@field_address cs (@list_struct cs list_structid list_link list_token LS) (@nil gfield) p)) (valid_pointer p) *)
 apply LsegGeneral.sizeof_list_struct_pos.
(* Goal: @derives mpred Nveric (valid_pointer (@field_address cs (@list_struct cs list_structid list_link list_token LS) (@nil gfield) p)) (valid_pointer p) *)
 unfold field_address.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
 if_tac; auto.
(* Goal: @derives mpred Nveric (valid_pointer (offset_val (@nested_field_offset cs (@list_struct cs list_structid list_link list_token LS) (@nil gfield)) p)) (valid_pointer p) *)
(* Goal: @derives mpred Nveric (valid_pointer Vundef) (valid_pointer p) *)
 change (Int.repr (nested_field_offset list_struct nil)) with Int.zero.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
  rewrite valid_pointer_offset_val_zero; auto.
(* Goal: @derives mpred Nveric (valid_pointer Vundef) (valid_pointer p) *)
 simpl.
(* Goal: @derives mpred Nveric (@predicates_hered.FF compcert_rmaps.RML.R.rmap compcert_rmaps.RML.R.ag_rmap) (valid_pointer p) *)
 change predicates_hered.FF with FF. apply FF_left.
Qed.

Lemma list_cell_valid_pointerx:
  forall (ls : listspec list_structid list_link list_token)  sh v p,
   sh <> Share.bot ->
   list_cell ls sh v p |-- valid_pointer p.
Proof.
(* Goal: forall (v' : @elemtype cs list_structid list_link list_token ls) (ash bsh psh : share) (p : val) (v : @elemtype cs list_structid list_link list_token ls) (_ : @sepalg.join share Share.Join_ba ash bsh psh) (_ : not (readable_share ash)) (_ : readable_share bsh), @eq mpred (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls ash v' p) (@list_cell cs list_structid list_link list_token ls bsh v p)) (@list_cell cs list_structid list_link list_token ls psh v p) *)
 intros.
(* Goal: @derives mpred Nveric (@list_cell cs list_structid list_link list_token0 ls sh v p) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
 unfold list_cell.
Abort.  (* probably not true; would be true with a direct (non-magic-wand)
      definition of list_cell *)

Lemma lseg_valid_pointer:
  forall (ls : listspec list_structid list_link list_token) dsh psh contents p q R,
   sepalg.nonidentity dsh ->
   dsh <> Share.bot ->
   sepalg.join_sub dsh psh ->
   field_offset cenv_cs list_link list_fields + sizeof (field_type list_link list_fields)
   = field_offset_next cenv_cs list_link list_fields  (co_sizeof (get_co list_structid)) ->
    R |-- valid_pointer q ->
    R * lseg ls dsh psh contents p q |-- valid_pointer p.
Proof.
(* Goal: forall (v' : @elemtype cs list_structid list_link list_token ls) (ash bsh psh : share) (p : val) (v : @elemtype cs list_structid list_link list_token ls) (_ : @sepalg.join share Share.Join_ba ash bsh psh) (_ : not (readable_share ash)) (_ : readable_share bsh), @eq mpred (@sepcon mpred Nveric Sveric (@list_cell cs list_structid list_link list_token ls ash v' p) (@list_cell cs list_structid list_link list_token ls bsh v p)) (@list_cell cs list_structid list_link list_token ls psh v p) *)
intros.
(* Goal: @derives mpred Nveric match contents with | nil => @andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric) | cons (pair p1 h as p0) t => @andp mpred Nveric (@prop mpred Nveric (and (@eq val p1 p) (not (ptr_eq p q)))) (@exp mpred Nveric val (fun tail : val => @sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tail)) (list_token dsh p)) (@list_cell cs list_structid list_link list_token ls dsh h p)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tail) p)) (lseg ls dsh psh t tail q))) end (@prop mpred Nveric (and (is_pointer_or_null p) (iff (@eq val p q) (@eq (list (prod val (@elemtype cs list_structid list_link list_token ls))) contents (@nil (prod val (@elemtype cs list_structid list_link list_token ls))))))) *)
destruct contents.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
rewrite lseg_nil_eq. normalize.
(* Goal: @derives mpred Nveric (valid_pointer Vundef) (valid_pointer p) *)
unfold lseg; simpl.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) (@struct_pred (@all_but_link list_link (@list_fields cs list_structid list_link list_token0 ls)) (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) (fun (it : prod ident type) (v : @reptype cs (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls))) => withspacer sh (Z.add (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) (@sizeof (@cenv_cs cs) (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) (field_offset_next (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls) (co_sizeof (@get_co cs list_structid))) (at_offset (@data_at_rec cs sh (field_type (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)) v) (field_offset (@cenv_cs cs) (@fst ident type it) (@list_fields cs list_structid list_link list_token0 ls)))) v p)) (@prop mpred Nveric (@field_compatible cs (@list_struct cs list_structid list_link list_token0 ls) (@nil gfield) p)) *)
normalize.
apply sepcon_valid_pointer2.
rewrite !sepcon_assoc.
apply sepcon_valid_pointer2.
rewrite <- !sepcon_assoc.
apply sepcon_valid_pointer1.
eapply derives_trans with
  (list_cell ls dsh (vund  ls) p * field_at_ psh list_struct (StructField list_link :: nil) p).
cancel.
(* Goal: @derives mpred Nveric (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) (@andp mpred Nveric (@prop mpred Nveric (ptr_eq p q)) (@emp mpred Nveric Sveric)) *)
apply list_cell_valid_pointer; auto.
Qed.

End LIST2.

Lemma join_sub_Tsh:
  forall sh, sepalg.join_sub sh Tsh.
Admitted. (* easy *)
Hint Resolve join_sub_Tsh: valid_pointer.

Hint Rewrite @lseg_nil_eq : norm.

Hint Rewrite @lseg_eq using reflexivity: norm.

(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (is_pointer_or_null tl')) (list_token dsh nullval)) (@list_cell cs list_structid list_link list_token ls dsh x nullval)) (@field_at cs psh (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield)) (@valinject cs (@nested_field_type cs (@list_struct cs list_structid list_link list_token ls) (@cons gfield (StructField list_link) (@nil gfield))) tl') nullval)) (@emp mpred Nveric Sveric)) (@FF mpred Nveric) *)
Hint Resolve @lseg_local_facts : saturate_local.

Hint Resolve denote_tc_test_eq_split : valid_pointer.

Ltac resolve_lseg_valid_pointer :=
match goal with
 | |- ?Q |-- valid_pointer ?p =>
   match Q with context [lseg ?A ?B ?C ?D p ?q] =>
   repeat rewrite <- sepcon_assoc;
   pull_right (lseg A B C D p q);
   apply lseg_valid_pointer; [auto | | | reflexivity | ];
   auto 50 with valid_pointer
   end
 end.

Hint Extern 10 (_ |-- valid_pointer _) =>
       resolve_lseg_valid_pointer : valid_pointer.

Ltac resolve_list_cell_valid_pointer :=
 match goal with |- ?A |-- valid_pointer ?p =>
  match A with context [@list_cell ?cs ?sid ?lid ?tok ?LS ?dsh ?v p] =>
   match A with context [field_at ?psh ?t (StructField lid::nil) ?v' p] =>
    apply derives_trans with
      (@list_cell cs sid lid tok LS dsh v p *
      field_at_ psh t (StructField lid::nil) p * TT);
      [cancel
      | apply sepcon_valid_pointer1;
        apply list_cell_valid_pointer; [auto | | reflexivity]; auto with valid_pointer]
   end
  end
 end.

Hint Extern 10 (_ |-- valid_pointer _) =>
   resolve_list_cell_valid_pointer : valid_pointer.

End Links.

Arguments elemtype {cs} {list_structid} {list_link} {list_token} ls / .

