Section SUBJECT_REDUCTION.
Variable p: program.
Hypothesis wt_p: wt_program p.
Let ge := Genv.globalenv p.
Ltac VHT :=
match goal with
| [ |- Val.has_type (if Archi.ptr64 then _ else _) _] => unfold Val.has_type; destruct Archi.ptr64 eqn:?; VHT
| [ |- Val.has_type (match ?v with _ => _ end) _] => destruct v; VHT
| [ |- Val.has_type (Vptr _ _) Tptr ] => apply Val.Vptr_has_type
| [ |- Val.has_type _ _ ] => exact I
| [ |- Val.has_type (?f _ _ _ _ _) _ ] => unfold f; VHT
| [ |- Val.has_type (?f _ _ _ _) _ ] => unfold f; VHT
| [ |- Val.has_type (?f _ _) _ ] => unfold f; VHT
| [ |- Val.has_type (?f _ _ _) _ ] => unfold f; VHT
| [ |- Val.has_type (?f _) _ ] => unfold f; VHT
| [ |- True ] => exact I
| [ |- ?x = ?x ] => reflexivity
| _ => idtac
end.
Ltac VHT' :=
match goal with
| [ H: None = Some _ |- _ ] => discriminate
| [ H: Some _ = Some _ |- _ ] => inv H; VHT
| [ H: match ?x with _ => _ end = Some _ |- _ ] => destruct x; VHT'
| [ H: ?f _ _ _ _ = Some _ |- _ ] => unfold f in H; VHT'
| [ H: ?f _ _ _ = Some _ |- _ ] => unfold f in H; VHT'
| [ H: ?f _ _ = Some _ |- _ ] => unfold f in H; VHT'
| [ H: ?f _ = Some _ |- _ ] => unfold f in H; VHT'
| _ => idtac
end.
End SUBJECT_REDUCTION.
(** * Safe expressions *)
(** Function parameters and declared local variables are always defined throughout the execution of a function.  The following [known_idents] data structure represents the set of those variables, with efficient membership. *)
Definition known_idents := PTree.t unit.
Definition is_known (ki: known_idents) (id: ident) :=
match ki!id with Some _ => true | None => false end.
Definition known_id (f: function) : known_idents :=
let add (ki: known_idents) (id: ident) := PTree.set id tt ki in
List.fold_left add f.(fn_vars)
(List.fold_left add f.(fn_params) (PTree.empty unit)).
(** A Cminor expression is safe if it always evaluates to a value, never causing a run-time error. *)
Definition safe_unop (op: unary_operation) : bool :=
match op with
| Ointoffloat | Ointuoffloat | Ofloatofint | Ofloatofintu => false
| Ointofsingle | Ointuofsingle | Osingleofint | Osingleofintu => false
| Olongoffloat | Olonguoffloat | Ofloatoflong | Ofloatoflongu => false
| Olongofsingle | Olonguofsingle | Osingleoflong | Osingleoflongu => false
| _ => true
end.
Definition safe_binop (op: binary_operation) : bool :=
match op with
| Odiv | Odivu | Omod | Omodu => false
| Odivl | Odivlu | Omodl | Omodlu => false
| Ocmpl _ | Ocmplu _ => false
| _ => true
end.
Fixpoint safe_expr (ki: known_idents) (a: expr) : bool :=
match a with
| Evar v => is_known ki v
| Econst c => true
| Eunop op e1 => safe_unop op && safe_expr ki e1
| Ebinop op e1 e2 => safe_binop op && safe_expr ki e1 && safe_expr ki e2
| Eload chunk e => false
end.
(** Soundness of [known_id]. *)
(** Expressions that satisfy [safe_expr] always evaluate to a value. *)

Lemma eval_safe_expr:
forall ge f sp e m a,
def_env f e ->
safe_expr (known_id f) a = true ->
exists v, eval_expr ge sp e m a v.