(** * Relational specification of instruction selection *)

Definition match_fundef (cunit: Cminor.program) (f: Cminor.fundef) (tf: CminorSel.fundef) : Prop :=
  exists hf, helper_functions_declared cunit hf /\ sel_fundef (prog_defmap cunit) hf f = OK tf.Definition match_prog (p: Cminor.program) (tp: CminorSel.program) :=
  match_program match_fundef eq p tp.

(* Specifications: *)
Lemma lookup_helper_correct: forall p name sg id, lookup_helper (record_globdefs (prog_defmap p)) name sg = OK id -> helper_declared p id name sg.
Lemma get_helpers_correct: forall p hf, get_helpers (prog_defmap p) = OK hf -> helper_functions_declared p hf.
Theorem transf_program_match: forall p tp, sel_program p = OK tp -> match_prog p tp.
Lemma helper_functions_declared_linkorder: forall (p p': Cminor.program) hf, helper_functions_declared p hf -> linkorder p p' -> helper_functions_declared p' hf.
Lemma symbols_preserved: forall (s: ident), Genv.find_symbol tge s = Genv.find_symbol ge s.
Lemma senv_preserved: Senv.equiv (Genv.to_senv ge) (Genv.to_senv tge).
Lemma function_ptr_translated: forall (b: block) (f: Cminor.fundef), Genv.find_funct_ptr ge b = Some f -> exists cu tf, Genv.find_funct_ptr tge b = Some tf /\ match_fundef cu f tf /\ linkorder cu prog.
Lemma functions_translated: forall (v v': val) (f: Cminor.fundef), Genv.find_funct ge v = Some f -> Val.lessdef v v' -> exists cu tf, Genv.find_funct tge v' = Some tf /\ match_fundef cu f tf /\ linkorder cu prog.
Lemma sig_function_translated: forall cu f tf, match_fundef cu f tf -> funsig tf = Cminor.funsig f.
Lemma stackspace_function_translated: forall dm hf f tf, sel_function dm hf f = OK tf -> fn_stackspace tf = Cminor.fn_stackspace f.
Lemma helper_functions_preserved: forall hf, helper_functions_declared prog hf -> helper_functions_declared tprog hf.
Lemma eval_condexpr_of_expr: forall a le v b, eval_expr tge sp e m le a v -> Val.bool_of_val v b -> eval_condexpr tge sp e m le (condexpr_of_expr a) b.
Lemma eval_load: forall le a v chunk v', eval_expr tge sp e m le a v -> Mem.loadv chunk m v = Some v' -> eval_expr tge sp e m le (load chunk a) v'.
Lemma eval_store: forall chunk a1 a2 v1 v2 f k m', eval_expr tge sp e m nil a1 v1 -> eval_expr tge sp e m nil a2 v2 -> Mem.storev chunk m v1 v2 = Some m' -> step tge (State f (store chunk a1 a2) k sp e m) E0 (State f Sskip k sp e m').
Lemma eval_sel_unop: forall le op a1 v1 v, eval_expr tge sp e m le a1 v1 -> eval_unop op v1 = Some v -> exists v', eval_expr tge sp e m le (sel_unop op a1) v' /\ Val.lessdef v v'.
Lemma eval_sel_binop: forall le op a1 a2 v1 v2 v, eval_expr tge sp e m le a1 v1 -> eval_expr tge sp e m le a2 v2 -> eval_binop op v1 v2 m = Some v -> exists v', eval_expr tge sp e m le (sel_binop op a1 a2) v' /\ Val.lessdef v v'.
Lemma expr_is_addrof_ident_correct: forall e id, expr_is_addrof_ident e = Some id -> e = Cminor.Econst (Cminor.Oaddrsymbol id Ptrofs.zero).
Lemma classify_call_correct: forall unit sp e m a v fd, linkorder unit prog -> Cminor.eval_expr ge sp e m a v -> Genv.find_funct ge v = Some fd -> match classify_call (prog_defmap unit) a with | Call_default => True | Call_imm id => exists b, Genv.find_symbol ge id = Some b /\ v = Vptr b Ptrofs.zero | Call_builtin ef => fd = External ef end.