let cil_binop binop ty e1 e2 =
  let op = match binop with
  | PlusPI           
              (** pointer + integer *)
  -> 
      Wp_parameters.abort "(ptr+int) should be handled by the memory model"
  | IndexPI          
             (** pointer + integer *)
  -> 
      Wp_parameters.abort "(ptr[int]) should be handled by the memory model"
  | MinusPI          
             (** pointer - integer *)
  ->
      Wp_parameters.abort "(ptr-int) should be handled by the memory model"
  | MinusPP          
             (** pointer - pointer *)
  ->
      Wp_parameters.abort "(ptr-ptr) should be handled by the memory model"

  | PlusA 
    (** arithmetic + *)
  when Cil.isLogicIntegralType ty -> 
      "add_int" (* from integer.why *)
  | MinusA 
    (** arithmetic - *)
  when Cil.isLogicIntegralType ty -> 
      "sub_int" (* from integer.why *)
  | Mult   
      (** * *)
             when Cil.isLogicIntegralType ty -> 
      "mul_int" (* from integer.why *)
  | Div    
       (** / *)
             when Cil.isLogicIntegralType ty -> 
      "div_int" (* from integer.why *)
  | Mod    
       (** % *)
             when Cil.isLogicIntegralType ty -> 
      "mod_int" (* from integer.why *)

  | PlusA 
    (** arithmetic + *)
  when Cil.isLogicRealOrFloatType ty -> 
      "add_real" (* from integer.why *)
  | MinusA 
    (** arithmetic - *)
  when Cil.isLogicRealOrFloatType ty -> 
      "sub_real" (* from integer.why *)
  | Mult   
      (** * *)
             when Cil.isLogicRealOrFloatType ty -> 
      "mul_real" (* from integer.why *)
  | Div    
       (** / *)
             when Cil.isLogicRealOrFloatType ty -> 
      "div_real" (* from integer.why *)
  | Mod    
       (** % *)
             when Cil.isLogicRealOrFloatType ty -> 
      "mod_real" (* from integer.why *)

  | Lt | Gt | Le | Ge | Eq | Ne 
              (** arithmetic comparisons *)
 -> 
      assert false (* use bool_cmp_binop_name instead (different types) *)

  | BAnd      
         (** bitwise and *)
   -> "band" (* acsl.why : int -> int -> int *)
  | BXor      
         (** exclusive-or *)
  -> "bxor"   (* idem *)
  | BOr       
          (** inclusive-or *)
  -> "bor"    (* idem *)
  | Shiftlt   
      (** shift left *)
    -> "lshift" (* idem *)
  | Shiftrt   
      (** shift right *)
   -> "rshift" (* idem *)

    (* logical binary operations don't always evaluate both operands.
     * So, we cannot translate them directly into logical operations... 
    * *)

  | LAnd  
     (** logical and *)
 ->  "bool_and" 
                                 (* from bool.why : bool -> bool -> bool *)
  | LOr 
    (** logical or *)
    ->  "bool_or" 
                                 (* from bool.why : bool -> bool -> bool *)
  | _ ->
      let str = Pretty_utils.sfprintf "%a" !Ast_printer.d_logic_type ty in
      raise (UnnamedCilOp ("arithmetic operation for type "^str))
  in Fol.Tapp (op, [e1; e2])