(** * Properties of compile-time approximations of values *)
Definition val_match_approx (a: approx) (v: val) : Prop :=
match a with
| Int1 => v = Val.zero_ext 1 v
| Int7 => v = Val.zero_ext 8 v /\ v = Val.sign_ext 8 v
| Int8u => v = Val.zero_ext 8 v
| Int8s => v = Val.sign_ext 8 v
| Int15 => v = Val.zero_ext 16 v /\ v = Val.sign_ext 16 v
| Int16u => v = Val.zero_ext 16 v
| Int16s => v = Val.sign_ext 16 v
| Float32 => v = Val.singleoffloat v
| Any => True
end.
Remark undef_match_approx: forall a, val_match_approx a Vundef.

(* Specifications: *)
Lemma val_match_approx_increasing:
forall a1 a2 v,
Approx.bge a1 a2 = true -> val_match_approx a2 v -> val_match_approx a1 v.
Lemma approx_of_int_sound:
forall n, val_match_approx (Approx.of_int n) (Vint n).
Lemma approx_of_float_sound:
forall f, val_match_approx (Approx.of_float f) (Vfloat f).
Lemma approx_of_chunk_sound:
forall chunk m b ofs v,
Mem.load chunk m b ofs = Some v ->
val_match_approx (Approx.of_chunk chunk) v.
Lemma approx_of_unop_sound:
forall op v1 v a1,
eval_unop op v1 = Some v ->
val_match_approx a1 v1 ->
val_match_approx (Approx.unop op a1) v.
Lemma approx_bitwise_and_sound:
forall a1 v1 a2 v2,
val_match_approx a1 v1 -> val_match_approx a2 v2 ->
val_match_approx (Approx.bitwise_and a1 a2) (Val.and v1 v2).
Lemma approx_bitwise_or_sound:
forall (sem_op: val -> val -> val) a1 v1 a2 v2,
(forall a b c, sem_op (Val.and a (Vint c)) (Val.and b (Vint c)) =
Val.and (sem_op a b) (Vint c)) ->
val_match_approx a1 v1 -> val_match_approx a2 v2 ->
val_match_approx (Approx.bitwise_or a1 a2) (sem_op v1 v2).
Lemma approx_of_binop_sound:
forall op v1 a1 v2 a2 m v,
eval_binop op v1 v2 m = Some v ->
val_match_approx a1 v1 -> val_match_approx a2 v2 ->
val_match_approx (Approx.binop op a1 a2) v.
Lemma approx_unop_is_redundant_sound:
forall op a v,
Approx.unop_is_redundant op a = true ->
val_match_approx a v ->
eval_unop op v = Some v.
Lemma val_match_approx_increasing:
forall a1 a2 v,
Approx.bge a1 a2 = true -> val_match_approx a2 v -> val_match_approx a1 v.
Lemma approx_of_int_sound:
forall n, val_match_approx (Approx.of_int n) (Vint n).
Lemma approx_of_float_sound:
forall f, val_match_approx (Approx.of_float f) (Vfloat f).
Lemma approx_of_chunk_sound:
forall chunk m b ofs v,
Mem.load chunk m b ofs = Some v ->
val_match_approx (Approx.of_chunk chunk) v.
Lemma approx_of_unop_sound:
forall op v1 v a1,
eval_unop op v1 = Some v ->
val_match_approx a1 v1 ->
val_match_approx (Approx.unop op a1) v.
Lemma approx_bitwise_and_sound:
forall a1 v1 a2 v2,
val_match_approx a1 v1 -> val_match_approx a2 v2 ->
val_match_approx (Approx.bitwise_and a1 a2) (Val.and v1 v2).
Lemma approx_bitwise_or_sound:
forall (sem_op: val -> val -> val) a1 v1 a2 v2,
(forall a b c, sem_op (Val.and a (Vint c)) (Val.and b (Vint c)) =
Val.and (sem_op a b) (Vint c)) ->
val_match_approx a1 v1 -> val_match_approx a2 v2 ->
val_match_approx (Approx.bitwise_or a1 a2) (sem_op v1 v2).
Lemma approx_of_binop_sound:
forall op v1 a1 v2 a2 m v,
eval_binop op v1 v2 m = Some v ->
val_match_approx a1 v1 -> val_match_approx a2 v2 ->
val_match_approx (Approx.binop op a1 a2) v.
Lemma approx_unop_is_redundant_sound:
forall op a v,
Approx.unop_is_redundant op a = true ->
val_match_approx a v ->
eval_unop op v = Some v.