Require Export references memory_basics.
Require Import pointer_casts.
Local Open Scope ctype_scope.
Record addr (
K :
Set) :
Set :=
Addr {
addr_index :
index;
addr_ref_base :
ref K;
addr_byte :
nat;
addr_type_object :
type K;
addr_type_base :
type K;
addr_type :
ptr_type K
}.
Add Printing Constructor addr.
Arguments Addr {
_}
_ _ _ _ _ _.
Arguments addr_index {
_}
_.
Arguments addr_ref_base {
_}
_.
Arguments addr_byte {
_}
_.
Arguments addr_type_object {
_}
_.
Arguments addr_type_base {
_}
_.
Arguments addr_type {
_}
_.
Instance addr_eq_dec `{
K :
Set, ∀
k1 k2 :
K,
Decision (
k1 =
k2)}
(
a1 a2 :
addr K) :
Decision (
a1 =
a2).
Proof.
solve_decision. Defined.
Section address_operations.
Context `{
Env K}.
Inductive addr_typed' (Γ :
env K) (Δ :
memenv K) :
addr K →
ptr_type K →
Prop :=
Addr_typed o r i τ σ σ
p :
Δ ⊢
o : τ →
✓{Γ} τ →
Γ ⊢
r : τ ↣ σ →
ref_offset r = 0 →
i ≤
size_of Γ σ *
ref_size r →
(
ptr_size_of Γ σ
p |
i) →
σ >*> σ
p →
addr_typed' Γ Δ (
Addr o r i τ σ σ
p) σ
p.
Global Instance addr_typed :
Typed (
env K *
memenv K) (
ptr_type K) (
addr K) :=
curry addr_typed'.
Global Instance addr_freeze :
Freeze (
addr K) := λ β
a,
let '
Addr x r i τ σ σ
p :=
a in Addr x (
freeze β <$>
r)
i τ σ σ
p.
Global Instance type_of_addr:
TypeOf (
ptr_type K) (
addr K) :=
addr_type.
Global Instance addr_type_check:
TypeCheck (
env K *
memenv K) (
ptr_type K) (
addr K) := λ ΓΔ
a,
let (Γ,Δ) := ΓΔ
in
let '
Addr o r i τ σ σ
p :=
a in
guard (Δ ⊢
o : τ);
guard (✓{Γ} τ);
guard (Γ ⊢
r : τ ↣ σ);
guard (σ >*> σ
p);
guard (
ref_offset r = 0);
guard (
i ≤
size_of Γ σ *
ref_size r);
guard (
ptr_size_of Γ σ
p |
i);
Some σ
p.
Definition addr_strict (Γ :
env K) (
a :
addr K) :
Prop :=
addr_byte a <
size_of Γ (
addr_type_base a) *
ref_size (
addr_ref_base a).
Definition addr_is_obj (
a :
addr K) :
Prop :=
type_of a =
TType (
addr_type_base a).
Definition addr_ref (Γ :
env K) (
a :
addr K) :
ref K :=
ref_set_offset (
addr_byte a `
div`
size_of Γ (
addr_type_base a))
(
addr_ref_base a).
Definition addr_ref_byte (Γ :
env K) (
a :
addr K) :
nat :=
addr_byte a `
mod`
size_of Γ (
addr_type_base a).
Definition addr_object_offset (Γ :
env K) (
a :
addr K) :
nat :=
ref_object_offset Γ (
addr_ref_base a) +
addr_byte a *
char_bits.
Global Instance addr_disjoint:
DisjointE (
env K) (
addr K) := λ Γ
a1 a2,
(
addr_index a1 ≠
addr_index a2) ∨
(
addr_index a1 =
addr_index a2 ∧
addr_ref Γ
a1 ⊥
addr_ref Γ
a2) ∨
(
addr_index a1 =
addr_index a2 ∧
freeze true <$>
addr_ref Γ
a1 =
freeze true <$>
addr_ref Γ
a2 ∧
¬
addr_is_obj a1 ∧ ¬
addr_is_obj a2 ∧
addr_ref_byte Γ
a1 ≠
addr_ref_byte Γ
a2).
Definition addr_elt (Γ :
env K) (
rs :
ref_seg K) (
a :
addr K) :
addr K :=
from_option a $
σ ←
maybe TType (
type_of a) ≫=
lookupE Γ
rs;
Some (
Addr (
addr_index a)
(
ref_seg_base rs ::
addr_ref Γ
a) (
size_of Γ σ *
ref_seg_offset rs)
(
addr_type_object a) σ (
TType σ)).
Definition addr_top (
o :
index) (σ :
type K) :
addr K :=
Addr o [] 0 σ σ (
TType σ).
Definition addr_top_array (
o :
index) (σ :
type K) (
n :
Z) :
addr K :=
let n' :=
Z.to_nat n in Addr o [
RArray 0 σ
n'] 0 (σ.[
n']) σ (
TType σ).
Inductive addr_is_top_array :
addr K →
Prop :=
|
Addr_is_top_array o σ
n σ
p :
addr_is_top_array (
Addr o [
RArray 0 σ
n] 0 (σ.[
n]) σ σ
p).
End address_operations.
Typeclasses Opaque addr_strict addr_is_obj addr_disjoint.
Section addresses.
Context `{
EnvSpec K}.
Implicit Types Γ :
env K.
Implicit Types Δ :
memenv K.
Implicit Types τ σ :
type K.
Implicit Types τ
p σ
p :
ptr_type K.
Implicit Types rs :
ref_seg K.
Implicit Types r :
ref K.
Implicit Types a :
addr K.
Hint Immediate ref_typed_type_valid.
Arguments addr_type_check _ _ _ !
_ /.
Arguments addr_strict _ _ _ !
_ /.
Arguments addr_is_obj _ !
_ /.
Arguments addr_ref _ _ _ !
_ /.
Arguments addr_ref_byte _ _ _ !
_ /.
Arguments addr_object_offset _ _ _ !
_ /.
Arguments addr_elt _ _ _ _ !
_ /.
Typing and general properties
Lemma addr_freeze_freeze β1 β2
a :
freeze β1 (
freeze β2
a) =
freeze β1
a.
Proof.
destruct a; f_equal'; auto using ref_freeze_freeze. Qed.
Lemma addr_typed_alt Γ Δ
a σ
p :
(Γ,Δ) ⊢
a : σ
p ↔
Δ ⊢
addr_index a:
addr_type_object a ∧
✓{Γ} (
addr_type_object a) ∧
Γ ⊢
addr_ref_base a :
addr_type_object a ↣
addr_type_base a ∧
ref_offset (
addr_ref_base a) = 0 ∧
addr_byte a ≤
size_of Γ (
addr_type_base a) *
ref_size (
addr_ref_base a) ∧
(
ptr_size_of Γ σ
p |
addr_byte a) ∧
addr_type_base a >*> σ
p ∧
type_of a = σ
p.
Proof.
split; [destruct 1; naive_solver|intros (?&?&?&?&?&?&?&?)].
by destruct a; simplify_equality; constructor.
Qed.
Lemma addr_typed_index Γ Δ
a σ
p :
(Γ,Δ) ⊢
a : σ
p → Δ ⊢
addr_index a :
addr_type_object a.
Proof.
by destruct 1. Qed.
Lemma addr_typed_offset Γ Δ
a σ
p :
(Γ,Δ) ⊢
a : σ
p →
ref_offset (
addr_ref_base a) = 0.
Proof.
by destruct 1. Qed.
Lemma addr_typed_type_object_valid Γ Δ
a σ
p :
(Γ,Δ) ⊢
a : σ
p → ✓{Γ} (
addr_type_object a).
Proof.
by destruct 1. Qed.
Lemma addr_typed_ref_base_typed Γ Δ
a σ
p :
(Γ,Δ) ⊢
a : σ
p → Γ ⊢
addr_ref_base a :
addr_type_object a ↣
addr_type_base a.
Proof.
by destruct 1. Qed.
Lemma addr_typed_type_base_valid Γ Δ
a σ
p :
✓ Γ → (Γ,Δ) ⊢
a : σ
p → ✓{Γ} (
addr_type_base a).
Proof.
eauto using ref_typed_type_valid,
addr_typed_ref_base_typed, addr_typed_type_object_valid.
Qed.
Lemma addr_typed_ref_typed Γ Δ
a σ
p :
✓ Γ → (Γ,Δ) ⊢
a : σ
p →
addr_strict Γ
a →
Γ ⊢
addr_ref Γ
a :
addr_type_object a ↣
addr_type_base a.
Proof.
intros. apply ref_set_offset_typed; eauto using addr_typed_ref_base_typed.
apply Nat.div_lt_upper_bound;
eauto using size_of_ne_0, addr_typed_type_base_valid.
Qed.
Lemma addr_typed_cast Γ Δ
a σ
p : (Γ,Δ) ⊢
a : σ
p →
addr_type_base a >*> σ
p.
Proof.
by destruct 1. Qed.
Lemma addr_typed_type_valid Γ Δ
a σ : ✓ Γ → (Γ,Δ) ⊢
a :
TType σ → ✓{Γ} σ.
Proof.
inversion 2; eauto using castable_type_valid. Qed.
Lemma addr_typed_ptr_type_valid Γ Δ
a σ
p : ✓ Γ → (Γ,Δ) ⊢
a : σ
p → ✓{Γ} σ
p.
Proof.
destruct 2; eauto using castable_ptr_type_valid. Qed.
Lemma addr_size_of_ne_0 Γ Δ
a σ
p: ✓ Γ → (Γ,Δ) ⊢
a : σ
p →
ptr_size_of Γ σ
p ≠ 0.
Proof.
destruct σp; eauto using size_of_ne_0, addr_typed_type_valid. Qed.
Global Instance:
TypeOfSpec (
env K *
memenv K) (
ptr_type K) (
addr K).
Proof.
by intros [??]; destruct 1. Qed.
Global Instance:
TypeCheckSpec (
env K *
memenv K) (
ptr_type K) (
addr K) (λ
_,
True).
Proof.
intros [Γ Δ] a σ _. split.
* destruct a; intros; simplify_option_equality; constructor; auto.
* by destruct 1; simplify_option_equality.
Qed.
Lemma addr_size_of_weaken Γ1 Γ2 Δ
a σ
p :
✓ Γ1 → (Γ1,Δ) ⊢
a : σ
p → Γ1 ⊆ Γ2 →
ptr_size_of Γ1 σ
p =
ptr_size_of Γ2 σ
p.
Proof.
destruct σp; eauto using size_of_weaken, addr_typed_type_valid. Qed.
Lemma addr_typed_weaken Γ1 Γ2 Δ1 Δ2
a σ
p :
✓ Γ1 → (Γ1,Δ1) ⊢
a : σ
p → Γ1 ⊆ Γ2 → Δ1 ⇒ₘ Δ2 → (Γ2,Δ2) ⊢
a : σ
p.
Proof.
destruct 2 as [o r i τ σ σp]; intros ? [??].
constructor; simpl; split_ands;
eauto using type_valid_weaken, ref_typed_weaken.
* by erewrite <-size_of_weaken by eauto.
* by erewrite <-addr_size_of_weaken by (eauto; econstructor; eauto).
Qed.
Lemma addr_dead_weaken Γ Δ1 Δ2
a σ
p :
(Γ,Δ1) ⊢
a : σ
p →
index_alive Δ2 (
addr_index a) → Δ1 ⇒ₘ Δ2 →
index_alive Δ1 (
addr_index a).
Proof.
intros [] ? []; naive_solver. Qed.
Lemma addr_type_object_eq Γ Δ
a1 a2 σ
p1 σ
p2 :
(Γ,Δ) ⊢
a1 : σ
p1 → (Γ,Δ) ⊢
a2 : σ
p2 →
addr_index a1 =
addr_index a2 →
addr_type_object a1 =
addr_type_object a2.
Proof.
by destruct 1, 1; intros; simplify_type_equality'. Qed.
Global Instance addr_strict_dec Γ
a :
Decision (
addr_strict Γ
a).
Proof.
unfold addr_strict; apply _. Defined.
Global Instance addr_is_obj_dec a :
Decision (
addr_is_obj a).
Proof.
unfold addr_is_obj; apply _. Defined.
Lemma addr_index_freeze β
a :
addr_index (
freeze β
a) =
addr_index a.
Proof.
by destruct a. Qed.
Lemma addr_ref_base_freeze β
a :
addr_ref_base (
freeze β
a) =
freeze β <$>
addr_ref_base a.
Proof.
by destruct a. Qed.
Lemma addr_byte_freeze β
a :
addr_byte (
freeze β
a) =
addr_byte a.
Proof.
by destruct a. Qed.
Lemma addr_type_base_freeze β
a :
addr_type_base (
freeze β
a) =
addr_type_base a.
Proof.
by destruct a. Qed.
Lemma addr_type_of_freeze β
a :
type_of (
freeze β
a) =
type_of a.
Proof.
by destruct a. Qed.
Lemma addr_ref_freeze Γ β
a :
addr_ref Γ (
freeze β
a) =
freeze β <$>
addr_ref Γ
a.
Proof.
unfold addr_ref. by rewrite !addr_ref_base_freeze, addr_byte_freeze,
addr_type_base_freeze, ref_set_offset_freeze.
Qed.
Lemma addr_is_obj_freeze β
a :
addr_is_obj (
freeze β
a) ↔
addr_is_obj a.
Proof.
unfold addr_is_obj. by rewrite addr_type_of_freeze, addr_type_base_freeze.
Qed.
Lemma addr_is_obj_freeze_2 β
a :
addr_is_obj a →
addr_is_obj (
freeze β
a).
Proof.
by rewrite addr_is_obj_freeze. Qed.
Lemma addr_strict_freeze Γ β
a :
addr_strict Γ (
freeze β
a) ↔
addr_strict Γ
a.
Proof.
unfold addr_strict. by rewrite addr_byte_freeze, addr_type_base_freeze,
addr_ref_base_freeze, ref_size_freeze.
Qed.
Lemma addr_strict_freeze_2 Γ β
a :
addr_strict Γ
a →
addr_strict Γ (
freeze β
a).
Proof.
by rewrite addr_strict_freeze. Qed.
Lemma addr_ref_byte_freeze Γ β
a :
addr_ref_byte Γ (
freeze β
a) =
addr_ref_byte Γ
a.
Proof.
unfold addr_ref_byte. by rewrite addr_byte_freeze, addr_type_base_freeze.
Qed.
Lemma addr_typed_freeze Γ Δ β
a σ
p :
(Γ,Δ) ⊢
freeze β
a : σ
p ↔ (Γ,Δ) ⊢
a : σ
p.
Proof.
rewrite !addr_typed_alt; destruct a; simpl. by rewrite ref_offset_freeze,
ref_size_freeze; setoid_rewrite ref_typed_freeze.
Qed.
Lemma addr_is_obj_ref_byte Γ Δ
a σ
p :
✓ Γ → (Γ,Δ) ⊢
a : σ
p →
addr_is_obj a →
addr_ref_byte Γ
a = 0.
Proof.
destruct 2; intros; simplify_equality';
apply Nat.mod_divide; eauto using size_of_ne_0.
Qed.
Lemma addr_is_obj_type Γ Δ
a σ :
(Γ,Δ) ⊢
a :
TType σ →
addr_is_obj a → σ =
addr_type_base a.
Proof.
inversion 1; naive_solver. Qed.
Lemma addr_not_is_obj_type Γ Δ
a σ :
(Γ,Δ) ⊢
a :
TType σ → ¬
addr_is_obj a → σ =
ucharT.
Proof.
inversion 1;
match goal with H : _ >*> _ |- _ => inversion H end; naive_solver.
Qed.
Lemma addr_byte_range Γ Δ
a σ :
✓ Γ → (Γ,Δ) ⊢
a :
TType σ →
addr_strict Γ
a →
addr_ref_byte Γ
a +
size_of Γ σ ≤
size_of Γ (
addr_type_base a).
Proof.
intros. destruct (decide (addr_is_obj a)).
{ by erewrite <-addr_is_obj_type, addr_is_obj_ref_byte by eauto. }
erewrite (addr_not_is_obj_type _ _ _ σ), size_of_char by eauto.
rewrite Nat.add_1_r, Nat.le_succ_l.
apply Nat.mod_bound_pos; auto with lia.
eapply size_of_pos, addr_typed_type_base_valid; eauto.
Qed.
Lemma addr_bit_range Γ Δ
a σ :
✓ Γ → (Γ,Δ) ⊢
a :
TType σ →
addr_strict Γ
a →
addr_ref_byte Γ
a *
char_bits +
bit_size_of Γ σ
≤
bit_size_of Γ (
addr_type_base a).
Proof.
intros. unfold bit_size_of. rewrite <-Nat.mul_add_distr_r,
<-Nat.mul_le_mono_pos_r by auto using char_bits_pos.
eauto using addr_byte_range.
Qed.
Lemma addr_strict_weaken Γ1 Γ2
m1 a σ
p :
✓ Γ1 → (Γ1,
m1) ⊢
a : σ
p →
addr_strict Γ1
a → Γ1 ⊆ Γ2 →
addr_strict Γ2
a.
Proof.
unfold addr_strict. intros ????.
by erewrite <-size_of_weaken by eauto using addr_typed_type_base_valid.
Qed.
Lemma addr_ref_weaken Γ1 Γ2
m1 a σ
p :
✓ Γ1 → (Γ1,
m1) ⊢
a : σ
p → Γ1 ⊆ Γ2 →
addr_ref Γ1
a =
addr_ref Γ2
a.
Proof.
intros ? [] ?; simpl.
by erewrite size_of_weaken by eauto using ref_typed_type_valid.
Qed.
Lemma addr_ref_byte_weaken Γ1 Γ2
m1 a σ
p :
✓ Γ1 → (Γ1,
m1) ⊢
a : σ
p → Γ1 ⊆ Γ2 →
addr_ref_byte Γ1
a =
addr_ref_byte Γ2
a.
Proof.
intros ? [] ?; simpl.
by erewrite size_of_weaken by eauto using ref_typed_type_valid.
Qed.
Lemma addr_object_offset_weaken Γ1 Γ2 Δ
a σ
p :
✓ Γ1 → (Γ1,Δ) ⊢
a : σ
p → Γ1 ⊆ Γ2 →
addr_object_offset Γ1
a =
addr_object_offset Γ2
a.
Proof.
intros. unfold addr_object_offset; eauto using ref_object_offset_weaken,
addr_typed_ref_base_typed, addr_typed_type_object_valid.
Qed.
Lemma addr_object_offset_alt Γ Δ
a σ
p :
✓ Γ → (Γ,Δ) ⊢
a : σ
p →
addr_strict Γ
a →
addr_object_offset Γ
a
=
ref_object_offset Γ (
addr_ref Γ
a) +
addr_ref_byte Γ
a *
char_bits.
Proof.
intros ? [o r i τ σ' σp' Hor] ?; simpl in *.
erewrite ref_object_offset_set_offset_0
by eauto using Nat.div_lt_upper_bound, size_of_ne_0, ref_typed_type_valid.
rewrite (Nat.div_mod i (size_of Γ σ')) at 1
by eauto using size_of_ne_0,ref_typed_type_valid; unfold bit_size_of; lia.
Qed.
Lemma align_of_addr_object_offset Γ Δ
a σ :
✓ Γ → (Γ,Δ) ⊢
a :
TType σ → (
bit_align_of Γ σ |
addr_object_offset Γ
a).
Proof.
inversion_clear 2; simplify_equality'; apply Nat.divide_add_r;
eauto using Nat.mul_divide_mono_r, Nat.divide_trans,
bit_align_of_castable, align_of_divide, castable_type_valid,
size_of_ne_0, bit_align_of_ref_object_offset.
Qed.
Lemma addr_object_offset_bit_size Γ Δ
a σ
p :
✓ Γ → (Γ,Δ) ⊢
a : σ
p →
addr_strict Γ
a →
addr_object_offset Γ
a +
ptr_bit_size_of Γ σ
p
≤
bit_size_of Γ (
addr_type_object a).
Proof.
destruct 2 as [o r i τ σ σp ??? Hoff _ Hi Hcast];
intros Ha; simplify_equality'.
eapply Nat.le_trans; [|eapply ref_object_offset_size; eauto].
rewrite <-Nat.add_assoc, <-Nat.add_le_mono_l, Hoff, Nat.sub_0_r.
unfold bit_size_of; rewrite ptr_bit_size_of_alt.
rewrite Nat.mul_assoc, <-Nat.mul_add_distr_r.
rewrite <-Nat.mul_le_mono_pos_r by auto using char_bits_pos.
destruct Hi as [z ->]; inversion Hcast; simplify_equality'.
{ rewrite Nat.mul_comm; lia. }
{ rewrite size_of_char in Ha |- *; rewrite Nat.mul_comm; lia. }
rewrite <-Nat.mul_succ_l, <-Nat.mul_le_mono_pos_r
by eauto using size_of_pos, ref_typed_type_valid.
rewrite <-Nat.mul_comm, <-Nat.mul_lt_mono_pos_l in Ha
by eauto using size_of_pos, ref_typed_type_valid; lia.
Qed.
Lemma addr_elt_typed Γ Δ
a rs σ σ' :
✓ Γ → (Γ,Δ) ⊢
a :
TType σ →
addr_strict Γ
a → Γ ⊢
rs : σ ↣ σ' →
(Γ,Δ) ⊢
addr_elt Γ
rs a :
TType σ'.
Proof.
rewrite addr_typed_alt. intros ? (?&?&?&?&?&?&Hcast&?) ? Hrs.
destruct a as [o r' i τ σ'' σp]; simplify_equality'.
inversion Hcast; simplify_equality'; try solve [inversion Hrs].
assert (ref_seg_offset rs < ref_seg_size rs)
by eauto using ref_seg_typed_size.
erewrite path_type_check_complete by eauto; constructor; simpl; auto.
* apply ref_typed_cons; exists σ; split.
+ apply ref_set_offset_typed; auto.
apply Nat.div_lt_upper_bound;
eauto using size_of_ne_0, ref_typed_type_valid.
+ apply ref_seg_set_offset_typed; auto with lia.
* by rewrite ref_seg_offset_set_offset by lia.
* rewrite ref_seg_size_set_offset. apply Nat.mul_le_mono_l; lia.
* by apply Nat.divide_factor_l.
* constructor.
Qed.
Lemma addr_elt_strict Γ Δ
a rs σ σ' :
✓ Γ → (Γ,Δ) ⊢
a :
TType σ → Γ ⊢
rs : σ ↣ σ' →
addr_strict Γ (
addr_elt Γ
rs a).
Proof.
rewrite addr_typed_alt. intros ? (?&?&?&?&?&?&Hcast&?) Hrs.
destruct a as [o r i τ σ'' σp]; simplify_equality'.
inversion Hcast; simplify_equality'; try solve [inversion Hrs].
erewrite path_type_check_complete by eauto; simpl.
rewrite ref_seg_size_set_offset, <-Nat.mul_lt_mono_pos_l
by eauto using size_of_pos, ref_typed_type_valid, ref_seg_typed_type_valid;
eauto using ref_seg_typed_size.
Qed.
Lemma addr_elt_is_obj Γ Δ
a rs σ σ' :
(Γ,Δ) ⊢
a :
TType σ → Γ ⊢
rs : σ ↣ σ' →
addr_is_obj (
addr_elt Γ
rs a).
Proof.
rewrite addr_typed_alt. intros (?&?&?&?&?&?&Hcast&?) Hrs.
destruct a as [o r' i τ σ'' σp]; simplify_equality'.
by erewrite path_type_check_complete by eauto.
Qed.
Lemma addr_elt_weaken Γ1 Γ2 Δ1
a rs σ σ' :
✓ Γ1 → (Γ1,Δ1) ⊢
a :
TType σ → Γ1 ⊢
rs : σ ↣ σ' → Γ1 ⊆ Γ2 →
addr_elt Γ1
rs a =
addr_elt Γ2
rs a.
Proof.
intros. unfold addr_elt; simplify_type_equality'.
erewrite !path_type_check_complete by eauto using ref_seg_typed_weaken; simpl.
by erewrite addr_ref_weaken, size_of_weaken
by eauto using addr_typed_type_valid, ref_seg_typed_type_valid.
Qed.
Lemma addr_ref_byte_is_obj_parent Γ Δ
rs a σ σ' :
✓ Γ → (Γ,Δ) ⊢
a :
TType σ → Γ ⊢
rs : σ ↣ σ' →
addr_is_obj a.
Proof.
rewrite addr_typed_alt. intros ? (?&?&?&?&?&?&Hcast&?) Hrs.
destruct a as [o r i τ σ'' σp]; simplify_equality'.
by inversion Hcast; simplify_equality'; try solve [inversion Hrs].
Qed.
Lemma addr_ref_byte_is_obj Γ Δ
rs a σ σ' :
✓ Γ → (Γ,Δ) ⊢
a :
TType σ → Γ ⊢
rs : σ ↣ σ' →
addr_is_obj (
addr_elt Γ
rs a).
Proof.
unfold addr_elt; intros; simplify_type_equality'.
by erewrite !path_type_check_complete by eauto.
Qed.
Lemma addr_index_elt Γ
rs a :
addr_index (
addr_elt Γ
rs a) =
addr_index a.
Proof.
by destruct a; simpl; destruct (_ ≫= lookupE _ _). Qed.
Lemma addr_ref_elt Γ Δ
rs a σ σ' :
✓ Γ → (Γ,Δ) ⊢
a :
TType σ → Γ ⊢
rs : σ ↣ σ' →
addr_ref Γ (
addr_elt Γ
rs a) =
rs ::
addr_ref Γ
a.
Proof.
unfold addr_elt; intros; simplify_type_equality'.
erewrite !path_type_check_complete by eauto; f_equal'.
rewrite Nat.mul_comm, Nat.div_mul by eauto using size_of_ne_0,
addr_typed_type_valid, ref_seg_typed_type_valid.
by destruct rs.
Qed.
Lemma addr_ref_byte_elt Γ Δ
rs a σ σ' :
✓ Γ → (Γ,Δ) ⊢
a :
TType σ →
addr_strict Γ
a → Γ ⊢
rs : σ ↣ σ' →
addr_ref_byte Γ (
addr_elt Γ
rs a) = 0.
Proof.
eauto using addr_is_obj_ref_byte, addr_ref_byte_is_obj, addr_elt_typed.
Qed.
Lemma addr_top_typed Γ Δ
o τ :
✓ Γ → Δ ⊢
o : τ → ✓{Γ} τ → (Γ,Δ) ⊢
addr_top o τ :
TType τ.
Proof.
constructor; simpl; rewrite ?ref_typed_nil;
eauto using Nat.divide_0_r, castable_TType with lia.
Qed.
Lemma addr_top_strict Γ
o τ : ✓ Γ → ✓{Γ} τ →
addr_strict Γ (
addr_top o τ).
Proof.
unfold addr_strict, addr_top; simpl. rewrite Nat.mul_1_r.
eauto using size_of_pos.
Qed.
Lemma addr_top_is_obj o τ :
addr_is_obj (
addr_top o τ).
Proof.
done. Qed.
Lemma addr_top_array_alt Γ
o τ
n :
Z.to_nat n ≠ 0 →
let n' :=
Z.to_nat n in
addr_top_array o τ
n =
addr_elt Γ (
RArray 0 τ
n') (
addr_top o (τ.[
n'])).
Proof.
unfold addr_elt, addr_top_array; simplify_option_equality;
auto with f_equal lia.
Qed.
Lemma addr_top_array_typed Γ Δ
o τ (
n :
Z) :
✓ Γ → Δ ⊢
o : τ.[
Z.to_nat n] → ✓{Γ} τ →
Z.to_nat n ≠ 0 →
(Γ,Δ) ⊢
addr_top_array o τ
n :
TType τ.
Proof.
intros. rewrite (addr_top_array_alt Γ) by done.
assert (0 ≤ n)%Z by (by destruct n).
eapply addr_elt_typed; eauto using addr_top_strict,
addr_top_typed, TArray_valid; constructor; lia.
Qed.
Lemma addr_top_array_strict Γ
o τ
n :
✓ Γ → ✓{Γ} τ →
Z.to_nat n ≠ 0 →
addr_strict Γ (
addr_top_array o τ
n).
Proof.
intros. apply Nat.mul_pos_pos; simpl; eauto using size_of_pos with lia.
Qed.
Lemma addr_is_top_array_alt Γ Δ
a σ
p :
✓ Γ → (Γ,Δ) ⊢
a : σ
p →
addr_is_top_array a ↔ ∃ τ
n,
addr_strict Γ
a ∧
addr_ref Γ
a = [
RArray 0 τ
n] ∧
addr_ref_byte Γ
a = 0.
Proof.
rewrite addr_typed_alt; intros ? (_&?&Hr&?&?&_); split.
* destruct 1 as [o τ' n σp']; simplify_equality'; exists τ' n.
assert (✓{Γ} τ' ∧ n ≠ 0) as [??] by auto using TArray_valid_inv.
rewrite Nat.div_0_l, Nat.mod_0_l by eauto using size_of_ne_0.
split_ands; auto using Nat.mul_pos_pos, size_of_pos with lia.
* intros (?&n&?&?&Hi); destruct a as [o [|[] r] i τ' σ σp']; simplify_equality'.
rewrite ref_typed_singleton in Hr; inversion Hr; simplify_equality'.
rewrite <-(Nat.mod_small i (size_of Γ σ)), Hi by
(apply Nat.div_small_iff; eauto using size_of_ne_0, TArray_valid_inv_type).
constructor.
Qed.
Global Instance addr_is_top_array_dec a :
Decision (
addr_is_top_array a).
Proof.
refine
match a with
| Addr o [RArray 0 σ1 n1] 0 (σ2.[n2]) σ3 σ4 =>
cast_if_and3 (decide (n1 = n2)) (decide (σ1 = σ2)) (decide (σ2 = σ3))
| _ => right _
end; abstract first [by inversion 1 | subst; constructor].
Defined.
Disjointness
Global Instance addr_disjoint_dec Γ
a1 a2 :
Decision (
a1 ⊥{Γ}
a2).
Proof.
unfold disjointE, addr_disjoint; apply _. Defined.
Lemma addr_disjoint_weaken Γ1 Γ2
m1 a1 a2 σ
p1 σ
p2 :
✓ Γ1 → (Γ1,
m1) ⊢
a1 : σ
p1 → (Γ1,
m1) ⊢
a2 : σ
p2 →
a1 ⊥{Γ1}
a2 → Γ1 ⊆ Γ2 →
a1 ⊥{Γ2}
a2.
Proof.
unfold disjointE, addr_disjoint. intros. by erewrite
<-!(addr_ref_weaken Γ1 Γ2), <-!(addr_ref_byte_weaken Γ1 Γ2) by eauto.
Qed.
Lemma addr_top_disjoint Γ Δ
o1 o2 τ1 τ2 :
Δ ⊢
o1 : τ1 → Δ ⊢
o2 : τ2 →
addr_top o1 τ1 =
addr_top o2 τ2 ∨
addr_top o1 τ1 ⊥{Γ}
addr_top o2 τ2.
Proof.
intros. destruct (decide (o1 = o2)); simplify_type_equality; auto.
by right; left.
Qed.
Lemma addr_disjoint_object_offset Γ Δ
a1 a2 σ1 σ2 :
✓ Γ → (Γ,Δ) ⊢
a1 :
TType σ1 →
addr_strict Γ
a1 →
(Γ,Δ) ⊢
a2 :
TType σ2 →
addr_strict Γ
a2 →
a1 ⊥{Γ}
a2 →
(* 1.) *) addr_index a1 ≠
addr_index a2 ∨
(* 2.) *)
addr_object_offset Γ
a1 +
bit_size_of Γ σ1 ≤
addr_object_offset Γ
a2 ∨
(* 3.) *)
addr_object_offset Γ
a2 +
bit_size_of Γ σ2 ≤
addr_object_offset Γ
a1.
Proof.
intros ?????. erewrite !addr_object_offset_alt by eauto.
intros [?|[[??]|(?&Hr&?&?&?)]]; auto.
{ destruct (ref_disjoint_object_offset Γ (addr_type_object a1)
(addr_ref Γ a1) (addr_ref Γ a2) (addr_type_base a1) (addr_type_base a2));
eauto using addr_typed_ref_typed;
erewrite ?(addr_type_object_eq _ _ a1 a2) by eauto;
eauto using addr_typed_ref_typed.
* feed pose proof (addr_bit_range Γ Δ a1 σ1); auto. right; left; lia.
* feed pose proof (addr_bit_range Γ Δ a2 σ2); auto. do 2 right; lia. }
erewrite (addr_not_is_obj_type _ _ _ σ1), (addr_not_is_obj_type _ _ _ σ2),
<-(ref_object_offset_freeze Γ true (addr_ref Γ a1)), Hr,
ref_object_offset_freeze, !bit_size_of_char by eauto.
destruct (decide (addr_ref_byte Γ a1 < addr_ref_byte Γ a2)).
* right; left. rewrite <-Nat.add_assoc, <-Nat.mul_succ_l.
apply Nat.add_le_mono_l, Nat.mul_le_mono_nonneg_r; lia.
* do 2 right. rewrite <-Nat.add_assoc, <-Nat.mul_succ_l.
apply Nat.add_le_mono_l, Nat.mul_le_mono_nonneg_r; lia.
Qed.
End addresses.