(* *********************************************************************)
(*                                                                     *)
(*              The Compcert verified compiler                         *)
(*                                                                     *)
(*          Xavier Leroy, INRIA Paris-Rocquencourt                     *)
(*                                                                     *)
(*  Copyright Institut National de Recherche en Informatique et en     *)
(*  Automatique.  All rights reserved.  This file is distributed       *)
(*  under the terms of the GNU General Public License as published by  *)
(*  the Free Software Foundation, either version 2 of the License, or  *)
(*  (at your option) any later version.  This file is also distributed *)
(*  under the terms of the INRIA Non-Commercial License Agreement.     *)
(*                                                                     *)
(* *********************************************************************)
(* and a few modifications... *)
(** Arithmetic and logical operators for the Compcert C and Clight languages *)
(*In this file, only Clight-independent (but possibly Ctypes-dependent) notions are defined. Maybe rename file to CommonOp.v ?*)
(** Computational version of type_eq **)
Definition eqb_option {A} (f: A -> A -> bool) (x y: option A) : bool :=
match x, y with
| None, None => true
| Some x' , Some y' => f x' y'
| _, _ => false
end.
Definition eqb_attr (a b: attr) : bool :=
match a, b with
| mk_attr av an, mk_attr bv bn => eqb av bv && eqb_option N.eqb an bn
end.
Definition eqb_floatsize (a b: floatsize) : bool :=
match a , b with
| F32, F32 => true
| F64, F64 => true
| _, _ => false
end.
Definition eqb_ident : ident -> ident -> bool := Pos.eqb.
Definition eqb_intsize (a b: intsize) : bool :=
match a , b with
| I8, I8 => true
| I16, I16 => true
| I32, I32 => true
| IBool, IBool => true
| _, _ => false
end.
Definition eqb_signedness (a b : signedness) :=
match a, b with
| Signed, Signed => true
| Unsigned, Unsigned => true
| _, _ => false
end.
Definition eqb_calling_convention (a b: calling_convention) :=
andb (eqb (cc_vararg a) (cc_vararg b))
(andb  (eqb (cc_unproto a) (cc_unproto b))
(eqb (cc_structret a) (cc_structret b))).
Fixpoint eqb_type (a b: type) {struct a} : bool :=
match a, b with
| Tvoid, Tvoid => true
| Tint ia sa aa, Tint ib sb ab => andb (eqb_intsize ia ib)
(andb (eqb_signedness sa sb) (eqb_attr aa ab))
| Tlong sa aa, Tlong sb ab => andb (eqb_signedness sa sb) (eqb_attr aa ab)
| Tfloat sa aa, Tfloat sb ab => andb (eqb_floatsize sa sb) (eqb_attr aa ab)
| Tpointer ta aa, Tpointer tb ab => andb (eqb_type ta tb) (eqb_attr aa ab)
| Tarray ta sa aa, Tarray tb sb ab => andb (eqb_type ta tb)
(andb (Zeq_bool sa sb) (eqb_attr aa ab))
| Tfunction sa ta ca, Tfunction sb tb cb =>
andb (andb (eqb_typelist sa sb) (eqb_type ta tb)) (eqb_calling_convention ca cb)
| Tstruct ia aa, Tstruct ib ab => andb (eqb_ident ia ib) (eqb_attr aa ab)
| Tunion ia aa, Tunion ib ab => andb (eqb_ident ia ib) (eqb_attr aa ab)
| _, _ => false
end
with eqb_typelist (a b: typelist)  {struct a}: bool :=
match a, b with
| Tcons ta ra, Tcons tb rb => andb (eqb_type ta tb) (eqb_typelist ra rb)
| Tnil, Tnil => true
| _ , _ => false
end.
Scheme eqb_type_sch := Induction for type Sort Prop
with eqb_typelist_sch := Induction for  typelist Sort Prop.
Definition eqb_member (it1 it2: ident * type): bool :=
eqb_ident (fst it1) (fst it2) && eqb_type (snd it1) (snd it2).
Definition eqb_su (su1 su2: struct_or_union): bool :=
match su1, su2 with
| Struct, Struct
| Union, Union => true
| _, _ => false
end.

(* Specifications: *)
Lemma eqb_intsize_spec: forall i j, eqb_intsize i j = true <-> i=j.
Lemma eqb_ident_spec: forall i j, eqb_ident i j = true <-> i=j.
Lemma eqb_type_spec: forall a b, eqb_type a b = true <-> a=b.
Lemma eqb_type_true: forall a b, eqb_type a b = true -> a=b.
Lemma eqb_type_false: forall a b, eqb_type a b = false <-> a<>b.
Lemma eqb_type_refl: forall a, eqb_type a a = true.
Lemma eqb_member_spec: forall a b, eqb_member a b = true <-> a=b.
Lemma eqb_su_spec: forall a b, eqb_su a b = true <-> a=b.
Definition log2_sizeof_pointer : N :=
ltac:(let n := eval compute in
(N.log2 (Z.to_N (@sizeof (PTree.empty _) (Tpointer Tvoid noattr))))
in exact (n)).