Require Import Coqlib.
Require Import ZArith.
Require Import Values.
Require Import AST.
Require Import Integers.
Require Import Floats.
This module defines the type of symbolic values, along with their
type-checking functions.
Inductive styp :=
Tint |
Tlong |
Tfloat |
Tsingle.
Definition styp_eq (
x y :
styp) : {
x =
y} + {
x <>
y}.
Proof.
decide equality.
Defined.
Lemma styp_eq_refl:
forall x,
styp_eq x x =
left eq_refl.
Proof.
destruct x; simpl; auto.
Qed.
The type lval defines low-level values, i.e. values without pointer or
undefined values
Definition of unary/binary operators
Inductive se_signedness :=
SESigned |
SEUnsigned.
Inductive unop_t :=
OpBoolval :
unop_t
|
OpNotbool :
unop_t
|
OpNeg :
unop_t
|
OpNot :
unop_t
|
OpZeroext :
Z ->
unop_t
|
OpSignext :
Z ->
unop_t
|
OpRolm :
int ->
int ->
unop_t
|
OpAbsf
|
OpConvert :
se_signedness -> (
styp*
se_signedness) ->
unop_t
|
OpLoword :
unop_t
|
OpHiword :
unop_t
|
OpSingleofbits :
unop_t
|
OpDoubleofbits :
unop_t
|
OpBitsofsingle :
unop_t
|
OpBitsofdouble :
unop_t.
Inductive binop_t :=
|
OpAnd :
binop_t
|
OpOr :
binop_t
|
OpXor :
binop_t
|
OpAdd :
binop_t
|
OpSub :
binop_t
|
OpMul :
binop_t
|
OpMulh :
se_signedness ->
binop_t
|
OpMull' :
binop_t
|
OpShrx :
binop_t
|
OpShr_carry :
binop_t
|
OpRor :
binop_t
|
OpFloatofwords :
binop_t
|
OpLongofwords :
binop_t
|
OpDiv :
se_signedness ->
binop_t
|
OpMod :
se_signedness ->
binop_t
|
OpCmp :
se_signedness ->
comparison ->
binop_t
|
OpShr :
se_signedness ->
binop_t
|
OpShl :
binop_t
|
OpSubOverflow :
binop_t.
The type sval is identical to CompCert's value with the exception that
undefined values are labelled by a location.
Inductive expr_sym :
Type :=
|
Eval :
val ->
expr_sym
|
Eundef :
block ->
int ->
expr_sym
|
Eunop :
unop_t ->
styp ->
expr_sym ->
expr_sym
|
Ebinop :
binop_t ->
styp ->
styp ->
expr_sym ->
expr_sym ->
expr_sym.
Definition comp_eq_dec (
c1 c2:
comparison) : {
c1=
c2} + {
c1 <>
c2}.
Proof.
decide equality.
Defined.
Definition se_signedness_eq_dec (
s1 s2:
se_signedness) : {
s1=
s2} + {
s1 <>
s2}.
Proof.
decide equality.
Defined.
Hint Resolve Val.eq_val_dec.
Hint Resolve eq_nat_dec.
Hint Resolve Z_eq_dec.
Hint Resolve Int.eq_dec.
Hint Resolve Int64.eq_dec.
Hint Resolve styp_eq.
Hint Resolve se_signedness_eq_dec.
Hint Resolve comp_eq_dec.
Hint Resolve Float.eq_dec.
Hint Resolve Float32.eq_dec.
Definition eq_expr_sym_dec (
e1 e2:
expr_sym) : {
e1=
e2} + {
e1 <>
e2}.
Proof.
repeat decide equality; auto.
Defined.
Definition wt_val (
v:
val) (
r:
styp) :
Prop :=
match v,
r with
Vundef,
_
|
Vint _,
Tint
|
Vlong _,
Tlong
|
Vptr _ _,
Tint
|
Vfloat _,
Tfloat
|
Vsingle _,
Tsingle =>
True
|
_,
_ =>
False
end.
Lemma wt_val_dec :
forall v r, {
wt_val v r} + {~
wt_val v r}.
Proof.
intros.
destruct v; destruct r; simpl; intuition.
Defined.
Inductive is_lval_typ :
styp ->
Prop :=
|
isTint :
is_lval_typ Tint
|
isTlong :
is_lval_typ Tlong.
Definition is_lval_typ_dec (
t :
styp) : {
is_lval_typ t} +{ ~
is_lval_typ t}.
Proof.
Inductive is_float_typ :
styp ->
Prop :=
|
isTfloat:
is_float_typ Tfloat
|
isTsingle:
is_float_typ Tsingle.
Definition is_float_typ_dec (
t :
styp) : {
is_float_typ t} +{ ~
is_float_typ t}.
Proof.
wt_unop o t r holds if the operator o can be used with an argument of type t and returns a result of type r
Definition styp_of_ast (
t :
typ) :
styp :=
match t with
Tany32 |
AST.Tint =>
Tint
|
Tany64 |
AST.Tlong =>
Tlong
|
AST.Tfloat =>
Tfloat
|
AST.Tsingle =>
Tsingle
end.
Definition wt_unop (
u :
unop_t) (
t :
styp) (
r :
styp) :
Prop :=
match u with
|
OpBoolval |
OpNotbool |
OpRolm _ _ =>
t =
Tint /\
r =
t
|
OpNeg =>
t =
r
|
OpNot =>
t =
r /\
is_lval_typ t
|
OpZeroext z =>
t =
r /\
is_lval_typ t
|
OpSignext z =>
t =
r /\
is_lval_typ t
|
OpAbsf =>
t =
r /\
is_float_typ t
|
OpConvert s' (
ti,
s) =>
ti =
r
|
OpLoword =>
t =
Tlong /\
r =
Tint
|
OpHiword =>
t =
Tlong /\
r =
Tint
|
OpSingleofbits =>
t =
Tint /\
r =
Tsingle
|
OpDoubleofbits =>
t =
Tlong /\
r =
Tfloat
|
OpBitsofsingle =>
t =
Tsingle /\
r =
Tint
|
OpBitsofdouble =>
t =
Tfloat /\
r =
Tlong
end.
Binary operators are parametrised by a single type.
This is sufficient to recover the type information for the arguments.
Definition wt_binop (
b :
binop_t) (
t1 :
styp) (
t2 :
styp) (
r :
styp) :
Prop :=
match b with
|
OpAnd |
OpOr |
OpXor =>
t1 =
t2 /\
t1 =
r /\
is_lval_typ t1
|
OpAdd |
OpSub
|
OpMul |
OpDiv _ =>
t1 =
t2 /\
t1 =
r
|
OpMod _ =>
t1 =
t2 /\
t1 =
r /\
is_lval_typ t1
|
OpCmp _ _ =>
t1 =
t2 /\
r =
Tint
|
OpShrx |
OpShr_carry
|
OpRor =>
t1 =
t2 /\
t1 =
Tint /\
r =
Tint
|
OpMull' =>
t1 =
t2 /\
t1 =
Tint /\
r =
Tlong
|
OpMulh _ =>
t1 =
t2 /\
t1 =
Tint /\
r =
Tint
|
OpFloatofwords =>
t1 =
t2 /\
t1 =
Tint /\
r =
Tfloat
|
OpLongofwords =>
t1 =
t2 /\
t1 =
Tint /\
r =
Tlong
|
OpShl |
OpShr _ =>
t1 =
r /\
t2 =
Tint /\
is_lval_typ t1
|
OpSubOverflow =>
t1 =
Tint /\
t2 =
Tint /\
r =
Tint
end.
Fixpoint wt_expr (
e:
expr_sym) (
r:
styp) {
struct e}:
Prop :=
match e with
|
Eval v =>
wt_val v r
|
Eundef b i =>
r =
Tint
|
Eunop u t e =>
wt_expr e t /\
wt_unop u t r
|
Ebinop b t1 t2 e1 e2 =>
wt_expr e1 t1 /\
wt_expr e2 t2 /\
wt_binop b t1 t2 r
end.
Definition weak_wt (
e:
expr_sym) (
t:
styp) :
Prop :=
wt_expr e t \/ ~
exists t,
wt_expr e t.
Lemma wt_unop_determ:
forall u t s s',
wt_unop u t s ->
wt_unop u t s' ->
s =
s'.
Proof.
des u; des t; des s; des s'.
Qed.
Lemma wt_binop_determ:
forall b t1 t2 s s',
wt_binop b t1 t2 s ->
wt_binop b t1 t2 s' ->
s =
s'.
Proof.
des b; des t1; des t2; des s; des s'.
Qed.
Lemma wt_expr_2_is_undef:
forall e t t',
wt_expr e t ->
wt_expr e t' ->
t <>
t' ->
e =
Eval Vundef.
Proof.
induction e;
simpl;
intros;
eauto.
-
des v;
des t;
des t'.
-
congruence.
-
exfalso;
apply H1.
eapply wt_unop_determ;
intuition eauto.
-
exfalso;
apply H1.
eapply wt_binop_determ;
intuition eauto.
Qed.
Lemma wt_unop_dec :
forall u s r, {
wt_unop u s r } + { ~
wt_unop u s r }.
Proof.
Lemma wt_binop_dec :
forall b t1 t2 r, {
wt_binop b t1 t2 r } + { ~
wt_binop b t1 t2 r }.
Proof.
des b;
des t1;
des t2;
des r;
match goal with
|- {?
a = ?
a /\ ?
b = ?
b /\
is_lval_typ Tint} + {
_} =>
left;
repeat split;
auto;
constructor
| |- {?
a = ?
a /\ ?
b = ?
b /\
is_lval_typ Tlong} + {
_} =>
left;
repeat split;
auto;
constructor
| |- {?
a = ?
a /\ ?
b = ?
b /\
is_lval_typ Tfloat} + {
_} =>
right;
intros [
A [
C B]];
inv B
| |- {?
a = ?
a /\ ?
b = ?
b /\
is_lval_typ Tsingle} + {
_} =>
right;
intros [
A [
C B]];
inv B
| |- {?
a = ?
a /\ ?
b = ?
b /\
is_float_typ Tint} + {
_} =>
right;
intros [
A [
C B]];
inv B
| |- {?
a = ?
a /\ ?
b = ?
b /\
is_float_typ Tlong} + {
_} =>
right;
intros [
A [
C B]];
inv B
| |- {?
a = ?
a /\ ?
b = ?
b /\
is_float_typ Tfloat} + {
_} =>
left;
repeat split;
auto;
constructor
| |- {?
a = ?
a /\ ?
b = ?
b /\
is_float_typ Tsingle} + {
_} =>
left;
repeat split;
auto;
constructor
| |- {?
a =
_} + {
_} =>
des a
end.
Qed.
Lemma wt_expr_dec :
forall e r, {
wt_expr e r } + { ~
wt_expr e r }.
Proof.
induction e;
simpl;
intros;
auto.
-
apply wt_val_dec.
-
destruct (
IHe s);
destruct (
wt_unop_dec u s r);
intuition.
-
destruct (
IHe1 s);
destruct (
IHe2 s0);
destruct (
wt_binop_dec b s s0 r);
intuition.
Defined.
When we normalise a symbolic expression, we must know into what kind of
value we want to normalise it. This is the purpose of the result type. In
particular, we would have no way of knowing whether an expression with type
Tint should be normalised into a pointer or an integer.
Inductive result :=
Int |
Long |
Float |
Single |
Ptr .
Definition result_eq_dec (
r1 r2:
result) : {
r1=
r2 } + {
r1 <>
r2 }.
Proof.
decide equality.
Defined.