Correctness of instruction selection for operators
Require Import Coqlib.
Require Import AST Integers Floats.
Require Import Values Memory Builtins Globalenvs.
Require Import Cminor Op CminorSel.
Require Import SelectOp.
Require Import OpHelpers OpHelpersproof.
Require ExtValues.
Local Open Scope cminorsel_scope.
Local Transparent Archi.ptr64.
Useful lemmas and tactics
The following are trivial lemmas and custom tactics that help
perform backward (inversion) and forward reasoning over the evaluation
of operator applications.
Ltac EvalOp :=
eapply eval_Eop;
eauto with evalexpr.
Ltac InvEval1 :=
match goal with
| [
H: (
eval_expr _ _ _ _ _ (
Eop _
Enil) _) |- _ ] =>
inv H;
InvEval1
| [
H: (
eval_expr _ _ _ _ _ (
Eop _ (_ :::
Enil)) _) |- _ ] =>
inv H;
InvEval1
| [
H: (
eval_expr _ _ _ _ _ (
Eop _ (_ ::: _ :::
Enil)) _) |- _ ] =>
inv H;
InvEval1
| [
H: (
eval_exprlist _ _ _ _ _
Enil _) |- _ ] =>
inv H;
InvEval1
| [
H: (
eval_exprlist _ _ _ _ _ (_ ::: _) _) |- _ ] =>
inv H;
InvEval1
| _ =>
idtac
end.
Ltac InvEval2 :=
match goal with
| [
H: (
eval_operation _ _ _
nil _ =
Some _) |- _ ] =>
simpl in H;
inv H
| [
H: (
eval_operation _ _ _ (_ ::
nil) _ =
Some _) |- _ ] =>
simpl in H;
FuncInv
| [
H: (
eval_operation _ _ _ (_ :: _ ::
nil) _ =
Some _) |- _ ] =>
simpl in H;
FuncInv
| [
H: (
eval_operation _ _ _ (_ :: _ :: _ ::
nil) _ =
Some _) |- _ ] =>
simpl in H;
FuncInv
| _ =>
idtac
end.
Ltac InvEval :=
InvEval1;
InvEval2;
InvEval2.
Ltac TrivialExists :=
match goal with
| [ |-
exists v, _ /\
Val.lessdef ?
a v ] =>
exists a;
split; [
EvalOp |
auto]
end.
Correctness of the smart constructors
Section CMCONSTR.
Variable prog:
program.
Variable hf:
helper_functions.
Hypothesis HELPERS:
helper_functions_declared prog hf.
Let ge :=
Genv.globalenv prog.
Variable sp:
val.
Variable e:
env.
Variable m:
mem.
We now show that the code generated by "smart constructor" functions
such as
Selection.notint behaves as expected. Continuing the
notint example, we show that if the expression
e
evaluates to some integer value
Vint n, then
Selection.notint e
evaluates to a value
Vint (Int.not n) which is indeed the integer
negation of the value of
e.
All proofs follow a common pattern:
-
Reasoning by case over the result of the classification functions
(such as add_match for integer addition), gathering additional
information on the shape of the argument expressions in the non-default
cases.
-
Inversion of the evaluations of the arguments, exploiting the additional
information thus gathered.
-
Equational reasoning over the arithmetic operations performed,
using the lemmas from the Int and Float modules.
-
Construction of an evaluation derivation for the expression returned
by the smart constructor.
Definition unary_constructor_sound (
cstr:
expr ->
expr) (
sem:
val ->
val) :
Prop :=
forall le a x,
eval_expr ge sp e m le a x ->
exists v,
eval_expr ge sp e m le (
cstr a)
v /\
Val.lessdef (
sem x)
v.
Definition binary_constructor_sound (
cstr:
expr ->
expr ->
expr) (
sem:
val ->
val ->
val) :
Prop :=
forall le a x b y,
eval_expr ge sp e m le a x ->
eval_expr ge sp e m le b y ->
exists v,
eval_expr ge sp e m le (
cstr a b)
v /\
Val.lessdef (
sem x y)
v.
Theorem eval_addrsymbol:
forall le id ofs,
exists v,
eval_expr ge sp e m le (
addrsymbol id ofs)
v /\
Val.lessdef (
Genv.symbol_address ge id ofs)
v.
Proof.
intros.
unfold addrsymbol.
econstructor;
split.
EvalOp.
simpl;
eauto.
auto.
Qed.
Theorem eval_addrstack:
forall le ofs,
exists v,
eval_expr ge sp e m le (
addrstack ofs)
v /\
Val.lessdef (
Val.offset_ptr sp ofs)
v.
Proof.
intros.
unfold addrstack.
econstructor;
split.
EvalOp.
simpl;
eauto.
auto.
Qed.
Theorem eval_notint:
unary_constructor_sound notint Val.notint.
Proof.
Theorem eval_addimm:
forall n,
unary_constructor_sound (
addimm n) (
fun x =>
Val.add x (
Vint n)).
Proof.
Lemma val_add_mul_neg_zero_eq:
forall a b c,
Val.add (
Val.mul (
Val.sub Vzero a)
b)
c =
Val.sub c (
Val.mul a b).
Proof.
Lemma eval_match_neg:
forall le ex t v,
match_neg ex =
Some t ->
eval_expr ge sp e m le ex v ->
exists v',
eval_expr ge sp e m le t v' /\
v =
Val.sub Vzero v'.
Proof.
intros le0 ex t v MN EV.
unfold match_neg in MN.
destruct ex as [|
op args| | | | | |];
try discriminate.
destruct op;
try discriminate.
destruct args as [|
arg1 args1tail];
try discriminate.
destruct args1tail;
try discriminate.
destruct (
Int.eq i Int.zero)
eqn:
Hi;
try discriminate.
inv MN.
apply Int.same_if_eq in Hi.
subst i.
inv EV.
inv H2.
inv H6.
simpl in H4.
inv H4.
exists v1;
split;
auto.
Qed.
Lemma eval_mls_or_mla:
forall le e1 e2 e3 v1 v2 v3,
eval_expr ge sp e m le e1 v1 ->
eval_expr ge sp e m le e2 v2 ->
eval_expr ge sp e m le e3 v3 ->
exists v,
eval_expr ge sp e m le (
mls_or_mla e1 e2 e3)
v
/\
Val.lessdef (
Val.add (
Val.mul v1 v2)
v3)
v.
Proof.
Theorem eval_add:
binary_constructor_sound add Val.add.
Proof.
Theorem eval_rsubimm:
forall n,
unary_constructor_sound (
rsubimm n) (
fun v =>
Val.sub (
Vint n)
v).
Proof.
Theorem eval_sub:
binary_constructor_sound sub Val.sub.
Proof.
Theorem eval_negint:
unary_constructor_sound negint (
fun v =>
Val.sub Vzero v).
Proof.
Theorem eval_shlimm:
forall n,
unary_constructor_sound (
fun a =>
shlimm a n)
(
fun x =>
Val.shl x (
Vint n)).
Proof.
Theorem eval_shrimm:
forall n,
unary_constructor_sound (
fun a =>
shrimm a n)
(
fun x =>
Val.shr x (
Vint n)).
Proof.
Theorem eval_shruimm:
forall n,
unary_constructor_sound (
fun a =>
shruimm a n)
(
fun x =>
Val.shru x (
Vint n)).
Proof.
Lemma eval_mulimm_base:
forall n,
unary_constructor_sound (
mulimm_base n) (
fun x =>
Val.mul x (
Vint n)).
Proof.
Theorem eval_mulimm:
forall n,
unary_constructor_sound (
mulimm n) (
fun x =>
Val.mul x (
Vint n)).
Proof.
Theorem eval_mul:
binary_constructor_sound mul Val.mul.
Proof.
Theorem eval_mulhs:
binary_constructor_sound mulhs Val.mulhs.
Proof.
unfold mulhs;
red;
intros;
TrivialExists.
Qed.
Theorem eval_mulhu:
binary_constructor_sound mulhu Val.mulhu.
Proof.
unfold mulhu;
red;
intros;
TrivialExists.
Qed.
Lemma ones_max_range:
forall h ma (
RANGE : 0 <=
h <=
ma),
0 <=
Z.ones h < 2^
ma.
Proof.
Lemma ones_max_range32:
forall h (
RANGE : 0 <=
h <= 32),
0 <=
Z.ones h <=
Int.max_unsigned.
Proof.
Lemma and_max_unsigned:
forall i, (
Int.and i (
Int.repr 4294967295)) =
i.
Proof.
Theorem eval_andimm:
forall n,
unary_constructor_sound (
andimm n) (
fun x =>
Val.and x (
Vint n)).
Proof.
Theorem eval_and:
binary_constructor_sound and Val.and.
Proof.
Theorem eval_orimm:
forall n,
unary_constructor_sound (
orimm n) (
fun x =>
Val.or x (
Vint n)).
Proof.
Scheme expr_ind2 :=
Induction for expr Sort Prop
with exprlist_ind2 :=
Induction for exprlist Sort Prop
with condexpr_ind2 :=
Induction for condexpr Sort Prop.
Remark eval_same_expr:
forall a1 a2 le v1 v2,
same_expr_pure a1 a2 =
true ->
eval_expr ge sp e m le a1 v1 ->
eval_expr ge sp e m le a2 v2 ->
a1 =
a2 /\
v1 =
v2.
Proof.
intros a1.
apply (
expr_ind2
(
fun a1 =>
forall a2 le v1 v2,
same_expr_pure a1 a2 =
true ->
eval_expr ge sp e m le a1 v1 ->
eval_expr ge sp e m le a2 v2 ->
a1 =
a2 /\
v1 =
v2)
(
fun es1 =>
forall es2 le vs1 vs2,
same_exprlist_pure es1 es2 =
true ->
eval_exprlist ge sp e m le es1 vs1 ->
eval_exprlist ge sp e m le es2 vs2 ->
es1 =
es2 /\
vs1 =
vs2)
(
fun _ =>
True));
intros;
auto.
-
destruct a2;
simpl in H;
try discriminate.
destruct (
ident_eq i i0);
try discriminate.
subst i0.
inv H0.
inv H1.
split;
congruence.
-
destruct a2;
simpl in H0;
try discriminate.
destruct (
eq_operation o o0);
try discriminate.
subst o0.
inv H1.
inv H2.
exploit H;
eauto.
intros [
Es Evs].
subst e0 vl0.
split; [
reflexivity |
congruence].
-
destruct a2;
simpl in H0;
try discriminate.
destruct (
chunk_eq m0 m1);
try discriminate.
destruct (
eq_addressing a a0);
try discriminate.
subst m1 a0.
inv H1.
inv H2.
exploit H;
eauto.
intros [
Es Evs].
subst e0 vl0.
split; [
reflexivity |
congruence].
-
destruct a2;
simpl in H1;
discriminate.
-
destruct a2;
simpl in H1;
discriminate.
-
destruct a2;
simpl in H;
discriminate.
-
destruct a2;
simpl in H0;
discriminate.
-
destruct a2;
simpl in H0;
discriminate.
-
destruct es2;
simpl in H;
try discriminate.
inv H0.
inv H1.
split;
reflexivity.
-
destruct es2 as [|
e2 es2'];
simpl in H1;
try discriminate.
destruct (
same_expr_pure e0 e2)
eqn:
Sa;
try discriminate.
inv H2.
inv H3.
exploit H;
eauto.
intros [
Ea Eva].
subst e2 v0.
exploit H0;
eauto.
intros [
Es Evs].
subst es2' vl0.
split;
reflexivity.
Qed.
Lemma shifted_masks:
forall sz, 0 <=
sz <= 32 ->
Int.shl (
Int.repr (
Z.ones sz))
Int.zero =
Int.not (
Int.shl (
Int.repr (
Z.ones (32 -
sz))) (
Int.repr sz)).
Proof.
Lemma val_or_shru_shl_ror_lessdef:
forall v vn,
Val.lessdef
(
Val.or (
Val.shru v vn)
(
Val.shl v (
Val.sub (
Vint Int.iwordsize)
vn)))
(
Val.ror v vn).
Proof.
Lemma val_or_shl_shru_ror_lessdef:
forall v vn,
Val.lessdef
(
Val.or (
Val.shl v (
Val.sub (
Vint Int.iwordsize)
vn))
(
Val.shru v vn))
(
Val.ror v vn).
Proof.
Lemma val_or_shl_shru_rolimm_lessdef:
forall v vn,
Val.lessdef
(
Val.or (
Val.shl v vn)
(
Val.shru v (
Val.sub (
Vint Int.iwordsize)
vn)))
(
Val.ror v (
Val.sub (
Vint Int.iwordsize)
vn)).
Proof.
Theorem eval_or:
binary_constructor_sound or Val.or.
Proof.
red;
intros until y;
unfold or;
case (
or_match a b);
intros;
InvEval.
-
TrivialExists.
-
rewrite Val.or_commut.
apply eval_orimm;
auto.
-
apply eval_orimm;
auto.
-
destruct (
Int.eq s8 (
Int.repr 8) &&
Int.eq s24a (
Int.repr 24) &&
Int.eq s8a (
Int.repr 8) &&
Int.eq s24b (
Int.repr 24) &&
Int.eq c1 (
Int.repr 65280) &&
Int.eq c2 (
Int.repr 16711680) &&
Int.eq cFF (
Int.repr 255) &&
Int.eq cFF000000 (
Int.repr 4278190080) &&
same_expr_pure x1 x2 &&
same_expr_pure x2 x3 &&
same_expr_pure x3 x4)
eqn:
GUARD;
cycle 1.
{
exists (
Val.or x y);
split; [|
apply Val.lessdef_refl].
repeat (
try eassumption;
econstructor);
cbn;
eauto.
cbn in H6,
H7.
inv H6.
inv H7.
reflexivity. }
InvBooleans.
exploit (
eval_same_expr x1 x2);
eauto.
intros [_
Eq12].
exploit (
eval_same_expr x2 x3);
eauto.
intros [_
Eq23].
exploit (
eval_same_expr x3 x4);
eauto.
intros [_
Eq34].
subst v5 v7 v9.
apply Int.same_if_eq in H10,
H22,
H21,
H20,
H19,
H18,
H17,
H16.
eexists;
split.
{
eapply eval_Eop;
[
eapply eval_Econs; [
eassumption |
apply eval_Enil] |
cbn;
reflexivity]. }
cbn in H6,
H7,
H9,
H11,
H13,
H14.
inv H6.
inv H7.
inv H9.
inv H11.
inv H13.
inv H14.
destruct s8 as [
s8 ?];
destruct s24a as [
s24a ?];
destruct s8a as [
s8a ?];
destruct s24b as [
s24b ?];
cbn in *.
subst s8 s24a s8a s24b.
destruct v3;
cbn;
auto.
-
destruct (
Int.eq (
Int.add n1 n2)
Int.iwordsize &&
same_expr_pure t1 t2)
eqn:?.
destruct (
andb_prop _ _
Heqb0).
generalize (
Int.eq_spec (
Int.add n1 n2)
Int.iwordsize);
rewrite H1;
intros.
exploit eval_same_expr;
eauto.
intros [
EQ1 EQ2].
subst.
exists (
Val.ror v0 (
Vint n2));
split.
EvalOp.
destruct v0;
simpl;
auto.
destruct (
Int.ltu n1 Int.iwordsize)
eqn:?;
auto.
destruct (
Int.ltu n2 Int.iwordsize)
eqn:?;
auto.
simpl.
rewrite <-
Int.or_ror;
auto.
subst.
TrivialExists.
econstructor.
EvalOp.
simpl;
eauto.
econstructor;
eauto.
constructor.
simpl.
auto.
-
destruct (
Int.eq (
Int.add n2 n1)
Int.iwordsize &&
same_expr_pure t1 t2)
eqn:?.
destruct (
andb_prop _ _
Heqb0).
generalize (
Int.eq_spec (
Int.add n2 n1)
Int.iwordsize);
rewrite H1;
intros.
exploit eval_same_expr;
eauto.
intros [
EQ1 EQ2].
subst.
exists (
Val.ror v0 (
Vint n1));
split.
EvalOp.
destruct v0;
simpl;
auto.
destruct (
Int.ltu n1 Int.iwordsize)
eqn:?;
auto.
destruct (
Int.ltu n2 Int.iwordsize)
eqn:?;
auto.
simpl.
rewrite Int.or_commut.
rewrite <-
Int.or_ror;
auto.
subst.
TrivialExists.
econstructor.
EvalOp.
simpl;
eauto.
econstructor;
eauto.
constructor.
simpl.
auto.
-
destruct (
Int.eq c32 Int.iwordsize &&
same_expr_pure t1 t2 &&
same_expr_pure n1 n2)
eqn:
GUARD.
+
destruct (
andb_prop _ _
GUARD)
as [
GUARD' SP_n].
destruct (
andb_prop _ _
GUARD')
as [
HEQ SP_t].
generalize (
Int.eq_spec c32 Int.iwordsize);
rewrite HEQ;
intros C32EQ.
subst c32.
exploit (
eval_same_expr t1 t2);
eauto.
intros [_
EQT].
exploit (
eval_same_expr n1 n2);
eauto.
intros [_
EQN].
subst v2;
subst v4.
eexists;
split.
{
eapply eval_Eop.
eapply eval_Econs.
exact H2.
eapply eval_Econs.
exact H3.
apply eval_Enil.
cbn.
reflexivity. }
subst x.
replace v3 with (
Val.sub (
Vint Int.iwordsize)
v0)
by (
destruct v0;
cbn in H |- *;
auto).
cbn in H6.
inv H6.
apply val_or_shru_shl_ror_lessdef.
+
subst x.
eexists;
split; [|
apply Val.lessdef_refl].
eapply eval_Eop.
eapply eval_Econs.
{
eapply eval_Eop.
eapply eval_Econs.
exact H2.
eapply eval_Econs.
exact H3.
apply eval_Enil.
cbn.
reflexivity. }
eapply eval_Econs.
{
eapply eval_Eop.
eapply eval_Econs.
exact H5.
eapply eval_Econs.
{
eapply eval_Eop.
eapply eval_Econs.
exact H4.
apply eval_Enil.
cbn.
f_equal. }
apply eval_Enil.
rewrite H.
exact H6. }
apply eval_Enil.
cbn.
reflexivity.
-
destruct (
Int.eq c32 Int.iwordsize &&
same_expr_pure t1 t2 &&
same_expr_pure n1 n2)
eqn:
GUARD.
+
destruct (
andb_prop _ _
GUARD)
as [
GUARD' SP_n].
destruct (
andb_prop _ _
GUARD')
as [
HEQ SP_t].
generalize (
Int.eq_spec c32 Int.iwordsize);
rewrite HEQ;
intros C32EQ.
subst c32.
exploit (
eval_same_expr t1 t2);
eauto.
intros [_
EQT].
exploit (
eval_same_expr n1 n2);
eauto.
intros [_
EQN].
subst v2;
subst v4.
eexists;
split.
{
eapply eval_Eop.
eapply eval_Econs.
exact H2.
eapply eval_Econs.
{
eapply eval_Eop.
eapply eval_Econs.
exact H3.
apply eval_Enil.
cbn.
reflexivity. }
apply eval_Enil.
cbn.
reflexivity. }
subst x.
replace v3 with (
Val.sub (
Vint Int.iwordsize)
v0)
by (
destruct v0;
cbn in H |- *;
auto).
cbn in H6.
inv H6.
apply val_or_shl_shru_rolimm_lessdef.
+
subst x.
eexists;
split; [|
apply Val.lessdef_refl].
eapply eval_Eop.
eapply eval_Econs.
{
eapply eval_Eop.
eapply eval_Econs.
exact H2.
eapply eval_Econs.
exact H3.
apply eval_Enil.
cbn.
reflexivity. }
eapply eval_Econs.
{
eapply eval_Eop.
eapply eval_Econs.
exact H5.
eapply eval_Econs.
{
eapply eval_Eop.
eapply eval_Econs.
exact H4.
apply eval_Enil.
cbn.
f_equal. }
apply eval_Enil.
rewrite H.
exact H6. }
apply eval_Enil.
cbn.
reflexivity.
-
destruct DecBoolOps.and_dec as [[[
ZERO LSB]
SZ] | ];
cycle 1.
{
TrivialExists.
repeat (
try eassumption;
econstructor).
cbn in *;
congruence. }
subst usz.
subst ulsb.
TrivialExists.
cbn.
rewrite Val.or_commut.
f_equal.
cbn in H6.
unfold ExtValues.insf,
ExtValues.clearf in H6 |- *.
destruct (
ExtValues.is_bitfield lsb sz)
eqn:
IBF;
cycle 1.
{
injection H6.
clear H6.
intros HY.
subst y.
rewrite <-
H0.
cbn.
reflexivity. }
injection H6.
clear H6.
intros HY.
subst y.
rewrite <-
H0.
rewrite <-
H.
pose proof (
Int.unsigned_range sz)
as Hsz.
pose proof (
Int.unsigned_range lsb)
as Hlsb.
unfold ExtValues.is_bitfield in IBF.
apply Z.leb_le in IBF.
assert (
Int.ltu lsb2 Int.iwordsize =
true)
as LTU2.
{
destruct lsb2 as [
a' Ha'].
cbn.
exact Ha'. }
assert (
Int.ltu lsb Int.iwordsize =
true)
as LTU.
{
rewrite LSB.
exact LTU2. }
f_equal.
destruct v0;
cbn;
try reflexivity.
change (
Int.ltu Int.zero Int.iwordsize)
with true.
cbn.
rewrite Int.shru_zero.
rewrite LTU2.
rewrite LTU.
cbn.
f_equal.
rewrite <-
LSB.
unfold ExtValues.bitfield_mask.
rewrite Int.and_shl.
rewrite (
Int.zero_ext_and (
Int.unsigned sz))
by lia.
do 3
f_equal.
rewrite Z.ones_equiv.
rewrite two_p_equiv.
lia.
-
destruct DecBoolOps.and_dec as [[[
ZERO LSB]
SZ] | ];
cycle 1.
{
TrivialExists.
repeat (
try eassumption;
econstructor).
cbn in *;
congruence. }
subst usz.
subst ulsb.
TrivialExists.
cbn.
f_equal.
cbn in H6.
unfold ExtValues.insf,
ExtValues.clearf in H0 |- *.
destruct (
ExtValues.is_bitfield lsb sz)
eqn:
IBF;
cycle 1.
{
subst x.
cbn.
reflexivity. }
subst x.
pose proof (
Int.unsigned_range sz)
as Hsz.
pose proof (
Int.unsigned_range lsb)
as Hlsb.
unfold ExtValues.is_bitfield in IBF.
apply Z.leb_le in IBF.
assert (
Int.ltu lsb2 Int.iwordsize =
true)
as LTU2.
{
destruct lsb2 as [
a' Ha'].
cbn.
exact Ha'. }
assert (
Int.ltu lsb Int.iwordsize =
true)
as LTU.
{
rewrite LSB.
exact LTU2. }
f_equal.
cbn in H6.
injection H6.
clear H6.
intros HY.
subst y.
rewrite <-
H.
destruct v2;
cbn;
try reflexivity.
change (
Int.ltu Int.zero Int.iwordsize)
with true.
cbn.
rewrite Int.shru_zero.
rewrite LTU2.
rewrite LTU.
cbn.
f_equal.
rewrite <-
LSB.
unfold ExtValues.bitfield_mask.
rewrite Int.and_shl.
rewrite (
Int.zero_ext_and (
Int.unsigned sz))
by lia.
do 3
f_equal.
rewrite Z.ones_equiv.
rewrite two_p_equiv.
lia.
-
destruct DecBoolOps.and_dec as [[[
LSB CLLSB] [
CLSUM CLBF1]] | ];
cycle 1.
{
TrivialExists.
repeat (
try eassumption;
econstructor).
cbn in *;
congruence. }
TrivialExists.
cbn.
rewrite Val.or_commut.
f_equal.
cbn in H6.
unfold ExtValues.insf,
ExtValues.clearf in H6 |- *.
destruct (
ExtValues.is_bitfield lsb sz)
eqn:
IBF;
cycle 1.
{
injection H6.
clear H6.
intros HY.
subst y.
rewrite <-
H0.
cbn.
reflexivity. }
injection H6.
clear H6.
intros HY.
subst y.
rewrite <-
H0.
rewrite <-
H.
pose proof (
Int.unsigned_range sz)
as Hsz.
pose proof (
Int.unsigned_range lsb)
as Hlsb.
unfold ExtValues.is_bitfield in IBF.
apply Z.leb_le in IBF.
assert (
Int.ltu lsb2 Int.iwordsize =
true)
as LTU2.
{
destruct lsb2 as [
a' Ha'].
cbn.
exact Ha'. }
assert (
Int.ltu lsb Int.iwordsize =
true)
as LTU.
{
rewrite LSB.
exact LTU2. }
f_equal.
unfold ExtValues.clearf,
ExtValues.is_bitfield,
ExtValues.bitfield_mask.
assert (
CLBF: (
Int.unsigned cl_lsb +
Int.unsigned cl_sz <=? 32) =
true)
by (
apply Z.leb_le;
exact CLBF1).
rewrite CLBF.
destruct v0;
cbn;
try reflexivity.
rewrite LTU2.
rewrite LTU.
cbn.
f_equal.
rewrite <-
LSB.
rewrite Int.and_shl.
rewrite CLLSB.
f_equal.
apply Int.same_bits_eq.
intros i_idx Hi.
rewrite !
Int.bits_and by lia.
rewrite Int.bits_not by lia.
rewrite Int.bits_shl by lia.
rewrite Int.testbit_repr by lia.
rewrite Z.testbit_ones_nonneg by (
pose proof (
Int.unsigned_range sz);
lia).
assert (
CLEQ:
Int.unsigned cl_sz = 32 -
Int.unsigned sz).
{
assert (
CLA:
Int.unsigned (
Int.add cl_lsb cl_sz) = 32)
by (
rewrite CLSUM;
reflexivity).
unfold Int.add in CLA.
pose proof (
Int.unsigned_range cl_lsb).
pose proof (
Int.unsigned_range cl_sz).
rewrite Int.unsigned_repr in CLA by (
change Int.max_unsigned with 4294967295;
lia).
rewrite CLLSB in CLA.
lia. }
destruct (
zlt i_idx (
Int.unsigned sz))
as [
Hi_lt |
Hi_ge].
+
assert ((
i_idx <?
Int.unsigned sz)%
Z =
true)
as ->
by (
apply Z.ltb_lt;
lia).
cbn.
reflexivity.
+
rewrite Int.testbit_repr by lia.
rewrite Z.testbit_ones_nonneg by (
pose proof (
Int.unsigned_range cl_sz);
lia).
assert ((
i_idx <?
Int.unsigned sz)%
Z =
false)
as ->
by (
apply Z.ltb_ge;
lia).
cbn.
assert ((
i_idx -
Int.unsigned sz <?
Int.unsigned cl_sz)%
Z =
true)
as ->.
{
apply Z.ltb_lt.
rewrite CLEQ.
change Int.zwordsize with 32
in Hi.
lia. }
rewrite !
andb_false_r.
reflexivity.
-
destruct DecBoolOps.and_dec as [[[
LSB CLLSB] [
CLSUM CLBF1]] | ];
cycle 1.
{
TrivialExists.
repeat (
try eassumption;
econstructor).
cbn in *;
congruence. }
TrivialExists.
cbn.
f_equal.
cbn in H6.
unfold ExtValues.insf,
ExtValues.clearf in H0 |- *.
destruct (
ExtValues.is_bitfield lsb sz)
eqn:
IBF;
cycle 1.
{
subst x.
cbn.
reflexivity. }
subst x.
pose proof (
Int.unsigned_range sz)
as Hsz.
pose proof (
Int.unsigned_range lsb)
as Hlsb.
unfold ExtValues.is_bitfield in IBF.
apply Z.leb_le in IBF.
assert (
Int.ltu lsb2 Int.iwordsize =
true)
as LTU2.
{
destruct lsb2 as [
a' Ha'].
cbn.
exact Ha'. }
assert (
Int.ltu lsb Int.iwordsize =
true)
as LTU.
{
rewrite LSB.
exact LTU2. }
f_equal.
cbn in H6.
injection H6.
clear H6.
intros HY.
subst y.
rewrite <-
H.
unfold ExtValues.clearf,
ExtValues.is_bitfield,
ExtValues.bitfield_mask.
assert (
CLBF: (
Int.unsigned cl_lsb +
Int.unsigned cl_sz <=? 32) =
true)
by (
apply Z.leb_le;
exact CLBF1).
rewrite CLBF.
destruct v2;
cbn;
try reflexivity.
rewrite LTU2.
rewrite LTU.
cbn.
f_equal.
rewrite <-
LSB.
rewrite Int.and_shl.
rewrite CLLSB.
f_equal.
apply Int.same_bits_eq.
intros i_idx Hi.
rewrite !
Int.bits_and by lia.
rewrite Int.bits_not by lia.
rewrite Int.bits_shl by lia.
rewrite Int.testbit_repr by lia.
rewrite Z.testbit_ones_nonneg by (
pose proof (
Int.unsigned_range sz);
lia).
assert (
CLEQ:
Int.unsigned cl_sz = 32 -
Int.unsigned sz).
{
assert (
CLA:
Int.unsigned (
Int.add cl_lsb cl_sz) = 32)
by (
rewrite CLSUM;
reflexivity).
unfold Int.add in CLA.
pose proof (
Int.unsigned_range cl_lsb).
pose proof (
Int.unsigned_range cl_sz).
rewrite Int.unsigned_repr in CLA by (
change Int.max_unsigned with 4294967295;
lia).
rewrite CLLSB in CLA.
lia. }
destruct (
zlt i_idx (
Int.unsigned sz))
as [
Hi_lt |
Hi_ge].
+
assert ((
i_idx <?
Int.unsigned sz)%
Z =
true)
as ->
by (
apply Z.ltb_lt;
lia).
cbn.
reflexivity.
+
rewrite Int.testbit_repr by lia.
rewrite Z.testbit_ones_nonneg by (
pose proof (
Int.unsigned_range cl_sz);
lia).
assert ((
i_idx <?
Int.unsigned sz)%
Z =
false)
as ->
by (
apply Z.ltb_ge;
lia).
cbn.
assert ((
i_idx -
Int.unsigned sz <?
Int.unsigned cl_sz)%
Z =
true)
as ->.
{
apply Z.ltb_lt.
rewrite CLEQ.
change Int.zwordsize with 32
in Hi.
lia. }
rewrite !
andb_false_r.
reflexivity.
-
destruct DecBoolOps.and_dec as [[
LSB VAL]| ];
cycle 1.
{
TrivialExists.
repeat (
try eassumption;
econstructor).
cbn.
congruence. }
TrivialExists.
cbn.
f_equal.
cbn in H6.
unfold ExtValues.insf,
ExtValues.clearf in *.
destruct (
ExtValues.is_bitfield lsb sz);
inv H6;
cycle 1.
{
rewrite Val.or_commut.
reflexivity. }
rewrite Val.or_commut.
f_equal.
unfold ExtValues.bitfield_mask.
destruct v0;
cbn;
auto.
pose proof (
s_range lsb2)
as Hsr.
rewrite Hsr.
cbn.
f_equal.
rewrite Int.and_shl.
reflexivity.
-
destruct DecBoolOps.and_dec as [[
LSB VAL]| ];
cycle 1.
{
TrivialExists.
repeat (
try eassumption;
econstructor).
cbn in *;
congruence. }
TrivialExists.
cbn.
f_equal.
cbn in H6.
unfold ExtValues.insf,
ExtValues.clearf in *.
destruct (
ExtValues.is_bitfield lsb sz);
inv H6;
cycle 1.
{
reflexivity. }
f_equal.
unfold ExtValues.bitfield_mask.
destruct v2;
cbn;
auto.
pose proof (
s_range lsb2)
as Hsr.
rewrite Hsr.
cbn.
f_equal.
rewrite Int.and_shl.
reflexivity.
-
subst.
rewrite Val.or_commut.
TrivialExists.
-
subst.
TrivialExists.
-
destruct DecBoolOps.and_dec as [[
LSB VAL]| ];
cycle 1.
{
TrivialExists.
repeat (
try eassumption;
econstructor).
cbn.
congruence. }
TrivialExists.
cbn.
f_equal.
cbn in H6.
unfold ExtValues.insf,
ExtValues.clearf in *.
destruct (
ExtValues.is_bitfield lsb sz);
inv H6;
cycle 1.
{
rewrite Val.or_commut.
reflexivity. }
rewrite Val.or_commut.
reflexivity.
-
destruct DecBoolOps.and_dec as [[
LSB VAL]| ];
cycle 1.
{
TrivialExists.
repeat (
try eassumption;
econstructor).
cbn in *;
congruence. }
TrivialExists.
cbn.
f_equal.
cbn in H6.
unfold ExtValues.insf,
ExtValues.clearf in *.
destruct (
ExtValues.is_bitfield lsb sz);
inv H6;
cycle 1.
{
reflexivity. }
reflexivity.
-
destruct DecBoolOps.and_dec as [[[
EQ1 EQ2]
EQ3]| ];
cycle 1.
{
TrivialExists.
repeat (
try eassumption;
econstructor).
cbn.
congruence. }
unfold ExtValues.insf,
ExtValues.clearf,
ExtValues.is_bitfield in *.
destruct (
Int.unsigned rest_lsb +
Int.unsigned rest_sz <=? 32)
eqn:
LEQ1;
cycle 1.
{
subst x.
cbn.
eexists.
split.
repeat (
try eassumption;
econstructor).
constructor. }
destruct (
Int.unsigned lsb +
Int.unsigned sz <=? 32)
eqn:
LEQ2;
cycle 1.
{
subst y.
rewrite Val.or_commut.
cbn.
eexists.
split.
repeat (
try eassumption;
econstructor).
constructor. }
TrivialExists.
cbn.
unfold ExtValues.insf,
ExtValues.is_bitfield.
unfold ExtValues.bitfield_mask in *.
subst lsb.
subst rest_lsb.
rewrite LEQ2.
rewrite Val.or_commut.
f_equal.
f_equal.
{
subst x.
destruct v1;
cbn;
try reflexivity.
unfold Int.ltu.
rewrite zlt_true;
cycle 1.
{
change (
Int.unsigned Int.zero)
with 0.
change (
Int.unsigned Int.iwordsize)
with 32.
lia.
}
change (
Int.unsigned Int.zero)
with 0
in LEQ2.
rewrite Z.add_0_l in LEQ2.
rewrite Int.shl_zero.
cbn.
f_equal.
f_equal.
rewrite shifted_masks;
cycle 1.
{
pose proof (
Int.unsigned_range sz).
lia. }
rewrite Int.repr_unsigned.
f_equal.
f_equal.
f_equal.
f_equal.
replace sz with (
Int.sub (
Int.add sz rest_sz)
rest_sz);
cycle 1.
{
rewrite Int.sub_add_opp.
rewrite Int.add_assoc.
rewrite <-
Int.sub_add_opp.
rewrite Int.sub_idem.
apply Int.add_zero.
}
rewrite EQ3.
unfold Int.sub.
change (
Int.unsigned (
Int.repr 32))
with 32.
rewrite Int.unsigned_repr.
ring.
replace rest_sz with (
Int.sub (
Int.add sz rest_sz)
sz);
cycle 1.
{
rewrite Int.sub_add_opp.
rewrite (
Int.add_commut sz rest_sz).
rewrite Int.add_assoc.
rewrite <-
Int.sub_add_opp.
rewrite Int.sub_idem.
apply Int.add_zero.
}
rewrite EQ3.
unfold Int.sub.
change (
Int.unsigned (
Int.repr 32))
with 32.
pose proof (
Int.unsigned_range sz).
rewrite Int.unsigned_repr;
cycle 1.
{
change Int.modulus with 4294967296
in *.
change Int.max_unsigned with 4294967295
in *.
lia.
}
change Int.modulus with 4294967296
in *.
change Int.max_unsigned with 4294967295
in *.
lia.
}
assumption.
-
TrivialExists.
Qed.
Theorem eval_xorimm:
forall n,
unary_constructor_sound (
xorimm n) (
fun x =>
Val.xor x (
Vint n)).
Proof.
Theorem eval_xor:
binary_constructor_sound xor Val.xor.
Proof.
Lemma eval_mod_aux:
forall divop semdivop,
(
forall sp x y m,
eval_operation ge sp divop (
x ::
y ::
nil)
m =
semdivop x y) ->
forall le a b x y z,
eval_expr ge sp e m le a x ->
eval_expr ge sp e m le b y ->
semdivop x y =
Some z ->
exists v,
eval_expr ge sp e m le (
mod_aux divop a b)
v /\
Val.lessdef (
Val.sub x (
Val.mul z y))
v.
Proof.
Theorem eval_divs_base:
forall le a b x y z,
eval_expr ge sp e m le a x ->
eval_expr ge sp e m le b y ->
Val.divs x y =
Some z ->
exists v,
eval_expr ge sp e m le (
divs_base a b)
v /\
Val.lessdef z v.
Proof.
intros.
unfold divs_base.
exists z;
split.
EvalOp.
auto.
Qed.
Theorem eval_mods_base:
forall le a b x y z,
eval_expr ge sp e m le a x ->
eval_expr ge sp e m le b y ->
Val.mods x y =
Some z ->
exists v,
eval_expr ge sp e m le (
mods_base a b)
v /\
Val.lessdef z v.
Proof.
Theorem eval_divu_base:
forall le a x b y z,
eval_expr ge sp e m le a x ->
eval_expr ge sp e m le b y ->
Val.divu x y =
Some z ->
exists v,
eval_expr ge sp e m le (
divu_base a b)
v /\
Val.lessdef z v.
Proof.
intros.
unfold divu_base.
exists z;
split.
EvalOp.
auto.
Qed.
Theorem eval_modu_base:
forall le a x b y z,
eval_expr ge sp e m le a x ->
eval_expr ge sp e m le b y ->
Val.modu x y =
Some z ->
exists v,
eval_expr ge sp e m le (
modu_base a b)
v /\
Val.lessdef z v.
Proof.
Theorem eval_shrximm:
forall le a n x z,
eval_expr ge sp e m le a x ->
Val.shrx x (
Vint n) =
Some z ->
exists v,
eval_expr ge sp e m le (
shrximm a n)
v /\
Val.lessdef z v.
Proof.
Theorem eval_shl:
binary_constructor_sound shl Val.shl.
Proof.
Theorem eval_shr:
binary_constructor_sound shr Val.shr.
Proof.
Theorem eval_shru:
binary_constructor_sound shru Val.shru.
Proof.
Theorem eval_negf:
unary_constructor_sound negf Val.negf.
Proof.
red; intros. TrivialExists.
Qed.
Theorem eval_absf:
unary_constructor_sound absf Val.absf.
Proof.
red; intros. TrivialExists.
Qed.
Theorem eval_addf:
binary_constructor_sound addf Val.addf.
Proof.
intro.
intros e1 v1 e2 v2 He1 He2.
unfold addf.
destruct (
addf_match e1 e2).
-
InvEval.
subst.
TrivialExists.
-
TrivialExists.
Qed.
Theorem eval_subf:
binary_constructor_sound subf Val.subf.
Proof.
intro.
intros e1 v1 e2 v2 He1 He2.
unfold subf.
destruct (
subf_match e1 e2).
-
InvEval.
subst.
TrivialExists.
-
TrivialExists.
Qed.
Theorem eval_mulf:
binary_constructor_sound mulf Val.mulf.
Proof.
red; intros; TrivialExists.
Qed.
Theorem eval_sqrtf:
forall expr expr' le x
(
EVAL :
sqrtf expr =
Some expr')
(
EXPR :
eval_expr ge sp e m le expr x),
exists v,
eval_expr ge sp e m le expr' v /\
Val.lessdef (
Val.sqrtf x)
v.
Proof.
unfold sqrtf in *.
intros.
inv EVAL.
eexists.
split.
repeat econstructor.
exact EXPR.
constructor.
Qed.
Theorem eval_bswap32:
forall expr expr' le x
(
EVAL :
bswap32 expr =
Some expr')
(
EXPR :
eval_expr ge sp e m le expr x),
exists v,
eval_expr ge sp e m le expr' v
/\
Val.lessdef (
ExtValues.val_bswap32 x)
v.
Proof.
unfold bswap32 in *.
intros.
inv EVAL.
eexists.
split.
repeat econstructor.
exact EXPR.
constructor.
Qed.
Theorem eval_negfs:
unary_constructor_sound negfs Val.negfs.
Proof.
red; intros. TrivialExists.
Qed.
Theorem eval_absfs:
unary_constructor_sound absfs Val.absfs.
Proof.
red; intros. TrivialExists.
Qed.
Theorem eval_addfs:
binary_constructor_sound addfs Val.addfs.
Proof.
intro.
intros e1 v1 e2 v2 He1 He2.
unfold addfs.
destruct (
addfs_match e1 e2).
-
InvEval.
subst.
TrivialExists.
-
TrivialExists.
Qed.
Theorem eval_subfs:
binary_constructor_sound subfs Val.subfs.
Proof.
intro.
intros e1 v1 e2 v2 He1 He2.
unfold subfs.
destruct (
subfs_match e1 e2).
-
InvEval.
subst.
TrivialExists.
-
TrivialExists.
Qed.
Theorem eval_mulfs:
binary_constructor_sound mulfs Val.mulfs.
Proof.
red; intros; TrivialExists.
Qed.
Theorem eval_sqrtfs:
forall expr expr' le x
(
EVAL :
sqrtfs expr =
Some expr')
(
EXPR :
eval_expr ge sp e m le expr x),
exists v,
eval_expr ge sp e m le expr' v /\
Val.lessdef (
Val.sqrtfs x)
v.
Proof.
unfold sqrtfs in *.
intros.
inv EVAL.
eexists.
split.
repeat econstructor.
exact EXPR.
constructor.
Qed.
Bit-test identity: if mask is the single-bit power-of-two 2^k,
then (i & mask) != 0 is exactly (i >> k) & 1.
Lemma is_power2_bit_test_int:
forall i mask k,
Int.is_power2 mask =
Some k ->
Int.zero_ext 1 (
Int.shru i k) =
(
if Int.eq (
Int.and i mask)
Int.zero then Int.zero else Int.one).
Proof.
Section COMP_IMM.
Variable default:
comparison ->
int ->
condition.
Variable intsem:
comparison ->
int ->
int ->
bool.
Variable sem:
comparison ->
val ->
val ->
val.
Hypothesis sem_int:
forall c x y,
sem c (
Vint x) (
Vint y) =
Val.of_bool (
intsem c x y).
Hypothesis sem_undef:
forall c v,
sem c Vundef v =
Vundef.
Hypothesis sem_eq:
forall x y,
sem Ceq (
Vint x) (
Vint y) =
Val.of_bool (
Int.eq x y).
Hypothesis sem_ne:
forall x y,
sem Cne (
Vint x) (
Vint y) =
Val.of_bool (
negb (
Int.eq x y)).
Hypothesis sem_default:
forall c v n,
sem c v (
Vint n) =
Val.of_optbool (
eval_condition (
default c n) (
v ::
nil)
m).
Lemma eval_compimm:
forall le c a n2 x,
eval_expr ge sp e m le a x ->
exists v,
eval_expr ge sp e m le (
compimm default intsem c a n2)
v
/\
Val.lessdef (
sem c x (
Vint n2))
v.
Proof.
Hypothesis sem_swap:
forall c x y,
sem (
swap_comparison c)
x y =
sem c y x.
Lemma eval_compimm_swap:
forall le c a n2 x,
eval_expr ge sp e m le a x ->
exists v,
eval_expr ge sp e m le (
compimm default intsem (
swap_comparison c)
a n2)
v
/\
Val.lessdef (
sem c (
Vint n2)
x)
v.
Proof.
End COMP_IMM.
Theorem eval_comp:
forall c,
binary_constructor_sound (
comp c) (
Val.cmp c).
Proof.
Theorem eval_compu:
forall c,
binary_constructor_sound (
compu c) (
Val.cmpu (
Mem.valid_pointer m)
c).
Proof.
Theorem eval_compf:
forall c,
binary_constructor_sound (
compf c) (
Val.cmpf c).
Proof.
intros;
red;
intros.
unfold compf.
TrivialExists.
Qed.
Theorem eval_compfs:
forall c,
binary_constructor_sound (
compfs c) (
Val.cmpfs c).
Proof.
intros;
red;
intros.
unfold compfs.
TrivialExists.
Qed.
Lemma select_swap:
forall ob v1 v2,
Val.select (
option_map negb ob)
v2 v1 =
Val.select ob v1 v2.
Proof.
intros. destruct ob as [[]|]; reflexivity.
Qed.
Lemma eval_Osel_default:
forall le cond al vl a1 v1 a2 v2 ty,
eval_exprlist ge sp e m le al vl ->
eval_expr ge sp e m le a1 v1 ->
eval_expr ge sp e m le a2 v2 ->
exists v,
eval_expr ge sp e m le (
Eop (
Osel cond) (
a1 :::
a2 :::
al))
v
/\
Val.lessdef (
Val.normalize (
Val.select (
eval_condition cond vl m)
v1 v2)
ty)
v.
Proof.
Lemma eval_selectimm:
forall le cond al vl e1 v1 imm v2,
eval_exprlist ge sp e m le al vl ->
eval_expr ge sp e m le e1 v1 ->
v2 =
Vint imm ->
exists v,
eval_expr ge sp e m le (
selectimm cond al e1 imm)
v
/\
Val.lessdef (
Val.normalize (
Val.select (
eval_condition cond vl m)
v1 v2)
Tint)
v.
Proof.
Lemma eval_selimmn:
forall le cond al vl imm v1 e2 v2,
eval_exprlist ge sp e m le al vl ->
v1 =
Vint imm ->
eval_expr ge sp e m le e2 v2 ->
exists v,
eval_expr ge sp e m le (
selimmn cond al imm e2)
v
/\
Val.lessdef (
Val.normalize (
Val.select (
eval_condition cond vl m)
v1 v2)
Tint)
v.
Proof.
Lemma eval_selectimm2:
forall le cond al vl imm1 imm2 v1 v2,
eval_exprlist ge sp e m le al vl ->
v1 =
Vint imm1 ->
v2 =
Vint imm2 ->
exists v,
eval_expr ge sp e m le (
selectimm2 cond al imm1 imm2)
v
/\
Val.lessdef (
Val.normalize (
Val.select (
eval_condition cond vl m)
v1 v2)
Tint)
v.
Proof.
Ltac select_default :=
solve [
eapply eval_Osel_default;
eauto].
Theorem eval_select:
forall le ty cond al vl a1 v1 a2 v2,
select_supported ty =
true ->
eval_exprlist ge sp e m le al vl ->
eval_expr ge sp e m le a1 v1 ->
eval_expr ge sp e m le a2 v2 ->
exists v,
eval_expr ge sp e m le (
select ty cond al a1 a2)
v
/\
Val.lessdef (
Val.normalize (
Val.select (
eval_condition cond vl m)
v1 v2)
ty)
v.
Proof.
unfold select;
intros.
destruct ty;
try select_default.
destruct a1 as [ |
o e0 | | | | | | ];
try (
destruct a2 as [ |
o' e0' | | | | | | ];
try select_default;
destruct o';
try select_default;
destruct e0';
try select_default;
InvEval;
subst;
eapply eval_selectimm;
eauto).
destruct o;
try (
destruct a2 as [ |
o' e0' | | | | | | ];
try select_default;
destruct o';
try select_default;
destruct e0';
try select_default;
InvEval;
subst;
eapply eval_selectimm;
eauto).
destruct e0;
try (
destruct a2 as [ |
o' e0' | | | | | | ];
try select_default;
destruct o';
try select_default;
destruct e0';
try select_default;
InvEval;
subst;
eapply eval_selectimm;
eauto).
destruct a2;
try (
InvEval;
subst;
eapply eval_selimmn;
eauto).
destruct o;
try (
InvEval;
subst;
eapply eval_selimmn;
eauto).
destruct e0;
try (
InvEval;
subst;
eapply eval_selimmn;
eauto).
InvEval.
subst.
eapply eval_selectimm2;
eauto.
Qed.
Theorem eval_cast8signed:
unary_constructor_sound cast8signed (
Val.sign_ext 8).
Proof.
Theorem eval_cast8unsigned:
unary_constructor_sound cast8unsigned (
Val.zero_ext 8).
Proof.
Theorem eval_cast16signed:
unary_constructor_sound cast16signed (
Val.sign_ext 16).
Proof.
Theorem eval_cast16unsigned:
unary_constructor_sound cast16unsigned (
Val.zero_ext 16).
Proof.
Theorem eval_singleoffloat:
unary_constructor_sound singleoffloat Val.singleoffloat.
Proof.
Theorem eval_floatofsingle:
unary_constructor_sound floatofsingle Val.floatofsingle.
Proof.
Theorem eval_intoffloat:
forall le a x y,
eval_expr ge sp e m le a x ->
Val.intoffloat x =
Some y ->
exists v,
eval_expr ge sp e m le (
intoffloat a)
v /\
Val.lessdef y v.
Proof.
Theorem eval_floatofint:
forall le a x y,
eval_expr ge sp e m le a x ->
Val.floatofint x =
Some y ->
exists v,
eval_expr ge sp e m le (
floatofint a)
v /\
Val.lessdef y v.
Proof.
Theorem eval_intuoffloat:
forall le a x y,
eval_expr ge sp e m le a x ->
Val.intuoffloat x =
Some y ->
exists v,
eval_expr ge sp e m le (
intuoffloat a)
v /\
Val.lessdef y v.
Proof.
Theorem eval_floatofintu:
forall le a x y,
eval_expr ge sp e m le a x ->
Val.floatofintu x =
Some y ->
exists v,
eval_expr ge sp e m le (
floatofintu a)
v /\
Val.lessdef y v.
Proof.
Theorem eval_intofsingle:
forall le a x y,
eval_expr ge sp e m le a x ->
Val.intofsingle x =
Some y ->
exists v,
eval_expr ge sp e m le (
intofsingle a)
v /\
Val.lessdef y v.
Proof.
Theorem eval_singleofint:
forall le a x y,
eval_expr ge sp e m le a x ->
Val.singleofint x =
Some y ->
exists v,
eval_expr ge sp e m le (
singleofint a)
v /\
Val.lessdef y v.
Proof.
Theorem eval_intuofsingle:
forall le a x y,
eval_expr ge sp e m le a x ->
Val.intuofsingle x =
Some y ->
exists v,
eval_expr ge sp e m le (
intuofsingle a)
v /\
Val.lessdef y v.
Proof.
Theorem eval_singleofintu:
forall le a x y,
eval_expr ge sp e m le a x ->
Val.singleofintu x =
Some y ->
exists v,
eval_expr ge sp e m le (
singleofintu a)
v /\
Val.lessdef y v.
Proof.
Theorem eval_addressing:
forall le chunk a v b ofs,
eval_expr ge sp e m le a v ->
v =
Vptr b ofs ->
match addressing chunk a with (
mode,
args) =>
exists vl,
eval_exprlist ge sp e m le args vl /\
eval_addressing ge sp mode vl =
Some v
end.
Proof.
intros until v.
unfold addressing;
case (
addressing_match a);
intros;
InvEval.
exists (@
nil val).
split.
eauto with evalexpr.
simpl.
auto.
exists (
v1 ::
nil);
split.
eauto with evalexpr.
simpl.
congruence.
destruct (
can_use_Aindexed2shift chunk);
simpl.
exists (
v1 ::
v0 ::
nil);
split.
eauto with evalexpr.
congruence.
exists (
Vptr b ofs ::
nil);
split.
constructor.
EvalOp.
simpl.
congruence.
constructor.
simpl.
rewrite Ptrofs.add_zero;
auto.
destruct (
can_use_Aindexed2 chunk);
simpl.
exists (
v1 ::
v0 ::
nil);
split.
eauto with evalexpr.
congruence.
exists (
Vptr b ofs ::
nil);
split.
constructor.
EvalOp.
simpl.
congruence.
constructor.
simpl.
rewrite Ptrofs.add_zero;
auto.
exists (
v ::
nil);
split.
eauto with evalexpr.
subst.
simpl.
rewrite Ptrofs.add_zero;
auto.
Qed.
Theorem eval_builtin_arg:
forall a v,
eval_expr ge sp e m nil a v ->
CminorSel.eval_builtin_arg ge sp e m (
builtin_arg a)
v.
Proof.
intros until v.
unfold builtin_arg;
case (
builtin_arg_match a);
intros;
InvEval.
-
constructor.
-
constructor.
-
constructor.
-
simpl in H5.
inv H5.
constructor.
-
subst v.
constructor;
auto.
-
inv H.
InvEval.
simpl in H6;
inv H6.
constructor;
auto.
-
inv H.
InvEval.
simpl in H6.
rewrite <-
Genv.shift_symbol_address_32 in H6 by auto.
inv H6.
constructor;
auto.
-
inv H.
repeat constructor;
auto.
-
constructor;
auto.
Qed.
Theorem eval_divf_base:
forall le a b x y,
eval_expr ge sp e m le a x ->
eval_expr ge sp e m le b y ->
exists v,
eval_expr ge sp e m le (
divf_base a b)
v /\
Val.lessdef (
Val.divf x y)
v.
Proof.
intros;
unfold divf_base.
TrivialExists.
Qed.
Theorem eval_divfs_base:
forall le a b x y,
eval_expr ge sp e m le a x ->
eval_expr ge sp e m le b y ->
exists v,
eval_expr ge sp e m le (
divfs_base a b)
v /\
Val.lessdef (
Val.divfs x y)
v.
Proof.
Platform-specific known builtins
Theorem eval_platform_builtin:
forall bf al a vl v le,
platform_builtin bf al =
Some a ->
eval_exprlist ge sp e m le al vl ->
platform_builtin_sem bf vl =
Some v ->
exists v',
eval_expr ge sp e m le a v' /\
Val.lessdef v v'.
Proof.
destruct bf;
intros until le;
intro Heval.
1-3:
inversion Heval;
subst a;
clear Heval;
exists v;
split;
trivial;
repeat (
try econstructor;
try eassumption).
-
inv Heval.
intros Hexl Hsem.
destruct vl as [|
v1 [|? ?]];
try discriminate.
destruct v1;
simpl in Hsem;
try discriminate;
inv Hsem;
(
eexists;
split;
[
eapply eval_Eop;
[
econstructor;
[
eapply eval_Eop; [
eassumption |
reflexivity]
|
econstructor]
|
reflexivity]
|
auto]).
-
inversion Heval;
subst a;
clear Heval;
exists v;
split;
trivial;
repeat (
try econstructor;
try eassumption).
Qed.
Lemma eval_fast_isfinitef:
forall le a a' m
(
GEN :
fast_isfinitef a =
Some a')
v
(
EVAL :
eval_expr ge sp e m le a v),
exists v' :
val,
eval_expr ge sp e m le a' v' /\
Val.lessdef (
Val.of_optbool (
Val.isfinitef v))
v'.
Proof.
Lemma eval_fast_isfinite:
forall le a a' m
(
GEN :
fast_isfinite a =
Some a')
v
(
EVAL :
eval_expr ge sp e m le a v),
exists v' :
val,
eval_expr ge sp e m le a' v' /\
Val.lessdef (
Val.of_optbool (
Val.isfinite v))
v'.
Proof.
End CMCONSTR.