let compute_pdg_for_f kf =
  let pdg = BuildPdg.create kf in

  let f_locals, f_stmts =
    if !Db.Value.use_spec_instead_of_definition kf then [], []
    else let f = Kernel_function.get_definition kf in
         f.slocals, f.sbody.bstmts
  in
  let init_state =
    let _ = BuildPdg.process_entry_point pdg f_stmts in
    let formals = Kernel_function.get_formals kf in
    BuildPdg.process_declarations pdg formals f_locals
  in
  let froms = match f_stmts with
  | [] ->
      let state = init_state in
      BuildPdg.store_last_state pdg state ;
      let froms = !Db.From.get kf in
        Some (froms)
  | start :: stmts ->
      let ctrl_dpds_infos = CtrlDpds.compute kf in
      let module Computer = Computer (struct
                                        let current_pdg = pdg
                                        let ctrl_dpds_infos = ctrl_dpds_infos
                                      end)
      in
      let module Compute = Dataflow.ForwardsDataFlow(Computerin
      if Db.Value.is_reachable_stmt start then
        begin
          let init_state = Computer.computeFirstPredecessor start init_state in
          Computer.StmtStartData.add start.sid init_state ;
          let rec add acc l = match l with [] -> acc
            | s::tl -> 
                Computer.StmtStartData.add s.sid BuildPdg.empty_state;
                add (s::acc) tl
          in 
          let starts = add [start] (ctrl_no_preds stmts) in 
            Compute.compute starts ;
          None
        end
      else
        raise
          (Err_Bot
             (Printf.sprintf "unreachable entry point (sid:%d, function %s)"
                start.sid (Kernel_function.get_name kf)))
  in
  let pdg = BuildPdg.finalize_pdg pdg froms in
    pdg