let compute_internal_using_cfg kf =
  let compute_for_definition kf f =
    try
      let module Computer =
        Computer
          (struct let stmt_can_reach = Stmts_graph.stmt_can_reach kf end)
      in
      let module Compute = Dataflow.ForwardsDataFlow(Computerin
      Stack.iter
        (fun g -> if kf == g then begin
           Inout_parameters.warning ~current:true
             "ignoring recursive call detected in function %s during [inout context] computation."
             (Kernel_function.get_name kf);
           raise Exit
         end)
        call_stack;
      Stack.push kf call_stack;
      let res_if_termination =
        match f.sbody.bstmts with
          [] -> assert false
        | start :: _ ->
            let ret_id = Kernel_function.find_return kf in
            Computer.StmtStartData.add
              start.sid
              (Computer.computeFirstPredecessor
                 start
                 empty);
            Compute.compute [start];
            ignore (Stack.pop call_stack);
            try
              Computer.StmtStartData.find ret_id.sid
            with Not_found -> bottom
      in

      { Inout_type.over_inputs_if_termination = res_if_termination.over_inputs;
        under_outputs_if_termination = res_if_termination.under_outputs ;
        over_inputs =
          let acc = Computer.non_terminating_callees_inputs
          in
          Computer.StmtStartData.iter
            (fun _sid data -> acc := Zone.join data.over_inputs !acc);
          !acc}

    with Exit ->
      { Inout_type.over_inputs_if_termination = empty.over_inputs ;
        under_outputs_if_termination = empty.under_outputs ;
        over_inputs = empty.over_inputs
      }
  in
  match kf.fundec with
  | Declaration _ ->
      invalid_arg
        "compute_using_cfg cannot be called on library functions"
  | Definition (f, _) ->
      compute_for_definition kf f