let compute_using_prototype kf  ~state_with_formals =
  match kf.fundec with
  | Definition (_,_) -> assert false
  | Declaration (_,vi,_,_) when Cil.hasAttribute "noreturn" vi.vattr ->
      NoneRelations_type.Model.bottom, Location_Bits.Top_Param.bottom
  | Declaration (_spec,varinfo,_,_) ->
      let return_type,_formals_type,_inline,_attr =
        splitFunctionType (Kernel_function.get_type kf)
      in
      let behaviors = valid_behaviors kf state_with_formals in
      let assigns = Ast_info.merge_assigns behaviors in
      let returned_value, state_with_formals =
        return_value return_type kf state_with_formals
      in
      let returned_value = ref returned_value in
      let clobbered_set = ref Location_Bits.Top_Param.bottom in
      let state =
        match assigns with
        | [] -> state_with_formals
        | assigns -> (*VP: same behavior as before, but it is weird:
                       \from \nothing has the
                       same meaning as unspecified \from...
                     *)

            let treat_assign acc (out, ins) =
              let input_contents =
                try
                  List.fold_left
                    (fun acc term ->
                       let input_loc =
                         !Db.Properties.Interp.identified_term_zone_to_loc
                           ~result:None
                           state_with_formals
                           term
                       in
                       let r =
                         Relations_type.Model.find
                           ~with_alarms:CilE.warn_none_mode
                           state_with_formals
                           input_loc
                       in
        (*                 Format.printf "loc %a r %a@."
                           Locations.pretty input_loc
                           Cvalue_type.V.pretty r; *)

                         Cvalue_type.V.join acc r)
                    Cvalue_type.V.top_int
                    ins
                with Invalid_argument "not an lvalue" ->
                  Value_parameters.result
                    ~once:true ~current:true
                    "cannot interpret assigns in function %a"
                    Kernel_function.pretty_name kf;
                  Cvalue_type.V.top
              in
              let treat_output_loc loc acc =
                remember_bases_with_locals
                  clobbered_set
                  loc
                  input_contents;
                let bound =
                  Relations_type.Model.add_binding
                    ~with_alarms:CilE.warn_none_mode
                    ~exact:false acc loc input_contents
                in
                Relations_type.Model.join bound acc
              in
              try
                let lvals_out =
                  try
                    match out with
                    | Location out ->
                        !Db.Properties.Interp.loc_to_lval
                          ~result:None
                          out.it_content
                    | Nothing -> []
                  with
                    Invalid_argument "not an lvalue" as e ->
                      begin match out with
                        Location {it_content={term_node=
                            TLval (TMem {term_node=TBinOp((IndexPI|PlusPI) ,
                                                         t1,_o1)},
                                  _o2)}} ->
                          let deref_lvals =
                            !Db.Properties.Interp.loc_to_lval ~result:None t1
                          in
(*                          Format.printf "input: %a@."
                            Cvalue_type.V.pretty input_contents ; *)

                          raise (Deref_lvals deref_lvals)
                      | _ -> raise e
                      end
                in
                List.fold_left
                  (fun acc lval ->
                    let loc =
                      lval_to_loc  ~with_alarms:CilE.warn_none_mode
                        state_with_formals lval
                    in
                    treat_output_loc loc acc
                  )
                  acc
                  lvals_out
              with
                Invalid_argument "not an lvalue" ->
                  (match out with
                    Location out when
                        Logic_utils.is_result out.it_content ->
                          returned_value :=
                            Cvalue_type.V.join
                              (Cvalue_type.V.topify_arith_origin
                                  input_contents)
                              !returned_value;
                          acc
                  | Location _ ->
                      Value_parameters.warning ~once:true ~current:true
                        "Can not interpret assigns in function %a; effects will be ignored"
                        Kernel_function.pretty_name kf; acc
                  | Nothing -> assert false (* should not raise a failure
                                               when converting to cloc *)
)
              | Deref_lvals deref_lvals ->
                  let deref_loc =
                    List.fold_left
                      (fun acc lv ->
                        Location_Bits.join
                          (lval_to_loc ~with_alarms:CilE.warn_none_mode
                              state_with_formals lv).loc
                          acc)
                      Location_Bits.bottom
                      deref_lvals
                  in
                  let deref_loc = Location_Bits.topify_arith_origin deref_loc
                  in
                  let loc_bytes =
                    Relations_type.Model.find ~with_alarms:CilE.warn_none_mode
                      state_with_formals
                      (make_loc deref_loc Int_Base.top)
                  in
                  let loc =
                    make_loc (loc_bytes_to_loc_bits loc_bytes) Int_Base.top
                  in
                  treat_output_loc loc acc
            in
            (List.fold_left treat_assign state_with_formals assigns)
      in
      let retres_vi, state =
        if isVoidType return_type
        then None, state
        else
          let offsetmap =
            V_Offsetmap.update_ival
              ~with_alarms:CilE.warn_none_mode
              ~validity:Base.All
              ~offsets:Ival.zero
              ~exact:true
              ~size:(Int.of_int (bitsSizeOf return_type))
              V_Offsetmap.empty
              (Cvalue_type.V_Or_Uninitialized.initialized !returned_value)
          in
          Library_functions.add_retres_to_state
            varinfo
            offsetmap
            state
      in
      retres_vi, state, !clobbered_set