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 = (* result if termination *)
        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
                 empty);
            Compute.compute [start];
            let _poped = Stack.pop call_stack in
            try
              Computer.StmtStartData.find ret_id.sid
            with Not_found ->
              non_terminating
      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.under_inputs_termination_no_depend
        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 leaf functions"
  | Definition (f, _) ->
      compute_for_definition kf f