let compute_using_cfg kf ~call_kinstr initial_state =
  match kf.fundec with
  | Declaration _ -> assert false
  | Definition (f,_loc) ->
      (*if let (_,_,variadic,_) = splitFunctionTypeVI f.svar in variadic
        then raise Leaf (* Do not visit variadic bodies *)
        else *)

      begin
        let module Computer =
          Computer(struct
                     let stmt_can_reach = Stmts_graph.stmt_can_reach kf
                     let is_natural_loop = Loop.is_natural kf
                     let non_linear_assignments =
                       match kf.fundec with
                         Declaration(_funspec,_varinfo,_,_) ->                                                      dummy_non_linear_assignment
                       | Definition (fundec,_location) ->
                           let varinfo = fundec.svar in
                           (try
                             Non_linear_assignments.find varinfo
                           with
                             Not_found ->
                               let n = compute_non_linear_assignments f in
                               Non_linear_assignments.add varinfo n;
                               n)
                     let blocks_closed_by_edge =
                       Kernel_function.blocks_closed_by_edge
                   end)
        in
        let module Compute = Dataflow.ForwardsDataFlow(Computerin
        List.iter
          (function {called_kf = g} ->
             if kf == g
             then begin
               Value_parameters.warning ~current:true ~once:true
                 "ignoring recursive call during value analysis of %a (%a)"
                 Kernel_function.pretty_name kf
                 pretty_call_stack !call_stack ;
               raise Leaf
             end)
          !call_stack;
        push_call_stack {called_kf = kf;
                         call_site = call_kinstr;
                         called_merge_current = Computer.merge_current};
        match f.sbody.bstmts with
          [] -> assert false
        | start :: _ ->
            let ret_id = Kernel_function.find_return kf in
            (* We start with only the start block *)
            Computer.StmtStartData.add
              start.sid
              (Computer.computeFirstPredecessor
                 start
                 {
                   Computer.counter_unroll = 0;
                   value = initial_state});
            begin try
              Compute.compute [start]
            with Db.Value.Aborted as e ->
              (* Computation was aborted: pop the call stack and inform
                 the caller *)

               pop_call_stack ();
              raise e
            end;
            let last_ret,last_s,last_clob as last_state =
              try
                let _,state,_ as result =
                  try
                    Computer.externalize (Kstmt ret_id) kf
                  with Not_found -> assert false
                in
                if Relations_type.Model.is_reachable state
                then begin
                  if hasAttribute "noreturn" (Kernel_function.get_vi kf).vattr
                  then
                    Value_parameters.warning ~current:true ~once:true
                      "function %a may terminate but has the noreturn attribute"
                      Kernel_function.pretty_name kf;
                  Kf_state.mark_as_terminates kf
                end
                else raise Not_found;
                result
              with Not_found -> begin
                (
                  (*     Computer.merge_current (); this may already have been
                         done by externalize, and should not be done twice
                         because the callbacks are done there.

                         TODO: examine the usefulness of this statement
                  (* Save the values computed even
                         if the function does not terminate *) *)


                  Kf_state.mark_as_never_terminates kf);
                None,
                Relations_type.Model.bottom,
                Location_Bits.Top_Param.bottom
              end
            in
            Value_parameters.debug
              "@[RESULT FOR %a <-%a:@\n\\result -> %a@\n%a@\nClobered set:%a@]"
                Kernel_function.pretty_name kf
              pretty_call_stack !call_stack
              (fun fmt v ->
                 match v with
                 | None -> ()
                 | Some v -> V_Offsetmap.pretty fmt v)
              last_ret
              Relations_type.Model.pretty last_s
              Location_Bits.Top_Param.pretty
              last_clob;
            pop_call_stack ();
            last_state
      end