bedrock.lang.cpp.logic.translation_unit
(*
* Copyright (c) 2020 BedRock Systems, Inc.
* This software is distributed under the terms of the BedRock Open-Source License.
* See the LICENSE-BedRock file in the repository root for details.
*)
* Copyright (c) 2020 BedRock Systems, Inc.
* This software is distributed under the terms of the BedRock Open-Source License.
* See the LICENSE-BedRock file in the repository root for details.
*)
this module provides a denotational/axiomatic semantics to c++ compilation
units.
Require Import bedrock.prelude.base.
Require Import bedrock.lang.cpp.syntax.
Require Import bedrock.lang.cpp.semantics.
Require Import bedrock.lang.cpp.logic.pred.
Require Import bedrock.lang.cpp.logic.path_pred.
Require Import bedrock.lang.cpp.logic.heap_pred.
Require Import bedrock.lang.proofmode.proofmode.
Import ChargeNotation.
Section with_cpp.
Context `{Σ : cpp_logic} {σ : genv}.
Definition init_validR (ty : type) : Rep :=
if zero_sized_array ty then
validR
else
svalidR.
#[global] Instance init_validR_persistent : Persistent1 init_validR.
Proof. intros; rewrite /init_validR; case_match; apply _. Qed.
#[global] Instance init_validR_affine : Affine1 init_validR := _.
Definition denoteSymbol (tu : translation_unit) (n : obj_name) (o : ObjValue) : mpred :=
_global n |->
match o with
| Ovar t e => init_validR t
| Ofunction f =>
match f.(f_body) with
| None => svalidR
| Some body => as_Rep (code_at tu f)
end
| Omethod m =>
match m.(m_body) with
| None => svalidR
| Some body => as_Rep (method_at tu m)
end
| Oconstructor c =>
match c.(c_body) with
| None => svalidR
| Some body => as_Rep (ctor_at tu c)
end
| Odestructor d =>
match d.(d_body) with
| None => svalidR
| Some body => as_Rep (dtor_at tu d)
end
end.
#[global] Instance denoteSymbol_persistent {tu n o} : Persistent (denoteSymbol tu n o).
Proof. rewrite /denoteSymbol; repeat case_match; apply _. Qed.
#[global] Instance denoteSymbol_affine {tu n o} : Affine (denoteSymbol tu n o) := _.
Require Import bedrock.lang.cpp.syntax.
Require Import bedrock.lang.cpp.semantics.
Require Import bedrock.lang.cpp.logic.pred.
Require Import bedrock.lang.cpp.logic.path_pred.
Require Import bedrock.lang.cpp.logic.heap_pred.
Require Import bedrock.lang.proofmode.proofmode.
Import ChargeNotation.
Section with_cpp.
Context `{Σ : cpp_logic} {σ : genv}.
Definition init_validR (ty : type) : Rep :=
if zero_sized_array ty then
validR
else
svalidR.
#[global] Instance init_validR_persistent : Persistent1 init_validR.
Proof. intros; rewrite /init_validR; case_match; apply _. Qed.
#[global] Instance init_validR_affine : Affine1 init_validR := _.
Definition denoteSymbol (tu : translation_unit) (n : obj_name) (o : ObjValue) : mpred :=
_global n |->
match o with
| Ovar t e => init_validR t
| Ofunction f =>
match f.(f_body) with
| None => svalidR
| Some body => as_Rep (code_at tu f)
end
| Omethod m =>
match m.(m_body) with
| None => svalidR
| Some body => as_Rep (method_at tu m)
end
| Oconstructor c =>
match c.(c_body) with
| None => svalidR
| Some body => as_Rep (ctor_at tu c)
end
| Odestructor d =>
match d.(d_body) with
| None => svalidR
| Some body => as_Rep (dtor_at tu d)
end
end.
#[global] Instance denoteSymbol_persistent {tu n o} : Persistent (denoteSymbol tu n o).
Proof. rewrite /denoteSymbol; repeat case_match; apply _. Qed.
#[global] Instance denoteSymbol_affine {tu n o} : Affine (denoteSymbol tu n o) := _.
is_strict_valid o states that if the declaration o occurs in a
translation unit, the pointer to it is guaranteed to be strictly valid.
Definition is_strict_valid (o : ObjValue) : bool :=
match o with
| Ovar t _ => negb (zero_sized_array t)
| _ => true
end.
Lemma denoteSymbol_strict_valid tu n o :
is_strict_valid o ->
denoteSymbol tu n o |-- strict_valid_ptr (_global n).
Proof.
rewrite /denoteSymbol/init_validR/is_strict_valid; destruct o.
{ rewrite -_at_svalidR. by destruct zero_sized_array. }
all: intros _; case_match; last by rewrite _at_svalidR.
all: rewrite !_at_as_Rep; auto using
code_at_strict_valid, method_at_strict_valid, ctor_at_strict_valid, dtor_at_strict_valid.
Qed.
Lemma denoteSymbol_valid tu n o :
denoteSymbol tu n o |-- valid_ptr (_global n).
Proof.
destruct (is_strict_valid o) eqn:Hs.
{ by rewrite denoteSymbol_strict_valid ?Hs // strict_valid_valid. }
move: Hs.
rewrite -_at_validR /denoteSymbol /init_validR /is_strict_valid.
by destruct o => //= ?; case_match.
Qed.
match o with
| Ovar t _ => negb (zero_sized_array t)
| _ => true
end.
Lemma denoteSymbol_strict_valid tu n o :
is_strict_valid o ->
denoteSymbol tu n o |-- strict_valid_ptr (_global n).
Proof.
rewrite /denoteSymbol/init_validR/is_strict_valid; destruct o.
{ rewrite -_at_svalidR. by destruct zero_sized_array. }
all: intros _; case_match; last by rewrite _at_svalidR.
all: rewrite !_at_as_Rep; auto using
code_at_strict_valid, method_at_strict_valid, ctor_at_strict_valid, dtor_at_strict_valid.
Qed.
Lemma denoteSymbol_valid tu n o :
denoteSymbol tu n o |-- valid_ptr (_global n).
Proof.
destruct (is_strict_valid o) eqn:Hs.
{ by rewrite denoteSymbol_strict_valid ?Hs // strict_valid_valid. }
move: Hs.
rewrite -_at_validR /denoteSymbol /init_validR /is_strict_valid.
by destruct o => //= ?; case_match.
Qed.
TODO incomplete
Definition initSymbol (n : obj_name) (o : ObjValue) : mpred :=
_at (_global n)
match o with
| Ovar t (global_init.Init e) =>
emp (*
Exists Q : FreeTemps -> mpred,
□ (_at (_eq a) (uninitR (resolve:=resolve) t 1) -*
Forall ρ ti, wp_init (resolve:=resolve) ti ρ t (Vptr a) e Q) ** Q emp
*)
(* ^^ todo(gmm): static initialization is not yet supported *)
| Ovar t global_init.NoInit =>
uninitR t (cQp.m 1)
| _ => emp
end.
Definition denoteModule_def (tu : translation_unit) : mpred :=
([∗list] sv ∈ map_to_list tu.(symbols), denoteSymbol tu sv.1 sv.2) **
[| module_le tu σ.(genv_tu) |].
Definition denoteModule_aux : seal (@denoteModule_def). Proof. by eexists. Qed.
Definition denoteModule := denoteModule_aux.(unseal).
Definition denoteModule_eq : @denoteModule = _ := denoteModule_aux.(seal_eq).
#[global] Hint Opaque denoteModule : typeclass_instances.
#[global] Instance denoteModule_persistent {module} : Persistent (denoteModule module).
Proof.
red. rewrite denoteModule_eq /denoteModule_def; intros.
destruct module; simpl.
iIntros "[#M #H]"; iFrame "#".
Qed.
#[global] Instance denoteModule_affine {module} : Affine (denoteModule module).
Proof. refine _. Qed.
Lemma denoteModule_denoteSymbol n m o :
m.(symbols) !! n = Some o ->
denoteModule m |-- denoteSymbol m n o.
Proof.
rewrite denoteModule_eq/denoteModule_def.
iIntros (Hlookup) "[M _]".
move: (NM.map_to_list_elements _ _ _ Hlookup) => [l1][l2] ->.
rewrite big_opL_app big_opL_cons.
by iDestruct "M" as "[_ [M _]]".
Qed.
Lemma denoteModule_strict_valid n m :
is_strict_valid <$> (m.(symbols) !! n) = Some true ->
denoteModule m |-- strict_valid_ptr (_global n).
Proof.
case E: lookup => [s |//] /= [Hs].
by rewrite denoteModule_denoteSymbol // denoteSymbol_strict_valid // Hs.
Qed.
Lemma denoteModule_valid n m :
m.(symbols) !! n <> None ->
denoteModule m |-- valid_ptr (_global n).
Proof.
intros; iIntros "M".
destruct (symbols m !! n) eqn:?; try congruence.
iDestruct (denoteModule_denoteSymbol with "M") as "M"; eauto.
by iApply denoteSymbol_valid.
Qed.
#[global] Instance denoteModule_models_observe tu : Observe [| tu ⊧ σ |] (denoteModule tu).
Proof.
apply observe_intro_only_provable.
rewrite denoteModule_eq/denoteModule_def.
iIntros "[_ %]". iPureIntro. constructor.
destruct (module_le_spec tu (genv_tu σ)); eauto.
destruct H.
Qed.
End with_cpp.
Arguments denoteModule _ : simpl never.
_at (_global n)
match o with
| Ovar t (global_init.Init e) =>
emp (*
Exists Q : FreeTemps -> mpred,
□ (_at (_eq a) (uninitR (resolve:=resolve) t 1) -*
Forall ρ ti, wp_init (resolve:=resolve) ti ρ t (Vptr a) e Q) ** Q emp
*)
(* ^^ todo(gmm): static initialization is not yet supported *)
| Ovar t global_init.NoInit =>
uninitR t (cQp.m 1)
| _ => emp
end.
Definition denoteModule_def (tu : translation_unit) : mpred :=
([∗list] sv ∈ map_to_list tu.(symbols), denoteSymbol tu sv.1 sv.2) **
[| module_le tu σ.(genv_tu) |].
Definition denoteModule_aux : seal (@denoteModule_def). Proof. by eexists. Qed.
Definition denoteModule := denoteModule_aux.(unseal).
Definition denoteModule_eq : @denoteModule = _ := denoteModule_aux.(seal_eq).
#[global] Hint Opaque denoteModule : typeclass_instances.
#[global] Instance denoteModule_persistent {module} : Persistent (denoteModule module).
Proof.
red. rewrite denoteModule_eq /denoteModule_def; intros.
destruct module; simpl.
iIntros "[#M #H]"; iFrame "#".
Qed.
#[global] Instance denoteModule_affine {module} : Affine (denoteModule module).
Proof. refine _. Qed.
Lemma denoteModule_denoteSymbol n m o :
m.(symbols) !! n = Some o ->
denoteModule m |-- denoteSymbol m n o.
Proof.
rewrite denoteModule_eq/denoteModule_def.
iIntros (Hlookup) "[M _]".
move: (NM.map_to_list_elements _ _ _ Hlookup) => [l1][l2] ->.
rewrite big_opL_app big_opL_cons.
by iDestruct "M" as "[_ [M _]]".
Qed.
Lemma denoteModule_strict_valid n m :
is_strict_valid <$> (m.(symbols) !! n) = Some true ->
denoteModule m |-- strict_valid_ptr (_global n).
Proof.
case E: lookup => [s |//] /= [Hs].
by rewrite denoteModule_denoteSymbol // denoteSymbol_strict_valid // Hs.
Qed.
Lemma denoteModule_valid n m :
m.(symbols) !! n <> None ->
denoteModule m |-- valid_ptr (_global n).
Proof.
intros; iIntros "M".
destruct (symbols m !! n) eqn:?; try congruence.
iDestruct (denoteModule_denoteSymbol with "M") as "M"; eauto.
by iApply denoteSymbol_valid.
Qed.
#[global] Instance denoteModule_models_observe tu : Observe [| tu ⊧ σ |] (denoteModule tu).
Proof.
apply observe_intro_only_provable.
rewrite denoteModule_eq/denoteModule_def.
iIntros "[_ %]". iPureIntro. constructor.
destruct (module_le_spec tu (genv_tu σ)); eauto.
destruct H.
Qed.
End with_cpp.
Arguments denoteModule _ : simpl never.