let rec expr mem e =
    match (Cil.stripInfo e).enode with
      | Info _ -> WpLog.fatal "non translation for info type expression"
      | Const (cnst) -> expr_const mem cnst
      | CastE (ty,e) ->
          if Cil.isPointerType ty && Cil.isZero e then
            (let t = Ctypes.object_of_pointed (Ctypes.object_of ty) in
            M.V_pointer(t, M.null))
          else
          expr_cast (Cil.typeOf e) ty (expr mem e)
      | BinOp (op, e1, e2, ty) ->
          expr_binop mem op ty
            e1 (Cil.typeOf e1)
            e2 (Cil.typeOf e2)
      | UnOp (op, e1, ty) ->
          expr_unop mem op ty e1 (Cil.typeOf e1)

      | Lval lval ->
          let t = Cil.typeOf e in
          let l = addr mem lval in
          M.load mem (Ctypes.object_of t) l

      | StartOf lval ->
          let ty_elt = 
            Ctypes.object_of_pointed (Ctypes.object_of (Cil.typeOf e)) in
          M.V_pointer(ty_elt,startof mem ty_elt lval)

      | AddrOf lval ->
          let ty_elt = 
            Ctypes.object_of_pointed (Ctypes.object_of (Cil.typeOf e))
          in
          M.V_pointer(ty_elt,addr mem lval)

      | AlignOfE _ | AlignOf _
      | SizeOfE _ | SizeOf _ | SizeOfStr _ ->
          let e' = Cil.constFold true e in
          match e'.enode with
            | Const _ -> expr mem e'
            | _ ->
                WpLog.not_yet_implemented "sizeof(%a)"
                  !Ast_printer.d_exp e