Definition binarithType' t1 t2 ty deferr reterr : tc_assert :=
match classify_binarith' t1 t2 with
| Cop.bin_case_i sg =>  tc_bool (is_int32_type ty) reterr
| Cop.bin_case_l sg => tc_bool (is_long_type ty) reterr
| Cop.bin_case_f   => tc_bool (is_float_type ty) reterr
| Cop.bin_case_s   => tc_bool (is_single_type ty) reterr
| Cop.bin_default => tc_FF deferr
end.

(* Specifications: *)
Lemma classify_binarith_eq: classify_binarith = classify_binarith'.
Lemma binarithType_eq: binarithType = binarithType'.
Lemma den_isBinOpR: forall {CS: compspecs} op a1 a2 ty,
denote_tc_assert (isBinOpResultType op a1 a2 ty) =
let e := (Ebinop op a1 a2 ty) in
let reterr := op_result_type e in
let deferr := arg_type e in
denote_tc_assert
match op with
| Cop.Oadd => match classify_add' (typeof a1) (typeof a2) with
| Cop.add_case_pi t _ => tc_andp' (tc_andp' (tc_andp' (tc_isptr a1)
(tc_bool (complete_type cenv_cs t) reterr))
(tc_int_or_ptr_type (typeof a1)))
(tc_bool (is_pointer_type ty) reterr)
| Cop.add_case_ip _ t => tc_andp' (tc_andp' (tc_andp' (tc_isptr a2)
(tc_bool (complete_type cenv_cs t) reterr))
(tc_int_or_ptr_type (typeof a2)))
(tc_bool (is_pointer_type ty) reterr)
| Cop.add_case_pl t => tc_andp' (tc_andp' (tc_andp' (tc_isptr a1)
(tc_bool (complete_type cenv_cs t) reterr))
(tc_int_or_ptr_type (typeof a1)))
(tc_bool (is_pointer_type ty) reterr)
| Cop.add_case_lp t => tc_andp' (tc_andp' (tc_andp' (tc_isptr a2)
(tc_bool (complete_type cenv_cs t) reterr))
(tc_int_or_ptr_type (typeof a2)))
(tc_bool (is_pointer_type ty) reterr)
| Cop.add_default => tc_andp
(binarithType' (typeof a1) (typeof a2) ty deferr reterr)
(tc_nobinover Z.add a1 a2)
end
| Cop.Osub => match classify_sub' (typeof a1) (typeof a2) with
| Cop.sub_case_pi t _ => tc_andp' (tc_andp' (tc_andp' (tc_isptr a1)
(tc_bool (complete_type cenv_cs t) reterr))
(tc_int_or_ptr_type (typeof a1)))
(tc_bool (is_pointer_type ty) reterr)
| Cop.sub_case_pl t => tc_andp' (tc_andp' (tc_andp' (tc_isptr a1)
(tc_bool (complete_type cenv_cs t) reterr))
(tc_int_or_ptr_type (typeof a1)))
(tc_bool (is_pointer_type ty) reterr)
| Cop.sub_case_pp t =>
tc_andp' (tc_andp' (tc_andp' (tc_andp' (tc_andp' (tc_andp'
(tc_andp' (tc_andp' (tc_samebase a1 a2)
(tc_isptr a1))
(tc_isptr a2))
(tc_int_or_ptr_type (typeof a1)))
(tc_int_or_ptr_type (typeof a2)))
(tc_bool (is_ptrofs_type ty) reterr))
(tc_bool (negb (Z.eqb (sizeof t) 0))
(pp_compare_size_0 t)))
(tc_bool (complete_type cenv_cs t) reterr))
(tc_bool (Z.leb (sizeof t) Ptrofs.max_signed)
(pp_compare_size_exceed t))
| Cop.sub_default => tc_andp
(binarithType' (typeof a1) (typeof a2) ty deferr reterr)
(tc_nobinover Z.sub a1 a2)
end
| Cop.Omul => tc_andp (binarithType' (typeof a1) (typeof a2) ty deferr reterr)
(tc_nobinover Z.mul a1 a2)
| Cop.Omod => match classify_binarith' (typeof a1) (typeof a2) with
| Cop.bin_case_i Unsigned =>
tc_andp' (tc_nonzero' a2)
(tc_bool (is_int32_type ty) reterr)
| Cop.bin_case_l Unsigned =>
tc_andp' (tc_nonzero' a2)
(tc_bool (is_long_type ty) reterr)
| Cop.bin_case_i Signed => tc_andp' (tc_andp' (tc_nonzero' a2)
(tc_nodivover' a1 a2))
(tc_bool (is_int32_type ty) reterr)
| Cop.bin_case_l Signed => tc_andp' (tc_andp' (tc_nonzero' a2)
(tc_nodivover' a1 a2))
(tc_bool (is_long_type ty) reterr)
| _ => tc_FF deferr
end
| Cop.Odiv => match classify_binarith' (typeof a1) (typeof a2) with
| Cop.bin_case_i Unsigned => tc_andp' (tc_nonzero' a2) (tc_bool (is_int32_type ty) reterr)
| Cop.bin_case_l Unsigned => tc_andp' (tc_nonzero' a2) (tc_bool (is_long_type ty) reterr)
| Cop.bin_case_i Signed => tc_andp' (tc_andp' (tc_nonzero' a2) (tc_nodivover' a1 a2))
(tc_bool (is_int32_type ty) reterr)
| Cop.bin_case_l Signed => tc_andp' (tc_andp' (tc_nonzero' a2) (tc_nodivover' a1 a2))
(tc_bool (is_long_type ty) reterr)
| Cop.bin_case_f  =>  tc_bool (is_float_type ty) reterr
| Cop.bin_case_s  =>  tc_bool (is_single_type ty) reterr
| Cop.bin_default => tc_FF deferr
end
| Cop.Oshl | Cop.Oshr => match classify_shift' (typeof a1) (typeof a2) with
| Cop.shift_case_ii _ =>  tc_andp' (tc_ilt' a2 Int.iwordsize) (tc_bool (is_int32_type ty)
reterr)
| Cop.shift_case_il _ =>  tc_andp' (tc_llt' a2 (Int64.repr 32)) (tc_bool (is_int32_type ty)
reterr)
| Cop.shift_case_li _ =>  tc_andp' (tc_ilt' a2 Int64.iwordsize') (tc_bool (is_long_type ty)
reterr)
| Cop.shift_case_ll _ =>  tc_andp' (tc_llt' a2 Int64.iwordsize) (tc_bool (is_long_type ty)
reterr)
| _ => tc_FF deferr
end
| Cop.Oand | Cop.Oor | Cop.Oxor =>
match classify_binarith' (typeof a1) (typeof a2) with
| Cop.bin_case_i _ =>tc_bool (is_int32_type ty) reterr
| Cop.bin_case_l _ =>tc_bool (is_long_type ty) reterr
| Cop.bin_case_f => tc_FF deferr
| Cop.bin_case_s => tc_FF deferr
| Cop.bin_default => tc_FF deferr
end
| Cop.Oeq | Cop.One | Cop.Olt | Cop.Ogt | Cop.Ole | Cop.Oge =>
match classify_cmp' (typeof a1) (typeof a2) with
| Cop.cmp_default =>
tc_bool (is_numeric_type (typeof a1)
&& is_numeric_type (typeof a2)
&& is_int_type ty)
deferr
| Cop.cmp_case_pp => tc_andp' (tc_andp' (tc_int_or_ptr_type (typeof a1))
(tc_int_or_ptr_type (typeof a2)))
(check_pp_int' a1 a2 op ty e)
| Cop.cmp_case_pi si =>
tc_andp' (tc_int_or_ptr_type (typeof a1))
(check_pp_int' a1 (Ecast a2 size_t) op ty e)
| Cop.cmp_case_ip si =>
tc_andp' (tc_int_or_ptr_type (typeof a2))
(check_pp_int' (Ecast a1 size_t) a2 op ty e)
| Cop.cmp_case_pl =>
tc_andp' (tc_int_or_ptr_type (typeof a1))
(check_pp_int' a1 (Ecast a2 size_t) op ty e)
| Cop.cmp_case_lp =>
tc_andp' (tc_int_or_ptr_type (typeof a2))
(check_pp_int' (Ecast a1 size_t) a2 op ty e)
end
end.