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(Computer)
      in
      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