Require ArithLib.
Require ListAdom.
Require Mconvert.
Require Pun.
Require AbMemSignatureCsharpminor.
Require DebugCshm DebugAbMachineEnv.
Import
Utf8
String
Coqlib
Maps
Integers
Floats
Values
Memory
Globalenvs
AST
Cminor
Csharpminorannot
Util
AssocList
ToString
Sets
AdomLib
AlarmMon
ListAdom
AbMemSignatureCsharpminor
AbMachineEnv
PExpr
MemChunkTree
Cells
Pun
NoError
PointsTo
Mconvert
FastArith.
Require Import Annotagen.
Open Scope string.
Set Implicit Arguments.
Unset Elimination Schemes.
Definition injective_map {
A B} (
m:
A →
option B) :
Prop :=
∀
x x'
a,
m(
x) =
Some a →
m(
x') =
Some a →
x =
x'.
Definition stacks_tmp (
stk stk':
list (
temp_env *
env)) :
Prop :=
map snd stk =
map snd stk'.
Lemma stacks_tmp_in : ∀
stk stk',
stacks_tmp stk stk' →
∀
t e,
In (
t,
e)
stk' →
∃
t',
In (
t',
e)
stk.
Proof.
unfold stacks_tmp.
induction stk as [|(
t,
e)
stk IH];
intros stk'
H.
generalize (
map_nil_inv _ _ (
eq_sym H)).
intros -> ? ? ().
destruct stk'
as [|(
t',
e')
stk'].
apply map_nil_inv in H.
eq_some_inv.
simpl in H.
eq_some_inv.
subst.
intros t0 e [?|
H].
eq_some_inv.
subst.
vauto.
edestruct IH.
eassumption.
eassumption.
vauto.
Qed.
Lemma get_stk_tmp : ∀
stk stk',
stacks_tmp stk stk' →
∀
f,
option_map snd (
get_stk f stk) =
option_map snd (
get_stk f stk').
Proof.
Remark block_of_ablock_tmp ge : ∀
stk stk',
stacks_tmp stk stk' →
∀
ab,
block_of_ablock ge stk ab =
block_of_ablock ge stk'
ab.
Proof.
unfold stacks_tmp.
intros stk stk'
H.
intros [
f x|
b];
simpl;
auto.
generalize (
get_stk_tmp H f).
destruct (
get_stk f stk')
as [ (
t,
e) | ];
simpl;
intros X;
eq_some_inv.
destruct X as ((
t',
e') &
X & <-).
rewrite X.
reflexivity.
destruct (
get_stk _ _);
auto;
simpl in *;
eq_some_inv.
Qed.
Module N :=
Nconvert ACTree.
Module PT :=
N.PT.
Export PT.
Definition lvarset :
Type :=
PSet.t.
Definition tvarset :
Type :=
PSet.t.
Definition stack :
Type :=
list (
lvarset *
tvarset).
Instance fname_leb :
leb_op fname :=
flat_leb_op Pos.eqb.
Instance fname_join :
join_op fname (
fname+⊤) :=
flat_join_op Pos.eqb.
Instance lvarset_leb :
leb_op lvarset :=
flat_leb_op PSet.beq.
Instance lvarset_join :
join_op lvarset (
lvarset+⊤) :=
flat_join_op PSet.beq.
Definition sizes :
Type :=
ABTreeDom.t (
Z * (
permission *
bool)).
Definition sizes_gamma ge stk :
gamma_op sizes mem :=
λ
sz m,
∀
b hi perm vol b',
ABTreeDom.get b sz =
Just (
hi, (
perm,
vol)) →
block_of_ablock ge stk b =
Some b' →
Mem.range_perm m b' 0
hi Cur perm
∧
Bool.leb vol (
Senv.block_is_volatile ge b').
Instance BoolEqDec :
EqDec bool :=
eq_dec_of_beq _ Bool.eqb_true_iff.
Definition permission_beq (
x y:
permission) :
bool :=
match x,
y with
|
Freeable,
Freeable
|
Writable,
Writable
|
Readable,
Readable
|
Nonempty,
Nonempty
=>
true
|
_,
_ =>
false
end.
Lemma permission_beq_iff x y :
permission_beq x y =
true ↔
x =
y.
Proof.
split. now destruct x, y; intros; eq_some_inv. now intros <-; destruct x. Qed.
Instance PermissionEqDec :
EqDec permission :=
eq_dec_of_beq _ permission_beq_iff.
Instance PermissionToString :
ToString permission :=
λ
perm,
match perm with
|
Freeable => "
Freeable"
|
Writable => "
Writable"
|
Readable => "
Readable"
|
Nonempty => "
Nonempty"
end%
string.
Instance sizes_leb :
leb_op sizes :=
leb (
leb_op:=
ABTreeDom.leb_tree (
flat_leb_op eq_dec)
_).
Proof.
Instance sizes_join :
join_op sizes sizes :=
ABTreeDom.join_tree (
flat_join_op eq_dec)
_.
Proof.
Definition sizes_widen :
sizes ->
sizes ->
sizes :=
join.
Instance sizes_top_correct ge stk :
top_op_correct sizes mem (
G:=
sizes_gamma ge stk).
Proof.
Instance sizes_leb_correct ge stk :
leb_op_correct sizes mem (
G:=
sizes_gamma ge stk).
Proof.
Instance sizes_join_correct ge stk :
join_op_correct sizes sizes mem
(
GA:=
sizes_gamma ge stk) (
GB:=
sizes_gamma ge stk).
Proof.
intros x y a H b hi perm vol b'
G B'.
unfold join,
sizes_join in G.
rewrite ABTreeDom.get_joinwiden in G.
destruct (
ABTreeDom.get b x)
eqn:
Bx.
discriminate.
destruct (
ABTreeDom.get b y)
eqn:
By.
discriminate.
unfold flat_join_op in G.
simpl in G.
destruct (@
eq_dec _ _);
subst;
simpl in *;
inv G.
destruct H as [
H|
H];
specialize (
H b hi perm vol b');
first [
specialize (
H Bx) |
specialize (
H By) ];
exact (
H B').
Qed.
Lemma ptset_gamma_tmp ge : ∀
stk stk',
stacks_tmp stk stk' →
∀
bs,
ptset_gamma ge stk bs ⊆
ptset_gamma ge stk'
bs.
Proof.
intros stk stk'
H bs v.
intros (
b' &
Hb' &
K).
exists b'.
split.
exact Hb'.
erewrite <-
block_of_ablock_tmp;
eassumption.
Qed.
Lemma type_gamma_covariant :
∀ (
G G':
gamma_op BlockSet.t block),
(∀
bs,
G bs ⊆
G'
bs) →
∀
ty,
type_gamma G ty ⊆
type_gamma G'
ty.
Proof.
intros G G'
M ty v.
case ty;
try exact id;
(
intros [ |
bs ]; [
exact id |]);
destruct v;
try exact id;
apply M.
Qed.
Lemma points_to_gamma_tmp ge : ∀
stk stk',
stacks_tmp stk stk' →
∀
ptr,
points_to_gamma ge stk ptr ⊆
points_to_gamma ge stk'
ptr.
Proof.
Lemma sizes_gamma_tmp ge stk stk' :
stacks_tmp stk stk' →
∀
sz,
sizes_gamma ge stk sz ⊆
sizes_gamma ge stk'
sz.
Proof.
intros H sz a A b hi b'
B B'
ofs Hofs.
apply (
A b hi b');
auto.
rewrite (
block_of_ablock_tmp ge H).
assumption.
Qed.
Section num.
Context
{
num num_iter:
Type}
`{
numToString:
ToString num}
`{
numIterToString:
ToString num_iter}
(
NumDom:
ab_machine_env (
var:=
cell)
num num_iter).
Lemma gamma_num_ext :
∀ ρ ρ' :
cell →
mach_num,
(∀
x :
cell, ρ
x = ρ'
x) → ∀
m :
num +⊥, γ
m ρ → γ
m ρ'.
Proof.
Definition compat := (λ ρ ρ
n,
N.compat _ (λ
x,
x) ρ ρ
n).
Variable ge :
genv.
Local Instance AblockToString :
ToString ablock :=
AblockToString ge.
Local Instance CellToString :
ToString cell :=
CellToString ge.
Record invariant (
cs:
concrete_state) :
Prop :=
{
localFreeable :
∀
t e,
In (
t,
e) (
fst cs) →
∀
b hi,
In (
b, 0,
hi) (
blocks_of_env e) →
Mem.range_perm (
snd cs)
b 0
hi Cur Freeable
;
localNotGlobal :
∀
t e,
In (
t,
e) (
fst cs) →
∀
x b y b'
z,
Genv.find_symbol ge x =
Some b →
e !
y =
Some (
b',
z) →
b ≠
b'
;
localInj :
injective_map (λ
x_v,
do t_e <-
get_stk (
fst x_v) (
fst cs);
fmap fst ((
snd t_e) ! (
snd x_v)))
;
globalValid:
∀
x b,
Genv.find_symbol ge x =
Some b →
b ∈
Mem.valid_block (
snd cs)
;
localValid:
∀
t e,
In (
t,
e) (
fst cs) →
∀
x b z,
e !
x =
Some (
b,
z) →
b ∈
Mem.valid_block (
snd cs)
;
noIntFragment:
∀
ab b,
block_of_ablock ge (
fst cs)
ab =
Some b →
∀
o,
match ZMap.get o (
Mem.mem_contents (
snd cs)) !!
b with Fragment (
Vint _)
_ _ =>
False |
_ =>
True end
}.
Lemma invariant_tmp : ∀
stk stk',
stacks_tmp stk stk' →
∀
m,
invariant (
stk,
m) →
invariant (
stk',
m).
Proof.
intros stk stk'
H m INV.
split.
-
intros t e H0.
apply (
stacks_tmp_in H)
in H0.
hsplit.
generalize (
INV.(
localFreeable)
t'
e H0).
auto.
-
intros t e H0.
apply (
stacks_tmp_in H)
in H0.
hsplit.
generalize (
INV.(
localNotGlobal)
t'
e H0).
auto.
-
intros (
f,
x) (
f',
x')
b.
generalize (
INV.(@
localInj _) (
f,
x) (
f',
x')
b).
clear -
H.
simpl.
generalize (
get_stk_tmp H f').
generalize (
get_stk_tmp H f).
destruct (
get_stk f stk')
as [ (
t,
e) |];
simpl;
intros X;
eq_some_inv;
hsplit;
subst;
rewrite X.
2:
intros;
eq_some_inv.
destruct (
get_stk f'
stk')
as [ (
t',
e') |];
simpl;
intros X';
eq_some_inv;
hsplit;
subst;
rewrite X'.
2:
intros;
eq_some_inv.
easy.
-
exact INV.(
globalValid).
-
intros t e H0.
apply (
stacks_tmp_in H)
in H0.
hsplit.
generalize (
INV.(
localValid)
_ _ H0).
auto.
-
intros ab b.
rewrite <- (
block_of_ablock_tmp ge H).
apply INV.
Qed.
Lemma invariant_block_of_ablock_inj stk m :
(
stk,
m) ∈
invariant →
∀
ab₁
b₁
ab₂
b₂,
block_of_ablock ge stk ab₁ =
Some b₁ →
block_of_ablock ge stk ab₂ =
Some b₂ →
ab₁ ≠
ab₂ →
b₁ ≠
b₂.
Proof.
intros INV [
f x|
b]
b₁ [
f'
x'|
b']
b₂;
simpl.
-
generalize (
INV.(
localInj) (
f,
x) (
f',
x')).
simpl.
destruct (
get_stk f stk)
as [(
t,
e)|]. 2:
intros;
eq_some_inv.
destruct (
get_stk f'
stk)
as [(
t',
e')|]. 2:
intros;
eq_some_inv.
simpl.
destruct (
e!
x)
as [(
b, ?)|]. 2:
intros;
eq_some_inv.
destruct (
e'!
x')
as [(
b', ?)|]. 2:
intros;
eq_some_inv.
simpl.
intros H H0 H1 H2 ?.
eq_some_inv.
subst.
apply H2.
specialize (
H _ eq_refl eq_refl).
congruence.
-
destruct (
get_stk f stk)
as [(
t,
e)|]
eqn:
A. 2:
intros;
eq_some_inv.
simpl.
destruct (
e!
x)
as [(
b, ?)|]
eqn:
Hx. 2:
intros;
eq_some_inv.
destruct (
Genv.invert_symbol ge b')
as [
q|]
eqn:
Q;
intros;
eq_some_inv.
subst.
apply not_eq_sym.
exact (
INV.(
localNotGlobal)
t e (
get_stk_in A)
_ _ (
Genv.invert_find_symbol _ _ Q)
Hx).
-
destruct (
Genv.invert_symbol ge b)
as [
q|]
eqn:
Q;
intro;
eq_some_inv.
destruct (
get_stk f'
stk)
as [(
t',
e')|]
eqn:
A. 2:
intros;
eq_some_inv.
simpl.
destruct (
e'!
x')
as [(
b', ?)|]
eqn:
Hy;
intros;
eq_some_inv.
subst.
exact (
INV.(
localNotGlobal)
t'
e' (
get_stk_in A)
_ _ (
Genv.invert_find_symbol _ _ Q)
Hy).
-
destruct (
Genv.invert_symbol ge b)
as [
q|]
eqn:
Q;
intro;
eq_some_inv.
destruct (
Genv.invert_symbol ge b')
as [
q'|]
eqn:
Q';
intros;
eq_some_inv.
congruence.
Qed.
Lemma assign_const c i (
nm :
num) :
∀ ρ, ρ ∈ γ(
nm) →
match AbMachineEnv.assign c (
me_const_i _ i)
nm with
|
Bot =>
False
|
NotBot nm' => (
upd ρ
c (
MNint i)) ∈ γ(
nm')
end.
Proof.
Definition tnum :
Type := (
points_to *
num)%
type.
Definition tnum_iter :
Type := (
points_to *
num_iter)%
type.
Section TNUM_GAMMA.
Context (
stk:
list (
temp_env *
env)).
Instance tnum_gamma :
gamma_op tnum (
cell →
val) :=
λ τ
_ν ρ,
let '(τ, ν) := τ
_ν
in
ρ ∈
points_to_gamma ge stk (τ) ∧
∃ ρ',
ρ' ∈ (
compat ρ ∩ γ ν).
Instance tnum_iter_gamma :
gamma_op tnum_iter (
cell →
val) :=
λ τ
_ν ρ,
let '(τ, ν) := τ
_ν
in
ρ ∈
points_to_gamma ge stk (τ) ∧
∃ ρ',
ρ' ∈ (
compat ρ ∩ γ ν).
Instance tnum_leb_correct :
leb_op_correct (
points_to *
num) (
cell →
val).
Proof.
Instance tnum_top_correct :
top_op_correct ((
points_to *
num)+⊥) (
cell →
val).
Proof.
Instance tnum_join_correct :
join_op_correct (
points_to *
num) ((
points_to *
num)+⊥) (
cell →
val).
Proof.
Section REALIZATION.
Definition is_int (
tp:
points_to) (
c:
cell) :
bool :=
ACTreeDom.get c tp ⊑
Just TyInt.
Lemma is_int_intro (
tp:
points_to) (ρ:
cell →
val) (
TP: ρ ∈
points_to_gamma ge stk tp) (
c:
cell) (
P:
bool →
Prop):
(
P false) →
((∃
i, ρ
c =
Vint i) →
P true) →
P (
is_int tp c).
Proof.
intros F T.
generalize (
TP c).
unfold is_int.
case (
ACTreeDom.get).
intros _;
exact F.
intros ();
try (
intros _;
exact F);
try intros [ |
bs ];
try (
intros _;
exact F);
destruct (ρ
c);
try (
intros ();
fail);
intros Hi;
apply T;
vauto.
Qed.
Global Opaque is_int.
Definition realize_u8_from_κ (κ:
typed_memory_chunk) (
ab:
ablock) (
base:
Z) (
shift:
Z) (
tp:
points_to) (
nm:
num) :
tnum+⊥ :=
let uc :
cell :=
cell_from ab (
base +
shift,
exist _ Mint8unsigned I)
in
let c :
cell :=
cell_from ab (
base, κ)
in
do nm' <-
assign uc (
MEbinop Oand (
MEbinop Oshru (
MEvar MNTint c) (
MEconst _ (
MNint (
Int.repr (8 *
shift))))) (
MEconst _ (
MNint (
Int.repr 255))))
nm;
NotBot (
ACTreeDom.set tp uc (
Just TyInt),
nm').
Definition tnum_mono (
x y:
tnum) :
Prop :=
∀ ρ,
Pun.pun_u8 ρ →
ρ ∈ γ
x →
ρ ∈
points_to_gamma ge stk (
fst y) ∧
∀ ρ',
compat ρ ρ' →
ρ' ∈ γ (
snd x) → ρ' ∈ γ (
snd y).
Lemma tnum_m_stronger :
∀
x y,
tnum_mono x y →
Pun.pun_u8 ∩ γ (
x) ⊆ γ (
y).
Proof.
intros (
tp,
nm) (
tp',
nm')
M ρ (
Hpun &
TP & ρ' &
CPT &
NM).
destruct (
M ρ
Hpun (
conj TP (
ex_intro _ _ (
conj CPT NM))))
as (
TP' &
K).
vauto.
Qed.
Lemma tnum_mono_refl x :
tnum_mono x x.
Proof.
destruct x as (tp, nm).
intros ρ Hpun (TP & NM). auto.
Qed.
Lemma tnum_mono_trans y x z :
tnum_mono x y →
tnum_mono y z →
tnum_mono x z.
Proof.
unfold tnum_mono.
intros Hxy Hyz ?
Hp Hx.
destruct (
Hxy _ Hp Hx)
as (
Hy1 &
Hxy').
assert (ρ ∈ γ
y)
as Hy.
destruct y;
split.
auto.
destruct x,
Hx.
hsplit.
eauto.
destruct (
Hyz _ Hp Hy)
as (
Hz1 &
Hyz').
eauto.
Qed.
Definition tnum_mono' (
x:
tnum) (
y':
tnum+⊥) :
Prop :=
∀ ρ,
Pun.pun_u8 ρ →
ρ ∈ γ
x →
match y'
with
|
Bot =>
False
|
NotBot y =>
ρ ∈
points_to_gamma ge stk (
fst y) ∧
∀ ρ',
compat ρ ρ' →
ρ' ∈ γ (
snd x) → ρ' ∈ γ (
snd y)
end.
Lemma realize_u8_from_κ
_sound (κ:
typed_memory_chunk)
ab base shift (
tp:
points_to) (
nm:
num) :
(
Archi.big_endian =
false) →
(
align_chunk (
proj1_sig κ) |
base) →
0 <=
shift <
size_chunk (
proj1_sig κ) ∧
size_chunk (
proj1_sig κ) <= 4 →
let c :
cell :=
cell_from ab (
base, κ)
in
is_int tp c →
tnum_mono' (
tp,
nm) (
realize_u8_from_κ κ
ab base shift tp nm).
Proof.
intros LE AL Hshift c Hint ρ
Hpun (
TP & ρ' &
CPT &
NM).
assert (
Int.ltu (
Int.repr (8 *
shift))
Int.iwordsize)
as Hshift'.
{
set (
s :=
List.map Z.of_nat (
seq 0 4)).
apply (
forallb_forall (λ
x,
Int.ltu (
Int.repr (8 *
x))
Int.iwordsize)
s).
unfold s.
exact eq_refl.
unfold s.
apply in_map_iff.
exists (
Z.to_nat shift).
split.
apply Z2Nat.id.
easy.
apply In_seq.
Psatz.lia.
zify.
rewrite Z2Nat.id;
Psatz.lia.
}
unfold realize_u8_from_κ.
fold c.
set (
uc :=
cell_from ab (
base +
shift,
exist _ Mint8unsigned I)).
assert (∃
i, ρ
c =
Vint i)
as Hi.
{
revert Hint.
apply (
is_int_intro TP);
intros Hint.
exact (
false_not_true Hint _).
intros _.
exact Hint.
}
clear Hint.
destruct Hi as (
i &
Hi).
assert (ρ'
c =
MNint i)
as Hi'.
{
specialize (
CPT c).
rewrite Hi in CPT.
auto. }
set (
me := (
MEbinop Oand
(
MEbinop Oshru (
MEvar MNTint c)
(
MEconst cell (
MNint (
Int.repr (8 *
shift)))))
(
MEconst cell (
MNint (
Int.repr 255))))).
set (
n :=
Int.and (
Int.shru i (
Int.repr (8 *
shift))) (
Int.repr 255)).
assert (
eval_mexpr ρ'
me (
MNint n))
as MEV.
{
econstructor;
vauto.
econstructor;
vauto. }
generalize (@
assign_correct _ _ _ _ NumDom uc me ρ' (
MNint n)
nm NM MEV).
destruct (
assign _ _ _)
as [ |
nm' ]
eqn:
Hassn.
exact id.
intros NM'.
assert (ρ
uc =
Vint n)
as Huc.
{
unfold n.
change (
Int.repr 255)
with (
Int.repr (
two_p 8 - 1)).
erewrite <-
Int.zero_ext_and. 2:
Psatz.lia.
destruct (
Hpun ab κ
base AL)
as (
bytes &
Hnof &
Hbytes &
Hlen &
Huc).
assert (
NPeano.ltb (
Z.to_nat shift) (
Datatypes.length bytes))
as LT.
{
rewrite Hlen.
apply NPeano.ltb_lt.
zify.
unfold size_chunk_nat.
rewrite !
Z2Nat.id;
Psatz.lia. }
specialize (
Huc (
Z.to_nat shift)
LT).
rewrite Z2Nat.id in Huc. 2:
easy.
fold uc in Huc.
rewrite Huc.
fold c in Hbytes.
rewrite Hi in Hbytes.
revert Hlen Hbytes.
clear -
LE Hshift Hnof.
Opaque Z.mul.
unfold decode_val.
destruct bytes as [ |
b₀ [ |
b₁ [ |
b₂ [ |
b₃ [ |
b₄
bytes ] ] ] ] ].
-
discriminate.
-
destruct κ
as [()];
try discriminate;
intros _;
simpl in Hshift;
assert (
shift = 0)
by Psatz.lia;
clear Hshift;
subst shift;
rewrite Int.shru_zero;
destruct b₀;
try discriminate;
intros X;
inv X;
simpl;
f_equal.
rewrite Int.zero_sign_ext_narrow.
reflexivity.
Psatz.lia.
rewrite Int.zero_ext_narrow.
reflexivity.
Psatz.lia.
-
destruct κ
as [()];
try discriminate;
intros _;
simpl in Hshift;
assert (
shift = 0 ∨
shift = 1)
as Hs by Psatz.lia;
clear Hshift;
destruct Hs;
subst shift;
destruct b₀;
try discriminate;
destruct b₁;
try discriminate;
intros X;
inv X;
simpl;
f_equal.
rewrite Int.shru_zero,
Int.zero_sign_ext_narrow. 2:
Psatz.lia.
rewrite decode_int_1, (
decode_int_LE_2 LE).
rewrite Z.mul_comm.
apply z8.
apply (
decode_shift_1s LE).
rewrite Int.shru_zero,
Int.zero_ext_narrow. 2:
Psatz.lia.
rewrite decode_int_1, (
decode_int_LE_2 LE).
rewrite Z.mul_comm.
apply z8.
rewrite <- (
decode_shift_1u LE).
reflexivity.
-
destruct κ
as [()];
discriminate.
-
assert (
shift = 0 ∨
shift = 1 ∨
shift = 2 ∨
shift = 3)
as Hs by Psatz.lia;
clear Hshift.
destruct κ
as [()];
try discriminate;
intros _;
destruct b₀;
try discriminate;
destruct b₁;
try discriminate;
destruct b₂;
try discriminate;
destruct b₃;
try discriminate;
simpl;
try (
rewrite !
andb_false_r;
discriminate);
intros X;
inversion X;
clear X;
subst;
simpl;
f_equal.
repeat (
destruct Hs as [
Hs |
Hs ]);
subst shift.
simpl.
f_equal.
rewrite Int.shru_zero.
unfold decode_int,
rev_if_be.
rewrite LE.
simpl.
rewrite Z.add_0_r.
apply z8.
simpl.
f_equal.
apply NS1,
LE.
simpl.
f_equal.
apply NS2,
LE.
simpl.
f_equal.
apply NS3,
LE.
exfalso.
revert H0 Hnof.
clear.
bif.
destruct v;
intros X;
inv X.
exact false_eq_true_False.
exfalso.
revert H0 Hnof.
clear.
bif.
destruct v;
intros X;
inv X.
exact false_eq_true_False.
-
destruct κ
as [()];
try discriminate;
exfalso;
simpl in Hshift;
clear -
Hshift;
Psatz.lia.
}
split.
-
intros c'.
unfold fst,
upd.
rewrite ACTreeDom.gsspec.
case (
ACTree.elt_eq).
intros ->.
rewrite Huc.
exact I.
intros _.
apply (
TP c').
-
clear ρ'
CPT NM Hi'
MEV NM'.
unfold snd.
intros ρ'
CPT NM.
assert (ρ'
c =
MNint i)
as Hi'.
{
specialize (
CPT c).
rewrite Hi in CPT.
auto. }
assert (
eval_mexpr ρ'
me (
MNint n))
as MEV.
{
econstructor;
vauto.
econstructor;
vauto. }
generalize (@
assign_correct _ _ _ _ NumDom uc me ρ' (
MNint n)
nm NM MEV).
rewrite Hassn.
assert (ρ' +[
uc =>
MNint n ] = ρ')
as EXT.
{
apply Axioms.extensionality.
intros c'.
unfold upd.
case eq_dec.
intros ->.
generalize (
CPT uc).
rewrite Huc.
exact id.
reflexivity. }
setoid_rewrite EXT.
exact id.
Qed.
Definition cell_mem_rect {
T:
Type} :
T →
(
ablock →
Z →
typed_memory_chunk →
T) →
cell →
T :=
λ
b r c,
match c with
|
AClocal f x ofs κ =>
r (
ABlocal f x)
ofs κ
|
ACglobal g ofs κ =>
r (
ABglobal g)
ofs κ
|
ACtemp _ _ =>
b
end.
Definition cell_mem_rect_intro {
T:
Type} (
P:
cell →
T →
Prop) :
∀
b r,
(∀
f r,
P (
ACtemp f r)
b) →
(∀
ab ofs κ,
P (
cell_from ab (
ofs, κ)) (
r ab ofs κ)) →
∀
c,
P c (
cell_mem_rect b r c) :=
λ
b r B R c,
match c with
|
AClocal f x ofs κ =>
R (
ABlocal f x)
ofs κ
|
ACglobal g ofs κ =>
R (
ABglobal g)
ofs κ
|
ACtemp f r =>
B f r
end.
Global Opaque cell_mem_rect.
Definition optimistic_realization_one (
c:
cell) (
tn:
tnum) :
tnum+⊥ :=
let '(
tp,
nm) :=
tn in
match ACTreeDom.get c tp with
|
Just _ =>
NotBot tn
|
All =>
cell_mem_rect
(
NotBot tn)
(λ
ab ofs κ,
match κ
with
|
exist Mint8unsigned _ =>
let (
base,
shift) :=
Z.div_eucl ofs 4
in
let base := 4 *
base in
let c32 :=
cell_from ab (
base,
exist _ Mint32 I)
in
if is_int tp c32
then realize_u8_from_κ (
exist _ Mint32 I)
ab base shift tp nm
else
let (
base,
shift) :=
Z.div_eucl ofs 2
in
let base := 2 *
base in
let c16u :=
cell_from ab (
base,
exist _ Mint16unsigned I)
in
if is_int tp c16u
then realize_u8_from_κ (
exist _ Mint16unsigned I)
ab base shift tp nm
else
let c16s :=
cell_from ab (
base,
exist _ Mint16signed I)
in
if is_int tp c16s
then realize_u8_from_κ (
exist _ Mint16signed I)
ab base shift tp nm
else
let c8s :=
cell_from ab (
ofs,
exist _ Mint8signed I)
in
if is_int tp c8s
then realize_u8_from_κ (
exist _ Mint8signed I)
ab ofs 0
tp nm
else NotBot tn
|
exist Mint8signed _ =>
let c :=
cell_from ab (
ofs, κ)
in
let c8u :=
cell_from ab (
ofs,
exist _ Mint8unsigned I)
in
if is_int tp c8u then
do nm' <-
assign c (
MEunop Ocast8signed (
MEvar MNTint c8u))
nm;
NotBot (
ACTreeDom.set tp c (
Just TyInt),
nm')
else NotBot tn
|
exist Mint16signed _ =>
if ArithLib.divide ofs F2 then
let c :=
cell_from ab (
ofs, κ)
in
let c16u :=
cell_from ab (
ofs,
exist _ Mint16unsigned I)
in
if is_int tp c16u then
do nm' <-
assign c (
MEunop Ocast16signed (
MEvar MNTint c16u))
nm;
NotBot (
ACTreeDom.set tp c (
Just TyInt),
nm')
else NotBot tn
else NotBot tn
|
exist Mint32 _ =>
if ArithLib.divide ofs F4 then
let c :=
cell_from ab (
ofs, κ)
in
let c8 shift :=
cell_from ab (
ofs +
shift,
exist _ Mint8unsigned I)
in
if is_int tp (
c8 0)
then
if is_int tp (
c8 1)
then
if is_int tp (
c8 2)
then
if is_int tp (
c8 3)
then
do nm' <-
assign c
(
MEbinop Oadd (
MEvar MNTint (
c8 0))
(
MEbinop Oadd (
MEbinop Oshl (
MEvar MNTint (
c8 1)) (
MEconst _ (
MNint (
Int.repr 8))))
(
MEbinop Oadd (
MEbinop Oshl (
MEvar MNTint (
c8 2)) (
MEconst _ (
MNint (
Int.repr 16))))
(
MEbinop Oshl (
MEvar MNTint (
c8 3)) (
MEconst _ (
MNint (
Int.repr 24)))))))
nm;
NotBot (
ACTreeDom.set tp c (
Just TyInt),
nm')
else NotBot tn
else NotBot tn
else NotBot tn
else NotBot tn
else NotBot tn
|
_ =>
NotBot tn
end)
c
end.
Lemma optimistic_realization_one_sound (
c:
cell) (
tn:
tnum) :
tnum_mono'
tn (
optimistic_realization_one c tn).
Proof.
destruct tn as (
tp,
nm).
intros ρ
Hpun (
TP,
NM).
simpl.
destruct (
ACTreeDom.get _ _). 2:
auto.
apply cell_mem_rect_intro.
auto.
clear c.
intros ab ofs [() ()];
auto.
-
set (
c8u :=
cell_from ab (
ofs,
exist _ Mint8unsigned I)).
apply (
is_int_intro TP).
auto.
intros (
i &
Hi).
destruct NM as (ρ' &
CPT &
NM).
match goal with
| |-
appcontext[
assign ?
cx ?
mex _ ] =>
set (
c :=
cx);
set (
me :=
mex)
end.
assert (∀ ρ',
compat ρ ρ' →
eval_mexpr ρ'
me (
MNint (
Int.sign_ext 8
i)))
as MEV.
{
clear ρ'
CPT NM.
intros ρ'
CPT.
generalize (
CPT c8u).
rewrite Hi.
simpl.
intros Hi'.
unfold me.
econstructor.
constructor.
symmetry.
exact Hi'.
constructor.
vauto.
}
generalize (@
assign_correct _ _ _ _ NumDom c me ρ'
_ nm NM (
MEV _ CPT)).
destruct (
assign _ _ _)
as [ |
nm' ]
eqn:
Hassn;
simpl.
exact id.
intros NM'.
assert (ρ
c =
Vint (
Int.sign_ext 8
i))
as Hc.
{
destruct (
Hpun ab (
exist _ Mint8signed I)
ofs)
as (
bytes &
Hnof &
Hbytes &
Hlen &
Huc);
simpl in *.
exists ofs;
Psatz.lia.
etransitivity.
exact Hbytes.
clear Hbytes.
destruct bytes as [ |
b₀ [ | ? ? ] ];
try discriminate.
clear Hlen.
generalize (
Huc 0%
nat eq_refl).
simpl.
rewrite Z.add_0_r.
fold c8u.
rewrite Hi.
destruct b₀
as [ |
i₀ | ];
try discriminate.
intros X;
inv X.
unfold decode_val.
simpl.
rewrite !
decode_int_1.
rewrite Int.sign_ext_zero_ext.
reflexivity.
reflexivity.
}
split.
*
intros c'.
unfold ACTreeDom.get.
rewrite ACTree.gsspec.
case (
ACTree.elt_eq).
intros ->.
rewrite Hc.
exact I.
intros _.
exact (
TP c').
*
clear ρ'
CPT NM NM'.
intros ρ'
CPT NM.
generalize (@
assign_correct _ _ _ _ NumDom c me ρ' (
MNint (
Int.sign_ext 8
i))
nm NM).
rewrite Hassn.
assert (ρ' +[
c =>
MNint (
Int.sign_ext 8
i) ] = ρ')
as EXT.
{
apply Axioms.extensionality.
intros c'.
unfold upd.
case eq_dec.
intros ->.
generalize (
CPT c).
rewrite Hc.
exact id.
reflexivity. }
setoid_rewrite EXT.
intros X;
apply X.
apply MEV,
CPT.
-
elim_div.
intros (-> & [
Hrem | ? ]).
Psatz.lia. 2:
Psatz.lia.
bif'.
apply realize_u8_from_κ
_sound;
auto.
simpl.
eexists;
apply Z.mul_comm.
simpl.
Psatz.lia.
split;
assumption.
elim_div.
intros (
Hdiv & [
Hrem' | ? ]).
Psatz.lia. 2:
Psatz.lia.
bif'.
apply realize_u8_from_κ
_sound;
auto.
simpl.
eexists;
apply Z.mul_comm.
simpl.
Psatz.lia.
split;
assumption.
bif'.
apply realize_u8_from_κ
_sound;
auto.
simpl.
eexists;
apply Z.mul_comm.
simpl.
Psatz.lia.
split;
assumption.
bif'.
apply realize_u8_from_κ
_sound;
auto.
simpl.
eexists;
symmetry;
apply Z.mul_1_r.
simpl.
Psatz.lia.
split;
assumption.
auto.
-
assert (
Hdiv:=
ArithLib.divide_ok ofs F2).
destruct ArithLib.divide. 2:
auto.
set (
c16u :=
cell_from ab (
ofs,
exist _ Mint16unsigned I)).
apply (
is_int_intro TP).
auto.
intros (
i &
Hi).
destruct NM as (ρ' &
CPT &
NM).
match goal with
| |-
appcontext[
assign ?
cx ?
mex _ ] =>
set (
c :=
cx);
set (
me :=
mex)
end.
assert (∀ ρ',
compat ρ ρ' →
eval_mexpr ρ'
me (
MNint (
Int.sign_ext 16
i)))
as MEV.
{
clear ρ'
CPT NM.
intros ρ'
CPT.
generalize (
CPT c16u).
rewrite Hi.
simpl.
intros Hi'.
unfold me.
econstructor.
constructor.
symmetry.
exact Hi'.
constructor.
vauto.
}
generalize (@
assign_correct _ _ _ _ NumDom c me ρ'
_ nm NM (
MEV _ CPT)).
destruct (
assign _ _ _)
as [ |
nm' ]
eqn:
Hassn;
simpl.
exact id.
intros NM'.
assert (ρ
c =
Vint (
Int.sign_ext 16
i))
as Hc.
{
destruct (
Hpun ab (
exist _ Mint16signed I)
ofs)
as (
bytes &
Hnof &
Hbytes &
Hlen &
Huc);
simpl in *.
intuition.
etransitivity.
exact Hbytes.
clear Hbytes.
destruct bytes as [ |
b₀ [ |
b₁ [ | ? ? ] ] ];
try discriminate.
clear Hlen.
destruct (
Hpun ab (
exist _ Mint16unsigned I)
ofs)
as (
bytes' &
Hnof' &
Hbytes' &
Hlen' &
Huc');
simpl in *.
intuition.
destruct bytes'
as [ |
b'₀ [ |
b'₁ [ | ? ? ] ] ];
try discriminate.
clear Hlen'.
unfold typed_memory_chunk in Hbytes'.
fold c16u in Hbytes'.
rewrite Hi in Hbytes'.
destruct b'₀
as [ |
i'₀ | ];
try discriminate.
destruct b'₁
as [ |
i'₁ | ];
try discriminate.
unfold decode_val in Hbytes'.
simpl in Hbytes'.
inv Hbytes'.
generalize (
Huc 0%
nat eq_refl).
rewrite (
Huc' 0%
nat eq_refl).
simpl.
destruct b₀
as [ |
i₀ | ];
try discriminate.
generalize (
Huc 1%
nat eq_refl).
rewrite (
Huc' 1%
nat eq_refl).
simpl.
destruct b₁
as [ |
i₁ | ];
try discriminate.
unfold decode_val.
simpl.
rewrite !
decode_int_1, !
decode_int_LE_2;
auto.
assert (∀
x y,
Vint x =
Vint y →
x =
y)
as vint_inj.
exact (λ
x y H,
let '
eq_refl :=
H in eq_refl).
assert (∀
x y,
eqb (
Int.eq (
Int.zero_ext 8 (
Int.repr (
Byte.unsigned x))) (
Int.zero_ext 8 (
Int.repr (
Byte.unsigned y)))) (
Byte.eq x y))
as ze8rbu_inj'.
intros x.
apply (
for_all_byte_correct).
revert x.
apply (
for_all_byte_correct).
vm_compute.
reflexivity.
assert (∀
x y, (
Int.zero_ext 8 (
Int.repr (
Byte.unsigned x))) =
Int.zero_ext 8 (
Int.repr (
Byte.unsigned y)) →
x =
y)
as ze8rbu_inj.
{
intros x y H.
generalize (
ze8rbu_inj'
x y).
rewrite H,
Int.eq_true.
generalize (
Byte.eq_spec x y).
simpl.
case Byte.eq;
easy. }
intros Hi₁.
apply vint_inj,
ze8rbu_inj in Hi₁.
intros Hi₀.
apply vint_inj,
ze8rbu_inj in Hi₀.
f_equal.
rewrite Int.sign_ext_zero_ext.
congruence.
reflexivity.
}
split.
*
intros c'.
unfold ACTreeDom.get.
rewrite ACTree.gsspec.
case (
ACTree.elt_eq).
intros ->.
rewrite Hc.
exact I.
intros _.
exact (
TP c').
*
clear ρ'
CPT NM NM'.
intros ρ'
CPT NM.
generalize (@
assign_correct _ _ _ _ NumDom c me ρ' (
MNint (
Int.sign_ext 16
i))
nm NM).
rewrite Hassn.
assert (ρ' +[
c =>
MNint (
Int.sign_ext 16
i) ] = ρ')
as EXT.
{
apply Axioms.extensionality.
intros c'.
unfold upd.
case eq_dec.
intros ->.
generalize (
CPT c).
rewrite Hc.
exact id.
reflexivity. }
setoid_rewrite EXT.
intros X;
apply X.
apply MEV,
CPT.
-
assert (
Hdiv:=
ArithLib.divide_ok ofs F4).
destruct ArithLib.divide. 2:
auto.
destruct Hdiv as [
Hdiv _].
specialize (
Hdiv eq_refl).
set (
c8 shift :=
cell_from ab (
ofs +
shift,
exist _ Mint8unsigned I)).
fold (
c8 0).
fold (
c8 1).
fold (
c8 2).
fold (
c8 3).
apply (
is_int_intro TP).
auto.
intros Hint₀.
apply (
is_int_intro TP).
auto.
intros Hint₁.
apply (
is_int_intro TP).
auto.
intros Hint₂.
apply (
is_int_intro TP).
auto.
intros Hint₃.
destruct NM as (ρ' &
CPT &
NM).
hsplit.
match goal with
| |-
appcontext[
assign ?
cx ?
mex _ ] =>
set (
c :=
cx);
set (
me :=
mex)
end.
set (
n :=
Int.add i2 (
Int.add (
Int.shl i1 (
Int.repr 8))
(
Int.add (
Int.shl i0 (
Int.repr 16)) (
Int.shl i (
Int.repr 24))))).
assert (∀ ρ',
compat ρ ρ' →
eval_mexpr ρ'
me (
MNint n))
as MEV.
{
clear ρ'
CPT NM.
intros ρ'
CPT.
generalize (
CPT (
c8 0)).
rewrite Hint₀.
simpl.
intros H₀.
generalize (
CPT (
c8 1)).
rewrite Hint₁.
simpl.
intros H₁.
generalize (
CPT (
c8 2)).
rewrite Hint₂.
simpl.
intros H₂.
generalize (
CPT (
c8 3)).
rewrite Hint₃.
simpl.
intros H₃.
unfold me.
econstructor.
constructor.
symmetry.
eassumption.
constructor.
econstructor.
econstructor.
constructor.
symmetry.
eassumption.
constructor.
vauto.
vauto.
econstructor.
econstructor.
constructor.
symmetry.
eassumption.
constructor.
vauto.
vauto.
econstructor.
constructor.
symmetry.
eassumption.
constructor.
vauto.
vauto.
vauto.
vauto.
vauto.
}
generalize (@
assign_correct _ _ _ _ NumDom c me ρ'
_ nm NM (
MEV _ CPT)).
destruct (
assign _ _ _)
as [ |
nm' ]
eqn:
Hassn;
simpl.
exact id.
unfold n in MEV.
intros NM'.
assert (ρ
c =
Vint (
Int.add i2 (
Int.add (
Int.shl i1 (
Int.repr 8)) (
Int.add (
Int.shl i0 (
Int.repr 16)) (
Int.shl i (
Int.repr 24))))))
as Hc.
{
clear NM'.
destruct (
Hpun ab (
exist _ Mint32 I)
_ Hdiv)
as (
bytes &
Hnof &
Hbytes &
Hlen &
Huc).
etransitivity.
exact Hbytes.
clear Hbytes.
simpl in *.
destruct bytes as [ |
b₀ [ |
b₁ [ |
b₂ [ |
b₃ [ |
b₄
bytes ] ] ] ] ];
try discriminate.
clear Hlen.
generalize (
Huc 0%
nat eq_refl).
simpl.
fold (
c8 0).
rewrite Hint₀.
destruct b₀
as [ |
i₀ | ];
try discriminate.
intros X;
inv X.
generalize (
Huc 1%
nat eq_refl).
simpl.
fold (
c8 1).
rewrite Hint₁.
destruct b₁
as [ |
i₁ | ];
try discriminate.
intros X;
inv X.
generalize (
Huc 2%
nat eq_refl).
simpl.
fold (
c8 2).
rewrite Hint₂.
destruct b₂
as [ |
i₂ | ];
try discriminate.
intros X;
inv X.
generalize (
Huc 3%
nat eq_refl).
simpl.
fold (
c8 3).
rewrite Hint₃.
destruct b₃
as [ |
i₃ | ];
try discriminate.
intros X;
inv X.
unfold decode_val.
simpl.
rewrite decode_int_LE_4. 2:
auto.
rewrite !
decode_int_1.
f_equal.
rewrite Int.add_unsigned.
f_equal.
rewrite !
Int.shl_mul_two_p.
change (
two_p (
Int.unsigned (
Int.repr 8)))
with 256.
change (
two_p (
Int.unsigned (
Int.repr 16)))
with 65536.
change (
two_p (
Int.unsigned (
Int.repr 24)))
with 16777216.
rewrite !
Z.mul_add_distr_r.
assert (
Int.unsigned (
Int.mul (
Int.zero_ext 8 (
Int.repr (
Byte.unsigned i₂))) (
Int.repr 65536)) +
Int.unsigned
(
Int.mul (
Int.zero_ext 8 (
Int.repr (
Byte.unsigned i₃)))
(
Int.repr 16777216)) <
Int.modulus).
{
clear.
generalize (
mul_byte1 i₂).
generalize (
mul_byte2 i₃).
change Int.modulus with 4294967296.
Psatz.lia. }
rewrite unsigned_add.
f_equal.
clear.
apply Z.eqb_eq.
revert i₀.
apply (
for_all_byte_correct).
vm_compute.
reflexivity.
rewrite unsigned_add.
f_equal.
clear.
apply Z.eqb_eq.
revert i₁.
apply (
for_all_byte_correct).
vm_compute.
reflexivity.
f_equal.
clear.
apply Z.eqb_eq.
revert i₂.
apply (
for_all_byte_correct).
vm_compute.
reflexivity.
clear.
apply Z.eqb_eq.
revert i₃.
apply (
for_all_byte_correct).
vm_compute.
reflexivity.
auto.
rewrite unsigned_add. 2:
auto.
generalize (
mul_byte0 i₁).
generalize (
mul_byte1 i₂).
generalize (
mul_byte2 i₃).
change Int.modulus with 4294967296.
clear.
Psatz.lia.
}
split.
*
intros c'.
unfold ACTreeDom.get.
rewrite ACTree.gsspec.
case (
ACTree.elt_eq).
intros ->.
unfold typed_memory_chunk.
fold c.
rewrite Hc.
exact I.
intros _.
exact (
TP c').
*
clear ρ'
CPT NM NM'.
intros ρ'
CPT NM.
generalize (@
assign_correct _ _ _ _ NumDom c me ρ' (
MNint n)
nm NM).
rewrite Hassn.
assert (ρ' +[
c =>
MNint n ] = ρ')
as EXT.
{
apply Axioms.extensionality.
intros c'.
unfold upd.
case eq_dec.
intros ->.
generalize (
CPT c).
rewrite Hc.
exact id.
reflexivity. }
setoid_rewrite EXT.
intros X;
apply X.
apply MEV,
CPT.
Qed.
Global Opaque optimistic_realization_one.
Definition optimistic_realization (
cells:
CellSet.t) (
tn:
tnum) :
tnum+⊥ :=
CellSet.fold (λ
c tn,
bind tn (
optimistic_realization_one c))
cells (
NotBot tn).
Lemma optimistic_realization_sound cells tn:
tnum_mono'
tn (
optimistic_realization cells tn).
Proof.
destruct tn as (
tp,
nm).
intros ρ
Hpun (
TP &
NM).
unfold optimistic_realization.
apply CSO.foldspec;
auto.
clear -
Hpun NM.
intros cells cells'
tn tn'
c Hc Hrem TN.
destruct tn'
as [ |
tn' ].
exact TN.
destruct TN as [
TP'
NM'].
simpl.
generalize (
optimistic_realization_one_sound c tn'
Hpun).
destruct (
optimistic_realization_one _ _)
as [ | (
tp',
nm') ].
intros X;
apply X.
destruct tn'
as (
tp',
nm').
split.
exact TP'.
hsplit.
eauto.
intros [
TP''
NM'' ].
destruct tn'.
split.
auto.
hsplit;
eauto.
split.
exact TP''.
intros ρ'
CPT NMx.
simpl.
apply NM'';
auto.
Qed.
Global Opaque optimistic_realization.
End REALIZATION.
End TNUM_GAMMA.
Variable max_concretize :
N.
Section CONVERT.
Current function.
Variable μ :
fname.
Set of local variables.
Variable ε :
lvarset.
Definition is_local (
v:
ident) :
bool :=
PSet.mem v ε.
Definition addr_of (
v:
ident) :
BlockSet.t :=
if is_local v
then BSO.singleton (
ABlocal μ
v)
else match Genv.find_symbol ge v with
|
Some b =>
BSO.singleton (
ABglobal b)
|
None =>
BlockSet.empty
end.
Variable sz :
sizes.
Definition me_of_pe (
tn:
tnum) (
pe:
pexpr cell) :
nconvert_t annotation_log (
mexpr cell) :=
let '(
tp,
nm) :=
tn in
do me <-
N.nconvert _ ge μ
_ _ (λ
x,
x)
_ _ NumDom sz nm tp pe;
do _ <-
assert _ (
AbMachineEnv.noerror me nm)
(λ
_, "
me_of_pe(" ++
to_string pe ++ "):
error " ++
to_string me);
ret me.
Definition check_align (
nm:
num) (
sz:
Z) (
me:
mexpr cell) :
bool :=
match is_one sz with
|
false =>
is_bot (
AbMachineEnv.assume
(
MEbinop (
Ocmp Cne)
(
MEbinop Omodu me (
me_const_i _ (
Int.repr sz)))
(
me_const_i _ Int.zero))
true nm)
|
e =>
e
end.
Definition join_cellsets (
cs:
list (
CellSet.t+⊤)) :
CellSet.t+⊤ :=
List.fold_left
(λ
acc cells,
match acc with
|
All =>
All
|
Just acc =>
fmap (
CellSet.union acc)
cells
end)
cs
(
Just CellSet.empty).
Lemma join_cellsets_correct cs :
match join_cellsets cs with
|
All =>
In All cs
|
Just cells =>
(∀
s,
In s cs → ∃
s',
s =
Just s') ∧
(∀
s,
In (
Just s)
cs → ∀
c,
CellSet.mem c s →
CellSet.mem c cells) ∧
(∀
c,
CellSet.mem c cells → ∃
s,
CellSet.mem c s ∧
In (
Just s)
cs)
end.
Proof.
elim cs using rev_ind;
clear cs.
-
split.
intros _ ().
split.
intros _ ().
intros c X;
elim (
CellSet.mem_empty X).
-
intros s cs IH.
unfold join_cellsets.
rewrite fold_left_app.
fold (
join_cellsets cs).
simpl.
destruct (
join_cellsets _).
apply in_app;
left;
exact IH.
destruct IH as (
IHall &
IH &
IH').
destruct s as [ |
s ].
apply in_app;
right;
left;
reflexivity.
split; [ |
split ].
+
intros s'
H.
apply in_app in H.
destruct H as [
H | [ <- | () ] ];
eauto.
+
intros s'
H c Hc.
apply in_app in H.
rewrite CellSet.mem_union.
destruct H as [
H | [
H | () ] ].
specialize (
IH _ H _ Hc).
bleft.
exact IH.
bright.
congruence.
+
intros c H.
rewrite CellSet.mem_union in H.
apply orb_prop in H.
destruct H as [
H |
H ].
destruct (
IH'
_ H)
as (
s' &
Hs' &
H').
exists s'.
split.
exact Hs'.
apply in_app;
left;
exact H'.
exists s.
split.
exact H.
apply in_app;
right;
left;
reflexivity.
Qed.
Definition has_type_VP (
pe:
pexpr cell) :
bool :=
match pexpr_get_ty pe with
|
VP =>
true
|
_ =>
false
end.
Definition itv_of_me (
nm:
num) (
me:
mexpr cell) :
mach_num_itv+⊥ :=
get_itv me nm.
Definition int_pair_of_nvi (
nvi:
mach_num_itv+⊥) : (
int *
int)+⊤ :=
match nvi with
|
Bot =>
All
| (
NotBot r) =>
match r with
|
MNIint (
Just (
ZIntervals.ZITV lo hi)) =>
Just (
Int.repr lo,
Int.repr hi)
|
_ =>
All
end
end.
Definition depth (
f:
ident) :
nat :=
(
Pos.to_nat μ -
Pos.to_nat f)%
nat.
Definition mk_log (α:
Annotations.annotation) (
nm:
num) (
ptr:
BlockSet.t) (
me:
mexpr cell) :
Annotations.annotation :=
(
fst α,
match int_pair_of_nvi (
itv_of_me nm me)
with
|
All =>
nil
|
Just rng =>
List.map
(λ
b,
match b with
|
ABlocal f x =>
Annotations.ABlocal (
depth f)
x rng
|
ABglobal b =>
Annotations.ABglobal match Genv.invert_symbol ge b with Some g =>
g |
None =>
xH end rng
end
)
(
BlockSet.elements ptr)
end).
Definition am_log (
a:
annotation_log) :
nconvert_t annotation_log unit :=
(
tt ::
nil, (
nil,
a ::
nil)).
Definition deref_pexpr (α:
option _) (
tn:
tnum) (κ:
typed_memory_chunk) (
lpe:
list (
pexpr cell)) :
alarm_mon annotation_log (
CellSet.t+⊤) :=
let al :=
align_chunk (
proj1_sig κ)
in
do cells <- ((
do pe <- (
ret lpe :
nconvert_t _ (
pexpr cell));
do _ <-
assert _ (
has_type_VP pe)
(λ
_, "
deref_pexpr:
maybe not a pointer (" ++
to_string pe ++ ")");
let aptr :=
pt_eval_pexpr ge μ (
fst tn)
pe in
do me <-
me_of_pe tn pe;
do _ <-
assert _ (
check_align (
snd tn)
al me)
(λ
_, "
bad align (" ++
to_string (
proj1_sig κ) ++ "): " ++
to_string me);
let offs :=
concretize_int max_concretize me (
snd tn)
in
match aptr with
|
Just (
TyPtr (
Just ptr) |
TyZPtr (
Just ptr)) =>
do _ <-
match α
with None =>
ret tt |
Some α' =>
am_log (
mk_log α' (
snd tn)
ptr me)
end;
ret (
set_product ptr κ
offs)
|
_ =>
ret All
end) :
alarm_mon _ (
list (
CellSet.t+⊤)));
ret (
join_cellsets cells).
Lemma deref_pexpr_inv α
tn κ
lpe cells :
am_get (
deref_pexpr α
tn κ
lpe) =
Some cells →
let al :=
align_chunk (
proj1_sig κ)
in
∀
pe,
In pe lpe →
pexpr_get_ty pe =
VP ∧
∃
lme,
am_get (
me_of_pe tn pe) =
Some lme ∧
∀
me,
In me lme →
check_align (
snd tn)
al me =
true ∧
let ofs :=
concretize_int max_concretize me (
snd tn)
in
match cells with All =>
True |
Just cells =>
ofs ≠
NotBot All ∧
∃
ptr,
(
pt_eval_pexpr ge μ (
fst tn)
pe =
Just (
TyPtr (
Just ptr)) ∨
pt_eval_pexpr ge μ (
fst tn)
pe =
Just (
TyZPtr (
Just ptr))) ∧
∀
b i,
BlockSet.mem b ptr →
i ∈ γ(
ofs) →
CellSet.mem (
cell_from b (
Int.unsigned i, κ))
cells
end.
Proof.
Definition constant_of_constant (
c:
Csharpminor.constant) :
constant :=
match c with
|
Csharpminor.Ointconst i =>
Ointconst i
|
Csharpminor.Olongconst i =>
Olongconst i
|
Csharpminor.Ofloatconst f =>
Ofloatconst f
|
Csharpminor.Osingleconst f =>
Osingleconst f
end.
Definition convert_err (
e:
expr)
msg :=
("
convert(" ++
to_string e ++ "): " ++
msg ++
new_line ++
"
Function: " ++
to_string μ ++
new_line ++
"
Locals: " ++
to_string ε ++
new_line ).
Opaque convert_err.
Definition convert_t A :=
tnum ->
alarm_mon annotation_log (
tnum *
A).
Local Instance convert_monad :
monad convert_t :=
{
ret A := λ
a tn,
ret (
tn,
a);
bind A B := λ
m f tn,
do (
tn',
a) <-
m tn;
f a tn'
}.
Let get_tnum :
convert_t tnum := λ
tn,
ret (
tn,
tn).
Let lift {
A} (
m:
alarm_mon annotation_log A) :
convert_t A :=
λ
tn,
fmap (λ
x, (
tn,
x))
m.
Local Notation "'
alarm'
e" := ((λ
tn, (((
tn,
tt), ((λ
_,
e) ::
nil,
nil)))):(
convert_t _)) (
at level 100).
Definition typ_of_type (
ty:
type) :
typ :=
match ty with
|
TyFloat =>
VF
|
TySingle =>
VS
|
TyLong =>
VL
|
TyZero |
TyInt =>
VI
|
TyPtr _ =>
VP
|
TyZPtr _ |
TyIntPtr =>
VIP
end.
Let convert_var (
e:
expr) (
c:
cell) :
convert_t (
list (
pexpr cell)) :=
λ
tn,
let '(
tp,
nm) :=
tn in
match ACTreeDom.get c tp with
|
Just ty =>
ret (
PEvar c (
typ_of_type ty) ::
nil)
tn
|
All => (
do _ <-
alarm (
convert_err e ("
bad temp in " ++
to_string μ));
ret nil)
tn
end.
Let realize (
cells:
CellSet.t) :
convert_t (
list cell) :=
λ
tn,
match optimistic_realization cells tn with
|
Bot =>
ret nil tn
|
NotBot tn' =>
ret (
CellSet.elements cells)
tn'
end.
Definition typ_eval_constant (
cst:
constant) :
typ :=
match cst with
|
Ointconst n =>
VI
|
Ofloatconst n =>
VF
|
Osingleconst n =>
VS
|
Olongconst n =>
VL
|
Oaddrsymbol s ofs =>
VP
end.
Definition typ_eval_binop (
op:
binary_operation) (
arg1 arg2:
typ):
typ :=
match op with
|
Oadd =>
match arg1,
arg2 with
|
VP,
VI
|
VI,
VP =>
VP
|
VI,
VI =>
VI
|
_,
_ =>
VIP
end
|
Osub =>
match arg1,
arg2 with
|
VP,
VI =>
VP
|
VP,
VP
|
VI,
VI =>
VI
|
_,
_ =>
VIP
end
|
Omul |
Odiv |
Odivu |
Omod |
Omodu |
Oand |
Oor |
Oxor |
Oshl
|
Oshr |
Oshru |
Ocmp _ |
Ocmpu _ |
Ocmpf _ |
Ocmpfs _ |
Ocmpl _ |
Ocmplu _ =>
VI
|
Oaddf |
Osubf |
Omulf |
Odivf =>
VF
|
Oaddfs |
Osubfs |
Omulfs |
Odivfs =>
VS
|
Oaddl |
Osubl |
Omull |
Odivl |
Odivlu |
Omodl |
Omodlu |
Oandl
|
Oorl |
Oxorl |
Oshll |
Oshrl |
Oshrlu =>
VL
end.
Remark eval_constant_wt {
c} :
type_of_constant c (
typ_eval_constant c).
Proof.
case c;
intros;
exact eq_refl. Qed.
Remark eval_binop_wt {
op ty ty'} :
type_of_binop op (
typ_eval_binop op ty ty').
Proof.
destruct op;
try reflexivity;
destruct ty;
try exact I;
destruct ty';
exact I.
Qed.
Fixpoint convert (
e:
expr) :
convert_t (
list (
pexpr cell)) :=
let err :=
convert_err e in
match e with
|
Evar v =>
convert_var e (
ACtemp μ
v)
|
Eaddrof i =>
if is_local i
then ret (
PElocal _ i ::
nil)
else match Genv.find_symbol ge i with
|
Some _ =>
ret (
PEconst _ (
Oaddrsymbol i Int.zero)
VP eq_refl ::
nil)
|
None =>
do _ <-
alarm (
err "
bad global variable");
ret nil
end
|
Econst cst =>
let cst :=
constant_of_constant cst in
ret (
PEconst _ cst (
typ_eval_constant cst)
eval_constant_wt ::
nil)
|
Eunop op e1 =>
do e1' <-
convert e1;
ret (
rev_map (λ
e,
PEunop op e (
t :=
type_of_unop op)
eq_refl)
e1')
|
Ebinop op e1 e2 =>
do e1' <-
convert e1;
do e2' <-
convert e2;
ret (
map2 (λ
e1 e2,
PEbinop op e1 e2
(
typ_eval_binop op (
pexpr_get_ty e1) (
pexpr_get_ty e2))
eval_binop_wt
)
e1'
e2')
|
Eload α κ
e1 =>
do e1' <-
convert e1;
do κ <-
match κ
return convert_t (
option typed_memory_chunk)
with
|
Many32 |
Many64 =>
do _ <-
alarm (
err "
Many32 or Many64");
ret None
| κ =>
ret (
Some (
exist _ κ
I:
typed_memory_chunk))
end;
do tn <-
get_tnum;
do cells <-
match κ
with Some κ =>
lift (
deref_pexpr (
Some α)
tn κ
e1') |
None =>
ret All end;
match cells with
|
All =>
do _ <-
alarm (
err "
too many cells");
ret nil
|
Just cells =>
do cells <-
realize cells;
λ
tn,
let '(
tp,
nm) :=
tn in
lift (
am_map'
annotation_log (λ
c,
match ACTreeDom.get c tp with
|
All =>
Error None (
err ("
bad cell: " ++
to_string c))
|
Just ty =>
Result (
PEvar c (
typ_of_type ty))
end)
cells
)
tn
end
end.
Definition me_of_pe_list (
tn:
tnum) (
lpe:
list (
pexpr cell)) :
alarm_mon annotation_log (
list (
mexpr cell)) :=
flat_map_a annotation_log (
me_of_pe tn) (
ret lpe).
Definition nconvert (
e:
expr) :
convert_t (
list (
mexpr cell)) :=
do lpe <-
convert e;
λ
tn,
lift (
me_of_pe_list tn lpe)
tn.
Definition deref_expr_err (
tn:
tnum) (
e:
expr) (κ:
typed_memory_chunk) (
lpe:
list (
pexpr cell)) :=
("
deref_expr(" ++
to_string e ++ ", " ++
to_string (
proj1_sig κ) ++ ") " ++
to_string lpe )%
string.
Opaque deref_expr_err.
Definition deref_expr α κ (
e:
expr) :
convert_t (
list cell) :=
do lpe <-
convert e;
λ
tn,
lift (
do cells <-
deref_pexpr α
tn κ
lpe;
match cells with
|
All =>
do _ <-
alarm_am (
deref_expr_err tn e κ
lpe);
ret nil
|
Just cell_set =>
ret (
CellSet.elements cell_set)
end
)
tn.
Section CONVERT_CORRECT.
Context (
e:
env) (
tmp:
temp_env) (
m:
mem).
Context (
stk:
list (
temp_env *
env)).
Context (
Hstk: μ =
plength stk).
Let ρ :=
mem_as_fun ge ((
tmp,
e) ::
stk,
m).
Hypothesis E: ∀
i,
is_local i =
true ↔
e !
i ≠
None.
Hypothesis INV :
invariant ((
tmp,
e) ::
stk,
m).
Hypothesis SZ:
m ∈
sizes_gamma ge ((
tmp,
e) ::
stk)
sz.
Lemma Tmp: ∀
i v,
tmp !
i =
Some v → ρ (
ACtemp μ
i) =
v.
Proof.
Hint Resolve Tmp.
Lemma me_of_pe_correct (
tp:
points_to) (
nm:
num) (ρ
n:
cell →
mach_num) (
NM: ρ
n ∈ γ(
nm))
pe lme :
am_get (
me_of_pe (
tp,
nm)
pe) =
Some lme →
am_get (
N.nconvert annotation_log ge μ
_ _ (λ
x,
x)
_ _ NumDom sz nm tp pe) =
Some lme ∧
∀
me,
In me lme → ¬
error_mexpr ρ
n me.
Proof.
Ltac with_me_of_pe q :=
repeat match goal with
|
H :
appcontext[
me_of_pe ?
nm ?
pe ] |-
_ =>
generalize (
me_of_pe_correct pe);
destruct (
me_of_pe nm pe);
q
end.
Lemma me_of_pe_list_correct nm lpe lme log :
me_of_pe_list nm lpe = (
lme, (
nil,
log)) →
flat_map_a_spec _ (
me_of_pe nm)
lpe lme.
Proof.
Lemma pexpr_get_ty_ok (
pe:
pexpr cell)
v :
eval_pexpr ge m ρ
e pe v →
v ≠
Vundef →
v ∈ γ(
pexpr_get_ty pe).
Proof.
Lemma check_align_correct (
nm:
num) (ρ
n:
cell →
mach_num) (
NM: ρ
n ∈ γ(
nm))
al me :
al = 1 ∨
al = 2 ∨
al = 4 ∨
al = 8 →
check_align nm al me =
true →
∀
n,
eval_mexpr ρ
n me (
MNint n) →
Int.unsigned n =
al *
Int.unsigned (
Int.divu n (
Int.repr al)).
Proof.
Ltac subs :=
repeat match goal with H : ?
a = ?
b |-
_ =>
subst a ||
subst b end.
Let Hpun : ρ ∈
pun_u8 :=
mem_as_fun_pun_u8 _ _ INV.(
noIntFragment).
Lemma typ_of_type_gamma G ty :
type_gamma G ty ⊆
gamma_typ (
typ_of_type ty).
Proof.
intros x TY.
apply type_gamma_inv in TY.
destruct ty;
hsplit;
repeat match goal with H :
_ ∨
_ |-
_ =>
destruct H;
hsplit |
H :
x =
_ |-
_ =>
rewrite H end;
exact I.
Qed.
Lemma convert_wf (
q:
expr):
∀ (
tn:
tnum) (
TN: ρ ∈
tnum_gamma ((
tmp,
e) ::
stk)
tn),
match am_get (
convert q tn)
with
|
Some (
tn',
lp) =>
tnum_mono ((
tmp,
e) ::
stk)
tn tn'
∧
∀
pe,
In pe lp →
N.nconvert_def_pre ge e ρ
pe
|
None =>
True
end.
Proof.
induction q;
intros (
tp,
nm)
TN.
-
simpl.
set (
c :=
ACtemp μ
i).
generalize (
proj1 TN c).
destruct (
ACTreeDom.get c tp)
as [
ty|].
exact id.
intros TY.
simpl.
split.
apply tnum_mono_refl.
intros pe [ <- | () ].
simpl.
revert TY.
apply typ_of_type_gamma.
-
simpl.
generalize (
E i).
destruct is_local.
intros (
A &
_).
split.
apply tnum_mono_refl.
intros pe [ <- | () ].
simpl.
unfold env_as_fun.
destruct (
e !
i)
as [()|].
intro;
eq_some_inv.
elim (
A eq_refl eq_refl).
intros _.
destruct (
Genv.find_symbol ge i)
eqn:
FS.
split.
apply tnum_mono_refl.
intros pe [ <- | () ].
simpl.
rewrite FS.
intro;
eq_some_inv.
exact I.
-
split.
apply tnum_mono_refl.
intros pe [ <- | () ].
destruct c;
exact I.
-
simpl.
unfold bind.
simpl.
apply am_bind_case.
easy.
intros;
exact I.
intros ((
tp',
nm'),
lp)
log LP.
specialize (
IHq (
tp,
nm)
TN).
rewrite LP in IHq.
destruct IHq as (
MONO &
IHq ).
split.
easy.
intros pe PE.
rewrite rev_map_correct, <-
in_rev,
in_map_iff in PE.
destruct PE as (
pe' & <- &
PE).
simpl.
apply IHq;
auto.
-
simpl.
unfold bind.
simpl.
apply am_bind_case.
easy.
intros;
exact I.
intros ((
tp1,
nm1),
lp1)
log1 LP1.
specialize (
IHq1 (
tp,
nm)
TN).
rewrite LP1 in IHq1.
destruct IHq1 as (
MONO1 &
IHq1 ).
apply am_bind_case.
easy.
intros;
exact I.
intros ((
tp2,
nm2),
lp2)
log2 LP2.
specialize (
IHq2 (
tp1,
nm1) (
tnum_m_stronger MONO1 (
conj (
mem_as_fun_pun_u8 _ _ INV.(
noIntFragment))
TN))).
rewrite LP2 in IHq2.
destruct IHq2 as (
MONO2 &
IHq2 ).
split.
eauto using tnum_mono_trans.
destruct b;
try (
intros pe PE;
rewrite map2_correct in PE;
unfold map2_spec in PE;
rewrite <-
in_rev,
in_flat_map in PE;
destruct PE as (
pe1 &
PE1 &
PE);
rewrite in_map_iff in PE;
destruct PE as (
pe2 & <- &
PE);
vauto).
-
rename m0 into κ.
simpl.
unfold bind.
simpl.
apply am_bind_case.
easy.
intros;
exact I.
intros ((
tp1,
nm1),
lp)
log1 LP.
apply am_bind_case.
easy.
intros;
exact I.
intros ((
tp2,
nm2), κ')
log2 K.
assert (
Hκ:
log2 =
nil ∧
tp2 =
tp1 ∧
nm2 =
nm1 ∧ ∃
Hκ, κ' =
Some (
exist _ κ
Hκ))
by (
destruct κ;
eq_some_inv;
subs;
eauto).
destruct Hκ
as (-> & -> & -> & [
Hκ ->]).
clear K.
apply am_bind_case.
easy.
intros;
exact I.
intros (
nm3, [|
cells]).
intros;
exact I.
unfold lift,
fmap.
apply am_bind_case.
intros x y l l'
H l0 H0.
eq_some_inv.
subs.
specialize (
H _ eq_refl).
auto.
intros;
eq_some_inv.
intros x log Hcells log'
Q.
simpl in Q.
eq_some_inv;
subs.
generalize (
deref_pexpr_inv (
Some a) (
tp1,
nm1) (
exist _ κ
Hκ)
lp).
rewrite Hcells.
intros K.
specialize (
IHq (
tp,
nm)
TN).
rewrite LP in IHq.
destruct IHq as (
MONO1 &
IHq ).
assert (ρ ∈
tnum_gamma ((
tmp,
e) ::
stk) (
tp1,
nm1))
as TN1.
apply (
tnum_m_stronger MONO1);
auto.
unfold realize.
generalize (@
optimistic_realization_sound ((
tmp,
e) ::
stk)
cells (
tp1,
nm1)).
destruct (
optimistic_realization _ _)
as [ | (
tp',
nm') ];
simpl;
intros Hreal;
elim (
Hreal ρ
Hpun TN1).
intros TP'
NM'.
with_am_map'.
simpl.
intros (
X &
Y).
split.
eauto using tnum_mono_trans.
clear Hreal.
intros pe PE.
destruct (
X pe PE)
as (
c &
C &
C').
simpl in *.
destruct (
ACTreeDom.get c _)
as [|
ty]
eqn:
TY;
inversion C.
unfold N.nconvert_def_pre.
generalize (
TP'
c).
rewrite TY.
apply typ_of_type_gamma.
Qed.
Lemma convert_free_def (
q:
expr) :
∀ (
tn:
tnum) (
TN: ρ ∈
tnum_gamma ((
tmp,
e) ::
stk)
tn),
match am_get (
convert q tn)
with
|
Some (
tn',
lp) =>
∀
pe,
In pe lp ->
∀
x,
pe_free_var pe x -> ρ
x ≠
Vundef
|
None =>
True
end.
Proof.
induction q;
intros tn TN.
-
destruct tn as (
tp,
nm).
destruct TN as (
TP,
NM).
simpl.
set (
c :=
ACtemp μ
i).
generalize (
TP c).
destruct (
ACTreeDom.get c tp).
exact id.
intros H pe [<-|[]]
x ->
EQ.
rewrite EQ in H.
apply type_gamma_inv'
in H.
exact H.
-
simpl.
destruct is_local.
now intros pe [<-|[]]
x [].
destruct (
Genv.find_symbol ge i).
now intros pe [<-|[]]
x [].
exact I.
-
now intros pe [<-|[]]
x [].
-
simpl.
unfold bind.
simpl.
apply am_bind_case.
easy.
intros;
exact I.
intros ((
tp1,
nm1),
lp)
log LP pe PE.
rewrite rev_map_correct, <-
in_rev,
in_map_iff in PE.
destruct PE as (
pe' & <- &
PE).
specialize (
IHq _ TN).
rewrite LP in IHq.
simpl.
apply IHq;
auto.
-
simpl.
unfold bind.
simpl.
apply am_bind_case.
easy.
intros;
exact I.
intros ((
tp1,
nm1),
lp1)
log1 LP1.
apply am_bind_case.
easy.
intros;
exact I.
intros ((
tp2,
nm2),
lp2)
log2 LP2.
specialize (
IHq1 _ TN).
rewrite LP1 in IHq1.
generalize (
convert_wf q1 _ TN).
rewrite LP1.
intros [
MONO1 _].
specialize (
IHq2 _ (
tnum_m_stronger MONO1 (
conj Hpun TN))).
generalize (
convert_wf q2 _ (
tnum_m_stronger MONO1 (
conj Hpun TN))).
rewrite LP2.
intros [
MONO2 _].
rewrite LP2 in IHq2.
simpl in IHq1,
IHq2.
destruct b;
try (
intros pe PE;
rewrite map2_correct in PE;
unfold map2_spec in PE;
rewrite <-
in_rev,
in_flat_map in PE;
destruct PE as (
pe1 &
PE1 &
PE);
rewrite in_map_iff in PE;
destruct PE as (
pe2 & <- &
PE);
intros x [
Hx|
Hx];
eauto).
-
rename m0 into κ.
simpl.
unfold bind.
simpl.
apply am_bind_case.
easy.
intros;
exact I.
intros ((
tp1,
nm1),
lp)
log LP.
generalize (
convert_wf q _ TN).
rewrite LP.
intros [
MONO1 _].
apply am_bind_case.
easy.
intros;
exact I.
intros ((
tp2,
nm2), κ')
log2 K.
assert (
Hκ:
log2 =
nil ∧
tp2 =
tp1 ∧
nm2 =
nm1 ∧ ∃
Hκ, κ' =
Some (
exist _ κ
Hκ))
by (
destruct κ;
eq_some_inv;
eauto).
destruct Hκ
as (-> & -> & -> & [
Hκ ->]).
clear K.
apply am_bind_case.
easy.
intros;
exact I.
intros (
nm3, [|
cells]).
intros;
exact I.
unfold lift,
fmap.
apply am_bind_case.
intros x y l l'
H ? ?;
eq_some_inv;
subs.
specialize (
H _ eq_refl).
auto.
intros;
eq_some_inv.
intros x log''
Hcells log'
Q.
simpl in Q.
eq_some_inv;
subs.
generalize (
deref_pexpr_inv (
Some a) (
tp1,
nm1) (
exist _ κ
Hκ)
lp).
rewrite Hcells.
clear Hcells.
intros K.
assert (ρ ∈
tnum_gamma ((
tmp,
e) ::
stk) (
tp1,
nm1))
as TN1.
apply (
tnum_m_stronger MONO1);
auto.
unfold realize.
generalize (@
optimistic_realization_sound ((
tmp,
e) ::
stk)
cells (
tp1,
nm1)).
destruct (
optimistic_realization _ _)
as [ | (
tp',
nm') ];
simpl;
intros Hreal;
elim (
Hreal ρ
Hpun TN1).
intros TP'
NM'.
with_am_map'.
simpl in *.
intros (
X &
Y)
pe PE.
destruct (
X pe PE)
as (
c &
C &
C').
destruct (
ACTreeDom.get c _)
as [|
ty]
eqn:
TY;
inversion C.
intros ? <-
Hdef.
generalize (
TP'
c).
fold ρ.
rewrite TY,
Hdef.
now intros H;
apply type_gamma_inv'
in H.
Qed.
Remark align_chunk_4_cases (κ:
memory_chunk) :
align_chunk κ = 1 ∨
align_chunk κ = 2 ∨
align_chunk κ = 4 ∨
align_chunk κ = 8.
Proof.
destruct κ; vauto. Qed.
Lemma type_of_unop_correct op arg v :
Cminor.eval_unop op arg =
Some v →
v ≠
Vundef →
γ (
type_of_unop op)
v.
Proof.
Lemma typ_eval_binop_correct op arg1 arg2 p t1 t2 v :
Cminor.eval_binop op arg1 arg2 p =
Some v →
v ≠
Vundef →
γ
t1 arg1 →
γ
t2 arg2 →
γ (
typ_eval_binop op t1 t2)
v.
Proof.
clear.
assert (∀
b,
Val.of_optbool b ≠
Vundef →
gamma_typ VI (
Val.of_optbool b))
as Hob.
{
intros [ () | ];
exact (λ
_,
I) ||
exact (λ
K,
K eq_refl). }
assert (∀
v w,
option_map Val.of_bool v = (
Some w) →
gamma_typ VI w)
as Hob'.
{
intros [ () | ]
w H;
apply option_map_some in H;
hsplit;
eq_some_inv;
subst;
vauto. }
intros EV Hv Ht1 Ht2.
destruct op;
simpl in *;
eq_some_inv;
subst;
try exact (
Hob _ Hv);
try exact (
Hob'
_ _ EV);
destruct arg1;
try (
specialize (
Hv eq_refl);
exact Hv ||
elim Hv);
apply gamma_typ_inv'
in Ht1;
try subst t1;
try easy;
destruct arg2;
try (
specialize (
Hv eq_refl);
exact Hv ||
elim Hv);
apply gamma_typ_inv'
in Ht2;
try subst t2;
try easy;
try exact I;
simpl in *;
try (
repeat (
destruct Ht1 as [
Ht1 |
Ht1 ]);
subst t1;
try exact I;
repeat (
destruct Ht2 as [
Ht2 |
Ht2 ]);
subst t2;
try exact I
);
try (
revert EV);
try (
bif;
intros;
eq_some_inv;
subst;
vauto)
.
Qed.
Lemma convert_correct (
q:
expr) :
∀ (
tn:
tnum) (
TN: ρ ∈
tnum_gamma ((
tmp,
e) ::
stk)
tn),
match am_get (
convert q tn)
with
|
Some (
tn',
lp) =>
∀
v,
eval_expr ge e tmp m (
expr_erase q)
v →
∃
a,
In a lp ∧
eval_pexpr ge m ρ
e a v
|
None =>
True
end.
Proof.
Ltac ok :=
let K :=
fresh in
intros ?
K;
eexists;
split; [
left;
reflexivity|
eval_expr_inv;
try econstructor;
eauto].
induction q;
intros (
tp,
nm)
TN;
simpl;
try (
split;[
ok|
auto]).
-
set (
c :=
ACtemp μ
i).
destruct TN as (
TP &
NM).
specialize (
TP c).
destruct (
ACTreeDom.get c tp).
exact I.
subst c.
intros ?
K.
eval_expr_inv.
rewrite (
Tmp _ K)
in TP.
eexists.
split.
left.
reflexivity.
econstructor;
eauto.
right.
revert TP.
apply typ_of_type_gamma.
-
bif'.
ok.
unfold env_as_fun.
apply E in Heqb.
subs.
constructor.
inversion H;
clear H;
subs.
rewrite H0.
auto.
congruence.
bif.
simpl.
ok.
inversion H;
clear H;
subs.
exfalso.
generalize (
proj2 (
E i)).
intuition congruence.
simpl.
rewrite H1.
reflexivity.
subs.
simpl.
auto.
exact I.
-
intros v V.
eval_expr_inv.
eexists.
split.
left;
reflexivity.
destruct c;
simpl in *;
eq_some_inv;
subs;
econstructor;
simpl;
eauto.
-
unfold bind.
simpl.
apply am_bind_case.
easy.
intros;
exact I.
intros ((
tp',
nm'),
lp)
log Hlp.
specialize (
IHq _ TN).
rewrite Hlp in IHq.
intros v K.
eval_expr_inv.
destruct (
IHq _ H)
as (
a &
A &
B).
clear IHq.
exists (
PEunop u a (
t :=
type_of_unop u)
eq_refl).
split.
rewrite rev_map_correct, <-
in_rev.
exact (
in_map _ _ _ A).
econstructor;
eauto.
assert (
v =
Vundef \/
v ≠
Vundef)
as D by (
destruct v;
auto;
right;
discriminate).
destruct D.
auto.
right.
eapply type_of_unop_correct;
eassumption.
-
unfold bind.
simpl.
apply am_bind_case.
easy.
intros;
exact I.
intros ((
tp1,
nm1),
lp1)
log1 Hq1.
apply am_bind_case.
easy.
intros;
exact I.
intros ((
tp2,
nm2),
lp2)
log2 Hq2.
specialize (
IHq1 _ TN).
generalize (
convert_wf q1 (
tp,
nm)
TN).
rewrite Hq1.
intros [
MONO1 _].
rewrite Hq1 in IHq1.
specialize (
IHq2 _ (
tnum_m_stronger MONO1 (
conj Hpun TN))).
rewrite Hq2 in IHq2.
simpl in *.
assert (∀
v (
P:
Prop), (
v ≠
Vundef →
P) → (
v =
Vundef ∨
P))
as X by (
clear;
intuition tauto).
destruct b;
try (
intros v V;
eval_expr_inv;
destruct (
IHq1 _ H)
as (
a1 &
A1 &
A1');
destruct (
IHq2 _ H0)
as (
a2 &
A2 &
A2');
try (
eexists;
split; [
eapply in_map2;
eassumption |
econstructor;
eauto];
apply X;
intros Hv;
eapply typ_eval_binop_correct;
eauto;
apply pexpr_get_ty_ok;
eauto;
intros ->;
simpl in *;
eq_some_inv;
try (
destruct v1);
try (
unfold Val.cmp,
Val.cmpu,
Val.cmpf,
Val.cmpfs,
Val.cmpl,
Val.cmplu in *;
destruct c);
simpl in *;
eq_some_inv;
hsplit;
congruence )).
-
unfold bind.
simpl.
rename m0 into κ.
apply am_bind_case.
easy.
intros;
exact I.
intros ((
tp1,
nm1),
lp)
log1 Hlp.
specialize (
IHq _ TN).
rewrite Hlp in IHq.
generalize (
convert_wf q (
tp,
nm)
TN).
rewrite Hlp.
intros [
MONO1 _].
apply am_bind_case.
easy.
intros;
exact I.
intros ((
tp2,
nm2), κ')
log2 K.
assert (
Hκ:
log2 =
nil /\
tp2 =
tp1 /\
nm2 =
nm1 /\ ∃
Hκ, κ' =
Some (
exist _ κ
Hκ))
by (
destruct κ;
eq_some_inv;
eauto).
destruct Hκ
as ( -> & -> & -> & [
Hκ ->]).
clear K.
apply am_bind_case.
easy.
intros;
exact I.
intros (
nm3, [|
cells]).
intros;
exact I.
unfold lift,
fmap.
apply am_bind_case.
intros x y l l'
H ? ?;
eq_some_inv;
subs;
specialize (
H _ eq_refl);
auto.
intros;
eq_some_inv.
intros x log Hcells log'
Q.
simpl in Q.
eq_some_inv;
subs.
generalize (
deref_pexpr_inv (
Some a) (
tp1,
nm1) (
exist _ κ
Hκ)
lp).
rewrite Hcells.
clear Hcells.
intros Q.
assert (ρ ∈
tnum_gamma ((
tmp,
e) ::
stk) (
tp1,
nm1))
as Hρ1.
apply (
tnum_m_stronger MONO1);
auto.
unfold realize.
generalize (@
optimistic_realization_sound ((
tmp,
e) ::
stk)
cells (
tp1,
nm1)).
destruct (
optimistic_realization _ _)
as [ | (
tp',
nm') ];
simpl;
intros Hreal;
elim (
Hreal ρ
Hpun Hρ1).
intros TP'
NM'.
with_am_map'.
intros (
X &
Y).
intros v H.
eval_expr_inv.
destruct v1;
try discriminate.
specialize (
IHq _ H0).
destruct IHq as (
a' &
A &
B).
specialize (
Q _ eq_refl _ A).
destruct Q as (
Hty &
lme &
Hlme &
Q).
destruct (
proj2 (
tnum_m_stronger MONO1 (
conj Hpun TN)))
as (ρ
n &
Nc &
NM).
generalize (
me_of_pe_correct _ _ ρ
n NM _ Hlme).
intros (
NC &
NB).
destruct (λ
K,
N.nconvert_correct _ ge m _ _ _ _ Hstk _ _ (λ
x,
x)
_ _ NumDom sz nm1 ρ ρ
n Nc (@
invariant_block_of_ablock_inj _ _ INV)
_ _ B _ K _ NC)
as (
me &
Hme &
n &
Z &
EV & ?).
apply Hρ1.
discriminate.
simpl in Z.
subst n.
specialize (
Q me Hme).
destruct Q as (
CA &
CI &
CS).
destruct CS as (
ptr &
Hptr &
CS).
assert (∃
ab,
BlockSet.mem ab ptr ∧
block_of_ablock ge ((
tmp,
e) ::
stk)
ab =
Some b)
as K.
generalize (
pt_eval_pexpr_correct Hstk (
proj1 Hρ1)
B I).
simpl in Hptr.
destruct Hptr as [
Hptr |
Hptr ];
rewrite Hptr;
exact id.
clear Hptr.
destruct K as (
ab &
IN &
BA).
set (
c :=
cell_from ab (
Int.unsigned i,
exist _ κ
Hκ)).
edestruct (
Y c)
as (
pe &
PE).
apply CellSet.elements_spec.
subst c.
apply CS.
apply IN.
eapply concretize_int_correct.
eauto.
assumption.
destruct PE as [
PE PE'].
specialize (
TP'
c).
destruct (
ACTreeDom.get c _);
inversion PE;
clear PE.
subst pe.
exists (
PEvar c (
typ_of_type t)).
split.
exact PE'.
assert (ρ
c =
v).
{
subst c.
simpl in H.
destruct ab as [
f loc|
b'].
-
simpl in BA.
unfold ρ.
simpl.
destruct (
get_stk _ _)
as [ (? &
e') | ];
eq_some_inv.
simpl.
destruct (
e' !
loc)
as [(
b' & ?)|];
eq_some_inv.
simpl.
subs.
rewrite H.
reflexivity.
-
unfold ρ.
simpl in *.
destruct (
Genv.invert_symbol);
eq_some_inv.
subs.
rewrite H.
reflexivity. }
constructor.
auto.
right.
subs.
revert TP'.
apply typ_of_type_gamma.
Qed.
Lemma SZ' :
∀ (
b :
ABTree.elt) (
hi :
Z) (
md :
permission *
bool)
(
b' :
block),
ABTreeDom.get b sz =
Just (
hi,
md)
→
block_of_ablock ge ((
tmp,
e) ::
stk)
b =
Some b'
→
Mem.range_perm m b' 0
hi Cur Nonempty.
Proof.
Lemma convert_noerror (
q:
expr) :
∀ (
tn:
tnum) (
TN: ρ ∈
tnum_gamma ((
tmp,
e) ::
stk)
tn),
match am_get (
convert q tn)
with
|
Some (
tn',
lp) => (∀
pe,
In pe lp → ¬
error_pexpr ge m ρ
e pe) → ¬
error_expr ge e tmp m (
expr_erase q)
|
None =>
True
end.
Proof.
unfold ρ.
induction q;
intros (
tp,
nm)
TN.
-
simpl.
set (
c :=
ACtemp μ
i).
destruct (
ACTreeDom.get c tp)
eqn:
TY.
exact I.
intros NB.
specialize (
NB _ (
or_introl eq_refl)).
intros B.
subst c.
inv B;
apply NB.
simpl.
rewrite get_stk_length.
simpl.
rewrite H0.
reflexivity.
simpl.
rewrite get_stk_length.
simpl.
rewrite H0.
reflexivity.
-
generalize (
E i).
simpl.
destruct is_local.
intros [
K _].
specialize (
K eq_refl).
intros _ B.
inversion B.
intuition.
intros [
_ K].
destruct (
Genv.find_symbol ge i)
eqn:
FS.
intros _ B;
inversion B.
congruence.
exact I.
-
intros _ B.
inversion B.
-
simpl.
unfold bind.
simpl.
apply am_bind_case.
easy.
intros;
exact I.
intros ((
tp',
nm'),
lp)
log LP.
specialize (
IHq _ TN).
rewrite LP in IHq.
simpl in IHq.
simpl.
intros NB.
assert ( ∀
pe,
In pe lp → ¬
error_pexpr ge m ρ
e pe)
as NB'.
{
intros pe PE B.
eapply NB.
rewrite rev_map_correct, <-
in_rev,
in_map_iff.
eexists.
split.
reflexivity.
exact PE.
vauto.
}
specialize (
IHq NB').
intros B.
apply error_expr_Unop_inv in B.
destruct B as [(
v &
V &
B) |
B]. 2:
auto.
generalize (
convert_correct q _ TN).
rewrite LP.
simpl.
intros X.
specialize (
X _ V).
destruct X as (
pe &
PE &
EV).
eapply NB.
rewrite rev_map_correct, <-
in_rev,
in_map_iff.
eexists.
split.
reflexivity.
exact PE.
vauto.
-
simpl.
unfold bind.
simpl.
apply am_bind_case.
easy.
intros;
exact I.
intros ((
tp1,
nm1),
lp1)
log1 LP1.
specialize (
IHq1 _ TN).
rewrite LP1 in IHq1.
simpl in IHq1.
generalize (
convert_wf q1 (
tp,
nm)
TN).
rewrite LP1.
intros [
MONO1 _].
generalize (
convert_correct q1 _ TN).
rewrite LP1.
intros H1.
apply am_bind_case.
easy.
intros;
exact I.
intros ((
tp2,
nm2),
lp2)
log2 LP2.
generalize (
convert_correct q2 _ (
tnum_m_stronger MONO1 (
conj Hpun TN))).
rewrite LP2.
intros H2.
specialize (
IHq2 _ (
tnum_m_stronger MONO1 (
conj Hpun TN))).
rewrite LP2 in IHq2.
simpl in IHq2.
destruct lp2 as [|
pe2 lp2].
destruct (
noerror_eval_expr (
IHq2 (λ
_ K,
False_ind _ K)))
as (
v2 &
Hv2).
destruct (
H2 v2 Hv2)
as (? & () &
_).
destruct lp1 as [|
pe1 lp1].
destruct (
noerror_eval_expr (
IHq1 (λ
_ K,
False_ind _ K)))
as (
v1 &
Hv1).
destruct (
H1 v1 Hv1)
as (? & () &
_).
unfold am_get in H1,
H2.
destruct b;
try (
with_am_map';
intros [
_ Y]);
intros NB;
try (
assert ( ∀
pe,
In pe (
pe1::
lp1) → ¬
error_pexpr ge m ρ
e pe)
as NB1
by (
intros pe PE B;
eapply NB; [
apply in_map2;
first [
eassumption |
left;
reflexivity] |
vauto]);
specialize (
IHq1 NB1));
intros B;
apply error_expr_Binop_inv in B;
destruct B as [(
v &
w &
V &
W &
B) | [
B | (
v &
V &
B)] ];
auto;
try (
specialize (
H1 _ V);
destruct H1 as (
pe1' &
PE1 &
EV1));
try (
specialize (
H2 _ W);
destruct H2 as (
pe2' &
PE2 &
EV2));
try (
assert ( ∀
pe,
In pe (
pe2::
lp2) → ¬
error_pexpr ge m ρ
e pe)
as NB2
by (
intros pe PE B';
eapply NB; [
apply in_map2;
first [
eassumption |
left;
reflexivity] |
vauto]);
specialize (
IHq2 NB2)
);
auto;
try (
(
eapply NB; [
apply in_map2;
eauto |
vauto])
).
-
rename m0 into κ.
simpl.
unfold bind.
simpl.
apply am_bind_case.
easy.
intros;
exact I.
intros ((
tp1,
nm1),
lp)
log1 LP.
specialize (
IHq _ TN).
generalize (
convert_correct q _ TN).
rewrite LP.
intros H1.
rewrite LP in IHq.
simpl in IHq.
generalize (
convert_wf q (
tp,
nm)
TN);
rewrite LP.
intros (
MONO1 &
WF).
apply am_bind_case.
easy.
intros;
exact I.
intros ((
tp2,
nm2), κ')
log2 K.
assert (
Hκ:
log2 =
nil /\
tp2 =
tp1 /\
nm2 =
nm1 /\ ∃
Hκ, κ' =
Some (
exist _ κ
Hκ))
by (
destruct κ;
eq_some_inv;
eauto).
destruct Hκ
as (-> & -> & -> & [
Hκ ->]).
clear K.
apply am_bind_case.
easy.
intros;
exact I.
intros (
nm3, [|
cells]).
intros;
exact I.
unfold lift,
fmap.
apply am_bind_case.
intros x y l l'
H ? ?;
eq_some_inv;
subs;
specialize (
H _ eq_refl);
auto.
intros;
eq_some_inv.
intros x log Hcells log'
Q.
simpl in Q.
eq_some_inv;
subs.
generalize (
deref_pexpr_inv (
Some a) (
tp1,
nm1) (
exist _ κ
Hκ)
lp).
rewrite Hcells.
clear Hcells.
intros Q.
simpl.
assert (ρ ∈
tnum_gamma ((
tmp,
e) ::
stk) (
tp1,
nm1))
as Hρ1.
apply (
tnum_m_stronger MONO1);
auto.
unfold realize.
generalize (@
optimistic_realization_sound ((
tmp,
e) ::
stk)
cells (
tp1,
nm1)).
destruct (
optimistic_realization _ _)
as [ | (
tp',
nm') ];
simpl;
intros Hreal;
elim (
Hreal ρ
Hpun Hρ1).
intros TP'
NM'.
destruct (
proj2 (
tnum_m_stronger MONO1 (
conj Hpun TN)))
as (ρ
n &
Nc &
NM).
with_am_map'.
simpl.
intros (
X &
Y)
NB.
assert ( ∀
pe,
In pe lp → ¬
error_pexpr ge m ρ
e pe)
as NB'.
{
intros pe PE B.
specialize (
Q _ eq_refl _ PE).
destruct Q as (
Q &
lme &
Hlme &
LME).
generalize (
me_of_pe_correct tp1 nm1 ρ
n NM pe Hlme).
intros (
NC &
MEB).
apply (λ
P,
N.nconvert_def _ ge m _ _ _ _ Hstk _ _ (λ
x,
x)
_ _ NumDom sz SZ'
_ ρ ρ
n Nc (@
invariant_block_of_ablock_inj _ _ INV)
NM _ (
proj1 Hρ1)
_ P _ NC MEB B).
intuition.
}
specialize (
IHq NB').
intros B.
apply error_expr_Load_inv in B.
destruct B as [(
v' &
V' &
B) |
B]. 2:
easy.
specialize (
H1 _ V').
destruct H1 as (
pe &
PE &
EV).
specialize (
Q _ eq_refl pe PE).
destruct Q as (
TY &
lme &
Hlme &
Q).
generalize (
me_of_pe_correct _ _ _ NM pe Hlme).
intros (
ME &
MEB).
generalize (λ
P,
error_pexpr_def (
N.nconvert_def _ ge m _ _ _ _ Hstk _ _ (λ
x,
x)
_ _ NumDom sz SZ'
_ ρ ρ
n Nc (@
invariant_block_of_ablock_inj _ _ INV)
NM _ (
proj1 Hρ1)
_ P _ ME MEB)
EV).
intros Z.
specialize (
Z (
WF _ PE)).
generalize (
pexpr_get_ty_ok EV Z).
rewrite TY.
intros TY'.
apply gamma_typ_inv in TY'.
hsplit.
subst v'.
clear Z TY.
destruct (
N.nconvert_correct _ _ _ _ _ _ _ Hstk _ _ _ _ _ _ _ _ _ _ Nc (@
invariant_block_of_ablock_inj _ _ INV)
_ _ EV _ (
proj1 Hρ1)
_ ME)
as (
me &
Hme &
n &
Z &
EV' & ?).
discriminate.
simpl in Z.
subst n.
specialize (
Q _ Hme).
destruct Q as (
CA &
CI &
CS).
destruct CS as (
ptr &
Hptr &
OFS).
assert (∃
bs,
BlockSet.mem bs ptr ∧
block_of_ablock ge ((
tmp,
e) ::
stk)
bs =
Some b)
as K.
generalize (
pt_eval_pexpr_correct Hstk (
proj1 Hρ1)
EV I).
simpl in Hptr.
destruct Hptr as [
Hptr |
Hptr ];
rewrite Hptr;
exact id.
clear Hptr.
destruct K as (
bs &
BS &
Hb).
assert (∃
v,
Mem.load κ
m b (
Int.unsigned i) =
Some v ∧
v ≠
Vundef)
as (
v &
V &
DEF).
{
set (
c :=
cell_from bs (
Int.unsigned i,
exist _ κ
Hκ)).
destruct (
Y c)
as (
pe' &
PE' &
IN).
rewrite <-
CellSet.elements_spec.
subst c.
eapply OFS;
auto.
eapply concretize_int_correct;
eauto.
generalize (
TP'
c).
destruct (
ACTreeDom.get _ _)
as [|
ty].
discriminate.
inversion PE'.
subst pe'.
clear PE'.
unfold ρ.
simpl.
destruct bs as [
f r |
ab ];
simpl in *;
eq_some_inv.
*
destruct (
get_stk _ _)
as [ (? &
e') | ]. 2:
eq_some_inv.
simpl in *.
destruct (
e' !
r)
as [(?,?)|];
eq_some_inv.
simpl in *.
subst b.
destruct (
Mem.load)
as [
v|].
intros V.
exists v.
split.
reflexivity.
intros ->.
destruct ty;
destruct V.
destruct ty;
destruct 1.
*
destruct Genv.invert_symbol;
eq_some_inv.
subst c ab.
destruct (
Mem.load)
as [
v|].
intros V.
exists v.
split.
reflexivity.
intros ->.
destruct ty;
destruct V.
destruct ty;
destruct 1.
}
inversion B.
auto.
congruence.
congruence.
Qed.
Lemma deref_expr_correct α (
tn:
tnum) (
TN: ρ ∈
tnum_gamma ((
tmp,
e) ::
stk)
tn) κ
q :
match am_get (
deref_expr α κ
q tn)
with
|
Some (
tn',
cells) =>
tnum_mono ((
tmp,
e) ::
stk)
tn tn' ∧
¬
error_expr ge e tmp m (
expr_erase q) ∧
∀
v,
eval_expr ge e tmp m (
expr_erase q)
v →
∃
ab b i,
v =
Vptr b i ∧
In (
cell_from ab (
Int.unsigned i, κ))
cells ∧
block_of_ablock ge ((
tmp,
e) ::
stk)
ab =
Some b ∧
(
align_chunk (
proj1_sig κ) |
Int.unsigned i)
|
None =>
True
end.
Proof.
unfold deref_expr.
unfold bind at 1.
simpl.
apply am_bind_case.
easy.
intros;
exact I.
intros ((
tp1,
nm1),
lpe)
log1 LPE.
unfold lift,
fmap.
simpl.
apply am_bind_case.
easy.
intros;
exact I.
intros cells'.
simpl.
apply am_bind_case.
intros;
eq_some_inv;
subs;
eauto.
intros;
eq_some_inv.
intros [|
cells].
intros;
eq_some_inv.
intros log Hcells log'
X;
eq_some_inv;
subst cells'.
generalize (
deref_pexpr_inv α (
tp1,
nm1) κ
lpe).
rewrite Hcells.
intros Q.
generalize (
convert_correct q _ TN).
rewrite LPE.
simpl.
intros CC.
generalize (
convert_wf q _ TN);
rewrite LPE.
simpl.
intros [
MONO1 WF].
split.
easy.
destruct (
proj2 (
tnum_m_stronger MONO1 (
conj Hpun TN)))
as (ρ
n &
Nc &
NM).
split.
-
generalize (
convert_noerror q _ TN).
rewrite LPE.
simpl.
intros X.
apply X.
intros pe PE.
specialize (
Q _ eq_refl _ PE).
destruct Q as (
TY &
lme &
Hlme &
Q).
generalize (
me_of_pe_correct _ _ _ NM pe Hlme).
intros (
ME &
MEB).
generalize (λ
P,
N.nconvert_def _ ge m _ _ _ _ Hstk _ _ (λ
x,
x)
_ _ NumDom sz SZ'
_ ρ ρ
n Nc (@
invariant_block_of_ablock_inj _ _ INV)
NM _ (
proj1 (
tnum_m_stronger MONO1 (
conj Hpun TN)))
_ P _ ME MEB).
intros Y.
specialize (
Y (
WF _ PE)).
exact Y.
-
intros v EV.
specialize (
CC _ EV).
destruct CC as (
pe &
PE &
EV').
specialize (
Q _ eq_refl pe PE).
destruct Q as (
TY &
lme &
Hlme &
Q).
generalize (
me_of_pe_correct tp1 nm1 _ NM pe Hlme).
intros (
ME &
MEB).
set (
PT :=
proj1 (
tnum_m_stronger MONO1 (
conj Hpun TN))).
generalize (λ
P,
error_pexpr_def (
N.nconvert_def _ ge m _ _ _ _ Hstk _ _ (λ
x,
x)
_ _ NumDom sz SZ'
_ ρ ρ
n Nc (@
invariant_block_of_ablock_inj _ _ INV)
NM _ PT _ P _ ME MEB)
EV').
intros Y.
specialize (
Y (
WF _ PE)).
generalize (
pexpr_get_ty_ok EV'
Y).
rewrite TY.
clear Y TY.
intros H.
apply gamma_typ_inv in H.
hsplit.
subst v.
destruct (
N.nconvert_correct _ _ _ _ _ _ _ Hstk _ _ _ _ _ _ _ _ _ _ Nc (@
invariant_block_of_ablock_inj _ _ INV)
_ _ EV'
_ PT _ ME)
as (
me &
Hme &
n &
Z &
EVn & ?).
discriminate.
specialize (
Q _ Hme).
destruct Q as (
CA & ? &
ptr &
Hptr &
OFS).
simpl in Z.
subst n.
assert (∃
bs,
BlockSet.mem bs ptr ∧
block_of_ablock ge ((
tmp,
e) ::
stk)
bs =
Some b)
as K.
generalize (
pt_eval_pexpr_correct Hstk PT EV'
I).
simpl in Hptr.
destruct Hptr as [
Hptr |
Hptr ];
rewrite Hptr;
exact id.
clear Hptr.
destruct K as (
ab &
AB &
Hab).
eexists ab,
b,
i.
repeat (
refine (
conj _ _)).
reflexivity. 2:
assumption.
apply CellSet.elements_spec.
apply OFS.
apply AB.
eapply concretize_int_correct.
apply NM.
assumption.
rewrite (
check_align_correct _ NM (
align_chunk_4_cases _)
CA EVn).
rewrite Z.mul_comm.
eexists.
reflexivity.
Qed.
Lemma nconvert_sound (
tn:
tnum) (
TN: ρ ∈
tnum_gamma ((
tmp,
e) ::
stk)
tn) (
q:
expr) :
match am_get (
nconvert q tn)
with
|
Some (
tn',
_) =>
tnum_mono ((
tmp,
e) ::
stk)
tn tn' ∧
¬
error_expr ge e tmp m (
expr_erase q)
|
None =>
True
end.
Proof.
Lemma nconvert_ex (
tn:
tnum) (
TN: ρ ∈
tnum_gamma ((
tmp,
e) ::
stk)
tn) (
q:
expr) :
match am_get (
nconvert q tn)
with
|
Some ((
tp',
nm'),
lme) =>
tnum_mono ((
tmp,
e) ::
stk)
tn (
tp',
nm') ∧
∃
lpe,
am_get (
convert q tn) =
Some ((
tp',
nm'),
lpe) ∧
∀
v,
eval_expr ge e tmp m (
expr_erase q)
v →
v ≠
Vundef →
∀ (
TP: ρ ∈
points_to_gamma ge ((
tmp,
e) ::
stk)
tp') (ρ
n:
cell →
mach_num) (
Nc:
compat ρ ρ
n) (
NM: ρ
n ∈ γ
nm'),
∃
pe lme'
me n,
In pe lpe ∧
eval_pexpr ge m ρ
e pe v ∧
am_get (
N.nconvert annotation_log ge μ
_ _ (λ
x,
x)
_ _ NumDom sz nm'
tp'
pe) =
Some lme' ∧
(∀
me',
In me'
lme' →
In me'
lme) ∧
In me lme' ∧
N.ncompat v n ∧
N.wtype_num n (
pexpr_get_ty pe) ∧
eval_mexpr ρ
n me n
|
None =>
True
end.
Proof.
Lemma convert_to_me (
tn:
tnum) (
TN: ρ ∈
tnum_gamma ((
tmp,
e) ::
stk)
tn) (
q:
expr) :
match am_get (
convert q tn)
with
|
Some ((
tp',
nm'),
lpe) =>
match am_get (
me_of_pe_list (
tp',
nm')
lpe)
with
|
Some lme =>
tnum_mono ((
tmp,
e) ::
stk)
tn (
tp',
nm') ∧
∃
v,
eval_expr ge e tmp m (
expr_erase q)
v ∧
v ≠
Vundef
∧ ∀ (
TP: ρ ∈
points_to_gamma ge ((
tmp,
e) ::
stk)
tp') (ρ
n:
cell →
mach_num) (
Nc:
compat ρ ρ
n) (
NM: ρ
n ∈ γ
nm'),
∃
pe lme'
me n,
In pe lpe ∧
eval_pexpr ge m ρ
e pe v ∧
am_get (
N.nconvert annotation_log ge μ
_ _ (λ
x,
x)
_ _ NumDom sz nm'
tp'
pe) =
Some lme' ∧
(∀
me',
In me'
lme' →
In me'
lme) ∧
In me lme' ∧
N.ncompat v n ∧
N.wtype_num n (
pexpr_get_ty pe) ∧
eval_mexpr ρ
n me n
|
None =>
True
end
|
None =>
True
end.
Proof.
generalize (
nconvert_sound _ TN q).
generalize (
nconvert_ex _ TN q).
unfold nconvert,
bind.
simpl.
destruct (
convert q _)
as (((
tp',
nm'),
lpe) & ([|],?)). 2:
intros;
exact I.
simpl.
destruct (
me_of_pe_list _ lpe)
as (
lme & ([|],?)). 2:
intros;
exact I.
simpl.
intros (
MONO &
lpe' &
Hlpe' &
H) (
_ &
NB);
eq_some_inv;
subst.
destruct (
noerror_eval_expr_def NB)
as (
v &
Def &
V).
specialize (
H v V Def).
split.
exact MONO.
exists v.
split.
exact V.
split.
exact Def.
intros TP ρ
n Nc NM.
specialize (
H TP _ Nc NM).
destruct H as (
pe &
lme' &
me &
n &
Hn &
Hpn &
Hvn &
Htn &
Vn).
exists pe,
lme',
me,
n.
intuition.
Qed.
End CONVERT_CORRECT.
End CONVERT.
Definition t :
Type := (
stack+⊤ * (
sizes *
tnum))%
type.
Definition iter_t :
Type := (
stack+⊤ * (
sizes * (
points_to *
num_iter)))%
type.
Definition AbMem stk sz tp nm :
t := (
stk, (
sz, (
tp,
nm))).
Definition ab_stk (
ab:
t) :
stack+⊤ :=
fst ab.
Definition ab_sz (
ab:
t) :
sizes :=
fst (
snd ab).
Definition ab_nm (
ab:
t) :
tnum :=
snd (
snd ab).
Definition ab_tp (
ab:
t) :
points_to :=
fst (
snd (
snd ab)).
Definition ab_num (
ab:
t) :
num :=
snd (
snd (
snd ab)).
Arguments ab_stk ab /.
Arguments ab_sz ab /.
Arguments ab_nm ab /.
Arguments ab_tp ab /.
Arguments ab_num ab /.
Definition ab_stk_iter (
ab:
iter_t) :
stack+⊤ :=
fst ab.
Definition ab_sz_iter (
ab:
iter_t) :
sizes :=
fst (
snd ab).
Definition ab_nm_iter (
ab:
iter_t) :
tnum_iter :=
snd (
snd ab).
Definition ab_tp_iter (
ab:
iter_t) :
points_to :=
fst (
snd (
snd ab)).
Definition ab_num_iter (
ab:
iter_t) :
num_iter :=
snd (
snd (
snd ab)).
Definition with_stk (
f:
stack+⊤ →
stack+⊤) (
ab:
t) :
t :=
AbMem (
f (
ab_stk ab)) (
ab_sz ab) (
ab_tp ab) (
ab_num ab).
Definition with_sz (
f:
sizes →
sizes) (
ab:
t) :
t :=
AbMem (
ab_stk ab) (
f (
ab_sz ab)) (
ab_tp ab) (
ab_num ab).
Definition with_tp (
f:
points_to →
points_to) (
ab:
t) :
t :=
AbMem (
ab_stk ab) (
ab_sz ab) (
f (
ab_tp ab)) (
ab_num ab).
Definition with_num (
f:
num →
num) (
ab:
t) :
t :=
AbMem (
ab_stk ab) (
ab_sz ab) (
ab_tp ab) (
f (
ab_num ab)).
Definition with_tnum (
f:
tnum →
tnum) (
ab:
t) :
t :=
(
ab_stk ab, (
ab_sz ab,
f (
ab_nm ab))).
Definition dom {
A} (
x:
positive) (
m:
PTree.t A) :
bool :=
match PTree.get x m with
|
Some _ =>
true
|
None =>
false
end.
Remark dom_set {
A}
x m y (
a:
A) :
dom x (
PTree.set y a m) =
peq x y ||
dom x m.
Proof.
Instance stack_elt_gamma :
gamma_op (
lvarset *
tvarset) (
temp_env *
env) :=
λ
ltv te_e,
∀
x,
PSet.mem x (
fst ltv) =
dom x (
snd te_e).
Instance join_stack_elt_correct :
join_op_correct (
lvarset*
tvarset) ((
lvarset *
tvarset)+⊤) (
temp_env *
env).
Proof.
Instance leb_stack_elt_correct :
leb_op_correct (
lvarset *
tvarset) (
temp_env *
env).
Proof.
Record gamma (
ab:
t) (
cs:
concrete_state) :
Prop :=
{
_ :
fst cs ∈ γ(
ab_stk ab)
;
_ :
ab_stk ab ≠
All →
invariant cs
;
_ :
snd cs ∈
sizes_gamma ge (
fst cs) (
ab_sz ab)
;
_ :
mem_as_fun ge cs ∈ (
tnum_gamma (
fst cs) (
ab_nm ab))
}.
Instance t_gamma :
gamma_op t concrete_state :=
gamma.
Record iter_gamma (
ab:
iter_t) (
cs:
concrete_state) :
Prop :=
{
_ :
fst cs ∈ γ(
ab_stk_iter ab)
;
_ :
ab_stk_iter ab ≠
All →
invariant cs
;
_ :
snd cs ∈
sizes_gamma ge (
fst cs) (
ab_sz_iter ab)
;
_ :
mem_as_fun ge cs ∈ (
tnum_iter_gamma (
fst cs) (
ab_nm_iter ab))
}.
Instance iter_t_gamma :
gamma_op iter_t concrete_state :=
iter_gamma.
Definition split_t (
ab:
t) :
option (
ident *
lvarset *
tvarset *
stack *
sizes *
tnum) :=
match ab_stk ab with
|
All |
Just nil =>
None
|
Just ((ε, τ) :: σ) =>
let '(
sz,
tn) := (
snd ab)
in
Some (
plength σ, ε, τ, σ,
sz,
tn)
end.
Definition noerror (
exp:
expr) (
ab:
t) :
alarm_mon _ unit :=
match split_t ab with
|
Some (μ, ε, τ, σ,
sz,
tn) =>
do _ <-
nconvert μ ε
sz exp tn;
ret tt
|
None =>
do _ <-
alarm_am "
anomaly (
noerror)";
ret tt
end.
Definition ab_eval_expr (
ab:
t) (
a:
expr)
:
alarm_mon _ ((
tnum *
type+⊤ *
list (
mexpr cell)) +⊥) :=
match split_t ab with
|
Some (μ, ε, τ, σ,
sz,
tn) =>
do (
tn',
lp) <-
convert μ ε
sz a tn;
let '(
tp',
nm') :=
tn'
in
do ln <-
me_of_pe_list μ
sz tn'
lp;
match lp with nil =>
ret Bot |
_ =>
let ty :=
union_list_map (
pt_eval_pexpr ge μ
tp')
All lp in
ret (
NotBot (
tn',
ty,
ln))
end
|
None =>
do _ <-
alarm_am "
ab_eval_expr failed";
ret Bot
end.
Fixpoint ab_eval_exprlist (
ab:
t) (
e:
list expr) :
alarm_mon _ ((
t *
list (
type+⊤ *
list (
mexpr cell)))+⊥) :=
match e with
|
nil =>
ret (
NotBot (
ab,
nil))
|
e ::
e' =>
do r <-
ab_eval_expr ab e;
match r with
|
Bot =>
ret Bot
|
NotBot (
tn,
ty,
me) =>
do m <-
ab_eval_exprlist (
with_tnum (λ
_,
tn)
ab)
e';
match m with
|
Bot =>
ret Bot
|
NotBot (
ab,
y) =>
ret (
NotBot (
ab, (
ty,
me) ::
y))
end
end
end.
Definition nm_forget_all :=
fold_left (λ
m c,
bind m (
AbMachineEnv.forget c)).
Definition nm_upd (
nm:
num) (
c:
cell) (
e:(
mexpr cell)) :
num+⊥ :=
let nm' :=
AbMachineEnv.assign c e nm in
nm_forget_all (
overlap c)
nm'.
Definition nm_upd_cells (
nm:
num) (
l:
list cell) (
e:(
mexpr cell)) :
num+⊥ :=
union_list_map (λ
c,
nm_upd nm c e) (
NotBot nm)
l.
Definition ct_forget_all {
A:
Type} :=
fold_left (λ (
m:
ACTreeDom.t A)
c,
ACTreeDom.set m c All).
Definition ct_upd {
A} (
m:
ACTreeDom.t A) (
c:
cell) (
a:
A+⊤) :
ACTreeDom.t A :=
ACTreeDom.set (
ct_forget_all (
overlap c)
m)
c a.
Definition tp_upd_cells (
tp:
points_to) (
l:
list cell) (
tt:
type+⊤) :
points_to :=
union_list_map (λ
c,
ct_upd tp c tt)
tp l.
Definition chunk_type (κ:
typed_memory_chunk) (
ty:
typ+⊤) :
bool :=
match ty with
|
All =>
false
|
Just ty' =>
match κ,
ty'
with
|
exist (
Mint8signed |
Mint8unsigned |
Mint16signed |
Mint16unsigned)
_,
VI
|
exist Mint32 _, (
VI |
VP |
VIP)
|
exist Mint64 _,
VL
|
exist Mfloat64 _,
VF
|
exist Mfloat32 _,
VS
=>
true
|
_,
_ =>
false
end
end.
Local Instance string_of_type :
ToString type :=
string_of_type ge.
Definition assign_cells (κ:
option typed_memory_chunk) (
c:
list cell) (
a:
expr) (
ab:
t) :
alarm_mon _ (
t+⊥) :=
do res <-
ab_eval_expr ab a;
match res with
|
NotBot ((
tp,
nm),
ty,
ln) =>
do _ <-
am_assert match κ
with Some κ =>
chunk_type κ (
fmap typ_of_type ty) |
None =>
true end
("
bad type: " ++
to_string ty);
ret (
do nm' <-
union_list_map (
nm_upd_cells nm c) (
NotBot nm)
ln;
let tp' :=
tp_upd_cells tp c ty in
ret (
AbMem (
ab_stk ab) (
ab_sz ab)
tp'
nm')
)
|
Bot =>
ret Bot
end.
Definition assign_in (μ:
fname) (
x:
ident) (
a:
expr) (
ab:
t) :
alarm_mon _ (
t+⊥) :=
(
assign_cells None (
ACtemp μ
x ::
nil)
a ab).
Definition assign (
x:
ident) (
a:
expr) (
ab:
t) :
alarm_mon _ (
t+⊥) :=
match ab_stk ab with
|
Just (
_::σ) =>
assign_in (
plength σ)
x a ab
|
_ =>
do _ <-
alarm_am "
assign failed";
ret Bot
end.
Let type_of_typ (
ty:
typ) :
type+⊤ :=
match ty with
|
VI =>
Just TyInt
|
VF =>
Just TyFloat
|
VS =>
Just TySingle
|
VL =>
Just TyLong
|
_ =>
All
end.
Definition assign_any (
x:
ident) (
ty:
typ) (
ab:
t) :
alarm_mon annotation_log (
t+⊥) :=
match split_t ab with
|
Some (μ, ε, τ, σ,
sz,
tn) =>
let '(
tp,
nm) :=
tn in
let c :=
ACtemp μ
x in
do nm' <-
match ty with
|
VI |
VL |
VF |
VS =>
ret (
AbMachineEnv.forget c nm)
|
_ =>
do _ <-
alarm_am ("
assign_any:
bad type " ++
to_string ty);
ret Bot
end;
ret (
do nm' <-
nm';
ret (
with_num (λ
_,
nm')
(
with_tp (λ
tp,
ACTreeDom.set tp c (
type_of_typ ty))
ab)))
|
None =>
do _ <-
alarm_am "
assign_any failed";
ret Bot
end.
Definition permission_can_write (
p:
permission) :
bool :=
match p with
| (
Freeable |
Writable) =>
true
| (
Readable |
Nonempty) =>
false
end.
Definition cell_in_bounds (κ:
typed_memory_chunk) (
ab:
t) (
c:
cell) :
alarm_mon annotation_log unit :=
let b :=
ablock_of_cell c in
let '(
ofs,
_) :=
range_of_cell c in
match ABTreeDom.get b (
ab_sz ab)
with
|
All =>
do _ <-
alarm_am ("
block of unknown size: " ++
to_string b);
ret tt
|
Just (
hi, (
perm,
vol)) =>
if permission_can_write perm then
if zle 0
ofs &&
zle (
ofs +
size_chunk (
proj1_sig κ))
hi
then ret tt
else do _ <-
alarm_am ("
cell out of range("++
to_string hi ++"): " ++
to_string c);
ret tt
else do _ <-
alarm_am ("
read-
only cell: " ++
to_string c);
ret tt
end.
Definition expr_has_cast_for_chunk (
e:
expr) (κ:
typed_memory_chunk) :
bool :=
match κ,
e with
|
exist Mint8signed _,
Eunop Ocast8signed _
|
exist Mint8unsigned _,
Eunop Ocast8unsigned _
|
exist Mint16signed _,
Eunop Ocast16signed _
|
exist Mint16unsigned _,
Eunop Ocast16unsigned _
|
exist Mint32 _,
_
|
exist Mint64 _,
_
|
exist Mfloat32 _,
_
|
exist Mfloat64 _,
_
=>
true
|
_,
_ =>
false
end.
Definition store (α:
Annotations.annotation) (κ:
memory_chunk) (
a e:
expr) (
ab:
t) :
alarm_mon _ (
t+⊥) :=
let κ :
option typed_memory_chunk :=
match κ
with
|
Many32 |
Many64 =>
None
| κ =>
Some (
exist _ κ
I)
end
in
match κ
with
|
None =>
do _ <-
alarm_am "
invalid store memory chunk";
ret Bot
|
Some κ =>
match split_t ab with
|
Some (μ, ε, τ, σ,
sz,
tn) =>
do _ <-
am_assert (
expr_has_cast_for_chunk e κ)
("
Uncasted expr for " ++
to_string (
proj1_sig κ) ++ ": " ++
to_string e);
do (
tn',
cells) <-
deref_expr μ ε
sz (
Some α) κ
a tn;
let ab :=
with_tnum (λ
_,
tn')
ab in
match cells with nil =>
ret Bot |
_ =>
do _ <-
am_rev_map (
cell_in_bounds κ
ab)
cells;
assign_cells (
Some κ)
cells e ab
end
|
None =>
do _ <-
alarm_am "
store failed";
ret Bot
end
end.
Definition nassume b nm (
F:
mexpr cell →
mexpr cell)
e :
num+⊥ :=
union_list_map (λ
me,
AbMachineEnv.assume (
F me)
b nm) (
NotBot nm)
e.
Definition bool_expr (
e:
expr) :
expr :=
match e with
|
Ebinop (
Ocmp _|
Ocmpu _|
Ocmpf _|
Ocmpfs _|
Ocmpl _|
Ocmplu _)
_ _ =>
e
|
_ =>
Ebinop (
Ocmp Cne)
e (
Econst (
Csharpminor.Ointconst Int.zero))
end.
Definition assume (
b:
expr) (
ab:
t) :
alarm_mon _ (
t+⊥ *
t+⊥) :=
match split_t ab with
|
Some (μ, ε, τ, σ,
sz,
tn) =>
let b :=
bool_expr b in
do (
tn',
b') <-
nconvert μ ε
sz b tn;
let '(
tp,
nm) :=
tn'
in
ret
(
do nz <-
nassume true nm id b';
ret (
AbMem (
Just ((ε,τ)::σ))
sz tp nz),
do z <-
nassume false nm id b';
ret (
AbMem (
Just ((ε,τ)::σ))
sz tp z))
|
None =>
do _ <-
alarm_am "
assume failed";
ret (
Bot,
Bot)
end.
Definition deref_fun (
e:
expr) (
ab:
t) :
alarm_mon annotation_log (
list (
ident *
fundef)) :=
match split_t ab with
|
Some (μ, ε, τ, σ,
sz,
tn) =>
do (
tn,
cells) <-
deref_expr μ ε
sz None (
exist _ Mint32 I)
e tn;
am_map'
_ (λ
c,
match c with
|
ACglobal b 0 (
exist Mint32 _) =>
match Genv.find_funct_ptr ge b with
|
Some f =>
match Genv.invert_symbol ge b with
|
Some i =>
Result (
i,
f)
|
None =>
Error None "
unknown function"
end
|
None =>
Error None ("
bad function pointer " ++
to_string b)
end
|
_ =>
Error None ("
bad function pointer (2)")
end)
cells
|
None =>
do _ <-
alarm_am "
anomaly:
deref_fun";
ret nil
end.
Definition ab_bind_parameters (μ:
ident)
(
formals:
list ident) (
args:
list (
type+⊤ *
list (
mexpr cell)))
:
alarm_mon annotation_log (
t+⊥) →
alarm_mon _ (
t+⊥) :=
fold_left2
(λ
acc id v,
do ab' <-
acc;
ret (
do ab' <-
ab';
let c :=
ACtemp μ
id in
let '(
ty,
ln) :=
v in
do nm' <-
union_list_map (λ
me,
AbMachineEnv.assign c me (
ab_num ab')) (
NotBot (
ab_num ab'))
ln;
ret (
AbMem (
ab_stk ab') (
ab_sz ab')
(
ct_upd (
ab_tp ab')
c ty)
nm'))
)
(λ
_ _,
do _ <-
alarm_am "
ab_bind_parameters:
too many formals";
ret Bot)
(λ
_ _,
do _ <-
alarm_am "
ab_bind_parameters:
too many arguments";
ret Bot)
formals args.
Definition set_local_sizes μ
vars :
sizes →
sizes :=
fold_left (λ
sz x_hi,
ABTreeDom.set sz (
ABlocal μ (
fst x_hi)) (
Just (
snd x_hi, (
Freeable,
false))))
vars.
Definition push_frame (μ
_def:
function) (
args:
list expr) (
ab:
t) :
alarm_mon _ (
t+⊥) :=
do σ' <-
match ab_stk ab with
|
All =>
do _ <-
alarm_am "
no stack";
ret nil
|
Just σ' =>
ret σ'
end;
let μ :=
plength σ'
in
do res <-
ab_eval_exprlist ab args;
match res with
|
Bot =>
ret Bot
|
NotBot (
ab,
eargs) =>
let ε :=
PSetOp.build (
rev_map fst μ
_def.(
fn_vars))
in
let τ :=
PSetOp.build (μ
_def.(
fn_temps) ++ μ
_def.(
fn_params))
in
let σ := (ε, τ) :: σ'
in
let ab' :=
with_stk (λ
_,
Just σ) (
with_sz (
set_local_sizes μ μ
_def.(
fn_vars))
ab)
in
ab_bind_parameters μ μ
_def.(
fn_params)
eargs (
ret (
NotBot ab'))
end.
Invalidate cells local to μ.
Definition is_local_cell (μ:
fname) (
c:
cell) :
bool :=
match c with
|
AClocal μ'
_ _ _
|
ACtemp μ'
_ =>
eq_dec μ μ'
|
ACglobal _ _ _ =>
false
end.
Definition is_local_block (μ:
fname) (
ab:
ablock) :
bool :=
match ab with
|
ABlocal μ'
_ =>
eq_dec μ μ'
|
ABglobal _ =>
false
end.
Invalidate pointers to cells local to μ.
Definition pop_local_pt (μ:
fname) :
points_to →
points_to :=
ACTreeDom.SP.filter
(λ
c ty,
if is_local_cell μ
c
then false
else match ty with
| (
TyPtr (
Just bs) |
TyZPtr (
Just bs)) =>
negb (
BSO.existsb (
is_local_block μ)
bs)
|
TyPtr All |
TyZPtr All
|
TyFloat |
TySingle |
TyLong |
TyInt |
TyZero |
TyIntPtr =>
true
end).
Definition clear_local_sizes μ ε :
sizes →
sizes :=
PSet.fold (λ
x,
ABTree.remove (
ABlocal μ
x)) ε.
Definition all_local_cells (μ:
ident) (ε:
lvarset) (
sz:
sizes) :
list cell :=
PSet.fold (λ
x,
let z :=
match ABTree.get (
ABlocal μ
x)
sz with Some (
z,
_) =>
z |
None =>
Z0 end in
memory_chunk_fold (λ
acc κ,
let k :=
align_chunk (
proj1_sig κ)
in
N.peano_rect _
acc
(λ
n,
cons (
AClocal μ
x (
Z.of_N n *
k) κ))
(
Z.to_N (
z /
k))
)
) ε
nil.
Definition pop_local_num (μ:
ident) (ε:
lvarset) (τ:
tvarset) (
sz:
sizes) :
num+⊥ →
num+⊥ :=
(
nm_forget_all (
all_local_cells μ ε
sz)) ∘ (
nm_forget_all (
List.map (
ACtemp μ) (
PSet.elements τ))).
Definition pop_frame (
res:
option (
expr)) (
temp :
option (
ident)) (
ab:
t) :
alarm_mon _ (
t+⊥) :=
match ab_stk ab,
res,
temp with
|
Just ((ε₀, τ₀)::(ε,τ)::σ),
Some r,
Some x =>
let μ :=
plength σ
in
let μ₀ :=
Pos.succ μ
in
(
do ab' <-
assign_in μ
x r ab;
match ab'
with
|
NotBot ab'' =>
ret (
do nm' <-
pop_local_num μ₀ ε₀ τ₀ (
ab_sz ab'') (
NotBot (
ab_num ab''));
ret (
with_sz (
clear_local_sizes μ₀ ε₀)
(
with_tp (
pop_local_pt μ₀)
(
with_stk (λ
_,
Just ((ε,τ)::σ))
(
with_num (λ
_,
nm')
ab'')))))
|
Bot =>
ret Bot
end
)
|
Just ((ε,τ)::
nil),
Some r,
_ =>
let μ :=
xH in
do ret' <-
ab_eval_expr ab r;
match ret'
with
|
Bot =>
ret Bot
|
NotBot (
_,
ty,
_) =>
do _ <-
am_assert match ty with Just (
TyInt |
TyZero) =>
true |
_ =>
false end "
main ret not an int";
ret (
NotBot (
with_sz (
clear_local_sizes μ ε)
(
with_tp (
pop_local_pt μ)
(
with_stk (λ
_,
Just nil)
ab))))
end
|
Just (
_::
nil),
_,
_ =>
do _ <-
alarm_am "
pop_frame failed at main";
ret Bot
|
Just ((ε,τ)::σ),
None,
None =>
let μ :=
plength σ
in
ret (
do nm' <-
pop_local_num μ ε τ (
ab_sz ab) (
NotBot (
ab_num ab));
ret (
with_sz (
clear_local_sizes μ ε)
(
with_tp (
pop_local_pt μ)
(
with_stk (λ
_,
Just σ)
(
with_num (λ
_,
nm')
ab)))))
|
Just ((ε,τ)::σ),
Some r,
None =>
let μ :=
plength σ
in
do _ <-
noerror r ab;
ret (
do nm' <-
pop_local_num μ ε τ (
ab_sz ab) (
NotBot (
ab_num ab));
ret (
with_sz (
clear_local_sizes μ ε)
(
with_tp (
pop_local_pt μ)
(
with_stk (λ
_,
Just σ)
(
with_num (λ
_,
nm')
ab)))))
|
_,
_,
_ =>
do _ <-
alarm_am ("
pop_frame failed: " ++
to_string temp ++ " := " ++
to_string res );
ret Bot
end.
Let bad_align {
T} (
r:
T) :
alarm_mon annotation_log _ :=
do _ <-
alarm_am "
misaligned init data";
ret r.
Instance InitDataToString :
ToString init_data :=
λ
id,
match id with
|
Init_int8 i => "
int8: " ++
to_string i
|
Init_int16 i => "
int16: " ++
to_string i
|
Init_int32 i => "
int32: " ++
to_string i
|
Init_int64 i => "
int64: " ++
to_string i
|
Init_float32 f => "
float32: " ++
to_string f
|
Init_float64 f => "
float64: " ++
to_string f
|
Init_space n => "
space: " ++
to_string n
|
Init_addrof i o => "&" ++
to_string i ++ " + " ++
to_string o
end.
Definition zero_type_of_chunk (κ:
typed_memory_chunk) :
type :=
match κ
with
|
exist (
Mint8signed |
Mint8unsigned |
Mint16signed |
Mint16unsigned |
Mint32)
_
=>
TyZero
|
exist Mint64 _ =>
TyLong
|
exist Mfloat64 _ =>
TyFloat
|
exist Mfloat32 _ =>
TySingle
|
exist _ H =>
match H with end
end.
Definition permission_can_read (
p:
permission) : {
perm_order p Readable } + {
p =
Nonempty } :=
match p with
|
Freeable =>
left (
perm_F_any Readable)
|
Writable =>
left perm_W_R
|
Readable =>
left (
perm_refl Readable)
|
Nonempty =>
right eq_refl
end.
Definition zero_all_cells (
b:
block) (
base:
Z) (
sz:
Z) (
ab:
t):
t+⊥ :=
N.peano_rect
(λ
_,
t+⊥)
(
NotBot ab)
(λ
ofs ab,
memory_chunk_fold
(λ
ab κ,
let ofs' :=
base +
Z.of_N ofs in
if Zdivide_dec (
align_chunk (
proj1_sig κ))
ofs' (
align_chunk_pos (
proj1_sig κ))
&&
zle (
Z.of_N ofs +
size_chunk (
proj1_sig κ))
sz then
do ab <-
ab;
let c :=
ACglobal b ofs' κ
in
do nm <-
AbMachineEnv.assign c
(
match κ
with
|
exist (
Mint8signed |
Mint8unsigned |
Mint16signed |
Mint16unsigned |
Mint32)
_
=>
me_const_i _ Int.zero
|
exist Mint64 _ =>
me_const_l _ Int64.zero
|
exist (
Mfloat32)
_ =>
me_const_s _ Float32.zero
|
exist (
Mfloat64)
_ =>
me_const_f _ Float.zero
|
exist _ H =>
match H with end
end)
(
ab_num ab);
ret
(
with_tp (
ACTree.set c (
zero_type_of_chunk κ))
(
with_num (λ
_,
nm)
ab))
else ab
)
ab)
(
Z.to_N sz).
Definition ab_alloc_global perm vol b (
gv:
list init_data)
ab :
alarm_mon _ (
t+⊥) :=
do sz_ab' <-
am_fold
(λ (
acc:
_*(
_+⊥))
id,
let '(
ofs,
ab) :=
acc in
let ofs' :=
ofs +
Genv.init_data_size id in
let c κ
H :=
ACglobal b ofs (
exist _ κ
H)
in
if match id with
|
Init_space _
|
Init_int8 _ =>
true
|
Init_int16 _ =>
Zdivide_dec (
align_chunk Mint16signed)
ofs eq_refl
|
Init_int32 _
|
Init_addrof _ _ =>
Zdivide_dec (
align_chunk Mint32)
ofs eq_refl
|
Init_int64 _ =>
Zdivide_dec (
align_chunk Mint64)
ofs eq_refl
|
Init_float32 _ =>
Zdivide_dec (
align_chunk Mfloat32)
ofs eq_refl
|
Init_float64 _ =>
Zdivide_dec (
align_chunk Mfloat64)
ofs eq_refl
end then
match id return alarm_mon _ (
Z*
t+⊥)
with
|
Init_int32 n =>
ret (
ofs',
if permission_can_read perm
then
do ab' <-
ab;
do nm <-
AbMachineEnv.assign (
c Mint32 I) (
me_const_i _ n) (
ab_num ab');
ret (
with_tp (
ACTree.set (
c Mint32 I) (
type_of_int n))
(
with_num (λ
_,
nm)
ab'))
else ab)
|
Init_int64 n =>
ret (
ofs',
if permission_can_read perm
then
do ab' <-
ab;
do nm <-
AbMachineEnv.assign (
c Mint64 I) (
me_const_l _ n) (
ab_num ab');
ret (
with_tp (
ACTree.set (
c Mint64 I)
TyLong)
(
with_num (λ
_,
nm)
ab'))
else ab)
|
Init_addrof s o =>
match Genv.find_symbol ge s with
|
Some b' =>
ret (
ofs',
if permission_can_read perm
then
do ab' <-
ab;
do nm <-
AbMachineEnv.assign (
c Mint32 I) (
me_const_i _ o) (
ab_num ab');
ret (
with_tp (
ACTree.set (
c Mint32 I) (
TyPtr (
Just (
BSO.singleton (
ABglobal b')))))
(
with_num (λ
_,
nm)
ab'))
else ab)
|
None =>
do _ <-
alarm_am ("
ab_alloc_globals:
not a symbol ("
++
to_string s ++ ")");
ret (
ofs',
ab)
end
|
Init_space s =>
ret (
ofs',
if negb (
permission_can_read perm)
then ab else do ab' <-
ab;
zero_all_cells b ofs s ab')
|
Init_float64 f =>
ret (
ofs',
if negb (
permission_can_read perm)
then ab
else
do ab' <-
ab;
do nm <-
AbMachineEnv.assign (
c Mfloat64 I) (
MEconst _ (
MNfloat f)) (
ab_num ab');
ret (
with_tp (
ACTree.set (
c Mfloat64 I)
TyFloat)
(
with_num (λ
_,
nm)
ab')))
|
Init_float32 f =>
ret (
ofs',
if negb (
permission_can_read perm)
then ab
else
do ab' <-
ab;
do nm <-
AbMachineEnv.assign (
c Mfloat32 I) (
MEconst _ (
MNsingle f)) (
ab_num ab');
ret (
with_tp (
ACTree.set (
c Mfloat32 I)
TySingle)
(
with_num (λ
_,
nm)
ab')))
|
Init_int8 i =>
ret (
ofs',
if permission_can_read perm
then
do ab' <-
ab;
do nm <-
AbMachineEnv.assign (
c Mint8unsigned I) (
MEunop Ocast8unsigned (
me_const_i _ i)) (
ab_num ab');
ret (
with_tp (
ACTree.set (
c Mint8unsigned I) (
type_of_int i))
(
with_num (λ
_,
nm)
ab'))
else ab)
|
Init_int16 i =>
ret (
ofs',
if permission_can_read perm
then
do ab' <-
ab;
do nm <-
AbMachineEnv.assign (
c Mint16unsigned I) (
MEunop Ocast16unsigned (
me_const_i _ i)) (
ab_num ab');
ret (
with_tp (
ACTree.set (
c Mint16unsigned I) (
type_of_int i))
(
with_num (λ
_,
nm)
ab'))
else ab)
end
else bad_align acc)
gv
(0,
ab);
let '(
sz,
ab') :=
sz_ab'
in
ret (
do ab'' <-
ab';
ret (
with_sz (
ABTree.set (
ABglobal b) (
sz, (
perm,
vol)))
ab'')).
Definition ab_alloc_globals (
gl:
list (
ident *
globdef fundef unit)) :
alarm_mon _ (
block *
t+⊥) :=
(
am_fold
(λ
acc ig,
let '(
b,
ab) :=
acc in
let b' :=
Pos.succ b in
match ig with
| (
_,
Gfun _) =>
ret (
b',
fmap (
with_sz (
ABTree.set (
ABglobal b) (1, (
Nonempty,
false))))
ab)
| (
_,
Gvar gv) =>
do ab' <-
ab_alloc_global (
Genv.perm_globvar gv) (
gvar_volatile gv)
b gv.(
gvar_init)
ab;
ret (
b',
ab')
end)
gl
(
xH,
do t <- ⊤;
ret (
Just nil,
t))).
Definition init_mem (
defs:
list (
ident *
globdef fundef unit)) :
alarm_mon _ (
t+⊥) :=
do _ <-
am_assert (
norepet_map fst defs) ("
duplicate name in globals");
do ab <-
ab_alloc_globals defs;
ret (
snd ab).
Definition validate_volatile_ptr (
sz:
sizes) (
ptr:
BlockSet.t) (
lne:
list (
mexpr cell)) :
bool →
bool :=
BlockSet.fold
(λ
blk (
acc:
bool),
if acc
then
match blk with
|
ABlocal _ _ =>
false
|
ABglobal b =>
match Genv.invert_symbol ge b with
|
None =>
false
|
Some g =>
match ABTreeDom.get blk sz with
|
Just (
hi, (
perm,
vol)) =>
vol
|
All =>
false
end
end
end
else acc)
ptr.
Definition check_volatile (
tgt: (
ident *
int) +
expr) (κ:
memory_chunk) (
ab:
t) :
alarm_mon _ ident :=
do _ <-
match tgt with
|
inl (
g,
ofs) =>
match Genv.find_symbol ge g with
|
None =>
alarm_am "
check_volatile:
bad global"
|
Some b =>
let b :=
ABglobal b in
match ABTreeDom.get b (
ab_sz ab)
with
|
Just (
hi, (
perm,
vol)) =>
am_assert vol ("
check_volatile:
not volatile")
|
All =>
alarm_am "
check_volatile:
unknown size"
end
end
|
inr addr =>
do z <-
ab_eval_expr ab addr;
match z with
|
NotBot (
tn,
Just (
TyPtr (
Just ptr)),
ne) =>
am_assert (
validate_volatile_ptr (
ab_sz ab)
ptr ne true) ("
check_volatile:
bad pointer")
|
_ =>
alarm_am "
check_volatile:
unresolved expression"
end
end;
match ab_stk ab with
|
Just (
_ :: σ ) =>
ret (
plength σ)
|
_ =>
do _ <-
alarm_am "
check_volatile:
no stack";
ret xH
end.
Definition forget_cell (
ab:
t) (
c:
cell) :
t+⊥ :=
do nm' <-
AbMachineEnv.forget c (
ab_num ab);
NotBot (
(
with_tp (λ
tp,
ACTreeDom.set tp c (⊤))
(
with_num (λ
_,
nm')
ab))).
Definition vload (
rettemp:
option ident) (
g_ofs:
option (
ident *
int)) (κ:
memory_chunk) (
args:
list expr) (
ab:
t) :
alarm_mon _ (
t+⊥) :=
do _ <-
am_assert match κ
with Mint64 |
Mint32 |
Mfloat32 |
Mfloat64 =>
true |
_ =>
false end "
vload:
bad chunk";
match
match g_ofs,
args with
|
Some q,
nil =>
Some (
inl q)
|
None,
addr ::
nil =>
Some (
inr addr)
|
_,
_ =>
None
end
with
|
None =>
do _ <-
alarm_am "
vload:
bad arguments";
ret Bot
|
Some tgt =>
do μ <-
check_volatile tgt κ
ab;
match rettemp with
|
None =>
ret (
NotBot ab)
|
Some r =>
match κ
with
|
Mint64 =>
assign_any r VL ab
|
Mfloat64 =>
assign_any r VF ab
|
Mfloat32 =>
assign_any r VS ab
|
_ =>
ret (
forget_cell ab (
ACtemp μ
r))
end
end
end.
Definition only_global_pointer (
aptr:
BlockSet.t+⊤) :
bool :=
match aptr with
|
All =>
false
|
Just ptr =>
negb (
BSO.existsb (λ
p,
match p with
|
ABglobal b =>
match Genv.invert_symbol ge b with Some g =>
negb (
Senv.public_symbol ge g) |
None =>
true end
|
ABlocal _ _ =>
true
end)
ptr)
end.
Definition vstore (
rettemp:
option ident) (
g_ofs:
option (
ident *
int)) (κ:
memory_chunk) (
args:
list expr) (
ab:
t) :
alarm_mon _ (
t+⊥) :=
match
match g_ofs,
args with
|
Some q,
arg ::
nil =>
Some (
inl q,
arg)
|
None,
addr ::
arg ::
nil =>
Some (
inr addr,
arg)
|
_,
_ =>
None
end
with
|
None =>
do _ <-
alarm_am "
vstore:
bad arguments";
ret Bot
|
Some (
tgt,
arg) =>
do μ <-
check_volatile tgt κ
ab;
do v <-
ab_eval_expr ab arg;
match v with
|
Bot =>
ret Bot
|
NotBot (
tn,
ptr,
lne) =>
do _ <-
am_assert
match ptr with
|
Just ty =>
match ty, κ
with
|
TyLong,
Mint64
|
TySingle,
Mfloat32
|
TyFloat,
Mfloat64
| (
TyInt |
TyZero), (
Mint32 |
Mint8signed |
Mint8unsigned |
Mint16signed |
Mint16unsigned )
=>
true
| (
TyPtr bs |
TyZPtr bs),
Mint32 =>
only_global_pointer bs
|
_,
_ =>
false
end
|
All =>
false
end
("
vstore:
cannot prove that the argument " ++
to_string arg ++ "
is well-
typed " ++
to_string ptr);
let ab :=
with_tnum (λ
_,
tn)
ab in
match rettemp with
|
None =>
ret (
NotBot ab)
|
Some r =>
ret (
forget_cell ab (
ACtemp μ
r))
end
end
end.
Instance widen_mem :
widen_op (
iter_t+⊥) (
t+⊥) :=
{|
widen A B :=
let '(
NUM_it_ret,
NUM_ret) :=
match A with
|
Bot =>
init_iter Bot
|
NotBot (
_, (
_, (
_,
NUM))) =>
NUM
end ▽
match B with
|
Bot =>
Bot
|
NotBot (
_, (
_, (
_,
NUM))) =>
NotBot NUM
end
in
match B with
|
Bot =>
match A with
|
Bot => (
Bot,
Bot)
|
NotBot (
STK, (
SZ, (
PT,
_))) =>
(
NotBot (
STK, (
SZ, (
PT,
NUM_it_ret))),
do NUM_ret <-
NUM_ret;
ret (
STK, (
SZ, (
PT,
NUM_ret))))
end
|
NotBot (
STK', (
SZ', (
PT',
_))) =>
match A with
|
Bot =>
(
NotBot (
STK', (
SZ', (
PT',
NUM_it_ret))),
do NUM_ret <-
NUM_ret;
ret (
STK', (
SZ', (
PT',
NUM_ret))))
|
NotBot (
STK, (
SZ, (
PT,
NUM))) =>
let STK_ret :=
match STK,
STK'
with
|
Just STK,
Just STK' =>
list_widen join STK STK'
|
_,
_ =>
All
end
in
let SZ_ret :=
sizes_widen SZ SZ'
in
let PT_ret :=
points_to_widen PT PT'
in
(
NotBot (
STK_ret, (
SZ_ret, (
PT_ret,
NUM_it_ret))),
do NUM_ret <-
NUM_ret;
ret (
STK_ret, (
SZ_ret, (
PT_ret,
NUM_ret))))
end
end;
init_iter x :=
do x <-
x;
ret (
ab_stk x, (
ab_sz x, (
ab_tp x,
init_iter (
NotBot (
ab_num x)))))
|}.
Instance mem_cshm_dom :
mem_dom annotation_log t (
iter_t+⊥) :=
{|
assign :=
assign
;
assign_any :=
assign_any
;
store :=
store
;
assume :=
assume
;
noerror :=
noerror
;
deref_fun :=
deref_fun
;
ab_vload :=
vload
;
ab_vstore :=
vstore
;
push_frame :=
push_frame
;
pop_frame :=
pop_frame
;
ab_malloc sz dst ab :=
do _ <-
alarm_am "
malloc";
ret (⊤)
;
ab_free e ab :=
do _ <-
alarm_am "
free";
ret (⊤)
;
ab_memcpy sz al dst src ab :=
do _ <-
alarm_am ("
memcpy(" ++
to_string sz ++ ", " ++
to_string al ++ ", " ++
to_string dst ++ ", " ++
to_string src ++ ")");
ret (⊤)
;
init_mem :=
init_mem
|}.
Instance t_join_correct :
join_op_correct t (
t+⊥)
concrete_state.
Proof.
Instance t_leb_correct :
leb_op_correct t concrete_state.
Proof.
intros (
stk &
sz &
tpnm) (
stk' &
sz' &
tpnm')
LE (σ &
m) [
STK INV SZ NUM ].
unfold WProd.leb_prod,
leb in LE.
simpl in *.
unfold leb in LE.
simpl in *.
repeat rewrite andb_true_iff in LE.
destruct LE as (
LEstk &
LEsz &
LEnm).
constructor.
simpl.
eapply leb_correct;
eauto.
simpl.
destruct stk'
as [|
stk'].
intuition.
intros _.
apply INV.
destruct stk.
simpl in LEstk.
eq_some_inv.
discriminate.
simpl.
eapply leb_correct;
eauto.
eapply (
leb_correct (
leb_op_correct :=
tnum_leb_correct σ));
eauto.
Qed.
Instance TToString :
ToString t :=
(λ
x,
"
Mem { " ++ "
stack : " ++
to_string (
ab_stk x) ++
new_line
++ "
blocks: " ++
to_string (
ab_sz x) ++
new_line
++ "
types : " ++
to_string (
ab_tp x) ++
new_line
++ "
num : " ++
to_string (
ab_num x) ++
new_line
++ "}" ++
new_line ).
Instance IterTToString :
ToString iter_t :=
(λ
x,
"
Mem { " ++ "
stack : " ++
to_string (
ab_stk_iter x) ++
new_line
++ "
blocks: " ++
to_string (
ab_sz_iter x) ++
new_line
++ "
types : " ++
to_string (
ab_tp_iter x) ++
new_line
++ "
num : " ++
to_string (
ab_num_iter x) ++
new_line
++ "}" ++
new_line ).
End num.