let merge_fun_callers get_list get_value merge is_top acc proj kf =
  if is_top acc then acc
  else begin
    let acc = ref acc in
    let table = ref Cil_datatype.Varinfo.Set.empty in
      try
        let merge m =
          acc := merge m !acc ;
          if is_top !acc then
            raise StopMerging (* acceleration when top is reached *)
        in
        let rec merge_fun_callers kf =
          let merge_fun_caller (kf,_) = merge_fun_callers kf in
          let vf = Kernel_function.get_vi kf in
          if not (Cil_datatype.Varinfo.Set.mem vf !table) then begin
            table := Cil_datatype.Varinfo.Set.add vf !table ;
            List.iter (fun x -> merge (get_value x)) (get_list proj kf) ;
            List.iter merge_fun_caller (!Db.Value.callers kf)
          end
        (*  else no way to add something, the [kf] contribution is already
            accumulated. *)

        in
        merge_fun_callers kf;
        !acc
      with StopMerging ->
        !acc
  end